* arc-dis.c (print_insn): New parameter `big_p'. Callers updated.
[external/binutils.git] / opcodes / arc-opc.c
1 /* Opcode table for the ARC.
2    Copyright 1994, 1995 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
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
18
19 #include "ansidecl.h"
20 #include "opcode/arc.h"
21
22 #define INSERT_FN(fn) \
23 static arc_insn fn PARAMS ((arc_insn, const struct arc_operand *, \
24                             int, const struct arc_operand_value *, long, \
25                             const char **))
26 #define EXTRACT_FN(fn) \
27 static long fn PARAMS ((arc_insn *, const struct arc_operand *, \
28                         int, const struct arc_operand_value **, int *))
29
30 INSERT_FN (insert_reg);
31 INSERT_FN (insert_shimmfinish);
32 INSERT_FN (insert_limmfinish);
33 INSERT_FN (insert_shimmoffset);
34 INSERT_FN (insert_shimmzero);
35 INSERT_FN (insert_flag);
36 INSERT_FN (insert_flagfinish);
37 INSERT_FN (insert_cond);
38 INSERT_FN (insert_forcelimm);
39 INSERT_FN (insert_reladdr);
40 INSERT_FN (insert_absaddr);
41 INSERT_FN (insert_unopmacro);
42 INSERT_FN (insert_multshift);
43
44 EXTRACT_FN (extract_reg);
45 EXTRACT_FN (extract_flag);
46 EXTRACT_FN (extract_cond);
47 EXTRACT_FN (extract_reladdr);
48 EXTRACT_FN (extract_unopmacro);
49 EXTRACT_FN (extract_multshift);
50
51 /* Various types of ARC operands, including insn suffixes.  */
52
53 /* Insn format values:
54
55    'a'  REGA            register A field
56    'b'  REGB            register B field
57    'c'  REGC            register C field
58    'S'  SHIMMFINISH     finish inserting a shimm value
59    'L'  LIMMFINISH      finish inserting a limm value
60    'd'  SHIMMOFFSET     shimm offset in ld,st insns
61    '0'  SHIMMZERO       0 shimm value in ld,st insns
62    'f'  FLAG            F flag
63    'F'  FLAGFINISH      finish inserting the F flag
64    'G'  FLAGINSN        insert F flag in "flag" insn
65    'n'  DELAY           N field (nullify field)
66    'q'  COND            condition code field
67    'Q'  FORCELIMM       set `cond_p' to 1 to ensure a constant is a limm
68    'B'  BRANCH          branch address (22 bit pc relative)
69    'J'  JUMP            jump address (26 bit absolute)
70    'z'  SIZE1           size field in ld a,[b,c]
71    'Z'  SIZE10          size field in ld a,[b,shimm]
72    'y'  SIZE22          size field in st c,[b,shimm]
73    'x'  SIGN0           sign extend field ld a,[b,c]
74    'X'  SIGN9           sign extend field ld a,[b,shimm]
75    'w'  ADDRESS3        write-back field in ld a,[b,c]
76    'W'  ADDRESS12       write-back field in ld a,[b,shimm]
77    'v'  ADDRESS24       write-back field in st c,[b,shimm]
78    'e'  CACHEBYPASS5    cache bypass in ld a,[b,c]
79    'E'  CACHEBYPASS14   cache bypass in ld a,[b,shimm]
80    'D'  CACHEBYPASS26   cache bypass in st c,[b,shimm]
81    'u'  UNSIGNED        unsigned multiply
82    's'  SATURATION      saturation limit in audio arc mac insn
83    'U'  UNOPMACRO       fake operand to copy REGB to REGC for unop macros
84
85    The following modifiers may appear between the % and char (eg: %.f):
86
87    '.'  MODDOT          '.' prefix must be present
88    'r'  REG             generic register value, for register table
89    'A'  AUXREG          auxiliary register in lr a,[b], sr c,[b]
90
91    Fields are:
92
93    CHAR BITS SHIFT FLAGS INSERT_FN EXTRACT_FN
94 */
95
96 const struct arc_operand arc_operands[] =
97 {
98 /* place holder (??? not sure if needed) */
99 #define UNUSED 0
100   { 0 },
101
102 /* register A or shimm/limm indicator */
103 #define REGA (UNUSED + 1)
104   { 'a', 6, ARC_SHIFT_REGA, 0, insert_reg, extract_reg },
105
106 /* register B or shimm/limm indicator */
107 #define REGB (REGA + 1)
108   { 'b', 6, ARC_SHIFT_REGB, 0, insert_reg, extract_reg },
109
110 /* register C or shimm/limm indicator */
111 #define REGC (REGB + 1)
112   { 'c', 6, ARC_SHIFT_REGC, 0, insert_reg, extract_reg },
113
114 /* fake operand used to insert shimm value into most instructions */
115 #define SHIMMFINISH (REGC + 1)
116   { 'S', 9, 0, ARC_OPERAND_SIGNED + ARC_OPERAND_FAKE, insert_shimmfinish, 0 },
117
118 /* fake operand used to insert limm value into most instructions;
119    this is also used for .word handling  */
120 #define LIMMFINISH (SHIMMFINISH + 1)
121   { 'L', 32, 32, ARC_OPERAND_ADDRESS + ARC_OPERAND_LIMM + ARC_OPERAND_FAKE, insert_limmfinish, 0 },
122
123 /* shimm operand when there is no reg indicator (ld,st) */
124 #define SHIMMOFFSET (LIMMFINISH + 1)
125   { 'd', 9, 0, ARC_OPERAND_SIGNED, insert_shimmoffset, 0 },
126
127 /* 0 shimm operand for ld,st insns */
128 #define SHIMMZERO (SHIMMOFFSET + 1)
129   { '0', 9, 0, ARC_OPERAND_FAKE, insert_shimmzero, 0 },
130
131 /* flag update bit (insertion is defered until we know how) */
132 #define FLAG (SHIMMZERO + 1)
133   { 'f', 1, 8, ARC_OPERAND_SUFFIX, insert_flag, extract_flag },
134
135 /* fake utility operand to finish 'f' suffix handling */
136 #define FLAGFINISH (FLAG + 1)
137   { 'F', 1, 8, ARC_OPERAND_FAKE, insert_flagfinish, 0 },
138
139 /* fake utility operand to set the 'f' flag for the "flag" insn */
140 #define FLAGINSN (FLAGFINISH + 1)
141   { 'G', 1, 8, ARC_OPERAND_FAKE, insert_flag, 0 },
142
143 /* branch delay types */
144 #define DELAY (FLAGINSN + 1)
145   { 'n', 2, 5, ARC_OPERAND_SUFFIX },
146
147 /* conditions */
148 #define COND (DELAY + 1)
149   { 'q', 5, 0, ARC_OPERAND_SUFFIX, insert_cond, extract_cond },
150
151 /* set `cond_p' to 1 to ensure a constant is treated as a limm */
152 #define FORCELIMM (COND + 1)
153   { 'Q', 0, 0, ARC_OPERAND_FAKE, insert_forcelimm },
154
155 /* branch address; b, bl, and lp insns */
156 #define BRANCH (FORCELIMM + 1)
157   { 'B', 20, 7, ARC_OPERAND_RELATIVE_BRANCH + ARC_OPERAND_SIGNED, insert_reladdr, extract_reladdr },
158
159 /* jump address; j insn (this is basically the same as 'L' except that the
160    value is right shifted by 2); this is also used for .word handling */
161 #define JUMP (BRANCH + 1)
162   { 'J', 24, 32, ARC_OPERAND_ABSOLUTE_BRANCH + ARC_OPERAND_LIMM + ARC_OPERAND_FAKE, insert_absaddr },
163
164 /* size field, stored in bit 1,2 */
165 #define SIZE1 (JUMP + 1)
166   { 'z', 2, 1, ARC_OPERAND_SUFFIX },
167
168 /* size field, stored in bit 10,11 */
169 #define SIZE10 (SIZE1 + 1)
170   { 'Z', 2, 10, ARC_OPERAND_SUFFIX, },
171
172 /* size field, stored in bit 22,23 */
173 #define SIZE22 (SIZE10 + 1)
174   { 'y', 2, 22, ARC_OPERAND_SUFFIX, },
175
176 /* sign extend field, stored in bit 0 */
177 #define SIGN0 (SIZE22 + 1)
178   { 'x', 1, 0, ARC_OPERAND_SUFFIX },
179
180 /* sign extend field, stored in bit 9 */
181 #define SIGN9 (SIGN0 + 1)
182   { 'X', 1, 9, ARC_OPERAND_SUFFIX },
183
184 /* address write back, stored in bit 3 */
185 #define ADDRESS3 (SIGN9 + 1)
186   { 'w', 1, 3, ARC_OPERAND_SUFFIX },
187
188 /* address write back, stored in bit 12 */
189 #define ADDRESS12 (ADDRESS3 + 1)
190   { 'W', 1, 12, ARC_OPERAND_SUFFIX },
191
192 /* address write back, stored in bit 24 */
193 #define ADDRESS24 (ADDRESS12 + 1)
194   { 'v', 1, 24, ARC_OPERAND_SUFFIX },
195
196 /* cache bypass, stored in bit 5 */
197 #define CACHEBYPASS5 (ADDRESS24 + 1)
198   { 'e', 1, 5, ARC_OPERAND_SUFFIX },
199
200 /* cache bypass, stored in bit 14 */
201 #define CACHEBYPASS14 (CACHEBYPASS5 + 1)
202   { 'E', 1, 14, ARC_OPERAND_SUFFIX },
203
204 /* cache bypass, stored in bit 26 */
205 #define CACHEBYPASS26 (CACHEBYPASS14 + 1)
206   { 'D', 1, 26, ARC_OPERAND_SUFFIX },
207
208 /* unsigned multiply */
209 #define UNSIGNED (CACHEBYPASS26 + 1)
210   { 'u', 1, 27, ARC_OPERAND_SUFFIX },
211
212 /* unsigned multiply */
213 #define SATURATION (UNSIGNED + 1)
214   { 's', 1, 28, ARC_OPERAND_SUFFIX },
215
216 /* unop macro, used to copy REGB to REGC */
217 #define UNOPMACRO (SATURATION + 1)
218   { 'U', 6, ARC_SHIFT_REGC, ARC_OPERAND_FAKE, insert_unopmacro, extract_unopmacro },
219
220 /* '.' modifier ('.' required).  */
221 #define MODDOT (UNOPMACRO + 1)
222   { '.', 1, 0, ARC_MOD_DOT },
223
224 /* Dummy 'r' modifier for the register table.
225    It's called a "dummy" because there's no point in inserting an 'r' into all
226    the %a/%b/%c occurrences in the insn table.  */
227 #define REG (MODDOT + 1)
228   { 'r', 6, 0, ARC_MOD_REG },
229
230 /* Known auxiliary register modifier (stored in shimm field).  */
231 #define AUXREG (REG + 1)
232   { 'A', 9, 0, ARC_MOD_AUXREG },
233
234 /* end of list place holder */
235   { 0 }
236 };
237 \f
238 /* Given a format letter, yields the index into `arc_operands'.
239    eg: arc_operand_map['a'] = REGA.  */
240 unsigned char arc_operand_map[256];
241
242 #define I(x) (((x) & 31) << 27)
243 #define A(x) (((x) & ARC_MASK_REG) << ARC_SHIFT_REGA)
244 #define B(x) (((x) & ARC_MASK_REG) << ARC_SHIFT_REGB)
245 #define C(x) (((x) & ARC_MASK_REG) << ARC_SHIFT_REGC)
246 #define R(x,b,m) (((x) & (m)) << (b))   /* value X, mask M, at bit B */
247
248 /* ARC instructions (sorted by at least the first letter, and equivalent
249    opcodes kept together).
250
251    By recording the insns this way, the table is not hashable on the opcode.
252    That's not a real loss though as there are only a few entries for each
253    insn (ld/st being the exception), which are quickly found and since
254    they're stored together (eg: all `ld' variants are together) very little
255    time is spent on the opcode itself.  The slow part is parsing the options,
256    but that's always going to be slow.
257
258    Longer versions of insns must appear before shorter ones (if gas sees
259    "lsr r2,r3,1" when it's parsing "lsr %a,%b" it will think the ",1" is
260    junk).
261
262    This table is best viewed on a wide screen (161 columns).
263    I'd prefer to keep it this way.  */
264
265 /* ??? This table also includes macros: asl, lsl, and mov.  The ppc port has
266    a more general facility for dealing with macros which could be used if
267    we need to.  */
268 /* ??? As an experiment, the "mov" macro appears at the start so it is
269    prefered to "and" when disassembling.  At present, the table needn't be
270    sorted, though all opcodes with the same first letter must be kept
271    together.  */
272
273 const struct arc_opcode arc_opcodes[] = {
274   { "mac%u%.s%.q%.f %a,%b,%c%F%S%L",    I(-4),          I(24),          ARC_MACH_AUDIO },
275   /* Note that "mov" is really an "and".  */
276   { "mov%.q%.f %a,%b%F%S%L%U",          I(-1),          I(12) },
277   { "mul%u%.q%.f %a,%b,%c%F%S%L",       I(-2),          I(28),          ARC_MACH_AUDIO },
278   /* ??? This insn allows an optional "0," preceding the args.  */
279   /* We can't use %u here because it's not a suffix (the "64" is in the way).  */
280   { "mul64%.q%.f %b,%c%F%S%L",          I(-1)+A(-1),    I(20)+A(-1),    ARC_MACH_HOST+ARC_MACH_GRAPHICS },
281   { "mulu64%.q%.f %b,%c%F%S%L",         I(-1)+A(-1),    I(21)+A(-1),    ARC_MACH_HOST+ARC_MACH_GRAPHICS },
282
283   { "adc%.q%.f %a,%b,%c%F%S%L",         I(-1),          I(9) },
284   { "add%.q%.f %a,%b,%c%F%S%L",         I(-1),          I(8) },
285   { "and%.q%.f %a,%b,%c%F%S%L",         I(-1),          I(12) },
286   { "asl%.q%.f %a,%b,%c%F%S%L",         I(-1),          I(16),          ARC_MACH_HOST+ARC_MACH_GRAPHICS },
287   /* Note that "asl" is really an "add".  */
288   { "asl%.q%.f %a,%b%F%S%L%U",          I(-1),          I(8) },
289   { "asr%.q%.f %a,%b,%c%F%S%L",         I(-1),          I(18),          ARC_MACH_HOST+ARC_MACH_GRAPHICS },
290   { "asr%.q%.f %a,%b%F%S%L",            I(-1)+C(-1),    I(3)+C(1) },
291   { "bic%.q%.f %a,%b,%c%F%S%L",         I(-1),          I(14) },
292   { "b%q%.n %B",                        I(-1),          I(4) },
293   { "bl%q%.n %B",                       I(-1),          I(5) },
294   { "extb%.q%.f %a,%b%F%S%L",           I(-1)+C(-1),    I(3)+C(7) },
295   { "extw%.q%.f %a,%b%F%S%L",           I(-1)+C(-1),    I(3)+C(8) },
296   { "flag%.q %b%G%S%L",                 I(-1)+A(-1)+C(-1),              I(3)+A(ARC_REG_SHIMM_UPDATE)+C(0) },
297   /* %Q: force cond_p=1 --> no shimm values */
298   /* ??? This insn allows an optional flags spec.  */
299   { "j%q%Q%.n%.f %b%J",                 I(-1)+A(-1)+C(-1)+R(-1,7,1),    I(7)+A(0)+C(0)+R(0,7,1) },
300   /* Put opcode 1 ld insns first so shimm gets prefered over limm.  */
301   /* "[%b]" is before "[%b,%d]" so 0 offsets don't get printed.  */
302   { "ld%Z%.X%.W%.E %0%a,[%b]%L",        I(-1)+R(-1,13,1)+R(-1,0,511),   I(1)+R(0,13,1)+R(0,0,511) },
303   { "ld%Z%.X%.W%.E %a,[%b,%d]%S%L",     I(-1)+R(-1,13,1),               I(1)+R(0,13,1) },
304   { "ld%z%.x%.w%.e %a,[%b,%c]",         I(-1)+R(-1,4,1)+R(-1,6,7),      I(0)+R(0,4,1)+R(0,6,7) },
305   { "lp%q%.n %B",                       I(-1),          I(6), },
306   { "lr %a,[%Ab]%S%L",                  I(-1)+C(-1),    I(1)+C(0x10) },
307   /* Note that "lsl" is really an "add".  */
308   { "lsl%.q%.f %a,%b%F%S%L%U",          I(-1),          I(8) },
309   { "lsr%.q%.f %a,%b,%c%F%S%L",         I(-1),          I(17),          ARC_MACH_HOST+ARC_MACH_GRAPHICS },
310   { "lsr%.q%.f %a,%b%F%S%L",            I(-1)+C(-1),    I(3)+C(2) },
311   /* Note that "nop" is really an "xor".  */
312   { "nop",                              0xffffffff,     0x7fffffff },
313   { "or%.q%.f %a,%b,%c%F%S%L",          I(-1),          I(13) },
314   /* ??? The %a here should be %p or something.  */
315   { "padc%.q%.f %a,%b,%c%F%S%L",        I(-1),          I(25),          ARC_MACH_GRAPHICS },
316   { "padd%.q%.f %a,%b,%c%F%S%L",        I(-1),          I(24),          ARC_MACH_GRAPHICS },
317   /* Note that "pmov" is really a "pand".  */
318   { "pmov%.q%.f %a,%b%F%S%L%U",         I(-1),          I(28),          ARC_MACH_GRAPHICS },
319   { "pand%.q%.f %a,%b,%c%F%S%L",        I(-1),          I(28),          ARC_MACH_GRAPHICS },
320   { "psbc%.q%.f %a,%b,%c%F%S%L",        I(-1),          I(27),          ARC_MACH_GRAPHICS },
321   { "psub%.q%.f %a,%b,%c%F%S%L",        I(-1),          I(26),          ARC_MACH_GRAPHICS },
322   /* Note that "rlc" is really an "adc".  */
323   { "rlc%.q%.f %a,%b%F%S%L%U",          I(-1),          I(9) },
324   { "ror%.q%.f %a,%b,%c%F%S%L",         I(-1),          I(19),          ARC_MACH_HOST+ARC_MACH_GRAPHICS },
325   { "ror%.q%.f %a,%b%F%S%L",            I(-1)+C(-1),    I(3)+C(3) },
326   { "rrc%.q%.f %a,%b%F%S%L",            I(-1)+C(-1),    I(3)+C(4) },
327   { "sbc%.q%.f %a,%b,%c%F%S%L",         I(-1),          I(11) },
328   { "sexb%.q%.f %a,%b%F%S%L",           I(-1)+C(-1),    I(3)+C(5) },
329   { "sexw%.q%.f %a,%b%F%S%L",           I(-1)+C(-1),    I(3)+C(6) },
330   { "sr %c,[%Ab]%S%L",                  I(-1)+A(-1),            I(2)+A(0x10) },
331   /* "[%b]" is before "[%b,%d]" so 0 offsets don't get printed.  */
332   { "st%y%.v%.D %0%c,[%b]%L",           I(-1)+R(-1,25,3)+R(-1,21,1)+R(-1,0,511),        I(2)+R(0,25,3)+R(0,21,1)+R(0,0,511) },
333   { "st%y%.v%.D %c,[%b,%d]%S%L",        I(-1)+R(-1,25,3)+R(-1,21,1),                    I(2)+R(0,25,3)+R(0,21,1) },
334   { "sub%.q%.f %a,%b,%c%F%S%L",         I(-1),          I(10) },
335   { "swap%.q%.f %a,%b%F%S%L",           I(-1)+C(-1),    I(3)+C(9),      ARC_MACH_AUDIO },
336   { "xor%.q%.f %a,%b,%c%F%S%L",         I(-1),          I(15) }
337 };
338 const int arc_opcodes_count = sizeof (arc_opcodes) / sizeof (arc_opcodes[0]);
339
340 const struct arc_operand_value arc_reg_names[] =
341 {
342   /* Sort this so that the first 61 entries are sequential.
343      IE: For each i (i<61), arc_reg_names[i].value == i.  */
344
345   { "r0", 0, REG }, { "r1", 1, REG }, { "r2", 2, REG }, { "r3", 3, REG },
346   { "r4", 4, REG }, { "r5", 5, REG }, { "r6", 6, REG }, { "r7", 7, REG },
347   { "r8", 8, REG }, { "r9", 9, REG }, { "r10", 10, REG }, { "r11", 11, REG },
348   { "r12", 12, REG }, { "r13", 13, REG }, { "r14", 14, REG }, { "r15", 15, REG },
349   { "r16", 16, REG }, { "r17", 17, REG }, { "r18", 18, REG }, { "r19", 19, REG },
350   { "r20", 20, REG }, { "r21", 21, REG }, { "r22", 22, REG }, { "r23", 23, REG },
351   { "r24", 24, REG }, { "r25", 25, REG }, { "r26", 26, REG }, { "fp", 27, REG },
352   { "sp", 28, REG }, { "ilink1", 29, REG }, { "ilink2", 30, REG }, { "blink", 31, REG },
353   { "r32", 32, REG }, { "r33", 33, REG }, { "r34", 34, REG }, { "r35", 35, REG },
354   { "r36", 36, REG }, { "r37", 37, REG }, { "r38", 38, REG }, { "r39", 39, REG },
355   { "r40", 40, REG }, { "r41", 41, REG }, { "r42", 42, REG }, { "r43", 43, REG },
356   { "r44", 44, REG }, { "r45", 45, REG }, { "r46", 46, REG }, { "r47", 47, REG },
357   { "r48", 48, REG }, { "r49", 49, REG }, { "r50", 50, REG }, { "r51", 51, REG },
358   { "r52", 52, REG }, { "r53", 53, REG }, { "r54", 54, REG }, { "r55", 55, REG },
359   { "r56", 56, REG }, { "r57", 57, REG }, { "r58", 58, REG }, { "r59", 59, REG },
360   { "lp_count", 60, REG },
361
362   /* I'd prefer to output these as "fp" and "sp" by default, but we still need
363      to recognize the canonical values.  */
364   { "r27", 27, REG }, { "r28", 28, REG },
365
366   /* Standard auxiliary registers.  */
367   { "status",   0, AUXREG },
368   { "semaphore", 1, AUXREG },
369   { "lp_start", 2, AUXREG },
370   { "lp_end",   3, AUXREG },
371   { "identity", 4, AUXREG },
372   { "debug",    5, AUXREG },
373
374   /* Host ARC Extensions.  */
375   { "mlo",      57, REG, ARC_MACH_HOST },
376   { "mmid",     58, REG, ARC_MACH_HOST },
377   { "mhi",      59, REG, ARC_MACH_HOST },
378   { "ivic",     0x10, AUXREG, ARC_MACH_HOST },
379   { "ivdc",     0x11, AUXREG, ARC_MACH_HOST },
380   { "ivdcn",    0x12, AUXREG, ARC_MACH_HOST },
381   { "flushd",   0x13, AUXREG, ARC_MACH_HOST },
382   { "saha",     0x14, AUXREG, ARC_MACH_HOST },
383   { "gahd",     0x15, AUXREG, ARC_MACH_HOST },
384   { "aahd",     0x16, AUXREG, ARC_MACH_HOST },
385   { "rrcr",     0x17, AUXREG, ARC_MACH_HOST },
386   { "rpcr",     0x18, AUXREG, ARC_MACH_HOST },
387   { "flushdn",  0x19, AUXREG, ARC_MACH_HOST },
388   { "dbgad1",   0x1a, AUXREG, ARC_MACH_HOST },
389   { "dbgad2",   0x1b, AUXREG, ARC_MACH_HOST },
390   { "dbgmde",   0x1c, AUXREG, ARC_MACH_HOST },
391   { "dbgstat",  0x1d, AUXREG, ARC_MACH_HOST },
392   { "wag",      0x1e, AUXREG, ARC_MACH_HOST },
393   { "mulhi",    0x1f, AUXREG, ARC_MACH_HOST },
394   { "intwide",  0x20, AUXREG, ARC_MACH_HOST },
395   { "intgen",   0x21, AUXREG, ARC_MACH_HOST },
396   { "rfsh_n",   0x22, AUXREG, ARC_MACH_HOST },
397
398   /* Graphics ARC Extensions.  */
399   { "mlo",      57, REG, ARC_MACH_GRAPHICS },
400   { "mmid",     58, REG, ARC_MACH_GRAPHICS },
401   { "mhi",      59, REG, ARC_MACH_GRAPHICS },
402   { "ivic",     0x10, AUXREG, ARC_MACH_GRAPHICS },
403   { "wag",      0x1e, AUXREG, ARC_MACH_GRAPHICS },
404   { "mulhi",    0x1f, AUXREG, ARC_MACH_GRAPHICS },
405   { "intwide",  0x20, AUXREG, ARC_MACH_GRAPHICS },
406   { "intgen",   0x21, AUXREG, ARC_MACH_GRAPHICS },
407   { "pix",      0x100, AUXREG, ARC_MACH_GRAPHICS },
408   { "scratch",  0x120, AUXREG, ARC_MACH_GRAPHICS },
409
410   /* Audio ARC Extensions.  */
411   { "macmode",  39, REG, ARC_MACH_AUDIO },
412   { "rs1",      40, REG, ARC_MACH_AUDIO },
413   { "rs1n",     41, REG, ARC_MACH_AUDIO },
414   { "rs1start", 42, REG, ARC_MACH_AUDIO },
415   { "rs1size",  43, REG, ARC_MACH_AUDIO },
416   { "rs1delta", 44, REG, ARC_MACH_AUDIO },
417   { "rs1pos",   45, REG, ARC_MACH_AUDIO },
418   { "rd1",      46, REG, ARC_MACH_AUDIO },
419   { "rd1n",     47, REG, ARC_MACH_AUDIO },
420   { "rd1d",     48, REG, ARC_MACH_AUDIO },
421   { "rd1pos",   49, REG, ARC_MACH_AUDIO },
422   { "rs2",      50, REG, ARC_MACH_AUDIO },
423   { "rs2n",     51, REG, ARC_MACH_AUDIO },
424   { "rs2start", 52, REG, ARC_MACH_AUDIO },
425   { "rs2size",  53, REG, ARC_MACH_AUDIO },
426   { "rs2delta", 54, REG, ARC_MACH_AUDIO },
427   { "rs2pos",   55, REG, ARC_MACH_AUDIO },
428   { "rd2",      56, REG, ARC_MACH_AUDIO },
429   { "rd2n",     57, REG, ARC_MACH_AUDIO },
430   { "rd2d",     58, REG, ARC_MACH_AUDIO },
431   { "rd2pos",   59, REG, ARC_MACH_AUDIO },
432   { "ivic",     0x10, AUXREG, ARC_MACH_AUDIO },
433   { "wag",      0x1e, AUXREG, ARC_MACH_AUDIO },
434   { "intwide",  0x20, AUXREG, ARC_MACH_AUDIO },
435   { "intgen",   0x21, AUXREG, ARC_MACH_AUDIO },
436   { "bm_sstart", 0x30, AUXREG, ARC_MACH_AUDIO },
437   { "bm_length", 0x31, AUXREG, ARC_MACH_AUDIO },
438   { "bm_rstart", 0x32, AUXREG, ARC_MACH_AUDIO },
439   { "bm_go",    0x33, AUXREG, ARC_MACH_AUDIO },
440   { "xtp_newval", 0x40, AUXREG, ARC_MACH_AUDIO },
441   { "sram",     0x400, AUXREG, ARC_MACH_AUDIO },
442   { "reg_file", 0x800, AUXREG, ARC_MACH_AUDIO },
443 };
444 const int arc_reg_names_count = sizeof (arc_reg_names) / sizeof (arc_reg_names[0]);
445
446 /* The suffix table.
447    Operands with the same name must be stored together.  */
448
449 const struct arc_operand_value arc_suffixes[] =
450 {
451   /* Entry 0 is special, default values aren't printed by the disassembler.  */
452   { "", 0, -1 },
453   { "al", 0, COND },
454   { "ra", 0, COND },
455   { "eq", 1, COND },
456   { "z", 1, COND },
457   { "ne", 2, COND },
458   { "nz", 2, COND },
459   { "p", 3, COND },
460   { "pl", 3, COND },
461   { "n", 4, COND },
462   { "mi", 4, COND },
463   { "c", 5, COND },
464   { "cs", 5, COND },
465   { "lo", 5, COND },
466   { "nc", 6, COND },
467   { "cc", 6, COND },
468   { "hs", 6, COND },
469   { "v", 7, COND },
470   { "vs", 7, COND },
471   { "nv", 8, COND },
472   { "vc", 8, COND },
473   { "gt", 9, COND },
474   { "ge", 10, COND },
475   { "lt", 11, COND },
476   { "le", 12, COND },
477   { "hi", 13, COND },
478   { "ls", 14, COND },
479   { "pnz", 15, COND },
480   { "f", 1, FLAG },
481   { "nd", 0, DELAY },
482   { "d", 1, DELAY },
483   { "jd", 2, DELAY },
484 /*{ "b", 7, SIZEEXT },*/
485 /*{ "b", 5, SIZESEX },*/
486   { "b", 1, SIZE1 },
487   { "b", 1, SIZE10 },
488   { "b", 1, SIZE22 },
489 /*{ "w", 8, SIZEEXT },*/
490 /*{ "w", 6, SIZESEX },*/
491   { "w", 2, SIZE1 },
492   { "w", 2, SIZE10 },
493   { "w", 2, SIZE22 },
494   { "x", 1, SIGN0 },
495   { "x", 1, SIGN9 },
496   { "a", 1, ADDRESS3 },
497   { "a", 1, ADDRESS12 },
498   { "a", 1, ADDRESS24 },
499   { "di", 1, CACHEBYPASS5 },
500   { "di", 1, CACHEBYPASS14 },
501   { "di", 1, CACHEBYPASS26 },
502
503   /* Audio ARC Extensions.  */
504   /* ??? The values here are guesses.  */
505   { "ss", 16, COND, ARC_MACH_AUDIO },
506   { "sc", 17, COND, ARC_MACH_AUDIO },
507   { "mh", 18, COND, ARC_MACH_AUDIO },
508   { "ml", 19, COND, ARC_MACH_AUDIO },
509 };
510 const int arc_suffixes_count = sizeof (arc_suffixes) / sizeof (arc_suffixes[0]);
511 \f
512 /* Configuration flags.  */
513
514 /* Various ARC_HAVE_XXX bits.  */
515 static int cpu_type;
516
517 /* Translate a bfd_mach_arc_xxx value to a ARC_MACH_XXX value.  */
518
519 int
520 arc_get_opcode_mach (bfd_mach, big_p)
521      int bfd_mach, big_p;
522 {
523   static int mach_type_map[] =
524     {
525       ARC_MACH_BASE, ARC_MACH_HOST, ARC_MACH_GRAPHICS, ARC_MACH_AUDIO
526     };
527
528   return mach_type_map[bfd_mach] | (big_p ? ARC_MACH_BIG : 0);
529 }
530
531 /* Initialize any tables that need it.
532    Must be called once at start up (or when first needed).
533
534    FLAGS is a set of bits that say what version of the cpu we have,
535    and in particular at least (one of) ARC_MACH_XXX.  */
536
537 void
538 arc_opcode_init_tables (flags)
539      int flags;
540 {
541   register int i,n;
542   static int map_init_p = 0;
543
544   cpu_type = flags;
545
546   /* We may be intentionally called more than once (for example gdb will call
547      us each time the user switches cpu).  This table only needs to be init'd
548      once though.  */
549   if (!map_init_p)
550     {
551       memset (arc_operand_map, 0, sizeof (arc_operand_map));
552       n = sizeof (arc_operands) / sizeof (arc_operands[0]);
553       for (i = 0; i < n; i++)
554         arc_operand_map[arc_operands[i].fmt] = i;
555       map_init_p = 1;
556     }
557 }
558
559 /* Return non-zero if OPCODE is supported on the specified cpu.
560    Cpu selection is made when calling `arc_opcode_init_tables'.  */
561
562 int
563 arc_opcode_supported (opcode)
564      const struct arc_opcode *opcode;
565 {
566   if (ARC_OPCODE_CPU (opcode->flags) == 0)
567     return 1;
568   if (ARC_OPCODE_CPU (opcode->flags) & ARC_HAVE_CPU (cpu_type))
569     return 1;
570   return 0;
571 }
572
573 /* Return non-zero if OPVAL is supported on the specified cpu.
574    Cpu selection is made when calling `arc_opcode_init_tables'.  */
575
576 int
577 arc_opval_supported (opval)
578      const struct arc_operand_value *opval;
579 {
580   if (ARC_OPVAL_CPU (opval->flags) == 0)
581     return 1;
582   if (ARC_OPVAL_CPU (opval->flags) & ARC_HAVE_CPU (cpu_type))
583     return 1;
584   return 0;
585 }
586 \f
587 /* Nonzero if we've seen an 'f' suffix (in certain insns).  */
588 static int flag_p;
589
590 /* Nonzero if we've finished processing the 'f' suffix.  */
591 static int flagshimm_handled_p;
592
593 /* Nonzero if we've seen a 'q' suffix (condition code).  */
594 static int cond_p;
595
596 /* Nonzero if we've inserted a shimm.  */
597 static int shimm_p;
598
599 /* The value of the shimm we inserted (each insn only gets one but it can
600    appear multiple times.  */
601 static int shimm;
602
603 /* Nonzero if we've inserted a limm (during assembly) or seen a limm
604    (during disassembly).  */
605 static int limm_p;
606
607 /* The value of the limm we inserted.  Each insn only gets one but it can
608    appear multiple times.  */
609 static long limm;
610 \f
611 /* Insertion functions.  */
612
613 /* Called by the assembler before parsing an instruction.  */
614
615 void
616 arc_opcode_init_insert ()
617 {
618   flag_p = 0;
619   flagshimm_handled_p = 0;
620   cond_p = 0;
621   shimm_p = 0;
622   limm_p = 0;
623 }
624
625 /* Called by the assembler to see if the insn has a limm operand.
626    Also called by the disassembler to see if the insn contains a limm.  */
627
628 int
629 arc_opcode_limm_p (limmp)
630      long *limmp;
631 {
632   if (limmp)
633     *limmp = limm;
634   return limm_p;
635 }
636
637 /* Insert a value into a register field.
638    If REG is NULL, then this is actually a constant.
639
640    We must also handle auxiliary registers for lr/sr insns.  */
641
642 static arc_insn
643 insert_reg (insn, operand, mods, reg, value, errmsg)
644      arc_insn insn;
645      const struct arc_operand *operand;
646      int mods;
647      const struct arc_operand_value *reg;
648      long value;
649      const char **errmsg;
650 {
651   static char buf[100];
652
653   if (!reg)
654     {
655       /* We have a constant that also requires a value stored in a register
656          field.  Handle these by updating the register field and saving the
657          value for later handling by either %S (shimm) or %L (limm).  */
658
659       /* Try to use a shimm value before a limm one.  */
660       if (ARC_SHIMM_CONST_P (value)
661           /* If we've seen a conditional suffix we have to use a limm.  */
662           && !cond_p
663           /* If we already have a shimm value that is different than ours
664              we have to use a limm.  */
665           && (!shimm_p || shimm == value))
666         {
667           int marker = flag_p ? ARC_REG_SHIMM_UPDATE : ARC_REG_SHIMM;
668           flagshimm_handled_p = 1;
669           shimm_p = 1;
670           shimm = value;
671           insn |= marker << operand->shift;
672           /* insn |= value & 511; - done later */
673         }
674       /* We have to use a limm.  If we've already seen one they must match.  */
675       else if (!limm_p || limm == value)
676         {
677           limm_p = 1;
678           limm = value;
679           insn |= ARC_REG_LIMM << operand->shift;
680           /* The constant is stored later.  */
681         }
682       else
683         {
684           *errmsg = "unable to fit different valued constants into instruction";
685         }
686     }
687   else
688     {
689       /* We have to handle both normal and auxiliary registers.  */
690
691       if (reg->type == AUXREG)
692         {
693           if (!(mods & ARC_MOD_AUXREG))
694             *errmsg = "auxiliary register not allowed here";
695           else
696             {
697               insn |= ARC_REG_SHIMM << operand->shift;
698               insn |= reg->value << arc_operands[reg->type].shift;
699             }
700         }
701       else
702         {
703           /* We should never get an invalid register number here.  */
704           if ((unsigned int) reg->value > 60)
705             {
706               sprintf (buf, "invalid register number `%d'", reg->value);
707               *errmsg = buf;
708             }
709           else
710             insn |= reg->value << operand->shift;
711         }
712     }
713
714   return insn;
715 }
716
717 /* Called when we see an 'f' flag.  */
718
719 static arc_insn
720 insert_flag (insn, operand, mods, reg, value, errmsg)
721      arc_insn insn;
722      const struct arc_operand *operand;
723      int mods;
724      const struct arc_operand_value *reg;
725      long value;
726      const char **errmsg;
727 {
728   /* We can't store anything in the insn until we've parsed the registers.
729      Just record the fact that we've got this flag.  `insert_reg' will use it
730      to store the correct value (ARC_REG_SHIMM_UPDATE or bit 0x100).  */
731   flag_p = 1;
732
733   return insn;
734 }
735
736 /* Called after completely building an insn to ensure the 'f' flag gets set
737    properly.  This is needed because we don't know how to set this flag until
738    we've parsed the registers.  */
739
740 static arc_insn
741 insert_flagfinish (insn, operand, mods, reg, value, errmsg)
742      arc_insn insn;
743      const struct arc_operand *operand;
744      int mods;
745      const struct arc_operand_value *reg;
746      long value;
747      const char **errmsg;
748 {
749   if (flag_p && !flagshimm_handled_p)
750     {
751       if (shimm_p)
752         abort ();
753       flagshimm_handled_p = 1;
754       insn |= (1 << operand->shift);
755     }
756   return insn;
757 }
758
759 /* Called when we see a conditional flag (eg: .eq).  */
760
761 static arc_insn
762 insert_cond (insn, operand, mods, reg, value, errmsg)
763      arc_insn insn;
764      const struct arc_operand *operand;
765      int mods;
766      const struct arc_operand_value *reg;
767      long value;
768      const char **errmsg;
769 {
770   cond_p = 1;
771   insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
772   return insn;
773 }
774
775 /* Used in the "j" instruction to prevent constants from being interpreted as
776    shimm values (which the jump insn doesn't accept).  This can also be used
777    to force the use of limm values in other situations (eg: ld r0,[foo] uses
778    this).
779    ??? The mechanism is sound.  Access to it is a bit klunky right now.  */
780
781 static arc_insn
782 insert_forcelimm (insn, operand, mods, reg, value, errmsg)
783      arc_insn insn;
784      const struct arc_operand *operand;
785      int mods;
786      const struct arc_operand_value *reg;
787      long value;
788      const char **errmsg;
789 {
790   cond_p = 1;
791   return insn;
792 }
793
794 /* Used in ld/st insns to handle the shimm offset field.  */
795
796 static arc_insn
797 insert_shimmoffset (insn, operand, mods, reg, value, errmsg)
798      arc_insn insn;
799      const struct arc_operand *operand;
800      int mods;
801      const struct arc_operand_value *reg;
802      long value;
803      const char **errmsg;
804 {
805   insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
806   return insn;
807 }
808
809 /* Used in ld/st insns when the shimm offset is 0.  */
810
811 static arc_insn
812 insert_shimmzero (insn, operand, mods, reg, value, errmsg)
813      arc_insn insn;
814      const struct arc_operand *operand;
815      int mods;
816      const struct arc_operand_value *reg;
817      long value;
818      const char **errmsg;
819 {
820   shimm_p = 1;
821   shimm = 0;
822   return insn;
823 }
824
825 /* Called at the end of processing normal insns (eg: add) to insert a shimm
826    value (if present) into the insn.  */
827
828 static arc_insn
829 insert_shimmfinish (insn, operand, mods, reg, value, errmsg)
830      arc_insn insn;
831      const struct arc_operand *operand;
832      int mods;
833      const struct arc_operand_value *reg;
834      long value;
835      const char **errmsg;
836 {
837   if (shimm_p)
838     insn |= (shimm & ((1 << operand->bits) - 1)) << operand->shift;
839   return insn;
840 }
841
842 /* Called at the end of processing normal insns (eg: add) to insert a limm
843    value (if present) into the insn.
844
845    Note that this function is only intended to handle instructions (with 4 byte
846    immediate operands).  It is not intended to handle data.  */
847
848 /* ??? Actually, there's nothing for us to do as we can't call frag_more, the
849    caller must do that.  The extract fns take a pointer to two words.  The
850    insert fns could be converted and then we could do something useful, but
851    then the reloc handlers would have to know to work on the second word of
852    a 2 word quantity.  That's too much so we don't handle them.  */
853
854 static arc_insn
855 insert_limmfinish (insn, operand, mods, reg, value, errmsg)
856      arc_insn insn;
857      const struct arc_operand *operand;
858      int mods;
859      const struct arc_operand_value *reg;
860      long value;
861      const char **errmsg;
862 {
863   if (limm_p)
864     /* FIXME: put an abort here and see what happens.  */
865     ; /* nothing to do, gas does it */
866   return insn;
867 }
868
869 /* Called at the end of unary operand macros to copy the B field to C.  */
870
871 static arc_insn
872 insert_unopmacro (insn, operand, mods, reg, value, errmsg)
873      arc_insn insn;
874      const struct arc_operand *operand;
875      int mods;
876      const struct arc_operand_value *reg;
877      long value;
878      const char **errmsg;
879 {
880   insn |= ((insn >> ARC_SHIFT_REGB) & ARC_MASK_REG) << operand->shift;
881   return insn;
882 }
883
884 /* Insert a relative address for a branch insn (b, bl, or lp).  */
885
886 static arc_insn
887 insert_reladdr (insn, operand, mods, reg, value, errmsg)
888      arc_insn insn;
889      const struct arc_operand *operand;
890      int mods;
891      const struct arc_operand_value *reg;
892      long value;
893      const char **errmsg;
894 {
895   if (value & 3)
896     *errmsg = "branch address not on 4 byte boundary";
897   insn |= ((value >> 2) & ((1 << operand->bits) - 1)) << operand->shift;
898   return insn;
899 }
900
901 /* Insert a limm value as a 26 bit address right shifted 2 into the insn.
902
903    Note that this function is only intended to handle instructions (with 4 byte
904    immediate operands).  It is not intended to handle data.  */
905
906 /* ??? Actually, there's nothing for us to do as we can't call frag_more, the
907    caller must do that.  The extract fns take a pointer to two words.  The
908    insert fns could be converted and then we could do something useful, but
909    then the reloc handlers would have to know to work on the second word of
910    a 2 word quantity.  That's too much so we don't handle them.  */
911
912 static arc_insn
913 insert_absaddr (insn, operand, mods, reg, value, errmsg)
914      arc_insn insn;
915      const struct arc_operand *operand;
916      int mods;
917      const struct arc_operand_value *reg;
918      long value;
919      const char **errmsg;
920 {
921   if (limm_p)
922     /* FIXME: put an abort here and see what happens.  */
923     ; /* nothing to do */
924   return insn;
925 }
926 \f
927 /* Extraction functions.
928
929    The suffix extraction functions' return value is redundant since it can be
930    obtained from (*OPVAL)->value.  However, the boolean suffixes don't have
931    a suffix table entry for the "false" case, so values of zero must be
932    obtained from the return value (*OPVAL == NULL).  */
933
934 static const struct arc_operand_value *lookup_register (int type, long regno);
935
936 /* Called by the disassembler before printing an instruction.  */
937
938 void
939 arc_opcode_init_extract ()
940 {
941   flag_p = 0;
942   flagshimm_handled_p = 0;
943   shimm_p = 0;
944   limm_p = 0;
945 }
946
947 /* As we're extracting registers, keep an eye out for the 'f' indicator
948    (ARC_REG_SHIMM_UPDATE).  If we find a register (not a constant marker,
949    like ARC_REG_SHIMM), set OPVAL so our caller will know this is a register.
950
951    We must also handle auxiliary registers for lr/sr insns.  They are just
952    constants with special names.  */
953
954 static long
955 extract_reg (insn, operand, mods, opval, invalid)
956      arc_insn *insn;
957      const struct arc_operand *operand;
958      int mods;
959      const struct arc_operand_value **opval;
960      int *invalid;
961 {
962   int regno;
963   long value;
964
965   /* Get the register number.  */
966   regno = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
967
968   /* Is it a constant marker?  */
969   if (regno == ARC_REG_SHIMM)
970     {
971       value = insn[0] & 511;
972       if ((operand->flags & ARC_OPERAND_SIGNED)
973           && (value & 256))
974         value -= 512;
975       flagshimm_handled_p = 1;
976     }
977   else if (regno == ARC_REG_SHIMM_UPDATE)
978     {
979       value = insn[0] & 511;
980       if ((operand->flags & ARC_OPERAND_SIGNED)
981           && (value & 256))
982         value -= 512;
983       flag_p = 1;
984       flagshimm_handled_p = 1;
985     }
986   else if (regno == ARC_REG_LIMM)
987     {
988       value = insn[1];
989       limm_p = 1;
990     }
991   /* It's a register, set OPVAL (that's the only way we distinguish registers
992      from constants here).  */
993   else
994     {
995       const struct arc_operand_value *reg = lookup_register (REG, regno);
996
997       if (!reg)
998         abort ();
999       if (opval)
1000         *opval = reg;
1001       value = regno;
1002     }
1003
1004   /* If this field takes an auxiliary register, see if it's a known one.  */
1005   if ((mods & ARC_MOD_AUXREG)
1006       && ARC_REG_CONSTANT_P (regno))
1007     {
1008       const struct arc_operand_value *reg = lookup_register (AUXREG, value);
1009
1010       /* This is really a constant, but tell the caller it has a special
1011          name.  */
1012       if (reg && opval)
1013         *opval = reg;
1014     }
1015
1016   return value;
1017 }
1018
1019 /* Return the value of the "flag update" field for shimm insns.
1020    This value is actually stored in the register field.  */
1021
1022 static long
1023 extract_flag (insn, operand, mods, opval, invalid)
1024      arc_insn *insn;
1025      const struct arc_operand *operand;
1026      int mods;
1027      const struct arc_operand_value **opval;
1028      int *invalid;
1029 {
1030   int f;
1031   const struct arc_operand_value *val;
1032
1033   if (flagshimm_handled_p)
1034     f = flag_p != 0;
1035   else
1036     f = (insn[0] & (1 << operand->shift)) != 0;
1037
1038   /* There is no text for zero values.  */
1039   if (f == 0)
1040     return 0;
1041
1042   val = arc_opcode_lookup_suffix (operand, 1);
1043   if (opval && val)
1044     *opval = val;
1045   return val->value;
1046 }
1047
1048 /* Extract the condition code (if it exists).
1049    If we've seen a shimm value in this insn (meaning that the insn can't have
1050    a condition code field), then we don't store anything in OPVAL and return
1051    zero.  */
1052
1053 static long
1054 extract_cond (insn, operand, mods, opval, invalid)
1055      arc_insn *insn;
1056      const struct arc_operand *operand;
1057      int mods;
1058      const struct arc_operand_value **opval;
1059      int *invalid;
1060 {
1061   long cond;
1062   const struct arc_operand_value *val;
1063
1064   if (flagshimm_handled_p)
1065     return 0;
1066
1067   cond = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
1068   val = arc_opcode_lookup_suffix (operand, cond);
1069
1070   /* Ignore NULL values of `val'.  Several condition code values are
1071      reserved for extensions.  */
1072   if (opval && val)
1073     *opval = val;
1074   return cond;
1075 }
1076
1077 /* Extract a branch address.
1078    We return the value as a real address (not right shifted by 2).  */
1079
1080 static long
1081 extract_reladdr (insn, operand, mods, opval, invalid)
1082      arc_insn *insn;
1083      const struct arc_operand *operand;
1084      int mods;
1085      const struct arc_operand_value **opval;
1086      int *invalid;
1087 {
1088   long addr;
1089
1090   addr = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
1091   if ((operand->flags & ARC_OPERAND_SIGNED)
1092       && (addr & (1 << (operand->bits - 1))))
1093     addr -= 1 << operand->bits;
1094
1095   return addr << 2;
1096 }
1097
1098 /* The only thing this does is set the `invalid' flag if B != C.
1099    This is needed because the "mov" macro appears before it's real insn "and"
1100    and we don't want the disassembler to confuse them.  */
1101
1102 static long
1103 extract_unopmacro (insn, operand, mods, opval, invalid)
1104      arc_insn *insn;
1105      const struct arc_operand *operand;
1106      int mods;
1107      const struct arc_operand_value **opval;
1108      int *invalid;
1109 {
1110   /* ??? This misses the case where B == ARC_REG_SHIMM_UPDATE &&
1111      C == ARC_REG_SHIMM (or vice versa).  No big deal.  Those insns will get
1112      printed as "and"s.  */
1113   if (((insn[0] >> ARC_SHIFT_REGB) & ARC_MASK_REG)
1114       != ((insn[0] >> ARC_SHIFT_REGC) & ARC_MASK_REG))
1115     if (invalid)
1116       *invalid = 1;
1117
1118   return 0;
1119 }
1120
1121 /* Utility for the extraction functions to return the index into
1122    `arc_suffixes'.  */
1123
1124 const struct arc_operand_value *
1125 arc_opcode_lookup_suffix (type, value)
1126      const struct arc_operand *type;
1127      int value;
1128 {
1129   register const struct arc_operand_value *v,*end;
1130
1131   /* ??? This is a little slow and can be speeded up.  */
1132
1133   for (v = arc_suffixes, end = arc_suffixes + arc_suffixes_count; v < end; ++v)
1134     if (type == &arc_operands[v->type]
1135         && value == v->value)
1136       return v;
1137   return 0;
1138 }
1139
1140 static const struct arc_operand_value *
1141 lookup_register (type, regno)
1142      int type;
1143      long regno;
1144 {
1145   register const struct arc_operand_value *r,*end;
1146
1147   if (type == REG)
1148     return &arc_reg_names[regno];
1149
1150   /* ??? This is a little slow and can be speeded up.  */
1151
1152   for (r = arc_reg_names, end = arc_reg_names + arc_reg_names_count;
1153        r < end; ++r)
1154     if (type == r->type && regno == r->value)
1155       return r;
1156   return 0;
1157 }