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