1 /* Opcode table for the ARC. 2 Copyright (C) 1994-2014 Free Software Foundation, Inc. 3 Contributed by Doug Evans (dje (at) cygnus.com). 4 5 This file is part of libopcodes. 6 7 This library is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 It is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software Foundation, 19 Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 20 21 #include "sysdep.h" 22 #include <stdio.h> 23 #include "ansidecl.h" 24 #include "bfd.h" 25 #include "opcode/arc.h" 26 #include "opintl.h" 27 28 enum operand {OP_NONE,OP_REG,OP_SHIMM,OP_LIMM}; 29 30 #define OPERANDS 3 31 32 enum operand ls_operand[OPERANDS]; 33 34 struct arc_opcode *arc_ext_opcodes; 35 struct arc_ext_operand_value *arc_ext_operands; 36 37 #define LS_VALUE 0 38 #define LS_DEST 0 39 #define LS_BASE 1 40 #define LS_OFFSET 2 41 42 /* Given a format letter, yields the index into `arc_operands'. 43 eg: arc_operand_map['a'] = REGA. */ 44 unsigned char arc_operand_map[256]; 45 46 /* Nonzero if we've seen an 'f' suffix (in certain insns). */ 47 static int flag_p; 48 49 /* Nonzero if we've finished processing the 'f' suffix. */ 50 static int flagshimm_handled_p; 51 52 /* Nonzero if we've seen a 'a' suffix (address writeback). */ 53 static int addrwb_p; 54 55 /* Nonzero if we've seen a 'q' suffix (condition code). */ 56 static int cond_p; 57 58 /* Nonzero if we've inserted a nullify condition. */ 59 static int nullify_p; 60 61 /* The value of the a nullify condition we inserted. */ 62 static int nullify; 63 64 /* Nonzero if we've inserted jumpflags. */ 65 static int jumpflags_p; 66 67 /* Nonzero if we've inserted a shimm. */ 68 static int shimm_p; 69 70 /* The value of the shimm we inserted (each insn only gets one but it can 71 appear multiple times). */ 72 static int shimm; 73 74 /* Nonzero if we've inserted a limm (during assembly) or seen a limm 75 (during disassembly). */ 76 static int limm_p; 77 78 /* The value of the limm we inserted. Each insn only gets one but it can 79 appear multiple times. */ 80 static long limm; 81 82 #define INSERT_FN(fn) \ 84 static arc_insn fn (arc_insn, const struct arc_operand *, \ 85 int, const struct arc_operand_value *, long, \ 86 const char **) 87 88 #define EXTRACT_FN(fn) \ 89 static long fn (arc_insn *, const struct arc_operand *, \ 90 int, const struct arc_operand_value **, int *) 91 92 INSERT_FN (insert_reg); 93 INSERT_FN (insert_shimmfinish); 94 INSERT_FN (insert_limmfinish); 95 INSERT_FN (insert_offset); 96 INSERT_FN (insert_base); 97 INSERT_FN (insert_st_syntax); 98 INSERT_FN (insert_ld_syntax); 99 INSERT_FN (insert_addr_wb); 100 INSERT_FN (insert_flag); 101 INSERT_FN (insert_nullify); 102 INSERT_FN (insert_flagfinish); 103 INSERT_FN (insert_cond); 104 INSERT_FN (insert_forcelimm); 105 INSERT_FN (insert_reladdr); 106 INSERT_FN (insert_absaddr); 107 INSERT_FN (insert_jumpflags); 108 INSERT_FN (insert_unopmacro); 109 110 EXTRACT_FN (extract_reg); 111 EXTRACT_FN (extract_ld_offset); 112 EXTRACT_FN (extract_ld_syntax); 113 EXTRACT_FN (extract_st_offset); 114 EXTRACT_FN (extract_st_syntax); 115 EXTRACT_FN (extract_flag); 116 EXTRACT_FN (extract_cond); 117 EXTRACT_FN (extract_reladdr); 118 EXTRACT_FN (extract_jumpflags); 119 EXTRACT_FN (extract_unopmacro); 120 121 /* Various types of ARC operands, including insn suffixes. */ 122 123 /* Insn format values: 124 125 'a' REGA register A field 126 'b' REGB register B field 127 'c' REGC register C field 128 'S' SHIMMFINISH finish inserting a shimm value 129 'L' LIMMFINISH finish inserting a limm value 130 'o' OFFSET offset in st insns 131 'O' OFFSET offset in ld insns 132 '0' SYNTAX_ST_NE enforce store insn syntax, no errors 133 '1' SYNTAX_LD_NE enforce load insn syntax, no errors 134 '2' SYNTAX_ST enforce store insn syntax, errors, last pattern only 135 '3' SYNTAX_LD enforce load insn syntax, errors, last pattern only 136 's' BASE base in st insn 137 'f' FLAG F flag 138 'F' FLAGFINISH finish inserting the F flag 139 'G' FLAGINSN insert F flag in "flag" insn 140 'n' DELAY N field (nullify field) 141 'q' COND condition code field 142 'Q' FORCELIMM set `cond_p' to 1 to ensure a constant is a limm 143 'B' BRANCH branch address (22 bit pc relative) 144 'J' JUMP jump address (26 bit absolute) 145 'j' JUMPFLAGS optional high order bits of 'J' 146 'z' SIZE1 size field in ld a,[b,c] 147 'Z' SIZE10 size field in ld a,[b,shimm] 148 'y' SIZE22 size field in st c,[b,shimm] 149 'x' SIGN0 sign extend field ld a,[b,c] 150 'X' SIGN9 sign extend field ld a,[b,shimm] 151 'w' ADDRESS3 write-back field in ld a,[b,c] 152 'W' ADDRESS12 write-back field in ld a,[b,shimm] 153 'v' ADDRESS24 write-back field in st c,[b,shimm] 154 'e' CACHEBYPASS5 cache bypass in ld a,[b,c] 155 'E' CACHEBYPASS14 cache bypass in ld a,[b,shimm] 156 'D' CACHEBYPASS26 cache bypass in st c,[b,shimm] 157 'U' UNOPMACRO fake operand to copy REGB to REGC for unop macros 158 159 The following modifiers may appear between the % and char (eg: %.f): 160 161 '.' MODDOT '.' prefix must be present 162 'r' REG generic register value, for register table 163 'A' AUXREG auxiliary register in lr a,[b], sr c,[b] 164 165 Fields are: 166 167 CHAR BITS SHIFT FLAGS INSERT_FN EXTRACT_FN */ 168 169 const struct arc_operand arc_operands[] = 170 { 171 /* Place holder (??? not sure if needed). */ 172 #define UNUSED 0 173 { 0, 0, 0, 0, 0, 0 }, 174 175 /* Register A or shimm/limm indicator. */ 176 #define REGA (UNUSED + 1) 177 { 'a', 6, ARC_SHIFT_REGA, ARC_OPERAND_SIGNED | ARC_OPERAND_ERROR, insert_reg, extract_reg }, 178 179 /* Register B or shimm/limm indicator. */ 180 #define REGB (REGA + 1) 181 { 'b', 6, ARC_SHIFT_REGB, ARC_OPERAND_SIGNED | ARC_OPERAND_ERROR, insert_reg, extract_reg }, 182 183 /* Register C or shimm/limm indicator. */ 184 #define REGC (REGB + 1) 185 { 'c', 6, ARC_SHIFT_REGC, ARC_OPERAND_SIGNED | ARC_OPERAND_ERROR, insert_reg, extract_reg }, 186 187 /* Fake operand used to insert shimm value into most instructions. */ 188 #define SHIMMFINISH (REGC + 1) 189 { 'S', 9, 0, ARC_OPERAND_SIGNED + ARC_OPERAND_FAKE, insert_shimmfinish, 0 }, 190 191 /* Fake operand used to insert limm value into most instructions. */ 192 #define LIMMFINISH (SHIMMFINISH + 1) 193 { 'L', 32, 32, ARC_OPERAND_ADDRESS + ARC_OPERAND_LIMM + ARC_OPERAND_FAKE, insert_limmfinish, 0 }, 194 195 /* Shimm operand when there is no reg indicator (st). */ 196 #define ST_OFFSET (LIMMFINISH + 1) 197 { 'o', 9, 0, ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED | ARC_OPERAND_STORE, insert_offset, extract_st_offset }, 198 199 /* Shimm operand when there is no reg indicator (ld). */ 200 #define LD_OFFSET (ST_OFFSET + 1) 201 { 'O', 9, 0,ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED | ARC_OPERAND_LOAD, insert_offset, extract_ld_offset }, 202 203 /* Operand for base. */ 204 #define BASE (LD_OFFSET + 1) 205 { 's', 6, ARC_SHIFT_REGB, ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED, insert_base, extract_reg}, 206 207 /* 0 enforce syntax for st insns. */ 208 #define SYNTAX_ST_NE (BASE + 1) 209 { '0', 9, 0, ARC_OPERAND_FAKE, insert_st_syntax, extract_st_syntax }, 210 211 /* 1 enforce syntax for ld insns. */ 212 #define SYNTAX_LD_NE (SYNTAX_ST_NE + 1) 213 { '1', 9, 0, ARC_OPERAND_FAKE, insert_ld_syntax, extract_ld_syntax }, 214 215 /* 0 enforce syntax for st insns. */ 216 #define SYNTAX_ST (SYNTAX_LD_NE + 1) 217 { '2', 9, 0, ARC_OPERAND_FAKE | ARC_OPERAND_ERROR, insert_st_syntax, extract_st_syntax }, 218 219 /* 0 enforce syntax for ld insns. */ 220 #define SYNTAX_LD (SYNTAX_ST + 1) 221 { '3', 9, 0, ARC_OPERAND_FAKE | ARC_OPERAND_ERROR, insert_ld_syntax, extract_ld_syntax }, 222 223 /* Flag update bit (insertion is defered until we know how). */ 224 #define FLAG (SYNTAX_LD + 1) 225 { 'f', 1, 8, ARC_OPERAND_SUFFIX, insert_flag, extract_flag }, 226 227 /* Fake utility operand to finish 'f' suffix handling. */ 228 #define FLAGFINISH (FLAG + 1) 229 { 'F', 1, 8, ARC_OPERAND_FAKE, insert_flagfinish, 0 }, 230 231 /* Fake utility operand to set the 'f' flag for the "flag" insn. */ 232 #define FLAGINSN (FLAGFINISH + 1) 233 { 'G', 1, 8, ARC_OPERAND_FAKE, insert_flag, 0 }, 234 235 /* Branch delay types. */ 236 #define DELAY (FLAGINSN + 1) 237 { 'n', 2, 5, ARC_OPERAND_SUFFIX , insert_nullify, 0 }, 238 239 /* Conditions. */ 240 #define COND (DELAY + 1) 241 { 'q', 5, 0, ARC_OPERAND_SUFFIX, insert_cond, extract_cond }, 242 243 /* Set `cond_p' to 1 to ensure a constant is treated as a limm. */ 244 #define FORCELIMM (COND + 1) 245 { 'Q', 0, 0, ARC_OPERAND_FAKE, insert_forcelimm, 0 }, 246 247 /* Branch address; b, bl, and lp insns. */ 248 #define BRANCH (FORCELIMM + 1) 249 { 'B', 20, 7, (ARC_OPERAND_RELATIVE_BRANCH + ARC_OPERAND_SIGNED) | ARC_OPERAND_ERROR, insert_reladdr, extract_reladdr }, 250 251 /* Jump address; j insn (this is basically the same as 'L' except that the 252 value is right shifted by 2). */ 253 #define JUMP (BRANCH + 1) 254 { 'J', 24, 32, ARC_OPERAND_ERROR | (ARC_OPERAND_ABSOLUTE_BRANCH + ARC_OPERAND_LIMM + ARC_OPERAND_FAKE), insert_absaddr, 0 }, 255 256 /* Jump flags; j{,l} insn value or'ed into 'J' addr for flag values. */ 257 #define JUMPFLAGS (JUMP + 1) 258 { 'j', 6, 26, ARC_OPERAND_JUMPFLAGS | ARC_OPERAND_ERROR, insert_jumpflags, extract_jumpflags }, 259 260 /* Size field, stored in bit 1,2. */ 261 #define SIZE1 (JUMPFLAGS + 1) 262 { 'z', 2, 1, ARC_OPERAND_SUFFIX, 0, 0 }, 263 264 /* Size field, stored in bit 10,11. */ 265 #define SIZE10 (SIZE1 + 1) 266 { 'Z', 2, 10, ARC_OPERAND_SUFFIX, 0, 0 }, 267 268 /* Size field, stored in bit 22,23. */ 269 #define SIZE22 (SIZE10 + 1) 270 { 'y', 2, 22, ARC_OPERAND_SUFFIX, 0, 0 }, 271 272 /* Sign extend field, stored in bit 0. */ 273 #define SIGN0 (SIZE22 + 1) 274 { 'x', 1, 0, ARC_OPERAND_SUFFIX, 0, 0 }, 275 276 /* Sign extend field, stored in bit 9. */ 277 #define SIGN9 (SIGN0 + 1) 278 { 'X', 1, 9, ARC_OPERAND_SUFFIX, 0, 0 }, 279 280 /* Address write back, stored in bit 3. */ 281 #define ADDRESS3 (SIGN9 + 1) 282 { 'w', 1, 3, ARC_OPERAND_SUFFIX, insert_addr_wb, 0}, 283 284 /* Address write back, stored in bit 12. */ 285 #define ADDRESS12 (ADDRESS3 + 1) 286 { 'W', 1, 12, ARC_OPERAND_SUFFIX, insert_addr_wb, 0}, 287 288 /* Address write back, stored in bit 24. */ 289 #define ADDRESS24 (ADDRESS12 + 1) 290 { 'v', 1, 24, ARC_OPERAND_SUFFIX, insert_addr_wb, 0}, 291 292 /* Cache bypass, stored in bit 5. */ 293 #define CACHEBYPASS5 (ADDRESS24 + 1) 294 { 'e', 1, 5, ARC_OPERAND_SUFFIX, 0, 0 }, 295 296 /* Cache bypass, stored in bit 14. */ 297 #define CACHEBYPASS14 (CACHEBYPASS5 + 1) 298 { 'E', 1, 14, ARC_OPERAND_SUFFIX, 0, 0 }, 299 300 /* Cache bypass, stored in bit 26. */ 301 #define CACHEBYPASS26 (CACHEBYPASS14 + 1) 302 { 'D', 1, 26, ARC_OPERAND_SUFFIX, 0, 0 }, 303 304 /* Unop macro, used to copy REGB to REGC. */ 305 #define UNOPMACRO (CACHEBYPASS26 + 1) 306 { 'U', 6, ARC_SHIFT_REGC, ARC_OPERAND_FAKE, insert_unopmacro, extract_unopmacro }, 307 308 /* '.' modifier ('.' required). */ 309 #define MODDOT (UNOPMACRO + 1) 310 { '.', 1, 0, ARC_MOD_DOT, 0, 0 }, 311 312 /* Dummy 'r' modifier for the register table. 313 It's called a "dummy" because there's no point in inserting an 'r' into all 314 the %a/%b/%c occurrences in the insn table. */ 315 #define REG (MODDOT + 1) 316 { 'r', 6, 0, ARC_MOD_REG, 0, 0 }, 317 318 /* Known auxiliary register modifier (stored in shimm field). */ 319 #define AUXREG (REG + 1) 320 { 'A', 9, 0, ARC_MOD_AUXREG, 0, 0 }, 321 322 /* End of list place holder. */ 323 { 0, 0, 0, 0, 0, 0 } 324 }; 325 326 /* Insert a value into a register field. 328 If REG is NULL, then this is actually a constant. 329 330 We must also handle auxiliary registers for lr/sr insns. */ 331 332 static arc_insn 333 insert_reg (arc_insn insn, 334 const struct arc_operand *operand, 335 int mods, 336 const struct arc_operand_value *reg, 337 long value, 338 const char **errmsg) 339 { 340 static char buf[100]; 341 enum operand op_type = OP_NONE; 342 343 if (reg == NULL) 344 { 345 /* We have a constant that also requires a value stored in a register 346 field. Handle these by updating the register field and saving the 347 value for later handling by either %S (shimm) or %L (limm). */ 348 349 /* Try to use a shimm value before a limm one. */ 350 if (ARC_SHIMM_CONST_P (value) 351 /* If we've seen a conditional suffix we have to use a limm. */ 352 && !cond_p 353 /* If we already have a shimm value that is different than ours 354 we have to use a limm. */ 355 && (!shimm_p || shimm == value)) 356 { 357 int marker; 358 359 op_type = OP_SHIMM; 360 /* Forget about shimm as dest mlm. */ 361 362 if ('a' != operand->fmt) 363 { 364 shimm_p = 1; 365 shimm = value; 366 flagshimm_handled_p = 1; 367 marker = flag_p ? ARC_REG_SHIMM_UPDATE : ARC_REG_SHIMM; 368 } 369 else 370 { 371 /* Don't request flag setting on shimm as dest. */ 372 marker = ARC_REG_SHIMM; 373 } 374 insn |= marker << operand->shift; 375 /* insn |= value & 511; - done later. */ 376 } 377 /* We have to use a limm. If we've already seen one they must match. */ 378 else if (!limm_p || limm == value) 379 { 380 op_type = OP_LIMM; 381 limm_p = 1; 382 limm = value; 383 insn |= ARC_REG_LIMM << operand->shift; 384 /* The constant is stored later. */ 385 } 386 else 387 *errmsg = _("unable to fit different valued constants into instruction"); 388 } 389 else 390 { 391 /* We have to handle both normal and auxiliary registers. */ 392 393 if (reg->type == AUXREG) 394 { 395 if (!(mods & ARC_MOD_AUXREG)) 396 *errmsg = _("auxiliary register not allowed here"); 397 else 398 { 399 if ((insn & I(-1)) == I(2)) /* Check for use validity. */ 400 { 401 if (reg->flags & ARC_REGISTER_READONLY) 402 *errmsg = _("attempt to set readonly register"); 403 } 404 else 405 { 406 if (reg->flags & ARC_REGISTER_WRITEONLY) 407 *errmsg = _("attempt to read writeonly register"); 408 } 409 insn |= ARC_REG_SHIMM << operand->shift; 410 insn |= reg->value << arc_operands[reg->type].shift; 411 } 412 } 413 else 414 { 415 /* check for use validity. */ 416 if ('a' == operand->fmt || ((insn & I(-1)) < I(2))) 417 { 418 if (reg->flags & ARC_REGISTER_READONLY) 419 *errmsg = _("attempt to set readonly register"); 420 } 421 if ('a' != operand->fmt) 422 { 423 if (reg->flags & ARC_REGISTER_WRITEONLY) 424 *errmsg = _("attempt to read writeonly register"); 425 } 426 /* We should never get an invalid register number here. */ 427 if ((unsigned int) reg->value > 60) 428 { 429 sprintf (buf, _("invalid register number `%d'"), reg->value); 430 *errmsg = buf; 431 } 432 insn |= reg->value << operand->shift; 433 op_type = OP_REG; 434 } 435 } 436 437 switch (operand->fmt) 438 { 439 case 'a': 440 ls_operand[LS_DEST] = op_type; 441 break; 442 case 's': 443 ls_operand[LS_BASE] = op_type; 444 break; 445 case 'c': 446 if ((insn & I(-1)) == I(2)) 447 ls_operand[LS_VALUE] = op_type; 448 else 449 ls_operand[LS_OFFSET] = op_type; 450 break; 451 case 'o': case 'O': 452 ls_operand[LS_OFFSET] = op_type; 453 break; 454 } 455 456 return insn; 457 } 458 459 /* Called when we see an 'f' flag. */ 460 461 static arc_insn 462 insert_flag (arc_insn insn, 463 const struct arc_operand *operand ATTRIBUTE_UNUSED, 464 int mods ATTRIBUTE_UNUSED, 465 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 466 long value ATTRIBUTE_UNUSED, 467 const char **errmsg ATTRIBUTE_UNUSED) 468 { 469 /* We can't store anything in the insn until we've parsed the registers. 470 Just record the fact that we've got this flag. `insert_reg' will use it 471 to store the correct value (ARC_REG_SHIMM_UPDATE or bit 0x100). */ 472 flag_p = 1; 473 return insn; 474 } 475 476 /* Called when we see an nullify condition. */ 477 478 static arc_insn 479 insert_nullify (arc_insn insn, 480 const struct arc_operand *operand, 481 int mods ATTRIBUTE_UNUSED, 482 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 483 long value, 484 const char **errmsg ATTRIBUTE_UNUSED) 485 { 486 nullify_p = 1; 487 insn |= (value & ((1 << operand->bits) - 1)) << operand->shift; 488 nullify = value; 489 return insn; 490 } 491 492 /* Called after completely building an insn to ensure the 'f' flag gets set 493 properly. This is needed because we don't know how to set this flag until 494 we've parsed the registers. */ 495 496 static arc_insn 497 insert_flagfinish (arc_insn insn, 498 const struct arc_operand *operand, 499 int mods ATTRIBUTE_UNUSED, 500 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 501 long value ATTRIBUTE_UNUSED, 502 const char **errmsg ATTRIBUTE_UNUSED) 503 { 504 if (flag_p && !flagshimm_handled_p) 505 { 506 if (shimm_p) 507 abort (); 508 flagshimm_handled_p = 1; 509 insn |= (1 << operand->shift); 510 } 511 return insn; 512 } 513 514 /* Called when we see a conditional flag (eg: .eq). */ 515 516 static arc_insn 517 insert_cond (arc_insn insn, 518 const struct arc_operand *operand, 519 int mods ATTRIBUTE_UNUSED, 520 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 521 long value, 522 const char **errmsg ATTRIBUTE_UNUSED) 523 { 524 cond_p = 1; 525 insn |= (value & ((1 << operand->bits) - 1)) << operand->shift; 526 return insn; 527 } 528 529 /* Used in the "j" instruction to prevent constants from being interpreted as 530 shimm values (which the jump insn doesn't accept). This can also be used 531 to force the use of limm values in other situations (eg: ld r0,[foo] uses 532 this). 533 ??? The mechanism is sound. Access to it is a bit klunky right now. */ 534 535 static arc_insn 536 insert_forcelimm (arc_insn insn, 537 const struct arc_operand *operand ATTRIBUTE_UNUSED, 538 int mods ATTRIBUTE_UNUSED, 539 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 540 long value ATTRIBUTE_UNUSED, 541 const char **errmsg ATTRIBUTE_UNUSED) 542 { 543 cond_p = 1; 544 return insn; 545 } 546 547 static arc_insn 548 insert_addr_wb (arc_insn insn, 549 const struct arc_operand *operand, 550 int mods ATTRIBUTE_UNUSED, 551 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 552 long value ATTRIBUTE_UNUSED, 553 const char **errmsg ATTRIBUTE_UNUSED) 554 { 555 addrwb_p = 1 << operand->shift; 556 return insn; 557 } 558 559 static arc_insn 560 insert_base (arc_insn insn, 561 const struct arc_operand *operand, 562 int mods, 563 const struct arc_operand_value *reg, 564 long value, 565 const char **errmsg) 566 { 567 if (reg != NULL) 568 { 569 arc_insn myinsn; 570 myinsn = insert_reg (0, operand,mods, reg, value, errmsg) >> operand->shift; 571 insn |= B(myinsn); 572 ls_operand[LS_BASE] = OP_REG; 573 } 574 else if (ARC_SHIMM_CONST_P (value) && !cond_p) 575 { 576 if (shimm_p && value != shimm) 577 { 578 /* Convert the previous shimm operand to a limm. */ 579 limm_p = 1; 580 limm = shimm; 581 insn &= ~C(-1); /* We know where the value is in insn. */ 582 insn |= C(ARC_REG_LIMM); 583 ls_operand[LS_VALUE] = OP_LIMM; 584 } 585 insn |= ARC_REG_SHIMM << operand->shift; 586 shimm_p = 1; 587 shimm = value; 588 ls_operand[LS_BASE] = OP_SHIMM; 589 ls_operand[LS_OFFSET] = OP_SHIMM; 590 } 591 else 592 { 593 if (limm_p && value != limm) 594 { 595 *errmsg = _("too many long constants"); 596 return insn; 597 } 598 limm_p = 1; 599 limm = value; 600 insn |= B(ARC_REG_LIMM); 601 ls_operand[LS_BASE] = OP_LIMM; 602 } 603 604 return insn; 605 } 606 607 /* Used in ld/st insns to handle the offset field. We don't try to 608 match operand syntax here. we catch bad combinations later. */ 609 610 static arc_insn 611 insert_offset (arc_insn insn, 612 const struct arc_operand *operand, 613 int mods, 614 const struct arc_operand_value *reg, 615 long value, 616 const char **errmsg) 617 { 618 long minval, maxval; 619 620 if (reg != NULL) 621 { 622 arc_insn myinsn; 623 myinsn = insert_reg (0,operand,mods,reg,value,errmsg) >> operand->shift; 624 ls_operand[LS_OFFSET] = OP_REG; 625 if (operand->flags & ARC_OPERAND_LOAD) /* Not if store, catch it later. */ 626 if ((insn & I(-1)) != I(1)) /* Not if opcode == 1, catch it later. */ 627 insn |= C (myinsn); 628 } 629 else 630 { 631 /* This is *way* more general than necessary, but maybe some day it'll 632 be useful. */ 633 if (operand->flags & ARC_OPERAND_SIGNED) 634 { 635 minval = -(1 << (operand->bits - 1)); 636 maxval = (1 << (operand->bits - 1)) - 1; 637 } 638 else 639 { 640 minval = 0; 641 maxval = (1 << operand->bits) - 1; 642 } 643 if ((cond_p && !limm_p) || (value < minval || value > maxval)) 644 { 645 if (limm_p && value != limm) 646 *errmsg = _("too many long constants"); 647 648 else 649 { 650 limm_p = 1; 651 limm = value; 652 if (operand->flags & ARC_OPERAND_STORE) 653 insn |= B(ARC_REG_LIMM); 654 if (operand->flags & ARC_OPERAND_LOAD) 655 insn |= C(ARC_REG_LIMM); 656 ls_operand[LS_OFFSET] = OP_LIMM; 657 } 658 } 659 else 660 { 661 if ((value < minval || value > maxval)) 662 *errmsg = "need too many limms"; 663 else if (shimm_p && value != shimm) 664 { 665 /* Check for bad operand combinations 666 before we lose info about them. */ 667 if ((insn & I(-1)) == I(1)) 668 { 669 *errmsg = _("too many shimms in load"); 670 goto out; 671 } 672 if (limm_p && operand->flags & ARC_OPERAND_LOAD) 673 { 674 *errmsg = _("too many long constants"); 675 goto out; 676 } 677 /* Convert what we thought was a shimm to a limm. */ 678 limm_p = 1; 679 limm = shimm; 680 if (ls_operand[LS_VALUE] == OP_SHIMM 681 && operand->flags & ARC_OPERAND_STORE) 682 { 683 insn &= ~C(-1); 684 insn |= C(ARC_REG_LIMM); 685 ls_operand[LS_VALUE] = OP_LIMM; 686 } 687 if (ls_operand[LS_BASE] == OP_SHIMM 688 && operand->flags & ARC_OPERAND_STORE) 689 { 690 insn &= ~B(-1); 691 insn |= B(ARC_REG_LIMM); 692 ls_operand[LS_BASE] = OP_LIMM; 693 } 694 } 695 shimm = value; 696 shimm_p = 1; 697 ls_operand[LS_OFFSET] = OP_SHIMM; 698 } 699 } 700 out: 701 return insn; 702 } 703 704 /* Used in st insns to do final disasemble syntax check. */ 705 706 static long 707 extract_st_syntax (arc_insn *insn, 708 const struct arc_operand *operand ATTRIBUTE_UNUSED, 709 int mods ATTRIBUTE_UNUSED, 710 const struct arc_operand_value **opval ATTRIBUTE_UNUSED, 711 int *invalid) 712 { 713 #define ST_SYNTAX(V,B,O) \ 714 ((ls_operand[LS_VALUE] == (V) && \ 715 ls_operand[LS_BASE] == (B) && \ 716 ls_operand[LS_OFFSET] == (O))) 717 718 if (!((ST_SYNTAX(OP_REG,OP_REG,OP_NONE) && (insn[0] & 511) == 0) 719 || ST_SYNTAX(OP_REG,OP_LIMM,OP_NONE) 720 || (ST_SYNTAX(OP_SHIMM,OP_REG,OP_NONE) && (insn[0] & 511) == 0) 721 || (ST_SYNTAX(OP_SHIMM,OP_SHIMM,OP_NONE) && (insn[0] & 511) == 0) 722 || ST_SYNTAX(OP_SHIMM,OP_LIMM,OP_NONE) 723 || ST_SYNTAX(OP_SHIMM,OP_LIMM,OP_SHIMM) 724 || ST_SYNTAX(OP_SHIMM,OP_SHIMM,OP_SHIMM) 725 || (ST_SYNTAX(OP_LIMM,OP_REG,OP_NONE) && (insn[0] & 511) == 0) 726 || ST_SYNTAX(OP_REG,OP_REG,OP_SHIMM) 727 || ST_SYNTAX(OP_REG,OP_SHIMM,OP_SHIMM) 728 || ST_SYNTAX(OP_SHIMM,OP_REG,OP_SHIMM) 729 || ST_SYNTAX(OP_LIMM,OP_SHIMM,OP_SHIMM) 730 || ST_SYNTAX(OP_LIMM,OP_SHIMM,OP_NONE) 731 || ST_SYNTAX(OP_LIMM,OP_REG,OP_SHIMM))) 732 *invalid = 1; 733 return 0; 734 } 735 736 int 737 arc_limm_fixup_adjust (arc_insn insn) 738 { 739 int retval = 0; 740 741 /* Check for st shimm,[limm]. */ 742 if ((insn & (I(-1) | C(-1) | B(-1))) == 743 (I(2) | C(ARC_REG_SHIMM) | B(ARC_REG_LIMM))) 744 { 745 retval = insn & 0x1ff; 746 if (retval & 0x100) /* Sign extend 9 bit offset. */ 747 retval |= ~0x1ff; 748 } 749 return -retval; /* Negate offset for return. */ 750 } 751 752 /* Used in st insns to do final syntax check. */ 753 754 static arc_insn 755 insert_st_syntax (arc_insn insn, 756 const struct arc_operand *operand ATTRIBUTE_UNUSED, 757 int mods ATTRIBUTE_UNUSED, 758 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 759 long value ATTRIBUTE_UNUSED, 760 const char **errmsg) 761 { 762 if (ST_SYNTAX (OP_SHIMM,OP_REG,OP_NONE) && shimm != 0) 763 { 764 /* Change an illegal insn into a legal one, it's easier to 765 do it here than to try to handle it during operand scan. */ 766 limm_p = 1; 767 limm = shimm; 768 shimm_p = 0; 769 shimm = 0; 770 insn = insn & ~(C(-1) | 511); 771 insn |= ARC_REG_LIMM << ARC_SHIFT_REGC; 772 ls_operand[LS_VALUE] = OP_LIMM; 773 } 774 775 if (ST_SYNTAX (OP_REG, OP_SHIMM, OP_NONE) 776 || ST_SYNTAX (OP_LIMM, OP_SHIMM, OP_NONE)) 777 { 778 /* Try to salvage this syntax. */ 779 if (shimm & 0x1) /* Odd shimms won't work. */ 780 { 781 if (limm_p) /* Do we have a limm already? */ 782 *errmsg = _("impossible store"); 783 784 limm_p = 1; 785 limm = shimm; 786 shimm = 0; 787 shimm_p = 0; 788 insn = insn & ~(B(-1) | 511); 789 insn |= B(ARC_REG_LIMM); 790 ls_operand[LS_BASE] = OP_LIMM; 791 } 792 else 793 { 794 shimm >>= 1; 795 insn = insn & ~511; 796 insn |= shimm; 797 ls_operand[LS_OFFSET] = OP_SHIMM; 798 } 799 } 800 if (ST_SYNTAX(OP_SHIMM,OP_LIMM,OP_NONE)) 801 limm += arc_limm_fixup_adjust(insn); 802 803 if (! (ST_SYNTAX (OP_REG,OP_REG,OP_NONE) 804 || ST_SYNTAX (OP_REG,OP_LIMM,OP_NONE) 805 || ST_SYNTAX (OP_REG,OP_REG,OP_SHIMM) 806 || ST_SYNTAX (OP_REG,OP_SHIMM,OP_SHIMM) 807 || (ST_SYNTAX (OP_SHIMM,OP_SHIMM,OP_NONE) && (shimm == 0)) 808 || ST_SYNTAX (OP_SHIMM,OP_LIMM,OP_NONE) 809 || ST_SYNTAX (OP_SHIMM,OP_REG,OP_NONE) 810 || ST_SYNTAX (OP_SHIMM,OP_REG,OP_SHIMM) 811 || ST_SYNTAX (OP_SHIMM,OP_SHIMM,OP_SHIMM) 812 || ST_SYNTAX (OP_LIMM,OP_SHIMM,OP_SHIMM) 813 || ST_SYNTAX (OP_LIMM,OP_REG,OP_NONE) 814 || ST_SYNTAX (OP_LIMM,OP_REG,OP_SHIMM))) 815 *errmsg = _("st operand error"); 816 if (addrwb_p) 817 { 818 if (ls_operand[LS_BASE] != OP_REG) 819 *errmsg = _("address writeback not allowed"); 820 insn |= addrwb_p; 821 } 822 if (ST_SYNTAX(OP_SHIMM,OP_REG,OP_NONE) && shimm) 823 *errmsg = _("store value must be zero"); 824 return insn; 825 } 826 827 /* Used in ld insns to do final syntax check. */ 828 829 static arc_insn 830 insert_ld_syntax (arc_insn insn, 831 const struct arc_operand *operand ATTRIBUTE_UNUSED, 832 int mods ATTRIBUTE_UNUSED, 833 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 834 long value ATTRIBUTE_UNUSED, 835 const char **errmsg) 836 { 837 #define LD_SYNTAX(D, B, O) \ 838 ( (ls_operand[LS_DEST] == (D) \ 839 && ls_operand[LS_BASE] == (B) \ 840 && ls_operand[LS_OFFSET] == (O))) 841 842 int test = insn & I (-1); 843 844 if (!(test == I (1))) 845 { 846 if ((ls_operand[LS_DEST] == OP_SHIMM || ls_operand[LS_BASE] == OP_SHIMM 847 || ls_operand[LS_OFFSET] == OP_SHIMM)) 848 *errmsg = _("invalid load/shimm insn"); 849 } 850 if (!(LD_SYNTAX(OP_REG,OP_REG,OP_NONE) 851 || LD_SYNTAX(OP_REG,OP_REG,OP_REG) 852 || LD_SYNTAX(OP_REG,OP_REG,OP_SHIMM) 853 || (LD_SYNTAX(OP_REG,OP_LIMM,OP_REG) && !(test == I(1))) 854 || (LD_SYNTAX(OP_REG,OP_REG,OP_LIMM) && !(test == I(1))) 855 || LD_SYNTAX(OP_REG,OP_SHIMM,OP_SHIMM) 856 || (LD_SYNTAX(OP_REG,OP_LIMM,OP_NONE) && (test == I(1))))) 857 *errmsg = _("ld operand error"); 858 if (addrwb_p) 859 { 860 if (ls_operand[LS_BASE] != OP_REG) 861 *errmsg = _("address writeback not allowed"); 862 insn |= addrwb_p; 863 } 864 return insn; 865 } 866 867 /* Used in ld insns to do final syntax check. */ 868 869 static long 870 extract_ld_syntax (arc_insn *insn, 871 const struct arc_operand *operand ATTRIBUTE_UNUSED, 872 int mods ATTRIBUTE_UNUSED, 873 const struct arc_operand_value **opval ATTRIBUTE_UNUSED, 874 int *invalid) 875 { 876 int test = insn[0] & I(-1); 877 878 if (!(test == I(1))) 879 { 880 if ((ls_operand[LS_DEST] == OP_SHIMM || ls_operand[LS_BASE] == OP_SHIMM 881 || ls_operand[LS_OFFSET] == OP_SHIMM)) 882 *invalid = 1; 883 } 884 if (!( (LD_SYNTAX (OP_REG, OP_REG, OP_NONE) && (test == I(1))) 885 || LD_SYNTAX (OP_REG, OP_REG, OP_REG) 886 || LD_SYNTAX (OP_REG, OP_REG, OP_SHIMM) 887 || (LD_SYNTAX (OP_REG, OP_REG, OP_LIMM) && !(test == I(1))) 888 || (LD_SYNTAX (OP_REG, OP_LIMM, OP_REG) && !(test == I(1))) 889 || (LD_SYNTAX (OP_REG, OP_SHIMM, OP_NONE) && (shimm == 0)) 890 || LD_SYNTAX (OP_REG, OP_SHIMM, OP_SHIMM) 891 || (LD_SYNTAX (OP_REG, OP_LIMM, OP_NONE) && (test == I(1))))) 892 *invalid = 1; 893 return 0; 894 } 895 896 /* Called at the end of processing normal insns (eg: add) to insert a shimm 897 value (if present) into the insn. */ 898 899 static arc_insn 900 insert_shimmfinish (arc_insn insn, 901 const struct arc_operand *operand, 902 int mods ATTRIBUTE_UNUSED, 903 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 904 long value ATTRIBUTE_UNUSED, 905 const char **errmsg ATTRIBUTE_UNUSED) 906 { 907 if (shimm_p) 908 insn |= (shimm & ((1 << operand->bits) - 1)) << operand->shift; 909 return insn; 910 } 911 912 /* Called at the end of processing normal insns (eg: add) to insert a limm 913 value (if present) into the insn. 914 915 Note that this function is only intended to handle instructions (with 4 byte 916 immediate operands). It is not intended to handle data. */ 917 918 /* ??? Actually, there's nothing for us to do as we can't call frag_more, the 919 caller must do that. The extract fns take a pointer to two words. The 920 insert fns could be converted and then we could do something useful, but 921 then the reloc handlers would have to know to work on the second word of 922 a 2 word quantity. That's too much so we don't handle them. */ 923 924 static arc_insn 925 insert_limmfinish (arc_insn insn, 926 const struct arc_operand *operand ATTRIBUTE_UNUSED, 927 int mods ATTRIBUTE_UNUSED, 928 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 929 long value ATTRIBUTE_UNUSED, 930 const char **errmsg ATTRIBUTE_UNUSED) 931 { 932 return insn; 933 } 934 935 static arc_insn 936 insert_jumpflags (arc_insn insn, 937 const struct arc_operand *operand, 938 int mods ATTRIBUTE_UNUSED, 939 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 940 long value, 941 const char **errmsg) 942 { 943 if (!flag_p) 944 *errmsg = _("jump flags, but no .f seen"); 945 946 else if (!limm_p) 947 *errmsg = _("jump flags, but no limm addr"); 948 949 else if (limm & 0xfc000000) 950 *errmsg = _("flag bits of jump address limm lost"); 951 952 else if (limm & 0x03000000) 953 *errmsg = _("attempt to set HR bits"); 954 955 else if ((value & ((1 << operand->bits) - 1)) != value) 956 *errmsg = _("bad jump flags value"); 957 958 jumpflags_p = 1; 959 limm = ((limm & ((1 << operand->shift) - 1)) 960 | ((value & ((1 << operand->bits) - 1)) << operand->shift)); 961 return insn; 962 } 963 964 /* Called at the end of unary operand macros to copy the B field to C. */ 965 966 static arc_insn 967 insert_unopmacro (arc_insn insn, 968 const struct arc_operand *operand, 969 int mods ATTRIBUTE_UNUSED, 970 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 971 long value ATTRIBUTE_UNUSED, 972 const char **errmsg ATTRIBUTE_UNUSED) 973 { 974 insn |= ((insn >> ARC_SHIFT_REGB) & ARC_MASK_REG) << operand->shift; 975 return insn; 976 } 977 978 /* Insert a relative address for a branch insn (b, bl, or lp). */ 979 980 static arc_insn 981 insert_reladdr (arc_insn insn, 982 const struct arc_operand *operand, 983 int mods ATTRIBUTE_UNUSED, 984 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 985 long value, 986 const char **errmsg) 987 { 988 if (value & 3) 989 *errmsg = _("branch address not on 4 byte boundary"); 990 insn |= ((value >> 2) & ((1 << operand->bits) - 1)) << operand->shift; 991 return insn; 992 } 993 994 /* Insert a limm value as a 26 bit address right shifted 2 into the insn. 995 996 Note that this function is only intended to handle instructions (with 4 byte 997 immediate operands). It is not intended to handle data. */ 998 999 /* ??? Actually, there's little for us to do as we can't call frag_more, the 1000 caller must do that. The extract fns take a pointer to two words. The 1001 insert fns could be converted and then we could do something useful, but 1002 then the reloc handlers would have to know to work on the second word of 1003 a 2 word quantity. That's too much so we don't handle them. 1004 1005 We do check for correct usage of the nullify suffix, or we 1006 set the default correctly, though. */ 1007 1008 static arc_insn 1009 insert_absaddr (arc_insn insn, 1010 const struct arc_operand *operand ATTRIBUTE_UNUSED, 1011 int mods ATTRIBUTE_UNUSED, 1012 const struct arc_operand_value *reg ATTRIBUTE_UNUSED, 1013 long value ATTRIBUTE_UNUSED, 1014 const char **errmsg) 1015 { 1016 if (limm_p) 1017 { 1018 /* If it is a jump and link, .jd must be specified. */ 1019 if (insn & R (-1, 9, 1)) 1020 { 1021 if (!nullify_p) 1022 insn |= 0x02 << 5; /* Default nullify to .jd. */ 1023 1024 else if (nullify != 0x02) 1025 *errmsg = _("must specify .jd or no nullify suffix"); 1026 } 1027 } 1028 return insn; 1029 } 1030 1031 /* Extraction functions. 1033 1034 The suffix extraction functions' return value is redundant since it can be 1035 obtained from (*OPVAL)->value. However, the boolean suffixes don't have 1036 a suffix table entry for the "false" case, so values of zero must be 1037 obtained from the return value (*OPVAL == NULL). */ 1038 1039 /* Called by the disassembler before printing an instruction. */ 1040 1041 void 1042 arc_opcode_init_extract (void) 1043 { 1044 arc_opcode_init_insert (); 1045 } 1046 1047 static const struct arc_operand_value * 1048 lookup_register (int type, long regno) 1049 { 1050 const struct arc_operand_value *r,*end; 1051 struct arc_ext_operand_value *ext_oper = arc_ext_operands; 1052 1053 while (ext_oper) 1054 { 1055 if (ext_oper->operand.type == type && ext_oper->operand.value == regno) 1056 return (&ext_oper->operand); 1057 ext_oper = ext_oper->next; 1058 } 1059 1060 if (type == REG) 1061 return &arc_reg_names[regno]; 1062 1063 /* ??? This is a little slow and can be speeded up. */ 1064 for (r = arc_reg_names, end = arc_reg_names + arc_reg_names_count; 1065 r < end; ++r) 1066 if (type == r->type && regno == r->value) 1067 return r; 1068 return 0; 1069 } 1070 1071 /* As we're extracting registers, keep an eye out for the 'f' indicator 1072 (ARC_REG_SHIMM_UPDATE). If we find a register (not a constant marker, 1073 like ARC_REG_SHIMM), set OPVAL so our caller will know this is a register. 1074 1075 We must also handle auxiliary registers for lr/sr insns. They are just 1076 constants with special names. */ 1077 1078 static long 1079 extract_reg (arc_insn *insn, 1080 const struct arc_operand *operand, 1081 int mods, 1082 const struct arc_operand_value **opval, 1083 int *invalid ATTRIBUTE_UNUSED) 1084 { 1085 int regno; 1086 long value; 1087 enum operand op_type; 1088 1089 /* Get the register number. */ 1090 regno = (*insn >> operand->shift) & ((1 << operand->bits) - 1); 1091 1092 /* Is it a constant marker? */ 1093 if (regno == ARC_REG_SHIMM) 1094 { 1095 op_type = OP_SHIMM; 1096 /* Always return zero if dest is a shimm mlm. */ 1097 1098 if ('a' != operand->fmt) 1099 { 1100 value = *insn & 511; 1101 if ((operand->flags & ARC_OPERAND_SIGNED) 1102 && (value & 256)) 1103 value -= 512; 1104 if (!flagshimm_handled_p) 1105 flag_p = 0; 1106 flagshimm_handled_p = 1; 1107 } 1108 else 1109 value = 0; 1110 } 1111 else if (regno == ARC_REG_SHIMM_UPDATE) 1112 { 1113 op_type = OP_SHIMM; 1114 1115 /* Always return zero if dest is a shimm mlm. */ 1116 if ('a' != operand->fmt) 1117 { 1118 value = *insn & 511; 1119 if ((operand->flags & ARC_OPERAND_SIGNED) && (value & 256)) 1120 value -= 512; 1121 } 1122 else 1123 value = 0; 1124 1125 flag_p = 1; 1126 flagshimm_handled_p = 1; 1127 } 1128 else if (regno == ARC_REG_LIMM) 1129 { 1130 op_type = OP_LIMM; 1131 value = insn[1]; 1132 limm_p = 1; 1133 1134 /* If this is a jump instruction (j,jl), show new pc correctly. */ 1135 if (0x07 == ((*insn & I(-1)) >> 27)) 1136 value = (value & 0xffffff); 1137 } 1138 1139 /* It's a register, set OPVAL (that's the only way we distinguish registers 1140 from constants here). */ 1141 else 1142 { 1143 const struct arc_operand_value *reg = lookup_register (REG, regno); 1144 1145 op_type = OP_REG; 1146 1147 if (reg == NULL) 1148 abort (); 1149 if (opval != NULL) 1150 *opval = reg; 1151 value = regno; 1152 } 1153 1154 /* If this field takes an auxiliary register, see if it's a known one. */ 1155 if ((mods & ARC_MOD_AUXREG) 1156 && ARC_REG_CONSTANT_P (regno)) 1157 { 1158 const struct arc_operand_value *reg = lookup_register (AUXREG, value); 1159 1160 /* This is really a constant, but tell the caller it has a special 1161 name. */ 1162 if (reg != NULL && opval != NULL) 1163 *opval = reg; 1164 } 1165 1166 switch(operand->fmt) 1167 { 1168 case 'a': 1169 ls_operand[LS_DEST] = op_type; 1170 break; 1171 case 's': 1172 ls_operand[LS_BASE] = op_type; 1173 break; 1174 case 'c': 1175 if ((insn[0]& I(-1)) == I(2)) 1176 ls_operand[LS_VALUE] = op_type; 1177 else 1178 ls_operand[LS_OFFSET] = op_type; 1179 break; 1180 case 'o': case 'O': 1181 ls_operand[LS_OFFSET] = op_type; 1182 break; 1183 } 1184 1185 return value; 1186 } 1187 1188 /* Return the value of the "flag update" field for shimm insns. 1189 This value is actually stored in the register field. */ 1190 1191 static long 1192 extract_flag (arc_insn *insn, 1193 const struct arc_operand *operand, 1194 int mods ATTRIBUTE_UNUSED, 1195 const struct arc_operand_value **opval, 1196 int *invalid ATTRIBUTE_UNUSED) 1197 { 1198 int f; 1199 const struct arc_operand_value *val; 1200 1201 if (flagshimm_handled_p) 1202 f = flag_p != 0; 1203 else 1204 f = (*insn & (1 << operand->shift)) != 0; 1205 1206 /* There is no text for zero values. */ 1207 if (f == 0) 1208 return 0; 1209 flag_p = 1; 1210 val = arc_opcode_lookup_suffix (operand, 1); 1211 if (opval != NULL && val != NULL) 1212 *opval = val; 1213 return val->value; 1214 } 1215 1216 /* Extract the condition code (if it exists). 1217 If we've seen a shimm value in this insn (meaning that the insn can't have 1218 a condition code field), then we don't store anything in OPVAL and return 1219 zero. */ 1220 1221 static long 1222 extract_cond (arc_insn *insn, 1223 const struct arc_operand *operand, 1224 int mods ATTRIBUTE_UNUSED, 1225 const struct arc_operand_value **opval, 1226 int *invalid ATTRIBUTE_UNUSED) 1227 { 1228 long cond; 1229 const struct arc_operand_value *val; 1230 1231 if (flagshimm_handled_p) 1232 return 0; 1233 1234 cond = (*insn >> operand->shift) & ((1 << operand->bits) - 1); 1235 val = arc_opcode_lookup_suffix (operand, cond); 1236 1237 /* Ignore NULL values of `val'. Several condition code values are 1238 reserved for extensions. */ 1239 if (opval != NULL && val != NULL) 1240 *opval = val; 1241 return cond; 1242 } 1243 1244 /* Extract a branch address. 1245 We return the value as a real address (not right shifted by 2). */ 1246 1247 static long 1248 extract_reladdr (arc_insn *insn, 1249 const struct arc_operand *operand, 1250 int mods ATTRIBUTE_UNUSED, 1251 const struct arc_operand_value **opval ATTRIBUTE_UNUSED, 1252 int *invalid ATTRIBUTE_UNUSED) 1253 { 1254 long addr; 1255 1256 addr = (*insn >> operand->shift) & ((1 << operand->bits) - 1); 1257 if ((operand->flags & ARC_OPERAND_SIGNED) 1258 && (addr & (1 << (operand->bits - 1)))) 1259 addr -= 1 << operand->bits; 1260 return addr << 2; 1261 } 1262 1263 /* Extract the flags bits from a j or jl long immediate. */ 1264 1265 static long 1266 extract_jumpflags (arc_insn *insn, 1267 const struct arc_operand *operand, 1268 int mods ATTRIBUTE_UNUSED, 1269 const struct arc_operand_value **opval ATTRIBUTE_UNUSED, 1270 int *invalid) 1271 { 1272 if (!flag_p || !limm_p) 1273 *invalid = 1; 1274 return ((flag_p && limm_p) 1275 ? (insn[1] >> operand->shift) & ((1 << operand->bits) -1): 0); 1276 } 1277 1278 /* Extract st insn's offset. */ 1279 1280 static long 1281 extract_st_offset (arc_insn *insn, 1282 const struct arc_operand *operand, 1283 int mods ATTRIBUTE_UNUSED, 1284 const struct arc_operand_value **opval ATTRIBUTE_UNUSED, 1285 int *invalid) 1286 { 1287 int value = 0; 1288 1289 if (ls_operand[LS_VALUE] != OP_SHIMM || ls_operand[LS_BASE] != OP_LIMM) 1290 { 1291 value = insn[0] & 511; 1292 if ((operand->flags & ARC_OPERAND_SIGNED) && (value & 256)) 1293 value -= 512; 1294 if (value) 1295 ls_operand[LS_OFFSET] = OP_SHIMM; 1296 } 1297 else 1298 *invalid = 1; 1299 1300 return value; 1301 } 1302 1303 /* Extract ld insn's offset. */ 1304 1305 static long 1306 extract_ld_offset (arc_insn *insn, 1307 const struct arc_operand *operand, 1308 int mods, 1309 const struct arc_operand_value **opval, 1310 int *invalid) 1311 { 1312 int test = insn[0] & I(-1); 1313 int value; 1314 1315 if (test) 1316 { 1317 value = insn[0] & 511; 1318 if ((operand->flags & ARC_OPERAND_SIGNED) && (value & 256)) 1319 value -= 512; 1320 if (value) 1321 ls_operand[LS_OFFSET] = OP_SHIMM; 1322 1323 return value; 1324 } 1325 /* If it isn't in the insn, it's concealed behind reg 'c'. */ 1326 return extract_reg (insn, &arc_operands[arc_operand_map['c']], 1327 mods, opval, invalid); 1328 } 1329 1330 /* The only thing this does is set the `invalid' flag if B != C. 1331 This is needed because the "mov" macro appears before it's real insn "and" 1332 and we don't want the disassembler to confuse them. */ 1333 1334 static long 1335 extract_unopmacro (arc_insn *insn, 1336 const struct arc_operand *operand ATTRIBUTE_UNUSED, 1337 int mods ATTRIBUTE_UNUSED, 1338 const struct arc_operand_value **opval ATTRIBUTE_UNUSED, 1339 int *invalid) 1340 { 1341 /* This misses the case where B == ARC_REG_SHIMM_UPDATE && 1342 C == ARC_REG_SHIMM (or vice versa). No big deal. Those insns will get 1343 printed as "and"s. */ 1344 if (((*insn >> ARC_SHIFT_REGB) & ARC_MASK_REG) 1345 != ((*insn >> ARC_SHIFT_REGC) & ARC_MASK_REG)) 1346 if (invalid != NULL) 1347 *invalid = 1; 1348 return 0; 1349 } 1350 1351 /* ARC instructions. 1353 1354 Longer versions of insns must appear before shorter ones (if gas sees 1355 "lsr r2,r3,1" when it's parsing "lsr %a,%b" it will think the ",1" is 1356 junk). This isn't necessary for `ld' because of the trailing ']'. 1357 1358 Instructions that are really macros based on other insns must appear 1359 before the real insn so they're chosen when disassembling. Eg: The `mov' 1360 insn is really the `and' insn. */ 1361 1362 struct arc_opcode arc_opcodes[] = 1363 { 1364 /* Base case instruction set (core versions 5-8). */ 1365 1366 /* "mov" is really an "and". */ 1367 { "mov%.q%.f %a,%b%F%S%L%U", I(-1), I(12), ARC_MACH_5, 0, 0 }, 1368 /* "asl" is really an "add". */ 1369 { "asl%.q%.f %a,%b%F%S%L%U", I(-1), I(8), ARC_MACH_5, 0, 0 }, 1370 /* "lsl" is really an "add". */ 1371 { "lsl%.q%.f %a,%b%F%S%L%U", I(-1), I(8), ARC_MACH_5, 0, 0 }, 1372 /* "nop" is really an "xor". */ 1373 { "nop", 0x7fffffff, 0x7fffffff, ARC_MACH_5, 0, 0 }, 1374 /* "rlc" is really an "adc". */ 1375 { "rlc%.q%.f %a,%b%F%S%L%U", I(-1), I(9), ARC_MACH_5, 0, 0 }, 1376 { "adc%.q%.f %a,%b,%c%F%S%L", I(-1), I(9), ARC_MACH_5, 0, 0 }, 1377 { "add%.q%.f %a,%b,%c%F%S%L", I(-1), I(8), ARC_MACH_5, 0, 0 }, 1378 { "and%.q%.f %a,%b,%c%F%S%L", I(-1), I(12), ARC_MACH_5, 0, 0 }, 1379 { "asr%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(1), ARC_MACH_5, 0, 0 }, 1380 { "bic%.q%.f %a,%b,%c%F%S%L", I(-1), I(14), ARC_MACH_5, 0, 0 }, 1381 { "b%q%.n %B", I(-1), I(4), ARC_MACH_5 | ARC_OPCODE_COND_BRANCH, 0, 0 }, 1382 { "bl%q%.n %B", I(-1), I(5), ARC_MACH_5 | ARC_OPCODE_COND_BRANCH, 0, 0 }, 1383 { "extb%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(7), ARC_MACH_5, 0, 0 }, 1384 { "extw%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(8), ARC_MACH_5, 0, 0 }, 1385 { "flag%.q %b%G%S%L", I(-1)|A(-1)|C(-1), I(3)|A(ARC_REG_SHIMM_UPDATE)|C(0), ARC_MACH_5, 0, 0 }, 1386 { "brk", 0x1ffffe00, 0x1ffffe00, ARC_MACH_7, 0, 0 }, 1387 { "sleep", 0x1ffffe01, 0x1ffffe01, ARC_MACH_7, 0, 0 }, 1388 { "swi", 0x1ffffe02, 0x1ffffe02, ARC_MACH_8, 0, 0 }, 1389 /* %Q: force cond_p=1 -> no shimm values. This insn allows an 1390 optional flags spec. */ 1391 { "j%q%Q%.n%.f %b%F%J,%j", I(-1)|A(-1)|C(-1)|R(-1,7,1), I(7)|A(0)|C(0)|R(0,7,1), ARC_MACH_5 | ARC_OPCODE_COND_BRANCH, 0, 0 }, 1392 { "j%q%Q%.n%.f %b%F%J", I(-1)|A(-1)|C(-1)|R(-1,7,1), I(7)|A(0)|C(0)|R(0,7,1), ARC_MACH_5 | ARC_OPCODE_COND_BRANCH, 0, 0 }, 1393 /* This insn allows an optional flags spec. */ 1394 { "jl%q%Q%.n%.f %b%F%J,%j", I(-1)|A(-1)|C(-1)|R(-1,7,1)|R(-1,9,1), I(7)|A(0)|C(0)|R(0,7,1)|R(1,9,1), ARC_MACH_6 | ARC_OPCODE_COND_BRANCH, 0, 0 }, 1395 { "jl%q%Q%.n%.f %b%F%J", I(-1)|A(-1)|C(-1)|R(-1,7,1)|R(-1,9,1), I(7)|A(0)|C(0)|R(0,7,1)|R(1,9,1), ARC_MACH_6 | ARC_OPCODE_COND_BRANCH, 0, 0 }, 1396 /* Put opcode 1 ld insns first so shimm gets prefered over limm. 1397 "[%b]" is before "[%b,%o]" so 0 offsets don't get printed. */ 1398 { "ld%Z%.X%.W%.E %a,[%s]%S%L%1", I(-1)|R(-1,13,1)|R(-1,0,511), I(1)|R(0,13,1)|R(0,0,511), ARC_MACH_5, 0, 0 }, 1399 { "ld%z%.x%.w%.e %a,[%s]%S%L%1", I(-1)|R(-1,4,1)|R(-1,6,7), I(0)|R(0,4,1)|R(0,6,7), ARC_MACH_5, 0, 0 }, 1400 { "ld%z%.x%.w%.e %a,[%s,%O]%S%L%1", I(-1)|R(-1,4,1)|R(-1,6,7), I(0)|R(0,4,1)|R(0,6,7), ARC_MACH_5, 0, 0 }, 1401 { "ld%Z%.X%.W%.E %a,[%s,%O]%S%L%3", I(-1)|R(-1,13,1), I(1)|R(0,13,1), ARC_MACH_5, 0, 0 }, 1402 { "lp%q%.n %B", I(-1), I(6), ARC_MACH_5, 0, 0 }, 1403 { "lr %a,[%Ab]%S%L", I(-1)|C(-1), I(1)|C(0x10), ARC_MACH_5, 0, 0 }, 1404 { "lsr%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(2), ARC_MACH_5, 0, 0 }, 1405 { "or%.q%.f %a,%b,%c%F%S%L", I(-1), I(13), ARC_MACH_5, 0, 0 }, 1406 { "ror%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(3), ARC_MACH_5, 0, 0 }, 1407 { "rrc%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(4), ARC_MACH_5, 0, 0 }, 1408 { "sbc%.q%.f %a,%b,%c%F%S%L", I(-1), I(11), ARC_MACH_5, 0, 0 }, 1409 { "sexb%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(5), ARC_MACH_5, 0, 0 }, 1410 { "sexw%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(6), ARC_MACH_5, 0, 0 }, 1411 { "sr %c,[%Ab]%S%L", I(-1)|A(-1), I(2)|A(0x10), ARC_MACH_5, 0, 0 }, 1412 /* "[%b]" is before "[%b,%o]" so 0 offsets don't get printed. */ 1413 { "st%y%.v%.D %c,[%s]%L%S%0", I(-1)|R(-1,25,1)|R(-1,21,1), I(2)|R(0,25,1)|R(0,21,1), ARC_MACH_5, 0, 0 }, 1414 { "st%y%.v%.D %c,[%s,%o]%S%L%2", I(-1)|R(-1,25,1)|R(-1,21,1), I(2)|R(0,25,1)|R(0,21,1), ARC_MACH_5, 0, 0 }, 1415 { "sub%.q%.f %a,%b,%c%F%S%L", I(-1), I(10), ARC_MACH_5, 0, 0 }, 1416 { "xor%.q%.f %a,%b,%c%F%S%L", I(-1), I(15), ARC_MACH_5, 0, 0 } 1417 }; 1418 1419 const int arc_opcodes_count = sizeof (arc_opcodes) / sizeof (arc_opcodes[0]); 1420 1421 const struct arc_operand_value arc_reg_names[] = 1422 { 1423 /* Core register set r0-r63. */ 1424 1425 /* r0-r28 - general purpose registers. */ 1426 { "r0", 0, REG, 0 }, { "r1", 1, REG, 0 }, { "r2", 2, REG, 0 }, 1427 { "r3", 3, REG, 0 }, { "r4", 4, REG, 0 }, { "r5", 5, REG, 0 }, 1428 { "r6", 6, REG, 0 }, { "r7", 7, REG, 0 }, { "r8", 8, REG, 0 }, 1429 { "r9", 9, REG, 0 }, { "r10", 10, REG, 0 }, { "r11", 11, REG, 0 }, 1430 { "r12", 12, REG, 0 }, { "r13", 13, REG, 0 }, { "r14", 14, REG, 0 }, 1431 { "r15", 15, REG, 0 }, { "r16", 16, REG, 0 }, { "r17", 17, REG, 0 }, 1432 { "r18", 18, REG, 0 }, { "r19", 19, REG, 0 }, { "r20", 20, REG, 0 }, 1433 { "r21", 21, REG, 0 }, { "r22", 22, REG, 0 }, { "r23", 23, REG, 0 }, 1434 { "r24", 24, REG, 0 }, { "r25", 25, REG, 0 }, { "r26", 26, REG, 0 }, 1435 { "r27", 27, REG, 0 }, { "r28", 28, REG, 0 }, 1436 /* Maskable interrupt link register. */ 1437 { "ilink1", 29, REG, 0 }, 1438 /* Maskable interrupt link register. */ 1439 { "ilink2", 30, REG, 0 }, 1440 /* Branch-link register. */ 1441 { "blink", 31, REG, 0 }, 1442 1443 /* r32-r59 reserved for extensions. */ 1444 { "r32", 32, REG, 0 }, { "r33", 33, REG, 0 }, { "r34", 34, REG, 0 }, 1445 { "r35", 35, REG, 0 }, { "r36", 36, REG, 0 }, { "r37", 37, REG, 0 }, 1446 { "r38", 38, REG, 0 }, { "r39", 39, REG, 0 }, { "r40", 40, REG, 0 }, 1447 { "r41", 41, REG, 0 }, { "r42", 42, REG, 0 }, { "r43", 43, REG, 0 }, 1448 { "r44", 44, REG, 0 }, { "r45", 45, REG, 0 }, { "r46", 46, REG, 0 }, 1449 { "r47", 47, REG, 0 }, { "r48", 48, REG, 0 }, { "r49", 49, REG, 0 }, 1450 { "r50", 50, REG, 0 }, { "r51", 51, REG, 0 }, { "r52", 52, REG, 0 }, 1451 { "r53", 53, REG, 0 }, { "r54", 54, REG, 0 }, { "r55", 55, REG, 0 }, 1452 { "r56", 56, REG, 0 }, { "r57", 57, REG, 0 }, { "r58", 58, REG, 0 }, 1453 { "r59", 59, REG, 0 }, 1454 1455 /* Loop count register (24 bits). */ 1456 { "lp_count", 60, REG, 0 }, 1457 /* Short immediate data indicator setting flags. */ 1458 { "r61", 61, REG, ARC_REGISTER_READONLY }, 1459 /* Long immediate data indicator setting flags. */ 1460 { "r62", 62, REG, ARC_REGISTER_READONLY }, 1461 /* Short immediate data indicator not setting flags. */ 1462 { "r63", 63, REG, ARC_REGISTER_READONLY }, 1463 1464 /* Small-data base register. */ 1465 { "gp", 26, REG, 0 }, 1466 /* Frame pointer. */ 1467 { "fp", 27, REG, 0 }, 1468 /* Stack pointer. */ 1469 { "sp", 28, REG, 0 }, 1470 1471 { "r29", 29, REG, 0 }, 1472 { "r30", 30, REG, 0 }, 1473 { "r31", 31, REG, 0 }, 1474 { "r60", 60, REG, 0 }, 1475 1476 /* Auxiliary register set. */ 1477 1478 /* Auxiliary register address map: 1479 0xffffffff-0xffffff00 (-1..-256) - customer shimm allocation 1480 0xfffffeff-0x80000000 - customer limm allocation 1481 0x7fffffff-0x00000100 - ARC limm allocation 1482 0x000000ff-0x00000000 - ARC shimm allocation */ 1483 1484 /* Base case auxiliary registers (shimm address). */ 1485 { "status", 0x00, AUXREG, 0 }, 1486 { "semaphore", 0x01, AUXREG, 0 }, 1487 { "lp_start", 0x02, AUXREG, 0 }, 1488 { "lp_end", 0x03, AUXREG, 0 }, 1489 { "identity", 0x04, AUXREG, ARC_REGISTER_READONLY }, 1490 { "debug", 0x05, AUXREG, 0 }, 1491 }; 1492 1493 const int arc_reg_names_count = 1494 sizeof (arc_reg_names) / sizeof (arc_reg_names[0]); 1495 1496 /* The suffix table. 1497 Operands with the same name must be stored together. */ 1498 1499 const struct arc_operand_value arc_suffixes[] = 1500 { 1501 /* Entry 0 is special, default values aren't printed by the disassembler. */ 1502 { "", 0, -1, 0 }, 1503 1504 /* Base case condition codes. */ 1505 { "al", 0, COND, 0 }, 1506 { "ra", 0, COND, 0 }, 1507 { "eq", 1, COND, 0 }, 1508 { "z", 1, COND, 0 }, 1509 { "ne", 2, COND, 0 }, 1510 { "nz", 2, COND, 0 }, 1511 { "pl", 3, COND, 0 }, 1512 { "p", 3, COND, 0 }, 1513 { "mi", 4, COND, 0 }, 1514 { "n", 4, COND, 0 }, 1515 { "cs", 5, COND, 0 }, 1516 { "c", 5, COND, 0 }, 1517 { "lo", 5, COND, 0 }, 1518 { "cc", 6, COND, 0 }, 1519 { "nc", 6, COND, 0 }, 1520 { "hs", 6, COND, 0 }, 1521 { "vs", 7, COND, 0 }, 1522 { "v", 7, COND, 0 }, 1523 { "vc", 8, COND, 0 }, 1524 { "nv", 8, COND, 0 }, 1525 { "gt", 9, COND, 0 }, 1526 { "ge", 10, COND, 0 }, 1527 { "lt", 11, COND, 0 }, 1528 { "le", 12, COND, 0 }, 1529 { "hi", 13, COND, 0 }, 1530 { "ls", 14, COND, 0 }, 1531 { "pnz", 15, COND, 0 }, 1532 1533 /* Condition codes 16-31 reserved for extensions. */ 1534 1535 { "f", 1, FLAG, 0 }, 1536 1537 { "nd", ARC_DELAY_NONE, DELAY, 0 }, 1538 { "d", ARC_DELAY_NORMAL, DELAY, 0 }, 1539 { "jd", ARC_DELAY_JUMP, DELAY, 0 }, 1540 1541 { "b", 1, SIZE1, 0 }, 1542 { "b", 1, SIZE10, 0 }, 1543 { "b", 1, SIZE22, 0 }, 1544 { "w", 2, SIZE1, 0 }, 1545 { "w", 2, SIZE10, 0 }, 1546 { "w", 2, SIZE22, 0 }, 1547 { "x", 1, SIGN0, 0 }, 1548 { "x", 1, SIGN9, 0 }, 1549 { "a", 1, ADDRESS3, 0 }, 1550 { "a", 1, ADDRESS12, 0 }, 1551 { "a", 1, ADDRESS24, 0 }, 1552 1553 { "di", 1, CACHEBYPASS5, 0 }, 1554 { "di", 1, CACHEBYPASS14, 0 }, 1555 { "di", 1, CACHEBYPASS26, 0 }, 1556 }; 1557 1558 const int arc_suffixes_count = 1559 sizeof (arc_suffixes) / sizeof (arc_suffixes[0]); 1560 1561 /* Indexed by first letter of opcode. Points to chain of opcodes with same 1562 first letter. */ 1563 static struct arc_opcode *opcode_map[26 + 1]; 1564 1565 /* Indexed by insn code. Points to chain of opcodes with same insn code. */ 1566 static struct arc_opcode *icode_map[32]; 1567 1568 /* Configuration flags. */ 1570 1571 /* Various ARC_HAVE_XXX bits. */ 1572 static int cpu_type; 1573 1574 /* Translate a bfd_mach_arc_xxx value to a ARC_MACH_XXX value. */ 1575 1576 int 1577 arc_get_opcode_mach (int bfd_mach, int big_p) 1578 { 1579 static int mach_type_map[] = 1580 { 1581 ARC_MACH_5, 1582 ARC_MACH_6, 1583 ARC_MACH_7, 1584 ARC_MACH_8 1585 }; 1586 return mach_type_map[bfd_mach - bfd_mach_arc_5] | (big_p ? ARC_MACH_BIG : 0); 1587 } 1588 1589 /* Initialize any tables that need it. 1590 Must be called once at start up (or when first needed). 1591 1592 FLAGS is a set of bits that say what version of the cpu we have, 1593 and in particular at least (one of) ARC_MACH_XXX. */ 1594 1595 void 1596 arc_opcode_init_tables (int flags) 1597 { 1598 static int init_p = 0; 1599 1600 cpu_type = flags; 1601 1602 /* We may be intentionally called more than once (for example gdb will call 1603 us each time the user switches cpu). These tables only need to be init'd 1604 once though. */ 1605 if (!init_p) 1606 { 1607 int i,n; 1608 1609 memset (arc_operand_map, 0, sizeof (arc_operand_map)); 1610 n = sizeof (arc_operands) / sizeof (arc_operands[0]); 1611 for (i = 0; i < n; ++i) 1612 arc_operand_map[arc_operands[i].fmt] = i; 1613 1614 memset (opcode_map, 0, sizeof (opcode_map)); 1615 memset (icode_map, 0, sizeof (icode_map)); 1616 /* Scan the table backwards so macros appear at the front. */ 1617 for (i = arc_opcodes_count - 1; i >= 0; --i) 1618 { 1619 int opcode_hash = ARC_HASH_OPCODE (arc_opcodes[i].syntax); 1620 int icode_hash = ARC_HASH_ICODE (arc_opcodes[i].value); 1621 1622 arc_opcodes[i].next_asm = opcode_map[opcode_hash]; 1623 opcode_map[opcode_hash] = &arc_opcodes[i]; 1624 1625 arc_opcodes[i].next_dis = icode_map[icode_hash]; 1626 icode_map[icode_hash] = &arc_opcodes[i]; 1627 } 1628 1629 init_p = 1; 1630 } 1631 } 1632 1633 /* Return non-zero if OPCODE is supported on the specified cpu. 1634 Cpu selection is made when calling `arc_opcode_init_tables'. */ 1635 1636 int 1637 arc_opcode_supported (const struct arc_opcode *opcode) 1638 { 1639 if (ARC_OPCODE_CPU (opcode->flags) <= cpu_type) 1640 return 1; 1641 return 0; 1642 } 1643 1644 /* Return the first insn in the chain for assembling INSN. */ 1645 1646 const struct arc_opcode * 1647 arc_opcode_lookup_asm (const char *insn) 1648 { 1649 return opcode_map[ARC_HASH_OPCODE (insn)]; 1650 } 1651 1652 /* Return the first insn in the chain for disassembling INSN. */ 1653 1654 const struct arc_opcode * 1655 arc_opcode_lookup_dis (unsigned int insn) 1656 { 1657 return icode_map[ARC_HASH_ICODE (insn)]; 1658 } 1659 1660 /* Called by the assembler before parsing an instruction. */ 1661 1662 void 1663 arc_opcode_init_insert (void) 1664 { 1665 int i; 1666 1667 for(i = 0; i < OPERANDS; i++) 1668 ls_operand[i] = OP_NONE; 1669 1670 flag_p = 0; 1671 flagshimm_handled_p = 0; 1672 cond_p = 0; 1673 addrwb_p = 0; 1674 shimm_p = 0; 1675 limm_p = 0; 1676 jumpflags_p = 0; 1677 nullify_p = 0; 1678 nullify = 0; /* The default is important. */ 1679 } 1680 1681 /* Called by the assembler to see if the insn has a limm operand. 1682 Also called by the disassembler to see if the insn contains a limm. */ 1683 1684 int 1685 arc_opcode_limm_p (long *limmp) 1686 { 1687 if (limmp) 1688 *limmp = limm; 1689 return limm_p; 1690 } 1691 1692 /* Utility for the extraction functions to return the index into 1693 `arc_suffixes'. */ 1694 1695 const struct arc_operand_value * 1696 arc_opcode_lookup_suffix (const struct arc_operand *type, int value) 1697 { 1698 const struct arc_operand_value *v,*end; 1699 struct arc_ext_operand_value *ext_oper = arc_ext_operands; 1700 1701 while (ext_oper) 1702 { 1703 if (type == &arc_operands[ext_oper->operand.type] 1704 && value == ext_oper->operand.value) 1705 return (&ext_oper->operand); 1706 ext_oper = ext_oper->next; 1707 } 1708 1709 /* ??? This is a little slow and can be speeded up. */ 1710 for (v = arc_suffixes, end = arc_suffixes + arc_suffixes_count; v < end; ++v) 1711 if (type == &arc_operands[v->type] 1712 && value == v->value) 1713 return v; 1714 return 0; 1715 } 1716 1717 int 1718 arc_insn_is_j (arc_insn insn) 1719 { 1720 return (insn & (I(-1))) == I(0x7); 1721 } 1722 1723 int 1724 arc_insn_not_jl (arc_insn insn) 1725 { 1726 return ((insn & (I(-1)|A(-1)|C(-1)|R(-1,7,1)|R(-1,9,1))) 1727 != (I(0x7) | R(-1,9,1))); 1728 } 1729 1730 int 1731 arc_operand_type (int opertype) 1732 { 1733 switch (opertype) 1734 { 1735 case 0: 1736 return COND; 1737 break; 1738 case 1: 1739 return REG; 1740 break; 1741 case 2: 1742 return AUXREG; 1743 break; 1744 } 1745 return -1; 1746 } 1747 1748 struct arc_operand_value * 1749 get_ext_suffix (char *s) 1750 { 1751 struct arc_ext_operand_value *suffix = arc_ext_operands; 1752 1753 while (suffix) 1754 { 1755 if ((COND == suffix->operand.type) 1756 && !strcmp(s,suffix->operand.name)) 1757 return(&suffix->operand); 1758 suffix = suffix->next; 1759 } 1760 return NULL; 1761 } 1762 1763 int 1764 arc_get_noshortcut_flag (void) 1765 { 1766 return ARC_REGISTER_NOSHORT_CUT; 1767 } 1768