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

Subversion Repositories openrisc

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

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

Line No. Rev Author Line
1 205 julius
/* Print National Semiconductor 32000 instructions.
2
   Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005, 2007
3
   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 index;
470
  int size;
471
 
472
  switch (d)
473
    {
474
    case 'f':
475
      /* A "gen" operand but 5 bits from the end of instruction.  */
476
      ioffset -= 5;
477
    case 'Z':
478
    case 'F':
479
    case 'L':
480
    case 'I':
481
    case 'B':
482
    case 'W':
483
    case 'D':
484
    case 'A':
485
      addr_mode = bit_extract (buffer, ioffset - 5, 5);
486
      ioffset -= 5;
487
      switch (addr_mode)
488
        {
489
        case 0x0: case 0x1: case 0x2: case 0x3:
490
        case 0x4: case 0x5: case 0x6: case 0x7:
491
          /* Register mode R0 -- R7.  */
492
          switch (d)
493
            {
494
            case 'F':
495
            case 'L':
496
            case 'Z':
497
              sprintf (result, "f%d", addr_mode);
498
              break;
499
            default:
500
              sprintf (result, "r%d", addr_mode);
501
            }
502
          break;
503
        case 0x8: case 0x9: case 0xa: case 0xb:
504
        case 0xc: case 0xd: case 0xe: case 0xf:
505
          /* Register relative disp(R0 -- R7).  */
506
          disp1 = get_displacement (buffer, aoffsetp);
507
          sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
508
          break;
509
        case 0x10:
510
        case 0x11:
511
        case 0x12:
512
          /* Memory relative disp2(disp1(FP, SP, SB)).  */
513
          disp1 = get_displacement (buffer, aoffsetp);
514
          disp2 = get_displacement (buffer, aoffsetp);
515
          sprintf (result, "%d(%d(%s))", disp2, disp1,
516
                   addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
517
          break;
518
        case 0x13:
519
          /* Reserved.  */
520
          sprintf (result, "reserved");
521
          break;
522
        case 0x14:
523
          /* Immediate.  */
524
          switch (d)
525
            {
526
            case 'I':
527
            case 'Z':
528
            case 'A':
529
              /* I and Z are output operands and can`t be immediate
530
                 A is an address and we can`t have the address of
531
                 an immediate either. We don't know how much to increase
532
                 aoffsetp by since whatever generated this is broken
533
                 anyway!  */
534
              sprintf (result, _("$<undefined>"));
535
              break;
536
            case 'B':
537
              Ivalue = bit_extract (buffer, *aoffsetp, 8);
538
              Ivalue = sign_extend (Ivalue, 8);
539
              *aoffsetp += 8;
540
              sprintf (result, "$%d", Ivalue);
541
              break;
542
            case 'W':
543
              Ivalue = bit_extract (buffer, *aoffsetp, 16);
544
              flip_bytes ((char *) & Ivalue, 2);
545
              *aoffsetp += 16;
546
              Ivalue = sign_extend (Ivalue, 16);
547
              sprintf (result, "$%d", Ivalue);
548
              break;
549
            case 'D':
550
              Ivalue = bit_extract (buffer, *aoffsetp, 32);
551
              flip_bytes ((char *) & Ivalue, 4);
552
              *aoffsetp += 32;
553
              sprintf (result, "$%d", Ivalue);
554
              break;
555
            case 'F':
556
              bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
557
              flip_bytes ((char *) &value.f, 4);
558
              *aoffsetp += 32;
559
              if (INVALID_FLOAT (&value.f, 4))
560
                sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
561
              else /* Assume host has ieee float.  */
562
                sprintf (result, "$%g", value.f);
563
              break;
564
            case 'L':
565
              bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
566
              flip_bytes ((char *) &value.d, 8);
567
              *aoffsetp += 64;
568
              if (INVALID_FLOAT (&value.d, 8))
569
                sprintf (result, "<<invalid double 0x%.8x%.8x>>",
570
                         value.i[1], value.i[0]);
571
              else /* Assume host has ieee float.  */
572
                sprintf (result, "$%g", value.d);
573
              break;
574
            }
575
          break;
576
        case 0x15:
577
          /* Absolute @disp.  */
578
          disp1 = get_displacement (buffer, aoffsetp);
579
          sprintf (result, "@|%d|", disp1);
580
          break;
581
        case 0x16:
582
          /* External EXT(disp1) + disp2 (Mod table stuff).  */
583
          disp1 = get_displacement (buffer, aoffsetp);
584
          disp2 = get_displacement (buffer, aoffsetp);
585
          sprintf (result, "EXT(%d) + %d", disp1, disp2);
586
          break;
587
        case 0x17:
588
          /* Top of stack tos.  */
589
          sprintf (result, "tos");
590
          break;
591
        case 0x18:
592
          /* Memory space disp(FP).  */
593
          disp1 = get_displacement (buffer, aoffsetp);
594
          sprintf (result, "%d(fp)", disp1);
595
          break;
596
        case 0x19:
597
          /* Memory space disp(SP).  */
598
          disp1 = get_displacement (buffer, aoffsetp);
599
          sprintf (result, "%d(sp)", disp1);
600
          break;
601
        case 0x1a:
602
          /* Memory space disp(SB).  */
603
          disp1 = get_displacement (buffer, aoffsetp);
604
          sprintf (result, "%d(sb)", disp1);
605
          break;
606
        case 0x1b:
607
          /* Memory space disp(PC).  */
608
          disp1 = get_displacement (buffer, aoffsetp);
609
          *result++ = NEXT_IS_ADDR;
610
          sprintf_vma (result, addr + disp1);
611
          result += strlen (result);
612
          *result++ = NEXT_IS_ADDR;
613
          *result = '\0';
614
          break;
615
        case 0x1c:
616
        case 0x1d:
617
        case 0x1e:
618
        case 0x1f:
619
          /* Scaled index basemode[R0 -- R7:B,W,D,Q].  */
620
          index = bit_extract (buffer, index_offset - 8, 3);
621
          print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
622
                          result, 0);
623
          {
624
            static const char *ind = "bwdq";
625
            char *off;
626
 
627
            off = result + strlen (result);
628
            sprintf (off, "[r%d:%c]", index,
629
                     ind[addr_mode & 3]);
630
          }
631
          break;
632
        }
633
      break;
634
    case 'H':
635
    case 'q':
636
      Ivalue = bit_extract (buffer, ioffset-4, 4);
637
      Ivalue = sign_extend (Ivalue, 4);
638
      sprintf (result, "%d", Ivalue);
639
      ioffset -= 4;
640
      break;
641
    case 'r':
642
      Ivalue = bit_extract (buffer, ioffset-3, 3);
643
      sprintf (result, "r%d", Ivalue&7);
644
      ioffset -= 3;
645
      break;
646
    case 'd':
647
      sprintf (result, "%d", get_displacement (buffer, aoffsetp));
648
      break;
649
    case 'b':
650
      Ivalue = get_displacement (buffer, aoffsetp);
651
      /* Warning!!  HACK ALERT!
652
         Operand type 'b' is only used by the cmp{b,w,d} and
653
         movm{b,w,d} instructions; we need to know whether
654
         it's a `b' or `w' or `d' instruction; and for both
655
         cmpm and movm it's stored at the same place so we
656
         just grab two bits of the opcode and look at it...  */
657
      size = bit_extract(buffer, ioffset-6, 2);
658
      if (size == 0)             /* 00 => b.  */
659
        size = 1;
660
      else if (size == 1)       /* 01 => w.  */
661
        size = 2;
662
      else
663
        size = 4;               /* 11 => d.  */
664
 
665
      sprintf (result, "%d", (Ivalue / size) + 1);
666
      break;
667
    case 'p':
668
      *result++ = NEXT_IS_ADDR;
669
      sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
670
      result += strlen (result);
671
      *result++ = NEXT_IS_ADDR;
672
      *result = '\0';
673
      break;
674
    case 'i':
675
      Ivalue = bit_extract (buffer, *aoffsetp, 8);
676
      *aoffsetp += 8;
677
      sprintf (result, "0x%x", Ivalue);
678
      break;
679
    case 'u':
680
      Ivalue = bit_extract (buffer, *aoffsetp, 8);
681
      optlist (Ivalue, opt_u, result);
682
      *aoffsetp += 8;
683
      break;
684
    case 'U':
685
      Ivalue = bit_extract (buffer, *aoffsetp, 8);
686
      optlist (Ivalue, opt_U, result);
687
      *aoffsetp += 8;
688
      break;
689
    case 'O':
690
      Ivalue = bit_extract (buffer, ioffset - 9, 9);
691
      optlist (Ivalue, opt_O, result);
692
      ioffset -= 9;
693
      break;
694
    case 'C':
695
      Ivalue = bit_extract (buffer, ioffset - 4, 4);
696
      optlist (Ivalue, opt_C, result);
697
      ioffset -= 4;
698
      break;
699
    case 'S':
700
      Ivalue = bit_extract (buffer, ioffset - 8, 8);
701
      optlist (Ivalue, opt_S, result);
702
      ioffset -= 8;
703
      break;
704
    case 'M':
705
      Ivalue = bit_extract (buffer, ioffset - 4, 4);
706
      list_search (Ivalue, 0 ? list_M032 : list_M532, result);
707
      ioffset -= 4;
708
      break;
709
    case 'P':
710
      Ivalue = bit_extract (buffer, ioffset - 4, 4);
711
      list_search (Ivalue, 0 ? list_P032 : list_P532, result);
712
      ioffset -= 4;
713
      break;
714
    case 'g':
715
      Ivalue = bit_extract (buffer, *aoffsetp, 3);
716
      sprintf (result, "%d", Ivalue);
717
      *aoffsetp += 3;
718
      break;
719
    case 'G':
720
      Ivalue = bit_extract(buffer, *aoffsetp, 5);
721
      sprintf (result, "%d", Ivalue + 1);
722
      *aoffsetp += 5;
723
      break;
724
    }
725
  return ioffset;
726
}
727
 
728
 
729
/* Print the 32000 instruction at address MEMADDR in debugged memory,
730
   on STREAM.  Returns length of the instruction, in bytes.  */
731
 
732
int
733
print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
734
{
735
  unsigned int i;
736
  const char *d;
737
  unsigned short first_word;
738
  int ioffset;          /* Bits into instruction.  */
739
  int aoffset;          /* Bits into arguments.  */
740
  char arg_bufs[MAX_ARGS+1][ARG_LEN];
741
  int argnum;
742
  int maxarg;
743
  struct private priv;
744
  bfd_byte *buffer = priv.the_buffer;
745
  dis_info = info;
746
 
747
  info->private_data = & priv;
748
  priv.max_fetched = priv.the_buffer;
749
  priv.insn_start = memaddr;
750
  if (setjmp (priv.bailout) != 0)
751
    /* Error return.  */
752
    return -1;
753
 
754
  /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
755
     us over the end of accessible data unnecessarilly.  */
756
  FETCH_DATA (info, buffer + 1);
757
  for (i = 0; i < NOPCODES; i++)
758
    if (ns32k_opcodes[i].opcode_id_size <= 8
759
        && ((buffer[0]
760
             & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
761
            == ns32k_opcodes[i].opcode_seed))
762
      break;
763
  if (i == NOPCODES)
764
    {
765
      /* Maybe it is 9 to 16 bits big.  */
766
      FETCH_DATA (info, buffer + 2);
767
      first_word = read_memory_integer(buffer, 2);
768
 
769
      for (i = 0; i < NOPCODES; i++)
770
        if ((first_word
771
             & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
772
            == ns32k_opcodes[i].opcode_seed)
773
          break;
774
 
775
      /* Handle undefined instructions.  */
776
      if (i == NOPCODES)
777
        {
778
          (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
779
          return 1;
780
        }
781
    }
782
 
783
  (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
784
 
785
  ioffset = ns32k_opcodes[i].opcode_size;
786
  aoffset = ns32k_opcodes[i].opcode_size;
787
  d = ns32k_opcodes[i].operands;
788
 
789
  if (*d)
790
    {
791
      /* Offset in bits of the first thing beyond each index byte.
792
         Element 0 is for operand A and element 1 is for operand B.
793
         The rest are irrelevant, but we put them here so we don't
794
         index outside the array.  */
795
      int index_offset[MAX_ARGS];
796
 
797
      /* 0 for operand A, 1 for operand B, greater for other args.  */
798
      int whicharg = 0;
799
 
800
      (*dis_info->fprintf_func)(dis_info->stream, "\t");
801
 
802
      maxarg = 0;
803
 
804
      /* First we have to find and keep track of the index bytes,
805
         if we are using scaled indexed addressing mode, since the index
806
         bytes occur right after the basic instruction, not as part
807
         of the addressing extension.  */
808
      if (Is_gen(d[1]))
809
        {
810
          int addr_mode = bit_extract (buffer, ioffset - 5, 5);
811
 
812
          if (Adrmod_is_index (addr_mode))
813
            {
814
              aoffset += 8;
815
              index_offset[0] = aoffset;
816
            }
817
        }
818
 
819
      if (d[2] && Is_gen(d[3]))
820
        {
821
          int addr_mode = bit_extract (buffer, ioffset - 10, 5);
822
 
823
          if (Adrmod_is_index (addr_mode))
824
            {
825
              aoffset += 8;
826
              index_offset[1] = aoffset;
827
            }
828
        }
829
 
830
      while (*d)
831
        {
832
          argnum = *d - '1';
833
          d++;
834
          if (argnum > maxarg && argnum < MAX_ARGS)
835
            maxarg = argnum;
836
          ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
837
                                    memaddr, arg_bufs[argnum],
838
                                    index_offset[whicharg]);
839
          d++;
840
          whicharg++;
841
        }
842
      for (argnum = 0; argnum <= maxarg; argnum++)
843
        {
844
          bfd_vma addr;
845
          char *ch;
846
 
847
          for (ch = arg_bufs[argnum]; *ch;)
848
            {
849
              if (*ch == NEXT_IS_ADDR)
850
                {
851
                  ++ch;
852
                  addr = bfd_scan_vma (ch, NULL, 16);
853
                  (*dis_info->print_address_func) (addr, dis_info);
854
                  while (*ch && *ch != NEXT_IS_ADDR)
855
                    ++ch;
856
                  if (*ch)
857
                    ++ch;
858
                }
859
              else
860
                (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
861
            }
862
          if (argnum < maxarg)
863
            (*dis_info->fprintf_func)(dis_info->stream, ", ");
864
        }
865
    }
866
  return aoffset / 8;
867
}

powered by: WebSVN 2.1.0

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