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