Home | History | Annotate | Download | only in cpu
      1 /* m32c opcode support.  -*- C -*-
      2 
      3    Copyright 2005, 2007, 2009, 2010 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 3 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,
     22    MA 02110-1301, USA.  */
     23 
     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"
     38    <arch>-ibd.h additions use: "-- ibd.h".  */
     39 
     40 /* -- opc.h */
     42 
     43 /* Needed for RTL's 'ext' and 'trunc' operators.  */
     44 #include "cgen/basic-modes.h"
     45 #include "cgen/basic-ops.h"
     46 
     47 /* We can't use the default hash size because many bits are used by
     48    operands.  */
     49 #define CGEN_DIS_HASH_SIZE 1
     50 #define CGEN_DIS_HASH(buf, value) 0
     51 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
     52 #define CGEN_VALIDATE_INSN_SUPPORTED
     53 
     54 extern int m32c_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
     55 
     56 #define CGEN_ASM_HASH_SIZE 0xffff
     57 #define CGEN_ASM_HASH(mnem) m32c_asm_hash ((mnem))
     58 
     59 /* -- */
     60 
     61 /* -- opc.c */
     63 static unsigned int
     64 m32c_asm_hash (const char *mnem)
     65 {
     66   unsigned int h;
     67 
     68   /* The length of the mnemonic for the Jcnd insns is 1.  Hash jsri.  */
     69   if (mnem[0] == 'j' && mnem[1] != 's')
     70     return 'j';
     71 
     72   /* Don't hash scCND  */
     73   if (mnem[0] == 's' && mnem[1] == 'c')
     74     return 's';
     75 
     76   /* Don't hash bmCND  */
     77   if (mnem[0] == 'b' && mnem[1] == 'm')
     78     return 'b';
     79 
     80   for (h = 0; *mnem && *mnem != ' ' && *mnem != ':'; ++mnem)
     81     h += *mnem;
     82   return h % CGEN_ASM_HASH_SIZE;
     83 }
     84 
     85 /* -- asm.c */
     87 #include "safe-ctype.h"
     88 
     89 #define MACH_M32C 5		/* Must match md_begin.  */
     90 
     91 static int
     92 m32c_cgen_isa_register (const char **strp)
     93  {
     94    int u;
     95    const char *s = *strp;
     96    static char * m32c_register_names [] =
     97      {
     98        "r0", "r1", "r2", "r3", "r0l", "r0h", "r1l", "r1h",
     99        "a0", "a1", "r2r0", "r3r1", "sp", "fb", "dct0", "dct1", "flg", "svf",
    100        "drc0", "drc1", "dmd0", "dmd1", "intb", "svp", "vct", "isp", "dma0",
    101        "dma1", "dra0", "dra1", "dsa0", "dsa1", 0
    102      };
    103 
    104    for (u = 0; m32c_register_names[u]; u++)
    105      {
    106        int len = strlen (m32c_register_names[u]);
    107 
    108        if (memcmp (m32c_register_names[u], s, len) == 0
    109 	   && (s[len] == 0 || ! ISALNUM (s[len])))
    110         return 1;
    111      }
    112    return 0;
    113 }
    114 
    115 #define PARSE_UNSIGNED							\
    116   do									\
    117     {									\
    118       /* Don't successfully parse literals beginning with '['.  */	\
    119       if (**strp == '[')						\
    120 	return "Invalid literal"; /* Anything -- will not be seen.  */	\
    121 									\
    122       errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);\
    123       if (errmsg)							\
    124 	return errmsg;							\
    125     }									\
    126   while (0)
    127 
    128 #define PARSE_SIGNED							\
    129   do									\
    130     {									\
    131       /* Don't successfully parse literals beginning with '['.  */	\
    132       if (**strp == '[')						\
    133 	return "Invalid literal"; /* Anything -- will not be seen.  */	\
    134 									\
    135       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);  \
    136       if (errmsg)							\
    137 	return errmsg;							\
    138     }									\
    139   while (0)
    140 
    141 static const char *
    142 parse_unsigned6 (CGEN_CPU_DESC cd, const char **strp,
    143 		 int opindex, unsigned long *valuep)
    144 {
    145   const char *errmsg = 0;
    146   unsigned long value;
    147 
    148   PARSE_UNSIGNED;
    149 
    150   if (value > 0x3f)
    151     return _("imm:6 immediate is out of range");
    152 
    153   *valuep = value;
    154   return 0;
    155 }
    156 
    157 static const char *
    158 parse_unsigned8 (CGEN_CPU_DESC cd, const char **strp,
    159 		 int opindex, unsigned long *valuep)
    160 {
    161   const char *errmsg = 0;
    162   unsigned long value = 0;
    163   long have_zero = 0;
    164 
    165   if (strncasecmp (*strp, "%dsp8(", 6) == 0)
    166     {
    167       enum cgen_parse_operand_result result_type;
    168       bfd_vma val;
    169 
    170       *strp += 6;
    171       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_8,
    172 				   & result_type, & val);
    173       if (**strp != ')')
    174 	return _("missing `)'");
    175       (*strp) ++;
    176 
    177       if (errmsg == NULL
    178   	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    179 	return _("%dsp8() takes a symbolic address, not a number");
    180 
    181       value = val;
    182       *valuep = value;
    183       return errmsg;
    184     }
    185 
    186   if (strncmp (*strp, "0x0", 3) == 0
    187       || (**strp == '0' && *(*strp + 1) != 'x'))
    188     have_zero = 1;
    189 
    190   PARSE_UNSIGNED;
    191 
    192   if (value > 0xff)
    193     return _("dsp:8 immediate is out of range");
    194 
    195   /* If this field may require a relocation then use larger dsp16.  */
    196   if (! have_zero && value == 0)
    197     return _("dsp:8 immediate is out of range");
    198 
    199   *valuep = value;
    200   return 0;
    201 }
    202 
    203 static const char *
    204 parse_signed4 (CGEN_CPU_DESC cd, const char **strp,
    205 	       int opindex, signed long *valuep)
    206 {
    207   const char *errmsg = 0;
    208   signed long value;
    209   long have_zero = 0;
    210 
    211   if (strncmp (*strp, "0x0", 3) == 0
    212       || (**strp == '0' && *(*strp + 1) != 'x'))
    213     have_zero = 1;
    214 
    215   PARSE_SIGNED;
    216 
    217   if (value < -8 || value > 7)
    218     return _("Immediate is out of range -8 to 7");
    219 
    220   /* If this field may require a relocation then use larger dsp16.  */
    221   if (! have_zero && value == 0)
    222     return _("Immediate is out of range -8 to 7");
    223 
    224   *valuep = value;
    225   return 0;
    226 }
    227 
    228 static const char *
    229 parse_signed4n (CGEN_CPU_DESC cd, const char **strp,
    230 		int opindex, signed long *valuep)
    231 {
    232   const char *errmsg = 0;
    233   signed long value;
    234   long have_zero = 0;
    235 
    236   if (strncmp (*strp, "0x0", 3) == 0
    237       || (**strp == '0' && *(*strp + 1) != 'x'))
    238     have_zero = 1;
    239 
    240   PARSE_SIGNED;
    241 
    242   if (value < -7 || value > 8)
    243     return _("Immediate is out of range -7 to 8");
    244 
    245   /* If this field may require a relocation then use larger dsp16.  */
    246   if (! have_zero && value == 0)
    247     return _("Immediate is out of range -7 to 8");
    248 
    249   *valuep = -value;
    250   return 0;
    251 }
    252 
    253 static const char *
    254 parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
    255 	       int opindex, signed long *valuep)
    256 {
    257   const char *errmsg = 0;
    258   signed long value = 0;
    259 
    260   if (strncasecmp (*strp, "%hi8(", 5) == 0)
    261     {
    262       enum cgen_parse_operand_result result_type;
    263       bfd_vma val;
    264 
    265       *strp += 5;
    266       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32C_HI8,
    267 				   & result_type, & val);
    268       if (**strp != ')')
    269 	return _("missing `)'");
    270       (*strp) ++;
    271 
    272       if (errmsg == NULL
    273   	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    274 	val >>= 16;
    275 
    276       value = val;
    277       *valuep = value;
    278       return errmsg;
    279     }
    280 
    281   PARSE_SIGNED;
    282 
    283   if (value <= 255 && value > 127)
    284     value -= 0x100;
    285 
    286   if (value < -128 || value > 127)
    287     return _("dsp:8 immediate is out of range");
    288 
    289   *valuep = value;
    290   return 0;
    291 }
    292 
    293 static const char *
    294 parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp,
    295 		 int opindex, unsigned long *valuep)
    296 {
    297   const char *errmsg = 0;
    298   unsigned long value = 0;
    299   long have_zero = 0;
    300 
    301   if (strncasecmp (*strp, "%dsp16(", 7) == 0)
    302     {
    303       enum cgen_parse_operand_result result_type;
    304       bfd_vma val;
    305 
    306       *strp += 7;
    307       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
    308 				   & result_type, & val);
    309       if (**strp != ')')
    310 	return _("missing `)'");
    311       (*strp) ++;
    312 
    313       if (errmsg == NULL
    314   	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    315 	return _("%dsp16() takes a symbolic address, not a number");
    316 
    317       value = val;
    318       *valuep = value;
    319       return errmsg;
    320     }
    321 
    322   /* Don't successfully parse literals beginning with '['.  */
    323   if (**strp == '[')
    324     return "Invalid literal"; /* Anything -- will not be seen.  */
    325 
    326   /* Don't successfully parse register names.  */
    327   if (m32c_cgen_isa_register (strp))
    328     return "Invalid literal"; /* Anything -- will not be seen.  */
    329 
    330   if (strncmp (*strp, "0x0", 3) == 0
    331       || (**strp == '0' && *(*strp + 1) != 'x'))
    332     have_zero = 1;
    333 
    334   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
    335   if (errmsg)
    336     return errmsg;
    337 
    338   if (value > 0xffff)
    339     return _("dsp:16 immediate is out of range");
    340 
    341   /* If this field may require a relocation then use larger dsp24.  */
    342   if (cd->machs == MACH_M32C && ! have_zero && value == 0
    343       && (strncmp (*strp, "[a", 2) == 0
    344 	  || **strp == ','
    345 	  || **strp == 0))
    346     return _("dsp:16 immediate is out of range");
    347 
    348   *valuep = value;
    349   return 0;
    350 }
    351 
    352 static const char *
    353 parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
    354 	       int opindex, signed long *valuep)
    355 {
    356   const char *errmsg = 0;
    357   signed long value = 0;
    358 
    359   if (strncasecmp (*strp, "%lo16(", 6) == 0)
    360     {
    361       enum cgen_parse_operand_result result_type;
    362       bfd_vma val;
    363 
    364       *strp += 6;
    365       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
    366 				   & result_type, & val);
    367       if (**strp != ')')
    368 	return _("missing `)'");
    369       (*strp) ++;
    370 
    371       if (errmsg == NULL
    372   	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    373 	val &= 0xffff;
    374 
    375       value = val;
    376       *valuep = value;
    377       return errmsg;
    378     }
    379 
    380   if (strncasecmp (*strp, "%hi16(", 6) == 0)
    381     {
    382       enum cgen_parse_operand_result result_type;
    383       bfd_vma val;
    384 
    385       *strp += 6;
    386       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
    387 				   & result_type, & val);
    388       if (**strp != ')')
    389 	return _("missing `)'");
    390       (*strp) ++;
    391 
    392       if (errmsg == NULL
    393   	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    394 	val >>= 16;
    395 
    396       value = val;
    397       *valuep = value;
    398       return errmsg;
    399     }
    400 
    401   PARSE_SIGNED;
    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 
    413 static const char *
    414 parse_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 
    420   /* Don't successfully parse literals beginning with '['.  */
    421   if (**strp == '[')
    422     return "Invalid literal"; /* Anything -- will not be seen.  */
    423 
    424   /* Don't successfully parse register names.  */
    425   if (m32c_cgen_isa_register (strp))
    426     return "Invalid literal"; /* Anything -- will not be seen.  */
    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 
    439 static const char *
    440 parse_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 
    446   /* Don't successfully parse literals beginning with '['.  */
    447   if (**strp == '[')
    448     return "Invalid literal"; /* Anything -- will not be seen.  */
    449 
    450   /* Don't successfully parse register names.  */
    451   if (m32c_cgen_isa_register (strp))
    452     return "Invalid literal"; /* Anything -- will not be seen.  */
    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 
    465 /* This should only be used for #imm->reg.  */
    466 static const char *
    467 parse_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 
    485 static const char *
    486 parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
    487 		int opindex, signed long *valuep)
    488 {
    489   const char *errmsg = 0;
    490   signed long value;
    491 
    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 
    500 static const char *
    501 parse_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;
    506 
    507   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
    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 
    518 static const char *
    519 parse_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 
    525   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
    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 
    536 static const char *
    537 parse_bit3_S (CGEN_CPU_DESC cd, const char **strp,
    538 	     int opindex, signed long *valuep)
    539 {
    540   const char *errmsg = 0;
    541   signed long value;
    542 
    543   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
    544   if (errmsg)
    545     return errmsg;
    546 
    547   if (value < 0 || value > 7)
    548     return _("immediate is out of range 0-7");
    549 
    550   *valuep = value;
    551   return 0;
    552 }
    553 
    554 static const char *
    555 parse_lab_5_3 (CGEN_CPU_DESC cd,
    556 	       const char **strp,
    557 	       int opindex ATTRIBUTE_UNUSED,
    558 	       int opinfo,
    559 	       enum cgen_parse_operand_result *type_addr,
    560 	       bfd_vma *valuep)
    561 {
    562   const char *errmsg = 0;
    563   bfd_vma value;
    564   enum cgen_parse_operand_result op_res;
    565 
    566   errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
    567 			       opinfo, & op_res, & value);
    568 
    569   if (type_addr)
    570     *type_addr = op_res;
    571 
    572   if (op_res == CGEN_PARSE_OPERAND_RESULT_QUEUED)
    573     {
    574       /* This is a hack; the field cannot handle near-zero signed
    575 	 offsets that CGEN wants to put in to indicate an "empty"
    576 	 operand at first.  */
    577       *valuep = 2;
    578       return 0;
    579     }
    580   if (errmsg)
    581     return errmsg;
    582 
    583   if (value < 2 || value > 9)
    584     return _("immediate is out of range 2-9");
    585 
    586   *valuep = value;
    587   return 0;
    588 }
    589 
    590 static const char *
    591 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
    592 		int opindex, unsigned long *valuep)
    593 {
    594   const char *errmsg = 0;
    595   unsigned long value;
    596 
    597   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
    598   if (errmsg)
    599     return errmsg;
    600 
    601   if (value > 15)
    602     return _("Bit number for indexing general register is out of range 0-15");
    603 
    604   *valuep = value;
    605   return 0;
    606 }
    607 
    608 static const char *
    609 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
    610 			int opindex, unsigned long *valuep,
    611 			unsigned bits, int allow_syms)
    612 {
    613   const char *errmsg = 0;
    614   unsigned long bit;
    615   unsigned long base;
    616   const char *newp = *strp;
    617   unsigned long long bitbase;
    618   long have_zero = 0;
    619 
    620   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
    621   if (errmsg)
    622     return errmsg;
    623 
    624   if (*newp != ',')
    625     return "Missing base for bit,base:8";
    626 
    627   ++newp;
    628 
    629   if (strncmp (newp, "0x0", 3) == 0
    630       || (newp[0] == '0' && newp[1] != 'x'))
    631     have_zero = 1;
    632 
    633   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
    634   if (errmsg)
    635     return errmsg;
    636 
    637   bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
    638 
    639   if (bitbase >= (1ull << bits))
    640     return _("bit,base is out of range");
    641 
    642   /* If this field may require a relocation then use larger displacement.  */
    643   if (! have_zero && base == 0)
    644     {
    645       switch (allow_syms) {
    646       case 0:
    647 	return _("bit,base out of range for symbol");
    648       case 1:
    649 	break;
    650       case 2:
    651 	if (strncmp (newp, "[sb]", 4) != 0)
    652 	  return _("bit,base out of range for symbol");
    653 	break;
    654       }
    655     }
    656 
    657   *valuep = bitbase;
    658   *strp = newp;
    659   return 0;
    660 }
    661 
    662 static const char *
    663 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
    664 		      int opindex, signed long *valuep,
    665 		      unsigned bits, int allow_syms)
    666 {
    667   const char *errmsg = 0;
    668   unsigned long bit;
    669   signed long base;
    670   const char *newp = *strp;
    671   long long bitbase;
    672   long long limit;
    673   long have_zero = 0;
    674 
    675   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
    676   if (errmsg)
    677     return errmsg;
    678 
    679   if (*newp != ',')
    680     return "Missing base for bit,base:8";
    681 
    682   ++newp;
    683 
    684   if (strncmp (newp, "0x0", 3) == 0
    685       || (newp[0] == '0' && newp[1] != 'x'))
    686     have_zero = 1;
    687 
    688   errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
    689   if (errmsg)
    690     return errmsg;
    691 
    692   bitbase = (long long)bit + ((long long)base * 8);
    693 
    694   limit = 1ll << (bits - 1);
    695   if (bitbase < -limit || bitbase >= limit)
    696     return _("bit,base is out of range");
    697 
    698   /* If this field may require a relocation then use larger displacement.  */
    699   if (! have_zero && base == 0 && ! allow_syms)
    700     return _("bit,base out of range for symbol");
    701 
    702   *valuep = bitbase;
    703   *strp = newp;
    704   return 0;
    705 }
    706 
    707 static const char *
    708 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
    709 			 int opindex, unsigned long *valuep)
    710 {
    711   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8, 0);
    712 }
    713 
    714 static const char *
    715 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
    716 			 int opindex, unsigned long *valuep)
    717 {
    718   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11, 0);
    719 }
    720 
    721 static const char *
    722 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
    723 			  int opindex, unsigned long *valuep)
    724 {
    725   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16, 1);
    726 }
    727 
    728 static const char *
    729 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
    730 			 int opindex, unsigned long *valuep)
    731 {
    732   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19, 2);
    733 }
    734 
    735 static const char *
    736 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
    737 			 int opindex, unsigned long *valuep)
    738 {
    739   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27, 1);
    740 }
    741 
    742 static const char *
    743 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
    744 		       int opindex, signed long *valuep)
    745 {
    746   return parse_signed_bitbase (cd, strp, opindex, valuep, 8, 1);
    747 }
    748 
    749 static const char *
    750 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
    751 		       int opindex, signed long *valuep)
    752 {
    753   return parse_signed_bitbase (cd, strp, opindex, valuep, 11, 0);
    754 }
    755 
    756 static const char *
    757 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
    758 		       int opindex, signed long *valuep)
    759 {
    760   return parse_signed_bitbase (cd, strp, opindex, valuep, 19, 1);
    761 }
    762 
    763 /* Parse the suffix as :<char> or as nothing followed by a whitespace.  */
    764 
    765 static const char *
    766 parse_suffix (const char **strp, char suffix)
    767 {
    768   const char *newp = *strp;
    769 
    770   if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
    771     newp = *strp + 2;
    772 
    773   if (ISSPACE (*newp))
    774     {
    775       *strp = newp;
    776       return 0;
    777     }
    778 
    779   return "Invalid suffix"; /* Anything -- will not be seen.  */
    780 }
    781 
    782 static const char *
    783 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
    784 	 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
    785 {
    786   return parse_suffix (strp, 's');
    787 }
    788 
    789 static const char *
    790 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
    791 	 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
    792 {
    793   return parse_suffix (strp, 'g');
    794 }
    795 
    796 static const char *
    797 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
    798 	 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
    799 {
    800   return parse_suffix (strp, 'q');
    801 }
    802 
    803 static const char *
    804 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
    805 	 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
    806 {
    807   return parse_suffix (strp, 'z');
    808 }
    809 
    810 /* Parse an empty suffix. Fail if the next char is ':'.  */
    811 
    812 static const char *
    813 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
    814 	 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
    815 {
    816   if (**strp == ':')
    817     return "Unexpected suffix";
    818   return 0;
    819 }
    820 
    821 static const char *
    822 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
    823 	       int opindex ATTRIBUTE_UNUSED, signed long *valuep)
    824 {
    825   const char *errmsg;
    826   signed long value;
    827   signed long junk;
    828   const char *newp = *strp;
    829 
    830   /* Parse r0[hl].  */
    831   errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
    832   if (errmsg)
    833     return errmsg;
    834 
    835   if (*newp != ',')
    836     return _("not a valid r0l/r0h pair");
    837   ++newp;
    838 
    839   /* Parse the second register in the pair.  */
    840   if (value == 0) /* r0l */
    841     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
    842   else
    843     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
    844   if (errmsg)
    845     return errmsg;
    846 
    847   *strp = newp;
    848   *valuep = ! value;
    849   return 0;
    850 }
    851 
    852 /* Accept .b or .w in any case.  */
    853 
    854 static const char *
    855 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
    856 	    int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
    857 {
    858   if (**strp == '.'
    859       && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
    860 	  || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
    861     {
    862       *strp += 2;
    863       return NULL;
    864     }
    865 
    866   return _("Invalid size specifier");
    867 }
    868 
    869 /* Special check to ensure that instruction exists for given machine.  */
    870 
    871 int
    872 m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
    873 			  const CGEN_INSN *insn)
    874 {
    875   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
    876   CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
    877 
    878   /* If attributes are absent, assume no restriction.  */
    879   if (machs == 0)
    880     machs = ~0;
    881 
    882   return ((machs & cd->machs)
    883           && cgen_bitset_intersect_p (& isas, cd->isas));
    884 }
    885 
    886 /* Parse a set of registers, R0,R1,A0,A1,SB,FB.  */
    887 
    888 static const char *
    889 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    890 	      const char **strp,
    891 	      int opindex ATTRIBUTE_UNUSED,
    892 	      unsigned long *valuep,
    893 	      int push)
    894 {
    895   const char *errmsg = 0;
    896   int regno = 0;
    897 
    898   *valuep = 0;
    899   while (**strp && **strp != ')')
    900     {
    901       if (**strp == 'r' || **strp == 'R')
    902 	{
    903 	  ++*strp;
    904 	  regno = **strp - '0';
    905 	  if (regno > 4)
    906 	    errmsg = _("Register number is not valid");
    907 	}
    908       else if (**strp == 'a' || **strp == 'A')
    909 	{
    910 	  ++*strp;
    911 	  regno = **strp - '0';
    912 	  if (regno > 2)
    913 	    errmsg = _("Register number is not valid");
    914 	  regno = **strp - '0' + 4;
    915 	}
    916 
    917       else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
    918 	{
    919 	  regno = 6;
    920 	  ++*strp;
    921 	}
    922 
    923       else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
    924 	{
    925 	  regno = 7;
    926 	  ++*strp;
    927 	}
    928 
    929       if (push) /* Mask is reversed for push.  */
    930 	*valuep |= 0x80 >> regno;
    931       else
    932 	*valuep |= 1 << regno;
    933 
    934       ++*strp;
    935       if (**strp == ',')
    936         {
    937           if (*(*strp + 1) == ')')
    938             break;
    939           ++*strp;
    940         }
    941     }
    942 
    943   if (!*strp)
    944     errmsg = _("Register list is not valid");
    945 
    946   return errmsg;
    947 }
    948 
    949 #define POP  0
    950 #define PUSH 1
    951 
    952 static const char *
    953 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    954 		  const char **strp,
    955 		  int opindex ATTRIBUTE_UNUSED,
    956 		  unsigned long *valuep)
    957 {
    958   return parse_regset (cd, strp, opindex, valuep, POP);
    959 }
    960 
    961 static const char *
    962 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    963 		   const char **strp,
    964 		   int opindex ATTRIBUTE_UNUSED,
    965 		   unsigned long *valuep)
    966 {
    967   return parse_regset (cd, strp, opindex, valuep, PUSH);
    968 }
    969 
    970 /* -- dis.c */
    971 
    972 #include "elf/m32c.h"
    973 #include "elf-bfd.h"
    974 
    975 /* Always print the short insn format suffix as ':<char>'.  */
    976 
    977 static void
    978 print_suffix (void * dis_info, char suffix)
    979 {
    980   disassemble_info *info = dis_info;
    981 
    982   (*info->fprintf_func) (info->stream, ":%c", suffix);
    983 }
    984 
    985 static void
    986 print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    987 	 void * dis_info,
    988 	 long value ATTRIBUTE_UNUSED,
    989 	 unsigned int attrs ATTRIBUTE_UNUSED,
    990 	 bfd_vma pc ATTRIBUTE_UNUSED,
    991 	 int length ATTRIBUTE_UNUSED)
    992 {
    993   print_suffix (dis_info, 's');
    994 }
    995 
    996 
    997 static void
    998 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    999 	 void * dis_info,
   1000 	 long value ATTRIBUTE_UNUSED,
   1001 	 unsigned int attrs ATTRIBUTE_UNUSED,
   1002 	 bfd_vma pc ATTRIBUTE_UNUSED,
   1003 	 int length ATTRIBUTE_UNUSED)
   1004 {
   1005   print_suffix (dis_info, 'g');
   1006 }
   1007 
   1008 static void
   1009 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1010 	 void * dis_info,
   1011 	 long value ATTRIBUTE_UNUSED,
   1012 	 unsigned int attrs ATTRIBUTE_UNUSED,
   1013 	 bfd_vma pc ATTRIBUTE_UNUSED,
   1014 	 int length ATTRIBUTE_UNUSED)
   1015 {
   1016   print_suffix (dis_info, 'q');
   1017 }
   1018 
   1019 static void
   1020 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1021 	 void * dis_info,
   1022 	 long value ATTRIBUTE_UNUSED,
   1023 	 unsigned int attrs ATTRIBUTE_UNUSED,
   1024 	 bfd_vma pc ATTRIBUTE_UNUSED,
   1025 	 int length ATTRIBUTE_UNUSED)
   1026 {
   1027   print_suffix (dis_info, 'z');
   1028 }
   1029 
   1030 /* Print the empty suffix.  */
   1031 
   1032 static void
   1033 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1034 	 void * dis_info ATTRIBUTE_UNUSED,
   1035 	 long value ATTRIBUTE_UNUSED,
   1036 	 unsigned int attrs ATTRIBUTE_UNUSED,
   1037 	 bfd_vma pc ATTRIBUTE_UNUSED,
   1038 	 int length ATTRIBUTE_UNUSED)
   1039 {
   1040   return;
   1041 }
   1042 
   1043 static void
   1044 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1045 	       void * dis_info,
   1046 	       long value,
   1047 	       unsigned int attrs ATTRIBUTE_UNUSED,
   1048 	       bfd_vma pc ATTRIBUTE_UNUSED,
   1049 	       int length ATTRIBUTE_UNUSED)
   1050 {
   1051   disassemble_info *info = dis_info;
   1052 
   1053   if (value == 0)
   1054     (*info->fprintf_func) (info->stream, "r0h,r0l");
   1055   else
   1056     (*info->fprintf_func) (info->stream, "r0l,r0h");
   1057 }
   1058 
   1059 static void
   1060 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1061 			void * dis_info,
   1062 			unsigned long value,
   1063 			unsigned int attrs ATTRIBUTE_UNUSED,
   1064 			bfd_vma pc ATTRIBUTE_UNUSED,
   1065 			int length ATTRIBUTE_UNUSED)
   1066 {
   1067   disassemble_info *info = dis_info;
   1068 
   1069   (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
   1070 }
   1071 
   1072 static void
   1073 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1074 		      void * dis_info,
   1075 		      signed long value,
   1076 		      unsigned int attrs ATTRIBUTE_UNUSED,
   1077 		      bfd_vma pc ATTRIBUTE_UNUSED,
   1078 		      int length ATTRIBUTE_UNUSED)
   1079 {
   1080   disassemble_info *info = dis_info;
   1081 
   1082   (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
   1083 }
   1084 
   1085 static void
   1086 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1087 	    void * dis_info,
   1088 	    long value ATTRIBUTE_UNUSED,
   1089 	    unsigned int attrs ATTRIBUTE_UNUSED,
   1090 	    bfd_vma pc ATTRIBUTE_UNUSED,
   1091 	    int length ATTRIBUTE_UNUSED)
   1092 {
   1093   /* Always print the size as '.w'.  */
   1094   disassemble_info *info = dis_info;
   1095 
   1096   (*info->fprintf_func) (info->stream, ".w");
   1097 }
   1098 
   1099 #define POP  0
   1100 #define PUSH 1
   1101 
   1102 static void print_pop_regset  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
   1103 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
   1104 
   1105 /* Print a set of registers, R0,R1,A0,A1,SB,FB.  */
   1106 
   1107 static void
   1108 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1109 	      void * dis_info,
   1110 	      long value,
   1111 	      unsigned int attrs ATTRIBUTE_UNUSED,
   1112 	      bfd_vma pc ATTRIBUTE_UNUSED,
   1113 	      int length ATTRIBUTE_UNUSED,
   1114 	      int push)
   1115 {
   1116   static char * m16c_register_names [] =
   1117   {
   1118     "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
   1119   };
   1120   disassemble_info *info = dis_info;
   1121   int mask;
   1122   int reg_index = 0;
   1123   char* comma = "";
   1124 
   1125   if (push)
   1126     mask = 0x80;
   1127   else
   1128     mask = 1;
   1129 
   1130   if (value & mask)
   1131     {
   1132       (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
   1133       comma = ",";
   1134     }
   1135 
   1136   for (reg_index = 1; reg_index <= 7; ++reg_index)
   1137     {
   1138       if (push)
   1139         mask >>= 1;
   1140       else
   1141         mask <<= 1;
   1142 
   1143       if (value & mask)
   1144         {
   1145           (*info->fprintf_func) (info->stream, "%s%s", comma,
   1146 				 m16c_register_names [reg_index]);
   1147           comma = ",";
   1148         }
   1149     }
   1150 }
   1151 
   1152 static void
   1153 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1154 		  void * dis_info,
   1155 		  long value,
   1156 		  unsigned int attrs ATTRIBUTE_UNUSED,
   1157 		  bfd_vma pc ATTRIBUTE_UNUSED,
   1158 		  int length ATTRIBUTE_UNUSED)
   1159 {
   1160   print_regset (cd, dis_info, value, attrs, pc, length, POP);
   1161 }
   1162 
   1163 static void
   1164 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1165 		   void * dis_info,
   1166 		   long value,
   1167 		   unsigned int attrs ATTRIBUTE_UNUSED,
   1168 		   bfd_vma pc ATTRIBUTE_UNUSED,
   1169 		   int length ATTRIBUTE_UNUSED)
   1170 {
   1171   print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
   1172 }
   1173 
   1174 static void
   1175 print_signed4n (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1176 		void * dis_info,
   1177 		signed long value,
   1178 		unsigned int attrs ATTRIBUTE_UNUSED,
   1179 		bfd_vma pc ATTRIBUTE_UNUSED,
   1180 		int length ATTRIBUTE_UNUSED)
   1181 {
   1182   disassemble_info *info = dis_info;
   1183 
   1184   (*info->fprintf_func) (info->stream, "%ld", -value);
   1185 }
   1186