diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 9f6e3e42..89b246d6 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.11"; + static const string Version = "100.12"; 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 bc1c858f..0db7a32e 100644 --- a/higan/md/cpu/cpu.cpp +++ b/higan/md/cpu/cpu.cpp @@ -28,6 +28,8 @@ auto CPU::step(uint clocks) -> void { auto CPU::power() -> void { M68K::power(); + + for(auto& byte : ram) byte = 0x00; } auto CPU::reset() -> void { @@ -37,11 +39,23 @@ auto CPU::reset() -> void { auto CPU::read(bool word, uint24 addr) -> uint16 { if(addr < 0x400000) return cartridge.read(word, addr); - return 0x0000; + if(addr < 0xe00000) return 0x0000; + + uint16 data = ram[addr & 65535]; + if(word) data = data << 8 | ram[addr + 1 & 65535]; + return data; } auto CPU::write(bool word, uint24 addr, uint16 data) -> void { if(addr < 0x400000) return cartridge.write(word, addr, data); + if(addr < 0xe00000) return; + + if(!word) { + ram[addr & 65535] = data; + } else { + ram[addr + 0 & 65535] = data >> 8; + ram[addr + 1 & 65535] = data >> 0; + } } } diff --git a/higan/md/cpu/cpu.hpp b/higan/md/cpu/cpu.hpp index 298d89b7..32fa51cc 100644 --- a/higan/md/cpu/cpu.hpp +++ b/higan/md/cpu/cpu.hpp @@ -11,6 +11,9 @@ struct CPU : Processor::M68K, Thread { auto read(bool word, uint24 addr) -> uint16 override; auto write(bool word, uint24 addr, uint16 data) -> void override; + +private: + uint8 ram[64 * 1024]; }; extern CPU cpu; diff --git a/higan/processor/m68k/disassembler.cpp b/higan/processor/m68k/disassembler.cpp index 2efb539f..83e5e776 100644 --- a/higan/processor/m68k/disassembler.cpp +++ b/higan/processor/m68k/disassembler.cpp @@ -17,11 +17,11 @@ template auto M68K::_readPC() -> uint32 { return clip(data); } -auto M68K::_register(DataRegister dr) -> string { +auto M68K::_dataRegister(DataRegister dr) -> string { return {"d", dr.number}; } -auto M68K::_register(AddressRegister ar) -> string { +auto M68K::_addressRegister(AddressRegister ar) -> string { return {"a", ar.number}; } @@ -34,27 +34,23 @@ template auto M68K::_address(EffectiveAddress& ea) -> string { return "???"; } -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}), ")"}; +template auto M68K::_effectiveAddress(EffectiveAddress& ea) -> string { + if(ea.mode == 0) return {_dataRegister(DataRegister{ea.reg})}; + if(ea.mode == 1) return {_addressRegister(AddressRegister{ea.reg})}; + if(ea.mode == 2) return {"(", _addressRegister(AddressRegister{ea.reg}), ")"}; + if(ea.mode == 3) return {"(", _addressRegister(AddressRegister{ea.reg}), ")+"}; + if(ea.mode == 4) return {"-(", _addressRegister(AddressRegister{ea.reg}), ")"}; if(ea.mode == 5) return {"($", hex(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(EffectiveAddress& ea) -> string { - return _read(ea); -} - auto M68K::_branch(uint8 displacement) -> string { - uint16 word = _readPC(); - if(displacement) displacement = (int8)displacement, _pc -= 2; - else displacement = (int16)displacement; - return {"$", hex(_pc + displacement, 6L)}; + uint16 extension = _readPC(); + _pc -= 2; + int32 offset = displacement ? sign(displacement) : sign(extension); + return {"$", hex(_pc + offset, 6L)}; } template auto M68K::_suffix() -> string { @@ -97,14 +93,14 @@ template auto M68K::disassembleADD(DataRegister dr, uint1 direction, string op{"add", _suffix(), " "}; if(direction == 0) { - return {op, _read(ea), ",", _register(dr)}; + return {op, _effectiveAddress(ea), ",", _dataRegister(dr)}; } else { - return {op, "", _register(dr), ",", _read(ea)}; + return {op, "", _dataRegister(dr), ",", _effectiveAddress(ea)}; } } template auto M68K::disassembleANDI(EffectiveAddress ea) -> string { - return {"andi", _suffix(), " ", _immediate(), ",", _read(ea)}; + return {"andi", _suffix(), " ", _immediate(), ",", _effectiveAddress(ea)}; } auto M68K::disassembleANDI_TO_CCR() -> string { @@ -115,6 +111,30 @@ auto M68K::disassembleANDI_TO_SR() -> string { return {"andi ", _immediate(), ",sr"}; } +template auto M68K::disassembleASL(uint4 shift, DataRegister modify) -> string { + return {"asl", _suffix(), " #", shift, ",", _dataRegister(modify)}; +} + +template auto M68K::disassembleASL(DataRegister shift, DataRegister modify) -> string { + return {"asl", _suffix(), " ", _dataRegister(shift), ",", _dataRegister(modify)}; +} + +auto M68K::disassembleASL(EffectiveAddress modify) -> string { + return {"asl", _suffix(), " ", _effectiveAddress(modify)}; +} + +template auto M68K::disassembleASR(uint4 shift, DataRegister modify) -> string { + return {"asr", _suffix(), " #", shift, ",", _dataRegister(modify)}; +} + +template auto M68K::disassembleASR(DataRegister shift, DataRegister modify) -> string { + return {"asr", _suffix(), " ", _dataRegister(shift), ",", _dataRegister(modify)}; +} + +auto M68K::disassembleASR(EffectiveAddress modify) -> string { + return {"asr", _suffix(), " ", _effectiveAddress(modify)}; +} + auto M68K::disassembleBCC(uint4 condition, uint8 displacement) -> string { auto cc = _condition(condition); if(condition == 0) cc = "ra"; @@ -123,25 +143,25 @@ auto M68K::disassembleBCC(uint4 condition, uint8 displacement) -> string { } template auto M68K::disassembleBTST(DataRegister dr, EffectiveAddress ea) -> string { - return {"btst ", _register(dr), ",", _read(ea)}; + return {"btst ", _dataRegister(dr), ",", _effectiveAddress(ea)}; } template auto M68K::disassembleBTST(EffectiveAddress ea) -> string { - return {"btst ", _immediate(), ",", _read(ea)}; + return {"btst ", _immediate(), ",", _effectiveAddress(ea)}; } template auto M68K::disassembleCLR(EffectiveAddress ea) -> string { - return {"clr", _suffix(), " ", _read(ea)}; + return {"clr", _suffix(), " ", _effectiveAddress(ea)}; } template auto M68K::disassembleCMP(DataRegister dr, EffectiveAddress ea) -> string { - return {"cmp", _suffix(), " ", _read(ea), ",", _register(dr)}; + return {"cmp", _suffix(), " ", _effectiveAddress(ea), ",", _dataRegister(dr)}; } auto M68K::disassembleDBCC(uint4 condition, DataRegister dr) -> string { auto base = _pc; auto displacement = (int16)_readPC(); - return {"db", _condition(condition), " ", _register(dr), ",$", hex(base + displacement, 6L)}; + return {"db", _condition(condition), " ", _dataRegister(dr), ",$", hex(base + displacement, 6L)}; } auto M68K::disassembleEORI_TO_CCR() -> string { @@ -153,15 +173,39 @@ auto M68K::disassembleEORI_TO_SR() -> string { } auto M68K::disassembleLEA(AddressRegister ar, EffectiveAddress ea) -> string { - return {"lea ", _address(ea), ",", _register(ar)}; + return {"lea ", _address(ea), ",", _addressRegister(ar)}; +} + +template auto M68K::disassembleLSL(uint4 immediate, DataRegister dr) -> string { + return {"lsl", _suffix(), " #", immediate, ",", _dataRegister(dr)}; +} + +template auto M68K::disassembleLSL(DataRegister sr, DataRegister dr) -> string { + return {"lsl", _suffix(), " ", _dataRegister(sr), ",", _dataRegister(dr)}; +} + +auto M68K::disassembleLSL(EffectiveAddress ea) -> string { + return {"lsl", _suffix(), " ", _effectiveAddress(ea)}; +} + +template auto M68K::disassembleLSR(uint4 immediate, DataRegister dr) -> string { + return {"lsr", _suffix(), " #", immediate, ",", _dataRegister(dr)}; +} + +template auto M68K::disassembleLSR(DataRegister shift, DataRegister dr) -> string { + return {"lsr", _suffix(), " ", _dataRegister(shift), ",", _dataRegister(dr)}; +} + +auto M68K::disassembleLSR(EffectiveAddress ea) -> string { + return {"lsr", _suffix(), " ", _effectiveAddress(ea)}; } template auto M68K::disassembleMOVE(EffectiveAddress to, EffectiveAddress from) -> string { - return {"move", _suffix(), " ", _read(from), ",", _write(to)}; + return {"move", _suffix(), " ", _effectiveAddress(from), ",", _effectiveAddress(to)}; } template auto M68K::disassembleMOVEA(AddressRegister ar, EffectiveAddress ea) -> string { - return {"movea ", _read(ea), ",", _register(ar)}; + return {"movea ", _effectiveAddress(ea), ",", _addressRegister(ar)}; } template auto M68K::disassembleMOVEM(uint1 direction, EffectiveAddress ea) -> string { @@ -169,40 +213,40 @@ template auto M68K::disassembleMOVEM(uint1 direction, EffectiveAddres uint16 list = _readPC(); string regs; - for(uint n : range(8)) if(list.bit(0 + n)) regs.append(_register(DataRegister{n}), ","); + for(uint n : range(8)) if(list.bit(0 + n)) regs.append(_dataRegister(DataRegister{n}), ","); regs.trimRight(","); if(regs && list >> 8) regs.append("/"); - for(uint n : range(8)) if(list.bit(8 + n)) regs.append(_register(AddressRegister{n}), ","); + for(uint n : range(8)) if(list.bit(8 + n)) regs.append(_addressRegister(AddressRegister{n}), ","); regs.trimRight(","); if(direction == 0) { - return {op, regs, ",", _read(ea)}; + return {op, regs, ",", _effectiveAddress(ea)}; } else { - return {op, _read(ea), ",", regs}; + return {op, _effectiveAddress(ea), ",", regs}; } } auto M68K::disassembleMOVEQ(DataRegister dr, uint8 immediate) -> string { - return {"moveq #$", hex(immediate, 2L), ",", _register(dr)}; + return {"moveq #$", hex(immediate, 2L), ",", _dataRegister(dr)}; } auto M68K::disassembleMOVE_FROM_SR(EffectiveAddress ea) -> string { - return {"move sr,", _read(ea)}; + return {"move sr,", _effectiveAddress(ea)}; } auto M68K::disassembleMOVE_TO_CCR(EffectiveAddress ea) -> string { - return {"move ", _read(ea), ",ccr"}; + return {"move ", _effectiveAddress(ea), ",ccr"}; } auto M68K::disassembleMOVE_TO_SR(EffectiveAddress ea) -> string { - return {"move ", _read(ea), ",sr"}; + return {"move ", _effectiveAddress(ea), ",sr"}; } auto M68K::disassembleMOVE_USP(uint1 direction, AddressRegister ar) -> string { if(direction == 0) { - return {"move ", _register(ar), ",usp"}; + return {"move ", _addressRegister(ar), ",usp"}; } else { - return {"move usp,", _register(ar)}; + return {"move usp,", _addressRegister(ar)}; } } @@ -218,10 +262,62 @@ auto M68K::disassembleORI_TO_SR() -> string { return {"ori ", _immediate(), ",sr"}; } +template auto M68K::disassembleROL(uint4 shift, DataRegister modify) -> string { + return {"rol", _suffix(), " #", shift, ",", _dataRegister(modify)}; +} + +template auto M68K::disassembleROL(DataRegister shift, DataRegister modify) -> string { + return {"rol", _suffix(), " ", _dataRegister(shift), ",", _dataRegister(modify)}; +} + +auto M68K::disassembleROL(EffectiveAddress modify) -> string { + return {"rol", _suffix(), " ", _effectiveAddress(modify)}; +} + +template auto M68K::disassembleROR(uint4 shift, DataRegister modify) -> string { + return {"ror", _suffix(), " #", shift, ",", _dataRegister(modify)}; +} + +template auto M68K::disassembleROR(DataRegister shift, DataRegister modify) -> string { + return {"ror", _suffix(), " ", _dataRegister(shift) ,",", _dataRegister(modify)}; +} + +auto M68K::disassembleROR(EffectiveAddress modify) -> string { + return {"ror", _suffix(), " ", _effectiveAddress(modify)}; +} + +template auto M68K::disassembleROXL(uint4 shift, DataRegister modify) -> string { + return {"roxl", _suffix(), " #", shift, ",", _dataRegister(modify)}; +} + +template auto M68K::disassembleROXL(DataRegister shift, DataRegister modify) -> string { + return {"roxl", _suffix(), " ", _dataRegister(shift), ",", _dataRegister(modify)}; +} + +auto M68K::disassembleROXL(EffectiveAddress modify) -> string { + return {"roxl", _suffix(), " ", _effectiveAddress(modify)}; +} + +template auto M68K::disassembleROXR(uint4 shift, DataRegister modify) -> string { + return {"roxr", _suffix(), " #", shift, ",", _dataRegister(modify)}; +} + +template auto M68K::disassembleROXR(DataRegister shift, DataRegister modify) -> string { + return {"roxr", _suffix(), " ", _dataRegister(shift), ",", _dataRegister(modify)}; +} + +auto M68K::disassembleROXR(EffectiveAddress modify) -> string { + return {"roxr", _suffix(), " ", _effectiveAddress(modify)}; +} + auto M68K::disassembleRTS() -> string { return {"rts "}; } -template auto M68K::disassembleTST(EffectiveAddress ea) -> string { - return {"tst", _suffix(), " ", _read(ea)}; +template auto M68K::disassembleSUBQ(uint4 immediate, EffectiveAddress ea) -> string { + return {"subq", _suffix(), " #", immediate, _effectiveAddress(ea)}; +} + +template auto M68K::disassembleTST(EffectiveAddress ea) -> string { + return {"tst", _suffix(), " ", _effectiveAddress(ea)}; } diff --git a/higan/processor/m68k/effective-address.cpp b/higan/processor/m68k/effective-address.cpp index ba3383d3..e080b1e2 100644 --- a/higan/processor/m68k/effective-address.cpp +++ b/higan/processor/m68k/effective-address.cpp @@ -87,13 +87,13 @@ template auto M68K::read(EffectiveAddress& ea) -> uint32 case AddressRegisterIndirectWithPostIncrement: { auto data = read(ea.address); - if(Update) write(AddressRegister{ea.reg}, ea.address += (Size == Long ? 4 : 2)); + if(Update) write(AddressRegister{ea.reg}, ea.address += bytes()); return data; } case AddressRegisterIndirectWithPreDecrement: { - auto data = read(ea.address - (Size == Long ? 4 : 2)); - if(Update) write(AddressRegister{ea.reg}, ea.address -= (Size == Long ? 4 : 2)); + auto data = read(ea.address - bytes()); + if(Update) write(AddressRegister{ea.reg}, ea.address -= bytes()); return data; } @@ -149,13 +149,13 @@ template auto M68K::write(EffectiveAddress& ea, uint32 d case AddressRegisterIndirectWithPostIncrement: { write(ea.address, data); - if(Update) write(AddressRegister{ea.reg}, ea.address += (Size == Long ? 4 : 2)); + if(Update) write(AddressRegister{ea.reg}, ea.address += bytes()); return; } case AddressRegisterIndirectWithPreDecrement: { - write(ea.address - (Size == Long ? 4 : 2), data); - if(Update) write(AddressRegister{ea.reg}, ea.address -= (Size == Long ? 4 : 2)); + write(ea.address - bytes(), data); + if(Update) write(AddressRegister{ea.reg}, ea.address -= bytes()); return; } diff --git a/higan/processor/m68k/instruction.cpp b/higan/processor/m68k/instruction.cpp index 3be822f2..8fa0756d 100644 --- a/higan/processor/m68k/instruction.cpp +++ b/higan/processor/m68k/instruction.cpp @@ -9,11 +9,13 @@ auto M68K::trap() -> void { auto M68K::instruction() -> void { instructionsExecuted++; - if(instructionsExecuted >= 20) trap(); +// if(instructionsExecuted >= 851570) trap(); - print(disassembleRegisters(), "\n"); - print(disassemble(r.pc), "\n"); - print("\n"); +// if(instructionsExecuted >= 851530) { +// print(disassembleRegisters(), "\n"); +// print(disassemble(r.pc), "\n"); +// print("\n"); +// } opcode = readPC(); return instructionTable[opcode](); @@ -75,6 +77,74 @@ M68K::M68K() { bind(opcode, ANDI_TO_SR); } + //ASL (immediate) + for(uint3 count : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---1 ++00 0---") | count << 9 | dreg << 0; + + auto shift = count ? (uint4)count : (uint4)8; + DataRegister modify{dreg}; + bind(opcode | 0 << 6, ASL, shift, modify); + bind(opcode | 1 << 6, ASL, shift, modify); + bind(opcode | 2 << 6, ASL, shift, modify); + } + + //ASL (register) + for(uint3 sreg : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---1 ++10 0---") | sreg << 9 | dreg << 0; + + DataRegister shift{sreg}; + DataRegister modify{dreg}; + bind(opcode | 0 << 6, ASL, shift, modify); + bind(opcode | 1 << 6, ASL, shift, modify); + bind(opcode | 2 << 6, ASL, shift, modify); + } + + //ASL (effective address) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("1110 0001 11-- ----") | mode << 3 | reg << 0; + if(mode <= 1 || (mode == 7 && reg >= 2)) continue; + + EffectiveAddress modify{mode, reg}; + bind(opcode, ASL, modify); + } + + //ASR (immediate) + for(uint3 count : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---0 ++00 0---") | count << 9 | dreg << 0; + + auto shift = count ? (uint4)count : (uint4)8; + DataRegister modify{dreg}; + bind(opcode | 0 << 6, ASR, shift, modify); + bind(opcode | 1 << 6, ASR, shift, modify); + bind(opcode | 2 << 6, ASR, shift, modify); + } + + //ASR (register) + for(uint3 sreg : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---0 ++10 0---") | sreg << 9 | dreg << 0; + + DataRegister shift{sreg}; + DataRegister modify{dreg}; + bind(opcode | 0 << 6, ASR, shift, modify); + bind(opcode | 1 << 6, ASR, shift, modify); + bind(opcode | 2 << 6, ASR, shift, modify); + } + + //ASR (effective address) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("1110 0000 11-- ----") | mode << 3 | reg << 0; + if(mode <= 1 || (mode == 7 && reg >= 2)) continue; + + EffectiveAddress modify{mode, reg}; + bind(opcode, ASR, modify); + } + //BCC for(uint4 condition : range( 16)) for(uint8 displacement : range(256)) { @@ -88,7 +158,7 @@ M68K::M68K() { for(uint3 mode : range(8)) for(uint3 reg : range(8)) { auto opcode = pattern("0000 ---1 00-- ----") | dreg << 9 | mode << 3 | reg << 0; - if(mode == 1) continue; + if(mode == 1 || (mode == 7 && reg >= 5)) continue; DataRegister dr{dreg}; EffectiveAddress ea{mode, reg}; @@ -100,7 +170,7 @@ M68K::M68K() { for(uint3 mode : range(8)) for(uint3 reg : range(8)) { auto opcode = pattern("0000 1000 00-- ----") | mode << 3 | reg << 0; - if(mode == 1 || (mode == 7 && reg == 2)) continue; + if(mode == 1 || (mode == 7 && (reg == 2 || reg >= 5))) continue; EffectiveAddress ea{mode, reg}; if(mode == 0) bind(opcode, BTST, ea); @@ -124,6 +194,7 @@ M68K::M68K() { for(uint3 mode : range(8)) for(uint3 reg : range(8)) { auto opcode = pattern("1011 ---0 ++-- ----") | dreg << 9 | mode << 3 | reg << 0; + if(mode == 7 && reg >= 5) continue; DataRegister dr{dreg}; EffectiveAddress ea{mode, reg}; @@ -160,13 +231,81 @@ M68K::M68K() { 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; + if(mode <= 1 || mode == 3 || mode == 4 || (mode == 7 && reg >= 4)) continue; AddressRegister ar{areg}; EffectiveAddress ea{mode, reg}; bind(opcode, LEA, ar, ea); } + //LSL (immediate) + for(uint3 data : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---1 ++00 1---") | data << 9 | dreg << 0; + + auto immediate = data ? (uint4)data : (uint4)8; + DataRegister dr{dreg}; + bind(opcode | 0 << 6, LSL, immediate, dr); + bind(opcode | 1 << 6, LSL, immediate, dr); + bind(opcode | 2 << 6, LSL, immediate, dr); + } + + //LSL (register) + for(uint3 sreg : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---1 ++10 1---") | sreg << 9 | dreg << 0; + + DataRegister sr{sreg}; + DataRegister dr{dreg}; + bind(opcode | 0 << 6, LSL, sr, dr); + bind(opcode | 1 << 6, LSL, sr, dr); + bind(opcode | 2 << 6, LSL, sr, dr); + } + + //LSL (effective address) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("1110 0011 11-- ----") | mode << 3 | reg << 0; + if(mode <= 1 || (mode == 7 && reg >= 2)) continue; + + EffectiveAddress ea{mode, reg}; + bind(opcode, LSL, ea); + } + + //LSR (immediate) + for(uint3 data : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---0 ++00 1---") | data << 9 | dreg << 0; + + auto immediate = data ? (uint4)data : (uint4)8; + DataRegister dr{dreg}; + bind(opcode | 0 << 6, LSR, immediate, dr); + bind(opcode | 1 << 6, LSR, immediate, dr); + bind(opcode | 2 << 6, LSR, immediate, dr); + } + + //LSR (register) + for(uint3 count : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---0 ++10 1---") | count << 9 | dreg << 0; + + DataRegister shift{count}; + DataRegister dr{dreg}; + bind(opcode | 0 << 6, LSR, shift, dr); + bind(opcode | 1 << 6, LSR, shift, dr); + bind(opcode | 2 << 6, LSR, shift, dr); + } + + //LSR (effective address) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("1110 0010 11-- ----") | mode << 3 | reg << 0; + if(mode <= 1 || (mode == 7 && reg >= 2)) continue; + + EffectiveAddress ea{mode, reg}; + bind(opcode, LSR, ea); + } + //MOVE for(uint3 toReg : range(8)) for(uint3 toMode : range(8)) @@ -174,6 +313,7 @@ M68K::M68K() { for(uint3 fromReg : range(8)) { auto opcode = pattern("00++ ---- ---- ----") | toReg << 9 | toMode << 6 | fromMode << 3 | fromReg << 0; if(toMode == 1 || (toMode == 7 && toReg >= 2)) continue; + if(fromMode == 7 && fromReg >= 5) continue; EffectiveAddress to{toMode, toReg}; EffectiveAddress from{fromMode, fromReg}; @@ -189,6 +329,7 @@ M68K::M68K() { for(uint3 mode : range(8)) for(uint3 reg : range(8)) { auto opcode = pattern("00++ ---0 01-- ----") | areg << 9 | mode << 3 | reg << 0; + if(mode == 7 && reg >= 5) continue; AddressRegister ar{areg}; EffectiveAddress ea{mode, reg}; @@ -202,7 +343,7 @@ M68K::M68K() { for(uint3 reg : range(8)) { auto opcode = pattern("0100 1-00 1+-- ----") | direction << 10 | mode << 3 | reg << 0; if(direction == 0 && (mode <= 1 || mode == 3 || (mode == 7 && reg >= 2))); - if(direction == 1 && (mode <= 1 || mode == 4 || (mode == 7 && reg == 4))); + if(direction == 1 && (mode <= 1 || mode == 4 || (mode == 7 && reg >= 4))); EffectiveAddress ea{mode, reg}; bind(opcode | 0 << 6, MOVEM, direction, ea); @@ -232,7 +373,7 @@ M68K::M68K() { for(uint3 mode : range(8)) for(uint3 reg : range(8)) { auto opcode = pattern("0100 0100 11-- ----") | mode << 3 | reg << 0; - if(mode == 1) continue; + if(mode == 1 || (mode == 7 && reg >= 5)) continue; EffectiveAddress ea{mode, reg}; bind(opcode, MOVE_TO_CCR, ea); @@ -242,7 +383,7 @@ M68K::M68K() { for(uint3 mode : range(8)) for(uint3 reg : range(8)) { auto opcode = pattern("0100 0110 11-- ----") | mode << 3 | reg << 0; - if(mode == 1) continue; + if(mode == 1 || (mode == 7 && reg >= 5)) continue; EffectiveAddress ea{mode, reg}; bind(opcode, MOVE_TO_SR, ea); @@ -275,12 +416,164 @@ M68K::M68K() { bind(opcode, ORI_TO_SR); } + //ROL (immediate) + for(uint3 count : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---1 ++01 1---") | count << 9 | dreg << 0; + + auto shift = count ? (uint4)count : (uint4)8; + DataRegister modify{dreg}; + bind(opcode | 0 << 6, ROL, shift, modify); + bind(opcode | 1 << 6, ROL, shift, modify); + bind(opcode | 2 << 6, ROL, shift, modify); + } + + //ROL (register) + for(uint3 sreg : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---1 ++11 1---") | sreg << 9 | dreg << 0; + + DataRegister shift{sreg}; + DataRegister modify{dreg}; + bind(opcode | 0 << 6, ROL, shift, modify); + bind(opcode | 1 << 6, ROL, shift, modify); + bind(opcode | 2 << 6, ROL, shift, modify); + } + + //ROL (effective address) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("1110 0111 11-- ----") | mode << 3 | reg << 0; + if(mode <= 1 || (mode == 7 && reg >= 2)) continue; + + EffectiveAddress modify{mode, reg}; + bind(opcode, ROL, modify); + } + + //ROR (immediate) + for(uint3 count : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---0 ++01 1---") | count << 9 | dreg << 0; + + auto shift = count ? (uint4)count : (uint4)8; + DataRegister modify{dreg}; + bind(opcode | 0 << 6, ROR, shift, modify); + bind(opcode | 1 << 6, ROR, shift, modify); + bind(opcode | 2 << 6, ROR, shift, modify); + } + + //ROR (register) + for(uint3 sreg : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---0 ++11 1---") | sreg << 9 | dreg << 0; + + DataRegister shift{sreg}; + DataRegister modify{dreg}; + bind(opcode | 0 << 6, ROR, shift, modify); + bind(opcode | 1 << 6, ROR, shift, modify); + bind(opcode | 2 << 6, ROR, shift, modify); + } + + //ROR (effective address) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("1110 0110 11-- ----") | mode << 3 | reg << 0; + if(mode <= 1 || (mode == 7 && reg >= 2)) continue; + + EffectiveAddress modify{mode, reg}; + bind(opcode, ROR, modify); + } + + //ROXL (immediate) + for(uint3 count : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---1 ++01 0---") | count << 9 | dreg << 0; + + auto shift = count ? (uint4)count : (uint4)8; + DataRegister modify{dreg}; + bind(opcode | 0 << 6, ROXL, shift, modify); + bind(opcode | 1 << 6, ROXL, shift, modify); + bind(opcode | 2 << 6, ROXL, shift, modify); + } + + //ROXL (register) + for(uint3 sreg : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---1 ++11 0---") | sreg << 9 | dreg << 0; + + DataRegister shift{sreg}; + DataRegister modify{dreg}; + bind(opcode | 0 << 6, ROXL, shift, modify); + bind(opcode | 1 << 6, ROXL, shift, modify); + bind(opcode | 2 << 6, ROXL, shift, modify); + } + + //ROXL (effective address) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("1110 0101 11-- ----") | mode << 3 | reg << 0; + if(mode <= 1 || (mode == 7 && reg >= 2)) continue; + + EffectiveAddress modify{mode, reg}; + bind(opcode, ROXL, modify); + } + + //ROXR (immediate) + for(uint3 count : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---0 ++01 0---") | count << 9 | dreg << 0; + + auto shift = count ? (uint4)count : (uint4)8; + DataRegister modify{dreg}; + bind(opcode | 0 << 6, ROXR, shift, modify); + bind(opcode | 1 << 6, ROXR, shift, modify); + bind(opcode | 2 << 6, ROXR, shift, modify); + } + + //ROXR (register) + for(uint3 sreg : range(8)) + for(uint3 dreg : range(8)) { + auto opcode = pattern("1110 ---0 ++11 0---") | sreg << 9 | dreg << 0; + + DataRegister shift{sreg}; + DataRegister modify{dreg}; + bind(opcode | 0 << 6, ROXR, shift, modify); + bind(opcode | 1 << 6, ROXR, shift, modify); + bind(opcode | 2 << 6, ROXR, shift, modify); + } + + //ROXR (effective address) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("1110 0100 11-- ----") | mode << 3 | reg << 0; + if(mode <= 1 || (mode == 7 && reg >= 2)) continue; + + EffectiveAddress modify{mode, reg}; + bind(opcode, ROXR, modify); + } + //RTS { auto opcode = pattern("0100 1110 0111 0101"); bind(opcode, RTS); } + //SUBQ + for(uint3 data : range(8)) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("0101 ---1 ++-- ----") | data << 9 | mode << 3 | reg << 0; + if(mode == 7 && reg >= 2) continue; + + auto immediate = data ? (uint4)data : (uint4)8; + EffectiveAddress ea{mode, reg}; + bind(opcode | 0 << 6, SUBQ, immediate, ea); + bind(opcode | 1 << 6, SUBQ, immediate, ea); + bind(opcode | 2 << 6, SUBQ, immediate, ea); + + if(mode == 1) unbind(opcode | 0 << 6); + } + //TST for(uint3 mode : range(8)) for(uint3 reg : range(8)) { diff --git a/higan/processor/m68k/instructions.cpp b/higan/processor/m68k/instructions.cpp index d8e995f9..95af4643 100644 --- a/higan/processor/m68k/instructions.cpp +++ b/higan/processor/m68k/instructions.cpp @@ -22,10 +22,20 @@ auto M68K::testCondition(uint4 condition) -> bool { // +template<> auto M68K::bytes() -> uint { return 1; } +template<> auto M68K::bytes() -> uint { return 2; } +template<> auto M68K::bytes() -> uint { return 4; } + template<> auto M68K::bits() -> uint { return 8; } template<> auto M68K::bits() -> uint { return 16; } template<> auto M68K::bits() -> uint { return 32; } +template auto M68K::lsb() -> uint32 { return 1; } + +template<> auto M68K::msb() -> uint32 { return 0x80; } +template<> auto M68K::msb() -> uint32 { return 0x8000; } +template<> auto M68K::msb() -> uint32 { return 0x80000000; } + template<> auto M68K::mask() -> uint32 { return 0xff; } template<> auto M68K::mask() -> uint32 { return 0xffff; } template<> auto M68K::mask() -> uint32 { return 0xffffffff; } @@ -38,14 +48,6 @@ template<> auto M68K::sign(uint32 data) -> int32 { return (int8)data; } template<> auto M68K::sign(uint32 data) -> int32 { return (int16)data; } template<> auto M68K::sign(uint32 data) -> int32 { return (int32)data; } -template auto M68K::carry(uint32 result, uint32 source) -> bool { - return clip(result) < clip(source); -} - -template auto M68K::overflow(uint32 result, uint32 source, uint32 target) -> bool { - return sign((target ^ source) & (target ^ result)) < 0; -} - template auto M68K::zero(uint32 result) -> bool { return clip(result) == 0; } @@ -57,9 +59,7 @@ template auto M68K::negative(uint32 result) -> bool { // template auto M68K::instructionADD(DataRegister dr, uint1 direction, EffectiveAddress ea) -> void { - uint32 source; - uint32 target; - uint32 result; + uint64 source, target, result; if(direction == 0) { source = read(ea); @@ -73,10 +73,10 @@ template auto M68K::instructionADD(DataRegister dr, uint1 direction, write(ea, result); } - r.c = carry(result, source); - r.v = overflow(result, source, target); - r.z = zero(result); - r.n = negative(result); + r.c = sign(result >> 1) < 0; + r.v = sign(~(target ^ source) & (target ^ result)) < 0; + r.z = clip(result) == 0; + r.n = sign(result) < 0; r.x = r.c; } @@ -104,12 +104,85 @@ auto M68K::instructionANDI_TO_SR() -> void { writeSR(readSR() & data); } +template auto M68K::ASL(uint32 result, uint shift) -> uint32 { + bool carry = false; + uint32 overflow = 0; + for(auto _ : range(shift)) { + carry = result & msb(); + uint32 before = result; + result <<= 1; + overflow |= before ^ result; + } + + r.c = carry; + r.v = sign(overflow) < 0; + r.z = clip(result) == 0; + r.n = sign(result) < 0; + if(shift) r.x = r.c; + + return clip(result); +} + +template auto M68K::instructionASL(uint4 shift, DataRegister modify) -> void { + auto result = ASL(read(modify), shift); + write(modify, result); +} + +template auto M68K::instructionASL(DataRegister shift, DataRegister modify) -> void { + auto count = read(shift) & 63; + auto result = ASL(read(modify), count); + write(modify, result); +} + +auto M68K::instructionASL(EffectiveAddress modify) -> void { + auto result = ASL(read(modify), 1); + write(modify, result); +} + +template auto M68K::ASR(uint32 result, uint shift) -> uint32 { + bool carry = false; + uint32 overflow = 0; + for(auto _ : range(shift)) { + carry = result & lsb(); + uint32 before = result; + result = sign(result) >> 1; + overflow |= before ^ result; + } + + r.c = carry; + r.v = sign(overflow) < 0; + r.z = clip(result) == 0; + r.n = sign(result) < 0; + if(shift) r.x = r.c; + + return clip(result); +} + +template auto M68K::instructionASR(uint4 shift, DataRegister modify) -> void { + auto result = ASR(read(modify), shift); + write(modify, result); +} + +template auto M68K::instructionASR(DataRegister shift, DataRegister modify) -> void { + auto count = read(shift) & 63; + auto result = ASR(read(modify), count); + write(modify, result); +} + +auto M68K::instructionASR(EffectiveAddress modify) -> void { + auto result = ASR(read(modify), 1); + write(modify, result); +} + auto M68K::instructionBCC(uint4 condition, uint8 displacement) -> void { - auto extension = readPC(); + auto extension = readPC(); if(condition == 1) push(r.pc); - r.pc -= 2; - if(condition >= 2 && !testCondition(condition)) return; //0 = BRA; 1 = BSR - r.pc += displacement ? sign(displacement) : sign(extension); + if(condition >= 2 && !testCondition(condition)) { //0 = BRA; 1 = BSR + if(displacement) r.pc -= 2; + } else { + r.pc -= 2; + r.pc += displacement ? sign(displacement) : sign(extension); + } } template auto M68K::instructionBTST(DataRegister dr, EffectiveAddress ea) -> void { @@ -139,22 +212,22 @@ template auto M68K::instructionCLR(EffectiveAddress ea) -> void { } template auto M68K::instructionCMP(DataRegister dr, EffectiveAddress ea) -> void { - auto source = read(ea); - auto target = read(dr); - auto result = target - source; + uint64 source = read(ea); + uint64 target = read(dr); + uint64 result = target - source; - r.c = carry(result, source); - r.v = overflow(result, source, target); - r.z = zero(result); - r.n = negative(result); + r.c = sign(result >> 1) < 0; + r.v = sign((target ^ source) & (target ^ result)) < 0; + r.z = clip(result) == 0; + r.n = sign(result) < 0; } auto M68K::instructionDBCC(uint4 condition, DataRegister dr) -> void { - auto displacement = (int16)readPC(); + auto displacement = readPC(); if(!testCondition(condition)) { uint16 result = read(dr); write(dr, result - 1); - if(result) r.pc -= 2, r.pc += displacement; + if(result) r.pc -= 2, r.pc += sign(displacement); } } @@ -174,6 +247,70 @@ auto M68K::instructionLEA(AddressRegister ar, EffectiveAddress ea) -> void { write(ar, fetch(ea)); } +template auto M68K::LSL(uint32 result, uint shift) -> uint32 { + bool carry = false; + for(auto _ : range(shift)) { + carry = result & msb(); + result <<= 1; + } + + r.c = carry; + r.v = 0; + r.z = clip(result) == 0; + r.n = sign(result) < 0; + if(shift) r.x = r.c; + + return clip(result); +} + +template auto M68K::instructionLSL(uint4 immediate, DataRegister dr) -> void { + auto result = LSL(read(dr), immediate); + write(dr, result); +} + +template auto M68K::instructionLSL(DataRegister sr, DataRegister dr) -> void { + auto shift = read(sr) & 63; + auto result = LSL(read(dr), shift); + write(dr, result); +} + +auto M68K::instructionLSL(EffectiveAddress ea) -> void { + auto result = LSL(read(ea), 1); + write(ea, result); +} + +template auto M68K::LSR(uint32 result, uint shift) -> uint32 { + bool carry = false; + for(auto _ : range(shift)) { + carry = result & lsb(); + result >>= 1; + } + + r.c = carry; + r.v = 0; + r.z = clip(result) == 0; + r.n = sign(result) < 0; + if(shift) r.x = r.c; + + return clip(result); +} + +template auto M68K::instructionLSR(uint4 immediate, DataRegister dr) -> void { + auto result = LSR(read(dr), immediate); + write(dr, result); +} + +template auto M68K::instructionLSR(DataRegister shift, DataRegister dr) -> void { + auto count = read(shift) & 63; + auto result = LSR(read(dr), count); + write(dr, result); +} + +auto M68K::instructionLSR(EffectiveAddress ea) -> void { + auto result = LSR(read(ea), 1); + write(ea, result); +} + template auto M68K::instructionMOVE(EffectiveAddress to, EffectiveAddress from) -> void { auto data = read(from); write(to, data); @@ -191,25 +328,33 @@ template auto M68K::instructionMOVEA(AddressRegister ar, EffectiveAdd template auto M68K::instructionMOVEM(uint1 direction, EffectiveAddress ea) -> void { auto list = readPC(); - auto addr = fetch(ea); + auto addr = fetch(ea); - 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(16)) { + if(!list.bit(n)) continue; + + //pre-decrement mode traverses registers in reverse order {A7-A0, D7-D0} + uint index = ea.mode == AddressRegisterIndirectWithPreDecrement ? 15 - n : n; + + if(ea.mode == AddressRegisterIndirectWithPreDecrement) addr -= bytes(); + + if(direction == 0) { + auto data = index < 8 ? read(DataRegister{index}) : read(AddressRegister{index}); + write(addr, data); + } else { + auto data = read(addr); + data = sign(data); + index < 8 ? write(DataRegister{index}, data) : write(AddressRegister{index}, data); + } + + if(ea.mode == AddressRegisterIndirectWithPostIncrement) addr += bytes(); } - for(uint n : range(8)) { - if(!list.bit(8 + n)) continue; - write(AddressRegister{n}, read(addr)); - addr += Size == Long ? 4 : 2; - } - - flush(ea, addr); + flush(ea, addr); } auto M68K::instructionMOVEQ(DataRegister dr, uint8 immediate) -> void { - write(dr, immediate); + write(dr, immediate); r.c = 0; r.v = 0; @@ -259,10 +404,153 @@ auto M68K::instructionORI_TO_SR() -> void { writeSR(readSR() | data); } +template auto M68K::ROL(uint32 result, uint shift) -> uint32 { + bool carry = false; + for(auto _ : range(shift)) { + carry = result & msb(); + result = result << 1 | carry; + } + + r.c = carry; + r.v = 0; + r.z = clip(result) == 0; + r.n = sign(result) < 0; + + return clip(result); +} + +template auto M68K::instructionROL(uint4 shift, DataRegister modify) -> void { + auto result = ROL(read(modify), shift); + write(modify, result); +} + +template auto M68K::instructionROL(DataRegister shift, DataRegister modify) -> void { + auto count = read(shift) & 63; + auto result = ROL(read(modify), count); + write(modify, result); +} + +auto M68K::instructionROL(EffectiveAddress modify) -> void { + auto result = ROL(read(modify), 1); + write(modify, result); +} + +template auto M68K::ROR(uint32 result, uint shift) -> uint32 { + bool carry = false; + for(auto _ : range(shift)) { + carry = result & lsb(); + result >>= 1; + if(carry) result |= msb(); + } + + r.c = carry; + r.v = 0; + r.z = clip(result) == 0; + r.n = sign(result) < 0; + + return clip(result); +} + +template auto M68K::instructionROR(uint4 shift, DataRegister modify) -> void { + auto result = ROR(read(modify), shift); + write(modify, result); +} + +template auto M68K::instructionROR(DataRegister shift, DataRegister modify) -> void { + auto count = read(shift) & 63; + auto result = ROR(read(modify), count); + write(modify, result); +} + +auto M68K::instructionROR(EffectiveAddress modify) -> void { + auto result = ROR(read(modify), 1); + write(modify, result); +} + +template auto M68K::ROXL(uint32 result, uint shift) -> uint32 { + bool carry = r.x; + for(auto _ : range(shift)) { + bool extend = carry; + carry = result & msb(); + result = result << 1 | extend; + } + + r.c = carry; + r.v = 0; + r.z = clip(result) == 0; + r.n = sign(result) < 0; + r.x = r.c; + + return clip(result); +} + +template auto M68K::instructionROXL(uint4 shift, DataRegister modify) -> void { + auto result = ROXL(read(modify), shift); + write(modify, result); +} + +template auto M68K::instructionROXL(DataRegister shift, DataRegister modify) -> void { + auto count = read(shift) & 63; + auto result = ROXL(read(modify), count); + write(modify, result); +} + +auto M68K::instructionROXL(EffectiveAddress modify) -> void { + auto result = ROXL(read(modify), 1); + write(modify, result); +} + +template auto M68K::ROXR(uint32 result, uint shift) -> uint32 { + bool carry = r.x; + for(auto _ : range(shift)) { + bool extend = carry; + carry = result & lsb(); + result >>= 1; + if(extend) result |= msb(); + } + + r.c = carry; + r.v = 0; + r.z = clip(result) == 0; + r.n = sign(result) < 0; + r.x = r.c; + + return clip(result); +} + +template auto M68K::instructionROXR(uint4 shift, DataRegister modify) -> void { + auto result = ROXR(read(modify), shift); + write(modify, result); +} + +template auto M68K::instructionROXR(DataRegister shift, DataRegister modify) -> void { + auto count = read(shift) & 63; + auto result = ROXR(read(modify), count); + write(modify, result); +} + +auto M68K::instructionROXR(EffectiveAddress modify) -> void { + auto result = ROXR(read(modify), 1); + write(modify, result); +} + auto M68K::instructionRTS() -> void { r.pc = pop(); } +template auto M68K::instructionSUBQ(uint4 immediate, EffectiveAddress ea) -> void { + uint64 target = read(ea); + uint64 source = immediate; + uint64 result = target - source; + write(ea, result); + + r.c = sign(result >> 1) < 0; + r.v = sign((target ^ source) & (target ^ result)) < 0; + r.z = clip(result) == 0; + r.n = sign(result) < 0; + r.x = r.c; +} + template auto M68K::instructionTST(EffectiveAddress ea) -> void { auto data = read(ea); diff --git a/higan/processor/m68k/m68k.cpp b/higan/processor/m68k/m68k.cpp index 22fa3f12..1b0c5c69 100644 --- a/higan/processor/m68k/m68k.cpp +++ b/higan/processor/m68k/m68k.cpp @@ -29,7 +29,7 @@ auto M68K::reset() -> void { r.z = 0; r.n = 0; r.x = 0; - r.i = 0; + r.i = 7; r.s = 1; r.t = 0; } diff --git a/higan/processor/m68k/m68k.hpp b/higan/processor/m68k/m68k.hpp index 28dc7fc0..0c3443b0 100644 --- a/higan/processor/m68k/m68k.hpp +++ b/higan/processor/m68k/m68k.hpp @@ -86,13 +86,14 @@ struct M68K { //instructions.cpp auto testCondition(uint4 condition) -> bool; + template auto bytes() -> uint; template auto bits() -> uint; + template auto lsb() -> uint32; + template auto msb() -> uint32; template auto mask() -> uint32; template auto clip(uint32 data) -> uint32; template auto sign(uint32 data) -> int32; - template auto carry(uint32 result, uint32 source) -> bool; - template auto overflow(uint32 result, uint32 source, uint32 target) -> bool; template auto zero(uint32 result) -> bool; template auto negative(uint32 result) -> bool; @@ -100,6 +101,14 @@ struct M68K { template auto instructionANDI(EffectiveAddress ea) -> void; auto instructionANDI_TO_CCR() -> void; auto instructionANDI_TO_SR() -> void; + template auto ASL(uint32 result, uint shift) -> uint32; + template auto instructionASL(uint4 shift, DataRegister modify) -> void; + template auto instructionASL(DataRegister shift, DataRegister modify) -> void; + auto instructionASL(EffectiveAddress modify) -> void; + template auto ASR(uint32 result, uint shift) -> uint32; + template auto instructionASR(uint4 shift, DataRegister modify) -> void; + template auto instructionASR(DataRegister shift, DataRegister modify) -> void; + auto instructionASR(EffectiveAddress modify) -> void; auto instructionBCC(uint4 condition, uint8 displacement) -> void; template auto instructionBTST(DataRegister dr, EffectiveAddress ea) -> void; template auto instructionBTST(EffectiveAddress ea) -> void; @@ -109,6 +118,14 @@ struct M68K { auto instructionEORI_TO_CCR() -> void; auto instructionEORI_TO_SR() -> void; auto instructionLEA(AddressRegister ar, EffectiveAddress ea) -> void; + template auto LSL(uint32 result, uint shift) -> uint32; + template auto instructionLSL(uint4 immediate, DataRegister dr) -> void; + template auto instructionLSL(DataRegister sr, DataRegister dr) -> void; + auto instructionLSL(EffectiveAddress ea) -> void; + template auto LSR(uint32 result, uint shift) -> uint32; + template auto instructionLSR(uint4 immediate, DataRegister dr) -> void; + template auto instructionLSR(DataRegister shift, DataRegister dr) -> void; + auto instructionLSR(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; @@ -120,7 +137,24 @@ struct M68K { auto instructionNOP() -> void; auto instructionORI_TO_CCR() -> void; auto instructionORI_TO_SR() -> void; + template auto ROL(uint32 result, uint shift) -> uint32; + template auto instructionROL(uint4 shift, DataRegister modify) -> void; + template auto instructionROL(DataRegister shift, DataRegister modify) -> void; + auto instructionROL(EffectiveAddress modify) -> void; + template auto ROR(uint32 result, uint shift) -> uint32; + template auto instructionROR(uint4 shift, DataRegister modify) -> void; + template auto instructionROR(DataRegister shift, DataRegister modify) -> void; + auto instructionROR(EffectiveAddress modify) -> void; + template auto ROXL(uint32 result, uint shift) -> uint32; + template auto instructionROXL(uint4 shift, DataRegister modify) -> void; + template auto instructionROXL(DataRegister shift, DataRegister modify) -> void; + auto instructionROXL(EffectiveAddress modify) -> void; + template auto ROXR(uint32 result, uint shift) -> uint32; + template auto instructionROXR(uint4 shift, DataRegister modify) -> void; + template auto instructionROXR(DataRegister shift, DataRegister modify) -> void; + auto instructionROXR(EffectiveAddress modify) -> void; auto instructionRTS() -> void; + template auto instructionSUBQ(uint4 immediate, EffectiveAddress ea) -> void; template auto instructionTST(EffectiveAddress ea) -> void; //disassembler.cpp @@ -154,6 +188,12 @@ private: template auto disassembleANDI(EffectiveAddress ea) -> string; auto disassembleANDI_TO_CCR() -> string; auto disassembleANDI_TO_SR() -> string; + template auto disassembleASL(uint4 shift, DataRegister modify) -> string; + template auto disassembleASL(DataRegister shift, DataRegister modify) -> string; + auto disassembleASL(EffectiveAddress modify) -> string; + template auto disassembleASR(uint4 shift, DataRegister modify) -> string; + template auto disassembleASR(DataRegister shift, DataRegister modify) -> string; + auto disassembleASR(EffectiveAddress modify) -> string; auto disassembleBCC(uint4 condition, uint8 displacement) -> string; template auto disassembleBTST(DataRegister dr, EffectiveAddress ea) -> string; template auto disassembleBTST(EffectiveAddress ea) -> string; @@ -163,6 +203,12 @@ private: auto disassembleEORI_TO_CCR() -> string; auto disassembleEORI_TO_SR() -> string; auto disassembleLEA(AddressRegister ar, EffectiveAddress ea) -> string; + template auto disassembleLSL(uint4 immediate, DataRegister dr) -> string; + template auto disassembleLSL(DataRegister sr, DataRegister dr) -> string; + auto disassembleLSL(EffectiveAddress ea) -> string; + template auto disassembleLSR(uint4 immediate, DataRegister dr) -> string; + template auto disassembleLSR(DataRegister shift, DataRegister dr) -> string; + auto disassembleLSR(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; @@ -174,17 +220,29 @@ private: auto disassembleNOP() -> string; auto disassembleORI_TO_CCR() -> string; auto disassembleORI_TO_SR() -> string; + template auto disassembleROL(uint4 shift, DataRegister modify) -> string; + template auto disassembleROL(DataRegister shift, DataRegister modify) -> string; + auto disassembleROL(EffectiveAddress modify) -> string; + template auto disassembleROR(uint4 shift, DataRegister modify) -> string; + template auto disassembleROR(DataRegister shift, DataRegister modify) -> string; + auto disassembleROR(EffectiveAddress modify) -> string; + template auto disassembleROXL(uint4 shift, DataRegister modify) -> string; + template auto disassembleROXL(DataRegister shift, DataRegister modify) -> string; + auto disassembleROXL(EffectiveAddress modify) -> string; + template auto disassembleROXR(uint4 shift, DataRegister modify) -> string; + template auto disassembleROXR(DataRegister shift, DataRegister modify) -> string; + auto disassembleROXR(EffectiveAddress modify) -> string; auto disassembleRTS() -> string; + template auto disassembleSUBQ(uint4 immediate, EffectiveAddress ea) -> string; template auto disassembleTST(EffectiveAddress ea) -> string; template auto _read(uint32 addr) -> uint32; template auto _readPC() -> uint32; - auto _register(DataRegister dr) -> string; - auto _register(AddressRegister ar) -> string; + auto _dataRegister(DataRegister dr) -> string; + auto _addressRegister(AddressRegister ar) -> string; template auto _immediate() -> string; template auto _address(EffectiveAddress& ea) -> string; - template auto _read(EffectiveAddress& ea) -> string; - template auto _write(EffectiveAddress& ea) -> string; + template auto _effectiveAddress(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 f02c66af..811ba080 100644 --- a/higan/processor/m68k/memory.cpp +++ b/higan/processor/m68k/memory.cpp @@ -81,11 +81,11 @@ template<> auto M68K::readPC() -> uint32 { template auto M68K::pop() -> uint32 { auto data = read((uint32)r.a[7]); - r.a[7] += Size == Long ? 4 : 2; + r.a[7] += bytes(); return data; } template auto M68K::push(uint32 data) -> void { - r.a[7] -= Size == Long ? 4 : 2; + r.a[7] -= bytes(); return write((uint32)r.a[7], data); }