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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [opcodes/] [arc-opc.c] - Blame information for rev 55

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

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

powered by: WebSVN 2.1.0

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