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