1 /* pj-dis.c -- Disassemble picoJava instructions. 2 Copyright (C) 1999-2014 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