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:
Tim Allen 2017-06-28 17:24:46 +10:00
parent 3517d5c4a4
commit 78f341489e
10 changed files with 561 additions and 610 deletions

View File

@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator { namespace Emulator {
static const string Name = "higan"; 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 Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "http://byuu.org/"; static const string Website = "http://byuu.org/";

View File

@ -25,7 +25,7 @@ auto PSG::main() -> void {
output += levels[noise.volume] * noise.output; output += levels[noise.volume] * noise.output;
stream->sample(sclamp<16>(output) / 32768.0); stream->sample(sclamp<16>(output) / 32768.0);
step(1); step(16);
} }
auto PSG::step(uint clocks) -> void { auto PSG::step(uint clocks) -> void {
@ -36,7 +36,7 @@ auto PSG::step(uint clocks) -> void {
auto PSG::power() -> void { auto PSG::power() -> void {
create(PSG::Enter, system.frequency() / 15.0); 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::HighPass, 20.0);
stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::LowPass, 2840.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); stream->addFilter(Emulator::Filter::Order::Second, Emulator::Filter::Type::LowPass, 20000.0, 3);

View File

@ -54,6 +54,7 @@ auto M68K::instructionABCD(EffectiveAddress with, EffectiveAddress from) -> void
auto source = read<Byte>(from); auto source = read<Byte>(from);
auto target = read<Byte, Hold>(with); auto target = read<Byte, Hold>(with);
auto result = source + target + r.x; auto result = source + target + r.x;
bool c = false;
bool v = false; bool v = false;
if(((target ^ source ^ result) & 0x10) || (result & 0x0f) >= 0x0a) { if(((target ^ source ^ result) & 0x10) || (result & 0x0f) >= 0x0a) {
@ -65,12 +66,13 @@ auto M68K::instructionABCD(EffectiveAddress with, EffectiveAddress from) -> void
if(result >= 0xa0) { if(result >= 0xa0) {
auto previous = result; auto previous = result;
result += 0x60; result += 0x60;
c = true;
v |= ((~previous & 0x80) & (result & 0x80)); v |= ((~previous & 0x80) & (result & 0x80));
} }
write<Byte>(with, result); write<Byte>(with, result);
r.c = sign<Byte>(result >> 1) < 0; r.c = c;
r.v = v; r.v = v;
r.z = clip<Byte>(result) ? 0 : r.z; r.z = clip<Byte>(result) ? 0 : r.z;
r.n = sign<Byte>(result) < 0; 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 M68K::instructionNBCD(EffectiveAddress with) -> void {
auto source = 0u; auto source = read<Byte, Hold>(with);
auto target = read<Byte, Hold>(with); auto target = 0u;
auto result = target - source - r.x; auto result = target - source - r.x;
bool c = false;
bool v = false; bool v = false;
const bool adjustLo = (target ^ source ^ result) & 0x10; const bool adjustLo = (target ^ source ^ result) & 0x10;
@ -765,21 +768,24 @@ auto M68K::instructionNBCD(EffectiveAddress with) -> void {
if(adjustLo) { if(adjustLo) {
auto previous = result; auto previous = result;
result -= 0x06; result -= 0x06;
v |= (previous & 0x80) & (~result & 0x80); c = (~previous & 0x80) & ( result & 0x80);
v |= ( previous & 0x80) & (~result & 0x80);
} }
if(adjustHi) { if(adjustHi) {
auto previous = result; auto previous = result;
result -= 0x60; result -= 0x60;
c = true;
v |= (previous & 0x80) & (~result & 0x80); v |= (previous & 0x80) & (~result & 0x80);
} }
write<Byte>(with, result); write<Byte>(with, result);
r.c = sign<Byte>(result >> 1) < 0; r.c = c;
r.v = v; r.v = v;
r.z = clip<Byte>(result) ? 0 : r.z; r.z = clip<Byte>(result) ? 0 : r.z;
r.n = sign<Byte>(result) < 0; r.n = sign<Byte>(result) < 0;
r.x = r.c;
} }
template<uint Size> auto M68K::instructionNEG(EffectiveAddress with) -> void { 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 source = read<Byte>(from);
auto target = read<Byte, Hold>(with); auto target = read<Byte, Hold>(with);
auto result = target - source - r.x; auto result = target - source - r.x;
bool c = false;
bool v = false; bool v = false;
const bool adjustLo = (target ^ source ^ result) & 0x10; const bool adjustLo = (target ^ source ^ result) & 0x10;
@ -1019,21 +1026,24 @@ auto M68K::instructionSBCD(EffectiveAddress with, EffectiveAddress from) -> void
if(adjustLo) { if(adjustLo) {
auto previous = result; auto previous = result;
result -= 0x06; result -= 0x06;
v |= (previous & 0x80) & (~result & 0x80); c = (~previous & 0x80) & ( result & 0x80);
v |= ( previous & 0x80) & (~result & 0x80);
} }
if(adjustHi) { if(adjustHi) {
auto previous = result; auto previous = result;
result -= 0x60; result -= 0x60;
c = true;
v |= (previous & 0x80) & (~result & 0x80); v |= (previous & 0x80) & (~result & 0x80);
} }
write<Byte>(with, result); write<Byte>(with, result);
r.c = sign<Byte>(result >> 1) < 0; r.c = c;
r.v = v; r.v = v;
r.z = clip<Byte>(result) ? 0 : r.z; r.z = clip<Byte>(result) ? 0 : r.z;
r.n = sign<Byte>(result) < 0; r.n = sign<Byte>(result) < 0;
r.x = r.c;
} }
auto M68K::instructionSCC(uint4 condition, EffectiveAddress to) -> void { auto M68K::instructionSCC(uint4 condition, EffectiveAddress to) -> void {

View File

@ -2,11 +2,11 @@
#define fp(name) &SPC700::algorithm##name #define fp(name) &SPC700::algorithm##name
auto SPC700::instruction() -> void { auto SPC700::instruction() -> void {
switch(fetch()) { switch(read(PC++)) {
op(0x00, NOP) op(0x00, NoOperation)
op(0x01, JST, 0) op(0x01, CallTable, 0)
op(0x02, SET, 0) op(0x02, AbsoluteBitSet, 0, true)
op(0x03, BBS, 0) op(0x03, BranchBit, 0, true)
op(0x04, DirectRead, fp(OR), A) op(0x04, DirectRead, fp(OR), A)
op(0x05, AbsoluteRead, fp(OR), A) op(0x05, AbsoluteRead, fp(OR), A)
op(0x06, IndirectXRead, fp(OR)) op(0x06, IndirectXRead, fp(OR))
@ -17,12 +17,12 @@ auto SPC700::instruction() -> void {
op(0x0b, DirectModify, fp(ASL)) op(0x0b, DirectModify, fp(ASL))
op(0x0c, AbsoluteModify, fp(ASL)) op(0x0c, AbsoluteModify, fp(ASL))
op(0x0d, Push, P) op(0x0d, Push, P)
op(0x0e, TSBAbsolute) op(0x0e, TestSetBitsAbsolute, true)
op(0x0f, BRK) op(0x0f, Break)
op(0x10, Branch, NF == 0) op(0x10, Branch, NF == 0)
op(0x11, JST, 1) op(0x11, CallTable, 1)
op(0x12, CLR, 0) op(0x12, AbsoluteBitSet, 0, false)
op(0x13, BBC, 0) op(0x13, BranchBit, 0, false)
op(0x14, DirectIndexedRead, fp(OR), A, X) op(0x14, DirectIndexedRead, fp(OR), A, X)
op(0x15, AbsoluteIndexedRead, fp(OR), X) op(0x15, AbsoluteIndexedRead, fp(OR), X)
op(0x16, AbsoluteIndexedRead, fp(OR), Y) op(0x16, AbsoluteIndexedRead, fp(OR), Y)
@ -34,11 +34,11 @@ auto SPC700::instruction() -> void {
op(0x1c, ImpliedModify, fp(ASL), A) op(0x1c, ImpliedModify, fp(ASL), A)
op(0x1d, ImpliedModify, fp(DEC), X) op(0x1d, ImpliedModify, fp(DEC), X)
op(0x1e, AbsoluteRead, fp(CMP), X) op(0x1e, AbsoluteRead, fp(CMP), X)
op(0x1f, JMPIndirectX) op(0x1f, JumpIndirectX)
op(0x20, FlagClear, PF) op(0x20, FlagSet, PF, false)
op(0x21, JST, 2) op(0x21, CallTable, 2)
op(0x22, SET, 1) op(0x22, AbsoluteBitSet, 1, true)
op(0x23, BBS, 1) op(0x23, BranchBit, 1, true)
op(0x24, DirectRead, fp(AND), A) op(0x24, DirectRead, fp(AND), A)
op(0x25, AbsoluteRead, fp(AND), A) op(0x25, AbsoluteRead, fp(AND), A)
op(0x26, IndirectXRead, fp(AND)) op(0x26, IndirectXRead, fp(AND))
@ -49,12 +49,12 @@ auto SPC700::instruction() -> void {
op(0x2b, DirectModify, fp(ROL)) op(0x2b, DirectModify, fp(ROL))
op(0x2c, AbsoluteModify, fp(ROL)) op(0x2c, AbsoluteModify, fp(ROL))
op(0x2d, Push, A) op(0x2d, Push, A)
op(0x2e, BNEDirect) op(0x2e, BranchNotDirect)
op(0x2f, Branch, true) op(0x2f, Branch, true)
op(0x30, Branch, NF == 1) op(0x30, Branch, NF == 1)
op(0x31, JST, 3) op(0x31, CallTable, 3)
op(0x32, CLR, 1) op(0x32, AbsoluteBitSet, 1, false)
op(0x33, BBC, 1) op(0x33, BranchBit, 1, false)
op(0x34, DirectIndexedRead, fp(AND), A, X) op(0x34, DirectIndexedRead, fp(AND), A, X)
op(0x35, AbsoluteIndexedRead, fp(AND), X) op(0x35, AbsoluteIndexedRead, fp(AND), X)
op(0x36, AbsoluteIndexedRead, fp(AND), Y) op(0x36, AbsoluteIndexedRead, fp(AND), Y)
@ -66,11 +66,11 @@ auto SPC700::instruction() -> void {
op(0x3c, ImpliedModify, fp(ROL), A) op(0x3c, ImpliedModify, fp(ROL), A)
op(0x3d, ImpliedModify, fp(INC), X) op(0x3d, ImpliedModify, fp(INC), X)
op(0x3e, DirectRead, fp(CMP), X) op(0x3e, DirectRead, fp(CMP), X)
op(0x3f, JSRAbsolute) op(0x3f, CallAbsolute)
op(0x40, FlagSet, PF) op(0x40, FlagSet, PF, true)
op(0x41, JST, 4) op(0x41, CallTable, 4)
op(0x42, SET, 2) op(0x42, AbsoluteBitSet, 2, true)
op(0x43, BBS, 2) op(0x43, BranchBit, 2, true)
op(0x44, DirectRead, fp(EOR), A) op(0x44, DirectRead, fp(EOR), A)
op(0x45, AbsoluteRead, fp(EOR), A) op(0x45, AbsoluteRead, fp(EOR), A)
op(0x46, IndirectXRead, fp(EOR)) op(0x46, IndirectXRead, fp(EOR))
@ -81,12 +81,12 @@ auto SPC700::instruction() -> void {
op(0x4b, DirectModify, fp(LSR)) op(0x4b, DirectModify, fp(LSR))
op(0x4c, AbsoluteModify, fp(LSR)) op(0x4c, AbsoluteModify, fp(LSR))
op(0x4d, Push, X) op(0x4d, Push, X)
op(0x4e, TRBAbsolute) op(0x4e, TestSetBitsAbsolute, false)
op(0x4f, JSPDirect) op(0x4f, CallPage)
op(0x50, Branch, VF == 0) op(0x50, Branch, VF == 0)
op(0x51, JST, 5) op(0x51, CallTable, 5)
op(0x52, CLR, 2) op(0x52, AbsoluteBitSet, 2, false)
op(0x53, BBC, 2) op(0x53, BranchBit, 2, false)
op(0x54, DirectIndexedRead, fp(EOR), A, X) op(0x54, DirectIndexedRead, fp(EOR), A, X)
op(0x55, AbsoluteIndexedRead, fp(EOR), X) op(0x55, AbsoluteIndexedRead, fp(EOR), X)
op(0x56, AbsoluteIndexedRead, fp(EOR), Y) op(0x56, AbsoluteIndexedRead, fp(EOR), Y)
@ -98,11 +98,11 @@ auto SPC700::instruction() -> void {
op(0x5c, ImpliedModify, fp(LSR), A) op(0x5c, ImpliedModify, fp(LSR), A)
op(0x5d, Transfer, A, X) op(0x5d, Transfer, A, X)
op(0x5e, AbsoluteRead, fp(CMP), Y) op(0x5e, AbsoluteRead, fp(CMP), Y)
op(0x5f, JMPAbsolute) op(0x5f, JumpAbsolute)
op(0x60, FlagClear, CF) op(0x60, FlagSet, CF, false)
op(0x61, JST, 6) op(0x61, CallTable, 6)
op(0x62, SET, 3) op(0x62, AbsoluteBitSet, 3, true)
op(0x63, BBS, 3) op(0x63, BranchBit, 3, true)
op(0x64, DirectRead, fp(CMP), A) op(0x64, DirectRead, fp(CMP), A)
op(0x65, AbsoluteRead, fp(CMP), A) op(0x65, AbsoluteRead, fp(CMP), A)
op(0x66, IndirectXRead, fp(CMP)) op(0x66, IndirectXRead, fp(CMP))
@ -113,12 +113,12 @@ auto SPC700::instruction() -> void {
op(0x6b, DirectModify, fp(ROR)) op(0x6b, DirectModify, fp(ROR))
op(0x6c, AbsoluteModify, fp(ROR)) op(0x6c, AbsoluteModify, fp(ROR))
op(0x6d, Push, Y) op(0x6d, Push, Y)
op(0x6e, BNEDirectDecrement) op(0x6e, BranchNotDirectDecrement)
op(0x6f, RTS) op(0x6f, ReturnSubroutine)
op(0x70, Branch, VF == 1) op(0x70, Branch, VF == 1)
op(0x71, JST, 7) op(0x71, CallTable, 7)
op(0x72, CLR, 3) op(0x72, AbsoluteBitSet, 3, false)
op(0x73, BBC, 3) op(0x73, BranchBit, 3, false)
op(0x74, DirectIndexedRead, fp(CMP), A, X) op(0x74, DirectIndexedRead, fp(CMP), A, X)
op(0x75, AbsoluteIndexedRead, fp(CMP), X) op(0x75, AbsoluteIndexedRead, fp(CMP), X)
op(0x76, AbsoluteIndexedRead, fp(CMP), Y) op(0x76, AbsoluteIndexedRead, fp(CMP), Y)
@ -130,11 +130,11 @@ auto SPC700::instruction() -> void {
op(0x7c, ImpliedModify, fp(ROR), A) op(0x7c, ImpliedModify, fp(ROR), A)
op(0x7d, Transfer, X, A) op(0x7d, Transfer, X, A)
op(0x7e, DirectRead, fp(CMP), Y) op(0x7e, DirectRead, fp(CMP), Y)
op(0x7f, RTI) op(0x7f, ReturnInterrupt)
op(0x80, FlagSet, CF) op(0x80, FlagSet, CF, true)
op(0x81, JST, 8) op(0x81, CallTable, 8)
op(0x82, SET, 4) op(0x82, AbsoluteBitSet, 4, true)
op(0x83, BBS, 4) op(0x83, BranchBit, 4, true)
op(0x84, DirectRead, fp(ADC), A) op(0x84, DirectRead, fp(ADC), A)
op(0x85, AbsoluteRead, fp(ADC), A) op(0x85, AbsoluteRead, fp(ADC), A)
op(0x86, IndirectXRead, fp(ADC)) op(0x86, IndirectXRead, fp(ADC))
@ -145,12 +145,12 @@ auto SPC700::instruction() -> void {
op(0x8b, DirectModify, fp(DEC)) op(0x8b, DirectModify, fp(DEC))
op(0x8c, AbsoluteModify, fp(DEC)) op(0x8c, AbsoluteModify, fp(DEC))
op(0x8d, ImmediateRead, fp(LD), Y) op(0x8d, ImmediateRead, fp(LD), Y)
op(0x8e, PLP) op(0x8e, PullP)
op(0x8f, DirectWriteImmediate, fp(ST)) op(0x8f, DirectWriteImmediate, fp(ST))
op(0x90, Branch, CF == 0) op(0x90, Branch, CF == 0)
op(0x91, JST, 9) op(0x91, CallTable, 9)
op(0x92, CLR, 4) op(0x92, AbsoluteBitSet, 4, false)
op(0x93, BBC, 4) op(0x93, BranchBit, 4, false)
op(0x94, DirectIndexedRead, fp(ADC), A, X) op(0x94, DirectIndexedRead, fp(ADC), A, X)
op(0x95, AbsoluteIndexedRead, fp(ADC), X) op(0x95, AbsoluteIndexedRead, fp(ADC), X)
op(0x96, AbsoluteIndexedRead, fp(ADC), Y) op(0x96, AbsoluteIndexedRead, fp(ADC), Y)
@ -161,12 +161,12 @@ auto SPC700::instruction() -> void {
op(0x9b, DirectIndexedModify, fp(DEC), X) op(0x9b, DirectIndexedModify, fp(DEC), X)
op(0x9c, ImpliedModify, fp(DEC), A) op(0x9c, ImpliedModify, fp(DEC), A)
op(0x9d, Transfer, S, X) op(0x9d, Transfer, S, X)
op(0x9e, DIV) op(0x9e, Divide)
op(0x9f, XCN) op(0x9f, ExchangeNibble)
op(0xa0, FlagSet, IF) op(0xa0, FlagSet, IF, true)
op(0xa1, JST, 10) op(0xa1, CallTable, 10)
op(0xa2, SET, 5) op(0xa2, AbsoluteBitSet, 5, true)
op(0xa3, BBS, 5) op(0xa3, BranchBit, 5, true)
op(0xa4, DirectRead, fp(SBC), A) op(0xa4, DirectRead, fp(SBC), A)
op(0xa5, AbsoluteRead, fp(SBC), A) op(0xa5, AbsoluteRead, fp(SBC), A)
op(0xa6, IndirectXRead, fp(SBC)) op(0xa6, IndirectXRead, fp(SBC))
@ -180,9 +180,9 @@ auto SPC700::instruction() -> void {
op(0xae, Pull, A) op(0xae, Pull, A)
op(0xaf, IndirectXIncrementWrite, A) op(0xaf, IndirectXIncrementWrite, A)
op(0xb0, Branch, CF == 1) op(0xb0, Branch, CF == 1)
op(0xb1, JST, 11) op(0xb1, CallTable, 11)
op(0xb2, CLR, 5) op(0xb2, AbsoluteBitSet, 5, false)
op(0xb3, BBC, 5) op(0xb3, BranchBit, 5, false)
op(0xb4, DirectIndexedRead, fp(SBC), A, X) op(0xb4, DirectIndexedRead, fp(SBC), A, X)
op(0xb5, AbsoluteIndexedRead, fp(SBC), X) op(0xb5, AbsoluteIndexedRead, fp(SBC), X)
op(0xb6, AbsoluteIndexedRead, fp(SBC), Y) op(0xb6, AbsoluteIndexedRead, fp(SBC), Y)
@ -193,12 +193,12 @@ auto SPC700::instruction() -> void {
op(0xbb, DirectIndexedModify, fp(INC), X) op(0xbb, DirectIndexedModify, fp(INC), X)
op(0xbc, ImpliedModify, fp(INC), A) op(0xbc, ImpliedModify, fp(INC), A)
op(0xbd, Transfer, X, S) op(0xbd, Transfer, X, S)
op(0xbe, DAS) op(0xbe, DecimalAdjustSub)
op(0xbf, IndirectXIncrementRead, A) op(0xbf, IndirectXIncrementRead, A)
op(0xc0, FlagClear, IF) op(0xc0, FlagSet, IF, false)
op(0xc1, JST, 12) op(0xc1, CallTable, 12)
op(0xc2, SET, 6) op(0xc2, AbsoluteBitSet, 6, true)
op(0xc3, BBS, 6) op(0xc3, BranchBit, 6, true)
op(0xc4, DirectWrite, A) op(0xc4, DirectWrite, A)
op(0xc5, AbsoluteWrite, A) op(0xc5, AbsoluteWrite, A)
op(0xc6, IndirectXWrite, A) op(0xc6, IndirectXWrite, A)
@ -210,27 +210,27 @@ auto SPC700::instruction() -> void {
op(0xcc, AbsoluteWrite, Y) op(0xcc, AbsoluteWrite, Y)
op(0xcd, ImmediateRead, fp(LD), X) op(0xcd, ImmediateRead, fp(LD), X)
op(0xce, Pull, X) op(0xce, Pull, X)
op(0xcf, MUL) op(0xcf, Multiply)
op(0xd0, Branch, ZF == 0) op(0xd0, Branch, ZF == 0)
op(0xd1, JST, 13) op(0xd1, CallTable, 13)
op(0xd2, CLR, 6) op(0xd2, AbsoluteBitSet, 6, false)
op(0xd3, BBC, 6) op(0xd3, BranchBit, 6, false)
op(0xd4, DirectIndexedWrite, A, X) op(0xd4, DirectIndexedWrite, A, X)
op(0xd5, AbsoluteIndexedWrite, X) op(0xd5, AbsoluteIndexedWrite, X)
op(0xd6, AbsoluteIndexedWrite, Y) op(0xd6, AbsoluteIndexedWrite, Y)
op(0xd7, IndirectIndexedWrite, A, Y) op(0xd7, IndirectIndexedWrite, A, Y)
op(0xd8, DirectWrite, X) op(0xd8, DirectWrite, X)
op(0xd9, DirectIndexedWrite, X, Y) op(0xd9, DirectIndexedWrite, X, Y)
op(0xda, STWDirect) op(0xda, DirectWriteWord)
op(0xdb, DirectIndexedWrite, Y, X) op(0xdb, DirectIndexedWrite, Y, X)
op(0xdc, ImpliedModify, fp(DEC), Y) op(0xdc, ImpliedModify, fp(DEC), Y)
op(0xdd, Transfer, Y, A) op(0xdd, Transfer, Y, A)
op(0xde, BNEDirectX) op(0xde, BranchNotDirectX)
op(0xdf, DAA) op(0xdf, DecimalAdjustAdd)
op(0xe0, CLV) op(0xe0, OverflowClear)
op(0xe1, JST, 14) op(0xe1, CallTable, 14)
op(0xe2, SET, 7) op(0xe2, AbsoluteBitSet, 7, true)
op(0xe3, BBS, 7) op(0xe3, BranchBit, 7, true)
op(0xe4, DirectRead, fp(LD), A) op(0xe4, DirectRead, fp(LD), A)
op(0xe5, AbsoluteRead, fp(LD), A) op(0xe5, AbsoluteRead, fp(LD), A)
op(0xe6, IndirectXRead, fp(LD)) op(0xe6, IndirectXRead, fp(LD))
@ -240,13 +240,13 @@ auto SPC700::instruction() -> void {
op(0xea, AbsoluteBitModify, 7) op(0xea, AbsoluteBitModify, 7)
op(0xeb, DirectRead, fp(LD), Y) op(0xeb, DirectRead, fp(LD), Y)
op(0xec, AbsoluteRead, fp(LD), Y) op(0xec, AbsoluteRead, fp(LD), Y)
op(0xed, CMC) op(0xed, ComplementCarry)
op(0xee, Pull, Y) op(0xee, Pull, Y)
op(0xef, WAI) op(0xef, Wait)
op(0xf0, Branch, ZF == 1) op(0xf0, Branch, ZF == 1)
op(0xf1, JST, 15) op(0xf1, CallTable, 15)
op(0xf2, CLR, 7) op(0xf2, AbsoluteBitSet, 7, false)
op(0xf3, BBC, 7) op(0xf3, BranchBit, 7, false)
op(0xf4, DirectIndexedRead, fp(LD), A, X) op(0xf4, DirectIndexedRead, fp(LD), A, X)
op(0xf5, AbsoluteIndexedRead, fp(LD), X) op(0xf5, AbsoluteIndexedRead, fp(LD), X)
op(0xf6, AbsoluteIndexedRead, fp(LD), Y) op(0xf6, AbsoluteIndexedRead, fp(LD), Y)
@ -257,8 +257,8 @@ auto SPC700::instruction() -> void {
op(0xfb, DirectIndexedRead, fp(LD), Y, X) op(0xfb, DirectIndexedRead, fp(LD), Y, X)
op(0xfc, ImpliedModify, fp(INC), Y) op(0xfc, ImpliedModify, fp(INC), Y)
op(0xfd, Transfer, A, Y) op(0xfd, Transfer, A, Y)
op(0xfe, BNEYDecrement) op(0xfe, BranchNotYDecrement)
op(0xff, STP) op(0xff, Stop)
} }
} }

View File

@ -1,16 +1,16 @@
auto SPC700::instructionAbsoluteBitModify(uint3 mode) -> void { auto SPC700::instructionAbsoluteBitModify(uint3 mode) -> void {
uint16 absolute = fetch(); uint16 address = read(PC++);
absolute |= fetch() << 8; address |= read(PC++) << 8;
uint3 bit = absolute >> 13; uint3 bit = address >> 13;
absolute &= 0x1fff; address &= 0x1fff;
uint8 data = read(absolute); uint8 data = read(address);
switch(mode) { switch(mode) {
case 0: //orc addr:bit case 0: //or addr:bit
idle(); idle(address);
CF |= data.bit(bit); CF |= data.bit(bit);
break; break;
case 1: //orc !addr:bit case 1: //or !addr:bit
idle(); idle(address);
CF |= !data.bit(bit); CF |= !data.bit(bit);
break; break;
case 2: //and addr:bit case 2: //and addr:bit
@ -20,360 +20,185 @@ auto SPC700::instructionAbsoluteBitModify(uint3 mode) -> void {
CF &= !data.bit(bit); CF &= !data.bit(bit);
break; break;
case 4: //eor addr:bit case 4: //eor addr:bit
idle(); idle(address);
CF ^= data.bit(bit); CF ^= data.bit(bit);
break; break;
case 5: //ldc addr:bit case 5: //ld addr:bit
CF = data.bit(bit); CF = data.bit(bit);
break; break;
case 6: //stc addr:bit case 6: //st addr:bit
idle(); idle(address);
data.bit(bit) = CF; data.bit(bit) = CF;
write(absolute, data); write(address, data);
break; break;
case 7: //not addr:bit case 7: //not addr:bit
data.bit(bit) ^= 1; data.bit(bit) ^= 1;
write(absolute, data); write(address, data);
break; 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 { auto SPC700::instructionAbsoluteRead(fpb op, uint8& target) -> void {
uint16 absolute = fetch(); uint16 address = read(PC++);
absolute |= fetch() << 8; address |= read(PC++) << 8;
uint8 data = read(absolute); uint8 data = read(address);
target = alu(target, data); target = alu(target, data);
} }
auto SPC700::instructionAbsoluteModify(fps op) -> void { auto SPC700::instructionAbsoluteModify(fps op) -> void {
uint16 absolute = fetch(); uint16 address = read(PC++);
absolute |= fetch() << 8; address |= read(PC++) << 8;
uint8 data = read(absolute); uint8 data = read(address);
write(absolute, alu(data)); write(address, alu(data));
} }
auto SPC700::instructionAbsoluteWrite(uint8& data) -> void { auto SPC700::instructionAbsoluteWrite(uint8& data) -> void {
uint16 absolute = fetch(); uint16 address = read(PC++);
absolute |= fetch() << 8; address |= read(PC++) << 8;
read(absolute); read(address);
write(absolute, data); write(address, data);
} }
auto SPC700::instructionAbsoluteIndexedRead(fpb op, uint8& index) -> void { auto SPC700::instructionAbsoluteIndexedRead(fpb op, uint8& index) -> void {
uint16 absolute = fetch(); uint16 address = read(PC++);
absolute |= fetch() << 8; address |= read(PC++) << 8;
idle(); idle(PC - 1);
uint8 data = read(absolute + index); uint8 data = read(address + index);
A = alu(A, data); A = alu(A, data);
} }
auto SPC700::instructionAbsoluteIndexedWrite(uint8& index) -> void { auto SPC700::instructionAbsoluteIndexedWrite(uint8& index) -> void {
uint16 absolute = fetch(); uint16 address = read(PC++);
absolute |= fetch() << 8; address |= read(PC++) << 8;
idle(); idle(PC - 1);
absolute += index; read(address + index);
read(absolute); write(address + index, A);
write(absolute, A);
} }
auto SPC700::instructionBranch(bool take) -> void { auto SPC700::instructionBranch(bool take) -> void {
uint8 data = fetch(); uint8 data = read(PC++);
if(!take) return; if(!take) return;
idle(); idle(PC - 1);
idle(); idle(PC - 1);
PC += (int8)data; PC += (int8)data;
} }
auto SPC700::instructionDirectRead(fpb op, uint8& target) -> void { auto SPC700::instructionBranchBit(uint3 bit, bool match) -> void {
uint8 direct = fetch(); uint8 address = read(PC++);
uint8 data = load(direct); uint8 data = read(page(address));
target = alu(target, data); idle(page(address));
} uint8 displacement = read(PC++);
if(data.bit(bit) != match) return;
auto SPC700::instructionDirectModify(fps op) -> void { idle(PC - 1);
uint8 direct = fetch(); idle(PC - 1);
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();
PC += (int8)displacement; PC += (int8)displacement;
} }
auto SPC700::instructionBBS(uint3 bit) -> void { auto SPC700::instructionBranchNotDirect() -> void {
uint8 direct = fetch(); uint8 address = read(PC++);
uint8 data = load(direct); uint8 data = read(page(address));
uint8 displacement = fetch(); idle(page(address));
idle(); uint8 displacement = read(PC++);
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();
if(A == data) return; if(A == data) return;
idle(); idle(PC - 1);
idle(); idle(PC - 1);
PC += (int8)displacement; PC += (int8)displacement;
} }
auto SPC700::instructionBNEDirectDecrement() -> void { auto SPC700::instructionBranchNotDirectDecrement() -> void {
uint8 direct = fetch(); uint8 address = read(PC++);
uint8 data = load(direct); uint8 data = read(page(address));
store(direct, --data); write(page(address), --data);
uint8 displacement = fetch(); uint8 displacement = read(PC++);
if(data == 0) return; if(data == 0) return;
idle(); idle(PC - 1);
idle(); idle(PC - 1);
PC += (int8)displacement; PC += (int8)displacement;
} }
auto SPC700::instructionBNEDirectX() -> void { auto SPC700::instructionBranchNotDirectX() -> void {
uint8 direct = fetch(); uint8 address = read(PC++);
idle(); idle(PC - 1);
uint8 data = load(direct + X); uint8 data = read(page(address + X));
uint8 displacement = fetch(); idle(page(address + X));
idle(); uint8 displacement = read(PC++);
if(A == data) return; if(A == data) return;
idle(); idle(PC - 1);
idle(); idle(PC - 1);
PC += (int8)displacement; PC += (int8)displacement;
} }
auto SPC700::instructionBNEYDecrement() -> void { auto SPC700::instructionBranchNotYDecrement() -> void {
uint8 displacement = fetch(); idle(PC);
idle(); idle(PC);
idle(); uint8 displacement = read(PC++);
if(--Y == 0) return; if(--Y == 0) return;
idle(); idle(PC - 1);
idle(); idle(PC - 1);
PC += (int8)displacement; PC += (int8)displacement;
} }
auto SPC700::instructionBRK() -> void { auto SPC700::instructionBreak() -> void {
uint16 absolute = read(0xffde); idle(PC);
absolute |= read(0xffdf) << 8; write(stack(S--), PC >> 8);
idle(); write(stack(S--), PC >> 0);
idle(); write(stack(S--), P);
push(PC >> 8); idle(stack(S + 1));
push(PC >> 0); uint16 address = read(0xffde + 0);
push(P); address |= read(0xffde + 1) << 8;
PC = absolute; PC = address;
IF = 0; IF = 0;
BF = 1; BF = 1;
} }
auto SPC700::instructionCLR(uint3 bit) -> void { auto SPC700::instructionCallAbsolute() -> void {
uint8 direct = fetch(); uint16 address = read(PC++);
uint8 data = load(direct); address |= read(PC++) << 8;
data.bit(bit) = 0; idle(stack(S));
store(direct, data); write(stack(S--), PC >> 8);
write(stack(S--), PC >> 0);
idle(stack(S + 1));
idle(stack(S + 1));
PC = address;
} }
auto SPC700::instructionCLV() -> void { auto SPC700::instructionCallPage() -> void {
idle(); uint8 address = read(PC++);
HF = 0; idle(PC - 1);
VF = 0; write(stack(S--), PC >> 8);
write(stack(S--), PC >> 0);
idle(stack(S + 1));
PC = 0xff00 | address;
} }
auto SPC700::instructionCMC() -> void { auto SPC700::instructionCallTable(uint4 vector) -> void {
idle(); idle(PC);
idle(); 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; CF = !CF;
} }
auto SPC700::instructionDAA() -> void { auto SPC700::instructionDecimalAdjustAdd() -> void {
idle(); idle(PC);
idle(); idle(PC);
if(CF || A > 0x99) { if(CF || A > 0x99) {
A += 0x60; A += 0x60;
CF = 1; CF = 1;
@ -385,9 +210,9 @@ auto SPC700::instructionDAA() -> void {
NF = A & 0x80; NF = A & 0x80;
} }
auto SPC700::instructionDAS() -> void { auto SPC700::instructionDecimalAdjustSub() -> void {
idle(); idle(PC);
idle(); idle(PC);
if(!CF || A > 0x99) { if(!CF || A > 0x99) {
A -= 0x60; A -= 0x60;
CF = 0; CF = 0;
@ -399,18 +224,100 @@ auto SPC700::instructionDAS() -> void {
NF = A & 0x80; NF = A & 0x80;
} }
auto SPC700::instructionDIV() -> void { auto SPC700::instructionDirectRead(fpb op, uint8& target) -> void {
idle(); uint8 address = read(PC++);
idle(); uint8 data = read(page(address));
idle(); target = alu(target, data);
idle(); }
idle();
idle(); auto SPC700::instructionDirectModify(fps op) -> void {
idle(); uint8 address = read(PC++);
idle(); uint8 data = read(page(address));
idle(); write(page(address), alu(data));
idle(); }
idle();
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; uint16 ya = YA;
//overflow set if quotient >= 256 //overflow set if quotient >= 256
HF = (Y & 15) >= (X & 15); HF = (Y & 15) >= (X & 15);
@ -430,63 +337,126 @@ auto SPC700::instructionDIV() -> void {
NF = A & 0x80; NF = A & 0x80;
} }
auto SPC700::instructionJMPAbsolute() -> void { auto SPC700::instructionExchangeNibble() -> void {
uint16 absolute = fetch(); idle(PC);
absolute |= fetch() << 8; idle(PC);
PC = absolute; idle(PC);
idle(PC);
A = A >> 4 | A << 4;
ZF = A == 0;
NF = A & 0x80;
} }
auto SPC700::instructionJMPIndirectX() -> void { auto SPC700::instructionFlagSet(bool& flag, bool value) -> void {
uint16 absolute = fetch(); idle(PC);
absolute |= fetch() << 8; if(&flag == &IF) idle(PC);
idle(); flag = value;
absolute += X; }
uint16 pc = read(absolute++);
pc |= read(absolute++) << 8; 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; PC = pc;
} }
auto SPC700::instructionJSPDirect() -> void { auto SPC700::instructionMultiply() -> void {
uint8 direct = fetch(); idle(PC);
idle(); idle(PC);
idle(); idle(PC);
push(PC >> 8); idle(PC);
push(PC >> 0); idle(PC);
PC = 0xff00 | direct; idle(PC);
} idle(PC);
idle(PC);
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();
uint16 ya = Y * A; uint16 ya = Y * A;
A = ya >> 0; A = ya >> 0;
Y = ya >> 8; Y = ya >> 8;
@ -495,89 +465,81 @@ auto SPC700::instructionMUL() -> void {
NF = Y & 0x80; NF = Y & 0x80;
} }
auto SPC700::instructionNOP() -> void { auto SPC700::instructionNoOperation() -> void {
idle(); idle(PC);
} }
auto SPC700::instructionPLP() -> void { auto SPC700::instructionOverflowClear() -> void {
idle(); idle(PC);
idle(); HF = 0;
P = pull(); VF = 0;
} }
auto SPC700::instructionRTI() -> void { auto SPC700::instructionPull(uint8& data) -> void {
P = pull(); idle(PC);
uint16 absolute = pull(); idle(stack(S));
absolute |= pull() << 8; data = read(stack(++S));
idle();
idle();
PC = absolute;
} }
auto SPC700::instructionRTS() -> void { auto SPC700::instructionPullP() -> void {
uint16 absolute = pull(); idle(PC);
absolute |= pull() << 8; idle(stack(S));
idle(); P = read(stack(++S));
idle();
PC = absolute;
} }
auto SPC700::instructionSET(uint3 bit) -> void { auto SPC700::instructionPush(uint8 data) -> void {
uint8 direct = fetch(); idle(PC);
uint8 data = load(direct); write(stack(S--), data);
data.bit(bit) = 1; idle(stack(S + 1));
store(direct, data);
} }
auto SPC700::instructionSTP() -> void { auto SPC700::instructionReturnInterrupt() -> void {
r.stp = true; idle(PC);
while(r.stp && !synchronizing()) { idle(stack(S));
idle(); P = read(stack(++S));
idle(); 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 { auto SPC700::instructionTestSetBitsAbsolute(bool set) -> void {
uint8 direct = fetch(); uint16 address = read(PC++);
load(direct); address |= read(PC++) << 8;
store(direct++, A); uint8 data = read(address);
store(direct++, Y);
}
auto SPC700::instructionTRBAbsolute() -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
uint8 data = read(absolute);
ZF = (A - data) == 0; ZF = (A - data) == 0;
NF = (A - data) & 0x80; NF = (A - data) & 0x80;
read(absolute); idle(address);
write(absolute, data & ~A); write(address, set ? data | A : data & ~A);
} }
auto SPC700::instructionTSBAbsolute() -> void { auto SPC700::instructionTransfer(uint8& from, uint8& to) -> void {
uint16 absolute = fetch(); idle(PC);
absolute |= fetch() << 8; to = from;
uint8 data = read(absolute); if(&to == &S) return;
ZF = (A - data) == 0; ZF = to == 0;
NF = (A - data) & 0x80; NF = to & 0x80;
read(absolute);
write(absolute, data | A);
} }
auto SPC700::instructionWAI() -> void { auto SPC700::instructionWait() -> void {
r.wai = true; r.wait = true;
while(r.wai && !synchronizing()) { while(r.wait && !synchronizing()) {
idle(); idle(PC);
idle(); idle(PC);
} }
} }
auto SPC700::instructionXCN() -> void {
idle();
idle();
idle();
idle();
A = A >> 4 | A << 4;
ZF = A == 0;
NF = A & 0x80;
}

View File

@ -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);
}

View File

@ -12,6 +12,6 @@ auto SPC700::serialize(serializer& s) -> void {
s.integer(r.p.v); s.integer(r.p.v);
s.integer(r.p.n); s.integer(r.p.n);
s.integer(r.wai); s.integer(r.wait);
s.integer(r.stp); s.integer(r.stop);
} }

View File

@ -22,13 +22,35 @@ namespace Processor {
#define alu (this->*op) #define alu (this->*op)
#include "memory.cpp"
#include "algorithms.cpp" #include "algorithms.cpp"
#include "instructions.cpp" #include "instructions.cpp"
#include "instruction.cpp" #include "instruction.cpp"
#include "serialization.cpp" #include "serialization.cpp"
#include "disassembler.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 PC
#undef YA #undef YA
#undef A #undef A
@ -48,15 +70,4 @@ namespace Processor {
#undef alu #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;
}
} }

View File

@ -3,26 +3,22 @@
namespace Processor { namespace Processor {
struct SPC700 { struct SPC700 {
virtual auto read(uint16 addr) -> uint8 = 0; virtual auto read(uint16 address) -> uint8 = 0;
virtual auto write(uint16 addr, uint8 data) -> void = 0; virtual auto write(uint16 addessr, uint8 data) -> void = 0;
virtual auto synchronizing() const -> bool = 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 //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; auto power() -> void;
//instruction.cpp //instruction.cpp
auto instruction() -> void; 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 //algorithms.cpp
auto algorithmADC(uint8, uint8) -> uint8; auto algorithmADC(uint8, uint8) -> uint8;
auto algorithmAND(uint8, uint8) -> uint8; auto algorithmAND(uint8, uint8) -> uint8;
@ -49,12 +45,25 @@ struct SPC700 {
using fpw = auto (SPC700::*)(uint16, uint16) -> uint16; using fpw = auto (SPC700::*)(uint16, uint16) -> uint16;
auto instructionAbsoluteBitModify(uint3) -> void; auto instructionAbsoluteBitModify(uint3) -> void;
auto instructionAbsoluteBitSet(uint3, bool) -> void;
auto instructionAbsoluteRead(fpb, uint8&) -> void; auto instructionAbsoluteRead(fpb, uint8&) -> void;
auto instructionAbsoluteModify(fps) -> void; auto instructionAbsoluteModify(fps) -> void;
auto instructionAbsoluteWrite(uint8&) -> void; auto instructionAbsoluteWrite(uint8&) -> void;
auto instructionAbsoluteIndexedRead(fpb, uint8&) -> void; auto instructionAbsoluteIndexedRead(fpb, uint8&) -> void;
auto instructionAbsoluteIndexedWrite(uint8&) -> void; auto instructionAbsoluteIndexedWrite(uint8&) -> void;
auto instructionBranch(bool) -> 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 instructionDirectRead(fpb, uint8&) -> void;
auto instructionDirectModify(fps) -> void; auto instructionDirectModify(fps) -> void;
auto instructionDirectWrite(uint8&) -> void; auto instructionDirectWrite(uint8&) -> void;
@ -62,11 +71,13 @@ struct SPC700 {
auto instructionDirectWriteImmediate(fpb) -> void; auto instructionDirectWriteImmediate(fpb) -> void;
auto instructionDirectReadWord(fpw) -> void; auto instructionDirectReadWord(fpw) -> void;
auto instructionDirectModifyWord(int) -> void; auto instructionDirectModifyWord(int) -> void;
auto instructionDirectWriteWord() -> void;
auto instructionDirectIndexedRead(fpb, uint8&, uint8&) -> void; auto instructionDirectIndexedRead(fpb, uint8&, uint8&) -> void;
auto instructionDirectIndexedModify(fps, uint8&) -> void; auto instructionDirectIndexedModify(fps, uint8&) -> void;
auto instructionDirectIndexedWrite(uint8&, uint8&) -> void; auto instructionDirectIndexedWrite(uint8&, uint8&) -> void;
auto instructionFlagClear(bool&) -> void; auto instructionDivide() -> void;
auto instructionFlagSet(bool&) -> void; auto instructionExchangeNibble() -> void;
auto instructionFlagSet(bool&, bool) -> void;
auto instructionImmediateRead(fpb, uint8&) -> void; auto instructionImmediateRead(fpb, uint8&) -> void;
auto instructionImpliedModify(fps, uint8&) -> void; auto instructionImpliedModify(fps, uint8&) -> void;
auto instructionIndexedIndirectRead(fpb, uint8&) -> void; auto instructionIndexedIndirectRead(fpb, uint8&) -> void;
@ -78,46 +89,26 @@ struct SPC700 {
auto instructionIndirectXIncrementRead(uint8&) -> void; auto instructionIndirectXIncrementRead(uint8&) -> void;
auto instructionIndirectXIncrementWrite(uint8&) -> void; auto instructionIndirectXIncrementWrite(uint8&) -> void;
auto instructionIndirectXWriteIndirectY(fpb) -> 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 instructionPull(uint8&) -> void;
auto instructionPullP() -> void;
auto instructionPush(uint8) -> void; auto instructionPush(uint8) -> void;
auto instructionReturnInterrupt() -> void;
auto instructionReturnSubroutine() -> void;
auto instructionStop() -> void;
auto instructionTestSetBitsAbsolute(bool) -> void;
auto instructionTransfer(uint8&, uint8&) -> void; auto instructionTransfer(uint8&, uint8&) -> void;
auto instructionWait() -> 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;
//serialization.cpp //serialization.cpp
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;
//disassembler.cpp //disassembler.cpp
auto disassemble(uint16 addr, bool p) -> string; auto disassemble(uint16 address, bool p) -> string;
struct Flags { struct Flags {
bool c; //carry bool c; //carry
@ -155,8 +146,8 @@ struct SPC700 {
uint8 x, s; uint8 x, s;
Flags p; Flags p;
bool wai = false; bool wait = false;
bool stp = false; bool stop = false;
} r; } r;
}; };

View File

@ -17,8 +17,8 @@ auto SMP::Enter() -> void {
} }
auto SMP::main() -> void { auto SMP::main() -> void {
if(r.wai) return instructionWAI(); if(r.wait) return instructionWait();
if(r.stp) return instructionSTP(); if(r.stop) return instructionStop();
instruction(); instruction();
} }