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