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