]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - opcodes/ns32k-dis.c
Add support for the GBZ80, Z180, and eZ80 variants of the Z80 architecure. Add an...
[thirdparty/binutils-gdb.git] / opcodes / ns32k-dis.c
1 /* Print National Semiconductor 32000 instructions.
2 Copyright (C) 1986-2020 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 #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 {
38 long val;
39 int i;
40
41 for (val = 0, i = nr - 1; i >= 0; i--)
42 {
43 val = (val << 8);
44 val |= (0xff & *(addr + i));
45 }
46 return val;
47 }
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 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
69 ? 1 : fetch_data ((info), (addr)))
70
71 static int
72 fetch_data (struct disassemble_info *info, bfd_byte *addr)
73 {
74 int status;
75 struct private *priv = (struct private *) info->private_data;
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);
85 OPCODES_SIGLONGJMP (priv->bailout, 1);
86 }
87 else
88 priv->max_fetched = addr;
89 return 1;
90 }
91
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
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 \f
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 {
220 if (options == 0)
221 {
222 sprintf (result, "[]");
223 return;
224 }
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, ",");
237 }
238 }
239
240 if (options != 0)
241 strcat (result, "undefined");
242
243 strcat (result, "]");
244 }
245
246 static void
247 list_search (int reg_value, const struct ns32k_option *optionP, char *result)
248 {
249 for (; optionP->pattern; optionP++)
250 {
251 if ((reg_value & optionP->match) == optionP->value)
252 {
253 sprintf (result, "%s", optionP->pattern);
254 return;
255 }
256 }
257 sprintf (result, "undefined");
258 }
259 \f
260 /* Extract "count" bits starting "offset" bits into buffer. */
261
262 static int
263 bit_extract (bfd_byte *buffer, int offset, int count)
264 {
265 unsigned int result;
266 unsigned int bit;
267
268 if (offset < 0 || count < 0)
269 return 0;
270 buffer += offset >> 3;
271 offset &= 7;
272 bit = 1;
273 result = 0;
274 while (count--)
275 {
276 FETCH_DATA (dis_info, buffer + 1);
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
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 {
294 unsigned int result;
295 unsigned int bit;
296
297 if (offset < 0 || count < 0)
298 return 0;
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
317 static void
318 bit_copy (bfd_byte *buffer, int offset, int count, char *to)
319 {
320 if (offset < 0 || count < 0)
321 return;
322 for (; count > 8; count -= 8, to++, offset += 8)
323 *to = bit_extract (buffer, offset, 8);
324 *to = bit_extract (buffer, offset, count);
325 }
326
327 static int
328 sign_extend (unsigned int value, unsigned int bits)
329 {
330 unsigned int sign = 1u << (bits - 1);
331 return ((value & (sign + sign - 1)) ^ sign) - sign;
332 }
333
334 static void
335 flip_bytes (char *ptr, int count)
336 {
337 char tmp;
338
339 while (count > 0)
340 {
341 tmp = ptr[0];
342 ptr[0] = ptr[count - 1];
343 ptr[count - 1] = tmp;
344 ptr++;
345 count -= 2;
346 }
347 }
348 \f
349 /* Given a character C, does it represent a general addressing mode? */
350 #define Is_gen(c) \
351 ((c) == 'F' || (c) == 'L' || (c) == 'B' \
352 || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
353
354 /* Adressing modes. */
355 #define Adrmod_index_byte 0x1c
356 #define Adrmod_index_word 0x1d
357 #define Adrmod_index_doubleword 0x1e
358 #define Adrmod_index_quadword 0x1f
359
360 /* Is MODE an indexed addressing mode? */
361 #define Adrmod_is_index(mode) \
362 ( mode == Adrmod_index_byte \
363 || mode == Adrmod_index_word \
364 || mode == Adrmod_index_doubleword \
365 || mode == Adrmod_index_quadword)
366
367 \f
368 static int
369 get_displacement (bfd_byte *buffer, int *aoffsetp)
370 {
371 int Ivalue;
372 short Ivalue2;
373
374 Ivalue = bit_extract (buffer, *aoffsetp, 8);
375 switch (Ivalue & 0xc0)
376 {
377 case 0x00:
378 case 0x40:
379 Ivalue = sign_extend (Ivalue, 7);
380 *aoffsetp += 8;
381 break;
382 case 0x80:
383 Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
384 flip_bytes ((char *) & Ivalue2, 2);
385 Ivalue = sign_extend (Ivalue2, 14);
386 *aoffsetp += 16;
387 break;
388 case 0xc0:
389 Ivalue = bit_extract (buffer, *aoffsetp, 32);
390 flip_bytes ((char *) & Ivalue, 4);
391 Ivalue = sign_extend (Ivalue, 30);
392 *aoffsetp += 32;
393 break;
394 }
395 return Ivalue;
396 }
397
398 #if 1 /* A version that should work on ns32k f's&d's on any machine. */
399 static int
400 invalid_float (bfd_byte *p, int len)
401 {
402 int val;
403
404 if (len == 4)
405 val = (bit_extract_simple (p, 23, 8)/*exponent*/ == 0xff
406 || (bit_extract_simple (p, 23, 8)/*exponent*/ == 0
407 && bit_extract_simple (p, 0, 23)/*mantisa*/ != 0));
408 else if (len == 8)
409 val = (bit_extract_simple (p, 52, 11)/*exponent*/ == 0x7ff
410 || (bit_extract_simple (p, 52, 11)/*exponent*/ == 0
411 && (bit_extract_simple (p, 0, 32)/*low mantisa*/ != 0
412 || bit_extract_simple (p, 32, 20)/*high mantisa*/ != 0)));
413 else
414 val = 1;
415 return (val);
416 }
417 #else
418 /* Assumes the bytes have been swapped to local order. */
419 typedef union
420 {
421 double d;
422 float f;
423 struct { unsigned m:23, e:8, :1;} sf;
424 struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
425 } float_type_u;
426
427 static int
428 invalid_float (float_type_u *p, int len)
429 {
430 int val;
431
432 if (len == sizeof (float))
433 val = (p->sf.e == 0xff
434 || (p->sf.e == 0 && p->sf.m != 0));
435 else if (len == sizeof (double))
436 val = (p->sd.e == 0x7ff
437 || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
438 else
439 val = 1;
440 return val;
441 }
442 #endif
443
444 /* Print an instruction operand of category given by d. IOFFSET is
445 the bit position below which small (<1 byte) parts of the operand can
446 be found (usually in the basic instruction, but for indexed
447 addressing it can be in the index byte). AOFFSETP is a pointer to the
448 bit position of the addressing extension. BUFFER contains the
449 instruction. ADDR is where BUFFER was read from. Put the disassembled
450 version of the operand in RESULT. INDEX_OFFSET is the bit position
451 of the index byte (it contains garbage if this operand is not a
452 general operand using scaled indexed addressing mode). */
453
454 static int
455 print_insn_arg (int d,
456 int ioffset,
457 int *aoffsetp,
458 bfd_byte *buffer,
459 bfd_vma addr,
460 char *result,
461 int index_offset)
462 {
463 union
464 {
465 float f;
466 double d;
467 int i[2];
468 } value;
469 int Ivalue;
470 int addr_mode;
471 int disp1, disp2;
472 int size;
473
474 switch (d)
475 {
476 case 'f':
477 /* A "gen" operand but 5 bits from the end of instruction. */
478 ioffset -= 5;
479 /* Fall through. */
480 case 'Z':
481 case 'F':
482 case 'L':
483 case 'I':
484 case 'B':
485 case 'W':
486 case 'D':
487 case 'A':
488 addr_mode = bit_extract (buffer, ioffset - 5, 5);
489 ioffset -= 5;
490 switch (addr_mode)
491 {
492 case 0x0: case 0x1: case 0x2: case 0x3:
493 case 0x4: case 0x5: case 0x6: case 0x7:
494 /* Register mode R0 -- R7. */
495 switch (d)
496 {
497 case 'F':
498 case 'L':
499 case 'Z':
500 sprintf (result, "f%d", addr_mode);
501 break;
502 default:
503 sprintf (result, "r%d", addr_mode);
504 }
505 break;
506 case 0x8: case 0x9: case 0xa: case 0xb:
507 case 0xc: case 0xd: case 0xe: case 0xf:
508 /* Register relative disp(R0 -- R7). */
509 disp1 = get_displacement (buffer, aoffsetp);
510 sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
511 break;
512 case 0x10:
513 case 0x11:
514 case 0x12:
515 /* Memory relative disp2(disp1(FP, SP, SB)). */
516 disp1 = get_displacement (buffer, aoffsetp);
517 disp2 = get_displacement (buffer, aoffsetp);
518 sprintf (result, "%d(%d(%s))", disp2, disp1,
519 addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
520 break;
521 case 0x13:
522 /* Reserved. */
523 sprintf (result, "reserved");
524 break;
525 case 0x14:
526 /* Immediate. */
527 switch (d)
528 {
529 case 'I':
530 case 'Z':
531 case 'A':
532 /* I and Z are output operands and can`t be immediate
533 A is an address and we can`t have the address of
534 an immediate either. We don't know how much to increase
535 aoffsetp by since whatever generated this is broken
536 anyway! */
537 sprintf (result, _("$<undefined>"));
538 break;
539 case 'B':
540 Ivalue = bit_extract (buffer, *aoffsetp, 8);
541 Ivalue = sign_extend (Ivalue, 8);
542 *aoffsetp += 8;
543 sprintf (result, "$%d", Ivalue);
544 break;
545 case 'W':
546 Ivalue = bit_extract (buffer, *aoffsetp, 16);
547 flip_bytes ((char *) & Ivalue, 2);
548 *aoffsetp += 16;
549 Ivalue = sign_extend (Ivalue, 16);
550 sprintf (result, "$%d", Ivalue);
551 break;
552 case 'D':
553 Ivalue = bit_extract (buffer, *aoffsetp, 32);
554 flip_bytes ((char *) & Ivalue, 4);
555 *aoffsetp += 32;
556 sprintf (result, "$%d", Ivalue);
557 break;
558 case 'F':
559 bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
560 flip_bytes ((char *) &value.f, 4);
561 *aoffsetp += 32;
562 if (INVALID_FLOAT (&value.f, 4))
563 sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
564 else /* Assume host has ieee float. */
565 sprintf (result, "$%g", value.f);
566 break;
567 case 'L':
568 bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
569 flip_bytes ((char *) &value.d, 8);
570 *aoffsetp += 64;
571 if (INVALID_FLOAT (&value.d, 8))
572 sprintf (result, "<<invalid double 0x%.8x%.8x>>",
573 value.i[1], value.i[0]);
574 else /* Assume host has ieee float. */
575 sprintf (result, "$%g", value.d);
576 break;
577 }
578 break;
579 case 0x15:
580 /* Absolute @disp. */
581 disp1 = get_displacement (buffer, aoffsetp);
582 sprintf (result, "@|%d|", disp1);
583 break;
584 case 0x16:
585 /* External EXT(disp1) + disp2 (Mod table stuff). */
586 disp1 = get_displacement (buffer, aoffsetp);
587 disp2 = get_displacement (buffer, aoffsetp);
588 sprintf (result, "EXT(%d) + %d", disp1, disp2);
589 break;
590 case 0x17:
591 /* Top of stack tos. */
592 sprintf (result, "tos");
593 break;
594 case 0x18:
595 /* Memory space disp(FP). */
596 disp1 = get_displacement (buffer, aoffsetp);
597 sprintf (result, "%d(fp)", disp1);
598 break;
599 case 0x19:
600 /* Memory space disp(SP). */
601 disp1 = get_displacement (buffer, aoffsetp);
602 sprintf (result, "%d(sp)", disp1);
603 break;
604 case 0x1a:
605 /* Memory space disp(SB). */
606 disp1 = get_displacement (buffer, aoffsetp);
607 sprintf (result, "%d(sb)", disp1);
608 break;
609 case 0x1b:
610 /* Memory space disp(PC). */
611 disp1 = get_displacement (buffer, aoffsetp);
612 *result++ = NEXT_IS_ADDR;
613 sprintf_vma (result, addr + disp1);
614 result += strlen (result);
615 *result++ = NEXT_IS_ADDR;
616 *result = '\0';
617 break;
618 case 0x1c:
619 case 0x1d:
620 case 0x1e:
621 case 0x1f:
622 {
623 int bit_index;
624 static const char *ind = "bwdq";
625 char *off;
626
627 /* Scaled index basemode[R0 -- R7:B,W,D,Q]. */
628 bit_index = bit_extract (buffer, index_offset - 8, 3);
629 print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
630 result, 0);
631 off = result + strlen (result);
632 sprintf (off, "[r%d:%c]", bit_index, ind[addr_mode & 3]);
633 }
634 break;
635 }
636 break;
637 case 'H':
638 case 'q':
639 Ivalue = bit_extract (buffer, ioffset-4, 4);
640 Ivalue = sign_extend (Ivalue, 4);
641 sprintf (result, "%d", Ivalue);
642 ioffset -= 4;
643 break;
644 case 'r':
645 Ivalue = bit_extract (buffer, ioffset-3, 3);
646 sprintf (result, "r%d", Ivalue&7);
647 ioffset -= 3;
648 break;
649 case 'd':
650 sprintf (result, "%d", get_displacement (buffer, aoffsetp));
651 break;
652 case 'b':
653 Ivalue = get_displacement (buffer, aoffsetp);
654 /* Warning!! HACK ALERT!
655 Operand type 'b' is only used by the cmp{b,w,d} and
656 movm{b,w,d} instructions; we need to know whether
657 it's a `b' or `w' or `d' instruction; and for both
658 cmpm and movm it's stored at the same place so we
659 just grab two bits of the opcode and look at it... */
660 size = bit_extract(buffer, ioffset-6, 2);
661 if (size == 0) /* 00 => b. */
662 size = 1;
663 else if (size == 1) /* 01 => w. */
664 size = 2;
665 else
666 size = 4; /* 11 => d. */
667
668 sprintf (result, "%d", (Ivalue / size) + 1);
669 break;
670 case 'p':
671 *result++ = NEXT_IS_ADDR;
672 sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
673 result += strlen (result);
674 *result++ = NEXT_IS_ADDR;
675 *result = '\0';
676 break;
677 case 'i':
678 Ivalue = bit_extract (buffer, *aoffsetp, 8);
679 *aoffsetp += 8;
680 sprintf (result, "0x%x", Ivalue);
681 break;
682 case 'u':
683 Ivalue = bit_extract (buffer, *aoffsetp, 8);
684 optlist (Ivalue, opt_u, result);
685 *aoffsetp += 8;
686 break;
687 case 'U':
688 Ivalue = bit_extract (buffer, *aoffsetp, 8);
689 optlist (Ivalue, opt_U, result);
690 *aoffsetp += 8;
691 break;
692 case 'O':
693 Ivalue = bit_extract (buffer, ioffset - 9, 9);
694 optlist (Ivalue, opt_O, result);
695 ioffset -= 9;
696 break;
697 case 'C':
698 Ivalue = bit_extract (buffer, ioffset - 4, 4);
699 optlist (Ivalue, opt_C, result);
700 ioffset -= 4;
701 break;
702 case 'S':
703 Ivalue = bit_extract (buffer, ioffset - 8, 8);
704 optlist (Ivalue, opt_S, result);
705 ioffset -= 8;
706 break;
707 case 'M':
708 Ivalue = bit_extract (buffer, ioffset - 4, 4);
709 list_search (Ivalue, 0 ? list_M032 : list_M532, result);
710 ioffset -= 4;
711 break;
712 case 'P':
713 Ivalue = bit_extract (buffer, ioffset - 4, 4);
714 list_search (Ivalue, 0 ? list_P032 : list_P532, result);
715 ioffset -= 4;
716 break;
717 case 'g':
718 Ivalue = bit_extract (buffer, *aoffsetp, 3);
719 sprintf (result, "%d", Ivalue);
720 *aoffsetp += 3;
721 break;
722 case 'G':
723 Ivalue = bit_extract(buffer, *aoffsetp, 5);
724 sprintf (result, "%d", Ivalue + 1);
725 *aoffsetp += 5;
726 break;
727 }
728 return ioffset;
729 }
730
731 \f
732 /* Print the 32000 instruction at address MEMADDR in debugged memory,
733 on STREAM. Returns length of the instruction, in bytes. */
734
735 int
736 print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
737 {
738 unsigned int i;
739 const char *d;
740 unsigned short first_word;
741 int ioffset; /* Bits into instruction. */
742 int aoffset; /* Bits into arguments. */
743 char arg_bufs[MAX_ARGS+1][ARG_LEN];
744 int argnum;
745 int maxarg;
746 struct private priv;
747 bfd_byte *buffer = priv.the_buffer;
748 dis_info = info;
749
750 info->private_data = & priv;
751 priv.max_fetched = priv.the_buffer;
752 priv.insn_start = memaddr;
753 if (OPCODES_SIGSETJMP (priv.bailout) != 0)
754 /* Error return. */
755 return -1;
756
757 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
758 us over the end of accessible data unnecessarilly. */
759 FETCH_DATA (info, buffer + 1);
760 for (i = 0; i < NOPCODES; i++)
761 if (ns32k_opcodes[i].opcode_id_size <= 8
762 && ((buffer[0]
763 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
764 == ns32k_opcodes[i].opcode_seed))
765 break;
766 if (i == NOPCODES)
767 {
768 /* Maybe it is 9 to 16 bits big. */
769 FETCH_DATA (info, buffer + 2);
770 first_word = read_memory_integer(buffer, 2);
771
772 for (i = 0; i < NOPCODES; i++)
773 if ((first_word
774 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
775 == ns32k_opcodes[i].opcode_seed)
776 break;
777
778 /* Handle undefined instructions. */
779 if (i == NOPCODES)
780 {
781 (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
782 return 1;
783 }
784 }
785
786 (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
787
788 ioffset = ns32k_opcodes[i].opcode_size;
789 aoffset = ns32k_opcodes[i].opcode_size;
790 d = ns32k_opcodes[i].operands;
791
792 if (*d)
793 {
794 /* Offset in bits of the first thing beyond each index byte.
795 Element 0 is for operand A and element 1 is for operand B.
796 The rest are irrelevant, but we put them here so we don't
797 index outside the array. */
798 int index_offset[MAX_ARGS];
799
800 /* 0 for operand A, 1 for operand B, greater for other args. */
801 int whicharg = 0;
802
803 (*dis_info->fprintf_func)(dis_info->stream, "\t");
804
805 maxarg = 0;
806
807 /* First we have to find and keep track of the index bytes,
808 if we are using scaled indexed addressing mode, since the index
809 bytes occur right after the basic instruction, not as part
810 of the addressing extension. */
811 if (Is_gen(d[1]))
812 {
813 int addr_mode = bit_extract (buffer, ioffset - 5, 5);
814
815 if (Adrmod_is_index (addr_mode))
816 {
817 aoffset += 8;
818 index_offset[0] = aoffset;
819 }
820 }
821
822 if (d[2] && Is_gen(d[3]))
823 {
824 int addr_mode = bit_extract (buffer, ioffset - 10, 5);
825
826 if (Adrmod_is_index (addr_mode))
827 {
828 aoffset += 8;
829 index_offset[1] = aoffset;
830 }
831 }
832
833 while (*d)
834 {
835 argnum = *d - '1';
836 d++;
837 if (argnum > maxarg && argnum < MAX_ARGS)
838 maxarg = argnum;
839 ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
840 memaddr, arg_bufs[argnum],
841 index_offset[whicharg]);
842 d++;
843 if (whicharg++ >= 1)
844 break;
845 }
846
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;
872 }