xref: /openbsd-src/gnu/usr.bin/binutils-2.17/opcodes/ns32k-dis.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* Print National Semiconductor 32000 instructions.
2*3d8817e4Smiod    Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005
3*3d8817e4Smiod    Free Software Foundation, Inc.
4*3d8817e4Smiod 
5*3d8817e4Smiod    This file is part of opcodes library.
6*3d8817e4Smiod 
7*3d8817e4Smiod    This program is free software; you can redistribute it and/or modify
8*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
9*3d8817e4Smiod    the Free Software Foundation; either version 2 of the License, or
10*3d8817e4Smiod    (at your option) any later version.
11*3d8817e4Smiod 
12*3d8817e4Smiod    This program is distributed in the hope that it will be useful,
13*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*3d8817e4Smiod    GNU General Public License for more details.
16*3d8817e4Smiod 
17*3d8817e4Smiod    You should have received a copy of the GNU General Public License
18*3d8817e4Smiod    along with this program; if not, write to the Free Software
19*3d8817e4Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20*3d8817e4Smiod    MA 02110-1301, USA.  */
21*3d8817e4Smiod 
22*3d8817e4Smiod 
23*3d8817e4Smiod #include "bfd.h"
24*3d8817e4Smiod #include "sysdep.h"
25*3d8817e4Smiod #include "dis-asm.h"
26*3d8817e4Smiod #if !defined(const) && !defined(__STDC__)
27*3d8817e4Smiod #define const
28*3d8817e4Smiod #endif
29*3d8817e4Smiod #include "opcode/ns32k.h"
30*3d8817e4Smiod #include "opintl.h"
31*3d8817e4Smiod 
32*3d8817e4Smiod static disassemble_info *dis_info;
33*3d8817e4Smiod 
34*3d8817e4Smiod /* Hacks to get it to compile <= READ THESE AS FIXES NEEDED.  */
35*3d8817e4Smiod #define INVALID_FLOAT(val, size) invalid_float ((bfd_byte *) val, size)
36*3d8817e4Smiod 
37*3d8817e4Smiod static long
read_memory_integer(unsigned char * addr,int nr)38*3d8817e4Smiod read_memory_integer (unsigned char * addr, int nr)
39*3d8817e4Smiod {
40*3d8817e4Smiod   long val;
41*3d8817e4Smiod   int i;
42*3d8817e4Smiod 
43*3d8817e4Smiod   for (val = 0, i = nr - 1; i >= 0; i--)
44*3d8817e4Smiod     {
45*3d8817e4Smiod       val =  (val << 8);
46*3d8817e4Smiod       val |= (0xff & *(addr + i));
47*3d8817e4Smiod     }
48*3d8817e4Smiod   return val;
49*3d8817e4Smiod }
50*3d8817e4Smiod 
51*3d8817e4Smiod /* 32000 instructions are never longer than this.  */
52*3d8817e4Smiod #define MAXLEN 62
53*3d8817e4Smiod 
54*3d8817e4Smiod #include <setjmp.h>
55*3d8817e4Smiod 
56*3d8817e4Smiod struct private
57*3d8817e4Smiod {
58*3d8817e4Smiod   /* Points to first byte not fetched.  */
59*3d8817e4Smiod   bfd_byte *max_fetched;
60*3d8817e4Smiod   bfd_byte the_buffer[MAXLEN];
61*3d8817e4Smiod   bfd_vma insn_start;
62*3d8817e4Smiod   jmp_buf bailout;
63*3d8817e4Smiod };
64*3d8817e4Smiod 
65*3d8817e4Smiod 
66*3d8817e4Smiod /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
67*3d8817e4Smiod    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
68*3d8817e4Smiod    on error.  */
69*3d8817e4Smiod #define FETCH_DATA(info, addr) \
70*3d8817e4Smiod   ((addr) <= ((struct private *)(info->private_data))->max_fetched \
71*3d8817e4Smiod    ? 1 : fetch_data ((info), (addr)))
72*3d8817e4Smiod 
73*3d8817e4Smiod static int
fetch_data(struct disassemble_info * info,bfd_byte * addr)74*3d8817e4Smiod fetch_data (struct disassemble_info *info, bfd_byte *addr)
75*3d8817e4Smiod {
76*3d8817e4Smiod   int status;
77*3d8817e4Smiod   struct private *priv = (struct private *) info->private_data;
78*3d8817e4Smiod   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
79*3d8817e4Smiod 
80*3d8817e4Smiod   status = (*info->read_memory_func) (start,
81*3d8817e4Smiod 				      priv->max_fetched,
82*3d8817e4Smiod 				      addr - priv->max_fetched,
83*3d8817e4Smiod 				      info);
84*3d8817e4Smiod   if (status != 0)
85*3d8817e4Smiod     {
86*3d8817e4Smiod       (*info->memory_error_func) (status, start, info);
87*3d8817e4Smiod       longjmp (priv->bailout, 1);
88*3d8817e4Smiod     }
89*3d8817e4Smiod   else
90*3d8817e4Smiod     priv->max_fetched = addr;
91*3d8817e4Smiod   return 1;
92*3d8817e4Smiod }
93*3d8817e4Smiod 
94*3d8817e4Smiod /* Number of elements in the opcode table.  */
95*3d8817e4Smiod #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
96*3d8817e4Smiod 
97*3d8817e4Smiod #define NEXT_IS_ADDR	'|'
98*3d8817e4Smiod 
99*3d8817e4Smiod 
100*3d8817e4Smiod struct ns32k_option
101*3d8817e4Smiod {
102*3d8817e4Smiod   char *pattern;		/* The option itself.  */
103*3d8817e4Smiod   unsigned long value;		/* Binary value of the option.  */
104*3d8817e4Smiod   unsigned long match;		/* These bits must match.  */
105*3d8817e4Smiod };
106*3d8817e4Smiod 
107*3d8817e4Smiod 
108*3d8817e4Smiod static const struct ns32k_option opt_u[]= /* Restore, exit.  */
109*3d8817e4Smiod {
110*3d8817e4Smiod   { "r0",	0x80,	0x80	},
111*3d8817e4Smiod   { "r1",	0x40,	0x40	},
112*3d8817e4Smiod   { "r2",	0x20,	0x20	},
113*3d8817e4Smiod   { "r3",	0x10,	0x10	},
114*3d8817e4Smiod   { "r4",	0x08,	0x08	},
115*3d8817e4Smiod   { "r5",	0x04,	0x04	},
116*3d8817e4Smiod   { "r6",	0x02,	0x02	},
117*3d8817e4Smiod   { "r7",	0x01,	0x01	},
118*3d8817e4Smiod   {  0 ,	0x00,	0x00	}
119*3d8817e4Smiod };
120*3d8817e4Smiod 
121*3d8817e4Smiod static const struct ns32k_option opt_U[]= /* Save, enter.  */
122*3d8817e4Smiod {
123*3d8817e4Smiod   { "r0",	0x01,	0x01	},
124*3d8817e4Smiod   { "r1",	0x02,	0x02	},
125*3d8817e4Smiod   { "r2",	0x04,	0x04	},
126*3d8817e4Smiod   { "r3",	0x08,	0x08	},
127*3d8817e4Smiod   { "r4",	0x10,	0x10	},
128*3d8817e4Smiod   { "r5",	0x20,	0x20	},
129*3d8817e4Smiod   { "r6",	0x40,	0x40	},
130*3d8817e4Smiod   { "r7",	0x80,	0x80	},
131*3d8817e4Smiod   {  0 ,	0x00,	0x00	}
132*3d8817e4Smiod };
133*3d8817e4Smiod 
134*3d8817e4Smiod static const struct ns32k_option opt_O[]= /* Setcfg.  */
135*3d8817e4Smiod {
136*3d8817e4Smiod   { "c",	0x8,	0x8	},
137*3d8817e4Smiod   { "m",	0x4,	0x4	},
138*3d8817e4Smiod   { "f",	0x2,	0x2	},
139*3d8817e4Smiod   { "i",	0x1,	0x1	},
140*3d8817e4Smiod   {  0 ,	0x0,	0x0	}
141*3d8817e4Smiod };
142*3d8817e4Smiod 
143*3d8817e4Smiod static const struct ns32k_option opt_C[]= /* Cinv.  */
144*3d8817e4Smiod {
145*3d8817e4Smiod   { "a",	0x4,	0x4	},
146*3d8817e4Smiod   { "i",	0x2,	0x2	},
147*3d8817e4Smiod   { "d",	0x1,	0x1	},
148*3d8817e4Smiod   {  0 ,	0x0,	0x0	}
149*3d8817e4Smiod };
150*3d8817e4Smiod 
151*3d8817e4Smiod static const struct ns32k_option opt_S[]= /* String inst.  */
152*3d8817e4Smiod {
153*3d8817e4Smiod   { "b",	0x1,	0x1	},
154*3d8817e4Smiod   { "u",	0x6,	0x6	},
155*3d8817e4Smiod   { "w",	0x2,	0x2	},
156*3d8817e4Smiod   {  0 ,	0x0,	0x0	}
157*3d8817e4Smiod };
158*3d8817e4Smiod 
159*3d8817e4Smiod static const struct ns32k_option list_P532[]= /* Lpr spr.  */
160*3d8817e4Smiod {
161*3d8817e4Smiod   { "us",	0x0,	0xf	},
162*3d8817e4Smiod   { "dcr",	0x1,	0xf	},
163*3d8817e4Smiod   { "bpc",	0x2,	0xf	},
164*3d8817e4Smiod   { "dsr",	0x3,	0xf	},
165*3d8817e4Smiod   { "car",	0x4,	0xf	},
166*3d8817e4Smiod   { "fp",	0x8,	0xf	},
167*3d8817e4Smiod   { "sp",	0x9,	0xf	},
168*3d8817e4Smiod   { "sb",	0xa,	0xf	},
169*3d8817e4Smiod   { "usp",	0xb,	0xf	},
170*3d8817e4Smiod   { "cfg",	0xc,	0xf	},
171*3d8817e4Smiod   { "psr",	0xd,	0xf	},
172*3d8817e4Smiod   { "intbase",	0xe,	0xf	},
173*3d8817e4Smiod   { "mod",	0xf,	0xf	},
174*3d8817e4Smiod   {  0 ,	0x00,	0xf	}
175*3d8817e4Smiod };
176*3d8817e4Smiod 
177*3d8817e4Smiod static const struct ns32k_option list_M532[]= /* Lmr smr.  */
178*3d8817e4Smiod {
179*3d8817e4Smiod   { "mcr",	0x9,	0xf	},
180*3d8817e4Smiod   { "msr",	0xa,	0xf	},
181*3d8817e4Smiod   { "tear",	0xb,	0xf	},
182*3d8817e4Smiod   { "ptb0",	0xc,	0xf	},
183*3d8817e4Smiod   { "ptb1",	0xd,	0xf	},
184*3d8817e4Smiod   { "ivar0",	0xe,	0xf	},
185*3d8817e4Smiod   { "ivar1",	0xf,	0xf	},
186*3d8817e4Smiod   {  0 ,	0x0,	0xf	}
187*3d8817e4Smiod };
188*3d8817e4Smiod 
189*3d8817e4Smiod static const struct ns32k_option list_P032[]= /* Lpr spr.  */
190*3d8817e4Smiod {
191*3d8817e4Smiod   { "upsr",	0x0,	0xf	},
192*3d8817e4Smiod   { "fp",	0x8,	0xf	},
193*3d8817e4Smiod   { "sp",	0x9,	0xf	},
194*3d8817e4Smiod   { "sb",	0xa,	0xf	},
195*3d8817e4Smiod   { "psr",	0xb,	0xf	},
196*3d8817e4Smiod   { "intbase",	0xe,	0xf	},
197*3d8817e4Smiod   { "mod",	0xf,	0xf	},
198*3d8817e4Smiod   {  0 ,	0x0,	0xf	}
199*3d8817e4Smiod };
200*3d8817e4Smiod 
201*3d8817e4Smiod static const struct ns32k_option list_M032[]= /* Lmr smr.  */
202*3d8817e4Smiod {
203*3d8817e4Smiod   { "bpr0",	0x0,	0xf	},
204*3d8817e4Smiod   { "bpr1",	0x1,	0xf	},
205*3d8817e4Smiod   { "pf0",	0x4,	0xf	},
206*3d8817e4Smiod   { "pf1",	0x5,	0xf	},
207*3d8817e4Smiod   { "sc",	0x8,	0xf	},
208*3d8817e4Smiod   { "msr",	0xa,	0xf	},
209*3d8817e4Smiod   { "bcnt",	0xb,	0xf	},
210*3d8817e4Smiod   { "ptb0",	0xc,	0xf	},
211*3d8817e4Smiod   { "ptb1",	0xd,	0xf	},
212*3d8817e4Smiod   { "eia",	0xf,	0xf	},
213*3d8817e4Smiod   {  0 ,	0x0,	0xf	}
214*3d8817e4Smiod };
215*3d8817e4Smiod 
216*3d8817e4Smiod 
217*3d8817e4Smiod /* Figure out which options are present.   */
218*3d8817e4Smiod 
219*3d8817e4Smiod static void
optlist(int options,const struct ns32k_option * optionP,char * result)220*3d8817e4Smiod optlist (int options, const struct ns32k_option * optionP, char * result)
221*3d8817e4Smiod {
222*3d8817e4Smiod   if (options == 0)
223*3d8817e4Smiod     {
224*3d8817e4Smiod       sprintf (result, "[]");
225*3d8817e4Smiod       return;
226*3d8817e4Smiod     }
227*3d8817e4Smiod 
228*3d8817e4Smiod   sprintf (result, "[");
229*3d8817e4Smiod 
230*3d8817e4Smiod   for (; (options != 0) && optionP->pattern; optionP++)
231*3d8817e4Smiod     {
232*3d8817e4Smiod       if ((options & optionP->match) == optionP->value)
233*3d8817e4Smiod 	{
234*3d8817e4Smiod 	  /* We found a match, update result and options.  */
235*3d8817e4Smiod 	  strcat (result, optionP->pattern);
236*3d8817e4Smiod 	  options &= ~optionP->value;
237*3d8817e4Smiod 	  if (options != 0)	/* More options to come.  */
238*3d8817e4Smiod 	    strcat (result, ",");
239*3d8817e4Smiod 	}
240*3d8817e4Smiod     }
241*3d8817e4Smiod 
242*3d8817e4Smiod   if (options != 0)
243*3d8817e4Smiod     strcat (result, "undefined");
244*3d8817e4Smiod 
245*3d8817e4Smiod   strcat (result, "]");
246*3d8817e4Smiod }
247*3d8817e4Smiod 
248*3d8817e4Smiod static void
list_search(int reg_value,const struct ns32k_option * optionP,char * result)249*3d8817e4Smiod list_search (int reg_value, const struct ns32k_option *optionP, char *result)
250*3d8817e4Smiod {
251*3d8817e4Smiod   for (; optionP->pattern; optionP++)
252*3d8817e4Smiod     {
253*3d8817e4Smiod       if ((reg_value & optionP->match) == optionP->value)
254*3d8817e4Smiod 	{
255*3d8817e4Smiod 	  sprintf (result, "%s", optionP->pattern);
256*3d8817e4Smiod 	  return;
257*3d8817e4Smiod 	}
258*3d8817e4Smiod     }
259*3d8817e4Smiod   sprintf (result, "undefined");
260*3d8817e4Smiod }
261*3d8817e4Smiod 
262*3d8817e4Smiod /* Extract "count" bits starting "offset" bits into buffer.  */
263*3d8817e4Smiod 
264*3d8817e4Smiod static int
bit_extract(bfd_byte * buffer,int offset,int count)265*3d8817e4Smiod bit_extract (bfd_byte *buffer, int offset, int count)
266*3d8817e4Smiod {
267*3d8817e4Smiod   int result;
268*3d8817e4Smiod   int bit;
269*3d8817e4Smiod 
270*3d8817e4Smiod   buffer += offset >> 3;
271*3d8817e4Smiod   offset &= 7;
272*3d8817e4Smiod   bit = 1;
273*3d8817e4Smiod   result = 0;
274*3d8817e4Smiod   while (count--)
275*3d8817e4Smiod     {
276*3d8817e4Smiod       FETCH_DATA (dis_info, buffer + 1);
277*3d8817e4Smiod       if ((*buffer & (1 << offset)))
278*3d8817e4Smiod 	result |= bit;
279*3d8817e4Smiod       if (++offset == 8)
280*3d8817e4Smiod 	{
281*3d8817e4Smiod 	  offset = 0;
282*3d8817e4Smiod 	  buffer++;
283*3d8817e4Smiod 	}
284*3d8817e4Smiod       bit <<= 1;
285*3d8817e4Smiod     }
286*3d8817e4Smiod   return result;
287*3d8817e4Smiod }
288*3d8817e4Smiod 
289*3d8817e4Smiod /* Like bit extract but the buffer is valid and doen't need to be fetched.  */
290*3d8817e4Smiod 
291*3d8817e4Smiod static int
bit_extract_simple(bfd_byte * buffer,int offset,int count)292*3d8817e4Smiod bit_extract_simple (bfd_byte *buffer, int offset, int count)
293*3d8817e4Smiod {
294*3d8817e4Smiod   int result;
295*3d8817e4Smiod   int bit;
296*3d8817e4Smiod 
297*3d8817e4Smiod   buffer += offset >> 3;
298*3d8817e4Smiod   offset &= 7;
299*3d8817e4Smiod   bit = 1;
300*3d8817e4Smiod   result = 0;
301*3d8817e4Smiod   while (count--)
302*3d8817e4Smiod     {
303*3d8817e4Smiod       if ((*buffer & (1 << offset)))
304*3d8817e4Smiod 	result |= bit;
305*3d8817e4Smiod       if (++offset == 8)
306*3d8817e4Smiod 	{
307*3d8817e4Smiod 	  offset = 0;
308*3d8817e4Smiod 	  buffer++;
309*3d8817e4Smiod 	}
310*3d8817e4Smiod       bit <<= 1;
311*3d8817e4Smiod     }
312*3d8817e4Smiod   return result;
313*3d8817e4Smiod }
314*3d8817e4Smiod 
315*3d8817e4Smiod static void
bit_copy(bfd_byte * buffer,int offset,int count,char * to)316*3d8817e4Smiod bit_copy (bfd_byte *buffer, int offset, int count, char *to)
317*3d8817e4Smiod {
318*3d8817e4Smiod   for (; count > 8; count -= 8, to++, offset += 8)
319*3d8817e4Smiod     *to = bit_extract (buffer, offset, 8);
320*3d8817e4Smiod   *to = bit_extract (buffer, offset, count);
321*3d8817e4Smiod }
322*3d8817e4Smiod 
323*3d8817e4Smiod static int
sign_extend(int value,int bits)324*3d8817e4Smiod sign_extend (int value, int bits)
325*3d8817e4Smiod {
326*3d8817e4Smiod   value = value & ((1 << bits) - 1);
327*3d8817e4Smiod   return (value & (1 << (bits - 1))
328*3d8817e4Smiod 	  ? value | (~((1 << bits) - 1))
329*3d8817e4Smiod 	  : value);
330*3d8817e4Smiod }
331*3d8817e4Smiod 
332*3d8817e4Smiod static void
flip_bytes(char * ptr,int count)333*3d8817e4Smiod flip_bytes (char *ptr, int count)
334*3d8817e4Smiod {
335*3d8817e4Smiod   char tmp;
336*3d8817e4Smiod 
337*3d8817e4Smiod   while (count > 0)
338*3d8817e4Smiod     {
339*3d8817e4Smiod       tmp = ptr[0];
340*3d8817e4Smiod       ptr[0] = ptr[count - 1];
341*3d8817e4Smiod       ptr[count - 1] = tmp;
342*3d8817e4Smiod       ptr++;
343*3d8817e4Smiod       count -= 2;
344*3d8817e4Smiod     }
345*3d8817e4Smiod }
346*3d8817e4Smiod 
347*3d8817e4Smiod /* Given a character C, does it represent a general addressing mode?  */
348*3d8817e4Smiod #define Is_gen(c) \
349*3d8817e4Smiod   ((c) == 'F' || (c) == 'L' || (c) == 'B' \
350*3d8817e4Smiod    || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
351*3d8817e4Smiod 
352*3d8817e4Smiod /* Adressing modes.  */
353*3d8817e4Smiod #define Adrmod_index_byte        0x1c
354*3d8817e4Smiod #define Adrmod_index_word        0x1d
355*3d8817e4Smiod #define Adrmod_index_doubleword  0x1e
356*3d8817e4Smiod #define Adrmod_index_quadword    0x1f
357*3d8817e4Smiod 
358*3d8817e4Smiod /* Is MODE an indexed addressing mode?  */
359*3d8817e4Smiod #define Adrmod_is_index(mode) \
360*3d8817e4Smiod   (   mode == Adrmod_index_byte \
361*3d8817e4Smiod    || mode == Adrmod_index_word \
362*3d8817e4Smiod    || mode == Adrmod_index_doubleword \
363*3d8817e4Smiod    || mode == Adrmod_index_quadword)
364*3d8817e4Smiod 
365*3d8817e4Smiod 
366*3d8817e4Smiod static int
get_displacement(bfd_byte * buffer,int * aoffsetp)367*3d8817e4Smiod get_displacement (bfd_byte *buffer, int *aoffsetp)
368*3d8817e4Smiod {
369*3d8817e4Smiod   int Ivalue;
370*3d8817e4Smiod   short Ivalue2;
371*3d8817e4Smiod 
372*3d8817e4Smiod   Ivalue = bit_extract (buffer, *aoffsetp, 8);
373*3d8817e4Smiod   switch (Ivalue & 0xc0)
374*3d8817e4Smiod     {
375*3d8817e4Smiod     case 0x00:
376*3d8817e4Smiod     case 0x40:
377*3d8817e4Smiod       Ivalue = sign_extend (Ivalue, 7);
378*3d8817e4Smiod       *aoffsetp += 8;
379*3d8817e4Smiod       break;
380*3d8817e4Smiod     case 0x80:
381*3d8817e4Smiod       Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
382*3d8817e4Smiod       flip_bytes ((char *) & Ivalue2, 2);
383*3d8817e4Smiod       Ivalue = sign_extend (Ivalue2, 14);
384*3d8817e4Smiod       *aoffsetp += 16;
385*3d8817e4Smiod       break;
386*3d8817e4Smiod     case 0xc0:
387*3d8817e4Smiod       Ivalue = bit_extract (buffer, *aoffsetp, 32);
388*3d8817e4Smiod       flip_bytes ((char *) & Ivalue, 4);
389*3d8817e4Smiod       Ivalue = sign_extend (Ivalue, 30);
390*3d8817e4Smiod       *aoffsetp += 32;
391*3d8817e4Smiod       break;
392*3d8817e4Smiod     }
393*3d8817e4Smiod   return Ivalue;
394*3d8817e4Smiod }
395*3d8817e4Smiod 
396*3d8817e4Smiod #if 1 /* A version that should work on ns32k f's&d's on any machine.  */
397*3d8817e4Smiod static int
invalid_float(bfd_byte * p,int len)398*3d8817e4Smiod invalid_float (bfd_byte *p, int len)
399*3d8817e4Smiod {
400*3d8817e4Smiod   int val;
401*3d8817e4Smiod 
402*3d8817e4Smiod   if (len == 4)
403*3d8817e4Smiod     val = (bit_extract_simple (p, 23, 8)/*exponent*/ == 0xff
404*3d8817e4Smiod 	   || (bit_extract_simple (p, 23, 8)/*exponent*/ == 0
405*3d8817e4Smiod 	       && bit_extract_simple (p, 0, 23)/*mantisa*/ != 0));
406*3d8817e4Smiod   else if (len == 8)
407*3d8817e4Smiod     val = (bit_extract_simple (p, 52, 11)/*exponent*/ == 0x7ff
408*3d8817e4Smiod 	   || (bit_extract_simple (p, 52, 11)/*exponent*/ == 0
409*3d8817e4Smiod 	       && (bit_extract_simple (p, 0, 32)/*low mantisa*/ != 0
410*3d8817e4Smiod 		   || bit_extract_simple (p, 32, 20)/*high mantisa*/ != 0)));
411*3d8817e4Smiod   else
412*3d8817e4Smiod     val = 1;
413*3d8817e4Smiod   return (val);
414*3d8817e4Smiod }
415*3d8817e4Smiod #else
416*3d8817e4Smiod /* Assumes the bytes have been swapped to local order.  */
417*3d8817e4Smiod typedef union
418*3d8817e4Smiod {
419*3d8817e4Smiod   double d;
420*3d8817e4Smiod   float f;
421*3d8817e4Smiod   struct { unsigned m:23, e:8, :1;} sf;
422*3d8817e4Smiod   struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
423*3d8817e4Smiod } float_type_u;
424*3d8817e4Smiod 
425*3d8817e4Smiod static int
invalid_float(float_type_u * p,int len)426*3d8817e4Smiod invalid_float (float_type_u *p, int len)
427*3d8817e4Smiod {
428*3d8817e4Smiod   int val;
429*3d8817e4Smiod 
430*3d8817e4Smiod   if (len == sizeof (float))
431*3d8817e4Smiod     val = (p->sf.e == 0xff
432*3d8817e4Smiod 	   || (p->sf.e == 0 && p->sf.m != 0));
433*3d8817e4Smiod   else if (len == sizeof (double))
434*3d8817e4Smiod     val = (p->sd.e == 0x7ff
435*3d8817e4Smiod 	   || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
436*3d8817e4Smiod   else
437*3d8817e4Smiod     val = 1;
438*3d8817e4Smiod   return val;
439*3d8817e4Smiod }
440*3d8817e4Smiod #endif
441*3d8817e4Smiod 
442*3d8817e4Smiod /* Print an instruction operand of category given by d.  IOFFSET is
443*3d8817e4Smiod    the bit position below which small (<1 byte) parts of the operand can
444*3d8817e4Smiod    be found (usually in the basic instruction, but for indexed
445*3d8817e4Smiod    addressing it can be in the index byte).  AOFFSETP is a pointer to the
446*3d8817e4Smiod    bit position of the addressing extension.  BUFFER contains the
447*3d8817e4Smiod    instruction.  ADDR is where BUFFER was read from.  Put the disassembled
448*3d8817e4Smiod    version of the operand in RESULT.  INDEX_OFFSET is the bit position
449*3d8817e4Smiod    of the index byte (it contains garbage if this operand is not a
450*3d8817e4Smiod    general operand using scaled indexed addressing mode).  */
451*3d8817e4Smiod 
452*3d8817e4Smiod static int
print_insn_arg(int d,int ioffset,int * aoffsetp,bfd_byte * buffer,bfd_vma addr,char * result,int index_offset)453*3d8817e4Smiod print_insn_arg (int d,
454*3d8817e4Smiod 		int ioffset,
455*3d8817e4Smiod 		int *aoffsetp,
456*3d8817e4Smiod 		bfd_byte *buffer,
457*3d8817e4Smiod 		bfd_vma addr,
458*3d8817e4Smiod 		char *result,
459*3d8817e4Smiod 		int index_offset)
460*3d8817e4Smiod {
461*3d8817e4Smiod   union
462*3d8817e4Smiod   {
463*3d8817e4Smiod     float f;
464*3d8817e4Smiod     double d;
465*3d8817e4Smiod     int i[2];
466*3d8817e4Smiod   } value;
467*3d8817e4Smiod   int Ivalue;
468*3d8817e4Smiod   int addr_mode;
469*3d8817e4Smiod   int disp1, disp2;
470*3d8817e4Smiod   int index;
471*3d8817e4Smiod   int size;
472*3d8817e4Smiod 
473*3d8817e4Smiod   switch (d)
474*3d8817e4Smiod     {
475*3d8817e4Smiod     case 'f':
476*3d8817e4Smiod       /* A "gen" operand but 5 bits from the end of instruction.  */
477*3d8817e4Smiod       ioffset -= 5;
478*3d8817e4Smiod     case 'Z':
479*3d8817e4Smiod     case 'F':
480*3d8817e4Smiod     case 'L':
481*3d8817e4Smiod     case 'I':
482*3d8817e4Smiod     case 'B':
483*3d8817e4Smiod     case 'W':
484*3d8817e4Smiod     case 'D':
485*3d8817e4Smiod     case 'A':
486*3d8817e4Smiod       addr_mode = bit_extract (buffer, ioffset - 5, 5);
487*3d8817e4Smiod       ioffset -= 5;
488*3d8817e4Smiod       switch (addr_mode)
489*3d8817e4Smiod 	{
490*3d8817e4Smiod 	case 0x0: case 0x1: case 0x2: case 0x3:
491*3d8817e4Smiod 	case 0x4: case 0x5: case 0x6: case 0x7:
492*3d8817e4Smiod 	  /* Register mode R0 -- R7.  */
493*3d8817e4Smiod 	  switch (d)
494*3d8817e4Smiod 	    {
495*3d8817e4Smiod 	    case 'F':
496*3d8817e4Smiod 	    case 'L':
497*3d8817e4Smiod 	    case 'Z':
498*3d8817e4Smiod 	      sprintf (result, "f%d", addr_mode);
499*3d8817e4Smiod 	      break;
500*3d8817e4Smiod 	    default:
501*3d8817e4Smiod 	      sprintf (result, "r%d", addr_mode);
502*3d8817e4Smiod 	    }
503*3d8817e4Smiod 	  break;
504*3d8817e4Smiod 	case 0x8: case 0x9: case 0xa: case 0xb:
505*3d8817e4Smiod 	case 0xc: case 0xd: case 0xe: case 0xf:
506*3d8817e4Smiod 	  /* Register relative disp(R0 -- R7).  */
507*3d8817e4Smiod 	  disp1 = get_displacement (buffer, aoffsetp);
508*3d8817e4Smiod 	  sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
509*3d8817e4Smiod 	  break;
510*3d8817e4Smiod 	case 0x10:
511*3d8817e4Smiod 	case 0x11:
512*3d8817e4Smiod 	case 0x12:
513*3d8817e4Smiod 	  /* Memory relative disp2(disp1(FP, SP, SB)).  */
514*3d8817e4Smiod 	  disp1 = get_displacement (buffer, aoffsetp);
515*3d8817e4Smiod 	  disp2 = get_displacement (buffer, aoffsetp);
516*3d8817e4Smiod 	  sprintf (result, "%d(%d(%s))", disp2, disp1,
517*3d8817e4Smiod 		   addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
518*3d8817e4Smiod 	  break;
519*3d8817e4Smiod 	case 0x13:
520*3d8817e4Smiod 	  /* Reserved.  */
521*3d8817e4Smiod 	  sprintf (result, "reserved");
522*3d8817e4Smiod 	  break;
523*3d8817e4Smiod 	case 0x14:
524*3d8817e4Smiod 	  /* Immediate.  */
525*3d8817e4Smiod 	  switch (d)
526*3d8817e4Smiod 	    {
527*3d8817e4Smiod 	    case 'I':
528*3d8817e4Smiod 	    case 'Z':
529*3d8817e4Smiod 	    case 'A':
530*3d8817e4Smiod 	      /* I and Z are output operands and can`t be immediate
531*3d8817e4Smiod 	         A is an address and we can`t have the address of
532*3d8817e4Smiod 	         an immediate either. We don't know how much to increase
533*3d8817e4Smiod 	         aoffsetp by since whatever generated this is broken
534*3d8817e4Smiod 	         anyway!  */
535*3d8817e4Smiod 	      sprintf (result, _("$<undefined>"));
536*3d8817e4Smiod 	      break;
537*3d8817e4Smiod 	    case 'B':
538*3d8817e4Smiod 	      Ivalue = bit_extract (buffer, *aoffsetp, 8);
539*3d8817e4Smiod 	      Ivalue = sign_extend (Ivalue, 8);
540*3d8817e4Smiod 	      *aoffsetp += 8;
541*3d8817e4Smiod 	      sprintf (result, "$%d", Ivalue);
542*3d8817e4Smiod 	      break;
543*3d8817e4Smiod 	    case 'W':
544*3d8817e4Smiod 	      Ivalue = bit_extract (buffer, *aoffsetp, 16);
545*3d8817e4Smiod 	      flip_bytes ((char *) & Ivalue, 2);
546*3d8817e4Smiod 	      *aoffsetp += 16;
547*3d8817e4Smiod 	      Ivalue = sign_extend (Ivalue, 16);
548*3d8817e4Smiod 	      sprintf (result, "$%d", Ivalue);
549*3d8817e4Smiod 	      break;
550*3d8817e4Smiod 	    case 'D':
551*3d8817e4Smiod 	      Ivalue = bit_extract (buffer, *aoffsetp, 32);
552*3d8817e4Smiod 	      flip_bytes ((char *) & Ivalue, 4);
553*3d8817e4Smiod 	      *aoffsetp += 32;
554*3d8817e4Smiod 	      sprintf (result, "$%d", Ivalue);
555*3d8817e4Smiod 	      break;
556*3d8817e4Smiod 	    case 'F':
557*3d8817e4Smiod 	      bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
558*3d8817e4Smiod 	      flip_bytes ((char *) &value.f, 4);
559*3d8817e4Smiod 	      *aoffsetp += 32;
560*3d8817e4Smiod 	      if (INVALID_FLOAT (&value.f, 4))
561*3d8817e4Smiod 		sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
562*3d8817e4Smiod 	      else /* Assume host has ieee float.  */
563*3d8817e4Smiod 		sprintf (result, "$%g", value.f);
564*3d8817e4Smiod 	      break;
565*3d8817e4Smiod 	    case 'L':
566*3d8817e4Smiod 	      bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
567*3d8817e4Smiod 	      flip_bytes ((char *) &value.d, 8);
568*3d8817e4Smiod 	      *aoffsetp += 64;
569*3d8817e4Smiod 	      if (INVALID_FLOAT (&value.d, 8))
570*3d8817e4Smiod 		sprintf (result, "<<invalid double 0x%.8x%.8x>>",
571*3d8817e4Smiod 			 value.i[1], value.i[0]);
572*3d8817e4Smiod 	      else /* Assume host has ieee float.  */
573*3d8817e4Smiod 		sprintf (result, "$%g", value.d);
574*3d8817e4Smiod 	      break;
575*3d8817e4Smiod 	    }
576*3d8817e4Smiod 	  break;
577*3d8817e4Smiod 	case 0x15:
578*3d8817e4Smiod 	  /* Absolute @disp.  */
579*3d8817e4Smiod 	  disp1 = get_displacement (buffer, aoffsetp);
580*3d8817e4Smiod 	  sprintf (result, "@|%d|", disp1);
581*3d8817e4Smiod 	  break;
582*3d8817e4Smiod 	case 0x16:
583*3d8817e4Smiod 	  /* External EXT(disp1) + disp2 (Mod table stuff).  */
584*3d8817e4Smiod 	  disp1 = get_displacement (buffer, aoffsetp);
585*3d8817e4Smiod 	  disp2 = get_displacement (buffer, aoffsetp);
586*3d8817e4Smiod 	  sprintf (result, "EXT(%d) + %d", disp1, disp2);
587*3d8817e4Smiod 	  break;
588*3d8817e4Smiod 	case 0x17:
589*3d8817e4Smiod 	  /* Top of stack tos.  */
590*3d8817e4Smiod 	  sprintf (result, "tos");
591*3d8817e4Smiod 	  break;
592*3d8817e4Smiod 	case 0x18:
593*3d8817e4Smiod 	  /* Memory space disp(FP).  */
594*3d8817e4Smiod 	  disp1 = get_displacement (buffer, aoffsetp);
595*3d8817e4Smiod 	  sprintf (result, "%d(fp)", disp1);
596*3d8817e4Smiod 	  break;
597*3d8817e4Smiod 	case 0x19:
598*3d8817e4Smiod 	  /* Memory space disp(SP).  */
599*3d8817e4Smiod 	  disp1 = get_displacement (buffer, aoffsetp);
600*3d8817e4Smiod 	  sprintf (result, "%d(sp)", disp1);
601*3d8817e4Smiod 	  break;
602*3d8817e4Smiod 	case 0x1a:
603*3d8817e4Smiod 	  /* Memory space disp(SB).  */
604*3d8817e4Smiod 	  disp1 = get_displacement (buffer, aoffsetp);
605*3d8817e4Smiod 	  sprintf (result, "%d(sb)", disp1);
606*3d8817e4Smiod 	  break;
607*3d8817e4Smiod 	case 0x1b:
608*3d8817e4Smiod 	  /* Memory space disp(PC).  */
609*3d8817e4Smiod 	  disp1 = get_displacement (buffer, aoffsetp);
610*3d8817e4Smiod 	  *result++ = NEXT_IS_ADDR;
611*3d8817e4Smiod 	  sprintf_vma (result, addr + disp1);
612*3d8817e4Smiod 	  result += strlen (result);
613*3d8817e4Smiod 	  *result++ = NEXT_IS_ADDR;
614*3d8817e4Smiod 	  *result = '\0';
615*3d8817e4Smiod 	  break;
616*3d8817e4Smiod 	case 0x1c:
617*3d8817e4Smiod 	case 0x1d:
618*3d8817e4Smiod 	case 0x1e:
619*3d8817e4Smiod 	case 0x1f:
620*3d8817e4Smiod 	  /* Scaled index basemode[R0 -- R7:B,W,D,Q].  */
621*3d8817e4Smiod 	  index = bit_extract (buffer, index_offset - 8, 3);
622*3d8817e4Smiod 	  print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
623*3d8817e4Smiod 			  result, 0);
624*3d8817e4Smiod 	  {
625*3d8817e4Smiod 	    static const char *ind = "bwdq";
626*3d8817e4Smiod 	    char *off;
627*3d8817e4Smiod 
628*3d8817e4Smiod 	    off = result + strlen (result);
629*3d8817e4Smiod 	    sprintf (off, "[r%d:%c]", index,
630*3d8817e4Smiod 		     ind[addr_mode & 3]);
631*3d8817e4Smiod 	  }
632*3d8817e4Smiod 	  break;
633*3d8817e4Smiod 	}
634*3d8817e4Smiod       break;
635*3d8817e4Smiod     case 'H':
636*3d8817e4Smiod     case 'q':
637*3d8817e4Smiod       Ivalue = bit_extract (buffer, ioffset-4, 4);
638*3d8817e4Smiod       Ivalue = sign_extend (Ivalue, 4);
639*3d8817e4Smiod       sprintf (result, "%d", Ivalue);
640*3d8817e4Smiod       ioffset -= 4;
641*3d8817e4Smiod       break;
642*3d8817e4Smiod     case 'r':
643*3d8817e4Smiod       Ivalue = bit_extract (buffer, ioffset-3, 3);
644*3d8817e4Smiod       sprintf (result, "r%d", Ivalue&7);
645*3d8817e4Smiod       ioffset -= 3;
646*3d8817e4Smiod       break;
647*3d8817e4Smiod     case 'd':
648*3d8817e4Smiod       sprintf (result, "%d", get_displacement (buffer, aoffsetp));
649*3d8817e4Smiod       break;
650*3d8817e4Smiod     case 'b':
651*3d8817e4Smiod       Ivalue = get_displacement (buffer, aoffsetp);
652*3d8817e4Smiod       /* Warning!!  HACK ALERT!
653*3d8817e4Smiod          Operand type 'b' is only used by the cmp{b,w,d} and
654*3d8817e4Smiod          movm{b,w,d} instructions; we need to know whether
655*3d8817e4Smiod          it's a `b' or `w' or `d' instruction; and for both
656*3d8817e4Smiod          cmpm and movm it's stored at the same place so we
657*3d8817e4Smiod          just grab two bits of the opcode and look at it...  */
658*3d8817e4Smiod       size = bit_extract(buffer, ioffset-6, 2);
659*3d8817e4Smiod       if (size == 0)		/* 00 => b.  */
660*3d8817e4Smiod 	size = 1;
661*3d8817e4Smiod       else if (size == 1)	/* 01 => w.  */
662*3d8817e4Smiod 	size = 2;
663*3d8817e4Smiod       else
664*3d8817e4Smiod 	size = 4;		/* 11 => d.  */
665*3d8817e4Smiod 
666*3d8817e4Smiod       sprintf (result, "%d", (Ivalue / size) + 1);
667*3d8817e4Smiod       break;
668*3d8817e4Smiod     case 'p':
669*3d8817e4Smiod       *result++ = NEXT_IS_ADDR;
670*3d8817e4Smiod       sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
671*3d8817e4Smiod       result += strlen (result);
672*3d8817e4Smiod       *result++ = NEXT_IS_ADDR;
673*3d8817e4Smiod       *result = '\0';
674*3d8817e4Smiod       break;
675*3d8817e4Smiod     case 'i':
676*3d8817e4Smiod       Ivalue = bit_extract (buffer, *aoffsetp, 8);
677*3d8817e4Smiod       *aoffsetp += 8;
678*3d8817e4Smiod       sprintf (result, "0x%x", Ivalue);
679*3d8817e4Smiod       break;
680*3d8817e4Smiod     case 'u':
681*3d8817e4Smiod       Ivalue = bit_extract (buffer, *aoffsetp, 8);
682*3d8817e4Smiod       optlist (Ivalue, opt_u, result);
683*3d8817e4Smiod       *aoffsetp += 8;
684*3d8817e4Smiod       break;
685*3d8817e4Smiod     case 'U':
686*3d8817e4Smiod       Ivalue = bit_extract (buffer, *aoffsetp, 8);
687*3d8817e4Smiod       optlist (Ivalue, opt_U, result);
688*3d8817e4Smiod       *aoffsetp += 8;
689*3d8817e4Smiod       break;
690*3d8817e4Smiod     case 'O':
691*3d8817e4Smiod       Ivalue = bit_extract (buffer, ioffset - 9, 9);
692*3d8817e4Smiod       optlist (Ivalue, opt_O, result);
693*3d8817e4Smiod       ioffset -= 9;
694*3d8817e4Smiod       break;
695*3d8817e4Smiod     case 'C':
696*3d8817e4Smiod       Ivalue = bit_extract (buffer, ioffset - 4, 4);
697*3d8817e4Smiod       optlist (Ivalue, opt_C, result);
698*3d8817e4Smiod       ioffset -= 4;
699*3d8817e4Smiod       break;
700*3d8817e4Smiod     case 'S':
701*3d8817e4Smiod       Ivalue = bit_extract (buffer, ioffset - 8, 8);
702*3d8817e4Smiod       optlist (Ivalue, opt_S, result);
703*3d8817e4Smiod       ioffset -= 8;
704*3d8817e4Smiod       break;
705*3d8817e4Smiod     case 'M':
706*3d8817e4Smiod       Ivalue = bit_extract (buffer, ioffset - 4, 4);
707*3d8817e4Smiod       list_search (Ivalue, 0 ? list_M032 : list_M532, result);
708*3d8817e4Smiod       ioffset -= 4;
709*3d8817e4Smiod       break;
710*3d8817e4Smiod     case 'P':
711*3d8817e4Smiod       Ivalue = bit_extract (buffer, ioffset - 4, 4);
712*3d8817e4Smiod       list_search (Ivalue, 0 ? list_P032 : list_P532, result);
713*3d8817e4Smiod       ioffset -= 4;
714*3d8817e4Smiod       break;
715*3d8817e4Smiod     case 'g':
716*3d8817e4Smiod       Ivalue = bit_extract (buffer, *aoffsetp, 3);
717*3d8817e4Smiod       sprintf (result, "%d", Ivalue);
718*3d8817e4Smiod       *aoffsetp += 3;
719*3d8817e4Smiod       break;
720*3d8817e4Smiod     case 'G':
721*3d8817e4Smiod       Ivalue = bit_extract(buffer, *aoffsetp, 5);
722*3d8817e4Smiod       sprintf (result, "%d", Ivalue + 1);
723*3d8817e4Smiod       *aoffsetp += 5;
724*3d8817e4Smiod       break;
725*3d8817e4Smiod     }
726*3d8817e4Smiod   return ioffset;
727*3d8817e4Smiod }
728*3d8817e4Smiod 
729*3d8817e4Smiod 
730*3d8817e4Smiod /* Print the 32000 instruction at address MEMADDR in debugged memory,
731*3d8817e4Smiod    on STREAM.  Returns length of the instruction, in bytes.  */
732*3d8817e4Smiod 
733*3d8817e4Smiod int
print_insn_ns32k(bfd_vma memaddr,disassemble_info * info)734*3d8817e4Smiod print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
735*3d8817e4Smiod {
736*3d8817e4Smiod   unsigned int i;
737*3d8817e4Smiod   const char *d;
738*3d8817e4Smiod   unsigned short first_word;
739*3d8817e4Smiod   int ioffset;		/* Bits into instruction.  */
740*3d8817e4Smiod   int aoffset;		/* Bits into arguments.  */
741*3d8817e4Smiod   char arg_bufs[MAX_ARGS+1][ARG_LEN];
742*3d8817e4Smiod   int argnum;
743*3d8817e4Smiod   int maxarg;
744*3d8817e4Smiod   struct private priv;
745*3d8817e4Smiod   bfd_byte *buffer = priv.the_buffer;
746*3d8817e4Smiod   dis_info = info;
747*3d8817e4Smiod 
748*3d8817e4Smiod   info->private_data = & priv;
749*3d8817e4Smiod   priv.max_fetched = priv.the_buffer;
750*3d8817e4Smiod   priv.insn_start = memaddr;
751*3d8817e4Smiod   if (setjmp (priv.bailout) != 0)
752*3d8817e4Smiod     /* Error return.  */
753*3d8817e4Smiod     return -1;
754*3d8817e4Smiod 
755*3d8817e4Smiod   /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
756*3d8817e4Smiod      us over the end of accessible data unnecessarilly.  */
757*3d8817e4Smiod   FETCH_DATA (info, buffer + 1);
758*3d8817e4Smiod   for (i = 0; i < NOPCODES; i++)
759*3d8817e4Smiod     if (ns32k_opcodes[i].opcode_id_size <= 8
760*3d8817e4Smiod 	&& ((buffer[0]
761*3d8817e4Smiod 	     & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
762*3d8817e4Smiod 	    == ns32k_opcodes[i].opcode_seed))
763*3d8817e4Smiod       break;
764*3d8817e4Smiod   if (i == NOPCODES)
765*3d8817e4Smiod     {
766*3d8817e4Smiod       /* Maybe it is 9 to 16 bits big.  */
767*3d8817e4Smiod       FETCH_DATA (info, buffer + 2);
768*3d8817e4Smiod       first_word = read_memory_integer(buffer, 2);
769*3d8817e4Smiod 
770*3d8817e4Smiod       for (i = 0; i < NOPCODES; i++)
771*3d8817e4Smiod 	if ((first_word
772*3d8817e4Smiod 	     & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
773*3d8817e4Smiod 	    == ns32k_opcodes[i].opcode_seed)
774*3d8817e4Smiod 	  break;
775*3d8817e4Smiod 
776*3d8817e4Smiod       /* Handle undefined instructions.  */
777*3d8817e4Smiod       if (i == NOPCODES)
778*3d8817e4Smiod 	{
779*3d8817e4Smiod 	  (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
780*3d8817e4Smiod 	  return 1;
781*3d8817e4Smiod 	}
782*3d8817e4Smiod     }
783*3d8817e4Smiod 
784*3d8817e4Smiod   (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
785*3d8817e4Smiod 
786*3d8817e4Smiod   ioffset = ns32k_opcodes[i].opcode_size;
787*3d8817e4Smiod   aoffset = ns32k_opcodes[i].opcode_size;
788*3d8817e4Smiod   d = ns32k_opcodes[i].operands;
789*3d8817e4Smiod 
790*3d8817e4Smiod   if (*d)
791*3d8817e4Smiod     {
792*3d8817e4Smiod       /* Offset in bits of the first thing beyond each index byte.
793*3d8817e4Smiod 	 Element 0 is for operand A and element 1 is for operand B.
794*3d8817e4Smiod 	 The rest are irrelevant, but we put them here so we don't
795*3d8817e4Smiod 	 index outside the array.  */
796*3d8817e4Smiod       int index_offset[MAX_ARGS];
797*3d8817e4Smiod 
798*3d8817e4Smiod       /* 0 for operand A, 1 for operand B, greater for other args.  */
799*3d8817e4Smiod       int whicharg = 0;
800*3d8817e4Smiod 
801*3d8817e4Smiod       (*dis_info->fprintf_func)(dis_info->stream, "\t");
802*3d8817e4Smiod 
803*3d8817e4Smiod       maxarg = 0;
804*3d8817e4Smiod 
805*3d8817e4Smiod       /* First we have to find and keep track of the index bytes,
806*3d8817e4Smiod 	 if we are using scaled indexed addressing mode, since the index
807*3d8817e4Smiod 	 bytes occur right after the basic instruction, not as part
808*3d8817e4Smiod 	 of the addressing extension.  */
809*3d8817e4Smiod       if (Is_gen(d[1]))
810*3d8817e4Smiod 	{
811*3d8817e4Smiod 	  int addr_mode = bit_extract (buffer, ioffset - 5, 5);
812*3d8817e4Smiod 
813*3d8817e4Smiod 	  if (Adrmod_is_index (addr_mode))
814*3d8817e4Smiod 	    {
815*3d8817e4Smiod 	      aoffset += 8;
816*3d8817e4Smiod 	      index_offset[0] = aoffset;
817*3d8817e4Smiod 	    }
818*3d8817e4Smiod 	}
819*3d8817e4Smiod 
820*3d8817e4Smiod       if (d[2] && Is_gen(d[3]))
821*3d8817e4Smiod 	{
822*3d8817e4Smiod 	  int addr_mode = bit_extract (buffer, ioffset - 10, 5);
823*3d8817e4Smiod 
824*3d8817e4Smiod 	  if (Adrmod_is_index (addr_mode))
825*3d8817e4Smiod 	    {
826*3d8817e4Smiod 	      aoffset += 8;
827*3d8817e4Smiod 	      index_offset[1] = aoffset;
828*3d8817e4Smiod 	    }
829*3d8817e4Smiod 	}
830*3d8817e4Smiod 
831*3d8817e4Smiod       while (*d)
832*3d8817e4Smiod 	{
833*3d8817e4Smiod 	  argnum = *d - '1';
834*3d8817e4Smiod 	  d++;
835*3d8817e4Smiod 	  if (argnum > maxarg && argnum < MAX_ARGS)
836*3d8817e4Smiod 	    maxarg = argnum;
837*3d8817e4Smiod 	  ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
838*3d8817e4Smiod 				    memaddr, arg_bufs[argnum],
839*3d8817e4Smiod 				    index_offset[whicharg]);
840*3d8817e4Smiod 	  d++;
841*3d8817e4Smiod 	  whicharg++;
842*3d8817e4Smiod 	}
843*3d8817e4Smiod       for (argnum = 0; argnum <= maxarg; argnum++)
844*3d8817e4Smiod 	{
845*3d8817e4Smiod 	  bfd_vma addr;
846*3d8817e4Smiod 	  char *ch;
847*3d8817e4Smiod 
848*3d8817e4Smiod 	  for (ch = arg_bufs[argnum]; *ch;)
849*3d8817e4Smiod 	    {
850*3d8817e4Smiod 	      if (*ch == NEXT_IS_ADDR)
851*3d8817e4Smiod 		{
852*3d8817e4Smiod 		  ++ch;
853*3d8817e4Smiod 		  addr = bfd_scan_vma (ch, NULL, 16);
854*3d8817e4Smiod 		  (*dis_info->print_address_func) (addr, dis_info);
855*3d8817e4Smiod 		  while (*ch && *ch != NEXT_IS_ADDR)
856*3d8817e4Smiod 		    ++ch;
857*3d8817e4Smiod 		  if (*ch)
858*3d8817e4Smiod 		    ++ch;
859*3d8817e4Smiod 		}
860*3d8817e4Smiod 	      else
861*3d8817e4Smiod 		(*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
862*3d8817e4Smiod 	    }
863*3d8817e4Smiod 	  if (argnum < maxarg)
864*3d8817e4Smiod 	    (*dis_info->fprintf_func)(dis_info->stream, ", ");
865*3d8817e4Smiod 	}
866*3d8817e4Smiod     }
867*3d8817e4Smiod   return aoffset / 8;
868*3d8817e4Smiod }
869