Mercurial > repos > blastem
diff 68kinst.c @ 18:3e7bfde7606e
M68K to x86 translation works for a limited subset of instructions and addressing modes
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 04 Dec 2012 19:13:12 -0800 |
parents | c0f339564819 |
children | f2aaaf36c875 |
line wrap: on
line diff
--- a/68kinst.c Tue Nov 27 22:54:38 2012 -0800 +++ b/68kinst.c Tue Dec 04 19:13:12 2012 -0800 @@ -86,12 +86,12 @@ decoded->extra.cond = (op >> 0x8) & 0xF; } -uint8_t m68K_reg_quick_field(uint16_t op) +uint8_t m68k_reg_quick_field(uint16_t op) { return (op >> 9) & 0x7; } -uint16_t * m68K_decode(uint16_t * istream, m68kinst * decoded) +uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address) { uint8_t optype = *istream >> 12; uint8_t size; @@ -101,6 +101,7 @@ decoded->op = M68K_INVALID; decoded->src.addr_mode = decoded->dst.addr_mode = MODE_UNUSED; decoded->variant = VAR_NORMAL; + decoded->address = address; switch(optype) { case BIT_MOVEP_IMMED: @@ -122,7 +123,7 @@ break; } decoded->src.addr_mode = MODE_REG; - decoded->src.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); decoded->extra.size = OPSIZE_LONG; istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->dst)); } else if ((*istream & 0xF00) == 0x800) { @@ -353,13 +354,13 @@ if (*istream & 0x80) { //memory dest decoded->src.addr_mode = MODE_REG; - decoded->src.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); decoded->dst.addr_mode = MODE_AREG_DISPLACE; decoded->dst.params.regs.pri = *istream & 0x7; } else { //memory source decoded->dst.addr_mode = MODE_REG; - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); decoded->src.addr_mode = MODE_AREG_DISPLACE; decoded->src.params.regs.pri = *istream & 0x7; } @@ -374,8 +375,10 @@ case MOVE_WORD: decoded->op = M68K_MOVE; decoded->extra.size = optype == MOVE_BYTE ? OPSIZE_BYTE : (optype == MOVE_WORD ? OPSIZE_WORD : OPSIZE_LONG); + opmode = (*istream >> 6) & 0x7; + reg = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); - istream = m68k_decode_op_ex(istream, (*istream >> 6) & 0x7, m68K_reg_quick_field(*istream), decoded->extra.size, &(decoded->dst)); + istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); break; case MISC: @@ -383,7 +386,7 @@ decoded->op = M68K_LEA; decoded->extra.size = OPSIZE_LONG; decoded->dst.addr_mode = MODE_AREG; - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); } else { if (*istream & 0x100) { @@ -401,7 +404,7 @@ } istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); decoded->dst.addr_mode = MODE_REG; - decoded->dst.addr_mode = m68K_reg_quick_field(*istream); + decoded->dst.addr_mode = m68k_reg_quick_field(*istream); } else { opmode = (*istream >> 3) & 0x7; if ((*istream & 0xB80) == 0x880 && opmode != MODE_REG && opmode != MODE_AREG && opmode != MODE_AREG_POSTINC) { @@ -684,7 +687,7 @@ decoded->extra.size = size; decoded->src.addr_mode = MODE_IMMEDIATE; istream = m68k_decode_op(istream, size, &(decoded->dst)); - immed = m68K_reg_quick_field(*istream); + immed = m68k_reg_quick_field(*istream); if (!immed) { immed = 8; } @@ -722,7 +725,7 @@ decoded->src.addr_mode = MODE_IMMEDIATE; decoded->src.params.immed = sign_extend8(*istream & 0xFF); decoded->dst.addr_mode = MODE_REG; - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); immed = *istream & 0xFF; break; case OR_DIV_SBCD: @@ -785,10 +788,12 @@ //SUBA.l decoded->extra.size = OPSIZE_LONG; decoded->dst.addr_mode = MODE_AREG; + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); } else { decoded->extra.size = size; decoded->src.addr_mode = MODE_REG; + decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, size, &(decoded->dst)); } } else { @@ -797,7 +802,7 @@ decoded->extra.size = size; istream = m68k_decode_op(istream, size, &(decoded->src)); decoded->dst.addr_mode = decoded->src.addr_mode; - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); } } else { if (size == OPSIZE_INVALID) { @@ -808,7 +813,7 @@ decoded->extra.size = size; decoded->dst.addr_mode = MODE_REG; } - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); } break; @@ -824,19 +829,19 @@ //CMPM decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG_POSTINC; decoded->src.params.regs.pri = decoded->dst.params.regs.pri; - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); } else { //EOR decoded->op = M68K_EOR; decoded->extra.size = size; decoded->src.addr_mode = MODE_REG; - decoded->src.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); } } else { //CMP decoded->extra.size = size; decoded->dst.addr_mode = MODE_REG; - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, size, &(decoded->src)); } break; @@ -855,18 +860,18 @@ decoded->op = M68K_MULS; decoded->extra.size = OPSIZE_WORD; decoded->dst.addr_mode = MODE_REG; - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); } else if(!(*istream & 0xF0)) { decoded->op = M68K_ABCD; decoded->extra.size = OPSIZE_BYTE; decoded->src.params.regs.pri = *istream & 0x7; - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); decoded->dst.addr_mode = decoded->src.addr_mode = (*istream & 8) ? MODE_AREG_PREDEC : MODE_REG; } else if(!(*istream & 0x30)) { decoded->op = M68K_EXG; decoded->extra.size = OPSIZE_LONG; - decoded->src.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); decoded->dst.params.regs.pri = *istream & 0x7; if (*istream & 0x8) { if (*istream & 0x80) { @@ -882,7 +887,7 @@ decoded->op = M68K_AND; decoded->extra.size = (*istream >> 6); decoded->dst.addr_mode = MODE_REG; - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); } } else { @@ -890,13 +895,13 @@ decoded->op = M68K_MULU; decoded->extra.size = OPSIZE_WORD; decoded->dst.addr_mode = MODE_REG; - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); } else { decoded->op = M68K_AND; decoded->extra.size = (*istream >> 6); decoded->src.addr_mode = MODE_REG; - decoded->src.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); } } @@ -911,10 +916,12 @@ //ADDA.l decoded->extra.size = OPSIZE_LONG; decoded->dst.addr_mode = MODE_AREG; + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); } else { decoded->extra.size = size; decoded->src.addr_mode = MODE_REG; + decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, size, &(decoded->dst)); } } else { @@ -924,7 +931,7 @@ decoded->extra.size = size; istream = m68k_decode_op(istream, size, &(decoded->src)); decoded->dst.addr_mode = decoded->src.addr_mode; - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); } } else { if (size == OPSIZE_INVALID) { @@ -935,7 +942,7 @@ decoded->extra.size = size; decoded->dst.addr_mode = MODE_REG; } - decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); + decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); } break;