1
/* Opcode table for the ARC.
2
Copyright 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2004, 2005, 2007
3
Free Software Foundation, Inc.
4
Contributed by Doug Evans (dje@cygnus.com).
6
This file is part of libopcodes.
8
This library is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3, or (at your option)
13
It is distributed in the hope that it will be useful, but WITHOUT
14
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16
License for more details.
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software Foundation,
20
Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
26
#include "opcode/arc.h"
29
enum operand {OP_NONE,OP_REG,OP_SHIMM,OP_LIMM};
33
enum operand ls_operand[OPERANDS];
35
struct arc_opcode *arc_ext_opcodes;
36
struct arc_ext_operand_value *arc_ext_operands;
43
/* Given a format letter, yields the index into `arc_operands'.
44
eg: arc_operand_map['a'] = REGA. */
45
unsigned char arc_operand_map[256];
47
/* Nonzero if we've seen an 'f' suffix (in certain insns). */
50
/* Nonzero if we've finished processing the 'f' suffix. */
51
static int flagshimm_handled_p;
53
/* Nonzero if we've seen a 'a' suffix (address writeback). */
56
/* Nonzero if we've seen a 'q' suffix (condition code). */
59
/* Nonzero if we've inserted a nullify condition. */
62
/* The value of the a nullify condition we inserted. */
65
/* Nonzero if we've inserted jumpflags. */
66
static int jumpflags_p;
68
/* Nonzero if we've inserted a shimm. */
71
/* The value of the shimm we inserted (each insn only gets one but it can
72
appear multiple times). */
75
/* Nonzero if we've inserted a limm (during assembly) or seen a limm
76
(during disassembly). */
79
/* The value of the limm we inserted. Each insn only gets one but it can
80
appear multiple times. */
83
#define INSERT_FN(fn) \
84
static arc_insn fn (arc_insn, const struct arc_operand *, \
85
int, const struct arc_operand_value *, long, \
88
#define EXTRACT_FN(fn) \
89
static long fn (arc_insn *, const struct arc_operand *, \
90
int, const struct arc_operand_value **, int *)
92
INSERT_FN (insert_reg);
93
INSERT_FN (insert_shimmfinish);
94
INSERT_FN (insert_limmfinish);
95
INSERT_FN (insert_offset);
96
INSERT_FN (insert_base);
97
INSERT_FN (insert_st_syntax);
98
INSERT_FN (insert_ld_syntax);
99
INSERT_FN (insert_addr_wb);
100
INSERT_FN (insert_flag);
101
INSERT_FN (insert_nullify);
102
INSERT_FN (insert_flagfinish);
103
INSERT_FN (insert_cond);
104
INSERT_FN (insert_forcelimm);
105
INSERT_FN (insert_reladdr);
106
INSERT_FN (insert_absaddr);
107
INSERT_FN (insert_jumpflags);
108
INSERT_FN (insert_unopmacro);
110
EXTRACT_FN (extract_reg);
111
EXTRACT_FN (extract_ld_offset);
112
EXTRACT_FN (extract_ld_syntax);
113
EXTRACT_FN (extract_st_offset);
114
EXTRACT_FN (extract_st_syntax);
115
EXTRACT_FN (extract_flag);
116
EXTRACT_FN (extract_cond);
117
EXTRACT_FN (extract_reladdr);
118
EXTRACT_FN (extract_jumpflags);
119
EXTRACT_FN (extract_unopmacro);
121
/* Various types of ARC operands, including insn suffixes. */
123
/* Insn format values:
125
'a' REGA register A field
126
'b' REGB register B field
127
'c' REGC register C field
128
'S' SHIMMFINISH finish inserting a shimm value
129
'L' LIMMFINISH finish inserting a limm value
130
'o' OFFSET offset in st insns
131
'O' OFFSET offset in ld insns
132
'0' SYNTAX_ST_NE enforce store insn syntax, no errors
133
'1' SYNTAX_LD_NE enforce load insn syntax, no errors
134
'2' SYNTAX_ST enforce store insn syntax, errors, last pattern only
135
'3' SYNTAX_LD enforce load insn syntax, errors, last pattern only
136
's' BASE base in st insn
138
'F' FLAGFINISH finish inserting the F flag
139
'G' FLAGINSN insert F flag in "flag" insn
140
'n' DELAY N field (nullify field)
141
'q' COND condition code field
142
'Q' FORCELIMM set `cond_p' to 1 to ensure a constant is a limm
143
'B' BRANCH branch address (22 bit pc relative)
144
'J' JUMP jump address (26 bit absolute)
145
'j' JUMPFLAGS optional high order bits of 'J'
146
'z' SIZE1 size field in ld a,[b,c]
147
'Z' SIZE10 size field in ld a,[b,shimm]
148
'y' SIZE22 size field in st c,[b,shimm]
149
'x' SIGN0 sign extend field ld a,[b,c]
150
'X' SIGN9 sign extend field ld a,[b,shimm]
151
'w' ADDRESS3 write-back field in ld a,[b,c]
152
'W' ADDRESS12 write-back field in ld a,[b,shimm]
153
'v' ADDRESS24 write-back field in st c,[b,shimm]
154
'e' CACHEBYPASS5 cache bypass in ld a,[b,c]
155
'E' CACHEBYPASS14 cache bypass in ld a,[b,shimm]
156
'D' CACHEBYPASS26 cache bypass in st c,[b,shimm]
157
'U' UNOPMACRO fake operand to copy REGB to REGC for unop macros
159
The following modifiers may appear between the % and char (eg: %.f):
161
'.' MODDOT '.' prefix must be present
162
'r' REG generic register value, for register table
163
'A' AUXREG auxiliary register in lr a,[b], sr c,[b]
167
CHAR BITS SHIFT FLAGS INSERT_FN EXTRACT_FN */
169
const struct arc_operand arc_operands[] =
171
/* Place holder (??? not sure if needed). */
173
{ 0, 0, 0, 0, 0, 0 },
175
/* Register A or shimm/limm indicator. */
176
#define REGA (UNUSED + 1)
177
{ 'a', 6, ARC_SHIFT_REGA, ARC_OPERAND_SIGNED | ARC_OPERAND_ERROR, insert_reg, extract_reg },
179
/* Register B or shimm/limm indicator. */
180
#define REGB (REGA + 1)
181
{ 'b', 6, ARC_SHIFT_REGB, ARC_OPERAND_SIGNED | ARC_OPERAND_ERROR, insert_reg, extract_reg },
183
/* Register C or shimm/limm indicator. */
184
#define REGC (REGB + 1)
185
{ 'c', 6, ARC_SHIFT_REGC, ARC_OPERAND_SIGNED | ARC_OPERAND_ERROR, insert_reg, extract_reg },
187
/* Fake operand used to insert shimm value into most instructions. */
188
#define SHIMMFINISH (REGC + 1)
189
{ 'S', 9, 0, ARC_OPERAND_SIGNED + ARC_OPERAND_FAKE, insert_shimmfinish, 0 },
191
/* Fake operand used to insert limm value into most instructions. */
192
#define LIMMFINISH (SHIMMFINISH + 1)
193
{ 'L', 32, 32, ARC_OPERAND_ADDRESS + ARC_OPERAND_LIMM + ARC_OPERAND_FAKE, insert_limmfinish, 0 },
195
/* Shimm operand when there is no reg indicator (st). */
196
#define ST_OFFSET (LIMMFINISH + 1)
197
{ 'o', 9, 0, ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED | ARC_OPERAND_STORE, insert_offset, extract_st_offset },
199
/* Shimm operand when there is no reg indicator (ld). */
200
#define LD_OFFSET (ST_OFFSET + 1)
201
{ 'O', 9, 0,ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED | ARC_OPERAND_LOAD, insert_offset, extract_ld_offset },
203
/* Operand for base. */
204
#define BASE (LD_OFFSET + 1)
205
{ 's', 6, ARC_SHIFT_REGB, ARC_OPERAND_LIMM | ARC_OPERAND_SIGNED, insert_base, extract_reg},
207
/* 0 enforce syntax for st insns. */
208
#define SYNTAX_ST_NE (BASE + 1)
209
{ '0', 9, 0, ARC_OPERAND_FAKE, insert_st_syntax, extract_st_syntax },
211
/* 1 enforce syntax for ld insns. */
212
#define SYNTAX_LD_NE (SYNTAX_ST_NE + 1)
213
{ '1', 9, 0, ARC_OPERAND_FAKE, insert_ld_syntax, extract_ld_syntax },
215
/* 0 enforce syntax for st insns. */
216
#define SYNTAX_ST (SYNTAX_LD_NE + 1)
217
{ '2', 9, 0, ARC_OPERAND_FAKE | ARC_OPERAND_ERROR, insert_st_syntax, extract_st_syntax },
219
/* 0 enforce syntax for ld insns. */
220
#define SYNTAX_LD (SYNTAX_ST + 1)
221
{ '3', 9, 0, ARC_OPERAND_FAKE | ARC_OPERAND_ERROR, insert_ld_syntax, extract_ld_syntax },
223
/* Flag update bit (insertion is defered until we know how). */
224
#define FLAG (SYNTAX_LD + 1)
225
{ 'f', 1, 8, ARC_OPERAND_SUFFIX, insert_flag, extract_flag },
227
/* Fake utility operand to finish 'f' suffix handling. */
228
#define FLAGFINISH (FLAG + 1)
229
{ 'F', 1, 8, ARC_OPERAND_FAKE, insert_flagfinish, 0 },
231
/* Fake utility operand to set the 'f' flag for the "flag" insn. */
232
#define FLAGINSN (FLAGFINISH + 1)
233
{ 'G', 1, 8, ARC_OPERAND_FAKE, insert_flag, 0 },
235
/* Branch delay types. */
236
#define DELAY (FLAGINSN + 1)
237
{ 'n', 2, 5, ARC_OPERAND_SUFFIX , insert_nullify, 0 },
240
#define COND (DELAY + 1)
241
{ 'q', 5, 0, ARC_OPERAND_SUFFIX, insert_cond, extract_cond },
243
/* Set `cond_p' to 1 to ensure a constant is treated as a limm. */
244
#define FORCELIMM (COND + 1)
245
{ 'Q', 0, 0, ARC_OPERAND_FAKE, insert_forcelimm, 0 },
247
/* Branch address; b, bl, and lp insns. */
248
#define BRANCH (FORCELIMM + 1)
249
{ 'B', 20, 7, (ARC_OPERAND_RELATIVE_BRANCH + ARC_OPERAND_SIGNED) | ARC_OPERAND_ERROR, insert_reladdr, extract_reladdr },
251
/* Jump address; j insn (this is basically the same as 'L' except that the
252
value is right shifted by 2). */
253
#define JUMP (BRANCH + 1)
254
{ 'J', 24, 32, ARC_OPERAND_ERROR | (ARC_OPERAND_ABSOLUTE_BRANCH + ARC_OPERAND_LIMM + ARC_OPERAND_FAKE), insert_absaddr, 0 },
256
/* Jump flags; j{,l} insn value or'ed into 'J' addr for flag values. */
257
#define JUMPFLAGS (JUMP + 1)
258
{ 'j', 6, 26, ARC_OPERAND_JUMPFLAGS | ARC_OPERAND_ERROR, insert_jumpflags, extract_jumpflags },
260
/* Size field, stored in bit 1,2. */
261
#define SIZE1 (JUMPFLAGS + 1)
262
{ 'z', 2, 1, ARC_OPERAND_SUFFIX, 0, 0 },
264
/* Size field, stored in bit 10,11. */
265
#define SIZE10 (SIZE1 + 1)
266
{ 'Z', 2, 10, ARC_OPERAND_SUFFIX, 0, 0 },
268
/* Size field, stored in bit 22,23. */
269
#define SIZE22 (SIZE10 + 1)
270
{ 'y', 2, 22, ARC_OPERAND_SUFFIX, 0, 0 },
272
/* Sign extend field, stored in bit 0. */
273
#define SIGN0 (SIZE22 + 1)
274
{ 'x', 1, 0, ARC_OPERAND_SUFFIX, 0, 0 },
276
/* Sign extend field, stored in bit 9. */
277
#define SIGN9 (SIGN0 + 1)
278
{ 'X', 1, 9, ARC_OPERAND_SUFFIX, 0, 0 },
280
/* Address write back, stored in bit 3. */
281
#define ADDRESS3 (SIGN9 + 1)
282
{ 'w', 1, 3, ARC_OPERAND_SUFFIX, insert_addr_wb, 0},
284
/* Address write back, stored in bit 12. */
285
#define ADDRESS12 (ADDRESS3 + 1)
286
{ 'W', 1, 12, ARC_OPERAND_SUFFIX, insert_addr_wb, 0},
288
/* Address write back, stored in bit 24. */
289
#define ADDRESS24 (ADDRESS12 + 1)
290
{ 'v', 1, 24, ARC_OPERAND_SUFFIX, insert_addr_wb, 0},
292
/* Cache bypass, stored in bit 5. */
293
#define CACHEBYPASS5 (ADDRESS24 + 1)
294
{ 'e', 1, 5, ARC_OPERAND_SUFFIX, 0, 0 },
296
/* Cache bypass, stored in bit 14. */
297
#define CACHEBYPASS14 (CACHEBYPASS5 + 1)
298
{ 'E', 1, 14, ARC_OPERAND_SUFFIX, 0, 0 },
300
/* Cache bypass, stored in bit 26. */
301
#define CACHEBYPASS26 (CACHEBYPASS14 + 1)
302
{ 'D', 1, 26, ARC_OPERAND_SUFFIX, 0, 0 },
304
/* Unop macro, used to copy REGB to REGC. */
305
#define UNOPMACRO (CACHEBYPASS26 + 1)
306
{ 'U', 6, ARC_SHIFT_REGC, ARC_OPERAND_FAKE, insert_unopmacro, extract_unopmacro },
308
/* '.' modifier ('.' required). */
309
#define MODDOT (UNOPMACRO + 1)
310
{ '.', 1, 0, ARC_MOD_DOT, 0, 0 },
312
/* Dummy 'r' modifier for the register table.
313
It's called a "dummy" because there's no point in inserting an 'r' into all
314
the %a/%b/%c occurrences in the insn table. */
315
#define REG (MODDOT + 1)
316
{ 'r', 6, 0, ARC_MOD_REG, 0, 0 },
318
/* Known auxiliary register modifier (stored in shimm field). */
319
#define AUXREG (REG + 1)
320
{ 'A', 9, 0, ARC_MOD_AUXREG, 0, 0 },
322
/* End of list place holder. */
326
/* Insert a value into a register field.
327
If REG is NULL, then this is actually a constant.
329
We must also handle auxiliary registers for lr/sr insns. */
332
insert_reg (arc_insn insn,
333
const struct arc_operand *operand,
335
const struct arc_operand_value *reg,
339
static char buf[100];
340
enum operand op_type = OP_NONE;
344
/* We have a constant that also requires a value stored in a register
345
field. Handle these by updating the register field and saving the
346
value for later handling by either %S (shimm) or %L (limm). */
348
/* Try to use a shimm value before a limm one. */
349
if (ARC_SHIMM_CONST_P (value)
350
/* If we've seen a conditional suffix we have to use a limm. */
352
/* If we already have a shimm value that is different than ours
353
we have to use a limm. */
354
&& (!shimm_p || shimm == value))
359
/* Forget about shimm as dest mlm. */
361
if ('a' != operand->fmt)
365
flagshimm_handled_p = 1;
366
marker = flag_p ? ARC_REG_SHIMM_UPDATE : ARC_REG_SHIMM;
370
/* Don't request flag setting on shimm as dest. */
371
marker = ARC_REG_SHIMM;
373
insn |= marker << operand->shift;
374
/* insn |= value & 511; - done later. */
376
/* We have to use a limm. If we've already seen one they must match. */
377
else if (!limm_p || limm == value)
382
insn |= ARC_REG_LIMM << operand->shift;
383
/* The constant is stored later. */
386
*errmsg = _("unable to fit different valued constants into instruction");
390
/* We have to handle both normal and auxiliary registers. */
392
if (reg->type == AUXREG)
394
if (!(mods & ARC_MOD_AUXREG))
395
*errmsg = _("auxiliary register not allowed here");
398
if ((insn & I(-1)) == I(2)) /* Check for use validity. */
400
if (reg->flags & ARC_REGISTER_READONLY)
401
*errmsg = _("attempt to set readonly register");
405
if (reg->flags & ARC_REGISTER_WRITEONLY)
406
*errmsg = _("attempt to read writeonly register");
408
insn |= ARC_REG_SHIMM << operand->shift;
409
insn |= reg->value << arc_operands[reg->type].shift;
414
/* check for use validity. */
415
if ('a' == operand->fmt || ((insn & I(-1)) < I(2)))
417
if (reg->flags & ARC_REGISTER_READONLY)
418
*errmsg = _("attempt to set readonly register");
420
if ('a' != operand->fmt)
422
if (reg->flags & ARC_REGISTER_WRITEONLY)
423
*errmsg = _("attempt to read writeonly register");
425
/* We should never get an invalid register number here. */
426
if ((unsigned int) reg->value > 60)
428
sprintf (buf, _("invalid register number `%d'"), reg->value);
431
insn |= reg->value << operand->shift;
436
switch (operand->fmt)
439
ls_operand[LS_DEST] = op_type;
442
ls_operand[LS_BASE] = op_type;
445
if ((insn & I(-1)) == I(2))
446
ls_operand[LS_VALUE] = op_type;
448
ls_operand[LS_OFFSET] = op_type;
451
ls_operand[LS_OFFSET] = op_type;
458
/* Called when we see an 'f' flag. */
461
insert_flag (arc_insn insn,
462
const struct arc_operand *operand ATTRIBUTE_UNUSED,
463
int mods ATTRIBUTE_UNUSED,
464
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
465
long value ATTRIBUTE_UNUSED,
466
const char **errmsg ATTRIBUTE_UNUSED)
468
/* We can't store anything in the insn until we've parsed the registers.
469
Just record the fact that we've got this flag. `insert_reg' will use it
470
to store the correct value (ARC_REG_SHIMM_UPDATE or bit 0x100). */
475
/* Called when we see an nullify condition. */
478
insert_nullify (arc_insn insn,
479
const struct arc_operand *operand,
480
int mods ATTRIBUTE_UNUSED,
481
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
483
const char **errmsg ATTRIBUTE_UNUSED)
486
insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
491
/* Called after completely building an insn to ensure the 'f' flag gets set
492
properly. This is needed because we don't know how to set this flag until
493
we've parsed the registers. */
496
insert_flagfinish (arc_insn insn,
497
const struct arc_operand *operand,
498
int mods ATTRIBUTE_UNUSED,
499
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
500
long value ATTRIBUTE_UNUSED,
501
const char **errmsg ATTRIBUTE_UNUSED)
503
if (flag_p && !flagshimm_handled_p)
507
flagshimm_handled_p = 1;
508
insn |= (1 << operand->shift);
513
/* Called when we see a conditional flag (eg: .eq). */
516
insert_cond (arc_insn insn,
517
const struct arc_operand *operand,
518
int mods ATTRIBUTE_UNUSED,
519
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
521
const char **errmsg ATTRIBUTE_UNUSED)
524
insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
528
/* Used in the "j" instruction to prevent constants from being interpreted as
529
shimm values (which the jump insn doesn't accept). This can also be used
530
to force the use of limm values in other situations (eg: ld r0,[foo] uses
532
??? The mechanism is sound. Access to it is a bit klunky right now. */
535
insert_forcelimm (arc_insn insn,
536
const struct arc_operand *operand ATTRIBUTE_UNUSED,
537
int mods ATTRIBUTE_UNUSED,
538
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
539
long value ATTRIBUTE_UNUSED,
540
const char **errmsg ATTRIBUTE_UNUSED)
547
insert_addr_wb (arc_insn insn,
548
const struct arc_operand *operand,
549
int mods ATTRIBUTE_UNUSED,
550
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
551
long value ATTRIBUTE_UNUSED,
552
const char **errmsg ATTRIBUTE_UNUSED)
554
addrwb_p = 1 << operand->shift;
559
insert_base (arc_insn insn,
560
const struct arc_operand *operand,
562
const struct arc_operand_value *reg,
569
myinsn = insert_reg (0, operand,mods, reg, value, errmsg) >> operand->shift;
571
ls_operand[LS_BASE] = OP_REG;
573
else if (ARC_SHIMM_CONST_P (value) && !cond_p)
575
if (shimm_p && value != shimm)
577
/* Convert the previous shimm operand to a limm. */
580
insn &= ~C(-1); /* We know where the value is in insn. */
581
insn |= C(ARC_REG_LIMM);
582
ls_operand[LS_VALUE] = OP_LIMM;
584
insn |= ARC_REG_SHIMM << operand->shift;
587
ls_operand[LS_BASE] = OP_SHIMM;
588
ls_operand[LS_OFFSET] = OP_SHIMM;
592
if (limm_p && value != limm)
594
*errmsg = _("too many long constants");
599
insn |= B(ARC_REG_LIMM);
600
ls_operand[LS_BASE] = OP_LIMM;
606
/* Used in ld/st insns to handle the offset field. We don't try to
607
match operand syntax here. we catch bad combinations later. */
610
insert_offset (arc_insn insn,
611
const struct arc_operand *operand,
613
const struct arc_operand_value *reg,
622
myinsn = insert_reg (0,operand,mods,reg,value,errmsg) >> operand->shift;
623
ls_operand[LS_OFFSET] = OP_REG;
624
if (operand->flags & ARC_OPERAND_LOAD) /* Not if store, catch it later. */
625
if ((insn & I(-1)) != I(1)) /* Not if opcode == 1, catch it later. */
630
/* This is *way* more general than necessary, but maybe some day it'll
632
if (operand->flags & ARC_OPERAND_SIGNED)
634
minval = -(1 << (operand->bits - 1));
635
maxval = (1 << (operand->bits - 1)) - 1;
640
maxval = (1 << operand->bits) - 1;
642
if ((cond_p && !limm_p) || (value < minval || value > maxval))
644
if (limm_p && value != limm)
645
*errmsg = _("too many long constants");
651
if (operand->flags & ARC_OPERAND_STORE)
652
insn |= B(ARC_REG_LIMM);
653
if (operand->flags & ARC_OPERAND_LOAD)
654
insn |= C(ARC_REG_LIMM);
655
ls_operand[LS_OFFSET] = OP_LIMM;
660
if ((value < minval || value > maxval))
661
*errmsg = "need too many limms";
662
else if (shimm_p && value != shimm)
664
/* Check for bad operand combinations
665
before we lose info about them. */
666
if ((insn & I(-1)) == I(1))
668
*errmsg = _("too many shimms in load");
671
if (limm_p && operand->flags & ARC_OPERAND_LOAD)
673
*errmsg = _("too many long constants");
676
/* Convert what we thought was a shimm to a limm. */
679
if (ls_operand[LS_VALUE] == OP_SHIMM
680
&& operand->flags & ARC_OPERAND_STORE)
683
insn |= C(ARC_REG_LIMM);
684
ls_operand[LS_VALUE] = OP_LIMM;
686
if (ls_operand[LS_BASE] == OP_SHIMM
687
&& operand->flags & ARC_OPERAND_STORE)
690
insn |= B(ARC_REG_LIMM);
691
ls_operand[LS_BASE] = OP_LIMM;
696
ls_operand[LS_OFFSET] = OP_SHIMM;
703
/* Used in st insns to do final disasemble syntax check. */
706
extract_st_syntax (arc_insn *insn,
707
const struct arc_operand *operand ATTRIBUTE_UNUSED,
708
int mods ATTRIBUTE_UNUSED,
709
const struct arc_operand_value **opval ATTRIBUTE_UNUSED,
712
#define ST_SYNTAX(V,B,O) \
713
((ls_operand[LS_VALUE] == (V) && \
714
ls_operand[LS_BASE] == (B) && \
715
ls_operand[LS_OFFSET] == (O)))
717
if (!((ST_SYNTAX(OP_REG,OP_REG,OP_NONE) && (insn[0] & 511) == 0)
718
|| ST_SYNTAX(OP_REG,OP_LIMM,OP_NONE)
719
|| (ST_SYNTAX(OP_SHIMM,OP_REG,OP_NONE) && (insn[0] & 511) == 0)
720
|| (ST_SYNTAX(OP_SHIMM,OP_SHIMM,OP_NONE) && (insn[0] & 511) == 0)
721
|| ST_SYNTAX(OP_SHIMM,OP_LIMM,OP_NONE)
722
|| ST_SYNTAX(OP_SHIMM,OP_LIMM,OP_SHIMM)
723
|| ST_SYNTAX(OP_SHIMM,OP_SHIMM,OP_SHIMM)
724
|| (ST_SYNTAX(OP_LIMM,OP_REG,OP_NONE) && (insn[0] & 511) == 0)
725
|| ST_SYNTAX(OP_REG,OP_REG,OP_SHIMM)
726
|| ST_SYNTAX(OP_REG,OP_SHIMM,OP_SHIMM)
727
|| ST_SYNTAX(OP_SHIMM,OP_REG,OP_SHIMM)
728
|| ST_SYNTAX(OP_LIMM,OP_SHIMM,OP_SHIMM)
729
|| ST_SYNTAX(OP_LIMM,OP_SHIMM,OP_NONE)
730
|| ST_SYNTAX(OP_LIMM,OP_REG,OP_SHIMM)))
736
arc_limm_fixup_adjust (arc_insn insn)
740
/* Check for st shimm,[limm]. */
741
if ((insn & (I(-1) | C(-1) | B(-1))) ==
742
(I(2) | C(ARC_REG_SHIMM) | B(ARC_REG_LIMM)))
744
retval = insn & 0x1ff;
745
if (retval & 0x100) /* Sign extend 9 bit offset. */
748
return -retval; /* Negate offset for return. */
751
/* Used in st insns to do final syntax check. */
754
insert_st_syntax (arc_insn insn,
755
const struct arc_operand *operand ATTRIBUTE_UNUSED,
756
int mods ATTRIBUTE_UNUSED,
757
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
758
long value ATTRIBUTE_UNUSED,
761
if (ST_SYNTAX (OP_SHIMM,OP_REG,OP_NONE) && shimm != 0)
763
/* Change an illegal insn into a legal one, it's easier to
764
do it here than to try to handle it during operand scan. */
769
insn = insn & ~(C(-1) | 511);
770
insn |= ARC_REG_LIMM << ARC_SHIFT_REGC;
771
ls_operand[LS_VALUE] = OP_LIMM;
774
if (ST_SYNTAX (OP_REG, OP_SHIMM, OP_NONE)
775
|| ST_SYNTAX (OP_LIMM, OP_SHIMM, OP_NONE))
777
/* Try to salvage this syntax. */
778
if (shimm & 0x1) /* Odd shimms won't work. */
780
if (limm_p) /* Do we have a limm already? */
781
*errmsg = _("impossible store");
787
insn = insn & ~(B(-1) | 511);
788
insn |= B(ARC_REG_LIMM);
789
ls_operand[LS_BASE] = OP_LIMM;
796
ls_operand[LS_OFFSET] = OP_SHIMM;
799
if (ST_SYNTAX(OP_SHIMM,OP_LIMM,OP_NONE))
800
limm += arc_limm_fixup_adjust(insn);
802
if (! (ST_SYNTAX (OP_REG,OP_REG,OP_NONE)
803
|| ST_SYNTAX (OP_REG,OP_LIMM,OP_NONE)
804
|| ST_SYNTAX (OP_REG,OP_REG,OP_SHIMM)
805
|| ST_SYNTAX (OP_REG,OP_SHIMM,OP_SHIMM)
806
|| (ST_SYNTAX (OP_SHIMM,OP_SHIMM,OP_NONE) && (shimm == 0))
807
|| ST_SYNTAX (OP_SHIMM,OP_LIMM,OP_NONE)
808
|| ST_SYNTAX (OP_SHIMM,OP_REG,OP_NONE)
809
|| ST_SYNTAX (OP_SHIMM,OP_REG,OP_SHIMM)
810
|| ST_SYNTAX (OP_SHIMM,OP_SHIMM,OP_SHIMM)
811
|| ST_SYNTAX (OP_LIMM,OP_SHIMM,OP_SHIMM)
812
|| ST_SYNTAX (OP_LIMM,OP_REG,OP_NONE)
813
|| ST_SYNTAX (OP_LIMM,OP_REG,OP_SHIMM)))
814
*errmsg = _("st operand error");
817
if (ls_operand[LS_BASE] != OP_REG)
818
*errmsg = _("address writeback not allowed");
821
if (ST_SYNTAX(OP_SHIMM,OP_REG,OP_NONE) && shimm)
822
*errmsg = _("store value must be zero");
826
/* Used in ld insns to do final syntax check. */
829
insert_ld_syntax (arc_insn insn,
830
const struct arc_operand *operand ATTRIBUTE_UNUSED,
831
int mods ATTRIBUTE_UNUSED,
832
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
833
long value ATTRIBUTE_UNUSED,
836
#define LD_SYNTAX(D, B, O) \
837
( (ls_operand[LS_DEST] == (D) \
838
&& ls_operand[LS_BASE] == (B) \
839
&& ls_operand[LS_OFFSET] == (O)))
841
int test = insn & I (-1);
843
if (!(test == I (1)))
845
if ((ls_operand[LS_DEST] == OP_SHIMM || ls_operand[LS_BASE] == OP_SHIMM
846
|| ls_operand[LS_OFFSET] == OP_SHIMM))
847
*errmsg = _("invalid load/shimm insn");
849
if (!(LD_SYNTAX(OP_REG,OP_REG,OP_NONE)
850
|| LD_SYNTAX(OP_REG,OP_REG,OP_REG)
851
|| LD_SYNTAX(OP_REG,OP_REG,OP_SHIMM)
852
|| (LD_SYNTAX(OP_REG,OP_LIMM,OP_REG) && !(test == I(1)))
853
|| (LD_SYNTAX(OP_REG,OP_REG,OP_LIMM) && !(test == I(1)))
854
|| LD_SYNTAX(OP_REG,OP_SHIMM,OP_SHIMM)
855
|| (LD_SYNTAX(OP_REG,OP_LIMM,OP_NONE) && (test == I(1)))))
856
*errmsg = _("ld operand error");
859
if (ls_operand[LS_BASE] != OP_REG)
860
*errmsg = _("address writeback not allowed");
866
/* Used in ld insns to do final syntax check. */
869
extract_ld_syntax (arc_insn *insn,
870
const struct arc_operand *operand ATTRIBUTE_UNUSED,
871
int mods ATTRIBUTE_UNUSED,
872
const struct arc_operand_value **opval ATTRIBUTE_UNUSED,
875
int test = insn[0] & I(-1);
879
if ((ls_operand[LS_DEST] == OP_SHIMM || ls_operand[LS_BASE] == OP_SHIMM
880
|| ls_operand[LS_OFFSET] == OP_SHIMM))
883
if (!( (LD_SYNTAX (OP_REG, OP_REG, OP_NONE) && (test == I(1)))
884
|| LD_SYNTAX (OP_REG, OP_REG, OP_REG)
885
|| LD_SYNTAX (OP_REG, OP_REG, OP_SHIMM)
886
|| (LD_SYNTAX (OP_REG, OP_REG, OP_LIMM) && !(test == I(1)))
887
|| (LD_SYNTAX (OP_REG, OP_LIMM, OP_REG) && !(test == I(1)))
888
|| (LD_SYNTAX (OP_REG, OP_SHIMM, OP_NONE) && (shimm == 0))
889
|| LD_SYNTAX (OP_REG, OP_SHIMM, OP_SHIMM)
890
|| (LD_SYNTAX (OP_REG, OP_LIMM, OP_NONE) && (test == I(1)))))
895
/* Called at the end of processing normal insns (eg: add) to insert a shimm
896
value (if present) into the insn. */
899
insert_shimmfinish (arc_insn insn,
900
const struct arc_operand *operand,
901
int mods ATTRIBUTE_UNUSED,
902
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
903
long value ATTRIBUTE_UNUSED,
904
const char **errmsg ATTRIBUTE_UNUSED)
907
insn |= (shimm & ((1 << operand->bits) - 1)) << operand->shift;
911
/* Called at the end of processing normal insns (eg: add) to insert a limm
912
value (if present) into the insn.
914
Note that this function is only intended to handle instructions (with 4 byte
915
immediate operands). It is not intended to handle data. */
917
/* ??? Actually, there's nothing for us to do as we can't call frag_more, the
918
caller must do that. The extract fns take a pointer to two words. The
919
insert fns could be converted and then we could do something useful, but
920
then the reloc handlers would have to know to work on the second word of
921
a 2 word quantity. That's too much so we don't handle them. */
924
insert_limmfinish (arc_insn insn,
925
const struct arc_operand *operand ATTRIBUTE_UNUSED,
926
int mods ATTRIBUTE_UNUSED,
927
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
928
long value ATTRIBUTE_UNUSED,
929
const char **errmsg ATTRIBUTE_UNUSED)
935
insert_jumpflags (arc_insn insn,
936
const struct arc_operand *operand,
937
int mods ATTRIBUTE_UNUSED,
938
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
943
*errmsg = _("jump flags, but no .f seen");
946
*errmsg = _("jump flags, but no limm addr");
948
else if (limm & 0xfc000000)
949
*errmsg = _("flag bits of jump address limm lost");
951
else if (limm & 0x03000000)
952
*errmsg = _("attempt to set HR bits");
954
else if ((value & ((1 << operand->bits) - 1)) != value)
955
*errmsg = _("bad jump flags value");
958
limm = ((limm & ((1 << operand->shift) - 1))
959
| ((value & ((1 << operand->bits) - 1)) << operand->shift));
963
/* Called at the end of unary operand macros to copy the B field to C. */
966
insert_unopmacro (arc_insn insn,
967
const struct arc_operand *operand,
968
int mods ATTRIBUTE_UNUSED,
969
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
970
long value ATTRIBUTE_UNUSED,
971
const char **errmsg ATTRIBUTE_UNUSED)
973
insn |= ((insn >> ARC_SHIFT_REGB) & ARC_MASK_REG) << operand->shift;
977
/* Insert a relative address for a branch insn (b, bl, or lp). */
980
insert_reladdr (arc_insn insn,
981
const struct arc_operand *operand,
982
int mods ATTRIBUTE_UNUSED,
983
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
988
*errmsg = _("branch address not on 4 byte boundary");
989
insn |= ((value >> 2) & ((1 << operand->bits) - 1)) << operand->shift;
993
/* Insert a limm value as a 26 bit address right shifted 2 into the insn.
995
Note that this function is only intended to handle instructions (with 4 byte
996
immediate operands). It is not intended to handle data. */
998
/* ??? Actually, there's little for us to do as we can't call frag_more, the
999
caller must do that. The extract fns take a pointer to two words. The
1000
insert fns could be converted and then we could do something useful, but
1001
then the reloc handlers would have to know to work on the second word of
1002
a 2 word quantity. That's too much so we don't handle them.
1004
We do check for correct usage of the nullify suffix, or we
1005
set the default correctly, though. */
1008
insert_absaddr (arc_insn insn,
1009
const struct arc_operand *operand ATTRIBUTE_UNUSED,
1010
int mods ATTRIBUTE_UNUSED,
1011
const struct arc_operand_value *reg ATTRIBUTE_UNUSED,
1012
long value ATTRIBUTE_UNUSED,
1013
const char **errmsg)
1017
/* If it is a jump and link, .jd must be specified. */
1018
if (insn & R (-1, 9, 1))
1021
insn |= 0x02 << 5; /* Default nullify to .jd. */
1023
else if (nullify != 0x02)
1024
*errmsg = _("must specify .jd or no nullify suffix");
1030
/* Extraction functions.
1032
The suffix extraction functions' return value is redundant since it can be
1033
obtained from (*OPVAL)->value. However, the boolean suffixes don't have
1034
a suffix table entry for the "false" case, so values of zero must be
1035
obtained from the return value (*OPVAL == NULL). */
1037
/* Called by the disassembler before printing an instruction. */
1040
arc_opcode_init_extract (void)
1042
arc_opcode_init_insert ();
1045
static const struct arc_operand_value *
1046
lookup_register (int type, long regno)
1048
const struct arc_operand_value *r,*end;
1049
struct arc_ext_operand_value *ext_oper = arc_ext_operands;
1053
if (ext_oper->operand.type == type && ext_oper->operand.value == regno)
1054
return (&ext_oper->operand);
1055
ext_oper = ext_oper->next;
1059
return &arc_reg_names[regno];
1061
/* ??? This is a little slow and can be speeded up. */
1062
for (r = arc_reg_names, end = arc_reg_names + arc_reg_names_count;
1064
if (type == r->type && regno == r->value)
1069
/* As we're extracting registers, keep an eye out for the 'f' indicator
1070
(ARC_REG_SHIMM_UPDATE). If we find a register (not a constant marker,
1071
like ARC_REG_SHIMM), set OPVAL so our caller will know this is a register.
1073
We must also handle auxiliary registers for lr/sr insns. They are just
1074
constants with special names. */
1077
extract_reg (arc_insn *insn,
1078
const struct arc_operand *operand,
1080
const struct arc_operand_value **opval,
1081
int *invalid ATTRIBUTE_UNUSED)
1085
enum operand op_type;
1087
/* Get the register number. */
1088
regno = (*insn >> operand->shift) & ((1 << operand->bits) - 1);
1090
/* Is it a constant marker? */
1091
if (regno == ARC_REG_SHIMM)
1094
/* Always return zero if dest is a shimm mlm. */
1096
if ('a' != operand->fmt)
1098
value = *insn & 511;
1099
if ((operand->flags & ARC_OPERAND_SIGNED)
1102
if (!flagshimm_handled_p)
1104
flagshimm_handled_p = 1;
1109
else if (regno == ARC_REG_SHIMM_UPDATE)
1113
/* Always return zero if dest is a shimm mlm. */
1114
if ('a' != operand->fmt)
1116
value = *insn & 511;
1117
if ((operand->flags & ARC_OPERAND_SIGNED) && (value & 256))
1124
flagshimm_handled_p = 1;
1126
else if (regno == ARC_REG_LIMM)
1132
/* If this is a jump instruction (j,jl), show new pc correctly. */
1133
if (0x07 == ((*insn & I(-1)) >> 27))
1134
value = (value & 0xffffff);
1137
/* It's a register, set OPVAL (that's the only way we distinguish registers
1138
from constants here). */
1141
const struct arc_operand_value *reg = lookup_register (REG, regno);
1152
/* If this field takes an auxiliary register, see if it's a known one. */
1153
if ((mods & ARC_MOD_AUXREG)
1154
&& ARC_REG_CONSTANT_P (regno))
1156
const struct arc_operand_value *reg = lookup_register (AUXREG, value);
1158
/* This is really a constant, but tell the caller it has a special
1160
if (reg != NULL && opval != NULL)
1164
switch(operand->fmt)
1167
ls_operand[LS_DEST] = op_type;
1170
ls_operand[LS_BASE] = op_type;
1173
if ((insn[0]& I(-1)) == I(2))
1174
ls_operand[LS_VALUE] = op_type;
1176
ls_operand[LS_OFFSET] = op_type;
1179
ls_operand[LS_OFFSET] = op_type;
1186
/* Return the value of the "flag update" field for shimm insns.
1187
This value is actually stored in the register field. */
1190
extract_flag (arc_insn *insn,
1191
const struct arc_operand *operand,
1192
int mods ATTRIBUTE_UNUSED,
1193
const struct arc_operand_value **opval,
1194
int *invalid ATTRIBUTE_UNUSED)
1197
const struct arc_operand_value *val;
1199
if (flagshimm_handled_p)
1202
f = (*insn & (1 << operand->shift)) != 0;
1204
/* There is no text for zero values. */
1208
val = arc_opcode_lookup_suffix (operand, 1);
1209
if (opval != NULL && val != NULL)
1214
/* Extract the condition code (if it exists).
1215
If we've seen a shimm value in this insn (meaning that the insn can't have
1216
a condition code field), then we don't store anything in OPVAL and return
1220
extract_cond (arc_insn *insn,
1221
const struct arc_operand *operand,
1222
int mods ATTRIBUTE_UNUSED,
1223
const struct arc_operand_value **opval,
1224
int *invalid ATTRIBUTE_UNUSED)
1227
const struct arc_operand_value *val;
1229
if (flagshimm_handled_p)
1232
cond = (*insn >> operand->shift) & ((1 << operand->bits) - 1);
1233
val = arc_opcode_lookup_suffix (operand, cond);
1235
/* Ignore NULL values of `val'. Several condition code values are
1236
reserved for extensions. */
1237
if (opval != NULL && val != NULL)
1242
/* Extract a branch address.
1243
We return the value as a real address (not right shifted by 2). */
1246
extract_reladdr (arc_insn *insn,
1247
const struct arc_operand *operand,
1248
int mods ATTRIBUTE_UNUSED,
1249
const struct arc_operand_value **opval ATTRIBUTE_UNUSED,
1250
int *invalid ATTRIBUTE_UNUSED)
1254
addr = (*insn >> operand->shift) & ((1 << operand->bits) - 1);
1255
if ((operand->flags & ARC_OPERAND_SIGNED)
1256
&& (addr & (1 << (operand->bits - 1))))
1257
addr -= 1 << operand->bits;
1261
/* Extract the flags bits from a j or jl long immediate. */
1264
extract_jumpflags (arc_insn *insn,
1265
const struct arc_operand *operand,
1266
int mods ATTRIBUTE_UNUSED,
1267
const struct arc_operand_value **opval ATTRIBUTE_UNUSED,
1270
if (!flag_p || !limm_p)
1272
return ((flag_p && limm_p)
1273
? (insn[1] >> operand->shift) & ((1 << operand->bits) -1): 0);
1276
/* Extract st insn's offset. */
1279
extract_st_offset (arc_insn *insn,
1280
const struct arc_operand *operand,
1281
int mods ATTRIBUTE_UNUSED,
1282
const struct arc_operand_value **opval ATTRIBUTE_UNUSED,
1287
if (ls_operand[LS_VALUE] != OP_SHIMM || ls_operand[LS_BASE] != OP_LIMM)
1289
value = insn[0] & 511;
1290
if ((operand->flags & ARC_OPERAND_SIGNED) && (value & 256))
1293
ls_operand[LS_OFFSET] = OP_SHIMM;
1301
/* Extract ld insn's offset. */
1304
extract_ld_offset (arc_insn *insn,
1305
const struct arc_operand *operand,
1307
const struct arc_operand_value **opval,
1310
int test = insn[0] & I(-1);
1315
value = insn[0] & 511;
1316
if ((operand->flags & ARC_OPERAND_SIGNED) && (value & 256))
1319
ls_operand[LS_OFFSET] = OP_SHIMM;
1323
/* If it isn't in the insn, it's concealed behind reg 'c'. */
1324
return extract_reg (insn, &arc_operands[arc_operand_map['c']],
1325
mods, opval, invalid);
1328
/* The only thing this does is set the `invalid' flag if B != C.
1329
This is needed because the "mov" macro appears before it's real insn "and"
1330
and we don't want the disassembler to confuse them. */
1333
extract_unopmacro (arc_insn *insn,
1334
const struct arc_operand *operand ATTRIBUTE_UNUSED,
1335
int mods ATTRIBUTE_UNUSED,
1336
const struct arc_operand_value **opval ATTRIBUTE_UNUSED,
1339
/* This misses the case where B == ARC_REG_SHIMM_UPDATE &&
1340
C == ARC_REG_SHIMM (or vice versa). No big deal. Those insns will get
1341
printed as "and"s. */
1342
if (((*insn >> ARC_SHIFT_REGB) & ARC_MASK_REG)
1343
!= ((*insn >> ARC_SHIFT_REGC) & ARC_MASK_REG))
1344
if (invalid != NULL)
1349
/* ARC instructions.
1351
Longer versions of insns must appear before shorter ones (if gas sees
1352
"lsr r2,r3,1" when it's parsing "lsr %a,%b" it will think the ",1" is
1353
junk). This isn't necessary for `ld' because of the trailing ']'.
1355
Instructions that are really macros based on other insns must appear
1356
before the real insn so they're chosen when disassembling. Eg: The `mov'
1357
insn is really the `and' insn. */
1359
struct arc_opcode arc_opcodes[] =
1361
/* Base case instruction set (core versions 5-8). */
1363
/* "mov" is really an "and". */
1364
{ "mov%.q%.f %a,%b%F%S%L%U", I(-1), I(12), ARC_MACH_5, 0, 0 },
1365
/* "asl" is really an "add". */
1366
{ "asl%.q%.f %a,%b%F%S%L%U", I(-1), I(8), ARC_MACH_5, 0, 0 },
1367
/* "lsl" is really an "add". */
1368
{ "lsl%.q%.f %a,%b%F%S%L%U", I(-1), I(8), ARC_MACH_5, 0, 0 },
1369
/* "nop" is really an "xor". */
1370
{ "nop", 0x7fffffff, 0x7fffffff, ARC_MACH_5, 0, 0 },
1371
/* "rlc" is really an "adc". */
1372
{ "rlc%.q%.f %a,%b%F%S%L%U", I(-1), I(9), ARC_MACH_5, 0, 0 },
1373
{ "adc%.q%.f %a,%b,%c%F%S%L", I(-1), I(9), ARC_MACH_5, 0, 0 },
1374
{ "add%.q%.f %a,%b,%c%F%S%L", I(-1), I(8), ARC_MACH_5, 0, 0 },
1375
{ "and%.q%.f %a,%b,%c%F%S%L", I(-1), I(12), ARC_MACH_5, 0, 0 },
1376
{ "asr%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(1), ARC_MACH_5, 0, 0 },
1377
{ "bic%.q%.f %a,%b,%c%F%S%L", I(-1), I(14), ARC_MACH_5, 0, 0 },
1378
{ "b%q%.n %B", I(-1), I(4), ARC_MACH_5 | ARC_OPCODE_COND_BRANCH, 0, 0 },
1379
{ "bl%q%.n %B", I(-1), I(5), ARC_MACH_5 | ARC_OPCODE_COND_BRANCH, 0, 0 },
1380
{ "extb%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(7), ARC_MACH_5, 0, 0 },
1381
{ "extw%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(8), ARC_MACH_5, 0, 0 },
1382
{ "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 },
1383
{ "brk", 0x1ffffe00, 0x1ffffe00, ARC_MACH_7, 0, 0 },
1384
{ "sleep", 0x1ffffe01, 0x1ffffe01, ARC_MACH_7, 0, 0 },
1385
{ "swi", 0x1ffffe02, 0x1ffffe02, ARC_MACH_8, 0, 0 },
1386
/* %Q: force cond_p=1 -> no shimm values. This insn allows an
1387
optional flags spec. */
1388
{ "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 },
1389
{ "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 },
1390
/* This insn allows an optional flags spec. */
1391
{ "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 },
1392
{ "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 },
1393
/* Put opcode 1 ld insns first so shimm gets prefered over limm.
1394
"[%b]" is before "[%b,%o]" so 0 offsets don't get printed. */
1395
{ "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 },
1396
{ "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 },
1397
{ "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 },
1398
{ "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 },
1399
{ "lp%q%.n %B", I(-1), I(6), ARC_MACH_5, 0, 0 },
1400
{ "lr %a,[%Ab]%S%L", I(-1)|C(-1), I(1)|C(0x10), ARC_MACH_5, 0, 0 },
1401
{ "lsr%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(2), ARC_MACH_5, 0, 0 },
1402
{ "or%.q%.f %a,%b,%c%F%S%L", I(-1), I(13), ARC_MACH_5, 0, 0 },
1403
{ "ror%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(3), ARC_MACH_5, 0, 0 },
1404
{ "rrc%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(4), ARC_MACH_5, 0, 0 },
1405
{ "sbc%.q%.f %a,%b,%c%F%S%L", I(-1), I(11), ARC_MACH_5, 0, 0 },
1406
{ "sexb%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(5), ARC_MACH_5, 0, 0 },
1407
{ "sexw%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(6), ARC_MACH_5, 0, 0 },
1408
{ "sr %c,[%Ab]%S%L", I(-1)|A(-1), I(2)|A(0x10), ARC_MACH_5, 0, 0 },
1409
/* "[%b]" is before "[%b,%o]" so 0 offsets don't get printed. */
1410
{ "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 },
1411
{ "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 },
1412
{ "sub%.q%.f %a,%b,%c%F%S%L", I(-1), I(10), ARC_MACH_5, 0, 0 },
1413
{ "xor%.q%.f %a,%b,%c%F%S%L", I(-1), I(15), ARC_MACH_5, 0, 0 }
1416
const int arc_opcodes_count = sizeof (arc_opcodes) / sizeof (arc_opcodes[0]);
1418
const struct arc_operand_value arc_reg_names[] =
1420
/* Core register set r0-r63. */
1422
/* r0-r28 - general purpose registers. */
1423
{ "r0", 0, REG, 0 }, { "r1", 1, REG, 0 }, { "r2", 2, REG, 0 },
1424
{ "r3", 3, REG, 0 }, { "r4", 4, REG, 0 }, { "r5", 5, REG, 0 },
1425
{ "r6", 6, REG, 0 }, { "r7", 7, REG, 0 }, { "r8", 8, REG, 0 },
1426
{ "r9", 9, REG, 0 }, { "r10", 10, REG, 0 }, { "r11", 11, REG, 0 },
1427
{ "r12", 12, REG, 0 }, { "r13", 13, REG, 0 }, { "r14", 14, REG, 0 },
1428
{ "r15", 15, REG, 0 }, { "r16", 16, REG, 0 }, { "r17", 17, REG, 0 },
1429
{ "r18", 18, REG, 0 }, { "r19", 19, REG, 0 }, { "r20", 20, REG, 0 },
1430
{ "r21", 21, REG, 0 }, { "r22", 22, REG, 0 }, { "r23", 23, REG, 0 },
1431
{ "r24", 24, REG, 0 }, { "r25", 25, REG, 0 }, { "r26", 26, REG, 0 },
1432
{ "r27", 27, REG, 0 }, { "r28", 28, REG, 0 },
1433
/* Maskable interrupt link register. */
1434
{ "ilink1", 29, REG, 0 },
1435
/* Maskable interrupt link register. */
1436
{ "ilink2", 30, REG, 0 },
1437
/* Branch-link register. */
1438
{ "blink", 31, REG, 0 },
1440
/* r32-r59 reserved for extensions. */
1441
{ "r32", 32, REG, 0 }, { "r33", 33, REG, 0 }, { "r34", 34, REG, 0 },
1442
{ "r35", 35, REG, 0 }, { "r36", 36, REG, 0 }, { "r37", 37, REG, 0 },
1443
{ "r38", 38, REG, 0 }, { "r39", 39, REG, 0 }, { "r40", 40, REG, 0 },
1444
{ "r41", 41, REG, 0 }, { "r42", 42, REG, 0 }, { "r43", 43, REG, 0 },
1445
{ "r44", 44, REG, 0 }, { "r45", 45, REG, 0 }, { "r46", 46, REG, 0 },
1446
{ "r47", 47, REG, 0 }, { "r48", 48, REG, 0 }, { "r49", 49, REG, 0 },
1447
{ "r50", 50, REG, 0 }, { "r51", 51, REG, 0 }, { "r52", 52, REG, 0 },
1448
{ "r53", 53, REG, 0 }, { "r54", 54, REG, 0 }, { "r55", 55, REG, 0 },
1449
{ "r56", 56, REG, 0 }, { "r57", 57, REG, 0 }, { "r58", 58, REG, 0 },
1450
{ "r59", 59, REG, 0 },
1452
/* Loop count register (24 bits). */
1453
{ "lp_count", 60, REG, 0 },
1454
/* Short immediate data indicator setting flags. */
1455
{ "r61", 61, REG, ARC_REGISTER_READONLY },
1456
/* Long immediate data indicator setting flags. */
1457
{ "r62", 62, REG, ARC_REGISTER_READONLY },
1458
/* Short immediate data indicator not setting flags. */
1459
{ "r63", 63, REG, ARC_REGISTER_READONLY },
1461
/* Small-data base register. */
1462
{ "gp", 26, REG, 0 },
1463
/* Frame pointer. */
1464
{ "fp", 27, REG, 0 },
1465
/* Stack pointer. */
1466
{ "sp", 28, REG, 0 },
1468
{ "r29", 29, REG, 0 },
1469
{ "r30", 30, REG, 0 },
1470
{ "r31", 31, REG, 0 },
1471
{ "r60", 60, REG, 0 },
1473
/* Auxiliary register set. */
1475
/* Auxiliary register address map:
1476
0xffffffff-0xffffff00 (-1..-256) - customer shimm allocation
1477
0xfffffeff-0x80000000 - customer limm allocation
1478
0x7fffffff-0x00000100 - ARC limm allocation
1479
0x000000ff-0x00000000 - ARC shimm allocation */
1481
/* Base case auxiliary registers (shimm address). */
1482
{ "status", 0x00, AUXREG, 0 },
1483
{ "semaphore", 0x01, AUXREG, 0 },
1484
{ "lp_start", 0x02, AUXREG, 0 },
1485
{ "lp_end", 0x03, AUXREG, 0 },
1486
{ "identity", 0x04, AUXREG, ARC_REGISTER_READONLY },
1487
{ "debug", 0x05, AUXREG, 0 },
1490
const int arc_reg_names_count =
1491
sizeof (arc_reg_names) / sizeof (arc_reg_names[0]);
1493
/* The suffix table.
1494
Operands with the same name must be stored together. */
1496
const struct arc_operand_value arc_suffixes[] =
1498
/* Entry 0 is special, default values aren't printed by the disassembler. */
1501
/* Base case condition codes. */
1502
{ "al", 0, COND, 0 },
1503
{ "ra", 0, COND, 0 },
1504
{ "eq", 1, COND, 0 },
1505
{ "z", 1, COND, 0 },
1506
{ "ne", 2, COND, 0 },
1507
{ "nz", 2, COND, 0 },
1508
{ "pl", 3, COND, 0 },
1509
{ "p", 3, COND, 0 },
1510
{ "mi", 4, COND, 0 },
1511
{ "n", 4, COND, 0 },
1512
{ "cs", 5, COND, 0 },
1513
{ "c", 5, COND, 0 },
1514
{ "lo", 5, COND, 0 },
1515
{ "cc", 6, COND, 0 },
1516
{ "nc", 6, COND, 0 },
1517
{ "hs", 6, COND, 0 },
1518
{ "vs", 7, COND, 0 },
1519
{ "v", 7, COND, 0 },
1520
{ "vc", 8, COND, 0 },
1521
{ "nv", 8, COND, 0 },
1522
{ "gt", 9, COND, 0 },
1523
{ "ge", 10, COND, 0 },
1524
{ "lt", 11, COND, 0 },
1525
{ "le", 12, COND, 0 },
1526
{ "hi", 13, COND, 0 },
1527
{ "ls", 14, COND, 0 },
1528
{ "pnz", 15, COND, 0 },
1530
/* Condition codes 16-31 reserved for extensions. */
1532
{ "f", 1, FLAG, 0 },
1534
{ "nd", ARC_DELAY_NONE, DELAY, 0 },
1535
{ "d", ARC_DELAY_NORMAL, DELAY, 0 },
1536
{ "jd", ARC_DELAY_JUMP, DELAY, 0 },
1538
{ "b", 1, SIZE1, 0 },
1539
{ "b", 1, SIZE10, 0 },
1540
{ "b", 1, SIZE22, 0 },
1541
{ "w", 2, SIZE1, 0 },
1542
{ "w", 2, SIZE10, 0 },
1543
{ "w", 2, SIZE22, 0 },
1544
{ "x", 1, SIGN0, 0 },
1545
{ "x", 1, SIGN9, 0 },
1546
{ "a", 1, ADDRESS3, 0 },
1547
{ "a", 1, ADDRESS12, 0 },
1548
{ "a", 1, ADDRESS24, 0 },
1550
{ "di", 1, CACHEBYPASS5, 0 },
1551
{ "di", 1, CACHEBYPASS14, 0 },
1552
{ "di", 1, CACHEBYPASS26, 0 },
1555
const int arc_suffixes_count =
1556
sizeof (arc_suffixes) / sizeof (arc_suffixes[0]);
1558
/* Indexed by first letter of opcode. Points to chain of opcodes with same
1560
static struct arc_opcode *opcode_map[26 + 1];
1562
/* Indexed by insn code. Points to chain of opcodes with same insn code. */
1563
static struct arc_opcode *icode_map[32];
1565
/* Configuration flags. */
1567
/* Various ARC_HAVE_XXX bits. */
1568
static int cpu_type;
1570
/* Translate a bfd_mach_arc_xxx value to a ARC_MACH_XXX value. */
1573
arc_get_opcode_mach (int bfd_mach, int big_p)
1575
static int mach_type_map[] =
1582
return mach_type_map[bfd_mach - bfd_mach_arc_5] | (big_p ? ARC_MACH_BIG : 0);
1585
/* Initialize any tables that need it.
1586
Must be called once at start up (or when first needed).
1588
FLAGS is a set of bits that say what version of the cpu we have,
1589
and in particular at least (one of) ARC_MACH_XXX. */
1592
arc_opcode_init_tables (int flags)
1594
static int init_p = 0;
1598
/* We may be intentionally called more than once (for example gdb will call
1599
us each time the user switches cpu). These tables only need to be init'd
1605
memset (arc_operand_map, 0, sizeof (arc_operand_map));
1606
n = sizeof (arc_operands) / sizeof (arc_operands[0]);
1607
for (i = 0; i < n; ++i)
1608
arc_operand_map[arc_operands[i].fmt] = i;
1610
memset (opcode_map, 0, sizeof (opcode_map));
1611
memset (icode_map, 0, sizeof (icode_map));
1612
/* Scan the table backwards so macros appear at the front. */
1613
for (i = arc_opcodes_count - 1; i >= 0; --i)
1615
int opcode_hash = ARC_HASH_OPCODE (arc_opcodes[i].syntax);
1616
int icode_hash = ARC_HASH_ICODE (arc_opcodes[i].value);
1618
arc_opcodes[i].next_asm = opcode_map[opcode_hash];
1619
opcode_map[opcode_hash] = &arc_opcodes[i];
1621
arc_opcodes[i].next_dis = icode_map[icode_hash];
1622
icode_map[icode_hash] = &arc_opcodes[i];
1629
/* Return non-zero if OPCODE is supported on the specified cpu.
1630
Cpu selection is made when calling `arc_opcode_init_tables'. */
1633
arc_opcode_supported (const struct arc_opcode *opcode)
1635
if (ARC_OPCODE_CPU (opcode->flags) <= cpu_type)
1640
/* Return the first insn in the chain for assembling INSN. */
1642
const struct arc_opcode *
1643
arc_opcode_lookup_asm (const char *insn)
1645
return opcode_map[ARC_HASH_OPCODE (insn)];
1648
/* Return the first insn in the chain for disassembling INSN. */
1650
const struct arc_opcode *
1651
arc_opcode_lookup_dis (unsigned int insn)
1653
return icode_map[ARC_HASH_ICODE (insn)];
1656
/* Called by the assembler before parsing an instruction. */
1659
arc_opcode_init_insert (void)
1663
for(i = 0; i < OPERANDS; i++)
1664
ls_operand[i] = OP_NONE;
1667
flagshimm_handled_p = 0;
1674
nullify = 0; /* The default is important. */
1677
/* Called by the assembler to see if the insn has a limm operand.
1678
Also called by the disassembler to see if the insn contains a limm. */
1681
arc_opcode_limm_p (long *limmp)
1688
/* Utility for the extraction functions to return the index into
1691
const struct arc_operand_value *
1692
arc_opcode_lookup_suffix (const struct arc_operand *type, int value)
1694
const struct arc_operand_value *v,*end;
1695
struct arc_ext_operand_value *ext_oper = arc_ext_operands;
1699
if (type == &arc_operands[ext_oper->operand.type]
1700
&& value == ext_oper->operand.value)
1701
return (&ext_oper->operand);
1702
ext_oper = ext_oper->next;
1705
/* ??? This is a little slow and can be speeded up. */
1706
for (v = arc_suffixes, end = arc_suffixes + arc_suffixes_count; v < end; ++v)
1707
if (type == &arc_operands[v->type]
1708
&& value == v->value)
1714
arc_insn_is_j (arc_insn insn)
1716
return (insn & (I(-1))) == I(0x7);
1720
arc_insn_not_jl (arc_insn insn)
1722
return ((insn & (I(-1)|A(-1)|C(-1)|R(-1,7,1)|R(-1,9,1)))
1723
!= (I(0x7) | R(-1,9,1)));
1727
arc_operand_type (int opertype)
1744
struct arc_operand_value *
1745
get_ext_suffix (char *s)
1747
struct arc_ext_operand_value *suffix = arc_ext_operands;
1751
if ((COND == suffix->operand.type)
1752
&& !strcmp(s,suffix->operand.name))
1753
return(&suffix->operand);
1754
suffix = suffix->next;
1760
arc_get_noshortcut_flag (void)
1762
return ARC_REGISTER_NOSHORT_CUT;