OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [opcodes/] [arc-opc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.