1 /* Opcode table for the ARC.
2 Copyright 1994 Free Software Foundation, Inc.
3 Contributed by Doug Evans (dje@cygnus.com).
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)
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.
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. */
20 #include "opcode/arc.h"
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, \
26 #define EXTRACT_FN(fn) \
27 static long fn PARAMS ((arc_insn *, const struct arc_operand *, \
28 int, const struct arc_operand_value **, int *))
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_unopmacro
);
41 INSERT_FN (insert_multshift
);
43 EXTRACT_FN (extract_reg
);
44 EXTRACT_FN (extract_flag
);
45 EXTRACT_FN (extract_cond
);
46 EXTRACT_FN (extract_unopmacro
);
47 EXTRACT_FN (extract_multshift
);
49 /* Various types of ARC operands, including insn suffixes. */
51 /* Insn format values:
53 'a' REGA register A field
54 'b' REGB register B field
55 'c' REGC register C field
56 'S' SHIMMFINISH finish inserting a shimm value
57 'L' LIMMFINISH finish inserting a limm value
58 'd' SHIMMOFFSET shimm offset in ld,st insns
59 '0' SHIMMZERO 0 shimm value in ld,st insns
61 'F' FLAGFINISH finish inserting the F flag
62 'G' FLAGINSN insert F flag in "flag" insn
63 'n' DELAY N field (nullify field)
64 'q' COND condition code field
65 'Q' FORCELIMM set `cond_p' to 1 to ensure a constant is a limm
66 'B' BRANCH branch address
67 'z' SIZE1 size field in ld a,[b,c]
68 'Z' SIZE10 size field in ld a,[b,shimm]
69 'y' SIZE22 size field in st c,[b,shimm]
70 'x' SIGN0 sign extend field ld a,[b,c]
71 'X' SIGN9 sign extend field ld a,[b,shimm]
72 'u' ADDRESS3 update field in ld a,[b,c]
73 'v' ADDRESS12 update field in ld a,[b,shimm]
74 'w' ADDRESS24 update field in st c,[b,shimm]
75 'D' CACHEBYPASS5 direct to memory enable (cache bypass) in ld a,[b,c]
76 'e' CACHEBYPASS14 direct to memory enable (cache bypass) in ld a,[b,shimm]
77 'E' CACHEBYPASS26 direct to memory enable (cache bypass) in st c,[b,shimm]
78 'U' UNOPMACRO fake operand to copy REGB to REGC for unop macros
79 'M' MULTSHIFT fake operand to check if target has multiply/shifter
81 The following modifiers may appear between the % and char (eg: %.f):
83 '.' MODDOT '.' prefix must be present
84 'r' REG generic register value, for register table
85 'A' AUXREG auxiliary register in lr a,[b], sr c,[b]
89 CHAR BITS SHIFT FLAGS INSERT_FN EXTRACT_FN
92 const struct arc_operand arc_operands
[] =
94 /* place holder (??? not sure if needed) */
98 /* register A or shimm/limm indicator */
99 #define REGA (UNUSED + 1)
100 { 'a', 6, ARC_SHIFT_REGA
, 0, insert_reg
, extract_reg
},
102 /* register B or shimm/limm indicator */
103 #define REGB (REGA + 1)
104 { 'b', 6, ARC_SHIFT_REGB
, 0, insert_reg
, extract_reg
},
106 /* register C or shimm/limm indicator */
107 #define REGC (REGB + 1)
108 { 'c', 6, ARC_SHIFT_REGC
, 0, insert_reg
, extract_reg
},
110 /* fake operand used to insert shimm value into most instructions */
111 #define SHIMMFINISH (REGC + 1)
112 { 'S', 9, 0, ARC_OPERAND_SIGNED
+ ARC_OPERAND_FAKE
, insert_shimmfinish
, 0 },
114 /* fake operand used to insert limm value into most instructions */
115 #define LIMMFINISH (SHIMMFINISH + 1)
116 { 'L', 32, 32, ARC_OPERAND_ABSOLUTE
+ ARC_OPERAND_FAKE
, insert_limmfinish
, 0 },
118 /* shimm operand when there is no reg indicator (ld,st) */
119 #define SHIMMOFFSET (LIMMFINISH + 1)
120 { 'd', 9, 0, ARC_OPERAND_SIGNED
, insert_shimmoffset
, 0 },
122 /* 0 shimm operand for ld,st insns */
123 #define SHIMMZERO (SHIMMOFFSET + 1)
124 { '0', 9, 0, ARC_OPERAND_FAKE
, insert_shimmzero
, 0 },
126 /* flag update bit (insertion is defered until we know how) */
127 #define FLAG (SHIMMZERO + 1)
128 { 'f', 1, 8, ARC_OPERAND_SUFFIX
, insert_flag
, extract_flag
},
130 /* fake utility operand to finish 'f' suffix handling */
131 #define FLAGFINISH (FLAG + 1)
132 { 'F', 1, 8, ARC_OPERAND_FAKE
, insert_flagfinish
, 0 },
134 /* fake utility operand to set the 'f' flag for the "flag" insn */
135 #define FLAGINSN (FLAGFINISH + 1)
136 { 'G', 1, 8, ARC_OPERAND_FAKE
, insert_flag
, 0 },
138 /* branch delay types */
139 #define DELAY (FLAGINSN + 1)
140 { 'n', 2, 5, ARC_OPERAND_SUFFIX
},
143 #define COND (DELAY + 1)
144 { 'q', 5, 0, ARC_OPERAND_SUFFIX
, insert_cond
, extract_cond
},
146 /* set `cond_p' to 1 to ensure a constant is treated as a limm */
147 #define FORCELIMM (COND + 1)
148 { 'Q', 0, 0, ARC_OPERAND_FAKE
, insert_forcelimm
},
150 /* branch address b, bl, and lp insns */
151 #define BRANCH (FORCELIMM + 1)
152 { 'B', 20, 7, ARC_OPERAND_RELATIVE
+ ARC_OPERAND_SIGNED
, insert_reladdr
},
154 /* size field, stored in bit 1,2 */
155 #define SIZE1 (BRANCH + 1)
156 { 'z', 2, 1, ARC_OPERAND_SUFFIX
},
158 /* size field, stored in bit 10,11 */
159 #define SIZE10 (SIZE1 + 1)
160 { 'Z', 2, 10, ARC_OPERAND_SUFFIX
, },
162 /* size field, stored in bit 22,23 */
163 #define SIZE22 (SIZE10 + 1)
164 { 'y', 2, 22, ARC_OPERAND_SUFFIX
, },
166 /* sign extend field, stored in bit 0 */
167 #define SIGN0 (SIZE22 + 1)
168 { 'x', 1, 0, ARC_OPERAND_SUFFIX
},
170 /* sign extend field, stored in bit 9 */
171 #define SIGN9 (SIGN0 + 1)
172 { 'X', 1, 9, ARC_OPERAND_SUFFIX
},
174 /* address write back, stored in bit 3 */
175 #define ADDRESS3 (SIGN9 + 1)
176 { 'u', 1, 3, ARC_OPERAND_SUFFIX
},
178 /* address write back, stored in bit 12 */
179 #define ADDRESS12 (ADDRESS3 + 1)
180 { 'v', 1, 12, ARC_OPERAND_SUFFIX
},
182 /* address write back, stored in bit 24 */
183 #define ADDRESS24 (ADDRESS12 + 1)
184 { 'w', 1, 24, ARC_OPERAND_SUFFIX
},
186 /* address write back, stored in bit 3 */
187 #define CACHEBYPASS5 (ADDRESS24 + 1)
188 { 'D', 1, 5, ARC_OPERAND_SUFFIX
},
190 /* address write back, stored in bit 12 */
191 #define CACHEBYPASS14 (CACHEBYPASS5 + 1)
192 { 'e', 1, 14, ARC_OPERAND_SUFFIX
},
194 /* address write back, stored in bit 24 */
195 #define CACHEBYPASS26 (CACHEBYPASS14 + 1)
196 { 'E', 1, 26, ARC_OPERAND_SUFFIX
},
198 /* unop macro, used to copy REGB to REGC */
199 #define UNOPMACRO (CACHEBYPASS26 + 1)
200 { 'U', 6, ARC_SHIFT_REGC
, ARC_OPERAND_FAKE
, insert_unopmacro
, extract_unopmacro
},
202 /* multiply/shifter detector */
203 /* ??? Using ARC_OPERAND_FAKE this way is probably taking things too far. */
204 #define MULTSHIFT (UNOPMACRO + 1)
205 { 'M', 0, 0, ARC_OPERAND_FAKE
, insert_multshift
, extract_multshift
},
207 /* '.' modifier ('.' required). */
208 #define MODDOT (MULTSHIFT + 1)
209 { '.', 1, 0, ARC_MOD_DOT
},
211 /* Dummy 'r' modifier for the register table.
212 It's called a "dummy" because there's no point in inserting an 'r' into all
213 the %a/%b/%c occurrences in the insn table. */
214 #define REG (MODDOT + 1)
215 { 'r', 6, 0, ARC_MOD_REG
},
217 /* Known auxiliary register modifier (stored in shimm field). */
218 #define AUXREG (REG + 1)
219 { 'A', 9, 0, ARC_MOD_AUXREG
},
221 /* end of list place holder */
225 /* Given a format letter, yields the index into `arc_operands'.
226 eg: arc_operand_map['a'] = REGA. */
227 unsigned char arc_operand_map
[256];
229 #define I(x) (((x) & 31) << 27)
230 #define A(x) (((x) & ARC_MASK_REG) << ARC_SHIFT_REGA)
231 #define B(x) (((x) & ARC_MASK_REG) << ARC_SHIFT_REGB)
232 #define C(x) (((x) & ARC_MASK_REG) << ARC_SHIFT_REGC)
233 #define R(x,b,m) (((x) & (m)) << (b)) /* value X, mask M, at bit B */
235 /* ARC instructions (sorted by at least the first letter, and equivalent
236 opcodes kept together).
238 By recording the insns this way, the table is not hashable on the opcode.
239 That's not a real loss though as there are only a few entries for each
240 insn (ld/st being the exception), which are quickly found and since
241 they're stored together (eg: all `ld' variants are together) very little
242 time is spent on the opcode itself. The slow part is parsing the options,
243 but that's always going to be slow.
245 Longer versions of insns must appear before shorter ones (if gas sees
246 "lsr r2,r3,1" when it's parsing "lsr %a,%b" it will think the ",1" is
249 /* ??? This table also includes macros: asl, lsl, and mov. The ppc port has
250 a more general facility for dealing with macros which could be used if
252 /* ??? As an experiment, the "mov" macro appears at the start so it is
253 prefered to "and" when disassembling. At present, the table needn't be
254 sorted, though all opcodes with the same first letter must be kept
257 const struct arc_opcode arc_opcodes
[] = {
258 /* Note that "mov" is really an "and". */
259 { "mov%.q%.f %a,%b%F%S%L%U", I(-1), I(12) },
260 { "mul%M%.q%.f %a,%b,%c%F%S%L", I(-1), I(20) },
261 { "mulu%M%.q%.f %a,%b,%c%F%S%L", I(-1), I(21) },
263 { "adc%.q%.f %a,%b,%c%F%S%L", I(-1), I(9) },
264 { "add%.q%.f %a,%b,%c%F%S%L", I(-1), I(8) },
265 { "and%.q%.f %a,%b,%c%F%S%L", I(-1), I(12) },
266 { "asl%M%.q%.f %a,%b,%c%F%S%L", I(-1), I(16) },
267 /* Note that "asl" is really an "add". */
268 { "asl%.q%.f %a,%b%F%S%L%U", I(-1), I(8) },
269 { "asr%M%.q%.f %a,%b,%c%F%S%L", I(-1), I(18) },
270 { "asr%.q%.f %a,%b%F%S%L", I(-1)+C(-1), I(3)+C(1) },
271 { "bic%.q%.f %a,%b,%c%F%S%L", I(-1), I(14) },
272 { "b%q%.n %B", I(-1), I(4) },
273 { "bl%q%.n %B", I(-1), I(5) },
274 { "extb%.q%.f %a,%b%F%S%L", I(-1)+C(-1), I(3)+C(7) },
275 { "extw%.q%.f %a,%b%F%S%L", I(-1)+C(-1), I(3)+C(8) },
276 { "flag%.q %b%G%S%L", I(-1)+A(-1)+C(-1), I(3)+A(ARC_REG_SHIMM_UPDATE
)+C(0) },
277 /* %Q: force cond_p=1 --> no shimm values */
278 { "j%q%Q%.n%.f %b%L", I(-1)+A(-1)+C(-1)+R(-1,7,1), I(7)+A(0)+C(0)+R(0,7,1) },
279 /* Put opcode 1 ld insns first so shimm gets prefered over limm. */
280 /* "[%b]" is before "[%b,%d]" so 0 offsets don't get printed. */
281 { "ld%Z%.X%.v%.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) },
282 { "ld%Z%.X%.v%.e %a,[%b,%d]%S%L", I(-1)+R(-1,13,1), I(1)+R(0,13,1) },
283 { "ld%z%.x%.u%.D %a,[%b,%c]", I(-1)+R(-1,4,1)+R(-1,6,7), I(0)+R(0,4,1)+R(0,6,7) },
284 { "lp%q%.n %B", I(-1), I(6), },
285 { "lr %a,[%Ab]%S%L", I(-1)+C(-1), I(1)+C(0x10) },
286 /* Note that "lsl" is really an "add". */
287 { "lsl%.q%.f %a,%b%F%S%L%U", I(-1), I(8) },
288 { "lsr%M%.q%.f %a,%b,%c%F%S%L", I(-1), I(17) },
289 { "lsr%.q%.f %a,%b%F%S%L", I(-1)+C(-1), I(3)+C(2) },
290 /* Note that "nop" is really an "xor". */
291 { "nop", 0xffffffff, 0x7fffffff },
292 { "or%.q%.f %a,%b,%c%F%S%L", I(-1), I(13) },
293 /* Note that "rlc" is really an "adc". */
294 { "rlc%.q%.f %a,%b%F%S%L%U", I(-1), I(9) },
295 { "ror%M%.q%.f %a,%b,%c%F%S%L", I(-1), I(19) },
296 { "ror%.q%.f %a,%b%F%S%L", I(-1)+C(-1), I(3)+C(3) },
297 { "rrc%.q%.f %a,%b%F%S%L", I(-1)+C(-1), I(3)+C(4) },
298 { "sbc%.q%.f %a,%b,%c%F%S%L", I(-1), I(11) },
299 { "sexb%.q%.f %a,%b%F%S%L", I(-1)+C(-1), I(3)+C(5) },
300 { "sexw%.q%.f %a,%b%F%S%L", I(-1)+C(-1), I(3)+C(6) },
301 { "sr %c,[%Ab]%S%L", I(-1)+A(-1), I(2)+A(0x10) },
302 /* "[%b]" is before "[%b,%d]" so 0 offsets don't get printed. */
303 { "st%y%.w%.E %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) },
304 { "st%y%.w%.E %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) },
305 { "sub%.q%.f %a,%b,%c%F%S%L", I(-1), I(10) },
306 { "xor%.q%.f %a,%b,%c%F%S%L", I(-1), I(15) }
308 int arc_opcodes_count
= sizeof (arc_opcodes
) / sizeof (arc_opcodes
[0]);
310 const struct arc_operand_value arc_reg_names
[] =
312 /* Sort this so that the first 61 entries are sequential.
313 IE: For each i (i<61), arc_reg_names[i].value == i. */
315 { "r0", 0, REG
}, { "r1", 1, REG
}, { "r2", 2, REG
}, { "r3", 3, REG
},
316 { "r4", 4, REG
}, { "r5", 5, REG
}, { "r6", 6, REG
}, { "r7", 7, REG
},
317 { "r8", 8, REG
}, { "r9", 9, REG
}, { "r10", 10, REG
}, { "r11", 11, REG
},
318 { "r12", 12, REG
}, { "r13", 13, REG
}, { "r14", 14, REG
}, { "r15", 15, REG
},
319 { "r16", 16, REG
}, { "r17", 17, REG
}, { "r18", 18, REG
}, { "r19", 19, REG
},
320 { "r20", 20, REG
}, { "r21", 21, REG
}, { "r22", 22, REG
}, { "r23", 23, REG
},
321 { "r24", 24, REG
}, { "r25", 25, REG
}, { "r26", 26, REG
}, { "fp", 27, REG
},
322 { "sp", 28, REG
}, { "ilink1", 29, REG
}, { "ilink2", 30, REG
}, { "blink", 31, REG
},
323 { "r32", 32, REG
}, { "r33", 33, REG
}, { "r34", 34, REG
}, { "r35", 35, REG
},
324 { "r36", 36, REG
}, { "r37", 37, REG
}, { "r38", 38, REG
}, { "r39", 39, REG
},
325 { "r40", 40, REG
}, { "r41", 41, REG
}, { "r42", 42, REG
}, { "r43", 43, REG
},
326 { "r44", 44, REG
}, { "r45", 45, REG
}, { "r46", 46, REG
}, { "r47", 47, REG
},
327 { "r48", 48, REG
}, { "r49", 49, REG
}, { "r50", 50, REG
}, { "r51", 51, REG
},
328 { "r52", 52, REG
}, { "r53", 53, REG
}, { "r54", 54, REG
}, { "r55", 55, REG
},
329 { "r56", 56, REG
}, { "r57", 57, REG
}, { "r58", 58, REG
}, { "r59", 59, REG
},
330 { "lp_count", 60, REG
},
332 /* I'd prefer to output these as "fp" and "sp" by default, but we still need
333 to recognize the canonical values. */
334 { "r27", 27, REG
}, { "r28", 28, REG
},
336 /* Standard auxiliary registers. */
337 { "status", 0, AUXREG
},
338 { "semaphore", 1, AUXREG
},
339 { "lp_start", 2, AUXREG
},
340 { "lp_end", 3, AUXREG
},
341 { "identity", 4, AUXREG
},
342 { "debug", 5, AUXREG
},
344 int arc_reg_names_count
= sizeof (arc_reg_names
) / sizeof (arc_reg_names
[0]);
347 Operands with the same name must be stored together. */
349 const struct arc_operand_value arc_suffixes
[] =
351 /* Entry 0 is special, default values aren't printed by the disassembler. */
384 /* { "b", 7, SIZEEXT },*/
385 /* { "b", 5, SIZESEX },*/
389 /* { "w", 8, SIZEEXT },*/
390 /* { "w", 6, SIZESEX },*/
396 { "a", 1, ADDRESS3
},
397 { "a", 1, ADDRESS12
},
398 { "a", 1, ADDRESS24
},
399 { "di", 1, CACHEBYPASS5
},
400 { "di", 1, CACHEBYPASS14
},
401 { "di", 1, CACHEBYPASS26
},
403 int arc_suffixes_count
= sizeof (arc_suffixes
) / sizeof (arc_suffixes
[0]);
405 /* Configuration flags. */
407 /* Various ARC_HAVE_XXX bits. */
410 /* Initialize any tables that need it.
411 Must be called once at start up (or when first needed).
413 CPU is a set of bits that say what version of the cpu we have. */
416 arc_opcode_init_tables (cpu
)
421 memset (arc_operand_map
, 0, sizeof (arc_operand_map
));
422 n
= sizeof (arc_operands
) / sizeof (arc_operands
[0]);
423 for (i
= 0; i
< n
; i
++)
424 arc_operand_map
[arc_operands
[i
].fmt
] = i
;
429 /* Nonzero if we've seen an 'f' suffix (in certain insns). */
432 /* Nonzero if we've finished processing the 'f' suffix. */
433 static int flagshimm_handled_p
;
435 /* Nonzero if we've seen a 'q' suffix (condition code). */
438 /* Nonzero if we've inserted a shimm. */
441 /* The value of the shimm we inserted (each insn only gets one but it can
442 appear multiple times. */
445 /* Nonzero if we've inserted a limm (during assembly) or seen a limm
446 (during disassembly). */
449 /* The value of the limm we inserted. Each insn only gets one but it can
450 appear multiple times. */
453 /* Called by the assembler before parsing an instruction. */
456 arc_opcode_init_insert ()
459 flagshimm_handled_p
= 0;
465 /* Called by the assembler to see if the insn has a limm operand.
466 Also called by the disassembler to see if the insn contains a limm. */
469 arc_opcode_limm_p (limmp
)
477 /* Insert a value into a register field.
478 If REG is NULL, then this is actually a constant.
480 We must also handle auxiliary registers for lr/sr insns. */
483 insert_reg (insn
, operand
, mods
, reg
, value
, errmsg
)
485 const struct arc_operand
*operand
;
487 const struct arc_operand_value
*reg
;
491 static char buf
[100];
495 /* We have a constant that also requires a value stored in a register
496 field. Handle these by updating the register field and saving the
497 value for later handling by either %S (shimm) or %L (limm). */
499 /* Try to use a shimm value before a limm one. */
500 if (ARC_SHIMM_CONST_P (value
)
501 /* If we've seen a conditional suffix we have to use a limm. */
503 /* If we already have a shimm value that is different than ours
504 we have to use a limm. */
505 && (!shimm_p
|| shimm
== value
))
507 int marker
= flag_p
? ARC_REG_SHIMM_UPDATE
: ARC_REG_SHIMM
;
508 flagshimm_handled_p
= 1;
511 insn
|= marker
<< operand
->shift
;
512 /* insn |= value & 511; - done later */
514 /* We have to use a limm. If we've already seen one they must match. */
515 else if (!limm_p
|| limm
== value
)
519 insn
|= ARC_REG_LIMM
<< operand
->shift
;
520 /* The constant is stored later. */
524 *errmsg
= "unable to fit different valued constants into instruction";
529 /* We have to handle both normal and auxiliary registers. */
531 if (reg
->type
== AUXREG
)
533 if (!(mods
& ARC_MOD_AUXREG
))
534 *errmsg
= "auxiliary register not allowed here";
537 insn
|= ARC_REG_SHIMM
<< operand
->shift
;
538 insn
|= reg
->value
<< arc_operands
[reg
->type
].shift
;
543 /* We should never get an invalid register number here. */
544 if ((unsigned int) reg
->value
> 60)
546 sprintf (buf
, "invalid register number `%d'", reg
->value
);
550 insn
|= reg
->value
<< operand
->shift
;
557 /* Called when we see an 'f' flag. */
560 insert_flag (insn
, operand
, mods
, reg
, value
, errmsg
)
562 const struct arc_operand
*operand
;
564 const struct arc_operand_value
*reg
;
568 /* We can't store anything in the insn until we've parsed the registers.
569 Just record the fact that we've got this flag. `insert_reg' will use it
570 to store the correct value (ARC_REG_SHIMM_UPDATE or bit 0x100). */
576 /* Called after completely building an insn to ensure the 'f' flag gets set
577 properly. This is needed because we don't know how to set this flag until
578 we've parsed the registers. */
581 insert_flagfinish (insn
, operand
, mods
, reg
, value
, errmsg
)
583 const struct arc_operand
*operand
;
585 const struct arc_operand_value
*reg
;
589 if (flag_p
&& !flagshimm_handled_p
)
593 flagshimm_handled_p
= 1;
594 insn
|= (1 << operand
->shift
);
599 /* Called when we see a conditional flag (eg: .eq). */
602 insert_cond (insn
, operand
, mods
, reg
, value
, errmsg
)
604 const struct arc_operand
*operand
;
606 const struct arc_operand_value
*reg
;
611 insn
|= (value
& ((1 << operand
->bits
) - 1)) << operand
->shift
;
615 /* Used in the "j" instruction to prevent constants from being interpreted as
616 shimm values (which the jump insn doesn't accept). This can also be used
617 to force the use of limm values in other situations (eg: ld r0,[foo] uses
619 ??? The mechanism is sound. Access to it is a bit klunky right now. */
622 insert_forcelimm (insn
, operand
, mods
, reg
, value
, errmsg
)
624 const struct arc_operand
*operand
;
626 const struct arc_operand_value
*reg
;
634 /* Used in ld/st insns to handle the shimm offset field. */
637 insert_shimmoffset (insn
, operand
, mods
, reg
, value
, errmsg
)
639 const struct arc_operand
*operand
;
641 const struct arc_operand_value
*reg
;
645 insn
|= (value
& ((1 << operand
->bits
) - 1)) << operand
->shift
;
649 /* Used in ld/st insns when the shimm offset is 0. */
652 insert_shimmzero (insn
, operand
, mods
, reg
, value
, errmsg
)
654 const struct arc_operand
*operand
;
656 const struct arc_operand_value
*reg
;
665 /* Called at the end of processing normal insns (eg: add) to insert a shimm
666 value (if present) into the insn. */
669 insert_shimmfinish (insn
, operand
, mods
, reg
, value
, errmsg
)
671 const struct arc_operand
*operand
;
673 const struct arc_operand_value
*reg
;
678 insn
|= (shimm
& ((1 << operand
->bits
) - 1)) << operand
->shift
;
682 /* Called at the end of processing normal insns (eg: add) to insert a limm
683 value (if present) into the insn. Actually, there's nothing for us to do
684 as we can't call frag_more, the caller must do that. */
685 /* ??? The extract fns take a pointer to two words. The insert insns could be
686 converted and then we could do something useful. Not sure it's worth it. */
689 insert_limmfinish (insn
, operand
, mods
, reg
, value
, errmsg
)
691 const struct arc_operand
*operand
;
693 const struct arc_operand_value
*reg
;
698 ; /* nothing to do */
702 /* Called at the end of unary operand macros to copy the B field to C. */
705 insert_unopmacro (insn
, operand
, mods
, reg
, value
, errmsg
)
707 const struct arc_operand
*operand
;
709 const struct arc_operand_value
*reg
;
713 insn
|= ((insn
>> ARC_SHIFT_REGB
) & ARC_MASK_REG
) << operand
->shift
;
717 /* Insert a relative address for a branch insn (b, bl, or lp). */
720 insert_reladdr (insn
, operand
, mods
, reg
, value
, errmsg
)
722 const struct arc_operand
*operand
;
724 const struct arc_operand_value
*reg
;
728 /* FIXME: Addresses are stored * 4. Do we want to handle that here? */
729 insn
|= (value
& ((1 << operand
->bits
) - 1)) << operand
->shift
;
733 /* Fake operand to disallow the multiply and variable shift insns if the cpu
734 doesn't have them. */
737 insert_multshift (insn
, operand
, mods
, reg
, value
, errmsg
)
739 const struct arc_operand
*operand
;
741 const struct arc_operand_value
*reg
;
745 if (!(cpu_type
& ARC_HAVE_MULT_SHIFT
))
746 *errmsg
= "cpu doesn't support this insn";
750 /* Extraction functions.
752 The suffix extraction functions' return value is redundant since it can be
753 obtained from (*OPVAL)->value. However, the boolean suffixes don't have
754 a suffix table entry for the "false" case, so values of zero must be
755 obtained from the return value (*OPVAL == NULL). */
757 static const struct arc_operand_value
*lookup_register (int type
, long regno
);
759 /* Called by the disassembler before printing an instruction. */
762 arc_opcode_init_extract ()
765 flagshimm_handled_p
= 0;
770 /* As we're extracting registers, keep an eye out for the 'f' indicator
771 (ARC_REG_SHIMM_UPDATE). If we find a register (not a constant marker,
772 like ARC_REG_SHIMM), set OPVAL so our caller will know this is a register.
774 We must also handle auxiliary registers for lr/sr insns. They are just
775 constants with special names. */
778 extract_reg (insn
, operand
, mods
, opval
, invalid
)
780 const struct arc_operand
*operand
;
782 const struct arc_operand_value
**opval
;
788 /* Get the register number. */
789 regno
= (insn
[0] >> operand
->shift
) & ((1 << operand
->bits
) - 1);
791 /* Is it a constant marker? */
792 if (regno
== ARC_REG_SHIMM
)
794 value
= insn
[0] & 511;
795 if ((operand
->flags
& ARC_OPERAND_SIGNED
)
798 flagshimm_handled_p
= 1;
800 else if (regno
== ARC_REG_SHIMM_UPDATE
)
802 value
= insn
[0] & 511;
803 if ((operand
->flags
& ARC_OPERAND_SIGNED
)
807 flagshimm_handled_p
= 1;
809 else if (regno
== ARC_REG_LIMM
)
814 /* It's a register, set OPVAL (that's the only way we distinguish registers
815 from constants here). */
818 const struct arc_operand_value
*reg
= lookup_register (REG
, regno
);
827 /* If this field takes an auxiliary register, see if it's a known one. */
828 if ((mods
& ARC_MOD_AUXREG
)
829 && ARC_REG_CONSTANT_P (regno
))
831 const struct arc_operand_value
*reg
= lookup_register (AUXREG
, value
);
833 /* This is really a constant, but tell the caller it has a special
842 /* Return the value of the "flag update" field for shimm insns.
843 This value is actually stored in the register field. */
846 extract_flag (insn
, operand
, mods
, opval
, invalid
)
848 const struct arc_operand
*operand
;
850 const struct arc_operand_value
**opval
;
854 const struct arc_operand_value
*val
;
856 if (flagshimm_handled_p
)
859 f
= (insn
[0] & (1 << operand
->shift
)) != 0;
861 /* There is no text for zero values. */
865 val
= arc_opcode_lookup_suffix (operand
, 1);
871 /* Extract the condition code (if it exists).
872 If we've seen a shimm value in this insn (meaning that the insn can't have
873 a condition code field), then we don't store anything in OPVAL and return
877 extract_cond (insn
, operand
, mods
, opval
, invalid
)
879 const struct arc_operand
*operand
;
881 const struct arc_operand_value
**opval
;
885 const struct arc_operand_value
*val
;
887 if (flagshimm_handled_p
)
890 cond
= (insn
[0] >> operand
->shift
) & ((1 << operand
->bits
) - 1);
891 val
= arc_opcode_lookup_suffix (operand
, cond
);
893 /* Ignore NULL values of `val'. Several condition code values aren't
900 /* The only thing this does is set the `invalid' flag if B != C.
901 This is needed because the "mov" macro appears before it's real insn "and"
902 and we don't want the disassembler to confuse them. */
905 extract_unopmacro (insn
, operand
, mods
, opval
, invalid
)
907 const struct arc_operand
*operand
;
909 const struct arc_operand_value
**opval
;
912 /* ??? This misses the case where B == ARC_REG_SHIMM_UPDATE &&
913 C == ARC_REG_SHIMM (or vice versa). No big deal. Those insns will get
914 printed as "and"s. */
915 if (((insn
[0] >> ARC_SHIFT_REGB
) & ARC_MASK_REG
)
916 != ((insn
[0] >> ARC_SHIFT_REGC
) & ARC_MASK_REG
))
923 /* Don't recognize the multiply and variable shift insns if the cpu doesn't
926 ??? Actually, we probably should anyway. */
929 extract_multshift (insn
, operand
, mods
, opval
, invalid
)
931 const struct arc_operand
*operand
;
933 const struct arc_operand_value
**opval
;
939 /* Utility for the extraction functions to return the index into
942 const struct arc_operand_value
*
943 arc_opcode_lookup_suffix (type
, value
)
944 const struct arc_operand
*type
;
947 register const struct arc_operand_value
*v
,*end
;
949 /* ??? This is a little slow and can be speeded up. */
951 for (v
= arc_suffixes
, end
= arc_suffixes
+ arc_suffixes_count
; v
< end
; ++v
)
952 if (type
== &arc_operands
[v
->type
]
953 && value
== v
->value
)
958 static const struct arc_operand_value
*
959 lookup_register (type
, regno
)
963 register const struct arc_operand_value
*r
,*end
;
966 return &arc_reg_names
[regno
];
968 /* ??? This is a little slow and can be speeded up. */
970 for (r
= arc_reg_names
, end
= arc_reg_names
+ arc_reg_names_count
;
972 if (type
== r
->type
&& regno
== r
->value
)