1 1.1 skrll /* Morpho Technologies mRISC opcode support, for GNU Binutils. -*- C -*- 2 1.1.1.3 christos Copyright 2001, 2007, 2008, 2009, 2012 Free Software Foundation, Inc. 3 1.1 skrll 4 1.1 skrll Contributed by Red Hat Inc; developed under contract from 5 1.1 skrll Morpho Technologies. 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 25 1.1 skrll /* Each section is delimited with start and end markers. 26 1.1 skrll 27 1.1 skrll <arch>-opc.h additions use: "-- opc.h" 28 1.1 skrll <arch>-opc.c additions use: "-- opc.c" 29 1.1 skrll <arch>-asm.c additions use: "-- asm.c" 30 1.1 skrll <arch>-dis.c additions use: "-- dis.c" 31 1.1 skrll <arch>-ibd.h additions use: "-- ibd.h" */ 32 1.1 skrll 33 1.1 skrll /* -- opc.h */ 35 1.1 skrll 36 1.1 skrll /* Check applicability of instructions against machines. */ 37 1.1 skrll #define CGEN_VALIDATE_INSN_SUPPORTED 38 1.1 skrll 39 1.1 skrll /* Allows reason codes to be output when assembler errors occur. */ 40 1.1 skrll #define CGEN_VERBOSE_ASSEMBLER_ERRORS 41 1.1 skrll 42 1.1 skrll /* Override disassembly hashing - there are variable bits in the top 43 1.1 skrll byte of these instructions. */ 44 1.1 skrll #define CGEN_DIS_HASH_SIZE 8 45 1.1 skrll #define CGEN_DIS_HASH(buf, value) (((* (unsigned char *) (buf)) >> 5) % CGEN_DIS_HASH_SIZE) 46 1.1 skrll 47 1.1 skrll #define CGEN_ASM_HASH_SIZE 127 48 1.1 skrll #define CGEN_ASM_HASH(insn) mt_asm_hash (insn) 49 1.1 skrll 50 1.1 skrll extern unsigned int mt_asm_hash (const char *); 51 1.1 skrll 52 1.1 skrll extern int mt_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *); 53 1.1 skrll 54 1.1 skrll 55 1.1 skrll /* -- opc.c */ 57 1.1 skrll #include "safe-ctype.h" 58 1.1 skrll 59 1.1 skrll /* Special check to ensure that instruction exists for given machine. */ 60 1.1 skrll 61 1.1 skrll int 62 1.1 skrll mt_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn) 63 1.1 skrll { 64 1.1 skrll int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH); 65 1.1 skrll 66 1.1 skrll /* No mach attribute? Assume it's supported for all machs. */ 67 1.1 skrll if (machs == 0) 68 1.1 skrll return 1; 69 1.1 skrll 70 1.1 skrll return ((machs & cd->machs) != 0); 71 1.1 skrll } 72 1.1 skrll 73 1.1 skrll /* A better hash function for instruction mnemonics. */ 74 1.1 skrll 75 1.1 skrll unsigned int 76 1.1 skrll mt_asm_hash (const char* insn) 77 1.1 skrll { 78 1.1 skrll unsigned int hash; 79 1.1 skrll const char* m = insn; 80 1.1 skrll 81 1.1 skrll for (hash = 0; *m && ! ISSPACE (*m); m++) 82 1.1 skrll hash = (hash * 23) ^ (0x1F & TOLOWER (*m)); 83 1.1 skrll 84 1.1 skrll /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */ 85 1.1 skrll 86 1.1 skrll return hash % CGEN_ASM_HASH_SIZE; 87 1.1 skrll } 88 1.1 skrll 89 1.1 skrll 90 1.1 skrll /* -- asm.c */ 92 1.1 skrll /* Range checking for signed numbers. Returns 0 if acceptable 93 1.1 skrll and 1 if the value is out of bounds for a signed quantity. */ 94 1.1 skrll 95 1.1 skrll static int 96 1.1 skrll signed_out_of_bounds (long val) 97 1.1 skrll { 98 1.1 skrll if ((val < -32768) || (val > 32767)) 99 1.1 skrll return 1; 100 1.1 skrll return 0; 101 1.1 skrll } 102 1.1 skrll 103 1.1 skrll static const char * 104 1.1 skrll parse_loopsize (CGEN_CPU_DESC cd, 105 1.1 skrll const char **strp, 106 1.1 skrll int opindex, 107 1.1 skrll void *arg) 108 1.1 skrll { 109 1.1 skrll signed long * valuep = (signed long *) arg; 110 1.1 skrll const char *errmsg; 111 1.1 skrll bfd_reloc_code_real_type code = BFD_RELOC_NONE; 112 1.1 skrll enum cgen_parse_operand_result result_type; 113 1.1 skrll bfd_vma value; 114 1.1 skrll 115 1.1 skrll /* Is it a control transfer instructions? */ 116 1.1 skrll if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_LOOPSIZE) 117 1.1 skrll { 118 1.1 skrll code = BFD_RELOC_MT_PCINSN8; 119 1.1 skrll errmsg = cgen_parse_address (cd, strp, opindex, code, 120 1.1 skrll & result_type, & value); 121 1.1 skrll *valuep = value; 122 1.1 skrll return errmsg; 123 1.1 skrll } 124 1.1 skrll 125 1.1 skrll abort (); 126 1.1 skrll } 127 1.1 skrll 128 1.1 skrll static const char * 129 1.1 skrll parse_imm16 (CGEN_CPU_DESC cd, 130 1.1 skrll const char **strp, 131 1.1 skrll int opindex, 132 1.1 skrll void *arg) 133 1.1 skrll { 134 1.1 skrll signed long * valuep = (signed long *) arg; 135 1.1 skrll const char *errmsg; 136 1.1 skrll enum cgen_parse_operand_result result_type; 137 1.1 skrll bfd_reloc_code_real_type code = BFD_RELOC_NONE; 138 1.1 skrll bfd_vma value; 139 1.1 skrll 140 1.1 skrll /* Is it a control transfer instructions? */ 141 1.1 skrll if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16O) 142 1.1 skrll { 143 1.1 skrll code = BFD_RELOC_16_PCREL; 144 1.1 skrll errmsg = cgen_parse_address (cd, strp, opindex, code, 145 1.1 skrll & result_type, & value); 146 1.1 skrll if (errmsg == NULL) 147 1.1 skrll { 148 1.1 skrll if (signed_out_of_bounds (value)) 149 1.1 skrll errmsg = _("Operand out of range. Must be between -32768 and 32767."); 150 1.1 skrll } 151 1.1 skrll *valuep = value; 152 1.1 skrll return errmsg; 153 1.1 skrll } 154 1.1 skrll 155 1.1 skrll /* If it's not a control transfer instruction, then 156 1.1 skrll we have to check for %OP relocating operators. */ 157 1.1 skrll if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16L) 158 1.1 skrll ; 159 1.1 skrll else if (strncmp (*strp, "%hi16", 5) == 0) 160 1.1 skrll { 161 1.1 skrll *strp += 5; 162 1.1 skrll code = BFD_RELOC_HI16; 163 1.1 skrll } 164 1.1 skrll else if (strncmp (*strp, "%lo16", 5) == 0) 165 1.1 skrll { 166 1.1 skrll *strp += 5; 167 1.1 skrll code = BFD_RELOC_LO16; 168 1.1 skrll } 169 1.1 skrll 170 1.1 skrll /* If we found a %OP relocating operator, then parse it as an address. 171 1.1 skrll If not, we need to parse it as an integer, either signed or unsigned 172 1.1 skrll depending on which operand type we have. */ 173 1.1 skrll if (code != BFD_RELOC_NONE) 174 1.1 skrll { 175 1.1 skrll /* %OP relocating operator found. */ 176 1.1 skrll errmsg = cgen_parse_address (cd, strp, opindex, code, 177 1.1 skrll & result_type, & value); 178 1.1 skrll if (errmsg == NULL) 179 1.1 skrll { 180 1.1 skrll switch (result_type) 181 1.1 skrll { 182 1.1 skrll case (CGEN_PARSE_OPERAND_RESULT_NUMBER): 183 1.1 skrll if (code == BFD_RELOC_HI16) 184 1.1 skrll value = (value >> 16) & 0xFFFF; 185 1.1 skrll else if (code == BFD_RELOC_LO16) 186 1.1 skrll value = value & 0xFFFF; 187 1.1 skrll else 188 1.1 skrll errmsg = _("Biiiig Trouble in parse_imm16!"); 189 1.1 skrll break; 190 1.1 skrll 191 1.1 skrll case (CGEN_PARSE_OPERAND_RESULT_QUEUED): 192 1.1 skrll /* No special processing for this case. */ 193 1.1 skrll break; 194 1.1 skrll 195 1.1 skrll default: 196 1.1 skrll errmsg = _("The percent-operator's operand is not a symbol"); 197 1.1 skrll break; 198 1.1 skrll } 199 1.1 skrll } 200 1.1 skrll *valuep = value; 201 1.1 skrll } 202 1.1 skrll else 203 1.1 skrll { 204 1.1 skrll /* Parse hex values like 0xffff as unsigned, and sign extend 205 1.1 skrll them manually. */ 206 1.1 skrll int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MT_OPERAND_IMM16); 207 1.1 skrll 208 1.1 skrll if ((*strp)[0] == '0' 209 1.1 skrll && ((*strp)[1] == 'x' || (*strp)[1] == 'X')) 210 1.1 skrll parse_signed = 0; 211 1.1 skrll 212 1.1 skrll /* No relocating operator. Parse as an number. */ 213 1.1 skrll if (parse_signed) 214 1.1 skrll { 215 1.1 skrll /* Parse as as signed integer. */ 216 1.1 skrll 217 1.1 skrll errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep); 218 1.1 skrll 219 1.1 skrll if (errmsg == NULL) 220 1.1 skrll { 221 1.1 skrll #if 0 222 1.1 skrll /* Manual range checking is needed for the signed case. */ 223 1.1 skrll if (*valuep & 0x8000) 224 1.1 skrll value = 0xffff0000 | *valuep; 225 1.1 skrll else 226 1.1 skrll value = *valuep; 227 1.1 skrll 228 1.1 skrll if (signed_out_of_bounds (value)) 229 1.1 skrll errmsg = _("Operand out of range. Must be between -32768 and 32767."); 230 1.1 skrll /* Truncate to 16 bits. This is necessary 231 1.1 skrll because cgen will have sign extended *valuep. */ 232 1.1 skrll *valuep &= 0xFFFF; 233 1.1 skrll #endif 234 1.1 skrll } 235 1.1 skrll } 236 1.1 skrll else 237 1.1 skrll { 238 1.1 skrll /* MT_OPERAND_IMM16Z. Parse as an unsigned integer. */ 239 1.1 skrll errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep); 240 1.1 skrll 241 1.1 skrll if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16 242 1.1 skrll && *valuep >= 0x8000 243 1.1 skrll && *valuep <= 0xffff) 244 1.1 skrll *valuep -= 0x10000; 245 1.1 skrll } 246 1.1 skrll } 247 1.1 skrll 248 1.1 skrll return errmsg; 249 1.1 skrll } 250 1.1 skrll 251 1.1 skrll 252 1.1 skrll static const char * 253 1.1 skrll parse_dup (CGEN_CPU_DESC cd, 254 1.1 skrll const char **strp, 255 1.1 skrll int opindex, 256 1.1 skrll unsigned long *valuep) 257 1.1 skrll { 258 1.1 skrll const char *errmsg = NULL; 259 1.1 skrll 260 1.1 skrll if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0) 261 1.1 skrll { 262 1.1 skrll *strp += 3; 263 1.1 skrll *valuep = 1; 264 1.1 skrll } 265 1.1 skrll else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0) 266 1.1 skrll { 267 1.1 skrll *strp += 2; 268 1.1 skrll *valuep = 0; 269 1.1 skrll } 270 1.1 skrll else 271 1.1 skrll errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 272 1.1 skrll 273 1.1 skrll return errmsg; 274 1.1 skrll } 275 1.1 skrll 276 1.1 skrll 277 1.1 skrll static const char * 278 1.1 skrll parse_ball (CGEN_CPU_DESC cd, 279 1.1 skrll const char **strp, 280 1.1 skrll int opindex, 281 1.1 skrll unsigned long *valuep) 282 1.1 skrll { 283 1.1 skrll const char *errmsg = NULL; 284 1.1 skrll 285 1.1 skrll if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0) 286 1.1 skrll { 287 1.1 skrll *strp += 3; 288 1.1 skrll *valuep = 1; 289 1.1 skrll } 290 1.1 skrll else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0) 291 1.1 skrll { 292 1.1 skrll *strp += 3; 293 1.1 skrll *valuep = 0; 294 1.1 skrll } 295 1.1 skrll else 296 1.1 skrll errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 297 1.1 skrll 298 1.1 skrll return errmsg; 299 1.1 skrll } 300 1.1 skrll 301 1.1 skrll static const char * 302 1.1 skrll parse_xmode (CGEN_CPU_DESC cd, 303 1.1 skrll const char **strp, 304 1.1 skrll int opindex, 305 1.1 skrll unsigned long *valuep) 306 1.1 skrll { 307 1.1 skrll const char *errmsg = NULL; 308 1.1 skrll 309 1.1 skrll if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0) 310 1.1 skrll { 311 1.1 skrll *strp += 2; 312 1.1 skrll *valuep = 1; 313 1.1 skrll } 314 1.1 skrll else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0) 315 1.1 skrll { 316 1.1 skrll *strp += 2; 317 1.1 skrll *valuep = 0; 318 1.1 skrll } 319 1.1 skrll else 320 1.1 skrll errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 321 1.1 skrll 322 1.1 skrll return errmsg; 323 1.1 skrll } 324 1.1 skrll 325 1.1 skrll static const char * 326 1.1 skrll parse_rc (CGEN_CPU_DESC cd, 327 1.1 skrll const char **strp, 328 1.1 skrll int opindex, 329 1.1 skrll unsigned long *valuep) 330 1.1 skrll { 331 1.1 skrll const char *errmsg = NULL; 332 1.1 skrll 333 1.1 skrll if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0) 334 1.1 skrll { 335 1.1 skrll *strp += 1; 336 1.1 skrll *valuep = 1; 337 1.1 skrll } 338 1.1 skrll else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0) 339 1.1 skrll { 340 1.1 skrll *strp += 1; 341 1.1 skrll *valuep = 0; 342 1.1 skrll } 343 1.1 skrll else 344 1.1 skrll errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 345 1.1 skrll 346 1.1 skrll return errmsg; 347 1.1 skrll } 348 1.1 skrll 349 1.1 skrll static const char * 350 1.1 skrll parse_cbrb (CGEN_CPU_DESC cd, 351 1.1 skrll const char **strp, 352 1.1 skrll int opindex, 353 1.1 skrll unsigned long *valuep) 354 1.1 skrll { 355 1.1 skrll const char *errmsg = NULL; 356 1.1 skrll 357 1.1 skrll if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0) 358 1.1 skrll { 359 1.1 skrll *strp += 2; 360 1.1 skrll *valuep = 1; 361 1.1 skrll } 362 1.1 skrll else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0) 363 1.1 skrll { 364 1.1 skrll *strp += 2; 365 1.1 skrll *valuep = 0; 366 1.1 skrll } 367 1.1 skrll else 368 1.1 skrll errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 369 1.1 skrll 370 1.1 skrll return errmsg; 371 1.1 skrll } 372 1.1 skrll 373 1.1 skrll static const char * 374 1.1 skrll parse_rbbc (CGEN_CPU_DESC cd, 375 1.1 skrll const char **strp, 376 1.1 skrll int opindex, 377 1.1 skrll unsigned long *valuep) 378 1.1 skrll { 379 1.1 skrll const char *errmsg = NULL; 380 1.1 skrll 381 1.1 skrll if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0) 382 1.1 skrll { 383 1.1 skrll *strp += 2; 384 1.1 skrll *valuep = 0; 385 1.1 skrll } 386 1.1 skrll else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0) 387 1.1 skrll { 388 1.1 skrll *strp += 3; 389 1.1 skrll *valuep = 1; 390 1.1 skrll } 391 1.1 skrll else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0) 392 1.1 skrll { 393 1.1 skrll *strp += 3; 394 1.1 skrll *valuep = 2; 395 1.1 skrll } 396 1.1 skrll else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0) 397 1.1 skrll { 398 1.1 skrll *strp += 2; 399 1.1 skrll *valuep = 3; 400 1.1 skrll } 401 1.1 skrll else 402 1.1 skrll errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 403 1.1 skrll 404 1.1 skrll return errmsg; 405 1.1 skrll } 406 1.1 skrll 407 1.1 skrll static const char * 408 1.1 skrll parse_type (CGEN_CPU_DESC cd, 409 1.1 skrll const char **strp, 410 1.1 skrll int opindex, 411 1.1 skrll unsigned long *valuep) 412 1.1 skrll { 413 1.1 skrll const char *errmsg = NULL; 414 1.1 skrll 415 1.1 skrll if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0) 416 1.1 skrll { 417 1.1 skrll *strp += 3; 418 1.1 skrll *valuep = 0; 419 1.1 skrll } 420 1.1 skrll else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0) 421 1.1 skrll { 422 1.1 skrll *strp += 4; 423 1.1 skrll *valuep = 1; 424 1.1 skrll } 425 1.1 skrll else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0) 426 1.1 skrll { 427 1.1 skrll *strp += 2; 428 1.1 skrll *valuep = 2; 429 1.1 skrll } 430 1.1 skrll else 431 1.1 skrll errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 432 1.1 skrll 433 1.1 skrll if ((errmsg == NULL) && (*valuep == 3)) 434 1.1 skrll errmsg = _("invalid operand. type may have values 0,1,2 only."); 435 1.1 skrll 436 1.1 skrll return errmsg; 437 1.1 skrll } 438 1.1 skrll 439 1.1 skrll /* -- dis.c */ 440 1.1 skrll static void 441 1.1 skrll print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 442 1.1 skrll void * dis_info, 443 1.1 skrll long value, 444 1.1 skrll unsigned int attrs ATTRIBUTE_UNUSED, 445 1.1 skrll bfd_vma pc ATTRIBUTE_UNUSED, 446 1.1 skrll int length ATTRIBUTE_UNUSED) 447 1.1.1.3 christos { 448 1.1 skrll disassemble_info *info = (disassemble_info *) dis_info; 449 1.1 skrll 450 1.1 skrll info->fprintf_func (info->stream, "$%lx", value & 0xffffffff); 451 1.1 skrll 452 1.1 skrll if (0) 453 1.1 skrll print_normal (cd, dis_info, value, attrs, pc, length); 454 1.1 skrll } 455 1.1 skrll 456 1.1 skrll static void 457 1.1 skrll print_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 458 1.1 skrll void * dis_info, 459 1.1 skrll long value, 460 1.1 skrll unsigned int attrs ATTRIBUTE_UNUSED, 461 1.1 skrll bfd_vma pc ATTRIBUTE_UNUSED, 462 1.1 skrll int length ATTRIBUTE_UNUSED) 463 1.1 skrll { 464 1.1 skrll print_address (cd, dis_info, value + pc, attrs, pc, length); 465 1.1 skrll } 466 1.1 skrll 467 1.1 skrll /* -- */ 468 1.1 skrll 469 1.1 skrll 470 471 472 473