xref: /openbsd-src/gnu/usr.bin/binutils-2.17/opcodes/vax-dis.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* Print VAX instructions.
2*3d8817e4Smiod    Copyright 1995, 1998, 2000, 2001, 2002, 2005
3*3d8817e4Smiod    Free Software Foundation, Inc.
4*3d8817e4Smiod    Contributed by Pauline Middelink <middelin@polyware.iaf.nl>
5*3d8817e4Smiod 
6*3d8817e4Smiod    This program is free software; you can redistribute it and/or modify
7*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
8*3d8817e4Smiod    the Free Software Foundation; either version 2 of the License, or
9*3d8817e4Smiod    (at your option) any later version.
10*3d8817e4Smiod 
11*3d8817e4Smiod    This program is distributed in the hope that it will be useful,
12*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*3d8817e4Smiod    GNU General Public License for more details.
15*3d8817e4Smiod 
16*3d8817e4Smiod    You should have received a copy of the GNU General Public License
17*3d8817e4Smiod    along with this program; if not, write to the Free Software
18*3d8817e4Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19*3d8817e4Smiod    MA 02110-1301, USA.  */
20*3d8817e4Smiod 
21*3d8817e4Smiod #include <setjmp.h>
22*3d8817e4Smiod #include <string.h>
23*3d8817e4Smiod #include "sysdep.h"
24*3d8817e4Smiod #include "opcode/vax.h"
25*3d8817e4Smiod #include "dis-asm.h"
26*3d8817e4Smiod 
27*3d8817e4Smiod static char *reg_names[] =
28*3d8817e4Smiod {
29*3d8817e4Smiod   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
30*3d8817e4Smiod   "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc"
31*3d8817e4Smiod };
32*3d8817e4Smiod 
33*3d8817e4Smiod /* Definitions for the function entry mask bits.  */
34*3d8817e4Smiod static char *entry_mask_bit[] =
35*3d8817e4Smiod {
36*3d8817e4Smiod   /* Registers 0 and 1 shall not be saved, since they're used to pass back
37*3d8817e4Smiod      a function's result to its caller...  */
38*3d8817e4Smiod   "~r0~", "~r1~",
39*3d8817e4Smiod   /* Registers 2 .. 11 are normal registers.  */
40*3d8817e4Smiod   "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
41*3d8817e4Smiod   /* Registers 12 and 13 are argument and frame pointer and must not
42*3d8817e4Smiod      be saved by using the entry mask.  */
43*3d8817e4Smiod   "~ap~", "~fp~",
44*3d8817e4Smiod   /* Bits 14 and 15 control integer and decimal overflow.  */
45*3d8817e4Smiod   "IntOvfl", "DecOvfl",
46*3d8817e4Smiod };
47*3d8817e4Smiod 
48*3d8817e4Smiod /* Sign-extend an (unsigned char). */
49*3d8817e4Smiod #define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
50*3d8817e4Smiod 
51*3d8817e4Smiod /* Get a 1 byte signed integer.  */
52*3d8817e4Smiod #define NEXTBYTE(p)  \
53*3d8817e4Smiod   (p += 1, FETCH_DATA (info, p), \
54*3d8817e4Smiod   COERCE_SIGNED_CHAR(p[-1]))
55*3d8817e4Smiod 
56*3d8817e4Smiod /* Get a 2 byte signed integer.  */
57*3d8817e4Smiod #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
58*3d8817e4Smiod #define NEXTWORD(p)  \
59*3d8817e4Smiod   (p += 2, FETCH_DATA (info, p), \
60*3d8817e4Smiod    COERCE16 ((p[-1] << 8) + p[-2]))
61*3d8817e4Smiod 
62*3d8817e4Smiod /* Get a 4 byte signed integer.  */
63*3d8817e4Smiod #define COERCE32(x) ((int) (((x) ^ 0x80000000) - 0x80000000))
64*3d8817e4Smiod #define NEXTLONG(p)  \
65*3d8817e4Smiod   (p += 4, FETCH_DATA (info, p), \
66*3d8817e4Smiod    (COERCE32 ((((((p[-1] << 8) + p[-2]) << 8) + p[-3]) << 8) + p[-4])))
67*3d8817e4Smiod 
68*3d8817e4Smiod /* Maximum length of an instruction.  */
69*3d8817e4Smiod #define MAXLEN 25
70*3d8817e4Smiod 
71*3d8817e4Smiod struct private
72*3d8817e4Smiod {
73*3d8817e4Smiod   /* Points to first byte not fetched.  */
74*3d8817e4Smiod   bfd_byte * max_fetched;
75*3d8817e4Smiod   bfd_byte   the_buffer[MAXLEN];
76*3d8817e4Smiod   bfd_vma    insn_start;
77*3d8817e4Smiod   jmp_buf    bailout;
78*3d8817e4Smiod };
79*3d8817e4Smiod 
80*3d8817e4Smiod /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
81*3d8817e4Smiod    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
82*3d8817e4Smiod    on error.  */
83*3d8817e4Smiod #define FETCH_DATA(info, addr) \
84*3d8817e4Smiod   ((addr) <= ((struct private *)(info->private_data))->max_fetched \
85*3d8817e4Smiod    ? 1 : fetch_data ((info), (addr)))
86*3d8817e4Smiod 
87*3d8817e4Smiod static int
fetch_data(struct disassemble_info * info,bfd_byte * addr)88*3d8817e4Smiod fetch_data (struct disassemble_info *info, bfd_byte *addr)
89*3d8817e4Smiod {
90*3d8817e4Smiod   int status;
91*3d8817e4Smiod   struct private *priv = (struct private *) info->private_data;
92*3d8817e4Smiod   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
93*3d8817e4Smiod 
94*3d8817e4Smiod   status = (*info->read_memory_func) (start,
95*3d8817e4Smiod 				      priv->max_fetched,
96*3d8817e4Smiod 				      addr - priv->max_fetched,
97*3d8817e4Smiod 				      info);
98*3d8817e4Smiod   if (status != 0)
99*3d8817e4Smiod     {
100*3d8817e4Smiod       (*info->memory_error_func) (status, start, info);
101*3d8817e4Smiod       longjmp (priv->bailout, 1);
102*3d8817e4Smiod     }
103*3d8817e4Smiod   else
104*3d8817e4Smiod     priv->max_fetched = addr;
105*3d8817e4Smiod 
106*3d8817e4Smiod   return 1;
107*3d8817e4Smiod }
108*3d8817e4Smiod 
109*3d8817e4Smiod /* Entry mask handling.  */
110*3d8817e4Smiod static unsigned int  entry_addr_occupied_slots = 0;
111*3d8817e4Smiod static unsigned int  entry_addr_total_slots = 0;
112*3d8817e4Smiod static bfd_vma *     entry_addr = NULL;
113*3d8817e4Smiod 
114*3d8817e4Smiod /* Parse the VAX specific disassembler options.  These contain function
115*3d8817e4Smiod    entry addresses, which can be useful to disassemble ROM images, since
116*3d8817e4Smiod    there's no symbol table.  Returns TRUE upon success, FALSE otherwise.  */
117*3d8817e4Smiod 
118*3d8817e4Smiod static bfd_boolean
parse_disassembler_options(char * options)119*3d8817e4Smiod parse_disassembler_options (char * options)
120*3d8817e4Smiod {
121*3d8817e4Smiod   const char * entry_switch = "entry:";
122*3d8817e4Smiod 
123*3d8817e4Smiod   while ((options = strstr (options, entry_switch)))
124*3d8817e4Smiod     {
125*3d8817e4Smiod       options += strlen (entry_switch);
126*3d8817e4Smiod 
127*3d8817e4Smiod       /* The greater-than part of the test below is paranoia.  */
128*3d8817e4Smiod       if (entry_addr_occupied_slots >= entry_addr_total_slots)
129*3d8817e4Smiod 	{
130*3d8817e4Smiod 	  /* A guesstimate of the number of entries we will have to create.  */
131*3d8817e4Smiod 	  entry_addr_total_slots +=
132*3d8817e4Smiod 	    strlen (options) / (strlen (entry_switch) + 5);
133*3d8817e4Smiod 
134*3d8817e4Smiod 	  entry_addr = realloc (entry_addr, sizeof (bfd_vma)
135*3d8817e4Smiod 				* entry_addr_total_slots);
136*3d8817e4Smiod 	}
137*3d8817e4Smiod 
138*3d8817e4Smiod       if (entry_addr == NULL)
139*3d8817e4Smiod 	return FALSE;
140*3d8817e4Smiod 
141*3d8817e4Smiod       entry_addr[entry_addr_occupied_slots] = bfd_scan_vma (options, NULL, 0);
142*3d8817e4Smiod       entry_addr_occupied_slots ++;
143*3d8817e4Smiod     }
144*3d8817e4Smiod 
145*3d8817e4Smiod   return TRUE;
146*3d8817e4Smiod }
147*3d8817e4Smiod 
148*3d8817e4Smiod #if 0 /* FIXME:  Ideally the disassembler should have target specific
149*3d8817e4Smiod 	 initialisation and termination function pointers.  Then
150*3d8817e4Smiod 	 parse_disassembler_options could be the init function and
151*3d8817e4Smiod 	 free_entry_array (below) could be the termination routine.
152*3d8817e4Smiod 	 Until then there is no way for the disassembler to tell us
153*3d8817e4Smiod 	 that it has finished and that we no longer need the entry
154*3d8817e4Smiod 	 array, so this routine is suppressed for now.  It does mean
155*3d8817e4Smiod 	 that we leak memory, but only to the extent that we do not
156*3d8817e4Smiod 	 free it just before the disassembler is about to terminate
157*3d8817e4Smiod 	 anyway.  */
158*3d8817e4Smiod 
159*3d8817e4Smiod /* Free memory allocated to our entry array.  */
160*3d8817e4Smiod 
161*3d8817e4Smiod static void
162*3d8817e4Smiod free_entry_array (void)
163*3d8817e4Smiod {
164*3d8817e4Smiod   if (entry_addr)
165*3d8817e4Smiod     {
166*3d8817e4Smiod       free (entry_addr);
167*3d8817e4Smiod       entry_addr = NULL;
168*3d8817e4Smiod       entry_addr_occupied_slots = entry_addr_total_slots = 0;
169*3d8817e4Smiod     }
170*3d8817e4Smiod }
171*3d8817e4Smiod #endif
172*3d8817e4Smiod /* Check if the given address is a known function entry. Either there must
173*3d8817e4Smiod    be a symbol of function type at this address, or the address must be
174*3d8817e4Smiod    a forced entry point.  The later helps in disassembling ROM images, because
175*3d8817e4Smiod    there's no symbol table at all.  Forced entry points can be given by
176*3d8817e4Smiod    supplying several -M options to objdump: -M entry:0xffbb7730.  */
177*3d8817e4Smiod 
178*3d8817e4Smiod static bfd_boolean
is_function_entry(struct disassemble_info * info,bfd_vma addr)179*3d8817e4Smiod is_function_entry (struct disassemble_info *info, bfd_vma addr)
180*3d8817e4Smiod {
181*3d8817e4Smiod   unsigned int i;
182*3d8817e4Smiod 
183*3d8817e4Smiod   /* Check if there's a BSF_FUNCTION symbol at our address.  */
184*3d8817e4Smiod   if (info->symbols
185*3d8817e4Smiod       && info->symbols[0]
186*3d8817e4Smiod       && (info->symbols[0]->flags & BSF_FUNCTION)
187*3d8817e4Smiod       && addr == bfd_asymbol_value (info->symbols[0]))
188*3d8817e4Smiod     return TRUE;
189*3d8817e4Smiod 
190*3d8817e4Smiod   /* Check for forced function entry address.  */
191*3d8817e4Smiod   for (i = entry_addr_occupied_slots; i--;)
192*3d8817e4Smiod     if (entry_addr[i] == addr)
193*3d8817e4Smiod       return TRUE;
194*3d8817e4Smiod 
195*3d8817e4Smiod   return FALSE;
196*3d8817e4Smiod }
197*3d8817e4Smiod 
198*3d8817e4Smiod static int
print_insn_mode(const char * d,int size,unsigned char * p0,bfd_vma addr,disassemble_info * info)199*3d8817e4Smiod print_insn_mode (const char *d,
200*3d8817e4Smiod 		 int size,
201*3d8817e4Smiod 		 unsigned char *p0,
202*3d8817e4Smiod 		 bfd_vma addr,	/* PC for this arg to be relative to.  */
203*3d8817e4Smiod 		 disassemble_info *info)
204*3d8817e4Smiod {
205*3d8817e4Smiod   unsigned char *p = p0;
206*3d8817e4Smiod   unsigned char mode, reg;
207*3d8817e4Smiod 
208*3d8817e4Smiod   /* Fetch and interpret mode byte.  */
209*3d8817e4Smiod   mode = (unsigned char) NEXTBYTE (p);
210*3d8817e4Smiod   reg = mode & 0xF;
211*3d8817e4Smiod   switch (mode & 0xF0)
212*3d8817e4Smiod     {
213*3d8817e4Smiod     case 0x00:
214*3d8817e4Smiod     case 0x10:
215*3d8817e4Smiod     case 0x20:
216*3d8817e4Smiod     case 0x30: /* Literal mode			$number.  */
217*3d8817e4Smiod       if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
218*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "$0x%x [%c-float]", mode, d[1]);
219*3d8817e4Smiod       else
220*3d8817e4Smiod         (*info->fprintf_func) (info->stream, "$0x%x", mode);
221*3d8817e4Smiod       break;
222*3d8817e4Smiod     case 0x40: /* Index:			base-addr[Rn] */
223*3d8817e4Smiod       p += print_insn_mode (d, size, p0 + 1, addr + 1, info);
224*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "[%s]", reg_names[reg]);
225*3d8817e4Smiod       break;
226*3d8817e4Smiod     case 0x50: /* Register:			Rn */
227*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%s", reg_names[reg]);
228*3d8817e4Smiod       break;
229*3d8817e4Smiod     case 0x60: /* Register deferred:		(Rn) */
230*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "(%s)", reg_names[reg]);
231*3d8817e4Smiod       break;
232*3d8817e4Smiod     case 0x70: /* Autodecrement:		-(Rn) */
233*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "-(%s)", reg_names[reg]);
234*3d8817e4Smiod       break;
235*3d8817e4Smiod     case 0x80: /* Autoincrement:		(Rn)+ */
236*3d8817e4Smiod       if (reg == 0xF)
237*3d8817e4Smiod 	{	/* Immediate?  */
238*3d8817e4Smiod 	  int i;
239*3d8817e4Smiod 
240*3d8817e4Smiod 	  FETCH_DATA (info, p + size);
241*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "$0x");
242*3d8817e4Smiod 	  if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
243*3d8817e4Smiod 	    {
244*3d8817e4Smiod 	      int float_word;
245*3d8817e4Smiod 
246*3d8817e4Smiod 	      float_word = p[0] | (p[1] << 8);
247*3d8817e4Smiod 	      if ((d[1] == 'd' || d[1] == 'f')
248*3d8817e4Smiod 		  && (float_word & 0xff80) == 0x8000)
249*3d8817e4Smiod 		{
250*3d8817e4Smiod 		  (*info->fprintf_func) (info->stream, "[invalid %c-float]",
251*3d8817e4Smiod 					 d[1]);
252*3d8817e4Smiod 		}
253*3d8817e4Smiod 	      else
254*3d8817e4Smiod 		{
255*3d8817e4Smiod 	          for (i = 0; i < size; i++)
256*3d8817e4Smiod 		    (*info->fprintf_func) (info->stream, "%02x",
257*3d8817e4Smiod 		                           p[size - i - 1]);
258*3d8817e4Smiod 	          (*info->fprintf_func) (info->stream, " [%c-float]", d[1]);
259*3d8817e4Smiod 		}
260*3d8817e4Smiod 	    }
261*3d8817e4Smiod 	  else
262*3d8817e4Smiod 	    {
263*3d8817e4Smiod 	      for (i = 0; i < size; i++)
264*3d8817e4Smiod 	        (*info->fprintf_func) (info->stream, "%02x", p[size - i - 1]);
265*3d8817e4Smiod 	    }
266*3d8817e4Smiod 	  p += size;
267*3d8817e4Smiod 	}
268*3d8817e4Smiod       else
269*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "(%s)+", reg_names[reg]);
270*3d8817e4Smiod       break;
271*3d8817e4Smiod     case 0x90: /* Autoincrement deferred:	@(Rn)+ */
272*3d8817e4Smiod       if (reg == 0xF)
273*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "*0x%x", NEXTLONG (p));
274*3d8817e4Smiod       else
275*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "@(%s)+", reg_names[reg]);
276*3d8817e4Smiod       break;
277*3d8817e4Smiod     case 0xB0: /* Displacement byte deferred:	*displ(Rn).  */
278*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "*");
279*3d8817e4Smiod     case 0xA0: /* Displacement byte:		displ(Rn).  */
280*3d8817e4Smiod       if (reg == 0xF)
281*3d8817e4Smiod 	(*info->print_address_func) (addr + 2 + NEXTBYTE (p), info);
282*3d8817e4Smiod       else
283*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTBYTE (p),
284*3d8817e4Smiod 			       reg_names[reg]);
285*3d8817e4Smiod       break;
286*3d8817e4Smiod     case 0xD0: /* Displacement word deferred:	*displ(Rn).  */
287*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "*");
288*3d8817e4Smiod     case 0xC0: /* Displacement word:		displ(Rn).  */
289*3d8817e4Smiod       if (reg == 0xF)
290*3d8817e4Smiod 	(*info->print_address_func) (addr + 3 + NEXTWORD (p), info);
291*3d8817e4Smiod       else
292*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTWORD (p),
293*3d8817e4Smiod 			       reg_names[reg]);
294*3d8817e4Smiod       break;
295*3d8817e4Smiod     case 0xF0: /* Displacement long deferred:	*displ(Rn).  */
296*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "*");
297*3d8817e4Smiod     case 0xE0: /* Displacement long:		displ(Rn).  */
298*3d8817e4Smiod       if (reg == 0xF)
299*3d8817e4Smiod 	(*info->print_address_func) (addr + 5 + NEXTLONG (p), info);
300*3d8817e4Smiod       else
301*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTLONG (p),
302*3d8817e4Smiod 			       reg_names[reg]);
303*3d8817e4Smiod       break;
304*3d8817e4Smiod     }
305*3d8817e4Smiod 
306*3d8817e4Smiod   return p - p0;
307*3d8817e4Smiod }
308*3d8817e4Smiod 
309*3d8817e4Smiod /* Returns number of bytes "eaten" by the operand, or return -1 if an
310*3d8817e4Smiod    invalid operand was found, or -2 if an opcode tabel error was
311*3d8817e4Smiod    found. */
312*3d8817e4Smiod 
313*3d8817e4Smiod static int
print_insn_arg(const char * d,unsigned char * p0,bfd_vma addr,disassemble_info * info)314*3d8817e4Smiod print_insn_arg (const char *d,
315*3d8817e4Smiod 		unsigned char *p0,
316*3d8817e4Smiod 		bfd_vma addr,	/* PC for this arg to be relative to.  */
317*3d8817e4Smiod 		disassemble_info *info)
318*3d8817e4Smiod {
319*3d8817e4Smiod   int arg_len;
320*3d8817e4Smiod 
321*3d8817e4Smiod   /* Check validity of addressing length.  */
322*3d8817e4Smiod   switch (d[1])
323*3d8817e4Smiod     {
324*3d8817e4Smiod     case 'b' : arg_len = 1;	break;
325*3d8817e4Smiod     case 'd' : arg_len = 8;	break;
326*3d8817e4Smiod     case 'f' : arg_len = 4;	break;
327*3d8817e4Smiod     case 'g' : arg_len = 8;	break;
328*3d8817e4Smiod     case 'h' : arg_len = 16;	break;
329*3d8817e4Smiod     case 'l' : arg_len = 4;	break;
330*3d8817e4Smiod     case 'o' : arg_len = 16;	break;
331*3d8817e4Smiod     case 'w' : arg_len = 2;	break;
332*3d8817e4Smiod     case 'q' : arg_len = 8;	break;
333*3d8817e4Smiod     default  : abort ();
334*3d8817e4Smiod     }
335*3d8817e4Smiod 
336*3d8817e4Smiod   /* Branches have no mode byte.  */
337*3d8817e4Smiod   if (d[0] == 'b')
338*3d8817e4Smiod     {
339*3d8817e4Smiod       unsigned char *p = p0;
340*3d8817e4Smiod 
341*3d8817e4Smiod       if (arg_len == 1)
342*3d8817e4Smiod 	(*info->print_address_func) (addr + 1 + NEXTBYTE (p), info);
343*3d8817e4Smiod       else
344*3d8817e4Smiod 	(*info->print_address_func) (addr + 2 + NEXTWORD (p), info);
345*3d8817e4Smiod 
346*3d8817e4Smiod       return p - p0;
347*3d8817e4Smiod     }
348*3d8817e4Smiod 
349*3d8817e4Smiod   return print_insn_mode (d, arg_len, p0, addr, info);
350*3d8817e4Smiod }
351*3d8817e4Smiod 
352*3d8817e4Smiod /* Print the vax instruction at address MEMADDR in debugged memory,
353*3d8817e4Smiod    on INFO->STREAM.  Returns length of the instruction, in bytes.  */
354*3d8817e4Smiod 
355*3d8817e4Smiod int
print_insn_vax(bfd_vma memaddr,disassemble_info * info)356*3d8817e4Smiod print_insn_vax (bfd_vma memaddr, disassemble_info *info)
357*3d8817e4Smiod {
358*3d8817e4Smiod   static bfd_boolean parsed_disassembler_options = FALSE;
359*3d8817e4Smiod   const struct vot *votp;
360*3d8817e4Smiod   const char *argp;
361*3d8817e4Smiod   unsigned char *arg;
362*3d8817e4Smiod   struct private priv;
363*3d8817e4Smiod   bfd_byte *buffer = priv.the_buffer;
364*3d8817e4Smiod 
365*3d8817e4Smiod   info->private_data = & priv;
366*3d8817e4Smiod   priv.max_fetched = priv.the_buffer;
367*3d8817e4Smiod   priv.insn_start = memaddr;
368*3d8817e4Smiod 
369*3d8817e4Smiod   if (! parsed_disassembler_options
370*3d8817e4Smiod       && info->disassembler_options != NULL)
371*3d8817e4Smiod     {
372*3d8817e4Smiod       parse_disassembler_options (info->disassembler_options);
373*3d8817e4Smiod 
374*3d8817e4Smiod       /* To avoid repeated parsing of these options.  */
375*3d8817e4Smiod       parsed_disassembler_options = TRUE;
376*3d8817e4Smiod     }
377*3d8817e4Smiod 
378*3d8817e4Smiod   if (setjmp (priv.bailout) != 0)
379*3d8817e4Smiod     /* Error return.  */
380*3d8817e4Smiod     return -1;
381*3d8817e4Smiod 
382*3d8817e4Smiod   argp = NULL;
383*3d8817e4Smiod   /* Check if the info buffer has more than one byte left since
384*3d8817e4Smiod      the last opcode might be a single byte with no argument data.  */
385*3d8817e4Smiod   if (info->buffer_length - (memaddr - info->buffer_vma) > 1)
386*3d8817e4Smiod     {
387*3d8817e4Smiod       FETCH_DATA (info, buffer + 2);
388*3d8817e4Smiod     }
389*3d8817e4Smiod   else
390*3d8817e4Smiod     {
391*3d8817e4Smiod       FETCH_DATA (info, buffer + 1);
392*3d8817e4Smiod       buffer[1] = 0;
393*3d8817e4Smiod     }
394*3d8817e4Smiod 
395*3d8817e4Smiod   /* Decode function entry mask.  */
396*3d8817e4Smiod   if (is_function_entry (info, memaddr))
397*3d8817e4Smiod     {
398*3d8817e4Smiod       int i = 0;
399*3d8817e4Smiod       int register_mask = buffer[1] << 8 | buffer[0];
400*3d8817e4Smiod 
401*3d8817e4Smiod       (*info->fprintf_func) (info->stream, ".word 0x%04x # Entry mask: <",
402*3d8817e4Smiod 			     register_mask);
403*3d8817e4Smiod 
404*3d8817e4Smiod       for (i = 15; i >= 0; i--)
405*3d8817e4Smiod 	if (register_mask & (1 << i))
406*3d8817e4Smiod           (*info->fprintf_func) (info->stream, " %s", entry_mask_bit[i]);
407*3d8817e4Smiod 
408*3d8817e4Smiod       (*info->fprintf_func) (info->stream, " >");
409*3d8817e4Smiod 
410*3d8817e4Smiod       return 2;
411*3d8817e4Smiod     }
412*3d8817e4Smiod 
413*3d8817e4Smiod   for (votp = &votstrs[0]; votp->name[0]; votp++)
414*3d8817e4Smiod     {
415*3d8817e4Smiod       vax_opcodeT opcode = votp->detail.code;
416*3d8817e4Smiod 
417*3d8817e4Smiod       /* 2 byte codes match 2 buffer pos. */
418*3d8817e4Smiod       if ((bfd_byte) opcode == buffer[0]
419*3d8817e4Smiod 	  && (opcode >> 8 == 0 || opcode >> 8 == buffer[1]))
420*3d8817e4Smiod 	{
421*3d8817e4Smiod 	  argp = votp->detail.args;
422*3d8817e4Smiod 	  break;
423*3d8817e4Smiod 	}
424*3d8817e4Smiod     }
425*3d8817e4Smiod   if (argp == NULL)
426*3d8817e4Smiod     {
427*3d8817e4Smiod       /* Handle undefined instructions. */
428*3d8817e4Smiod       (*info->fprintf_func) (info->stream, ".word 0x%x",
429*3d8817e4Smiod 			     (buffer[0] << 8) + buffer[1]);
430*3d8817e4Smiod       return 2;
431*3d8817e4Smiod     }
432*3d8817e4Smiod 
433*3d8817e4Smiod   /* Point at first byte of argument data, and at descriptor for first
434*3d8817e4Smiod      argument.  */
435*3d8817e4Smiod   arg = buffer + ((votp->detail.code >> 8) ? 2 : 1);
436*3d8817e4Smiod 
437*3d8817e4Smiod   /* Make sure we have it in mem */
438*3d8817e4Smiod   FETCH_DATA (info, arg);
439*3d8817e4Smiod 
440*3d8817e4Smiod   (*info->fprintf_func) (info->stream, "%s", votp->name);
441*3d8817e4Smiod   if (*argp)
442*3d8817e4Smiod     (*info->fprintf_func) (info->stream, " ");
443*3d8817e4Smiod 
444*3d8817e4Smiod   while (*argp)
445*3d8817e4Smiod     {
446*3d8817e4Smiod       arg += print_insn_arg (argp, arg, memaddr + arg - buffer, info);
447*3d8817e4Smiod       argp += 2;
448*3d8817e4Smiod       if (*argp)
449*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, ",");
450*3d8817e4Smiod     }
451*3d8817e4Smiod 
452*3d8817e4Smiod   return arg - buffer;
453*3d8817e4Smiod }
454*3d8817e4Smiod 
455