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 
29 enum operand {OP_NONE,OP_REG,OP_SHIMM,OP_LIMM};
30 
31 #define OPERANDS 3
32 
33 enum operand ls_operand[OPERANDS];
34 
35 struct arc_opcode *arc_ext_opcodes;
36 struct 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.  */
45 unsigned char arc_operand_map[256];
46 
47 /* Nonzero if we've seen an 'f' suffix (in certain insns).  */
48 static int flag_p;
49 
50 /* Nonzero if we've finished processing the 'f' suffix.  */
51 static int flagshimm_handled_p;
52 
53 /* Nonzero if we've seen a 'a' suffix (address writeback).  */
54 static int addrwb_p;
55 
56 /* Nonzero if we've seen a 'q' suffix (condition code).  */
57 static int cond_p;
58 
59 /* Nonzero if we've inserted a nullify condition.  */
60 static int nullify_p;
61 
62 /* The value of the a nullify condition we inserted.  */
63 static int nullify;
64 
65 /* Nonzero if we've inserted jumpflags.  */
66 static int jumpflags_p;
67 
68 /* Nonzero if we've inserted a shimm.  */
69 static int shimm_p;
70 
71 /* The value of the shimm we inserted (each insn only gets one but it can
72    appear multiple times).  */
73 static int shimm;
74 
75 /* Nonzero if we've inserted a limm (during assembly) or seen a limm
76    (during disassembly).  */
77 static int limm_p;
78 
79 /* The value of the limm we inserted.  Each insn only gets one but it can
80    appear multiple times.  */
81 static long limm;
82 
83 #define INSERT_FN(fn) \
84 static arc_insn fn (arc_insn, const struct arc_operand *, \
85 		    int, const struct arc_operand_value *, long, \
86 		    const char **)
87 
88 #define EXTRACT_FN(fn) \
89 static long fn (arc_insn *, const struct arc_operand *, \
90 		int, const struct arc_operand_value **, int *)
91 
92 INSERT_FN (insert_reg);
93 INSERT_FN (insert_shimmfinish);
94 INSERT_FN (insert_limmfinish);
95 INSERT_FN (insert_offset);
96 INSERT_FN (insert_base);
97 INSERT_FN (insert_st_syntax);
98 INSERT_FN (insert_ld_syntax);
99 INSERT_FN (insert_addr_wb);
100 INSERT_FN (insert_flag);
101 INSERT_FN (insert_nullify);
102 INSERT_FN (insert_flagfinish);
103 INSERT_FN (insert_cond);
104 INSERT_FN (insert_forcelimm);
105 INSERT_FN (insert_reladdr);
106 INSERT_FN (insert_absaddr);
107 INSERT_FN (insert_jumpflags);
108 INSERT_FN (insert_unopmacro);
109 
110 EXTRACT_FN (extract_reg);
111 EXTRACT_FN (extract_ld_offset);
112 EXTRACT_FN (extract_ld_syntax);
113 EXTRACT_FN (extract_st_offset);
114 EXTRACT_FN (extract_st_syntax);
115 EXTRACT_FN (extract_flag);
116 EXTRACT_FN (extract_cond);
117 EXTRACT_FN (extract_reladdr);
118 EXTRACT_FN (extract_jumpflags);
119 EXTRACT_FN (extract_unopmacro);
120 
121 /* Various types of ARC operands, including insn suffixes.  */
122 
123 /* Insn format values:
124 
125    'a'	REGA		register A field
126    'b'	REGB		register B field
127    'c'	REGC		register C field
128    'S'	SHIMMFINISH	finish inserting a shimm value
129    'L'	LIMMFINISH	finish inserting a limm value
130    'o'	OFFSET		offset in st insns
131    'O'	OFFSET		offset in ld insns
132    '0'	SYNTAX_ST_NE	enforce store insn syntax, no errors
133    '1'	SYNTAX_LD_NE	enforce load insn syntax, no errors
134    '2'  SYNTAX_ST       enforce store insn syntax, errors, last pattern only
135    '3'  SYNTAX_LD       enforce load insn syntax, errors, last pattern only
136    's'  BASE            base in st insn
137    'f'	FLAG		F flag
138    'F'	FLAGFINISH	finish inserting the F flag
139    'G'	FLAGINSN	insert F flag in "flag" insn
140    'n'	DELAY		N field (nullify field)
141    'q'	COND		condition code field
142    'Q'	FORCELIMM	set `cond_p' to 1 to ensure a constant is a limm
143    'B'	BRANCH		branch address (22 bit pc relative)
144    'J'	JUMP		jump address (26 bit absolute)
145    'j'  JUMPFLAGS       optional high order bits of 'J'
146    'z'	SIZE1		size field in ld a,[b,c]
147    'Z'	SIZE10		size field in ld a,[b,shimm]
148    'y'	SIZE22		size field in st c,[b,shimm]
149    'x'	SIGN0		sign extend field ld a,[b,c]
150    'X'	SIGN9		sign extend field ld a,[b,shimm]
151    'w'	ADDRESS3	write-back field in ld a,[b,c]
152    'W'	ADDRESS12	write-back field in ld a,[b,shimm]
153    'v'	ADDRESS24	write-back field in st c,[b,shimm]
154    'e'	CACHEBYPASS5	cache bypass in ld a,[b,c]
155    'E'	CACHEBYPASS14	cache bypass in ld a,[b,shimm]
156    'D'	CACHEBYPASS26	cache bypass in st c,[b,shimm]
157    'U'	UNOPMACRO	fake operand to copy REGB to REGC for unop macros
158 
159    The following modifiers may appear between the % and char (eg: %.f):
160 
161    '.'	MODDOT		'.' prefix must be present
162    'r'	REG		generic register value, for register table
163    'A'	AUXREG		auxiliary register in lr a,[b], sr c,[b]
164 
165    Fields are:
166 
167    CHAR BITS SHIFT FLAGS INSERT_FN EXTRACT_FN  */
168 
169 const struct arc_operand arc_operands[] =
170 {
171 /* Place holder (??? not sure if needed).  */
172 #define UNUSED 0
173   { 0, 0, 0, 0, 0, 0 },
174 
175 /* Register A or shimm/limm indicator.  */
176 #define REGA (UNUSED + 1)
177   { 'a', 6, ARC_SHIFT_REGA, ARC_OPERAND_SIGNED | ARC_OPERAND_ERROR, insert_reg, extract_reg },
178 
179 /* Register B or shimm/limm indicator.  */
180 #define REGB (REGA + 1)
181   { 'b', 6, ARC_SHIFT_REGB, ARC_OPERAND_SIGNED | ARC_OPERAND_ERROR, insert_reg, extract_reg },
182 
183 /* Register C or shimm/limm indicator.  */
184 #define REGC (REGB + 1)
185   { 'c', 6, ARC_SHIFT_REGC, ARC_OPERAND_SIGNED | ARC_OPERAND_ERROR, insert_reg, extract_reg },
186 
187 /* Fake operand used to insert shimm value into most instructions.  */
188 #define SHIMMFINISH (REGC + 1)
189   { 'S', 9, 0, ARC_OPERAND_SIGNED + ARC_OPERAND_FAKE, insert_shimmfinish, 0 },
190 
191 /* Fake operand used to insert limm value into most instructions.  */
192 #define LIMMFINISH (SHIMMFINISH + 1)
193   { 'L', 32, 32, ARC_OPERAND_ADDRESS + ARC_OPERAND_LIMM + ARC_OPERAND_FAKE, insert_limmfinish, 0 },
194 
195 /* Shimm operand when there is no reg indicator (st).  */
196 #define ST_OFFSET (LIMMFINISH + 1)
197   { 'o', 9, 0, ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED | ARC_OPERAND_STORE, insert_offset, extract_st_offset },
198 
199 /* Shimm operand when there is no reg indicator (ld).  */
200 #define LD_OFFSET (ST_OFFSET + 1)
201   { 'O', 9, 0,ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED | ARC_OPERAND_LOAD, insert_offset, extract_ld_offset },
202 
203 /* Operand for base.  */
204 #define BASE (LD_OFFSET + 1)
205   { 's', 6, ARC_SHIFT_REGB, ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED, insert_base, extract_reg},
206 
207 /* 0 enforce syntax for st insns.  */
208 #define SYNTAX_ST_NE (BASE + 1)
209   { '0', 9, 0, ARC_OPERAND_FAKE, insert_st_syntax, extract_st_syntax },
210 
211 /* 1 enforce syntax for ld insns.  */
212 #define SYNTAX_LD_NE (SYNTAX_ST_NE + 1)
213   { '1', 9, 0, ARC_OPERAND_FAKE, insert_ld_syntax, extract_ld_syntax },
214 
215 /* 0 enforce syntax for st insns.  */
216 #define SYNTAX_ST (SYNTAX_LD_NE + 1)
217   { '2', 9, 0, ARC_OPERAND_FAKE | ARC_OPERAND_ERROR, insert_st_syntax, extract_st_syntax },
218 
219 /* 0 enforce syntax for ld insns.  */
220 #define SYNTAX_LD (SYNTAX_ST + 1)
221   { '3', 9, 0, ARC_OPERAND_FAKE | ARC_OPERAND_ERROR, insert_ld_syntax, extract_ld_syntax },
222 
223 /* Flag update bit (insertion is defered until we know how).  */
224 #define FLAG (SYNTAX_LD + 1)
225   { 'f', 1, 8, ARC_OPERAND_SUFFIX, insert_flag, extract_flag },
226 
227 /* Fake utility operand to finish 'f' suffix handling.  */
228 #define FLAGFINISH (FLAG + 1)
229   { 'F', 1, 8, ARC_OPERAND_FAKE, insert_flagfinish, 0 },
230 
231 /* Fake utility operand to set the 'f' flag for the "flag" insn.  */
232 #define FLAGINSN (FLAGFINISH + 1)
233   { 'G', 1, 8, ARC_OPERAND_FAKE, insert_flag, 0 },
234 
235 /* Branch delay types.  */
236 #define DELAY (FLAGINSN + 1)
237   { 'n', 2, 5, ARC_OPERAND_SUFFIX , insert_nullify, 0 },
238 
239 /* Conditions.  */
240 #define COND (DELAY + 1)
241   { 'q', 5, 0, ARC_OPERAND_SUFFIX, insert_cond, extract_cond },
242 
243 /* Set `cond_p' to 1 to ensure a constant is treated as a limm.  */
244 #define FORCELIMM (COND + 1)
245   { 'Q', 0, 0, ARC_OPERAND_FAKE, insert_forcelimm, 0 },
246 
247 /* Branch address; b, bl, and lp insns.  */
248 #define BRANCH (FORCELIMM + 1)
249   { 'B', 20, 7, (ARC_OPERAND_RELATIVE_BRANCH + ARC_OPERAND_SIGNED) | ARC_OPERAND_ERROR, insert_reladdr, extract_reladdr },
250 
251 /* Jump address; j insn (this is basically the same as 'L' except that the
252    value is right shifted by 2).  */
253 #define JUMP (BRANCH + 1)
254   { 'J', 24, 32, ARC_OPERAND_ERROR | (ARC_OPERAND_ABSOLUTE_BRANCH + ARC_OPERAND_LIMM + ARC_OPERAND_FAKE), insert_absaddr, 0 },
255 
256 /* Jump flags; j{,l} insn value or'ed into 'J' addr for flag values.  */
257 #define JUMPFLAGS (JUMP + 1)
258   { 'j', 6, 26, ARC_OPERAND_JUMPFLAGS | ARC_OPERAND_ERROR, insert_jumpflags, extract_jumpflags },
259 
260 /* Size field, stored in bit 1,2.  */
261 #define SIZE1 (JUMPFLAGS + 1)
262   { 'z', 2, 1, ARC_OPERAND_SUFFIX, 0, 0 },
263 
264 /* Size field, stored in bit 10,11.  */
265 #define SIZE10 (SIZE1 + 1)
266   { 'Z', 2, 10, ARC_OPERAND_SUFFIX, 0, 0 },
267 
268 /* Size field, stored in bit 22,23.  */
269 #define SIZE22 (SIZE10 + 1)
270   { 'y', 2, 22, ARC_OPERAND_SUFFIX, 0, 0 },
271 
272 /* Sign extend field, stored in bit 0.  */
273 #define SIGN0 (SIZE22 + 1)
274   { 'x', 1, 0, ARC_OPERAND_SUFFIX, 0, 0 },
275 
276 /* Sign extend field, stored in bit 9.  */
277 #define SIGN9 (SIGN0 + 1)
278   { 'X', 1, 9, ARC_OPERAND_SUFFIX, 0, 0 },
279 
280 /* Address write back, stored in bit 3.  */
281 #define ADDRESS3 (SIGN9 + 1)
282   { 'w', 1, 3, ARC_OPERAND_SUFFIX, insert_addr_wb, 0},
283 
284 /* Address write back, stored in bit 12.  */
285 #define ADDRESS12 (ADDRESS3 + 1)
286   { 'W', 1, 12, ARC_OPERAND_SUFFIX, insert_addr_wb, 0},
287 
288 /* Address write back, stored in bit 24.  */
289 #define ADDRESS24 (ADDRESS12 + 1)
290   { 'v', 1, 24, ARC_OPERAND_SUFFIX, insert_addr_wb, 0},
291 
292 /* Cache bypass, stored in bit 5.  */
293 #define CACHEBYPASS5 (ADDRESS24 + 1)
294   { 'e', 1, 5, ARC_OPERAND_SUFFIX, 0, 0 },
295 
296 /* Cache bypass, stored in bit 14.  */
297 #define CACHEBYPASS14 (CACHEBYPASS5 + 1)
298   { 'E', 1, 14, ARC_OPERAND_SUFFIX, 0, 0 },
299 
300 /* Cache bypass, stored in bit 26.  */
301 #define CACHEBYPASS26 (CACHEBYPASS14 + 1)
302   { 'D', 1, 26, ARC_OPERAND_SUFFIX, 0, 0 },
303 
304 /* Unop macro, used to copy REGB to REGC.  */
305 #define UNOPMACRO (CACHEBYPASS26 + 1)
306   { 'U', 6, ARC_SHIFT_REGC, ARC_OPERAND_FAKE, insert_unopmacro, extract_unopmacro },
307 
308 /* '.' modifier ('.' required).  */
309 #define MODDOT (UNOPMACRO + 1)
310   { '.', 1, 0, ARC_MOD_DOT, 0, 0 },
311 
312 /* Dummy 'r' modifier for the register table.
313    It's called a "dummy" because there's no point in inserting an 'r' into all
314    the %a/%b/%c occurrences in the insn table.  */
315 #define REG (MODDOT + 1)
316   { 'r', 6, 0, ARC_MOD_REG, 0, 0 },
317 
318 /* Known auxiliary register modifier (stored in shimm field).  */
319 #define AUXREG (REG + 1)
320   { 'A', 9, 0, ARC_MOD_AUXREG, 0, 0 },
321 
322 /* End of list place holder.  */
323   { 0, 0, 0, 0, 0, 0 }
324 };
325 
326 /* Insert a value into a register field.
327    If REG is NULL, then this is actually a constant.
328 
329    We must also handle auxiliary registers for lr/sr insns.  */
330 
331 static arc_insn
insert_reg(arc_insn insn,const struct arc_operand * operand,int mods,const struct arc_operand_value * reg,long value,const char ** errmsg)332 insert_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 
460 static arc_insn
insert_flag(arc_insn insn,const struct arc_operand * operand ATTRIBUTE_UNUSED,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value ATTRIBUTE_UNUSED,const char ** errmsg ATTRIBUTE_UNUSED)461 insert_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 
477 static arc_insn
insert_nullify(arc_insn insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value,const char ** errmsg ATTRIBUTE_UNUSED)478 insert_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 
495 static arc_insn
insert_flagfinish(arc_insn insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value ATTRIBUTE_UNUSED,const char ** errmsg ATTRIBUTE_UNUSED)496 insert_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 
515 static arc_insn
insert_cond(arc_insn insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value,const char ** errmsg ATTRIBUTE_UNUSED)516 insert_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 
534 static arc_insn
insert_forcelimm(arc_insn insn,const struct arc_operand * operand ATTRIBUTE_UNUSED,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value ATTRIBUTE_UNUSED,const char ** errmsg ATTRIBUTE_UNUSED)535 insert_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 
546 static arc_insn
insert_addr_wb(arc_insn insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value ATTRIBUTE_UNUSED,const char ** errmsg ATTRIBUTE_UNUSED)547 insert_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 
558 static arc_insn
insert_base(arc_insn insn,const struct arc_operand * operand,int mods,const struct arc_operand_value * reg,long value,const char ** errmsg)559 insert_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 
609 static arc_insn
insert_offset(arc_insn insn,const struct arc_operand * operand,int mods,const struct arc_operand_value * reg,long value,const char ** errmsg)610 insert_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 = _("too 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 
705 static long
extract_st_syntax(arc_insn * insn,const struct arc_operand * operand ATTRIBUTE_UNUSED,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value ** opval ATTRIBUTE_UNUSED,int * invalid)706 extract_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 
735 int
arc_limm_fixup_adjust(arc_insn insn)736 arc_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 
753 static arc_insn
insert_st_syntax(arc_insn insn,const struct arc_operand * operand ATTRIBUTE_UNUSED,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value ATTRIBUTE_UNUSED,const char ** errmsg)754 insert_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 
828 static arc_insn
insert_ld_syntax(arc_insn insn,const struct arc_operand * operand ATTRIBUTE_UNUSED,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value ATTRIBUTE_UNUSED,const char ** errmsg)829 insert_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 
868 static long
extract_ld_syntax(arc_insn * insn,const struct arc_operand * operand ATTRIBUTE_UNUSED,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value ** opval ATTRIBUTE_UNUSED,int * invalid)869 extract_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 
898 static arc_insn
insert_shimmfinish(arc_insn insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value ATTRIBUTE_UNUSED,const char ** errmsg ATTRIBUTE_UNUSED)899 insert_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 
923 static arc_insn
insert_limmfinish(arc_insn insn,const struct arc_operand * operand ATTRIBUTE_UNUSED,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value ATTRIBUTE_UNUSED,const char ** errmsg ATTRIBUTE_UNUSED)924 insert_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 
934 static arc_insn
insert_jumpflags(arc_insn insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value,const char ** errmsg)935 insert_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 
965 static arc_insn
insert_unopmacro(arc_insn insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value ATTRIBUTE_UNUSED,const char ** errmsg ATTRIBUTE_UNUSED)966 insert_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 
979 static arc_insn
insert_reladdr(arc_insn insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value,const char ** errmsg)980 insert_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 
1007 static arc_insn
insert_absaddr(arc_insn insn,const struct arc_operand * operand ATTRIBUTE_UNUSED,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value * reg ATTRIBUTE_UNUSED,long value ATTRIBUTE_UNUSED,const char ** errmsg)1008 insert_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 
1039 void
arc_opcode_init_extract(void)1040 arc_opcode_init_extract (void)
1041 {
1042   arc_opcode_init_insert ();
1043 }
1044 
1045 static const struct arc_operand_value *
lookup_register(int type,long regno)1046 lookup_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 
1076 static long
extract_reg(arc_insn * insn,const struct arc_operand * operand,int mods,const struct arc_operand_value ** opval,int * invalid ATTRIBUTE_UNUSED)1077 extract_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 
1189 static long
extract_flag(arc_insn * insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value ** opval,int * invalid ATTRIBUTE_UNUSED)1190 extract_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 
1219 static long
extract_cond(arc_insn * insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value ** opval,int * invalid ATTRIBUTE_UNUSED)1220 extract_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 
1245 static long
extract_reladdr(arc_insn * insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value ** opval ATTRIBUTE_UNUSED,int * invalid ATTRIBUTE_UNUSED)1246 extract_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 
1263 static long
extract_jumpflags(arc_insn * insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value ** opval ATTRIBUTE_UNUSED,int * invalid)1264 extract_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 
1278 static long
extract_st_offset(arc_insn * insn,const struct arc_operand * operand,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value ** opval ATTRIBUTE_UNUSED,int * invalid)1279 extract_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 
1303 static long
extract_ld_offset(arc_insn * insn,const struct arc_operand * operand,int mods,const struct arc_operand_value ** opval,int * invalid)1304 extract_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 
1332 static long
extract_unopmacro(arc_insn * insn,const struct arc_operand * operand ATTRIBUTE_UNUSED,int mods ATTRIBUTE_UNUSED,const struct arc_operand_value ** opval ATTRIBUTE_UNUSED,int * invalid)1333 extract_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 
1359 struct 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 
1416 const int arc_opcodes_count = sizeof (arc_opcodes) / sizeof (arc_opcodes[0]);
1417 
1418 const 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 
1490 const 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 
1496 const 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 
1555 const 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.  */
1560 static struct arc_opcode *opcode_map[26 + 1];
1561 
1562 /* Indexed by insn code.  Points to chain of opcodes with same insn code.  */
1563 static struct arc_opcode *icode_map[32];
1564 
1565 /* Configuration flags.  */
1566 
1567 /* Various ARC_HAVE_XXX bits.  */
1568 static int cpu_type;
1569 
1570 /* Translate a bfd_mach_arc_xxx value to a ARC_MACH_XXX value.  */
1571 
1572 int
arc_get_opcode_mach(int bfd_mach,int big_p)1573 arc_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 
1591 void
arc_opcode_init_tables(int flags)1592 arc_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 
1632 int
arc_opcode_supported(const struct arc_opcode * opcode)1633 arc_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 
1642 const struct arc_opcode *
arc_opcode_lookup_asm(const char * insn)1643 arc_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 
1650 const struct arc_opcode *
arc_opcode_lookup_dis(unsigned int insn)1651 arc_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 
1658 void
arc_opcode_init_insert(void)1659 arc_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 
1680 int
arc_opcode_limm_p(long * limmp)1681 arc_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 
1691 const struct arc_operand_value *
arc_opcode_lookup_suffix(const struct arc_operand * type,int value)1692 arc_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 
1713 int
arc_insn_is_j(arc_insn insn)1714 arc_insn_is_j (arc_insn insn)
1715 {
1716   return (insn & (I(-1))) == I(0x7);
1717 }
1718 
1719 int
arc_insn_not_jl(arc_insn insn)1720 arc_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 
1726 int
arc_operand_type(int opertype)1727 arc_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 
1744 struct arc_operand_value *
get_ext_suffix(char * s)1745 get_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 
1759 int
arc_get_noshortcut_flag(void)1760 arc_get_noshortcut_flag (void)
1761 {
1762   return ARC_REGISTER_NOSHORT_CUT;
1763 }
1764