Coverage Report

Created: 2025-06-24 06:45

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