Change source files over to GPLv3.
[deliverable/binutils-gdb.git] / opcodes / ns32k-dis.c
CommitLineData
252b5132 1/* Print National Semiconductor 32000 instructions.
3db64b00 2 Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005, 2007
060d22b0 3 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
RH
468 int disp1, disp2;
469 int index;
470 int size;
471
472 switch (d)
473 {
474 case 'f':
47b0e7ad 475 /* A "gen" operand but 5 bits from the end of instruction. */
252b5132
RH
476 ioffset -= 5;
477 case 'Z':
478 case 'F':
479 case 'L':
480 case 'I':
481 case 'B':
482 case 'W':
483 case 'D':
484 case 'A':
47b0e7ad 485 addr_mode = bit_extract (buffer, ioffset - 5, 5);
252b5132
RH
486 ioffset -= 5;
487 switch (addr_mode)
488 {
489 case 0x0: case 0x1: case 0x2: case 0x3:
490 case 0x4: case 0x5: case 0x6: case 0x7:
47b0e7ad 491 /* Register mode R0 -- R7. */
252b5132
RH
492 switch (d)
493 {
494 case 'F':
495 case 'L':
496 case 'Z':
497 sprintf (result, "f%d", addr_mode);
498 break;
499 default:
500 sprintf (result, "r%d", addr_mode);
501 }
502 break;
503 case 0x8: case 0x9: case 0xa: case 0xb:
504 case 0xc: case 0xd: case 0xe: case 0xf:
47b0e7ad 505 /* Register relative disp(R0 -- R7). */
252b5132
RH
506 disp1 = get_displacement (buffer, aoffsetp);
507 sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
508 break;
509 case 0x10:
510 case 0x11:
511 case 0x12:
47b0e7ad 512 /* Memory relative disp2(disp1(FP, SP, SB)). */
252b5132
RH
513 disp1 = get_displacement (buffer, aoffsetp);
514 disp2 = get_displacement (buffer, aoffsetp);
515 sprintf (result, "%d(%d(%s))", disp2, disp1,
47b0e7ad 516 addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
252b5132
RH
517 break;
518 case 0x13:
47b0e7ad 519 /* Reserved. */
252b5132
RH
520 sprintf (result, "reserved");
521 break;
522 case 0x14:
47b0e7ad 523 /* Immediate. */
252b5132
RH
524 switch (d)
525 {
47b0e7ad
NC
526 case 'I':
527 case 'Z':
528 case 'A':
252b5132 529 /* I and Z are output operands and can`t be immediate
47b0e7ad
NC
530 A is an address and we can`t have the address of
531 an immediate either. We don't know how much to increase
532 aoffsetp by since whatever generated this is broken
533 anyway! */
252b5132
RH
534 sprintf (result, _("$<undefined>"));
535 break;
536 case 'B':
537 Ivalue = bit_extract (buffer, *aoffsetp, 8);
538 Ivalue = sign_extend (Ivalue, 8);
539 *aoffsetp += 8;
540 sprintf (result, "$%d", Ivalue);
541 break;
542 case 'W':
543 Ivalue = bit_extract (buffer, *aoffsetp, 16);
fc05c67f 544 flip_bytes ((char *) & Ivalue, 2);
252b5132
RH
545 *aoffsetp += 16;
546 Ivalue = sign_extend (Ivalue, 16);
547 sprintf (result, "$%d", Ivalue);
548 break;
549 case 'D':
550 Ivalue = bit_extract (buffer, *aoffsetp, 32);
fc05c67f 551 flip_bytes ((char *) & Ivalue, 4);
252b5132
RH
552 *aoffsetp += 32;
553 sprintf (result, "$%d", Ivalue);
554 break;
555 case 'F':
6a51a8a8
AM
556 bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
557 flip_bytes ((char *) &value.f, 4);
252b5132 558 *aoffsetp += 32;
6a51a8a8
AM
559 if (INVALID_FLOAT (&value.f, 4))
560 sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
47b0e7ad 561 else /* Assume host has ieee float. */
6a51a8a8 562 sprintf (result, "$%g", value.f);
252b5132
RH
563 break;
564 case 'L':
6a51a8a8
AM
565 bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
566 flip_bytes ((char *) &value.d, 8);
252b5132 567 *aoffsetp += 64;
6a51a8a8
AM
568 if (INVALID_FLOAT (&value.d, 8))
569 sprintf (result, "<<invalid double 0x%.8x%.8x>>",
570 value.i[1], value.i[0]);
47b0e7ad 571 else /* Assume host has ieee float. */
6a51a8a8 572 sprintf (result, "$%g", value.d);
252b5132
RH
573 break;
574 }
575 break;
576 case 0x15:
47b0e7ad 577 /* Absolute @disp. */
252b5132
RH
578 disp1 = get_displacement (buffer, aoffsetp);
579 sprintf (result, "@|%d|", disp1);
580 break;
581 case 0x16:
47b0e7ad 582 /* External EXT(disp1) + disp2 (Mod table stuff). */
252b5132
RH
583 disp1 = get_displacement (buffer, aoffsetp);
584 disp2 = get_displacement (buffer, aoffsetp);
585 sprintf (result, "EXT(%d) + %d", disp1, disp2);
586 break;
587 case 0x17:
47b0e7ad 588 /* Top of stack tos. */
252b5132
RH
589 sprintf (result, "tos");
590 break;
591 case 0x18:
47b0e7ad 592 /* Memory space disp(FP). */
252b5132
RH
593 disp1 = get_displacement (buffer, aoffsetp);
594 sprintf (result, "%d(fp)", disp1);
595 break;
596 case 0x19:
47b0e7ad 597 /* Memory space disp(SP). */
252b5132
RH
598 disp1 = get_displacement (buffer, aoffsetp);
599 sprintf (result, "%d(sp)", disp1);
600 break;
601 case 0x1a:
47b0e7ad 602 /* Memory space disp(SB). */
252b5132
RH
603 disp1 = get_displacement (buffer, aoffsetp);
604 sprintf (result, "%d(sb)", disp1);
605 break;
606 case 0x1b:
47b0e7ad 607 /* Memory space disp(PC). */
252b5132
RH
608 disp1 = get_displacement (buffer, aoffsetp);
609 *result++ = NEXT_IS_ADDR;
610 sprintf_vma (result, addr + disp1);
611 result += strlen (result);
612 *result++ = NEXT_IS_ADDR;
613 *result = '\0';
614 break;
615 case 0x1c:
616 case 0x1d:
617 case 0x1e:
618 case 0x1f:
47b0e7ad 619 /* Scaled index basemode[R0 -- R7:B,W,D,Q]. */
252b5132
RH
620 index = bit_extract (buffer, index_offset - 8, 3);
621 print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
622 result, 0);
623 {
624 static const char *ind = "bwdq";
625 char *off;
626
627 off = result + strlen (result);
628 sprintf (off, "[r%d:%c]", index,
629 ind[addr_mode & 3]);
630 }
631 break;
632 }
633 break;
634 case 'H':
635 case 'q':
636 Ivalue = bit_extract (buffer, ioffset-4, 4);
637 Ivalue = sign_extend (Ivalue, 4);
638 sprintf (result, "%d", Ivalue);
639 ioffset -= 4;
640 break;
641 case 'r':
642 Ivalue = bit_extract (buffer, ioffset-3, 3);
643 sprintf (result, "r%d", Ivalue&7);
644 ioffset -= 3;
645 break;
646 case 'd':
647 sprintf (result, "%d", get_displacement (buffer, aoffsetp));
648 break;
649 case 'b':
650 Ivalue = get_displacement (buffer, aoffsetp);
47b0e7ad
NC
651 /* Warning!! HACK ALERT!
652 Operand type 'b' is only used by the cmp{b,w,d} and
653 movm{b,w,d} instructions; we need to know whether
654 it's a `b' or `w' or `d' instruction; and for both
655 cmpm and movm it's stored at the same place so we
656 just grab two bits of the opcode and look at it... */
252b5132 657 size = bit_extract(buffer, ioffset-6, 2);
47b0e7ad 658 if (size == 0) /* 00 => b. */
252b5132 659 size = 1;
47b0e7ad 660 else if (size == 1) /* 01 => w. */
252b5132
RH
661 size = 2;
662 else
47b0e7ad 663 size = 4; /* 11 => d. */
252b5132
RH
664
665 sprintf (result, "%d", (Ivalue / size) + 1);
666 break;
667 case 'p':
668 *result++ = NEXT_IS_ADDR;
669 sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
670 result += strlen (result);
671 *result++ = NEXT_IS_ADDR;
672 *result = '\0';
673 break;
674 case 'i':
675 Ivalue = bit_extract (buffer, *aoffsetp, 8);
676 *aoffsetp += 8;
677 sprintf (result, "0x%x", Ivalue);
678 break;
679 case 'u':
680 Ivalue = bit_extract (buffer, *aoffsetp, 8);
47b0e7ad 681 optlist (Ivalue, opt_u, result);
252b5132
RH
682 *aoffsetp += 8;
683 break;
684 case 'U':
47b0e7ad
NC
685 Ivalue = bit_extract (buffer, *aoffsetp, 8);
686 optlist (Ivalue, opt_U, result);
252b5132
RH
687 *aoffsetp += 8;
688 break;
689 case 'O':
47b0e7ad
NC
690 Ivalue = bit_extract (buffer, ioffset - 9, 9);
691 optlist (Ivalue, opt_O, result);
252b5132
RH
692 ioffset -= 9;
693 break;
694 case 'C':
47b0e7ad
NC
695 Ivalue = bit_extract (buffer, ioffset - 4, 4);
696 optlist (Ivalue, opt_C, result);
252b5132
RH
697 ioffset -= 4;
698 break;
699 case 'S':
47b0e7ad
NC
700 Ivalue = bit_extract (buffer, ioffset - 8, 8);
701 optlist (Ivalue, opt_S, result);
252b5132
RH
702 ioffset -= 8;
703 break;
704 case 'M':
47b0e7ad
NC
705 Ivalue = bit_extract (buffer, ioffset - 4, 4);
706 list_search (Ivalue, 0 ? list_M032 : list_M532, result);
252b5132
RH
707 ioffset -= 4;
708 break;
709 case 'P':
47b0e7ad
NC
710 Ivalue = bit_extract (buffer, ioffset - 4, 4);
711 list_search (Ivalue, 0 ? list_P032 : list_P532, result);
252b5132
RH
712 ioffset -= 4;
713 break;
714 case 'g':
47b0e7ad
NC
715 Ivalue = bit_extract (buffer, *aoffsetp, 3);
716 sprintf (result, "%d", Ivalue);
252b5132
RH
717 *aoffsetp += 3;
718 break;
719 case 'G':
720 Ivalue = bit_extract(buffer, *aoffsetp, 5);
47b0e7ad 721 sprintf (result, "%d", Ivalue + 1);
252b5132
RH
722 *aoffsetp += 5;
723 break;
724 }
725 return ioffset;
726}
727
47b0e7ad
NC
728\f
729/* Print the 32000 instruction at address MEMADDR in debugged memory,
730 on STREAM. Returns length of the instruction, in bytes. */
731
732int
733print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
252b5132 734{
47b0e7ad
NC
735 unsigned int i;
736 const char *d;
737 unsigned short first_word;
738 int ioffset; /* Bits into instruction. */
739 int aoffset; /* Bits into arguments. */
740 char arg_bufs[MAX_ARGS+1][ARG_LEN];
741 int argnum;
742 int maxarg;
743 struct private priv;
744 bfd_byte *buffer = priv.the_buffer;
745 dis_info = info;
252b5132 746
47b0e7ad
NC
747 info->private_data = & priv;
748 priv.max_fetched = priv.the_buffer;
749 priv.insn_start = memaddr;
750 if (setjmp (priv.bailout) != 0)
751 /* Error return. */
752 return -1;
753
754 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
755 us over the end of accessible data unnecessarilly. */
756 FETCH_DATA (info, buffer + 1);
757 for (i = 0; i < NOPCODES; i++)
758 if (ns32k_opcodes[i].opcode_id_size <= 8
759 && ((buffer[0]
760 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
761 == ns32k_opcodes[i].opcode_seed))
252b5132 762 break;
47b0e7ad
NC
763 if (i == NOPCODES)
764 {
765 /* Maybe it is 9 to 16 bits big. */
766 FETCH_DATA (info, buffer + 2);
767 first_word = read_memory_integer(buffer, 2);
768
769 for (i = 0; i < NOPCODES; i++)
770 if ((first_word
771 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
772 == ns32k_opcodes[i].opcode_seed)
773 break;
774
775 /* Handle undefined instructions. */
776 if (i == NOPCODES)
777 {
778 (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
779 return 1;
780 }
252b5132 781 }
252b5132 782
47b0e7ad 783 (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
252b5132 784
47b0e7ad
NC
785 ioffset = ns32k_opcodes[i].opcode_size;
786 aoffset = ns32k_opcodes[i].opcode_size;
787 d = ns32k_opcodes[i].operands;
252b5132 788
47b0e7ad
NC
789 if (*d)
790 {
791 /* Offset in bits of the first thing beyond each index byte.
792 Element 0 is for operand A and element 1 is for operand B.
793 The rest are irrelevant, but we put them here so we don't
794 index outside the array. */
795 int index_offset[MAX_ARGS];
796
797 /* 0 for operand A, 1 for operand B, greater for other args. */
798 int whicharg = 0;
799
800 (*dis_info->fprintf_func)(dis_info->stream, "\t");
801
802 maxarg = 0;
803
804 /* First we have to find and keep track of the index bytes,
805 if we are using scaled indexed addressing mode, since the index
806 bytes occur right after the basic instruction, not as part
807 of the addressing extension. */
808 if (Is_gen(d[1]))
809 {
810 int addr_mode = bit_extract (buffer, ioffset - 5, 5);
811
812 if (Adrmod_is_index (addr_mode))
813 {
814 aoffset += 8;
815 index_offset[0] = aoffset;
816 }
817 }
818
819 if (d[2] && Is_gen(d[3]))
820 {
821 int addr_mode = bit_extract (buffer, ioffset - 10, 5);
822
823 if (Adrmod_is_index (addr_mode))
824 {
825 aoffset += 8;
826 index_offset[1] = aoffset;
827 }
828 }
829
830 while (*d)
831 {
832 argnum = *d - '1';
833 d++;
834 if (argnum > maxarg && argnum < MAX_ARGS)
835 maxarg = argnum;
836 ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
837 memaddr, arg_bufs[argnum],
838 index_offset[whicharg]);
839 d++;
840 whicharg++;
841 }
842 for (argnum = 0; argnum <= maxarg; argnum++)
843 {
844 bfd_vma addr;
845 char *ch;
846
847 for (ch = arg_bufs[argnum]; *ch;)
848 {
849 if (*ch == NEXT_IS_ADDR)
850 {
851 ++ch;
852 addr = bfd_scan_vma (ch, NULL, 16);
853 (*dis_info->print_address_func) (addr, dis_info);
854 while (*ch && *ch != NEXT_IS_ADDR)
855 ++ch;
856 if (*ch)
857 ++ch;
858 }
859 else
860 (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
861 }
862 if (argnum < maxarg)
863 (*dis_info->fprintf_func)(dis_info->stream, ", ");
864 }
865 }
866 return aoffset / 8;
252b5132 867}
This page took 0.389042 seconds and 4 git commands to generate.