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