source: vendor/binutils/current/opcodes/arc-opc.c

Last change on this file was 609, checked in by bird, 22 years ago

binutils v2.14 - offical sources.

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