xref: /openbsd-src/gnu/usr.bin/binutils/opcodes/ns32k-dis.c (revision c074d1c999f3e07019cd5e9a2f190b057ef3b935)
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