/* Print National Semiconductor 32000 instructions.
- Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005
- Free Software Foundation, Inc.
+ Copyright (C) 1986-2015 Free Software Foundation, Inc.
-This file is part of opcodes library.
+ This file is part of the GNU opcodes library.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ It is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "dis-asm.h"
#if !defined(const) && !defined(__STDC__)
#define const
static disassemble_info *dis_info;
-/*
- * Hacks to get it to compile <= READ THESE AS FIXES NEEDED
- */
-#define INVALID_FLOAT(val, size) invalid_float((bfd_byte *)val, size)
-
-static int print_insn_arg
- PARAMS ((int, int, int *, bfd_byte *, bfd_vma, char *, int));
-static int get_displacement PARAMS ((bfd_byte *, int *));
-static int invalid_float PARAMS ((bfd_byte *, int));
-static long int read_memory_integer PARAMS ((unsigned char *, int));
-static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
-struct ns32k_option;
-static void optlist PARAMS ((int, const struct ns32k_option *, char *));
-static void list_search PARAMS ((int, const struct ns32k_option *, char *));
-static int bit_extract PARAMS ((bfd_byte *, int, int));
-static int bit_extract_simple PARAMS ((bfd_byte *, int, int));
-static void bit_copy PARAMS ((bfd_byte *, int, int, char *));
-static int sign_extend PARAMS ((int, int));
-static void flip_bytes PARAMS ((char *, int));
-
-static long read_memory_integer(addr, nr)
- unsigned char *addr;
- int nr;
+/* Hacks to get it to compile <= READ THESE AS FIXES NEEDED. */
+#define INVALID_FLOAT(val, size) invalid_float ((bfd_byte *) val, size)
+
+static long
+read_memory_integer (unsigned char * addr, int nr)
{
long val;
int i;
- for (val = 0, i = nr - 1; i >= 0; i--) {
- val = (val << 8);
- val |= (0xff & *(addr + i));
- }
+
+ for (val = 0, i = nr - 1; i >= 0; i--)
+ {
+ val = (val << 8);
+ val |= (0xff & *(addr + i));
+ }
return val;
}
/* 32000 instructions are never longer than this. */
#define MAXLEN 62
-
#include <setjmp.h>
struct private
bfd_byte *max_fetched;
bfd_byte the_buffer[MAXLEN];
bfd_vma insn_start;
- jmp_buf bailout;
+ OPCODES_SIGJMP_BUF bailout;
};
? 1 : fetch_data ((info), (addr)))
static int
-fetch_data (info, addr)
- struct disassemble_info *info;
- bfd_byte *addr;
+fetch_data (struct disassemble_info *info, bfd_byte *addr)
{
int status;
- struct private *priv = (struct private *)info->private_data;
+ struct private *priv = (struct private *) info->private_data;
bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
status = (*info->read_memory_func) (start,
if (status != 0)
{
(*info->memory_error_func) (status, start, info);
- longjmp (priv->bailout, 1);
+ OPCODES_SIGLONGJMP (priv->bailout, 1);
}
else
priv->max_fetched = addr;
return 1;
}
+
/* Number of elements in the opcode table. */
#define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
#define NEXT_IS_ADDR '|'
\f
-struct ns32k_option {
- char *pattern; /* the option itself */
- unsigned long value; /* binary value of the option */
- unsigned long match; /* these bits must match */
+struct ns32k_option
+{
+ char *pattern; /* The option itself. */
+ unsigned long value; /* Binary value of the option. */
+ unsigned long match; /* These bits must match. */
};
\f
-static const struct ns32k_option opt_u[]= /* restore, exit */
+static const struct ns32k_option opt_u[]= /* Restore, exit. */
{
{ "r0", 0x80, 0x80 },
{ "r1", 0x40, 0x40 },
{ 0 , 0x00, 0x00 }
};
-static const struct ns32k_option opt_U[]= /* save, enter */
+static const struct ns32k_option opt_U[]= /* Save, enter. */
{
{ "r0", 0x01, 0x01 },
{ "r1", 0x02, 0x02 },
{ 0 , 0x00, 0x00 }
};
-static const struct ns32k_option opt_O[]= /* setcfg */
+static const struct ns32k_option opt_O[]= /* Setcfg. */
{
{ "c", 0x8, 0x8 },
{ "m", 0x4, 0x4 },
{ 0 , 0x0, 0x0 }
};
-static const struct ns32k_option opt_C[]= /* cinv */
+static const struct ns32k_option opt_C[]= /* Cinv. */
{
{ "a", 0x4, 0x4 },
{ "i", 0x2, 0x2 },
{ 0 , 0x0, 0x0 }
};
-static const struct ns32k_option opt_S[]= /* string inst */
+static const struct ns32k_option opt_S[]= /* String inst. */
{
{ "b", 0x1, 0x1 },
{ "u", 0x6, 0x6 },
{ 0 , 0x0, 0x0 }
};
-static const struct ns32k_option list_P532[]= /* lpr spr */
+static const struct ns32k_option list_P532[]= /* Lpr spr. */
{
{ "us", 0x0, 0xf },
{ "dcr", 0x1, 0xf },
{ 0 , 0x00, 0xf }
};
-static const struct ns32k_option list_M532[]= /* lmr smr */
+static const struct ns32k_option list_M532[]= /* Lmr smr. */
{
{ "mcr", 0x9, 0xf },
{ "msr", 0xa, 0xf },
{ 0 , 0x0, 0xf }
};
-static const struct ns32k_option list_P032[]= /* lpr spr */
+static const struct ns32k_option list_P032[]= /* Lpr spr. */
{
{ "upsr", 0x0, 0xf },
{ "fp", 0x8, 0xf },
{ 0 , 0x0, 0xf }
};
-static const struct ns32k_option list_M032[]= /* lmr smr */
+static const struct ns32k_option list_M032[]= /* Lmr smr. */
{
{ "bpr0", 0x0, 0xf },
{ "bpr1", 0x1, 0xf },
};
-/*
- * figure out which options are present
- */
+/* Figure out which options are present. */
+
static void
-optlist(options, optionP, result)
- int options;
- const struct ns32k_option *optionP;
- char *result;
+optlist (int options, const struct ns32k_option * optionP, char * result)
{
- if (options == 0) {
- sprintf(result, "[]");
- return;
+ if (options == 0)
+ {
+ sprintf (result, "[]");
+ return;
}
- sprintf(result, "[");
-
- for (; (options != 0) && optionP->pattern; optionP++) {
- if ((options & optionP->match) == optionP->value) {
- /* we found a match, update result and options */
- strcat(result, optionP->pattern);
- options &= ~optionP->value;
- if (options != 0) /* more options to come */
- strcat(result, ",");
+
+ sprintf (result, "[");
+
+ for (; (options != 0) && optionP->pattern; optionP++)
+ {
+ if ((options & optionP->match) == optionP->value)
+ {
+ /* We found a match, update result and options. */
+ strcat (result, optionP->pattern);
+ options &= ~optionP->value;
+ if (options != 0) /* More options to come. */
+ strcat (result, ",");
}
}
- if (options != 0)
- strcat(result, "undefined");
- strcat(result, "]");
+ if (options != 0)
+ strcat (result, "undefined");
+
+ strcat (result, "]");
}
static void
-list_search (reg_value, optionP, result)
- int reg_value;
- const struct ns32k_option *optionP;
- char *result;
+list_search (int reg_value, const struct ns32k_option *optionP, char *result)
{
- for (; optionP->pattern; optionP++) {
- if ((reg_value & optionP->match) == optionP->value) {
- sprintf(result, "%s", optionP->pattern);
- return;
+ for (; optionP->pattern; optionP++)
+ {
+ if ((reg_value & optionP->match) == optionP->value)
+ {
+ sprintf (result, "%s", optionP->pattern);
+ return;
}
}
- sprintf(result, "undefined");
+ sprintf (result, "undefined");
}
\f
-/*
- * extract "count" bits starting "offset" bits
- * into buffer
- */
+/* Extract "count" bits starting "offset" bits into buffer. */
static int
-bit_extract (buffer, offset, count)
- bfd_byte *buffer;
- int offset;
- int count;
+bit_extract (bfd_byte *buffer, int offset, int count)
{
int result;
int bit;
result = 0;
while (count--)
{
- FETCH_DATA(dis_info, buffer + 1);
+ FETCH_DATA (dis_info, buffer + 1);
if ((*buffer & (1 << offset)))
result |= bit;
if (++offset == 8)
return result;
}
-/* Like bit extract but the buffer is valid and doen't need to be
- * fetched
- */
+/* Like bit extract but the buffer is valid and doen't need to be fetched. */
+
static int
-bit_extract_simple (buffer, offset, count)
- bfd_byte *buffer;
- int offset;
- int count;
+bit_extract_simple (bfd_byte *buffer, int offset, int count)
{
int result;
int bit;
}
static void
-bit_copy (buffer, offset, count, to)
- bfd_byte *buffer;
- int offset;
- int count;
- char *to;
+bit_copy (bfd_byte *buffer, int offset, int count, char *to)
{
- for(; count > 8; count -= 8, to++, offset += 8)
+ for (; count > 8; count -= 8, to++, offset += 8)
*to = bit_extract (buffer, offset, 8);
*to = bit_extract (buffer, offset, count);
}
-
static int
-sign_extend (value, bits)
- int value, bits;
+sign_extend (int value, int bits)
{
value = value & ((1 << bits) - 1);
- return (value & (1 << (bits-1))
+ return (value & (1 << (bits - 1))
? value | (~((1 << bits) - 1))
: value);
}
static void
-flip_bytes (ptr, count)
- char *ptr;
- int count;
+flip_bytes (char *ptr, int count)
{
char tmp;
while (count > 0)
{
tmp = ptr[0];
- ptr[0] = ptr[count-1];
- ptr[count-1] = tmp;
+ ptr[0] = ptr[count - 1];
+ ptr[count - 1] = tmp;
ptr++;
count -= 2;
}
|| (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
/* Adressing modes. */
-#define Adrmod_index_byte 0x1c
-#define Adrmod_index_word 0x1d
-#define Adrmod_index_doubleword 0x1e
-#define Adrmod_index_quadword 0x1f
+#define Adrmod_index_byte 0x1c
+#define Adrmod_index_word 0x1d
+#define Adrmod_index_doubleword 0x1e
+#define Adrmod_index_quadword 0x1f
/* Is MODE an indexed addressing mode? */
#define Adrmod_is_index(mode) \
- (mode == Adrmod_index_byte \
+ ( mode == Adrmod_index_byte \
|| mode == Adrmod_index_word \
|| mode == Adrmod_index_doubleword \
|| mode == Adrmod_index_quadword)
\f
-/* Print the 32000 instruction at address MEMADDR in debugged memory,
- on STREAM. Returns length of the instruction, in bytes. */
-
-int
-print_insn_ns32k (memaddr, info)
- bfd_vma memaddr;
- disassemble_info *info;
+static int
+get_displacement (bfd_byte *buffer, int *aoffsetp)
{
- unsigned int i;
- const char *d;
- unsigned short first_word;
- int ioffset; /* bits into instruction */
- int aoffset; /* bits into arguments */
- char arg_bufs[MAX_ARGS+1][ARG_LEN];
- int argnum;
- int maxarg;
- struct private priv;
- bfd_byte *buffer = priv.the_buffer;
- dis_info = info;
-
- info->private_data = (PTR) &priv;
- priv.max_fetched = priv.the_buffer;
- priv.insn_start = memaddr;
- if (setjmp (priv.bailout) != 0)
- /* Error return. */
- return -1;
-
- /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
- * us over the end of accessible data unnecessarilly
- */
- FETCH_DATA(info, buffer + 1);
- for (i = 0; i < NOPCODES; i++)
- if (ns32k_opcodes[i].opcode_id_size <= 8
- && ((buffer[0]
- & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
- == ns32k_opcodes[i].opcode_seed))
- break;
- if (i == NOPCODES) {
- /* Maybe it is 9 to 16 bits big */
- FETCH_DATA(info, buffer + 2);
- first_word = read_memory_integer(buffer, 2);
-
- for (i = 0; i < NOPCODES; i++)
- if ((first_word
- & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
- == ns32k_opcodes[i].opcode_seed)
- break;
-
- /* Handle undefined instructions. */
- if (i == NOPCODES)
- {
- (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
- return 1;
- }
- }
-
- (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
-
- ioffset = ns32k_opcodes[i].opcode_size;
- aoffset = ns32k_opcodes[i].opcode_size;
- d = ns32k_opcodes[i].operands;
+ int Ivalue;
+ short Ivalue2;
- if (*d)
+ Ivalue = bit_extract (buffer, *aoffsetp, 8);
+ switch (Ivalue & 0xc0)
{
- /* Offset in bits of the first thing beyond each index byte.
- Element 0 is for operand A and element 1 is for operand B.
- The rest are irrelevant, but we put them here so we don't
- index outside the array. */
- int index_offset[MAX_ARGS];
-
- /* 0 for operand A, 1 for operand B, greater for other args. */
- int whicharg = 0;
-
- (*dis_info->fprintf_func)(dis_info->stream, "\t");
-
- maxarg = 0;
-
- /* First we have to find and keep track of the index bytes,
- if we are using scaled indexed addressing mode, since the index
- bytes occur right after the basic instruction, not as part
- of the addressing extension. */
- if (Is_gen(d[1]))
- {
- int addr_mode = bit_extract (buffer, ioffset - 5, 5);
+ case 0x00:
+ case 0x40:
+ Ivalue = sign_extend (Ivalue, 7);
+ *aoffsetp += 8;
+ break;
+ case 0x80:
+ Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
+ flip_bytes ((char *) & Ivalue2, 2);
+ Ivalue = sign_extend (Ivalue2, 14);
+ *aoffsetp += 16;
+ break;
+ case 0xc0:
+ Ivalue = bit_extract (buffer, *aoffsetp, 32);
+ flip_bytes ((char *) & Ivalue, 4);
+ Ivalue = sign_extend (Ivalue, 30);
+ *aoffsetp += 32;
+ break;
+ }
+ return Ivalue;
+}
- if (Adrmod_is_index (addr_mode))
- {
- aoffset += 8;
- index_offset[0] = aoffset;
- }
- }
- if (d[2] && Is_gen(d[3]))
- {
- int addr_mode = bit_extract (buffer, ioffset - 10, 5);
+#if 1 /* A version that should work on ns32k f's&d's on any machine. */
+static int
+invalid_float (bfd_byte *p, int len)
+{
+ int val;
+
+ if (len == 4)
+ val = (bit_extract_simple (p, 23, 8)/*exponent*/ == 0xff
+ || (bit_extract_simple (p, 23, 8)/*exponent*/ == 0
+ && bit_extract_simple (p, 0, 23)/*mantisa*/ != 0));
+ else if (len == 8)
+ val = (bit_extract_simple (p, 52, 11)/*exponent*/ == 0x7ff
+ || (bit_extract_simple (p, 52, 11)/*exponent*/ == 0
+ && (bit_extract_simple (p, 0, 32)/*low mantisa*/ != 0
+ || bit_extract_simple (p, 32, 20)/*high mantisa*/ != 0)));
+ else
+ val = 1;
+ return (val);
+}
+#else
+/* Assumes the bytes have been swapped to local order. */
+typedef union
+{
+ double d;
+ float f;
+ struct { unsigned m:23, e:8, :1;} sf;
+ struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
+} float_type_u;
- if (Adrmod_is_index (addr_mode))
- {
- aoffset += 8;
- index_offset[1] = aoffset;
- }
- }
+static int
+invalid_float (float_type_u *p, int len)
+{
+ int val;
- while (*d)
- {
- argnum = *d - '1';
- d++;
- if (argnum > maxarg && argnum < MAX_ARGS)
- maxarg = argnum;
- ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
- memaddr, arg_bufs[argnum],
- index_offset[whicharg]);
- d++;
- whicharg++;
- }
- for (argnum = 0; argnum <= maxarg; argnum++)
- {
- bfd_vma addr;
- char *ch;
- for (ch = arg_bufs[argnum]; *ch;)
- {
- if (*ch == NEXT_IS_ADDR)
- {
- ++ch;
- addr = bfd_scan_vma (ch, NULL, 16);
- (*dis_info->print_address_func) (addr, dis_info);
- while (*ch && *ch != NEXT_IS_ADDR)
- ++ch;
- if (*ch)
- ++ch;
- }
- else
- (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
- }
- if (argnum < maxarg)
- (*dis_info->fprintf_func)(dis_info->stream, ", ");
- }
- }
- return aoffset / 8;
+ if (len == sizeof (float))
+ val = (p->sf.e == 0xff
+ || (p->sf.e == 0 && p->sf.m != 0));
+ else if (len == sizeof (double))
+ val = (p->sd.e == 0x7ff
+ || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
+ else
+ val = 1;
+ return val;
}
+#endif
/* Print an instruction operand of category given by d. IOFFSET is
the bit position below which small (<1 byte) parts of the operand can
general operand using scaled indexed addressing mode). */
static int
-print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset)
- int d;
- int ioffset, *aoffsetp;
- bfd_byte *buffer;
- bfd_vma addr;
- char *result;
- int index_offset;
+print_insn_arg (int d,
+ int ioffset,
+ int *aoffsetp,
+ bfd_byte *buffer,
+ bfd_vma addr,
+ char *result,
+ int index_offset)
{
- union {
+ union
+ {
float f;
double d;
int i[2];
int Ivalue;
int addr_mode;
int disp1, disp2;
- int index;
int size;
switch (d)
{
case 'f':
- /* a "gen" operand but 5 bits from the end of instruction */
+ /* A "gen" operand but 5 bits from the end of instruction. */
ioffset -= 5;
case 'Z':
case 'F':
case 'W':
case 'D':
case 'A':
- addr_mode = bit_extract (buffer, ioffset-5, 5);
+ addr_mode = bit_extract (buffer, ioffset - 5, 5);
ioffset -= 5;
switch (addr_mode)
{
case 0x0: case 0x1: case 0x2: case 0x3:
case 0x4: case 0x5: case 0x6: case 0x7:
- /* register mode R0 -- R7 */
+ /* Register mode R0 -- R7. */
switch (d)
{
case 'F':
break;
case 0x8: case 0x9: case 0xa: case 0xb:
case 0xc: case 0xd: case 0xe: case 0xf:
- /* Register relative disp(R0 -- R7) */
+ /* Register relative disp(R0 -- R7). */
disp1 = get_displacement (buffer, aoffsetp);
sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
break;
case 0x10:
case 0x11:
case 0x12:
- /* Memory relative disp2(disp1(FP, SP, SB)) */
+ /* Memory relative disp2(disp1(FP, SP, SB)). */
disp1 = get_displacement (buffer, aoffsetp);
disp2 = get_displacement (buffer, aoffsetp);
sprintf (result, "%d(%d(%s))", disp2, disp1,
- addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
+ addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
break;
case 0x13:
- /* reserved */
+ /* Reserved. */
sprintf (result, "reserved");
break;
case 0x14:
- /* Immediate */
+ /* Immediate. */
switch (d)
{
- case 'I': case 'Z': case 'A':
+ case 'I':
+ case 'Z':
+ case 'A':
/* I and Z are output operands and can`t be immediate
- * A is an address and we can`t have the address of
- * an immediate either. We don't know how much to increase
- * aoffsetp by since whatever generated this is broken
- * anyway!
- */
+ A is an address and we can`t have the address of
+ an immediate either. We don't know how much to increase
+ aoffsetp by since whatever generated this is broken
+ anyway! */
sprintf (result, _("$<undefined>"));
break;
case 'B':
*aoffsetp += 32;
if (INVALID_FLOAT (&value.f, 4))
sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
- else /* assume host has ieee float */
+ else /* Assume host has ieee float. */
sprintf (result, "$%g", value.f);
break;
case 'L':
if (INVALID_FLOAT (&value.d, 8))
sprintf (result, "<<invalid double 0x%.8x%.8x>>",
value.i[1], value.i[0]);
- else /* assume host has ieee float */
+ else /* Assume host has ieee float. */
sprintf (result, "$%g", value.d);
break;
}
break;
case 0x15:
- /* Absolute @disp */
+ /* Absolute @disp. */
disp1 = get_displacement (buffer, aoffsetp);
sprintf (result, "@|%d|", disp1);
break;
case 0x16:
- /* External EXT(disp1) + disp2 (Mod table stuff) */
+ /* External EXT(disp1) + disp2 (Mod table stuff). */
disp1 = get_displacement (buffer, aoffsetp);
disp2 = get_displacement (buffer, aoffsetp);
sprintf (result, "EXT(%d) + %d", disp1, disp2);
break;
case 0x17:
- /* Top of stack tos */
+ /* Top of stack tos. */
sprintf (result, "tos");
break;
case 0x18:
- /* Memory space disp(FP) */
+ /* Memory space disp(FP). */
disp1 = get_displacement (buffer, aoffsetp);
sprintf (result, "%d(fp)", disp1);
break;
case 0x19:
- /* Memory space disp(SP) */
+ /* Memory space disp(SP). */
disp1 = get_displacement (buffer, aoffsetp);
sprintf (result, "%d(sp)", disp1);
break;
case 0x1a:
- /* Memory space disp(SB) */
+ /* Memory space disp(SB). */
disp1 = get_displacement (buffer, aoffsetp);
sprintf (result, "%d(sb)", disp1);
break;
case 0x1b:
- /* Memory space disp(PC) */
+ /* Memory space disp(PC). */
disp1 = get_displacement (buffer, aoffsetp);
*result++ = NEXT_IS_ADDR;
sprintf_vma (result, addr + disp1);
case 0x1d:
case 0x1e:
case 0x1f:
- /* Scaled index basemode[R0 -- R7:B,W,D,Q] */
- index = bit_extract (buffer, index_offset - 8, 3);
- print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
- result, 0);
{
+ int bit_index;
static const char *ind = "bwdq";
char *off;
-
+
+ /* Scaled index basemode[R0 -- R7:B,W,D,Q]. */
+ bit_index = bit_extract (buffer, index_offset - 8, 3);
+ print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
+ result, 0);
off = result + strlen (result);
- sprintf (off, "[r%d:%c]", index,
- ind[addr_mode & 3]);
+ sprintf (off, "[r%d:%c]", bit_index, ind[addr_mode & 3]);
}
break;
}
break;
case 'b':
Ivalue = get_displacement (buffer, aoffsetp);
- /*
- * Warning!! HACK ALERT!
- * Operand type 'b' is only used by the cmp{b,w,d} and
- * movm{b,w,d} instructions; we need to know whether
- * it's a `b' or `w' or `d' instruction; and for both
- * cmpm and movm it's stored at the same place so we
- * just grab two bits of the opcode and look at it...
- *
- */
+ /* Warning!! HACK ALERT!
+ Operand type 'b' is only used by the cmp{b,w,d} and
+ movm{b,w,d} instructions; we need to know whether
+ it's a `b' or `w' or `d' instruction; and for both
+ cmpm and movm it's stored at the same place so we
+ just grab two bits of the opcode and look at it... */
size = bit_extract(buffer, ioffset-6, 2);
- if (size == 0) /* 00 => b */
+ if (size == 0) /* 00 => b. */
size = 1;
- else if (size == 1) /* 01 => w */
+ else if (size == 1) /* 01 => w. */
size = 2;
else
- size = 4; /* 11 => d */
+ size = 4; /* 11 => d. */
sprintf (result, "%d", (Ivalue / size) + 1);
break;
break;
case 'u':
Ivalue = bit_extract (buffer, *aoffsetp, 8);
- optlist(Ivalue, opt_u, result);
+ optlist (Ivalue, opt_u, result);
*aoffsetp += 8;
break;
case 'U':
- Ivalue = bit_extract(buffer, *aoffsetp, 8);
- optlist(Ivalue, opt_U, result);
+ Ivalue = bit_extract (buffer, *aoffsetp, 8);
+ optlist (Ivalue, opt_U, result);
*aoffsetp += 8;
break;
case 'O':
- Ivalue = bit_extract(buffer, ioffset-9, 9);
- optlist(Ivalue, opt_O, result);
+ Ivalue = bit_extract (buffer, ioffset - 9, 9);
+ optlist (Ivalue, opt_O, result);
ioffset -= 9;
break;
case 'C':
- Ivalue = bit_extract(buffer, ioffset-4, 4);
- optlist(Ivalue, opt_C, result);
+ Ivalue = bit_extract (buffer, ioffset - 4, 4);
+ optlist (Ivalue, opt_C, result);
ioffset -= 4;
break;
case 'S':
- Ivalue = bit_extract(buffer, ioffset - 8, 8);
- optlist(Ivalue, opt_S, result);
+ Ivalue = bit_extract (buffer, ioffset - 8, 8);
+ optlist (Ivalue, opt_S, result);
ioffset -= 8;
break;
case 'M':
- Ivalue = bit_extract(buffer, ioffset-4, 4);
- list_search(Ivalue, 0 ? list_M032 : list_M532, result);
+ Ivalue = bit_extract (buffer, ioffset - 4, 4);
+ list_search (Ivalue, 0 ? list_M032 : list_M532, result);
ioffset -= 4;
break;
case 'P':
- Ivalue = bit_extract(buffer, ioffset-4, 4);
- list_search(Ivalue, 0 ? list_P032 : list_P532, result);
+ Ivalue = bit_extract (buffer, ioffset - 4, 4);
+ list_search (Ivalue, 0 ? list_P032 : list_P532, result);
ioffset -= 4;
break;
case 'g':
- Ivalue = bit_extract(buffer, *aoffsetp, 3);
- sprintf(result, "%d", Ivalue);
+ Ivalue = bit_extract (buffer, *aoffsetp, 3);
+ sprintf (result, "%d", Ivalue);
*aoffsetp += 3;
break;
case 'G':
Ivalue = bit_extract(buffer, *aoffsetp, 5);
- sprintf(result, "%d", Ivalue + 1);
+ sprintf (result, "%d", Ivalue + 1);
*aoffsetp += 5;
break;
}
return ioffset;
}
-static int
-get_displacement (buffer, aoffsetp)
- bfd_byte *buffer;
- int *aoffsetp;
+\f
+/* Print the 32000 instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
{
- int Ivalue;
- short Ivalue2;
+ unsigned int i;
+ const char *d;
+ unsigned short first_word;
+ int ioffset; /* Bits into instruction. */
+ int aoffset; /* Bits into arguments. */
+ char arg_bufs[MAX_ARGS+1][ARG_LEN];
+ int argnum;
+ int maxarg;
+ struct private priv;
+ bfd_byte *buffer = priv.the_buffer;
+ dis_info = info;
- Ivalue = bit_extract (buffer, *aoffsetp, 8);
- switch (Ivalue & 0xc0)
- {
- case 0x00:
- case 0x40:
- Ivalue = sign_extend (Ivalue, 7);
- *aoffsetp += 8;
- break;
- case 0x80:
- Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
- flip_bytes ((char *) & Ivalue2, 2);
- Ivalue = sign_extend (Ivalue2, 14);
- *aoffsetp += 16;
- break;
- case 0xc0:
- Ivalue = bit_extract (buffer, *aoffsetp, 32);
- flip_bytes ((char *) & Ivalue, 4);
- Ivalue = sign_extend (Ivalue, 30);
- *aoffsetp += 32;
+ info->private_data = & priv;
+ priv.max_fetched = priv.the_buffer;
+ priv.insn_start = memaddr;
+ if (OPCODES_SIGSETJMP (priv.bailout) != 0)
+ /* Error return. */
+ return -1;
+
+ /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
+ us over the end of accessible data unnecessarilly. */
+ FETCH_DATA (info, buffer + 1);
+ for (i = 0; i < NOPCODES; i++)
+ if (ns32k_opcodes[i].opcode_id_size <= 8
+ && ((buffer[0]
+ & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
+ == ns32k_opcodes[i].opcode_seed))
break;
+ if (i == NOPCODES)
+ {
+ /* Maybe it is 9 to 16 bits big. */
+ FETCH_DATA (info, buffer + 2);
+ first_word = read_memory_integer(buffer, 2);
+
+ for (i = 0; i < NOPCODES; i++)
+ if ((first_word
+ & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
+ == ns32k_opcodes[i].opcode_seed)
+ break;
+
+ /* Handle undefined instructions. */
+ if (i == NOPCODES)
+ {
+ (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
+ return 1;
+ }
}
- return Ivalue;
-}
-\f
-#if 1 /* a version that should work on ns32k f's&d's on any machine */
-static int
-invalid_float (p, len)
- register bfd_byte *p;
- register int len;
-{
- register int val;
-
- if ( len == 4 )
- val = (bit_extract_simple(p, 23, 8)/*exponent*/ == 0xff
- || (bit_extract_simple(p, 23, 8)/*exponent*/ == 0 &&
- bit_extract_simple(p, 0, 23)/*mantisa*/ != 0));
- else if ( len == 8 )
- val = (bit_extract_simple(p, 52, 11)/*exponent*/ == 0x7ff
- || (bit_extract_simple(p, 52, 11)/*exponent*/ == 0
- && (bit_extract_simple(p, 0, 32)/*low mantisa*/ != 0
- || bit_extract_simple(p, 32, 20)/*high mantisa*/ != 0)));
- else
- val = 1;
- return (val);
-}
-#else
+ (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
-/* assumes the bytes have been swapped to local order */
-typedef union { double d;
- float f;
- struct { unsigned m:23, e:8, :1;} sf;
- struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
- } float_type_u;
+ ioffset = ns32k_opcodes[i].opcode_size;
+ aoffset = ns32k_opcodes[i].opcode_size;
+ d = ns32k_opcodes[i].operands;
-static int
-invalid_float (p, len)
- register float_type_u *p;
- register int len;
-{
- register int val;
- if ( len == sizeof (float) )
- val = (p->sf.e == 0xff
- || (p->sf.e == 0 && p->sf.m != 0));
- else if ( len == sizeof (double) )
- val = (p->sd.e == 0x7ff
- || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
- else
- val = 1;
- return (val);
+ if (*d)
+ {
+ /* Offset in bits of the first thing beyond each index byte.
+ Element 0 is for operand A and element 1 is for operand B.
+ The rest are irrelevant, but we put them here so we don't
+ index outside the array. */
+ int index_offset[MAX_ARGS];
+
+ /* 0 for operand A, 1 for operand B, greater for other args. */
+ int whicharg = 0;
+
+ (*dis_info->fprintf_func)(dis_info->stream, "\t");
+
+ maxarg = 0;
+
+ /* First we have to find and keep track of the index bytes,
+ if we are using scaled indexed addressing mode, since the index
+ bytes occur right after the basic instruction, not as part
+ of the addressing extension. */
+ if (Is_gen(d[1]))
+ {
+ int addr_mode = bit_extract (buffer, ioffset - 5, 5);
+
+ if (Adrmod_is_index (addr_mode))
+ {
+ aoffset += 8;
+ index_offset[0] = aoffset;
+ }
+ }
+
+ if (d[2] && Is_gen(d[3]))
+ {
+ int addr_mode = bit_extract (buffer, ioffset - 10, 5);
+
+ if (Adrmod_is_index (addr_mode))
+ {
+ aoffset += 8;
+ index_offset[1] = aoffset;
+ }
+ }
+
+ while (*d)
+ {
+ argnum = *d - '1';
+ d++;
+ if (argnum > maxarg && argnum < MAX_ARGS)
+ maxarg = argnum;
+ ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
+ memaddr, arg_bufs[argnum],
+ index_offset[whicharg]);
+ d++;
+ whicharg++;
+ }
+ for (argnum = 0; argnum <= maxarg; argnum++)
+ {
+ bfd_vma addr;
+ char *ch;
+
+ for (ch = arg_bufs[argnum]; *ch;)
+ {
+ if (*ch == NEXT_IS_ADDR)
+ {
+ ++ch;
+ addr = bfd_scan_vma (ch, NULL, 16);
+ (*dis_info->print_address_func) (addr, dis_info);
+ while (*ch && *ch != NEXT_IS_ADDR)
+ ++ch;
+ if (*ch)
+ ++ch;
+ }
+ else
+ (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
+ }
+ if (argnum < maxarg)
+ (*dis_info->fprintf_func)(dis_info->stream, ", ");
+ }
+ }
+ return aoffset / 8;
}
-#endif