Coverage Report

Created: 2023-08-28 06:23

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