template<> auto M68K::_read(uint32 addr) -> uint32 { return bus->readByte(addr); } template<> auto M68K::_read(uint32 addr) -> uint32 { return bus->readWord(addr); } template<> auto M68K::_read(uint32 addr) -> uint32 { uint32 data = _read(addr + 0) << 16; return data | _read(addr + 2) << 0; } template auto M68K::_readPC() -> uint32 { auto data = _read(_pc); _pc += Size == Long ? 4 : 2; return clip(data); } auto M68K::_readDisplacement(uint32 base) -> uint32 { return base + (int16)_readPC(); } auto M68K::_readIndex(uint32 base) -> uint32 { auto extension = _readPC(); auto index = extension & 0x8000 ? read(AddressRegister{extension >> 12}) : read(DataRegister{extension >> 12}); if(extension & 0x800) index = (int16)index; return base + index + (int8)extension; } auto M68K::_dataRegister(DataRegister dr) -> string { return {"d", dr.number}; } auto M68K::_addressRegister(AddressRegister ar) -> string { return {"a", ar.number}; } template auto M68K::_immediate() -> string { return {"#$", hex(_readPC(), 2 << Size)}; } template auto M68K::_address(EffectiveAddress& ea) -> string { if(ea.mode == 9) return {"$", hex(_pc + (int16)_readPC(), 6L)}; return "???"; } template auto M68K::_effectiveAddress(EffectiveAddress& ea) -> string { if(ea.mode == 0) return {_dataRegister(DataRegister{ea.reg})}; if(ea.mode == 1) return {_addressRegister(AddressRegister{ea.reg})}; if(ea.mode == 2) return {"(", _addressRegister(AddressRegister{ea.reg}), ")"}; if(ea.mode == 3) return {"(", _addressRegister(AddressRegister{ea.reg}), ")+"}; if(ea.mode == 4) return {"-(", _addressRegister(AddressRegister{ea.reg}), ")"}; if(ea.mode == 5) return {"($", hex(_readDisplacement(read(AddressRegister{ea.reg})), 6L), ")"}; if(ea.mode == 6) return {"($", hex(_readIndex(read(AddressRegister{ea.reg})), 6L), ")"}; if(ea.mode == 7) return {"($", hex((int16)_readPC(), 6L), ")"}; if(ea.mode == 8) return {"($", hex(_readPC(), 6L), ")"}; if(ea.mode == 9) return {"($", hex(_readDisplacement(_pc), 6L), ")"}; if(ea.mode == 10) return {"($", hex(_readIndex(_pc), 6L), ")"}; if(ea.mode == 11) return {"#$", hex(_readPC(), 2 << Size)}; return "???"; //should never occur } auto M68K::_branch(uint8 displacement) -> string { uint16 extension = _readPC(); _pc -= 2; int32 offset = displacement ? sign(displacement) : sign(extension); return {"$", hex(_pc + offset, 6L)}; } template auto M68K::_suffix() -> string { return Size == Byte ? ".b" : Size == Word ? ".w" : ".l"; } auto M68K::_condition(uint4 condition) -> string { static const string conditions[16] = { "t ", "f ", "hi", "ls", "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi", "ge", "lt", "gt", "le", }; return conditions[condition]; } auto M68K::disassemble(uint32 pc) -> string { uint16 opcode; return {hex(_pc = pc, 6L), " ", hex(opcode = _readPC(), 4L), " ", disassembleTable[opcode]()}; } auto M68K::disassembleRegisters() -> string { return { hex(r.d[0], 8L), " ", hex(r.d[1], 8L), " ", hex(r.d[2], 8L), " ", hex(r.d[3], 8L), " ", hex(r.d[4], 8L), " ", hex(r.d[5], 8L), " ", hex(r.d[6], 8L), " ", hex(r.d[7], 8L), " ", r.t ? "T" : "t", r.s ? "S" : "s", (uint)r.i, r.c ? "C" : "c", r.v ? "V" : "v", r.z ? "Z" : "z", r.n ? "N" : "n", r.x ? "X" : "x", "\n", hex(r.a[0], 8L), " ", hex(r.a[1], 8L), " ", hex(r.a[2], 8L), " ", hex(r.a[3], 8L), " ", hex(r.a[4], 8L), " ", hex(r.a[5], 8L), " ", hex(r.a[6], 8L), " ", hex(r.a[7], 8L), " ", hex(r.sp, 8L) }; } // auto M68K::disassembleABCD(EffectiveAddress with, EffectiveAddress from) -> string { return {"abcd ", _effectiveAddress(from), ",", _effectiveAddress(with)}; } template auto M68K::disassembleADD(EffectiveAddress from, DataRegister with) -> string { return {"add", _suffix(), " ", _effectiveAddress(from), ",", _dataRegister(with)}; } template auto M68K::disassembleADD(DataRegister from, EffectiveAddress with) -> string { return {"add", _suffix(), " ", _dataRegister(from), ",", _effectiveAddress(with)}; } template auto M68K::disassembleADDA(AddressRegister ar, EffectiveAddress ea) -> string { return {"adda", _suffix(), " ", _effectiveAddress(ea), ",", _addressRegister(ar)}; } template auto M68K::disassembleADDI(EffectiveAddress ea) -> string { return {"addi", _suffix(), " ", _immediate(), ",", _effectiveAddress(ea)}; } template auto M68K::disassembleADDQ(uint4 immediate, EffectiveAddress with) -> string { return {"addq", _suffix(), " #", immediate, ",", _effectiveAddress(with)}; } template auto M68K::disassembleADDQ(uint4 immediate, AddressRegister with) -> string { return {"addq", _suffix(), " #", immediate, ",", _addressRegister(with)}; } template auto M68K::disassembleADDX(EffectiveAddress with, EffectiveAddress from) -> string { return {"addx", _suffix(), " ", _effectiveAddress(from), ",", _effectiveAddress(with)}; } template auto M68K::disassembleAND(EffectiveAddress from, DataRegister with) -> string { return {"and", _suffix(), " ", _effectiveAddress(from), ",", _dataRegister(with)}; } template auto M68K::disassembleAND(DataRegister from, EffectiveAddress with) -> string { return {"and", _suffix(), " ", _dataRegister(from), ",", _effectiveAddress(with)}; } template auto M68K::disassembleANDI(EffectiveAddress ea) -> string { return {"andi", _suffix(), " ", _immediate(), ",", _effectiveAddress(ea)}; } auto M68K::disassembleANDI_TO_CCR() -> string { return {"andi ", _immediate(), ",ccr"}; } auto M68K::disassembleANDI_TO_SR() -> string { return {"andi ", _immediate(), ",sr"}; } template auto M68K::disassembleASL(uint4 shift, DataRegister modify) -> string { return {"asl", _suffix(), " #", shift, ",", _dataRegister(modify)}; } template auto M68K::disassembleASL(DataRegister shift, DataRegister modify) -> string { return {"asl", _suffix(), " ", _dataRegister(shift), ",", _dataRegister(modify)}; } auto M68K::disassembleASL(EffectiveAddress modify) -> string { return {"asl", _suffix(), " ", _effectiveAddress(modify)}; } template auto M68K::disassembleASR(uint4 shift, DataRegister modify) -> string { return {"asr", _suffix(), " #", shift, ",", _dataRegister(modify)}; } template auto M68K::disassembleASR(DataRegister shift, DataRegister modify) -> string { return {"asr", _suffix(), " ", _dataRegister(shift), ",", _dataRegister(modify)}; } auto M68K::disassembleASR(EffectiveAddress modify) -> string { return {"asr", _suffix(), " ", _effectiveAddress(modify)}; } auto M68K::disassembleBCC(uint4 condition, uint8 displacement) -> string { auto cc = _condition(condition); if(condition == 0) cc = "ra"; if(condition == 1) cc = "sr"; return {"b", cc, " ", _branch(displacement)}; } template auto M68K::disassembleBCHG(DataRegister bit, EffectiveAddress with) -> string { return {"bchg", _suffix(), " ", _dataRegister(bit), ",", _effectiveAddress(with)}; } template auto M68K::disassembleBCHG(EffectiveAddress with) -> string { return {"bchg", _suffix(), " ", _immediate(), ",", _effectiveAddress(with)}; } template auto M68K::disassembleBCLR(DataRegister bit, EffectiveAddress with) -> string { return {"bclr", _suffix(), " ", _dataRegister(bit), ",", _effectiveAddress(with)}; } template auto M68K::disassembleBCLR(EffectiveAddress with) -> string { return {"bclr", _suffix(), " ", _immediate(), ",", _effectiveAddress(with)}; } template auto M68K::disassembleBSET(DataRegister bit, EffectiveAddress with) -> string { return {"bset", _suffix(), " ", _dataRegister(bit), ",", _effectiveAddress(with)}; } template auto M68K::disassembleBSET(EffectiveAddress with) -> string { return {"bset", _suffix(), " ", _immediate(), ",", _effectiveAddress(with)}; } template auto M68K::disassembleBTST(DataRegister bit, EffectiveAddress with) -> string { return {"btst", _suffix(), " ", _dataRegister(bit), ",", _effectiveAddress(with)}; } template auto M68K::disassembleBTST(EffectiveAddress with) -> string { return {"btst", _suffix(), " ", _immediate(), ",", _effectiveAddress(with)}; } auto M68K::disassembleCHK(DataRegister compare, EffectiveAddress maximum) -> string { return {"chk", _suffix(), " ", _effectiveAddress(maximum), ",", _dataRegister(compare)}; } template auto M68K::disassembleCLR(EffectiveAddress ea) -> string { return {"clr", _suffix(), " ", _effectiveAddress(ea)}; } template auto M68K::disassembleCMP(DataRegister dr, EffectiveAddress ea) -> string { return {"cmp", _suffix(), " ", _effectiveAddress(ea), ",", _dataRegister(dr)}; } template auto M68K::disassembleCMPA(AddressRegister ar, EffectiveAddress ea) -> string { return {"cmpa", _suffix(), " ", _effectiveAddress(ea), ",", _addressRegister(ar)}; } template auto M68K::disassembleCMPI(EffectiveAddress ea) -> string { return {"cmpi", _suffix(), " ", _immediate(), ",", _effectiveAddress(ea)}; } template auto M68K::disassembleCMPM(EffectiveAddress ax, EffectiveAddress ay) -> string { return {"cmpm", _suffix(), " ", _effectiveAddress(ay), ",", _effectiveAddress(ax)}; } auto M68K::disassembleDBCC(uint4 condition, DataRegister dr) -> string { auto base = _pc; auto displacement = (int16)_readPC(); return {"db", _condition(condition), " ", _dataRegister(dr), ",$", hex(base + displacement, 6L)}; } auto M68K::disassembleDIVS(DataRegister with, EffectiveAddress from) -> string { return {"divs", _suffix(), " ", _effectiveAddress(from), ",", _dataRegister(with)}; } auto M68K::disassembleDIVU(DataRegister with, EffectiveAddress from) -> string { return {"divu", _suffix(), " ", _effectiveAddress(from), ",", _dataRegister(with)}; } template auto M68K::disassembleEOR(DataRegister from, EffectiveAddress with) -> string { return {"eor", _suffix(), " ", _dataRegister(from), ",", _effectiveAddress(with)}; } template auto M68K::disassembleEORI(EffectiveAddress with) -> string { return {"eori", _suffix(), " ", _immediate(), ",", _effectiveAddress(with)}; } auto M68K::disassembleEORI_TO_CCR() -> string { return {"eori ", _immediate(), ",ccr"}; } auto M68K::disassembleEORI_TO_SR() -> string { return {"eori ", _immediate(), ",sr"}; } auto M68K::disassembleEXG(DataRegister x, DataRegister y) -> string { return {"exg ", _dataRegister(x), ",", _dataRegister(y)}; } auto M68K::disassembleEXG(AddressRegister x, AddressRegister y) -> string { return {"exg ", _addressRegister(x), ",", _addressRegister(y)}; } auto M68K::disassembleEXG(DataRegister x, AddressRegister y) -> string { return {"exg ", _dataRegister(x), ",", _addressRegister(y)}; } template auto M68K::disassembleEXT(DataRegister with) -> string { return {"ext", _suffix(), " ", _dataRegister(with)}; } auto M68K::disassembleILLEGAL() -> string { return {"illegal "}; } auto M68K::disassembleJMP(EffectiveAddress target) -> string { return {"jmp ", _effectiveAddress(target)}; } auto M68K::disassembleJSR(EffectiveAddress target) -> string { return {"jsr ", _effectiveAddress(target)}; } auto M68K::disassembleLEA(AddressRegister ar, EffectiveAddress ea) -> string { return {"lea ", _address(ea), ",", _addressRegister(ar)}; } auto M68K::disassembleLINK(AddressRegister with) -> string { return {"link ", _addressRegister(with), ",", _immediate()}; } template auto M68K::disassembleLSL(uint4 immediate, DataRegister dr) -> string { return {"lsl", _suffix(), " #", immediate, ",", _dataRegister(dr)}; } template auto M68K::disassembleLSL(DataRegister sr, DataRegister dr) -> string { return {"lsl", _suffix(), " ", _dataRegister(sr), ",", _dataRegister(dr)}; } auto M68K::disassembleLSL(EffectiveAddress ea) -> string { return {"lsl", _suffix(), " ", _effectiveAddress(ea)}; } template auto M68K::disassembleLSR(uint4 immediate, DataRegister dr) -> string { return {"lsr", _suffix(), " #", immediate, ",", _dataRegister(dr)}; } template auto M68K::disassembleLSR(DataRegister shift, DataRegister dr) -> string { return {"lsr", _suffix(), " ", _dataRegister(shift), ",", _dataRegister(dr)}; } auto M68K::disassembleLSR(EffectiveAddress ea) -> string { return {"lsr", _suffix(), " ", _effectiveAddress(ea)}; } template auto M68K::disassembleMOVE(EffectiveAddress to, EffectiveAddress from) -> string { return {"move", _suffix(), " ", _effectiveAddress(from), ",", _effectiveAddress(to)}; } template auto M68K::disassembleMOVEA(AddressRegister ar, EffectiveAddress ea) -> string { return {"movea ", _effectiveAddress(ea), ",", _addressRegister(ar)}; } template auto M68K::disassembleMOVEM_TO_MEM(EffectiveAddress to) -> string { string op{"movem", _suffix(), " "}; uint16 list = _readPC(); string regs; for(uint n : range(8)) if(list.bit(0 + n)) regs.append(_dataRegister(DataRegister{n}), ","); regs.trimRight(","); if(regs && list >> 8) regs.append("/"); for(uint n : range(8)) if(list.bit(8 + n)) regs.append(_addressRegister(AddressRegister{n}), ","); regs.trimRight(","); return {op, regs, ",", _effectiveAddress(to)}; } template auto M68K::disassembleMOVEM_TO_REG(EffectiveAddress from) -> string { string op{"movem", _suffix(), " "}; uint16 list = _readPC(); string regs; for(uint n : range(8)) if(list.bit(0 + n)) regs.append(_dataRegister(DataRegister{n}), ","); regs.trimRight(","); if(regs && list >> 8) regs.append("/"); for(uint n : range(8)) if(list.bit(8 + n)) regs.append(_addressRegister(AddressRegister{n}), ","); regs.trimRight(","); return {op, _effectiveAddress(from), ",", regs}; } template auto M68K::disassembleMOVEP(DataRegister from, EffectiveAddress to) -> string { return {"movep", _suffix(), " ", _dataRegister(from), ",", _effectiveAddress(to)}; } template auto M68K::disassembleMOVEP(EffectiveAddress from, DataRegister to) -> string { return {"movep", _suffix(), " ", _effectiveAddress(from), ",", _dataRegister(to)}; } auto M68K::disassembleMOVEQ(DataRegister dr, uint8 immediate) -> string { return {"moveq #$", hex(immediate, 2L), ",", _dataRegister(dr)}; } auto M68K::disassembleMOVE_FROM_SR(EffectiveAddress ea) -> string { return {"move sr,", _effectiveAddress(ea)}; } auto M68K::disassembleMOVE_TO_CCR(EffectiveAddress ea) -> string { return {"move ", _effectiveAddress(ea), ",ccr"}; } auto M68K::disassembleMOVE_TO_SR(EffectiveAddress ea) -> string { return {"move ", _effectiveAddress(ea), ",sr"}; } auto M68K::disassembleMOVE_FROM_USP(AddressRegister to) -> string { return {"move usp,", _addressRegister(to)}; } auto M68K::disassembleMOVE_TO_USP(AddressRegister from) -> string { return {"move ", _addressRegister(from), ",usp"}; } auto M68K::disassembleMULS(DataRegister with, EffectiveAddress from) -> string { return {"muls", _suffix(), " ", _effectiveAddress(from), ",", _dataRegister(with)}; } auto M68K::disassembleMULU(DataRegister with, EffectiveAddress from) -> string { return {"mulu", _suffix(), " ", _effectiveAddress(from), ",", _dataRegister(with)}; } auto M68K::disassembleNBCD(EffectiveAddress with) -> string { return {"nbcd ", _effectiveAddress(with)}; } template auto M68K::disassembleNEG(EffectiveAddress with) -> string { return {"neg", _suffix(), " ", _effectiveAddress(with)}; } template auto M68K::disassembleNEGX(EffectiveAddress with) -> string { return {"negx", _suffix(), " ", _effectiveAddress(with)}; } auto M68K::disassembleNOP() -> string { return {"nop "}; } template auto M68K::disassembleNOT(EffectiveAddress with) -> string { return {"not", _suffix(), " ", _effectiveAddress(with)}; } template auto M68K::disassembleOR(EffectiveAddress from, DataRegister with) -> string { return {"or", _suffix(), " ", _effectiveAddress(from), ",", _dataRegister(with)}; } template auto M68K::disassembleOR(DataRegister from, EffectiveAddress with) -> string { return {"or", _suffix(), " ", _dataRegister(from), ",", _effectiveAddress(with)}; } template auto M68K::disassembleORI(EffectiveAddress with) -> string { return {"ori", _suffix(), " ", _immediate(), ",", _effectiveAddress(with)}; } auto M68K::disassembleORI_TO_CCR() -> string { return {"ori ", _immediate(), ",ccr"}; } auto M68K::disassembleORI_TO_SR() -> string { return {"ori ", _immediate(), ",sr"}; } auto M68K::disassemblePEA(EffectiveAddress from) -> string { return {"pea ", _effectiveAddress(from)}; } auto M68K::disassembleRESET() -> string { return {"reset "}; } template auto M68K::disassembleROL(uint4 shift, DataRegister modify) -> string { return {"rol", _suffix(), " #", shift, ",", _dataRegister(modify)}; } template auto M68K::disassembleROL(DataRegister shift, DataRegister modify) -> string { return {"rol", _suffix(), " ", _dataRegister(shift), ",", _dataRegister(modify)}; } auto M68K::disassembleROL(EffectiveAddress modify) -> string { return {"rol", _suffix(), " ", _effectiveAddress(modify)}; } template auto M68K::disassembleROR(uint4 shift, DataRegister modify) -> string { return {"ror", _suffix(), " #", shift, ",", _dataRegister(modify)}; } template auto M68K::disassembleROR(DataRegister shift, DataRegister modify) -> string { return {"ror", _suffix(), " ", _dataRegister(shift) ,",", _dataRegister(modify)}; } auto M68K::disassembleROR(EffectiveAddress modify) -> string { return {"ror", _suffix(), " ", _effectiveAddress(modify)}; } template auto M68K::disassembleROXL(uint4 shift, DataRegister modify) -> string { return {"roxl", _suffix(), " #", shift, ",", _dataRegister(modify)}; } template auto M68K::disassembleROXL(DataRegister shift, DataRegister modify) -> string { return {"roxl", _suffix(), " ", _dataRegister(shift), ",", _dataRegister(modify)}; } auto M68K::disassembleROXL(EffectiveAddress modify) -> string { return {"roxl", _suffix(), " ", _effectiveAddress(modify)}; } template auto M68K::disassembleROXR(uint4 shift, DataRegister modify) -> string { return {"roxr", _suffix(), " #", shift, ",", _dataRegister(modify)}; } template auto M68K::disassembleROXR(DataRegister shift, DataRegister modify) -> string { return {"roxr", _suffix(), " ", _dataRegister(shift), ",", _dataRegister(modify)}; } auto M68K::disassembleROXR(EffectiveAddress modify) -> string { return {"roxr", _suffix(), " ", _effectiveAddress(modify)}; } auto M68K::disassembleRTE() -> string { return {"rte "}; } auto M68K::disassembleRTR() -> string { return {"rtr "}; } auto M68K::disassembleRTS() -> string { return {"rts "}; } auto M68K::disassembleSBCD(EffectiveAddress with, EffectiveAddress from) -> string { return {"sbcd ", _effectiveAddress(from), ",", _effectiveAddress(with)}; } auto M68K::disassembleSCC(uint4 condition, EffectiveAddress to) -> string { return {"s", _condition(condition), " ", _effectiveAddress(to)}; } auto M68K::disassembleSTOP() -> string { return {"stop ", _immediate()}; } template auto M68K::disassembleSUB(EffectiveAddress source, DataRegister target) -> string { return {"sub", _suffix(), " ", _effectiveAddress(source), ",", _dataRegister(target)}; } template auto M68K::disassembleSUB(DataRegister source, EffectiveAddress target) -> string { return {"sub", _suffix(), " ", _dataRegister(source), ",", _effectiveAddress(target)}; } template auto M68K::disassembleSUBA(AddressRegister to, EffectiveAddress from) -> string { return {"suba", _suffix(), " ", _addressRegister(to), ",", _effectiveAddress(from)}; } template auto M68K::disassembleSUBI(EffectiveAddress with) -> string { return {"subi", _suffix(), " ", _immediate(), ",", _effectiveAddress(with)}; } template auto M68K::disassembleSUBQ(uint4 immediate, EffectiveAddress with) -> string { return {"subq", _suffix(), " #", immediate, ",", _effectiveAddress(with)}; } template auto M68K::disassembleSUBQ(uint4 immediate, AddressRegister with) -> string { return {"subq", _suffix(), " #", immediate, ",", _addressRegister(with)}; } template auto M68K::disassembleSUBX(EffectiveAddress with, EffectiveAddress from) -> string { return {"subx", _suffix(), " ", _effectiveAddress(from), ",", _effectiveAddress(with)}; } auto M68K::disassembleSWAP(DataRegister with) -> string { return {"swap ", _dataRegister(with)}; } auto M68K::disassembleTAS(EffectiveAddress with) -> string { return {"tas ", _effectiveAddress(with)}; } auto M68K::disassembleTRAP(uint4 vector) -> string { return {"trap #", vector}; } auto M68K::disassembleTRAPV() -> string { return {"trapv "}; } template auto M68K::disassembleTST(EffectiveAddress ea) -> string { return {"tst", _suffix(), " ", _effectiveAddress(ea)}; } auto M68K::disassembleUNLK(AddressRegister with) -> string { return {"unlk ", _addressRegister(with)}; }