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

Subversion Repositories open8_urisc

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

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

Line No. Rev Author Line
1 18 khays
/* Print National Semiconductor 32000 instructions.
2
   Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005, 2007,
3
   2009  Free Software Foundation, Inc.
4
 
5
   This file is part of the GNU opcodes library.
6
 
7
   This library is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3, or (at your option)
10
   any later version.
11
 
12
   It is distributed in the hope that it will be useful, but WITHOUT
13
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15
   License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
#include "sysdep.h"
23
#include "bfd.h"
24
#include "dis-asm.h"
25
#if !defined(const) && !defined(__STDC__)
26
#define const
27
#endif
28
#include "opcode/ns32k.h"
29
#include "opintl.h"
30
 
31
static disassemble_info *dis_info;
32
 
33
/* Hacks to get it to compile <= READ THESE AS FIXES NEEDED.  */
34
#define INVALID_FLOAT(val, size) invalid_float ((bfd_byte *) val, size)
35
 
36
static long
37
read_memory_integer (unsigned char * addr, int nr)
38
{
39
  long val;
40
  int i;
41
 
42
  for (val = 0, i = nr - 1; i >= 0; i--)
43
    {
44
      val =  (val << 8);
45
      val |= (0xff & *(addr + i));
46
    }
47
  return val;
48
}
49
 
50
/* 32000 instructions are never longer than this.  */
51
#define MAXLEN 62
52
 
53
#include <setjmp.h>
54
 
55
struct private
56
{
57
  /* Points to first byte not fetched.  */
58
  bfd_byte *max_fetched;
59
  bfd_byte the_buffer[MAXLEN];
60
  bfd_vma insn_start;
61
  jmp_buf bailout;
62
};
63
 
64
 
65
/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
66
   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
67
   on error.  */
68
#define FETCH_DATA(info, addr) \
69
  ((addr) <= ((struct private *)(info->private_data))->max_fetched \
70
   ? 1 : fetch_data ((info), (addr)))
71
 
72
static int
73
fetch_data (struct disassemble_info *info, bfd_byte *addr)
74
{
75
  int status;
76
  struct private *priv = (struct private *) info->private_data;
77
  bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
78
 
79
  status = (*info->read_memory_func) (start,
80
                                      priv->max_fetched,
81
                                      addr - priv->max_fetched,
82
                                      info);
83
  if (status != 0)
84
    {
85
      (*info->memory_error_func) (status, start, info);
86
      longjmp (priv->bailout, 1);
87
    }
88
  else
89
    priv->max_fetched = addr;
90
  return 1;
91
}
92
 
93
/* Number of elements in the opcode table.  */
94
#define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
95
 
96
#define NEXT_IS_ADDR    '|'
97
 
98
 
99
struct ns32k_option
100
{
101
  char *pattern;                /* The option itself.  */
102
  unsigned long value;          /* Binary value of the option.  */
103
  unsigned long match;          /* These bits must match.  */
104
};
105
 
106
 
107
static const struct ns32k_option opt_u[]= /* Restore, exit.  */
108
{
109
  { "r0",       0x80,   0x80    },
110
  { "r1",       0x40,   0x40    },
111
  { "r2",       0x20,   0x20    },
112
  { "r3",       0x10,   0x10    },
113
  { "r4",       0x08,   0x08    },
114
  { "r5",       0x04,   0x04    },
115
  { "r6",       0x02,   0x02    },
116
  { "r7",       0x01,   0x01    },
117
  {  0 , 0x00,   0x00    }
118
};
119
 
120
static const struct ns32k_option opt_U[]= /* Save, enter.  */
121
{
122
  { "r0",       0x01,   0x01    },
123
  { "r1",       0x02,   0x02    },
124
  { "r2",       0x04,   0x04    },
125
  { "r3",       0x08,   0x08    },
126
  { "r4",       0x10,   0x10    },
127
  { "r5",       0x20,   0x20    },
128
  { "r6",       0x40,   0x40    },
129
  { "r7",       0x80,   0x80    },
130
  {  0 , 0x00,   0x00    }
131
};
132
 
133
static const struct ns32k_option opt_O[]= /* Setcfg.  */
134
{
135
  { "c",        0x8,    0x8     },
136
  { "m",        0x4,    0x4     },
137
  { "f",        0x2,    0x2     },
138
  { "i",        0x1,    0x1     },
139
  {  0 , 0x0,    0x0     }
140
};
141
 
142
static const struct ns32k_option opt_C[]= /* Cinv.  */
143
{
144
  { "a",        0x4,    0x4     },
145
  { "i",        0x2,    0x2     },
146
  { "d",        0x1,    0x1     },
147
  {  0 , 0x0,    0x0     }
148
};
149
 
150
static const struct ns32k_option opt_S[]= /* String inst.  */
151
{
152
  { "b",        0x1,    0x1     },
153
  { "u",        0x6,    0x6     },
154
  { "w",        0x2,    0x2     },
155
  {  0 , 0x0,    0x0     }
156
};
157
 
158
static const struct ns32k_option list_P532[]= /* Lpr spr.  */
159
{
160
  { "us",       0x0,    0xf     },
161
  { "dcr",      0x1,    0xf     },
162
  { "bpc",      0x2,    0xf     },
163
  { "dsr",      0x3,    0xf     },
164
  { "car",      0x4,    0xf     },
165
  { "fp",       0x8,    0xf     },
166
  { "sp",       0x9,    0xf     },
167
  { "sb",       0xa,    0xf     },
168
  { "usp",      0xb,    0xf     },
169
  { "cfg",      0xc,    0xf     },
170
  { "psr",      0xd,    0xf     },
171
  { "intbase",  0xe,    0xf     },
172
  { "mod",      0xf,    0xf     },
173
  {  0 , 0x00,   0xf     }
174
};
175
 
176
static const struct ns32k_option list_M532[]= /* Lmr smr.  */
177
{
178
  { "mcr",      0x9,    0xf     },
179
  { "msr",      0xa,    0xf     },
180
  { "tear",     0xb,    0xf     },
181
  { "ptb0",     0xc,    0xf     },
182
  { "ptb1",     0xd,    0xf     },
183
  { "ivar0",    0xe,    0xf     },
184
  { "ivar1",    0xf,    0xf     },
185
  {  0 , 0x0,    0xf     }
186
};
187
 
188
static const struct ns32k_option list_P032[]= /* Lpr spr.  */
189
{
190
  { "upsr",     0x0,    0xf     },
191
  { "fp",       0x8,    0xf     },
192
  { "sp",       0x9,    0xf     },
193
  { "sb",       0xa,    0xf     },
194
  { "psr",      0xb,    0xf     },
195
  { "intbase",  0xe,    0xf     },
196
  { "mod",      0xf,    0xf     },
197
  {  0 , 0x0,    0xf     }
198
};
199
 
200
static const struct ns32k_option list_M032[]= /* Lmr smr.  */
201
{
202
  { "bpr0",     0x0,    0xf     },
203
  { "bpr1",     0x1,    0xf     },
204
  { "pf0",      0x4,    0xf     },
205
  { "pf1",      0x5,    0xf     },
206
  { "sc",       0x8,    0xf     },
207
  { "msr",      0xa,    0xf     },
208
  { "bcnt",     0xb,    0xf     },
209
  { "ptb0",     0xc,    0xf     },
210
  { "ptb1",     0xd,    0xf     },
211
  { "eia",      0xf,    0xf     },
212
  {  0 , 0x0,    0xf     }
213
};
214
 
215
 
216
/* Figure out which options are present.   */
217
 
218
static void
219
optlist (int options, const struct ns32k_option * optionP, char * result)
220
{
221
  if (options == 0)
222
    {
223
      sprintf (result, "[]");
224
      return;
225
    }
226
 
227
  sprintf (result, "[");
228
 
229
  for (; (options != 0) && optionP->pattern; optionP++)
230
    {
231
      if ((options & optionP->match) == optionP->value)
232
        {
233
          /* We found a match, update result and options.  */
234
          strcat (result, optionP->pattern);
235
          options &= ~optionP->value;
236
          if (options != 0)      /* More options to come.  */
237
            strcat (result, ",");
238
        }
239
    }
240
 
241
  if (options != 0)
242
    strcat (result, "undefined");
243
 
244
  strcat (result, "]");
245
}
246
 
247
static void
248
list_search (int reg_value, const struct ns32k_option *optionP, char *result)
249
{
250
  for (; optionP->pattern; optionP++)
251
    {
252
      if ((reg_value & optionP->match) == optionP->value)
253
        {
254
          sprintf (result, "%s", optionP->pattern);
255
          return;
256
        }
257
    }
258
  sprintf (result, "undefined");
259
}
260
 
261
/* Extract "count" bits starting "offset" bits into buffer.  */
262
 
263
static int
264
bit_extract (bfd_byte *buffer, int offset, int count)
265
{
266
  int result;
267
  int bit;
268
 
269
  buffer += offset >> 3;
270
  offset &= 7;
271
  bit = 1;
272
  result = 0;
273
  while (count--)
274
    {
275
      FETCH_DATA (dis_info, buffer + 1);
276
      if ((*buffer & (1 << offset)))
277
        result |= bit;
278
      if (++offset == 8)
279
        {
280
          offset = 0;
281
          buffer++;
282
        }
283
      bit <<= 1;
284
    }
285
  return result;
286
}
287
 
288
/* Like bit extract but the buffer is valid and doen't need to be fetched.  */
289
 
290
static int
291
bit_extract_simple (bfd_byte *buffer, int offset, int count)
292
{
293
  int result;
294
  int bit;
295
 
296
  buffer += offset >> 3;
297
  offset &= 7;
298
  bit = 1;
299
  result = 0;
300
  while (count--)
301
    {
302
      if ((*buffer & (1 << offset)))
303
        result |= bit;
304
      if (++offset == 8)
305
        {
306
          offset = 0;
307
          buffer++;
308
        }
309
      bit <<= 1;
310
    }
311
  return result;
312
}
313
 
314
static void
315
bit_copy (bfd_byte *buffer, int offset, int count, char *to)
316
{
317
  for (; count > 8; count -= 8, to++, offset += 8)
318
    *to = bit_extract (buffer, offset, 8);
319
  *to = bit_extract (buffer, offset, count);
320
}
321
 
322
static int
323
sign_extend (int value, int bits)
324
{
325
  value = value & ((1 << bits) - 1);
326
  return (value & (1 << (bits - 1))
327
          ? value | (~((1 << bits) - 1))
328
          : value);
329
}
330
 
331
static void
332
flip_bytes (char *ptr, int count)
333
{
334
  char tmp;
335
 
336
  while (count > 0)
337
    {
338
      tmp = ptr[0];
339
      ptr[0] = ptr[count - 1];
340
      ptr[count - 1] = tmp;
341
      ptr++;
342
      count -= 2;
343
    }
344
}
345
 
346
/* Given a character C, does it represent a general addressing mode?  */
347
#define Is_gen(c) \
348
  ((c) == 'F' || (c) == 'L' || (c) == 'B' \
349
   || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
350
 
351
/* Adressing modes.  */
352
#define Adrmod_index_byte        0x1c
353
#define Adrmod_index_word        0x1d
354
#define Adrmod_index_doubleword  0x1e
355
#define Adrmod_index_quadword    0x1f
356
 
357
/* Is MODE an indexed addressing mode?  */
358
#define Adrmod_is_index(mode) \
359
  (   mode == Adrmod_index_byte \
360
   || mode == Adrmod_index_word \
361
   || mode == Adrmod_index_doubleword \
362
   || mode == Adrmod_index_quadword)
363
 
364
 
365
static int
366
get_displacement (bfd_byte *buffer, int *aoffsetp)
367
{
368
  int Ivalue;
369
  short Ivalue2;
370
 
371
  Ivalue = bit_extract (buffer, *aoffsetp, 8);
372
  switch (Ivalue & 0xc0)
373
    {
374
    case 0x00:
375
    case 0x40:
376
      Ivalue = sign_extend (Ivalue, 7);
377
      *aoffsetp += 8;
378
      break;
379
    case 0x80:
380
      Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
381
      flip_bytes ((char *) & Ivalue2, 2);
382
      Ivalue = sign_extend (Ivalue2, 14);
383
      *aoffsetp += 16;
384
      break;
385
    case 0xc0:
386
      Ivalue = bit_extract (buffer, *aoffsetp, 32);
387
      flip_bytes ((char *) & Ivalue, 4);
388
      Ivalue = sign_extend (Ivalue, 30);
389
      *aoffsetp += 32;
390
      break;
391
    }
392
  return Ivalue;
393
}
394
 
395
#if 1 /* A version that should work on ns32k f's&d's on any machine.  */
396
static int
397
invalid_float (bfd_byte *p, int len)
398
{
399
  int val;
400
 
401
  if (len == 4)
402
    val = (bit_extract_simple (p, 23, 8)/*exponent*/ == 0xff
403
           || (bit_extract_simple (p, 23, 8)/*exponent*/ == 0
404
               && bit_extract_simple (p, 0, 23)/*mantisa*/ != 0));
405
  else if (len == 8)
406
    val = (bit_extract_simple (p, 52, 11)/*exponent*/ == 0x7ff
407
           || (bit_extract_simple (p, 52, 11)/*exponent*/ == 0
408
               && (bit_extract_simple (p, 0, 32)/*low mantisa*/ != 0
409
                   || bit_extract_simple (p, 32, 20)/*high mantisa*/ != 0)));
410
  else
411
    val = 1;
412
  return (val);
413
}
414
#else
415
/* Assumes the bytes have been swapped to local order.  */
416
typedef union
417
{
418
  double d;
419
  float f;
420
  struct { unsigned m:23, e:8, :1;} sf;
421
  struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
422
} float_type_u;
423
 
424
static int
425
invalid_float (float_type_u *p, int len)
426
{
427
  int val;
428
 
429
  if (len == sizeof (float))
430
    val = (p->sf.e == 0xff
431
           || (p->sf.e == 0 && p->sf.m != 0));
432
  else if (len == sizeof (double))
433
    val = (p->sd.e == 0x7ff
434
           || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
435
  else
436
    val = 1;
437
  return val;
438
}
439
#endif
440
 
441
/* Print an instruction operand of category given by d.  IOFFSET is
442
   the bit position below which small (<1 byte) parts of the operand can
443
   be found (usually in the basic instruction, but for indexed
444
   addressing it can be in the index byte).  AOFFSETP is a pointer to the
445
   bit position of the addressing extension.  BUFFER contains the
446
   instruction.  ADDR is where BUFFER was read from.  Put the disassembled
447
   version of the operand in RESULT.  INDEX_OFFSET is the bit position
448
   of the index byte (it contains garbage if this operand is not a
449
   general operand using scaled indexed addressing mode).  */
450
 
451
static int
452
print_insn_arg (int d,
453
                int ioffset,
454
                int *aoffsetp,
455
                bfd_byte *buffer,
456
                bfd_vma addr,
457
                char *result,
458
                int index_offset)
459
{
460
  union
461
  {
462
    float f;
463
    double d;
464
    int i[2];
465
  } value;
466
  int Ivalue;
467
  int addr_mode;
468
  int disp1, disp2;
469
  int size;
470
 
471
  switch (d)
472
    {
473
    case 'f':
474
      /* A "gen" operand but 5 bits from the end of instruction.  */
475
      ioffset -= 5;
476
    case 'Z':
477
    case 'F':
478
    case 'L':
479
    case 'I':
480
    case 'B':
481
    case 'W':
482
    case 'D':
483
    case 'A':
484
      addr_mode = bit_extract (buffer, ioffset - 5, 5);
485
      ioffset -= 5;
486
      switch (addr_mode)
487
        {
488
        case 0x0: case 0x1: case 0x2: case 0x3:
489
        case 0x4: case 0x5: case 0x6: case 0x7:
490
          /* Register mode R0 -- R7.  */
491
          switch (d)
492
            {
493
            case 'F':
494
            case 'L':
495
            case 'Z':
496
              sprintf (result, "f%d", addr_mode);
497
              break;
498
            default:
499
              sprintf (result, "r%d", addr_mode);
500
            }
501
          break;
502
        case 0x8: case 0x9: case 0xa: case 0xb:
503
        case 0xc: case 0xd: case 0xe: case 0xf:
504
          /* Register relative disp(R0 -- R7).  */
505
          disp1 = get_displacement (buffer, aoffsetp);
506
          sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
507
          break;
508
        case 0x10:
509
        case 0x11:
510
        case 0x12:
511
          /* Memory relative disp2(disp1(FP, SP, SB)).  */
512
          disp1 = get_displacement (buffer, aoffsetp);
513
          disp2 = get_displacement (buffer, aoffsetp);
514
          sprintf (result, "%d(%d(%s))", disp2, disp1,
515
                   addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
516
          break;
517
        case 0x13:
518
          /* Reserved.  */
519
          sprintf (result, "reserved");
520
          break;
521
        case 0x14:
522
          /* Immediate.  */
523
          switch (d)
524
            {
525
            case 'I':
526
            case 'Z':
527
            case 'A':
528
              /* I and Z are output operands and can`t be immediate
529
                 A is an address and we can`t have the address of
530
                 an immediate either. We don't know how much to increase
531
                 aoffsetp by since whatever generated this is broken
532
                 anyway!  */
533
              sprintf (result, _("$<undefined>"));
534
              break;
535
            case 'B':
536
              Ivalue = bit_extract (buffer, *aoffsetp, 8);
537
              Ivalue = sign_extend (Ivalue, 8);
538
              *aoffsetp += 8;
539
              sprintf (result, "$%d", Ivalue);
540
              break;
541
            case 'W':
542
              Ivalue = bit_extract (buffer, *aoffsetp, 16);
543
              flip_bytes ((char *) & Ivalue, 2);
544
              *aoffsetp += 16;
545
              Ivalue = sign_extend (Ivalue, 16);
546
              sprintf (result, "$%d", Ivalue);
547
              break;
548
            case 'D':
549
              Ivalue = bit_extract (buffer, *aoffsetp, 32);
550
              flip_bytes ((char *) & Ivalue, 4);
551
              *aoffsetp += 32;
552
              sprintf (result, "$%d", Ivalue);
553
              break;
554
            case 'F':
555
              bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
556
              flip_bytes ((char *) &value.f, 4);
557
              *aoffsetp += 32;
558
              if (INVALID_FLOAT (&value.f, 4))
559
                sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
560
              else /* Assume host has ieee float.  */
561
                sprintf (result, "$%g", value.f);
562
              break;
563
            case 'L':
564
              bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
565
              flip_bytes ((char *) &value.d, 8);
566
              *aoffsetp += 64;
567
              if (INVALID_FLOAT (&value.d, 8))
568
                sprintf (result, "<<invalid double 0x%.8x%.8x>>",
569
                         value.i[1], value.i[0]);
570
              else /* Assume host has ieee float.  */
571
                sprintf (result, "$%g", value.d);
572
              break;
573
            }
574
          break;
575
        case 0x15:
576
          /* Absolute @disp.  */
577
          disp1 = get_displacement (buffer, aoffsetp);
578
          sprintf (result, "@|%d|", disp1);
579
          break;
580
        case 0x16:
581
          /* External EXT(disp1) + disp2 (Mod table stuff).  */
582
          disp1 = get_displacement (buffer, aoffsetp);
583
          disp2 = get_displacement (buffer, aoffsetp);
584
          sprintf (result, "EXT(%d) + %d", disp1, disp2);
585
          break;
586
        case 0x17:
587
          /* Top of stack tos.  */
588
          sprintf (result, "tos");
589
          break;
590
        case 0x18:
591
          /* Memory space disp(FP).  */
592
          disp1 = get_displacement (buffer, aoffsetp);
593
          sprintf (result, "%d(fp)", disp1);
594
          break;
595
        case 0x19:
596
          /* Memory space disp(SP).  */
597
          disp1 = get_displacement (buffer, aoffsetp);
598
          sprintf (result, "%d(sp)", disp1);
599
          break;
600
        case 0x1a:
601
          /* Memory space disp(SB).  */
602
          disp1 = get_displacement (buffer, aoffsetp);
603
          sprintf (result, "%d(sb)", disp1);
604
          break;
605
        case 0x1b:
606
          /* Memory space disp(PC).  */
607
          disp1 = get_displacement (buffer, aoffsetp);
608
          *result++ = NEXT_IS_ADDR;
609
          sprintf_vma (result, addr + disp1);
610
          result += strlen (result);
611
          *result++ = NEXT_IS_ADDR;
612
          *result = '\0';
613
          break;
614
        case 0x1c:
615
        case 0x1d:
616
        case 0x1e:
617
        case 0x1f:
618
          {
619
            int bit_index;
620
            static const char *ind = "bwdq";
621
            char *off;
622
 
623
            /* Scaled index basemode[R0 -- R7:B,W,D,Q].  */
624
            bit_index = bit_extract (buffer, index_offset - 8, 3);
625
            print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
626
                            result, 0);
627
            off = result + strlen (result);
628
            sprintf (off, "[r%d:%c]", bit_index, ind[addr_mode & 3]);
629
          }
630
          break;
631
        }
632
      break;
633
    case 'H':
634
    case 'q':
635
      Ivalue = bit_extract (buffer, ioffset-4, 4);
636
      Ivalue = sign_extend (Ivalue, 4);
637
      sprintf (result, "%d", Ivalue);
638
      ioffset -= 4;
639
      break;
640
    case 'r':
641
      Ivalue = bit_extract (buffer, ioffset-3, 3);
642
      sprintf (result, "r%d", Ivalue&7);
643
      ioffset -= 3;
644
      break;
645
    case 'd':
646
      sprintf (result, "%d", get_displacement (buffer, aoffsetp));
647
      break;
648
    case 'b':
649
      Ivalue = get_displacement (buffer, aoffsetp);
650
      /* Warning!!  HACK ALERT!
651
         Operand type 'b' is only used by the cmp{b,w,d} and
652
         movm{b,w,d} instructions; we need to know whether
653
         it's a `b' or `w' or `d' instruction; and for both
654
         cmpm and movm it's stored at the same place so we
655
         just grab two bits of the opcode and look at it...  */
656
      size = bit_extract(buffer, ioffset-6, 2);
657
      if (size == 0)             /* 00 => b.  */
658
        size = 1;
659
      else if (size == 1)       /* 01 => w.  */
660
        size = 2;
661
      else
662
        size = 4;               /* 11 => d.  */
663
 
664
      sprintf (result, "%d", (Ivalue / size) + 1);
665
      break;
666
    case 'p':
667
      *result++ = NEXT_IS_ADDR;
668
      sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
669
      result += strlen (result);
670
      *result++ = NEXT_IS_ADDR;
671
      *result = '\0';
672
      break;
673
    case 'i':
674
      Ivalue = bit_extract (buffer, *aoffsetp, 8);
675
      *aoffsetp += 8;
676
      sprintf (result, "0x%x", Ivalue);
677
      break;
678
    case 'u':
679
      Ivalue = bit_extract (buffer, *aoffsetp, 8);
680
      optlist (Ivalue, opt_u, result);
681
      *aoffsetp += 8;
682
      break;
683
    case 'U':
684
      Ivalue = bit_extract (buffer, *aoffsetp, 8);
685
      optlist (Ivalue, opt_U, result);
686
      *aoffsetp += 8;
687
      break;
688
    case 'O':
689
      Ivalue = bit_extract (buffer, ioffset - 9, 9);
690
      optlist (Ivalue, opt_O, result);
691
      ioffset -= 9;
692
      break;
693
    case 'C':
694
      Ivalue = bit_extract (buffer, ioffset - 4, 4);
695
      optlist (Ivalue, opt_C, result);
696
      ioffset -= 4;
697
      break;
698
    case 'S':
699
      Ivalue = bit_extract (buffer, ioffset - 8, 8);
700
      optlist (Ivalue, opt_S, result);
701
      ioffset -= 8;
702
      break;
703
    case 'M':
704
      Ivalue = bit_extract (buffer, ioffset - 4, 4);
705
      list_search (Ivalue, 0 ? list_M032 : list_M532, result);
706
      ioffset -= 4;
707
      break;
708
    case 'P':
709
      Ivalue = bit_extract (buffer, ioffset - 4, 4);
710
      list_search (Ivalue, 0 ? list_P032 : list_P532, result);
711
      ioffset -= 4;
712
      break;
713
    case 'g':
714
      Ivalue = bit_extract (buffer, *aoffsetp, 3);
715
      sprintf (result, "%d", Ivalue);
716
      *aoffsetp += 3;
717
      break;
718
    case 'G':
719
      Ivalue = bit_extract(buffer, *aoffsetp, 5);
720
      sprintf (result, "%d", Ivalue + 1);
721
      *aoffsetp += 5;
722
      break;
723
    }
724
  return ioffset;
725
}
726
 
727
 
728
/* Print the 32000 instruction at address MEMADDR in debugged memory,
729
   on STREAM.  Returns length of the instruction, in bytes.  */
730
 
731
int
732
print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
733
{
734
  unsigned int i;
735
  const char *d;
736
  unsigned short first_word;
737
  int ioffset;          /* Bits into instruction.  */
738
  int aoffset;          /* Bits into arguments.  */
739
  char arg_bufs[MAX_ARGS+1][ARG_LEN];
740
  int argnum;
741
  int maxarg;
742
  struct private priv;
743
  bfd_byte *buffer = priv.the_buffer;
744
  dis_info = info;
745
 
746
  info->private_data = & priv;
747
  priv.max_fetched = priv.the_buffer;
748
  priv.insn_start = memaddr;
749
  if (setjmp (priv.bailout) != 0)
750
    /* Error return.  */
751
    return -1;
752
 
753
  /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
754
     us over the end of accessible data unnecessarilly.  */
755
  FETCH_DATA (info, buffer + 1);
756
  for (i = 0; i < NOPCODES; i++)
757
    if (ns32k_opcodes[i].opcode_id_size <= 8
758
        && ((buffer[0]
759
             & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
760
            == ns32k_opcodes[i].opcode_seed))
761
      break;
762
  if (i == NOPCODES)
763
    {
764
      /* Maybe it is 9 to 16 bits big.  */
765
      FETCH_DATA (info, buffer + 2);
766
      first_word = read_memory_integer(buffer, 2);
767
 
768
      for (i = 0; i < NOPCODES; i++)
769
        if ((first_word
770
             & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
771
            == ns32k_opcodes[i].opcode_seed)
772
          break;
773
 
774
      /* Handle undefined instructions.  */
775
      if (i == NOPCODES)
776
        {
777
          (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
778
          return 1;
779
        }
780
    }
781
 
782
  (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
783
 
784
  ioffset = ns32k_opcodes[i].opcode_size;
785
  aoffset = ns32k_opcodes[i].opcode_size;
786
  d = ns32k_opcodes[i].operands;
787
 
788
  if (*d)
789
    {
790
      /* Offset in bits of the first thing beyond each index byte.
791
         Element 0 is for operand A and element 1 is for operand B.
792
         The rest are irrelevant, but we put them here so we don't
793
         index outside the array.  */
794
      int index_offset[MAX_ARGS];
795
 
796
      /* 0 for operand A, 1 for operand B, greater for other args.  */
797
      int whicharg = 0;
798
 
799
      (*dis_info->fprintf_func)(dis_info->stream, "\t");
800
 
801
      maxarg = 0;
802
 
803
      /* First we have to find and keep track of the index bytes,
804
         if we are using scaled indexed addressing mode, since the index
805
         bytes occur right after the basic instruction, not as part
806
         of the addressing extension.  */
807
      if (Is_gen(d[1]))
808
        {
809
          int addr_mode = bit_extract (buffer, ioffset - 5, 5);
810
 
811
          if (Adrmod_is_index (addr_mode))
812
            {
813
              aoffset += 8;
814
              index_offset[0] = aoffset;
815
            }
816
        }
817
 
818
      if (d[2] && Is_gen(d[3]))
819
        {
820
          int addr_mode = bit_extract (buffer, ioffset - 10, 5);
821
 
822
          if (Adrmod_is_index (addr_mode))
823
            {
824
              aoffset += 8;
825
              index_offset[1] = aoffset;
826
            }
827
        }
828
 
829
      while (*d)
830
        {
831
          argnum = *d - '1';
832
          d++;
833
          if (argnum > maxarg && argnum < MAX_ARGS)
834
            maxarg = argnum;
835
          ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
836
                                    memaddr, arg_bufs[argnum],
837
                                    index_offset[whicharg]);
838
          d++;
839
          whicharg++;
840
        }
841
      for (argnum = 0; argnum <= maxarg; argnum++)
842
        {
843
          bfd_vma addr;
844
          char *ch;
845
 
846
          for (ch = arg_bufs[argnum]; *ch;)
847
            {
848
              if (*ch == NEXT_IS_ADDR)
849
                {
850
                  ++ch;
851
                  addr = bfd_scan_vma (ch, NULL, 16);
852
                  (*dis_info->print_address_func) (addr, dis_info);
853
                  while (*ch && *ch != NEXT_IS_ADDR)
854
                    ++ch;
855
                  if (*ch)
856
                    ++ch;
857
                }
858
              else
859
                (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
860
            }
861
          if (argnum < maxarg)
862
            (*dis_info->fprintf_func)(dis_info->stream, ", ");
863
        }
864
    }
865
  return aoffset / 8;
866
}

powered by: WebSVN 2.1.0

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