1 /* Disassemble MN10200 instructions. 2 Copyright (C) 1996, 1997, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 17 18 19 #include <stdio.h> 20 21 #include "sysdep.h" 22 #include "opcode/mn10200.h" 23 #include "dis-asm.h" 24 #include "opintl.h" 25 26 static void disassemble PARAMS ((bfd_vma, struct disassemble_info *, 27 unsigned long insn, unsigned long, 28 unsigned int)); 29 30 int 31 print_insn_mn10200 (memaddr, info) 32 bfd_vma memaddr; 33 struct disassemble_info *info; 34 { 35 int status; 36 bfd_byte buffer[4]; 37 unsigned long insn; 38 unsigned long extension = 0; 39 unsigned int consume; 40 41 /* First figure out how big the opcode is. */ 42 status = (*info->read_memory_func) (memaddr, buffer, 1, info); 43 if (status != 0) 44 { 45 (*info->memory_error_func) (status, memaddr, info); 46 return -1; 47 } 48 49 insn = *(unsigned char *) buffer; 50 51 /* These are one byte insns. */ 52 if ((insn & 0xf0) == 0x00 53 || (insn & 0xf0) == 0x10 54 || (insn & 0xf0) == 0x20 55 || (insn & 0xf0) == 0x30 56 || ((insn & 0xf0) == 0x80 57 && (insn & 0x0c) >> 2 != (insn & 0x03)) 58 || (insn & 0xf0) == 0x90 59 || (insn & 0xf0) == 0xa0 60 || (insn & 0xf0) == 0xb0 61 || (insn & 0xff) == 0xeb 62 || (insn & 0xff) == 0xf6 63 || (insn & 0xff) == 0xfe 64 || (insn & 0xff) == 0xff) 65 { 66 extension = 0; 67 consume = 1; 68 } 69 70 /* These are two byte insns. */ 71 else if ((insn & 0xf0) == 0x40 72 || (insn & 0xf0) == 0x50 73 || (insn & 0xf0) == 0x60 74 || (insn & 0xf0) == 0x70 75 || (insn & 0xf0) == 0x80 76 || (insn & 0xfc) == 0xd0 77 || (insn & 0xfc) == 0xd4 78 || (insn & 0xfc) == 0xd8 79 || (insn & 0xfc) == 0xe0 80 || (insn & 0xfc) == 0xe4 81 || (insn & 0xff) == 0xe8 82 || (insn & 0xff) == 0xe9 83 || (insn & 0xff) == 0xea 84 || (insn & 0xff) == 0xf0 85 || (insn & 0xff) == 0xf1 86 || (insn & 0xff) == 0xf2 87 || (insn & 0xff) == 0xf3) 88 { 89 status = (*info->read_memory_func) (memaddr, buffer, 2, info); 90 if (status != 0) 91 { 92 (*info->memory_error_func) (status, memaddr, info); 93 return -1; 94 } 95 insn = bfd_getb16 (buffer); 96 consume = 2; 97 } 98 99 /* These are three byte insns with a 16bit operand in little 100 endian form. */ 101 else if ((insn & 0xf0) == 0xc0 102 || (insn & 0xfc) == 0xdc 103 || (insn & 0xfc) == 0xec 104 || (insn & 0xff) == 0xf8 105 || (insn & 0xff) == 0xf9 106 || (insn & 0xff) == 0xfa 107 || (insn & 0xff) == 0xfb 108 || (insn & 0xff) == 0xfc 109 || (insn & 0xff) == 0xfd) 110 { 111 status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info); 112 if (status != 0) 113 { 114 (*info->memory_error_func) (status, memaddr, info); 115 return -1; 116 } 117 insn <<= 16; 118 insn |= bfd_getl16 (buffer); 119 extension = 0; 120 consume = 3; 121 } 122 /* These are three byte insns too, but we don't have to mess with 123 endianness stuff. */ 124 else if ((insn & 0xff) == 0xf5) 125 { 126 status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info); 127 if (status != 0) 128 { 129 (*info->memory_error_func) (status, memaddr, info); 130 return -1; 131 } 132 insn <<= 16; 133 insn |= bfd_getb16 (buffer); 134 extension = 0; 135 consume = 3; 136 } 137 138 /* These are four byte insns. */ 139 else if ((insn & 0xff) == 0xf7) 140 { 141 status = (*info->read_memory_func) (memaddr, buffer, 2, info); 142 if (status != 0) 143 { 144 (*info->memory_error_func) (status, memaddr, info); 145 return -1; 146 } 147 insn = bfd_getb16 (buffer); 148 insn <<= 16; 149 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info); 150 if (status != 0) 151 { 152 (*info->memory_error_func) (status, memaddr, info); 153 return -1; 154 } 155 insn |= bfd_getl16 (buffer); 156 extension = 0; 157 consume = 4; 158 } 159 160 /* These are five byte insns. */ 161 else if ((insn & 0xff) == 0xf4) 162 { 163 status = (*info->read_memory_func) (memaddr, buffer, 2, info); 164 if (status != 0) 165 { 166 (*info->memory_error_func) (status, memaddr, info); 167 return -1; 168 } 169 insn = bfd_getb16 (buffer); 170 insn <<= 16; 171 172 status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info); 173 if (status != 0) 174 { 175 (*info->memory_error_func) (status, memaddr, info); 176 return -1; 177 } 178 insn |= (*(unsigned char *)buffer << 8) & 0xff00; 179 180 status = (*info->read_memory_func) (memaddr + 3, buffer, 1, info); 181 if (status != 0) 182 { 183 (*info->memory_error_func) (status, memaddr, info); 184 return -1; 185 } 186 insn |= (*(unsigned char *)buffer) & 0xff; 187 188 status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info); 189 if (status != 0) 190 { 191 (*info->memory_error_func) (status, memaddr, info); 192 return -1; 193 } 194 extension = (*(unsigned char *)buffer) & 0xff; 195 consume = 5; 196 } 197 else 198 { 199 (*info->fprintf_func) (info->stream, _("unknown\t0x%02x"), insn); 200 return 1; 201 } 202 203 disassemble (memaddr, info, insn, extension, consume); 204 205 return consume; 206 } 207 208 static void 209 disassemble (memaddr, info, insn, extension, size) 210 bfd_vma memaddr; 211 struct disassemble_info *info; 212 unsigned long insn; 213 unsigned long extension; 214 unsigned int size; 215 { 216 struct mn10200_opcode *op = (struct mn10200_opcode *)mn10200_opcodes; 217 const struct mn10200_operand *operand; 218 int match = 0; 219 220 /* Find the opcode. */ 221 while (op->name) 222 { 223 int mysize, extra_shift; 224 225 if (op->format == FMT_1) 226 mysize = 1; 227 else if (op->format == FMT_2 228 || op->format == FMT_4) 229 mysize = 2; 230 else if (op->format == FMT_3 231 || op->format == FMT_5) 232 mysize = 3; 233 else if (op->format == FMT_6) 234 mysize = 4; 235 else if (op->format == FMT_7) 236 mysize = 5; 237 else 238 abort (); 239 240 if (op->format == FMT_2 || op->format == FMT_5) 241 extra_shift = 8; 242 else if (op->format == FMT_3 243 || op->format == FMT_6 244 || op->format == FMT_7) 245 extra_shift = 16; 246 else 247 extra_shift = 0; 248 249 if ((op->mask & insn) == op->opcode 250 && size == (unsigned int) mysize) 251 { 252 const unsigned char *opindex_ptr; 253 unsigned int nocomma; 254 int paren = 0; 255 256 match = 1; 257 (*info->fprintf_func) (info->stream, "%s\t", op->name); 258 259 /* Now print the operands. */ 260 for (opindex_ptr = op->operands, nocomma = 1; 261 *opindex_ptr != 0; 262 opindex_ptr++) 263 { 264 unsigned long value; 265 266 operand = &mn10200_operands[*opindex_ptr]; 267 268 if ((operand->flags & MN10200_OPERAND_EXTENDED) != 0) 269 { 270 value = (insn & 0xffff) << 8; 271 value |= extension; 272 } 273 else 274 { 275 value = ((insn >> (operand->shift)) 276 & ((1L << operand->bits) - 1L)); 277 } 278 279 if ((operand->flags & MN10200_OPERAND_SIGNED) != 0) 280 value = ((long)(value << (32 - operand->bits)) 281 >> (32 - operand->bits)); 282 283 if (!nocomma 284 && (!paren 285 || ((operand->flags & MN10200_OPERAND_PAREN) == 0))) 286 (*info->fprintf_func) (info->stream, ","); 287 288 nocomma = 0; 289 290 if ((operand->flags & MN10200_OPERAND_DREG) != 0) 291 { 292 value = ((insn >> (operand->shift + extra_shift)) 293 & ((1 << operand->bits) - 1)); 294 (*info->fprintf_func) (info->stream, "d%d", value); 295 } 296 297 else if ((operand->flags & MN10200_OPERAND_AREG) != 0) 298 { 299 value = ((insn >> (operand->shift + extra_shift)) 300 & ((1 << operand->bits) - 1)); 301 (*info->fprintf_func) (info->stream, "a%d", value); 302 } 303 304 else if ((operand->flags & MN10200_OPERAND_PSW) != 0) 305 (*info->fprintf_func) (info->stream, "psw"); 306 307 else if ((operand->flags & MN10200_OPERAND_MDR) != 0) 308 (*info->fprintf_func) (info->stream, "mdr"); 309 310 else if ((operand->flags & MN10200_OPERAND_PAREN) != 0) 311 { 312 if (paren) 313 (*info->fprintf_func) (info->stream, ")"); 314 else 315 { 316 (*info->fprintf_func) (info->stream, "("); 317 nocomma = 1; 318 } 319 paren = !paren; 320 } 321 322 else if ((operand->flags & MN10200_OPERAND_PCREL) != 0) 323 (*info->print_address_func) ((value + memaddr + mysize) & 0xffffff, info); 324 325 else if ((operand->flags & MN10200_OPERAND_MEMADDR) != 0) 326 (*info->print_address_func) (value, info); 327 328 else 329 (*info->fprintf_func) (info->stream, "%ld", value); 330 } 331 /* All done. */ 332 break; 333 } 334 op++; 335 } 336 337 if (!match) 338 { 339 (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn); 340 } 341 } 342