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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [opcodes/] [arc-dis.c] - Blame information for rev 818

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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