Restore from version 1.1
[deliverable/binutils-gdb.git] / cpu / mt.opc
CommitLineData
b081650b
DB
1/* Morpho Technologies mRISC opcode support, for GNU Binutils. -*- C -*-
2 Copyright 2001 Free Software Foundation, Inc.
3
4 Contributed by Red Hat Inc; developed under contract from
5 Morpho Technologies.
6
7 This file is part of the GNU Binutils.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
22
23*/
24
25/*
26 Each section is delimited with start and end markers.
27
28 <arch>-opc.h additions use: "-- opc.h"
29 <arch>-opc.c additions use: "-- opc.c"
30 <arch>-asm.c additions use: "-- asm.c"
31 <arch>-dis.c additions use: "-- dis.c"
32 <arch>-ibd.h additions use: "-- ibd.h"
33*/
34\f
35/* -- opc.h */
36
37/* Check applicability of instructions against machines. */
38#define CGEN_VALIDATE_INSN_SUPPORTED
39
40/* Allows reason codes to be output when assembler errors occur. */
41#define CGEN_VERBOSE_ASSEMBLER_ERRORS
42
43/* Override disassembly hashing - there are variable bits in the top
44 byte of these instructions. */
45#define CGEN_DIS_HASH_SIZE 8
46#define CGEN_DIS_HASH(buf, value) (((* (unsigned char *) (buf)) >> 5) % CGEN_DIS_HASH_SIZE)
47
48#define CGEN_ASM_HASH_SIZE 127
d031aafb 49#define CGEN_ASM_HASH(insn) mt_asm_hash (insn)
b081650b 50
d031aafb 51extern unsigned int mt_asm_hash (const char *);
b081650b 52
d031aafb 53extern int mt_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
b081650b
DB
54
55\f
56/* -- opc.c */
57#include "safe-ctype.h"
58
59/* Special check to ensure that instruction exists for given machine. */
60
61int
d031aafb 62mt_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
b081650b
DB
63{
64 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
65
66 /* No mach attribute? Assume it's supported for all machs. */
67 if (machs == 0)
68 return 1;
69
70 return ((machs & cd->machs) != 0);
71}
72
73/* A better hash function for instruction mnemonics. */
74
75unsigned int
d031aafb 76mt_asm_hash (const char* insn)
b081650b
DB
77{
78 unsigned int hash;
79 const char* m = insn;
80
81 for (hash = 0; *m && ! ISSPACE (*m); m++)
82 hash = (hash * 23) ^ (0x1F & TOLOWER (*m));
83
84 /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
85
86 return hash % CGEN_ASM_HASH_SIZE;
87}
88
89\f
90/* -- asm.c */
b081650b
DB
91/* Range checking for signed numbers. Returns 0 if acceptable
92 and 1 if the value is out of bounds for a signed quantity. */
93
94static int
95signed_out_of_bounds (long val)
96{
97 if ((val < -32768) || (val > 32767))
98 return 1;
99 return 0;
100}
101
6f84a2a6
NS
102static const char *
103parse_loopsize (CGEN_CPU_DESC cd,
104 const char **strp,
105 int opindex,
106 void *arg)
107{
108 signed long * valuep = (signed long *) arg;
109 const char *errmsg;
110 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
111 enum cgen_parse_operand_result result_type;
112 bfd_vma value;
113
114 /* Is it a control transfer instructions? */
d031aafb 115 if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_LOOPSIZE)
6f84a2a6 116 {
d031aafb 117 code = BFD_RELOC_MT_PCINSN8;
6f84a2a6
NS
118 errmsg = cgen_parse_address (cd, strp, opindex, code,
119 & result_type, & value);
120 *valuep = value;
121 return errmsg;
122 }
123
124 abort ();
125}
126
b081650b
DB
127static const char *
128parse_imm16 (CGEN_CPU_DESC cd,
129 const char **strp,
130 int opindex,
3ec2b351 131 void *arg)
b081650b 132{
3ec2b351 133 signed long * valuep = (signed long *) arg;
b081650b
DB
134 const char *errmsg;
135 enum cgen_parse_operand_result result_type;
136 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
137 bfd_vma value;
138
139 /* Is it a control transfer instructions? */
d031aafb 140 if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16O)
b081650b
DB
141 {
142 code = BFD_RELOC_16_PCREL;
143 errmsg = cgen_parse_address (cd, strp, opindex, code,
144 & result_type, & value);
145 if (errmsg == NULL)
146 {
147 if (signed_out_of_bounds (value))
148 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
149 }
150 *valuep = value;
151 return errmsg;
152 }
153
154 /* If it's not a control transfer instruction, then
155 we have to check for %OP relocating operators. */
d031aafb 156 if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16L)
6f84a2a6
NS
157 ;
158 else if (strncmp (*strp, "%hi16", 5) == 0)
b081650b
DB
159 {
160 *strp += 5;
161 code = BFD_RELOC_HI16;
162 }
163 else if (strncmp (*strp, "%lo16", 5) == 0)
164 {
165 *strp += 5;
166 code = BFD_RELOC_LO16;
167 }
168
169 /* If we found a %OP relocating operator, then parse it as an address.
170 If not, we need to parse it as an integer, either signed or unsigned
171 depending on which operand type we have. */
172 if (code != BFD_RELOC_NONE)
173 {
174 /* %OP relocating operator found. */
175 errmsg = cgen_parse_address (cd, strp, opindex, code,
176 & result_type, & value);
177 if (errmsg == NULL)
178 {
179 switch (result_type)
180 {
181 case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
182 if (code == BFD_RELOC_HI16)
183 value = (value >> 16) & 0xFFFF;
184 else if (code == BFD_RELOC_LO16)
185 value = value & 0xFFFF;
186 else
187 errmsg = _("Biiiig Trouble in parse_imm16!");
188 break;
189
190 case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
191 /* No special processing for this case. */
192 break;
193
194 default:
195 errmsg = _("%operator operand is not a symbol");
196 break;
197 }
198 }
199 *valuep = value;
200 }
201 else
202 {
203 /* Parse hex values like 0xffff as unsigned, and sign extend
204 them manually. */
d031aafb 205 int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MT_OPERAND_IMM16);
b081650b
DB
206
207 if ((*strp)[0] == '0'
208 && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
209 parse_signed = 0;
210
211 /* No relocating operator. Parse as an number. */
212 if (parse_signed)
213 {
214 /* Parse as as signed integer. */
215
216 errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
217
218 if (errmsg == NULL)
219 {
220#if 0
221 /* Manual range checking is needed for the signed case. */
222 if (*valuep & 0x8000)
223 value = 0xffff0000 | *valuep;
224 else
225 value = *valuep;
226
227 if (signed_out_of_bounds (value))
228 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
229 /* Truncate to 16 bits. This is necessary
230 because cgen will have sign extended *valuep. */
231 *valuep &= 0xFFFF;
232#endif
233 }
234 }
235 else
236 {
d031aafb 237 /* MT_OPERAND_IMM16Z. Parse as an unsigned integer. */
3ec2b351 238 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
b081650b 239
d031aafb 240 if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16
b081650b
DB
241 && *valuep >= 0x8000
242 && *valuep <= 0xffff)
243 *valuep -= 0x10000;
244 }
245 }
246
247 return errmsg;
248}
249
250
251static const char *
252parse_dup (CGEN_CPU_DESC cd,
253 const char **strp,
254 int opindex,
3ec2b351 255 unsigned long *valuep)
b081650b
DB
256{
257 const char *errmsg = NULL;
258
259 if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
260 {
261 *strp += 3;
262 *valuep = 1;
263 }
264 else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
265 {
266 *strp += 2;
267 *valuep = 0;
268 }
269 else
270 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
271
272 return errmsg;
273}
274
275
276static const char *
277parse_ball (CGEN_CPU_DESC cd,
278 const char **strp,
279 int opindex,
3ec2b351 280 unsigned long *valuep)
b081650b
DB
281{
282 const char *errmsg = NULL;
283
284 if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
285 {
286 *strp += 3;
287 *valuep = 1;
288 }
289 else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
290 {
291 *strp += 3;
292 *valuep = 0;
293 }
294 else
295 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
296
297 return errmsg;
298}
299
300static const char *
301parse_xmode (CGEN_CPU_DESC cd,
302 const char **strp,
303 int opindex,
3ec2b351 304 unsigned long *valuep)
b081650b
DB
305{
306 const char *errmsg = NULL;
307
308 if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
309 {
310 *strp += 2;
311 *valuep = 1;
312 }
313 else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
314 {
315 *strp += 2;
316 *valuep = 0;
317 }
318 else
319 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
320
321 return errmsg;
322}
323
324static const char *
325parse_rc (CGEN_CPU_DESC cd,
326 const char **strp,
327 int opindex,
3ec2b351 328 unsigned long *valuep)
b081650b
DB
329{
330 const char *errmsg = NULL;
331
332 if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
333 {
334 *strp += 1;
335 *valuep = 1;
336 }
337 else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
338 {
339 *strp += 1;
340 *valuep = 0;
341 }
342 else
343 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
344
345 return errmsg;
346}
347
348static const char *
349parse_cbrb (CGEN_CPU_DESC cd,
350 const char **strp,
351 int opindex,
3ec2b351 352 unsigned long *valuep)
b081650b
DB
353{
354 const char *errmsg = NULL;
355
356 if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
357 {
358 *strp += 2;
359 *valuep = 1;
360 }
361 else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
362 {
363 *strp += 2;
364 *valuep = 0;
365 }
366 else
367 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
368
369 return errmsg;
370}
371
372static const char *
373parse_rbbc (CGEN_CPU_DESC cd,
374 const char **strp,
375 int opindex,
3ec2b351 376 unsigned long *valuep)
b081650b
DB
377{
378 const char *errmsg = NULL;
379
380 if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
381 {
382 *strp += 2;
383 *valuep = 0;
384 }
385 else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
386 {
387 *strp += 3;
388 *valuep = 1;
389 }
390 else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
391 {
392 *strp += 3;
393 *valuep = 2;
394 }
395 else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
396 {
397 *strp += 2;
398 *valuep = 3;
399 }
400 else
401 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
402
403 return errmsg;
404}
405
406static const char *
407parse_type (CGEN_CPU_DESC cd,
408 const char **strp,
409 int opindex,
3ec2b351 410 unsigned long *valuep)
b081650b
DB
411{
412 const char *errmsg = NULL;
413
414 if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
415 {
416 *strp += 3;
417 *valuep = 0;
418 }
419 else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
420 {
421 *strp += 4;
422 *valuep = 1;
423 }
424 else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
425 {
426 *strp += 2;
427 *valuep = 2;
428 }
429 else
430 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
431
432 if ((errmsg == NULL) && (*valuep == 3))
433 errmsg = _("invalid operand. type may have values 0,1,2 only.");
434
435 return errmsg;
436}
437
438/* -- dis.c */
439static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
6f84a2a6 440static void print_pcrel (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
b081650b
DB
441
442static void
443print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
444 void * dis_info,
445 long value,
446 unsigned int attrs ATTRIBUTE_UNUSED,
447 bfd_vma pc ATTRIBUTE_UNUSED,
448 int length ATTRIBUTE_UNUSED)
449{
450 disassemble_info *info = (disassemble_info *) dis_info;
451
0e6b69be 452 info->fprintf_func (info->stream, "$%lx", value);
b081650b
DB
453
454 if (0)
455 print_normal (cd, dis_info, value, attrs, pc, length);
456}
457
6f84a2a6
NS
458static void
459print_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
460 void * dis_info,
461 long value,
462 unsigned int attrs ATTRIBUTE_UNUSED,
463 bfd_vma pc ATTRIBUTE_UNUSED,
464 int length ATTRIBUTE_UNUSED)
465{
466 print_address (cd, dis_info, value + pc, attrs, pc, length);
467}
b081650b
DB
468
469/* -- */
470
471
472
473
474
This page took 0.089633 seconds and 4 git commands to generate.