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