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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [arc-dis.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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