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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [gdb-5.3/] [opcodes/] [arc-dis.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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