]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/ns32k-dis.c
Add -Wshadow to the gcc command line options used when compiling the binutils.
[thirdparty/binutils-gdb.git] / opcodes / ns32k-dis.c
CommitLineData
252b5132 1/* Print National Semiconductor 32000 instructions.
91d6fa6a
NC
2 Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005, 2007,
3 2009 Free Software Foundation, Inc.
252b5132 4
9b201bb5 5 This file is part of the GNU opcodes library.
252b5132 6
9b201bb5 7 This library is free software; you can redistribute it and/or modify
47b0e7ad 8 it under the terms of the GNU General Public License as published by
9b201bb5
NC
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
252b5132 11
9b201bb5
NC
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
252b5132 16
47b0e7ad
NC
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
252b5132 21
252b5132 22#include "sysdep.h"
3db64b00 23#include "bfd.h"
252b5132
RH
24#include "dis-asm.h"
25#if !defined(const) && !defined(__STDC__)
26#define const
27#endif
28#include "opcode/ns32k.h"
29#include "opintl.h"
30
31static disassemble_info *dis_info;
32
47b0e7ad
NC
33/* Hacks to get it to compile <= READ THESE AS FIXES NEEDED. */
34#define INVALID_FLOAT(val, size) invalid_float ((bfd_byte *) val, size)
35
36static long
37read_memory_integer (unsigned char * addr, int nr)
252b5132
RH
38{
39 long val;
40 int i;
47b0e7ad
NC
41
42 for (val = 0, i = nr - 1; i >= 0; i--)
43 {
44 val = (val << 8);
45 val |= (0xff & *(addr + i));
46 }
252b5132
RH
47 return val;
48}
49
50/* 32000 instructions are never longer than this. */
51#define MAXLEN 62
52
252b5132
RH
53#include <setjmp.h>
54
55struct private
56{
57 /* Points to first byte not fetched. */
58 bfd_byte *max_fetched;
59 bfd_byte the_buffer[MAXLEN];
60 bfd_vma insn_start;
61 jmp_buf bailout;
62};
63
64
65/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
66 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
67 on error. */
68#define FETCH_DATA(info, addr) \
69 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
70 ? 1 : fetch_data ((info), (addr)))
71
72static int
47b0e7ad 73fetch_data (struct disassemble_info *info, bfd_byte *addr)
252b5132
RH
74{
75 int status;
47b0e7ad 76 struct private *priv = (struct private *) info->private_data;
252b5132
RH
77 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
78
79 status = (*info->read_memory_func) (start,
80 priv->max_fetched,
81 addr - priv->max_fetched,
82 info);
83 if (status != 0)
84 {
85 (*info->memory_error_func) (status, start, info);
86 longjmp (priv->bailout, 1);
87 }
88 else
89 priv->max_fetched = addr;
90 return 1;
91}
47b0e7ad 92
252b5132
RH
93/* Number of elements in the opcode table. */
94#define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
95
96#define NEXT_IS_ADDR '|'
97
98\f
47b0e7ad
NC
99struct ns32k_option
100{
101 char *pattern; /* The option itself. */
102 unsigned long value; /* Binary value of the option. */
103 unsigned long match; /* These bits must match. */
252b5132
RH
104};
105
106\f
47b0e7ad 107static const struct ns32k_option opt_u[]= /* Restore, exit. */
252b5132
RH
108{
109 { "r0", 0x80, 0x80 },
110 { "r1", 0x40, 0x40 },
111 { "r2", 0x20, 0x20 },
112 { "r3", 0x10, 0x10 },
113 { "r4", 0x08, 0x08 },
114 { "r5", 0x04, 0x04 },
115 { "r6", 0x02, 0x02 },
116 { "r7", 0x01, 0x01 },
117 { 0 , 0x00, 0x00 }
118};
119
47b0e7ad 120static const struct ns32k_option opt_U[]= /* Save, enter. */
252b5132
RH
121{
122 { "r0", 0x01, 0x01 },
123 { "r1", 0x02, 0x02 },
124 { "r2", 0x04, 0x04 },
125 { "r3", 0x08, 0x08 },
126 { "r4", 0x10, 0x10 },
127 { "r5", 0x20, 0x20 },
128 { "r6", 0x40, 0x40 },
129 { "r7", 0x80, 0x80 },
130 { 0 , 0x00, 0x00 }
131};
132
47b0e7ad 133static const struct ns32k_option opt_O[]= /* Setcfg. */
252b5132
RH
134{
135 { "c", 0x8, 0x8 },
136 { "m", 0x4, 0x4 },
137 { "f", 0x2, 0x2 },
138 { "i", 0x1, 0x1 },
139 { 0 , 0x0, 0x0 }
140};
141
47b0e7ad 142static const struct ns32k_option opt_C[]= /* Cinv. */
252b5132
RH
143{
144 { "a", 0x4, 0x4 },
145 { "i", 0x2, 0x2 },
146 { "d", 0x1, 0x1 },
147 { 0 , 0x0, 0x0 }
148};
149
47b0e7ad 150static const struct ns32k_option opt_S[]= /* String inst. */
252b5132
RH
151{
152 { "b", 0x1, 0x1 },
153 { "u", 0x6, 0x6 },
154 { "w", 0x2, 0x2 },
155 { 0 , 0x0, 0x0 }
156};
157
47b0e7ad 158static const struct ns32k_option list_P532[]= /* Lpr spr. */
252b5132
RH
159{
160 { "us", 0x0, 0xf },
161 { "dcr", 0x1, 0xf },
162 { "bpc", 0x2, 0xf },
163 { "dsr", 0x3, 0xf },
164 { "car", 0x4, 0xf },
165 { "fp", 0x8, 0xf },
166 { "sp", 0x9, 0xf },
167 { "sb", 0xa, 0xf },
168 { "usp", 0xb, 0xf },
169 { "cfg", 0xc, 0xf },
170 { "psr", 0xd, 0xf },
171 { "intbase", 0xe, 0xf },
172 { "mod", 0xf, 0xf },
173 { 0 , 0x00, 0xf }
174};
175
47b0e7ad 176static const struct ns32k_option list_M532[]= /* Lmr smr. */
252b5132
RH
177{
178 { "mcr", 0x9, 0xf },
179 { "msr", 0xa, 0xf },
180 { "tear", 0xb, 0xf },
181 { "ptb0", 0xc, 0xf },
182 { "ptb1", 0xd, 0xf },
183 { "ivar0", 0xe, 0xf },
184 { "ivar1", 0xf, 0xf },
185 { 0 , 0x0, 0xf }
186};
187
47b0e7ad 188static const struct ns32k_option list_P032[]= /* Lpr spr. */
252b5132
RH
189{
190 { "upsr", 0x0, 0xf },
191 { "fp", 0x8, 0xf },
192 { "sp", 0x9, 0xf },
193 { "sb", 0xa, 0xf },
194 { "psr", 0xb, 0xf },
195 { "intbase", 0xe, 0xf },
196 { "mod", 0xf, 0xf },
197 { 0 , 0x0, 0xf }
198};
199
47b0e7ad 200static const struct ns32k_option list_M032[]= /* Lmr smr. */
252b5132
RH
201{
202 { "bpr0", 0x0, 0xf },
203 { "bpr1", 0x1, 0xf },
204 { "pf0", 0x4, 0xf },
205 { "pf1", 0x5, 0xf },
206 { "sc", 0x8, 0xf },
207 { "msr", 0xa, 0xf },
208 { "bcnt", 0xb, 0xf },
209 { "ptb0", 0xc, 0xf },
210 { "ptb1", 0xd, 0xf },
211 { "eia", 0xf, 0xf },
212 { 0 , 0x0, 0xf }
213};
214
215
47b0e7ad
NC
216/* Figure out which options are present. */
217
252b5132 218static void
47b0e7ad 219optlist (int options, const struct ns32k_option * optionP, char * result)
252b5132 220{
47b0e7ad
NC
221 if (options == 0)
222 {
223 sprintf (result, "[]");
224 return;
252b5132 225 }
47b0e7ad
NC
226
227 sprintf (result, "[");
228
229 for (; (options != 0) && optionP->pattern; optionP++)
230 {
231 if ((options & optionP->match) == optionP->value)
232 {
233 /* We found a match, update result and options. */
234 strcat (result, optionP->pattern);
235 options &= ~optionP->value;
236 if (options != 0) /* More options to come. */
237 strcat (result, ",");
252b5132
RH
238 }
239 }
252b5132 240
47b0e7ad
NC
241 if (options != 0)
242 strcat (result, "undefined");
243
244 strcat (result, "]");
252b5132
RH
245}
246
247static void
47b0e7ad 248list_search (int reg_value, const struct ns32k_option *optionP, char *result)
252b5132 249{
47b0e7ad
NC
250 for (; optionP->pattern; optionP++)
251 {
252 if ((reg_value & optionP->match) == optionP->value)
253 {
254 sprintf (result, "%s", optionP->pattern);
255 return;
252b5132
RH
256 }
257 }
47b0e7ad 258 sprintf (result, "undefined");
252b5132
RH
259}
260\f
47b0e7ad 261/* Extract "count" bits starting "offset" bits into buffer. */
252b5132
RH
262
263static int
47b0e7ad 264bit_extract (bfd_byte *buffer, int offset, int count)
252b5132
RH
265{
266 int result;
267 int bit;
268
269 buffer += offset >> 3;
270 offset &= 7;
271 bit = 1;
272 result = 0;
273 while (count--)
274 {
47b0e7ad 275 FETCH_DATA (dis_info, buffer + 1);
252b5132
RH
276 if ((*buffer & (1 << offset)))
277 result |= bit;
278 if (++offset == 8)
279 {
280 offset = 0;
281 buffer++;
282 }
283 bit <<= 1;
284 }
285 return result;
286}
287
47b0e7ad
NC
288/* Like bit extract but the buffer is valid and doen't need to be fetched. */
289
252b5132 290static int
47b0e7ad 291bit_extract_simple (bfd_byte *buffer, int offset, int count)
252b5132
RH
292{
293 int result;
252b5132
RH
294 int bit;
295
296 buffer += offset >> 3;
297 offset &= 7;
298 bit = 1;
299 result = 0;
300 while (count--)
301 {
302 if ((*buffer & (1 << offset)))
303 result |= bit;
304 if (++offset == 8)
305 {
306 offset = 0;
307 buffer++;
308 }
309 bit <<= 1;
310 }
311 return result;
312}
313
314static void
47b0e7ad 315bit_copy (bfd_byte *buffer, int offset, int count, char *to)
252b5132 316{
47b0e7ad 317 for (; count > 8; count -= 8, to++, offset += 8)
252b5132
RH
318 *to = bit_extract (buffer, offset, 8);
319 *to = bit_extract (buffer, offset, count);
320}
321
252b5132 322static int
47b0e7ad 323sign_extend (int value, int bits)
252b5132
RH
324{
325 value = value & ((1 << bits) - 1);
47b0e7ad 326 return (value & (1 << (bits - 1))
252b5132
RH
327 ? value | (~((1 << bits) - 1))
328 : value);
329}
330
331static void
47b0e7ad 332flip_bytes (char *ptr, int count)
252b5132
RH
333{
334 char tmp;
335
336 while (count > 0)
337 {
338 tmp = ptr[0];
47b0e7ad
NC
339 ptr[0] = ptr[count - 1];
340 ptr[count - 1] = tmp;
252b5132
RH
341 ptr++;
342 count -= 2;
343 }
344}
345\f
346/* Given a character C, does it represent a general addressing mode? */
347#define Is_gen(c) \
348 ((c) == 'F' || (c) == 'L' || (c) == 'B' \
349 || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
350
351/* Adressing modes. */
47b0e7ad
NC
352#define Adrmod_index_byte 0x1c
353#define Adrmod_index_word 0x1d
354#define Adrmod_index_doubleword 0x1e
355#define Adrmod_index_quadword 0x1f
252b5132
RH
356
357/* Is MODE an indexed addressing mode? */
358#define Adrmod_is_index(mode) \
47b0e7ad 359 ( mode == Adrmod_index_byte \
252b5132
RH
360 || mode == Adrmod_index_word \
361 || mode == Adrmod_index_doubleword \
362 || mode == Adrmod_index_quadword)
363
364\f
47b0e7ad
NC
365static int
366get_displacement (bfd_byte *buffer, int *aoffsetp)
252b5132 367{
47b0e7ad
NC
368 int Ivalue;
369 short Ivalue2;
252b5132 370
47b0e7ad
NC
371 Ivalue = bit_extract (buffer, *aoffsetp, 8);
372 switch (Ivalue & 0xc0)
252b5132 373 {
47b0e7ad
NC
374 case 0x00:
375 case 0x40:
376 Ivalue = sign_extend (Ivalue, 7);
377 *aoffsetp += 8;
378 break;
379 case 0x80:
380 Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
381 flip_bytes ((char *) & Ivalue2, 2);
382 Ivalue = sign_extend (Ivalue2, 14);
383 *aoffsetp += 16;
384 break;
385 case 0xc0:
386 Ivalue = bit_extract (buffer, *aoffsetp, 32);
387 flip_bytes ((char *) & Ivalue, 4);
388 Ivalue = sign_extend (Ivalue, 30);
389 *aoffsetp += 32;
390 break;
391 }
392 return Ivalue;
393}
252b5132 394
47b0e7ad
NC
395#if 1 /* A version that should work on ns32k f's&d's on any machine. */
396static int
397invalid_float (bfd_byte *p, int len)
398{
399 int val;
400
401 if (len == 4)
402 val = (bit_extract_simple (p, 23, 8)/*exponent*/ == 0xff
403 || (bit_extract_simple (p, 23, 8)/*exponent*/ == 0
404 && bit_extract_simple (p, 0, 23)/*mantisa*/ != 0));
405 else if (len == 8)
406 val = (bit_extract_simple (p, 52, 11)/*exponent*/ == 0x7ff
407 || (bit_extract_simple (p, 52, 11)/*exponent*/ == 0
408 && (bit_extract_simple (p, 0, 32)/*low mantisa*/ != 0
409 || bit_extract_simple (p, 32, 20)/*high mantisa*/ != 0)));
410 else
411 val = 1;
412 return (val);
413}
414#else
415/* Assumes the bytes have been swapped to local order. */
416typedef union
417{
418 double d;
419 float f;
420 struct { unsigned m:23, e:8, :1;} sf;
421 struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
422} float_type_u;
252b5132 423
47b0e7ad
NC
424static int
425invalid_float (float_type_u *p, int len)
426{
427 int val;
252b5132 428
47b0e7ad
NC
429 if (len == sizeof (float))
430 val = (p->sf.e == 0xff
431 || (p->sf.e == 0 && p->sf.m != 0));
432 else if (len == sizeof (double))
433 val = (p->sd.e == 0x7ff
434 || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
435 else
436 val = 1;
437 return val;
252b5132 438}
47b0e7ad 439#endif
252b5132
RH
440
441/* Print an instruction operand of category given by d. IOFFSET is
442 the bit position below which small (<1 byte) parts of the operand can
443 be found (usually in the basic instruction, but for indexed
444 addressing it can be in the index byte). AOFFSETP is a pointer to the
445 bit position of the addressing extension. BUFFER contains the
446 instruction. ADDR is where BUFFER was read from. Put the disassembled
447 version of the operand in RESULT. INDEX_OFFSET is the bit position
448 of the index byte (it contains garbage if this operand is not a
449 general operand using scaled indexed addressing mode). */
450
451static int
47b0e7ad
NC
452print_insn_arg (int d,
453 int ioffset,
454 int *aoffsetp,
455 bfd_byte *buffer,
456 bfd_vma addr,
457 char *result,
458 int index_offset)
252b5132 459{
47b0e7ad
NC
460 union
461 {
6a51a8a8
AM
462 float f;
463 double d;
464 int i[2];
465 } value;
252b5132 466 int Ivalue;
6a51a8a8 467 int addr_mode;
252b5132 468 int disp1, disp2;
252b5132
RH
469 int size;
470
471 switch (d)
472 {
473 case 'f':
47b0e7ad 474 /* A "gen" operand but 5 bits from the end of instruction. */
252b5132
RH
475 ioffset -= 5;
476 case 'Z':
477 case 'F':
478 case 'L':
479 case 'I':
480 case 'B':
481 case 'W':
482 case 'D':
483 case 'A':
47b0e7ad 484 addr_mode = bit_extract (buffer, ioffset - 5, 5);
252b5132
RH
485 ioffset -= 5;
486 switch (addr_mode)
487 {
488 case 0x0: case 0x1: case 0x2: case 0x3:
489 case 0x4: case 0x5: case 0x6: case 0x7:
47b0e7ad 490 /* Register mode R0 -- R7. */
252b5132
RH
491 switch (d)
492 {
493 case 'F':
494 case 'L':
495 case 'Z':
496 sprintf (result, "f%d", addr_mode);
497 break;
498 default:
499 sprintf (result, "r%d", addr_mode);
500 }
501 break;
502 case 0x8: case 0x9: case 0xa: case 0xb:
503 case 0xc: case 0xd: case 0xe: case 0xf:
47b0e7ad 504 /* Register relative disp(R0 -- R7). */
252b5132
RH
505 disp1 = get_displacement (buffer, aoffsetp);
506 sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
507 break;
508 case 0x10:
509 case 0x11:
510 case 0x12:
47b0e7ad 511 /* Memory relative disp2(disp1(FP, SP, SB)). */
252b5132
RH
512 disp1 = get_displacement (buffer, aoffsetp);
513 disp2 = get_displacement (buffer, aoffsetp);
514 sprintf (result, "%d(%d(%s))", disp2, disp1,
47b0e7ad 515 addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
252b5132
RH
516 break;
517 case 0x13:
47b0e7ad 518 /* Reserved. */
252b5132
RH
519 sprintf (result, "reserved");
520 break;
521 case 0x14:
47b0e7ad 522 /* Immediate. */
252b5132
RH
523 switch (d)
524 {
47b0e7ad
NC
525 case 'I':
526 case 'Z':
527 case 'A':
252b5132 528 /* I and Z are output operands and can`t be immediate
47b0e7ad
NC
529 A is an address and we can`t have the address of
530 an immediate either. We don't know how much to increase
531 aoffsetp by since whatever generated this is broken
532 anyway! */
252b5132
RH
533 sprintf (result, _("$<undefined>"));
534 break;
535 case 'B':
536 Ivalue = bit_extract (buffer, *aoffsetp, 8);
537 Ivalue = sign_extend (Ivalue, 8);
538 *aoffsetp += 8;
539 sprintf (result, "$%d", Ivalue);
540 break;
541 case 'W':
542 Ivalue = bit_extract (buffer, *aoffsetp, 16);
fc05c67f 543 flip_bytes ((char *) & Ivalue, 2);
252b5132
RH
544 *aoffsetp += 16;
545 Ivalue = sign_extend (Ivalue, 16);
546 sprintf (result, "$%d", Ivalue);
547 break;
548 case 'D':
549 Ivalue = bit_extract (buffer, *aoffsetp, 32);
fc05c67f 550 flip_bytes ((char *) & Ivalue, 4);
252b5132
RH
551 *aoffsetp += 32;
552 sprintf (result, "$%d", Ivalue);
553 break;
554 case 'F':
6a51a8a8
AM
555 bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
556 flip_bytes ((char *) &value.f, 4);
252b5132 557 *aoffsetp += 32;
6a51a8a8
AM
558 if (INVALID_FLOAT (&value.f, 4))
559 sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
47b0e7ad 560 else /* Assume host has ieee float. */
6a51a8a8 561 sprintf (result, "$%g", value.f);
252b5132
RH
562 break;
563 case 'L':
6a51a8a8
AM
564 bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
565 flip_bytes ((char *) &value.d, 8);
252b5132 566 *aoffsetp += 64;
6a51a8a8
AM
567 if (INVALID_FLOAT (&value.d, 8))
568 sprintf (result, "<<invalid double 0x%.8x%.8x>>",
569 value.i[1], value.i[0]);
47b0e7ad 570 else /* Assume host has ieee float. */
6a51a8a8 571 sprintf (result, "$%g", value.d);
252b5132
RH
572 break;
573 }
574 break;
575 case 0x15:
47b0e7ad 576 /* Absolute @disp. */
252b5132
RH
577 disp1 = get_displacement (buffer, aoffsetp);
578 sprintf (result, "@|%d|", disp1);
579 break;
580 case 0x16:
47b0e7ad 581 /* External EXT(disp1) + disp2 (Mod table stuff). */
252b5132
RH
582 disp1 = get_displacement (buffer, aoffsetp);
583 disp2 = get_displacement (buffer, aoffsetp);
584 sprintf (result, "EXT(%d) + %d", disp1, disp2);
585 break;
586 case 0x17:
47b0e7ad 587 /* Top of stack tos. */
252b5132
RH
588 sprintf (result, "tos");
589 break;
590 case 0x18:
47b0e7ad 591 /* Memory space disp(FP). */
252b5132
RH
592 disp1 = get_displacement (buffer, aoffsetp);
593 sprintf (result, "%d(fp)", disp1);
594 break;
595 case 0x19:
47b0e7ad 596 /* Memory space disp(SP). */
252b5132
RH
597 disp1 = get_displacement (buffer, aoffsetp);
598 sprintf (result, "%d(sp)", disp1);
599 break;
600 case 0x1a:
47b0e7ad 601 /* Memory space disp(SB). */
252b5132
RH
602 disp1 = get_displacement (buffer, aoffsetp);
603 sprintf (result, "%d(sb)", disp1);
604 break;
605 case 0x1b:
47b0e7ad 606 /* Memory space disp(PC). */
252b5132
RH
607 disp1 = get_displacement (buffer, aoffsetp);
608 *result++ = NEXT_IS_ADDR;
609 sprintf_vma (result, addr + disp1);
610 result += strlen (result);
611 *result++ = NEXT_IS_ADDR;
612 *result = '\0';
613 break;
614 case 0x1c:
615 case 0x1d:
616 case 0x1e:
617 case 0x1f:
252b5132 618 {
91d6fa6a 619 int bit_index;
252b5132
RH
620 static const char *ind = "bwdq";
621 char *off;
91d6fa6a
NC
622
623 /* Scaled index basemode[R0 -- R7:B,W,D,Q]. */
624 bit_index = bit_extract (buffer, index_offset - 8, 3);
625 print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
626 result, 0);
252b5132 627 off = result + strlen (result);
91d6fa6a 628 sprintf (off, "[r%d:%c]", bit_index, ind[addr_mode & 3]);
252b5132
RH
629 }
630 break;
631 }
632 break;
633 case 'H':
634 case 'q':
635 Ivalue = bit_extract (buffer, ioffset-4, 4);
636 Ivalue = sign_extend (Ivalue, 4);
637 sprintf (result, "%d", Ivalue);
638 ioffset -= 4;
639 break;
640 case 'r':
641 Ivalue = bit_extract (buffer, ioffset-3, 3);
642 sprintf (result, "r%d", Ivalue&7);
643 ioffset -= 3;
644 break;
645 case 'd':
646 sprintf (result, "%d", get_displacement (buffer, aoffsetp));
647 break;
648 case 'b':
649 Ivalue = get_displacement (buffer, aoffsetp);
47b0e7ad
NC
650 /* Warning!! HACK ALERT!
651 Operand type 'b' is only used by the cmp{b,w,d} and
652 movm{b,w,d} instructions; we need to know whether
653 it's a `b' or `w' or `d' instruction; and for both
654 cmpm and movm it's stored at the same place so we
655 just grab two bits of the opcode and look at it... */
252b5132 656 size = bit_extract(buffer, ioffset-6, 2);
47b0e7ad 657 if (size == 0) /* 00 => b. */
252b5132 658 size = 1;
47b0e7ad 659 else if (size == 1) /* 01 => w. */
252b5132
RH
660 size = 2;
661 else
47b0e7ad 662 size = 4; /* 11 => d. */
252b5132
RH
663
664 sprintf (result, "%d", (Ivalue / size) + 1);
665 break;
666 case 'p':
667 *result++ = NEXT_IS_ADDR;
668 sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
669 result += strlen (result);
670 *result++ = NEXT_IS_ADDR;
671 *result = '\0';
672 break;
673 case 'i':
674 Ivalue = bit_extract (buffer, *aoffsetp, 8);
675 *aoffsetp += 8;
676 sprintf (result, "0x%x", Ivalue);
677 break;
678 case 'u':
679 Ivalue = bit_extract (buffer, *aoffsetp, 8);
47b0e7ad 680 optlist (Ivalue, opt_u, result);
252b5132
RH
681 *aoffsetp += 8;
682 break;
683 case 'U':
47b0e7ad
NC
684 Ivalue = bit_extract (buffer, *aoffsetp, 8);
685 optlist (Ivalue, opt_U, result);
252b5132
RH
686 *aoffsetp += 8;
687 break;
688 case 'O':
47b0e7ad
NC
689 Ivalue = bit_extract (buffer, ioffset - 9, 9);
690 optlist (Ivalue, opt_O, result);
252b5132
RH
691 ioffset -= 9;
692 break;
693 case 'C':
47b0e7ad
NC
694 Ivalue = bit_extract (buffer, ioffset - 4, 4);
695 optlist (Ivalue, opt_C, result);
252b5132
RH
696 ioffset -= 4;
697 break;
698 case 'S':
47b0e7ad
NC
699 Ivalue = bit_extract (buffer, ioffset - 8, 8);
700 optlist (Ivalue, opt_S, result);
252b5132
RH
701 ioffset -= 8;
702 break;
703 case 'M':
47b0e7ad
NC
704 Ivalue = bit_extract (buffer, ioffset - 4, 4);
705 list_search (Ivalue, 0 ? list_M032 : list_M532, result);
252b5132
RH
706 ioffset -= 4;
707 break;
708 case 'P':
47b0e7ad
NC
709 Ivalue = bit_extract (buffer, ioffset - 4, 4);
710 list_search (Ivalue, 0 ? list_P032 : list_P532, result);
252b5132
RH
711 ioffset -= 4;
712 break;
713 case 'g':
47b0e7ad
NC
714 Ivalue = bit_extract (buffer, *aoffsetp, 3);
715 sprintf (result, "%d", Ivalue);
252b5132
RH
716 *aoffsetp += 3;
717 break;
718 case 'G':
719 Ivalue = bit_extract(buffer, *aoffsetp, 5);
47b0e7ad 720 sprintf (result, "%d", Ivalue + 1);
252b5132
RH
721 *aoffsetp += 5;
722 break;
723 }
724 return ioffset;
725}
726
47b0e7ad
NC
727\f
728/* Print the 32000 instruction at address MEMADDR in debugged memory,
729 on STREAM. Returns length of the instruction, in bytes. */
730
731int
732print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
252b5132 733{
47b0e7ad
NC
734 unsigned int i;
735 const char *d;
736 unsigned short first_word;
737 int ioffset; /* Bits into instruction. */
738 int aoffset; /* Bits into arguments. */
739 char arg_bufs[MAX_ARGS+1][ARG_LEN];
740 int argnum;
741 int maxarg;
742 struct private priv;
743 bfd_byte *buffer = priv.the_buffer;
744 dis_info = info;
252b5132 745
47b0e7ad
NC
746 info->private_data = & priv;
747 priv.max_fetched = priv.the_buffer;
748 priv.insn_start = memaddr;
749 if (setjmp (priv.bailout) != 0)
750 /* Error return. */
751 return -1;
752
753 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
754 us over the end of accessible data unnecessarilly. */
755 FETCH_DATA (info, buffer + 1);
756 for (i = 0; i < NOPCODES; i++)
757 if (ns32k_opcodes[i].opcode_id_size <= 8
758 && ((buffer[0]
759 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
760 == ns32k_opcodes[i].opcode_seed))
252b5132 761 break;
47b0e7ad
NC
762 if (i == NOPCODES)
763 {
764 /* Maybe it is 9 to 16 bits big. */
765 FETCH_DATA (info, buffer + 2);
766 first_word = read_memory_integer(buffer, 2);
767
768 for (i = 0; i < NOPCODES; i++)
769 if ((first_word
770 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
771 == ns32k_opcodes[i].opcode_seed)
772 break;
773
774 /* Handle undefined instructions. */
775 if (i == NOPCODES)
776 {
777 (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
778 return 1;
779 }
252b5132 780 }
252b5132 781
47b0e7ad 782 (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
252b5132 783
47b0e7ad
NC
784 ioffset = ns32k_opcodes[i].opcode_size;
785 aoffset = ns32k_opcodes[i].opcode_size;
786 d = ns32k_opcodes[i].operands;
252b5132 787
47b0e7ad
NC
788 if (*d)
789 {
790 /* Offset in bits of the first thing beyond each index byte.
791 Element 0 is for operand A and element 1 is for operand B.
792 The rest are irrelevant, but we put them here so we don't
793 index outside the array. */
794 int index_offset[MAX_ARGS];
795
796 /* 0 for operand A, 1 for operand B, greater for other args. */
797 int whicharg = 0;
798
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. */
807 if (Is_gen(d[1]))
808 {
809 int addr_mode = bit_extract (buffer, ioffset - 5, 5);
810
811 if (Adrmod_is_index (addr_mode))
812 {
813 aoffset += 8;
814 index_offset[0] = aoffset;
815 }
816 }
817
818 if (d[2] && Is_gen(d[3]))
819 {
820 int addr_mode = bit_extract (buffer, ioffset - 10, 5);
821
822 if (Adrmod_is_index (addr_mode))
823 {
824 aoffset += 8;
825 index_offset[1] = aoffset;
826 }
827 }
828
829 while (*d)
830 {
831 argnum = *d - '1';
832 d++;
833 if (argnum > maxarg && argnum < MAX_ARGS)
834 maxarg = argnum;
835 ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
836 memaddr, arg_bufs[argnum],
837 index_offset[whicharg]);
838 d++;
839 whicharg++;
840 }
841 for (argnum = 0; argnum <= maxarg; argnum++)
842 {
843 bfd_vma addr;
844 char *ch;
845
846 for (ch = arg_bufs[argnum]; *ch;)
847 {
848 if (*ch == NEXT_IS_ADDR)
849 {
850 ++ch;
851 addr = bfd_scan_vma (ch, NULL, 16);
852 (*dis_info->print_address_func) (addr, dis_info);
853 while (*ch && *ch != NEXT_IS_ADDR)
854 ++ch;
855 if (*ch)
856 ++ch;
857 }
858 else
859 (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
860 }
861 if (argnum < maxarg)
862 (*dis_info->fprintf_func)(dis_info->stream, ", ");
863 }
864 }
865 return aoffset / 8;
252b5132 866}