annotate 68kinst.c @ 989:d70000fdff0b

Implemented IR and undefined bits of info word for address error exception frames
author Michael Pavone <pavone@retrodev.com>
date Wed, 27 Apr 2016 21:39:17 -0700
parents 902c53d9c16f
children 261995d06897
rev   line source
pavone@467 1 /*
pavone@467 2 Copyright 2013 Michael Pavone
pavone@518 3 This file is part of BlastEm.
pavone@467 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
pavone@467 5 */
pavone@0 6 #include "68kinst.h"
pavone@2 7 #include <string.h>
pavone@2 8 #include <stdio.h>
pavone@0 9
pavone@2 10 uint32_t sign_extend16(uint32_t val)
pavone@0 11 {
pavone@2 12 return (val & 0x8000) ? val | 0xFFFF0000 : val;
pavone@2 13 }
pavone@2 14
pavone@2 15 uint32_t sign_extend8(uint32_t val)
pavone@2 16 {
pavone@2 17 return (val & 0x80) ? val | 0xFFFFFF00 : val;
pavone@2 18 }
pavone@2 19
pavone@2 20 uint16_t *m68k_decode_op_ex(uint16_t *cur, uint8_t mode, uint8_t reg, uint8_t size, m68k_op_info *dst)
pavone@2 21 {
pavone@638 22 uint16_t ext, tmp;
pavone@0 23 dst->addr_mode = mode;
pavone@0 24 switch(mode)
pavone@0 25 {
pavone@0 26 case MODE_REG:
pavone@0 27 case MODE_AREG:
pavone@2 28 case MODE_AREG_INDIRECT:
pavone@2 29 case MODE_AREG_POSTINC:
pavone@2 30 case MODE_AREG_PREDEC:
pavone@0 31 dst->params.regs.pri = reg;
pavone@0 32 break;
pavone@2 33 case MODE_AREG_DISPLACE:
pavone@2 34 ext = *(++cur);
pavone@2 35 dst->params.regs.pri = reg;
pavone@2 36 dst->params.regs.displacement = sign_extend16(ext);
pavone@2 37 break;
pavone@2 38 case MODE_AREG_INDEX_MEM:
pavone@638 39 dst->params.regs.pri = reg;
pavone@638 40 ext = *(++cur);
pavone@638 41 dst->params.regs.sec = ext >> 11;//includes areg/dreg bit, reg num and word/long bit
pavone@638 42 #ifdef M68020
pavone@638 43 dst->params.regs.scale = ext >> 9 & 3;
pavone@638 44 if (ext & 0x100)
pavone@638 45 {
pavone@638 46 dst->params.regs.disp_sizes = ext >> 4 & 3;
pavone@638 47 switch (dst->params.regs.disp_sizes)
pavone@638 48 {
pavone@638 49 case 0:
pavone@638 50 //reserved
pavone@638 51 return NULL;
pavone@638 52 case 1:
pavone@638 53 dst->params.regs.displacement = 0;
pavone@638 54 break;
pavone@638 55 case 2:
pavone@638 56 dst->params.regs.displacement = sign_extend16(*(cur++));
pavone@638 57 break;
pavone@638 58 case 3:
pavone@638 59 tmp = *(cur++);
pavone@638 60 dst->params.regs.displacement = tmp << 16 | *(cur++);
pavone@638 61 break;
pavone@638 62 }
pavone@638 63 if (ext & 0x3)
pavone@638 64 {
pavone@638 65 //memory indirect
pavone@638 66 switch (ext & 0xC4)
pavone@638 67 {
pavone@638 68 case 0x00:
pavone@638 69 dst->addr_mode = MODE_AREG_PREINDEX;
pavone@638 70 break;
pavone@638 71 case 0x04:
pavone@638 72 dst->addr_mode = MODE_AREG_POSTINDEX;
pavone@638 73 break;
pavone@638 74 case 0x40:
pavone@638 75 dst->addr_mode = MODE_AREG_MEM_INDIRECT;
pavone@638 76 break;
pavone@638 77 case 0x80:
pavone@638 78 dst->addr_mode = MODE_PREINDEX;
pavone@638 79 break;
pavone@638 80 case 0x84:
pavone@638 81 dst->addr_mode = MODE_POSTINDEX;
pavone@638 82 break;
pavone@638 83 case 0xC0:
pavone@638 84 dst->addr_mode = MODE_MEM_INDIRECT;
pavone@638 85 break;
pavone@638 86 }
pavone@638 87 dst->params.regs.disp_sizes |= ext << 4 & 0x30;
pavone@638 88 switch (ext & 0x3)
pavone@638 89 {
pavone@638 90 case 0:
pavone@638 91 //reserved
pavone@638 92 return NULL;
pavone@638 93 case 1:
pavone@638 94 dst->params.regs.outer_disp = 0;
pavone@638 95 break;
pavone@638 96 case 2:
pavone@638 97 dst->params.regs.outer_disp = sign_extend16(*(cur++));
pavone@638 98 break;
pavone@638 99 case 3:
pavone@638 100 tmp = *(cur++);
pavone@638 101 dst->params.regs.outer_disp = tmp << 16 | *(cur++);
pavone@638 102 break;
pavone@638 103 }
pavone@638 104 } else {
pavone@638 105 switch (ext >> 6 & 3)
pavone@638 106 {
pavone@638 107 case 0:
pavone@638 108 dst->addr_mode = MODE_AREG_INDEX_BASE_DISP;
pavone@638 109 break;
pavone@638 110 case 1:
pavone@638 111 dst->addr_mode = MODE_AREG_BASE_DISP;
pavone@638 112 break;
pavone@638 113 case 2:
pavone@638 114 dst->addr_mode = MODE_INDEX_BASE_DISP;
pavone@638 115 break;
pavone@638 116 case 3:
pavone@638 117 dst->addr_mode = MODE_BASE_DISP;
pavone@638 118 break;
pavone@638 119 }
pavone@638 120 }
pavone@638 121 } else {
pavone@638 122 #endif
pavone@79 123 dst->addr_mode = MODE_AREG_INDEX_DISP8;
pavone@79 124 dst->params.regs.displacement = sign_extend8(ext&0xFF);
pavone@638 125 #ifdef M68020
pavone@638 126 }
pavone@638 127 #endif
pavone@2 128 break;
pavone@2 129 case MODE_PC_INDIRECT_ABS_IMMED:
pavone@2 130 switch(reg)
pavone@2 131 {
pavone@2 132 case 0:
pavone@2 133 dst->addr_mode = MODE_ABSOLUTE_SHORT;
pavone@2 134 ext = *(++cur);
pavone@15 135 dst->params.immed = sign_extend16(ext);
pavone@2 136 break;
pavone@2 137 case 1:
pavone@2 138 dst->addr_mode = MODE_ABSOLUTE;
pavone@2 139 ext = *(++cur);
pavone@15 140 dst->params.immed = ext << 16 | *(++cur);
pavone@2 141 break;
pavone@79 142 case 3:
pavone@638 143 ext = *(++cur);
pavone@638 144 dst->params.regs.sec = ext >> 11;//includes areg/dreg bit, reg num and word/long bit
pavone@638 145 #ifdef M68020
pavone@638 146 dst->params.regs.scale = ext >> 9 & 3;
pavone@638 147 if (ext & 0x100)
pavone@638 148 {
pavone@638 149 dst->params.regs.disp_sizes = ext >> 4 & 3;
pavone@638 150 switch (dst->params.regs.disp_sizes)
pavone@638 151 {
pavone@638 152 case 0:
pavone@638 153 //reserved
pavone@638 154 return NULL;
pavone@638 155 case 1:
pavone@638 156 dst->params.regs.displacement = 0;
pavone@638 157 break;
pavone@638 158 case 2:
pavone@638 159 dst->params.regs.displacement = sign_extend16(*(cur++));
pavone@638 160 break;
pavone@638 161 case 3:
pavone@638 162 tmp = *(cur++);
pavone@638 163 dst->params.regs.displacement = tmp << 16 | *(cur++);
pavone@638 164 break;
pavone@638 165 }
pavone@638 166 if (ext & 0x3)
pavone@638 167 {
pavone@638 168 //memory indirect
pavone@638 169 switch (ext & 0xC4)
pavone@638 170 {
pavone@638 171 case 0x00:
pavone@638 172 dst->addr_mode = MODE_PC_PREINDEX;
pavone@638 173 break;
pavone@638 174 case 0x04:
pavone@638 175 dst->addr_mode = MODE_PC_POSTINDEX;
pavone@638 176 break;
pavone@638 177 case 0x40:
pavone@638 178 dst->addr_mode = MODE_PC_MEM_INDIRECT;
pavone@638 179 break;
pavone@638 180 case 0x80:
pavone@638 181 dst->addr_mode = MODE_ZPC_PREINDEX;
pavone@638 182 break;
pavone@638 183 case 0x84:
pavone@638 184 dst->addr_mode = MODE_ZPC_POSTINDEX;
pavone@638 185 break;
pavone@638 186 case 0xC0:
pavone@638 187 dst->addr_mode = MODE_ZPC_MEM_INDIRECT;
pavone@638 188 break;
pavone@638 189 }
pavone@638 190 dst->params.regs.disp_sizes |= ext << 4 & 0x30;
pavone@638 191 switch (ext & 0x3)
pavone@638 192 {
pavone@638 193 case 0:
pavone@638 194 //reserved
pavone@638 195 return NULL;
pavone@638 196 case 1:
pavone@638 197 dst->params.regs.outer_disp = 0;
pavone@638 198 break;
pavone@638 199 case 2:
pavone@638 200 dst->params.regs.outer_disp = sign_extend16(*(cur++));
pavone@638 201 break;
pavone@638 202 case 3:
pavone@638 203 tmp = *(cur++);
pavone@638 204 dst->params.regs.outer_disp = tmp << 16 | *(cur++);
pavone@638 205 break;
pavone@638 206 }
pavone@638 207 } else {
pavone@638 208 switch (ext >> 6 & 3)
pavone@638 209 {
pavone@638 210 case 0:
pavone@638 211 dst->addr_mode = MODE_PC_INDEX_BASE_DISP;
pavone@638 212 break;
pavone@638 213 case 1:
pavone@638 214 dst->addr_mode = MODE_PC_BASE_DISP;
pavone@638 215 break;
pavone@638 216 case 2:
pavone@638 217 dst->addr_mode = MODE_ZPC_INDEX_BASE_DISP;
pavone@638 218 break;
pavone@638 219 case 3:
pavone@638 220 dst->addr_mode = MODE_ZPC_BASE_DISP;
pavone@638 221 break;
pavone@638 222 }
pavone@638 223 }
pavone@638 224 } else {
pavone@638 225 #endif
pavone@638 226 dst->addr_mode = MODE_PC_INDEX_DISP8;
pavone@638 227 dst->params.regs.displacement = sign_extend8(ext&0xFF);
pavone@638 228 #ifdef M68020
pavone@638 229 }
pavone@638 230 #endif
pavone@95 231 break;
pavone@2 232 case 2:
pavone@2 233 dst->addr_mode = MODE_PC_DISPLACE;
pavone@2 234 ext = *(++cur);
pavone@2 235 dst->params.regs.displacement = sign_extend16(ext);
pavone@2 236 break;
pavone@2 237 case 4:
pavone@2 238 dst->addr_mode = MODE_IMMEDIATE;
pavone@2 239 ext = *(++cur);
pavone@2 240 switch (size)
pavone@2 241 {
pavone@2 242 case OPSIZE_BYTE:
pavone@15 243 dst->params.immed = ext & 0xFF;
pavone@2 244 break;
pavone@2 245 case OPSIZE_WORD:
pavone@15 246 dst->params.immed = ext;
pavone@2 247 break;
pavone@2 248 case OPSIZE_LONG:
pavone@15 249 dst->params.immed = ext << 16 | *(++cur);
pavone@2 250 break;
pavone@2 251 }
pavone@2 252 break;
pavone@176 253 default:
pavone@176 254 return NULL;
pavone@2 255 }
pavone@2 256 break;
pavone@0 257 }
pavone@2 258 return cur;
pavone@2 259 }
pavone@2 260
pavone@823 261 uint8_t m68k_valid_immed_dst(m68k_op_info *dst)
pavone@823 262 {
pavone@823 263 if (dst->addr_mode == MODE_AREG || dst->addr_mode == MODE_IMMEDIATE) {
pavone@823 264 return 0;
pavone@823 265 }
pavone@823 266 return 1;
pavone@823 267 }
pavone@823 268
pavone@823 269 uint8_t m68k_valid_immed_limited_dst(m68k_op_info *dst)
pavone@823 270 {
pavone@823 271 if (dst->addr_mode == MODE_AREG || dst->addr_mode > MODE_ABSOLUTE) {
pavone@823 272 return 0;
pavone@823 273 }
pavone@823 274 return 1;
pavone@823 275 }
pavone@823 276
pavone@2 277 uint16_t *m68k_decode_op(uint16_t *cur, uint8_t size, m68k_op_info *dst)
pavone@2 278 {
pavone@2 279 uint8_t mode = (*cur >> 3) & 0x7;
pavone@2 280 uint8_t reg = *cur & 0x7;
pavone@2 281 return m68k_decode_op_ex(cur, mode, reg, size, dst);
pavone@2 282 }
pavone@2 283
pavone@2 284 void m68k_decode_cond(uint16_t op, m68kinst * decoded)
pavone@2 285 {
pavone@2 286 decoded->extra.cond = (op >> 0x8) & 0xF;
pavone@2 287 }
pavone@2 288
pavone@18 289 uint8_t m68k_reg_quick_field(uint16_t op)
pavone@2 290 {
pavone@2 291 return (op >> 9) & 0x7;
pavone@0 292 }
pavone@0 293
pavone@18 294 uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
pavone@0 295 {
pavone@176 296 uint16_t *start = istream;
pavone@0 297 uint8_t optype = *istream >> 12;
pavone@0 298 uint8_t size;
pavone@4 299 uint8_t reg;
pavone@4 300 uint8_t opmode;
pavone@2 301 uint32_t immed;
pavone@2 302 decoded->op = M68K_INVALID;
pavone@2 303 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_UNUSED;
pavone@2 304 decoded->variant = VAR_NORMAL;
pavone@18 305 decoded->address = address;
pavone@0 306 switch(optype)
pavone@0 307 {
pavone@0 308 case BIT_MOVEP_IMMED:
pavone@163 309 if ((*istream & 0x138) == 0x108) {
pavone@163 310 //MOVEP
pavone@163 311 decoded->op = M68K_MOVEP;
pavone@163 312 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD;
pavone@163 313 if (*istream & 0x80) {
pavone@163 314 //memory dest
pavone@163 315 decoded->src.addr_mode = MODE_REG;
pavone@163 316 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@163 317 decoded->dst.addr_mode = MODE_AREG_DISPLACE;
pavone@163 318 decoded->dst.params.regs.pri = *istream & 0x7;
pavone@163 319 decoded->dst.params.regs.displacement = *(++istream);
pavone@163 320 } else {
pavone@163 321 //memory source
pavone@163 322 decoded->dst.addr_mode = MODE_REG;
pavone@163 323 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@163 324 decoded->src.addr_mode = MODE_AREG_DISPLACE;
pavone@163 325 decoded->src.params.regs.pri = *istream & 0x7;
pavone@163 326 decoded->src.params.regs.displacement = *(++istream);
pavone@163 327 }
pavone@163 328 } else if (*istream & 0x100) {
pavone@4 329 //BTST, BCHG, BCLR, BSET
pavone@4 330 switch ((*istream >> 6) & 0x3)
pavone@4 331 {
pavone@4 332 case 0:
pavone@4 333 decoded->op = M68K_BTST;
pavone@4 334 break;
pavone@4 335 case 1:
pavone@4 336 decoded->op = M68K_BCHG;
pavone@4 337 break;
pavone@4 338 case 2:
pavone@4 339 decoded->op = M68K_BCLR;
pavone@4 340 break;
pavone@4 341 case 3:
pavone@4 342 decoded->op = M68K_BSET;
pavone@4 343 break;
pavone@4 344 }
pavone@4 345 decoded->src.addr_mode = MODE_REG;
pavone@18 346 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@61 347 decoded->extra.size = OPSIZE_BYTE;
pavone@61 348 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst));
pavone@176 349 if (!istream) {
pavone@176 350 decoded->op = M68K_INVALID;
pavone@630 351 break;
pavone@176 352 }
pavone@61 353 if (decoded->dst.addr_mode == MODE_REG) {
pavone@61 354 decoded->extra.size = OPSIZE_LONG;
pavone@61 355 }
pavone@8 356 } else if ((*istream & 0xF00) == 0x800) {
pavone@12 357 //BTST, BCHG, BCLR, BSET
pavone@12 358 switch ((*istream >> 6) & 0x3)
pavone@12 359 {
pavone@12 360 case 0:
pavone@12 361 decoded->op = M68K_BTST;
pavone@12 362 break;
pavone@12 363 case 1:
pavone@12 364 decoded->op = M68K_BCHG;
pavone@12 365 break;
pavone@12 366 case 2:
pavone@12 367 decoded->op = M68K_BCLR;
pavone@12 368 break;
pavone@12 369 case 3:
pavone@12 370 decoded->op = M68K_BSET;
pavone@12 371 break;
pavone@12 372 }
pavone@12 373 opmode = (*istream >> 3) & 0x7;
pavone@12 374 reg = *istream & 0x7;
pavone@61 375 decoded->src.addr_mode = MODE_IMMEDIATE_WORD;
pavone@15 376 decoded->src.params.immed = *(++istream) & 0xFF;
pavone@12 377 decoded->extra.size = OPSIZE_BYTE;
pavone@61 378 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
pavone@176 379 if (!istream) {
pavone@176 380 decoded->op = M68K_INVALID;
pavone@630 381 break;
pavone@176 382 }
pavone@61 383 if (decoded->dst.addr_mode == MODE_REG) {
pavone@61 384 decoded->extra.size = OPSIZE_LONG;
pavone@61 385 }
pavone@8 386 } else if ((*istream & 0xC0) == 0xC0) {
pavone@8 387 #ifdef M68020
pavone@8 388 //CMP2, CHK2, CAS, CAS2, RTM, CALLM
pavone@8 389 #endif
pavone@4 390 } else {
pavone@4 391 switch ((*istream >> 9) & 0x7)
pavone@4 392 {
pavone@4 393 case 0:
pavone@4 394 if ((*istream & 0xFF) == 0x3C) {
pavone@4 395 decoded->op = M68K_ORI_CCR;
pavone@4 396 decoded->extra.size = OPSIZE_BYTE;
pavone@4 397 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@15 398 decoded->src.params.immed = *(++istream) & 0xFF;
pavone@4 399 } else if((*istream & 0xFF) == 0x7C) {
pavone@4 400 decoded->op = M68K_ORI_SR;
pavone@4 401 decoded->extra.size = OPSIZE_WORD;
pavone@4 402 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@15 403 decoded->src.params.immed = *(++istream);
pavone@4 404 } else {
pavone@8 405 decoded->op = M68K_OR;
pavone@8 406 decoded->variant = VAR_IMMEDIATE;
pavone@8 407 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@8 408 decoded->extra.size = size = (*istream >> 6) & 3;
pavone@8 409 reg = *istream & 0x7;
pavone@8 410 opmode = (*istream >> 3) & 0x7;
pavone@8 411 switch (size)
pavone@8 412 {
pavone@8 413 case OPSIZE_BYTE:
pavone@15 414 decoded->src.params.immed = *(++istream) & 0xFF;
pavone@8 415 break;
pavone@8 416 case OPSIZE_WORD:
pavone@15 417 decoded->src.params.immed = *(++istream);
pavone@8 418 break;
pavone@8 419 case OPSIZE_LONG:
pavone@8 420 immed = *(++istream);
pavone@15 421 decoded->src.params.immed = immed << 16 | *(++istream);
pavone@8 422 break;
pavone@4 423 }
pavone@8 424 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
pavone@823 425 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
pavone@176 426 decoded->op = M68K_INVALID;
pavone@630 427 break;
pavone@176 428 }
pavone@4 429 }
pavone@4 430 break;
pavone@4 431 case 1:
pavone@8 432 //ANDI, ANDI to CCR, ANDI to SR
pavone@5 433 if ((*istream & 0xFF) == 0x3C) {
pavone@5 434 decoded->op = M68K_ANDI_CCR;
pavone@5 435 decoded->extra.size = OPSIZE_BYTE;
pavone@5 436 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@15 437 decoded->src.params.immed = *(++istream) & 0xFF;
pavone@5 438 } else if((*istream & 0xFF) == 0x7C) {
pavone@5 439 decoded->op = M68K_ANDI_SR;
pavone@5 440 decoded->extra.size = OPSIZE_WORD;
pavone@5 441 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@15 442 decoded->src.params.immed = *(++istream);
pavone@5 443 } else {
pavone@8 444 decoded->op = M68K_AND;
pavone@8 445 decoded->variant = VAR_IMMEDIATE;
pavone@5 446 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@5 447 decoded->extra.size = size = (*istream >> 6) & 3;
pavone@5 448 reg = *istream & 0x7;
pavone@5 449 opmode = (*istream >> 3) & 0x7;
pavone@5 450 switch (size)
pavone@5 451 {
pavone@5 452 case OPSIZE_BYTE:
pavone@15 453 decoded->src.params.immed = *(++istream) & 0xFF;
pavone@5 454 break;
pavone@5 455 case OPSIZE_WORD:
pavone@15 456 decoded->src.params.immed = *(++istream);
pavone@5 457 break;
pavone@5 458 case OPSIZE_LONG:
pavone@5 459 immed = *(++istream);
pavone@15 460 decoded->src.params.immed = immed << 16 | *(++istream);
pavone@5 461 break;
pavone@5 462 }
pavone@5 463 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
pavone@823 464 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
pavone@176 465 decoded->op = M68K_INVALID;
pavone@630 466 break;
pavone@176 467 }
pavone@5 468 }
pavone@4 469 break;
pavone@8 470 case 2:
pavone@8 471 decoded->op = M68K_SUB;
pavone@8 472 decoded->variant = VAR_IMMEDIATE;
pavone@8 473 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@8 474 decoded->extra.size = size = (*istream >> 6) & 3;
pavone@8 475 reg = *istream & 0x7;
pavone@8 476 opmode = (*istream >> 3) & 0x7;
pavone@8 477 switch (size)
pavone@8 478 {
pavone@8 479 case OPSIZE_BYTE:
pavone@15 480 decoded->src.params.immed = *(++istream) & 0xFF;
pavone@8 481 break;
pavone@8 482 case OPSIZE_WORD:
pavone@15 483 decoded->src.params.immed = *(++istream);
pavone@8 484 break;
pavone@8 485 case OPSIZE_LONG:
pavone@8 486 immed = *(++istream);
pavone@15 487 decoded->src.params.immed = immed << 16 | *(++istream);
pavone@8 488 break;
pavone@8 489 }
pavone@8 490 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
pavone@823 491 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
pavone@176 492 decoded->op = M68K_INVALID;
pavone@630 493 break;
pavone@176 494 }
pavone@8 495 break;
pavone@4 496 case 3:
pavone@8 497 decoded->op = M68K_ADD;
pavone@8 498 decoded->variant = VAR_IMMEDIATE;
pavone@8 499 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@8 500 decoded->extra.size = size = (*istream >> 6) & 3;
pavone@8 501 reg = *istream & 0x7;
pavone@8 502 opmode = (*istream >> 3) & 0x7;
pavone@8 503 switch (size)
pavone@8 504 {
pavone@8 505 case OPSIZE_BYTE:
pavone@15 506 decoded->src.params.immed = *(++istream) & 0xFF;
pavone@8 507 break;
pavone@8 508 case OPSIZE_WORD:
pavone@15 509 decoded->src.params.immed = *(++istream);
pavone@8 510 break;
pavone@8 511 case OPSIZE_LONG:
pavone@8 512 immed = *(++istream);
pavone@15 513 decoded->src.params.immed = immed << 16 | *(++istream);
pavone@8 514 break;
pavone@5 515 }
pavone@8 516 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
pavone@823 517 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
pavone@176 518 decoded->op = M68K_INVALID;
pavone@630 519 break;
pavone@176 520 }
pavone@4 521 break;
pavone@4 522 case 4:
pavone@5 523 //BTST, BCHG, BCLR, BSET
pavone@5 524 switch ((*istream >> 6) & 0x3)
pavone@5 525 {
pavone@5 526 case 0:
pavone@5 527 decoded->op = M68K_BTST;
pavone@5 528 break;
pavone@5 529 case 1:
pavone@5 530 decoded->op = M68K_BCHG;
pavone@5 531 break;
pavone@5 532 case 2:
pavone@5 533 decoded->op = M68K_BCLR;
pavone@5 534 break;
pavone@5 535 case 3:
pavone@5 536 decoded->op = M68K_BSET;
pavone@5 537 break;
pavone@5 538 }
pavone@5 539 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@15 540 decoded->src.params.immed = *(++istream) & 0xFF;
pavone@5 541 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
pavone@176 542 if (!istream) {
pavone@176 543 decoded->op = M68K_INVALID;
pavone@630 544 break;
pavone@176 545 }
pavone@4 546 break;
pavone@4 547 case 5:
pavone@5 548 //EORI, EORI to CCR, EORI to SR
pavone@5 549 if ((*istream & 0xFF) == 0x3C) {
pavone@5 550 decoded->op = M68K_EORI_CCR;
pavone@5 551 decoded->extra.size = OPSIZE_BYTE;
pavone@5 552 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@15 553 decoded->src.params.immed = *(++istream) & 0xFF;
pavone@5 554 } else if((*istream & 0xFF) == 0x7C) {
pavone@5 555 decoded->op = M68K_EORI_SR;
pavone@5 556 decoded->extra.size = OPSIZE_WORD;
pavone@5 557 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@15 558 decoded->src.params.immed = *(++istream);
pavone@5 559 } else {
pavone@8 560 decoded->op = M68K_EOR;
pavone@8 561 decoded->variant = VAR_IMMEDIATE;
pavone@8 562 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@8 563 decoded->extra.size = size = (*istream >> 6) & 3;
pavone@8 564 reg = *istream & 0x7;
pavone@8 565 opmode = (*istream >> 3) & 0x7;
pavone@8 566 switch (size)
pavone@8 567 {
pavone@8 568 case OPSIZE_BYTE:
pavone@15 569 decoded->src.params.immed = *(++istream) & 0xFF;
pavone@8 570 break;
pavone@8 571 case OPSIZE_WORD:
pavone@15 572 decoded->src.params.immed = *(++istream);
pavone@8 573 break;
pavone@8 574 case OPSIZE_LONG:
pavone@8 575 immed = *(++istream);
pavone@15 576 decoded->src.params.immed = immed << 16 | *(++istream);
pavone@8 577 break;
pavone@5 578 }
pavone@8 579 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
pavone@823 580 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
pavone@176 581 decoded->op = M68K_INVALID;
pavone@630 582 break;
pavone@176 583 }
pavone@5 584 }
pavone@4 585 break;
pavone@4 586 case 6:
pavone@8 587 decoded->op = M68K_CMP;
pavone@8 588 decoded->variant = VAR_IMMEDIATE;
pavone@8 589 decoded->extra.size = (*istream >> 6) & 0x3;
pavone@8 590 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@8 591 reg = *istream & 0x7;
pavone@8 592 opmode = (*istream >> 3) & 0x7;
pavone@8 593 switch (decoded->extra.size)
pavone@8 594 {
pavone@8 595 case OPSIZE_BYTE:
pavone@15 596 decoded->src.params.immed = *(++istream) & 0xFF;
pavone@8 597 break;
pavone@8 598 case OPSIZE_WORD:
pavone@15 599 decoded->src.params.immed = *(++istream);
pavone@8 600 break;
pavone@8 601 case OPSIZE_LONG:
pavone@8 602 immed = *(++istream);
pavone@15 603 decoded->src.params.immed = (immed << 16) | *(++istream);
pavone@8 604 break;
pavone@8 605 }
pavone@630 606 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
pavone@823 607 if (!istream || !m68k_valid_immed_dst(&(decoded->dst))) {
pavone@176 608 decoded->op = M68K_INVALID;
pavone@630 609 break;
pavone@176 610 }
pavone@4 611 break;
pavone@4 612 case 7:
pavone@630 613 #ifdef M68010
pavone@630 614 decoded->op = M68K_MOVES;
pavone@630 615 decoded->extra.size = *istream >> 6 & 0x3;
pavone@630 616 immed = *(++istream);
pavone@630 617 reg = immed >> 12 & 0x7;
pavone@630 618 opmode = immed & 0x8000 ? MODE_AREG : MODE_REG;
pavone@630 619 if (immed & 0x800) {
pavone@642 620 decoded->src.addr_mode = opmode;
pavone@642 621 decoded->src.params.regs.pri = reg;
pavone@642 622 m68k_decode_op_ex(istream, *start >> 3 & 0x7, *start & 0x7, decoded->extra.size, &(decoded->dst));
pavone@642 623 } else {
pavone@630 624 m68k_decode_op_ex(istream, *start >> 3 & 0x7, *start & 0x7, decoded->extra.size, &(decoded->src));
pavone@630 625 decoded->dst.addr_mode = opmode;
pavone@630 626 decoded->dst.params.regs.pri = reg;
pavone@630 627 }
pavone@630 628 #endif
pavone@4 629 break;
pavone@4 630 }
pavone@4 631 }
pavone@0 632 break;
pavone@0 633 case MOVE_BYTE:
pavone@0 634 case MOVE_LONG:
pavone@0 635 case MOVE_WORD:
pavone@0 636 decoded->op = M68K_MOVE;
pavone@0 637 decoded->extra.size = optype == MOVE_BYTE ? OPSIZE_BYTE : (optype == MOVE_WORD ? OPSIZE_WORD : OPSIZE_LONG);
pavone@18 638 opmode = (*istream >> 6) & 0x7;
pavone@18 639 reg = m68k_reg_quick_field(*istream);
pavone@2 640 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
pavone@176 641 if (!istream) {
pavone@176 642 decoded->op = M68K_INVALID;
pavone@630 643 break;
pavone@176 644 }
pavone@18 645 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
pavone@197 646 if (!istream || decoded->dst.addr_mode == MODE_IMMEDIATE) {
pavone@176 647 decoded->op = M68K_INVALID;
pavone@630 648 break;
pavone@176 649 }
pavone@0 650 break;
pavone@0 651 case MISC:
pavone@518 652
pavone@2 653 if ((*istream & 0x1C0) == 0x1C0) {
pavone@2 654 decoded->op = M68K_LEA;
pavone@2 655 decoded->extra.size = OPSIZE_LONG;
pavone@2 656 decoded->dst.addr_mode = MODE_AREG;
pavone@18 657 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@2 658 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
pavone@176 659 if (!istream) {
pavone@176 660 decoded->op = M68K_INVALID;
pavone@630 661 break;
pavone@176 662 }
pavone@2 663 } else {
pavone@2 664 if (*istream & 0x100) {
pavone@2 665 decoded->op = M68K_CHK;
pavone@2 666 if ((*istream & 0x180) == 0x180) {
pavone@2 667 decoded->extra.size = OPSIZE_WORD;
pavone@2 668 } else {
pavone@2 669 //only on M68020+
pavone@9 670 #ifdef M68020
pavone@2 671 decoded->extra.size = OPSIZE_LONG;
pavone@9 672 #else
pavone@9 673 decoded->op = M68K_INVALID;
pavone@9 674 break;
pavone@9 675 #endif
pavone@2 676 }
pavone@184 677 decoded->dst.addr_mode = MODE_REG;
pavone@325 678 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@2 679 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
pavone@176 680 if (!istream) {
pavone@176 681 decoded->op = M68K_INVALID;
pavone@630 682 break;
pavone@176 683 }
pavone@2 684 } else {
pavone@13 685 opmode = (*istream >> 3) & 0x7;
pavone@61 686 if ((*istream & 0xB80) == 0x880 && opmode != MODE_REG && opmode != MODE_AREG) {
pavone@61 687 //TODO: Check for invalid modes that are dependent on direction
pavone@9 688 decoded->op = M68K_MOVEM;
pavone@9 689 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD;
pavone@13 690 reg = *istream & 0x7;
pavone@9 691 if(*istream & 0x400) {
pavone@9 692 decoded->dst.addr_mode = MODE_REG;
pavone@68 693 decoded->dst.params.immed = *(++istream);
pavone@9 694 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->src));
pavone@176 695 if (!istream) {
pavone@176 696 decoded->op = M68K_INVALID;
pavone@630 697 break;
pavone@176 698 }
pavone@412 699 if (decoded->src.addr_mode == MODE_PC_DISPLACE || decoded->src.addr_mode == MODE_PC_INDEX_DISP8) {
pavone@412 700 //adjust displacement to account for extra instruction word
pavone@412 701 decoded->src.params.regs.displacement += 2;
pavone@412 702 }
pavone@2 703 } else {
pavone@9 704 decoded->src.addr_mode = MODE_REG;
pavone@68 705 decoded->src.params.immed = *(++istream);
pavone@9 706 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
pavone@176 707 if (!istream) {
pavone@176 708 decoded->op = M68K_INVALID;
pavone@630 709 break;
pavone@176 710 }
pavone@9 711 }
pavone@9 712 } else {
pavone@9 713 optype = (*istream >> 9) & 0x7;
pavone@9 714 size = (*istream >> 6) & 0x3;
pavone@9 715 switch(optype)
pavone@9 716 {
pavone@9 717 case 0:
pavone@9 718 //Move from SR or NEGX
pavone@2 719 if (size == OPSIZE_INVALID) {
pavone@9 720 decoded->op = M68K_MOVE_FROM_SR;
pavone@9 721 size = OPSIZE_WORD;
pavone@2 722 } else {
pavone@9 723 decoded->op = M68K_NEGX;
pavone@2 724 }
pavone@9 725 decoded->extra.size = size;
pavone@9 726 istream= m68k_decode_op(istream, size, &(decoded->dst));
pavone@176 727 if (!istream) {
pavone@176 728 decoded->op = M68K_INVALID;
pavone@630 729 break;
pavone@176 730 }
pavone@9 731 break;
pavone@9 732 case 1:
pavone@9 733 //MOVE from CCR or CLR
pavone@9 734 if (size == OPSIZE_INVALID) {
pavone@9 735 #ifdef M68010
pavone@9 736 decoded->op = M68K_MOVE_FROM_CCR;
pavone@9 737 size = OPSIZE_WORD;
pavone@9 738 #else
pavone@630 739 break;
pavone@9 740 #endif
pavone@9 741 } else {
pavone@9 742 decoded->op = M68K_CLR;
pavone@9 743 }
pavone@9 744 decoded->extra.size = size;
pavone@9 745 istream= m68k_decode_op(istream, size, &(decoded->dst));
pavone@176 746 if (!istream) {
pavone@176 747 decoded->op = M68K_INVALID;
pavone@630 748 break;
pavone@176 749 }
pavone@9 750 break;
pavone@9 751 case 2:
pavone@9 752 //MOVE to CCR or NEG
pavone@9 753 if (size == OPSIZE_INVALID) {
pavone@9 754 decoded->op = M68K_MOVE_CCR;
pavone@9 755 size = OPSIZE_WORD;
pavone@9 756 istream= m68k_decode_op(istream, size, &(decoded->src));
pavone@176 757 if (!istream) {
pavone@176 758 decoded->op = M68K_INVALID;
pavone@630 759 break;
pavone@176 760 }
pavone@9 761 } else {
pavone@9 762 decoded->op = M68K_NEG;
pavone@9 763 istream= m68k_decode_op(istream, size, &(decoded->dst));
pavone@176 764 if (!istream) {
pavone@176 765 decoded->op = M68K_INVALID;
pavone@630 766 break;
pavone@176 767 }
pavone@9 768 }
pavone@9 769 decoded->extra.size = size;
pavone@9 770 break;
pavone@9 771 case 3:
pavone@9 772 //MOVE to SR or NOT
pavone@9 773 if (size == OPSIZE_INVALID) {
pavone@9 774 decoded->op = M68K_MOVE_SR;
pavone@9 775 size = OPSIZE_WORD;
pavone@9 776 istream= m68k_decode_op(istream, size, &(decoded->src));
pavone@176 777 if (!istream) {
pavone@176 778 decoded->op = M68K_INVALID;
pavone@630 779 break;
pavone@176 780 }
pavone@9 781 } else {
pavone@9 782 decoded->op = M68K_NOT;
pavone@9 783 istream= m68k_decode_op(istream, size, &(decoded->dst));
pavone@176 784 if (!istream) {
pavone@176 785 decoded->op = M68K_INVALID;
pavone@630 786 break;
pavone@176 787 }
pavone@9 788 }
pavone@9 789 decoded->extra.size = size;
pavone@9 790 break;
pavone@9 791 case 4:
pavone@9 792 //EXT, EXTB, LINK.l, NBCD, SWAP, BKPT, PEA
pavone@9 793 switch((*istream >> 3) & 0x3F)
pavone@2 794 {
pavone@2 795 case 1:
pavone@9 796 #ifdef M68020
pavone@9 797 decoded->op = M68K_LINK;
pavone@9 798 decoded->extra.size = OPSIZE_LONG;
pavone@9 799 reg = *istream & 0x7;
pavone@9 800 immed = *(++istream) << 16;
pavone@9 801 immed |= *(++istream);
pavone@9 802 #endif
pavone@2 803 break;
pavone@9 804 case 8:
pavone@9 805 decoded->op = M68K_SWAP;
pavone@9 806 decoded->src.addr_mode = MODE_REG;
pavone@9 807 decoded->src.params.regs.pri = *istream & 0x7;
pavone@9 808 decoded->extra.size = OPSIZE_WORD;
pavone@2 809 break;
pavone@9 810 case 9:
pavone@9 811 #ifdef M68010
pavone@9 812 decoded->op = M68K_BKPT;
pavone@9 813 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@10 814 decoded->extra.size = OPSIZE_UNSIZED;
pavone@15 815 decoded->src.params.immed = *istream & 0x7;
pavone@9 816 #endif
pavone@2 817 break;
pavone@9 818 case 0x10:
pavone@9 819 decoded->op = M68K_EXT;
pavone@93 820 decoded->dst.addr_mode = MODE_REG;
pavone@93 821 decoded->dst.params.regs.pri = *istream & 0x7;
pavone@9 822 decoded->extra.size = OPSIZE_WORD;
pavone@2 823 break;
pavone@9 824 case 0x18:
pavone@9 825 decoded->op = M68K_EXT;
pavone@93 826 decoded->dst.addr_mode = MODE_REG;
pavone@93 827 decoded->dst.params.regs.pri = *istream & 0x7;
pavone@9 828 decoded->extra.size = OPSIZE_LONG;
pavone@9 829 break;
pavone@9 830 case 0x38:
pavone@9 831 #ifdef M68020
pavone@9 832 #endif
pavone@9 833 break;
pavone@9 834 default:
pavone@9 835 if (!(*istream & 0x1C0)) {
pavone@9 836 decoded->op = M68K_NBCD;
pavone@9 837 decoded->extra.size = OPSIZE_BYTE;
pavone@9 838 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
pavone@176 839 if (!istream) {
pavone@176 840 decoded->op = M68K_INVALID;
pavone@630 841 break;
pavone@176 842 }
pavone@13 843 } else if((*istream & 0x1C0) == 0x40) {
pavone@9 844 decoded->op = M68K_PEA;
pavone@9 845 decoded->extra.size = OPSIZE_LONG;
pavone@116 846 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src));
pavone@176 847 if (!istream) {
pavone@176 848 decoded->op = M68K_INVALID;
pavone@630 849 break;
pavone@176 850 }
pavone@9 851 }
pavone@9 852 }
pavone@9 853 break;
pavone@9 854 case 5:
pavone@9 855 //BGND, ILLEGAL, TAS, TST
pavone@9 856 optype = *istream & 0xFF;
pavone@9 857 if (optype == 0xFA) {
pavone@9 858 //BGND - CPU32 only
pavone@9 859 } else if (optype == 0xFC) {
pavone@9 860 decoded->op = M68K_ILLEGAL;
pavone@10 861 decoded->extra.size = OPSIZE_UNSIZED;
pavone@9 862 } else {
pavone@9 863 if (size == OPSIZE_INVALID) {
pavone@9 864 decoded->op = M68K_TAS;
pavone@835 865 decoded->extra.size = OPSIZE_BYTE;
pavone@835 866 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst));
pavone@835 867 if (!istream) {
pavone@835 868 decoded->op = M68K_INVALID;
pavone@835 869 break;
pavone@835 870 }
pavone@9 871 } else {
pavone@9 872 decoded->op = M68K_TST;
pavone@9 873 decoded->extra.size = size;
pavone@9 874 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
pavone@176 875 if (!istream) {
pavone@176 876 decoded->op = M68K_INVALID;
pavone@630 877 break;
pavone@176 878 }
pavone@9 879 }
pavone@9 880 }
pavone@518 881 break;
pavone@9 882 case 6:
pavone@9 883 //MULU, MULS, DIVU, DIVUL, DIVS, DIVSL
pavone@9 884 #ifdef M68020
pavone@9 885 //TODO: Implement these for 68020+ support
pavone@9 886 #endif
pavone@9 887 break;
pavone@9 888 case 7:
pavone@9 889 //TRAP, LINK.w, UNLNK, MOVE USP, RESET, NOP, STOP, RTE, RTD, RTS, TRAPV, RTR, MOVEC, JSR, JMP
pavone@9 890 if (*istream & 0x80) {
pavone@9 891 //JSR, JMP
pavone@9 892 if (*istream & 0x40) {
pavone@9 893 decoded->op = M68K_JMP;
pavone@9 894 } else {
pavone@9 895 decoded->op = M68K_JSR;
pavone@9 896 }
pavone@10 897 decoded->extra.size = OPSIZE_UNSIZED;
pavone@10 898 istream = m68k_decode_op(istream, OPSIZE_UNSIZED, &(decoded->src));
pavone@176 899 if (!istream) {
pavone@176 900 decoded->op = M68K_INVALID;
pavone@630 901 break;
pavone@176 902 }
pavone@9 903 } else {
pavone@9 904 //it would appear bit 6 needs to be set for it to be a valid instruction here
pavone@9 905 switch((*istream >> 3) & 0x7)
pavone@2 906 {
pavone@2 907 case 0:
pavone@2 908 case 1:
pavone@9 909 //TRAP
pavone@9 910 decoded->op = M68K_TRAP;
pavone@10 911 decoded->extra.size = OPSIZE_UNSIZED;
pavone@9 912 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@15 913 decoded->src.params.immed = *istream & 0xF;
pavone@2 914 break;
pavone@2 915 case 2:
pavone@9 916 //LINK.w
pavone@9 917 decoded->op = M68K_LINK;
pavone@2 918 decoded->extra.size = OPSIZE_WORD;
pavone@9 919 decoded->src.addr_mode = MODE_AREG;
pavone@9 920 decoded->src.params.regs.pri = *istream & 0x7;
pavone@9 921 decoded->dst.addr_mode = MODE_IMMEDIATE;
pavone@93 922 decoded->dst.params.immed = sign_extend16(*(++istream));
pavone@2 923 break;
pavone@2 924 case 3:
pavone@9 925 //UNLK
pavone@9 926 decoded->op = M68K_UNLK;
pavone@10 927 decoded->extra.size = OPSIZE_UNSIZED;
pavone@9 928 decoded->dst.addr_mode = MODE_AREG;
pavone@9 929 decoded->dst.params.regs.pri = *istream & 0x7;
pavone@2 930 break;
pavone@2 931 case 4:
pavone@9 932 case 5:
pavone@9 933 //MOVE USP
pavone@9 934 decoded->op = M68K_MOVE_USP;
pavone@9 935 if (*istream & 0x8) {
pavone@9 936 decoded->dst.addr_mode = MODE_AREG;
pavone@9 937 decoded->dst.params.regs.pri = *istream & 0x7;
pavone@9 938 } else {
pavone@9 939 decoded->src.addr_mode = MODE_AREG;
pavone@9 940 decoded->src.params.regs.pri = *istream & 0x7;
pavone@9 941 }
pavone@9 942 break;
pavone@9 943 case 6:
pavone@10 944 decoded->extra.size = OPSIZE_UNSIZED;
pavone@9 945 switch(*istream & 0x7)
pavone@9 946 {
pavone@9 947 case 0:
pavone@9 948 decoded->op = M68K_RESET;
pavone@9 949 break;
pavone@9 950 case 1:
pavone@9 951 decoded->op = M68K_NOP;
pavone@9 952 break;
pavone@9 953 case 2:
pavone@9 954 decoded->op = M68K_STOP;
pavone@9 955 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@15 956 decoded->src.params.immed =*(++istream);
pavone@9 957 break;
pavone@9 958 case 3:
pavone@9 959 decoded->op = M68K_RTE;
pavone@9 960 break;
pavone@9 961 case 4:
pavone@2 962 #ifdef M68010
pavone@9 963 decoded->op = M68K_RTD;
pavone@9 964 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@15 965 decoded->src.params.immed =*(++istream);
pavone@9 966 #endif
pavone@9 967 break;
pavone@9 968 case 5:
pavone@9 969 decoded->op = M68K_RTS;
pavone@9 970 break;
pavone@9 971 case 6:
pavone@9 972 decoded->op = M68K_TRAPV;
pavone@9 973 break;
pavone@9 974 case 7:
pavone@9 975 decoded->op = M68K_RTR;
pavone@9 976 break;
pavone@9 977 }
pavone@9 978 break;
pavone@9 979 case 7:
pavone@9 980 //MOVEC
pavone@9 981 #ifdef M68010
pavone@630 982 decoded->op = M68K_MOVEC;
pavone@630 983 immed = *(++istream);
pavone@630 984 reg = immed >> 12 & 0x7;
pavone@630 985 opmode = immed & 0x8000 ? MODE_AREG : MODE_REG;
pavone@641 986 immed &= 0xFFF;
pavone@630 987 if (immed & 0x800) {
pavone@630 988 if (immed > MAX_HIGH_CR) {
pavone@630 989 decoded->op = M68K_INVALID;
pavone@630 990 break;
pavone@630 991 } else {
pavone@630 992 immed = immed - 0x800 + CR_USP;
pavone@630 993 }
pavone@630 994 } else {
pavone@630 995 if (immed > MAX_LOW_CR) {
pavone@630 996 decoded->op = M68K_INVALID;
pavone@630 997 break;
pavone@630 998 }
pavone@630 999 }
pavone@630 1000 if (*start & 1) {
pavone@630 1001 decoded->src.addr_mode = opmode;
pavone@630 1002 decoded->src.params.regs.pri = reg;
pavone@630 1003 decoded->dst.params.immed = immed;
pavone@630 1004 } else {
pavone@630 1005 decoded->dst.addr_mode = opmode;
pavone@630 1006 decoded->dst.params.regs.pri = reg;
pavone@630 1007 decoded->src.params.immed = immed;
pavone@630 1008 }
pavone@2 1009 #endif
pavone@2 1010 break;
pavone@2 1011 }
pavone@2 1012 }
pavone@9 1013 break;
pavone@2 1014 }
pavone@2 1015 }
pavone@2 1016 }
pavone@2 1017 }
pavone@0 1018 break;
pavone@0 1019 case QUICK_ARITH_LOOP:
pavone@0 1020 size = (*istream >> 6) & 3;
pavone@0 1021 if (size == 0x3) {
pavone@0 1022 //DBcc, TRAPcc or Scc
pavone@2 1023 m68k_decode_cond(*istream, decoded);
pavone@111 1024 if (((*istream >> 3) & 0x7) == 1) {
pavone@0 1025 decoded->op = M68K_DBCC;
pavone@2 1026 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@0 1027 decoded->dst.addr_mode = MODE_REG;
pavone@2 1028 decoded->dst.params.regs.pri = *istream & 0x7;
pavone@46 1029 decoded->src.params.immed = sign_extend16(*(++istream));
pavone@111 1030 } else if(((*istream >> 3) & 0x7) == 1 && (*istream & 0x7) > 1 && (*istream & 0x7) < 5) {
pavone@2 1031 #ifdef M68020
pavone@0 1032 decoded->op = M68K_TRAPCC;
pavone@2 1033 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@0 1034 //TODO: Figure out what to do with OPMODE and optional extention words
pavone@2 1035 #endif
pavone@111 1036 } else {
pavone@0 1037 decoded->op = M68K_SCC;
pavone@111 1038 decoded->extra.cond = (*istream >> 8) & 0xF;
pavone@2 1039 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
pavone@176 1040 if (!istream) {
pavone@176 1041 decoded->op = M68K_INVALID;
pavone@630 1042 break;
pavone@176 1043 }
pavone@0 1044 }
pavone@0 1045 } else {
pavone@0 1046 //ADDQ, SUBQ
pavone@0 1047 decoded->variant = VAR_QUICK;
pavone@0 1048 decoded->extra.size = size;
pavone@2 1049 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@91 1050 immed = m68k_reg_quick_field(*istream);
pavone@0 1051 if (!immed) {
pavone@0 1052 immed = 8;
pavone@0 1053 }
pavone@15 1054 decoded->src.params.immed = immed;
pavone@2 1055 if (*istream & 0x100) {
pavone@0 1056 decoded->op = M68K_SUB;
pavone@0 1057 } else {
pavone@0 1058 decoded->op = M68K_ADD;
pavone@0 1059 }
pavone@94 1060 istream = m68k_decode_op(istream, size, &(decoded->dst));
pavone@176 1061 if (!istream) {
pavone@176 1062 decoded->op = M68K_INVALID;
pavone@630 1063 break;
pavone@176 1064 }
pavone@0 1065 }
pavone@0 1066 break;
pavone@2 1067 case BRANCH:
pavone@2 1068 m68k_decode_cond(*istream, decoded);
pavone@2 1069 decoded->op = decoded->extra.cond == COND_FALSE ? M68K_BSR : M68K_BCC;
pavone@2 1070 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@2 1071 immed = *istream & 0xFF;
pavone@2 1072 if (immed == 0) {
pavone@2 1073 decoded->variant = VAR_WORD;
pavone@2 1074 immed = *(++istream);
pavone@2 1075 immed = sign_extend16(immed);
pavone@154 1076 #ifdef M68020
pavone@2 1077 } else if (immed == 0xFF) {
pavone@2 1078 decoded->variant = VAR_LONG;
pavone@2 1079 immed = *(++istream) << 16;
pavone@2 1080 immed |= *(++istream);
pavone@154 1081 #endif
pavone@2 1082 } else {
pavone@2 1083 decoded->variant = VAR_BYTE;
pavone@2 1084 immed = sign_extend8(immed);
pavone@2 1085 }
pavone@15 1086 decoded->src.params.immed = immed;
pavone@2 1087 break;
pavone@2 1088 case MOVEQ:
pavone@208 1089 if (*istream & 0x100) {
pavone@208 1090 decoded->op = M68K_INVALID;
pavone@630 1091 break;
pavone@208 1092 }
pavone@2 1093 decoded->op = M68K_MOVE;
pavone@2 1094 decoded->variant = VAR_QUICK;
pavone@15 1095 decoded->extra.size = OPSIZE_LONG;
pavone@2 1096 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@15 1097 decoded->src.params.immed = sign_extend8(*istream & 0xFF);
pavone@2 1098 decoded->dst.addr_mode = MODE_REG;
pavone@18 1099 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@2 1100 immed = *istream & 0xFF;
pavone@2 1101 break;
pavone@2 1102 case OR_DIV_SBCD:
pavone@11 1103 //for OR, if opmode bit 2 is 1, then src = Dn, dst = <ea>
pavone@11 1104 opmode = (*istream >> 6) & 0x7;
pavone@11 1105 size = opmode & 0x3;
pavone@11 1106 if (size == OPSIZE_INVALID || (opmode & 0x4 && !(*istream & 0x30))) {
pavone@11 1107 switch(opmode)
pavone@11 1108 {
pavone@11 1109 case 3:
pavone@11 1110 decoded->op = M68K_DIVU;
pavone@11 1111 decoded->extra.size = OPSIZE_WORD;
pavone@11 1112 decoded->dst.addr_mode = MODE_REG;
pavone@11 1113 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7;
pavone@11 1114 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
pavone@183 1115 if (!istream || decoded->src.addr_mode == MODE_AREG) {
pavone@176 1116 decoded->op = M68K_INVALID;
pavone@630 1117 break;
pavone@176 1118 }
pavone@11 1119 break;
pavone@11 1120 case 4:
pavone@11 1121 decoded->op = M68K_SBCD;
pavone@613 1122 decoded->extra.size = OPSIZE_BYTE;
pavone@11 1123 decoded->dst.addr_mode = decoded->src.addr_mode = *istream & 0x8 ? MODE_AREG_PREDEC : MODE_REG;
pavone@11 1124 decoded->src.params.regs.pri = *istream & 0x7;
pavone@11 1125 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7;
pavone@11 1126 break;
pavone@11 1127 case 5:
pavone@11 1128 #ifdef M68020
pavone@11 1129 #endif
pavone@11 1130 break;
pavone@11 1131 case 6:
pavone@11 1132 #ifdef M68020
pavone@11 1133 #endif
pavone@11 1134 break;
pavone@11 1135 case 7:
pavone@11 1136 decoded->op = M68K_DIVS;
pavone@11 1137 decoded->extra.size = OPSIZE_WORD;
pavone@11 1138 decoded->dst.addr_mode = MODE_REG;
pavone@11 1139 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7;
pavone@11 1140 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
pavone@183 1141 if (!istream || decoded->src.addr_mode == MODE_AREG) {
pavone@176 1142 decoded->op = M68K_INVALID;
pavone@630 1143 break;
pavone@176 1144 }
pavone@518 1145 break;
pavone@11 1146 }
pavone@11 1147 } else {
pavone@11 1148 decoded->op = M68K_OR;
pavone@11 1149 decoded->extra.size = size;
pavone@11 1150 if (opmode & 0x4) {
pavone@11 1151 decoded->src.addr_mode = MODE_REG;
pavone@11 1152 decoded->src.params.regs.pri = (*istream >> 9) & 0x7;
pavone@11 1153 istream = m68k_decode_op(istream, size, &(decoded->dst));
pavone@176 1154 if (!istream) {
pavone@176 1155 decoded->op = M68K_INVALID;
pavone@630 1156 break;
pavone@176 1157 }
pavone@11 1158 } else {
pavone@11 1159 decoded->dst.addr_mode = MODE_REG;
pavone@11 1160 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7;
pavone@11 1161 istream = m68k_decode_op(istream, size, &(decoded->src));
pavone@176 1162 if (!istream) {
pavone@176 1163 decoded->op = M68K_INVALID;
pavone@630 1164 break;
pavone@176 1165 }
pavone@11 1166 }
pavone@11 1167 }
pavone@2 1168 break;
pavone@2 1169 case SUB_SUBX:
pavone@101 1170 size = (*istream >> 6) & 0x3;
pavone@2 1171 decoded->op = M68K_SUB;
pavone@2 1172 if (*istream & 0x100) {
pavone@2 1173 //<ea> destination, SUBA.l or SUBX
pavone@101 1174 if (*istream & 0x30 || size == OPSIZE_INVALID) {
pavone@2 1175 if (size == OPSIZE_INVALID) {
pavone@2 1176 //SUBA.l
pavone@2 1177 decoded->extra.size = OPSIZE_LONG;
pavone@2 1178 decoded->dst.addr_mode = MODE_AREG;
pavone@18 1179 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@2 1180 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src));
pavone@176 1181 if (!istream) {
pavone@176 1182 decoded->op = M68K_INVALID;
pavone@630 1183 break;
pavone@176 1184 }
pavone@2 1185 } else {
pavone@2 1186 decoded->extra.size = size;
pavone@2 1187 decoded->src.addr_mode = MODE_REG;
pavone@18 1188 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@2 1189 istream = m68k_decode_op(istream, size, &(decoded->dst));
pavone@176 1190 if (!istream) {
pavone@176 1191 decoded->op = M68K_INVALID;
pavone@630 1192 break;
pavone@176 1193 }
pavone@2 1194 }
pavone@2 1195 } else {
pavone@2 1196 //SUBX
pavone@2 1197 decoded->op = M68K_SUBX;
pavone@2 1198 decoded->extra.size = size;
pavone@184 1199 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@184 1200 decoded->src.params.regs.pri = *istream & 0x7;
pavone@184 1201 if (*istream & 0x8) {
pavone@184 1202 decoded->dst.addr_mode = decoded->src.addr_mode = MODE_AREG_PREDEC;
pavone@184 1203 } else {
pavone@184 1204 decoded->dst.addr_mode = decoded->src.addr_mode = MODE_REG;
pavone@176 1205 }
pavone@2 1206 }
pavone@2 1207 } else {
pavone@2 1208 if (size == OPSIZE_INVALID) {
pavone@2 1209 //SUBA.w
pavone@2 1210 decoded->extra.size = OPSIZE_WORD;
pavone@2 1211 decoded->dst.addr_mode = MODE_AREG;
pavone@2 1212 } else {
pavone@2 1213 decoded->extra.size = size;
pavone@2 1214 decoded->dst.addr_mode = MODE_REG;
pavone@2 1215 }
pavone@18 1216 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@2 1217 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
pavone@176 1218 if (!istream) {
pavone@176 1219 decoded->op = M68K_INVALID;
pavone@630 1220 break;
pavone@176 1221 }
pavone@2 1222 }
pavone@2 1223 break;
pavone@2 1224 case RESERVED:
pavone@2 1225 break;
pavone@2 1226 case CMP_XOR:
pavone@120 1227 size = (*istream >> 6) & 0x3;
pavone@2 1228 decoded->op = M68K_CMP;
pavone@2 1229 if (*istream & 0x100) {
pavone@120 1230 //CMPM or CMPA.l or EOR
pavone@120 1231 if (size == OPSIZE_INVALID) {
pavone@120 1232 decoded->extra.size = OPSIZE_LONG;
pavone@120 1233 decoded->dst.addr_mode = MODE_AREG;
pavone@18 1234 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@136 1235 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
pavone@176 1236 if (!istream) {
pavone@176 1237 decoded->op = M68K_INVALID;
pavone@630 1238 break;
pavone@176 1239 }
pavone@2 1240 } else {
pavone@184 1241 reg = m68k_reg_quick_field(*istream);
pavone@120 1242 istream = m68k_decode_op(istream, size, &(decoded->dst));
pavone@176 1243 if (!istream) {
pavone@176 1244 decoded->op = M68K_INVALID;
pavone@630 1245 break;
pavone@176 1246 }
pavone@181 1247 decoded->extra.size = size;
pavone@181 1248 if (decoded->dst.addr_mode == MODE_AREG) {
pavone@120 1249 //CMPM
pavone@120 1250 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG_POSTINC;
pavone@120 1251 decoded->src.params.regs.pri = decoded->dst.params.regs.pri;
pavone@184 1252 decoded->dst.params.regs.pri = reg;
pavone@120 1253 } else {
pavone@120 1254 //EOR
pavone@120 1255 decoded->op = M68K_EOR;
pavone@120 1256 decoded->src.addr_mode = MODE_REG;
pavone@184 1257 decoded->src.params.regs.pri = reg;
pavone@120 1258 }
pavone@2 1259 }
pavone@2 1260 } else {
pavone@120 1261 //CMP or CMPA.w
pavone@120 1262 if (size == OPSIZE_INVALID) {
pavone@120 1263 decoded->extra.size = OPSIZE_WORD;
pavone@120 1264 decoded->dst.addr_mode = MODE_AREG;
pavone@120 1265 } else {
pavone@120 1266 decoded->extra.size = size;
pavone@120 1267 decoded->dst.addr_mode = MODE_REG;
pavone@120 1268 }
pavone@18 1269 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@136 1270 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
pavone@176 1271 if (!istream) {
pavone@176 1272 decoded->op = M68K_INVALID;
pavone@630 1273 break;
pavone@176 1274 }
pavone@2 1275 }
pavone@2 1276 break;
pavone@2 1277 case AND_MUL_ABCD_EXG:
pavone@2 1278 //page 575 for summary
pavone@2 1279 //EXG opmodes:
pavone@2 1280 //01000 -data regs
pavone@2 1281 //01001 -addr regs
pavone@2 1282 //10001 -one of each
pavone@2 1283 //AND opmodes:
pavone@2 1284 //operand order bit + 2 size bits (00 - 10)
pavone@2 1285 //no address register direct addressing
pavone@2 1286 //data register direct not allowed when <ea> is the source (operand order bit of 1)
pavone@2 1287 if (*istream & 0x100) {
pavone@2 1288 if ((*istream & 0xC0) == 0xC0) {
pavone@2 1289 decoded->op = M68K_MULS;
pavone@2 1290 decoded->extra.size = OPSIZE_WORD;
pavone@3 1291 decoded->dst.addr_mode = MODE_REG;
pavone@18 1292 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@2 1293 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
pavone@176 1294 if (!istream) {
pavone@176 1295 decoded->op = M68K_INVALID;
pavone@630 1296 break;
pavone@176 1297 }
pavone@2 1298 } else if(!(*istream & 0xF0)) {
pavone@2 1299 decoded->op = M68K_ABCD;
pavone@3 1300 decoded->extra.size = OPSIZE_BYTE;
pavone@3 1301 decoded->src.params.regs.pri = *istream & 0x7;
pavone@18 1302 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@3 1303 decoded->dst.addr_mode = decoded->src.addr_mode = (*istream & 8) ? MODE_AREG_PREDEC : MODE_REG;
pavone@2 1304 } else if(!(*istream & 0x30)) {
pavone@2 1305 decoded->op = M68K_EXG;
pavone@2 1306 decoded->extra.size = OPSIZE_LONG;
pavone@18 1307 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@2 1308 decoded->dst.params.regs.pri = *istream & 0x7;
pavone@2 1309 if (*istream & 0x8) {
pavone@2 1310 if (*istream & 0x80) {
pavone@2 1311 decoded->src.addr_mode = MODE_REG;
pavone@2 1312 decoded->dst.addr_mode = MODE_AREG;
pavone@2 1313 } else {
pavone@2 1314 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG;
pavone@2 1315 }
pavone@2 1316 } else {
pavone@2 1317 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_REG;
pavone@2 1318 }
pavone@2 1319 } else {
pavone@2 1320 decoded->op = M68K_AND;
pavone@90 1321 decoded->extra.size = (*istream >> 6) & 0x3;
pavone@60 1322 decoded->src.addr_mode = MODE_REG;
pavone@60 1323 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@60 1324 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst));
pavone@176 1325 if (!istream) {
pavone@176 1326 decoded->op = M68K_INVALID;
pavone@630 1327 break;
pavone@176 1328 }
pavone@2 1329 }
pavone@2 1330 } else {
pavone@2 1331 if ((*istream & 0xC0) == 0xC0) {
pavone@2 1332 decoded->op = M68K_MULU;
pavone@2 1333 decoded->extra.size = OPSIZE_WORD;
pavone@3 1334 decoded->dst.addr_mode = MODE_REG;
pavone@18 1335 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@2 1336 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
pavone@176 1337 if (!istream) {
pavone@176 1338 decoded->op = M68K_INVALID;
pavone@630 1339 break;
pavone@176 1340 }
pavone@2 1341 } else {
pavone@2 1342 decoded->op = M68K_AND;
pavone@90 1343 decoded->extra.size = (*istream >> 6) & 0x3;
pavone@60 1344 decoded->dst.addr_mode = MODE_REG;
pavone@60 1345 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@60 1346 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
pavone@176 1347 if (!istream) {
pavone@176 1348 decoded->op = M68K_INVALID;
pavone@630 1349 break;
pavone@176 1350 }
pavone@2 1351 }
pavone@2 1352 }
pavone@2 1353 break;
pavone@2 1354 case ADD_ADDX:
pavone@101 1355 size = (*istream >> 6) & 0x3;
pavone@2 1356 decoded->op = M68K_ADD;
pavone@2 1357 if (*istream & 0x100) {
pavone@2 1358 //<ea> destination, ADDA.l or ADDX
pavone@101 1359 if (*istream & 0x30 || size == OPSIZE_INVALID) {
pavone@2 1360 if (size == OPSIZE_INVALID) {
pavone@2 1361 //ADDA.l
pavone@2 1362 decoded->extra.size = OPSIZE_LONG;
pavone@2 1363 decoded->dst.addr_mode = MODE_AREG;
pavone@18 1364 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@2 1365 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src));
pavone@176 1366 if (!istream) {
pavone@176 1367 decoded->op = M68K_INVALID;
pavone@630 1368 break;
pavone@176 1369 }
pavone@2 1370 } else {
pavone@2 1371 decoded->extra.size = size;
pavone@2 1372 decoded->src.addr_mode = MODE_REG;
pavone@18 1373 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@2 1374 istream = m68k_decode_op(istream, size, &(decoded->dst));
pavone@176 1375 if (!istream) {
pavone@176 1376 decoded->op = M68K_INVALID;
pavone@630 1377 break;
pavone@176 1378 }
pavone@2 1379 }
pavone@2 1380 } else {
pavone@2 1381 //ADDX
pavone@2 1382 decoded->op = M68K_ADDX;
pavone@2 1383 decoded->extra.size = size;
pavone@184 1384 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@184 1385 decoded->src.params.regs.pri = *istream & 0x7;
pavone@184 1386 if (*istream & 0x8) {
pavone@184 1387 decoded->dst.addr_mode = decoded->src.addr_mode = MODE_AREG_PREDEC;
pavone@184 1388 } else {
pavone@184 1389 decoded->dst.addr_mode = decoded->src.addr_mode = MODE_REG;
pavone@176 1390 }
pavone@2 1391 }
pavone@2 1392 } else {
pavone@2 1393 if (size == OPSIZE_INVALID) {
pavone@2 1394 //ADDA.w
pavone@2 1395 decoded->extra.size = OPSIZE_WORD;
pavone@2 1396 decoded->dst.addr_mode = MODE_AREG;
pavone@2 1397 } else {
pavone@2 1398 decoded->extra.size = size;
pavone@2 1399 decoded->dst.addr_mode = MODE_REG;
pavone@2 1400 }
pavone@18 1401 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
pavone@2 1402 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
pavone@176 1403 if (!istream) {
pavone@176 1404 decoded->op = M68K_INVALID;
pavone@630 1405 break;
pavone@176 1406 }
pavone@2 1407 }
pavone@2 1408 break;
pavone@2 1409 case SHIFT_ROTATE:
pavone@9 1410 if ((*istream & 0x8C0) == 0xC0) {
pavone@9 1411 switch((*istream >> 8) & 0x7)
pavone@9 1412 {
pavone@9 1413 case 0:
pavone@9 1414 decoded->op = M68K_ASR;
pavone@9 1415 break;
pavone@9 1416 case 1:
pavone@9 1417 decoded->op = M68K_ASL;
pavone@9 1418 break;
pavone@9 1419 case 2:
pavone@9 1420 decoded->op = M68K_LSR;
pavone@9 1421 break;
pavone@9 1422 case 3:
pavone@9 1423 decoded->op = M68K_LSL;
pavone@9 1424 break;
pavone@9 1425 case 4:
pavone@9 1426 decoded->op = M68K_ROXR;
pavone@9 1427 break;
pavone@9 1428 case 5:
pavone@9 1429 decoded->op = M68K_ROXL;
pavone@9 1430 break;
pavone@9 1431 case 6:
pavone@9 1432 decoded->op = M68K_ROR;
pavone@9 1433 break;
pavone@9 1434 case 7:
pavone@9 1435 decoded->op = M68K_ROL;
pavone@9 1436 break;
pavone@9 1437 }
pavone@9 1438 decoded->extra.size = OPSIZE_WORD;
pavone@9 1439 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->dst));
pavone@176 1440 if (!istream) {
pavone@176 1441 decoded->op = M68K_INVALID;
pavone@630 1442 break;
pavone@176 1443 }
pavone@9 1444 } else if((*istream & 0xC0) != 0xC0) {
pavone@9 1445 switch(((*istream >> 2) & 0x6) | ((*istream >> 8) & 1))
pavone@9 1446 {
pavone@9 1447 case 0:
pavone@9 1448 decoded->op = M68K_ASR;
pavone@9 1449 break;
pavone@9 1450 case 1:
pavone@9 1451 decoded->op = M68K_ASL;
pavone@9 1452 break;
pavone@9 1453 case 2:
pavone@9 1454 decoded->op = M68K_LSR;
pavone@9 1455 break;
pavone@9 1456 case 3:
pavone@9 1457 decoded->op = M68K_LSL;
pavone@9 1458 break;
pavone@9 1459 case 4:
pavone@9 1460 decoded->op = M68K_ROXR;
pavone@9 1461 break;
pavone@9 1462 case 5:
pavone@9 1463 decoded->op = M68K_ROXL;
pavone@9 1464 break;
pavone@9 1465 case 6:
pavone@9 1466 decoded->op = M68K_ROR;
pavone@9 1467 break;
pavone@9 1468 case 7:
pavone@9 1469 decoded->op = M68K_ROL;
pavone@9 1470 break;
pavone@9 1471 }
pavone@9 1472 decoded->extra.size = (*istream >> 6) & 0x3;
pavone@9 1473 immed = (*istream >> 9) & 0x7;
pavone@51 1474 if (*istream & 0x20) {
pavone@9 1475 decoded->src.addr_mode = MODE_REG;
pavone@9 1476 decoded->src.params.regs.pri = immed;
pavone@50 1477 } else {
pavone@50 1478 decoded->src.addr_mode = MODE_IMMEDIATE;
pavone@50 1479 if (!immed) {
pavone@50 1480 immed = 8;
pavone@50 1481 }
pavone@50 1482 decoded->src.params.immed = immed;
pavone@9 1483 }
pavone@9 1484 decoded->dst.addr_mode = MODE_REG;
pavone@9 1485 decoded->dst.params.regs.pri = *istream & 0x7;
pavone@518 1486
pavone@9 1487 } else {
pavone@9 1488 #ifdef M68020
pavone@9 1489 //TODO: Implement bitfield instructions for M68020+ support
pavone@636 1490 switch (*istream >> 8 & 7)
pavone@636 1491 {
pavone@636 1492 case 0:
pavone@636 1493 decoded->op = M68K_BFTST; //<ea>
pavone@636 1494 break;
pavone@636 1495 case 1:
pavone@636 1496 decoded->op = M68K_BFEXTU; //<ea>, Dn
pavone@636 1497 break;
pavone@636 1498 case 2:
pavone@636 1499 decoded->op = M68K_BFCHG; //<ea>
pavone@636 1500 break;
pavone@636 1501 case 3:
pavone@636 1502 decoded->op = M68K_BFEXTS; //<ea>, Dn
pavone@636 1503 break;
pavone@636 1504 case 4:
pavone@636 1505 decoded->op = M68K_BFCLR; //<ea>
pavone@636 1506 break;
pavone@636 1507 case 5:
pavone@636 1508 decoded->op = M68K_BFFFO; //<ea>, Dn
pavone@636 1509 break;
pavone@636 1510 case 6:
pavone@636 1511 decoded->op = M68K_BFSET; //<ea>
pavone@636 1512 break;
pavone@636 1513 case 7:
pavone@636 1514 decoded->op = M68K_BFINS; //Dn, <ea>
pavone@636 1515 break;
pavone@636 1516 }
pavone@636 1517 opmode = *istream >> 3 & 0x7;
pavone@636 1518 reg = *istream & 0x7;
pavone@636 1519 m68k_op_info *ea, *other;
pavone@636 1520 if (decoded->op == M68K_BFEXTU || decoded->op == M68K_BFEXTS || decoded->op == M68K_BFFFO)
pavone@636 1521 {
pavone@636 1522 ea = &(decoded->src);
pavone@636 1523 other = &(decoded->dst);
pavone@636 1524 } else {
pavone@636 1525 ea = &(decoded->dst);
pavone@636 1526 other = &(decoded->dst);
pavone@636 1527 }
pavone@636 1528 if (*istream & 0x100)
pavone@636 1529 {
pavone@636 1530 immed = *(istream++);
pavone@636 1531 other->addr_mode = MODE_REG;
pavone@636 1532 other->params.regs.pri = immed >> 12 & 0x7;
pavone@636 1533 } else {
pavone@636 1534 immed = *(istream++);
pavone@636 1535 }
pavone@636 1536 decoded->extra.size = OPSIZE_UNSIZED;
pavone@636 1537 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, ea);
pavone@636 1538 ea->addr_mode |= M68K_FLAG_BITFIELD;
pavone@636 1539 ea->bitfield = immed & 0xFFF;
pavone@9 1540 #endif
pavone@9 1541 }
pavone@2 1542 break;
pavone@2 1543 case COPROC:
pavone@2 1544 //TODO: Implement me
pavone@2 1545 break;
pavone@2 1546 }
pavone@630 1547 if (decoded->op == M68K_INVALID) {
pavone@630 1548 decoded->src.params.immed = *start;
pavone@981 1549 decoded->bytes = 2;
pavone@630 1550 return start + 1;
pavone@630 1551 }
pavone@981 1552 decoded->bytes = 2 * (istream + 1 - start);
pavone@2 1553 return istream+1;
pavone@2 1554 }
pavone@2 1555
pavone@518 1556 uint32_t m68k_branch_target(m68kinst * inst, uint32_t *dregs, uint32_t *aregs)
pavone@518 1557 {
pavone@518 1558 if(inst->op == M68K_BCC || inst->op == M68K_BSR || inst->op == M68K_DBCC) {
pavone@518 1559 return inst->address + 2 + inst->src.params.immed;
pavone@518 1560 } else if(inst->op == M68K_JMP || inst->op == M68K_JSR) {
pavone@518 1561 uint32_t ret = 0;
pavone@518 1562 switch(inst->src.addr_mode)
pavone@518 1563 {
pavone@518 1564 case MODE_AREG_INDIRECT:
pavone@518 1565 ret = aregs[inst->src.params.regs.pri];
pavone@518 1566 break;
pavone@518 1567 case MODE_AREG_INDEX_DISP8: {
pavone@518 1568 uint8_t sec_reg = inst->src.params.regs.sec >> 1 & 0x7;
pavone@518 1569 ret = aregs[inst->src.params.regs.pri];
pavone@518 1570 uint32_t * regfile = inst->src.params.regs.sec & 0x10 ? aregs : dregs;
pavone@518 1571 if (inst->src.params.regs.sec & 1) {
pavone@518 1572 //32-bit index register
pavone@518 1573 ret += regfile[sec_reg];
pavone@518 1574 } else {
pavone@518 1575 //16-bit index register
pavone@518 1576 if (regfile[sec_reg] & 0x8000) {
pavone@518 1577 ret += (0xFFFF0000 | regfile[sec_reg]);
pavone@518 1578 } else {
pavone@518 1579 ret += regfile[sec_reg];
pavone@518 1580 }
pavone@518 1581 }
pavone@518 1582 ret += inst->src.params.regs.displacement;
pavone@518 1583 break;
pavone@518 1584 }
pavone@518 1585 case MODE_PC_DISPLACE:
pavone@518 1586 ret = inst->src.params.regs.displacement + inst->address + 2;
pavone@518 1587 break;
pavone@518 1588 case MODE_PC_INDEX_DISP8: {
pavone@518 1589 uint8_t sec_reg = inst->src.params.regs.sec >> 1 & 0x7;
pavone@518 1590 ret = inst->address + 2;
pavone@518 1591 uint32_t * regfile = inst->src.params.regs.sec & 0x10 ? aregs : dregs;
pavone@518 1592 if (inst->src.params.regs.sec & 1) {
pavone@518 1593 //32-bit index register
pavone@518 1594 ret += regfile[sec_reg];
pavone@518 1595 } else {
pavone@518 1596 //16-bit index register
pavone@518 1597 if (regfile[sec_reg] & 0x8000) {
pavone@518 1598 ret += (0xFFFF0000 | regfile[sec_reg]);
pavone@518 1599 } else {
pavone@518 1600 ret += regfile[sec_reg];
pavone@518 1601 }
pavone@518 1602 }
pavone@518 1603 ret += inst->src.params.regs.displacement;
pavone@518 1604 break;
pavone@518 1605 }
pavone@518 1606 case MODE_ABSOLUTE:
pavone@518 1607 case MODE_ABSOLUTE_SHORT:
pavone@518 1608 ret = inst->src.params.immed;
pavone@518 1609 break;
pavone@518 1610 }
pavone@518 1611 return ret;
pavone@518 1612 }
pavone@518 1613 return 0;
pavone@518 1614 }
pavone@518 1615
pavone@518 1616 uint8_t m68k_is_branch(m68kinst * inst)
pavone@518 1617 {
pavone@518 1618 return (inst->op == M68K_BCC && inst->extra.cond != COND_FALSE)
pavone@518 1619 || (inst->op == M68K_DBCC && inst->extra.cond != COND_TRUE)
pavone@518 1620 || inst->op == M68K_BSR || inst->op == M68K_JMP || inst->op == M68K_JSR;
pavone@518 1621 }
pavone@518 1622
pavone@518 1623 uint8_t m68k_is_noncall_branch(m68kinst * inst)
pavone@518 1624 {
pavone@518 1625 return m68k_is_branch(inst) && inst->op != M68K_BSR && inst->op != M68K_JSR;
pavone@518 1626 }
pavone@518 1627
pavone@518 1628
pavone@2 1629 char * mnemonics[] = {
pavone@2 1630 "abcd",
pavone@2 1631 "add",
pavone@2 1632 "addx",
pavone@2 1633 "and",
pavone@13 1634 "andi",//ccr
pavone@13 1635 "andi",//sr
pavone@2 1636 "asl",
pavone@2 1637 "asr",
pavone@2 1638 "bcc",
pavone@2 1639 "bchg",
pavone@2 1640 "bclr",
pavone@2 1641 "bset",
pavone@2 1642 "bsr",
pavone@2 1643 "btst",
pavone@2 1644 "chk",
pavone@2 1645 "clr",
pavone@2 1646 "cmp",
pavone@2 1647 "dbcc",
pavone@2 1648 "divs",
pavone@2 1649 "divu",
pavone@2 1650 "eor",
pavone@13 1651 "eori",//ccr
pavone@13 1652 "eori",//sr
pavone@2 1653 "exg",
pavone@2 1654 "ext",
pavone@2 1655 "illegal",
pavone@2 1656 "jmp",
pavone@2 1657 "jsr",
pavone@2 1658 "lea",
pavone@2 1659 "link",
pavone@2 1660 "lsl",
pavone@2 1661 "lsr",
pavone@2 1662 "move",
pavone@13 1663 "move",//ccr
pavone@13 1664 "move",//from_sr
pavone@13 1665 "move",//sr
pavone@50 1666 "move",//usp
pavone@2 1667 "movem",
pavone@2 1668 "movep",
pavone@2 1669 "muls",
pavone@2 1670 "mulu",
pavone@2 1671 "nbcd",
pavone@2 1672 "neg",
pavone@2 1673 "negx",
pavone@2 1674 "nop",
pavone@2 1675 "not",
pavone@2 1676 "or",
pavone@13 1677 "ori",//ccr
pavone@13 1678 "ori",//sr
pavone@2 1679 "pea",
pavone@2 1680 "reset",
pavone@2 1681 "rol",
pavone@2 1682 "ror",
pavone@2 1683 "roxl",
pavone@2 1684 "roxr",
pavone@2 1685 "rte",
pavone@2 1686 "rtr",
pavone@2 1687 "rts",
pavone@2 1688 "sbcd",
pavone@2 1689 "scc",
pavone@2 1690 "stop",
pavone@2 1691 "sub",
pavone@2 1692 "subx",
pavone@2 1693 "swap",
pavone@2 1694 "tas",
pavone@2 1695 "trap",
pavone@2 1696 "trapv",
pavone@2 1697 "tst",
pavone@12 1698 "unlk",
pavone@630 1699 "invalid",
pavone@630 1700 #ifdef M68010
pavone@630 1701 "bkpt",
pavone@630 1702 "move", //from ccr
pavone@630 1703 "movec",
pavone@630 1704 "moves",
pavone@636 1705 "rtd",
pavone@630 1706 #endif
pavone@630 1707 #ifdef M68020
pavone@630 1708 "bfchg",
pavone@630 1709 "bfclr",
pavone@630 1710 "bfexts",
pavone@630 1711 "bfextu",
pavone@630 1712 "bfffo",
pavone@630 1713 "bfins",
pavone@630 1714 "bfset",
pavone@630 1715 "bftst",
pavone@630 1716 "callm",
pavone@630 1717 "cas",
pavone@630 1718 "cas2",
pavone@630 1719 "chk2",
pavone@630 1720 "cmp2",
pavone@630 1721 "cpbcc",
pavone@630 1722 "cpdbcc",
pavone@630 1723 "cpgen",
pavone@630 1724 "cprestore",
pavone@630 1725 "cpsave",
pavone@630 1726 "cpscc",
pavone@630 1727 "cptrapcc",
pavone@630 1728 "divsl",
pavone@630 1729 "divul",
pavone@630 1730 "extb",
pavone@630 1731 "pack",
pavone@630 1732 "rtm",
pavone@630 1733 "trapcc",
pavone@630 1734 "unpk"
pavone@630 1735 #endif
pavone@2 1736 };
pavone@2 1737
pavone@2 1738 char * cond_mnem[] = {
pavone@2 1739 "ra",
pavone@2 1740 "f",
pavone@2 1741 "hi",
pavone@2 1742 "ls",
pavone@2 1743 "cc",
pavone@2 1744 "cs",
pavone@2 1745 "ne",
pavone@2 1746 "eq",
pavone@2 1747 "vc",
pavone@2 1748 "vs",
pavone@2 1749 "pl",
pavone@2 1750 "mi",
pavone@2 1751 "ge",
pavone@2 1752 "lt",
pavone@2 1753 "gt",
pavone@2 1754 "le"
pavone@2 1755 };
pavone@630 1756 #ifdef M68010
pavone@630 1757 char * cr_mnem[] = {
pavone@630 1758 "SFC",
pavone@630 1759 "DFC",
pavone@630 1760 #ifdef M68020
pavone@630 1761 "CACR",
pavone@630 1762 #endif
pavone@630 1763 "USP",
pavone@630 1764 "VBR",
pavone@630 1765 #ifdef M68020
pavone@630 1766 "CAAR",
pavone@630 1767 "MSP",
pavone@630 1768 "ISP"
pavone@630 1769 #endif
pavone@630 1770 };
pavone@630 1771 #endif
pavone@2 1772
pavone@634 1773 int m68k_disasm_op(m68k_op_info *decoded, char *dst, int need_comma, uint8_t labels, uint32_t address, format_label_fun label_fun, void * data)
pavone@2 1774 {
pavone@2 1775 char * c = need_comma ? "," : "";
pavone@636 1776 int ret = 0;
pavone@636 1777 #ifdef M68020
pavone@636 1778 uint8_t addr_mode = decoded->addr_mode & (~M68K_FLAG_BITFIELD);
pavone@636 1779 #else
pavone@636 1780 uint8_t addr_mode = decoded->addr_mode;
pavone@636 1781 #endif
pavone@636 1782 switch(addr_mode)
pavone@2 1783 {
pavone@2 1784 case MODE_REG:
pavone@636 1785 ret = sprintf(dst, "%s d%d", c, decoded->params.regs.pri);
pavone@636 1786 break;
pavone@2 1787 case MODE_AREG:
pavone@636 1788 ret = sprintf(dst, "%s a%d", c, decoded->params.regs.pri);
pavone@636 1789 break;
pavone@2 1790 case MODE_AREG_INDIRECT:
pavone@636 1791 ret = sprintf(dst, "%s (a%d)", c, decoded->params.regs.pri);
pavone@636 1792 break;
pavone@2 1793 case MODE_AREG_POSTINC:
pavone@636 1794 ret = sprintf(dst, "%s (a%d)+", c, decoded->params.regs.pri);
pavone@636 1795 break;
pavone@2 1796 case MODE_AREG_PREDEC:
pavone@636 1797 ret = sprintf(dst, "%s -(a%d)", c, decoded->params.regs.pri);
pavone@636 1798 break;
pavone@13 1799 case MODE_AREG_DISPLACE:
pavone@636 1800 ret = sprintf(dst, "%s (%d, a%d)", c, decoded->params.regs.displacement, decoded->params.regs.pri);
pavone@636 1801 break;
pavone@79 1802 case MODE_AREG_INDEX_DISP8:
pavone@638 1803 #ifdef M68020
pavone@638 1804 if (decoded->params.regs.scale)
pavone@638 1805 {
pavone@638 1806 ret = sprintf(dst, "%s (%d, a%d, %c%d.%c*%d)", c, decoded->params.regs.displacement, decoded->params.regs.pri, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 1807 } else {
pavone@638 1808 #endif
pavone@638 1809 ret = sprintf(dst, "%s (%d, a%d, %c%d.%c)", c, decoded->params.regs.displacement, decoded->params.regs.pri, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w');
pavone@638 1810 #ifdef M68020
pavone@638 1811 }
pavone@638 1812 #endif
pavone@636 1813 break;
pavone@638 1814 #ifdef M68020
pavone@638 1815 case MODE_AREG_INDEX_BASE_DISP:
pavone@638 1816 if (decoded->params.regs.disp_sizes > 1)
pavone@638 1817 {
pavone@638 1818 ret = sprintf(dst, "%s (%d.%c, a%d, %c%d.%c*%d)", c, decoded->params.regs.displacement,
pavone@638 1819 decoded->params.regs.disp_sizes == 2 ? 'w' : 'l', decoded->params.regs.pri,
pavone@638 1820 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1821 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 1822 } else {
pavone@638 1823 ret = sprintf(dst, "%s (a%d, %c%d.%c*%d)", c, decoded->params.regs.pri,
pavone@638 1824 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1825 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 1826 }
pavone@638 1827 break;
pavone@638 1828 case MODE_AREG_PREINDEX:
pavone@638 1829 switch (decoded->params.regs.disp_sizes)
pavone@638 1830 {
pavone@638 1831 case 0x11:
pavone@638 1832 //no base displacement or outer displacement
pavone@638 1833 ret = sprintf(dst, "%s ([a%d, %c%d.%c*%d])", c, decoded->params.regs.pri,
pavone@638 1834 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1835 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 1836 break;
pavone@638 1837 case 0x12:
pavone@638 1838 case 0x13:
pavone@638 1839 //base displacement only
pavone@638 1840 ret = sprintf(dst, "%s ([%d.%c, a%d, %c%d.%c*%d])", c, decoded->params.regs.displacement,
pavone@638 1841 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
pavone@638 1842 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1843 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 1844 break;
pavone@638 1845 case 0x21:
pavone@638 1846 case 0x31:
pavone@638 1847 //outer displacement only
pavone@638 1848 ret = sprintf(dst, "%s ([a%d, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.pri,
pavone@638 1849 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1850 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
pavone@638 1851 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 1852 break;
pavone@638 1853 case 0x22:
pavone@638 1854 case 0x23:
pavone@638 1855 case 0x32:
pavone@638 1856 case 0x33:
pavone@638 1857 //both outer and inner displacement
pavone@638 1858 ret = sprintf(dst, "%s ([%d.%c, a%d, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement,
pavone@638 1859 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
pavone@638 1860 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1861 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
pavone@638 1862 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 1863 break;
pavone@638 1864 }
pavone@638 1865 break;
pavone@638 1866 case MODE_AREG_POSTINDEX:
pavone@638 1867 switch (decoded->params.regs.disp_sizes)
pavone@638 1868 {
pavone@638 1869 case 0x11:
pavone@638 1870 //no base displacement or outer displacement
pavone@638 1871 ret = sprintf(dst, "%s ([a%d], %c%d.%c*%d)", c, decoded->params.regs.pri,
pavone@638 1872 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1873 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 1874 break;
pavone@638 1875 case 0x12:
pavone@638 1876 case 0x13:
pavone@638 1877 //base displacement only
pavone@638 1878 ret = sprintf(dst, "%s ([%d.%c, a%d], %c%d.%c*%d)", c, decoded->params.regs.displacement,
pavone@638 1879 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
pavone@638 1880 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1881 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 1882 break;
pavone@638 1883 case 0x21:
pavone@638 1884 case 0x31:
pavone@638 1885 //outer displacement only
pavone@638 1886 ret = sprintf(dst, "%s ([a%d], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.pri,
pavone@638 1887 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1888 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
pavone@638 1889 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 1890 break;
pavone@638 1891 case 0x22:
pavone@638 1892 case 0x23:
pavone@638 1893 case 0x32:
pavone@638 1894 case 0x33:
pavone@638 1895 //both outer and inner displacement
pavone@638 1896 ret = sprintf(dst, "%s ([%d.%c, a%d], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement,
pavone@638 1897 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
pavone@638 1898 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1899 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
pavone@638 1900 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 1901 break;
pavone@638 1902 }
pavone@638 1903 break;
pavone@638 1904 case MODE_AREG_MEM_INDIRECT:
pavone@638 1905 switch (decoded->params.regs.disp_sizes)
pavone@638 1906 {
pavone@638 1907 case 0x11:
pavone@638 1908 //no base displacement or outer displacement
pavone@638 1909 ret = sprintf(dst, "%s ([a%d])", c, decoded->params.regs.pri);
pavone@638 1910 break;
pavone@638 1911 case 0x12:
pavone@638 1912 case 0x13:
pavone@638 1913 //base displacement only
pavone@638 1914 ret = sprintf(dst, "%s ([%d.%c, a%d])", c, decoded->params.regs.displacement,
pavone@638 1915 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri);
pavone@638 1916 break;
pavone@638 1917 case 0x21:
pavone@638 1918 case 0x31:
pavone@638 1919 //outer displacement only
pavone@638 1920 ret = sprintf(dst, "%s ([a%d], %d.%c)", c, decoded->params.regs.pri, decoded->params.regs.outer_disp,
pavone@638 1921 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 1922 break;
pavone@638 1923 case 0x22:
pavone@638 1924 case 0x23:
pavone@638 1925 case 0x32:
pavone@638 1926 case 0x33:
pavone@638 1927 //both outer and inner displacement
pavone@638 1928 ret = sprintf(dst, "%s ([%d.%c, a%d], %d.%c)", c, decoded->params.regs.displacement,
pavone@638 1929 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
pavone@638 1930 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 1931 break;
pavone@638 1932 }
pavone@638 1933 break;
pavone@638 1934 case MODE_AREG_BASE_DISP:
pavone@638 1935 if (decoded->params.regs.disp_sizes > 1)
pavone@638 1936 {
pavone@638 1937 ret = sprintf(dst, "%s (%d.%c, a%d)", c, decoded->params.regs.displacement,
pavone@638 1938 decoded->params.regs.disp_sizes == 2 ? 'w' : 'l', decoded->params.regs.pri);
pavone@638 1939 } else {
pavone@638 1940 //this is a lossy representation of the encoded instruction
pavone@638 1941 //not sure if there's a better way to print it though
pavone@638 1942 ret = sprintf(dst, "%s (a%d)", c, decoded->params.regs.pri);
pavone@638 1943 }
pavone@638 1944 break;
pavone@638 1945 case MODE_INDEX_BASE_DISP:
pavone@638 1946 if (decoded->params.regs.disp_sizes > 1)
pavone@638 1947 {
pavone@638 1948 ret = sprintf(dst, "%s (%d.%c, %c%d.%c*%d)", c, decoded->params.regs.displacement,
pavone@638 1949 decoded->params.regs.disp_sizes == 2 ? 'w' : 'l',
pavone@638 1950 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1951 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 1952 } else {
pavone@638 1953 ret = sprintf(dst, "%s (%c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 1954 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 1955 1 << decoded->params.regs.scale);
pavone@638 1956 }
pavone@638 1957 break;
pavone@638 1958 case MODE_PREINDEX:
pavone@638 1959 switch (decoded->params.regs.disp_sizes)
pavone@638 1960 {
pavone@638 1961 case 0x11:
pavone@638 1962 //no base displacement or outer displacement
pavone@638 1963 ret = sprintf(dst, "%s ([%c%d.%c*%d])", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 1964 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 1965 1 << decoded->params.regs.scale);
pavone@638 1966 break;
pavone@638 1967 case 0x12:
pavone@638 1968 case 0x13:
pavone@638 1969 //base displacement only
pavone@638 1970 ret = sprintf(dst, "%s ([%d.%c, %c%d.%c*%d])", c, decoded->params.regs.displacement,
pavone@638 1971 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
pavone@638 1972 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1973 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 1974 break;
pavone@638 1975 case 0x21:
pavone@638 1976 case 0x31:
pavone@638 1977 //outer displacement only
pavone@638 1978 ret = sprintf(dst, "%s ([%c%d.%c*%d], %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 1979 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 1980 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
pavone@638 1981 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 1982 break;
pavone@638 1983 case 0x22:
pavone@638 1984 case 0x23:
pavone@638 1985 case 0x32:
pavone@638 1986 case 0x33:
pavone@638 1987 //both outer and inner displacement
pavone@638 1988 ret = sprintf(dst, "%s ([%d.%c, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement,
pavone@638 1989 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
pavone@638 1990 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 1991 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
pavone@638 1992 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 1993 break;
pavone@638 1994 }
pavone@638 1995 break;
pavone@638 1996 case MODE_POSTINDEX:
pavone@638 1997 switch (decoded->params.regs.disp_sizes)
pavone@638 1998 {
pavone@638 1999 case 0x11:
pavone@638 2000 //no base displacement or outer displacement
pavone@638 2001 ret = sprintf(dst, "%s ([], %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 2002 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 2003 1 << decoded->params.regs.scale);
pavone@638 2004 break;
pavone@638 2005 case 0x12:
pavone@638 2006 case 0x13:
pavone@638 2007 //base displacement only
pavone@638 2008 ret = sprintf(dst, "%s ([%d.%c], %c%d.%c*%d)", c, decoded->params.regs.displacement,
pavone@638 2009 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
pavone@638 2010 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 2011 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 2012 break;
pavone@638 2013 case 0x21:
pavone@638 2014 case 0x31:
pavone@638 2015 //outer displacement only
pavone@638 2016 ret = sprintf(dst, "%s ([], %c%d.%c*%d, %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 2017 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 2018 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
pavone@638 2019 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2020 break;
pavone@638 2021 case 0x22:
pavone@638 2022 case 0x23:
pavone@638 2023 case 0x32:
pavone@638 2024 case 0x33:
pavone@638 2025 //both outer and inner displacement
pavone@638 2026 ret = sprintf(dst, "%s ([%d.%c], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement,
pavone@638 2027 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
pavone@638 2028 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 2029 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
pavone@638 2030 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2031 break;
pavone@638 2032 }
pavone@638 2033 break;
pavone@638 2034 case MODE_MEM_INDIRECT:
pavone@638 2035 switch (decoded->params.regs.disp_sizes)
pavone@638 2036 {
pavone@638 2037 case 0x11:
pavone@638 2038 //no base displacement or outer displacement
pavone@638 2039 ret = sprintf(dst, "%s ([])", c);
pavone@638 2040 break;
pavone@638 2041 case 0x12:
pavone@638 2042 case 0x13:
pavone@638 2043 //base displacement only
pavone@638 2044 ret = sprintf(dst, "%s ([%d.%c])", c, decoded->params.regs.displacement,
pavone@638 2045 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
pavone@638 2046 break;
pavone@638 2047 case 0x21:
pavone@638 2048 case 0x31:
pavone@638 2049 //outer displacement only
pavone@638 2050 ret = sprintf(dst, "%s ([], %d.%c)", c, decoded->params.regs.outer_disp,
pavone@638 2051 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2052 break;
pavone@638 2053 case 0x22:
pavone@638 2054 case 0x23:
pavone@638 2055 case 0x32:
pavone@638 2056 case 0x33:
pavone@638 2057 //both outer and inner displacement
pavone@638 2058 ret = sprintf(dst, "%s ([%d.%c], %d.%c)", c, decoded->params.regs.displacement,
pavone@638 2059 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.outer_disp,
pavone@638 2060 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2061 break;
pavone@638 2062 }
pavone@638 2063 break;
pavone@638 2064 case MODE_BASE_DISP:
pavone@638 2065 if (decoded->params.regs.disp_sizes > 1)
pavone@638 2066 {
pavone@638 2067 ret = sprintf(dst, "%s (%d.%c)", c, decoded->params.regs.displacement,
pavone@638 2068 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
pavone@638 2069 } else {
pavone@638 2070 ret = sprintf(dst, "%s ()", c);
pavone@638 2071 }
pavone@638 2072 break;
pavone@638 2073 #endif
pavone@2 2074 case MODE_IMMEDIATE:
pavone@61 2075 case MODE_IMMEDIATE_WORD:
pavone@636 2076 ret = sprintf(dst, (decoded->params.immed <= 128 ? "%s #%d" : "%s #$%X"), c, decoded->params.immed);
pavone@636 2077 break;
pavone@13 2078 case MODE_ABSOLUTE_SHORT:
pavone@638 2079 if (labels) {
pavone@636 2080 ret = sprintf(dst, "%s ", c);
pavone@634 2081 ret += label_fun(dst+ret, decoded->params.immed, data);
pavone@634 2082 strcat(dst+ret, ".w");
pavone@636 2083 ret = ret + 2;
pavone@134 2084 } else {
pavone@636 2085 ret = sprintf(dst, "%s $%X.w", c, decoded->params.immed);
pavone@134 2086 }
pavone@636 2087 break;
pavone@13 2088 case MODE_ABSOLUTE:
pavone@134 2089 if (labels) {
pavone@636 2090 ret = sprintf(dst, "%s ", c);
pavone@634 2091 ret += label_fun(dst+ret, decoded->params.immed, data);
pavone@634 2092 strcat(dst+ret, ".l");
pavone@636 2093 ret = ret + 2;
pavone@134 2094 } else {
pavone@636 2095 ret = sprintf(dst, "%s $%X", c, decoded->params.immed);
pavone@134 2096 }
pavone@636 2097 break;
pavone@13 2098 case MODE_PC_DISPLACE:
pavone@134 2099 if (labels) {
pavone@636 2100 ret = sprintf(dst, "%s ", c);
pavone@634 2101 ret += label_fun(dst+ret, address + 2 + decoded->params.regs.displacement, data);
pavone@634 2102 strcat(dst+ret, "(pc)");
pavone@636 2103 ret = ret + 4;
pavone@134 2104 } else {
pavone@636 2105 ret = sprintf(dst, "%s (%d, pc)", c, decoded->params.regs.displacement);
pavone@134 2106 }
pavone@636 2107 break;
pavone@79 2108 case MODE_PC_INDEX_DISP8:
pavone@638 2109 #ifdef M68020
pavone@638 2110 if (decoded->params.regs.scale)
pavone@638 2111 {
pavone@638 2112 ret = sprintf(dst, "%s (%d, pc, %c%d.%c*%d)", c, decoded->params.regs.displacement, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 2113 } else {
pavone@638 2114 #endif
pavone@638 2115 ret = sprintf(dst, "%s (%d, pc, %c%d.%c)", c, decoded->params.regs.displacement, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w');
pavone@638 2116 #ifdef M68020
pavone@638 2117 }
pavone@638 2118 #endif
pavone@638 2119 break;
pavone@638 2120 #ifdef M68020
pavone@638 2121 case MODE_PC_INDEX_BASE_DISP:
pavone@638 2122 if (decoded->params.regs.disp_sizes > 1)
pavone@638 2123 {
pavone@638 2124 ret = sprintf(dst, "%s (%d.%c, pc, %c%d.%c*%d)", c, decoded->params.regs.displacement,
pavone@638 2125 decoded->params.regs.disp_sizes == 2 ? 'w' : 'l',
pavone@638 2126 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 2127 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 2128 } else {
pavone@638 2129 ret = sprintf(dst, "%s (pc, %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 2130 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 2131 1 << decoded->params.regs.scale);
pavone@638 2132 }
pavone@638 2133 break;
pavone@638 2134 case MODE_PC_PREINDEX:
pavone@638 2135 switch (decoded->params.regs.disp_sizes)
pavone@638 2136 {
pavone@638 2137 case 0x11:
pavone@638 2138 //no base displacement or outer displacement
pavone@638 2139 ret = sprintf(dst, "%s ([pc, %c%d.%c*%d])", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 2140 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 2141 1 << decoded->params.regs.scale);
pavone@638 2142 break;
pavone@638 2143 case 0x12:
pavone@638 2144 case 0x13:
pavone@638 2145 //base displacement only
pavone@638 2146 ret = sprintf(dst, "%s ([%d.%c, pc, %c%d.%c*%d])", c, decoded->params.regs.displacement,
pavone@638 2147 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
pavone@638 2148 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 2149 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 2150 break;
pavone@638 2151 case 0x21:
pavone@638 2152 case 0x31:
pavone@638 2153 //outer displacement only
pavone@638 2154 ret = sprintf(dst, "%s ([pc, %c%d.%c*%d], %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 2155 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 2156 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
pavone@638 2157 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2158 break;
pavone@638 2159 case 0x22:
pavone@638 2160 case 0x23:
pavone@638 2161 case 0x32:
pavone@638 2162 case 0x33:
pavone@638 2163 //both outer and inner displacement
pavone@638 2164 ret = sprintf(dst, "%s ([%d.%c, pc, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement,
pavone@638 2165 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
pavone@638 2166 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 2167 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
pavone@638 2168 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2169 break;
pavone@638 2170 }
pavone@638 2171 break;
pavone@638 2172 case MODE_PC_POSTINDEX:
pavone@638 2173 switch (decoded->params.regs.disp_sizes)
pavone@638 2174 {
pavone@638 2175 case 0x11:
pavone@638 2176 //no base displacement or outer displacement
pavone@638 2177 ret = sprintf(dst, "%s ([pc], %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 2178 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 2179 1 << decoded->params.regs.scale);
pavone@638 2180 break;
pavone@638 2181 case 0x12:
pavone@638 2182 case 0x13:
pavone@638 2183 //base displacement only
pavone@638 2184 ret = sprintf(dst, "%s ([%d.%c, pc], %c%d.%c*%d)", c, decoded->params.regs.displacement,
pavone@638 2185 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
pavone@638 2186 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 2187 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 2188 break;
pavone@638 2189 case 0x21:
pavone@638 2190 case 0x31:
pavone@638 2191 //outer displacement only
pavone@638 2192 ret = sprintf(dst, "%s ([pc], %c%d.%c*%d, %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 2193 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 2194 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
pavone@638 2195 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2196 break;
pavone@638 2197 case 0x22:
pavone@638 2198 case 0x23:
pavone@638 2199 case 0x32:
pavone@638 2200 case 0x33:
pavone@638 2201 //both outer and inner displacement
pavone@638 2202 ret = sprintf(dst, "%s ([%d.%c, pc], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement,
pavone@638 2203 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
pavone@638 2204 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 2205 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
pavone@638 2206 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2207 break;
pavone@638 2208 }
pavone@638 2209 break;
pavone@638 2210 case MODE_PC_MEM_INDIRECT:
pavone@638 2211 switch (decoded->params.regs.disp_sizes)
pavone@638 2212 {
pavone@638 2213 case 0x11:
pavone@638 2214 //no base displacement or outer displacement
pavone@638 2215 ret = sprintf(dst, "%s ([pc])", c);
pavone@638 2216 break;
pavone@638 2217 case 0x12:
pavone@638 2218 case 0x13:
pavone@638 2219 //base displacement only
pavone@638 2220 ret = sprintf(dst, "%s ([%d.%c, pc])", c, decoded->params.regs.displacement,
pavone@638 2221 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
pavone@638 2222 break;
pavone@638 2223 case 0x21:
pavone@638 2224 case 0x31:
pavone@638 2225 //outer displacement only
pavone@638 2226 ret = sprintf(dst, "%s ([pc], %d.%c)", c, decoded->params.regs.outer_disp,
pavone@638 2227 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2228 break;
pavone@638 2229 case 0x22:
pavone@638 2230 case 0x23:
pavone@638 2231 case 0x32:
pavone@638 2232 case 0x33:
pavone@638 2233 //both outer and inner displacement
pavone@638 2234 ret = sprintf(dst, "%s ([%d.%c, pc], %d.%c)", c, decoded->params.regs.displacement,
pavone@638 2235 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.outer_disp,
pavone@638 2236 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2237 break;
pavone@638 2238 }
pavone@638 2239 break;
pavone@638 2240 case MODE_PC_BASE_DISP:
pavone@638 2241 if (decoded->params.regs.disp_sizes > 1)
pavone@638 2242 {
pavone@638 2243 ret = sprintf(dst, "%s (%d.%c, pc)", c, decoded->params.regs.displacement,
pavone@638 2244 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
pavone@638 2245 } else {
pavone@638 2246 ret = sprintf(dst, "%s (pc)", c);
pavone@638 2247 }
pavone@638 2248 break;
pavone@638 2249 case MODE_ZPC_INDEX_BASE_DISP:
pavone@638 2250 if (decoded->params.regs.disp_sizes > 1)
pavone@638 2251 {
pavone@638 2252 ret = sprintf(dst, "%s (%d.%c, zpc, %c%d.%c*%d)", c, decoded->params.regs.displacement,
pavone@638 2253 decoded->params.regs.disp_sizes == 2 ? 'w' : 'l',
pavone@638 2254 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 2255 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 2256 } else {
pavone@638 2257 ret = sprintf(dst, "%s (zpc, %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 2258 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 2259 1 << decoded->params.regs.scale);
pavone@638 2260 }
pavone@638 2261 break;
pavone@638 2262 case MODE_ZPC_PREINDEX:
pavone@638 2263 switch (decoded->params.regs.disp_sizes)
pavone@638 2264 {
pavone@638 2265 case 0x11:
pavone@638 2266 //no base displacement or outer displacement
pavone@638 2267 ret = sprintf(dst, "%s ([zpc, %c%d.%c*%d])", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 2268 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 2269 1 << decoded->params.regs.scale);
pavone@638 2270 break;
pavone@638 2271 case 0x12:
pavone@638 2272 case 0x13:
pavone@638 2273 //base displacement only
pavone@638 2274 ret = sprintf(dst, "%s ([%d.%c, zpc, %c%d.%c*%d])", c, decoded->params.regs.displacement,
pavone@638 2275 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
pavone@638 2276 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 2277 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 2278 break;
pavone@638 2279 case 0x21:
pavone@638 2280 case 0x31:
pavone@638 2281 //outer displacement only
pavone@638 2282 ret = sprintf(dst, "%s ([zpc, %c%d.%c*%d], %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 2283 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 2284 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
pavone@638 2285 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2286 break;
pavone@638 2287 case 0x22:
pavone@638 2288 case 0x23:
pavone@638 2289 case 0x32:
pavone@638 2290 case 0x33:
pavone@638 2291 //both outer and inner displacement
pavone@638 2292 ret = sprintf(dst, "%s ([%d.%c, zpc, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement,
pavone@638 2293 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
pavone@638 2294 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 2295 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
pavone@638 2296 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2297 break;
pavone@638 2298 }
pavone@638 2299 break;
pavone@638 2300 case MODE_ZPC_POSTINDEX:
pavone@638 2301 switch (decoded->params.regs.disp_sizes)
pavone@638 2302 {
pavone@638 2303 case 0x11:
pavone@638 2304 //no base displacement or outer displacement
pavone@638 2305 ret = sprintf(dst, "%s ([zpc], %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 2306 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 2307 1 << decoded->params.regs.scale);
pavone@638 2308 break;
pavone@638 2309 case 0x12:
pavone@638 2310 case 0x13:
pavone@638 2311 //base displacement only
pavone@638 2312 ret = sprintf(dst, "%s ([%d.%c, zpc], %c%d.%c*%d)", c, decoded->params.regs.displacement,
pavone@638 2313 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
pavone@638 2314 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 2315 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
pavone@638 2316 break;
pavone@638 2317 case 0x21:
pavone@638 2318 case 0x31:
pavone@638 2319 //outer displacement only
pavone@638 2320 ret = sprintf(dst, "%s ([zpc], %c%d.%c*%d, %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
pavone@638 2321 (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
pavone@638 2322 1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
pavone@638 2323 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2324 break;
pavone@638 2325 case 0x22:
pavone@638 2326 case 0x23:
pavone@638 2327 case 0x32:
pavone@638 2328 case 0x33:
pavone@638 2329 //both outer and inner displacement
pavone@638 2330 ret = sprintf(dst, "%s ([%d.%c, zpc], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement,
pavone@638 2331 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
pavone@638 2332 (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
pavone@638 2333 (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
pavone@638 2334 decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2335 break;
pavone@638 2336 }
pavone@638 2337 break;
pavone@638 2338 case MODE_ZPC_MEM_INDIRECT:
pavone@638 2339 switch (decoded->params.regs.disp_sizes)
pavone@638 2340 {
pavone@638 2341 case 0x11:
pavone@638 2342 //no base displacement or outer displacement
pavone@638 2343 ret = sprintf(dst, "%s ([zpc])", c);
pavone@638 2344 break;
pavone@638 2345 case 0x12:
pavone@638 2346 case 0x13:
pavone@638 2347 //base displacement only
pavone@638 2348 ret = sprintf(dst, "%s ([%d.%c, zpc])", c, decoded->params.regs.displacement,
pavone@638 2349 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
pavone@638 2350 break;
pavone@638 2351 case 0x21:
pavone@638 2352 case 0x31:
pavone@638 2353 //outer displacement only
pavone@638 2354 ret = sprintf(dst, "%s ([zpc], %d.%c)", c, decoded->params.regs.outer_disp,
pavone@638 2355 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2356 break;
pavone@638 2357 case 0x22:
pavone@638 2358 case 0x23:
pavone@638 2359 case 0x32:
pavone@638 2360 case 0x33:
pavone@638 2361 //both outer and inner displacement
pavone@638 2362 ret = sprintf(dst, "%s ([%d.%c, zpc], %d.%c)", c, decoded->params.regs.displacement,
pavone@638 2363 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.outer_disp,
pavone@638 2364 decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
pavone@638 2365 break;
pavone@638 2366 }
pavone@638 2367 break;
pavone@638 2368 case MODE_ZPC_BASE_DISP:
pavone@638 2369 if (decoded->params.regs.disp_sizes > 1)
pavone@638 2370 {
pavone@638 2371 ret = sprintf(dst, "%s (%d.%c, zpc)", c, decoded->params.regs.displacement,
pavone@638 2372 decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
pavone@638 2373 } else {
pavone@638 2374 ret = sprintf(dst, "%s (zpc)", c);
pavone@638 2375 }
pavone@638 2376 break;
pavone@638 2377 #endif
pavone@2 2378 default:
pavone@636 2379 ret = 0;
pavone@0 2380 }
pavone@636 2381 #ifdef M68020
pavone@636 2382 if (decoded->addr_mode & M68K_FLAG_BITFIELD)
pavone@636 2383 {
pavone@636 2384 switch (decoded->bitfield & 0x820)
pavone@636 2385 {
pavone@636 2386 case 0:
pavone@636 2387 return ret + sprintf(dst+ret, " {$%X:%d}", decoded->bitfield >> 6 & 0x1F, decoded->bitfield & 0x1F ? decoded->bitfield & 0x1F : 32);
pavone@636 2388 case 0x20:
pavone@636 2389 return ret + sprintf(dst+ret, " {$%X:d%d}", decoded->bitfield >> 6 & 0x1F, decoded->bitfield & 0x7);
pavone@636 2390 case 0x800:
pavone@636 2391 return ret + sprintf(dst+ret, " {d%d:%d}", decoded->bitfield >> 6 & 0x7, decoded->bitfield & 0x1F ? decoded->bitfield & 0x1F : 32);
pavone@636 2392 case 0x820:
pavone@636 2393 return ret + sprintf(dst+ret, " {d%d:d%d}", decoded->bitfield >> 6 & 0x7, decoded->bitfield & 0x7);
pavone@636 2394 }
pavone@636 2395 }
pavone@636 2396 #endif
pavone@636 2397 return ret;
pavone@0 2398 }
pavone@2 2399
pavone@634 2400 int m68k_disasm_movem_op(m68k_op_info *decoded, m68k_op_info *other, char *dst, int need_comma, uint8_t labels, uint32_t address, format_label_fun label_fun, void * data)
pavone@13 2401 {
pavone@13 2402 int8_t dir, reg, bit, regnum, last=-1, lastreg, first=-1;
pavone@13 2403 char *rtype, *last_rtype;
pavone@13 2404 int oplen;
pavone@13 2405 if (decoded->addr_mode == MODE_REG) {
pavone@13 2406 if (other->addr_mode == MODE_AREG_PREDEC) {
pavone@13 2407 bit = 15;
pavone@13 2408 dir = -1;
pavone@13 2409 } else {
pavone@69 2410 dir = 1;
pavone@69 2411 bit = 0;
pavone@13 2412 }
pavone@68 2413 if (need_comma) {
pavone@68 2414 strcat(dst, ", ");
pavone@68 2415 oplen = 2;
pavone@68 2416 } else {
pavone@68 2417 strcat(dst, " ");
pavone@68 2418 oplen = 1;
pavone@68 2419 }
pavone@68 2420 for (reg=0; bit < 16 && bit > -1; bit += dir, reg++) {
pavone@15 2421 if (decoded->params.immed & (1 << bit)) {
pavone@13 2422 if (reg > 7) {
pavone@13 2423 rtype = "a";
pavone@13 2424 regnum = reg - 8;
pavone@13 2425 } else {
pavone@13 2426 rtype = "d";
pavone@13 2427 regnum = reg;
pavone@13 2428 }
pavone@13 2429 if (last >= 0 && last == regnum - 1 && lastreg == reg - 1) {
pavone@13 2430 last = regnum;
pavone@13 2431 lastreg = reg;
pavone@13 2432 } else if(last >= 0) {
pavone@13 2433 if (first != last) {
pavone@13 2434 oplen += sprintf(dst + oplen, "-%s%d/%s%d",last_rtype, last, rtype, regnum);
pavone@13 2435 } else {
pavone@13 2436 oplen += sprintf(dst + oplen, "/%s%d", rtype, regnum);
pavone@13 2437 }
pavone@13 2438 first = last = regnum;
pavone@13 2439 last_rtype = rtype;
pavone@13 2440 lastreg = reg;
pavone@13 2441 } else {
pavone@13 2442 oplen += sprintf(dst + oplen, "%s%d", rtype, regnum);
pavone@13 2443 first = last = regnum;
pavone@13 2444 last_rtype = rtype;
pavone@13 2445 lastreg = reg;
pavone@13 2446 }
pavone@13 2447 }
pavone@13 2448 }
pavone@13 2449 if (last >= 0 && last != first) {
pavone@13 2450 oplen += sprintf(dst + oplen, "-%s%d", last_rtype, last);
pavone@13 2451 }
pavone@13 2452 return oplen;
pavone@13 2453 } else {
pavone@634 2454 return m68k_disasm_op(decoded, dst, need_comma, labels, address, label_fun, data);
pavone@13 2455 }
pavone@13 2456 }
pavone@13 2457
pavone@634 2458 int m68k_default_label_fun(char * dst, uint32_t address, void * data)
pavone@634 2459 {
pavone@634 2460 return sprintf(dst, "ADR_%X", address);
pavone@634 2461 }
pavone@634 2462
pavone@634 2463 int m68k_disasm_ex(m68kinst * decoded, char * dst, uint8_t labels, format_label_fun label_fun, void * data)
pavone@2 2464 {
pavone@2 2465 int ret,op1len;
pavone@2 2466 uint8_t size;
pavone@13 2467 char * special_op = "CCR";
pavone@13 2468 switch (decoded->op)
pavone@13 2469 {
pavone@13 2470 case M68K_BCC:
pavone@13 2471 case M68K_DBCC:
pavone@13 2472 case M68K_SCC:
pavone@2 2473 ret = strlen(mnemonics[decoded->op]) - 2;
pavone@2 2474 memcpy(dst, mnemonics[decoded->op], ret);
pavone@2 2475 dst[ret] = 0;
pavone@50 2476 strcpy(dst+ret, cond_mnem[decoded->extra.cond]);
pavone@2 2477 ret = strlen(dst);
pavone@50 2478 if (decoded->op != M68K_SCC) {
pavone@134 2479 if (labels) {
pavone@134 2480 if (decoded->op == M68K_DBCC) {
pavone@634 2481 ret += sprintf(dst+ret, " d%d, ", decoded->dst.params.regs.pri);
pavone@634 2482 ret += label_fun(dst+ret, decoded->address + 2 + decoded->src.params.immed, data);
pavone@134 2483 } else {
pavone@634 2484 dst[ret++] = ' ';
pavone@634 2485 ret += label_fun(dst+ret, decoded->address + 2 + decoded->src.params.immed, data);
pavone@134 2486 }
pavone@54 2487 } else {
pavone@134 2488 if (decoded->op == M68K_DBCC) {
pavone@134 2489 ret += sprintf(dst+ret, " d%d, #%d <%X>", decoded->dst.params.regs.pri, decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
pavone@134 2490 } else {
pavone@134 2491 ret += sprintf(dst+ret, " #%d <%X>", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
pavone@134 2492 }
pavone@54 2493 }
pavone@50 2494 return ret;
pavone@50 2495 }
pavone@13 2496 break;
pavone@13 2497 case M68K_BSR:
pavone@134 2498 if (labels) {
pavone@634 2499 ret = sprintf(dst, "bsr%s ", decoded->variant == VAR_BYTE ? ".s" : "");
pavone@634 2500 ret += label_fun(dst+ret, decoded->address + 2 + decoded->src.params.immed, data);
pavone@134 2501 } else {
pavone@134 2502 ret = sprintf(dst, "bsr%s #%d <%X>", decoded->variant == VAR_BYTE ? ".s" : "", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
pavone@134 2503 }
pavone@50 2504 return ret;
pavone@13 2505 case M68K_MOVE_FROM_SR:
pavone@13 2506 ret = sprintf(dst, "%s", mnemonics[decoded->op]);
pavone@13 2507 ret += sprintf(dst + ret, " SR");
pavone@634 2508 ret += m68k_disasm_op(&(decoded->dst), dst + ret, 1, labels, decoded->address, label_fun, data);
pavone@13 2509 return ret;
pavone@13 2510 case M68K_ANDI_SR:
pavone@13 2511 case M68K_EORI_SR:
pavone@13 2512 case M68K_MOVE_SR:
pavone@13 2513 case M68K_ORI_SR:
pavone@13 2514 special_op = "SR";
pavone@13 2515 case M68K_ANDI_CCR:
pavone@13 2516 case M68K_EORI_CCR:
pavone@13 2517 case M68K_MOVE_CCR:
pavone@13 2518 case M68K_ORI_CCR:
pavone@13 2519 ret = sprintf(dst, "%s", mnemonics[decoded->op]);
pavone@634 2520 ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data);
pavone@13 2521 ret += sprintf(dst + ret, ", %s", special_op);
pavone@13 2522 return ret;
pavone@50 2523 case M68K_MOVE_USP:
pavone@50 2524 ret = sprintf(dst, "%s", mnemonics[decoded->op]);
pavone@50 2525 if (decoded->src.addr_mode != MODE_UNUSED) {
pavone@634 2526 ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data);
pavone@50 2527 ret += sprintf(dst + ret, ", USP");
pavone@50 2528 } else {
pavone@50 2529 ret += sprintf(dst + ret, "USP, ");
pavone@634 2530 ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address, label_fun, data);
pavone@50 2531 }
pavone@50 2532 return ret;
pavone@630 2533 case M68K_INVALID:
pavone@630 2534 ret = sprintf(dst, "dc.w $%X", decoded->src.params.immed);
pavone@630 2535 return ret;
pavone@630 2536 #ifdef M68010
pavone@630 2537 case M68K_MOVEC:
pavone@630 2538 ret = sprintf(dst, "%s ", mnemonics[decoded->op]);
pavone@630 2539 if (decoded->src.addr_mode == MODE_UNUSED) {
pavone@630 2540 ret += sprintf(dst + ret, "%s, ", cr_mnem[decoded->src.params.immed]);
pavone@634 2541 ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address, label_fun, data);
pavone@630 2542 } else {
pavone@634 2543 ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data);
pavone@630 2544 ret += sprintf(dst + ret, ", %s", cr_mnem[decoded->dst.params.immed]);
pavone@630 2545 }
pavone@630 2546 return ret;
pavone@630 2547 #endif
pavone@13 2548 default:
pavone@2 2549 size = decoded->extra.size;
pavone@518 2550 ret = sprintf(dst, "%s%s%s",
pavone@518 2551 mnemonics[decoded->op],
pavone@518 2552 decoded->variant == VAR_QUICK ? "q" : (decoded->variant == VAR_IMMEDIATE ? "i" : ""),
pavone@13 2553 size == OPSIZE_BYTE ? ".b" : (size == OPSIZE_WORD ? ".w" : (size == OPSIZE_LONG ? ".l" : "")));
pavone@2 2554 }
pavone@13 2555 if (decoded->op == M68K_MOVEM) {
pavone@634 2556 op1len = m68k_disasm_movem_op(&(decoded->src), &(decoded->dst), dst + ret, 0, labels, decoded->address, label_fun, data);
pavone@13 2557 ret += op1len;
pavone@634 2558 ret += m68k_disasm_movem_op(&(decoded->dst), &(decoded->src), dst + ret, op1len, labels, decoded->address, label_fun, data);
pavone@13 2559 } else {
pavone@634 2560 op1len = m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data);
pavone@13 2561 ret += op1len;
pavone@634 2562 ret += m68k_disasm_op(&(decoded->dst), dst + ret, op1len, labels, decoded->address, label_fun, data);
pavone@13 2563 }
pavone@2 2564 return ret;
pavone@2 2565 }
pavone@2 2566
pavone@134 2567 int m68k_disasm(m68kinst * decoded, char * dst)
pavone@134 2568 {
pavone@634 2569 return m68k_disasm_ex(decoded, dst, 0, NULL, NULL);
pavone@134 2570 }
pavone@134 2571
pavone@634 2572 int m68k_disasm_labels(m68kinst * decoded, char * dst, format_label_fun label_fun, void * data)
pavone@134 2573 {
pavone@634 2574 if (!label_fun)
pavone@634 2575 {
pavone@634 2576 label_fun = m68k_default_label_fun;
pavone@634 2577 }
pavone@634 2578 return m68k_disasm_ex(decoded, dst, 1, label_fun, data);
pavone@134 2579 }