Fix %hi() operator for 64-bit hosts.
[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
e729279b
NC
536static const char *
537parse_lab_5_3 (CGEN_CPU_DESC cd,
538 const char **strp,
539 int opindex ATTRIBUTE_UNUSED,
540 int opinfo,
541 enum cgen_parse_operand_result *type_addr,
fd54057a 542 bfd_vma *valuep)
e729279b
NC
543{
544 const char *errmsg = 0;
fd54057a 545 bfd_vma value;
e729279b
NC
546 enum cgen_parse_operand_result op_res;
547
548 errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
549 opinfo, & op_res, & value);
550
551 if (type_addr)
552 *type_addr = op_res;
553
554 if (op_res == CGEN_PARSE_OPERAND_ADDRESS)
555 {
556 /* This is a hack; the field cannot handle near-zero signed
557 offsets that CGEN wants to put in to indicate an "empty"
558 operand at first. */
559 *valuep = 2;
560 return 0;
561 }
562 if (errmsg)
563 return errmsg;
564
565 if (value < 2 || value > 9)
566 return _("immediate is out of range 2-9");
567
568 *valuep = value;
569 return 0;
570}
571
49f58d10
JB
572static const char *
573parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
574 int opindex, unsigned long *valuep)
575{
576 const char *errmsg = 0;
577 unsigned long value;
578
49f58d10
JB
579 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
580 if (errmsg)
581 return errmsg;
582
583 if (value > 15)
584 return _("Bit number for indexing general register is out of range 0-15");
585
586 *valuep = value;
587 return 0;
588}
589
590static const char *
591parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
592 int opindex, unsigned long *valuep,
593 unsigned bits)
594{
595 const char *errmsg = 0;
596 unsigned long bit;
597 unsigned long base;
598 const char *newp = *strp;
599 unsigned long long bitbase;
600
49f58d10
JB
601 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
602 if (errmsg)
603 return errmsg;
604
605 if (*newp != ',')
606 return "Missing base for bit,base:8";
607
608 ++newp;
609 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
610 if (errmsg)
611 return errmsg;
612
e729279b 613 bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
49f58d10
JB
614
615 if (bitbase >= (1ull << bits))
616 return _("bit,base is out of range");
617
618 *valuep = bitbase;
619 *strp = newp;
620 return 0;
621}
622
623static const char *
624parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
625 int opindex, signed long *valuep,
626 unsigned bits)
627{
628 const char *errmsg = 0;
629 unsigned long bit;
630 signed long base;
631 const char *newp = *strp;
632 long long bitbase;
633 long long limit;
634
49f58d10
JB
635 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
636 if (errmsg)
637 return errmsg;
638
639 if (*newp != ',')
640 return "Missing base for bit,base:8";
641
642 ++newp;
643 errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
644 if (errmsg)
645 return errmsg;
646
647 bitbase = (long long)bit + ((long long)base * 8);
648
649 limit = 1ll << (bits - 1);
650 if (bitbase < -limit || bitbase >= limit)
651 return _("bit,base is out of range");
652
653 *valuep = bitbase;
654 *strp = newp;
655 return 0;
656}
657
658static const char *
659parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
660 int opindex, unsigned long *valuep)
661{
662 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8);
663}
664
665static const char *
666parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
667 int opindex, unsigned long *valuep)
668{
669 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11);
670}
671
672static const char *
673parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
674 int opindex, unsigned long *valuep)
675{
676 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16);
677}
678
679static const char *
680parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
681 int opindex, unsigned long *valuep)
682{
683 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19);
684}
685
686static const char *
687parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
688 int opindex, unsigned long *valuep)
689{
690 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27);
691}
692
693static const char *
694parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
695 int opindex, signed long *valuep)
696{
697 return parse_signed_bitbase (cd, strp, opindex, valuep, 8);
698}
699
700static const char *
701parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
702 int opindex, signed long *valuep)
703{
704 return parse_signed_bitbase (cd, strp, opindex, valuep, 11);
705}
706
707static const char *
708parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
709 int opindex, signed long *valuep)
710{
711 return parse_signed_bitbase (cd, strp, opindex, valuep, 19);
712}
713
714/* Parse the suffix as :<char> or as nothing followed by a whitespace. */
e729279b 715
49f58d10
JB
716static const char *
717parse_suffix (const char **strp, char suffix)
718{
719 const char *newp = *strp;
720
e729279b 721 if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
49f58d10
JB
722 newp = *strp + 2;
723
e729279b 724 if (ISSPACE (*newp))
49f58d10
JB
725 {
726 *strp = newp;
727 return 0;
728 }
729
e729279b 730 return "Invalid suffix"; /* Anything -- will not be seen. */
49f58d10
JB
731}
732
733static const char *
734parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
735 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
736{
737 return parse_suffix (strp, 's');
738}
739
740static const char *
741parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
742 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
743{
744 return parse_suffix (strp, 'g');
745}
746
747static const char *
748parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
749 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
750{
751 return parse_suffix (strp, 'q');
752}
753
754static const char *
755parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
756 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
757{
758 return parse_suffix (strp, 'z');
759}
760
761/* Parse an empty suffix. Fail if the next char is ':'. */
e729279b 762
49f58d10
JB
763static const char *
764parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
765 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
766{
767 if (**strp == ':')
768 return "Unexpected suffix";
769 return 0;
770}
771
772static const char *
773parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
774 int opindex ATTRIBUTE_UNUSED, signed long *valuep)
775{
776 const char *errmsg;
777 signed long value;
778 signed long junk;
779 const char *newp = *strp;
780
e729279b 781 /* Parse r0[hl]. */
49f58d10
JB
782 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
783 if (errmsg)
784 return errmsg;
785
786 if (*newp != ',')
e729279b 787 return _("not a valid r0l/r0h pair");
49f58d10
JB
788 ++newp;
789
e729279b 790 /* Parse the second register in the pair. */
49f58d10
JB
791 if (value == 0) /* r0l */
792 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
793 else
794 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
795 if (errmsg)
796 return errmsg;
797
798 *strp = newp;
799 *valuep = ! value;
800 return 0;
801}
802
e729279b
NC
803/* Accept .b or .w in any case. */
804
49f58d10
JB
805static const char *
806parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
807 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
808{
809 if (**strp == '.'
810 && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
811 || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
812 {
813 *strp += 2;
e729279b 814 return NULL;
49f58d10 815 }
e729279b
NC
816
817 return _("Invalid size specifier");
49f58d10
JB
818}
819
e729279b
NC
820/* Special check to ensure that instruction exists for given machine. */
821
49f58d10
JB
822int
823m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
824 const CGEN_INSN *insn)
825{
826 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
95b96521 827 CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
49f58d10 828
e729279b 829 /* If attributes are absent, assume no restriction. */
49f58d10
JB
830 if (machs == 0)
831 machs = ~0;
832
aa260854 833 return ((machs & cd->machs)
95b96521 834 && cgen_bitset_intersect_p (& isas, cd->isas));
49f58d10
JB
835}
836
837/* Parse a set of registers, R0,R1,A0,A1,SB,FB. */
838
839static const char *
840parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
841 const char **strp,
842 int opindex ATTRIBUTE_UNUSED,
843 unsigned long *valuep,
e729279b 844 int push)
49f58d10
JB
845{
846 const char *errmsg = 0;
847 int regno = 0;
848
849 *valuep = 0;
850 while (**strp && **strp != ')')
851 {
852 if (**strp == 'r' || **strp == 'R')
853 {
854 ++*strp;
855 regno = **strp - '0';
856 if (regno > 4)
857 errmsg = _("Register number is not valid");
858 }
859 else if (**strp == 'a' || **strp == 'A')
860 {
861 ++*strp;
862 regno = **strp - '0';
863 if (regno > 2)
864 errmsg = _("Register number is not valid");
865 regno = **strp - '0' + 4;
866 }
867
868 else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
869 {
870 regno = 6;
871 ++*strp;
872 }
873
874 else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
875 {
876 regno = 7;
877 ++*strp;
878 }
879
880 if (push) /* Mask is reversed for push. */
881 *valuep |= 0x80 >> regno;
882 else
883 *valuep |= 1 << regno;
884
885 ++*strp;
886 if (**strp == ',')
887 {
888 if (*(*strp + 1) == ')')
889 break;
890 ++*strp;
891 }
892 }
893
894 if (!*strp)
895 errmsg = _("Register list is not valid");
896
897 return errmsg;
898}
899
e729279b 900#define POP 0
49f58d10
JB
901#define PUSH 1
902
903static const char *
904parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b
NC
905 const char **strp,
906 int opindex ATTRIBUTE_UNUSED,
907 unsigned long *valuep)
49f58d10
JB
908{
909 return parse_regset (cd, strp, opindex, valuep, POP);
910}
911
912static const char *
913parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b
NC
914 const char **strp,
915 int opindex ATTRIBUTE_UNUSED,
916 unsigned long *valuep)
49f58d10
JB
917{
918 return parse_regset (cd, strp, opindex, valuep, PUSH);
919}
920
921/* -- dis.c */
922
923#include "elf/m32c.h"
924#include "elf-bfd.h"
925
e729279b
NC
926/* Always print the short insn format suffix as ':<char>'. */
927
49f58d10 928static void
e729279b 929print_suffix (void * dis_info, char suffix)
49f58d10
JB
930{
931 disassemble_info *info = dis_info;
e729279b 932
49f58d10
JB
933 (*info->fprintf_func) (info->stream, ":%c", suffix);
934}
935
936static void
937print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 938 void * dis_info,
49f58d10
JB
939 long value ATTRIBUTE_UNUSED,
940 unsigned int attrs ATTRIBUTE_UNUSED,
941 bfd_vma pc ATTRIBUTE_UNUSED,
942 int length ATTRIBUTE_UNUSED)
943{
944 print_suffix (dis_info, 's');
945}
946
947
948static void
949print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 950 void * dis_info,
49f58d10
JB
951 long value ATTRIBUTE_UNUSED,
952 unsigned int attrs ATTRIBUTE_UNUSED,
953 bfd_vma pc ATTRIBUTE_UNUSED,
954 int length ATTRIBUTE_UNUSED)
955{
956 print_suffix (dis_info, 'g');
957}
958
959static void
960print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 961 void * dis_info,
49f58d10
JB
962 long value ATTRIBUTE_UNUSED,
963 unsigned int attrs ATTRIBUTE_UNUSED,
964 bfd_vma pc ATTRIBUTE_UNUSED,
965 int length ATTRIBUTE_UNUSED)
966{
967 print_suffix (dis_info, 'q');
968}
969
970static void
971print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 972 void * dis_info,
49f58d10
JB
973 long value ATTRIBUTE_UNUSED,
974 unsigned int attrs ATTRIBUTE_UNUSED,
975 bfd_vma pc ATTRIBUTE_UNUSED,
976 int length ATTRIBUTE_UNUSED)
977{
978 print_suffix (dis_info, 'z');
979}
980
e729279b
NC
981/* Print the empty suffix. */
982
49f58d10
JB
983static void
984print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 985 void * dis_info ATTRIBUTE_UNUSED,
49f58d10
JB
986 long value ATTRIBUTE_UNUSED,
987 unsigned int attrs ATTRIBUTE_UNUSED,
988 bfd_vma pc ATTRIBUTE_UNUSED,
989 int length ATTRIBUTE_UNUSED)
990{
991 return;
992}
993
994static void
995print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 996 void * dis_info,
49f58d10
JB
997 long value,
998 unsigned int attrs ATTRIBUTE_UNUSED,
999 bfd_vma pc ATTRIBUTE_UNUSED,
1000 int length ATTRIBUTE_UNUSED)
1001{
1002 disassemble_info *info = dis_info;
e729279b 1003
49f58d10
JB
1004 if (value == 0)
1005 (*info->fprintf_func) (info->stream, "r0h,r0l");
1006 else
1007 (*info->fprintf_func) (info->stream, "r0l,r0h");
1008}
1009
1010static void
1011print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 1012 void * dis_info,
49f58d10
JB
1013 unsigned long value,
1014 unsigned int attrs ATTRIBUTE_UNUSED,
1015 bfd_vma pc ATTRIBUTE_UNUSED,
1016 int length ATTRIBUTE_UNUSED)
1017{
1018 disassemble_info *info = dis_info;
e729279b 1019
49f58d10
JB
1020 (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
1021}
1022
1023static void
1024print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 1025 void * dis_info,
49f58d10
JB
1026 signed long value,
1027 unsigned int attrs ATTRIBUTE_UNUSED,
1028 bfd_vma pc ATTRIBUTE_UNUSED,
1029 int length ATTRIBUTE_UNUSED)
1030{
1031 disassemble_info *info = dis_info;
e729279b 1032
49f58d10
JB
1033 (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
1034}
1035
1036static void
1037print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b 1038 void * dis_info,
49f58d10
JB
1039 long value ATTRIBUTE_UNUSED,
1040 unsigned int attrs ATTRIBUTE_UNUSED,
1041 bfd_vma pc ATTRIBUTE_UNUSED,
1042 int length ATTRIBUTE_UNUSED)
1043{
e729279b 1044 /* Always print the size as '.w'. */
49f58d10 1045 disassemble_info *info = dis_info;
e729279b 1046
49f58d10
JB
1047 (*info->fprintf_func) (info->stream, ".w");
1048}
1049
e729279b 1050#define POP 0
49f58d10
JB
1051#define PUSH 1
1052
e729279b
NC
1053static void print_pop_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1054static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
49f58d10
JB
1055
1056/* Print a set of registers, R0,R1,A0,A1,SB,FB. */
1057
1058static void
1059print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b
NC
1060 void * dis_info,
1061 long value,
1062 unsigned int attrs ATTRIBUTE_UNUSED,
1063 bfd_vma pc ATTRIBUTE_UNUSED,
1064 int length ATTRIBUTE_UNUSED,
1065 int push)
49f58d10
JB
1066{
1067 static char * m16c_register_names [] =
e729279b
NC
1068 {
1069 "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
1070 };
49f58d10
JB
1071 disassemble_info *info = dis_info;
1072 int mask;
1073 int index = 0;
1074 char* comma = "";
1075
1076 if (push)
1077 mask = 0x80;
1078 else
1079 mask = 1;
1080
1081 if (value & mask)
1082 {
1083 (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
1084 comma = ",";
1085 }
1086
1087 for (index = 1; index <= 7; ++index)
1088 {
1089 if (push)
1090 mask >>= 1;
1091 else
1092 mask <<= 1;
1093
1094 if (value & mask)
1095 {
1096 (*info->fprintf_func) (info->stream, "%s%s", comma,
1097 m16c_register_names [index]);
1098 comma = ",";
1099 }
1100 }
1101}
1102
1103static void
1104print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b
NC
1105 void * dis_info,
1106 long value,
1107 unsigned int attrs ATTRIBUTE_UNUSED,
1108 bfd_vma pc ATTRIBUTE_UNUSED,
1109 int length ATTRIBUTE_UNUSED)
49f58d10
JB
1110{
1111 print_regset (cd, dis_info, value, attrs, pc, length, POP);
1112}
1113
1114static void
1115print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
e729279b
NC
1116 void * dis_info,
1117 long value,
1118 unsigned int attrs ATTRIBUTE_UNUSED,
1119 bfd_vma pc ATTRIBUTE_UNUSED,
1120 int length ATTRIBUTE_UNUSED)
49f58d10
JB
1121{
1122 print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
1123}
c6552317
DD
1124
1125static void
1126print_signed4n (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1127 void * dis_info,
1128 signed long value,
1129 unsigned int attrs ATTRIBUTE_UNUSED,
1130 bfd_vma pc ATTRIBUTE_UNUSED,
1131 int length ATTRIBUTE_UNUSED)
1132{
1133 disassemble_info *info = dis_info;
1134
1135 (*info->fprintf_func) (info->stream, "%ld", -value);
1136}
This page took 0.084075 seconds and 4 git commands to generate.