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