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