From be3f6ac0d5e866fe1cb8cb6849266c0741fe19ca Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Tue, 19 Jul 2016 19:12:05 +1000 Subject: [PATCH] Update to v100r09 release. byuu says: Another six hours in ... I have all of the opcodes, memory access functions, disassembler mnemonics and table building converted over to the new template format. Certainly, it would be quite easy for this nightmare chip to throw me another curveball, but so far I can handle: - MOVE (EA to, EA from) case - read(from) has to update register index for +/-(aN) mode - MOVEM (EA from) case - when using +/-(aN), RA can't actually be updated until the transfer is completed - LEA (EA from) case - doesn't actually perform the final read; just returns the address to be read from - ANDI (EA from-and-to) case - same EA has to be read from and written to - for -(aN), the read has to come from aN-2, but can't update aN yet; so that the write also goes to aN-2 - no opcode can ever fetch the extension words more than once - manually control the order of extension word fetching order for proper opcode decoding To do all of that without a whole lot of duplicated code (or really bloating out every single instruction with red tape), I had to bring back the "bool valid / uint32 address" variables inside the EA struct =( If weird exceptions creep in like timing constraints only on certain opcodes, I can use template flags to the EA read/write functions to handle that. --- higan/emulator/emulator.hpp | 2 +- higan/md/cpu/cpu.cpp | 4 +- higan/processor/m68k/disassembler.cpp | 136 ++++---- higan/processor/m68k/ea.cpp | 464 +++++++------------------- higan/processor/m68k/instruction.cpp | 283 +++++++--------- higan/processor/m68k/instructions.cpp | 109 +++--- higan/processor/m68k/m68k.cpp | 3 +- higan/processor/m68k/m68k.hpp | 106 +++--- higan/processor/m68k/memory.cpp | 62 ++-- higan/processor/m68k/registers.cpp | 56 ++-- 10 files changed, 480 insertions(+), 745 deletions(-) diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 6c792040..b427d189 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.08"; + static const string Version = "100.09"; 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 f030a2b7..72d86add 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.ssp = readAbsolute(Long, 0); - r.pc = readAbsolute(Long, 4); + r.ssp = 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 ed133c21..410e119a 100644 --- a/higan/processor/m68k/disassembler.cpp +++ b/higan/processor/m68k/disassembler.cpp @@ -1,68 +1,53 @@ -auto M68K::_readByte(uint32 addr) -> uint8 { +template<> auto M68K::_read(uint32 addr) -> uint32 { return read(0, addr); } -auto M68K::_readWord(uint32 addr) -> uint16 { +template<> auto M68K::_read(uint32 addr) -> uint32 { return read(1, addr); } -auto M68K::_readLong(uint32 addr) -> uint32 { - uint32 data = _readWord(addr + 0) << 16; - return data |= _readWord(addr + 2) << 0; +template<> auto M68K::_read(uint32 addr) -> uint32 { + uint32 data = _read(addr + 0) << 16; + return data | _read(addr + 2) << 0; } -auto M68K::_readPC(uint2 size) -> uint32 { - uint32 data = _readWord(_pc); - _pc += 2; - if(size == Byte) return (uint8)data; - if(size == Word) return data; - data = (data << 16) | _readWord(_pc); - _pc += 2; - return data; +template auto M68K::_readPC() -> uint32 { + auto data = _read(_pc); + _pc += Size == Long ? 4 : 2; + return clip(data); } -auto M68K::_immediate(uint2 size) -> string { - if(size == Byte) return {"#$", hex(_readPC(Byte), 2L)}; - if(size == Word) return {"#$", hex(_readPC(Word), 4L)}; - if(size == Long) return {"#$", hex(_readPC(Long), 8L)}; - return "#???"; +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::_address(uint8 ea) -> string { - uint3 mode = ea >> 5; - uint3 reg = ea >> 2; - uint2 size = ea >> 0; +template auto M68K::_immediate() -> string { + return {"#$", hex(_readPC(), 2 << Size)}; +} - if(mode == 7) { - if(reg == 2) return {"$", hex(_pc + (int16)_readPC(Word), 6L)}; - } +template auto M68K::_address(EA ea) -> string { + if(ea.mode == 9) return {"$", hex(_pc + (int16)_readPC(), 6L)}; return "???"; } -auto M68K::_read(uint8 ea) -> string { - uint3 mode = ea >> 5; - uint3 reg = ea >> 2; - uint2 size = ea >> 0; - - if(mode == 0) return {"d", reg}; - if(mode == 1) return {"a", reg}; - if(mode == 2) return {"(a", reg, ")"}; - if(mode == 3) return {"(a", reg, ")+"}; - if(mode == 4) return {"-(a", reg, ")"}; - if(mode == 5) return {"($", hex(r.a(reg) + (int16)_readPC(Word), 6L), ")"}; - if(mode == 7) { - if(reg == 1) return {"($", hex(_readPC(Long), 6L), ")"}; - if(reg == 4) { - if(size == Byte) return {"#$", hex(_readPC(Byte), 2L)}; - if(size == Word) return {"#$", hex(_readPC(Word), 4L)}; - if(size == Long) return {"#$", hex(_readPC(Long), 8L)}; - } - } +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), ")"}; + if(ea.mode == 8) return {"($", hex(_readPC(), 6L), ")"}; + if(ea.mode == 11) return {"#$", hex(_readPC(), 2 << Size)}; return "???"; } -auto M68K::_write(uint8 ea) -> string { - return _read(ea); +template auto M68K::_write(EA ea) -> string { + return _read(ea); } auto M68K::_branch(uint8 displacement) -> string { @@ -72,11 +57,8 @@ auto M68K::_branch(uint8 displacement) -> string { return {"$", hex(_pc + displacement, 6L)}; } -auto M68K::_suffix(uint2 size) -> string { - if(size == Byte) return ".b"; - if(size == Word) return ".w"; - if(size == Long) return ".l"; - return ".?"; +template auto M68K::_suffix() -> string { + return Size == Byte ? ".b" : Size == Word ? ".w" : ".l"; } auto M68K::_condition(uint4 condition) -> string { @@ -111,64 +93,60 @@ auto M68K::disassembleRegisters() -> string { // -template auto M68K::disassembleADD(uint3 reg, uint1 direction, EA ea) -> string { - string op{"add", _suffix(ea.reg), " "}; -return op; +template auto M68K::disassembleADD(Register rd, uint1 direction, EA ea) -> string { + string op{"add", _suffix(), " "}; if(direction == 0) { -// return {op, _read(ea), ",d", reg}; + return {op, _read(ea), ",", _register(rd)}; } else { -// return {op, "d", reg, ",", _read(ea)}; + return {op, "", _register(rd), ",", _read(ea)}; } } -auto M68K::disassembleANDI(uint8 ea) -> string { - return {"andi", _suffix(ea), " ", _immediate(ea), ",", _read(ea)}; +template auto M68K::disassembleANDI(EA ea) -> string { + return {"andi", _suffix(), " ", _immediate(), ",", _read(ea)}; } auto M68K::disassembleBCC(uint4 condition, uint8 displacement) -> string { return {"b", _condition(condition), " ", _branch(displacement)}; } -auto M68K::disassembleLEA(uint3 to, uint8 ea) -> string { - return {"lea ", _address(ea), ",a", to}; +auto M68K::disassembleLEA(Register ra, EA ea) -> string { + return {"lea ", _address(ea), ",", _register(ra)}; } -auto M68K::disassembleMOVE(uint8 to, uint8 from) -> string { - return {"move", _suffix(from), " ", _read(from), ",", _write(to)}; +template auto M68K::disassembleMOVE(EA to, EA from) -> string { + return {"move", _suffix(), " ", _read(from), ",", _write(to)}; } -auto M68K::disassembleMOVEA(uint3 to, uint8 from) -> string { - return {"movea ", _read(from), ",a", to}; +template auto M68K::disassembleMOVEA(Register ra, EA ea) -> string { + return {"movea ", _read(ea), ",", _register(ra)}; } -auto M68K::disassembleMOVEM(uint1 direction, uint8 ea) -> string { - string op{"movem", _suffix(ea), " "}; +template auto M68K::disassembleMOVEM(uint1 direction, EA ea) -> string { + string op{"movem", _suffix(), " "}; uint16 list = _readPC(); string regs; - for(auto n : range(8)) if(list.bit(0 + n)) regs.append("d", n, ","); - regs.trimRight(","); - if(regs && list >> 8) regs.append("/"); - for(auto n : range(8)) if(list.bit(8 + n)) regs.append("a", n, ","); + for(uint rn : range(16)) if(list.bit(rn)) regs.append(_register(Register{rn}), ","); regs.trimRight(","); if(direction == 0) { - return {op, regs, ",", _read(ea)}; + return {op, regs, ",", _read(ea)}; } else { - return {op, _read(ea), ",", regs}; + return {op, _read(ea), ",", regs}; } } -auto M68K::disassembleMOVEQ(uint3 target, uint8 immediate) -> string { - return {"moveq #$", hex(immediate, 2L), ",d", target}; +auto M68K::disassembleMOVEQ(Register rd, uint8 immediate) -> string { + return {"moveq #$", hex(immediate, 2L), ",", _register(rd)}; } -auto M68K::disassembleMOVE_USP(uint1 direction, uint3 reg) -> string { +auto M68K::disassembleMOVE_USP(uint1 direction, Register ra) -> string { if(direction == 0) { - return {"move a", reg, ",usp"}; + return {"move ", _register(ra), ",usp"}; } else { - return {"move usp,a", reg}; + return {"move usp,", _register(ra)}; } } @@ -176,6 +154,6 @@ auto M68K::disassembleNOP() -> string { return {"nop "}; } -auto M68K::disassembleTST(uint8 ea) -> string { - return {"tst", _suffix(ea), " ", _read(ea)}; +template auto M68K::disassembleTST(EA ea) -> string { + return {"tst", _suffix(), " ", _read(ea)}; } diff --git a/higan/processor/m68k/ea.cpp b/higan/processor/m68k/ea.cpp index c34a0954..5cc2872a 100644 --- a/higan/processor/m68k/ea.cpp +++ b/higan/processor/m68k/ea.cpp @@ -1,423 +1,203 @@ -//effective addressing +template auto M68K::fetch(EA& ea) -> uint32 { + ea.valid = true; -//encoding: -// d7-d5: mode -// d4-d2: register -// d1-d0: size (0 = byte, 1 = word, 2 = long) + switch(ea.mode) { -auto M68K::address(uint8 ea) -> uint32 { - switch(ea) { - - //data register direct - case 0b000'000'00 ... 0b000'111'11: - return r.d(ea >> 2); - - //address register direct - case 0b001'000'00 ... 0b001'111'11: - return r.a(ea >> 2); - - //address register indirect - case 0b010'000'00 ... 0b010'111'11: - return r.a(ea >> 2); - - //address register indirect with post-increment - case 0b011'000'00 ... 0b011'111'11: - return r.a(ea >> 2); - - //address register indirect with pre-decrement - case 0b100'000'00 ... 0b100'111'11: - return r.a(ea >> 2); - - //address register indirect with displacement - case 0b101'000'00 ... 0b101'111'11: - return r.a(ea >> 2) + (int16)readPC(); - - //address register indirect with index - case 0b110'000'00 ... 0b110'111'11: { - auto word = readPC(); - auto index = word & 0x8000 ? r.a(word >> 12) : r.d(word >> 12); - if(word & 0x800) index = (int16)index; - return r.a(ea >> 2) + index + (int8)word; + case 0: { //data register direct + return read(ea.reg); } - //absolute short indirect - case 0b111'000'00 ... 0b111'000'11: + case 1: { //data register indirect + return read(ea.reg); + } + + case 2: { //address register indirect + return read(ea.reg); + } + + case 3: { //address register indirect with post-increment + return read(ea.reg); + } + + case 4: { //address register indirect with pre-decrement + return read(ea.reg); + } + + case 5: { //address register indirect with displacement + return read(ea.reg) + (int16)readPC(); + } + + case 6: { //address register indirect with index + auto extension = readPC(); + auto index = read(Register{extension >> 12}); + if(extension & 0x800) index = (int16)index; + return read(ea.reg) + index + (int8)extension; + } + + case 7: { //absolute short indirect return (int16)readPC(); - - //absolute long indirect - case 0b111'001'00 ... 0b111'001'11: { - uint32 address = readPC() << 16; - return address | readPC() << 0; } - //program counter indirect with displacement - case 0b111'010'00 ... 0b111'010'11: { + case 8: { //absolute long indirect + return readPC(); + } + + case 9: { //program counter indirect with displacement auto base = r.pc; return base + (int16)readPC(); } - //program counter indirect with index - case 0b111'011'00 ... 0b111'011'11: { + case 10: { //program counter indirect with index auto base = r.pc; - auto word = readPC(); - auto index = word & 0x8000 ? r.a(word >> 12) : r.d(word >> 12); - if(word & 0x800) index = (int16)index; - return base + index + (int8)word; + auto extension = readPC(); + auto index = read(Register{extension >> 12}); + if(extension & 0x800) index = (int16)index; + return base + index + (int8)extension; } - //immediate byte - case 0b111'100'00: - return (uint8)readPC(); - - //immediate word - case 0b111'100'01: - return readPC(); - - //immediate long - case 0b111'100'10: { - uint32 address = readPC() << 16; - return address | readPC() << 0; + case 11: { //immediate + return readPC(); } - //invalid - default: - return 0; - } + + return 0; } -template auto M68K::read(EA ea) -> uint32 { +template auto M68K::read(EA& ea) -> uint32 { + if(!ea.valid) ea.address = fetch(ea); + switch(ea.mode) { case 0: { //data register direct - return clip(r.d(ea.reg)); + return clip(ea.address); } case 1: { //address register direct - return clip(r.a(ea.reg)); + return clip(ea.address); } case 2: { //address register indirect - auto& address = r.a(ea.reg); - return read(address); + return read(ea.address); } case 3: { //address register indirect with post-increment - auto& address = r.a(ea.reg); - auto data = read(address); - address += Size == Long ? 4 : 2; + auto data = read(ea.address); + if(Update) write(ea.reg, ea.address += (Size == Long ? 4 : 2)); return data; } case 4: { //address register indirect with pre-decrement - auto& address = r.a(ea.reg); - address -= Size == Long ? 4 : 2; - return read(address); - } - - } -} - -template auto M68K::write(EA ea, uint32 data) -> void { - switch(ea.mode) { - - case 0: { //data register direct - r.d(ea.reg) = data; - return; - } - - case 1: { //address register direct - r.a(ea.reg) = data; - return; - } - - } -} - -auto M68K::read(uint8 ea) -> uint32 { - switch(ea) { - - //data register direct - case 0b000'000'00 ... 0b000'111'11: - return r.d(ea >> 2); - - //address register direct - case 0b001'000'00 ... 0b001'111'11: - return r.a(ea >> 2); - - //address register indirect - case 0b010'000'00 ... 0b010'111'11: { - auto address = r.a(ea >> 2); - return readAbsolute(ea, address); - } - - //address register indirect with post-increment - case 0b011'000'00 ... 0b011'111'11: { - auto& address = r.a(ea >> 2); - auto data = readAbsolute(ea, address); - address += 2 + (ea & 2); + auto data = read((uint32)(ea.address - (Size == Long ? 4 : 2))); + if(Update) write(ea.reg, ea.address -= (Size == Long ? 4 : 2)); return data; } - //address register indirect with pre-decrement - case 0b100'000'00 ... 0b100'111'11: { - auto& address = r.a(ea >> 2); - address -= 2 + (ea & 2); - return readAbsolute(ea, address); + case 5: { //address register indirect with displacement + return read(ea.address); } - //address register indirect with displacement - case 0b101'000'00 ... 0b101'111'11: - return readAbsolute(ea, r.a(ea >> 2) + (int16)readPC()); - - //address register indirect with index - case 0b110'000'00 ... 0b110'111'11: { - auto word = readPC(); - auto index = word & 0x8000 ? r.a(word >> 12) : r.d(word >> 12); - if(word & 0x800) index = (int16)index; - return readAbsolute(ea, r.a(ea >> 2) + index + (int8)word); + case 6: { //address register indirect with index + return read(ea.address); } - //absolute short indirect - case 0b111'000'00 ... 0b111'000'11: - return readAbsolute(ea, (int16)readPC()); - - //absolute long indirect - case 0b111'001'00 ... 0b111'001'11: { - uint32 address = readPC() << 16; - return readAbsolute(ea, address | readPC()); + case 7: { //absolute short indirect + return read(ea.address); } - //program counter indirect with displacement - case 0b111'010'00 ... 0b111'010'11: { - auto base = r.pc; - return readAbsolute(ea, base + (int16)readPC()); + case 8: { //absolute long indirect + return read(ea.address); } - //program counter indirect with index - case 0b111'011'00 ... 0b111'011'11: { - auto base = r.pc; - auto word = readPC(); - auto index = word & 0x8000 ? r.a(word >> 12) : r.d(word >> 12); - if(word & 0x800) index = (int16)index; - return readAbsolute(ea, base + index + (int8)word); + case 9: { //program counter indirect with displacement + return read(ea.address); } - //immediate byte - case 0b111'100'00: - return (uint8)readPC(); - - //immediate word - case 0b111'100'01: - return readPC(); - - //immediate long - case 0b111'100'10: { - uint32 address = readPC() << 16; - return address | readPC() << 0; + case 10: { //program counter indirect with index + return read(ea.address); } - //invalid - default: - return 0; + case 11: { //immediate + return clip(ea.address); + } } + + return 0; } -auto M68K::write(uint8 ea, uint32 data) -> void { - switch(ea) { +template auto M68K::write(EA& ea, uint32 data) -> void { + if(!ea.valid) ea.address = fetch(ea); - //data register direct - case 0b000'000'00 ... 0b000'111'11: - r.d(ea >> 2) = data; - return; + switch(ea.mode) { - //address register direct - case 0b001'000'00 ... 0b001'111'11: - r.a(ea >> 2) = data; - return; - - //address register indirect - case 0b010'000'00 ... 0b010'111'11: { - auto address = r.a(ea >> 2); - return writeAbsolute(ea, address, data); + case 0: { //data register direct + return write(ea.reg, data); } - //address register indirect with post-increment - case 0b011'000'00 ... 0b011'111'11: { - auto& address = r.a(ea >> 2); - writeAbsolute(ea, address, data); - address += 2 + (ea & 2); + case 1: { //address register direct + return write(ea.reg, data); + } + + case 2: { //address register indirect + return write(ea.address, data); + } + + case 3: { //address register indirect with post-increment + write(ea.address, data); + if(Update) write(ea.reg, ea.address += (Size == Long ? 4 : 2)); return; } - //address register indirect with pre-decrement - case 0b100'000'00 ... 0b100'111'11: { - auto& address = r.a(ea >> 2); - address -= 2 + (ea & 2); - return writeAbsolute(ea, address, data); + case 4: { //address register indirect with pre-decrement + write((uint32)(ea.address - (Size == Long ? 4 : 2)), data); + if(Update) write(ea.reg, ea.address -= (Size == Long ? 4 : 2)); + return; } - //address register indirect with displacement - case 0b101'000'00 ... 0b101'111'11: - return writeAbsolute(ea, r.a(ea >> 2) + (int16)readPC(), data); - - //address register indirect with index - case 0b110'000'00 ... 0b110'111'11: { - auto word = readPC(); - auto index = word & 0x8000 ? r.a(word >> 12) : r.d(word >> 12); - if(word & 0x800) index = (int16)index; - return writeAbsolute(ea, r.a(ea >> 2) + index + (int8)word, data); + case 5: { //address register indirect with displacement + return write(ea.address, data); } - //absolute short indirect - case 0b111'000'00 ... 0b111'000'11: - return writeAbsolute(ea, (int16)readPC(), data); - - //absolute long indirect - case 0b111'001'00 ... 0b111'001'11: { - uint32 address = readPC() << 16; - return writeAbsolute(ea, address | readPC(), data); + case 6: { //address register indirect with index + return write(ea.address, data); } - //program counter indirect with displacement - case 0b111'010'00 ... 0b111'010'11: { - auto base = r.pc; - return writeAbsolute(ea, base + (int16)readPC(), data); + case 7: { //absolute short indirect + return write(ea.address, data); } - //program counter indirect with index - case 0b111'011'00 ... 0b111'011'11: { - auto base = r.pc; - auto word = readPC(); - auto index = word & 0x8000 ? r.a(word >> 12) : r.d(word >> 12); - if(word & 0x800) index = (int16)index; - return writeAbsolute(ea, base + index + (int8)word, data); + case 8: { //absolute long indirect + return write(ea.address, data); + } + + case 9: { //program counter indirect with displacement + return write(ea.address, data); + } + + case 10: { //program counter indirect with index + return write(ea.address, data); + } + + case 11: { //immediate + return; } } } -auto M68K::modify(uint8 ea, uint32 data, const function& op) -> uint32 { - switch(ea) { +template auto M68K::flush(EA& ea, uint32 data) -> void { + switch(ea.mode) { - //data register direct - case 0b000'000'00 ... 0b000'111'11: { - auto& address = r.d(ea >> 2); - return address = op(address, data); + case 3: { //address register indirect with post-increment + write(ea.reg, data); + return; } - //address register direct - case 0b001'000'00 ... 0b001'111'11: { - auto& address = r.a(ea >> 2); - return address = op(address, data); - } - - //address register indirect - case 0b010'000'00 ... 0b010'111'11: { - auto address = r.a(ea >> 2); - auto memory = readAbsolute(ea, address); - writeAbsolute(ea, address, memory = op(memory, data)); - return memory; - } - - //address register indirect with post-increment - case 0b011'000'00 ... 0b011'111'11: { - auto& address = r.a(ea >> 2); - auto memory = readAbsolute(ea, address); - writeAbsolute(ea, address, memory = op(memory, data)); - address += 2 + (ea & 2); - return memory; - } - - //address register indirect with pre-decrement - case 0b100'000'00 ... 0b100'111'11: { - auto& address = r.a(ea >> 2); - address -= 2 + (ea & 2); - auto memory = readAbsolute(ea, address); - writeAbsolute(ea, address, memory = op(memory, data)); - return memory; - } - - //address register indirect with displacement - case 0b101'000'00 ... 0b101'111'11: { - auto address = r.a(ea >> 2) + (int16)readPC(); - auto memory = readAbsolute(ea, address); - writeAbsolute(ea, address, memory = op(memory, data)); - return memory; - } - - //address register indirect with index - case 0b110'000'00 ... 0b110'111'11: { - auto word = readPC(); - auto index = word & 0x8000 ? r.a(word >> 12) : r.d(word >> 12); - if(word & 0x800) index = (int16)index; - auto address = r.a(ea >> 2) + index + (int8)word; - auto memory = readAbsolute(ea, address); - writeAbsolute(ea, address, memory = op(memory, data)); - return memory; - } - - //absolute short indirect - case 0b111'000'00 ... 0b111'000'11: { - auto address = (int16)readPC(); - auto memory = readAbsolute(ea, address); - writeAbsolute(ea, address, memory = op(memory, data)); - return memory; - } - - //absolute long indirect - case 0b111'001'00 ... 0b111'001'11: { - auto word = readPC(); - uint32 address = word << 16 | readPC(); - auto memory = readAbsolute(ea, address); - writeAbsolute(ea, address, memory = op(memory, data)); - return memory; - } - - //program counter indirect with displacement - case 0b111'010'00 ... 0b111'010'11: { - auto address = r.pc; - address += (int16)readPC(); - auto memory = readAbsolute(ea, address); - writeAbsolute(ea, address, memory = op(memory, data)); - return memory; - } - - //program counter indirect with index - case 0b111'011'00 ... 0b111'011'11: { - auto address = r.pc; - auto word = readPC(); - auto index = word & 0x8000 ? r.a(word >> 12) : r.d(word >> 12); - if(word & 0x8000) index = (int16)index; - address += index + (int8)word; - auto memory = readAbsolute(ea, address); - writeAbsolute(ea, address, memory = op(memory, data)); - return memory; - } - - //immediate byte - case 0b111'100'00: - return op((uint8)readPC(), data); - - //immediate word - case 0b111'100'01: - return op(readPC(), data); - - //immediate long - case 0b111'100'10: { - uint32 immediate = readPC() << 16; - immediate |= readPC(); - return op(immediate, data); + case 4: { //address register indirect with pre-decrement + write(ea.reg, data); + return; } } } - -auto M68K::flush(uint8 ea, uint32 address) -> void { - //address register indirect with post-increment - //address register indirect with pre-decrement - if(ea >= 0b011'000'00 && ea <= 0b100'111'11) { - r.a(ea >> 2) = address; - } -} diff --git a/higan/processor/m68k/instruction.cpp b/higan/processor/m68k/instruction.cpp index b0af621a..11bd9937 100644 --- a/higan/processor/m68k/instruction.cpp +++ b/higan/processor/m68k/instruction.cpp @@ -8,7 +8,9 @@ auto M68K::trap() -> void { auto M68K::instruction() -> void { instructionsExecuted++; - print(disassembleRegisters(), "\n", disassemble(r.pc), "\n\n"); + print(disassembleRegisters(), "\n"); + print(disassemble(r.pc), "\n"); + print("\n"); opcode = readPC(); return instructionTable[opcode](); @@ -18,180 +20,141 @@ M68K::M68K() { #define bind(id, name, ...) \ assert(!instructionTable[id]); \ instructionTable[id] = [=] { return instruction##name(__VA_ARGS__); }; \ - disassembleTable[id] = [=] { return disassemble##name(__VA_ARGS__); }; \ + disassembleTable[id] = [=] { return disassemble##name(__VA_ARGS__); }; + + #define pattern(s) \ + std::integral_constant::value //ADD - for(uint3 d : range(8)) + for(uint3 dreg : range(8)) for(uint1 direction : range(2)) for(uint3 mode : range(8)) for(uint3 reg : range(8)) { - auto opcode = 0b1101'0000'0000'0000 | d << 9 | direction << 8 | mode << 3 | reg << 0; + 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{0u + dreg}; EA ea{mode, reg}; - bind(opcode | 0 << 6, ADD, d, direction, ea); - bind(opcode | 1 << 6, ADD, d, direction, ea); - bind(opcode | 2 << 6, ADD, d, direction, ea); + bind(opcode | 0 << 6, ADD, rd, direction, ea); + bind(opcode | 1 << 6, ADD, rd, direction, ea); + bind(opcode | 2 << 6, ADD, rd, direction, ea); + } + + //ANDI + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("0000 0010 ++-- ----") | mode << 3 | reg << 0; + if(mode == 1 || (mode == 7 && reg >= 4)) continue; + + EA ea{mode, reg}; + bind(opcode | 0 << 6, ANDI, ea); + bind(opcode | 1 << 6, ANDI, ea); + bind(opcode | 2 << 6, ANDI, ea); + } + + //BCC + for(uint4 condition : range( 16)) + for(uint8 displacement : range(256)) { + auto opcode = pattern("0110 ---- ---- ----") | condition << 8 | displacement << 0; + + bind(opcode, BCC, condition, displacement); + } + + //LEA + for(uint3 areg : range(8)) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + 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{8u + areg}; + EA ea{mode, reg}; + bind(opcode, LEA, ra, ea); + } + + //MOVE + for(uint3 toReg : range(8)) + for(uint3 toMode : range(8)) + for(uint3 fromMode : range(8)) + for(uint3 fromReg : range(8)) { + auto opcode = pattern("00++ ---- ---- ----") | toReg << 9 | toMode << 6 | fromMode << 3 | fromReg << 0; + if(toMode == 1 || (toMode == 7 && toReg >= 4)) continue; + + EA to{toMode, toReg}; + EA from{fromMode, fromReg}; + bind(opcode | 1 << 12, MOVE, to, from); + bind(opcode | 3 << 12, MOVE, to, from); + bind(opcode | 2 << 12, MOVE, to, from); + } + + //MOVEA + for(uint3 areg : range(8)) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("00++ ---0 01-- ----") | areg << 9 | mode << 3 | reg << 0; + + Register ra{8u + areg}; + EA ea{mode, reg}; + bind(opcode | 3 << 12, MOVEA, ra, ea); + bind(opcode | 2 << 12, MOVEA, ra, ea); + } + + //MOVEM + for(uint1 direction : range(2)) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("0100 1-00 1+-- ----") | direction << 10 | mode << 3 | reg << 0; + if(mode <= 1 || mode == 3 || (mode == 7 && reg >= 4)); + + EA ea{mode, reg}; + bind(opcode | 0 << 6, MOVEM, direction, ea); + bind(opcode | 1 << 6, MOVEM, direction, ea); + } + + //MOVEQ + for(uint3 dreg : range( 8)) + for(uint8 immediate : range(256)) { + auto opcode = pattern("0111 ---0 ---- ----") | dreg << 9 | immediate << 0; + + Register rd{0u + dreg}; + bind(opcode, MOVEQ, rd, immediate); + } + + //MOVE_USP + for(uint1 direction : range(2)) + for(uint3 areg : range(8)) { + auto opcode = pattern("0100 1110 0110 ----") | direction << 3 | areg << 0; + + Register ra{8u + areg}; + bind(opcode, MOVE_USP, direction, ra); + } + + //NOP + { auto opcode = pattern("0100 1110 0111 0001"); + + bind(opcode, NOP); + } + + //TST + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("0100 1010 ++-- ----") | mode << 3 | reg << 0; + + EA ea{mode, reg}; + bind(opcode | 0 << 6, TST, ea); + bind(opcode | 1 << 6, TST, ea); + bind(opcode | 2 << 6, TST, ea); } #undef bind + #undef pattern - #define match(pattern) if( \ - (opcode & std::integral_constant::value) \ - == std::integral_constant::value \ - ) - - #define bind(name, ...) \ - assert(!instructionTable[opcode]); \ - instructionTable[opcode] = [=] { return instruction##name(__VA_ARGS__); }; \ - disassembleTable[opcode] = [=] { return disassemble##name(__VA_ARGS__); }; \ - - #define bit(x) (uint)opcode.bit(x) - #define bits(x, y) (uint)opcode.bits(x, y) - - for(uint16 opcode : range(65536)) { - -/* - //ADD - match("1101 ---- ---- ----") { - uint3 r = bits(11,9); - uint1 direction = bit(8); - uint2 size = bits(7,6); - uint3 mode = bits(5,3); - uint3 reg = bits(2,0); - - if(size != 3 && (direction == 0 || (mode == 2 || mode == 3 || mode == 4 || mode == 5 || mode == 6 || (mode == 7 && reg <= 1)))) { - uint8 ea = mode << 5 | reg << 2 | size; - bind(ADD, r, direction, ea); - } - } -*/ - - //ANDI - match("0000 0010 ---- ----") { - uint2 size = bits(7,6); - uint3 mode = bits(5,3); - uint3 reg = bits(2,0); - - if(size != 3 && mode != 1) { - uint8 ea = mode << 5 | reg << 2 | size; - bind(ANDI, ea); - } - } - - //BCC - match("0110 ---- ---- ----") { - uint4 condition = bits(11,8); - uint8 displacement = bits(7,0); - - if(true) { - bind(BCC, condition, displacement); - } - } - - //LEA - match("0100 ---1 11-- ----") { - uint3 target = bits(11,9); - uint3 mode = bits(5,3); - uint3 reg = bits(2,0); - - if(mode == 2 || mode == 5 || mode == 6 || (mode == 7 && reg <= 4)) { - uint8 ea = mode << 5 | reg << 2 | Long; - bind(LEA, target, ea); - } - } - - //MOVE - match("00-- ---- ---- ----") { - uint2 size = bits(13,12) == 1 ? Byte : bits(13,12) == 3 ? Word : bits(13,12) == 2 ? Long : 3; - uint3 targetReg = bits(11,9); - uint3 targetMode = bits(8,6); - uint3 sourceMode = bits(5,3); - uint3 sourceReg = bits(2,0); - - if(size != 3 && targetMode != 1) { - uint8 to = targetMode << 5 | targetReg << 2 | size; - uint8 from = sourceMode << 5 | sourceReg << 2 | size; - bind(MOVE, to, from); - } - } - - //MOVEA - match("00-- ---0 01-- ----") { - uint2 size = bits(13,12) == 3 ? Word : bits(13,12) == 2 ? Long : 3; - uint3 to = bits(11,9); - uint3 mode = bits(5,3); - uint3 reg = bits(2,0); - - if(size != 3) { - uint8 from = mode << 5 | reg << 2 | size; - bind(MOVEA, to, from); - } - } - - //MOVEM - match("0100 1-00 1--- ----") { - uint1 direction = bit(10); - uint2 size = 1 + bit(6); - uint3 mode = bits(5,3); - uint3 reg = bits(2,0); - - if((direction == 0 && (mode == 2 || mode == 4 || mode == 5 || mode == 6 || (mode == 7 && reg <= 3))) - || (direction == 1 && (mode == 2 || mode == 3 || mode == 5 || mode == 6 || (mode == 7 && reg <= 3)))) { - uint8 ea = mode << 5 | reg << 2 | size; - bind(MOVEM, direction, ea); - } - } - - //MOVEQ - match("0111 ---0 ---- ----") { - uint3 target = bits(11,9); - uint8 immediate = bits(7,0); - - if(true) { - bind(MOVEQ, target, immediate); - } - } - - //MOVE_USP - match("0100 1110 0110 ----") { - uint1 direction = bit(3); - uint3 reg = bits(2,0); - - if(true) { - bind(MOVE_USP, direction, reg); - } - } - - //NOP - match("0100 1110 0111 0001") { - if(true) { - bind(NOP); - } - } - - //TST - match("0100 1010 ---- ----") { - uint2 size = bits(7,6); - uint3 mode = bits(5,3); - uint3 reg = bits(2,0); - - if(size != 3) { - uint8 ea = mode << 5 | reg << 2 | size << 0; - bind(TST, ea); - } - } - - } - - #undef match - #undef bind - #undef bit - #undef bits - + uint unimplemented = 0; for(uint16 opcode : range(65536)) { if(instructionTable[opcode]) continue; instructionTable[opcode] = [=] { trap(); }; disassembleTable[opcode] = [=] { return string{"???"}; }; + unimplemented++; } +//print("[M68K] unimplemented opcodes: ", unimplemented, "\n"); } diff --git a/higan/processor/m68k/instructions.cpp b/higan/processor/m68k/instructions.cpp index 8bbe7c7a..79278ed5 100644 --- a/higan/processor/m68k/instructions.cpp +++ b/higan/processor/m68k/instructions.cpp @@ -46,30 +46,20 @@ template auto M68K::negative(uint32 result) -> bool { return sign(result) < 0; } -auto M68K::zero(uint2 size, uint32 result) -> bool { - static const uint32 mask[4] = {0xff, 0xffff, 0xffffffff}; - return (result & mask[size]) == 0; -} - -auto M68K::negative(uint2 size, uint32 result) -> bool { - static const uint32 mask[4] = {0x80, 0x8000, 0x80000000}; - return result & mask[size]; -} - // -template auto M68K::instructionADD(uint3 reg, uint1 direction, EA ea) -> void { +template auto M68K::instructionADD(Register rd, uint1 direction, EA ea) -> void { uint32 source; uint32 target; uint32 result; if(direction == 0) { source = read(ea); - target = r.d(reg); + target = read(rd); result = source + target; - r.d(reg) = result; + write(rd, result); } else { - source = r.d(reg); + source = read(rd); target = read(ea); result = source + target; write(ea, result); @@ -82,95 +72,86 @@ template auto M68K::instructionADD(uint3 reg, uint1 direction, EA ea) r.x = r.c; } -auto M68K::instructionANDI(uint8 ea) -> void { - auto result = modify(ea, readPC(ea), [&](auto x, auto y) -> uint32 { - return x & y; - }); +template auto M68K::instructionANDI(EA ea) -> void { + auto source = readPC(); + auto target = read(ea); + auto result = target & source; + write(ea, result); r.c = 0; r.v = 0; - r.z = zero(ea, result); - r.n = negative(ea, result); + r.z = zero(result); + r.n = negative(result); } auto M68K::instructionBCC(uint4 condition, uint8 displacement) -> void { - auto word = readPC(); - if(displacement) displacement = (int8)displacement, r.pc -= 2; - else displacement = (int16)word; - if(condition == 1) { - condition = 0; - //pushLong(r.pc); - } - if(testCondition(condition)) r.pc += displacement; + auto extension = readPC(); + if(condition == 1); //push(r.pc); + r.pc -= 2; + if(!testCondition(condition == 1 ? (uint4)0 : condition)) return; + r.pc += displacement ? sign(displacement) : sign(extension); } -auto M68K::instructionLEA(uint3 target, uint8 ea) -> void { - r.a(target) = address(ea); +auto M68K::instructionLEA(Register ra, EA ea) -> void { + write(ra, fetch(ea)); } -auto M68K::instructionMOVE(uint8 to, uint8 from) -> void { - auto data = read(from); - write(to, data); +template auto M68K::instructionMOVE(EA to, EA from) -> void { + auto data = read(from); + write(to, data); r.c = 0; r.v = 0; - r.z = zero(from, data); - r.n = negative(from, data); + r.z = zero(data); + r.n = negative(data); } -auto M68K::instructionMOVEA(uint3 to, uint8 from) -> void { - auto data = read(from); - if(from & 1) data = (int16)data; - r.a(to) = data; +template auto M68K::instructionMOVEA(Register ra, EA ea) -> void { + auto data = read(ea); + if(Size == Word) data = (int16)data; + write(ra, data); } -auto M68K::instructionMOVEM(uint1 direction, uint8 ea) -> void { +template auto M68K::instructionMOVEM(uint1 direction, EA ea) -> void { auto list = readPC(); - auto addr = address(ea); + auto addr = fetch(ea); - for(uint n : range(8)) { - if(list.bit(0 + n)) { - r.d(n) = readAbsolute(ea, addr); - addr += 2 + (ea & 2); + 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(8 + n)) { - r.a(n) = readAbsolute(ea, addr); - addr += 2 + (ea & 2); - } - } - - flush(ea, addr); + flush(ea, addr); } -auto M68K::instructionMOVEQ(uint3 target, uint8 immediate) -> void { - r.d(target) = immediate; +auto M68K::instructionMOVEQ(Register rd, uint8 immediate) -> void { + write(rd, immediate); r.c = 0; r.v = 0; - r.z = immediate == 0; - r.n = negative(Byte, immediate); + r.z = zero(immediate); + r.n = negative(immediate); } -auto M68K::instructionMOVE_USP(uint1 direction, uint3 reg) -> void { +auto M68K::instructionMOVE_USP(uint1 direction, Register ra) -> void { if(!r.s) trap(); //todo: proper trap if(direction == 0) { - r.usp = r.a(reg); + r.usp = read(ra); } else { - r.a(reg) = r.usp; + write(ra, r.usp); } } auto M68K::instructionNOP() -> void { } -auto M68K::instructionTST(uint8 ea) -> void { - auto data = read(ea); +template auto M68K::instructionTST(EA ea) -> void { + auto data = read(ea); r.c = 0; r.v = 0; - r.z = zero(ea, data); - r.n = negative(ea, data); + r.z = zero(data); + r.n = negative(data); } diff --git a/higan/processor/m68k/m68k.cpp b/higan/processor/m68k/m68k.cpp index fed475b3..9e101a24 100644 --- a/higan/processor/m68k/m68k.cpp +++ b/higan/processor/m68k/m68k.cpp @@ -18,8 +18,7 @@ auto M68K::power() -> void { auto M68K::reset() -> void { instructionsExecuted = 0; - for(uint n : range(8)) r.d(n) = 0; - for(uint n : range(7)) r.a(n) = 0; + for(uint rn : range(15)) write(Register{rn}, 0); r.ssp = 0; r.usp = 0; r.pc = 0; diff --git a/higan/processor/m68k/m68k.hpp b/higan/processor/m68k/m68k.hpp index 210f9d13..e0579bac 100644 --- a/higan/processor/m68k/m68k.hpp +++ b/higan/processor/m68k/m68k.hpp @@ -6,6 +6,7 @@ namespace Processor { struct M68K { enum : uint { Byte, Word, Long }; + enum : bool { NoUpdate = 0 }; M68K(); @@ -16,32 +17,39 @@ struct M68K { auto power() -> void; auto reset() -> void; + //registers.cpp + struct Register { + Register(uint number) : number(number) {} + + uint4 number; + }; + + template auto read(Register reg) -> uint32; + template auto write(Register reg, uint32 value) -> void; + //memory.cpp - auto readAbsolute(uint2 size, uint32 addr) -> uint32; - auto writeAbsolute(uint2 size, uint32 addr, uint32 data) -> void; - - auto readPC(uint2 size = Word) -> uint32; - template auto read(uint32 addr) -> uint32; + template auto write(uint32 addr, uint32 data) -> void; + template auto readPC() -> uint32; //ea.cpp struct EA { - EA(uint3 mode, uint3 reg) : mode(mode), reg(reg) { - if(mode == 7) mode += reg; //optimization: convert modes {7; 0-4} to {8-11} + 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 } uint4 mode; - uint3 reg; + Register reg; + + boolean valid; + uint32 address; }; - template auto read(EA ea) -> uint32; - template auto write(EA ea, uint32 data) -> void; - - auto address(uint8 ea) -> uint32; - auto read(uint8 ea) -> uint32; - auto write(uint8 ea, uint32 data) -> void; - auto modify(uint8 ea, uint32 data, const function& op) -> uint32; - auto flush(uint8 ea, uint32 address) -> void; + 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; //instruction.cpp auto trap() -> void; @@ -57,29 +65,24 @@ struct M68K { template auto overflow(uint32 result, uint32 source, uint32 target) -> bool; template auto zero(uint32 result) -> bool; template auto negative(uint32 result) -> bool; - auto zero(uint2 size, uint32 result) -> bool; - auto negative(uint2 size, uint32 result) -> bool; - template auto instructionADD(uint3 reg, uint1 direction, EA ea) -> void; - auto instructionANDI(uint8 ea) -> void; - auto instructionBCC(uint4 condition, uint8 displacement) -> void; - auto instructionLEA(uint3 target, uint8 source) -> void; - auto instructionMOVE(uint8 to, uint8 from) -> void; - auto instructionMOVEA(uint3 to, uint8 ea) -> void; - auto instructionMOVEM(uint1 direction, uint8 ea) -> void; - auto instructionMOVEQ(uint3 target, uint8 immediate) -> void; - auto instructionMOVE_USP(uint1 direction, uint3 reg) -> void; - auto instructionNOP() -> void; - auto instructionTST(uint8 ea) -> void; + template auto instructionADD(Register rd, uint1 direction, EA ea) -> void; + template auto instructionANDI(EA ea) -> void; + auto instructionBCC(uint4 condition, uint8 displacement) -> 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_USP(uint1 direction, Register ra) -> void; + auto instructionNOP() -> void; + template auto instructionTST(EA ea) -> void; //disassembler.cpp auto disassemble(uint32 pc) -> string; auto disassembleRegisters() -> string; struct Registers { - auto d(uint3 r) -> uint32&; - auto a(uint3 r) -> uint32&; - uint32 d0, d1, d2, d3, d4, d5, d6, d7; uint32 a0, a1, a2, a3, a4, a5, a6, ssp, usp; uint32 pc; @@ -106,28 +109,27 @@ struct M68K { private: //disassembler.cpp - template auto disassembleADD(uint3 reg, uint1 direction, EA ea) -> string; - auto disassembleANDI(uint8 ea) -> string; - auto disassembleBCC(uint4 condition, uint8 displacement) -> string; - auto disassembleLEA(uint3 target, uint8 ea) -> string; - auto disassembleMOVE(uint8 to, uint8 from) -> string; - auto disassembleMOVEA(uint3 to, uint8 from) -> string; - auto disassembleMOVEM(uint1 direction, uint8 ea) -> string; - auto disassembleMOVEQ(uint3 target, uint8 immediate) -> string; - auto disassembleMOVE_USP(uint1 direction, uint3 reg) -> string; - auto disassembleNOP() -> string; - auto disassembleTST(uint8 ea) -> string; + template auto disassembleADD(Register rd, uint1 direction, EA ea) -> string; + template auto disassembleANDI(EA ea) -> string; + auto disassembleBCC(uint4 condition, uint8 displacement) -> 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_USP(uint1 direction, Register ra) -> string; + auto disassembleNOP() -> string; + template auto disassembleTST(EA ea) -> string; - auto _readByte(uint32 addr) -> uint8; - auto _readWord(uint32 addr) -> uint16; - auto _readLong(uint32 addr) -> uint32; - auto _readPC(uint2 size = Word) -> uint32; - auto _immediate(uint2 size) -> string; - auto _address(uint8 ea) -> string; - auto _read(uint8 ea) -> string; - auto _write(uint8 ea) -> string; + template auto _read(uint32 addr) -> uint32; + template auto _readPC() -> uint32; + auto _register(Register r) -> string; + template auto _immediate() -> string; + template auto _address(EA ea) -> string; + template auto _read(EA ea) -> string; + template auto _write(EA ea) -> string; auto _branch(uint8 displacement) -> string; - auto _suffix(uint2 size) -> string; + template auto _suffix() -> string; auto _condition(uint4 condition) -> string; uint32 _pc; diff --git a/higan/processor/m68k/memory.cpp b/higan/processor/m68k/memory.cpp index 1021964b..13723890 100644 --- a/higan/processor/m68k/memory.cpp +++ b/higan/processor/m68k/memory.cpp @@ -1,24 +1,4 @@ -auto M68K::readAbsolute(uint2 size, uint32 addr) -> uint32 { - step(4); - uint32 data = read(size != Byte, addr); - if(size != Long) return data; - - step(4); - data = data << 16 | read(1, addr + 2); - return data; -} - -auto M68K::writeAbsolute(uint2 size, uint32 addr, uint32 data) -> void { - if(size == Long) { - write(1, addr + 0, data >> 16); - write(1, addr + 2, data >> 0); - } else { - write(size != Byte, addr, data >> 0); - } -} - -// - +/* auto M68K::readPC(uint2 size) -> uint32 { step(4); uint32 data = read(size != Byte, r.pc); @@ -30,8 +10,7 @@ auto M68K::readPC(uint2 size) -> uint32 { r.pc += 2; return data; } - -// +*/ template<> auto M68K::read(uint32 addr) -> uint32 { step(4); @@ -49,3 +28,40 @@ template<> auto M68K::read(uint32 addr) -> uint32 { step(4); return data | read(1, addr + 2) << 0; } + +// + +template<> auto M68K::write(uint32 addr, uint32 data) -> void { +} + +template<> auto M68K::write(uint32 addr, uint32 data) -> void { +} + +template<> auto M68K::write(uint32 addr, uint32 data) -> void { +} + +// + +template<> auto M68K::readPC() -> uint32 { + step(4); + uint32 data = read(1, r.pc); + r.pc += 2; + return (uint8)data; +} + +template<> auto M68K::readPC() -> uint32 { + step(4); + uint32 data = read(1, r.pc); + r.pc += 2; + return data; +} + +template<> auto M68K::readPC() -> uint32 { + step(4); + uint32 data = read(1, r.pc) << 16; + r.pc += 2; + step(4); + data |= read(1, r.pc); + r.pc += 2; + return data; +} diff --git a/higan/processor/m68k/registers.cpp b/higan/processor/m68k/registers.cpp index b31f1faa..6b381315 100644 --- a/higan/processor/m68k/registers.cpp +++ b/higan/processor/m68k/registers.cpp @@ -1,26 +1,42 @@ -auto M68K::Registers::d(uint3 r) -> uint32& { - switch(r) { - case 0: return d0; - case 1: return d1; - case 2: return d2; - case 3: return d3; - case 4: return d4; - case 5: return d5; - case 6: return d6; - case 7: return d7; +template auto M68K::read(Register reg) -> uint32 { + switch(reg.number) { + case 0: return clip(r.d0); + case 1: return clip(r.d1); + case 2: return clip(r.d2); + case 3: return clip(r.d3); + case 4: return clip(r.d4); + case 5: return clip(r.d5); + case 6: return clip(r.d6); + case 7: return clip(r.d7); + case 8: return clip(r.a0); + case 9: return clip(r.a1); + case 10: return clip(r.a2); + case 11: return clip(r.a3); + case 12: return clip(r.a4); + case 13: return clip(r.a5); + case 14: return clip(r.a6); + case 15: return r.s ? clip(r.ssp) : clip(r.usp); } unreachable; } -auto M68K::Registers::a(uint3 r) -> uint32& { - switch(r) { - case 0: return a0; - case 1: return a1; - case 2: return a2; - case 3: return a3; - case 4: return a4; - case 5: return a5; - case 6: return a6; - case 7: return s ? ssp : usp; +template auto M68K::write(Register reg, uint32 data) -> void { + switch(reg.number) { + case 0: r.d0 = clip(data); return; + case 1: r.d1 = clip(data); return; + case 2: r.d2 = clip(data); return; + case 3: r.d3 = clip(data); return; + case 4: r.d4 = clip(data); return; + case 5: r.d5 = clip(data); return; + case 6: r.d6 = clip(data); return; + case 7: r.d7 = clip(data); return; + case 8: r.a0 = clip(data); return; + case 9: r.a1 = clip(data); return; + case 10: r.a2 = clip(data); return; + case 11: r.a3 = clip(data); return; + case 12: r.a4 = clip(data); return; + case 13: r.a5 = clip(data); return; + case 14: r.a6 = clip(data); return; + case 15: r.s ? r.ssp = clip(data) : r.usp = clip(data); return; } }