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
27enum operand {OP_NONE,OP_REG,OP_SHIMM,OP_LIMM};
28
29#define OPERANDS 3
30
31enum operand ls_operand[OPERANDS];
32
33struct arc_opcode *arc_ext_opcodes;
34struct 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.  */
43unsigned char arc_operand_map[256];
44
45/* Nonzero if we've seen an 'f' suffix (in certain insns).  */
46static int flag_p;
47
48/* Nonzero if we've finished processing the 'f' suffix.  */
49static int flagshimm_handled_p;
50
51/* Nonzero if we've seen a 'a' suffix (address writeback).  */
52static int addrwb_p;
53
54/* Nonzero if we've seen a 'q' suffix (condition code).  */
55static int cond_p;
56
57/* Nonzero if we've inserted a nullify condition.  */
58static int nullify_p;
59
60/* The value of the a nullify condition we inserted.  */
61static int nullify;
62
63/* Nonzero if we've inserted jumpflags.  */
64static int jumpflags_p;
65
66/* Nonzero if we've inserted a shimm.  */
67static int shimm_p;
68
69/* The value of the shimm we inserted (each insn only gets one but it can
70   appear multiple times).  */
71static int shimm;
72
73/* Nonzero if we've inserted a limm (during assembly) or seen a limm
74   (during disassembly).  */
75static int limm_p;
76
77/* The value of the limm we inserted.  Each insn only gets one but it can
78   appear multiple times.  */
79static long limm;
80
81#define INSERT_FN(fn) \
82static 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) \
87static long fn (arc_insn *, const struct arc_operand *, \
88		int, const struct arc_operand_value **, int *)
89
90INSERT_FN (insert_reg);
91INSERT_FN (insert_shimmfinish);
92INSERT_FN (insert_limmfinish);
93INSERT_FN (insert_offset);
94INSERT_FN (insert_base);
95INSERT_FN (insert_st_syntax);
96INSERT_FN (insert_ld_syntax);
97INSERT_FN (insert_addr_wb);
98INSERT_FN (insert_flag);
99INSERT_FN (insert_nullify);
100INSERT_FN (insert_flagfinish);
101INSERT_FN (insert_cond);
102INSERT_FN (insert_forcelimm);
103INSERT_FN (insert_reladdr);
104INSERT_FN (insert_absaddr);
105INSERT_FN (insert_jumpflags);
106INSERT_FN (insert_unopmacro);
107
108EXTRACT_FN (extract_reg);
109EXTRACT_FN (extract_ld_offset);
110EXTRACT_FN (extract_ld_syntax);
111EXTRACT_FN (extract_st_offset);
112EXTRACT_FN (extract_st_syntax);
113EXTRACT_FN (extract_flag);
114EXTRACT_FN (extract_cond);
115EXTRACT_FN (extract_reladdr);
116EXTRACT_FN (extract_jumpflags);
117EXTRACT_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
167const 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
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
329static arc_insn
330insert_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
458static arc_insn
459insert_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
475static arc_insn
476insert_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
493static arc_insn
494insert_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
513static arc_insn
514insert_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
532static arc_insn
533insert_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
544static arc_insn
545insert_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
556static arc_insn
557insert_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
607static arc_insn
608insert_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
703static long
704extract_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
733int
734arc_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
751static arc_insn
752insert_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
826static arc_insn
827insert_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
866static long
867extract_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
896static arc_insn
897insert_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
921static arc_insn
922insert_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
932static arc_insn
933insert_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
963static arc_insn
964insert_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
977static arc_insn
978insert_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
1005static arc_insn
1006insert_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
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
1037void
1038arc_opcode_init_extract (void)
1039{
1040  arc_opcode_init_insert ();
1041}
1042
1043static const struct arc_operand_value *
1044lookup_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
1074static long
1075extract_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
1187static long
1188extract_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
1217static long
1218extract_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
1243static long
1244extract_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
1261static long
1262extract_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
1276static long
1277extract_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
1301static long
1302extract_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
1330static long
1331extract_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
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
1357struct 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
1414const int arc_opcodes_count = sizeof (arc_opcodes) / sizeof (arc_opcodes[0]);
1415
1416const 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
1488const 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
1494const 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
1553const 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.  */
1558static struct arc_opcode *opcode_map[26 + 1];
1559
1560/* Indexed by insn code.  Points to chain of opcodes with same insn code.  */
1561static struct arc_opcode *icode_map[32];
1562
1563/* Configuration flags.  */
1564
1565/* Various ARC_HAVE_XXX bits.  */
1566static int cpu_type;
1567
1568/* Translate a bfd_mach_arc_xxx value to a ARC_MACH_XXX value.  */
1569
1570int
1571arc_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
1589void
1590arc_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
1630int
1631arc_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
1640const struct arc_opcode *
1641arc_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
1648const struct arc_opcode *
1649arc_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
1656void
1657arc_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
1678int
1679arc_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
1689const struct arc_operand_value *
1690arc_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
1711int
1712arc_insn_is_j (arc_insn insn)
1713{
1714  return (insn & (I(-1))) == I(0x7);
1715}
1716
1717int
1718arc_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
1724int
1725arc_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
1742struct arc_operand_value *
1743get_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
1757int
1758arc_get_noshortcut_flag (void)
1759{
1760  return ARC_REGISTER_NOSHORT_CUT;
1761}
1762