cpu/
[deliverable/binutils-gdb.git] / cpu / m32c.opc
1 /* m32c opcode support. -*- C -*-
2
3 Copyright 2005, 2007, 2009 Free Software Foundation, Inc.
4
5 Contributed by Red Hat Inc; developed under contract from Renesas
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 3 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,
22 MA 02110-1301, USA. */
23
24
25 /* This file is an addendum to m32c.cpu. Heavy use of C code isn't
26 appropriate in .cpu files, so it resides here. This especially applies
27 to assembly/disassembly where parsing/printing can be quite involved.
28 Such things aren't really part of the specification of the cpu, per se,
29 so .cpu files provide the general framework and .opc files handle the
30 nitty-gritty details as necessary.
31
32 Each section is delimited with start and end markers.
33
34 <arch>-opc.h additions use: "-- opc.h"
35 <arch>-opc.c additions use: "-- opc.c"
36 <arch>-asm.c additions use: "-- asm.c"
37 <arch>-dis.c additions use: "-- dis.c"
38 <arch>-ibd.h additions use: "-- ibd.h". */
39 \f
40 /* -- opc.h */
41
42 /* Needed for RTL's 'ext' and 'trunc' operators. */
43 #include "cgen/basic-modes.h"
44 #include "cgen/basic-ops.h"
45
46 /* We can't use the default hash size because many bits are used by
47 operands. */
48 #define CGEN_DIS_HASH_SIZE 1
49 #define CGEN_DIS_HASH(buf, value) 0
50 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
51 #define CGEN_VALIDATE_INSN_SUPPORTED
52
53 extern int m32c_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
54
55 #define CGEN_ASM_HASH_SIZE 0xffff
56 #define CGEN_ASM_HASH(mnem) m32c_asm_hash ((mnem))
57
58 /* -- */
59 \f
60 /* -- opc.c */
61 static unsigned int
62 m32c_asm_hash (const char *mnem)
63 {
64 unsigned int h;
65
66 /* The length of the mnemonic for the Jcnd insns is 1. Hash jsri. */
67 if (mnem[0] == 'j' && mnem[1] != 's')
68 return 'j';
69
70 /* Don't hash scCND */
71 if (mnem[0] == 's' && mnem[1] == 'c')
72 return 's';
73
74 /* Don't hash bmCND */
75 if (mnem[0] == 'b' && mnem[1] == 'm')
76 return 'b';
77
78 for (h = 0; *mnem && *mnem != ' ' && *mnem != ':'; ++mnem)
79 h += *mnem;
80 return h % CGEN_ASM_HASH_SIZE;
81 }
82 \f
83 /* -- asm.c */
84 #include "safe-ctype.h"
85
86 #define MACH_M32C 5 /* Must match md_begin. */
87
88 static int
89 m32c_cgen_isa_register (const char **strp)
90 {
91 int u;
92 const char *s = *strp;
93 static char * m32c_register_names [] =
94 {
95 "r0", "r1", "r2", "r3", "r0l", "r0h", "r1l", "r1h",
96 "a0", "a1", "r2r0", "r3r1", "sp", "fb", "dct0", "dct1", "flg", "svf",
97 "drc0", "drc1", "dmd0", "dmd1", "intb", "svp", "vct", "isp", "dma0",
98 "dma1", "dra0", "dra1", "dsa0", "dsa1", 0
99 };
100
101 for (u = 0; m32c_register_names[u]; u++)
102 {
103 int len = strlen (m32c_register_names[u]);
104
105 if (memcmp (m32c_register_names[u], s, len) == 0
106 && (s[len] == 0 || ! ISALNUM (s[len])))
107 return 1;
108 }
109 return 0;
110 }
111
112 #define PARSE_UNSIGNED \
113 do \
114 { \
115 /* Don't successfully parse literals beginning with '['. */ \
116 if (**strp == '[') \
117 return "Invalid literal"; /* Anything -- will not be seen. */ \
118 \
119 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);\
120 if (errmsg) \
121 return errmsg; \
122 } \
123 while (0)
124
125 #define PARSE_SIGNED \
126 do \
127 { \
128 /* Don't successfully parse literals beginning with '['. */ \
129 if (**strp == '[') \
130 return "Invalid literal"; /* Anything -- will not be seen. */ \
131 \
132 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); \
133 if (errmsg) \
134 return errmsg; \
135 } \
136 while (0)
137
138 static const char *
139 parse_unsigned6 (CGEN_CPU_DESC cd, const char **strp,
140 int opindex, unsigned long *valuep)
141 {
142 const char *errmsg = 0;
143 unsigned long value;
144
145 PARSE_UNSIGNED;
146
147 if (value > 0x3f)
148 return _("imm:6 immediate is out of range");
149
150 *valuep = value;
151 return 0;
152 }
153
154 static const char *
155 parse_unsigned8 (CGEN_CPU_DESC cd, const char **strp,
156 int opindex, unsigned long *valuep)
157 {
158 const char *errmsg = 0;
159 unsigned long value;
160 long have_zero = 0;
161
162 if (strncasecmp (*strp, "%dsp8(", 6) == 0)
163 {
164 enum cgen_parse_operand_result result_type;
165 bfd_vma value;
166 const char *errmsg;
167
168 *strp += 6;
169 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_8,
170 & result_type, & value);
171 if (**strp != ')')
172 return _("missing `)'");
173 (*strp) ++;
174
175 if (errmsg == NULL
176 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
177 {
178 return _("%dsp8() takes a symbolic address, not a number");
179 }
180 *valuep = value;
181 return errmsg;
182 }
183
184 if (strncmp (*strp, "0x0", 3) == 0
185 || (**strp == '0' && *(*strp + 1) != 'x'))
186 have_zero = 1;
187
188 PARSE_UNSIGNED;
189
190 if (value > 0xff)
191 return _("dsp:8 immediate is out of range");
192
193 /* If this field may require a relocation then use larger dsp16. */
194 if (! have_zero && value == 0)
195 return _("dsp:8 immediate is out of range");
196
197 *valuep = value;
198 return 0;
199 }
200
201 static const char *
202 parse_signed4 (CGEN_CPU_DESC cd, const char **strp,
203 int opindex, signed long *valuep)
204 {
205 const char *errmsg = 0;
206 signed long value;
207 long have_zero = 0;
208
209 if (strncmp (*strp, "0x0", 3) == 0
210 || (**strp == '0' && *(*strp + 1) != 'x'))
211 have_zero = 1;
212
213 PARSE_SIGNED;
214
215 if (value < -8 || value > 7)
216 return _("Immediate is out of range -8 to 7");
217
218 /* If this field may require a relocation then use larger dsp16. */
219 if (! have_zero && value == 0)
220 return _("Immediate is out of range -8 to 7");
221
222 *valuep = value;
223 return 0;
224 }
225
226 static const char *
227 parse_signed4n (CGEN_CPU_DESC cd, const char **strp,
228 int opindex, signed long *valuep)
229 {
230 const char *errmsg = 0;
231 signed long value;
232 long have_zero = 0;
233
234 if (strncmp (*strp, "0x0", 3) == 0
235 || (**strp == '0' && *(*strp + 1) != 'x'))
236 have_zero = 1;
237
238 PARSE_SIGNED;
239
240 if (value < -7 || value > 8)
241 return _("Immediate is out of range -7 to 8");
242
243 /* If this field may require a relocation then use larger dsp16. */
244 if (! have_zero && value == 0)
245 return _("Immediate is out of range -7 to 8");
246
247 *valuep = -value;
248 return 0;
249 }
250
251 static const char *
252 parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
253 int opindex, signed long *valuep)
254 {
255 const char *errmsg = 0;
256 signed long value;
257
258 if (strncasecmp (*strp, "%hi8(", 5) == 0)
259 {
260 enum cgen_parse_operand_result result_type;
261 bfd_vma value;
262 const char *errmsg;
263
264 *strp += 5;
265 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32C_HI8,
266 & result_type, & value);
267 if (**strp != ')')
268 return _("missing `)'");
269 (*strp) ++;
270
271 if (errmsg == NULL
272 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
273 {
274 value >>= 16;
275 }
276 *valuep = value;
277 return errmsg;
278 }
279
280 PARSE_SIGNED;
281
282 if (value <= 255 && value > 127)
283 value -= 0x100;
284
285 if (value < -128 || value > 127)
286 return _("dsp:8 immediate is out of range");
287
288 *valuep = value;
289 return 0;
290 }
291
292 static const char *
293 parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp,
294 int opindex, unsigned long *valuep)
295 {
296 const char *errmsg = 0;
297 unsigned long value;
298 long have_zero = 0;
299
300 if (strncasecmp (*strp, "%dsp16(", 7) == 0)
301 {
302 enum cgen_parse_operand_result result_type;
303 bfd_vma value;
304 const char *errmsg;
305
306 *strp += 7;
307 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
308 & result_type, & value);
309 if (**strp != ')')
310 return _("missing `)'");
311 (*strp) ++;
312
313 if (errmsg == NULL
314 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
315 {
316 return _("%dsp16() takes a symbolic address, not a number");
317 }
318 *valuep = value;
319 return errmsg;
320 }
321
322 /* Don't successfully parse literals beginning with '['. */
323 if (**strp == '[')
324 return "Invalid literal"; /* Anything -- will not be seen. */
325
326 /* Don't successfully parse register names. */
327 if (m32c_cgen_isa_register (strp))
328 return "Invalid literal"; /* Anything -- will not be seen. */
329
330 if (strncmp (*strp, "0x0", 3) == 0
331 || (**strp == '0' && *(*strp + 1) != 'x'))
332 have_zero = 1;
333
334 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
335 if (errmsg)
336 return errmsg;
337
338 if (value > 0xffff)
339 return _("dsp:16 immediate is out of range");
340
341 /* If this field may require a relocation then use larger dsp24. */
342 if (cd->machs == MACH_M32C && ! have_zero && value == 0
343 && (strncmp (*strp, "[a", 2) == 0
344 || **strp == ','
345 || **strp == 0))
346 return _("dsp:16 immediate is out of range");
347
348 *valuep = value;
349 return 0;
350 }
351
352 static const char *
353 parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
354 int opindex, signed long *valuep)
355 {
356 const char *errmsg = 0;
357 signed long value;
358
359 if (strncasecmp (*strp, "%lo16(", 6) == 0)
360 {
361 enum cgen_parse_operand_result result_type;
362 bfd_vma value;
363 const char *errmsg;
364
365 *strp += 6;
366 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
367 & result_type, & value);
368 if (**strp != ')')
369 return _("missing `)'");
370 (*strp) ++;
371
372 if (errmsg == NULL
373 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
374 {
375 value &= 0xffff;
376 }
377 *valuep = value;
378 return errmsg;
379 }
380
381 if (strncasecmp (*strp, "%hi16(", 6) == 0)
382 {
383 enum cgen_parse_operand_result result_type;
384 bfd_vma value;
385 const char *errmsg;
386
387 *strp += 6;
388 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
389 & result_type, & value);
390 if (**strp != ')')
391 return _("missing `)'");
392 (*strp) ++;
393
394 if (errmsg == NULL
395 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
396 {
397 value >>= 16;
398 }
399 *valuep = value;
400 return errmsg;
401 }
402
403 PARSE_SIGNED;
404
405 if (value <= 65535 && value > 32767)
406 value -= 0x10000;
407
408 if (value < -32768 || value > 32767)
409 return _("dsp:16 immediate is out of range");
410
411 *valuep = value;
412 return 0;
413 }
414
415 static const char *
416 parse_unsigned20 (CGEN_CPU_DESC cd, const char **strp,
417 int opindex, unsigned long *valuep)
418 {
419 const char *errmsg = 0;
420 unsigned long value;
421
422 /* Don't successfully parse literals beginning with '['. */
423 if (**strp == '[')
424 return "Invalid literal"; /* Anything -- will not be seen. */
425
426 /* Don't successfully parse register names. */
427 if (m32c_cgen_isa_register (strp))
428 return "Invalid literal"; /* Anything -- will not be seen. */
429
430 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
431 if (errmsg)
432 return errmsg;
433
434 if (value > 0xfffff)
435 return _("dsp:20 immediate is out of range");
436
437 *valuep = value;
438 return 0;
439 }
440
441 static const char *
442 parse_unsigned24 (CGEN_CPU_DESC cd, const char **strp,
443 int opindex, unsigned long *valuep)
444 {
445 const char *errmsg = 0;
446 unsigned long value;
447
448 /* Don't successfully parse literals beginning with '['. */
449 if (**strp == '[')
450 return "Invalid literal"; /* Anything -- will not be seen. */
451
452 /* Don't successfully parse register names. */
453 if (m32c_cgen_isa_register (strp))
454 return "Invalid literal"; /* Anything -- will not be seen. */
455
456 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
457 if (errmsg)
458 return errmsg;
459
460 if (value > 0xffffff)
461 return _("dsp:24 immediate is out of range");
462
463 *valuep = value;
464 return 0;
465 }
466
467 /* This should only be used for #imm->reg. */
468 static const char *
469 parse_signed24 (CGEN_CPU_DESC cd, const char **strp,
470 int opindex, signed long *valuep)
471 {
472 const char *errmsg = 0;
473 signed long value;
474
475 PARSE_SIGNED;
476
477 if (value <= 0xffffff && value > 0x7fffff)
478 value -= 0x1000000;
479
480 if (value > 0xffffff)
481 return _("dsp:24 immediate is out of range");
482
483 *valuep = value;
484 return 0;
485 }
486
487 static const char *
488 parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
489 int opindex, signed long *valuep)
490 {
491 const char *errmsg = 0;
492 signed long value;
493
494 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
495 if (errmsg)
496 return errmsg;
497
498 *valuep = value;
499 return 0;
500 }
501
502 static const char *
503 parse_imm1_S (CGEN_CPU_DESC cd, const char **strp,
504 int opindex, signed long *valuep)
505 {
506 const char *errmsg = 0;
507 signed long value;
508
509 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
510 if (errmsg)
511 return errmsg;
512
513 if (value < 1 || value > 2)
514 return _("immediate is out of range 1-2");
515
516 *valuep = value;
517 return 0;
518 }
519
520 static const char *
521 parse_imm3_S (CGEN_CPU_DESC cd, const char **strp,
522 int opindex, signed long *valuep)
523 {
524 const char *errmsg = 0;
525 signed long value;
526
527 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
528 if (errmsg)
529 return errmsg;
530
531 if (value < 1 || value > 8)
532 return _("immediate is out of range 1-8");
533
534 *valuep = value;
535 return 0;
536 }
537
538 static const char *
539 parse_bit3_S (CGEN_CPU_DESC cd, const char **strp,
540 int opindex, signed long *valuep)
541 {
542 const char *errmsg = 0;
543 signed long value;
544
545 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
546 if (errmsg)
547 return errmsg;
548
549 if (value < 0 || value > 7)
550 return _("immediate is out of range 0-7");
551
552 *valuep = value;
553 return 0;
554 }
555
556 static const char *
557 parse_lab_5_3 (CGEN_CPU_DESC cd,
558 const char **strp,
559 int opindex ATTRIBUTE_UNUSED,
560 int opinfo,
561 enum cgen_parse_operand_result *type_addr,
562 bfd_vma *valuep)
563 {
564 const char *errmsg = 0;
565 bfd_vma value;
566 enum cgen_parse_operand_result op_res;
567
568 errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
569 opinfo, & op_res, & value);
570
571 if (type_addr)
572 *type_addr = op_res;
573
574 if (op_res == CGEN_PARSE_OPERAND_RESULT_QUEUED)
575 {
576 /* This is a hack; the field cannot handle near-zero signed
577 offsets that CGEN wants to put in to indicate an "empty"
578 operand at first. */
579 *valuep = 2;
580 return 0;
581 }
582 if (errmsg)
583 return errmsg;
584
585 if (value < 2 || value > 9)
586 return _("immediate is out of range 2-9");
587
588 *valuep = value;
589 return 0;
590 }
591
592 static const char *
593 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
594 int opindex, unsigned long *valuep)
595 {
596 const char *errmsg = 0;
597 unsigned long value;
598
599 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
600 if (errmsg)
601 return errmsg;
602
603 if (value > 15)
604 return _("Bit number for indexing general register is out of range 0-15");
605
606 *valuep = value;
607 return 0;
608 }
609
610 static const char *
611 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
612 int opindex, unsigned long *valuep,
613 unsigned bits, int allow_syms)
614 {
615 const char *errmsg = 0;
616 unsigned long bit;
617 unsigned long base;
618 const char *newp = *strp;
619 unsigned long long bitbase;
620 long have_zero = 0;
621
622 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
623 if (errmsg)
624 return errmsg;
625
626 if (*newp != ',')
627 return "Missing base for bit,base:8";
628
629 ++newp;
630
631 if (strncmp (newp, "0x0", 3) == 0
632 || (newp[0] == '0' && newp[1] != 'x'))
633 have_zero = 1;
634
635 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
636 if (errmsg)
637 return errmsg;
638
639 bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
640
641 if (bitbase >= (1ull << bits))
642 return _("bit,base is out of range");
643
644 /* If this field may require a relocation then use larger displacement. */
645 if (! have_zero && base == 0)
646 {
647 switch (allow_syms) {
648 case 0:
649 return _("bit,base out of range for symbol");
650 case 1:
651 break;
652 case 2:
653 if (strncmp (newp, "[sb]", 4) != 0)
654 return _("bit,base out of range for symbol");
655 break;
656 }
657 }
658
659 *valuep = bitbase;
660 *strp = newp;
661 return 0;
662 }
663
664 static const char *
665 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
666 int opindex, signed long *valuep,
667 unsigned bits, int allow_syms)
668 {
669 const char *errmsg = 0;
670 unsigned long bit;
671 signed long base;
672 const char *newp = *strp;
673 long long bitbase;
674 long long limit;
675 long have_zero = 0;
676
677 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
678 if (errmsg)
679 return errmsg;
680
681 if (*newp != ',')
682 return "Missing base for bit,base:8";
683
684 ++newp;
685
686 if (strncmp (newp, "0x0", 3) == 0
687 || (newp[0] == '0' && newp[1] != 'x'))
688 have_zero = 1;
689
690 errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
691 if (errmsg)
692 return errmsg;
693
694 bitbase = (long long)bit + ((long long)base * 8);
695
696 limit = 1ll << (bits - 1);
697 if (bitbase < -limit || bitbase >= limit)
698 return _("bit,base is out of range");
699
700 /* If this field may require a relocation then use larger displacement. */
701 if (! have_zero && base == 0 && ! allow_syms)
702 return _("bit,base out of range for symbol");
703
704 *valuep = bitbase;
705 *strp = newp;
706 return 0;
707 }
708
709 static const char *
710 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
711 int opindex, unsigned long *valuep)
712 {
713 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8, 0);
714 }
715
716 static const char *
717 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
718 int opindex, unsigned long *valuep)
719 {
720 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11, 0);
721 }
722
723 static const char *
724 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
725 int opindex, unsigned long *valuep)
726 {
727 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16, 1);
728 }
729
730 static const char *
731 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
732 int opindex, unsigned long *valuep)
733 {
734 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19, 2);
735 }
736
737 static const char *
738 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
739 int opindex, unsigned long *valuep)
740 {
741 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27, 1);
742 }
743
744 static const char *
745 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
746 int opindex, signed long *valuep)
747 {
748 return parse_signed_bitbase (cd, strp, opindex, valuep, 8, 1);
749 }
750
751 static const char *
752 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
753 int opindex, signed long *valuep)
754 {
755 return parse_signed_bitbase (cd, strp, opindex, valuep, 11, 0);
756 }
757
758 static const char *
759 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
760 int opindex, signed long *valuep)
761 {
762 return parse_signed_bitbase (cd, strp, opindex, valuep, 19, 1);
763 }
764
765 /* Parse the suffix as :<char> or as nothing followed by a whitespace. */
766
767 static const char *
768 parse_suffix (const char **strp, char suffix)
769 {
770 const char *newp = *strp;
771
772 if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
773 newp = *strp + 2;
774
775 if (ISSPACE (*newp))
776 {
777 *strp = newp;
778 return 0;
779 }
780
781 return "Invalid suffix"; /* Anything -- will not be seen. */
782 }
783
784 static const char *
785 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
786 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
787 {
788 return parse_suffix (strp, 's');
789 }
790
791 static const char *
792 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
793 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
794 {
795 return parse_suffix (strp, 'g');
796 }
797
798 static const char *
799 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
800 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
801 {
802 return parse_suffix (strp, 'q');
803 }
804
805 static const char *
806 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
807 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
808 {
809 return parse_suffix (strp, 'z');
810 }
811
812 /* Parse an empty suffix. Fail if the next char is ':'. */
813
814 static const char *
815 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
816 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
817 {
818 if (**strp == ':')
819 return "Unexpected suffix";
820 return 0;
821 }
822
823 static const char *
824 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
825 int opindex ATTRIBUTE_UNUSED, signed long *valuep)
826 {
827 const char *errmsg;
828 signed long value;
829 signed long junk;
830 const char *newp = *strp;
831
832 /* Parse r0[hl]. */
833 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
834 if (errmsg)
835 return errmsg;
836
837 if (*newp != ',')
838 return _("not a valid r0l/r0h pair");
839 ++newp;
840
841 /* Parse the second register in the pair. */
842 if (value == 0) /* r0l */
843 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
844 else
845 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
846 if (errmsg)
847 return errmsg;
848
849 *strp = newp;
850 *valuep = ! value;
851 return 0;
852 }
853
854 /* Accept .b or .w in any case. */
855
856 static const char *
857 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
858 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
859 {
860 if (**strp == '.'
861 && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
862 || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
863 {
864 *strp += 2;
865 return NULL;
866 }
867
868 return _("Invalid size specifier");
869 }
870
871 /* Special check to ensure that instruction exists for given machine. */
872
873 int
874 m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
875 const CGEN_INSN *insn)
876 {
877 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
878 CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
879
880 /* If attributes are absent, assume no restriction. */
881 if (machs == 0)
882 machs = ~0;
883
884 return ((machs & cd->machs)
885 && cgen_bitset_intersect_p (& isas, cd->isas));
886 }
887
888 /* Parse a set of registers, R0,R1,A0,A1,SB,FB. */
889
890 static const char *
891 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
892 const char **strp,
893 int opindex ATTRIBUTE_UNUSED,
894 unsigned long *valuep,
895 int push)
896 {
897 const char *errmsg = 0;
898 int regno = 0;
899
900 *valuep = 0;
901 while (**strp && **strp != ')')
902 {
903 if (**strp == 'r' || **strp == 'R')
904 {
905 ++*strp;
906 regno = **strp - '0';
907 if (regno > 4)
908 errmsg = _("Register number is not valid");
909 }
910 else if (**strp == 'a' || **strp == 'A')
911 {
912 ++*strp;
913 regno = **strp - '0';
914 if (regno > 2)
915 errmsg = _("Register number is not valid");
916 regno = **strp - '0' + 4;
917 }
918
919 else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
920 {
921 regno = 6;
922 ++*strp;
923 }
924
925 else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
926 {
927 regno = 7;
928 ++*strp;
929 }
930
931 if (push) /* Mask is reversed for push. */
932 *valuep |= 0x80 >> regno;
933 else
934 *valuep |= 1 << regno;
935
936 ++*strp;
937 if (**strp == ',')
938 {
939 if (*(*strp + 1) == ')')
940 break;
941 ++*strp;
942 }
943 }
944
945 if (!*strp)
946 errmsg = _("Register list is not valid");
947
948 return errmsg;
949 }
950
951 #define POP 0
952 #define PUSH 1
953
954 static const char *
955 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
956 const char **strp,
957 int opindex ATTRIBUTE_UNUSED,
958 unsigned long *valuep)
959 {
960 return parse_regset (cd, strp, opindex, valuep, POP);
961 }
962
963 static const char *
964 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
965 const char **strp,
966 int opindex ATTRIBUTE_UNUSED,
967 unsigned long *valuep)
968 {
969 return parse_regset (cd, strp, opindex, valuep, PUSH);
970 }
971
972 /* -- dis.c */
973
974 #include "elf/m32c.h"
975 #include "elf-bfd.h"
976
977 /* Always print the short insn format suffix as ':<char>'. */
978
979 static void
980 print_suffix (void * dis_info, char suffix)
981 {
982 disassemble_info *info = dis_info;
983
984 (*info->fprintf_func) (info->stream, ":%c", suffix);
985 }
986
987 static void
988 print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
989 void * dis_info,
990 long value ATTRIBUTE_UNUSED,
991 unsigned int attrs ATTRIBUTE_UNUSED,
992 bfd_vma pc ATTRIBUTE_UNUSED,
993 int length ATTRIBUTE_UNUSED)
994 {
995 print_suffix (dis_info, 's');
996 }
997
998
999 static void
1000 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1001 void * dis_info,
1002 long value ATTRIBUTE_UNUSED,
1003 unsigned int attrs ATTRIBUTE_UNUSED,
1004 bfd_vma pc ATTRIBUTE_UNUSED,
1005 int length ATTRIBUTE_UNUSED)
1006 {
1007 print_suffix (dis_info, 'g');
1008 }
1009
1010 static void
1011 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1012 void * dis_info,
1013 long value ATTRIBUTE_UNUSED,
1014 unsigned int attrs ATTRIBUTE_UNUSED,
1015 bfd_vma pc ATTRIBUTE_UNUSED,
1016 int length ATTRIBUTE_UNUSED)
1017 {
1018 print_suffix (dis_info, 'q');
1019 }
1020
1021 static void
1022 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1023 void * dis_info,
1024 long value ATTRIBUTE_UNUSED,
1025 unsigned int attrs ATTRIBUTE_UNUSED,
1026 bfd_vma pc ATTRIBUTE_UNUSED,
1027 int length ATTRIBUTE_UNUSED)
1028 {
1029 print_suffix (dis_info, 'z');
1030 }
1031
1032 /* Print the empty suffix. */
1033
1034 static void
1035 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1036 void * dis_info ATTRIBUTE_UNUSED,
1037 long value ATTRIBUTE_UNUSED,
1038 unsigned int attrs ATTRIBUTE_UNUSED,
1039 bfd_vma pc ATTRIBUTE_UNUSED,
1040 int length ATTRIBUTE_UNUSED)
1041 {
1042 return;
1043 }
1044
1045 static void
1046 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1047 void * dis_info,
1048 long value,
1049 unsigned int attrs ATTRIBUTE_UNUSED,
1050 bfd_vma pc ATTRIBUTE_UNUSED,
1051 int length ATTRIBUTE_UNUSED)
1052 {
1053 disassemble_info *info = dis_info;
1054
1055 if (value == 0)
1056 (*info->fprintf_func) (info->stream, "r0h,r0l");
1057 else
1058 (*info->fprintf_func) (info->stream, "r0l,r0h");
1059 }
1060
1061 static void
1062 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1063 void * dis_info,
1064 unsigned long value,
1065 unsigned int attrs ATTRIBUTE_UNUSED,
1066 bfd_vma pc ATTRIBUTE_UNUSED,
1067 int length ATTRIBUTE_UNUSED)
1068 {
1069 disassemble_info *info = dis_info;
1070
1071 (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
1072 }
1073
1074 static void
1075 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1076 void * dis_info,
1077 signed long value,
1078 unsigned int attrs ATTRIBUTE_UNUSED,
1079 bfd_vma pc ATTRIBUTE_UNUSED,
1080 int length ATTRIBUTE_UNUSED)
1081 {
1082 disassemble_info *info = dis_info;
1083
1084 (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
1085 }
1086
1087 static void
1088 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1089 void * dis_info,
1090 long value ATTRIBUTE_UNUSED,
1091 unsigned int attrs ATTRIBUTE_UNUSED,
1092 bfd_vma pc ATTRIBUTE_UNUSED,
1093 int length ATTRIBUTE_UNUSED)
1094 {
1095 /* Always print the size as '.w'. */
1096 disassemble_info *info = dis_info;
1097
1098 (*info->fprintf_func) (info->stream, ".w");
1099 }
1100
1101 #define POP 0
1102 #define PUSH 1
1103
1104 static void print_pop_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1105 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1106
1107 /* Print a set of registers, R0,R1,A0,A1,SB,FB. */
1108
1109 static void
1110 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1111 void * dis_info,
1112 long value,
1113 unsigned int attrs ATTRIBUTE_UNUSED,
1114 bfd_vma pc ATTRIBUTE_UNUSED,
1115 int length ATTRIBUTE_UNUSED,
1116 int push)
1117 {
1118 static char * m16c_register_names [] =
1119 {
1120 "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
1121 };
1122 disassemble_info *info = dis_info;
1123 int mask;
1124 int index = 0;
1125 char* comma = "";
1126
1127 if (push)
1128 mask = 0x80;
1129 else
1130 mask = 1;
1131
1132 if (value & mask)
1133 {
1134 (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
1135 comma = ",";
1136 }
1137
1138 for (index = 1; index <= 7; ++index)
1139 {
1140 if (push)
1141 mask >>= 1;
1142 else
1143 mask <<= 1;
1144
1145 if (value & mask)
1146 {
1147 (*info->fprintf_func) (info->stream, "%s%s", comma,
1148 m16c_register_names [index]);
1149 comma = ",";
1150 }
1151 }
1152 }
1153
1154 static void
1155 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1156 void * dis_info,
1157 long value,
1158 unsigned int attrs ATTRIBUTE_UNUSED,
1159 bfd_vma pc ATTRIBUTE_UNUSED,
1160 int length ATTRIBUTE_UNUSED)
1161 {
1162 print_regset (cd, dis_info, value, attrs, pc, length, POP);
1163 }
1164
1165 static void
1166 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1167 void * dis_info,
1168 long value,
1169 unsigned int attrs ATTRIBUTE_UNUSED,
1170 bfd_vma pc ATTRIBUTE_UNUSED,
1171 int length ATTRIBUTE_UNUSED)
1172 {
1173 print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
1174 }
1175
1176 static void
1177 print_signed4n (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1178 void * dis_info,
1179 signed long value,
1180 unsigned int attrs ATTRIBUTE_UNUSED,
1181 bfd_vma pc ATTRIBUTE_UNUSED,
1182 int length ATTRIBUTE_UNUSED)
1183 {
1184 disassemble_info *info = dis_info;
1185
1186 (*info->fprintf_func) (info->stream, "%ld", -value);
1187 }
This page took 0.065286 seconds and 4 git commands to generate.