]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/ns32k-dis.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / opcodes / ns32k-dis.c
CommitLineData
252b5132 1/* Print National Semiconductor 32000 instructions.
b3adc24a 2 Copyright (C) 1986-2020 Free Software Foundation, Inc.
252b5132 3
9b201bb5 4 This file is part of the GNU opcodes library.
252b5132 5
9b201bb5 6 This library is free software; you can redistribute it and/or modify
47b0e7ad 7 it under the terms of the GNU General Public License as published by
9b201bb5
NC
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
252b5132 10
9b201bb5
NC
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.
252b5132 15
47b0e7ad
NC
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. */
252b5132 20
252b5132 21#include "sysdep.h"
3db64b00 22#include "bfd.h"
88c1242d 23#include "disassemble.h"
252b5132
RH
24#if !defined(const) && !defined(__STDC__)
25#define const
26#endif
27#include "opcode/ns32k.h"
28#include "opintl.h"
29
30static disassemble_info *dis_info;
31
47b0e7ad
NC
32/* Hacks to get it to compile <= READ THESE AS FIXES NEEDED. */
33#define INVALID_FLOAT(val, size) invalid_float ((bfd_byte *) val, size)
34
35static long
36read_memory_integer (unsigned char * addr, int nr)
252b5132
RH
37{
38 long val;
39 int i;
47b0e7ad
NC
40
41 for (val = 0, i = nr - 1; i >= 0; i--)
42 {
43 val = (val << 8);
44 val |= (0xff & *(addr + i));
45 }
252b5132
RH
46 return val;
47}
48
49/* 32000 instructions are never longer than this. */
50#define MAXLEN 62
51
252b5132
RH
52#include <setjmp.h>
53
54struct 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;
8df14d78 60 OPCODES_SIGJMP_BUF bailout;
252b5132
RH
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 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
69 ? 1 : fetch_data ((info), (addr)))
70
71static int
47b0e7ad 72fetch_data (struct disassemble_info *info, bfd_byte *addr)
252b5132
RH
73{
74 int status;
47b0e7ad 75 struct private *priv = (struct private *) info->private_data;
252b5132
RH
76 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
77
78 status = (*info->read_memory_func) (start,
79 priv->max_fetched,
80 addr - priv->max_fetched,
81 info);
82 if (status != 0)
83 {
84 (*info->memory_error_func) (status, start, info);
8df14d78 85 OPCODES_SIGLONGJMP (priv->bailout, 1);
252b5132
RH
86 }
87 else
88 priv->max_fetched = addr;
89 return 1;
90}
47b0e7ad 91
252b5132
RH
92/* Number of elements in the opcode table. */
93#define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
94
95#define NEXT_IS_ADDR '|'
96
97\f
47b0e7ad
NC
98struct 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. */
252b5132
RH
103};
104
105\f
47b0e7ad 106static const struct ns32k_option opt_u[]= /* Restore, exit. */
252b5132
RH
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
47b0e7ad 119static const struct ns32k_option opt_U[]= /* Save, enter. */
252b5132
RH
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
47b0e7ad 132static const struct ns32k_option opt_O[]= /* Setcfg. */
252b5132
RH
133{
134 { "c", 0x8, 0x8 },
135 { "m", 0x4, 0x4 },
136 { "f", 0x2, 0x2 },
137 { "i", 0x1, 0x1 },
138 { 0 , 0x0, 0x0 }
139};
140
47b0e7ad 141static const struct ns32k_option opt_C[]= /* Cinv. */
252b5132
RH
142{
143 { "a", 0x4, 0x4 },
144 { "i", 0x2, 0x2 },
145 { "d", 0x1, 0x1 },
146 { 0 , 0x0, 0x0 }
147};
148
47b0e7ad 149static const struct ns32k_option opt_S[]= /* String inst. */
252b5132
RH
150{
151 { "b", 0x1, 0x1 },
152 { "u", 0x6, 0x6 },
153 { "w", 0x2, 0x2 },
154 { 0 , 0x0, 0x0 }
155};
156
47b0e7ad 157static const struct ns32k_option list_P532[]= /* Lpr spr. */
252b5132
RH
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
47b0e7ad 175static const struct ns32k_option list_M532[]= /* Lmr smr. */
252b5132
RH
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
47b0e7ad 187static const struct ns32k_option list_P032[]= /* Lpr spr. */
252b5132
RH
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
47b0e7ad 199static const struct ns32k_option list_M032[]= /* Lmr smr. */
252b5132
RH
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
47b0e7ad
NC
215/* Figure out which options are present. */
216
252b5132 217static void
47b0e7ad 218optlist (int options, const struct ns32k_option * optionP, char * result)
252b5132 219{
47b0e7ad
NC
220 if (options == 0)
221 {
222 sprintf (result, "[]");
223 return;
252b5132 224 }
47b0e7ad
NC
225
226 sprintf (result, "[");
227
228 for (; (options != 0) && optionP->pattern; optionP++)
229 {
230 if ((options & optionP->match) == optionP->value)
231 {
232 /* We found a match, update result and options. */
233 strcat (result, optionP->pattern);
234 options &= ~optionP->value;
235 if (options != 0) /* More options to come. */
236 strcat (result, ",");
252b5132
RH
237 }
238 }
252b5132 239
47b0e7ad
NC
240 if (options != 0)
241 strcat (result, "undefined");
242
243 strcat (result, "]");
252b5132
RH
244}
245
246static void
47b0e7ad 247list_search (int reg_value, const struct ns32k_option *optionP, char *result)
252b5132 248{
47b0e7ad
NC
249 for (; optionP->pattern; optionP++)
250 {
251 if ((reg_value & optionP->match) == optionP->value)
252 {
253 sprintf (result, "%s", optionP->pattern);
254 return;
252b5132
RH
255 }
256 }
47b0e7ad 257 sprintf (result, "undefined");
252b5132
RH
258}
259\f
47b0e7ad 260/* Extract "count" bits starting "offset" bits into buffer. */
252b5132
RH
261
262static int
47b0e7ad 263bit_extract (bfd_byte *buffer, int offset, int count)
252b5132 264{
fb4cb4e2
AM
265 unsigned int result;
266 unsigned int bit;
252b5132 267
d1e304bc
NC
268 if (offset < 0 || count < 0)
269 return 0;
252b5132
RH
270 buffer += offset >> 3;
271 offset &= 7;
272 bit = 1;
273 result = 0;
274 while (count--)
275 {
47b0e7ad 276 FETCH_DATA (dis_info, buffer + 1);
252b5132
RH
277 if ((*buffer & (1 << offset)))
278 result |= bit;
279 if (++offset == 8)
280 {
281 offset = 0;
282 buffer++;
283 }
284 bit <<= 1;
285 }
286 return result;
287}
288
47b0e7ad
NC
289/* Like bit extract but the buffer is valid and doen't need to be fetched. */
290
252b5132 291static int
47b0e7ad 292bit_extract_simple (bfd_byte *buffer, int offset, int count)
252b5132 293{
fb4cb4e2
AM
294 unsigned int result;
295 unsigned int bit;
252b5132 296
d1e304bc
NC
297 if (offset < 0 || count < 0)
298 return 0;
252b5132
RH
299 buffer += offset >> 3;
300 offset &= 7;
301 bit = 1;
302 result = 0;
303 while (count--)
304 {
305 if ((*buffer & (1 << offset)))
306 result |= bit;
307 if (++offset == 8)
308 {
309 offset = 0;
310 buffer++;
311 }
312 bit <<= 1;
313 }
314 return result;
315}
316
317static void
47b0e7ad 318bit_copy (bfd_byte *buffer, int offset, int count, char *to)
252b5132 319{
d1e304bc
NC
320 if (offset < 0 || count < 0)
321 return;
47b0e7ad 322 for (; count > 8; count -= 8, to++, offset += 8)
252b5132
RH
323 *to = bit_extract (buffer, offset, 8);
324 *to = bit_extract (buffer, offset, count);
325}
326
252b5132 327static int
fb4cb4e2 328sign_extend (unsigned int value, unsigned int bits)
252b5132 329{
5afa80e9
AM
330 unsigned int sign = 1u << (bits - 1);
331 return ((value & (sign + sign - 1)) ^ sign) - sign;
252b5132
RH
332}
333
334static void
47b0e7ad 335flip_bytes (char *ptr, int count)
252b5132
RH
336{
337 char tmp;
338
339 while (count > 0)
340 {
341 tmp = ptr[0];
47b0e7ad
NC
342 ptr[0] = ptr[count - 1];
343 ptr[count - 1] = tmp;
252b5132
RH
344 ptr++;
345 count -= 2;
346 }
347}
348\f
349/* Given a character C, does it represent a general addressing mode? */
90dee485 350#define Is_gen(c) (strchr ("FLBWDAIZf", (c)) != NULL)
252b5132
RH
351
352/* Adressing modes. */
47b0e7ad
NC
353#define Adrmod_index_byte 0x1c
354#define Adrmod_index_word 0x1d
355#define Adrmod_index_doubleword 0x1e
356#define Adrmod_index_quadword 0x1f
252b5132
RH
357
358/* Is MODE an indexed addressing mode? */
359#define Adrmod_is_index(mode) \
47b0e7ad 360 ( mode == Adrmod_index_byte \
252b5132
RH
361 || mode == Adrmod_index_word \
362 || mode == Adrmod_index_doubleword \
363 || mode == Adrmod_index_quadword)
364
365\f
47b0e7ad
NC
366static int
367get_displacement (bfd_byte *buffer, int *aoffsetp)
252b5132 368{
47b0e7ad
NC
369 int Ivalue;
370 short Ivalue2;
252b5132 371
47b0e7ad
NC
372 Ivalue = bit_extract (buffer, *aoffsetp, 8);
373 switch (Ivalue & 0xc0)
252b5132 374 {
47b0e7ad
NC
375 case 0x00:
376 case 0x40:
377 Ivalue = sign_extend (Ivalue, 7);
378 *aoffsetp += 8;
379 break;
380 case 0x80:
381 Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
382 flip_bytes ((char *) & Ivalue2, 2);
383 Ivalue = sign_extend (Ivalue2, 14);
384 *aoffsetp += 16;
385 break;
386 case 0xc0:
387 Ivalue = bit_extract (buffer, *aoffsetp, 32);
388 flip_bytes ((char *) & Ivalue, 4);
389 Ivalue = sign_extend (Ivalue, 30);
390 *aoffsetp += 32;
391 break;
392 }
393 return Ivalue;
394}
252b5132 395
47b0e7ad
NC
396#if 1 /* A version that should work on ns32k f's&d's on any machine. */
397static int
398invalid_float (bfd_byte *p, int len)
399{
400 int val;
401
402 if (len == 4)
403 val = (bit_extract_simple (p, 23, 8)/*exponent*/ == 0xff
404 || (bit_extract_simple (p, 23, 8)/*exponent*/ == 0
405 && bit_extract_simple (p, 0, 23)/*mantisa*/ != 0));
406 else if (len == 8)
407 val = (bit_extract_simple (p, 52, 11)/*exponent*/ == 0x7ff
408 || (bit_extract_simple (p, 52, 11)/*exponent*/ == 0
409 && (bit_extract_simple (p, 0, 32)/*low mantisa*/ != 0
410 || bit_extract_simple (p, 32, 20)/*high mantisa*/ != 0)));
411 else
412 val = 1;
413 return (val);
414}
415#else
416/* Assumes the bytes have been swapped to local order. */
417typedef union
43e65147 418{
47b0e7ad
NC
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;
252b5132 424
47b0e7ad
NC
425static int
426invalid_float (float_type_u *p, int len)
427{
428 int val;
252b5132 429
47b0e7ad
NC
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;
252b5132 439}
47b0e7ad 440#endif
252b5132
RH
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
03704c77 449 of the index byte (it contains -1 if this operand is not a
252b5132
RH
450 general operand using scaled indexed addressing mode). */
451
452static int
47b0e7ad
NC
453print_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)
252b5132 460{
47b0e7ad
NC
461 union
462 {
6a51a8a8
AM
463 float f;
464 double d;
465 int i[2];
466 } value;
252b5132 467 int Ivalue;
6a51a8a8 468 int addr_mode;
252b5132 469 int disp1, disp2;
252b5132
RH
470 int size;
471
472 switch (d)
473 {
474 case 'f':
47b0e7ad 475 /* A "gen" operand but 5 bits from the end of instruction. */
252b5132 476 ioffset -= 5;
1a0670f3 477 /* Fall through. */
252b5132
RH
478 case 'Z':
479 case 'F':
480 case 'L':
481 case 'I':
482 case 'B':
483 case 'W':
484 case 'D':
485 case 'A':
47b0e7ad 486 addr_mode = bit_extract (buffer, ioffset - 5, 5);
252b5132
RH
487 ioffset -= 5;
488 switch (addr_mode)
489 {
490 case 0x0: case 0x1: case 0x2: case 0x3:
491 case 0x4: case 0x5: case 0x6: case 0x7:
47b0e7ad 492 /* Register mode R0 -- R7. */
252b5132
RH
493 switch (d)
494 {
495 case 'F':
496 case 'L':
497 case 'Z':
498 sprintf (result, "f%d", addr_mode);
499 break;
500 default:
501 sprintf (result, "r%d", addr_mode);
502 }
503 break;
504 case 0x8: case 0x9: case 0xa: case 0xb:
505 case 0xc: case 0xd: case 0xe: case 0xf:
47b0e7ad 506 /* Register relative disp(R0 -- R7). */
252b5132
RH
507 disp1 = get_displacement (buffer, aoffsetp);
508 sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
509 break;
510 case 0x10:
511 case 0x11:
512 case 0x12:
47b0e7ad 513 /* Memory relative disp2(disp1(FP, SP, SB)). */
252b5132
RH
514 disp1 = get_displacement (buffer, aoffsetp);
515 disp2 = get_displacement (buffer, aoffsetp);
516 sprintf (result, "%d(%d(%s))", disp2, disp1,
47b0e7ad 517 addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
252b5132
RH
518 break;
519 case 0x13:
47b0e7ad 520 /* Reserved. */
252b5132
RH
521 sprintf (result, "reserved");
522 break;
523 case 0x14:
47b0e7ad 524 /* Immediate. */
252b5132
RH
525 switch (d)
526 {
47b0e7ad
NC
527 case 'I':
528 case 'Z':
529 case 'A':
252b5132 530 /* I and Z are output operands and can`t be immediate
47b0e7ad
NC
531 A is an address and we can`t have the address of
532 an immediate either. We don't know how much to increase
533 aoffsetp by since whatever generated this is broken
534 anyway! */
252b5132
RH
535 sprintf (result, _("$<undefined>"));
536 break;
537 case 'B':
538 Ivalue = bit_extract (buffer, *aoffsetp, 8);
539 Ivalue = sign_extend (Ivalue, 8);
540 *aoffsetp += 8;
541 sprintf (result, "$%d", Ivalue);
542 break;
543 case 'W':
544 Ivalue = bit_extract (buffer, *aoffsetp, 16);
fc05c67f 545 flip_bytes ((char *) & Ivalue, 2);
252b5132
RH
546 *aoffsetp += 16;
547 Ivalue = sign_extend (Ivalue, 16);
548 sprintf (result, "$%d", Ivalue);
549 break;
550 case 'D':
551 Ivalue = bit_extract (buffer, *aoffsetp, 32);
fc05c67f 552 flip_bytes ((char *) & Ivalue, 4);
252b5132
RH
553 *aoffsetp += 32;
554 sprintf (result, "$%d", Ivalue);
555 break;
556 case 'F':
6a51a8a8
AM
557 bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
558 flip_bytes ((char *) &value.f, 4);
252b5132 559 *aoffsetp += 32;
6a51a8a8
AM
560 if (INVALID_FLOAT (&value.f, 4))
561 sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
47b0e7ad 562 else /* Assume host has ieee float. */
6a51a8a8 563 sprintf (result, "$%g", value.f);
252b5132
RH
564 break;
565 case 'L':
6a51a8a8
AM
566 bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
567 flip_bytes ((char *) &value.d, 8);
252b5132 568 *aoffsetp += 64;
6a51a8a8
AM
569 if (INVALID_FLOAT (&value.d, 8))
570 sprintf (result, "<<invalid double 0x%.8x%.8x>>",
571 value.i[1], value.i[0]);
47b0e7ad 572 else /* Assume host has ieee float. */
6a51a8a8 573 sprintf (result, "$%g", value.d);
252b5132
RH
574 break;
575 }
576 break;
577 case 0x15:
47b0e7ad 578 /* Absolute @disp. */
252b5132
RH
579 disp1 = get_displacement (buffer, aoffsetp);
580 sprintf (result, "@|%d|", disp1);
581 break;
582 case 0x16:
47b0e7ad 583 /* External EXT(disp1) + disp2 (Mod table stuff). */
252b5132
RH
584 disp1 = get_displacement (buffer, aoffsetp);
585 disp2 = get_displacement (buffer, aoffsetp);
586 sprintf (result, "EXT(%d) + %d", disp1, disp2);
587 break;
588 case 0x17:
47b0e7ad 589 /* Top of stack tos. */
252b5132
RH
590 sprintf (result, "tos");
591 break;
592 case 0x18:
47b0e7ad 593 /* Memory space disp(FP). */
252b5132
RH
594 disp1 = get_displacement (buffer, aoffsetp);
595 sprintf (result, "%d(fp)", disp1);
596 break;
597 case 0x19:
47b0e7ad 598 /* Memory space disp(SP). */
252b5132
RH
599 disp1 = get_displacement (buffer, aoffsetp);
600 sprintf (result, "%d(sp)", disp1);
601 break;
602 case 0x1a:
47b0e7ad 603 /* Memory space disp(SB). */
252b5132
RH
604 disp1 = get_displacement (buffer, aoffsetp);
605 sprintf (result, "%d(sb)", disp1);
606 break;
607 case 0x1b:
47b0e7ad 608 /* Memory space disp(PC). */
252b5132
RH
609 disp1 = get_displacement (buffer, aoffsetp);
610 *result++ = NEXT_IS_ADDR;
611 sprintf_vma (result, addr + disp1);
612 result += strlen (result);
613 *result++ = NEXT_IS_ADDR;
614 *result = '\0';
615 break;
616 case 0x1c:
617 case 0x1d:
618 case 0x1e:
619 case 0x1f:
252b5132 620 {
91d6fa6a 621 int bit_index;
252b5132
RH
622 static const char *ind = "bwdq";
623 char *off;
43e65147 624
91d6fa6a
NC
625 /* Scaled index basemode[R0 -- R7:B,W,D,Q]. */
626 bit_index = bit_extract (buffer, index_offset - 8, 3);
627 print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
628 result, 0);
252b5132 629 off = result + strlen (result);
91d6fa6a 630 sprintf (off, "[r%d:%c]", bit_index, ind[addr_mode & 3]);
252b5132
RH
631 }
632 break;
633 }
634 break;
635 case 'H':
636 case 'q':
637 Ivalue = bit_extract (buffer, ioffset-4, 4);
638 Ivalue = sign_extend (Ivalue, 4);
639 sprintf (result, "%d", Ivalue);
640 ioffset -= 4;
641 break;
642 case 'r':
643 Ivalue = bit_extract (buffer, ioffset-3, 3);
644 sprintf (result, "r%d", Ivalue&7);
645 ioffset -= 3;
646 break;
647 case 'd':
648 sprintf (result, "%d", get_displacement (buffer, aoffsetp));
649 break;
650 case 'b':
651 Ivalue = get_displacement (buffer, aoffsetp);
47b0e7ad
NC
652 /* Warning!! HACK ALERT!
653 Operand type 'b' is only used by the cmp{b,w,d} and
654 movm{b,w,d} instructions; we need to know whether
655 it's a `b' or `w' or `d' instruction; and for both
656 cmpm and movm it's stored at the same place so we
657 just grab two bits of the opcode and look at it... */
252b5132 658 size = bit_extract(buffer, ioffset-6, 2);
47b0e7ad 659 if (size == 0) /* 00 => b. */
252b5132 660 size = 1;
47b0e7ad 661 else if (size == 1) /* 01 => w. */
252b5132
RH
662 size = 2;
663 else
47b0e7ad 664 size = 4; /* 11 => d. */
252b5132
RH
665
666 sprintf (result, "%d", (Ivalue / size) + 1);
667 break;
668 case 'p':
669 *result++ = NEXT_IS_ADDR;
670 sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
671 result += strlen (result);
672 *result++ = NEXT_IS_ADDR;
673 *result = '\0';
674 break;
675 case 'i':
676 Ivalue = bit_extract (buffer, *aoffsetp, 8);
677 *aoffsetp += 8;
678 sprintf (result, "0x%x", Ivalue);
679 break;
680 case 'u':
681 Ivalue = bit_extract (buffer, *aoffsetp, 8);
47b0e7ad 682 optlist (Ivalue, opt_u, result);
252b5132
RH
683 *aoffsetp += 8;
684 break;
685 case 'U':
47b0e7ad
NC
686 Ivalue = bit_extract (buffer, *aoffsetp, 8);
687 optlist (Ivalue, opt_U, result);
252b5132
RH
688 *aoffsetp += 8;
689 break;
690 case 'O':
47b0e7ad
NC
691 Ivalue = bit_extract (buffer, ioffset - 9, 9);
692 optlist (Ivalue, opt_O, result);
252b5132
RH
693 ioffset -= 9;
694 break;
695 case 'C':
47b0e7ad
NC
696 Ivalue = bit_extract (buffer, ioffset - 4, 4);
697 optlist (Ivalue, opt_C, result);
252b5132
RH
698 ioffset -= 4;
699 break;
700 case 'S':
47b0e7ad
NC
701 Ivalue = bit_extract (buffer, ioffset - 8, 8);
702 optlist (Ivalue, opt_S, result);
252b5132
RH
703 ioffset -= 8;
704 break;
705 case 'M':
47b0e7ad
NC
706 Ivalue = bit_extract (buffer, ioffset - 4, 4);
707 list_search (Ivalue, 0 ? list_M032 : list_M532, result);
252b5132
RH
708 ioffset -= 4;
709 break;
710 case 'P':
47b0e7ad
NC
711 Ivalue = bit_extract (buffer, ioffset - 4, 4);
712 list_search (Ivalue, 0 ? list_P032 : list_P532, result);
252b5132
RH
713 ioffset -= 4;
714 break;
715 case 'g':
47b0e7ad
NC
716 Ivalue = bit_extract (buffer, *aoffsetp, 3);
717 sprintf (result, "%d", Ivalue);
252b5132
RH
718 *aoffsetp += 3;
719 break;
720 case 'G':
721 Ivalue = bit_extract(buffer, *aoffsetp, 5);
47b0e7ad 722 sprintf (result, "%d", Ivalue + 1);
252b5132
RH
723 *aoffsetp += 5;
724 break;
725 }
726 return ioffset;
727}
728
47b0e7ad
NC
729\f
730/* Print the 32000 instruction at address MEMADDR in debugged memory,
731 on STREAM. Returns length of the instruction, in bytes. */
732
733int
734print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
252b5132 735{
47b0e7ad
NC
736 unsigned int i;
737 const char *d;
738 unsigned short first_word;
739 int ioffset; /* Bits into instruction. */
740 int aoffset; /* Bits into arguments. */
741 char arg_bufs[MAX_ARGS+1][ARG_LEN];
742 int argnum;
743 int maxarg;
744 struct private priv;
745 bfd_byte *buffer = priv.the_buffer;
746 dis_info = info;
252b5132 747
47b0e7ad
NC
748 info->private_data = & priv;
749 priv.max_fetched = priv.the_buffer;
750 priv.insn_start = memaddr;
8df14d78 751 if (OPCODES_SIGSETJMP (priv.bailout) != 0)
47b0e7ad
NC
752 /* Error return. */
753 return -1;
754
755 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
756 us over the end of accessible data unnecessarilly. */
757 FETCH_DATA (info, buffer + 1);
758 for (i = 0; i < NOPCODES; i++)
759 if (ns32k_opcodes[i].opcode_id_size <= 8
760 && ((buffer[0]
761 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
762 == ns32k_opcodes[i].opcode_seed))
252b5132 763 break;
47b0e7ad
NC
764 if (i == NOPCODES)
765 {
766 /* Maybe it is 9 to 16 bits big. */
767 FETCH_DATA (info, buffer + 2);
768 first_word = read_memory_integer(buffer, 2);
769
770 for (i = 0; i < NOPCODES; i++)
771 if ((first_word
772 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
773 == ns32k_opcodes[i].opcode_seed)
774 break;
775
776 /* Handle undefined instructions. */
777 if (i == NOPCODES)
778 {
779 (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
780 return 1;
781 }
252b5132 782 }
252b5132 783
47b0e7ad 784 (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
252b5132 785
47b0e7ad
NC
786 ioffset = ns32k_opcodes[i].opcode_size;
787 aoffset = ns32k_opcodes[i].opcode_size;
788 d = ns32k_opcodes[i].operands;
252b5132 789
47b0e7ad
NC
790 if (*d)
791 {
792 /* Offset in bits of the first thing beyond each index byte.
03704c77
AM
793 Element 0 is for operand A and element 1 is for operand B. */
794 int index_offset[2];
47b0e7ad
NC
795
796 /* 0 for operand A, 1 for operand B, greater for other args. */
797 int whicharg = 0;
43e65147 798
47b0e7ad
NC
799 (*dis_info->fprintf_func)(dis_info->stream, "\t");
800
801 maxarg = 0;
802
803 /* First we have to find and keep track of the index bytes,
804 if we are using scaled indexed addressing mode, since the index
805 bytes occur right after the basic instruction, not as part
806 of the addressing extension. */
03704c77
AM
807 index_offset[0] = -1;
808 index_offset[1] = -1;
90dee485 809 if (Is_gen (d[1]))
47b0e7ad 810 {
90dee485
AM
811 int bitoff = d[1] == 'f' ? 10 : 5;
812 int addr_mode = bit_extract (buffer, ioffset - bitoff, 5);
47b0e7ad
NC
813
814 if (Adrmod_is_index (addr_mode))
815 {
816 aoffset += 8;
817 index_offset[0] = aoffset;
818 }
819 }
820
90dee485 821 if (d[2] && Is_gen (d[3]))
47b0e7ad
NC
822 {
823 int addr_mode = bit_extract (buffer, ioffset - 10, 5);
824
825 if (Adrmod_is_index (addr_mode))
826 {
827 aoffset += 8;
828 index_offset[1] = aoffset;
829 }
830 }
831
832 while (*d)
833 {
834 argnum = *d - '1';
03704c77
AM
835 if (argnum >= MAX_ARGS)
836 abort ();
47b0e7ad 837 d++;
03704c77 838 if (argnum > maxarg)
47b0e7ad
NC
839 maxarg = argnum;
840 ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
841 memaddr, arg_bufs[argnum],
03704c77 842 whicharg > 1 ? -1 : index_offset[whicharg]);
47b0e7ad 843 d++;
03704c77 844 whicharg++;
47b0e7ad 845 }
d1e304bc 846
47b0e7ad
NC
847 for (argnum = 0; argnum <= maxarg; argnum++)
848 {
849 bfd_vma addr;
850 char *ch;
851
852 for (ch = arg_bufs[argnum]; *ch;)
853 {
854 if (*ch == NEXT_IS_ADDR)
855 {
856 ++ch;
857 addr = bfd_scan_vma (ch, NULL, 16);
858 (*dis_info->print_address_func) (addr, dis_info);
859 while (*ch && *ch != NEXT_IS_ADDR)
860 ++ch;
861 if (*ch)
862 ++ch;
863 }
864 else
865 (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
866 }
867 if (argnum < maxarg)
868 (*dis_info->fprintf_func)(dis_info->stream, ", ");
869 }
870 }
871 return aoffset / 8;
252b5132 872}