1*3d8817e4Smiod/* IQ2000 opcode support. -*- C -*- 2*3d8817e4Smiod 3*3d8817e4Smiod Copyright 2000, 2001, 2002, 2005 Free Software Foundation, Inc. 4*3d8817e4Smiod 5*3d8817e4Smiod Contributed by Red Hat Inc; developed under contract from Fujitsu. 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, 22*3d8817e4Smiod MA 02110-1301, USA. */ 23*3d8817e4Smiod 24*3d8817e4Smiod/* This file is an addendum to iq2000.cpu. Heavy use of C code isn't 25*3d8817e4Smiod appropriate in .cpu files, so it resides here. This especially applies 26*3d8817e4Smiod to assembly/disassembly where parsing/printing can be quite involved. 27*3d8817e4Smiod Such things aren't really part of the specification of the cpu, per se, 28*3d8817e4Smiod so .cpu files provide the general framework and .opc files handle the 29*3d8817e4Smiod nitty-gritty details as necessary. 30*3d8817e4Smiod 31*3d8817e4Smiod Each section is delimited with start and end markers. 32*3d8817e4Smiod 33*3d8817e4Smiod <arch>-opc.h additions use: "-- opc.h" 34*3d8817e4Smiod <arch>-opc.c additions use: "-- opc.c" 35*3d8817e4Smiod <arch>-asm.c additions use: "-- asm.c" 36*3d8817e4Smiod <arch>-dis.c additions use: "-- dis.c" 37*3d8817e4Smiod <arch>-ibd.h additions use: "-- ibd.h". */ 38*3d8817e4Smiod 39*3d8817e4Smiod/* -- opc.h */ 40*3d8817e4Smiod 41*3d8817e4Smiod/* Allows reason codes to be output when assembler errors occur. */ 42*3d8817e4Smiod#define CGEN_VERBOSE_ASSEMBLER_ERRORS 43*3d8817e4Smiod 44*3d8817e4Smiod/* Override disassembly hashing - there are variable bits in the top 45*3d8817e4Smiod byte of these instructions. */ 46*3d8817e4Smiod#define CGEN_DIS_HASH_SIZE 8 47*3d8817e4Smiod#define CGEN_DIS_HASH(buf,value) (((* (unsigned char*) (buf)) >> 6) % CGEN_DIS_HASH_SIZE) 48*3d8817e4Smiod 49*3d8817e4Smiod/* following activates check beyond hashing since some iq2000 and iq10 50*3d8817e4Smiod instructions have same mnemonics but different functionality. */ 51*3d8817e4Smiod#define CGEN_VALIDATE_INSN_SUPPORTED 52*3d8817e4Smiod 53*3d8817e4Smiodextern int iq2000_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *); 54*3d8817e4Smiod 55*3d8817e4Smiod/* -- asm.c */ 56*3d8817e4Smiod 57*3d8817e4Smiod#include "safe-ctype.h" 58*3d8817e4Smiod 59*3d8817e4Smiodstatic const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'"); 60*3d8817e4Smiod 61*3d8817e4Smiod/* Special check to ensure that instruction exists for given machine. */ 62*3d8817e4Smiod 63*3d8817e4Smiodint 64*3d8817e4Smiodiq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn) 65*3d8817e4Smiod{ 66*3d8817e4Smiod int machs = cd->machs; 67*3d8817e4Smiod 68*3d8817e4Smiod return (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0; 69*3d8817e4Smiod} 70*3d8817e4Smiod 71*3d8817e4Smiodstatic int 72*3d8817e4Smiodiq2000_cgen_isa_register (const char **strp) 73*3d8817e4Smiod{ 74*3d8817e4Smiod int len; 75*3d8817e4Smiod int ch1, ch2; 76*3d8817e4Smiod 77*3d8817e4Smiod if (**strp == 'r' || **strp == 'R') 78*3d8817e4Smiod { 79*3d8817e4Smiod len = strlen (*strp); 80*3d8817e4Smiod if (len == 2) 81*3d8817e4Smiod { 82*3d8817e4Smiod ch1 = (*strp)[1]; 83*3d8817e4Smiod if ('0' <= ch1 && ch1 <= '9') 84*3d8817e4Smiod return 1; 85*3d8817e4Smiod } 86*3d8817e4Smiod else if (len == 3) 87*3d8817e4Smiod { 88*3d8817e4Smiod ch1 = (*strp)[1]; 89*3d8817e4Smiod ch2 = (*strp)[2]; 90*3d8817e4Smiod if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9')) 91*3d8817e4Smiod return 1; 92*3d8817e4Smiod if ('3' == ch1 && (ch2 == '0' || ch2 == '1')) 93*3d8817e4Smiod return 1; 94*3d8817e4Smiod } 95*3d8817e4Smiod } 96*3d8817e4Smiod if (**strp == '%' 97*3d8817e4Smiod && TOLOWER ((*strp)[1]) != 'l' 98*3d8817e4Smiod && TOLOWER ((*strp)[1]) != 'h') 99*3d8817e4Smiod return 1; 100*3d8817e4Smiod return 0; 101*3d8817e4Smiod} 102*3d8817e4Smiod 103*3d8817e4Smiod/* Handle negated literal. */ 104*3d8817e4Smiod 105*3d8817e4Smiodstatic const char * 106*3d8817e4Smiodparse_mimm (CGEN_CPU_DESC cd, 107*3d8817e4Smiod const char **strp, 108*3d8817e4Smiod int opindex, 109*3d8817e4Smiod unsigned long *valuep) 110*3d8817e4Smiod{ 111*3d8817e4Smiod const char *errmsg; 112*3d8817e4Smiod 113*3d8817e4Smiod /* Verify this isn't a register. */ 114*3d8817e4Smiod if (iq2000_cgen_isa_register (strp)) 115*3d8817e4Smiod errmsg = _("immediate value cannot be register"); 116*3d8817e4Smiod else 117*3d8817e4Smiod { 118*3d8817e4Smiod long value; 119*3d8817e4Smiod 120*3d8817e4Smiod errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 121*3d8817e4Smiod if (errmsg == NULL) 122*3d8817e4Smiod { 123*3d8817e4Smiod long x = (-value) & 0xFFFF0000; 124*3d8817e4Smiod 125*3d8817e4Smiod if (x != 0 && x != (long) 0xFFFF0000) 126*3d8817e4Smiod errmsg = _("immediate value out of range"); 127*3d8817e4Smiod else 128*3d8817e4Smiod *valuep = (-value & 0xFFFF); 129*3d8817e4Smiod } 130*3d8817e4Smiod } 131*3d8817e4Smiod return errmsg; 132*3d8817e4Smiod} 133*3d8817e4Smiod 134*3d8817e4Smiod/* Handle signed/unsigned literal. */ 135*3d8817e4Smiod 136*3d8817e4Smiodstatic const char * 137*3d8817e4Smiodparse_imm (CGEN_CPU_DESC cd, 138*3d8817e4Smiod const char **strp, 139*3d8817e4Smiod int opindex, 140*3d8817e4Smiod unsigned long *valuep) 141*3d8817e4Smiod{ 142*3d8817e4Smiod const char *errmsg; 143*3d8817e4Smiod 144*3d8817e4Smiod if (iq2000_cgen_isa_register (strp)) 145*3d8817e4Smiod errmsg = _("immediate value cannot be register"); 146*3d8817e4Smiod else 147*3d8817e4Smiod { 148*3d8817e4Smiod long value; 149*3d8817e4Smiod 150*3d8817e4Smiod errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); 151*3d8817e4Smiod if (errmsg == NULL) 152*3d8817e4Smiod { 153*3d8817e4Smiod long x = value & 0xFFFF0000; 154*3d8817e4Smiod 155*3d8817e4Smiod if (x != 0 && x != (long) 0xFFFF0000) 156*3d8817e4Smiod errmsg = _("immediate value out of range"); 157*3d8817e4Smiod else 158*3d8817e4Smiod *valuep = (value & 0xFFFF); 159*3d8817e4Smiod } 160*3d8817e4Smiod } 161*3d8817e4Smiod return errmsg; 162*3d8817e4Smiod} 163*3d8817e4Smiod 164*3d8817e4Smiod/* Handle iq10 21-bit jmp offset. */ 165*3d8817e4Smiod 166*3d8817e4Smiodstatic const char * 167*3d8817e4Smiodparse_jtargq10 (CGEN_CPU_DESC cd, 168*3d8817e4Smiod const char **strp, 169*3d8817e4Smiod int opindex, 170*3d8817e4Smiod int reloc ATTRIBUTE_UNUSED, 171*3d8817e4Smiod enum cgen_parse_operand_result *type_addr ATTRIBUTE_UNUSED, 172*3d8817e4Smiod bfd_vma *valuep) 173*3d8817e4Smiod{ 174*3d8817e4Smiod const char *errmsg; 175*3d8817e4Smiod bfd_vma value; 176*3d8817e4Smiod enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER; 177*3d8817e4Smiod 178*3d8817e4Smiod errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21, 179*3d8817e4Smiod & result_type, & value); 180*3d8817e4Smiod if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 181*3d8817e4Smiod { 182*3d8817e4Smiod /* Check value is within 23-bits 183*3d8817e4Smiod (remembering that 2-bit shift right will occur). */ 184*3d8817e4Smiod if (value > 0x7fffff) 185*3d8817e4Smiod return _("21-bit offset out of range"); 186*3d8817e4Smiod } 187*3d8817e4Smiod *valuep = (value & 0x7FFFFF); 188*3d8817e4Smiod return errmsg; 189*3d8817e4Smiod} 190*3d8817e4Smiod 191*3d8817e4Smiod/* Handle high(). */ 192*3d8817e4Smiod 193*3d8817e4Smiodstatic const char * 194*3d8817e4Smiodparse_hi16 (CGEN_CPU_DESC cd, 195*3d8817e4Smiod const char **strp, 196*3d8817e4Smiod int opindex, 197*3d8817e4Smiod unsigned long *valuep) 198*3d8817e4Smiod{ 199*3d8817e4Smiod if (strncasecmp (*strp, "%hi(", 4) == 0) 200*3d8817e4Smiod { 201*3d8817e4Smiod enum cgen_parse_operand_result result_type; 202*3d8817e4Smiod bfd_vma value; 203*3d8817e4Smiod const char *errmsg; 204*3d8817e4Smiod 205*3d8817e4Smiod *strp += 4; 206*3d8817e4Smiod errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16, 207*3d8817e4Smiod & result_type, & value); 208*3d8817e4Smiod if (**strp != ')') 209*3d8817e4Smiod return MISSING_CLOSING_PARENTHESIS; 210*3d8817e4Smiod 211*3d8817e4Smiod ++*strp; 212*3d8817e4Smiod if (errmsg == NULL 213*3d8817e4Smiod && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 214*3d8817e4Smiod { 215*3d8817e4Smiod /* If value has top-bit of %lo on, then it will 216*3d8817e4Smiod sign-propagate and so we compensate by adding 217*3d8817e4Smiod 1 to the resultant %hi value. */ 218*3d8817e4Smiod if (value & 0x8000) 219*3d8817e4Smiod value += 0x10000; 220*3d8817e4Smiod value >>= 16; 221*3d8817e4Smiod value &= 0xffff; 222*3d8817e4Smiod } 223*3d8817e4Smiod *valuep = value; 224*3d8817e4Smiod 225*3d8817e4Smiod return errmsg; 226*3d8817e4Smiod } 227*3d8817e4Smiod 228*3d8817e4Smiod /* We add %uhi in case a user just wants the high 16-bits or is using 229*3d8817e4Smiod an insn like ori for %lo which does not sign-propagate. */ 230*3d8817e4Smiod if (strncasecmp (*strp, "%uhi(", 5) == 0) 231*3d8817e4Smiod { 232*3d8817e4Smiod enum cgen_parse_operand_result result_type; 233*3d8817e4Smiod bfd_vma value; 234*3d8817e4Smiod const char *errmsg; 235*3d8817e4Smiod 236*3d8817e4Smiod *strp += 5; 237*3d8817e4Smiod errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16, 238*3d8817e4Smiod & result_type, & value); 239*3d8817e4Smiod if (**strp != ')') 240*3d8817e4Smiod return MISSING_CLOSING_PARENTHESIS; 241*3d8817e4Smiod 242*3d8817e4Smiod ++*strp; 243*3d8817e4Smiod if (errmsg == NULL 244*3d8817e4Smiod && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 245*3d8817e4Smiod value >>= 16; 246*3d8817e4Smiod 247*3d8817e4Smiod value &= 0xffff; 248*3d8817e4Smiod *valuep = value; 249*3d8817e4Smiod 250*3d8817e4Smiod return errmsg; 251*3d8817e4Smiod } 252*3d8817e4Smiod 253*3d8817e4Smiod return parse_imm (cd, strp, opindex, valuep); 254*3d8817e4Smiod} 255*3d8817e4Smiod 256*3d8817e4Smiod/* Handle %lo in a signed context. 257*3d8817e4Smiod The signedness of the value doesn't matter to %lo(), but this also 258*3d8817e4Smiod handles the case where %lo() isn't present. */ 259*3d8817e4Smiod 260*3d8817e4Smiodstatic const char * 261*3d8817e4Smiodparse_lo16 (CGEN_CPU_DESC cd, 262*3d8817e4Smiod const char **strp, 263*3d8817e4Smiod int opindex, 264*3d8817e4Smiod unsigned long *valuep) 265*3d8817e4Smiod{ 266*3d8817e4Smiod if (strncasecmp (*strp, "%lo(", 4) == 0) 267*3d8817e4Smiod { 268*3d8817e4Smiod const char *errmsg; 269*3d8817e4Smiod enum cgen_parse_operand_result result_type; 270*3d8817e4Smiod bfd_vma value; 271*3d8817e4Smiod 272*3d8817e4Smiod *strp += 4; 273*3d8817e4Smiod errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16, 274*3d8817e4Smiod & result_type, & value); 275*3d8817e4Smiod if (**strp != ')') 276*3d8817e4Smiod return MISSING_CLOSING_PARENTHESIS; 277*3d8817e4Smiod ++*strp; 278*3d8817e4Smiod if (errmsg == NULL 279*3d8817e4Smiod && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 280*3d8817e4Smiod value &= 0xffff; 281*3d8817e4Smiod *valuep = value; 282*3d8817e4Smiod return errmsg; 283*3d8817e4Smiod } 284*3d8817e4Smiod 285*3d8817e4Smiod return parse_imm (cd, strp, opindex, valuep); 286*3d8817e4Smiod} 287*3d8817e4Smiod 288*3d8817e4Smiod/* Handle %lo in a negated signed context. 289*3d8817e4Smiod The signedness of the value doesn't matter to %lo(), but this also 290*3d8817e4Smiod handles the case where %lo() isn't present. */ 291*3d8817e4Smiod 292*3d8817e4Smiodstatic const char * 293*3d8817e4Smiodparse_mlo16 (CGEN_CPU_DESC cd, 294*3d8817e4Smiod const char **strp, 295*3d8817e4Smiod int opindex, 296*3d8817e4Smiod unsigned long *valuep) 297*3d8817e4Smiod{ 298*3d8817e4Smiod if (strncasecmp (*strp, "%lo(", 4) == 0) 299*3d8817e4Smiod { 300*3d8817e4Smiod const char *errmsg; 301*3d8817e4Smiod enum cgen_parse_operand_result result_type; 302*3d8817e4Smiod bfd_vma value; 303*3d8817e4Smiod 304*3d8817e4Smiod *strp += 4; 305*3d8817e4Smiod errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16, 306*3d8817e4Smiod & result_type, & value); 307*3d8817e4Smiod if (**strp != ')') 308*3d8817e4Smiod return MISSING_CLOSING_PARENTHESIS; 309*3d8817e4Smiod ++*strp; 310*3d8817e4Smiod if (errmsg == NULL 311*3d8817e4Smiod && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 312*3d8817e4Smiod value = (-value) & 0xffff; 313*3d8817e4Smiod *valuep = value; 314*3d8817e4Smiod return errmsg; 315*3d8817e4Smiod } 316*3d8817e4Smiod 317*3d8817e4Smiod return parse_mimm (cd, strp, opindex, valuep); 318*3d8817e4Smiod} 319*3d8817e4Smiod 320*3d8817e4Smiod/* -- */ 321