source: trunk/src/binutils/opcodes/arc-opc.c@ 462

Last change on this file since 462 was 10, checked in by bird, 22 years ago

Initial revision

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