Stop potential illegal memory access in the NS32K disassembler.
[deliverable/binutils-gdb.git] / opcodes / ns32k-dis.c
CommitLineData
252b5132 1/* Print National Semiconductor 32000 instructions.
82704155 2 Copyright (C) 1986-2019 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
RH
264{
265 int result;
266 int bit;
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
RH
293{
294 int result;
252b5132
RH
295 int bit;
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
47b0e7ad 328sign_extend (int value, int bits)
252b5132
RH
329{
330 value = value & ((1 << bits) - 1);
47b0e7ad 331 return (value & (1 << (bits - 1))
252b5132
RH
332 ? value | (~((1 << bits) - 1))
333 : value);
334}
335
336static void
47b0e7ad 337flip_bytes (char *ptr, int count)
252b5132
RH
338{
339 char tmp;
340
341 while (count > 0)
342 {
343 tmp = ptr[0];
47b0e7ad
NC
344 ptr[0] = ptr[count - 1];
345 ptr[count - 1] = tmp;
252b5132
RH
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. */
47b0e7ad
NC
357#define Adrmod_index_byte 0x1c
358#define Adrmod_index_word 0x1d
359#define Adrmod_index_doubleword 0x1e
360#define Adrmod_index_quadword 0x1f
252b5132
RH
361
362/* Is MODE an indexed addressing mode? */
363#define Adrmod_is_index(mode) \
47b0e7ad 364 ( mode == Adrmod_index_byte \
252b5132
RH
365 || mode == Adrmod_index_word \
366 || mode == Adrmod_index_doubleword \
367 || mode == Adrmod_index_quadword)
368
369\f
47b0e7ad
NC
370static int
371get_displacement (bfd_byte *buffer, int *aoffsetp)
252b5132 372{
47b0e7ad
NC
373 int Ivalue;
374 short Ivalue2;
252b5132 375
47b0e7ad
NC
376 Ivalue = bit_extract (buffer, *aoffsetp, 8);
377 switch (Ivalue & 0xc0)
252b5132 378 {
47b0e7ad
NC
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}
252b5132 399
47b0e7ad
NC
400#if 1 /* A version that should work on ns32k f's&d's on any machine. */
401static int
402invalid_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. */
421typedef union
43e65147 422{
47b0e7ad
NC
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;
252b5132 428
47b0e7ad
NC
429static int
430invalid_float (float_type_u *p, int len)
431{
432 int val;
252b5132 433
47b0e7ad
NC
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;
252b5132 443}
47b0e7ad 444#endif
252b5132
RH
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
456static int
47b0e7ad
NC
457print_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)
252b5132 464{
47b0e7ad
NC
465 union
466 {
6a51a8a8
AM
467 float f;
468 double d;
469 int i[2];
470 } value;
252b5132 471 int Ivalue;
6a51a8a8 472 int addr_mode;
252b5132 473 int disp1, disp2;
252b5132
RH
474 int size;
475
476 switch (d)
477 {
478 case 'f':
47b0e7ad 479 /* A "gen" operand but 5 bits from the end of instruction. */
252b5132 480 ioffset -= 5;
1a0670f3 481 /* Fall through. */
252b5132
RH
482 case 'Z':
483 case 'F':
484 case 'L':
485 case 'I':
486 case 'B':
487 case 'W':
488 case 'D':
489 case 'A':
47b0e7ad 490 addr_mode = bit_extract (buffer, ioffset - 5, 5);
252b5132
RH
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:
47b0e7ad 496 /* Register mode R0 -- R7. */
252b5132
RH
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:
47b0e7ad 510 /* Register relative disp(R0 -- R7). */
252b5132
RH
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:
47b0e7ad 517 /* Memory relative disp2(disp1(FP, SP, SB)). */
252b5132
RH
518 disp1 = get_displacement (buffer, aoffsetp);
519 disp2 = get_displacement (buffer, aoffsetp);
520 sprintf (result, "%d(%d(%s))", disp2, disp1,
47b0e7ad 521 addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
252b5132
RH
522 break;
523 case 0x13:
47b0e7ad 524 /* Reserved. */
252b5132
RH
525 sprintf (result, "reserved");
526 break;
527 case 0x14:
47b0e7ad 528 /* Immediate. */
252b5132
RH
529 switch (d)
530 {
47b0e7ad
NC
531 case 'I':
532 case 'Z':
533 case 'A':
252b5132 534 /* I and Z are output operands and can`t be immediate
47b0e7ad
NC
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! */
252b5132
RH
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);
fc05c67f 549 flip_bytes ((char *) & Ivalue, 2);
252b5132
RH
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);
fc05c67f 556 flip_bytes ((char *) & Ivalue, 4);
252b5132
RH
557 *aoffsetp += 32;
558 sprintf (result, "$%d", Ivalue);
559 break;
560 case 'F':
6a51a8a8
AM
561 bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
562 flip_bytes ((char *) &value.f, 4);
252b5132 563 *aoffsetp += 32;
6a51a8a8
AM
564 if (INVALID_FLOAT (&value.f, 4))
565 sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
47b0e7ad 566 else /* Assume host has ieee float. */
6a51a8a8 567 sprintf (result, "$%g", value.f);
252b5132
RH
568 break;
569 case 'L':
6a51a8a8
AM
570 bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
571 flip_bytes ((char *) &value.d, 8);
252b5132 572 *aoffsetp += 64;
6a51a8a8
AM
573 if (INVALID_FLOAT (&value.d, 8))
574 sprintf (result, "<<invalid double 0x%.8x%.8x>>",
575 value.i[1], value.i[0]);
47b0e7ad 576 else /* Assume host has ieee float. */
6a51a8a8 577 sprintf (result, "$%g", value.d);
252b5132
RH
578 break;
579 }
580 break;
581 case 0x15:
47b0e7ad 582 /* Absolute @disp. */
252b5132
RH
583 disp1 = get_displacement (buffer, aoffsetp);
584 sprintf (result, "@|%d|", disp1);
585 break;
586 case 0x16:
47b0e7ad 587 /* External EXT(disp1) + disp2 (Mod table stuff). */
252b5132
RH
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:
47b0e7ad 593 /* Top of stack tos. */
252b5132
RH
594 sprintf (result, "tos");
595 break;
596 case 0x18:
47b0e7ad 597 /* Memory space disp(FP). */
252b5132
RH
598 disp1 = get_displacement (buffer, aoffsetp);
599 sprintf (result, "%d(fp)", disp1);
600 break;
601 case 0x19:
47b0e7ad 602 /* Memory space disp(SP). */
252b5132
RH
603 disp1 = get_displacement (buffer, aoffsetp);
604 sprintf (result, "%d(sp)", disp1);
605 break;
606 case 0x1a:
47b0e7ad 607 /* Memory space disp(SB). */
252b5132
RH
608 disp1 = get_displacement (buffer, aoffsetp);
609 sprintf (result, "%d(sb)", disp1);
610 break;
611 case 0x1b:
47b0e7ad 612 /* Memory space disp(PC). */
252b5132
RH
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:
252b5132 624 {
91d6fa6a 625 int bit_index;
252b5132
RH
626 static const char *ind = "bwdq";
627 char *off;
43e65147 628
91d6fa6a
NC
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);
252b5132 633 off = result + strlen (result);
91d6fa6a 634 sprintf (off, "[r%d:%c]", bit_index, ind[addr_mode & 3]);
252b5132
RH
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);
47b0e7ad
NC
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... */
252b5132 662 size = bit_extract(buffer, ioffset-6, 2);
47b0e7ad 663 if (size == 0) /* 00 => b. */
252b5132 664 size = 1;
47b0e7ad 665 else if (size == 1) /* 01 => w. */
252b5132
RH
666 size = 2;
667 else
47b0e7ad 668 size = 4; /* 11 => d. */
252b5132
RH
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);
47b0e7ad 686 optlist (Ivalue, opt_u, result);
252b5132
RH
687 *aoffsetp += 8;
688 break;
689 case 'U':
47b0e7ad
NC
690 Ivalue = bit_extract (buffer, *aoffsetp, 8);
691 optlist (Ivalue, opt_U, result);
252b5132
RH
692 *aoffsetp += 8;
693 break;
694 case 'O':
47b0e7ad
NC
695 Ivalue = bit_extract (buffer, ioffset - 9, 9);
696 optlist (Ivalue, opt_O, result);
252b5132
RH
697 ioffset -= 9;
698 break;
699 case 'C':
47b0e7ad
NC
700 Ivalue = bit_extract (buffer, ioffset - 4, 4);
701 optlist (Ivalue, opt_C, result);
252b5132
RH
702 ioffset -= 4;
703 break;
704 case 'S':
47b0e7ad
NC
705 Ivalue = bit_extract (buffer, ioffset - 8, 8);
706 optlist (Ivalue, opt_S, result);
252b5132
RH
707 ioffset -= 8;
708 break;
709 case 'M':
47b0e7ad
NC
710 Ivalue = bit_extract (buffer, ioffset - 4, 4);
711 list_search (Ivalue, 0 ? list_M032 : list_M532, result);
252b5132
RH
712 ioffset -= 4;
713 break;
714 case 'P':
47b0e7ad
NC
715 Ivalue = bit_extract (buffer, ioffset - 4, 4);
716 list_search (Ivalue, 0 ? list_P032 : list_P532, result);
252b5132
RH
717 ioffset -= 4;
718 break;
719 case 'g':
47b0e7ad
NC
720 Ivalue = bit_extract (buffer, *aoffsetp, 3);
721 sprintf (result, "%d", Ivalue);
252b5132
RH
722 *aoffsetp += 3;
723 break;
724 case 'G':
725 Ivalue = bit_extract(buffer, *aoffsetp, 5);
47b0e7ad 726 sprintf (result, "%d", Ivalue + 1);
252b5132
RH
727 *aoffsetp += 5;
728 break;
729 }
730 return ioffset;
731}
732
47b0e7ad
NC
733\f
734/* Print the 32000 instruction at address MEMADDR in debugged memory,
735 on STREAM. Returns length of the instruction, in bytes. */
736
737int
738print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
252b5132 739{
47b0e7ad
NC
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;
252b5132 751
47b0e7ad
NC
752 info->private_data = & priv;
753 priv.max_fetched = priv.the_buffer;
754 priv.insn_start = memaddr;
8df14d78 755 if (OPCODES_SIGSETJMP (priv.bailout) != 0)
47b0e7ad
NC
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))
252b5132 767 break;
47b0e7ad
NC
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 }
252b5132 786 }
252b5132 787
47b0e7ad 788 (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
252b5132 789
47b0e7ad
NC
790 ioffset = ns32k_opcodes[i].opcode_size;
791 aoffset = ns32k_opcodes[i].opcode_size;
792 d = ns32k_opcodes[i].operands;
252b5132 793
47b0e7ad
NC
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;
43e65147 804
47b0e7ad
NC
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++;
d1e304bc
NC
845 if (whicharg++ >= 1)
846 break;
47b0e7ad 847 }
d1e304bc 848
47b0e7ad
NC
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;
252b5132 874}
This page took 0.919708 seconds and 4 git commands to generate.