Home | History | Annotate | Download | only in opcodes
      1 /* pj-dis.c -- Disassemble picoJava instructions.
      2    Copyright (C) 1999-2016 Free Software Foundation, Inc.
      3    Contributed by Steve Chamberlain, of Transmeta (sac (at) pobox.com).
      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 <stdio.h>
     24 #include "opcode/pj.h"
     25 #include "dis-asm.h"
     26 
     27 extern const pj_opc_info_t pj_opc_info[512];
     28 
     29 static int
     30 get_int (bfd_vma memaddr, int *iptr, struct disassemble_info *info)
     31 {
     32   unsigned char ival[4];
     33   int status = info->read_memory_func (memaddr, ival, 4, info);
     34 
     35   *iptr = (ival[0] << 24)
     36     | (ival[1] << 16)
     37     | (ival[2] << 8)
     38     | (ival[3] << 0);
     39 
     40   return status;
     41 }
     42 
     43 int
     44 print_insn_pj (bfd_vma addr, struct disassemble_info *info)
     45 {
     46   fprintf_ftype fprintf_fn = info->fprintf_func;
     47   void *stream = info->stream;
     48   unsigned char opcode;
     49   int status;
     50 
     51   if ((status = info->read_memory_func (addr, &opcode, 1, info)))
     52     goto fail;
     53 
     54   if (opcode == 0xff)
     55     {
     56       unsigned char byte_2;
     57 
     58       if ((status = info->read_memory_func (addr + 1, &byte_2, 1, info)))
     59 	goto fail;
     60       fprintf_fn (stream, "%s\t", pj_opc_info[opcode + byte_2].u.name);
     61       return 2;
     62     }
     63   else
     64     {
     65       char *sep = "\t";
     66       int insn_start = addr;
     67       const pj_opc_info_t *op = &pj_opc_info[opcode];
     68       int a;
     69 
     70       addr++;
     71       fprintf_fn (stream, "%s", op->u.name);
     72 
     73       /* The tableswitch instruction is followed by the default
     74 	 address, low value, high value and the destinations.  */
     75 
     76       if (strcmp (op->u.name, "tableswitch") == 0)
     77 	{
     78 	  int lowval;
     79 	  int highval;
     80 	  int val;
     81 
     82 	  addr = (addr + 3) & ~3;
     83 	  if ((status = get_int (addr, &val, info)))
     84 	    goto fail;
     85 
     86 	  fprintf_fn (stream, " default: ");
     87 	  (*info->print_address_func) (val + insn_start, info);
     88 	  addr += 4;
     89 
     90 	  if ((status = get_int (addr, &lowval, info)))
     91 	    goto fail;
     92 	  addr += 4;
     93 
     94 	  if ((status = get_int (addr, &highval, info)))
     95 	    goto fail;
     96 	  addr += 4;
     97 
     98 	  while (lowval <= highval)
     99 	    {
    100 	      if ((status = get_int (addr, &val, info)))
    101 		goto fail;
    102 	      fprintf_fn (stream, " %d:[", lowval);
    103 	      (*info->print_address_func) (val + insn_start, info);
    104 	      fprintf_fn (stream, " ]");
    105 	      addr += 4;
    106 	      lowval++;
    107 	    }
    108 	  return addr - insn_start;
    109 	}
    110 
    111       /* The lookupswitch instruction is followed by the default
    112 	 address, element count and pairs of values and
    113 	 addresses.  */
    114       if (strcmp (op->u.name, "lookupswitch") == 0)
    115 	{
    116 	  int count;
    117 	  int val;
    118 
    119 	  addr = (addr + 3) & ~3;
    120 	  if ((status = get_int (addr, &val, info)))
    121 	    goto fail;
    122 	  addr += 4;
    123 
    124 	  fprintf_fn (stream, " default: ");
    125 	  (*info->print_address_func) (val + insn_start, info);
    126 
    127 	  if ((status = get_int (addr, &count, info)))
    128 	    goto fail;
    129 	  addr += 4;
    130 
    131 	  while (count--)
    132 	    {
    133 	      if ((status = get_int (addr, &val, info)))
    134 		goto fail;
    135 	      addr += 4;
    136 	      fprintf_fn (stream, " %d:[", val);
    137 
    138 	      if ((status = get_int (addr, &val, info)))
    139 		goto fail;
    140 	      addr += 4;
    141 
    142 	      (*info->print_address_func) (val + insn_start, info);
    143 	      fprintf_fn (stream, " ]");
    144 	    }
    145 	  return addr - insn_start;
    146 	}
    147 
    148       for (a = 0; op->arg[a]; a++)
    149 	{
    150 	  unsigned char data[4];
    151 	  int val = 0;
    152 	  int i;
    153 	  int size = ASIZE (op->arg[a]);
    154 
    155 	  if ((status = info->read_memory_func (addr, data, size, info)))
    156 	    goto fail;
    157 
    158 	  val = (UNS (op->arg[0]) || ((data[0] & 0x80) == 0)) ? 0 : -1;
    159 
    160 	  for (i = 0; i < size; i++)
    161 	    val = (val << 8) | (data[i] & 0xff);
    162 
    163 	  if (PCREL (op->arg[a]))
    164 	    (*info->print_address_func) (val + insn_start, info);
    165 	  else
    166 	    fprintf_fn (stream, "%s%d", sep, val);
    167 
    168 	  sep = ",";
    169 	  addr += size;
    170 	}
    171       return op->len;
    172     }
    173 
    174  fail:
    175   info->memory_error_func (status, addr, info);
    176   return -1;
    177 }
    178