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