xref: /netbsd-src/external/gpl3/binutils.old/dist/opcodes/vax-dis.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* Print VAX instructions.
2*e992f068Schristos    Copyright (C) 1995-2022 Free Software Foundation, Inc.
375fd0b74Schristos    Contributed by Pauline Middelink <middelin@polyware.iaf.nl>
475fd0b74Schristos 
575fd0b74Schristos    This file is part of the GNU opcodes library.
675fd0b74Schristos 
775fd0b74Schristos    This library is free software; you can redistribute it and/or modify
875fd0b74Schristos    it under the terms of the GNU General Public License as published by
975fd0b74Schristos    the Free Software Foundation; either version 3, or (at your option)
1075fd0b74Schristos    any later version.
1175fd0b74Schristos 
1275fd0b74Schristos    It is distributed in the hope that it will be useful, but WITHOUT
1375fd0b74Schristos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1475fd0b74Schristos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1575fd0b74Schristos    License for more details.
1675fd0b74Schristos 
1775fd0b74Schristos    You should have received a copy of the GNU General Public License
1875fd0b74Schristos    along with this program; if not, write to the Free Software
1975fd0b74Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
2075fd0b74Schristos    MA 02110-1301, USA.  */
2175fd0b74Schristos 
2275fd0b74Schristos #include "sysdep.h"
2375fd0b74Schristos #include <setjmp.h>
2475fd0b74Schristos #include <string.h>
2575fd0b74Schristos #include "opcode/vax.h"
26ede78133Schristos #include "disassemble.h"
2775fd0b74Schristos 
2875fd0b74Schristos static char *reg_names[] =
2975fd0b74Schristos {
3075fd0b74Schristos   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
3175fd0b74Schristos   "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc"
3275fd0b74Schristos };
3375fd0b74Schristos 
3475fd0b74Schristos /* Definitions for the function entry mask bits.  */
3575fd0b74Schristos static char *entry_mask_bit[] =
3675fd0b74Schristos {
3775fd0b74Schristos   /* Registers 0 and 1 shall not be saved, since they're used to pass back
3875fd0b74Schristos      a function's result to its caller...  */
3975fd0b74Schristos   "~r0~", "~r1~",
4075fd0b74Schristos   /* Registers 2 .. 11 are normal registers.  */
4175fd0b74Schristos   "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
4275fd0b74Schristos   /* Registers 12 and 13 are argument and frame pointer and must not
4375fd0b74Schristos      be saved by using the entry mask.  */
4475fd0b74Schristos   "~ap~", "~fp~",
4575fd0b74Schristos   /* Bits 14 and 15 control integer and decimal overflow.  */
4675fd0b74Schristos   "IntOvfl", "DecOvfl",
4775fd0b74Schristos };
4875fd0b74Schristos 
4975fd0b74Schristos /* Sign-extend an (unsigned char). */
5075fd0b74Schristos #define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
5175fd0b74Schristos 
5275fd0b74Schristos /* Get a 1 byte signed integer.  */
5375fd0b74Schristos #define NEXTBYTE(p)  \
5475fd0b74Schristos   (p += 1, FETCH_DATA (info, p), \
5575fd0b74Schristos   COERCE_SIGNED_CHAR(p[-1]))
5675fd0b74Schristos 
5775fd0b74Schristos /* Get a 2 byte signed integer.  */
5875fd0b74Schristos #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
5975fd0b74Schristos #define NEXTWORD(p)  \
6075fd0b74Schristos   (p += 2, FETCH_DATA (info, p), \
6175fd0b74Schristos    COERCE16 ((p[-1] << 8) + p[-2]))
6275fd0b74Schristos 
6375fd0b74Schristos /* Get a 4 byte signed integer.  */
6475fd0b74Schristos #define COERCE32(x) ((int) (((x) ^ 0x80000000) - 0x80000000))
6575fd0b74Schristos #define NEXTLONG(p)  \
6675fd0b74Schristos   (p += 4, FETCH_DATA (info, p), \
67012573ebSchristos    (COERCE32 (((((((unsigned) p[-1] << 8) + p[-2]) << 8) + p[-3]) << 8) + p[-4])))
6875fd0b74Schristos 
6975fd0b74Schristos /* Maximum length of an instruction.  */
7075fd0b74Schristos #define MAXLEN 25
7175fd0b74Schristos 
7275fd0b74Schristos struct private
7375fd0b74Schristos {
7475fd0b74Schristos   /* Points to first byte not fetched.  */
7575fd0b74Schristos   bfd_byte * max_fetched;
7675fd0b74Schristos   bfd_byte   the_buffer[MAXLEN];
7775fd0b74Schristos   bfd_vma    insn_start;
7875fd0b74Schristos   OPCODES_SIGJMP_BUF    bailout;
7975fd0b74Schristos };
8075fd0b74Schristos 
8175fd0b74Schristos /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
8275fd0b74Schristos    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
8375fd0b74Schristos    on error.  */
8475fd0b74Schristos #define FETCH_DATA(info, addr) \
8575fd0b74Schristos   ((addr) <= ((struct private *)(info->private_data))->max_fetched \
8675fd0b74Schristos    ? 1 : fetch_data ((info), (addr)))
8775fd0b74Schristos 
8875fd0b74Schristos static int
fetch_data(struct disassemble_info * info,bfd_byte * addr)8975fd0b74Schristos fetch_data (struct disassemble_info *info, bfd_byte *addr)
9075fd0b74Schristos {
9175fd0b74Schristos   int status;
9275fd0b74Schristos   struct private *priv = (struct private *) info->private_data;
9375fd0b74Schristos   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
9475fd0b74Schristos 
9575fd0b74Schristos   status = (*info->read_memory_func) (start,
9675fd0b74Schristos 				      priv->max_fetched,
9775fd0b74Schristos 				      addr - priv->max_fetched,
9875fd0b74Schristos 				      info);
9975fd0b74Schristos   if (status != 0)
10075fd0b74Schristos     {
10175fd0b74Schristos       (*info->memory_error_func) (status, start, info);
10275fd0b74Schristos       OPCODES_SIGLONGJMP (priv->bailout, 1);
10375fd0b74Schristos     }
10475fd0b74Schristos   else
10575fd0b74Schristos     priv->max_fetched = addr;
10675fd0b74Schristos 
10775fd0b74Schristos   return 1;
10875fd0b74Schristos }
10975fd0b74Schristos 
11075fd0b74Schristos /* Entry mask handling.  */
11175fd0b74Schristos static unsigned int  entry_addr_occupied_slots = 0;
11275fd0b74Schristos static unsigned int  entry_addr_total_slots = 0;
11375fd0b74Schristos static bfd_vma *     entry_addr = NULL;
11475fd0b74Schristos 
11575fd0b74Schristos /* Parse the VAX specific disassembler options.  These contain function
11675fd0b74Schristos    entry addresses, which can be useful to disassemble ROM images, since
11775fd0b74Schristos    there's no symbol table.  Returns TRUE upon success, FALSE otherwise.  */
11875fd0b74Schristos 
119*e992f068Schristos static bool
parse_disassembler_options(const char * options)120ede78133Schristos parse_disassembler_options (const char *options)
12175fd0b74Schristos {
12275fd0b74Schristos   const char * entry_switch = "entry:";
12375fd0b74Schristos 
12475fd0b74Schristos   while ((options = strstr (options, entry_switch)))
12575fd0b74Schristos     {
12675fd0b74Schristos       options += strlen (entry_switch);
12775fd0b74Schristos 
12875fd0b74Schristos       /* The greater-than part of the test below is paranoia.  */
12975fd0b74Schristos       if (entry_addr_occupied_slots >= entry_addr_total_slots)
13075fd0b74Schristos 	{
13175fd0b74Schristos 	  /* A guesstimate of the number of entries we will have to create.  */
132*e992f068Schristos 	  entry_addr_total_slots
133*e992f068Schristos 	    += 1 + strlen (options) / (strlen (entry_switch) + 5);
13475fd0b74Schristos 
13575fd0b74Schristos 	  entry_addr = realloc (entry_addr, sizeof (bfd_vma)
13675fd0b74Schristos 				* entry_addr_total_slots);
13775fd0b74Schristos 	}
13875fd0b74Schristos 
13975fd0b74Schristos       if (entry_addr == NULL)
140*e992f068Schristos 	return false;
14175fd0b74Schristos 
14275fd0b74Schristos       entry_addr[entry_addr_occupied_slots] = bfd_scan_vma (options, NULL, 0);
14375fd0b74Schristos       entry_addr_occupied_slots ++;
14475fd0b74Schristos     }
14575fd0b74Schristos 
146*e992f068Schristos   return true;
14775fd0b74Schristos }
14875fd0b74Schristos 
14975fd0b74Schristos #if 0 /* FIXME:  Ideally the disassembler should have target specific
15075fd0b74Schristos 	 initialisation and termination function pointers.  Then
15175fd0b74Schristos 	 parse_disassembler_options could be the init function and
15275fd0b74Schristos 	 free_entry_array (below) could be the termination routine.
15375fd0b74Schristos 	 Until then there is no way for the disassembler to tell us
15475fd0b74Schristos 	 that it has finished and that we no longer need the entry
15575fd0b74Schristos 	 array, so this routine is suppressed for now.  It does mean
15675fd0b74Schristos 	 that we leak memory, but only to the extent that we do not
15775fd0b74Schristos 	 free it just before the disassembler is about to terminate
15875fd0b74Schristos 	 anyway.  */
15975fd0b74Schristos 
16075fd0b74Schristos /* Free memory allocated to our entry array.  */
16175fd0b74Schristos 
16275fd0b74Schristos static void
16375fd0b74Schristos free_entry_array (void)
16475fd0b74Schristos {
16575fd0b74Schristos   if (entry_addr)
16675fd0b74Schristos     {
16775fd0b74Schristos       free (entry_addr);
16875fd0b74Schristos       entry_addr = NULL;
16975fd0b74Schristos       entry_addr_occupied_slots = entry_addr_total_slots = 0;
17075fd0b74Schristos     }
17175fd0b74Schristos }
17275fd0b74Schristos #endif
17375fd0b74Schristos /* Check if the given address is a known function entry point.  This is
17475fd0b74Schristos    the case if there is a symbol of the function type at this address.
17575fd0b74Schristos    We also check for synthetic symbols as these are used for PLT entries
17675fd0b74Schristos    (weak undefined symbols may not have the function type set).  Finally
17775fd0b74Schristos    the address may have been forced to be treated as an entry point.  The
17875fd0b74Schristos    latter helps in disassembling ROM images, because there's no symbol
17975fd0b74Schristos    table at all.  Forced entry points can be given by supplying several
18075fd0b74Schristos    -M options to objdump: -M entry:0xffbb7730.  */
18175fd0b74Schristos 
182*e992f068Schristos static bool
is_function_entry(struct disassemble_info * info,bfd_vma addr)18375fd0b74Schristos is_function_entry (struct disassemble_info *info, bfd_vma addr)
18475fd0b74Schristos {
18575fd0b74Schristos   unsigned int i;
18675fd0b74Schristos 
18775fd0b74Schristos   /* Check if there's a function or PLT symbol at our address.  */
18875fd0b74Schristos   if (info->symbols
18975fd0b74Schristos       && info->symbols[0]
19075fd0b74Schristos       && (info->symbols[0]->flags & (BSF_FUNCTION | BSF_SYNTHETIC))
19175fd0b74Schristos       && addr == bfd_asymbol_value (info->symbols[0]))
192*e992f068Schristos     return true;
19375fd0b74Schristos 
19475fd0b74Schristos   /* Check for forced function entry address.  */
19575fd0b74Schristos   for (i = entry_addr_occupied_slots; i--;)
19675fd0b74Schristos     if (entry_addr[i] == addr)
197*e992f068Schristos       return true;
19875fd0b74Schristos 
199*e992f068Schristos   return false;
20075fd0b74Schristos }
20175fd0b74Schristos 
20275fd0b74Schristos /* Check if the given address is the last longword of a PLT entry.
20375fd0b74Schristos    This longword is data and depending on the value it may interfere
20475fd0b74Schristos    with disassembly of further PLT entries.  We make use of the fact
20575fd0b74Schristos    PLT symbols are marked BSF_SYNTHETIC.  */
206*e992f068Schristos static bool
is_plt_tail(struct disassemble_info * info,bfd_vma addr)20775fd0b74Schristos is_plt_tail (struct disassemble_info *info, bfd_vma addr)
20875fd0b74Schristos {
20975fd0b74Schristos   if (info->symbols
21075fd0b74Schristos       && info->symbols[0]
21175fd0b74Schristos       && (info->symbols[0]->flags & BSF_SYNTHETIC)
21275fd0b74Schristos       && addr == bfd_asymbol_value (info->symbols[0]) + 8)
213*e992f068Schristos     return true;
21475fd0b74Schristos 
215*e992f068Schristos   return false;
21675fd0b74Schristos }
21775fd0b74Schristos 
21875fd0b74Schristos static int
print_insn_mode(const char * d,int size,unsigned char * p0,bfd_vma addr,disassemble_info * info)21975fd0b74Schristos print_insn_mode (const char *d,
22075fd0b74Schristos 		 int size,
22175fd0b74Schristos 		 unsigned char *p0,
22275fd0b74Schristos 		 bfd_vma addr,	/* PC for this arg to be relative to.  */
22375fd0b74Schristos 		 disassemble_info *info)
22475fd0b74Schristos {
22575fd0b74Schristos   unsigned char *p = p0;
22675fd0b74Schristos   unsigned char mode, reg;
22775fd0b74Schristos 
22875fd0b74Schristos   /* Fetch and interpret mode byte.  */
22975fd0b74Schristos   mode = (unsigned char) NEXTBYTE (p);
23075fd0b74Schristos   reg = mode & 0xF;
23175fd0b74Schristos   switch (mode & 0xF0)
23275fd0b74Schristos     {
23375fd0b74Schristos     case 0x00:
23475fd0b74Schristos     case 0x10:
23575fd0b74Schristos     case 0x20:
23675fd0b74Schristos     case 0x30: /* Literal mode			$number.  */
23775fd0b74Schristos       if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
23875fd0b74Schristos 	(*info->fprintf_func) (info->stream, "$0x%x [%c-float]", mode, d[1]);
23975fd0b74Schristos       else
24075fd0b74Schristos         (*info->fprintf_func) (info->stream, "$0x%x", mode);
24175fd0b74Schristos       break;
24275fd0b74Schristos     case 0x40: /* Index:			base-addr[Rn] */
243012573ebSchristos       {
244012573ebSchristos 	unsigned char *q = p0 + 1;
245012573ebSchristos 	unsigned char nextmode = NEXTBYTE (q);
246012573ebSchristos 	if (nextmode < 0x60 || nextmode == 0x8f)
247012573ebSchristos 	  /* Literal, index, register, or immediate is invalid.  In
248012573ebSchristos 	     particular don't recurse into another index mode which
249012573ebSchristos 	     might overflow the_buffer.   */
250012573ebSchristos 	  (*info->fprintf_func) (info->stream, "[invalid base]");
251012573ebSchristos 	else
25275fd0b74Schristos 	  p += print_insn_mode (d, size, p0 + 1, addr + 1, info);
25375fd0b74Schristos 	(*info->fprintf_func) (info->stream, "[%s]", reg_names[reg]);
254012573ebSchristos       }
25575fd0b74Schristos       break;
25675fd0b74Schristos     case 0x50: /* Register:			Rn */
25775fd0b74Schristos       (*info->fprintf_func) (info->stream, "%s", reg_names[reg]);
25875fd0b74Schristos       break;
25975fd0b74Schristos     case 0x60: /* Register deferred:		(Rn) */
26075fd0b74Schristos       (*info->fprintf_func) (info->stream, "(%s)", reg_names[reg]);
26175fd0b74Schristos       break;
26275fd0b74Schristos     case 0x70: /* Autodecrement:		-(Rn) */
26375fd0b74Schristos       (*info->fprintf_func) (info->stream, "-(%s)", reg_names[reg]);
26475fd0b74Schristos       break;
26575fd0b74Schristos     case 0x80: /* Autoincrement:		(Rn)+ */
26675fd0b74Schristos       if (reg == 0xF)
26775fd0b74Schristos 	{	/* Immediate?  */
26875fd0b74Schristos 	  int i;
26975fd0b74Schristos 
27075fd0b74Schristos 	  FETCH_DATA (info, p + size);
27175fd0b74Schristos 	  (*info->fprintf_func) (info->stream, "$0x");
27275fd0b74Schristos 	  if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
27375fd0b74Schristos 	    {
27475fd0b74Schristos 	      int float_word;
27575fd0b74Schristos 
27675fd0b74Schristos 	      float_word = p[0] | (p[1] << 8);
27775fd0b74Schristos 	      if ((d[1] == 'd' || d[1] == 'f')
27875fd0b74Schristos 		  && (float_word & 0xff80) == 0x8000)
27975fd0b74Schristos 		{
28075fd0b74Schristos 		  (*info->fprintf_func) (info->stream, "[invalid %c-float]",
28175fd0b74Schristos 					 d[1]);
28275fd0b74Schristos 		}
28375fd0b74Schristos 	      else
28475fd0b74Schristos 		{
28575fd0b74Schristos 	          for (i = 0; i < size; i++)
28675fd0b74Schristos 		    (*info->fprintf_func) (info->stream, "%02x",
28775fd0b74Schristos 		                           p[size - i - 1]);
28875fd0b74Schristos 	          (*info->fprintf_func) (info->stream, " [%c-float]", d[1]);
28975fd0b74Schristos 		}
29075fd0b74Schristos 	    }
29175fd0b74Schristos 	  else
29275fd0b74Schristos 	    {
29375fd0b74Schristos 	      for (i = 0; i < size; i++)
29475fd0b74Schristos 	        (*info->fprintf_func) (info->stream, "%02x", p[size - i - 1]);
29575fd0b74Schristos 	    }
29675fd0b74Schristos 	  p += size;
29775fd0b74Schristos 	}
29875fd0b74Schristos       else
29975fd0b74Schristos 	(*info->fprintf_func) (info->stream, "(%s)+", reg_names[reg]);
30075fd0b74Schristos       break;
30175fd0b74Schristos     case 0x90: /* Autoincrement deferred:	@(Rn)+ */
30275fd0b74Schristos       if (reg == 0xF)
30375fd0b74Schristos 	(*info->fprintf_func) (info->stream, "*0x%x", NEXTLONG (p));
30475fd0b74Schristos       else
30575fd0b74Schristos 	(*info->fprintf_func) (info->stream, "@(%s)+", reg_names[reg]);
30675fd0b74Schristos       break;
30775fd0b74Schristos     case 0xB0: /* Displacement byte deferred:	*displ(Rn).  */
30875fd0b74Schristos       (*info->fprintf_func) (info->stream, "*");
309ede78133Schristos       /* Fall through.  */
31075fd0b74Schristos     case 0xA0: /* Displacement byte:		displ(Rn).  */
31175fd0b74Schristos       if (reg == 0xF)
31275fd0b74Schristos 	(*info->print_address_func) (addr + 2 + NEXTBYTE (p), info);
31375fd0b74Schristos       else
31475fd0b74Schristos 	(*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTBYTE (p),
31575fd0b74Schristos 			       reg_names[reg]);
31675fd0b74Schristos       break;
31775fd0b74Schristos     case 0xD0: /* Displacement word deferred:	*displ(Rn).  */
31875fd0b74Schristos       (*info->fprintf_func) (info->stream, "*");
319ede78133Schristos       /* Fall through.  */
32075fd0b74Schristos     case 0xC0: /* Displacement word:		displ(Rn).  */
32175fd0b74Schristos       if (reg == 0xF)
32275fd0b74Schristos 	(*info->print_address_func) (addr + 3 + NEXTWORD (p), info);
32375fd0b74Schristos       else
32475fd0b74Schristos 	(*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTWORD (p),
32575fd0b74Schristos 			       reg_names[reg]);
32675fd0b74Schristos       break;
32775fd0b74Schristos     case 0xF0: /* Displacement long deferred:	*displ(Rn).  */
32875fd0b74Schristos       (*info->fprintf_func) (info->stream, "*");
329ede78133Schristos       /* Fall through.  */
33075fd0b74Schristos     case 0xE0: /* Displacement long:		displ(Rn).  */
33175fd0b74Schristos       if (reg == 0xF)
33275fd0b74Schristos 	(*info->print_address_func) (addr + 5 + NEXTLONG (p), info);
33375fd0b74Schristos       else
33475fd0b74Schristos 	(*info->fprintf_func) (info->stream, "0x%x(%s)", NEXTLONG (p),
33575fd0b74Schristos 			       reg_names[reg]);
33675fd0b74Schristos       break;
33775fd0b74Schristos     }
33875fd0b74Schristos 
33975fd0b74Schristos   return p - p0;
34075fd0b74Schristos }
34175fd0b74Schristos 
34275fd0b74Schristos /* Returns number of bytes "eaten" by the operand, or return -1 if an
34375fd0b74Schristos    invalid operand was found, or -2 if an opcode tabel error was
34475fd0b74Schristos    found. */
34575fd0b74Schristos 
34675fd0b74Schristos static int
print_insn_arg(const char * d,unsigned char * p0,bfd_vma addr,disassemble_info * info)34775fd0b74Schristos print_insn_arg (const char *d,
34875fd0b74Schristos 		unsigned char *p0,
34975fd0b74Schristos 		bfd_vma addr,	/* PC for this arg to be relative to.  */
35075fd0b74Schristos 		disassemble_info *info)
35175fd0b74Schristos {
35275fd0b74Schristos   int arg_len;
35375fd0b74Schristos 
35475fd0b74Schristos   /* Check validity of addressing length.  */
35575fd0b74Schristos   switch (d[1])
35675fd0b74Schristos     {
35775fd0b74Schristos     case 'b' : arg_len = 1;	break;
35875fd0b74Schristos     case 'd' : arg_len = 8;	break;
35975fd0b74Schristos     case 'f' : arg_len = 4;	break;
36075fd0b74Schristos     case 'g' : arg_len = 8;	break;
36175fd0b74Schristos     case 'h' : arg_len = 16;	break;
36275fd0b74Schristos     case 'l' : arg_len = 4;	break;
36375fd0b74Schristos     case 'o' : arg_len = 16;	break;
36475fd0b74Schristos     case 'w' : arg_len = 2;	break;
36575fd0b74Schristos     case 'q' : arg_len = 8;	break;
36675fd0b74Schristos     default  : abort ();
36775fd0b74Schristos     }
36875fd0b74Schristos 
36975fd0b74Schristos   /* Branches have no mode byte.  */
37075fd0b74Schristos   if (d[0] == 'b')
37175fd0b74Schristos     {
37275fd0b74Schristos       unsigned char *p = p0;
37375fd0b74Schristos 
37475fd0b74Schristos       if (arg_len == 1)
37575fd0b74Schristos 	(*info->print_address_func) (addr + 1 + NEXTBYTE (p), info);
37675fd0b74Schristos       else
37775fd0b74Schristos 	(*info->print_address_func) (addr + 2 + NEXTWORD (p), info);
37875fd0b74Schristos 
37975fd0b74Schristos       return p - p0;
38075fd0b74Schristos     }
38175fd0b74Schristos 
38275fd0b74Schristos   return print_insn_mode (d, arg_len, p0, addr, info);
38375fd0b74Schristos }
38475fd0b74Schristos 
38575fd0b74Schristos /* Print the vax instruction at address MEMADDR in debugged memory,
38675fd0b74Schristos    on INFO->STREAM.  Returns length of the instruction, in bytes.  */
38775fd0b74Schristos 
38875fd0b74Schristos int
print_insn_vax(bfd_vma memaddr,disassemble_info * info)38975fd0b74Schristos print_insn_vax (bfd_vma memaddr, disassemble_info *info)
39075fd0b74Schristos {
391*e992f068Schristos   static bool parsed_disassembler_options = false;
39275fd0b74Schristos   const struct vot *votp;
39375fd0b74Schristos   const char *argp;
39475fd0b74Schristos   unsigned char *arg;
39575fd0b74Schristos   struct private priv;
39675fd0b74Schristos   bfd_byte *buffer = priv.the_buffer;
39775fd0b74Schristos 
39875fd0b74Schristos   info->private_data = & priv;
39975fd0b74Schristos   priv.max_fetched = priv.the_buffer;
40075fd0b74Schristos   priv.insn_start = memaddr;
40175fd0b74Schristos 
40275fd0b74Schristos   if (! parsed_disassembler_options
40375fd0b74Schristos       && info->disassembler_options != NULL)
40475fd0b74Schristos     {
40575fd0b74Schristos       parse_disassembler_options (info->disassembler_options);
40675fd0b74Schristos 
40775fd0b74Schristos       /* To avoid repeated parsing of these options.  */
408*e992f068Schristos       parsed_disassembler_options = true;
40975fd0b74Schristos     }
41075fd0b74Schristos 
41175fd0b74Schristos   if (OPCODES_SIGSETJMP (priv.bailout) != 0)
41275fd0b74Schristos     /* Error return.  */
41375fd0b74Schristos     return -1;
41475fd0b74Schristos 
41575fd0b74Schristos   argp = NULL;
41675fd0b74Schristos   /* Check if the info buffer has more than one byte left since
41775fd0b74Schristos      the last opcode might be a single byte with no argument data.  */
41875fd0b74Schristos   if (info->buffer_length - (memaddr - info->buffer_vma) > 1
41975fd0b74Schristos       && (info->stop_vma == 0 || memaddr < (info->stop_vma - 1)))
42075fd0b74Schristos     {
42175fd0b74Schristos       FETCH_DATA (info, buffer + 2);
42275fd0b74Schristos     }
42375fd0b74Schristos   else
42475fd0b74Schristos     {
42575fd0b74Schristos       FETCH_DATA (info, buffer + 1);
42675fd0b74Schristos       buffer[1] = 0;
42775fd0b74Schristos     }
42875fd0b74Schristos 
42975fd0b74Schristos   /* Decode function entry mask.  */
43075fd0b74Schristos   if (is_function_entry (info, memaddr))
43175fd0b74Schristos     {
43275fd0b74Schristos       int i = 0;
43375fd0b74Schristos       int register_mask = buffer[1] << 8 | buffer[0];
43475fd0b74Schristos 
43575fd0b74Schristos       (*info->fprintf_func) (info->stream, ".word 0x%04x # Entry mask: <",
43675fd0b74Schristos 			     register_mask);
43775fd0b74Schristos 
43875fd0b74Schristos       for (i = 15; i >= 0; i--)
43975fd0b74Schristos 	if (register_mask & (1 << i))
44075fd0b74Schristos           (*info->fprintf_func) (info->stream, " %s", entry_mask_bit[i]);
44175fd0b74Schristos 
44275fd0b74Schristos       (*info->fprintf_func) (info->stream, " >");
44375fd0b74Schristos 
44475fd0b74Schristos       return 2;
44575fd0b74Schristos     }
44675fd0b74Schristos 
44775fd0b74Schristos   /* Decode PLT entry offset longword.  */
44875fd0b74Schristos   if (is_plt_tail (info, memaddr))
44975fd0b74Schristos     {
45075fd0b74Schristos       int offset;
45175fd0b74Schristos 
45275fd0b74Schristos       FETCH_DATA (info, buffer + 4);
453012573ebSchristos       offset = ((unsigned) buffer[3] << 24 | buffer[2] << 16
454012573ebSchristos 		| buffer[1] << 8 | buffer[0]);
45575fd0b74Schristos       (*info->fprintf_func) (info->stream, ".long 0x%08x", offset);
45675fd0b74Schristos 
45775fd0b74Schristos       return 4;
45875fd0b74Schristos     }
45975fd0b74Schristos 
46075fd0b74Schristos   for (votp = &votstrs[0]; votp->name[0]; votp++)
46175fd0b74Schristos     {
46275fd0b74Schristos       vax_opcodeT opcode = votp->detail.code;
46375fd0b74Schristos 
46475fd0b74Schristos       /* 2 byte codes match 2 buffer pos. */
46575fd0b74Schristos       if ((bfd_byte) opcode == buffer[0]
46675fd0b74Schristos 	  && (opcode >> 8 == 0 || opcode >> 8 == buffer[1]))
46775fd0b74Schristos 	{
46875fd0b74Schristos 	  argp = votp->detail.args;
46975fd0b74Schristos 	  break;
47075fd0b74Schristos 	}
47175fd0b74Schristos     }
47275fd0b74Schristos   if (argp == NULL)
47375fd0b74Schristos     {
47475fd0b74Schristos       /* Handle undefined instructions. */
47575fd0b74Schristos       (*info->fprintf_func) (info->stream, ".word 0x%x",
47675fd0b74Schristos 			     (buffer[0] << 8) + buffer[1]);
47775fd0b74Schristos       return 2;
47875fd0b74Schristos     }
47975fd0b74Schristos 
48075fd0b74Schristos   /* Point at first byte of argument data, and at descriptor for first
48175fd0b74Schristos      argument.  */
48275fd0b74Schristos   arg = buffer + ((votp->detail.code >> 8) ? 2 : 1);
48375fd0b74Schristos 
48475fd0b74Schristos   /* Make sure we have it in mem */
48575fd0b74Schristos   FETCH_DATA (info, arg);
48675fd0b74Schristos 
48775fd0b74Schristos   (*info->fprintf_func) (info->stream, "%s", votp->name);
48875fd0b74Schristos   if (*argp)
48975fd0b74Schristos     (*info->fprintf_func) (info->stream, " ");
49075fd0b74Schristos 
49175fd0b74Schristos   while (*argp)
49275fd0b74Schristos     {
493*e992f068Schristos       arg += print_insn_arg (argp, arg, memaddr + (arg - buffer), info);
49475fd0b74Schristos       argp += 2;
49575fd0b74Schristos       if (*argp)
49675fd0b74Schristos 	(*info->fprintf_func) (info->stream, ",");
49775fd0b74Schristos     }
49875fd0b74Schristos 
49975fd0b74Schristos   return arg - buffer;
50075fd0b74Schristos }
50175fd0b74Schristos 
502