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