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