Coverage Report

Created: 2023-08-28 06:31

/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
13.5k
#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
127k
{
38
127k
  long val;
39
127k
  int i;
40
41
381k
  for (val = 0, i = nr - 1; i >= 0; i--)
42
254k
    {
43
254k
      val =  (val << 8);
44
254k
      val |= (0xff & *(addr + i));
45
254k
    }
46
127k
  return val;
47
127k
}
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
11.2M
  ((addr) <= ((struct private *)(info->private_data))->max_fetched \
69
11.2M
   ? 1 : fetch_data ((info), (addr)))
70
71
static int
72
fetch_data (struct disassemble_info *info, bfd_byte *addr)
73
1.39M
{
74
1.39M
  int status;
75
1.39M
  struct private *priv = (struct private *) info->private_data;
76
1.39M
  bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
77
78
1.39M
  status = (*info->read_memory_func) (start,
79
1.39M
              priv->max_fetched,
80
1.39M
              addr - priv->max_fetched,
81
1.39M
              info);
82
1.39M
  if (status != 0)
83
627
    {
84
627
      (*info->memory_error_func) (status, start, info);
85
627
      OPCODES_SIGLONGJMP (priv->bailout, 1);
86
627
    }
87
1.39M
  else
88
1.39M
    priv->max_fetched = addr;
89
1.39M
  return 1;
90
1.39M
}
91
92
/* Number of elements in the opcode table.  */
93
111M
#define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
94
95
3.48M
#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
6.02k
{
220
6.02k
  if (options == 0)
221
628
    {
222
628
      sprintf (result, "[]");
223
628
      return;
224
628
    }
225
226
5.39k
  sprintf (result, "[");
227
228
39.5k
  for (; (options != 0) && optionP->pattern; optionP++)
229
34.1k
    {
230
34.1k
      if ((options & optionP->match) == optionP->value)
231
18.1k
  {
232
    /* We found a match, update result and options.  */
233
18.1k
    strcat (result, optionP->pattern);
234
18.1k
    options &= ~optionP->value;
235
18.1k
    if (options != 0)  /* More options to come.  */
236
13.1k
      strcat (result, ",");
237
18.1k
  }
238
34.1k
    }
239
240
5.39k
  if (options != 0)
241
440
    strcat (result, "undefined");
242
243
5.39k
  strcat (result, "]");
244
5.39k
}
245
246
static void
247
list_search (int reg_value, const struct ns32k_option *optionP, char *result)
248
12.8k
{
249
95.3k
  for (; optionP->pattern; optionP++)
250
94.4k
    {
251
94.4k
      if ((reg_value & optionP->match) == optionP->value)
252
11.9k
  {
253
11.9k
    sprintf (result, "%s", optionP->pattern);
254
11.9k
    return;
255
11.9k
  }
256
94.4k
    }
257
913
  sprintf (result, "undefined");
258
913
}
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
1.67M
{
265
1.67M
  unsigned int result;
266
1.67M
  unsigned int bit;
267
268
1.67M
  if (offset < 0 || count < 0)
269
34.4k
    return 0;
270
1.63M
  buffer += offset >> 3;
271
1.63M
  offset &= 7;
272
1.63M
  bit = 1;
273
1.63M
  result = 0;
274
12.3M
  while (count--)
275
10.6M
    {
276
10.6M
      FETCH_DATA (dis_info, buffer + 1);
277
10.6M
      if ((*buffer & (1 << offset)))
278
3.98M
  result |= bit;
279
10.6M
      if (++offset == 8)
280
1.75M
  {
281
1.75M
    offset = 0;
282
1.75M
    buffer++;
283
1.75M
  }
284
10.6M
      bit <<= 1;
285
10.6M
    }
286
1.63M
  return result;
287
1.67M
}
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
38.0k
{
294
38.0k
  unsigned int result;
295
38.0k
  unsigned int bit;
296
297
38.0k
  if (offset < 0 || count < 0)
298
0
    return 0;
299
38.0k
  buffer += offset >> 3;
300
38.0k
  offset &= 7;
301
38.0k
  bit = 1;
302
38.0k
  result = 0;
303
591k
  while (count--)
304
553k
    {
305
553k
      if ((*buffer & (1 << offset)))
306
86.9k
  result |= bit;
307
553k
      if (++offset == 8)
308
58.3k
  {
309
58.3k
    offset = 0;
310
58.3k
    buffer++;
311
58.3k
  }
312
553k
      bit <<= 1;
313
553k
    }
314
38.0k
  return result;
315
38.0k
}
316
317
static void
318
bit_copy (bfd_byte *buffer, int offset, int count, char *to)
319
13.5k
{
320
13.5k
  if (offset < 0 || count < 0)
321
0
    return;
322
82.7k
  for (; count > 8; count -= 8, to++, offset += 8)
323
69.2k
    *to = bit_extract (buffer, offset, 8);
324
13.5k
  *to = bit_extract (buffer, offset, count);
325
13.5k
}
326
327
static int
328
sign_extend (unsigned int value, unsigned int bits)
329
253k
{
330
253k
  unsigned int sign = 1u << (bits - 1);
331
253k
  return ((value & (sign + sign - 1)) ^ sign) - sign;
332
253k
}
333
334
static void
335
flip_bytes (char *ptr, int count)
336
100k
{
337
100k
  char tmp;
338
339
273k
  while (count > 0)
340
173k
    {
341
173k
      tmp = ptr[0];
342
173k
      ptr[0] = ptr[count - 1];
343
173k
      ptr[count - 1] = tmp;
344
173k
      ptr++;
345
173k
      count -= 2;
346
173k
    }
347
100k
}
348

349
/* Given a character C, does it represent a general addressing mode?  */
350
603k
#define Is_gen(c) (strchr ("FLBWDAIZf", (c)) != NULL)
351
352
/* Adressing modes.  */
353
1.08M
#define Adrmod_index_byte        0x1c
354
1.07M
#define Adrmod_index_word        0x1d
355
1.06M
#define Adrmod_index_doubleword  0x1e
356
1.05M
#define Adrmod_index_quadword    0x1f
357
358
/* Is MODE an indexed addressing mode?  */
359
#define Adrmod_is_index(mode) \
360
544k
  (   mode == Adrmod_index_byte \
361
544k
   || mode == Adrmod_index_word \
362
544k
   || mode == Adrmod_index_doubleword \
363
544k
   || mode == Adrmod_index_quadword)
364
365

366
static int
367
get_displacement (bfd_byte *buffer, int *aoffsetp)
368
229k
{
369
229k
  int Ivalue;
370
229k
  short Ivalue2;
371
372
229k
  Ivalue = bit_extract (buffer, *aoffsetp, 8);
373
229k
  switch (Ivalue & 0xc0)
374
229k
    {
375
80.4k
    case 0x00:
376
146k
    case 0x40:
377
146k
      Ivalue = sign_extend (Ivalue, 7);
378
146k
      *aoffsetp += 8;
379
146k
      break;
380
39.6k
    case 0x80:
381
39.6k
      Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
382
39.6k
      flip_bytes ((char *) & Ivalue2, 2);
383
39.6k
      Ivalue = sign_extend (Ivalue2, 14);
384
39.6k
      *aoffsetp += 16;
385
39.6k
      break;
386
43.5k
    case 0xc0:
387
43.5k
      Ivalue = bit_extract (buffer, *aoffsetp, 32);
388
43.5k
      flip_bytes ((char *) & Ivalue, 4);
389
43.5k
      Ivalue = sign_extend (Ivalue, 30);
390
43.5k
      *aoffsetp += 32;
391
43.5k
      break;
392
229k
    }
393
229k
  return Ivalue;
394
229k
}
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
13.4k
{
400
13.4k
  int val;
401
402
13.4k
  if (len == 4)
403
6.24k
    val = (bit_extract_simple (p, 23, 8)/*exponent*/ == 0xff
404
6.24k
     || (bit_extract_simple (p, 23, 8)/*exponent*/ == 0
405
5.81k
         && bit_extract_simple (p, 0, 23)/*mantisa*/ != 0));
406
7.18k
  else if (len == 8)
407
7.18k
    val = (bit_extract_simple (p, 52, 11)/*exponent*/ == 0x7ff
408
7.18k
     || (bit_extract_simple (p, 52, 11)/*exponent*/ == 0
409
7.04k
         && (bit_extract_simple (p, 0, 32)/*low mantisa*/ != 0
410
4.25k
       || bit_extract_simple (p, 32, 20)/*high mantisa*/ != 0)));
411
0
  else
412
0
    val = 1;
413
13.4k
  return (val);
414
13.4k
}
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
683k
{
461
683k
  union
462
683k
  {
463
683k
    float f;
464
683k
    double d;
465
683k
    int i[2];
466
683k
  } value;
467
683k
  int Ivalue;
468
683k
  int addr_mode;
469
683k
  int disp1, disp2;
470
683k
  int size;
471
472
683k
  switch (d)
473
683k
    {
474
198
    case 'f':
475
      /* A "gen" operand but 5 bits from the end of instruction.  */
476
198
      ioffset -= 5;
477
      /* Fall through.  */
478
1.47k
    case 'Z':
479
12.1k
    case 'F':
480
20.2k
    case 'L':
481
284k
    case 'I':
482
477k
    case 'B':
483
532k
    case 'W':
484
598k
    case 'D':
485
615k
    case 'A':
486
615k
      addr_mode = bit_extract (buffer, ioffset - 5, 5);
487
615k
      ioffset -= 5;
488
615k
      switch (addr_mode)
489
615k
  {
490
280k
  case 0x0: case 0x1: case 0x2: case 0x3:
491
334k
  case 0x4: case 0x5: case 0x6: case 0x7:
492
    /* Register mode R0 -- R7.  */
493
334k
    switch (d)
494
334k
      {
495
1.53k
      case 'F':
496
1.92k
      case 'L':
497
2.57k
      case 'Z':
498
2.57k
        sprintf (result, "f%d", addr_mode);
499
2.57k
        break;
500
331k
      default:
501
331k
        sprintf (result, "r%d", addr_mode);
502
334k
      }
503
334k
    break;
504
334k
  case 0x8: case 0x9: case 0xa: case 0xb:
505
90.9k
  case 0xc: case 0xd: case 0xe: case 0xf:
506
    /* Register relative disp(R0 -- R7).  */
507
90.9k
    disp1 = get_displacement (buffer, aoffsetp);
508
90.9k
    sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
509
90.9k
    break;
510
13.9k
  case 0x10:
511
23.4k
  case 0x11:
512
29.3k
  case 0x12:
513
    /* Memory relative disp2(disp1(FP, SP, SB)).  */
514
29.3k
    disp1 = get_displacement (buffer, aoffsetp);
515
29.3k
    disp2 = get_displacement (buffer, aoffsetp);
516
29.3k
    sprintf (result, "%d(%d(%s))", disp2, disp1,
517
29.3k
       addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
518
29.3k
    break;
519
7.00k
  case 0x13:
520
    /* Reserved.  */
521
7.00k
    sprintf (result, "reserved");
522
7.00k
    break;
523
28.5k
  case 0x14:
524
    /* Immediate.  */
525
28.5k
    switch (d)
526
28.5k
      {
527
7.73k
      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
7.73k
        sprintf (result, _("$<undefined>"));
534
7.73k
        break;
535
3.70k
      case 'B':
536
3.70k
        Ivalue = bit_extract (buffer, *aoffsetp, 8);
537
3.70k
        Ivalue = sign_extend (Ivalue, 8);
538
3.70k
        *aoffsetp += 8;
539
3.70k
        sprintf (result, "$%d", Ivalue);
540
3.70k
        break;
541
1.80k
      case 'W':
542
1.80k
        Ivalue = bit_extract (buffer, *aoffsetp, 16);
543
1.80k
        flip_bytes ((char *) & Ivalue, 2);
544
1.80k
        *aoffsetp += 16;
545
1.80k
        Ivalue = sign_extend (Ivalue, 16);
546
1.80k
        sprintf (result, "$%d", Ivalue);
547
1.80k
        break;
548
1.79k
      case 'D':
549
1.79k
        Ivalue = bit_extract (buffer, *aoffsetp, 32);
550
1.79k
        flip_bytes ((char *) & Ivalue, 4);
551
1.79k
        *aoffsetp += 32;
552
1.79k
        sprintf (result, "$%d", Ivalue);
553
1.79k
        break;
554
6.33k
      case 'F':
555
6.33k
        bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
556
6.33k
        flip_bytes ((char *) &value.f, 4);
557
6.33k
        *aoffsetp += 32;
558
6.33k
        if (INVALID_FLOAT (&value.f, 4))
559
3.29k
    sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
560
3.03k
        else /* Assume host has ieee float.  */
561
3.03k
    sprintf (result, "$%g", value.f);
562
6.33k
        break;
563
7.19k
      case 'L':
564
7.19k
        bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
565
7.19k
        flip_bytes ((char *) &value.d, 8);
566
7.19k
        *aoffsetp += 64;
567
7.19k
        if (INVALID_FLOAT (&value.d, 8))
568
3.74k
    sprintf (result, "<<invalid double 0x%.8x%.8x>>",
569
3.74k
       value.i[1], value.i[0]);
570
3.45k
        else /* Assume host has ieee float.  */
571
3.45k
    sprintf (result, "$%g", value.d);
572
7.19k
        break;
573
28.5k
      }
574
28.4k
    break;
575
28.4k
  case 0x15:
576
    /* Absolute @disp.  */
577
8.17k
    disp1 = get_displacement (buffer, aoffsetp);
578
8.17k
    sprintf (result, "@|%d|", disp1);
579
8.17k
    break;
580
6.60k
  case 0x16:
581
    /* External EXT(disp1) + disp2 (Mod table stuff).  */
582
6.60k
    disp1 = get_displacement (buffer, aoffsetp);
583
6.60k
    disp2 = get_displacement (buffer, aoffsetp);
584
6.60k
    sprintf (result, "EXT(%d) + %d", disp1, disp2);
585
6.60k
    break;
586
8.19k
  case 0x17:
587
    /* Top of stack tos.  */
588
8.19k
    sprintf (result, "tos");
589
8.19k
    break;
590
13.4k
  case 0x18:
591
    /* Memory space disp(FP).  */
592
13.4k
    disp1 = get_displacement (buffer, aoffsetp);
593
13.4k
    sprintf (result, "%d(fp)", disp1);
594
13.4k
    break;
595
6.55k
  case 0x19:
596
    /* Memory space disp(SP).  */
597
6.55k
    disp1 = get_displacement (buffer, aoffsetp);
598
6.55k
    sprintf (result, "%d(sp)", disp1);
599
6.55k
    break;
600
4.33k
  case 0x1a:
601
    /* Memory space disp(SB).  */
602
4.33k
    disp1 = get_displacement (buffer, aoffsetp);
603
4.33k
    sprintf (result, "%d(sb)", disp1);
604
4.33k
    break;
605
6.01k
  case 0x1b:
606
    /* Memory space disp(PC).  */
607
6.01k
    disp1 = get_displacement (buffer, aoffsetp);
608
6.01k
    *result++ = NEXT_IS_ADDR;
609
6.01k
    sprintf (result, "%" PRIx64, (uint64_t) (addr + disp1));
610
6.01k
    result += strlen (result);
611
6.01k
    *result++ = NEXT_IS_ADDR;
612
6.01k
    *result = '\0';
613
6.01k
    break;
614
16.1k
  case 0x1c:
615
27.7k
  case 0x1d:
616
41.0k
  case 0x1e:
617
71.2k
  case 0x1f:
618
71.2k
    {
619
71.2k
      int bit_index;
620
71.2k
      static const char *ind = "bwdq";
621
71.2k
      char *off;
622
623
      /* Scaled index basemode[R0 -- R7:B,W,D,Q].  */
624
71.2k
      bit_index = bit_extract (buffer, index_offset - 8, 3);
625
71.2k
      print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
626
71.2k
          result, 0);
627
71.2k
      off = result + strlen (result);
628
71.2k
      sprintf (off, "[r%d:%c]", bit_index, ind[addr_mode & 3]);
629
71.2k
    }
630
71.2k
    break;
631
615k
  }
632
614k
      break;
633
614k
    case 'H':
634
18.2k
    case 'q':
635
18.2k
      Ivalue = bit_extract (buffer, ioffset-4, 4);
636
18.2k
      Ivalue = sign_extend (Ivalue, 4);
637
18.2k
      sprintf (result, "%d", Ivalue);
638
18.2k
      ioffset -= 4;
639
18.2k
      break;
640
1.88k
    case 'r':
641
1.88k
      Ivalue = bit_extract (buffer, ioffset-3, 3);
642
1.88k
      sprintf (result, "r%d", Ivalue&7);
643
1.88k
      ioffset -= 3;
644
1.88k
      break;
645
9.30k
    case 'd':
646
9.30k
      sprintf (result, "%d", get_displacement (buffer, aoffsetp));
647
9.30k
      break;
648
368
    case 'b':
649
368
      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
368
      size = bit_extract(buffer, ioffset-6, 2);
657
368
      if (size == 0)    /* 00 => b.  */
658
237
  size = 1;
659
131
      else if (size == 1)  /* 01 => w.  */
660
59
  size = 2;
661
72
      else
662
72
  size = 4;   /* 11 => d.  */
663
664
368
      sprintf (result, "%d", (Ivalue / size) + 1);
665
368
      break;
666
18.5k
    case 'p':
667
18.5k
      *result++ = NEXT_IS_ADDR;
668
18.5k
      sprintf (result, "%" PRIx64,
669
18.5k
         (uint64_t) (addr + get_displacement (buffer, aoffsetp)));
670
18.5k
      result += strlen (result);
671
18.5k
      *result++ = NEXT_IS_ADDR;
672
18.5k
      *result = '\0';
673
18.5k
      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
2.99k
    case 'u':
680
2.99k
      Ivalue = bit_extract (buffer, *aoffsetp, 8);
681
2.99k
      optlist (Ivalue, opt_u, result);
682
2.99k
      *aoffsetp += 8;
683
2.99k
      break;
684
1.93k
    case 'U':
685
1.93k
      Ivalue = bit_extract (buffer, *aoffsetp, 8);
686
1.93k
      optlist (Ivalue, opt_U, result);
687
1.93k
      *aoffsetp += 8;
688
1.93k
      break;
689
166
    case 'O':
690
166
      Ivalue = bit_extract (buffer, ioffset - 9, 9);
691
166
      optlist (Ivalue, opt_O, result);
692
166
      ioffset -= 9;
693
166
      break;
694
205
    case 'C':
695
205
      Ivalue = bit_extract (buffer, ioffset - 4, 4);
696
205
      optlist (Ivalue, opt_C, result);
697
205
      ioffset -= 4;
698
205
      break;
699
733
    case 'S':
700
733
      Ivalue = bit_extract (buffer, ioffset - 8, 8);
701
733
      optlist (Ivalue, opt_S, result);
702
733
      ioffset -= 8;
703
733
      break;
704
243
    case 'M':
705
243
      Ivalue = bit_extract (buffer, ioffset - 4, 4);
706
243
      list_search (Ivalue, 0 ? list_M032 : list_M532, result);
707
243
      ioffset -= 4;
708
243
      break;
709
12.6k
    case 'P':
710
12.6k
      Ivalue = bit_extract (buffer, ioffset - 4, 4);
711
12.6k
      list_search (Ivalue, 0 ? list_P032 : list_P532, result);
712
12.6k
      ioffset -= 4;
713
12.6k
      break;
714
399
    case 'g':
715
399
      Ivalue = bit_extract (buffer, *aoffsetp, 3);
716
399
      sprintf (result, "%d", Ivalue);
717
399
      *aoffsetp += 3;
718
399
      break;
719
400
    case 'G':
720
400
      Ivalue = bit_extract(buffer, *aoffsetp, 5);
721
400
      sprintf (result, "%d", Ivalue + 1);
722
400
      *aoffsetp += 5;
723
400
      break;
724
683k
    }
725
682k
  return ioffset;
726
683k
}
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
436k
{
735
436k
  unsigned int i;
736
436k
  const char *d;
737
436k
  unsigned short first_word;
738
436k
  int ioffset;    /* Bits into instruction.  */
739
436k
  int aoffset;    /* Bits into arguments.  */
740
436k
  char arg_bufs[MAX_ARGS+1][ARG_LEN];
741
436k
  int argnum;
742
436k
  int maxarg;
743
436k
  struct private priv;
744
436k
  bfd_byte *buffer = priv.the_buffer;
745
436k
  dis_info = info;
746
747
436k
  info->private_data = & priv;
748
436k
  priv.max_fetched = priv.the_buffer;
749
436k
  priv.insn_start = memaddr;
750
436k
  if (OPCODES_SIGSETJMP (priv.bailout) != 0)
751
    /* Error return.  */
752
627
    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
436k
  FETCH_DATA (info, buffer + 1);
757
72.4M
  for (i = 0; i < NOPCODES; i++)
758
72.2M
    if (ns32k_opcodes[i].opcode_id_size <= 8
759
72.2M
  && ((buffer[0]
760
20.8M
       & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
761
20.8M
      == ns32k_opcodes[i].opcode_seed))
762
309k
      break;
763
436k
  if (i == NOPCODES)
764
127k
    {
765
      /* Maybe it is 9 to 16 bits big.  */
766
127k
      FETCH_DATA (info, buffer + 2);
767
127k
      first_word = read_memory_integer(buffer, 2);
768
769
38.5M
      for (i = 0; i < NOPCODES; i++)
770
38.4M
  if ((first_word
771
38.4M
       & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
772
38.4M
      == ns32k_opcodes[i].opcode_seed)
773
20.0k
    break;
774
775
      /* Handle undefined instructions.  */
776
127k
      if (i == NOPCODES)
777
107k
  {
778
107k
    (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
779
107k
    return 1;
780
107k
  }
781
127k
    }
782
783
329k
  (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
784
785
329k
  ioffset = ns32k_opcodes[i].opcode_size;
786
329k
  aoffset = ns32k_opcodes[i].opcode_size;
787
329k
  d = ns32k_opcodes[i].operands;
788
789
329k
  if (*d)
790
318k
    {
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
318k
      int index_offset[2];
794
795
      /* 0 for operand A, 1 for operand B, greater for other args.  */
796
318k
      int whicharg = 0;
797
798
318k
      (*dis_info->fprintf_func)(dis_info->stream, "\t");
799
800
318k
      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
318k
      index_offset[0] = -1;
807
318k
      index_offset[1] = -1;
808
318k
      if (Is_gen (d[1]))
809
290k
  {
810
290k
    int bitoff = d[1] == 'f' ? 10 : 5;
811
290k
    int addr_mode = bit_extract (buffer, ioffset - bitoff, 5);
812
813
290k
    if (Adrmod_is_index (addr_mode))
814
32.2k
      {
815
32.2k
        aoffset += 8;
816
32.2k
        index_offset[0] = aoffset;
817
32.2k
      }
818
290k
  }
819
820
318k
      if (d[2] && Is_gen (d[3]))
821
253k
  {
822
253k
    int addr_mode = bit_extract (buffer, ioffset - 10, 5);
823
824
253k
    if (Adrmod_is_index (addr_mode))
825
21.8k
      {
826
21.8k
        aoffset += 8;
827
21.8k
        index_offset[1] = aoffset;
828
21.8k
      }
829
253k
  }
830
831
930k
      while (*d)
832
611k
  {
833
611k
    argnum = *d - '1';
834
611k
    if (argnum >= MAX_ARGS)
835
0
      abort ();
836
611k
    d++;
837
611k
    if (argnum > maxarg)
838
293k
      maxarg = argnum;
839
611k
    ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
840
611k
            memaddr, arg_bufs[argnum],
841
611k
            whicharg > 1 ? -1 : index_offset[whicharg]);
842
611k
    d++;
843
611k
    whicharg++;
844
611k
  }
845
846
929k
      for (argnum = 0; argnum <= maxarg; argnum++)
847
611k
  {
848
611k
    bfd_vma addr;
849
611k
    char *ch;
850
851
3.81M
    for (ch = arg_bufs[argnum]; *ch;)
852
3.20M
      {
853
3.20M
        if (*ch == NEXT_IS_ADDR)
854
32.7k
    {
855
32.7k
      ++ch;
856
32.7k
      addr = bfd_scan_vma (ch, NULL, 16);
857
32.7k
      (*dis_info->print_address_func) (addr, dis_info);
858
225k
      while (*ch && *ch != NEXT_IS_ADDR)
859
192k
        ++ch;
860
32.7k
      if (*ch)
861
32.7k
        ++ch;
862
32.7k
    }
863
3.17M
        else
864
3.17M
    (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
865
3.20M
      }
866
611k
    if (argnum < maxarg)
867
293k
      (*dis_info->fprintf_func)(dis_info->stream, ", ");
868
611k
  }
869
318k
    }
870
329k
  return aoffset / 8;
871
329k
}