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

Subversion Repositories open8_urisc

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

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

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

powered by: WebSVN 2.1.0

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