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