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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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