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