Back to index

cell-binutils  2.17cvs20070401
pj-dis.c
Go to the documentation of this file.
00001 /* pj-dis.c -- Disassemble picoJava instructions.
00002    Copyright 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
00003    Contributed by Steve Chamberlain, of Transmeta (sac@pobox.com).
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 2 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
00018    MA 02110-1301, USA.  */
00019 
00020 #include <stdio.h>
00021 #include "sysdep.h"
00022 #include "opcode/pj.h"
00023 #include "dis-asm.h"
00024 
00025 extern const pj_opc_info_t pj_opc_info[512];
00026 
00027 static int
00028 get_int (bfd_vma memaddr, int *iptr, struct disassemble_info *info)
00029 {
00030   unsigned char ival[4];
00031   int status = info->read_memory_func (memaddr, ival, 4, info);
00032 
00033   *iptr = (ival[0] << 24)
00034     | (ival[1] << 16)
00035     | (ival[2] << 8)
00036     | (ival[3] << 0);
00037 
00038   return status;
00039 }
00040 
00041 int
00042 print_insn_pj (bfd_vma addr, struct disassemble_info *info)
00043 {
00044   fprintf_ftype fprintf_fn = info->fprintf_func;
00045   void *stream = info->stream;
00046   unsigned char opcode;
00047   int status;
00048 
00049   if ((status = info->read_memory_func (addr, &opcode, 1, info)))
00050     goto fail;
00051 
00052   if (opcode == 0xff)
00053     {
00054       unsigned char byte_2;
00055 
00056       if ((status = info->read_memory_func (addr + 1, &byte_2, 1, info)))
00057        goto fail;
00058       fprintf_fn (stream, "%s\t", pj_opc_info[opcode + byte_2].u.name);
00059       return 2;
00060     }
00061   else
00062     {
00063       char *sep = "\t";
00064       int insn_start = addr;
00065       const pj_opc_info_t *op = &pj_opc_info[opcode];
00066       int a;
00067 
00068       addr++;
00069       fprintf_fn (stream, "%s", op->u.name);
00070 
00071       /* The tableswitch instruction is followed by the default
00072         address, low value, high value and the destinations.  */
00073 
00074       if (strcmp (op->u.name, "tableswitch") == 0)
00075        {
00076          int lowval;
00077          int highval;
00078          int val;
00079 
00080          addr = (addr + 3) & ~3;
00081          if ((status = get_int (addr, &val, info)))
00082            goto fail;
00083 
00084          fprintf_fn (stream, " default: ");
00085          (*info->print_address_func) (val + insn_start, info);
00086          addr += 4;
00087 
00088          if ((status = get_int (addr, &lowval, info)))
00089            goto fail;
00090          addr += 4;
00091 
00092          if ((status = get_int (addr, &highval, info)))
00093            goto fail;
00094          addr += 4;
00095 
00096          while (lowval <= highval)
00097            {
00098              if ((status = get_int (addr, &val, info)))
00099               goto fail;
00100              fprintf_fn (stream, " %d:[", lowval);
00101              (*info->print_address_func) (val + insn_start, info);
00102              fprintf_fn (stream, " ]");
00103              addr += 4;
00104              lowval++;
00105            }
00106          return addr - insn_start;
00107        }
00108 
00109       /* The lookupswitch instruction is followed by the default
00110         address, element count and pairs of values and
00111         addresses.  */
00112       if (strcmp (op->u.name, "lookupswitch") == 0)
00113        {
00114          int count;
00115          int val;
00116 
00117          addr = (addr + 3) & ~3;
00118          if ((status = get_int (addr, &val, info)))
00119            goto fail;
00120          addr += 4;
00121 
00122          fprintf_fn (stream, " default: ");
00123          (*info->print_address_func) (val + insn_start, info);
00124 
00125          if ((status = get_int (addr, &count, info)))
00126            goto fail;
00127          addr += 4;
00128 
00129          while (count--)
00130            {
00131              if ((status = get_int (addr, &val, info)))
00132               goto fail;
00133              addr += 4;
00134              fprintf_fn (stream, " %d:[", val);
00135 
00136              if ((status = get_int (addr, &val, info)))
00137               goto fail;
00138              addr += 4;
00139 
00140              (*info->print_address_func) (val + insn_start, info);
00141              fprintf_fn (stream, " ]");
00142            }
00143          return addr - insn_start;
00144        }
00145 
00146       for (a = 0; op->arg[a]; a++)
00147        {
00148          unsigned char data[4];
00149          int val = 0;
00150          int i;
00151          int size = ASIZE (op->arg[a]);
00152 
00153          if ((status = info->read_memory_func (addr, data, size, info)))
00154            goto fail;
00155 
00156          val = (UNS (op->arg[0]) || ((data[0] & 0x80) == 0)) ? 0 : -1;
00157 
00158          for (i = 0; i < size; i++)
00159            val = (val << 8) | (data[i] & 0xff);
00160 
00161          if (PCREL (op->arg[a]))
00162            (*info->print_address_func) (val + insn_start, info);
00163          else
00164            fprintf_fn (stream, "%s%d", sep, val);
00165 
00166          sep = ",";
00167          addr += size;
00168        }
00169       return op->len;
00170     }
00171 
00172  fail:
00173   info->memory_error_func (status, addr, info);
00174   return -1;
00175 }