~ubuntu-branches/ubuntu/hoary/binutils/hoary

« back to all changes in this revision

Viewing changes to opcodes/arc-dis.c

  • Committer: Bazaar Package Importer
  • Author(s): James Troup
  • Date: 2004-05-19 10:35:44 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040519103544-17h3o6e8pwndydrg
Tags: 2.14.90.0.7-8
debian/rules: don't use gcc-2.95 on m68k.  Thanks to Adam Conrad for
pointing this out.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Instruction printing code for the ARC.
 
2
   Copyright 1994, 1995, 1997, 1998, 2000, 2001, 2002
 
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 of the License, or
 
9
   (at your option) 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
 
18
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
19
 
 
20
#include "ansidecl.h"
 
21
#include "libiberty.h"
 
22
#include "dis-asm.h"
 
23
#include "opcode/arc.h"
 
24
#include "elf-bfd.h"
 
25
#include "elf/arc.h"
 
26
#include <string.h>
 
27
#include "opintl.h"
 
28
 
 
29
#include <stdarg.h>
 
30
#include "arc-dis.h"
 
31
#include "arc-ext.h"
 
32
 
 
33
#ifndef dbg
 
34
#define dbg (0)
 
35
#endif
 
36
 
 
37
#define BIT(word,n)     ((word) & (1 << n))
 
38
#define BITS(word,s,e)  (((word) << (31 - e)) >> (s + (31 - e)))
 
39
#define OPCODE(word)    (BITS ((word), 27, 31))
 
40
#define FIELDA(word)    (BITS ((word), 21, 26))
 
41
#define FIELDB(word)    (BITS ((word), 15, 20))
 
42
#define FIELDC(word)    (BITS ((word),  9, 14))
 
43
 
 
44
/* FIELD D is signed in all of its uses, so we make sure argument is
 
45
   treated as signed for bit shifting purposes:  */
 
46
#define FIELDD(word)    (BITS (((signed int)word), 0, 8))
 
47
 
 
48
#define PUT_NEXT_WORD_IN(a)                                             \
 
49
  do                                                                    \
 
50
    {                                                                   \
 
51
      if (is_limm == 1 && !NEXT_WORD (1))                               \
 
52
        mwerror (state, _("Illegal limm reference in last instruction!\n")); \
 
53
      a = state->words[1];                                              \
 
54
    }                                                                   \
 
55
  while (0)
 
56
 
 
57
#define CHECK_FLAG_COND_NULLIFY()                               \
 
58
  do                                                            \
 
59
    {                                                           \
 
60
      if (is_shimm == 0)                                        \
 
61
        {                                                       \
 
62
          flag = BIT (state->words[0], 8);                      \
 
63
          state->nullifyMode = BITS (state->words[0], 5, 6);    \
 
64
          cond = BITS (state->words[0], 0, 4);                  \
 
65
        }                                                       \
 
66
    }                                                           \
 
67
  while (0)
 
68
 
 
69
#define CHECK_COND()                            \
 
70
  do                                            \
 
71
    {                                           \
 
72
      if (is_shimm == 0)                        \
 
73
        cond = BITS (state->words[0], 0, 4);    \
 
74
    }                                           \
 
75
  while (0)
 
76
 
 
77
#define CHECK_FIELD(field)                      \
 
78
  do                                            \
 
79
    {                                           \
 
80
      if (field == 62)                          \
 
81
        {                                       \
 
82
          is_limm++;                            \
 
83
          field##isReg = 0;                     \
 
84
          PUT_NEXT_WORD_IN (field);             \
 
85
          limm_value = field;                   \
 
86
        }                                       \
 
87
      else if (field > 60)                      \
 
88
        {                                       \
 
89
          field##isReg = 0;                     \
 
90
          is_shimm++;                           \
 
91
          flag = (field == 61);                 \
 
92
          field = FIELDD (state->words[0]);     \
 
93
        }                                       \
 
94
    }                                           \
 
95
  while (0)
 
96
 
 
97
#define CHECK_FIELD_A()                         \
 
98
  do                                            \
 
99
    {                                           \
 
100
      fieldA = FIELDA (state->words[0]);        \
 
101
      if (fieldA > 60)                          \
 
102
        {                                       \
 
103
          fieldAisReg = 0;                      \
 
104
          fieldA = 0;                           \
 
105
        }                                       \
 
106
    }                                           \
 
107
  while (0)
 
108
 
 
109
#define CHECK_FIELD_B()                         \
 
110
  do                                            \
 
111
    {                                           \
 
112
      fieldB = FIELDB (state->words[0]);        \
 
113
      CHECK_FIELD (fieldB);                     \
 
114
    }                                           \
 
115
  while (0)
 
116
 
 
117
#define CHECK_FIELD_C()                         \
 
118
  do                                            \
 
119
    {                                           \
 
120
      fieldC = FIELDC (state->words[0]);        \
 
121
      CHECK_FIELD (fieldC);                     \
 
122
    }                                           \
 
123
  while (0)
 
124
 
 
125
#define IS_SMALL(x) (((field##x) < 256) && ((field##x) > -257))
 
126
#define IS_REG(x)   (field##x##isReg)
 
127
#define WRITE_FORMAT_LB_Rx_RB(x)     WRITE_FORMAT(x,"[","]","","")
 
128
#define WRITE_FORMAT_x_COMMA_LB(x)   WRITE_FORMAT(x,"",",[","",",[")
 
129
#define WRITE_FORMAT_COMMA_x_RB(x)   WRITE_FORMAT(x,",","]",",","]")
 
130
#define WRITE_FORMAT_x_RB(x)         WRITE_FORMAT(x,"","]","","]")
 
131
#define WRITE_FORMAT_COMMA_x(x)      WRITE_FORMAT(x,",","",",","")
 
132
#define WRITE_FORMAT_x_COMMA(x)      WRITE_FORMAT(x,"",",","",",")
 
133
#define WRITE_FORMAT_x(x)            WRITE_FORMAT(x,"","","","")
 
134
#define WRITE_FORMAT(x,cb1,ca1,cb,ca) strcat (formatString,             \
 
135
                                     (IS_REG (x) ? cb1"%r"ca1 :         \
 
136
                                      usesAuxReg ? cb"%a"ca :           \
 
137
                                      IS_SMALL (x) ? cb"%d"ca : cb"%h"ca))
 
138
#define WRITE_FORMAT_RB()       strcat (formatString, "]")
 
139
#define WRITE_COMMENT(str)      (state->comm[state->commNum++] = (str))
 
140
#define WRITE_NOP_COMMENT()     if (!fieldAisReg && !flag) WRITE_COMMENT ("nop");
 
141
 
 
142
#define NEXT_WORD(x)    (offset += 4, state->words[x])
 
143
 
 
144
#define add_target(x)   (state->targets[state->tcnt++] = (x))
 
145
 
 
146
static char comment_prefix[] = "\t; ";
 
147
 
 
148
static const char *core_reg_name PARAMS ((struct arcDisState *, int));
 
149
static const char *aux_reg_name PARAMS ((struct arcDisState *, int));
 
150
static const char *cond_code_name PARAMS ((struct arcDisState *, int));
 
151
static const char *instruction_name
 
152
  PARAMS ((struct arcDisState *, int, int, int *));
 
153
static void mwerror PARAMS ((struct arcDisState *, const char *));
 
154
static const char *post_address PARAMS ((struct arcDisState *, int));
 
155
static void write_comments_
 
156
  PARAMS ((struct arcDisState *, int, int, long int));
 
157
static void write_instr_name_
 
158
  PARAMS ((struct arcDisState *, const char *, int, int, int, int, int, int));
 
159
static int dsmOneArcInst PARAMS ((bfd_vma, struct arcDisState *));
 
160
static const char *_coreRegName PARAMS ((void *, int));
 
161
static int decodeInstr PARAMS ((bfd_vma, disassemble_info *));
 
162
 
 
163
static const char *
 
164
core_reg_name (state, val)
 
165
     struct arcDisState * state;
 
166
     int                  val;
 
167
{
 
168
  if (state->coreRegName)
 
169
    return (*state->coreRegName)(state->_this, val);
 
170
  return 0;
 
171
}
 
172
 
 
173
static const char *
 
174
aux_reg_name (state, val)
 
175
     struct arcDisState * state;
 
176
     int                  val;
 
177
{
 
178
  if (state->auxRegName)
 
179
    return (*state->auxRegName)(state->_this, val);
 
180
  return 0;
 
181
}
 
182
 
 
183
static const char *
 
184
cond_code_name (state, val)
 
185
     struct arcDisState * state;
 
186
     int                  val;
 
187
{
 
188
  if (state->condCodeName)
 
189
    return (*state->condCodeName)(state->_this, val);
 
190
  return 0;
 
191
}
 
192
 
 
193
static const char *
 
194
instruction_name (state, op1, op2, flags)
 
195
     struct arcDisState * state;
 
196
     int    op1;
 
197
     int    op2;
 
198
     int *  flags;
 
199
{
 
200
  if (state->instName)
 
201
    return (*state->instName)(state->_this, op1, op2, flags);
 
202
  return 0;
 
203
}
 
204
 
 
205
static void
 
206
mwerror (state, msg)
 
207
     struct arcDisState * state;
 
208
     const char * msg;
 
209
{
 
210
  if (state->err != 0)
 
211
    (*state->err)(state->_this, (msg));
 
212
}
 
213
 
 
214
static const char *
 
215
post_address (state, addr)
 
216
     struct arcDisState * state;
 
217
     int addr;
 
218
{
 
219
  static char id[3 * ARRAY_SIZE (state->addresses)];
 
220
  int j, i = state->acnt;
 
221
 
 
222
  if (i < ((int) ARRAY_SIZE (state->addresses)))
 
223
    {
 
224
      state->addresses[i] = addr;
 
225
      ++state->acnt;
 
226
      j = i*3;
 
227
      id[j+0] = '@';
 
228
      id[j+1] = '0'+i;
 
229
      id[j+2] = 0;
 
230
 
 
231
      return id + j;
 
232
    }
 
233
  return "";
 
234
}
 
235
 
 
236
static void my_sprintf PARAMS ((struct arcDisState *, char *, const char *,
 
237
                                ...));
 
238
 
 
239
static void
 
240
my_sprintf VPARAMS ((struct arcDisState *state, char *buf, const char *format,
 
241
                     ...))
 
242
{
 
243
  char *bp;
 
244
  const char *p;
 
245
  int size, leading_zero, regMap[2];
 
246
  long auxNum;
 
247
 
 
248
  VA_OPEN (ap, format);
 
249
  VA_FIXEDARG (ap, struct arcDisState *, state);
 
250
  VA_FIXEDARG (ap, char *, buf);
 
251
  VA_FIXEDARG (ap, const char *, format);
 
252
 
 
253
  bp = buf;
 
254
  *bp = 0;
 
255
  p = format;
 
256
  auxNum = -1;
 
257
  regMap[0] = 0;
 
258
  regMap[1] = 0;
 
259
 
 
260
  while (1)
 
261
    switch (*p++)
 
262
      {
 
263
      case 0:
 
264
        goto DOCOMM; /* (return)  */
 
265
      default:
 
266
        *bp++ = p[-1];
 
267
        break;
 
268
      case '%':
 
269
        size = 0;
 
270
        leading_zero = 0;
 
271
      RETRY: ;
 
272
        switch (*p++)
 
273
          {
 
274
          case '0':
 
275
          case '1':
 
276
          case '2':
 
277
          case '3':
 
278
          case '4':
 
279
          case '5':
 
280
          case '6':
 
281
          case '7':
 
282
          case '8':
 
283
          case '9':
 
284
            {
 
285
              /* size.  */
 
286
              size = p[-1] - '0';
 
287
              if (size == 0)
 
288
                leading_zero = 1; /* e.g. %08x  */
 
289
              while (*p >= '0' && *p <= '9')
 
290
                {
 
291
                  size = size * 10 + *p - '0';
 
292
                  p++;
 
293
                }
 
294
              goto RETRY;
 
295
            }
 
296
#define inc_bp() bp = bp + strlen (bp)
 
297
 
 
298
          case 'h':
 
299
            {
 
300
              unsigned u = va_arg (ap, int);
 
301
 
 
302
              /* Hex.  We can change the format to 0x%08x in
 
303
                 one place, here, if we wish.
 
304
                 We add underscores for easy reading.  */
 
305
              if (u > 65536)
 
306
                sprintf (bp, "0x%x_%04x", u >> 16, u & 0xffff);
 
307
              else
 
308
                sprintf (bp, "0x%x", u);
 
309
              inc_bp ();
 
310
            }
 
311
            break;
 
312
          case 'X': case 'x':
 
313
            {
 
314
              int val = va_arg (ap, int);
 
315
 
 
316
              if (size != 0)
 
317
                if (leading_zero)
 
318
                  sprintf (bp, "%0*x", size, val);
 
319
                else
 
320
                  sprintf (bp, "%*x", size, val);
 
321
              else
 
322
                sprintf (bp, "%x", val);
 
323
              inc_bp ();
 
324
            }
 
325
            break;
 
326
          case 'd':
 
327
            {
 
328
              int val = va_arg (ap, int);
 
329
 
 
330
              if (size != 0)
 
331
                sprintf (bp, "%*d", size, val);
 
332
              else
 
333
                sprintf (bp, "%d", val);
 
334
              inc_bp ();
 
335
            }
 
336
            break;
 
337
          case 'r':
 
338
            {
 
339
              /* Register.  */
 
340
              int val = va_arg (ap, int);
 
341
 
 
342
#define REG2NAME(num, name) case num: sprintf (bp, ""name); \
 
343
  regMap[(num < 32) ? 0 : 1] |= 1 << (num - ((num < 32) ? 0 : 32)); break;
 
344
 
 
345
              switch (val)
 
346
                {
 
347
                  REG2NAME (26, "gp");
 
348
                  REG2NAME (27, "fp");
 
349
                  REG2NAME (28, "sp");
 
350
                  REG2NAME (29, "ilink1");
 
351
                  REG2NAME (30, "ilink2");
 
352
                  REG2NAME (31, "blink");
 
353
                  REG2NAME (60, "lp_count");
 
354
                default:
 
355
                  {
 
356
                    const char * ext;
 
357
 
 
358
                    ext = core_reg_name (state, val);
 
359
                    if (ext)
 
360
                      sprintf (bp, "%s", ext);
 
361
                    else
 
362
                      sprintf (bp,"r%d",val);
 
363
                  }
 
364
                  break;
 
365
                }
 
366
              inc_bp ();
 
367
            } break;
 
368
 
 
369
          case 'a':
 
370
            {
 
371
              /* Aux Register.  */
 
372
              int val = va_arg (ap, int);
 
373
 
 
374
#define AUXREG2NAME(num, name) case num: sprintf (bp,name); break;
 
375
 
 
376
              switch (val)
 
377
                {
 
378
                  AUXREG2NAME (0x0, "status");
 
379
                  AUXREG2NAME (0x1, "semaphore");
 
380
                  AUXREG2NAME (0x2, "lp_start");
 
381
                  AUXREG2NAME (0x3, "lp_end");
 
382
                  AUXREG2NAME (0x4, "identity");
 
383
                  AUXREG2NAME (0x5, "debug");
 
384
                default:
 
385
                  {
 
386
                    const char *ext;
 
387
 
 
388
                    ext = aux_reg_name (state, val);
 
389
                    if (ext)
 
390
                      sprintf (bp, "%s", ext);
 
391
                    else
 
392
                      my_sprintf (state, bp, "%h", val);
 
393
                  }
 
394
                  break;
 
395
                }
 
396
              inc_bp ();
 
397
            }
 
398
            break;
 
399
 
 
400
          case 's':
 
401
            {
 
402
              sprintf (bp, "%s", va_arg (ap, char *));
 
403
              inc_bp ();
 
404
            }
 
405
            break;
 
406
 
 
407
          default:
 
408
            fprintf (stderr, "?? format %c\n", p[-1]);
 
409
            break;
 
410
          }
 
411
      }
 
412
 
 
413
 DOCOMM: *bp = 0;
 
414
  VA_CLOSE (ap);
 
415
}
 
416
 
 
417
static void
 
418
write_comments_(state, shimm, is_limm, limm_value)
 
419
     struct arcDisState * state;
 
420
     int shimm;
 
421
     int is_limm;
 
422
     long limm_value;
 
423
{
 
424
  if (state->commentBuffer != 0)
 
425
    {
 
426
      int i;
 
427
 
 
428
      if (is_limm)
 
429
        {
 
430
          const char *name = post_address (state, limm_value + shimm);
 
431
 
 
432
          if (*name != 0)
 
433
            WRITE_COMMENT (name);
 
434
        }
 
435
      for (i = 0; i < state->commNum; i++)
 
436
        {
 
437
          if (i == 0)
 
438
            strcpy (state->commentBuffer, comment_prefix);
 
439
          else
 
440
            strcat (state->commentBuffer, ", ");
 
441
          strncat (state->commentBuffer, state->comm[i],
 
442
                   sizeof (state->commentBuffer));
 
443
        }
 
444
    }
 
445
}
 
446
 
 
447
#define write_comments2(x) write_comments_(state, x, is_limm, limm_value)
 
448
#define write_comments() write_comments2(0)
 
449
 
 
450
static const char *condName[] = {
 
451
  /* 0..15.  */
 
452
  ""   , "z"  , "nz" , "p"  , "n"  , "c"  , "nc" , "v"  ,
 
453
  "nv" , "gt" , "ge" , "lt" , "le" , "hi" , "ls" , "pnz"
 
454
};
 
455
 
 
456
static void
 
457
write_instr_name_(state, instrName, cond, condCodeIsPartOfName, flag, signExtend, addrWriteBack, directMem)
 
458
     struct arcDisState * state;
 
459
     const char * instrName;
 
460
     int cond;
 
461
     int condCodeIsPartOfName;
 
462
     int flag;
 
463
     int signExtend;
 
464
     int addrWriteBack;
 
465
     int directMem;
 
466
{
 
467
  strcpy (state->instrBuffer, instrName);
 
468
 
 
469
  if (cond > 0)
 
470
    {
 
471
      const char *cc = 0;
 
472
 
 
473
      if (!condCodeIsPartOfName)
 
474
        strcat (state->instrBuffer, ".");
 
475
 
 
476
      if (cond < 16)
 
477
        cc = condName[cond];
 
478
      else
 
479
        cc = cond_code_name (state, cond);
 
480
 
 
481
      if (!cc)
 
482
        cc = "???";
 
483
 
 
484
      strcat (state->instrBuffer, cc);
 
485
    }
 
486
 
 
487
  if (flag)
 
488
    strcat (state->instrBuffer, ".f");
 
489
 
 
490
  switch (state->nullifyMode)
 
491
    {
 
492
    case BR_exec_always:
 
493
      strcat (state->instrBuffer, ".d");
 
494
      break;
 
495
    case BR_exec_when_jump:
 
496
      strcat (state->instrBuffer, ".jd");
 
497
      break;
 
498
    }
 
499
 
 
500
  if (signExtend)
 
501
    strcat (state->instrBuffer, ".x");
 
502
 
 
503
  if (addrWriteBack)
 
504
    strcat (state->instrBuffer, ".a");
 
505
 
 
506
  if (directMem)
 
507
    strcat (state->instrBuffer, ".di");
 
508
}
 
509
 
 
510
#define write_instr_name()                                              \
 
511
  do                                                                    \
 
512
    {                                                                   \
 
513
      write_instr_name_(state, instrName,cond, condCodeIsPartOfName,    \
 
514
                        flag, signExtend, addrWriteBack, directMem);    \
 
515
      formatString[0] = '\0';                                           \
 
516
    }                                                                   \
 
517
  while (0)
 
518
 
 
519
enum {
 
520
  op_LD0 = 0, op_LD1 = 1, op_ST  = 2, op_3   = 3,
 
521
  op_BC  = 4, op_BLC = 5, op_LPC = 6, op_JC  = 7,
 
522
  op_ADD = 8, op_ADC = 9, op_SUB = 10, op_SBC = 11,
 
523
  op_AND = 12, op_OR  = 13, op_BIC = 14, op_XOR = 15
 
524
};
 
525
 
 
526
extern disassemble_info tm_print_insn_info;
 
527
 
 
528
static int
 
529
dsmOneArcInst (addr, state)
 
530
     bfd_vma              addr;
 
531
     struct arcDisState * state;
 
532
{
 
533
  int condCodeIsPartOfName = 0;
 
534
  int decodingClass;
 
535
  const char * instrName;
 
536
  int repeatsOp = 0;
 
537
  int fieldAisReg = 1;
 
538
  int fieldBisReg = 1;
 
539
  int fieldCisReg = 1;
 
540
  int fieldA;
 
541
  int fieldB;
 
542
  int fieldC = 0;
 
543
  int flag = 0;
 
544
  int cond = 0;
 
545
  int is_shimm = 0;
 
546
  int is_limm = 0;
 
547
  long limm_value = 0;
 
548
  int signExtend = 0;
 
549
  int addrWriteBack = 0;
 
550
  int directMem = 0;
 
551
  int is_linked = 0;
 
552
  int offset = 0;
 
553
  int usesAuxReg = 0;
 
554
  int flags;
 
555
  int ignoreFirstOpd;
 
556
  char formatString[60];
 
557
 
 
558
  state->instructionLen = 4;
 
559
  state->nullifyMode = BR_exec_when_no_jump;
 
560
  state->opWidth = 12;
 
561
  state->isBranch = 0;
 
562
 
 
563
  state->_mem_load = 0;
 
564
  state->_ea_present = 0;
 
565
  state->_load_len = 0;
 
566
  state->ea_reg1 = no_reg;
 
567
  state->ea_reg2 = no_reg;
 
568
  state->_offset = 0;
 
569
 
 
570
  if (! NEXT_WORD (0))
 
571
    return 0;
 
572
 
 
573
  state->_opcode = OPCODE (state->words[0]);
 
574
  instrName = 0;
 
575
  decodingClass = 0; /* default!  */
 
576
  repeatsOp = 0;
 
577
  condCodeIsPartOfName=0;
 
578
  state->commNum = 0;
 
579
  state->tcnt = 0;
 
580
  state->acnt = 0;
 
581
  state->flow = noflow;
 
582
  ignoreFirstOpd = 0;
 
583
 
 
584
  if (state->commentBuffer)
 
585
    state->commentBuffer[0] = '\0';
 
586
 
 
587
  switch (state->_opcode)
 
588
    {
 
589
    case op_LD0:
 
590
      switch (BITS (state->words[0],1,2))
 
591
        {
 
592
        case 0:
 
593
          instrName = "ld";
 
594
          state->_load_len = 4;
 
595
          break;
 
596
        case 1:
 
597
          instrName = "ldb";
 
598
          state->_load_len = 1;
 
599
          break;
 
600
        case 2:
 
601
          instrName = "ldw";
 
602
          state->_load_len = 2;
 
603
          break;
 
604
        default:
 
605
          instrName = "??? (0[3])";
 
606
          state->flow = invalid_instr;
 
607
          break;
 
608
        }
 
609
      decodingClass = 5;
 
610
      break;
 
611
 
 
612
    case op_LD1:
 
613
      if (BIT (state->words[0],13))
 
614
        {
 
615
          instrName = "lr";
 
616
          decodingClass = 10;
 
617
        }
 
618
      else
 
619
        {
 
620
          switch (BITS (state->words[0],10,11))
 
621
            {
 
622
            case 0:
 
623
              instrName = "ld";
 
624
              state->_load_len = 4;
 
625
              break;
 
626
            case 1:
 
627
              instrName = "ldb";
 
628
              state->_load_len = 1;
 
629
              break;
 
630
            case 2:
 
631
              instrName = "ldw";
 
632
              state->_load_len = 2;
 
633
              break;
 
634
            default:
 
635
              instrName = "??? (1[3])";
 
636
              state->flow = invalid_instr;
 
637
              break;
 
638
            }
 
639
          decodingClass = 6;
 
640
        }
 
641
      break;
 
642
 
 
643
    case op_ST:
 
644
      if (BIT (state->words[0],25))
 
645
        {
 
646
          instrName = "sr";
 
647
          decodingClass = 8;
 
648
        }
 
649
      else
 
650
        {
 
651
          switch (BITS (state->words[0],22,23))
 
652
            {
 
653
            case 0:
 
654
              instrName = "st";
 
655
              break;
 
656
            case 1:
 
657
              instrName = "stb";
 
658
              break;
 
659
            case 2:
 
660
              instrName = "stw";
 
661
              break;
 
662
            default:
 
663
              instrName = "??? (2[3])";
 
664
              state->flow = invalid_instr;
 
665
              break;
 
666
            }
 
667
          decodingClass = 7;
 
668
        }
 
669
      break;
 
670
 
 
671
    case op_3:
 
672
      decodingClass = 1;  /* default for opcode 3...  */
 
673
      switch (FIELDC (state->words[0]))
 
674
        {
 
675
        case  0:
 
676
          instrName = "flag";
 
677
          decodingClass = 2;
 
678
          break;
 
679
        case  1:
 
680
          instrName = "asr";
 
681
          break;
 
682
        case  2:
 
683
          instrName = "lsr";
 
684
          break;
 
685
        case  3:
 
686
          instrName = "ror";
 
687
          break;
 
688
        case  4:
 
689
          instrName = "rrc";
 
690
          break;
 
691
        case  5:
 
692
          instrName = "sexb";
 
693
          break;
 
694
        case  6:
 
695
          instrName = "sexw";
 
696
          break;
 
697
        case  7:
 
698
          instrName = "extb";
 
699
          break;
 
700
        case  8:
 
701
          instrName = "extw";
 
702
          break;
 
703
        case  0x3f:
 
704
          {
 
705
            decodingClass = 9;
 
706
            switch( FIELDD (state->words[0]) )
 
707
              {
 
708
              case 0:
 
709
                instrName = "brk";
 
710
                break;
 
711
              case 1:
 
712
                instrName = "sleep";
 
713
                break;
 
714
              case 2:
 
715
                instrName = "swi";
 
716
                break;
 
717
              default:
 
718
                instrName = "???";
 
719
                state->flow=invalid_instr;
 
720
                break;
 
721
              }
 
722
          }
 
723
          break;
 
724
 
 
725
          /* ARC Extension Library Instructions
 
726
             NOTE: We assume that extension codes are these instrs.  */
 
727
        default:
 
728
          instrName = instruction_name (state,
 
729
                                        state->_opcode,
 
730
                                        FIELDC (state->words[0]),
 
731
                                        &flags);
 
732
          if (!instrName)
 
733
            {
 
734
              instrName = "???";
 
735
              state->flow = invalid_instr;
 
736
            }
 
737
          if (flags & IGNORE_FIRST_OPD)
 
738
            ignoreFirstOpd = 1;
 
739
          break;
 
740
        }
 
741
      break;
 
742
 
 
743
    case op_BC:
 
744
      instrName = "b";
 
745
    case op_BLC:
 
746
      if (!instrName)
 
747
        instrName = "bl";
 
748
    case op_LPC:
 
749
      if (!instrName)
 
750
        instrName = "lp";
 
751
    case op_JC:
 
752
      if (!instrName)
 
753
        {
 
754
          if (BITS (state->words[0],9,9))
 
755
            {
 
756
              instrName = "jl";
 
757
              is_linked = 1;
 
758
            }
 
759
          else
 
760
            {
 
761
              instrName = "j";
 
762
              is_linked = 0;
 
763
            }
 
764
        }
 
765
      condCodeIsPartOfName = 1;
 
766
      decodingClass = ((state->_opcode == op_JC) ? 4 : 3);
 
767
      state->isBranch = 1;
 
768
      break;
 
769
 
 
770
    case op_ADD:
 
771
    case op_ADC:
 
772
    case op_AND:
 
773
      repeatsOp = (FIELDC (state->words[0]) == FIELDB (state->words[0]));
 
774
      decodingClass = 0;
 
775
 
 
776
      switch (state->_opcode)
 
777
        {
 
778
        case op_ADD:
 
779
          instrName = (repeatsOp ? "asl" : "add");
 
780
          break;
 
781
        case op_ADC:
 
782
          instrName = (repeatsOp ? "rlc" : "adc");
 
783
          break;
 
784
        case op_AND:
 
785
          instrName = (repeatsOp ? "mov" : "and");
 
786
          break;
 
787
        }
 
788
      break;
 
789
 
 
790
    case op_SUB: instrName = "sub";
 
791
      break;
 
792
    case op_SBC: instrName = "sbc";
 
793
      break;
 
794
    case op_OR:  instrName = "or";
 
795
      break;
 
796
    case op_BIC: instrName = "bic";
 
797
      break;
 
798
 
 
799
    case op_XOR:
 
800
      if (state->words[0] == 0x7fffffff)
 
801
        {
 
802
          /* nop encoded as xor -1, -1, -1  */
 
803
          instrName = "nop";
 
804
          decodingClass = 9;
 
805
        }
 
806
      else
 
807
        instrName = "xor";
 
808
      break;
 
809
 
 
810
    default:
 
811
      instrName = instruction_name (state,state->_opcode,0,&flags);
 
812
      /* if (instrName) printf("FLAGS=0x%x\n", flags);  */
 
813
      if (!instrName)
 
814
        {
 
815
          instrName = "???";
 
816
          state->flow=invalid_instr;
 
817
        }
 
818
      if (flags & IGNORE_FIRST_OPD)
 
819
        ignoreFirstOpd = 1;
 
820
      break;
 
821
    }
 
822
 
 
823
  fieldAisReg = fieldBisReg = fieldCisReg = 1; /* Assume regs for now.  */
 
824
  flag = cond = is_shimm = is_limm = 0;
 
825
  state->nullifyMode = BR_exec_when_no_jump;    /* 0  */
 
826
  signExtend = addrWriteBack = directMem = 0;
 
827
  usesAuxReg = 0;
 
828
 
 
829
  switch (decodingClass)
 
830
    {
 
831
    case 0:
 
832
      CHECK_FIELD_A ();
 
833
      CHECK_FIELD_B ();
 
834
      if (!repeatsOp)
 
835
        CHECK_FIELD_C ();
 
836
      CHECK_FLAG_COND_NULLIFY ();
 
837
 
 
838
      write_instr_name ();
 
839
      if (!ignoreFirstOpd)
 
840
        {
 
841
          WRITE_FORMAT_x (A);
 
842
          WRITE_FORMAT_COMMA_x (B);
 
843
          if (!repeatsOp)
 
844
            WRITE_FORMAT_COMMA_x (C);
 
845
          WRITE_NOP_COMMENT ();
 
846
          my_sprintf (state, state->operandBuffer, formatString,
 
847
                      fieldA, fieldB, fieldC);
 
848
        }
 
849
      else
 
850
        {
 
851
          WRITE_FORMAT_x (B);
 
852
          if (!repeatsOp)
 
853
            WRITE_FORMAT_COMMA_x (C);
 
854
          my_sprintf (state, state->operandBuffer, formatString,
 
855
                      fieldB, fieldC);
 
856
        }
 
857
      write_comments ();
 
858
      break;
 
859
 
 
860
    case 1:
 
861
      CHECK_FIELD_A ();
 
862
      CHECK_FIELD_B ();
 
863
      CHECK_FLAG_COND_NULLIFY ();
 
864
 
 
865
      write_instr_name ();
 
866
      if (!ignoreFirstOpd)
 
867
        {
 
868
          WRITE_FORMAT_x (A);
 
869
          WRITE_FORMAT_COMMA_x (B);
 
870
          WRITE_NOP_COMMENT ();
 
871
          my_sprintf (state, state->operandBuffer, formatString,
 
872
                      fieldA, fieldB);
 
873
        }
 
874
      else
 
875
        {
 
876
          WRITE_FORMAT_x (B);
 
877
          my_sprintf (state, state->operandBuffer, formatString, fieldB);
 
878
        }
 
879
      write_comments ();
 
880
      break;
 
881
 
 
882
    case 2:
 
883
      CHECK_FIELD_B ();
 
884
      CHECK_FLAG_COND_NULLIFY ();
 
885
      flag = 0; /* this is the FLAG instruction -- it's redundant  */
 
886
 
 
887
      write_instr_name ();
 
888
      WRITE_FORMAT_x (B);
 
889
      my_sprintf (state, state->operandBuffer, formatString, fieldB);
 
890
      write_comments ();
 
891
      break;
 
892
 
 
893
    case 3:
 
894
      fieldA = BITS (state->words[0],7,26) << 2;
 
895
      fieldA = (fieldA << 10) >> 10; /* make it signed  */
 
896
      fieldA += addr + 4;
 
897
      CHECK_FLAG_COND_NULLIFY ();
 
898
      flag = 0;
 
899
 
 
900
      write_instr_name ();
 
901
      /* This address could be a label we know. Convert it.  */
 
902
      if (state->_opcode != op_LPC /* LP  */)
 
903
        {
 
904
          add_target (fieldA); /* For debugger.  */
 
905
          state->flow = state->_opcode == op_BLC /* BL  */
 
906
            ? direct_call
 
907
            : direct_jump;
 
908
          /* indirect calls are achieved by "lr blink,[status];
 
909
             lr dest<- func addr; j [dest]"  */
 
910
        }
 
911
 
 
912
      strcat (formatString, "%s"); /* address/label name */
 
913
      my_sprintf (state, state->operandBuffer, formatString,
 
914
                  post_address (state, fieldA));
 
915
      write_comments ();
 
916
      break;
 
917
 
 
918
    case 4:
 
919
      /* For op_JC -- jump to address specified.
 
920
         Also covers jump and link--bit 9 of the instr. word
 
921
         selects whether linked, thus "is_linked" is set above.  */
 
922
      fieldA = 0;
 
923
      CHECK_FIELD_B ();
 
924
      CHECK_FLAG_COND_NULLIFY ();
 
925
 
 
926
      if (!fieldBisReg)
 
927
        {
 
928
          fieldAisReg = 0;
 
929
          fieldA = (fieldB >> 25) & 0x7F; /* flags */
 
930
          fieldB = (fieldB & 0xFFFFFF) << 2;
 
931
          state->flow = is_linked ? direct_call : direct_jump;
 
932
          add_target (fieldB);
 
933
          /* screwy JLcc requires .jd mode to execute correctly
 
934
           * but we pretend it is .nd (no delay slot).  */
 
935
          if (is_linked && state->nullifyMode == BR_exec_when_jump)
 
936
            state->nullifyMode = BR_exec_when_no_jump;
 
937
        }
 
938
      else
 
939
        {
 
940
          state->flow = is_linked ? indirect_call : indirect_jump;
 
941
          /* We should also treat this as indirect call if NOT linked
 
942
           * but the preceding instruction was a "lr blink,[status]"
 
943
           * and we have a delay slot with "add blink,blink,2".
 
944
           * For now we can't detect such.  */
 
945
          state->register_for_indirect_jump = fieldB;
 
946
        }
 
947
 
 
948
      write_instr_name ();
 
949
      strcat (formatString,
 
950
              IS_REG (B) ? "[%r]" : "%s"); /* address/label name  */
 
951
      if (fieldA != 0)
 
952
        {
 
953
          fieldAisReg = 0;
 
954
          WRITE_FORMAT_COMMA_x (A);
 
955
        }
 
956
      if (IS_REG (B))
 
957
        my_sprintf (state, state->operandBuffer, formatString, fieldB, fieldA);
 
958
      else
 
959
        my_sprintf (state, state->operandBuffer, formatString,
 
960
                    post_address (state, fieldB), fieldA);
 
961
      write_comments ();
 
962
      break;
 
963
 
 
964
    case 5:
 
965
      /* LD instruction.
 
966
         B and C can be regs, or one (both?) can be limm.  */
 
967
      CHECK_FIELD_A ();
 
968
      CHECK_FIELD_B ();
 
969
      CHECK_FIELD_C ();
 
970
      if (dbg)
 
971
        printf ("5:b reg %d %d c reg %d %d  \n",
 
972
                fieldBisReg,fieldB,fieldCisReg,fieldC);
 
973
      state->_offset = 0;
 
974
      state->_ea_present = 1;
 
975
      if (fieldBisReg)
 
976
        state->ea_reg1 = fieldB;
 
977
      else
 
978
        state->_offset += fieldB;
 
979
      if (fieldCisReg)
 
980
        state->ea_reg2 = fieldC;
 
981
      else
 
982
        state->_offset += fieldC;
 
983
      state->_mem_load = 1;
 
984
 
 
985
      directMem     = BIT (state->words[0],5);
 
986
      addrWriteBack = BIT (state->words[0],3);
 
987
      signExtend    = BIT (state->words[0],0);
 
988
 
 
989
      write_instr_name ();
 
990
      WRITE_FORMAT_x_COMMA_LB(A);
 
991
      if (fieldBisReg || fieldB != 0)
 
992
        WRITE_FORMAT_x_COMMA (B);
 
993
      else
 
994
        fieldB = fieldC;
 
995
 
 
996
      WRITE_FORMAT_x_RB (C);
 
997
      my_sprintf (state, state->operandBuffer, formatString,
 
998
                  fieldA, fieldB, fieldC);
 
999
      write_comments ();
 
1000
      break;
 
1001
 
 
1002
    case 6:
 
1003
      /* LD instruction.  */
 
1004
      CHECK_FIELD_B ();
 
1005
      CHECK_FIELD_A ();
 
1006
      fieldC = FIELDD (state->words[0]);
 
1007
 
 
1008
      if (dbg)
 
1009
        printf ("6:b reg %d %d c 0x%x  \n",
 
1010
                fieldBisReg, fieldB, fieldC);
 
1011
      state->_ea_present = 1;
 
1012
      state->_offset = fieldC;
 
1013
      state->_mem_load = 1;
 
1014
      if (fieldBisReg)
 
1015
        state->ea_reg1 = fieldB;
 
1016
      /* field B is either a shimm (same as fieldC) or limm (different!)
 
1017
         Say ea is not present, so only one of us will do the name lookup.  */
 
1018
      else
 
1019
        state->_offset += fieldB, state->_ea_present = 0;
 
1020
 
 
1021
      directMem     = BIT (state->words[0],14);
 
1022
      addrWriteBack = BIT (state->words[0],12);
 
1023
      signExtend    = BIT (state->words[0],9);
 
1024
 
 
1025
      write_instr_name ();
 
1026
      WRITE_FORMAT_x_COMMA_LB (A);
 
1027
      if (!fieldBisReg)
 
1028
        {
 
1029
          fieldB = state->_offset;
 
1030
          WRITE_FORMAT_x_RB (B);
 
1031
        }
 
1032
      else
 
1033
        {
 
1034
          WRITE_FORMAT_x (B);
 
1035
          if (fieldC != 0 && !BIT (state->words[0],13))
 
1036
            {
 
1037
              fieldCisReg = 0;
 
1038
              WRITE_FORMAT_COMMA_x_RB (C);
 
1039
            }
 
1040
          else
 
1041
            WRITE_FORMAT_RB ();
 
1042
        }
 
1043
      my_sprintf (state, state->operandBuffer, formatString,
 
1044
                  fieldA, fieldB, fieldC);
 
1045
      write_comments ();
 
1046
      break;
 
1047
 
 
1048
    case 7:
 
1049
      /* ST instruction.  */
 
1050
      CHECK_FIELD_B();
 
1051
      CHECK_FIELD_C();
 
1052
      fieldA = FIELDD(state->words[0]); /* shimm  */
 
1053
 
 
1054
      /* [B,A offset]  */
 
1055
      if (dbg) printf("7:b reg %d %x off %x\n",
 
1056
                      fieldBisReg,fieldB,fieldA);
 
1057
      state->_ea_present = 1;
 
1058
      state->_offset = fieldA;
 
1059
      if (fieldBisReg)
 
1060
        state->ea_reg1 = fieldB;
 
1061
      /* field B is either a shimm (same as fieldA) or limm (different!)
 
1062
         Say ea is not present, so only one of us will do the name lookup.
 
1063
         (for is_limm we do the name translation here).  */
 
1064
      else
 
1065
        state->_offset += fieldB, state->_ea_present = 0;
 
1066
 
 
1067
      directMem     = BIT(state->words[0],26);
 
1068
      addrWriteBack = BIT(state->words[0],24);
 
1069
 
 
1070
      write_instr_name();
 
1071
      WRITE_FORMAT_x_COMMA_LB(C);
 
1072
 
 
1073
      if (!fieldBisReg)
 
1074
        {
 
1075
          fieldB = state->_offset;
 
1076
          WRITE_FORMAT_x_RB(B);
 
1077
        }
 
1078
      else
 
1079
        {
 
1080
          WRITE_FORMAT_x(B);
 
1081
          if (fieldBisReg && fieldA != 0)
 
1082
            {
 
1083
              fieldAisReg = 0;
 
1084
              WRITE_FORMAT_COMMA_x_RB(A);
 
1085
            }
 
1086
          else
 
1087
            WRITE_FORMAT_RB();
 
1088
        }
 
1089
      my_sprintf (state, state->operandBuffer, formatString,
 
1090
                  fieldC, fieldB, fieldA);
 
1091
      write_comments2(fieldA);
 
1092
      break;
 
1093
    case 8:
 
1094
      /* SR instruction  */
 
1095
      CHECK_FIELD_B();
 
1096
      CHECK_FIELD_C();
 
1097
 
 
1098
      write_instr_name();
 
1099
      WRITE_FORMAT_x_COMMA_LB(C);
 
1100
      /* Try to print B as an aux reg if it is not a core reg.  */
 
1101
      usesAuxReg = 1;
 
1102
      WRITE_FORMAT_x(B);
 
1103
      WRITE_FORMAT_RB();
 
1104
      my_sprintf (state, state->operandBuffer, formatString, fieldC, fieldB);
 
1105
      write_comments();
 
1106
      break;
 
1107
 
 
1108
    case 9:
 
1109
      write_instr_name();
 
1110
      state->operandBuffer[0] = '\0';
 
1111
      break;
 
1112
 
 
1113
    case 10:
 
1114
      /* LR instruction */
 
1115
      CHECK_FIELD_A();
 
1116
      CHECK_FIELD_B();
 
1117
 
 
1118
      write_instr_name();
 
1119
      WRITE_FORMAT_x_COMMA_LB(A);
 
1120
      /* Try to print B as an aux reg if it is not a core reg. */
 
1121
      usesAuxReg = 1;
 
1122
      WRITE_FORMAT_x(B);
 
1123
      WRITE_FORMAT_RB();
 
1124
      my_sprintf (state, state->operandBuffer, formatString, fieldA, fieldB);
 
1125
      write_comments();
 
1126
      break;
 
1127
 
 
1128
    case 11:
 
1129
      CHECK_COND();
 
1130
      write_instr_name();
 
1131
      state->operandBuffer[0] = '\0';
 
1132
      break;
 
1133
 
 
1134
    default:
 
1135
      mwerror (state, "Bad decoding class in ARC disassembler");
 
1136
      break;
 
1137
    }
 
1138
 
 
1139
  state->_cond = cond;
 
1140
  return state->instructionLen = offset;
 
1141
}
 
1142
 
 
1143
 
 
1144
/* Returns the name the user specified core extension register.  */
 
1145
static const char *
 
1146
_coreRegName(arg, regval)
 
1147
     void * arg ATTRIBUTE_UNUSED;
 
1148
     int regval;
 
1149
{
 
1150
  return arcExtMap_coreRegName (regval);
 
1151
}
 
1152
 
 
1153
/* Returns the name the user specified AUX extension register.  */
 
1154
static const char *
 
1155
_auxRegName(void *_this ATTRIBUTE_UNUSED, int regval)
 
1156
{
 
1157
  return arcExtMap_auxRegName(regval);
 
1158
}
 
1159
 
 
1160
 
 
1161
/* Returns the name the user specified condition code name.  */
 
1162
static const char *
 
1163
_condCodeName(void *_this ATTRIBUTE_UNUSED, int regval)
 
1164
{
 
1165
  return arcExtMap_condCodeName(regval);
 
1166
}
 
1167
 
 
1168
/* Returns the name the user specified extension instruction.  */
 
1169
static const char *
 
1170
_instName (void *_this ATTRIBUTE_UNUSED, int majop, int minop, int *flags)
 
1171
{
 
1172
  return arcExtMap_instName(majop, minop, flags);
 
1173
}
 
1174
 
 
1175
/* Decode an instruction returning the size of the instruction
 
1176
   in bytes or zero if unrecognized.  */
 
1177
static int
 
1178
decodeInstr (address, info)
 
1179
     bfd_vma            address; /* Address of this instruction.  */
 
1180
     disassemble_info * info;
 
1181
{
 
1182
  int status;
 
1183
  bfd_byte buffer[4];
 
1184
  struct arcDisState s; /* ARC Disassembler state  */
 
1185
  void *stream = info->stream; /* output stream  */
 
1186
  fprintf_ftype func = info->fprintf_func;
 
1187
  int bytes;
 
1188
 
 
1189
  memset (&s, 0, sizeof(struct arcDisState));
 
1190
 
 
1191
  /* read first instruction  */
 
1192
  status = (*info->read_memory_func) (address, buffer, 4, info);
 
1193
  if (status != 0)
 
1194
    {
 
1195
      (*info->memory_error_func) (status, address, info);
 
1196
      return 0;
 
1197
    }
 
1198
  if (info->endian == BFD_ENDIAN_LITTLE)
 
1199
    s.words[0] = bfd_getl32(buffer);
 
1200
  else
 
1201
    s.words[0] = bfd_getb32(buffer);
 
1202
  /* always read second word in case of limm  */
 
1203
 
 
1204
  /* we ignore the result since last insn may not have a limm  */
 
1205
  status = (*info->read_memory_func) (address + 4, buffer, 4, info);
 
1206
  if (info->endian == BFD_ENDIAN_LITTLE)
 
1207
    s.words[1] = bfd_getl32(buffer);
 
1208
  else
 
1209
    s.words[1] = bfd_getb32(buffer);
 
1210
 
 
1211
  s._this = &s;
 
1212
  s.coreRegName = _coreRegName;
 
1213
  s.auxRegName = _auxRegName;
 
1214
  s.condCodeName = _condCodeName;
 
1215
  s.instName = _instName;
 
1216
 
 
1217
  /* disassemble  */
 
1218
  bytes = dsmOneArcInst(address, (void *)&s);
 
1219
 
 
1220
  /* display the disassembly instruction  */
 
1221
  (*func) (stream, "%08x ", s.words[0]);
 
1222
  (*func) (stream, "    ");
 
1223
 
 
1224
  (*func) (stream, "%-10s ", s.instrBuffer);
 
1225
 
 
1226
  if (__TRANSLATION_REQUIRED(s))
 
1227
    {
 
1228
      bfd_vma addr = s.addresses[s.operandBuffer[1] - '0'];
 
1229
      (*info->print_address_func) ((bfd_vma) addr, info);
 
1230
      (*func) (stream, "\n");
 
1231
    }
 
1232
  else
 
1233
    (*func) (stream, "%s",s.operandBuffer);
 
1234
  return s.instructionLen;
 
1235
}
 
1236
 
 
1237
/* Return the print_insn function to use.
 
1238
   Side effect: load (possibly empty) extension section  */
 
1239
 
 
1240
disassembler_ftype
 
1241
arc_get_disassembler (void *ptr)
 
1242
{
 
1243
  if (ptr)
 
1244
    build_ARC_extmap (ptr);
 
1245
  return decodeInstr;
 
1246
}