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