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