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