mirror of https://github.com/bsnes-emu/bsnes.git
Update to v103r03 release.
byuu says: Changelog: - md/psg: fixed output frequency rate regression from v103r02 - processor/m68k: fixed calculations for ABCD, NBCD, SBCD [hex\_usr, SuperMikeMan] - processor/spc700: renamed abbreviated instructions to functional descriptions (eg `XCN` → `ExchangeNibble`) - processor/spc700: removed memory.cpp shorthand functions (fetch, load, store, pull, push) - processor/spc700: updated all instructions to follow cycle behavior as documented by Overload with a logic analyzer Once again, the changes to the SPC700 core are really quite massive. And this time it's not just cosmetic: the idle cycles have been updated to pull from various memory addresses. This is why I removed the shorthand functions -- so that I could handle the at-times very bizarre addresses the SPC700 has on its address bus during its idle cycles. There is one behavior Overload mentioned that I don't emulate ... one of the cycles of the (X) transfer functions seems to not actually access the $f0-ff internal SMP registers? I don't fully understand what Overload is getting at, so I haven't tried to support it just yet. Also, there are limits to logic analyzers. In many cases the same address is read from twice consecutively. It is unclear which of the two reads the SPC700 actually utilizes. I tried to choose the most logical values (usually the first one), but ... I don't know that we'll be able to figure this one out. It's going to be virtually impossible to test this through software, because the PC can't really execute out of registers that have side effects on reads.
This commit is contained in:
parent
3517d5c4a4
commit
78f341489e
|
@ -12,7 +12,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "103.02";
|
||||
static const string Version = "103.03";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -25,7 +25,7 @@ auto PSG::main() -> void {
|
|||
output += levels[noise.volume] * noise.output;
|
||||
|
||||
stream->sample(sclamp<16>(output) / 32768.0);
|
||||
step(1);
|
||||
step(16);
|
||||
}
|
||||
|
||||
auto PSG::step(uint clocks) -> void {
|
||||
|
@ -36,7 +36,7 @@ auto PSG::step(uint clocks) -> void {
|
|||
|
||||
auto PSG::power() -> void {
|
||||
create(PSG::Enter, system.frequency() / 15.0);
|
||||
stream = Emulator::audio.createStream(1, frequency());
|
||||
stream = Emulator::audio.createStream(1, frequency() / 16.0);
|
||||
stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0);
|
||||
stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::LowPass, 2840.0);
|
||||
stream->addFilter(Emulator::Filter::Order::Second, Emulator::Filter::Type::LowPass, 20000.0, 3);
|
||||
|
|
|
@ -54,6 +54,7 @@ auto M68K::instructionABCD(EffectiveAddress with, EffectiveAddress from) -> void
|
|||
auto source = read<Byte>(from);
|
||||
auto target = read<Byte, Hold>(with);
|
||||
auto result = source + target + r.x;
|
||||
bool c = false;
|
||||
bool v = false;
|
||||
|
||||
if(((target ^ source ^ result) & 0x10) || (result & 0x0f) >= 0x0a) {
|
||||
|
@ -65,12 +66,13 @@ auto M68K::instructionABCD(EffectiveAddress with, EffectiveAddress from) -> void
|
|||
if(result >= 0xa0) {
|
||||
auto previous = result;
|
||||
result += 0x60;
|
||||
c = true;
|
||||
v |= ((~previous & 0x80) & (result & 0x80));
|
||||
}
|
||||
|
||||
write<Byte>(with, result);
|
||||
|
||||
r.c = sign<Byte>(result >> 1) < 0;
|
||||
r.c = c;
|
||||
r.v = v;
|
||||
r.z = clip<Byte>(result) ? 0 : r.z;
|
||||
r.n = sign<Byte>(result) < 0;
|
||||
|
@ -754,9 +756,10 @@ auto M68K::instructionMULU(DataRegister with, EffectiveAddress from) -> void {
|
|||
}
|
||||
|
||||
auto M68K::instructionNBCD(EffectiveAddress with) -> void {
|
||||
auto source = 0u;
|
||||
auto target = read<Byte, Hold>(with);
|
||||
auto source = read<Byte, Hold>(with);
|
||||
auto target = 0u;
|
||||
auto result = target - source - r.x;
|
||||
bool c = false;
|
||||
bool v = false;
|
||||
|
||||
const bool adjustLo = (target ^ source ^ result) & 0x10;
|
||||
|
@ -765,21 +768,24 @@ auto M68K::instructionNBCD(EffectiveAddress with) -> void {
|
|||
if(adjustLo) {
|
||||
auto previous = result;
|
||||
result -= 0x06;
|
||||
v |= (previous & 0x80) & (~result & 0x80);
|
||||
c = (~previous & 0x80) & ( result & 0x80);
|
||||
v |= ( previous & 0x80) & (~result & 0x80);
|
||||
}
|
||||
|
||||
if(adjustHi) {
|
||||
auto previous = result;
|
||||
result -= 0x60;
|
||||
c = true;
|
||||
v |= (previous & 0x80) & (~result & 0x80);
|
||||
}
|
||||
|
||||
write<Byte>(with, result);
|
||||
|
||||
r.c = sign<Byte>(result >> 1) < 0;
|
||||
r.c = c;
|
||||
r.v = v;
|
||||
r.z = clip<Byte>(result) ? 0 : r.z;
|
||||
r.n = sign<Byte>(result) < 0;
|
||||
r.x = r.c;
|
||||
}
|
||||
|
||||
template<uint Size> auto M68K::instructionNEG(EffectiveAddress with) -> void {
|
||||
|
@ -1011,6 +1017,7 @@ auto M68K::instructionSBCD(EffectiveAddress with, EffectiveAddress from) -> void
|
|||
auto source = read<Byte>(from);
|
||||
auto target = read<Byte, Hold>(with);
|
||||
auto result = target - source - r.x;
|
||||
bool c = false;
|
||||
bool v = false;
|
||||
|
||||
const bool adjustLo = (target ^ source ^ result) & 0x10;
|
||||
|
@ -1019,21 +1026,24 @@ auto M68K::instructionSBCD(EffectiveAddress with, EffectiveAddress from) -> void
|
|||
if(adjustLo) {
|
||||
auto previous = result;
|
||||
result -= 0x06;
|
||||
v |= (previous & 0x80) & (~result & 0x80);
|
||||
c = (~previous & 0x80) & ( result & 0x80);
|
||||
v |= ( previous & 0x80) & (~result & 0x80);
|
||||
}
|
||||
|
||||
if(adjustHi) {
|
||||
auto previous = result;
|
||||
result -= 0x60;
|
||||
c = true;
|
||||
v |= (previous & 0x80) & (~result & 0x80);
|
||||
}
|
||||
|
||||
write<Byte>(with, result);
|
||||
|
||||
r.c = sign<Byte>(result >> 1) < 0;
|
||||
r.c = c;
|
||||
r.v = v;
|
||||
r.z = clip<Byte>(result) ? 0 : r.z;
|
||||
r.n = sign<Byte>(result) < 0;
|
||||
r.x = r.c;
|
||||
}
|
||||
|
||||
auto M68K::instructionSCC(uint4 condition, EffectiveAddress to) -> void {
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
#define fp(name) &SPC700::algorithm##name
|
||||
|
||||
auto SPC700::instruction() -> void {
|
||||
switch(fetch()) {
|
||||
op(0x00, NOP)
|
||||
op(0x01, JST, 0)
|
||||
op(0x02, SET, 0)
|
||||
op(0x03, BBS, 0)
|
||||
switch(read(PC++)) {
|
||||
op(0x00, NoOperation)
|
||||
op(0x01, CallTable, 0)
|
||||
op(0x02, AbsoluteBitSet, 0, true)
|
||||
op(0x03, BranchBit, 0, true)
|
||||
op(0x04, DirectRead, fp(OR), A)
|
||||
op(0x05, AbsoluteRead, fp(OR), A)
|
||||
op(0x06, IndirectXRead, fp(OR))
|
||||
|
@ -17,12 +17,12 @@ auto SPC700::instruction() -> void {
|
|||
op(0x0b, DirectModify, fp(ASL))
|
||||
op(0x0c, AbsoluteModify, fp(ASL))
|
||||
op(0x0d, Push, P)
|
||||
op(0x0e, TSBAbsolute)
|
||||
op(0x0f, BRK)
|
||||
op(0x0e, TestSetBitsAbsolute, true)
|
||||
op(0x0f, Break)
|
||||
op(0x10, Branch, NF == 0)
|
||||
op(0x11, JST, 1)
|
||||
op(0x12, CLR, 0)
|
||||
op(0x13, BBC, 0)
|
||||
op(0x11, CallTable, 1)
|
||||
op(0x12, AbsoluteBitSet, 0, false)
|
||||
op(0x13, BranchBit, 0, false)
|
||||
op(0x14, DirectIndexedRead, fp(OR), A, X)
|
||||
op(0x15, AbsoluteIndexedRead, fp(OR), X)
|
||||
op(0x16, AbsoluteIndexedRead, fp(OR), Y)
|
||||
|
@ -34,11 +34,11 @@ auto SPC700::instruction() -> void {
|
|||
op(0x1c, ImpliedModify, fp(ASL), A)
|
||||
op(0x1d, ImpliedModify, fp(DEC), X)
|
||||
op(0x1e, AbsoluteRead, fp(CMP), X)
|
||||
op(0x1f, JMPIndirectX)
|
||||
op(0x20, FlagClear, PF)
|
||||
op(0x21, JST, 2)
|
||||
op(0x22, SET, 1)
|
||||
op(0x23, BBS, 1)
|
||||
op(0x1f, JumpIndirectX)
|
||||
op(0x20, FlagSet, PF, false)
|
||||
op(0x21, CallTable, 2)
|
||||
op(0x22, AbsoluteBitSet, 1, true)
|
||||
op(0x23, BranchBit, 1, true)
|
||||
op(0x24, DirectRead, fp(AND), A)
|
||||
op(0x25, AbsoluteRead, fp(AND), A)
|
||||
op(0x26, IndirectXRead, fp(AND))
|
||||
|
@ -49,12 +49,12 @@ auto SPC700::instruction() -> void {
|
|||
op(0x2b, DirectModify, fp(ROL))
|
||||
op(0x2c, AbsoluteModify, fp(ROL))
|
||||
op(0x2d, Push, A)
|
||||
op(0x2e, BNEDirect)
|
||||
op(0x2e, BranchNotDirect)
|
||||
op(0x2f, Branch, true)
|
||||
op(0x30, Branch, NF == 1)
|
||||
op(0x31, JST, 3)
|
||||
op(0x32, CLR, 1)
|
||||
op(0x33, BBC, 1)
|
||||
op(0x31, CallTable, 3)
|
||||
op(0x32, AbsoluteBitSet, 1, false)
|
||||
op(0x33, BranchBit, 1, false)
|
||||
op(0x34, DirectIndexedRead, fp(AND), A, X)
|
||||
op(0x35, AbsoluteIndexedRead, fp(AND), X)
|
||||
op(0x36, AbsoluteIndexedRead, fp(AND), Y)
|
||||
|
@ -66,11 +66,11 @@ auto SPC700::instruction() -> void {
|
|||
op(0x3c, ImpliedModify, fp(ROL), A)
|
||||
op(0x3d, ImpliedModify, fp(INC), X)
|
||||
op(0x3e, DirectRead, fp(CMP), X)
|
||||
op(0x3f, JSRAbsolute)
|
||||
op(0x40, FlagSet, PF)
|
||||
op(0x41, JST, 4)
|
||||
op(0x42, SET, 2)
|
||||
op(0x43, BBS, 2)
|
||||
op(0x3f, CallAbsolute)
|
||||
op(0x40, FlagSet, PF, true)
|
||||
op(0x41, CallTable, 4)
|
||||
op(0x42, AbsoluteBitSet, 2, true)
|
||||
op(0x43, BranchBit, 2, true)
|
||||
op(0x44, DirectRead, fp(EOR), A)
|
||||
op(0x45, AbsoluteRead, fp(EOR), A)
|
||||
op(0x46, IndirectXRead, fp(EOR))
|
||||
|
@ -81,12 +81,12 @@ auto SPC700::instruction() -> void {
|
|||
op(0x4b, DirectModify, fp(LSR))
|
||||
op(0x4c, AbsoluteModify, fp(LSR))
|
||||
op(0x4d, Push, X)
|
||||
op(0x4e, TRBAbsolute)
|
||||
op(0x4f, JSPDirect)
|
||||
op(0x4e, TestSetBitsAbsolute, false)
|
||||
op(0x4f, CallPage)
|
||||
op(0x50, Branch, VF == 0)
|
||||
op(0x51, JST, 5)
|
||||
op(0x52, CLR, 2)
|
||||
op(0x53, BBC, 2)
|
||||
op(0x51, CallTable, 5)
|
||||
op(0x52, AbsoluteBitSet, 2, false)
|
||||
op(0x53, BranchBit, 2, false)
|
||||
op(0x54, DirectIndexedRead, fp(EOR), A, X)
|
||||
op(0x55, AbsoluteIndexedRead, fp(EOR), X)
|
||||
op(0x56, AbsoluteIndexedRead, fp(EOR), Y)
|
||||
|
@ -98,11 +98,11 @@ auto SPC700::instruction() -> void {
|
|||
op(0x5c, ImpliedModify, fp(LSR), A)
|
||||
op(0x5d, Transfer, A, X)
|
||||
op(0x5e, AbsoluteRead, fp(CMP), Y)
|
||||
op(0x5f, JMPAbsolute)
|
||||
op(0x60, FlagClear, CF)
|
||||
op(0x61, JST, 6)
|
||||
op(0x62, SET, 3)
|
||||
op(0x63, BBS, 3)
|
||||
op(0x5f, JumpAbsolute)
|
||||
op(0x60, FlagSet, CF, false)
|
||||
op(0x61, CallTable, 6)
|
||||
op(0x62, AbsoluteBitSet, 3, true)
|
||||
op(0x63, BranchBit, 3, true)
|
||||
op(0x64, DirectRead, fp(CMP), A)
|
||||
op(0x65, AbsoluteRead, fp(CMP), A)
|
||||
op(0x66, IndirectXRead, fp(CMP))
|
||||
|
@ -113,12 +113,12 @@ auto SPC700::instruction() -> void {
|
|||
op(0x6b, DirectModify, fp(ROR))
|
||||
op(0x6c, AbsoluteModify, fp(ROR))
|
||||
op(0x6d, Push, Y)
|
||||
op(0x6e, BNEDirectDecrement)
|
||||
op(0x6f, RTS)
|
||||
op(0x6e, BranchNotDirectDecrement)
|
||||
op(0x6f, ReturnSubroutine)
|
||||
op(0x70, Branch, VF == 1)
|
||||
op(0x71, JST, 7)
|
||||
op(0x72, CLR, 3)
|
||||
op(0x73, BBC, 3)
|
||||
op(0x71, CallTable, 7)
|
||||
op(0x72, AbsoluteBitSet, 3, false)
|
||||
op(0x73, BranchBit, 3, false)
|
||||
op(0x74, DirectIndexedRead, fp(CMP), A, X)
|
||||
op(0x75, AbsoluteIndexedRead, fp(CMP), X)
|
||||
op(0x76, AbsoluteIndexedRead, fp(CMP), Y)
|
||||
|
@ -130,11 +130,11 @@ auto SPC700::instruction() -> void {
|
|||
op(0x7c, ImpliedModify, fp(ROR), A)
|
||||
op(0x7d, Transfer, X, A)
|
||||
op(0x7e, DirectRead, fp(CMP), Y)
|
||||
op(0x7f, RTI)
|
||||
op(0x80, FlagSet, CF)
|
||||
op(0x81, JST, 8)
|
||||
op(0x82, SET, 4)
|
||||
op(0x83, BBS, 4)
|
||||
op(0x7f, ReturnInterrupt)
|
||||
op(0x80, FlagSet, CF, true)
|
||||
op(0x81, CallTable, 8)
|
||||
op(0x82, AbsoluteBitSet, 4, true)
|
||||
op(0x83, BranchBit, 4, true)
|
||||
op(0x84, DirectRead, fp(ADC), A)
|
||||
op(0x85, AbsoluteRead, fp(ADC), A)
|
||||
op(0x86, IndirectXRead, fp(ADC))
|
||||
|
@ -145,12 +145,12 @@ auto SPC700::instruction() -> void {
|
|||
op(0x8b, DirectModify, fp(DEC))
|
||||
op(0x8c, AbsoluteModify, fp(DEC))
|
||||
op(0x8d, ImmediateRead, fp(LD), Y)
|
||||
op(0x8e, PLP)
|
||||
op(0x8e, PullP)
|
||||
op(0x8f, DirectWriteImmediate, fp(ST))
|
||||
op(0x90, Branch, CF == 0)
|
||||
op(0x91, JST, 9)
|
||||
op(0x92, CLR, 4)
|
||||
op(0x93, BBC, 4)
|
||||
op(0x91, CallTable, 9)
|
||||
op(0x92, AbsoluteBitSet, 4, false)
|
||||
op(0x93, BranchBit, 4, false)
|
||||
op(0x94, DirectIndexedRead, fp(ADC), A, X)
|
||||
op(0x95, AbsoluteIndexedRead, fp(ADC), X)
|
||||
op(0x96, AbsoluteIndexedRead, fp(ADC), Y)
|
||||
|
@ -161,12 +161,12 @@ auto SPC700::instruction() -> void {
|
|||
op(0x9b, DirectIndexedModify, fp(DEC), X)
|
||||
op(0x9c, ImpliedModify, fp(DEC), A)
|
||||
op(0x9d, Transfer, S, X)
|
||||
op(0x9e, DIV)
|
||||
op(0x9f, XCN)
|
||||
op(0xa0, FlagSet, IF)
|
||||
op(0xa1, JST, 10)
|
||||
op(0xa2, SET, 5)
|
||||
op(0xa3, BBS, 5)
|
||||
op(0x9e, Divide)
|
||||
op(0x9f, ExchangeNibble)
|
||||
op(0xa0, FlagSet, IF, true)
|
||||
op(0xa1, CallTable, 10)
|
||||
op(0xa2, AbsoluteBitSet, 5, true)
|
||||
op(0xa3, BranchBit, 5, true)
|
||||
op(0xa4, DirectRead, fp(SBC), A)
|
||||
op(0xa5, AbsoluteRead, fp(SBC), A)
|
||||
op(0xa6, IndirectXRead, fp(SBC))
|
||||
|
@ -180,9 +180,9 @@ auto SPC700::instruction() -> void {
|
|||
op(0xae, Pull, A)
|
||||
op(0xaf, IndirectXIncrementWrite, A)
|
||||
op(0xb0, Branch, CF == 1)
|
||||
op(0xb1, JST, 11)
|
||||
op(0xb2, CLR, 5)
|
||||
op(0xb3, BBC, 5)
|
||||
op(0xb1, CallTable, 11)
|
||||
op(0xb2, AbsoluteBitSet, 5, false)
|
||||
op(0xb3, BranchBit, 5, false)
|
||||
op(0xb4, DirectIndexedRead, fp(SBC), A, X)
|
||||
op(0xb5, AbsoluteIndexedRead, fp(SBC), X)
|
||||
op(0xb6, AbsoluteIndexedRead, fp(SBC), Y)
|
||||
|
@ -193,12 +193,12 @@ auto SPC700::instruction() -> void {
|
|||
op(0xbb, DirectIndexedModify, fp(INC), X)
|
||||
op(0xbc, ImpliedModify, fp(INC), A)
|
||||
op(0xbd, Transfer, X, S)
|
||||
op(0xbe, DAS)
|
||||
op(0xbe, DecimalAdjustSub)
|
||||
op(0xbf, IndirectXIncrementRead, A)
|
||||
op(0xc0, FlagClear, IF)
|
||||
op(0xc1, JST, 12)
|
||||
op(0xc2, SET, 6)
|
||||
op(0xc3, BBS, 6)
|
||||
op(0xc0, FlagSet, IF, false)
|
||||
op(0xc1, CallTable, 12)
|
||||
op(0xc2, AbsoluteBitSet, 6, true)
|
||||
op(0xc3, BranchBit, 6, true)
|
||||
op(0xc4, DirectWrite, A)
|
||||
op(0xc5, AbsoluteWrite, A)
|
||||
op(0xc6, IndirectXWrite, A)
|
||||
|
@ -210,27 +210,27 @@ auto SPC700::instruction() -> void {
|
|||
op(0xcc, AbsoluteWrite, Y)
|
||||
op(0xcd, ImmediateRead, fp(LD), X)
|
||||
op(0xce, Pull, X)
|
||||
op(0xcf, MUL)
|
||||
op(0xcf, Multiply)
|
||||
op(0xd0, Branch, ZF == 0)
|
||||
op(0xd1, JST, 13)
|
||||
op(0xd2, CLR, 6)
|
||||
op(0xd3, BBC, 6)
|
||||
op(0xd1, CallTable, 13)
|
||||
op(0xd2, AbsoluteBitSet, 6, false)
|
||||
op(0xd3, BranchBit, 6, false)
|
||||
op(0xd4, DirectIndexedWrite, A, X)
|
||||
op(0xd5, AbsoluteIndexedWrite, X)
|
||||
op(0xd6, AbsoluteIndexedWrite, Y)
|
||||
op(0xd7, IndirectIndexedWrite, A, Y)
|
||||
op(0xd8, DirectWrite, X)
|
||||
op(0xd9, DirectIndexedWrite, X, Y)
|
||||
op(0xda, STWDirect)
|
||||
op(0xda, DirectWriteWord)
|
||||
op(0xdb, DirectIndexedWrite, Y, X)
|
||||
op(0xdc, ImpliedModify, fp(DEC), Y)
|
||||
op(0xdd, Transfer, Y, A)
|
||||
op(0xde, BNEDirectX)
|
||||
op(0xdf, DAA)
|
||||
op(0xe0, CLV)
|
||||
op(0xe1, JST, 14)
|
||||
op(0xe2, SET, 7)
|
||||
op(0xe3, BBS, 7)
|
||||
op(0xde, BranchNotDirectX)
|
||||
op(0xdf, DecimalAdjustAdd)
|
||||
op(0xe0, OverflowClear)
|
||||
op(0xe1, CallTable, 14)
|
||||
op(0xe2, AbsoluteBitSet, 7, true)
|
||||
op(0xe3, BranchBit, 7, true)
|
||||
op(0xe4, DirectRead, fp(LD), A)
|
||||
op(0xe5, AbsoluteRead, fp(LD), A)
|
||||
op(0xe6, IndirectXRead, fp(LD))
|
||||
|
@ -240,13 +240,13 @@ auto SPC700::instruction() -> void {
|
|||
op(0xea, AbsoluteBitModify, 7)
|
||||
op(0xeb, DirectRead, fp(LD), Y)
|
||||
op(0xec, AbsoluteRead, fp(LD), Y)
|
||||
op(0xed, CMC)
|
||||
op(0xed, ComplementCarry)
|
||||
op(0xee, Pull, Y)
|
||||
op(0xef, WAI)
|
||||
op(0xef, Wait)
|
||||
op(0xf0, Branch, ZF == 1)
|
||||
op(0xf1, JST, 15)
|
||||
op(0xf2, CLR, 7)
|
||||
op(0xf3, BBC, 7)
|
||||
op(0xf1, CallTable, 15)
|
||||
op(0xf2, AbsoluteBitSet, 7, false)
|
||||
op(0xf3, BranchBit, 7, false)
|
||||
op(0xf4, DirectIndexedRead, fp(LD), A, X)
|
||||
op(0xf5, AbsoluteIndexedRead, fp(LD), X)
|
||||
op(0xf6, AbsoluteIndexedRead, fp(LD), Y)
|
||||
|
@ -257,8 +257,8 @@ auto SPC700::instruction() -> void {
|
|||
op(0xfb, DirectIndexedRead, fp(LD), Y, X)
|
||||
op(0xfc, ImpliedModify, fp(INC), Y)
|
||||
op(0xfd, Transfer, A, Y)
|
||||
op(0xfe, BNEYDecrement)
|
||||
op(0xff, STP)
|
||||
op(0xfe, BranchNotYDecrement)
|
||||
op(0xff, Stop)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,379 +1,204 @@
|
|||
auto SPC700::instructionAbsoluteBitModify(uint3 mode) -> void {
|
||||
uint16 absolute = fetch();
|
||||
absolute |= fetch() << 8;
|
||||
uint3 bit = absolute >> 13;
|
||||
absolute &= 0x1fff;
|
||||
uint8 data = read(absolute);
|
||||
uint16 address = read(PC++);
|
||||
address |= read(PC++) << 8;
|
||||
uint3 bit = address >> 13;
|
||||
address &= 0x1fff;
|
||||
uint8 data = read(address);
|
||||
switch(mode) {
|
||||
case 0: //orc addr:bit
|
||||
idle();
|
||||
case 0: //or addr:bit
|
||||
idle(address);
|
||||
CF |= data.bit(bit);
|
||||
break;
|
||||
case 1: //orc !addr:bit
|
||||
idle();
|
||||
case 1: //or !addr:bit
|
||||
idle(address);
|
||||
CF |= !data.bit(bit);
|
||||
break;
|
||||
case 2: //and addr:bit
|
||||
case 2: //and addr:bit
|
||||
CF &= data.bit(bit);
|
||||
break;
|
||||
case 3: //and !addr:bit
|
||||
CF &= !data.bit(bit);
|
||||
break;
|
||||
case 4: //eor addr:bit
|
||||
idle();
|
||||
case 4: //eor addr:bit
|
||||
idle(address);
|
||||
CF ^= data.bit(bit);
|
||||
break;
|
||||
case 5: //ldc addr:bit
|
||||
case 5: //ld addr:bit
|
||||
CF = data.bit(bit);
|
||||
break;
|
||||
case 6: //stc addr:bit
|
||||
idle();
|
||||
case 6: //st addr:bit
|
||||
idle(address);
|
||||
data.bit(bit) = CF;
|
||||
write(absolute, data);
|
||||
write(address, data);
|
||||
break;
|
||||
case 7: //not addr:bit
|
||||
case 7: //not addr:bit
|
||||
data.bit(bit) ^= 1;
|
||||
write(absolute, data);
|
||||
write(address, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto SPC700::instructionAbsoluteBitSet(uint3 bit, bool value) -> void {
|
||||
uint8 address = read(PC++);
|
||||
uint8 data = read(page(address));
|
||||
data.bit(bit) = value;
|
||||
write(page(address), data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionAbsoluteRead(fpb op, uint8& target) -> void {
|
||||
uint16 absolute = fetch();
|
||||
absolute |= fetch() << 8;
|
||||
uint8 data = read(absolute);
|
||||
uint16 address = read(PC++);
|
||||
address |= read(PC++) << 8;
|
||||
uint8 data = read(address);
|
||||
target = alu(target, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionAbsoluteModify(fps op) -> void {
|
||||
uint16 absolute = fetch();
|
||||
absolute |= fetch() << 8;
|
||||
uint8 data = read(absolute);
|
||||
write(absolute, alu(data));
|
||||
uint16 address = read(PC++);
|
||||
address |= read(PC++) << 8;
|
||||
uint8 data = read(address);
|
||||
write(address, alu(data));
|
||||
}
|
||||
|
||||
auto SPC700::instructionAbsoluteWrite(uint8& data) -> void {
|
||||
uint16 absolute = fetch();
|
||||
absolute |= fetch() << 8;
|
||||
read(absolute);
|
||||
write(absolute, data);
|
||||
uint16 address = read(PC++);
|
||||
address |= read(PC++) << 8;
|
||||
read(address);
|
||||
write(address, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionAbsoluteIndexedRead(fpb op, uint8& index) -> void {
|
||||
uint16 absolute = fetch();
|
||||
absolute |= fetch() << 8;
|
||||
idle();
|
||||
uint8 data = read(absolute + index);
|
||||
uint16 address = read(PC++);
|
||||
address |= read(PC++) << 8;
|
||||
idle(PC - 1);
|
||||
uint8 data = read(address + index);
|
||||
A = alu(A, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionAbsoluteIndexedWrite(uint8& index) -> void {
|
||||
uint16 absolute = fetch();
|
||||
absolute |= fetch() << 8;
|
||||
idle();
|
||||
absolute += index;
|
||||
read(absolute);
|
||||
write(absolute, A);
|
||||
uint16 address = read(PC++);
|
||||
address |= read(PC++) << 8;
|
||||
idle(PC - 1);
|
||||
read(address + index);
|
||||
write(address + index, A);
|
||||
}
|
||||
|
||||
auto SPC700::instructionBranch(bool take) -> void {
|
||||
uint8 data = fetch();
|
||||
uint8 data = read(PC++);
|
||||
if(!take) return;
|
||||
idle();
|
||||
idle();
|
||||
idle(PC - 1);
|
||||
idle(PC - 1);
|
||||
PC += (int8)data;
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectRead(fpb op, uint8& target) -> void {
|
||||
uint8 direct = fetch();
|
||||
uint8 data = load(direct);
|
||||
target = alu(target, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectModify(fps op) -> void {
|
||||
uint8 direct = fetch();
|
||||
uint8 data = load(direct);
|
||||
store(direct, alu(data));
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectWrite(uint8& data) -> void {
|
||||
uint8 direct = fetch();
|
||||
load(direct);
|
||||
store(direct, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectWriteDirect(fpb op) -> void {
|
||||
uint8 source = fetch();
|
||||
uint8 rhs = load(source);
|
||||
uint8 target = fetch();
|
||||
uint8 lhs;
|
||||
if(op != &SPC700::algorithmST) lhs = load(target);
|
||||
lhs = alu(lhs, rhs);
|
||||
op != &SPC700::algorithmCMP ? store(target, lhs) : idle();
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectWriteImmediate(fpb op) -> void {
|
||||
uint8 immediate = fetch();
|
||||
uint8 direct = fetch();
|
||||
uint8 data = load(direct);
|
||||
data = alu(data, immediate);
|
||||
op != &SPC700::algorithmCMP ? store(direct, data) : idle();
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectReadWord(fpw op) -> void {
|
||||
uint8 direct = fetch();
|
||||
uint16 data = load(direct++);
|
||||
if(op != &SPC700::algorithmCPW) idle();
|
||||
data |= load(direct++) << 8;
|
||||
YA = alu(YA, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectModifyWord(int adjust) -> void {
|
||||
uint8 direct = fetch();
|
||||
uint16 data = load(direct) + adjust;
|
||||
store(direct++, data >> 0);
|
||||
data += load(direct) << 8;
|
||||
store(direct++, data >> 8);
|
||||
ZF = data == 0;
|
||||
NF = data & 0x8000;
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectIndexedRead(fpb op, uint8& target, uint8& index) -> void {
|
||||
uint8 direct = fetch();
|
||||
idle();
|
||||
uint8 data = load(direct + index);
|
||||
target = alu(target, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectIndexedModify(fps op, uint8& index) -> void {
|
||||
uint8 direct = fetch();
|
||||
idle();
|
||||
uint8 data = load(direct + index);
|
||||
store(direct + index, alu(data));
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectIndexedWrite(uint8& data, uint8& index) -> void {
|
||||
uint8 direct = fetch() + index;
|
||||
idle();
|
||||
load(direct);
|
||||
store(direct, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionFlagClear(bool& flag) -> void {
|
||||
idle();
|
||||
if(&flag == &IF) idle();
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
auto SPC700::instructionFlagSet(bool& flag) -> void {
|
||||
idle();
|
||||
if(&flag == &IF) idle();
|
||||
flag = 1;
|
||||
}
|
||||
|
||||
auto SPC700::instructionImmediateRead(fpb op, uint8& target) -> void {
|
||||
uint8 data = fetch();
|
||||
target = alu(target, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionImpliedModify(fps op, uint8& target) -> void {
|
||||
idle();
|
||||
target = alu(target);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndexedIndirectRead(fpb op, uint8& index) -> void {
|
||||
uint8 direct = fetch() + index;
|
||||
idle();
|
||||
uint16 absolute = load(direct++);
|
||||
absolute |= load(direct++) << 8;
|
||||
uint8 data = read(absolute);
|
||||
A = alu(A, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndexedIndirectWrite(uint8& data, uint8& index) -> void {
|
||||
uint8 direct = fetch() + index;
|
||||
idle();
|
||||
uint16 absolute = load(direct++);
|
||||
absolute |= load(direct++) << 8;
|
||||
read(absolute);
|
||||
write(absolute, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectIndexedRead(fpb op, uint8& index) -> void {
|
||||
uint8 direct = fetch();
|
||||
uint16 absolute = load(direct++);
|
||||
absolute |= load(direct++) << 8;
|
||||
idle();
|
||||
uint8 data = read(absolute + index);
|
||||
A = alu(A, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectIndexedWrite(uint8& data, uint8& index) -> void {
|
||||
uint8 direct = fetch();
|
||||
uint16 absolute = load(direct++);
|
||||
absolute |= load(direct++) << 8;
|
||||
idle();
|
||||
read(absolute + index);
|
||||
write(absolute + index, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectXRead(fpb op) -> void {
|
||||
idle();
|
||||
uint8 data = load(X);
|
||||
A = alu(A, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectXWrite(uint8& data) -> void {
|
||||
idle();
|
||||
load(X);
|
||||
store(X, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectXIncrementRead(uint8& data) -> void {
|
||||
idle();
|
||||
data = load(X++);
|
||||
idle();
|
||||
ZF = data == 0;
|
||||
NF = data & 0x80;
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectXIncrementWrite(uint8& data) -> void {
|
||||
idle();
|
||||
idle();
|
||||
store(X++, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectXWriteIndirectY(fpb op) -> void {
|
||||
idle();
|
||||
uint8 rhs = load(Y);
|
||||
uint8 lhs = load(X);
|
||||
lhs = alu(lhs, rhs);
|
||||
op != &SPC700::algorithmCMP ? store(X, lhs) : idle();
|
||||
}
|
||||
|
||||
auto SPC700::instructionPull(uint8& data) -> void {
|
||||
idle();
|
||||
idle();
|
||||
data = pull();
|
||||
}
|
||||
|
||||
auto SPC700::instructionPush(uint8 data) -> void {
|
||||
idle();
|
||||
idle();
|
||||
push(data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionTransfer(uint8& from, uint8& to) -> void {
|
||||
idle();
|
||||
to = from;
|
||||
if(&to == &S) return;
|
||||
ZF = to == 0;
|
||||
NF = to & 0x80;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
auto SPC700::instructionBBC(uint3 bit) -> void {
|
||||
uint8 direct = fetch();
|
||||
uint8 data = load(direct);
|
||||
uint8 displacement = fetch();
|
||||
idle();
|
||||
if(data.bit(bit) == 1) return;
|
||||
idle();
|
||||
idle();
|
||||
auto SPC700::instructionBranchBit(uint3 bit, bool match) -> void {
|
||||
uint8 address = read(PC++);
|
||||
uint8 data = read(page(address));
|
||||
idle(page(address));
|
||||
uint8 displacement = read(PC++);
|
||||
if(data.bit(bit) != match) return;
|
||||
idle(PC - 1);
|
||||
idle(PC - 1);
|
||||
PC += (int8)displacement;
|
||||
}
|
||||
|
||||
auto SPC700::instructionBBS(uint3 bit) -> void {
|
||||
uint8 direct = fetch();
|
||||
uint8 data = load(direct);
|
||||
uint8 displacement = fetch();
|
||||
idle();
|
||||
if(data.bit(bit) == 0) return;
|
||||
idle();
|
||||
idle();
|
||||
PC += (int8)displacement;
|
||||
}
|
||||
|
||||
auto SPC700::instructionBNEDirect() -> void {
|
||||
uint8 direct = fetch();
|
||||
uint8 data = load(direct);
|
||||
uint8 displacement = fetch();
|
||||
idle();
|
||||
auto SPC700::instructionBranchNotDirect() -> void {
|
||||
uint8 address = read(PC++);
|
||||
uint8 data = read(page(address));
|
||||
idle(page(address));
|
||||
uint8 displacement = read(PC++);
|
||||
if(A == data) return;
|
||||
idle();
|
||||
idle();
|
||||
idle(PC - 1);
|
||||
idle(PC - 1);
|
||||
PC += (int8)displacement;
|
||||
}
|
||||
|
||||
auto SPC700::instructionBNEDirectDecrement() -> void {
|
||||
uint8 direct = fetch();
|
||||
uint8 data = load(direct);
|
||||
store(direct, --data);
|
||||
uint8 displacement = fetch();
|
||||
auto SPC700::instructionBranchNotDirectDecrement() -> void {
|
||||
uint8 address = read(PC++);
|
||||
uint8 data = read(page(address));
|
||||
write(page(address), --data);
|
||||
uint8 displacement = read(PC++);
|
||||
if(data == 0) return;
|
||||
idle();
|
||||
idle();
|
||||
idle(PC - 1);
|
||||
idle(PC - 1);
|
||||
PC += (int8)displacement;
|
||||
}
|
||||
|
||||
auto SPC700::instructionBNEDirectX() -> void {
|
||||
uint8 direct = fetch();
|
||||
idle();
|
||||
uint8 data = load(direct + X);
|
||||
uint8 displacement = fetch();
|
||||
idle();
|
||||
auto SPC700::instructionBranchNotDirectX() -> void {
|
||||
uint8 address = read(PC++);
|
||||
idle(PC - 1);
|
||||
uint8 data = read(page(address + X));
|
||||
idle(page(address + X));
|
||||
uint8 displacement = read(PC++);
|
||||
if(A == data) return;
|
||||
idle();
|
||||
idle();
|
||||
idle(PC - 1);
|
||||
idle(PC - 1);
|
||||
PC += (int8)displacement;
|
||||
}
|
||||
|
||||
auto SPC700::instructionBNEYDecrement() -> void {
|
||||
uint8 displacement = fetch();
|
||||
idle();
|
||||
idle();
|
||||
auto SPC700::instructionBranchNotYDecrement() -> void {
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
uint8 displacement = read(PC++);
|
||||
if(--Y == 0) return;
|
||||
idle();
|
||||
idle();
|
||||
idle(PC - 1);
|
||||
idle(PC - 1);
|
||||
PC += (int8)displacement;
|
||||
}
|
||||
|
||||
auto SPC700::instructionBRK() -> void {
|
||||
uint16 absolute = read(0xffde);
|
||||
absolute |= read(0xffdf) << 8;
|
||||
idle();
|
||||
idle();
|
||||
push(PC >> 8);
|
||||
push(PC >> 0);
|
||||
push(P);
|
||||
PC = absolute;
|
||||
auto SPC700::instructionBreak() -> void {
|
||||
idle(PC);
|
||||
write(stack(S--), PC >> 8);
|
||||
write(stack(S--), PC >> 0);
|
||||
write(stack(S--), P);
|
||||
idle(stack(S + 1));
|
||||
uint16 address = read(0xffde + 0);
|
||||
address |= read(0xffde + 1) << 8;
|
||||
PC = address;
|
||||
IF = 0;
|
||||
BF = 1;
|
||||
}
|
||||
|
||||
auto SPC700::instructionCLR(uint3 bit) -> void {
|
||||
uint8 direct = fetch();
|
||||
uint8 data = load(direct);
|
||||
data.bit(bit) = 0;
|
||||
store(direct, data);
|
||||
auto SPC700::instructionCallAbsolute() -> void {
|
||||
uint16 address = read(PC++);
|
||||
address |= read(PC++) << 8;
|
||||
idle(stack(S));
|
||||
write(stack(S--), PC >> 8);
|
||||
write(stack(S--), PC >> 0);
|
||||
idle(stack(S + 1));
|
||||
idle(stack(S + 1));
|
||||
PC = address;
|
||||
}
|
||||
|
||||
auto SPC700::instructionCLV() -> void {
|
||||
idle();
|
||||
HF = 0;
|
||||
VF = 0;
|
||||
auto SPC700::instructionCallPage() -> void {
|
||||
uint8 address = read(PC++);
|
||||
idle(PC - 1);
|
||||
write(stack(S--), PC >> 8);
|
||||
write(stack(S--), PC >> 0);
|
||||
idle(stack(S + 1));
|
||||
PC = 0xff00 | address;
|
||||
}
|
||||
|
||||
auto SPC700::instructionCMC() -> void {
|
||||
idle();
|
||||
idle();
|
||||
auto SPC700::instructionCallTable(uint4 vector) -> void {
|
||||
idle(PC);
|
||||
idle(stack(S));
|
||||
write(stack(S--), PC >> 8);
|
||||
write(stack(S--), PC >> 0);
|
||||
idle(stack(S + 1));
|
||||
uint16 address = 0xffde - (vector << 1);
|
||||
uint16 pc = read(address + 0);
|
||||
pc |= read(address + 1) << 8;
|
||||
PC = pc;
|
||||
}
|
||||
|
||||
auto SPC700::instructionComplementCarry() -> void {
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
CF = !CF;
|
||||
}
|
||||
|
||||
auto SPC700::instructionDAA() -> void {
|
||||
idle();
|
||||
idle();
|
||||
auto SPC700::instructionDecimalAdjustAdd() -> void {
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
if(CF || A > 0x99) {
|
||||
A += 0x60;
|
||||
CF = 1;
|
||||
|
@ -385,9 +210,9 @@ auto SPC700::instructionDAA() -> void {
|
|||
NF = A & 0x80;
|
||||
}
|
||||
|
||||
auto SPC700::instructionDAS() -> void {
|
||||
idle();
|
||||
idle();
|
||||
auto SPC700::instructionDecimalAdjustSub() -> void {
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
if(!CF || A > 0x99) {
|
||||
A -= 0x60;
|
||||
CF = 0;
|
||||
|
@ -399,18 +224,100 @@ auto SPC700::instructionDAS() -> void {
|
|||
NF = A & 0x80;
|
||||
}
|
||||
|
||||
auto SPC700::instructionDIV() -> void {
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
auto SPC700::instructionDirectRead(fpb op, uint8& target) -> void {
|
||||
uint8 address = read(PC++);
|
||||
uint8 data = read(page(address));
|
||||
target = alu(target, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectModify(fps op) -> void {
|
||||
uint8 address = read(PC++);
|
||||
uint8 data = read(page(address));
|
||||
write(page(address), alu(data));
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectWriteWord() -> void {
|
||||
uint8 address = read(PC++);
|
||||
idle(page(address + 0));
|
||||
write(page(address + 0), A);
|
||||
write(page(address + 1), Y);
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectWriteDirect(fpb op) -> void {
|
||||
uint8 source = read(PC++);
|
||||
uint8 rhs = read(page(source));
|
||||
uint8 target = read(PC++);
|
||||
uint8 lhs;
|
||||
if(op != &SPC700::algorithmST) lhs = read(page(target));
|
||||
lhs = alu(lhs, rhs);
|
||||
op != &SPC700::algorithmCMP ? write(page(target), lhs) : idle(page(target));
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectWriteImmediate(fpb op) -> void {
|
||||
uint8 immediate = read(PC++);
|
||||
uint8 address = read(PC++);
|
||||
uint8 data = read(page(address));
|
||||
data = alu(data, immediate);
|
||||
op != &SPC700::algorithmCMP ? write(page(address), data) : idle(page(address));
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectReadWord(fpw op) -> void {
|
||||
uint8 address = read(PC++);
|
||||
uint16 data = read(page(address + 0));
|
||||
if(op != &SPC700::algorithmCPW) idle(page(address + 0));
|
||||
data |= read(page(address + 1)) << 8;
|
||||
YA = alu(YA, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectModifyWord(int adjust) -> void {
|
||||
uint8 address = read(PC++);
|
||||
uint16 data = read(page(address + 0)) + adjust;
|
||||
write(page(address + 0), data >> 0);
|
||||
data += read(page(address + 1)) << 8;
|
||||
write(page(address + 1), data >> 8);
|
||||
ZF = data == 0;
|
||||
NF = data & 0x8000;
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectWrite(uint8& data) -> void {
|
||||
uint8 address = read(PC++);
|
||||
idle(page(address));
|
||||
write(page(address), data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectIndexedRead(fpb op, uint8& target, uint8& index) -> void {
|
||||
uint8 address = read(PC++);
|
||||
idle(PC - 1);
|
||||
uint8 data = read(page(address + index));
|
||||
target = alu(target, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectIndexedModify(fps op, uint8& index) -> void {
|
||||
uint8 address = read(PC++);
|
||||
idle(PC - 1);
|
||||
uint8 data = read(page(address + index));
|
||||
write(page(address + index), alu(data));
|
||||
}
|
||||
|
||||
auto SPC700::instructionDirectIndexedWrite(uint8& data, uint8& index) -> void {
|
||||
uint8 address = read(PC++);
|
||||
idle(PC - 1);
|
||||
idle(page(address + index));
|
||||
write(page(address + index), data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionDivide() -> void {
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
uint16 ya = YA;
|
||||
//overflow set if quotient >= 256
|
||||
HF = (Y & 15) >= (X & 15);
|
||||
|
@ -430,63 +337,126 @@ auto SPC700::instructionDIV() -> void {
|
|||
NF = A & 0x80;
|
||||
}
|
||||
|
||||
auto SPC700::instructionJMPAbsolute() -> void {
|
||||
uint16 absolute = fetch();
|
||||
absolute |= fetch() << 8;
|
||||
PC = absolute;
|
||||
auto SPC700::instructionExchangeNibble() -> void {
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
A = A >> 4 | A << 4;
|
||||
ZF = A == 0;
|
||||
NF = A & 0x80;
|
||||
}
|
||||
|
||||
auto SPC700::instructionJMPIndirectX() -> void {
|
||||
uint16 absolute = fetch();
|
||||
absolute |= fetch() << 8;
|
||||
idle();
|
||||
absolute += X;
|
||||
uint16 pc = read(absolute++);
|
||||
pc |= read(absolute++) << 8;
|
||||
auto SPC700::instructionFlagSet(bool& flag, bool value) -> void {
|
||||
idle(PC);
|
||||
if(&flag == &IF) idle(PC);
|
||||
flag = value;
|
||||
}
|
||||
|
||||
auto SPC700::instructionImmediateRead(fpb op, uint8& target) -> void {
|
||||
uint8 data = read(PC++);
|
||||
target = alu(target, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionImpliedModify(fps op, uint8& target) -> void {
|
||||
idle(PC);
|
||||
target = alu(target);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndexedIndirectRead(fpb op, uint8& index) -> void {
|
||||
uint8 indirect = read(PC++);
|
||||
idle(PC - 1);
|
||||
uint16 address = read(page(indirect + index + 0));
|
||||
address |= read(page(indirect + index + 1)) << 8;
|
||||
uint8 data = read(address);
|
||||
A = alu(A, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndexedIndirectWrite(uint8& data, uint8& index) -> void {
|
||||
uint8 indirect = read(PC++);
|
||||
idle(PC - 1);
|
||||
uint16 address = read(page(indirect + index + 0));
|
||||
address |= read(page(indirect + index + 1)) << 8;
|
||||
read(address);
|
||||
write(address, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectIndexedRead(fpb op, uint8& index) -> void {
|
||||
uint8 indirect = read(PC++);
|
||||
uint16 address = read(page(indirect + 0));
|
||||
address |= read(page(indirect + 1)) << 8;
|
||||
idle(page(indirect + 1));
|
||||
uint8 data = read(address + index);
|
||||
A = alu(A, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectIndexedWrite(uint8& data, uint8& index) -> void {
|
||||
uint8 indirect = read(PC++);
|
||||
uint16 address = read(page(indirect + 0));
|
||||
address |= read(page(indirect + 1)) << 8;
|
||||
idle(page(indirect + 1));
|
||||
read(address + index);
|
||||
write(address + index, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectXRead(fpb op) -> void {
|
||||
idle(PC);
|
||||
uint8 data = read(page(X));
|
||||
A = alu(A, data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectXWrite(uint8& data) -> void {
|
||||
idle(PC);
|
||||
idle(page(X));
|
||||
write(page(X), data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectXIncrementRead(uint8& data) -> void {
|
||||
idle(PC);
|
||||
data = read(page(X)); //todo: $f0-ff not accessible on this cycle?
|
||||
idle(page(X++));
|
||||
ZF = data == 0;
|
||||
NF = data & 0x80;
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectXIncrementWrite(uint8& data) -> void {
|
||||
idle(PC);
|
||||
idle(page(X)); //todo: $f0-ff not accessible on this cycle?
|
||||
write(page(X++), data);
|
||||
}
|
||||
|
||||
auto SPC700::instructionIndirectXWriteIndirectY(fpb op) -> void {
|
||||
idle(PC);
|
||||
uint8 rhs = read(page(Y));
|
||||
uint8 lhs = read(page(X));
|
||||
lhs = alu(lhs, rhs);
|
||||
op != &SPC700::algorithmCMP ? write(page(X), lhs) : idle(page(X));
|
||||
}
|
||||
|
||||
auto SPC700::instructionJumpAbsolute() -> void {
|
||||
uint16 address = read(PC++);
|
||||
address |= read(PC++) << 8;
|
||||
PC = address;
|
||||
}
|
||||
|
||||
auto SPC700::instructionJumpIndirectX() -> void {
|
||||
uint16 address = read(PC++);
|
||||
address |= read(PC++) << 8;
|
||||
idle(PC - 1);
|
||||
uint16 pc = read(address + X + 0);
|
||||
pc |= read(address + X + 1) << 8;
|
||||
PC = pc;
|
||||
}
|
||||
|
||||
auto SPC700::instructionJSPDirect() -> void {
|
||||
uint8 direct = fetch();
|
||||
idle();
|
||||
idle();
|
||||
push(PC >> 8);
|
||||
push(PC >> 0);
|
||||
PC = 0xff00 | direct;
|
||||
}
|
||||
|
||||
auto SPC700::instructionJSRAbsolute() -> void {
|
||||
uint16 absolute = fetch();
|
||||
absolute |= fetch() << 8;
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
push(PC >> 8);
|
||||
push(PC >> 0);
|
||||
PC = absolute;
|
||||
}
|
||||
|
||||
auto SPC700::instructionJST(uint4 vector) -> void {
|
||||
uint16 absolute = 0xffde - (vector << 1);
|
||||
uint16 pc = read(absolute++);
|
||||
pc |= read(absolute++) << 8;
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
push(PC >> 8);
|
||||
push(PC >> 0);
|
||||
PC = pc;
|
||||
}
|
||||
|
||||
auto SPC700::instructionMUL() -> void {
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
auto SPC700::instructionMultiply() -> void {
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
uint16 ya = Y * A;
|
||||
A = ya >> 0;
|
||||
Y = ya >> 8;
|
||||
|
@ -495,89 +465,81 @@ auto SPC700::instructionMUL() -> void {
|
|||
NF = Y & 0x80;
|
||||
}
|
||||
|
||||
auto SPC700::instructionNOP() -> void {
|
||||
idle();
|
||||
auto SPC700::instructionNoOperation() -> void {
|
||||
idle(PC);
|
||||
}
|
||||
|
||||
auto SPC700::instructionPLP() -> void {
|
||||
idle();
|
||||
idle();
|
||||
P = pull();
|
||||
auto SPC700::instructionOverflowClear() -> void {
|
||||
idle(PC);
|
||||
HF = 0;
|
||||
VF = 0;
|
||||
}
|
||||
|
||||
auto SPC700::instructionRTI() -> void {
|
||||
P = pull();
|
||||
uint16 absolute = pull();
|
||||
absolute |= pull() << 8;
|
||||
idle();
|
||||
idle();
|
||||
PC = absolute;
|
||||
auto SPC700::instructionPull(uint8& data) -> void {
|
||||
idle(PC);
|
||||
idle(stack(S));
|
||||
data = read(stack(++S));
|
||||
}
|
||||
|
||||
auto SPC700::instructionRTS() -> void {
|
||||
uint16 absolute = pull();
|
||||
absolute |= pull() << 8;
|
||||
idle();
|
||||
idle();
|
||||
PC = absolute;
|
||||
auto SPC700::instructionPullP() -> void {
|
||||
idle(PC);
|
||||
idle(stack(S));
|
||||
P = read(stack(++S));
|
||||
}
|
||||
|
||||
auto SPC700::instructionSET(uint3 bit) -> void {
|
||||
uint8 direct = fetch();
|
||||
uint8 data = load(direct);
|
||||
data.bit(bit) = 1;
|
||||
store(direct, data);
|
||||
auto SPC700::instructionPush(uint8 data) -> void {
|
||||
idle(PC);
|
||||
write(stack(S--), data);
|
||||
idle(stack(S + 1));
|
||||
}
|
||||
|
||||
auto SPC700::instructionSTP() -> void {
|
||||
r.stp = true;
|
||||
while(r.stp && !synchronizing()) {
|
||||
idle();
|
||||
idle();
|
||||
auto SPC700::instructionReturnInterrupt() -> void {
|
||||
idle(PC);
|
||||
idle(stack(S));
|
||||
P = read(stack(++S));
|
||||
uint16 address = read(stack(++S));
|
||||
address |= read(stack(++S)) << 8;
|
||||
PC = address;
|
||||
}
|
||||
|
||||
auto SPC700::instructionReturnSubroutine() -> void {
|
||||
idle(PC);
|
||||
idle(stack(S));
|
||||
uint16 address = read(stack(++S));
|
||||
address |= read(stack(++S)) << 8;
|
||||
PC = address;
|
||||
}
|
||||
|
||||
auto SPC700::instructionStop() -> void {
|
||||
r.stop = true;
|
||||
while(r.stop && !synchronizing()) {
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
}
|
||||
}
|
||||
|
||||
auto SPC700::instructionSTWDirect() -> void {
|
||||
uint8 direct = fetch();
|
||||
load(direct);
|
||||
store(direct++, A);
|
||||
store(direct++, Y);
|
||||
}
|
||||
|
||||
auto SPC700::instructionTRBAbsolute() -> void {
|
||||
uint16 absolute = fetch();
|
||||
absolute |= fetch() << 8;
|
||||
uint8 data = read(absolute);
|
||||
auto SPC700::instructionTestSetBitsAbsolute(bool set) -> void {
|
||||
uint16 address = read(PC++);
|
||||
address |= read(PC++) << 8;
|
||||
uint8 data = read(address);
|
||||
ZF = (A - data) == 0;
|
||||
NF = (A - data) & 0x80;
|
||||
read(absolute);
|
||||
write(absolute, data & ~A);
|
||||
idle(address);
|
||||
write(address, set ? data | A : data & ~A);
|
||||
}
|
||||
|
||||
auto SPC700::instructionTSBAbsolute() -> void {
|
||||
uint16 absolute = fetch();
|
||||
absolute |= fetch() << 8;
|
||||
uint8 data = read(absolute);
|
||||
ZF = (A - data) == 0;
|
||||
NF = (A - data) & 0x80;
|
||||
read(absolute);
|
||||
write(absolute, data | A);
|
||||
auto SPC700::instructionTransfer(uint8& from, uint8& to) -> void {
|
||||
idle(PC);
|
||||
to = from;
|
||||
if(&to == &S) return;
|
||||
ZF = to == 0;
|
||||
NF = to & 0x80;
|
||||
}
|
||||
|
||||
auto SPC700::instructionWAI() -> void {
|
||||
r.wai = true;
|
||||
while(r.wai && !synchronizing()) {
|
||||
idle();
|
||||
idle();
|
||||
auto SPC700::instructionWait() -> void {
|
||||
r.wait = true;
|
||||
while(r.wait && !synchronizing()) {
|
||||
idle(PC);
|
||||
idle(PC);
|
||||
}
|
||||
}
|
||||
|
||||
auto SPC700::instructionXCN() -> void {
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
idle();
|
||||
A = A >> 4 | A << 4;
|
||||
ZF = A == 0;
|
||||
NF = A & 0x80;
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
auto SPC700::idle() -> void {
|
||||
read(PC);
|
||||
}
|
||||
|
||||
auto SPC700::fetch() -> uint8 {
|
||||
return read(PC++);
|
||||
}
|
||||
|
||||
auto SPC700::pull() -> uint8 {
|
||||
return read(0x0100 | ++S);
|
||||
}
|
||||
|
||||
auto SPC700::push(uint8 data) -> void {
|
||||
return write(0x0100 | S--, data);
|
||||
}
|
||||
|
||||
auto SPC700::load(uint8 addr) -> uint8 {
|
||||
return read(PF << 8 | addr);
|
||||
}
|
||||
|
||||
auto SPC700::store(uint8 addr, uint8 data) -> void {
|
||||
return write(PF << 8 | addr, data);
|
||||
}
|
|
@ -12,6 +12,6 @@ auto SPC700::serialize(serializer& s) -> void {
|
|||
s.integer(r.p.v);
|
||||
s.integer(r.p.n);
|
||||
|
||||
s.integer(r.wai);
|
||||
s.integer(r.stp);
|
||||
s.integer(r.wait);
|
||||
s.integer(r.stop);
|
||||
}
|
||||
|
|
|
@ -22,13 +22,35 @@ namespace Processor {
|
|||
|
||||
#define alu (this->*op)
|
||||
|
||||
#include "memory.cpp"
|
||||
#include "algorithms.cpp"
|
||||
#include "instructions.cpp"
|
||||
#include "instruction.cpp"
|
||||
#include "serialization.cpp"
|
||||
#include "disassembler.cpp"
|
||||
|
||||
auto SPC700::idle(uint16 address) -> void {
|
||||
read(address);
|
||||
}
|
||||
|
||||
auto SPC700::page(uint8 address) const -> uint16 {
|
||||
return PF << 8 | address;
|
||||
}
|
||||
|
||||
auto SPC700::stack(uint8 address) const -> uint16 {
|
||||
return 1 << 8 | address;
|
||||
}
|
||||
|
||||
auto SPC700::power() -> void {
|
||||
PC = 0x0000;
|
||||
YA = 0x0000;
|
||||
X = 0x00;
|
||||
S = 0xef;
|
||||
P = 0x02;
|
||||
|
||||
r.wait = false;
|
||||
r.stop = false;
|
||||
}
|
||||
|
||||
#undef PC
|
||||
#undef YA
|
||||
#undef A
|
||||
|
@ -48,15 +70,4 @@ namespace Processor {
|
|||
|
||||
#undef alu
|
||||
|
||||
auto SPC700::power() -> void {
|
||||
r.pc.w = 0x0000;
|
||||
r.ya.w = 0x0000;
|
||||
r.x = 0x00;
|
||||
r.s = 0xef;
|
||||
r.p = 0x02;
|
||||
|
||||
r.wai = false;
|
||||
r.stp = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,26 +3,22 @@
|
|||
namespace Processor {
|
||||
|
||||
struct SPC700 {
|
||||
virtual auto read(uint16 addr) -> uint8 = 0;
|
||||
virtual auto write(uint16 addr, uint8 data) -> void = 0;
|
||||
virtual auto read(uint16 address) -> uint8 = 0;
|
||||
virtual auto write(uint16 addessr, uint8 data) -> void = 0;
|
||||
virtual auto synchronizing() const -> bool = 0;
|
||||
|
||||
virtual auto readDisassembler(uint16 addr) -> uint8 { return 0; }
|
||||
virtual auto readDisassembler(uint16 address) -> uint8 { return 0; }
|
||||
|
||||
//spc700.cpp
|
||||
inline auto idle(uint16 address) -> void;
|
||||
inline auto page(uint8 address) const -> uint16;
|
||||
inline auto stack(uint8 address) const -> uint16;
|
||||
|
||||
auto power() -> void;
|
||||
|
||||
//instruction.cpp
|
||||
auto instruction() -> void;
|
||||
|
||||
//memory.cpp
|
||||
auto idle() -> void;
|
||||
auto fetch() -> uint8;
|
||||
auto pull() -> uint8;
|
||||
auto push(uint8 data) -> void;
|
||||
auto load(uint8 addr) -> uint8;
|
||||
auto store(uint8 addr, uint8 data) -> void;
|
||||
|
||||
//algorithms.cpp
|
||||
auto algorithmADC(uint8, uint8) -> uint8;
|
||||
auto algorithmAND(uint8, uint8) -> uint8;
|
||||
|
@ -49,12 +45,25 @@ struct SPC700 {
|
|||
using fpw = auto (SPC700::*)(uint16, uint16) -> uint16;
|
||||
|
||||
auto instructionAbsoluteBitModify(uint3) -> void;
|
||||
auto instructionAbsoluteBitSet(uint3, bool) -> void;
|
||||
auto instructionAbsoluteRead(fpb, uint8&) -> void;
|
||||
auto instructionAbsoluteModify(fps) -> void;
|
||||
auto instructionAbsoluteWrite(uint8&) -> void;
|
||||
auto instructionAbsoluteIndexedRead(fpb, uint8&) -> void;
|
||||
auto instructionAbsoluteIndexedWrite(uint8&) -> void;
|
||||
auto instructionBranch(bool) -> void;
|
||||
auto instructionBranchBit(uint3, bool) -> void;
|
||||
auto instructionBranchNotDirect() -> void;
|
||||
auto instructionBranchNotDirectDecrement() -> void;
|
||||
auto instructionBranchNotDirectX() -> void;
|
||||
auto instructionBranchNotYDecrement() -> void;
|
||||
auto instructionBreak() -> void;
|
||||
auto instructionCallAbsolute() -> void;
|
||||
auto instructionCallPage() -> void;
|
||||
auto instructionCallTable(uint4) -> void;
|
||||
auto instructionComplementCarry() -> void;
|
||||
auto instructionDecimalAdjustAdd() -> void;
|
||||
auto instructionDecimalAdjustSub() -> void;
|
||||
auto instructionDirectRead(fpb, uint8&) -> void;
|
||||
auto instructionDirectModify(fps) -> void;
|
||||
auto instructionDirectWrite(uint8&) -> void;
|
||||
|
@ -62,11 +71,13 @@ struct SPC700 {
|
|||
auto instructionDirectWriteImmediate(fpb) -> void;
|
||||
auto instructionDirectReadWord(fpw) -> void;
|
||||
auto instructionDirectModifyWord(int) -> void;
|
||||
auto instructionDirectWriteWord() -> void;
|
||||
auto instructionDirectIndexedRead(fpb, uint8&, uint8&) -> void;
|
||||
auto instructionDirectIndexedModify(fps, uint8&) -> void;
|
||||
auto instructionDirectIndexedWrite(uint8&, uint8&) -> void;
|
||||
auto instructionFlagClear(bool&) -> void;
|
||||
auto instructionFlagSet(bool&) -> void;
|
||||
auto instructionDivide() -> void;
|
||||
auto instructionExchangeNibble() -> void;
|
||||
auto instructionFlagSet(bool&, bool) -> void;
|
||||
auto instructionImmediateRead(fpb, uint8&) -> void;
|
||||
auto instructionImpliedModify(fps, uint8&) -> void;
|
||||
auto instructionIndexedIndirectRead(fpb, uint8&) -> void;
|
||||
|
@ -78,46 +89,26 @@ struct SPC700 {
|
|||
auto instructionIndirectXIncrementRead(uint8&) -> void;
|
||||
auto instructionIndirectXIncrementWrite(uint8&) -> void;
|
||||
auto instructionIndirectXWriteIndirectY(fpb) -> void;
|
||||
auto instructionJumpAbsolute() -> void;
|
||||
auto instructionJumpIndirectX() -> void;
|
||||
auto instructionMultiply() -> void;
|
||||
auto instructionNoOperation() -> void;
|
||||
auto instructionOverflowClear() -> void;
|
||||
auto instructionPull(uint8&) -> void;
|
||||
auto instructionPullP() -> void;
|
||||
auto instructionPush(uint8) -> void;
|
||||
auto instructionReturnInterrupt() -> void;
|
||||
auto instructionReturnSubroutine() -> void;
|
||||
auto instructionStop() -> void;
|
||||
auto instructionTestSetBitsAbsolute(bool) -> void;
|
||||
auto instructionTransfer(uint8&, uint8&) -> void;
|
||||
|
||||
auto instructionBBC(uint3) -> void;
|
||||
auto instructionBBS(uint3) -> void;
|
||||
auto instructionBNEDirect() -> void;
|
||||
auto instructionBNEDirectDecrement() -> void;
|
||||
auto instructionBNEDirectX() -> void;
|
||||
auto instructionBNEYDecrement() -> void;
|
||||
auto instructionBRK() -> void;
|
||||
auto instructionCLR(uint3) -> void;
|
||||
auto instructionCLV() -> void;
|
||||
auto instructionCMC() -> void;
|
||||
auto instructionDAA() -> void;
|
||||
auto instructionDAS() -> void;
|
||||
auto instructionDIV() -> void;
|
||||
auto instructionJMPAbsolute() -> void;
|
||||
auto instructionJMPIndirectX() -> void;
|
||||
auto instructionJSPDirect() -> void;
|
||||
auto instructionJSRAbsolute() -> void;
|
||||
auto instructionJST(uint4) -> void;
|
||||
auto instructionMUL() -> void;
|
||||
auto instructionNOP() -> void;
|
||||
auto instructionPLP() -> void;
|
||||
auto instructionRTI() -> void;
|
||||
auto instructionRTS() -> void;
|
||||
auto instructionSET(uint3) -> void;
|
||||
auto instructionSTP() -> void;
|
||||
auto instructionSTWDirect() -> void;
|
||||
auto instructionTRBAbsolute() -> void;
|
||||
auto instructionTSBAbsolute() -> void;
|
||||
auto instructionWAI() -> void;
|
||||
auto instructionXCN() -> void;
|
||||
auto instructionWait() -> void;
|
||||
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
//disassembler.cpp
|
||||
auto disassemble(uint16 addr, bool p) -> string;
|
||||
auto disassemble(uint16 address, bool p) -> string;
|
||||
|
||||
struct Flags {
|
||||
bool c; //carry
|
||||
|
@ -155,8 +146,8 @@ struct SPC700 {
|
|||
uint8 x, s;
|
||||
Flags p;
|
||||
|
||||
bool wai = false;
|
||||
bool stp = false;
|
||||
bool wait = false;
|
||||
bool stop = false;
|
||||
} r;
|
||||
};
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ auto SMP::Enter() -> void {
|
|||
}
|
||||
|
||||
auto SMP::main() -> void {
|
||||
if(r.wai) return instructionWAI();
|
||||
if(r.stp) return instructionSTP();
|
||||
if(r.wait) return instructionWait();
|
||||
if(r.stop) return instructionStop();
|
||||
instruction();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue