diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 6dd1fcfc..9f6e3e42 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -11,7 +11,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "100.10"; + static const string Version = "100.11"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/md/cpu/cpu.cpp b/higan/md/cpu/cpu.cpp index 8a0b6ca2..bc1c858f 100644 --- a/higan/md/cpu/cpu.cpp +++ b/higan/md/cpu/cpu.cpp @@ -10,8 +10,8 @@ auto CPU::Enter() -> void { } auto CPU::boot() -> void { - r.da[A7] = read(1, 0) << 16 | read(1, 2) << 0; - r.pc = read(1, 4) << 16 | read(1, 6) << 0; + r.a[7] = read(1, 0) << 16 | read(1, 2) << 0; + r.pc = read(1, 4) << 16 | read(1, 6) << 0; } auto CPU::main() -> void { diff --git a/higan/processor/m68k/disassembler.cpp b/higan/processor/m68k/disassembler.cpp index ccd6b0d6..2efb539f 100644 --- a/higan/processor/m68k/disassembler.cpp +++ b/higan/processor/m68k/disassembler.cpp @@ -17,36 +17,36 @@ template auto M68K::_readPC() -> uint32 { return clip(data); } -auto M68K::_register(Register r) -> string { - static const string registers[16] = { - "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", - "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", - }; - return registers[r.number]; +auto M68K::_register(DataRegister dr) -> string { + return {"d", dr.number}; +} + +auto M68K::_register(AddressRegister ar) -> string { + return {"a", ar.number}; } template auto M68K::_immediate() -> string { return {"#$", hex(_readPC(), 2 << Size)}; } -template auto M68K::_address(EA ea) -> string { +template auto M68K::_address(EffectiveAddress& ea) -> string { if(ea.mode == 9) return {"$", hex(_pc + (int16)_readPC(), 6L)}; return "???"; } -template auto M68K::_read(EA ea) -> string { - if(ea.mode == 0) return {_register(ea.reg)}; - if(ea.mode == 1) return {_register(ea.reg)}; - if(ea.mode == 2) return {"(", _register(ea.reg), ")"}; - if(ea.mode == 3) return {"(", _register(ea.reg), ")+"}; - if(ea.mode == 4) return {"-(", _register(ea.reg), ")"}; - if(ea.mode == 5) return {"($", hex(read(ea.reg) + (int16)_readPC(), 6L), ")"}; +template auto M68K::_read(EffectiveAddress& ea) -> string { + if(ea.mode == 0) return {_register(DataRegister{ea.reg})}; + if(ea.mode == 1) return {_register(AddressRegister{ea.reg})}; + if(ea.mode == 2) return {"(", _register(AddressRegister{ea.reg}), ")"}; + if(ea.mode == 3) return {"(", _register(AddressRegister{ea.reg}), ")+"}; + if(ea.mode == 4) return {"-(", _register(AddressRegister{ea.reg}), ")"}; + if(ea.mode == 5) return {"($", hex(read(AddressRegister{ea.reg}) + (int16)_readPC(), 6L), ")"}; if(ea.mode == 8) return {"($", hex(_readPC(), 6L), ")"}; if(ea.mode == 11) return {"#$", hex(_readPC(), 2 << Size)}; return "???"; } -template auto M68K::_write(EA ea) -> string { +template auto M68K::_write(EffectiveAddress& ea) -> string { return _read(ea); } @@ -76,8 +76,8 @@ auto M68K::disassemble(uint32 pc) -> string { auto M68K::disassembleRegisters() -> string { return { - hex(r.da[D0], 8L), " ", hex(r.da[D1], 8L), " ", hex(r.da[D2], 8L), " ", hex(r.da[D3], 8L), " ", - hex(r.da[D4], 8L), " ", hex(r.da[D5], 8L), " ", hex(r.da[D6], 8L), " ", hex(r.da[D7], 8L), " ", + 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, @@ -86,27 +86,35 @@ auto M68K::disassembleRegisters() -> string { r.z ? "Z" : "z", r.n ? "N" : "n", r.x ? "X" : "x", "\n", - hex(r.da[A0], 8L), " ", hex(r.da[A1], 8L), " ", hex(r.da[A2], 8L), " ", hex(r.da[A3], 8L), " ", - hex(r.da[A4], 8L), " ", hex(r.da[A5], 8L), " ", hex(r.da[A6], 8L), " ", hex(r.da[A7], 8L), " ", hex(r.sp, 8L) + 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) }; } // -template auto M68K::disassembleADD(Register rd, uint1 direction, EA ea) -> string { +template auto M68K::disassembleADD(DataRegister dr, uint1 direction, EffectiveAddress ea) -> string { string op{"add", _suffix(), " "}; if(direction == 0) { - return {op, _read(ea), ",", _register(rd)}; + return {op, _read(ea), ",", _register(dr)}; } else { - return {op, "", _register(rd), ",", _read(ea)}; + return {op, "", _register(dr), ",", _read(ea)}; } } -template auto M68K::disassembleANDI(EA ea) -> string { +template auto M68K::disassembleANDI(EffectiveAddress ea) -> string { return {"andi", _suffix(), " ", _immediate(), ",", _read(ea)}; } +auto M68K::disassembleANDI_TO_CCR() -> string { + return {"andi ", _immediate(), ",ccr"}; +} + +auto M68K::disassembleANDI_TO_SR() -> string { + return {"andi ", _immediate(), ",sr"}; +} + auto M68K::disassembleBCC(uint4 condition, uint8 displacement) -> string { auto cc = _condition(condition); if(condition == 0) cc = "ra"; @@ -114,46 +122,57 @@ auto M68K::disassembleBCC(uint4 condition, uint8 displacement) -> string { return {"b", cc, " ", _branch(displacement)}; } -template auto M68K::disassembleBTST(Register rd, EA ea) -> string { - return {"btst ", _register(rd), ",", _read(ea)}; +template auto M68K::disassembleBTST(DataRegister dr, EffectiveAddress ea) -> string { + return {"btst ", _register(dr), ",", _read(ea)}; } -template auto M68K::disassembleBTST(EA ea) -> string { +template auto M68K::disassembleBTST(EffectiveAddress ea) -> string { return {"btst ", _immediate(), ",", _read(ea)}; } -template auto M68K::disassembleCLR(EA ea) -> string { +template auto M68K::disassembleCLR(EffectiveAddress ea) -> string { return {"clr", _suffix(), " ", _read(ea)}; } -template auto M68K::disassembleCMP(Register rd, EA ea) -> string { - return {"cmp", _suffix(), " ", _read(ea), ",", _register(rd)}; +template auto M68K::disassembleCMP(DataRegister dr, EffectiveAddress ea) -> string { + return {"cmp", _suffix(), " ", _read(ea), ",", _register(dr)}; } -auto M68K::disassembleDBCC(uint4 condition, Register rd) -> string { +auto M68K::disassembleDBCC(uint4 condition, DataRegister dr) -> string { auto base = _pc; auto displacement = (int16)_readPC(); - return {"db", _condition(condition), " ", _register(rd), ",$", hex(base + displacement, 6L)}; + return {"db", _condition(condition), " ", _register(dr), ",$", hex(base + displacement, 6L)}; } -auto M68K::disassembleLEA(Register ra, EA ea) -> string { - return {"lea ", _address(ea), ",", _register(ra)}; +auto M68K::disassembleEORI_TO_CCR() -> string { + return {"eori ", _immediate(), ",ccr"}; } -template auto M68K::disassembleMOVE(EA to, EA from) -> string { +auto M68K::disassembleEORI_TO_SR() -> string { + return {"eori ", _immediate(), ",sr"}; +} + +auto M68K::disassembleLEA(AddressRegister ar, EffectiveAddress ea) -> string { + return {"lea ", _address(ea), ",", _register(ar)}; +} + +template auto M68K::disassembleMOVE(EffectiveAddress to, EffectiveAddress from) -> string { return {"move", _suffix(), " ", _read(from), ",", _write(to)}; } -template auto M68K::disassembleMOVEA(Register ra, EA ea) -> string { - return {"movea ", _read(ea), ",", _register(ra)}; +template auto M68K::disassembleMOVEA(AddressRegister ar, EffectiveAddress ea) -> string { + return {"movea ", _read(ea), ",", _register(ar)}; } -template auto M68K::disassembleMOVEM(uint1 direction, EA ea) -> string { +template auto M68K::disassembleMOVEM(uint1 direction, EffectiveAddress ea) -> string { string op{"movem", _suffix(), " "}; uint16 list = _readPC(); string regs; - for(uint rn : range(16)) if(list.bit(rn)) regs.append(_register(Register{rn}), ","); + for(uint n : range(8)) if(list.bit(0 + n)) regs.append(_register(DataRegister{n}), ","); + regs.trimRight(","); + if(regs && list >> 8) regs.append("/"); + for(uint n : range(8)) if(list.bit(8 + n)) regs.append(_register(AddressRegister{n}), ","); regs.trimRight(","); if(direction == 0) { @@ -163,23 +182,27 @@ template auto M68K::disassembleMOVEM(uint1 direction, EA ea) -> strin } } -auto M68K::disassembleMOVEQ(Register rd, uint8 immediate) -> string { - return {"moveq #$", hex(immediate, 2L), ",", _register(rd)}; +auto M68K::disassembleMOVEQ(DataRegister dr, uint8 immediate) -> string { + return {"moveq #$", hex(immediate, 2L), ",", _register(dr)}; } -auto M68K::disassembleMOVE_FROM_SR(EA ea) -> string { +auto M68K::disassembleMOVE_FROM_SR(EffectiveAddress ea) -> string { return {"move sr,", _read(ea)}; } -auto M68K::disassembleMOVE_TO_SR(EA ea) -> string { +auto M68K::disassembleMOVE_TO_CCR(EffectiveAddress ea) -> string { + return {"move ", _read(ea), ",ccr"}; +} + +auto M68K::disassembleMOVE_TO_SR(EffectiveAddress ea) -> string { return {"move ", _read(ea), ",sr"}; } -auto M68K::disassembleMOVE_USP(uint1 direction, Register ra) -> string { +auto M68K::disassembleMOVE_USP(uint1 direction, AddressRegister ar) -> string { if(direction == 0) { - return {"move ", _register(ra), ",usp"}; + return {"move ", _register(ar), ",usp"}; } else { - return {"move usp,", _register(ra)}; + return {"move usp,", _register(ar)}; } } @@ -187,10 +210,18 @@ auto M68K::disassembleNOP() -> string { return {"nop "}; } +auto M68K::disassembleORI_TO_CCR() -> string { + return {"ori ", _immediate(), ",ccr"}; +} + +auto M68K::disassembleORI_TO_SR() -> string { + return {"ori ", _immediate(), ",sr"}; +} + auto M68K::disassembleRTS() -> string { return {"rts "}; } -template auto M68K::disassembleTST(EA ea) -> string { +template auto M68K::disassembleTST(EffectiveAddress ea) -> string { return {"tst", _suffix(), " ", _read(ea)}; } diff --git a/higan/processor/m68k/ea.cpp b/higan/processor/m68k/effective-address.cpp similarity index 68% rename from higan/processor/m68k/ea.cpp rename to higan/processor/m68k/effective-address.cpp index 58ab4c0f..ba3383d3 100644 --- a/higan/processor/m68k/ea.cpp +++ b/higan/processor/m68k/effective-address.cpp @@ -1,37 +1,39 @@ -template auto M68K::fetch(EA& ea) -> uint32 { +template auto M68K::fetch(EffectiveAddress& ea) -> uint32 { if(!ea.valid.raise()) return ea.address; switch(ea.mode) { case DataRegisterDirect: { - return read(ea.reg); + return read(DataRegister{ea.reg}); } case AddressRegisterDirect: { - return read(ea.reg); + return read(AddressRegister{ea.reg}); } case AddressRegisterIndirect: { - return read(ea.reg); + return read(AddressRegister{ea.reg}); } case AddressRegisterIndirectWithPostIncrement: { - return read(ea.reg); + return read(AddressRegister{ea.reg}); } case AddressRegisterIndirectWithPreDecrement: { - return read(ea.reg); + return read(AddressRegister{ea.reg}); } case AddressRegisterIndirectWithDisplacement: { - return read(ea.reg) + (int16)readPC(); + return read(AddressRegister{ea.reg}) + (int16)readPC(); } case AddressRegisterIndirectWithIndex: { auto extension = readPC(); - auto index = read(Register{extension >> 12}); + auto index = extension & 0x8000 + ? read(AddressRegister{extension >> 12}) + : read(DataRegister{extension >> 12}); if(extension & 0x800) index = (int16)index; - return read(ea.reg) + index + (int8)extension; + return read(AddressRegister{ea.reg}) + index + (int8)extension; } case AbsoluteShortIndirect: { @@ -50,7 +52,9 @@ template auto M68K::fetch(EA& ea) -> uint32 { case ProgramCounterIndirectWithIndex: { auto base = r.pc; auto extension = readPC(); - auto index = read(Register{extension >> 12}); + auto index = extension & 0x8000 + ? read(AddressRegister{extension >> 12}) + : read(DataRegister{extension >> 12}); if(extension & 0x800) index = (int16)index; return base + index + (int8)extension; } @@ -64,7 +68,7 @@ template auto M68K::fetch(EA& ea) -> uint32 { return 0; } -template auto M68K::read(EA& ea) -> uint32 { +template auto M68K::read(EffectiveAddress& ea) -> uint32 { ea.address = fetch(ea); switch(ea.mode) { @@ -83,13 +87,13 @@ template auto M68K::read(EA& ea) -> uint32 { case AddressRegisterIndirectWithPostIncrement: { auto data = read(ea.address); - if(Update) write(ea.reg, ea.address += (Size == Long ? 4 : 2)); + if(Update) write(AddressRegister{ea.reg}, ea.address += (Size == Long ? 4 : 2)); return data; } case AddressRegisterIndirectWithPreDecrement: { auto data = read(ea.address - (Size == Long ? 4 : 2)); - if(Update) write(ea.reg, ea.address -= (Size == Long ? 4 : 2)); + if(Update) write(AddressRegister{ea.reg}, ea.address -= (Size == Long ? 4 : 2)); return data; } @@ -126,17 +130,17 @@ template auto M68K::read(EA& ea) -> uint32 { return 0; } -template auto M68K::write(EA& ea, uint32 data) -> void { +template auto M68K::write(EffectiveAddress& ea, uint32 data) -> void { ea.address = fetch(ea); switch(ea.mode) { case DataRegisterDirect: { - return write(ea.reg, data); + return write(DataRegister{ea.reg}, data); } case AddressRegisterDirect: { - return write(ea.reg, data); + return write(AddressRegister{ea.reg}, data); } case AddressRegisterIndirect: { @@ -145,13 +149,13 @@ template auto M68K::write(EA& ea, uint32 data) -> void { case AddressRegisterIndirectWithPostIncrement: { write(ea.address, data); - if(Update) write(ea.reg, ea.address += (Size == Long ? 4 : 2)); + if(Update) write(AddressRegister{ea.reg}, ea.address += (Size == Long ? 4 : 2)); return; } case AddressRegisterIndirectWithPreDecrement: { write(ea.address - (Size == Long ? 4 : 2), data); - if(Update) write(ea.reg, ea.address -= (Size == Long ? 4 : 2)); + if(Update) write(AddressRegister{ea.reg}, ea.address -= (Size == Long ? 4 : 2)); return; } @@ -186,16 +190,16 @@ template auto M68K::write(EA& ea, uint32 data) -> void { } } -template auto M68K::flush(EA& ea, uint32 data) -> void { +template auto M68K::flush(EffectiveAddress& ea, uint32 data) -> void { switch(ea.mode) { case AddressRegisterIndirectWithPostIncrement: { - write(ea.reg, data); + write(AddressRegister{ea.reg}, data); return; } case AddressRegisterIndirectWithPreDecrement: { - write(ea.reg, data); + write(AddressRegister{ea.reg}, data); return; } diff --git a/higan/processor/m68k/instruction.cpp b/higan/processor/m68k/instruction.cpp index 5b0f7ecf..3be822f2 100644 --- a/higan/processor/m68k/instruction.cpp +++ b/higan/processor/m68k/instruction.cpp @@ -8,9 +8,12 @@ auto M68K::trap() -> void { auto M68K::instruction() -> void { instructionsExecuted++; -//print(disassembleRegisters(), "\n"); -//print(disassemble(r.pc), "\n"); -//print("\n"); + + if(instructionsExecuted >= 20) trap(); + + print(disassembleRegisters(), "\n"); + print(disassemble(r.pc), "\n"); + print("\n"); opcode = readPC(); return instructionTable[opcode](); @@ -39,11 +42,11 @@ M68K::M68K() { auto opcode = pattern("1101 ---- ++-- ----") | dreg << 9 | direction << 8 | mode << 3 | reg << 0; if(direction == 1 && (mode == 0 || mode == 1 || (mode == 7 && reg >= 2))) continue; - Register rd{D0 + dreg}; - EA ea{mode, reg}; - bind(opcode | 0 << 6, ADD, rd, direction, ea); - bind(opcode | 1 << 6, ADD, rd, direction, ea); - bind(opcode | 2 << 6, ADD, rd, direction, ea); + DataRegister dr{dreg}; + EffectiveAddress ea{mode, reg}; + bind(opcode | 0 << 6, ADD, dr, direction, ea); + bind(opcode | 1 << 6, ADD, dr, direction, ea); + bind(opcode | 2 << 6, ADD, dr, direction, ea); if(direction == 0 && mode == 1) unbind(opcode | 0 << 6); } @@ -54,12 +57,24 @@ M68K::M68K() { auto opcode = pattern("0000 0010 ++-- ----") | mode << 3 | reg << 0; if(mode == 1 || (mode == 7 && reg >= 2)) continue; - EA ea{mode, reg}; + EffectiveAddress ea{mode, reg}; bind(opcode | 0 << 6, ANDI, ea); bind(opcode | 1 << 6, ANDI, ea); bind(opcode | 2 << 6, ANDI, ea); } + //ANDI_TO_CCR + { auto opcode = pattern("0000 0010 0011 1100"); + + bind(opcode, ANDI_TO_CCR); + } + + //ANDI_TO_SR + { auto opcode = pattern("0000 0010 0111 1100"); + + bind(opcode, ANDI_TO_SR); + } + //BCC for(uint4 condition : range( 16)) for(uint8 displacement : range(256)) { @@ -75,10 +90,10 @@ M68K::M68K() { auto opcode = pattern("0000 ---1 00-- ----") | dreg << 9 | mode << 3 | reg << 0; if(mode == 1) continue; - Register rd{D0 + dreg}; - EA ea{mode, reg}; - if(mode == 0) bind(opcode, BTST, rd, ea); - if(mode != 0) bind(opcode, BTST, rd, ea); + DataRegister dr{dreg}; + EffectiveAddress ea{mode, reg}; + if(mode == 0) bind(opcode, BTST, dr, ea); + if(mode != 0) bind(opcode, BTST, dr, ea); } //BTST (immediate) @@ -87,7 +102,7 @@ M68K::M68K() { auto opcode = pattern("0000 1000 00-- ----") | mode << 3 | reg << 0; if(mode == 1 || (mode == 7 && reg == 2)) continue; - EA ea{mode, reg}; + EffectiveAddress ea{mode, reg}; if(mode == 0) bind(opcode, BTST, ea); if(mode != 0) bind(opcode, BTST, ea); } @@ -98,7 +113,7 @@ M68K::M68K() { auto opcode = pattern("0100 0010 ++-- ----") | mode << 3 | reg << 0; if(mode == 1 || (mode == 7 && reg >= 2)) continue; - EA ea{mode, reg}; + EffectiveAddress ea{mode, reg}; bind(opcode | 0 << 6, CLR, ea); bind(opcode | 1 << 6, CLR, ea); bind(opcode | 2 << 6, CLR, ea); @@ -110,11 +125,11 @@ M68K::M68K() { for(uint3 reg : range(8)) { auto opcode = pattern("1011 ---0 ++-- ----") | dreg << 9 | mode << 3 | reg << 0; - Register rd{D0 + dreg}; - EA ea{mode, reg}; - bind(opcode | 0 << 6, CMP, rd, ea); - bind(opcode | 1 << 6, CMP, rd, ea); - bind(opcode | 2 << 6, CMP, rd, ea); + DataRegister dr{dreg}; + EffectiveAddress ea{mode, reg}; + bind(opcode | 0 << 6, CMP, dr, ea); + bind(opcode | 1 << 6, CMP, dr, ea); + bind(opcode | 2 << 6, CMP, dr, ea); if(mode == 1) unbind(opcode | 0 << 6); } @@ -124,8 +139,20 @@ M68K::M68K() { for(uint3 dreg : range( 8)) { auto opcode = pattern("0101 ---- 1100 1---") | condition << 8 | dreg << 0; - Register rd{D0 + dreg}; - bind(opcode, DBCC, condition, rd); + DataRegister dr{dreg}; + bind(opcode, DBCC, condition, dr); + } + + //EORI_TO_CCR + { auto opcode = pattern("0000 1010 0011 1100"); + + bind(opcode, EORI_TO_CCR); + } + + //EORI_TO_SR + { auto opcode = pattern("0000 1010 0111 1100"); + + bind(opcode, EORI_TO_SR); } //LEA @@ -135,9 +162,9 @@ M68K::M68K() { auto opcode = pattern("0100 ---1 11-- ----") | areg << 9 | mode << 3 | reg << 0; if(mode <= 1 || mode == 3 || mode == 4 || (mode == 7 && reg == 4)) continue; - Register ra{A0 + areg}; - EA ea{mode, reg}; - bind(opcode, LEA, ra, ea); + AddressRegister ar{areg}; + EffectiveAddress ea{mode, reg}; + bind(opcode, LEA, ar, ea); } //MOVE @@ -148,8 +175,8 @@ M68K::M68K() { auto opcode = pattern("00++ ---- ---- ----") | toReg << 9 | toMode << 6 | fromMode << 3 | fromReg << 0; if(toMode == 1 || (toMode == 7 && toReg >= 2)) continue; - EA to{toMode, toReg}; - EA from{fromMode, fromReg}; + EffectiveAddress to{toMode, toReg}; + EffectiveAddress from{fromMode, fromReg}; bind(opcode | 1 << 12, MOVE, to, from); bind(opcode | 3 << 12, MOVE, to, from); bind(opcode | 2 << 12, MOVE, to, from); @@ -163,10 +190,10 @@ M68K::M68K() { for(uint3 reg : range(8)) { auto opcode = pattern("00++ ---0 01-- ----") | areg << 9 | mode << 3 | reg << 0; - Register ra{A0 + areg}; - EA ea{mode, reg}; - bind(opcode | 3 << 12, MOVEA, ra, ea); - bind(opcode | 2 << 12, MOVEA, ra, ea); + AddressRegister ar{areg}; + EffectiveAddress ea{mode, reg}; + bind(opcode | 3 << 12, MOVEA, ar, ea); + bind(opcode | 2 << 12, MOVEA, ar, ea); } //MOVEM @@ -177,7 +204,7 @@ M68K::M68K() { if(direction == 0 && (mode <= 1 || mode == 3 || (mode == 7 && reg >= 2))); if(direction == 1 && (mode <= 1 || mode == 4 || (mode == 7 && reg == 4))); - EA ea{mode, reg}; + EffectiveAddress ea{mode, reg}; bind(opcode | 0 << 6, MOVEM, direction, ea); bind(opcode | 1 << 6, MOVEM, direction, ea); } @@ -187,8 +214,8 @@ M68K::M68K() { for(uint8 immediate : range(256)) { auto opcode = pattern("0111 ---0 ---- ----") | dreg << 9 | immediate << 0; - Register rd{D0 + dreg}; - bind(opcode, MOVEQ, rd, immediate); + DataRegister dr{dreg}; + bind(opcode, MOVEQ, dr, immediate); } //MOVE_FROM_SR @@ -197,17 +224,27 @@ M68K::M68K() { auto opcode = pattern("0100 0000 11-- ----") | mode << 3 | reg << 0; if(mode == 1 || (mode == 7 && reg >= 2)) continue; - EA ea{mode, reg}; + EffectiveAddress ea{mode, reg}; bind(opcode, MOVE_FROM_SR, ea); } + //MOVE_TO_CCR + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("0100 0100 11-- ----") | mode << 3 | reg << 0; + if(mode == 1) continue; + + EffectiveAddress ea{mode, reg}; + bind(opcode, MOVE_TO_CCR, ea); + } + //MOVE_TO_SR for(uint3 mode : range(8)) for(uint3 reg : range(8)) { auto opcode = pattern("0100 0110 11-- ----") | mode << 3 | reg << 0; if(mode == 1) continue; - EA ea{mode, reg}; + EffectiveAddress ea{mode, reg}; bind(opcode, MOVE_TO_SR, ea); } @@ -216,8 +253,8 @@ M68K::M68K() { for(uint3 areg : range(8)) { auto opcode = pattern("0100 1110 0110 ----") | direction << 3 | areg << 0; - Register ra{A0 + areg}; - bind(opcode, MOVE_USP, direction, ra); + AddressRegister ar{areg}; + bind(opcode, MOVE_USP, direction, ar); } //NOP @@ -226,6 +263,18 @@ M68K::M68K() { bind(opcode, NOP); } + //ORI_TO_CCR + { auto opcode = pattern("0000 0000 0011 1100"); + + bind(opcode, ORI_TO_CCR); + } + + //ORI_TO_SR + { auto opcode = pattern("0000 0000 0111 1100"); + + bind(opcode, ORI_TO_SR); + } + //RTS { auto opcode = pattern("0100 1110 0111 0101"); @@ -238,7 +287,7 @@ M68K::M68K() { auto opcode = pattern("0100 1010 ++-- ----") | mode << 3 | reg << 0; if(mode == 7 && reg >= 2) continue; - EA ea{mode, reg}; + EffectiveAddress ea{mode, reg}; bind(opcode | 0 << 6, TST, ea); bind(opcode | 1 << 6, TST, ea); bind(opcode | 2 << 6, TST, ea); diff --git a/higan/processor/m68k/instructions.cpp b/higan/processor/m68k/instructions.cpp index 16ff6603..d8e995f9 100644 --- a/higan/processor/m68k/instructions.cpp +++ b/higan/processor/m68k/instructions.cpp @@ -56,18 +56,18 @@ template auto M68K::negative(uint32 result) -> bool { // -template auto M68K::instructionADD(Register rd, uint1 direction, EA ea) -> void { +template auto M68K::instructionADD(DataRegister dr, uint1 direction, EffectiveAddress ea) -> void { uint32 source; uint32 target; uint32 result; if(direction == 0) { source = read(ea); - target = read(rd); + target = read(dr); result = source + target; - write(rd, result); + write(dr, result); } else { - source = read(rd); + source = read(dr); target = read(ea); result = source + target; write(ea, result); @@ -80,7 +80,7 @@ template auto M68K::instructionADD(Register rd, uint1 direction, EA e r.x = r.c; } -template auto M68K::instructionANDI(EA ea) -> void { +template auto M68K::instructionANDI(EffectiveAddress ea) -> void { auto source = readPC(); auto target = read(ea); auto result = target & source; @@ -92,6 +92,18 @@ template auto M68K::instructionANDI(EA ea) -> void { r.n = negative(result); } +auto M68K::instructionANDI_TO_CCR() -> void { + auto data = readPC(); + writeCCR(readCCR() & data); +} + +auto M68K::instructionANDI_TO_SR() -> void { + if(!supervisor()) return; + + auto data = readPC(); + writeSR(readSR() & data); +} + auto M68K::instructionBCC(uint4 condition, uint8 displacement) -> void { auto extension = readPC(); if(condition == 1) push(r.pc); @@ -100,15 +112,15 @@ auto M68K::instructionBCC(uint4 condition, uint8 displacement) -> void { r.pc += displacement ? sign(displacement) : sign(extension); } -template auto M68K::instructionBTST(Register rd, EA ea) -> void { - auto bit = read(rd); +template auto M68K::instructionBTST(DataRegister dr, EffectiveAddress ea) -> void { + auto bit = read(dr); auto test = read(ea); bit &= bits() - 1; r.z = test.bit(bit) == 0; } -template auto M68K::instructionBTST(EA ea) -> void { +template auto M68K::instructionBTST(EffectiveAddress ea) -> void { auto bit = (uint8)readPC(); auto test = read(ea); bit &= bits() - 1; @@ -116,7 +128,7 @@ template auto M68K::instructionBTST(EA ea) -> void { r.z = test.bit(bit) == 0; } -template auto M68K::instructionCLR(EA ea) -> void { +template auto M68K::instructionCLR(EffectiveAddress ea) -> void { read(ea); write(ea, 0); @@ -126,9 +138,9 @@ template auto M68K::instructionCLR(EA ea) -> void { r.n = 0; } -template auto M68K::instructionCMP(Register rd, EA ea) -> void { +template auto M68K::instructionCMP(DataRegister dr, EffectiveAddress ea) -> void { auto source = read(ea); - auto target = read(rd); + auto target = read(dr); auto result = target - source; r.c = carry(result, source); @@ -137,20 +149,32 @@ template auto M68K::instructionCMP(Register rd, EA ea) -> void { r.n = negative(result); } -auto M68K::instructionDBCC(uint4 condition, Register rd) -> void { +auto M68K::instructionDBCC(uint4 condition, DataRegister dr) -> void { auto displacement = (int16)readPC(); if(!testCondition(condition)) { - uint16 result = read(rd); - write(rd, result - 1); + uint16 result = read(dr); + write(dr, result - 1); if(result) r.pc -= 2, r.pc += displacement; } } -auto M68K::instructionLEA(Register ra, EA ea) -> void { - write(ra, fetch(ea)); +auto M68K::instructionEORI_TO_CCR() -> void { + auto data = readPC(); + writeCCR(readCCR() ^ data); } -template auto M68K::instructionMOVE(EA to, EA from) -> void { +auto M68K::instructionEORI_TO_SR() -> void { + if(!supervisor()) return; + + auto data = readPC(); + writeSR(readSR() ^ data); +} + +auto M68K::instructionLEA(AddressRegister ar, EffectiveAddress ea) -> void { + write(ar, fetch(ea)); +} + +template auto M68K::instructionMOVE(EffectiveAddress to, EffectiveAddress from) -> void { auto data = read(from); write(to, data); @@ -160,28 +184,32 @@ template auto M68K::instructionMOVE(EA to, EA from) -> void { r.n = negative(data); } -template auto M68K::instructionMOVEA(Register ra, EA ea) -> void { +template auto M68K::instructionMOVEA(AddressRegister ar, EffectiveAddress ea) -> void { auto data = read(ea); - if(Size == Word) data = (int16)data; - write(ra, data); + write(ar, data); } -template auto M68K::instructionMOVEM(uint1 direction, EA ea) -> void { +template auto M68K::instructionMOVEM(uint1 direction, EffectiveAddress ea) -> void { auto list = readPC(); auto addr = fetch(ea); - for(uint rn : range(16)) { - if(list.bit(rn)) { - write(Register{rn}, read(addr)); - addr += Size == Long ? 4 : 2; - } + for(uint n : range(8)) { + if(!list.bit(0 + n)) continue; + write(DataRegister{n}, read(addr)); + addr += Size == Long ? 4 : 2; + } + + for(uint n : range(8)) { + if(!list.bit(8 + n)) continue; + write(AddressRegister{n}, read(addr)); + addr += Size == Long ? 4 : 2; } flush(ea, addr); } -auto M68K::instructionMOVEQ(Register rd, uint8 immediate) -> void { - write(rd, immediate); +auto M68K::instructionMOVEQ(DataRegister dr, uint8 immediate) -> void { + write(dr, immediate); r.c = 0; r.v = 0; @@ -189,34 +217,53 @@ auto M68K::instructionMOVEQ(Register rd, uint8 immediate) -> void { r.n = negative(immediate); } -auto M68K::instructionMOVE_FROM_SR(EA ea) -> void { - write(ea, r.sr); +auto M68K::instructionMOVE_FROM_SR(EffectiveAddress ea) -> void { + auto data = readSR(); + write(ea, data); } -auto M68K::instructionMOVE_TO_SR(EA ea) -> void { +auto M68K::instructionMOVE_TO_CCR(EffectiveAddress ea) -> void { + auto data = read(ea); + writeCCR(data); +} + +auto M68K::instructionMOVE_TO_SR(EffectiveAddress ea) -> void { if(!supervisor()) return; - setSR(read(ea)); + auto data = read(ea); + writeSR(data); } -auto M68K::instructionMOVE_USP(uint1 direction, Register ra) -> void { +auto M68K::instructionMOVE_USP(uint1 direction, AddressRegister ar) -> void { if(!supervisor()) return; if(direction == 0) { - r.sp = read(ra); + r.sp = read(ar); } else { - write(ra, r.sp); + write(ar, r.sp); } } auto M68K::instructionNOP() -> void { } +auto M68K::instructionORI_TO_CCR() -> void { + auto data = readPC(); + writeCCR(readCCR() | data); +} + +auto M68K::instructionORI_TO_SR() -> void { + if(!supervisor()) return; + + auto data = readPC(); + writeSR(readSR() | data); +} + auto M68K::instructionRTS() -> void { r.pc = pop(); } -template auto M68K::instructionTST(EA ea) -> void { +template auto M68K::instructionTST(EffectiveAddress ea) -> void { auto data = read(ea); r.c = 0; diff --git a/higan/processor/m68k/m68k.cpp b/higan/processor/m68k/m68k.cpp index df2b94bf..22fa3f12 100644 --- a/higan/processor/m68k/m68k.cpp +++ b/higan/processor/m68k/m68k.cpp @@ -8,7 +8,7 @@ enum : bool { Reverse = 1 }; #include "registers.cpp" #include "memory.cpp" -#include "ea.cpp" +#include "effective-address.cpp" #include "instruction.cpp" #include "instructions.cpp" #include "disassembler.cpp" @@ -19,10 +19,19 @@ auto M68K::power() -> void { auto M68K::reset() -> void { instructionsExecuted = 0; - for(auto& da : r.da) da = 0; + for(auto& dr : r.d) dr = 0; + for(auto& ar : r.a) ar = 0; r.sp = 0; r.pc = 0; - r.sr = 0x2000; + + r.c = 0; + r.v = 0; + r.z = 0; + r.n = 0; + r.x = 0; + r.i = 0; + r.s = 1; + r.t = 0; } auto M68K::supervisor() -> bool { diff --git a/higan/processor/m68k/m68k.hpp b/higan/processor/m68k/m68k.hpp index 9036b852..28dc7fc0 100644 --- a/higan/processor/m68k/m68k.hpp +++ b/higan/processor/m68k/m68k.hpp @@ -8,7 +8,6 @@ struct M68K { enum : bool { User, Supervisor }; enum : uint { Byte, Word, Long }; enum : bool { NoUpdate = 0, Reverse = 1 }; - enum : uint { D0, D1, D2, D3, D4, D5, D6, D7, A0, A1, A2, A3, A4, A5, A6, A7 }; enum : uint { DataRegisterDirect, @@ -36,15 +35,24 @@ struct M68K { auto supervisor() -> bool; //registers.cpp - struct Register { - explicit Register(uint number_) : number(number_) {} - - uint4 number; + struct DataRegister { + explicit DataRegister(uint number_) : number(number_) {} + uint3 number; }; + template auto read(DataRegister reg) -> uint32; + template auto write(DataRegister reg, uint32 data) -> void; - template auto read(Register reg) -> uint32; - template auto write(Register reg, uint32 value) -> void; - auto setSR(uint16 sr) -> void; + struct AddressRegister { + explicit AddressRegister(uint number_) : number(number_) {} + uint3 number; + }; + template auto read(AddressRegister reg) -> uint32; + template auto write(AddressRegister reg, uint32 data) -> void; + + auto readCCR() -> uint8; + auto readSR() -> uint16; + auto writeCCR(uint8 ccr) -> void; + auto writeSR(uint16 sr) -> void; //memory.cpp template auto read(uint32 addr) -> uint32; @@ -53,24 +61,23 @@ struct M68K { template auto pop() -> uint32; template auto push(uint32 data) -> void; - //ea.cpp - struct EA { - explicit EA(uint mode_, uint reg_) : mode(mode_), reg(reg_) { - if(mode == 7) mode += reg.number; //optimization: convert modes {7; 0-4} to {8-11} - if(mode != 0) reg.number += 8; //optimization: linear index to all registers: d0-d7; a0-a7 + //effective-address.cpp + struct EffectiveAddress { + explicit EffectiveAddress(uint mode_, uint reg_) : mode(mode_), reg(reg_) { + if(mode == 7) mode += reg; //optimization: convert modes {7; 0-4} to {8-11} } uint4 mode; - Register reg; + uint3 reg; boolean valid; uint32 address; }; - template auto fetch(EA& ea) -> uint32; - template auto read(EA& ea) -> uint32; - template auto write(EA& ea, uint32 data) -> void; - template auto flush(EA& ea, uint32 data) -> void; + template auto fetch(EffectiveAddress& ea) -> uint32; + template auto read(EffectiveAddress& ea) -> uint32; + template auto write(EffectiveAddress& ea, uint32 data) -> void; + template auto flush(EffectiveAddress& ea, uint32 data) -> void; //instruction.cpp auto trap() -> void; @@ -89,48 +96,51 @@ struct M68K { template auto zero(uint32 result) -> bool; template auto negative(uint32 result) -> bool; - template auto instructionADD(Register rd, uint1 direction, EA ea) -> void; - template auto instructionANDI(EA ea) -> void; + template auto instructionADD(DataRegister dr, uint1 direction, EffectiveAddress ea) -> void; + template auto instructionANDI(EffectiveAddress ea) -> void; + auto instructionANDI_TO_CCR() -> void; + auto instructionANDI_TO_SR() -> void; auto instructionBCC(uint4 condition, uint8 displacement) -> void; - template auto instructionBTST(Register rd, EA ea) -> void; - template auto instructionBTST(EA ea) -> void; - template auto instructionCLR(EA ea) -> void; - template auto instructionCMP(Register rd, EA ea) -> void; - auto instructionDBCC(uint4 condition, Register rd) -> void; - auto instructionLEA(Register ra, EA ea) -> void; - template auto instructionMOVE(EA to, EA from) -> void; - template auto instructionMOVEA(Register ra, EA ea) -> void; - template auto instructionMOVEM(uint1 direction, EA ea) -> void; - auto instructionMOVEQ(Register rd, uint8 immediate) -> void; - auto instructionMOVE_FROM_SR(EA ea) -> void; - auto instructionMOVE_TO_SR(EA ea) -> void; - auto instructionMOVE_USP(uint1 direction, Register ra) -> void; + template auto instructionBTST(DataRegister dr, EffectiveAddress ea) -> void; + template auto instructionBTST(EffectiveAddress ea) -> void; + template auto instructionCLR(EffectiveAddress ea) -> void; + template auto instructionCMP(DataRegister dr, EffectiveAddress ea) -> void; + auto instructionDBCC(uint4 condition, DataRegister dr) -> void; + auto instructionEORI_TO_CCR() -> void; + auto instructionEORI_TO_SR() -> void; + auto instructionLEA(AddressRegister ar, EffectiveAddress ea) -> void; + template auto instructionMOVE(EffectiveAddress to, EffectiveAddress from) -> void; + template auto instructionMOVEA(AddressRegister ar, EffectiveAddress ea) -> void; + template auto instructionMOVEM(uint1 direction, EffectiveAddress ea) -> void; + auto instructionMOVEQ(DataRegister dr, uint8 immediate) -> void; + auto instructionMOVE_FROM_SR(EffectiveAddress ea) -> void; + auto instructionMOVE_TO_CCR(EffectiveAddress ea) -> void; + auto instructionMOVE_TO_SR(EffectiveAddress ea) -> void; + auto instructionMOVE_USP(uint1 direction, AddressRegister ar) -> void; auto instructionNOP() -> void; + auto instructionORI_TO_CCR() -> void; + auto instructionORI_TO_SR() -> void; auto instructionRTS() -> void; - template auto instructionTST(EA ea) -> void; + template auto instructionTST(EffectiveAddress ea) -> void; //disassembler.cpp auto disassemble(uint32 pc) -> string; auto disassembleRegisters() -> string; struct Registers { - uint32 da[16]; //a7 = primary stack pointer - uint32 sp; //sp = secondary stack pointer + uint32 d[8]; + uint32 a[8]; + uint32 sp; uint32 pc; - union { - uint16 sr; - BooleanBitField c; //carry - BooleanBitField v; //overflow - BooleanBitField z; //zero - BooleanBitField n; //negative - BooleanBitField x; //extend - NaturalBitField i; //interrupt mask - BooleanBitField s; //supervisor mode - BooleanBitField t; //trace mode - }; - - Registers() : sr(0) {} + bool c; //carry + bool v; //overflow + bool z; //zero + bool n; //negative + bool x; //extend + uint3 i; //interrupt mask + bool s; //supervisor mode + bool t; //trace mode } r; uint16 opcode = 0; @@ -140,33 +150,41 @@ struct M68K { private: //disassembler.cpp - template auto disassembleADD(Register rd, uint1 direction, EA ea) -> string; - template auto disassembleANDI(EA ea) -> string; + template auto disassembleADD(DataRegister dr, uint1 direction, EffectiveAddress ea) -> string; + template auto disassembleANDI(EffectiveAddress ea) -> string; + auto disassembleANDI_TO_CCR() -> string; + auto disassembleANDI_TO_SR() -> string; auto disassembleBCC(uint4 condition, uint8 displacement) -> string; - template auto disassembleBTST(Register rd, EA ea) -> string; - template auto disassembleBTST(EA ea) -> string; - template auto disassembleCLR(EA ea) -> string; - template auto disassembleCMP(Register rd, EA ea) -> string; - auto disassembleDBCC(uint4 condition, Register rd) -> string; - auto disassembleLEA(Register ra, EA ea) -> string; - template auto disassembleMOVE(EA to, EA from) -> string; - template auto disassembleMOVEA(Register ra, EA ea) -> string; - template auto disassembleMOVEM(uint1 direction, EA ea) -> string; - auto disassembleMOVEQ(Register rd, uint8 immediate) -> string; - auto disassembleMOVE_FROM_SR(EA ea) -> string; - auto disassembleMOVE_TO_SR(EA ea) -> string; - auto disassembleMOVE_USP(uint1 direction, Register ra) -> string; + template auto disassembleBTST(DataRegister dr, EffectiveAddress ea) -> string; + template auto disassembleBTST(EffectiveAddress ea) -> string; + template auto disassembleCLR(EffectiveAddress ea) -> string; + template auto disassembleCMP(DataRegister dr, EffectiveAddress ea) -> string; + auto disassembleDBCC(uint4 condition, DataRegister dr) -> string; + auto disassembleEORI_TO_CCR() -> string; + auto disassembleEORI_TO_SR() -> string; + auto disassembleLEA(AddressRegister ar, EffectiveAddress ea) -> string; + template auto disassembleMOVE(EffectiveAddress to, EffectiveAddress from) -> string; + template auto disassembleMOVEA(AddressRegister ar, EffectiveAddress ea) -> string; + template auto disassembleMOVEM(uint1 direction, EffectiveAddress ea) -> string; + auto disassembleMOVEQ(DataRegister dr, uint8 immediate) -> string; + auto disassembleMOVE_FROM_SR(EffectiveAddress ea) -> string; + auto disassembleMOVE_TO_CCR(EffectiveAddress ea) -> string; + auto disassembleMOVE_TO_SR(EffectiveAddress ea) -> string; + auto disassembleMOVE_USP(uint1 direction, AddressRegister ar) -> string; auto disassembleNOP() -> string; + auto disassembleORI_TO_CCR() -> string; + auto disassembleORI_TO_SR() -> string; auto disassembleRTS() -> string; - template auto disassembleTST(EA ea) -> string; + template auto disassembleTST(EffectiveAddress ea) -> string; template auto _read(uint32 addr) -> uint32; template auto _readPC() -> uint32; - auto _register(Register r) -> string; + auto _register(DataRegister dr) -> string; + auto _register(AddressRegister ar) -> string; template auto _immediate() -> string; - template auto _address(EA ea) -> string; - template auto _read(EA ea) -> string; - template auto _write(EA ea) -> string; + template auto _address(EffectiveAddress& ea) -> string; + template auto _read(EffectiveAddress& ea) -> string; + template auto _write(EffectiveAddress& ea) -> string; auto _branch(uint8 displacement) -> string; template auto _suffix() -> string; auto _condition(uint4 condition) -> string; diff --git a/higan/processor/m68k/memory.cpp b/higan/processor/m68k/memory.cpp index 7d2bc58b..f02c66af 100644 --- a/higan/processor/m68k/memory.cpp +++ b/higan/processor/m68k/memory.cpp @@ -80,12 +80,12 @@ template<> auto M68K::readPC() -> uint32 { // template auto M68K::pop() -> uint32 { - auto data = read((uint32)r.da[A7]); - r.da[A7] += Size == Long ? 4 : 2; + auto data = read((uint32)r.a[7]); + r.a[7] += Size == Long ? 4 : 2; return data; } template auto M68K::push(uint32 data) -> void { - r.da[A7] -= Size == Long ? 4 : 2; - return write((uint32)r.da[A7], data); + r.a[7] -= Size == Long ? 4 : 2; + return write((uint32)r.a[7], data); } diff --git a/higan/processor/m68k/registers.cpp b/higan/processor/m68k/registers.cpp index 7e76b248..015a9c25 100644 --- a/higan/processor/m68k/registers.cpp +++ b/higan/processor/m68k/registers.cpp @@ -1,13 +1,48 @@ -template auto M68K::read(Register reg) -> uint32 { - return clip(r.da[reg.number]); +template auto M68K::read(DataRegister reg) -> uint32 { + return clip(r.d[reg.number]); } -template auto M68K::write(Register reg, uint32 data) -> void { - r.da[reg.number] = (r.da[reg.number] & ~mask()) | (data & mask()); +template auto M68K::write(DataRegister reg, uint32 data) -> void { + r.d[reg.number] = (r.d[reg.number] & ~mask()) | (data & mask()); } -auto M68K::setSR(uint16 sr) -> void { +// + +template auto M68K::read(AddressRegister reg) -> uint32 { + return sign(r.a[reg.number]); +} + +template auto M68K::write(AddressRegister reg, uint32 data) -> void { + r.a[reg.number] = sign(data); +} + +// + +//CCR,SR unused bits cannot be set; always read out as 0 + +auto M68K::readCCR() -> uint8 { + return r.c << 0 | r.v << 1 | r.z << 2 | r.n << 3 | r.x << 4; +} + +auto M68K::readSR() -> uint16 { + return readCCR() << 0 | r.i << 8 | r.s << 13 | r.t << 15; +} + +auto M68K::writeCCR(uint8 ccr) -> void { + r.c = ccr.bit(0); + r.v = ccr.bit(1); + r.z = ccr.bit(2); + r.n = ccr.bit(3); + r.x = ccr.bit(4); +} + +auto M68K::writeSR(uint16 sr) -> void { + writeCCR(sr); + //when entering or exiting supervisor mode; swap SSP and USP into A7 - if(r.sr.bit(13) != sr.bit(13)) swap(r.da[A7], r.sp); - r.sr = sr; + if(r.s != sr.bit(13)) swap(r.a[7], r.sp); + + r.i = sr.bits(8,10); + r.s = sr.bit(13); + r.t = sr.bit(15); }