OSDN Git Service

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