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