1 /* Disassemble Motorola M*Core instructions. 2 Copyright 1993, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; if not, write to the Free Software 16 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 17 18 #include "sysdep.h" 19 #include <stdio.h> 20 #define STATIC_TABLE 21 #define DEFINE_TABLE 22 23 #include "mcore-opc.h" 24 #include "dis-asm.h" 25 26 /* Mask for each mcore_opclass: */ 27 static const unsigned short imsk[] = { 28 /* O0 */ 0xFFFF, 29 /* OT */ 0xFFFC, 30 /* O1 */ 0xFFF0, 31 /* OC */ 0xFE00, 32 /* O2 */ 0xFF00, 33 /* X1 */ 0xFFF0, 34 /* OI */ 0xFE00, 35 /* OB */ 0xFE00, 36 37 /* OMa */ 0xFFF0, 38 /* SI */ 0xFE00, 39 /* I7 */ 0xF800, 40 /* LS */ 0xF000, 41 /* BR */ 0xF800, 42 /* BL */ 0xFF00, 43 /* LR */ 0xF000, 44 /* LJ */ 0xFF00, 45 46 /* RM */ 0xFFF0, 47 /* RQ */ 0xFFF0, 48 /* JSR */ 0xFFF0, 49 /* JMP */ 0xFFF0, 50 /* OBRa*/ 0xFFF0, 51 /* OBRb*/ 0xFF80, 52 /* OBRc*/ 0xFF00, 53 /* OBR2*/ 0xFE00, 54 55 /* O1R1*/ 0xFFF0, 56 /* OMb */ 0xFF80, 57 /* OMc */ 0xFF00, 58 /* SIa */ 0xFE00, 59 60 /* MULSH */ 0xFF00, 61 /* OPSR */ 0xFFF8, /* psrset/psrclr */ 62 63 /* JC */ 0, /* JC,JU,JL don't appear in object */ 64 /* JU */ 0, 65 /* JL */ 0, 66 /* RSI */ 0, 67 /* DO21*/ 0, 68 /* OB2 */ 0 /* OB2 won't appear in object. */ 69 }; 70 71 static const char *grname[] = { 72 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 73 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 74 }; 75 76 static const char X[] = "??"; 77 78 static const char *crname[] = { 79 "psr", "vbr", "epsr", "fpsr", "epc", "fpc", "ss0", "ss1", 80 "ss2", "ss3", "ss4", "gcr", "gsr", X, X, X, 81 X, X, X, X, X, X, X, X, 82 X, X, X, X, X, X, X, X 83 }; 84 85 static const unsigned isiz[] = { 2, 0, 1, 0 }; 86 87 int 88 print_insn_mcore (memaddr, info) 89 bfd_vma memaddr; 90 struct disassemble_info *info; 91 { 92 unsigned char ibytes[4]; 93 fprintf_ftype fprintf = info->fprintf_func; 94 void *stream = info->stream; 95 unsigned short inst; 96 const mcore_opcode_info *op; 97 int status; 98 99 info->bytes_per_chunk = 2; 100 101 status = info->read_memory_func (memaddr, ibytes, 2, info); 102 103 if (status != 0) 104 { 105 info->memory_error_func (status, memaddr, info); 106 return -1; 107 } 108 109 if (info->endian == BFD_ENDIAN_BIG) 110 inst = (ibytes[0] << 8) | ibytes[1]; 111 else if (info->endian == BFD_ENDIAN_LITTLE) 112 inst = (ibytes[1] << 8) | ibytes[0]; 113 else 114 abort (); 115 116 /* Just a linear search of the table. */ 117 for (op = mcore_table; op->name != 0; op++) 118 if (op->inst == (inst & imsk[op->opclass])) 119 break; 120 121 if (op->name == 0) 122 fprintf (stream, ".short 0x%04x", inst); 123 else 124 { 125 const char *name = grname[inst & 0x0F]; 126 127 fprintf (stream, "%s", op->name); 128 129 switch (op->opclass) 130 { 131 case O0: 132 break; 133 134 case OT: 135 fprintf (stream, "\t%d", inst & 0x3); 136 break; 137 138 case O1: 139 case JMP: 140 case JSR: 141 fprintf (stream, "\t%s", name); 142 break; 143 144 case OC: 145 fprintf (stream, "\t%s, %s", name, crname[(inst >> 4) & 0x1F]); 146 break; 147 148 case O1R1: 149 fprintf (stream, "\t%s, r1", name); 150 break; 151 152 case MULSH: 153 case O2: 154 fprintf (stream, "\t%s, %s", name, grname[(inst >> 4) & 0xF]); 155 break; 156 157 case X1: 158 fprintf (stream, "\tr1, %s", name); 159 break; 160 161 case OI: 162 fprintf (stream, "\t%s, %d", name, ((inst >> 4) & 0x1F) + 1); 163 break; 164 165 case RM: 166 fprintf (stream, "\t%s-r15, (r0)", name); 167 break; 168 169 case RQ: 170 fprintf (stream, "\tr4-r7, (%s)", name); 171 break; 172 173 case OB: 174 case OBRa: 175 case OBRb: 176 case OBRc: 177 case SI: 178 case SIa: 179 case OMa: 180 case OMb: 181 case OMc: 182 fprintf (stream, "\t%s, %d", name, (inst >> 4) & 0x1F); 183 break; 184 185 case I7: 186 fprintf (stream, "\t%s, %d", name, (inst >> 4) & 0x7F); 187 break; 188 189 case LS: 190 fprintf (stream, "\t%s, (%s, %d)", grname[(inst >> 8) & 0xF], 191 name, ((inst >> 4) & 0xF) << isiz[(inst >> 13) & 3]); 192 break; 193 194 case BR: 195 { 196 long val = inst & 0x3FF; 197 198 if (inst & 0x400) 199 val |= 0xFFFFFC00; 200 201 fprintf (stream, "\t0x%lx", (long)(memaddr + 2 + (val << 1))); 202 203 if (strcmp (op->name, "bsr") == 0) 204 { 205 /* For bsr, we'll try to get a symbol for the target. */ 206 val = memaddr + 2 + (val << 1); 207 208 if (info->print_address_func && val != 0) 209 { 210 fprintf (stream, "\t// "); 211 info->print_address_func (val, info); 212 } 213 } 214 } 215 break; 216 217 case BL: 218 { 219 long val; 220 val = (inst & 0x000F); 221 fprintf (stream, "\t%s, 0x%lx", 222 grname[(inst >> 4) & 0xF], (long)(memaddr - (val << 1))); 223 } 224 break; 225 226 case LR: 227 { 228 unsigned long val; 229 230 val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC; 231 232 status = info->read_memory_func (val, ibytes, 4, info); 233 if (status != 0) 234 { 235 info->memory_error_func (status, memaddr, info); 236 break; 237 } 238 239 if (info->endian == BFD_ENDIAN_LITTLE) 240 val = (ibytes[3] << 24) | (ibytes[2] << 16) 241 | (ibytes[1] << 8) | (ibytes[0]); 242 else 243 val = (ibytes[0] << 24) | (ibytes[1] << 16) 244 | (ibytes[2] << 8) | (ibytes[3]); 245 246 /* Removed [] around literal value to match ABI syntax 12/95. */ 247 fprintf (stream, "\t%s, 0x%lX", grname[(inst >> 8) & 0xF], val); 248 249 if (val == 0) 250 fprintf (stream, "\t// from address pool at 0x%lx", 251 (long)(memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC); 252 } 253 break; 254 255 case LJ: 256 { 257 unsigned long val; 258 259 val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC; 260 261 status = info->read_memory_func (val, ibytes, 4, info); 262 if (status != 0) 263 { 264 info->memory_error_func (status, memaddr, info); 265 break; 266 } 267 268 if (info->endian == BFD_ENDIAN_LITTLE) 269 val = (ibytes[3] << 24) | (ibytes[2] << 16) 270 | (ibytes[1] << 8) | (ibytes[0]); 271 else 272 val = (ibytes[0] << 24) | (ibytes[1] << 16) 273 | (ibytes[2] << 8) | (ibytes[3]); 274 275 /* Removed [] around literal value to match ABI syntax 12/95. */ 276 fprintf (stream, "\t0x%lX", val); 277 /* For jmpi/jsri, we'll try to get a symbol for the target. */ 278 if (info->print_address_func && val != 0) 279 { 280 fprintf (stream, "\t// "); 281 info->print_address_func (val, info); 282 } 283 else 284 { 285 fprintf (stream, "\t// from address pool at 0x%lx", 286 (long)(memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC); 287 } 288 } 289 break; 290 291 case OPSR: 292 { 293 static char *fields[] = { 294 "af", "ie", "fe", "fe,ie", 295 "ee", "ee,ie", "ee,fe", "ee,fe,ie" 296 }; 297 298 fprintf (stream, "\t%s", fields[inst & 0x7]); 299 } 300 break; 301 302 default: 303 /* If the disassembler lags the instruction set. */ 304 fprintf (stream, "\tundecoded operands, inst is 0x%04x", inst); 305 break; 306 } 307 } 308 309 /* Say how many bytes we consumed. */ 310 return 2; 311 } 312