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