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