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