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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [arc-opc.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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