From 7ccfbe0206b60fdfa10467c8769709de809b6ee3 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sat, 23 Jul 2016 12:32:35 +1000 Subject: [PATCH] Update to v100r11 release. byuu says: I split the Register class and read/write handlers into DataRegister and AddressRegister, given that they have different behaviors on byte/word accesses (data tends to preserve the upper bits; address tends to sign-extend things.) I expanded EA to EffectiveAddress. No sense in abbreviating things to death. I've now implemented 26 instructions. But the new ones are just all the stupid from/to ccr/sr instructions. Ryphecha confirmed that you can't set the undefined bits, so I don't think the BitField concept is appropriate for the CCR/SR. Instead, I'm just storing direct flags and have (read,write)(CCR,SR) instead. This isn't like the 65816 where you have subroutines that push and pop the flag register. It's much more common to access individual flags. Doesn't match the consistency angle of the other CPU cores, but ... I think this is the right thing to for the 68K specifically. --- higan/emulator/emulator.hpp | 2 +- higan/md/cpu/cpu.cpp | 4 +- higan/processor/m68k/disassembler.cpp | 123 ++++++++------ .../m68k/{ea.cpp => effective-address.cpp} | 46 +++--- higan/processor/m68k/instruction.cpp | 127 +++++++++----- higan/processor/m68k/instructions.cpp | 119 +++++++++---- higan/processor/m68k/m68k.cpp | 15 +- higan/processor/m68k/m68k.hpp | 156 ++++++++++-------- higan/processor/m68k/memory.cpp | 8 +- higan/processor/m68k/registers.cpp | 49 +++++- 10 files changed, 421 insertions(+), 228 deletions(-) rename higan/processor/m68k/{ea.cpp => effective-address.cpp} (68%) 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); }