From 306cac2b54bcfe251271066d1397ad51fd8a4422 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Tue, 26 Jul 2016 20:46:43 +1000 Subject: [PATCH] Update to v100r13 release. byuu says: Changelog: M68K improvements, new instructions added. --- higan/emulator/emulator.hpp | 2 +- higan/processor/m68k/disassembler.cpp | 31 ++++++++- higan/processor/m68k/instruction.cpp | 99 +++++++++++++++++++++++++-- higan/processor/m68k/instructions.cpp | 89 +++++++++++++++++++----- higan/processor/m68k/m68k.hpp | 16 +++++ 5 files changed, 211 insertions(+), 26 deletions(-) diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 89b246d6..4bf27581 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.12"; + static const string Version = "100.13"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/processor/m68k/disassembler.cpp b/higan/processor/m68k/disassembler.cpp index 83e5e776..26fb1e62 100644 --- a/higan/processor/m68k/disassembler.cpp +++ b/higan/processor/m68k/disassembler.cpp @@ -41,6 +41,7 @@ template auto M68K::_effectiveAddress(EffectiveAddress& ea) -> string 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 == 7) return {"($", hex((int16)_readPC(), 6L), ")"}; if(ea.mode == 8) return {"($", hex(_readPC(), 6L), ")"}; if(ea.mode == 11) return {"#$", hex(_readPC(), 2 << Size)}; return "???"; @@ -99,6 +100,18 @@ template auto M68K::disassembleADD(DataRegister dr, uint1 direction, } } +template auto M68K::disassembleADDA(AddressRegister ar, EffectiveAddress ea) -> string { + return {"adda", _suffix(), " ", _effectiveAddress(ea), ",", _addressRegister(ar)}; +} + +template auto M68K::disassembleADDI(EffectiveAddress ea) -> string { + return {"addi", _suffix(), " ", _immediate(), ",", _effectiveAddress(ea)}; +} + +template auto M68K::disassembleADDQ(uint4 immediate, EffectiveAddress modify) -> string { + return {"addq", _suffix(), " #", immediate, ",", _effectiveAddress(modify)}; +} + template auto M68K::disassembleANDI(EffectiveAddress ea) -> string { return {"andi", _suffix(), " ", _immediate(), ",", _effectiveAddress(ea)}; } @@ -155,7 +168,19 @@ template auto M68K::disassembleCLR(EffectiveAddress ea) -> string { } template auto M68K::disassembleCMP(DataRegister dr, EffectiveAddress ea) -> string { - return {"cmp", _suffix(), " ", _effectiveAddress(ea), ",", _dataRegister(dr)}; + return {"cmp", _suffix(), " ", _effectiveAddress(ea), ",", _dataRegister(dr)}; +} + +template auto M68K::disassembleCMPA(AddressRegister ar, EffectiveAddress ea) -> string { + return {"cmpa", _suffix(), " ", _effectiveAddress(ea), ",", _addressRegister(ar)}; +} + +template auto M68K::disassembleCMPI(EffectiveAddress ea) -> string { + return {"cmpi", _suffix(), " ", _immediate(), ",", _effectiveAddress(ea)}; +} + +template auto M68K::disassembleCMPM(EffectiveAddress ax, EffectiveAddress ay) -> string { + return {"cmpm", _suffix(), " ", _effectiveAddress(ay), ",", _effectiveAddress(ax)}; } auto M68K::disassembleDBCC(uint4 condition, DataRegister dr) -> string { @@ -172,6 +197,10 @@ auto M68K::disassembleEORI_TO_SR() -> string { return {"eori ", _immediate(), ",sr"}; } +auto M68K::disassembleJSR(EffectiveAddress target) -> string { + return {"jsr ", _effectiveAddress(target)}; +} + auto M68K::disassembleLEA(AddressRegister ar, EffectiveAddress ea) -> string { return {"lea ", _address(ea), ",", _addressRegister(ar)}; } diff --git a/higan/processor/m68k/instruction.cpp b/higan/processor/m68k/instruction.cpp index 8fa0756d..5a39868c 100644 --- a/higan/processor/m68k/instruction.cpp +++ b/higan/processor/m68k/instruction.cpp @@ -9,13 +9,13 @@ auto M68K::trap() -> void { auto M68K::instruction() -> void { instructionsExecuted++; -// if(instructionsExecuted >= 851570) trap(); +//if(instructionsExecuted >= 2000010) trap(); -// if(instructionsExecuted >= 851530) { -// print(disassembleRegisters(), "\n"); -// print(disassemble(r.pc), "\n"); -// print("\n"); -// } +//if(instructionsExecuted >= 2000000) { +// print(disassembleRegisters(), "\n"); +// print(disassemble(r.pc), "\n"); +// print("\n"); +//} opcode = readPC(); return instructionTable[opcode](); @@ -53,6 +53,47 @@ M68K::M68K() { if(direction == 0 && mode == 1) unbind(opcode | 0 << 6); } + //ADDA + for(uint3 areg : range(8)) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("1101 ---+ 11-- ----") | areg << 9 | mode << 3 | reg << 0; + if(mode == 7 && reg >= 5) continue; + + AddressRegister ar{areg}; + EffectiveAddress ea{mode, reg}; + bind(opcode | 0 << 8, ADDA, ar, ea); + bind(opcode | 1 << 8, ADDA, ar, ea); + } + + //ADDI + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("0000 0110 ++-- ----") | mode << 3 | reg << 0; + if(mode == 1 || (mode == 7 && reg >= 2)) continue; + + EffectiveAddress modify{mode, reg}; + bind(opcode | 0 << 6, ADDI, modify); + bind(opcode | 1 << 6, ADDI, modify); + bind(opcode | 2 << 6, ADDI, modify); + } + + //ADDQ + for(uint3 data : range(8)) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("0101 ---0 ++-- ----") | data << 9 | mode << 3 | reg << 0; + if(mode == 7 && reg >= 2) continue; + + uint4 immediate = data ? (uint4)data : (uint4)8; + EffectiveAddress modify{mode, reg}; + bind(opcode | 0 << 6, ADDQ, immediate, modify); + bind(opcode | 1 << 6, ADDQ, immediate, modify); + bind(opcode | 2 << 6, ADDQ, immediate, modify); + + if(mode == 1) unbind(opcode | 0 << 6); + } + //ANDI for(uint3 mode : range(8)) for(uint3 reg : range(8)) { @@ -205,6 +246,42 @@ M68K::M68K() { if(mode == 1) unbind(opcode | 0 << 6); } + //CMPA + for(uint3 areg : range(8)) + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("1011 ---+ 11-- ----") | areg << 9 | mode << 3 | reg << 0; + + AddressRegister ar{areg}; + EffectiveAddress ea{mode, reg}; + bind(opcode | 0 << 8, CMPA, ar, ea); + bind(opcode | 1 << 8, CMPA, ar, ea); + } + + //CMPI + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("0000 1100 ++-- ----") | mode << 3 | reg << 0; + if(mode == 1 || (mode == 7 && reg >= 2)) continue; + + EffectiveAddress ea{mode, reg}; + bind(opcode | 0 << 6, CMPI, ea); + bind(opcode | 1 << 6, CMPI, ea); + bind(opcode | 2 << 6, CMPI, ea); + } + + //CMPM + for(uint3 xreg : range(8)) + for(uint3 yreg : range(8)) { + auto opcode = pattern("1011 ---1 ++00 1---") | xreg << 9 | yreg << 0; + + EffectiveAddress ax{AddressRegisterIndirectWithPostIncrement, xreg}; + EffectiveAddress ay{AddressRegisterIndirectWithPostIncrement, yreg}; + bind(opcode | 0 << 6, CMPM, ax, ay); + bind(opcode | 1 << 6, CMPM, ax, ay); + bind(opcode | 2 << 6, CMPM, ax, ay); + } + //DBCC for(uint4 condition : range(16)) for(uint3 dreg : range( 8)) { @@ -226,6 +303,16 @@ M68K::M68K() { bind(opcode, EORI_TO_SR); } + //JSR + for(uint3 mode : range(8)) + for(uint3 reg : range(8)) { + auto opcode = pattern("0100 1110 10-- ----") | mode << 3 | reg << 0; + if(mode <= 1 || mode == 3 || mode == 4 || (mode == 7 && reg >= 4)) continue; + + EffectiveAddress target{mode, reg}; + bind(opcode, JSR, target); + } + //LEA for(uint3 areg : range(8)) for(uint3 mode : range(8)) diff --git a/higan/processor/m68k/instructions.cpp b/higan/processor/m68k/instructions.cpp index 95af4643..7f5ca589 100644 --- a/higan/processor/m68k/instructions.cpp +++ b/higan/processor/m68k/instructions.cpp @@ -58,26 +58,50 @@ template auto M68K::negative(uint32 result) -> bool { // -template auto M68K::instructionADD(DataRegister dr, uint1 direction, EffectiveAddress ea) -> void { - uint64 source, target, result; - - if(direction == 0) { - source = read(ea); - target = read(dr); - result = source + target; - write(dr, result); - } else { - source = read(dr); - target = read(ea); - result = source + target; - write(ea, result); - } +template auto M68K::ADD(uint32 source, uint32 target) -> uint32 { + uint64 result = (uint64)source + (uint64)target; 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; + + return clip(result); +} + +template auto M68K::instructionADD(DataRegister dr, uint1 direction, EffectiveAddress ea) -> void { + if(direction == 0) { + auto source = read(ea); + auto target = read(dr); + auto result = ADD(source, target); + write(dr, result); + } else { + auto source = read(dr); + auto target = read(ea); + auto result = ADD(source, target); + write(ea, result); + } +} + +template auto M68K::instructionADDI(EffectiveAddress modify) -> void { + auto source = readPC(); + auto target = read(modify); + auto result = ADD(source, target); + write(modify, result); +} + +template auto M68K::instructionADDA(AddressRegister ar, EffectiveAddress ea) -> void { + auto source = read(ea); + auto target = read(ar); + write(ar, source + target); +} + +template auto M68K::instructionADDQ(uint4 immediate, EffectiveAddress modify) -> void { + auto source = read(modify); + auto target = immediate; + auto result = ADD(source, target); + write(modify, result); } template auto M68K::instructionANDI(EffectiveAddress ea) -> void { @@ -211,15 +235,39 @@ template auto M68K::instructionCLR(EffectiveAddress ea) -> void { r.n = 0; } -template auto M68K::instructionCMP(DataRegister dr, EffectiveAddress ea) -> void { - uint64 source = read(ea); - uint64 target = read(dr); - uint64 result = target - source; +template auto M68K::CMP(uint32 source, uint32 target) -> uint32 { + uint64 result = (uint64)target - (uint64)source; r.c = sign(result >> 1) < 0; r.v = sign((target ^ source) & (target ^ result)) < 0; r.z = clip(result) == 0; r.n = sign(result) < 0; + + return clip(result); +} + +template auto M68K::instructionCMP(DataRegister dr, EffectiveAddress ea) -> void { + auto source = read(ea); + auto target = read(dr); + CMP(source, target); +} + +template auto M68K::instructionCMPA(AddressRegister ar, EffectiveAddress ea) -> void { + auto source = read(ea); + auto target = read(ar); + CMP(source, target); +} + +template auto M68K::instructionCMPI(EffectiveAddress ea) -> void { + auto source = readPC(); + auto target = read(ea); + CMP(source, target); +} + +template auto M68K::instructionCMPM(EffectiveAddress ax, EffectiveAddress ay) -> void { + auto source = read(ay); + auto target = read(ax); + CMP(source, target); } auto M68K::instructionDBCC(uint4 condition, DataRegister dr) -> void { @@ -243,6 +291,11 @@ auto M68K::instructionEORI_TO_SR() -> void { writeSR(readSR() ^ data); } +auto M68K::instructionJSR(EffectiveAddress target) -> void { + push(r.pc); + r.pc = fetch(target); +} + auto M68K::instructionLEA(AddressRegister ar, EffectiveAddress ea) -> void { write(ar, fetch(ea)); } diff --git a/higan/processor/m68k/m68k.hpp b/higan/processor/m68k/m68k.hpp index 0c3443b0..ddb7cb7c 100644 --- a/higan/processor/m68k/m68k.hpp +++ b/higan/processor/m68k/m68k.hpp @@ -97,7 +97,11 @@ struct M68K { template auto zero(uint32 result) -> bool; template auto negative(uint32 result) -> bool; + template auto ADD(uint32 source, uint32 target) -> uint32; template auto instructionADD(DataRegister dr, uint1 direction, EffectiveAddress ea) -> void; + template auto instructionADDA(AddressRegister ar, EffectiveAddress ea) -> void; + template auto instructionADDI(EffectiveAddress modify) -> void; + template auto instructionADDQ(uint4 immediate, EffectiveAddress modify) -> void; template auto instructionANDI(EffectiveAddress ea) -> void; auto instructionANDI_TO_CCR() -> void; auto instructionANDI_TO_SR() -> void; @@ -113,10 +117,15 @@ struct M68K { template auto instructionBTST(DataRegister dr, EffectiveAddress ea) -> void; template auto instructionBTST(EffectiveAddress ea) -> void; template auto instructionCLR(EffectiveAddress ea) -> void; + template auto CMP(uint32 source, uint32 target) -> uint32; template auto instructionCMP(DataRegister dr, EffectiveAddress ea) -> void; + template auto instructionCMPA(AddressRegister ar, EffectiveAddress ea) -> void; + template auto instructionCMPI(EffectiveAddress ea) -> void; + template auto instructionCMPM(EffectiveAddress ax, EffectiveAddress ay) -> void; auto instructionDBCC(uint4 condition, DataRegister dr) -> void; auto instructionEORI_TO_CCR() -> void; auto instructionEORI_TO_SR() -> void; + auto instructionJSR(EffectiveAddress target) -> void; auto instructionLEA(AddressRegister ar, EffectiveAddress ea) -> void; template auto LSL(uint32 result, uint shift) -> uint32; template auto instructionLSL(uint4 immediate, DataRegister dr) -> void; @@ -185,6 +194,9 @@ struct M68K { private: //disassembler.cpp template auto disassembleADD(DataRegister dr, uint1 direction, EffectiveAddress ea) -> string; + template auto disassembleADDA(AddressRegister ar, EffectiveAddress ea) -> string; + template auto disassembleADDI(EffectiveAddress modify) -> string; + template auto disassembleADDQ(uint4 immediate, EffectiveAddress modify) -> string; template auto disassembleANDI(EffectiveAddress ea) -> string; auto disassembleANDI_TO_CCR() -> string; auto disassembleANDI_TO_SR() -> string; @@ -199,9 +211,13 @@ private: template auto disassembleBTST(EffectiveAddress ea) -> string; template auto disassembleCLR(EffectiveAddress ea) -> string; template auto disassembleCMP(DataRegister dr, EffectiveAddress ea) -> string; + template auto disassembleCMPA(AddressRegister ar, EffectiveAddress ea) -> string; + template auto disassembleCMPI(EffectiveAddress ea) -> string; + template auto disassembleCMPM(EffectiveAddress ax, EffectiveAddress ay) -> string; auto disassembleDBCC(uint4 condition, DataRegister dr) -> string; auto disassembleEORI_TO_CCR() -> string; auto disassembleEORI_TO_SR() -> string; + auto disassembleJSR(EffectiveAddress target) -> string; auto disassembleLEA(AddressRegister ar, EffectiveAddress ea) -> string; template auto disassembleLSL(uint4 immediate, DataRegister dr) -> string; template auto disassembleLSL(DataRegister sr, DataRegister dr) -> string;