Back to index

cell-binutils  2.17cvs20070401
arc-opc.c
Go to the documentation of this file.
00001 /* Opcode table for the ARC.
00002    Copyright 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2004, 2005
00003    Free Software Foundation, Inc.
00004    Contributed by Doug Evans (dje@cygnus.com).
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2, or (at your option)
00009    any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software Foundation,
00018    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00019 
00020 #include "sysdep.h"
00021 #include <stdio.h>
00022 #include "ansidecl.h"
00023 #include "bfd.h"
00024 #include "opcode/arc.h"
00025 #include "opintl.h"
00026 
00027 enum operand {OP_NONE,OP_REG,OP_SHIMM,OP_LIMM};
00028 
00029 #define OPERANDS 3
00030 
00031 enum operand ls_operand[OPERANDS];
00032 
00033 struct arc_opcode *arc_ext_opcodes;
00034 struct arc_ext_operand_value *arc_ext_operands;
00035 
00036 #define LS_VALUE  0
00037 #define LS_DEST   0
00038 #define LS_BASE   1
00039 #define LS_OFFSET 2
00040 
00041 /* Given a format letter, yields the index into `arc_operands'.
00042    eg: arc_operand_map['a'] = REGA.  */
00043 unsigned char arc_operand_map[256];
00044 
00045 /* Nonzero if we've seen an 'f' suffix (in certain insns).  */
00046 static int flag_p;
00047 
00048 /* Nonzero if we've finished processing the 'f' suffix.  */
00049 static int flagshimm_handled_p;
00050 
00051 /* Nonzero if we've seen a 'a' suffix (address writeback).  */
00052 static int addrwb_p;
00053 
00054 /* Nonzero if we've seen a 'q' suffix (condition code).  */
00055 static int cond_p;
00056 
00057 /* Nonzero if we've inserted a nullify condition.  */
00058 static int nullify_p;
00059 
00060 /* The value of the a nullify condition we inserted.  */
00061 static int nullify;
00062 
00063 /* Nonzero if we've inserted jumpflags.  */
00064 static int jumpflags_p;
00065 
00066 /* Nonzero if we've inserted a shimm.  */
00067 static int shimm_p;
00068 
00069 /* The value of the shimm we inserted (each insn only gets one but it can
00070    appear multiple times).  */
00071 static int shimm;
00072 
00073 /* Nonzero if we've inserted a limm (during assembly) or seen a limm
00074    (during disassembly).  */
00075 static int limm_p;
00076 
00077 /* The value of the limm we inserted.  Each insn only gets one but it can
00078    appear multiple times.  */
00079 static long limm;
00080 
00081 #define INSERT_FN(fn) \
00082 static arc_insn fn (arc_insn, const struct arc_operand *, \
00083                   int, const struct arc_operand_value *, long, \
00084                   const char **)
00085 
00086 #define EXTRACT_FN(fn) \
00087 static long fn (arc_insn *, const struct arc_operand *, \
00088               int, const struct arc_operand_value **, int *)
00089 
00090 INSERT_FN (insert_reg);
00091 INSERT_FN (insert_shimmfinish);
00092 INSERT_FN (insert_limmfinish);
00093 INSERT_FN (insert_offset);
00094 INSERT_FN (insert_base);
00095 INSERT_FN (insert_st_syntax);
00096 INSERT_FN (insert_ld_syntax);
00097 INSERT_FN (insert_addr_wb);
00098 INSERT_FN (insert_flag);
00099 INSERT_FN (insert_nullify);
00100 INSERT_FN (insert_flagfinish);
00101 INSERT_FN (insert_cond);
00102 INSERT_FN (insert_forcelimm);
00103 INSERT_FN (insert_reladdr);
00104 INSERT_FN (insert_absaddr);
00105 INSERT_FN (insert_jumpflags);
00106 INSERT_FN (insert_unopmacro);
00107 
00108 EXTRACT_FN (extract_reg);
00109 EXTRACT_FN (extract_ld_offset);
00110 EXTRACT_FN (extract_ld_syntax);
00111 EXTRACT_FN (extract_st_offset);
00112 EXTRACT_FN (extract_st_syntax);
00113 EXTRACT_FN (extract_flag);
00114 EXTRACT_FN (extract_cond);
00115 EXTRACT_FN (extract_reladdr);
00116 EXTRACT_FN (extract_jumpflags);
00117 EXTRACT_FN (extract_unopmacro);
00118 
00119 /* Various types of ARC operands, including insn suffixes.  */
00120 
00121 /* Insn format values:
00122 
00123    'a' REGA          register A field
00124    'b' REGB          register B field
00125    'c' REGC          register C field
00126    'S' SHIMMFINISH   finish inserting a shimm value
00127    'L' LIMMFINISH    finish inserting a limm value
00128    'o' OFFSET        offset in st insns
00129    'O' OFFSET        offset in ld insns
00130    '0' SYNTAX_ST_NE  enforce store insn syntax, no errors
00131    '1' SYNTAX_LD_NE  enforce load insn syntax, no errors
00132    '2'  SYNTAX_ST       enforce store insn syntax, errors, last pattern only
00133    '3'  SYNTAX_LD       enforce load insn syntax, errors, last pattern only
00134    's'  BASE            base in st insn
00135    'f' FLAG          F flag
00136    'F' FLAGFINISH    finish inserting the F flag
00137    'G' FLAGINSN      insert F flag in "flag" insn
00138    'n' DELAY         N field (nullify field)
00139    'q' COND          condition code field
00140    'Q' FORCELIMM     set `cond_p' to 1 to ensure a constant is a limm
00141    'B' BRANCH        branch address (22 bit pc relative)
00142    'J' JUMP          jump address (26 bit absolute)
00143    'j'  JUMPFLAGS       optional high order bits of 'J'
00144    'z' SIZE1         size field in ld a,[b,c]
00145    'Z' SIZE10        size field in ld a,[b,shimm]
00146    'y' SIZE22        size field in st c,[b,shimm]
00147    'x' SIGN0         sign extend field ld a,[b,c]
00148    'X' SIGN9         sign extend field ld a,[b,shimm]
00149    'w' ADDRESS3      write-back field in ld a,[b,c]
00150    'W' ADDRESS12     write-back field in ld a,[b,shimm]
00151    'v' ADDRESS24     write-back field in st c,[b,shimm]
00152    'e' CACHEBYPASS5  cache bypass in ld a,[b,c]
00153    'E' CACHEBYPASS14 cache bypass in ld a,[b,shimm]
00154    'D' CACHEBYPASS26 cache bypass in st c,[b,shimm]
00155    'U' UNOPMACRO     fake operand to copy REGB to REGC for unop macros
00156 
00157    The following modifiers may appear between the % and char (eg: %.f):
00158 
00159    '.' MODDOT        '.' prefix must be present
00160    'r' REG           generic register value, for register table
00161    'A' AUXREG        auxiliary register in lr a,[b], sr c,[b]
00162 
00163    Fields are:
00164 
00165    CHAR BITS SHIFT FLAGS INSERT_FN EXTRACT_FN  */
00166 
00167 const struct arc_operand arc_operands[] =
00168 {
00169 /* Place holder (??? not sure if needed).  */
00170 #define UNUSED 0
00171   { 0, 0, 0, 0, 0, 0 },
00172 
00173 /* Register A or shimm/limm indicator.  */
00174 #define REGA (UNUSED + 1)
00175   { 'a', 6, ARC_SHIFT_REGA, ARC_OPERAND_SIGNED | ARC_OPERAND_ERROR, insert_reg, extract_reg },
00176 
00177 /* Register B or shimm/limm indicator.  */
00178 #define REGB (REGA + 1)
00179   { 'b', 6, ARC_SHIFT_REGB, ARC_OPERAND_SIGNED | ARC_OPERAND_ERROR, insert_reg, extract_reg },
00180 
00181 /* Register C or shimm/limm indicator.  */
00182 #define REGC (REGB + 1)
00183   { 'c', 6, ARC_SHIFT_REGC, ARC_OPERAND_SIGNED | ARC_OPERAND_ERROR, insert_reg, extract_reg },
00184 
00185 /* Fake operand used to insert shimm value into most instructions.  */
00186 #define SHIMMFINISH (REGC + 1)
00187   { 'S', 9, 0, ARC_OPERAND_SIGNED + ARC_OPERAND_FAKE, insert_shimmfinish, 0 },
00188 
00189 /* Fake operand used to insert limm value into most instructions.  */
00190 #define LIMMFINISH (SHIMMFINISH + 1)
00191   { 'L', 32, 32, ARC_OPERAND_ADDRESS + ARC_OPERAND_LIMM + ARC_OPERAND_FAKE, insert_limmfinish, 0 },
00192 
00193 /* Shimm operand when there is no reg indicator (st).  */
00194 #define ST_OFFSET (LIMMFINISH + 1)
00195   { 'o', 9, 0, ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED | ARC_OPERAND_STORE, insert_offset, extract_st_offset },
00196 
00197 /* Shimm operand when there is no reg indicator (ld).  */
00198 #define LD_OFFSET (ST_OFFSET + 1)
00199   { 'O', 9, 0,ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED | ARC_OPERAND_LOAD, insert_offset, extract_ld_offset },
00200 
00201 /* Operand for base.  */
00202 #define BASE (LD_OFFSET + 1)
00203   { 's', 6, ARC_SHIFT_REGB, ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED, insert_base, extract_reg},
00204 
00205 /* 0 enforce syntax for st insns.  */
00206 #define SYNTAX_ST_NE (BASE + 1)
00207   { '0', 9, 0, ARC_OPERAND_FAKE, insert_st_syntax, extract_st_syntax },
00208 
00209 /* 1 enforce syntax for ld insns.  */
00210 #define SYNTAX_LD_NE (SYNTAX_ST_NE + 1)
00211   { '1', 9, 0, ARC_OPERAND_FAKE, insert_ld_syntax, extract_ld_syntax },
00212 
00213 /* 0 enforce syntax for st insns.  */
00214 #define SYNTAX_ST (SYNTAX_LD_NE + 1)
00215   { '2', 9, 0, ARC_OPERAND_FAKE | ARC_OPERAND_ERROR, insert_st_syntax, extract_st_syntax },
00216 
00217 /* 0 enforce syntax for ld insns.  */
00218 #define SYNTAX_LD (SYNTAX_ST + 1)
00219   { '3', 9, 0, ARC_OPERAND_FAKE | ARC_OPERAND_ERROR, insert_ld_syntax, extract_ld_syntax },
00220 
00221 /* Flag update bit (insertion is defered until we know how).  */
00222 #define FLAG (SYNTAX_LD + 1)
00223   { 'f', 1, 8, ARC_OPERAND_SUFFIX, insert_flag, extract_flag },
00224 
00225 /* Fake utility operand to finish 'f' suffix handling.  */
00226 #define FLAGFINISH (FLAG + 1)
00227   { 'F', 1, 8, ARC_OPERAND_FAKE, insert_flagfinish, 0 },
00228 
00229 /* Fake utility operand to set the 'f' flag for the "flag" insn.  */
00230 #define FLAGINSN (FLAGFINISH + 1)
00231   { 'G', 1, 8, ARC_OPERAND_FAKE, insert_flag, 0 },
00232 
00233 /* Branch delay types.  */
00234 #define DELAY (FLAGINSN + 1)
00235   { 'n', 2, 5, ARC_OPERAND_SUFFIX , insert_nullify, 0 },
00236 
00237 /* Conditions.  */
00238 #define COND (DELAY + 1)
00239   { 'q', 5, 0, ARC_OPERAND_SUFFIX, insert_cond, extract_cond },
00240 
00241 /* Set `cond_p' to 1 to ensure a constant is treated as a limm.  */
00242 #define FORCELIMM (COND + 1)
00243   { 'Q', 0, 0, ARC_OPERAND_FAKE, insert_forcelimm, 0 },
00244 
00245 /* Branch address; b, bl, and lp insns.  */
00246 #define BRANCH (FORCELIMM + 1)
00247   { 'B', 20, 7, (ARC_OPERAND_RELATIVE_BRANCH + ARC_OPERAND_SIGNED) | ARC_OPERAND_ERROR, insert_reladdr, extract_reladdr },
00248 
00249 /* Jump address; j insn (this is basically the same as 'L' except that the
00250    value is right shifted by 2).  */
00251 #define JUMP (BRANCH + 1)
00252   { 'J', 24, 32, ARC_OPERAND_ERROR | (ARC_OPERAND_ABSOLUTE_BRANCH + ARC_OPERAND_LIMM + ARC_OPERAND_FAKE), insert_absaddr, 0 },
00253 
00254 /* Jump flags; j{,l} insn value or'ed into 'J' addr for flag values.  */
00255 #define JUMPFLAGS (JUMP + 1)
00256   { 'j', 6, 26, ARC_OPERAND_JUMPFLAGS | ARC_OPERAND_ERROR, insert_jumpflags, extract_jumpflags },
00257 
00258 /* Size field, stored in bit 1,2.  */
00259 #define SIZE1 (JUMPFLAGS + 1)
00260   { 'z', 2, 1, ARC_OPERAND_SUFFIX, 0, 0 },
00261 
00262 /* Size field, stored in bit 10,11.  */
00263 #define SIZE10 (SIZE1 + 1)
00264   { 'Z', 2, 10, ARC_OPERAND_SUFFIX, 0, 0 },
00265 
00266 /* Size field, stored in bit 22,23.  */
00267 #define SIZE22 (SIZE10 + 1)
00268   { 'y', 2, 22, ARC_OPERAND_SUFFIX, 0, 0 },
00269 
00270 /* Sign extend field, stored in bit 0.  */
00271 #define SIGN0 (SIZE22 + 1)
00272   { 'x', 1, 0, ARC_OPERAND_SUFFIX, 0, 0 },
00273 
00274 /* Sign extend field, stored in bit 9.  */
00275 #define SIGN9 (SIGN0 + 1)
00276   { 'X', 1, 9, ARC_OPERAND_SUFFIX, 0, 0 },
00277 
00278 /* Address write back, stored in bit 3.  */
00279 #define ADDRESS3 (SIGN9 + 1)
00280   { 'w', 1, 3, ARC_OPERAND_SUFFIX, insert_addr_wb, 0},
00281 
00282 /* Address write back, stored in bit 12.  */
00283 #define ADDRESS12 (ADDRESS3 + 1)
00284   { 'W', 1, 12, ARC_OPERAND_SUFFIX, insert_addr_wb, 0},
00285 
00286 /* Address write back, stored in bit 24.  */
00287 #define ADDRESS24 (ADDRESS12 + 1)
00288   { 'v', 1, 24, ARC_OPERAND_SUFFIX, insert_addr_wb, 0},
00289 
00290 /* Cache bypass, stored in bit 5.  */
00291 #define CACHEBYPASS5 (ADDRESS24 + 1)
00292   { 'e', 1, 5, ARC_OPERAND_SUFFIX, 0, 0 },
00293 
00294 /* Cache bypass, stored in bit 14.  */
00295 #define CACHEBYPASS14 (CACHEBYPASS5 + 1)
00296   { 'E', 1, 14, ARC_OPERAND_SUFFIX, 0, 0 },
00297 
00298 /* Cache bypass, stored in bit 26.  */
00299 #define CACHEBYPASS26 (CACHEBYPASS14 + 1)
00300   { 'D', 1, 26, ARC_OPERAND_SUFFIX, 0, 0 },
00301 
00302 /* Unop macro, used to copy REGB to REGC.  */
00303 #define UNOPMACRO (CACHEBYPASS26 + 1)
00304   { 'U', 6, ARC_SHIFT_REGC, ARC_OPERAND_FAKE, insert_unopmacro, extract_unopmacro },
00305 
00306 /* '.' modifier ('.' required).  */
00307 #define MODDOT (UNOPMACRO + 1)
00308   { '.', 1, 0, ARC_MOD_DOT, 0, 0 },
00309 
00310 /* Dummy 'r' modifier for the register table.
00311    It's called a "dummy" because there's no point in inserting an 'r' into all
00312    the %a/%b/%c occurrences in the insn table.  */
00313 #define REG (MODDOT + 1)
00314   { 'r', 6, 0, ARC_MOD_REG, 0, 0 },
00315 
00316 /* Known auxiliary register modifier (stored in shimm field).  */
00317 #define AUXREG (REG + 1)
00318   { 'A', 9, 0, ARC_MOD_AUXREG, 0, 0 },
00319 
00320 /* End of list place holder.  */
00321   { 0, 0, 0, 0, 0, 0 }
00322 };
00323 
00324 /* Insert a value into a register field.
00325    If REG is NULL, then this is actually a constant.
00326 
00327    We must also handle auxiliary registers for lr/sr insns.  */
00328 
00329 static arc_insn
00330 insert_reg (arc_insn insn,
00331            const struct arc_operand *operand,
00332            int mods,
00333            const struct arc_operand_value *reg,
00334            long value,
00335            const char **errmsg)
00336 {
00337   static char buf[100];
00338   enum operand op_type = OP_NONE;
00339 
00340   if (reg == NULL)
00341     {
00342       /* We have a constant that also requires a value stored in a register
00343         field.  Handle these by updating the register field and saving the
00344         value for later handling by either %S (shimm) or %L (limm).  */
00345 
00346       /* Try to use a shimm value before a limm one.  */
00347       if (ARC_SHIMM_CONST_P (value)
00348          /* If we've seen a conditional suffix we have to use a limm.  */
00349          && !cond_p
00350          /* If we already have a shimm value that is different than ours
00351             we have to use a limm.  */
00352          && (!shimm_p || shimm == value))
00353        {
00354          int marker;
00355 
00356          op_type = OP_SHIMM;
00357          /* Forget about shimm as dest mlm.  */
00358 
00359          if ('a' != operand->fmt)
00360            {
00361              shimm_p = 1;
00362              shimm = value;
00363              flagshimm_handled_p = 1;
00364              marker = flag_p ? ARC_REG_SHIMM_UPDATE : ARC_REG_SHIMM;
00365            }
00366          else
00367            {
00368              /* Don't request flag setting on shimm as dest.  */
00369              marker = ARC_REG_SHIMM;
00370            }
00371          insn |= marker << operand->shift;
00372          /* insn |= value & 511; - done later.  */
00373        }
00374       /* We have to use a limm.  If we've already seen one they must match.  */
00375       else if (!limm_p || limm == value)
00376        {
00377          op_type = OP_LIMM;
00378          limm_p = 1;
00379          limm = value;
00380          insn |= ARC_REG_LIMM << operand->shift;
00381          /* The constant is stored later.  */
00382        }
00383       else
00384        *errmsg = _("unable to fit different valued constants into instruction");
00385     }
00386   else
00387     {
00388       /* We have to handle both normal and auxiliary registers.  */
00389 
00390       if (reg->type == AUXREG)
00391        {
00392          if (!(mods & ARC_MOD_AUXREG))
00393            *errmsg = _("auxiliary register not allowed here");
00394          else
00395            {
00396              if ((insn & I(-1)) == I(2)) /* Check for use validity.  */
00397               {
00398                 if (reg->flags & ARC_REGISTER_READONLY)
00399                   *errmsg = _("attempt to set readonly register");
00400               }
00401              else
00402               {
00403                 if (reg->flags & ARC_REGISTER_WRITEONLY)
00404                   *errmsg = _("attempt to read writeonly register");
00405               }
00406              insn |= ARC_REG_SHIMM << operand->shift;
00407              insn |= reg->value << arc_operands[reg->type].shift;
00408            }
00409        }
00410       else
00411        {
00412          /* check for use validity.  */
00413          if ('a' == operand->fmt || ((insn & I(-1)) < I(2)))
00414            {
00415              if (reg->flags & ARC_REGISTER_READONLY)
00416               *errmsg = _("attempt to set readonly register");
00417            }
00418          if ('a' != operand->fmt)
00419            {
00420              if (reg->flags & ARC_REGISTER_WRITEONLY)
00421               *errmsg = _("attempt to read writeonly register");
00422            }
00423          /* We should never get an invalid register number here.  */
00424          if ((unsigned int) reg->value > 60)
00425            {
00426              sprintf (buf, _("invalid register number `%d'"), reg->value);
00427              *errmsg = buf;
00428            }
00429          insn |= reg->value << operand->shift;
00430          op_type = OP_REG;
00431        }
00432     }
00433 
00434   switch (operand->fmt)
00435     {
00436     case 'a':
00437       ls_operand[LS_DEST] = op_type;
00438       break;
00439     case 's':
00440       ls_operand[LS_BASE] = op_type;
00441       break;
00442     case 'c':
00443       if ((insn & I(-1)) == I(2))
00444        ls_operand[LS_VALUE] = op_type;
00445       else
00446        ls_operand[LS_OFFSET] = op_type;
00447       break;
00448     case 'o': case 'O':
00449       ls_operand[LS_OFFSET] = op_type;
00450       break;
00451     }
00452 
00453   return insn;
00454 }
00455 
00456 /* Called when we see an 'f' flag.  */
00457 
00458 static arc_insn
00459 insert_flag (arc_insn insn,
00460             const struct arc_operand *operand ATTRIBUTE_UNUSED,
00461             int mods ATTRIBUTE_UNUSED,
00462             const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00463             long value ATTRIBUTE_UNUSED,
00464             const char **errmsg ATTRIBUTE_UNUSED)
00465 {
00466   /* We can't store anything in the insn until we've parsed the registers.
00467      Just record the fact that we've got this flag.  `insert_reg' will use it
00468      to store the correct value (ARC_REG_SHIMM_UPDATE or bit 0x100).  */
00469   flag_p = 1;
00470   return insn;
00471 }
00472 
00473 /* Called when we see an nullify condition.  */
00474 
00475 static arc_insn
00476 insert_nullify (arc_insn insn,
00477               const struct arc_operand *operand,
00478               int mods ATTRIBUTE_UNUSED,
00479               const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00480               long value,
00481               const char **errmsg ATTRIBUTE_UNUSED)
00482 {
00483   nullify_p = 1;
00484   insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
00485   nullify = value;
00486   return insn;
00487 }
00488 
00489 /* Called after completely building an insn to ensure the 'f' flag gets set
00490    properly.  This is needed because we don't know how to set this flag until
00491    we've parsed the registers.  */
00492 
00493 static arc_insn
00494 insert_flagfinish (arc_insn insn,
00495                  const struct arc_operand *operand,
00496                  int mods ATTRIBUTE_UNUSED,
00497                  const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00498                  long value ATTRIBUTE_UNUSED,
00499                  const char **errmsg ATTRIBUTE_UNUSED)
00500 {
00501   if (flag_p && !flagshimm_handled_p)
00502     {
00503       if (shimm_p)
00504        abort ();
00505       flagshimm_handled_p = 1;
00506       insn |= (1 << operand->shift);
00507     }
00508   return insn;
00509 }
00510 
00511 /* Called when we see a conditional flag (eg: .eq).  */
00512 
00513 static arc_insn
00514 insert_cond (arc_insn insn,
00515             const struct arc_operand *operand,
00516             int mods ATTRIBUTE_UNUSED,
00517             const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00518             long value,
00519             const char **errmsg ATTRIBUTE_UNUSED)
00520 {
00521   cond_p = 1;
00522   insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
00523   return insn;
00524 }
00525 
00526 /* Used in the "j" instruction to prevent constants from being interpreted as
00527    shimm values (which the jump insn doesn't accept).  This can also be used
00528    to force the use of limm values in other situations (eg: ld r0,[foo] uses
00529    this).
00530    ??? The mechanism is sound.  Access to it is a bit klunky right now.  */
00531 
00532 static arc_insn
00533 insert_forcelimm (arc_insn insn,
00534                 const struct arc_operand *operand ATTRIBUTE_UNUSED,
00535                 int mods ATTRIBUTE_UNUSED,
00536                 const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00537                 long value ATTRIBUTE_UNUSED,
00538                 const char **errmsg ATTRIBUTE_UNUSED)
00539 {
00540   cond_p = 1;
00541   return insn;
00542 }
00543 
00544 static arc_insn
00545 insert_addr_wb (arc_insn insn,
00546               const struct arc_operand *operand,
00547               int mods ATTRIBUTE_UNUSED,
00548               const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00549               long value ATTRIBUTE_UNUSED,
00550               const char **errmsg ATTRIBUTE_UNUSED)
00551 {
00552   addrwb_p = 1 << operand->shift;
00553   return insn;
00554 }
00555 
00556 static arc_insn
00557 insert_base (arc_insn insn,
00558             const struct arc_operand *operand,
00559             int mods,
00560             const struct arc_operand_value *reg,
00561             long value,
00562             const char **errmsg)
00563 {
00564   if (reg != NULL)
00565     {
00566       arc_insn myinsn;
00567       myinsn = insert_reg (0, operand,mods, reg, value, errmsg) >> operand->shift;
00568       insn |= B(myinsn);
00569       ls_operand[LS_BASE] = OP_REG;
00570     }
00571   else if (ARC_SHIMM_CONST_P (value) && !cond_p)
00572     {
00573       if (shimm_p && value != shimm)
00574        {
00575          /* Convert the previous shimm operand to a limm.  */
00576          limm_p = 1;
00577          limm = shimm;
00578          insn &= ~C(-1); /* We know where the value is in insn.  */
00579          insn |= C(ARC_REG_LIMM);
00580          ls_operand[LS_VALUE] = OP_LIMM;
00581        }
00582       insn |= ARC_REG_SHIMM << operand->shift;
00583       shimm_p = 1;
00584       shimm = value;
00585       ls_operand[LS_BASE] = OP_SHIMM;
00586       ls_operand[LS_OFFSET] = OP_SHIMM;
00587     }
00588   else
00589     {
00590       if (limm_p && value != limm)
00591        {
00592          *errmsg = _("too many long constants");
00593          return insn;
00594        }
00595       limm_p = 1;
00596       limm = value;
00597       insn |= B(ARC_REG_LIMM);
00598       ls_operand[LS_BASE] = OP_LIMM;
00599     }
00600 
00601   return insn;
00602 }
00603 
00604 /* Used in ld/st insns to handle the offset field. We don't try to
00605    match operand syntax here. we catch bad combinations later.  */
00606 
00607 static arc_insn
00608 insert_offset (arc_insn insn,
00609               const struct arc_operand *operand,
00610               int mods,
00611               const struct arc_operand_value *reg,
00612               long value,
00613               const char **errmsg)
00614 {
00615   long minval, maxval;
00616 
00617   if (reg != NULL)
00618     {
00619       arc_insn myinsn;
00620       myinsn = insert_reg (0,operand,mods,reg,value,errmsg) >> operand->shift;
00621       ls_operand[LS_OFFSET] = OP_REG;
00622       if (operand->flags & ARC_OPERAND_LOAD) /* Not if store, catch it later.  */
00623        if ((insn & I(-1)) != I(1)) /* Not if opcode == 1, catch it later.  */
00624          insn |= C (myinsn);
00625     }
00626   else
00627     {
00628       /* This is *way* more general than necessary, but maybe some day it'll
00629         be useful.  */
00630       if (operand->flags & ARC_OPERAND_SIGNED)
00631        {
00632          minval = -(1 << (operand->bits - 1));
00633          maxval = (1 << (operand->bits - 1)) - 1;
00634        }
00635       else
00636        {
00637          minval = 0;
00638          maxval = (1 << operand->bits) - 1;
00639        }
00640       if ((cond_p && !limm_p) || (value < minval || value > maxval))
00641        {
00642          if (limm_p && value != limm)
00643            *errmsg = _("too many long constants");
00644 
00645          else
00646            {
00647              limm_p = 1;
00648              limm = value;
00649              if (operand->flags & ARC_OPERAND_STORE)
00650               insn |= B(ARC_REG_LIMM);
00651              if (operand->flags & ARC_OPERAND_LOAD)
00652               insn |= C(ARC_REG_LIMM);
00653              ls_operand[LS_OFFSET] = OP_LIMM;
00654            }
00655        }
00656       else
00657        {
00658          if ((value < minval || value > maxval))
00659            *errmsg = "need too many limms";
00660          else if (shimm_p && value != shimm)
00661            {
00662              /* Check for bad operand combinations
00663                before we lose info about them.  */
00664              if ((insn & I(-1)) == I(1))
00665               {
00666                 *errmsg = _("to many shimms in load");
00667                 goto out;
00668               }
00669              if (limm_p && operand->flags & ARC_OPERAND_LOAD)
00670               {
00671                 *errmsg = _("too many long constants");
00672                 goto out;
00673               }
00674              /* Convert what we thought was a shimm to a limm.  */
00675              limm_p = 1;
00676              limm = shimm;
00677              if (ls_operand[LS_VALUE] == OP_SHIMM
00678                 && operand->flags & ARC_OPERAND_STORE)
00679               {
00680                 insn &= ~C(-1);
00681                 insn |= C(ARC_REG_LIMM);
00682                 ls_operand[LS_VALUE] = OP_LIMM;
00683               }
00684              if (ls_operand[LS_BASE] == OP_SHIMM
00685                 && operand->flags & ARC_OPERAND_STORE)
00686               {
00687                 insn &= ~B(-1);
00688                 insn |= B(ARC_REG_LIMM);
00689                 ls_operand[LS_BASE] = OP_LIMM;
00690               }
00691            }
00692          shimm = value;
00693          shimm_p = 1;
00694          ls_operand[LS_OFFSET] = OP_SHIMM;
00695        }
00696     }
00697  out:
00698   return insn;
00699 }
00700 
00701 /* Used in st insns to do final disasemble syntax check.  */
00702 
00703 static long
00704 extract_st_syntax (arc_insn *insn,
00705                  const struct arc_operand *operand ATTRIBUTE_UNUSED,
00706                  int mods ATTRIBUTE_UNUSED,
00707                  const struct arc_operand_value **opval ATTRIBUTE_UNUSED,
00708                  int *invalid)
00709 {
00710 #define ST_SYNTAX(V,B,O) \
00711 ((ls_operand[LS_VALUE]  == (V) && \
00712   ls_operand[LS_BASE]   == (B) && \
00713   ls_operand[LS_OFFSET] == (O)))
00714 
00715   if (!((ST_SYNTAX(OP_REG,OP_REG,OP_NONE) && (insn[0] & 511) == 0)
00716        || ST_SYNTAX(OP_REG,OP_LIMM,OP_NONE)
00717        || (ST_SYNTAX(OP_SHIMM,OP_REG,OP_NONE) && (insn[0] & 511) == 0)
00718        || (ST_SYNTAX(OP_SHIMM,OP_SHIMM,OP_NONE) && (insn[0] & 511) == 0)
00719        || ST_SYNTAX(OP_SHIMM,OP_LIMM,OP_NONE)
00720        || ST_SYNTAX(OP_SHIMM,OP_LIMM,OP_SHIMM)
00721        || ST_SYNTAX(OP_SHIMM,OP_SHIMM,OP_SHIMM)
00722        || (ST_SYNTAX(OP_LIMM,OP_REG,OP_NONE) && (insn[0] & 511) == 0)
00723        || ST_SYNTAX(OP_REG,OP_REG,OP_SHIMM)
00724        || ST_SYNTAX(OP_REG,OP_SHIMM,OP_SHIMM)
00725        || ST_SYNTAX(OP_SHIMM,OP_REG,OP_SHIMM)
00726        || ST_SYNTAX(OP_LIMM,OP_SHIMM,OP_SHIMM)
00727        || ST_SYNTAX(OP_LIMM,OP_SHIMM,OP_NONE)
00728        || ST_SYNTAX(OP_LIMM,OP_REG,OP_SHIMM)))
00729     *invalid = 1;
00730   return 0;
00731 }
00732 
00733 int
00734 arc_limm_fixup_adjust (arc_insn insn)
00735 {
00736   int retval = 0;
00737 
00738   /* Check for st shimm,[limm].  */
00739   if ((insn & (I(-1) | C(-1) | B(-1))) ==
00740       (I(2) | C(ARC_REG_SHIMM) | B(ARC_REG_LIMM)))
00741     {
00742       retval = insn & 0x1ff;
00743       if (retval & 0x100) /* Sign extend 9 bit offset.  */
00744        retval |= ~0x1ff;
00745     }
00746   return -retval; /* Negate offset for return.  */
00747 }
00748 
00749 /* Used in st insns to do final syntax check.  */
00750 
00751 static arc_insn
00752 insert_st_syntax (arc_insn insn,
00753                 const struct arc_operand *operand ATTRIBUTE_UNUSED,
00754                 int mods ATTRIBUTE_UNUSED,
00755                 const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00756                 long value ATTRIBUTE_UNUSED,
00757                 const char **errmsg)
00758 {
00759   if (ST_SYNTAX (OP_SHIMM,OP_REG,OP_NONE) && shimm != 0)
00760     {
00761       /* Change an illegal insn into a legal one, it's easier to
00762         do it here than to try to handle it during operand scan.  */
00763       limm_p = 1;
00764       limm = shimm;
00765       shimm_p = 0;
00766       shimm = 0;
00767       insn = insn & ~(C(-1) | 511);
00768       insn |= ARC_REG_LIMM << ARC_SHIFT_REGC;
00769       ls_operand[LS_VALUE] = OP_LIMM;
00770     }
00771 
00772   if (ST_SYNTAX (OP_REG, OP_SHIMM, OP_NONE)
00773       || ST_SYNTAX (OP_LIMM, OP_SHIMM, OP_NONE))
00774     {
00775       /* Try to salvage this syntax.  */
00776       if (shimm & 0x1) /* Odd shimms won't work.  */
00777        {
00778          if (limm_p) /* Do we have a limm already?  */
00779            *errmsg = _("impossible store");
00780 
00781          limm_p = 1;
00782          limm = shimm;
00783          shimm = 0;
00784          shimm_p = 0;
00785          insn = insn & ~(B(-1) | 511);
00786          insn |= B(ARC_REG_LIMM);
00787          ls_operand[LS_BASE] = OP_LIMM;
00788        }
00789       else
00790        {
00791          shimm >>= 1;
00792          insn = insn & ~511;
00793          insn |= shimm;
00794          ls_operand[LS_OFFSET] = OP_SHIMM;
00795        }
00796     }
00797   if (ST_SYNTAX(OP_SHIMM,OP_LIMM,OP_NONE))
00798     limm += arc_limm_fixup_adjust(insn);
00799 
00800   if (!   (ST_SYNTAX (OP_REG,OP_REG,OP_NONE)
00801        || ST_SYNTAX (OP_REG,OP_LIMM,OP_NONE)
00802        || ST_SYNTAX (OP_REG,OP_REG,OP_SHIMM)
00803        || ST_SYNTAX (OP_REG,OP_SHIMM,OP_SHIMM)
00804        || (ST_SYNTAX (OP_SHIMM,OP_SHIMM,OP_NONE) && (shimm == 0))
00805        || ST_SYNTAX (OP_SHIMM,OP_LIMM,OP_NONE)
00806        || ST_SYNTAX (OP_SHIMM,OP_REG,OP_NONE)
00807        || ST_SYNTAX (OP_SHIMM,OP_REG,OP_SHIMM)
00808        || ST_SYNTAX (OP_SHIMM,OP_SHIMM,OP_SHIMM)
00809        || ST_SYNTAX (OP_LIMM,OP_SHIMM,OP_SHIMM)
00810        || ST_SYNTAX (OP_LIMM,OP_REG,OP_NONE)
00811        || ST_SYNTAX (OP_LIMM,OP_REG,OP_SHIMM)))
00812     *errmsg = _("st operand error");
00813   if (addrwb_p)
00814     {
00815       if (ls_operand[LS_BASE] != OP_REG)
00816        *errmsg = _("address writeback not allowed");
00817       insn |= addrwb_p;
00818     }
00819   if (ST_SYNTAX(OP_SHIMM,OP_REG,OP_NONE) && shimm)
00820     *errmsg = _("store value must be zero");
00821   return insn;
00822 }
00823 
00824 /* Used in ld insns to do final syntax check.  */
00825 
00826 static arc_insn
00827 insert_ld_syntax (arc_insn insn,
00828                 const struct arc_operand *operand ATTRIBUTE_UNUSED,
00829                 int mods ATTRIBUTE_UNUSED,
00830                 const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00831                 long value ATTRIBUTE_UNUSED,
00832                 const char **errmsg)
00833 {
00834 #define LD_SYNTAX(D, B, O) \
00835   (   (ls_operand[LS_DEST]   == (D) \
00836     && ls_operand[LS_BASE]   == (B) \
00837     && ls_operand[LS_OFFSET] == (O)))
00838 
00839   int test = insn & I (-1);
00840 
00841   if (!(test == I (1)))
00842     {
00843       if ((ls_operand[LS_DEST] == OP_SHIMM || ls_operand[LS_BASE] == OP_SHIMM
00844           || ls_operand[LS_OFFSET] == OP_SHIMM))
00845        *errmsg = _("invalid load/shimm insn");
00846     }
00847   if (!(LD_SYNTAX(OP_REG,OP_REG,OP_NONE)
00848        || LD_SYNTAX(OP_REG,OP_REG,OP_REG)
00849        || LD_SYNTAX(OP_REG,OP_REG,OP_SHIMM)
00850        || (LD_SYNTAX(OP_REG,OP_LIMM,OP_REG) && !(test == I(1)))
00851        || (LD_SYNTAX(OP_REG,OP_REG,OP_LIMM) && !(test == I(1)))
00852        || LD_SYNTAX(OP_REG,OP_SHIMM,OP_SHIMM)
00853        || (LD_SYNTAX(OP_REG,OP_LIMM,OP_NONE) && (test == I(1)))))
00854     *errmsg = _("ld operand error");
00855   if (addrwb_p)
00856     {
00857       if (ls_operand[LS_BASE] != OP_REG)
00858        *errmsg = _("address writeback not allowed");
00859       insn |= addrwb_p;
00860     }
00861   return insn;
00862 }
00863 
00864 /* Used in ld insns to do final syntax check.  */
00865 
00866 static long
00867 extract_ld_syntax (arc_insn *insn,
00868                  const struct arc_operand *operand ATTRIBUTE_UNUSED,
00869                  int mods ATTRIBUTE_UNUSED,
00870                  const struct arc_operand_value **opval ATTRIBUTE_UNUSED,
00871                  int *invalid)
00872 {
00873   int test = insn[0] & I(-1);
00874 
00875   if (!(test == I(1)))
00876     {
00877       if ((ls_operand[LS_DEST] == OP_SHIMM || ls_operand[LS_BASE] == OP_SHIMM
00878           || ls_operand[LS_OFFSET] == OP_SHIMM))
00879        *invalid = 1;
00880     }
00881   if (!(   (LD_SYNTAX (OP_REG, OP_REG, OP_NONE) && (test == I(1)))
00882        ||  LD_SYNTAX (OP_REG, OP_REG, OP_REG)
00883        ||  LD_SYNTAX (OP_REG, OP_REG, OP_SHIMM)
00884        || (LD_SYNTAX (OP_REG, OP_REG, OP_LIMM) && !(test == I(1)))
00885        || (LD_SYNTAX (OP_REG, OP_LIMM, OP_REG) && !(test == I(1)))
00886        || (LD_SYNTAX (OP_REG, OP_SHIMM, OP_NONE) && (shimm == 0))
00887        ||  LD_SYNTAX (OP_REG, OP_SHIMM, OP_SHIMM)
00888        || (LD_SYNTAX (OP_REG, OP_LIMM, OP_NONE) && (test == I(1)))))
00889     *invalid = 1;
00890   return 0;
00891 }
00892 
00893 /* Called at the end of processing normal insns (eg: add) to insert a shimm
00894    value (if present) into the insn.  */
00895 
00896 static arc_insn
00897 insert_shimmfinish (arc_insn insn,
00898                   const struct arc_operand *operand,
00899                   int mods ATTRIBUTE_UNUSED,
00900                   const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00901                   long value ATTRIBUTE_UNUSED,
00902                   const char **errmsg ATTRIBUTE_UNUSED)
00903 {
00904   if (shimm_p)
00905     insn |= (shimm & ((1 << operand->bits) - 1)) << operand->shift;
00906   return insn;
00907 }
00908 
00909 /* Called at the end of processing normal insns (eg: add) to insert a limm
00910    value (if present) into the insn.
00911 
00912    Note that this function is only intended to handle instructions (with 4 byte
00913    immediate operands).  It is not intended to handle data.  */
00914 
00915 /* ??? Actually, there's nothing for us to do as we can't call frag_more, the
00916    caller must do that.  The extract fns take a pointer to two words.  The
00917    insert fns could be converted and then we could do something useful, but
00918    then the reloc handlers would have to know to work on the second word of
00919    a 2 word quantity.  That's too much so we don't handle them.  */
00920 
00921 static arc_insn
00922 insert_limmfinish (arc_insn insn,
00923                  const struct arc_operand *operand ATTRIBUTE_UNUSED,
00924                  int mods ATTRIBUTE_UNUSED,
00925                  const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00926                  long value ATTRIBUTE_UNUSED,
00927                  const char **errmsg ATTRIBUTE_UNUSED)
00928 {
00929   return insn;
00930 }
00931 
00932 static arc_insn
00933 insert_jumpflags (arc_insn insn,
00934                 const struct arc_operand *operand,
00935                 int mods ATTRIBUTE_UNUSED,
00936                 const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00937                 long value,
00938                 const char **errmsg)
00939 {
00940   if (!flag_p)
00941     *errmsg = _("jump flags, but no .f seen");
00942 
00943   else if (!limm_p)
00944     *errmsg = _("jump flags, but no limm addr");
00945 
00946   else if (limm & 0xfc000000)
00947     *errmsg = _("flag bits of jump address limm lost");
00948 
00949   else if (limm & 0x03000000)
00950     *errmsg = _("attempt to set HR bits");
00951 
00952   else if ((value & ((1 << operand->bits) - 1)) != value)
00953     *errmsg = _("bad jump flags value");
00954 
00955   jumpflags_p = 1;
00956   limm = ((limm & ((1 << operand->shift) - 1))
00957          | ((value & ((1 << operand->bits) - 1)) << operand->shift));
00958   return insn;
00959 }
00960 
00961 /* Called at the end of unary operand macros to copy the B field to C.  */
00962 
00963 static arc_insn
00964 insert_unopmacro (arc_insn insn,
00965                 const struct arc_operand *operand,
00966                 int mods ATTRIBUTE_UNUSED,
00967                 const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00968                 long value ATTRIBUTE_UNUSED,
00969                 const char **errmsg ATTRIBUTE_UNUSED)
00970 {
00971   insn |= ((insn >> ARC_SHIFT_REGB) & ARC_MASK_REG) << operand->shift;
00972   return insn;
00973 }
00974 
00975 /* Insert a relative address for a branch insn (b, bl, or lp).  */
00976 
00977 static arc_insn
00978 insert_reladdr (arc_insn insn,
00979               const struct arc_operand *operand,
00980               int mods ATTRIBUTE_UNUSED,
00981               const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
00982               long value,
00983               const char **errmsg)
00984 {
00985   if (value & 3)
00986     *errmsg = _("branch address not on 4 byte boundary");
00987   insn |= ((value >> 2) & ((1 << operand->bits) - 1)) << operand->shift;
00988   return insn;
00989 }
00990 
00991 /* Insert a limm value as a 26 bit address right shifted 2 into the insn.
00992 
00993    Note that this function is only intended to handle instructions (with 4 byte
00994    immediate operands).  It is not intended to handle data.  */
00995 
00996 /* ??? Actually, there's little for us to do as we can't call frag_more, the
00997    caller must do that.  The extract fns take a pointer to two words.  The
00998    insert fns could be converted and then we could do something useful, but
00999    then the reloc handlers would have to know to work on the second word of
01000    a 2 word quantity.  That's too much so we don't handle them.
01001 
01002    We do check for correct usage of the nullify suffix, or we
01003    set the default correctly, though.  */
01004 
01005 static arc_insn
01006 insert_absaddr (arc_insn insn,
01007               const struct arc_operand *operand ATTRIBUTE_UNUSED,
01008               int mods ATTRIBUTE_UNUSED,
01009               const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
01010               long value ATTRIBUTE_UNUSED,
01011               const char **errmsg)
01012 {
01013   if (limm_p)
01014     {
01015       /* If it is a jump and link, .jd must be specified.  */
01016       if (insn & R (-1, 9, 1))
01017        {
01018          if (!nullify_p)
01019            insn |=  0x02 << 5;  /* Default nullify to .jd.  */
01020 
01021          else if (nullify != 0x02)
01022            *errmsg = _("must specify .jd or no nullify suffix");
01023        }
01024     }
01025   return insn;
01026 }
01027 
01028 /* Extraction functions.
01029 
01030    The suffix extraction functions' return value is redundant since it can be
01031    obtained from (*OPVAL)->value.  However, the boolean suffixes don't have
01032    a suffix table entry for the "false" case, so values of zero must be
01033    obtained from the return value (*OPVAL == NULL).  */
01034 
01035 /* Called by the disassembler before printing an instruction.  */
01036 
01037 void
01038 arc_opcode_init_extract (void)
01039 {
01040   arc_opcode_init_insert ();
01041 }
01042 
01043 static const struct arc_operand_value *
01044 lookup_register (int type, long regno)
01045 {
01046   const struct arc_operand_value *r,*end;
01047   struct arc_ext_operand_value *ext_oper = arc_ext_operands;
01048 
01049   while (ext_oper)
01050     {
01051       if (ext_oper->operand.type == type && ext_oper->operand.value == regno)
01052        return (&ext_oper->operand);
01053       ext_oper = ext_oper->next;
01054     }
01055 
01056   if (type == REG)
01057     return &arc_reg_names[regno];
01058 
01059   /* ??? This is a little slow and can be speeded up.  */
01060   for (r = arc_reg_names, end = arc_reg_names + arc_reg_names_count;
01061        r < end; ++r)
01062     if (type == r->type     && regno == r->value)
01063       return r;
01064   return 0;
01065 }
01066 
01067 /* As we're extracting registers, keep an eye out for the 'f' indicator
01068    (ARC_REG_SHIMM_UPDATE).  If we find a register (not a constant marker,
01069    like ARC_REG_SHIMM), set OPVAL so our caller will know this is a register.
01070 
01071    We must also handle auxiliary registers for lr/sr insns.  They are just
01072    constants with special names.  */
01073 
01074 static long
01075 extract_reg (arc_insn *insn,
01076             const struct arc_operand *operand,
01077             int mods,
01078             const struct arc_operand_value **opval,
01079             int *invalid ATTRIBUTE_UNUSED)
01080 {
01081   int regno;
01082   long value;
01083   enum operand op_type;
01084 
01085   /* Get the register number.  */
01086   regno = (*insn >> operand->shift) & ((1 << operand->bits) - 1);
01087 
01088   /* Is it a constant marker?  */
01089   if (regno == ARC_REG_SHIMM)
01090     {
01091       op_type = OP_SHIMM;
01092       /* Always return zero if dest is a shimm  mlm.  */
01093 
01094       if ('a' != operand->fmt)
01095        {
01096          value = *insn & 511;
01097          if ((operand->flags & ARC_OPERAND_SIGNED)
01098              && (value & 256))
01099            value -= 512;
01100          if (!flagshimm_handled_p)
01101            flag_p = 0;
01102          flagshimm_handled_p = 1;
01103        }
01104       else
01105        value = 0;
01106     }
01107   else if (regno == ARC_REG_SHIMM_UPDATE)
01108     {
01109       op_type = OP_SHIMM;
01110 
01111       /* Always return zero if dest is a shimm  mlm.  */
01112       if ('a' != operand->fmt)
01113        {
01114          value = *insn & 511;
01115          if ((operand->flags & ARC_OPERAND_SIGNED) && (value & 256))
01116            value -= 512;
01117        }
01118       else
01119        value = 0;
01120 
01121       flag_p = 1;
01122       flagshimm_handled_p = 1;
01123     }
01124   else if (regno == ARC_REG_LIMM)
01125     {
01126       op_type = OP_LIMM;
01127       value = insn[1];
01128       limm_p = 1;
01129 
01130       /* If this is a jump instruction (j,jl), show new pc correctly.  */
01131       if (0x07 == ((*insn & I(-1)) >> 27))
01132        value = (value & 0xffffff);
01133     }
01134 
01135   /* It's a register, set OPVAL (that's the only way we distinguish registers
01136      from constants here).  */
01137   else
01138     {
01139       const struct arc_operand_value *reg = lookup_register (REG, regno);
01140 
01141       op_type = OP_REG;
01142 
01143       if (reg == NULL)
01144        abort ();
01145       if (opval != NULL)
01146        *opval = reg;
01147       value = regno;
01148     }
01149 
01150   /* If this field takes an auxiliary register, see if it's a known one.  */
01151   if ((mods & ARC_MOD_AUXREG)
01152       && ARC_REG_CONSTANT_P (regno))
01153     {
01154       const struct arc_operand_value *reg = lookup_register (AUXREG, value);
01155 
01156       /* This is really a constant, but tell the caller it has a special
01157         name.  */
01158       if (reg != NULL && opval != NULL)
01159        *opval = reg;
01160     }
01161 
01162   switch(operand->fmt)
01163     {
01164     case 'a':
01165       ls_operand[LS_DEST] = op_type;
01166       break;
01167     case 's':
01168       ls_operand[LS_BASE] = op_type;
01169       break;
01170     case 'c':
01171       if ((insn[0]& I(-1)) == I(2))
01172        ls_operand[LS_VALUE] = op_type;
01173       else
01174        ls_operand[LS_OFFSET] = op_type;
01175       break;
01176     case 'o': case 'O':
01177       ls_operand[LS_OFFSET] = op_type;
01178       break;
01179     }
01180 
01181   return value;
01182 }
01183 
01184 /* Return the value of the "flag update" field for shimm insns.
01185    This value is actually stored in the register field.  */
01186 
01187 static long
01188 extract_flag (arc_insn *insn,
01189              const struct arc_operand *operand,
01190              int mods ATTRIBUTE_UNUSED,
01191              const struct arc_operand_value **opval,
01192              int *invalid ATTRIBUTE_UNUSED)
01193 {
01194   int f;
01195   const struct arc_operand_value *val;
01196 
01197   if (flagshimm_handled_p)
01198     f = flag_p != 0;
01199   else
01200     f = (*insn & (1 << operand->shift)) != 0;
01201 
01202   /* There is no text for zero values.  */
01203   if (f == 0)
01204     return 0;
01205   flag_p = 1;
01206   val = arc_opcode_lookup_suffix (operand, 1);
01207   if (opval != NULL && val != NULL)
01208     *opval = val;
01209   return val->value;
01210 }
01211 
01212 /* Extract the condition code (if it exists).
01213    If we've seen a shimm value in this insn (meaning that the insn can't have
01214    a condition code field), then we don't store anything in OPVAL and return
01215    zero.  */
01216 
01217 static long
01218 extract_cond (arc_insn *insn,
01219              const struct arc_operand *operand,
01220              int mods ATTRIBUTE_UNUSED,
01221              const struct arc_operand_value **opval,
01222              int *invalid ATTRIBUTE_UNUSED)
01223 {
01224   long cond;
01225   const struct arc_operand_value *val;
01226 
01227   if (flagshimm_handled_p)
01228     return 0;
01229 
01230   cond = (*insn >> operand->shift) & ((1 << operand->bits) - 1);
01231   val = arc_opcode_lookup_suffix (operand, cond);
01232 
01233   /* Ignore NULL values of `val'.  Several condition code values are
01234      reserved for extensions.  */
01235   if (opval != NULL && val != NULL)
01236     *opval = val;
01237   return cond;
01238 }
01239 
01240 /* Extract a branch address.
01241    We return the value as a real address (not right shifted by 2).  */
01242 
01243 static long
01244 extract_reladdr (arc_insn *insn,
01245                const struct arc_operand *operand,
01246                int mods ATTRIBUTE_UNUSED,
01247                const struct arc_operand_value **opval ATTRIBUTE_UNUSED,
01248                int *invalid ATTRIBUTE_UNUSED)
01249 {
01250   long addr;
01251 
01252   addr = (*insn >> operand->shift) & ((1 << operand->bits) - 1);
01253   if ((operand->flags & ARC_OPERAND_SIGNED)
01254       && (addr & (1 << (operand->bits - 1))))
01255     addr -= 1 << operand->bits;
01256   return addr << 2;
01257 }
01258 
01259 /* Extract the flags bits from a j or jl long immediate.  */
01260 
01261 static long
01262 extract_jumpflags (arc_insn *insn,
01263                  const struct arc_operand *operand,
01264                  int mods ATTRIBUTE_UNUSED,
01265                  const struct arc_operand_value **opval ATTRIBUTE_UNUSED,
01266                  int *invalid)
01267 {
01268   if (!flag_p || !limm_p)
01269     *invalid = 1;
01270   return ((flag_p && limm_p)
01271          ? (insn[1] >> operand->shift) & ((1 << operand->bits) -1): 0);
01272 }
01273 
01274 /* Extract st insn's offset.  */
01275 
01276 static long
01277 extract_st_offset (arc_insn *insn,
01278                  const struct arc_operand *operand,
01279                  int mods ATTRIBUTE_UNUSED,
01280                  const struct arc_operand_value **opval ATTRIBUTE_UNUSED,
01281                  int *invalid)
01282 {
01283   int value = 0;
01284 
01285   if (ls_operand[LS_VALUE] != OP_SHIMM || ls_operand[LS_BASE] != OP_LIMM)
01286     {
01287       value = insn[0] & 511;
01288       if ((operand->flags & ARC_OPERAND_SIGNED) && (value & 256))
01289        value -= 512;
01290       if (value)
01291        ls_operand[LS_OFFSET] = OP_SHIMM;
01292     }
01293   else
01294     *invalid = 1;
01295 
01296   return value;
01297 }
01298 
01299 /* Extract ld insn's offset.  */
01300 
01301 static long
01302 extract_ld_offset (arc_insn *insn,
01303                  const struct arc_operand *operand,
01304                  int mods,
01305                  const struct arc_operand_value **opval,
01306                  int *invalid)
01307 {
01308   int test = insn[0] & I(-1);
01309   int value;
01310 
01311   if (test)
01312     {
01313       value = insn[0] & 511;
01314       if ((operand->flags & ARC_OPERAND_SIGNED) && (value & 256))
01315        value -= 512;
01316       if (value)
01317        ls_operand[LS_OFFSET] = OP_SHIMM;
01318 
01319       return value;
01320     }
01321   /* If it isn't in the insn, it's concealed behind reg 'c'.  */
01322   return extract_reg (insn, &arc_operands[arc_operand_map['c']],
01323                     mods, opval, invalid);
01324 }
01325 
01326 /* The only thing this does is set the `invalid' flag if B != C.
01327    This is needed because the "mov" macro appears before it's real insn "and"
01328    and we don't want the disassembler to confuse them.  */
01329 
01330 static long
01331 extract_unopmacro (arc_insn *insn,
01332                  const struct arc_operand *operand ATTRIBUTE_UNUSED,
01333                  int mods ATTRIBUTE_UNUSED,
01334                  const struct arc_operand_value **opval ATTRIBUTE_UNUSED,
01335                  int *invalid)
01336 {
01337   /* This misses the case where B == ARC_REG_SHIMM_UPDATE &&
01338      C == ARC_REG_SHIMM (or vice versa).  No big deal.  Those insns will get
01339      printed as "and"s.  */
01340   if (((*insn >> ARC_SHIFT_REGB) & ARC_MASK_REG)
01341       != ((*insn >> ARC_SHIFT_REGC) & ARC_MASK_REG))
01342     if (invalid != NULL)
01343       *invalid = 1;
01344   return 0;
01345 }
01346 
01347 /* ARC instructions.
01348 
01349    Longer versions of insns must appear before shorter ones (if gas sees
01350    "lsr r2,r3,1" when it's parsing "lsr %a,%b" it will think the ",1" is
01351    junk).  This isn't necessary for `ld' because of the trailing ']'.
01352 
01353    Instructions that are really macros based on other insns must appear
01354    before the real insn so they're chosen when disassembling.  Eg: The `mov'
01355    insn is really the `and' insn.  */
01356 
01357 struct arc_opcode arc_opcodes[] =
01358 {
01359   /* Base case instruction set (core versions 5-8).  */
01360 
01361   /* "mov" is really an "and".  */
01362   { "mov%.q%.f %a,%b%F%S%L%U", I(-1), I(12), ARC_MACH_5, 0, 0 },
01363   /* "asl" is really an "add".  */
01364   { "asl%.q%.f %a,%b%F%S%L%U", I(-1), I(8), ARC_MACH_5, 0, 0 },
01365   /* "lsl" is really an "add".  */
01366   { "lsl%.q%.f %a,%b%F%S%L%U", I(-1), I(8), ARC_MACH_5, 0, 0 },
01367   /* "nop" is really an "xor".  */
01368   { "nop", 0x7fffffff, 0x7fffffff, ARC_MACH_5, 0, 0 },
01369   /* "rlc" is really an "adc".  */
01370   { "rlc%.q%.f %a,%b%F%S%L%U", I(-1), I(9), ARC_MACH_5, 0, 0 },
01371   { "adc%.q%.f %a,%b,%c%F%S%L", I(-1), I(9), ARC_MACH_5, 0, 0 },
01372   { "add%.q%.f %a,%b,%c%F%S%L", I(-1), I(8), ARC_MACH_5, 0, 0 },
01373   { "and%.q%.f %a,%b,%c%F%S%L", I(-1), I(12), ARC_MACH_5, 0, 0 },
01374   { "asr%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(1), ARC_MACH_5, 0, 0 },
01375   { "bic%.q%.f %a,%b,%c%F%S%L",    I(-1), I(14), ARC_MACH_5, 0, 0 },
01376   { "b%q%.n %B", I(-1), I(4), ARC_MACH_5 | ARC_OPCODE_COND_BRANCH, 0, 0 },
01377   { "bl%q%.n %B", I(-1), I(5), ARC_MACH_5 | ARC_OPCODE_COND_BRANCH, 0, 0 },
01378   { "extb%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(7), ARC_MACH_5, 0, 0 },
01379   { "extw%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(8), ARC_MACH_5, 0, 0 },
01380   { "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 },
01381   { "brk", 0x1ffffe00, 0x1ffffe00, ARC_MACH_7, 0, 0 },
01382   { "sleep", 0x1ffffe01, 0x1ffffe01, ARC_MACH_7, 0, 0 },
01383   { "swi", 0x1ffffe02, 0x1ffffe02, ARC_MACH_8, 0, 0 },
01384   /* %Q: force cond_p=1 -> no shimm values. This insn allows an
01385      optional flags spec.  */
01386   { "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 },
01387   { "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 },
01388   /* This insn allows an optional flags spec.  */
01389   { "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 },
01390   { "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 },
01391   /* Put opcode 1 ld insns first so shimm gets prefered over limm.
01392      "[%b]" is before "[%b,%o]" so 0 offsets don't get printed.  */
01393   { "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 },
01394   { "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 },
01395   { "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 },
01396   { "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 },
01397   { "lp%q%.n %B", I(-1), I(6), ARC_MACH_5, 0, 0 },
01398   { "lr %a,[%Ab]%S%L", I(-1)|C(-1), I(1)|C(0x10), ARC_MACH_5, 0, 0 },
01399   { "lsr%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(2), ARC_MACH_5, 0, 0 },
01400   { "or%.q%.f %a,%b,%c%F%S%L", I(-1), I(13), ARC_MACH_5, 0, 0 },
01401   { "ror%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(3), ARC_MACH_5, 0, 0 },
01402   { "rrc%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(4), ARC_MACH_5, 0, 0 },
01403   { "sbc%.q%.f %a,%b,%c%F%S%L",    I(-1), I(11), ARC_MACH_5, 0, 0 },
01404   { "sexb%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(5), ARC_MACH_5, 0, 0 },
01405   { "sexw%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(6), ARC_MACH_5, 0, 0 },
01406   { "sr %c,[%Ab]%S%L", I(-1)|A(-1), I(2)|A(0x10), ARC_MACH_5, 0, 0 },
01407   /* "[%b]" is before "[%b,%o]" so 0 offsets don't get printed.  */
01408   { "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 },
01409   { "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 },
01410   { "sub%.q%.f %a,%b,%c%F%S%L",    I(-1), I(10), ARC_MACH_5, 0, 0 },
01411   { "xor%.q%.f %a,%b,%c%F%S%L",    I(-1), I(15), ARC_MACH_5, 0, 0 }
01412 };
01413 
01414 const int arc_opcodes_count = sizeof (arc_opcodes) / sizeof (arc_opcodes[0]);
01415 
01416 const struct arc_operand_value arc_reg_names[] =
01417 {
01418   /* Core register set r0-r63.  */
01419 
01420   /* r0-r28 - general purpose registers.  */
01421   { "r0", 0, REG, 0 }, { "r1", 1, REG, 0 }, { "r2", 2, REG, 0 },
01422   { "r3", 3, REG, 0 }, { "r4", 4, REG, 0 }, { "r5", 5, REG, 0 },
01423   { "r6", 6, REG, 0 }, { "r7", 7, REG, 0 }, { "r8", 8, REG, 0 },
01424   { "r9", 9, REG, 0 }, { "r10", 10, REG, 0 }, { "r11", 11, REG, 0 },
01425   { "r12", 12, REG, 0 }, { "r13", 13, REG, 0 }, { "r14", 14, REG, 0 },
01426   { "r15", 15, REG, 0 }, { "r16", 16, REG, 0 }, { "r17", 17, REG, 0 },
01427   { "r18", 18, REG, 0 }, { "r19", 19, REG, 0 }, { "r20", 20, REG, 0 },
01428   { "r21", 21, REG, 0 }, { "r22", 22, REG, 0 }, { "r23", 23, REG, 0 },
01429   { "r24", 24, REG, 0 }, { "r25", 25, REG, 0 }, { "r26", 26, REG, 0 },
01430   { "r27", 27, REG, 0 }, { "r28", 28, REG, 0 },
01431   /* Maskable interrupt link register.  */
01432   { "ilink1", 29, REG, 0 },
01433   /* Maskable interrupt link register.  */
01434   { "ilink2", 30, REG, 0 },
01435   /* Branch-link register.  */
01436   { "blink", 31, REG, 0 },
01437 
01438   /* r32-r59 reserved for extensions.  */
01439   { "r32", 32, REG, 0 }, { "r33", 33, REG, 0 }, { "r34", 34, REG, 0 },
01440   { "r35", 35, REG, 0 }, { "r36", 36, REG, 0 }, { "r37", 37, REG, 0 },
01441   { "r38", 38, REG, 0 }, { "r39", 39, REG, 0 }, { "r40", 40, REG, 0 },
01442   { "r41", 41, REG, 0 }, { "r42", 42, REG, 0 }, { "r43", 43, REG, 0 },
01443   { "r44", 44, REG, 0 }, { "r45", 45, REG, 0 }, { "r46", 46, REG, 0 },
01444   { "r47", 47, REG, 0 }, { "r48", 48, REG, 0 }, { "r49", 49, REG, 0 },
01445   { "r50", 50, REG, 0 }, { "r51", 51, REG, 0 }, { "r52", 52, REG, 0 },
01446   { "r53", 53, REG, 0 }, { "r54", 54, REG, 0 }, { "r55", 55, REG, 0 },
01447   { "r56", 56, REG, 0 }, { "r57", 57, REG, 0 }, { "r58", 58, REG, 0 },
01448   { "r59", 59, REG, 0 },
01449 
01450   /* Loop count register (24 bits).  */
01451   { "lp_count", 60, REG, 0 },
01452   /* Short immediate data indicator setting flags.  */
01453   { "r61", 61, REG, ARC_REGISTER_READONLY },
01454   /* Long immediate data indicator setting flags.  */
01455   { "r62", 62, REG, ARC_REGISTER_READONLY },
01456   /* Short immediate data indicator not setting flags.  */
01457   { "r63", 63, REG, ARC_REGISTER_READONLY },
01458 
01459   /* Small-data base register.  */
01460   { "gp", 26, REG, 0 },
01461   /* Frame pointer.  */
01462   { "fp", 27, REG, 0 },
01463   /* Stack pointer.  */
01464   { "sp", 28, REG, 0 },
01465 
01466   { "r29", 29, REG, 0 },
01467   { "r30", 30, REG, 0 },
01468   { "r31", 31, REG, 0 },
01469   { "r60", 60, REG, 0 },
01470 
01471   /* Auxiliary register set.  */
01472 
01473   /* Auxiliary register address map:
01474      0xffffffff-0xffffff00 (-1..-256) - customer shimm allocation
01475      0xfffffeff-0x80000000 - customer limm allocation
01476      0x7fffffff-0x00000100 - ARC limm allocation
01477      0x000000ff-0x00000000 - ARC shimm allocation  */
01478 
01479   /* Base case auxiliary registers (shimm address).  */
01480   { "status",         0x00, AUXREG, 0 },
01481   { "semaphore",      0x01, AUXREG, 0 },
01482   { "lp_start",       0x02, AUXREG, 0 },
01483   { "lp_end",         0x03, AUXREG, 0 },
01484   { "identity",       0x04, AUXREG, ARC_REGISTER_READONLY },
01485   { "debug",          0x05, AUXREG, 0 },
01486 };
01487 
01488 const int arc_reg_names_count =
01489   sizeof (arc_reg_names) / sizeof (arc_reg_names[0]);
01490 
01491 /* The suffix table.
01492    Operands with the same name must be stored together.  */
01493 
01494 const struct arc_operand_value arc_suffixes[] =
01495 {
01496   /* Entry 0 is special, default values aren't printed by the disassembler.  */
01497   { "", 0, -1, 0 },
01498 
01499   /* Base case condition codes.  */
01500   { "al", 0, COND, 0 },
01501   { "ra", 0, COND, 0 },
01502   { "eq", 1, COND, 0 },
01503   { "z", 1, COND, 0 },
01504   { "ne", 2, COND, 0 },
01505   { "nz", 2, COND, 0 },
01506   { "pl", 3, COND, 0 },
01507   { "p", 3, COND, 0 },
01508   { "mi", 4, COND, 0 },
01509   { "n", 4, COND, 0 },
01510   { "cs", 5, COND, 0 },
01511   { "c", 5, COND, 0 },
01512   { "lo", 5, COND, 0 },
01513   { "cc", 6, COND, 0 },
01514   { "nc", 6, COND, 0 },
01515   { "hs", 6, COND, 0 },
01516   { "vs", 7, COND, 0 },
01517   { "v", 7, COND, 0 },
01518   { "vc", 8, COND, 0 },
01519   { "nv", 8, COND, 0 },
01520   { "gt", 9, COND, 0 },
01521   { "ge", 10, COND, 0 },
01522   { "lt", 11, COND, 0 },
01523   { "le", 12, COND, 0 },
01524   { "hi", 13, COND, 0 },
01525   { "ls", 14, COND, 0 },
01526   { "pnz", 15, COND, 0 },
01527 
01528   /* Condition codes 16-31 reserved for extensions.  */
01529 
01530   { "f", 1, FLAG, 0 },
01531 
01532   { "nd", ARC_DELAY_NONE, DELAY, 0 },
01533   { "d", ARC_DELAY_NORMAL, DELAY, 0 },
01534   { "jd", ARC_DELAY_JUMP, DELAY, 0 },
01535 
01536   { "b", 1, SIZE1, 0 },
01537   { "b", 1, SIZE10, 0 },
01538   { "b", 1, SIZE22, 0 },
01539   { "w", 2, SIZE1, 0 },
01540   { "w", 2, SIZE10, 0 },
01541   { "w", 2, SIZE22, 0 },
01542   { "x", 1, SIGN0, 0 },
01543   { "x", 1, SIGN9, 0 },
01544   { "a", 1, ADDRESS3, 0 },
01545   { "a", 1, ADDRESS12, 0 },
01546   { "a", 1, ADDRESS24, 0 },
01547 
01548   { "di", 1, CACHEBYPASS5, 0 },
01549   { "di", 1, CACHEBYPASS14, 0 },
01550   { "di", 1, CACHEBYPASS26, 0 },
01551 };
01552 
01553 const int arc_suffixes_count =
01554   sizeof (arc_suffixes) / sizeof (arc_suffixes[0]);
01555 
01556 /* Indexed by first letter of opcode.  Points to chain of opcodes with same
01557    first letter.  */
01558 static struct arc_opcode *opcode_map[26 + 1];
01559 
01560 /* Indexed by insn code.  Points to chain of opcodes with same insn code.  */
01561 static struct arc_opcode *icode_map[32];
01562 
01563 /* Configuration flags.  */
01564 
01565 /* Various ARC_HAVE_XXX bits.  */
01566 static int cpu_type;
01567 
01568 /* Translate a bfd_mach_arc_xxx value to a ARC_MACH_XXX value.  */
01569 
01570 int
01571 arc_get_opcode_mach (int bfd_mach, int big_p)
01572 {
01573   static int mach_type_map[] =
01574   {
01575     ARC_MACH_5,
01576     ARC_MACH_6,
01577     ARC_MACH_7,
01578     ARC_MACH_8
01579   };
01580   return mach_type_map[bfd_mach - bfd_mach_arc_5] | (big_p ? ARC_MACH_BIG : 0);
01581 }
01582 
01583 /* Initialize any tables that need it.
01584    Must be called once at start up (or when first needed).
01585 
01586    FLAGS is a set of bits that say what version of the cpu we have,
01587    and in particular at least (one of) ARC_MACH_XXX.  */
01588 
01589 void
01590 arc_opcode_init_tables (int flags)
01591 {
01592   static int init_p = 0;
01593 
01594   cpu_type = flags;
01595 
01596   /* We may be intentionally called more than once (for example gdb will call
01597      us each time the user switches cpu).  These tables only need to be init'd
01598      once though.  */
01599   if (!init_p)
01600     {
01601       int i,n;
01602 
01603       memset (arc_operand_map, 0, sizeof (arc_operand_map));
01604       n = sizeof (arc_operands) / sizeof (arc_operands[0]);
01605       for (i = 0; i < n; ++i)
01606        arc_operand_map[arc_operands[i].fmt] = i;
01607 
01608       memset (opcode_map, 0, sizeof (opcode_map));
01609       memset (icode_map, 0, sizeof (icode_map));
01610       /* Scan the table backwards so macros appear at the front.  */
01611       for (i = arc_opcodes_count - 1; i >= 0; --i)
01612        {
01613          int opcode_hash = ARC_HASH_OPCODE (arc_opcodes[i].syntax);
01614          int icode_hash = ARC_HASH_ICODE (arc_opcodes[i].value);
01615 
01616          arc_opcodes[i].next_asm = opcode_map[opcode_hash];
01617          opcode_map[opcode_hash] = &arc_opcodes[i];
01618 
01619          arc_opcodes[i].next_dis = icode_map[icode_hash];
01620          icode_map[icode_hash] = &arc_opcodes[i];
01621        }
01622 
01623       init_p = 1;
01624     }
01625 }
01626 
01627 /* Return non-zero if OPCODE is supported on the specified cpu.
01628    Cpu selection is made when calling `arc_opcode_init_tables'.  */
01629 
01630 int
01631 arc_opcode_supported (const struct arc_opcode *opcode)
01632 {
01633   if (ARC_OPCODE_CPU (opcode->flags) <= cpu_type)
01634     return 1;
01635   return 0;
01636 }
01637 
01638 /* Return the first insn in the chain for assembling INSN.  */
01639 
01640 const struct arc_opcode *
01641 arc_opcode_lookup_asm (const char *insn)
01642 {
01643   return opcode_map[ARC_HASH_OPCODE (insn)];
01644 }
01645 
01646 /* Return the first insn in the chain for disassembling INSN.  */
01647 
01648 const struct arc_opcode *
01649 arc_opcode_lookup_dis (unsigned int insn)
01650 {
01651   return icode_map[ARC_HASH_ICODE (insn)];
01652 }
01653 
01654 /* Called by the assembler before parsing an instruction.  */
01655 
01656 void
01657 arc_opcode_init_insert (void)
01658 {
01659   int i;
01660 
01661   for(i = 0; i < OPERANDS; i++)
01662     ls_operand[i] = OP_NONE;
01663 
01664   flag_p = 0;
01665   flagshimm_handled_p = 0;
01666   cond_p = 0;
01667   addrwb_p = 0;
01668   shimm_p = 0;
01669   limm_p = 0;
01670   jumpflags_p = 0;
01671   nullify_p = 0;
01672   nullify = 0; /* The default is important.  */
01673 }
01674 
01675 /* Called by the assembler to see if the insn has a limm operand.
01676    Also called by the disassembler to see if the insn contains a limm.  */
01677 
01678 int
01679 arc_opcode_limm_p (long *limmp)
01680 {
01681   if (limmp)
01682     *limmp = limm;
01683   return limm_p;
01684 }
01685 
01686 /* Utility for the extraction functions to return the index into
01687    `arc_suffixes'.  */
01688 
01689 const struct arc_operand_value *
01690 arc_opcode_lookup_suffix (const struct arc_operand *type, int value)
01691 {
01692   const struct arc_operand_value *v,*end;
01693   struct arc_ext_operand_value *ext_oper = arc_ext_operands;
01694 
01695   while (ext_oper)
01696     {
01697       if (type == &arc_operands[ext_oper->operand.type]
01698          && value == ext_oper->operand.value)
01699        return (&ext_oper->operand);
01700       ext_oper = ext_oper->next;
01701     }
01702 
01703   /* ??? This is a little slow and can be speeded up.  */
01704   for (v = arc_suffixes, end = arc_suffixes + arc_suffixes_count; v < end; ++v)
01705     if (type == &arc_operands[v->type]
01706        && value == v->value)
01707       return v;
01708   return 0;
01709 }
01710 
01711 int
01712 arc_insn_is_j (arc_insn insn)
01713 {
01714   return (insn & (I(-1))) == I(0x7);
01715 }
01716 
01717 int
01718 arc_insn_not_jl (arc_insn insn)
01719 {
01720   return ((insn & (I(-1)|A(-1)|C(-1)|R(-1,7,1)|R(-1,9,1)))
01721          != (I(0x7) | R(-1,9,1)));
01722 }
01723 
01724 int
01725 arc_operand_type (int opertype)
01726 {
01727   switch (opertype)
01728     {
01729     case 0:
01730       return COND;
01731       break;
01732     case 1:
01733       return REG;
01734       break;
01735     case 2:
01736       return AUXREG;
01737       break;
01738     }
01739   return -1;
01740 }
01741 
01742 struct arc_operand_value *
01743 get_ext_suffix (char *s)
01744 {
01745   struct arc_ext_operand_value *suffix = arc_ext_operands;
01746 
01747   while (suffix)
01748     {
01749       if ((COND == suffix->operand.type)
01750          && !strcmp(s,suffix->operand.name))
01751        return(&suffix->operand);
01752       suffix = suffix->next;
01753     }
01754   return NULL;
01755 }
01756 
01757 int
01758 arc_get_noshortcut_flag (void)
01759 {
01760   return ARC_REGISTER_NOSHORT_CUT;
01761 }