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