diff options
Diffstat (limited to 'opcodes/ns32k-dis.c')
-rw-r--r-- | opcodes/ns32k-dis.c | 737 |
1 files changed, 349 insertions, 388 deletions
diff --git a/opcodes/ns32k-dis.c b/opcodes/ns32k-dis.c index a7bcbc4..7ed4ab2 100644 --- a/opcodes/ns32k-dis.c +++ b/opcodes/ns32k-dis.c @@ -2,21 +2,22 @@ Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005 Free Software Foundation, Inc. -This file is part of opcodes library. + This file is part of 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 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 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. + 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. -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. */ + 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" @@ -30,43 +31,26 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 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 @@ -87,12 +71,10 @@ struct private ? 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, @@ -108,20 +90,22 @@ fetch_data (info, addr) 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 '|' -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. */ }; -static const struct ns32k_option opt_u[]= /* restore, exit */ +static const struct ns32k_option opt_u[]= /* Restore, exit. */ { { "r0", 0x80, 0x80 }, { "r1", 0x40, 0x40 }, @@ -134,7 +118,7 @@ static const struct ns32k_option opt_u[]= /* restore, exit */ { 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 }, @@ -147,7 +131,7 @@ static const struct ns32k_option opt_U[]= /* save, enter */ { 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 }, @@ -156,7 +140,7 @@ static const struct ns32k_option opt_O[]= /* setcfg */ { 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 }, @@ -164,7 +148,7 @@ static const struct ns32k_option opt_C[]= /* cinv */ { 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 }, @@ -172,7 +156,7 @@ static const struct ns32k_option opt_S[]= /* string inst */ { 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 }, @@ -190,7 +174,7 @@ static const struct ns32k_option list_P532[]= /* lpr spr */ { 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 }, @@ -202,7 +186,7 @@ static const struct ns32k_option list_M532[]= /* lmr smr */ { 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 }, @@ -214,7 +198,7 @@ static const struct ns32k_option list_P032[]= /* lpr spr */ { 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 }, @@ -230,61 +214,55 @@ static const struct ns32k_option list_M032[]= /* lmr smr */ }; -/* - * 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"); } -/* - * 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; @@ -295,7 +273,7 @@ bit_extract (buffer, offset, count) 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) @@ -308,14 +286,10 @@ bit_extract (buffer, offset, count) 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; @@ -339,40 +313,32 @@ bit_extract_simple (buffer, offset, count) } 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; } @@ -384,158 +350,94 @@ flip_bytes (ptr, count) || (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) -/* 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 @@ -548,15 +450,16 @@ print_insn_ns32k (memaddr, info) 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]; @@ -570,7 +473,7 @@ print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset) 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': @@ -580,13 +483,13 @@ print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset) 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': @@ -600,34 +503,35 @@ print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset) 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': @@ -655,7 +559,7 @@ print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset) *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': @@ -665,43 +569,43 @@ print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset) 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); @@ -713,7 +617,7 @@ print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset) case 0x1d: case 0x1e: case 0x1f: - /* Scaled index basemode[R0 -- R7:B,W,D,Q] */ + /* 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); @@ -745,22 +649,19 @@ print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset) 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; @@ -778,130 +679,190 @@ print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset) 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; + +/* 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 (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; + } } - return Ivalue; -} - -#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 |