12159047fSniklas /* Print National Semiconductor 32000 instructions.
2*c074d1c9Sdrahn Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002
3b55d4692Sfgsch Free Software Foundation, Inc.
42159047fSniklas
52159047fSniklas This file is part of opcodes library.
62159047fSniklas
72159047fSniklas This program is free software; you can redistribute it and/or modify
82159047fSniklas it under the terms of the GNU General Public License as published by
92159047fSniklas the Free Software Foundation; either version 2 of the License, or
102159047fSniklas (at your option) any later version.
112159047fSniklas
122159047fSniklas This program is distributed in the hope that it will be useful,
132159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
142159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
152159047fSniklas GNU General Public License for more details.
162159047fSniklas
172159047fSniklas You should have received a copy of the GNU General Public License
182159047fSniklas along with this program; if not, write to the Free Software
192159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
202159047fSniklas
212159047fSniklas
222159047fSniklas #include "bfd.h"
232159047fSniklas #include "sysdep.h"
242159047fSniklas #include "dis-asm.h"
252159047fSniklas #if !defined(const) && !defined(__STDC__)
262159047fSniklas #define const
272159047fSniklas #endif
282159047fSniklas #include "opcode/ns32k.h"
29f7cc78ecSespie #include "opintl.h"
302159047fSniklas
312159047fSniklas static disassemble_info *dis_info;
322159047fSniklas
332159047fSniklas /*
342159047fSniklas * Hacks to get it to compile <= READ THESE AS FIXES NEEDED
352159047fSniklas */
362159047fSniklas #define INVALID_FLOAT(val, size) invalid_float((char *)val, size)
372159047fSniklas
38f7cc78ecSespie static int print_insn_arg
39f7cc78ecSespie PARAMS ((int, int, int *, char *, bfd_vma, char *, int));
40f7cc78ecSespie static int get_displacement PARAMS ((char *, int *));
41f7cc78ecSespie static int invalid_float PARAMS ((char *, int));
42*c074d1c9Sdrahn static long int read_memory_integer PARAMS ((unsigned char *, int));
43*c074d1c9Sdrahn static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
44*c074d1c9Sdrahn struct ns32k_option;
45*c074d1c9Sdrahn static void optlist PARAMS ((int, const struct ns32k_option *, char *));
46*c074d1c9Sdrahn static void list_search PARAMS ((int, const struct ns32k_option *, char *));
47*c074d1c9Sdrahn static int bit_extract PARAMS ((bfd_byte *, int, int));
48*c074d1c9Sdrahn static int bit_extract_simple PARAMS ((bfd_byte *, int, int));
49*c074d1c9Sdrahn static void bit_copy PARAMS ((char *, int, int, char *));
50*c074d1c9Sdrahn static int sign_extend PARAMS ((int, int));
51*c074d1c9Sdrahn static void flip_bytes PARAMS ((char *, int));
52f7cc78ecSespie
read_memory_integer(addr,nr)532159047fSniklas static long read_memory_integer(addr, nr)
542159047fSniklas unsigned char *addr;
552159047fSniklas int nr;
562159047fSniklas {
572159047fSniklas long val;
582159047fSniklas int i;
592159047fSniklas for (val = 0, i = nr - 1; i >= 0; i--) {
602159047fSniklas val = (val << 8);
612159047fSniklas val |= (0xff & *(addr + i));
622159047fSniklas }
632159047fSniklas return val;
642159047fSniklas }
652159047fSniklas
662159047fSniklas /* 32000 instructions are never longer than this. */
672159047fSniklas #define MAXLEN 62
682159047fSniklas
692159047fSniklas
702159047fSniklas #include <setjmp.h>
712159047fSniklas
722159047fSniklas struct private
732159047fSniklas {
742159047fSniklas /* Points to first byte not fetched. */
752159047fSniklas bfd_byte *max_fetched;
762159047fSniklas bfd_byte the_buffer[MAXLEN];
772159047fSniklas bfd_vma insn_start;
782159047fSniklas jmp_buf bailout;
792159047fSniklas };
802159047fSniklas
812159047fSniklas
822159047fSniklas /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
832159047fSniklas to ADDR (exclusive) are valid. Returns 1 for success, longjmps
842159047fSniklas on error. */
852159047fSniklas #define FETCH_DATA(info, addr) \
862159047fSniklas ((addr) <= ((struct private *)(info->private_data))->max_fetched \
872159047fSniklas ? 1 : fetch_data ((info), (addr)))
882159047fSniklas
892159047fSniklas static int
fetch_data(info,addr)902159047fSniklas fetch_data (info, addr)
912159047fSniklas struct disassemble_info *info;
922159047fSniklas bfd_byte *addr;
932159047fSniklas {
942159047fSniklas int status;
952159047fSniklas struct private *priv = (struct private *)info->private_data;
962159047fSniklas bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
972159047fSniklas
982159047fSniklas status = (*info->read_memory_func) (start,
992159047fSniklas priv->max_fetched,
1002159047fSniklas addr - priv->max_fetched,
1012159047fSniklas info);
1022159047fSniklas if (status != 0)
1032159047fSniklas {
1042159047fSniklas (*info->memory_error_func) (status, start, info);
1052159047fSniklas longjmp (priv->bailout, 1);
1062159047fSniklas }
1072159047fSniklas else
1082159047fSniklas priv->max_fetched = addr;
1092159047fSniklas return 1;
1102159047fSniklas }
1112159047fSniklas /* Number of elements in the opcode table. */
1122159047fSniklas #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
1132159047fSniklas
1142159047fSniklas #define NEXT_IS_ADDR '|'
1152159047fSniklas
1162159047fSniklas
1172159047fSniklas struct ns32k_option {
1182159047fSniklas char *pattern; /* the option itself */
1192159047fSniklas unsigned long value; /* binary value of the option */
1202159047fSniklas unsigned long match; /* these bits must match */
1212159047fSniklas };
1222159047fSniklas
1232159047fSniklas
1242159047fSniklas static const struct ns32k_option opt_u[]= /* restore, exit */
1252159047fSniklas {
1262159047fSniklas { "r0", 0x80, 0x80 },
1272159047fSniklas { "r1", 0x40, 0x40 },
1282159047fSniklas { "r2", 0x20, 0x20 },
1292159047fSniklas { "r3", 0x10, 0x10 },
1302159047fSniklas { "r4", 0x08, 0x08 },
1312159047fSniklas { "r5", 0x04, 0x04 },
1322159047fSniklas { "r6", 0x02, 0x02 },
1332159047fSniklas { "r7", 0x01, 0x01 },
1342159047fSniklas { 0 , 0x00, 0x00 }
1352159047fSniklas };
1362159047fSniklas
1372159047fSniklas static const struct ns32k_option opt_U[]= /* save, enter */
1382159047fSniklas {
1392159047fSniklas { "r0", 0x01, 0x01 },
1402159047fSniklas { "r1", 0x02, 0x02 },
1412159047fSniklas { "r2", 0x04, 0x04 },
1422159047fSniklas { "r3", 0x08, 0x08 },
1432159047fSniklas { "r4", 0x10, 0x10 },
1442159047fSniklas { "r5", 0x20, 0x20 },
1452159047fSniklas { "r6", 0x40, 0x40 },
1462159047fSniklas { "r7", 0x80, 0x80 },
1472159047fSniklas { 0 , 0x00, 0x00 }
1482159047fSniklas };
1492159047fSniklas
1502159047fSniklas static const struct ns32k_option opt_O[]= /* setcfg */
1512159047fSniklas {
1522159047fSniklas { "c", 0x8, 0x8 },
1532159047fSniklas { "m", 0x4, 0x4 },
1542159047fSniklas { "f", 0x2, 0x2 },
1552159047fSniklas { "i", 0x1, 0x1 },
1562159047fSniklas { 0 , 0x0, 0x0 }
1572159047fSniklas };
1582159047fSniklas
1592159047fSniklas static const struct ns32k_option opt_C[]= /* cinv */
1602159047fSniklas {
1612159047fSniklas { "a", 0x4, 0x4 },
1622159047fSniklas { "i", 0x2, 0x2 },
1632159047fSniklas { "d", 0x1, 0x1 },
1642159047fSniklas { 0 , 0x0, 0x0 }
1652159047fSniklas };
1662159047fSniklas
1672159047fSniklas static const struct ns32k_option opt_S[]= /* string inst */
1682159047fSniklas {
1692159047fSniklas { "b", 0x1, 0x1 },
1702159047fSniklas { "u", 0x6, 0x6 },
1712159047fSniklas { "w", 0x2, 0x2 },
1722159047fSniklas { 0 , 0x0, 0x0 }
1732159047fSniklas };
1742159047fSniklas
1752159047fSniklas static const struct ns32k_option list_P532[]= /* lpr spr */
1762159047fSniklas {
1772159047fSniklas { "us", 0x0, 0xf },
1782159047fSniklas { "dcr", 0x1, 0xf },
1792159047fSniklas { "bpc", 0x2, 0xf },
1802159047fSniklas { "dsr", 0x3, 0xf },
1812159047fSniklas { "car", 0x4, 0xf },
1822159047fSniklas { "fp", 0x8, 0xf },
1832159047fSniklas { "sp", 0x9, 0xf },
1842159047fSniklas { "sb", 0xa, 0xf },
1852159047fSniklas { "usp", 0xb, 0xf },
1862159047fSniklas { "cfg", 0xc, 0xf },
1872159047fSniklas { "psr", 0xd, 0xf },
1882159047fSniklas { "intbase", 0xe, 0xf },
1892159047fSniklas { "mod", 0xf, 0xf },
1902159047fSniklas { 0 , 0x00, 0xf }
1912159047fSniklas };
1922159047fSniklas
1932159047fSniklas static const struct ns32k_option list_M532[]= /* lmr smr */
1942159047fSniklas {
1952159047fSniklas { "mcr", 0x9, 0xf },
1962159047fSniklas { "msr", 0xa, 0xf },
1972159047fSniklas { "tear", 0xb, 0xf },
1982159047fSniklas { "ptb0", 0xc, 0xf },
1992159047fSniklas { "ptb1", 0xd, 0xf },
2002159047fSniklas { "ivar0", 0xe, 0xf },
2012159047fSniklas { "ivar1", 0xf, 0xf },
2022159047fSniklas { 0 , 0x0, 0xf }
2032159047fSniklas };
2042159047fSniklas
2052159047fSniklas static const struct ns32k_option list_P032[]= /* lpr spr */
2062159047fSniklas {
2072159047fSniklas { "upsr", 0x0, 0xf },
2082159047fSniklas { "fp", 0x8, 0xf },
2092159047fSniklas { "sp", 0x9, 0xf },
2102159047fSniklas { "sb", 0xa, 0xf },
2112159047fSniklas { "psr", 0xb, 0xf },
2122159047fSniklas { "intbase", 0xe, 0xf },
2132159047fSniklas { "mod", 0xf, 0xf },
2142159047fSniklas { 0 , 0x0, 0xf }
2152159047fSniklas };
2162159047fSniklas
2172159047fSniklas static const struct ns32k_option list_M032[]= /* lmr smr */
2182159047fSniklas {
2192159047fSniklas { "bpr0", 0x0, 0xf },
2202159047fSniklas { "bpr1", 0x1, 0xf },
2212159047fSniklas { "pf0", 0x4, 0xf },
2222159047fSniklas { "pf1", 0x5, 0xf },
2232159047fSniklas { "sc", 0x8, 0xf },
2242159047fSniklas { "msr", 0xa, 0xf },
2252159047fSniklas { "bcnt", 0xb, 0xf },
2262159047fSniklas { "ptb0", 0xc, 0xf },
2272159047fSniklas { "ptb1", 0xd, 0xf },
2282159047fSniklas { "eia", 0xf, 0xf },
2292159047fSniklas { 0 , 0x0, 0xf }
2302159047fSniklas };
2312159047fSniklas
2322159047fSniklas
2332159047fSniklas /*
2342159047fSniklas * figure out which options are present
2352159047fSniklas */
2362159047fSniklas static void
optlist(options,optionP,result)2372159047fSniklas optlist(options, optionP, result)
2382159047fSniklas int options;
2392159047fSniklas const struct ns32k_option *optionP;
2402159047fSniklas char *result;
2412159047fSniklas {
2422159047fSniklas if (options == 0) {
2432159047fSniklas sprintf(result, "[]");
2442159047fSniklas return;
2452159047fSniklas }
2462159047fSniklas sprintf(result, "[");
2472159047fSniklas
2482159047fSniklas for (; (options != 0) && optionP->pattern; optionP++) {
2492159047fSniklas if ((options & optionP->match) == optionP->value) {
2502159047fSniklas /* we found a match, update result and options */
2512159047fSniklas strcat(result, optionP->pattern);
2522159047fSniklas options &= ~optionP->value;
2532159047fSniklas if (options != 0) /* more options to come */
2542159047fSniklas strcat(result, ",");
2552159047fSniklas }
2562159047fSniklas }
2572159047fSniklas if (options != 0)
2582159047fSniklas strcat(result, "undefined");
2592159047fSniklas
2602159047fSniklas strcat(result, "]");
2612159047fSniklas }
2622159047fSniklas
263f7cc78ecSespie static void
list_search(reg_value,optionP,result)264f7cc78ecSespie list_search (reg_value, optionP, result)
2652159047fSniklas int reg_value;
2662159047fSniklas const struct ns32k_option *optionP;
2672159047fSniklas char *result;
2682159047fSniklas {
2692159047fSniklas for (; optionP->pattern; optionP++) {
2702159047fSniklas if ((reg_value & optionP->match) == optionP->value) {
2712159047fSniklas sprintf(result, "%s", optionP->pattern);
2722159047fSniklas return;
2732159047fSniklas }
2742159047fSniklas }
2752159047fSniklas sprintf(result, "undefined");
2762159047fSniklas }
2772159047fSniklas
2782159047fSniklas /*
2792159047fSniklas * extract "count" bits starting "offset" bits
2802159047fSniklas * into buffer
2812159047fSniklas */
2822159047fSniklas
2832159047fSniklas static int
bit_extract(buffer,offset,count)2842159047fSniklas bit_extract (buffer, offset, count)
2852159047fSniklas bfd_byte *buffer;
2862159047fSniklas int offset;
2872159047fSniklas int count;
2882159047fSniklas {
2892159047fSniklas int result;
2902159047fSniklas int bit;
2912159047fSniklas
2922159047fSniklas buffer += offset >> 3;
2932159047fSniklas offset &= 7;
2942159047fSniklas bit = 1;
2952159047fSniklas result = 0;
2962159047fSniklas while (count--)
2972159047fSniklas {
2982159047fSniklas FETCH_DATA(dis_info, buffer + 1);
2992159047fSniklas if ((*buffer & (1 << offset)))
3002159047fSniklas result |= bit;
3012159047fSniklas if (++offset == 8)
3022159047fSniklas {
3032159047fSniklas offset = 0;
3042159047fSniklas buffer++;
3052159047fSniklas }
3062159047fSniklas bit <<= 1;
3072159047fSniklas }
3082159047fSniklas return result;
3092159047fSniklas }
3102159047fSniklas
311f7cc78ecSespie /* Like bit extract but the buffer is valid and doen't need to be
312f7cc78ecSespie * fetched
313f7cc78ecSespie */
314f7cc78ecSespie static int
bit_extract_simple(buffer,offset,count)315f7cc78ecSespie bit_extract_simple (buffer, offset, count)
316f7cc78ecSespie bfd_byte *buffer;
317f7cc78ecSespie int offset;
318f7cc78ecSespie int count;
319f7cc78ecSespie {
320f7cc78ecSespie int result;
321f7cc78ecSespie int bit;
322f7cc78ecSespie
323f7cc78ecSespie buffer += offset >> 3;
324f7cc78ecSespie offset &= 7;
325f7cc78ecSespie bit = 1;
326f7cc78ecSespie result = 0;
327f7cc78ecSespie while (count--)
328f7cc78ecSespie {
329f7cc78ecSespie if ((*buffer & (1 << offset)))
330f7cc78ecSespie result |= bit;
331f7cc78ecSespie if (++offset == 8)
332f7cc78ecSespie {
333f7cc78ecSespie offset = 0;
334f7cc78ecSespie buffer++;
335f7cc78ecSespie }
336f7cc78ecSespie bit <<= 1;
337f7cc78ecSespie }
338f7cc78ecSespie return result;
339f7cc78ecSespie }
340f7cc78ecSespie
3412159047fSniklas static void
bit_copy(buffer,offset,count,to)3422159047fSniklas bit_copy (buffer, offset, count, to)
3432159047fSniklas char *buffer;
3442159047fSniklas int offset;
3452159047fSniklas int count;
3462159047fSniklas char *to;
3472159047fSniklas {
3482159047fSniklas for(; count > 8; count -= 8, to++, offset += 8)
3492159047fSniklas *to = bit_extract (buffer, offset, 8);
3502159047fSniklas *to = bit_extract (buffer, offset, count);
3512159047fSniklas }
3522159047fSniklas
3532159047fSniklas
354f7cc78ecSespie static int
sign_extend(value,bits)355f7cc78ecSespie sign_extend (value, bits)
3562159047fSniklas int value, bits;
3572159047fSniklas {
3582159047fSniklas value = value & ((1 << bits) - 1);
3592159047fSniklas return (value & (1 << (bits-1))
3602159047fSniklas ? value | (~((1 << bits) - 1))
3612159047fSniklas : value);
3622159047fSniklas }
3632159047fSniklas
364f7cc78ecSespie static void
flip_bytes(ptr,count)365f7cc78ecSespie flip_bytes (ptr, count)
3662159047fSniklas char *ptr;
3672159047fSniklas int count;
3682159047fSniklas {
3692159047fSniklas char tmp;
3702159047fSniklas
3712159047fSniklas while (count > 0)
3722159047fSniklas {
3732159047fSniklas tmp = ptr[0];
3742159047fSniklas ptr[0] = ptr[count-1];
3752159047fSniklas ptr[count-1] = tmp;
3762159047fSniklas ptr++;
3772159047fSniklas count -= 2;
3782159047fSniklas }
3792159047fSniklas }
3802159047fSniklas
3812159047fSniklas /* Given a character C, does it represent a general addressing mode? */
3822159047fSniklas #define Is_gen(c) \
3832159047fSniklas ((c) == 'F' || (c) == 'L' || (c) == 'B' \
3842159047fSniklas || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
3852159047fSniklas
3862159047fSniklas /* Adressing modes. */
3872159047fSniklas #define Adrmod_index_byte 0x1c
3882159047fSniklas #define Adrmod_index_word 0x1d
3892159047fSniklas #define Adrmod_index_doubleword 0x1e
3902159047fSniklas #define Adrmod_index_quadword 0x1f
3912159047fSniklas
3922159047fSniklas /* Is MODE an indexed addressing mode? */
3932159047fSniklas #define Adrmod_is_index(mode) \
3942159047fSniklas (mode == Adrmod_index_byte \
3952159047fSniklas || mode == Adrmod_index_word \
3962159047fSniklas || mode == Adrmod_index_doubleword \
3972159047fSniklas || mode == Adrmod_index_quadword)
3982159047fSniklas
3992159047fSniklas
4002159047fSniklas /* Print the 32000 instruction at address MEMADDR in debugged memory,
4012159047fSniklas on STREAM. Returns length of the instruction, in bytes. */
4022159047fSniklas
4032159047fSniklas int
print_insn_ns32k(memaddr,info)4042159047fSniklas print_insn_ns32k (memaddr, info)
4052159047fSniklas bfd_vma memaddr;
4062159047fSniklas disassemble_info *info;
4072159047fSniklas {
408*c074d1c9Sdrahn unsigned int i;
409*c074d1c9Sdrahn const char *d;
4102159047fSniklas unsigned short first_word;
4112159047fSniklas int ioffset; /* bits into instruction */
4122159047fSniklas int aoffset; /* bits into arguments */
4132159047fSniklas char arg_bufs[MAX_ARGS+1][ARG_LEN];
4142159047fSniklas int argnum;
4152159047fSniklas int maxarg;
4162159047fSniklas struct private priv;
4172159047fSniklas bfd_byte *buffer = priv.the_buffer;
4182159047fSniklas dis_info = info;
4192159047fSniklas
4202159047fSniklas info->private_data = (PTR) &priv;
4212159047fSniklas priv.max_fetched = priv.the_buffer;
4222159047fSniklas priv.insn_start = memaddr;
4232159047fSniklas if (setjmp (priv.bailout) != 0)
4242159047fSniklas /* Error return. */
4252159047fSniklas return -1;
4262159047fSniklas
4272159047fSniklas /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
4282159047fSniklas * us over the end of accessible data unnecessarilly
4292159047fSniklas */
4302159047fSniklas FETCH_DATA(info, buffer + 1);
4312159047fSniklas for (i = 0; i < NOPCODES; i++)
4322159047fSniklas if (ns32k_opcodes[i].opcode_id_size <= 8
433f7cc78ecSespie && ((buffer[0]
434f7cc78ecSespie & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
4352159047fSniklas == ns32k_opcodes[i].opcode_seed))
4362159047fSniklas break;
4372159047fSniklas if (i == NOPCODES) {
4382159047fSniklas /* Maybe it is 9 to 16 bits big */
4392159047fSniklas FETCH_DATA(info, buffer + 2);
4402159047fSniklas first_word = read_memory_integer(buffer, 2);
4412159047fSniklas
4422159047fSniklas for (i = 0; i < NOPCODES; i++)
443f7cc78ecSespie if ((first_word
444f7cc78ecSespie & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
4452159047fSniklas == ns32k_opcodes[i].opcode_seed)
4462159047fSniklas break;
4472159047fSniklas
4482159047fSniklas /* Handle undefined instructions. */
4492159047fSniklas if (i == NOPCODES)
4502159047fSniklas {
4512159047fSniklas (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
4522159047fSniklas return 1;
4532159047fSniklas }
4542159047fSniklas }
4552159047fSniklas
4562159047fSniklas (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
4572159047fSniklas
4582159047fSniklas ioffset = ns32k_opcodes[i].opcode_size;
4592159047fSniklas aoffset = ns32k_opcodes[i].opcode_size;
4602159047fSniklas d = ns32k_opcodes[i].operands;
4612159047fSniklas
4622159047fSniklas if (*d)
4632159047fSniklas {
4642159047fSniklas /* Offset in bits of the first thing beyond each index byte.
4652159047fSniklas Element 0 is for operand A and element 1 is for operand B.
4662159047fSniklas The rest are irrelevant, but we put them here so we don't
4672159047fSniklas index outside the array. */
4682159047fSniklas int index_offset[MAX_ARGS];
4692159047fSniklas
4702159047fSniklas /* 0 for operand A, 1 for operand B, greater for other args. */
4712159047fSniklas int whicharg = 0;
4722159047fSniklas
4732159047fSniklas (*dis_info->fprintf_func)(dis_info->stream, "\t");
4742159047fSniklas
4752159047fSniklas maxarg = 0;
4762159047fSniklas
4772159047fSniklas /* First we have to find and keep track of the index bytes,
4782159047fSniklas if we are using scaled indexed addressing mode, since the index
4792159047fSniklas bytes occur right after the basic instruction, not as part
4802159047fSniklas of the addressing extension. */
4812159047fSniklas if (Is_gen(d[1]))
4822159047fSniklas {
4832159047fSniklas int addr_mode = bit_extract (buffer, ioffset - 5, 5);
4842159047fSniklas
4852159047fSniklas if (Adrmod_is_index (addr_mode))
4862159047fSniklas {
4872159047fSniklas aoffset += 8;
4882159047fSniklas index_offset[0] = aoffset;
4892159047fSniklas }
4902159047fSniklas }
4912159047fSniklas if (d[2] && Is_gen(d[3]))
4922159047fSniklas {
4932159047fSniklas int addr_mode = bit_extract (buffer, ioffset - 10, 5);
4942159047fSniklas
4952159047fSniklas if (Adrmod_is_index (addr_mode))
4962159047fSniklas {
4972159047fSniklas aoffset += 8;
4982159047fSniklas index_offset[1] = aoffset;
4992159047fSniklas }
5002159047fSniklas }
5012159047fSniklas
5022159047fSniklas while (*d)
5032159047fSniklas {
5042159047fSniklas argnum = *d - '1';
5052159047fSniklas d++;
5062159047fSniklas if (argnum > maxarg && argnum < MAX_ARGS)
5072159047fSniklas maxarg = argnum;
5082159047fSniklas ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
5092159047fSniklas memaddr, arg_bufs[argnum],
5102159047fSniklas index_offset[whicharg]);
5112159047fSniklas d++;
5122159047fSniklas whicharg++;
5132159047fSniklas }
5142159047fSniklas for (argnum = 0; argnum <= maxarg; argnum++)
5152159047fSniklas {
516f7cc78ecSespie bfd_vma addr;
5172159047fSniklas char *ch;
5182159047fSniklas for (ch = arg_bufs[argnum]; *ch;)
5192159047fSniklas {
5202159047fSniklas if (*ch == NEXT_IS_ADDR)
5212159047fSniklas {
5222159047fSniklas ++ch;
523f7cc78ecSespie addr = bfd_scan_vma (ch, NULL, 16);
5242159047fSniklas (*dis_info->print_address_func) (addr, dis_info);
5252159047fSniklas while (*ch && *ch != NEXT_IS_ADDR)
5262159047fSniklas ++ch;
5272159047fSniklas if (*ch)
5282159047fSniklas ++ch;
5292159047fSniklas }
5302159047fSniklas else
5312159047fSniklas (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
5322159047fSniklas }
5332159047fSniklas if (argnum < maxarg)
5342159047fSniklas (*dis_info->fprintf_func)(dis_info->stream, ", ");
5352159047fSniklas }
5362159047fSniklas }
5372159047fSniklas return aoffset / 8;
5382159047fSniklas }
5392159047fSniklas
5402159047fSniklas /* Print an instruction operand of category given by d. IOFFSET is
5412159047fSniklas the bit position below which small (<1 byte) parts of the operand can
5422159047fSniklas be found (usually in the basic instruction, but for indexed
5432159047fSniklas addressing it can be in the index byte). AOFFSETP is a pointer to the
5442159047fSniklas bit position of the addressing extension. BUFFER contains the
5452159047fSniklas instruction. ADDR is where BUFFER was read from. Put the disassembled
5462159047fSniklas version of the operand in RESULT. INDEX_OFFSET is the bit position
5472159047fSniklas of the index byte (it contains garbage if this operand is not a
5482159047fSniklas general operand using scaled indexed addressing mode). */
5492159047fSniklas
550f7cc78ecSespie static int
print_insn_arg(d,ioffset,aoffsetp,buffer,addr,result,index_offset)5512159047fSniklas print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset)
552f7cc78ecSespie int d;
5532159047fSniklas int ioffset, *aoffsetp;
5542159047fSniklas char *buffer;
555f7cc78ecSespie bfd_vma addr;
5562159047fSniklas char *result;
5572159047fSniklas int index_offset;
5582159047fSniklas {
559*c074d1c9Sdrahn union {
560*c074d1c9Sdrahn float f;
561*c074d1c9Sdrahn double d;
562*c074d1c9Sdrahn int i[2];
563*c074d1c9Sdrahn } value;
5642159047fSniklas int Ivalue;
565*c074d1c9Sdrahn int addr_mode;
5662159047fSniklas int disp1, disp2;
5672159047fSniklas int index;
5682159047fSniklas int size;
5692159047fSniklas
5702159047fSniklas switch (d)
5712159047fSniklas {
5722159047fSniklas case 'f':
5732159047fSniklas /* a "gen" operand but 5 bits from the end of instruction */
5742159047fSniklas ioffset -= 5;
5752159047fSniklas case 'Z':
5762159047fSniklas case 'F':
5772159047fSniklas case 'L':
5782159047fSniklas case 'I':
5792159047fSniklas case 'B':
5802159047fSniklas case 'W':
5812159047fSniklas case 'D':
5822159047fSniklas case 'A':
5832159047fSniklas addr_mode = bit_extract (buffer, ioffset-5, 5);
5842159047fSniklas ioffset -= 5;
5852159047fSniklas switch (addr_mode)
5862159047fSniklas {
5872159047fSniklas case 0x0: case 0x1: case 0x2: case 0x3:
5882159047fSniklas case 0x4: case 0x5: case 0x6: case 0x7:
5892159047fSniklas /* register mode R0 -- R7 */
5902159047fSniklas switch (d)
5912159047fSniklas {
5922159047fSniklas case 'F':
5932159047fSniklas case 'L':
5942159047fSniklas case 'Z':
5952159047fSniklas sprintf (result, "f%d", addr_mode);
5962159047fSniklas break;
5972159047fSniklas default:
5982159047fSniklas sprintf (result, "r%d", addr_mode);
5992159047fSniklas }
6002159047fSniklas break;
6012159047fSniklas case 0x8: case 0x9: case 0xa: case 0xb:
6022159047fSniklas case 0xc: case 0xd: case 0xe: case 0xf:
6032159047fSniklas /* Register relative disp(R0 -- R7) */
6042159047fSniklas disp1 = get_displacement (buffer, aoffsetp);
6052159047fSniklas sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
6062159047fSniklas break;
6072159047fSniklas case 0x10:
6082159047fSniklas case 0x11:
6092159047fSniklas case 0x12:
6102159047fSniklas /* Memory relative disp2(disp1(FP, SP, SB)) */
6112159047fSniklas disp1 = get_displacement (buffer, aoffsetp);
6122159047fSniklas disp2 = get_displacement (buffer, aoffsetp);
6132159047fSniklas sprintf (result, "%d(%d(%s))", disp2, disp1,
6142159047fSniklas addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
6152159047fSniklas break;
6162159047fSniklas case 0x13:
6172159047fSniklas /* reserved */
6182159047fSniklas sprintf (result, "reserved");
6192159047fSniklas break;
6202159047fSniklas case 0x14:
6212159047fSniklas /* Immediate */
6222159047fSniklas switch (d)
6232159047fSniklas {
6242159047fSniklas case 'I': case 'Z': case 'A':
6252159047fSniklas /* I and Z are output operands and can`t be immediate
6262159047fSniklas * A is an address and we can`t have the address of
6272159047fSniklas * an immediate either. We don't know how much to increase
6282159047fSniklas * aoffsetp by since whatever generated this is broken
6292159047fSniklas * anyway!
6302159047fSniklas */
631f7cc78ecSespie sprintf (result, _("$<undefined>"));
6322159047fSniklas break;
6332159047fSniklas case 'B':
6342159047fSniklas Ivalue = bit_extract (buffer, *aoffsetp, 8);
6352159047fSniklas Ivalue = sign_extend (Ivalue, 8);
6362159047fSniklas *aoffsetp += 8;
6372159047fSniklas sprintf (result, "$%d", Ivalue);
6382159047fSniklas break;
6392159047fSniklas case 'W':
6402159047fSniklas Ivalue = bit_extract (buffer, *aoffsetp, 16);
641*c074d1c9Sdrahn flip_bytes ((char *) & Ivalue, 2);
6422159047fSniklas *aoffsetp += 16;
6432159047fSniklas Ivalue = sign_extend (Ivalue, 16);
6442159047fSniklas sprintf (result, "$%d", Ivalue);
6452159047fSniklas break;
6462159047fSniklas case 'D':
6472159047fSniklas Ivalue = bit_extract (buffer, *aoffsetp, 32);
648*c074d1c9Sdrahn flip_bytes ((char *) & Ivalue, 4);
6492159047fSniklas *aoffsetp += 32;
6502159047fSniklas sprintf (result, "$%d", Ivalue);
6512159047fSniklas break;
6522159047fSniklas case 'F':
653*c074d1c9Sdrahn bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
654*c074d1c9Sdrahn flip_bytes ((char *) &value.f, 4);
6552159047fSniklas *aoffsetp += 32;
656*c074d1c9Sdrahn if (INVALID_FLOAT (&value.f, 4))
657*c074d1c9Sdrahn sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
6582159047fSniklas else /* assume host has ieee float */
659*c074d1c9Sdrahn sprintf (result, "$%g", value.f);
6602159047fSniklas break;
6612159047fSniklas case 'L':
662*c074d1c9Sdrahn bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
663*c074d1c9Sdrahn flip_bytes ((char *) &value.d, 8);
6642159047fSniklas *aoffsetp += 64;
665*c074d1c9Sdrahn if (INVALID_FLOAT (&value.d, 8))
666*c074d1c9Sdrahn sprintf (result, "<<invalid double 0x%.8x%.8x>>",
667*c074d1c9Sdrahn value.i[1], value.i[0]);
6682159047fSniklas else /* assume host has ieee float */
669*c074d1c9Sdrahn sprintf (result, "$%g", value.d);
6702159047fSniklas break;
6712159047fSniklas }
6722159047fSniklas break;
6732159047fSniklas case 0x15:
6742159047fSniklas /* Absolute @disp */
6752159047fSniklas disp1 = get_displacement (buffer, aoffsetp);
6762159047fSniklas sprintf (result, "@|%d|", disp1);
6772159047fSniklas break;
6782159047fSniklas case 0x16:
6792159047fSniklas /* External EXT(disp1) + disp2 (Mod table stuff) */
6802159047fSniklas disp1 = get_displacement (buffer, aoffsetp);
6812159047fSniklas disp2 = get_displacement (buffer, aoffsetp);
6822159047fSniklas sprintf (result, "EXT(%d) + %d", disp1, disp2);
6832159047fSniklas break;
6842159047fSniklas case 0x17:
6852159047fSniklas /* Top of stack tos */
6862159047fSniklas sprintf (result, "tos");
6872159047fSniklas break;
6882159047fSniklas case 0x18:
6892159047fSniklas /* Memory space disp(FP) */
6902159047fSniklas disp1 = get_displacement (buffer, aoffsetp);
6912159047fSniklas sprintf (result, "%d(fp)", disp1);
6922159047fSniklas break;
6932159047fSniklas case 0x19:
6942159047fSniklas /* Memory space disp(SP) */
6952159047fSniklas disp1 = get_displacement (buffer, aoffsetp);
6962159047fSniklas sprintf (result, "%d(sp)", disp1);
6972159047fSniklas break;
6982159047fSniklas case 0x1a:
6992159047fSniklas /* Memory space disp(SB) */
7002159047fSniklas disp1 = get_displacement (buffer, aoffsetp);
7012159047fSniklas sprintf (result, "%d(sb)", disp1);
7022159047fSniklas break;
7032159047fSniklas case 0x1b:
7042159047fSniklas /* Memory space disp(PC) */
7052159047fSniklas disp1 = get_displacement (buffer, aoffsetp);
706f7cc78ecSespie *result++ = NEXT_IS_ADDR;
707f7cc78ecSespie sprintf_vma (result, addr + disp1);
708f7cc78ecSespie result += strlen (result);
709f7cc78ecSespie *result++ = NEXT_IS_ADDR;
710f7cc78ecSespie *result = '\0';
7112159047fSniklas break;
7122159047fSniklas case 0x1c:
7132159047fSniklas case 0x1d:
7142159047fSniklas case 0x1e:
7152159047fSniklas case 0x1f:
7162159047fSniklas /* Scaled index basemode[R0 -- R7:B,W,D,Q] */
7172159047fSniklas index = bit_extract (buffer, index_offset - 8, 3);
7182159047fSniklas print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
7192159047fSniklas result, 0);
7202159047fSniklas {
7212159047fSniklas static const char *ind = "bwdq";
7222159047fSniklas char *off;
7232159047fSniklas
7242159047fSniklas off = result + strlen (result);
7252159047fSniklas sprintf (off, "[r%d:%c]", index,
7262159047fSniklas ind[addr_mode & 3]);
7272159047fSniklas }
7282159047fSniklas break;
7292159047fSniklas }
7302159047fSniklas break;
7312159047fSniklas case 'H':
7322159047fSniklas case 'q':
7332159047fSniklas Ivalue = bit_extract (buffer, ioffset-4, 4);
7342159047fSniklas Ivalue = sign_extend (Ivalue, 4);
7352159047fSniklas sprintf (result, "%d", Ivalue);
7362159047fSniklas ioffset -= 4;
7372159047fSniklas break;
7382159047fSniklas case 'r':
7392159047fSniklas Ivalue = bit_extract (buffer, ioffset-3, 3);
7402159047fSniklas sprintf (result, "r%d", Ivalue&7);
7412159047fSniklas ioffset -= 3;
7422159047fSniklas break;
7432159047fSniklas case 'd':
7442159047fSniklas sprintf (result, "%d", get_displacement (buffer, aoffsetp));
7452159047fSniklas break;
7462159047fSniklas case 'b':
7472159047fSniklas Ivalue = get_displacement (buffer, aoffsetp);
7482159047fSniklas /*
7492159047fSniklas * Warning!! HACK ALERT!
7502159047fSniklas * Operand type 'b' is only used by the cmp{b,w,d} and
7512159047fSniklas * movm{b,w,d} instructions; we need to know whether
7522159047fSniklas * it's a `b' or `w' or `d' instruction; and for both
7532159047fSniklas * cmpm and movm it's stored at the same place so we
7542159047fSniklas * just grab two bits of the opcode and look at it...
7552159047fSniklas *
7562159047fSniklas */
7572159047fSniklas size = bit_extract(buffer, ioffset-6, 2);
7582159047fSniklas if (size == 0) /* 00 => b */
7592159047fSniklas size = 1;
7602159047fSniklas else if (size == 1) /* 01 => w */
7612159047fSniklas size = 2;
7622159047fSniklas else
7632159047fSniklas size = 4; /* 11 => d */
7642159047fSniklas
7652159047fSniklas sprintf (result, "%d", (Ivalue / size) + 1);
7662159047fSniklas break;
7672159047fSniklas case 'p':
768f7cc78ecSespie *result++ = NEXT_IS_ADDR;
769f7cc78ecSespie sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
770f7cc78ecSespie result += strlen (result);
771f7cc78ecSespie *result++ = NEXT_IS_ADDR;
772f7cc78ecSespie *result = '\0';
7732159047fSniklas break;
7742159047fSniklas case 'i':
7752159047fSniklas Ivalue = bit_extract (buffer, *aoffsetp, 8);
7762159047fSniklas *aoffsetp += 8;
7772159047fSniklas sprintf (result, "0x%x", Ivalue);
7782159047fSniklas break;
7792159047fSniklas case 'u':
7802159047fSniklas Ivalue = bit_extract (buffer, *aoffsetp, 8);
7812159047fSniklas optlist(Ivalue, opt_u, result);
7822159047fSniklas *aoffsetp += 8;
7832159047fSniklas break;
7842159047fSniklas case 'U':
7852159047fSniklas Ivalue = bit_extract(buffer, *aoffsetp, 8);
7862159047fSniklas optlist(Ivalue, opt_U, result);
7872159047fSniklas *aoffsetp += 8;
7882159047fSniklas break;
7892159047fSniklas case 'O':
7902159047fSniklas Ivalue = bit_extract(buffer, ioffset-9, 9);
7912159047fSniklas optlist(Ivalue, opt_O, result);
7922159047fSniklas ioffset -= 9;
7932159047fSniklas break;
7942159047fSniklas case 'C':
7952159047fSniklas Ivalue = bit_extract(buffer, ioffset-4, 4);
7962159047fSniklas optlist(Ivalue, opt_C, result);
7972159047fSniklas ioffset -= 4;
7982159047fSniklas break;
7992159047fSniklas case 'S':
8002159047fSniklas Ivalue = bit_extract(buffer, ioffset - 8, 8);
8012159047fSniklas optlist(Ivalue, opt_S, result);
8022159047fSniklas ioffset -= 8;
8032159047fSniklas break;
8042159047fSniklas case 'M':
8052159047fSniklas Ivalue = bit_extract(buffer, ioffset-4, 4);
8062159047fSniklas list_search(Ivalue, 0 ? list_M032 : list_M532, result);
8072159047fSniklas ioffset -= 4;
8082159047fSniklas break;
8092159047fSniklas case 'P':
8102159047fSniklas Ivalue = bit_extract(buffer, ioffset-4, 4);
8112159047fSniklas list_search(Ivalue, 0 ? list_P032 : list_P532, result);
8122159047fSniklas ioffset -= 4;
8132159047fSniklas break;
8142159047fSniklas case 'g':
8152159047fSniklas Ivalue = bit_extract(buffer, *aoffsetp, 3);
8162159047fSniklas sprintf(result, "%d", Ivalue);
8172159047fSniklas *aoffsetp += 3;
8182159047fSniklas break;
8192159047fSniklas case 'G':
8202159047fSniklas Ivalue = bit_extract(buffer, *aoffsetp, 5);
8212159047fSniklas sprintf(result, "%d", Ivalue + 1);
8222159047fSniklas *aoffsetp += 5;
8232159047fSniklas break;
8242159047fSniklas }
8252159047fSniklas return ioffset;
8262159047fSniklas }
8272159047fSniklas
828f7cc78ecSespie static int
get_displacement(buffer,aoffsetp)8292159047fSniklas get_displacement (buffer, aoffsetp)
8302159047fSniklas char *buffer;
8312159047fSniklas int *aoffsetp;
8322159047fSniklas {
8332159047fSniklas int Ivalue;
8342159047fSniklas short Ivalue2;
8352159047fSniklas
8362159047fSniklas Ivalue = bit_extract (buffer, *aoffsetp, 8);
8372159047fSniklas switch (Ivalue & 0xc0)
8382159047fSniklas {
8392159047fSniklas case 0x00:
8402159047fSniklas case 0x40:
8412159047fSniklas Ivalue = sign_extend (Ivalue, 7);
8422159047fSniklas *aoffsetp += 8;
8432159047fSniklas break;
8442159047fSniklas case 0x80:
8452159047fSniklas Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
846*c074d1c9Sdrahn flip_bytes ((char *) & Ivalue2, 2);
8472159047fSniklas Ivalue = sign_extend (Ivalue2, 14);
8482159047fSniklas *aoffsetp += 16;
8492159047fSniklas break;
8502159047fSniklas case 0xc0:
8512159047fSniklas Ivalue = bit_extract (buffer, *aoffsetp, 32);
852*c074d1c9Sdrahn flip_bytes ((char *) & Ivalue, 4);
8532159047fSniklas Ivalue = sign_extend (Ivalue, 30);
8542159047fSniklas *aoffsetp += 32;
8552159047fSniklas break;
8562159047fSniklas }
8572159047fSniklas return Ivalue;
8582159047fSniklas }
8592159047fSniklas
8602159047fSniklas
8612159047fSniklas #if 1 /* a version that should work on ns32k f's&d's on any machine */
862f7cc78ecSespie static int
invalid_float(p,len)863f7cc78ecSespie invalid_float (p, len)
8642159047fSniklas register char *p;
8652159047fSniklas register int len;
8662159047fSniklas {
867f7cc78ecSespie register int val;
8682159047fSniklas
8692159047fSniklas if ( len == 4 )
870f7cc78ecSespie val = (bit_extract_simple(p, 23, 8)/*exponent*/ == 0xff
871f7cc78ecSespie || (bit_extract_simple(p, 23, 8)/*exponent*/ == 0 &&
872f7cc78ecSespie bit_extract_simple(p, 0, 23)/*mantisa*/ != 0));
8732159047fSniklas else if ( len == 8 )
874f7cc78ecSespie val = (bit_extract_simple(p, 52, 11)/*exponent*/ == 0x7ff
875f7cc78ecSespie || (bit_extract_simple(p, 52, 11)/*exponent*/ == 0
876f7cc78ecSespie && (bit_extract_simple(p, 0, 32)/*low mantisa*/ != 0
877f7cc78ecSespie || bit_extract_simple(p, 32, 20)/*high mantisa*/ != 0)));
8782159047fSniklas else
8792159047fSniklas val = 1;
8802159047fSniklas return (val);
8812159047fSniklas }
8822159047fSniklas #else
8832159047fSniklas
8842159047fSniklas /* assumes the bytes have been swapped to local order */
8852159047fSniklas typedef union { double d;
8862159047fSniklas float f;
8872159047fSniklas struct { unsigned m:23, e:8, :1;} sf;
8882159047fSniklas struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
8892159047fSniklas } float_type_u;
8902159047fSniklas
891f7cc78ecSespie static int
invalid_float(p,len)892f7cc78ecSespie invalid_float (p, len)
8932159047fSniklas register float_type_u *p;
8942159047fSniklas register int len;
8952159047fSniklas {
8962159047fSniklas register int val;
8972159047fSniklas if ( len == sizeof (float) )
8982159047fSniklas val = (p->sf.e == 0xff
8992159047fSniklas || (p->sf.e == 0 && p->sf.m != 0));
9002159047fSniklas else if ( len == sizeof (double) )
9012159047fSniklas val = (p->sd.e == 0x7ff
9022159047fSniklas || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
9032159047fSniklas else
9042159047fSniklas val = 1;
9052159047fSniklas return (val);
9062159047fSniklas }
9072159047fSniklas #endif
908