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