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