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