cpu/
[deliverable/binutils-gdb.git] / cpu / m32c.opc
CommitLineData
49f58d10 1/* m32c opcode support. -*- C -*-
0a665bfd 2
aa820537 3 Copyright 2005, 2007, 2009 Free Software Foundation, Inc.
0a665bfd
JB
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
9b201bb5 11 the Free Software Foundation; either version 3 of the License, or
0a665bfd
JB
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. */
23
49f58d10
JB
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"
e729279b 38 <arch>-ibd.h additions use: "-- ibd.h". */
49f58d10
JB
39\f
40/* -- opc.h */
41
42/* Needed for RTL's 'ext' and 'trunc' operators. */
ac1e9eca
DE
43#include "cgen/basic-modes.h"
44#include "cgen/basic-ops.h"
49f58d10
JB
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
53extern 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 */
61static unsigned int
62m32c_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
c6552317
DD
74 /* Don't hash bmCND */
75 if (mnem[0] == 'b' && mnem[1] == 'm')
76 return 'b';
77
49f58d10
JB
78 for (h = 0; *mnem && *mnem != ' ' && *mnem != ':'; ++mnem)
79 h += *mnem;
80 return h % CGEN_ASM_HASH_SIZE;
81}
82\f
83/* -- asm.c */
e729279b 84#include "safe-ctype.h"
49f58d10
JB
85
86#define MACH_M32C 5 /* Must match md_begin. */
87
88static int
89m32c_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
e729279b
NC
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
49f58d10
JB
138static const char *
139parse_unsigned6 (CGEN_CPU_DESC cd, const char **strp,
140 int opindex, unsigned long *valuep)
141{
142 const char *errmsg = 0;
143 unsigned long value;
49f58d10 144
e729279b 145 PARSE_UNSIGNED;
49f58d10
JB
146
147 if (value > 0x3f)
148 return _("imm:6 immediate is out of range");
149
150 *valuep = value;
151 return 0;
152}
153
154static const char *
155parse_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
fd54057a
DD
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
49f58d10
JB
184 if (strncmp (*strp, "0x0", 3) == 0
185 || (**strp == '0' && *(*strp + 1) != 'x'))
186 have_zero = 1;
187
e729279b 188 PARSE_UNSIGNED;
49f58d10
JB
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
201static const char *
202parse_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;
49f58d10
JB
208
209 if (strncmp (*strp, "0x0", 3) == 0
210 || (**strp == '0' && *(*strp + 1) != 'x'))
211 have_zero = 1;
212
e729279b 213 PARSE_SIGNED;
49f58d10
JB
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
c6552317
DD
226static const char *
227parse_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
49f58d10
JB
251static const char *
252parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
253 int opindex, signed long *valuep)
254{
255 const char *errmsg = 0;
256 signed long value;
fd54057a
DD
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
e729279b 280 PARSE_SIGNED;
49f58d10
JB
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
292static const char *
293parse_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;
fd54057a
DD
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
e729279b 322 /* Don't successfully parse literals beginning with '['. */
49f58d10 323 if (**strp == '[')
e729279b 324 return "Invalid literal"; /* Anything -- will not be seen. */
49f58d10 325
e729279b 326 /* Don't successfully parse register names. */
49f58d10 327 if (m32c_cgen_isa_register (strp))
e729279b 328 return "Invalid literal"; /* Anything -- will not be seen. */
49f58d10
JB
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
352static const char *
353parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
354 int opindex, signed long *valuep)
355{
356 const char *errmsg = 0;
357 signed long value;
49f58d10 358
fd54057a
DD
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
e729279b 403 PARSE_SIGNED;
49f58d10
JB
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
415static const char *
416parse_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
e729279b 422 /* Don't successfully parse literals beginning with '['. */
49f58d10 423 if (**strp == '[')
e729279b 424 return "Invalid literal"; /* Anything -- will not be seen. */
49f58d10 425
e729279b 426 /* Don't successfully parse register names. */
49f58d10 427 if (m32c_cgen_isa_register (strp))
e729279b 428 return "Invalid literal"; /* Anything -- will not be seen. */
49f58d10
JB
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
441static const char *
442parse_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
e729279b 448 /* Don't successfully parse literals beginning with '['. */
49f58d10 449 if (**strp == '[')
e729279b 450 return "Invalid literal"; /* Anything -- will not be seen. */
49f58d10 451
e729279b 452 /* Don't successfully parse register names. */
49f58d10 453 if (m32c_cgen_isa_register (strp))
e729279b 454 return "Invalid literal"; /* Anything -- will not be seen. */
49f58d10
JB
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
f75eb1c0
DD
467/* This should only be used for #imm->reg. */
468static const char *
469parse_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
49f58d10
JB
487static const char *
488parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
e729279b 489 int opindex, signed long *valuep)
49f58d10
JB
490{
491 const char *errmsg = 0;
492 signed long value;
493
49f58d10
JB
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
502static const char *
503parse_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;
49f58d10 508
e729279b 509 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
49f58d10
JB
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
520static const char *
521parse_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
e729279b 527 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
49f58d10
JB
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
43aa3bb1
DD
538static const char *
539parse_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
e729279b
NC
556static const char *
557parse_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,
fd54057a 562 bfd_vma *valuep)
e729279b
NC
563{
564 const char *errmsg = 0;
fd54057a 565 bfd_vma value;
e729279b
NC
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
1998a8e0 574 if (op_res == CGEN_PARSE_OPERAND_RESULT_QUEUED)
e729279b
NC
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
49f58d10
JB
592static const char *
593parse_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
49f58d10
JB
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
610static const char *
611parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
612 int opindex, unsigned long *valuep,
e78efa90 613 unsigned bits, int allow_syms)
49f58d10
JB
614{
615 const char *errmsg = 0;
616 unsigned long bit;
617 unsigned long base;
618 const char *newp = *strp;
619 unsigned long long bitbase;
e78efa90 620 long have_zero = 0;
49f58d10 621
49f58d10
JB
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;
e78efa90
DD
630
631 if (strncmp (newp, "0x0", 3) == 0
632 || (newp[0] == '0' && newp[1] != 'x'))
633 have_zero = 1;
634
49f58d10
JB
635 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
636 if (errmsg)
637 return errmsg;
638
e729279b 639 bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
49f58d10
JB
640
641 if (bitbase >= (1ull << bits))
642 return _("bit,base is out of range");
643
e78efa90
DD
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
49f58d10
JB
659 *valuep = bitbase;
660 *strp = newp;
661 return 0;
662}
663
664static const char *
665parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
666 int opindex, signed long *valuep,
e78efa90 667 unsigned bits, int allow_syms)
49f58d10
JB
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;
e78efa90 675 long have_zero = 0;
49f58d10 676
49f58d10
JB
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;
e78efa90
DD
685
686 if (strncmp (newp, "0x0", 3) == 0
687 || (newp[0] == '0' && newp[1] != 'x'))
688 have_zero = 1;
689
49f58d10
JB
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
e78efa90
DD
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
49f58d10
JB
704 *valuep = bitbase;
705 *strp = newp;
706 return 0;
707}
708
709static const char *
710parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
711 int opindex, unsigned long *valuep)
712{
e78efa90 713 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8, 0);
49f58d10
JB
714}
715
716static const char *
717parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
718 int opindex, unsigned long *valuep)
719{
e78efa90 720 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11, 0);
49f58d10
JB
721}
722
723static const char *
724parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
725 int opindex, unsigned long *valuep)
726{
e78efa90 727 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16, 1);
49f58d10
JB
728}
729
730static const char *
731parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
732 int opindex, unsigned long *valuep)
733{
e78efa90 734 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19, 2);
49f58d10
JB
735}
736
737static const char *
738parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
739 int opindex, unsigned long *valuep)
740{
e78efa90 741 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27, 1);
49f58d10
JB
742}
743
744static const char *
745parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
746 int opindex, signed long *valuep)
747{
e78efa90 748 return parse_signed_bitbase (cd, strp, opindex, valuep, 8, 1);
49f58d10
JB
749}
750
751static const char *
752parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
753 int opindex, signed long *valuep)
754{
e78efa90 755 return parse_signed_bitbase (cd, strp, opindex, valuep, 11, 0);
49f58d10
JB
756}
757
758static const char *
759parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
760 int opindex, signed long *valuep)
761{
e78efa90 762 return parse_signed_bitbase (cd, strp, opindex, valuep, 19, 1);
49f58d10
JB
763}
764
765/* Parse the suffix as :<char> or as nothing followed by a whitespace. */
e729279b 766
49f58d10
JB
767static const char *
768parse_suffix (const char **strp, char suffix)
769{
770 const char *newp = *strp;
771
e729279b 772 if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
49f58d10
JB
773 newp = *strp + 2;
774
e729279b 775 if (ISSPACE (*newp))
49f58d10
JB
776 {
777 *strp = newp;
778 return 0;
779 }
780
e729279b 781 return "Invalid suffix"; /* Anything -- will not be seen. */
49f58d10
JB
782}
783
784static const char *
785parse_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
791static const char *
792parse_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
798static const char *
799parse_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
805static const char *
806parse_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 ':'. */
e729279b 813
49f58d10
JB
814static const char *
815parse_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
823static const char *
824parse_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
e729279b 832 /* Parse r0[hl]. */
49f58d10
JB
833 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
834 if (errmsg)
835 return errmsg;
836
837 if (*newp != ',')
e729279b 838 return _("not a valid r0l/r0h pair");
49f58d10
JB
839 ++newp;
840
e729279b 841 /* Parse the second register in the pair. */
49f58d10
JB
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
e729279b
NC
854/* Accept .b or .w in any case. */
855
49f58d10
JB
856static const char *
857parse_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;
e729279b 865 return NULL;
49f58d10 866 }
e729279b
NC
867
868 return _("Invalid size specifier");
49f58d10
JB
869}
870
e729279b
NC
871/* Special check to ensure that instruction exists for given machine. */
872
49f58d10
JB
873int
874m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
875 const CGEN_INSN *insn)
876{
877 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
95b96521 878 CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
49f58d10 879
e729279b 880 /* If attributes are absent, assume no restriction. */
49f58d10
JB
881 if (machs == 0)
882 machs = ~0;
883
aa260854 884 return ((machs & cd->machs)
95b96521 885 && cgen_bitset_intersect_p (& isas, cd->isas));
49f58d10
JB
886}
887
888/* Parse a set of registers, R0,R1,A0,A1,SB,FB. */
889
890static const char *
891parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
892 const char **strp,
893 int opindex ATTRIBUTE_UNUSED,
894 unsigned long *valuep,
e729279b 895 int push)
49f58d10
JB
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
e729279b 951#define POP 0
49f58d10
JB
952#define PUSH 1
953
954static const char *
955parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b
NC
956 const char **strp,
957 int opindex ATTRIBUTE_UNUSED,
958 unsigned long *valuep)
49f58d10
JB
959{
960 return parse_regset (cd, strp, opindex, valuep, POP);
961}
962
963static const char *
964parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b
NC
965 const char **strp,
966 int opindex ATTRIBUTE_UNUSED,
967 unsigned long *valuep)
49f58d10
JB
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
e729279b
NC
977/* Always print the short insn format suffix as ':<char>'. */
978
49f58d10 979static void
e729279b 980print_suffix (void * dis_info, char suffix)
49f58d10
JB
981{
982 disassemble_info *info = dis_info;
e729279b 983
49f58d10
JB
984 (*info->fprintf_func) (info->stream, ":%c", suffix);
985}
986
987static void
988print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 989 void * dis_info,
49f58d10
JB
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
999static void
1000print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 1001 void * dis_info,
49f58d10
JB
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
1010static void
1011print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 1012 void * dis_info,
49f58d10
JB
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
1021static void
1022print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 1023 void * dis_info,
49f58d10
JB
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
e729279b
NC
1032/* Print the empty suffix. */
1033
49f58d10
JB
1034static void
1035print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 1036 void * dis_info ATTRIBUTE_UNUSED,
49f58d10
JB
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
1045static void
1046print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 1047 void * dis_info,
49f58d10
JB
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;
e729279b 1054
49f58d10
JB
1055 if (value == 0)
1056 (*info->fprintf_func) (info->stream, "r0h,r0l");
1057 else
1058 (*info->fprintf_func) (info->stream, "r0l,r0h");
1059}
1060
1061static void
1062print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 1063 void * dis_info,
49f58d10
JB
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;
e729279b 1070
49f58d10
JB
1071 (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
1072}
1073
1074static void
1075print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 1076 void * dis_info,
49f58d10
JB
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;
e729279b 1083
49f58d10
JB
1084 (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
1085}
1086
1087static void
1088print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 1089 void * dis_info,
49f58d10
JB
1090 long value ATTRIBUTE_UNUSED,
1091 unsigned int attrs ATTRIBUTE_UNUSED,
1092 bfd_vma pc ATTRIBUTE_UNUSED,
1093 int length ATTRIBUTE_UNUSED)
1094{
e729279b 1095 /* Always print the size as '.w'. */
49f58d10 1096 disassemble_info *info = dis_info;
e729279b 1097
49f58d10
JB
1098 (*info->fprintf_func) (info->stream, ".w");
1099}
1100
e729279b 1101#define POP 0
49f58d10
JB
1102#define PUSH 1
1103
e729279b
NC
1104static void print_pop_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1105static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
49f58d10
JB
1106
1107/* Print a set of registers, R0,R1,A0,A1,SB,FB. */
1108
1109static void
1110print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b
NC
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)
49f58d10
JB
1117{
1118 static char * m16c_register_names [] =
e729279b
NC
1119 {
1120 "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
1121 };
49f58d10
JB
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
1154static void
1155print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b
NC
1156 void * dis_info,
1157 long value,
1158 unsigned int attrs ATTRIBUTE_UNUSED,
1159 bfd_vma pc ATTRIBUTE_UNUSED,
1160 int length ATTRIBUTE_UNUSED)
49f58d10
JB
1161{
1162 print_regset (cd, dis_info, value, attrs, pc, length, POP);
1163}
1164
1165static void
1166print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b
NC
1167 void * dis_info,
1168 long value,
1169 unsigned int attrs ATTRIBUTE_UNUSED,
1170 bfd_vma pc ATTRIBUTE_UNUSED,
1171 int length ATTRIBUTE_UNUSED)
49f58d10
JB
1172{
1173 print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
1174}
c6552317
DD
1175
1176static void
1177print_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.212912 seconds and 4 git commands to generate.