From 3517d5c4a44a649a66a0e40f818b722d145ab400 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Tue, 27 Jun 2017 11:18:28 +1000 Subject: [PATCH] Update to v103r02 release. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit byuu says: Changelog: - fc/apu: improved phase duty cycle emulation (mode 3 is 25% phase inverted; counter decrements) - md/apu: power/reset do not cancel 68K bus requests - md/apu: 68K is not granted bus access on Z80 power/reset - md/controller: replaced System::Peripherals with ControllerPort concept - md/controller: CTRL port is now read-write, maintains value across controller changes (and soon, soft resets) - md/psg: PSG sampling rate unintentionally modified¹ - processor/spc700: improve cycle timing of (indirect),y instructions [Overload] - processor/spc700: idle() cycles actually read from the program counter; much like the 6502 [Overload] - some of the idle() cycles should read from other addresses; this still needs to be supported - processor/spc700: various cleanups to instruction function naming - processor/z80: prefix state (HL→IX,IY override) can now be serialized - icarus: fix install rule for certain platforms (it wasn't buggy on FreeBSD, but was on Linux?) ¹: the clock speed of the PSG is oscillator/15. But I was setting the sampling rate to oscillator/15/16, which was around 223KHz. I am not sure whether the PSG should be outputting at 3MHz or 223KHz. Amazingly ... I don't really hear a difference either way `o_O` I didn't actually mean to make this change; I just noticed it after comparing the diff between r01 and r02. If this turns out to be wrong, set stream = Emulator::audio.createStream(1, frequency() / 16.0); in md/psg.cpp to revert this change. --- higan/emulator/emulator.hpp | 2 +- higan/fc/apu/pulse.cpp | 11 +- higan/md/apu/apu.cpp | 12 +- higan/md/bus/bus.cpp | 24 +- higan/md/controller/controller.cpp | 56 +++- higan/md/controller/controller.hpp | 25 +- higan/md/cpu/cpu.cpp | 4 +- higan/md/interface/interface.cpp | 4 +- higan/md/psg/psg.cpp | 2 +- higan/md/system/peripherals.cpp | 55 ---- higan/md/system/serialization.cpp | 3 + higan/md/system/system.cpp | 19 +- higan/md/system/system.hpp | 15 +- higan/md/vdp/vdp.cpp | 2 +- higan/md/ym2612/ym2612.cpp | 2 +- higan/processor/spc700/instruction.cpp | 182 +++++------ higan/processor/spc700/instructions.cpp | 411 ++++++++++++------------ higan/processor/spc700/memory.cpp | 4 + higan/processor/spc700/spc700.hpp | 70 ++-- higan/processor/z80/instruction.cpp | 8 +- higan/processor/z80/registers.cpp | 6 +- higan/processor/z80/serialization.cpp | 3 +- higan/processor/z80/z80.cpp | 6 +- higan/processor/z80/z80.hpp | 4 +- higan/sfc/smp/memory.cpp | 5 - higan/sfc/smp/smp.hpp | 1 - icarus/GNUmakefile | 2 +- 27 files changed, 477 insertions(+), 461 deletions(-) delete mode 100644 higan/md/system/peripherals.cpp diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index f5ae48cd..9405fafb 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "103.01"; + static const string Version = "103.02"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/fc/apu/pulse.cpp b/higan/fc/apu/pulse.cpp index dea73908..0be52b68 100644 --- a/higan/fc/apu/pulse.cpp +++ b/higan/fc/apu/pulse.cpp @@ -8,13 +8,18 @@ auto APU::Pulse::clock() -> uint8 { if(!sweep.checkPeriod()) return 0; if(lengthCounter == 0) return 0; - static const uint dutyTable[] = {1, 2, 4, 6}; - uint8 result = (dutyCounter < dutyTable[duty]) ? envelope.volume() : 0; + static const uint dutyTable[4][8] = { + {0, 1, 0, 0, 0, 0, 0, 0}, //12.5% + {0, 1, 1, 0, 0, 0, 0, 0}, //25.0% + {0, 1, 1, 1, 1, 0, 0, 0}, //50.0% + {1, 0, 0, 1, 1, 1, 1, 1}, //25.0% (inverted) + }; + uint8 result = dutyTable[duty][dutyCounter] ? envelope.volume() : 0; if(sweep.pulsePeriod < 0x008) result = 0; if(--periodCounter == 0) { periodCounter = (sweep.pulsePeriod + 1) * 2; - dutyCounter++; + dutyCounter--; } return result; diff --git a/higan/md/apu/apu.cpp b/higan/md/apu/apu.cpp index 08cdaaee..bfe0908b 100644 --- a/higan/md/apu/apu.cpp +++ b/higan/md/apu/apu.cpp @@ -54,14 +54,16 @@ auto APU::enable(bool value) -> void { auto APU::power() -> void { Z80::bus = &busAPU; Z80::power(); - create(APU::Enter, system.colorburst()); - memory::fill(&state, sizeof(State)); + bus->grant(false); + create(APU::Enter, system.frequency() / 15.0); + state = {}; } auto APU::reset() -> void { - create(APU::Enter, system.colorburst()); - memory::fill(&r, sizeof(Registers)); - memory::fill(&state, sizeof(State)); + Z80::power(); + bus->grant(false); + create(APU::Enter, system.frequency() / 15.0); + state = {}; } } diff --git a/higan/md/bus/bus.cpp b/higan/md/bus/bus.cpp index 1145fdc4..ca78b524 100644 --- a/higan/md/bus/bus.cpp +++ b/higan/md/bus/bus.cpp @@ -73,13 +73,13 @@ auto BusCPU::readIO(uint24 addr) -> uint16 { | 0 << 0 //0 = Model 1; 1 = Model 2+ ); - case 0xa10002: return peripherals.controllerPort1->readData(); - case 0xa10004: return peripherals.controllerPort2->readData(); - case 0xa10006: return peripherals.extensionPort->readData(); + case 0xa10002: return controllerPort1.readData(); + case 0xa10004: return controllerPort2.readData(); + case 0xa10006: return extensionPort.readData(); - case 0xa10008: return peripherals.controllerPort1->readControl(); - case 0xa1000a: return peripherals.controllerPort2->readControl(); - case 0xa1000c: return peripherals.extensionPort->readControl(); + case 0xa10008: return controllerPort1.readControl(); + case 0xa1000a: return controllerPort2.readControl(); + case 0xa1000c: return extensionPort.readControl(); case 0xa11100: return !busAPU.granted(); } @@ -89,13 +89,13 @@ auto BusCPU::readIO(uint24 addr) -> uint16 { auto BusCPU::writeIO(uint24 addr, uint16 data) -> void { switch(addr & ~1) { - case 0xa10002: return peripherals.controllerPort1->writeData(data); - case 0xa10004: return peripherals.controllerPort2->writeData(data); - case 0xa10006: return peripherals.extensionPort->writeData(data); + case 0xa10002: return controllerPort1.writeData(data); + case 0xa10004: return controllerPort2.writeData(data); + case 0xa10006: return extensionPort.writeData(data); - case 0xa10008: return peripherals.controllerPort1->writeControl(data); - case 0xa1000a: return peripherals.controllerPort2->writeControl(data); - case 0xa1000c: return peripherals.extensionPort->writeControl(data); + case 0xa10008: return controllerPort1.writeControl(data); + case 0xa1000a: return controllerPort2.writeControl(data); + case 0xa1000c: return extensionPort.writeControl(data); case 0xa11100: return busAPU.request(data.bit(0)); case 0xa11200: return apu.enable(data.bit(0)); diff --git a/higan/md/controller/controller.cpp b/higan/md/controller/controller.cpp index d4572a4f..9beb61a5 100644 --- a/higan/md/controller/controller.cpp +++ b/higan/md/controller/controller.cpp @@ -2,6 +2,9 @@ namespace MegaDrive { +ControllerPort controllerPort1; +ControllerPort controllerPort2; +ControllerPort extensionPort; #include "gamepad/gamepad.cpp" Controller::Controller(uint port) : port(port) { @@ -15,9 +18,9 @@ Controller::~Controller() { auto Controller::Enter() -> void { while(true) { scheduler.synchronize(); - if(peripherals.controllerPort1->active()) peripherals.controllerPort1->main(); - if(peripherals.controllerPort2->active()) peripherals.controllerPort2->main(); - if(peripherals.extensionPort->active()) peripherals.extensionPort->main(); + if(controllerPort1.controller->active()) controllerPort1.controller->main(); + if(controllerPort2.controller->active()) controllerPort2.controller->main(); + if(extensionPort.controller->active()) extensionPort.controller->main(); } } @@ -26,4 +29,51 @@ auto Controller::main() -> void { synchronize(cpu); } +// + +auto ControllerPort::connect(uint device) -> void { + if(!system.loaded()) return; + delete controller; + + switch(device) { default: + case ID::Device::None: controller = new Controller(port); break; + case ID::Device::Gamepad: controller = new Gamepad(port); break; + } + + cpu.peripherals.reset(); + cpu.peripherals.append(controllerPort1.controller); + cpu.peripherals.append(controllerPort2.controller); + cpu.peripherals.append(extensionPort.controller); +} + +auto ControllerPort::readData() -> uint8 { + return controller->readData(); +} + +auto ControllerPort::writeData(uint8 data) -> void { + return controller->writeData(data); +} + +auto ControllerPort::readControl() -> uint8 { + return control; +} + +auto ControllerPort::writeControl(uint8 data) -> void { + control = data; +} + +auto ControllerPort::power(uint port) -> void { + this->port = port; + control = 0x00; +} + +auto ControllerPort::unload() -> void { + delete controller; + controller = nullptr; +} + +auto ControllerPort::serialize(serializer& s) -> void { + s.integer(control); +} + } diff --git a/higan/md/controller/controller.hpp b/higan/md/controller/controller.hpp index a2f23011..8d8a90e9 100644 --- a/higan/md/controller/controller.hpp +++ b/higan/md/controller/controller.hpp @@ -8,10 +8,29 @@ struct Controller : Thread { virtual auto readData() -> uint8 { return 0xff; } virtual auto writeData(uint8 data) -> void {} - virtual auto readControl() -> uint8 { return 0x00; } - virtual auto writeControl(uint8 data) -> void {} - const uint port; }; +struct ControllerPort { + auto connect(uint device) -> void; + + auto readData() -> uint8; + auto writeData(uint8 data) -> void; + + auto readControl() -> uint8; + auto writeControl(uint8 data) -> void; + + auto power(uint port) -> void; + auto unload() -> void; + auto serialize(serializer&) -> void; + + uint port; + uint8 control; + Controller* controller = nullptr; +}; + +extern ControllerPort controllerPort1; +extern ControllerPort controllerPort2; +extern ControllerPort extensionPort; + #include "gamepad/gamepad.hpp" diff --git a/higan/md/cpu/cpu.cpp b/higan/md/cpu/cpu.cpp index 27c4205f..ab60a3d3 100644 --- a/higan/md/cpu/cpu.cpp +++ b/higan/md/cpu/cpu.cpp @@ -68,9 +68,9 @@ auto CPU::lower(Interrupt interrupt) -> void { auto CPU::power() -> void { M68K::bus = &busCPU; M68K::power(); - create(CPU::Enter, system.colorburst() * 15.0 / 7.0); + create(CPU::Enter, system.frequency() / 7.0); - memory::fill(&state, sizeof(State)); + state = {}; state.interruptPending.bit((uint)Interrupt::Reset) = 1; } diff --git a/higan/md/interface/interface.cpp b/higan/md/interface/interface.cpp index 80d003cd..d3c7aadf 100644 --- a/higan/md/interface/interface.cpp +++ b/higan/md/interface/interface.cpp @@ -100,7 +100,9 @@ auto Interface::unload() -> void { } auto Interface::connect(uint port, uint device) -> void { - peripherals.connect(port, device); + if(port == ID::Port::Controller1) controllerPort1.connect(settings.controllerPort1 = device); + if(port == ID::Port::Controller2) controllerPort2.connect(settings.controllerPort2 = device); + if(port == ID::Port::Extension) extensionPort.connect(settings.extensionPort = device); } auto Interface::power() -> void { diff --git a/higan/md/psg/psg.cpp b/higan/md/psg/psg.cpp index b02527fb..ee48a500 100644 --- a/higan/md/psg/psg.cpp +++ b/higan/md/psg/psg.cpp @@ -35,7 +35,7 @@ auto PSG::step(uint clocks) -> void { } auto PSG::power() -> void { - create(PSG::Enter, system.colorburst() / 16.0); + create(PSG::Enter, system.frequency() / 15.0); stream = Emulator::audio.createStream(1, frequency()); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::LowPass, 2840.0); diff --git a/higan/md/system/peripherals.cpp b/higan/md/system/peripherals.cpp deleted file mode 100644 index 1afb1479..00000000 --- a/higan/md/system/peripherals.cpp +++ /dev/null @@ -1,55 +0,0 @@ -Peripherals peripherals; - -auto Peripherals::unload() -> void { - delete controllerPort1; - delete controllerPort2; - delete extensionPort; - controllerPort1 = nullptr; - controllerPort2 = nullptr; - extensionPort = nullptr; -} - -auto Peripherals::reset() -> void { - connect(ID::Port::Controller1, settings.controllerPort1); - connect(ID::Port::Controller2, settings.controllerPort2); - connect(ID::Port::Extension, settings.extensionPort); -} - -auto Peripherals::connect(uint port, uint device) -> void { - if(port == ID::Port::Controller1) { - settings.controllerPort1 = device; - if(!system.loaded()) return; - - delete controllerPort1; - switch(device) { default: - case ID::Device::None: controllerPort1 = new Controller(0); break; - case ID::Device::Gamepad: controllerPort1 = new Gamepad(0); break; - } - } - - if(port == ID::Port::Controller2) { - settings.controllerPort2 = device; - if(!system.loaded()) return; - - delete controllerPort2; - switch(device) { default: - case ID::Device::None: controllerPort2 = new Controller(1); break; - case ID::Device::Gamepad: controllerPort2 = new Gamepad(1); break; - } - } - - if(port == ID::Port::Extension) { - settings.extensionPort = device; - if(!system.loaded()) return; - - delete extensionPort; - switch(device) { default: - case ID::Device::None: extensionPort = new Controller(2); break; - } - } - - cpu.peripherals.reset(); - cpu.peripherals.append(controllerPort1); - cpu.peripherals.append(controllerPort2); - cpu.peripherals.append(extensionPort); -} diff --git a/higan/md/system/serialization.cpp b/higan/md/system/serialization.cpp index 5d0ba189..d5d80152 100644 --- a/higan/md/system/serialization.cpp +++ b/higan/md/system/serialization.cpp @@ -63,6 +63,9 @@ auto System::serializeAll(serializer& s) -> void { vdp.serialize(s); psg.serialize(s); ym2612.serialize(s); + controllerPort1.serialize(s); + controllerPort2.serialize(s); + extensionPort.serialize(s); } auto System::serialize(serializer& s) -> void { diff --git a/higan/md/system/system.cpp b/higan/md/system/system.cpp index 7ddf9459..7122136c 100644 --- a/higan/md/system/system.cpp +++ b/higan/md/system/system.cpp @@ -5,7 +5,6 @@ namespace MegaDrive { System system; Scheduler scheduler; Cheat cheat; -#include "peripherals.cpp" #include "serialization.cpp" auto System::run() -> void { @@ -32,15 +31,15 @@ auto System::load(Emulator::Interface* interface, maybe region) -> bool if(cartridge.region() == "NTSC-J") { information.region = Region::NTSCJ; - information.colorburst = Emulator::Constants::Colorburst::NTSC; + information.frequency = Emulator::Constants::Colorburst::NTSC * 15.0; } if(cartridge.region() == "NTSC-U") { information.region = Region::NTSCU; - information.colorburst = Emulator::Constants::Colorburst::NTSC; + information.frequency = Emulator::Constants::Colorburst::NTSC * 15.0; } if(cartridge.region() == "PAL") { information.region = Region::PAL; - information.colorburst = Emulator::Constants::Colorburst::PAL * 4.0 / 5.0; + information.frequency = Emulator::Constants::Colorburst::PAL * 12.0; } serializeInit(); @@ -53,7 +52,9 @@ auto System::save() -> void { } auto System::unload() -> void { - peripherals.unload(); + controllerPort1.unload(); + controllerPort2.unload(); + extensionPort.unload(); cartridge.unload(); } @@ -74,7 +75,13 @@ auto System::power() -> void { ym2612.power(); scheduler.primary(cpu); - peripherals.reset(); + controllerPort1.power(ID::Port::Controller1); + controllerPort2.power(ID::Port::Controller2); + extensionPort.power(ID::Port::Extension); + + controllerPort1.connect(settings.controllerPort1); + controllerPort2.connect(settings.controllerPort2); + extensionPort.connect(settings.extensionPort); } } diff --git a/higan/md/system/system.hpp b/higan/md/system/system.hpp index 64fc4c35..b98a991e 100644 --- a/higan/md/system/system.hpp +++ b/higan/md/system/system.hpp @@ -7,7 +7,7 @@ struct System { auto loaded() const -> bool { return information.loaded; } auto region() const -> Region { return information.region; } - auto colorburst() const -> double { return information.colorburst; } + auto frequency() const -> double { return information.frequency; } auto run() -> void; auto runToSave() -> void; @@ -31,23 +31,12 @@ private: string manifest; bool loaded = false; Region region = Region::NTSCJ; - double colorburst = Emulator::Constants::Colorburst::NTSC; + double frequency = Emulator::Constants::Colorburst::NTSC * 15.0; uint serializeSize = 0; } information; }; -struct Peripherals { - auto unload() -> void; - auto reset() -> void; - auto connect(uint port, uint device) -> void; - - Controller* controllerPort1 = nullptr; - Controller* controllerPort2 = nullptr; - Controller* extensionPort = nullptr; -}; - extern System system; -extern Peripherals peripherals; auto Region::NTSCJ() -> bool { return system.region() == System::Region::NTSCJ; } auto Region::NTSCU() -> bool { return system.region() == System::Region::NTSCU; } diff --git a/higan/md/vdp/vdp.cpp b/higan/md/vdp/vdp.cpp index 9b0b75bd..a0267a20 100644 --- a/higan/md/vdp/vdp.cpp +++ b/higan/md/vdp/vdp.cpp @@ -68,7 +68,7 @@ auto VDP::refresh() -> void { } auto VDP::power() -> void { - create(VDP::Enter, system.colorburst() * 15.0 / 2.0); + create(VDP::Enter, system.frequency() / 2.0); memory::fill(&io, sizeof(IO)); memory::fill(&latch, sizeof(Latch)); diff --git a/higan/md/ym2612/ym2612.cpp b/higan/md/ym2612/ym2612.cpp index 28f9775d..38f97d38 100644 --- a/higan/md/ym2612/ym2612.cpp +++ b/higan/md/ym2612/ym2612.cpp @@ -155,7 +155,7 @@ auto YM2612::step(uint clocks) -> void { } auto YM2612::power() -> void { - create(YM2612::Enter, system.colorburst() * 15.0 / 7.0); + create(YM2612::Enter, system.frequency() / 7.0); stream = Emulator::audio.createStream(2, frequency() / 144.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); diff --git a/higan/processor/spc700/instruction.cpp b/higan/processor/spc700/instruction.cpp index 22e280b7..1c5c43bc 100644 --- a/higan/processor/spc700/instruction.cpp +++ b/higan/processor/spc700/instruction.cpp @@ -7,14 +7,14 @@ auto SPC700::instruction() -> void { op(0x01, JST, 0) op(0x02, SET, 0) op(0x03, BBS, 0) - op(0x04, DirectPageRead, fp(OR), A) + op(0x04, DirectRead, fp(OR), A) op(0x05, AbsoluteRead, fp(OR), A) op(0x06, IndirectXRead, fp(OR)) - op(0x07, IndirectPageXRead, fp(OR)) + op(0x07, IndexedIndirectRead, fp(OR), X) op(0x08, ImmediateRead, fp(OR), A) - op(0x09, DirectPageWriteDirectPage, fp(OR)) - op(0x0a, AbsoluteModifyBit, 0) - op(0x0b, DirectPageModify, fp(ASL)) + op(0x09, DirectWriteDirect, fp(OR)) + op(0x0a, AbsoluteBitModify, 0) + op(0x0b, DirectModify, fp(ASL)) op(0x0c, AbsoluteModify, fp(ASL)) op(0x0d, Push, P) op(0x0e, TSBAbsolute) @@ -23,78 +23,78 @@ auto SPC700::instruction() -> void { op(0x11, JST, 1) op(0x12, CLR, 0) op(0x13, BBC, 0) - op(0x14, DirectPageIndexedRead, fp(OR), A, X) + op(0x14, DirectIndexedRead, fp(OR), A, X) op(0x15, AbsoluteIndexedRead, fp(OR), X) op(0x16, AbsoluteIndexedRead, fp(OR), Y) - op(0x17, IndirectPageYRead, fp(OR)) - op(0x18, DirectPageWriteImmediate, fp(OR)) + op(0x17, IndirectIndexedRead, fp(OR), Y) + op(0x18, DirectWriteImmediate, fp(OR)) op(0x19, IndirectXWriteIndirectY, fp(OR)) - op(0x1a, DirectPageModifyWord, -1) - op(0x1b, DirectPageXModify, fp(ASL)) + op(0x1a, DirectModifyWord, -1) + op(0x1b, DirectIndexedModify, fp(ASL), X) op(0x1c, ImpliedModify, fp(ASL), A) op(0x1d, ImpliedModify, fp(DEC), X) op(0x1e, AbsoluteRead, fp(CMP), X) - op(0x1f, JMPIndirectAbsoluteX) + op(0x1f, JMPIndirectX) op(0x20, FlagClear, PF) op(0x21, JST, 2) op(0x22, SET, 1) op(0x23, BBS, 1) - op(0x24, DirectPageRead, fp(AND), A) + op(0x24, DirectRead, fp(AND), A) op(0x25, AbsoluteRead, fp(AND), A) op(0x26, IndirectXRead, fp(AND)) - op(0x27, IndirectPageXRead, fp(AND)) + op(0x27, IndexedIndirectRead, fp(AND), X) op(0x28, ImmediateRead, fp(AND), A) - op(0x29, DirectPageWriteDirectPage, fp(AND)) - op(0x2a, AbsoluteModifyBit, 1) - op(0x2b, DirectPageModify, fp(ROL)) + op(0x29, DirectWriteDirect, fp(AND)) + op(0x2a, AbsoluteBitModify, 1) + op(0x2b, DirectModify, fp(ROL)) op(0x2c, AbsoluteModify, fp(ROL)) op(0x2d, Push, A) - op(0x2e, BNEDirectPage) + op(0x2e, BNEDirect) op(0x2f, Branch, true) op(0x30, Branch, NF == 1) op(0x31, JST, 3) op(0x32, CLR, 1) op(0x33, BBC, 1) - op(0x34, DirectPageIndexedRead, fp(AND), A, X) + op(0x34, DirectIndexedRead, fp(AND), A, X) op(0x35, AbsoluteIndexedRead, fp(AND), X) op(0x36, AbsoluteIndexedRead, fp(AND), Y) - op(0x37, IndirectPageYRead, fp(AND)) - op(0x38, DirectPageWriteImmediate, fp(AND)) + op(0x37, IndirectIndexedRead, fp(AND), Y) + op(0x38, DirectWriteImmediate, fp(AND)) op(0x39, IndirectXWriteIndirectY, fp(AND)) - op(0x3a, DirectPageModifyWord, +1) - op(0x3b, DirectPageXModify, fp(ROL)) + op(0x3a, DirectModifyWord, +1) + op(0x3b, DirectIndexedModify, fp(ROL), A) op(0x3c, ImpliedModify, fp(ROL), A) op(0x3d, ImpliedModify, fp(INC), X) - op(0x3e, DirectPageRead, fp(CMP), 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(0x44, DirectPageRead, fp(EOR), A) + op(0x44, DirectRead, fp(EOR), A) op(0x45, AbsoluteRead, fp(EOR), A) op(0x46, IndirectXRead, fp(EOR)) - op(0x47, IndirectPageXRead, fp(EOR)) + op(0x47, IndexedIndirectRead, fp(EOR), X) op(0x48, ImmediateRead, fp(EOR), A) - op(0x49, DirectPageWriteDirectPage, fp(EOR)) - op(0x4a, AbsoluteModifyBit, 2) - op(0x4b, DirectPageModify, fp(LSR)) + op(0x49, DirectWriteDirect, fp(EOR)) + op(0x4a, AbsoluteBitModify, 2) + op(0x4b, DirectModify, fp(LSR)) op(0x4c, AbsoluteModify, fp(LSR)) op(0x4d, Push, X) op(0x4e, TRBAbsolute) - op(0x4f, JSPDirectPage) + op(0x4f, JSPDirect) op(0x50, Branch, VF == 0) op(0x51, JST, 5) op(0x52, CLR, 2) op(0x53, BBC, 2) - op(0x54, DirectPageIndexedRead, fp(EOR), A, X) + op(0x54, DirectIndexedRead, fp(EOR), A, X) op(0x55, AbsoluteIndexedRead, fp(EOR), X) op(0x56, AbsoluteIndexedRead, fp(EOR), Y) - op(0x57, IndirectPageYRead, fp(EOR)) - op(0x58, DirectPageWriteImmediate, fp(EOR)) + op(0x57, IndirectIndexedRead, fp(EOR), Y) + op(0x58, DirectWriteImmediate, fp(EOR)) op(0x59, IndirectXWriteIndirectY, fp(EOR)) - op(0x5a, DirectPageReadWord, fp(CPW)) - op(0x5b, DirectPageXModify, fp(LSR)) + op(0x5a, DirectReadWord, fp(CPW)) + op(0x5b, DirectIndexedModify, fp(LSR), X) op(0x5c, ImpliedModify, fp(LSR), A) op(0x5d, Transfer, A, X) op(0x5e, AbsoluteRead, fp(CMP), Y) @@ -103,62 +103,62 @@ auto SPC700::instruction() -> void { op(0x61, JST, 6) op(0x62, SET, 3) op(0x63, BBS, 3) - op(0x64, DirectPageRead, fp(CMP), A) + op(0x64, DirectRead, fp(CMP), A) op(0x65, AbsoluteRead, fp(CMP), A) op(0x66, IndirectXRead, fp(CMP)) - op(0x67, IndirectPageXRead, fp(CMP)) + op(0x67, IndexedIndirectRead, fp(CMP), X) op(0x68, ImmediateRead, fp(CMP), A) - op(0x69, DirectPageWriteDirectPage, fp(CMP)) - op(0x6a, AbsoluteModifyBit, 3) - op(0x6b, DirectPageModify, fp(ROR)) + op(0x69, DirectWriteDirect, fp(CMP)) + op(0x6a, AbsoluteBitModify, 3) + op(0x6b, DirectModify, fp(ROR)) op(0x6c, AbsoluteModify, fp(ROR)) op(0x6d, Push, Y) - op(0x6e, BNEDirectPageDecrement) + op(0x6e, BNEDirectDecrement) op(0x6f, RTS) op(0x70, Branch, VF == 1) op(0x71, JST, 7) op(0x72, CLR, 3) op(0x73, BBC, 3) - op(0x74, DirectPageIndexedRead, fp(CMP), A, X) + op(0x74, DirectIndexedRead, fp(CMP), A, X) op(0x75, AbsoluteIndexedRead, fp(CMP), X) op(0x76, AbsoluteIndexedRead, fp(CMP), Y) - op(0x77, IndirectPageYRead, fp(CMP)) - op(0x78, DirectPageWriteImmediate, fp(CMP)) + op(0x77, IndirectIndexedRead, fp(CMP), Y) + op(0x78, DirectWriteImmediate, fp(CMP)) op(0x79, IndirectXWriteIndirectY, fp(CMP)) - op(0x7a, DirectPageReadWord, fp(ADW)) - op(0x7b, DirectPageXModify, fp(ROR)) + op(0x7a, DirectReadWord, fp(ADW)) + op(0x7b, DirectIndexedModify, fp(ROR), X) op(0x7c, ImpliedModify, fp(ROR), A) op(0x7d, Transfer, X, A) - op(0x7e, DirectPageRead, fp(CMP), Y) + 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(0x84, DirectPageRead, fp(ADC), A) + op(0x84, DirectRead, fp(ADC), A) op(0x85, AbsoluteRead, fp(ADC), A) op(0x86, IndirectXRead, fp(ADC)) - op(0x87, IndirectPageXRead, fp(ADC)) + op(0x87, IndexedIndirectRead, fp(ADC), X) op(0x88, ImmediateRead, fp(ADC), A) - op(0x89, DirectPageWriteDirectPage, fp(ADC)) - op(0x8a, AbsoluteModifyBit, 4) - op(0x8b, DirectPageModify, fp(DEC)) + op(0x89, DirectWriteDirect, fp(ADC)) + op(0x8a, AbsoluteBitModify, 4) + op(0x8b, DirectModify, fp(DEC)) op(0x8c, AbsoluteModify, fp(DEC)) op(0x8d, ImmediateRead, fp(LD), Y) op(0x8e, PLP) - op(0x8f, DirectPageWriteImmediate, fp(ST)) + op(0x8f, DirectWriteImmediate, fp(ST)) op(0x90, Branch, CF == 0) op(0x91, JST, 9) op(0x92, CLR, 4) op(0x93, BBC, 4) - op(0x94, DirectPageIndexedRead, fp(ADC), A, X) + op(0x94, DirectIndexedRead, fp(ADC), A, X) op(0x95, AbsoluteIndexedRead, fp(ADC), X) op(0x96, AbsoluteIndexedRead, fp(ADC), Y) - op(0x97, IndirectPageYRead, fp(ADC)) - op(0x98, DirectPageWriteImmediate, fp(ADC)) + op(0x97, IndirectIndexedRead, fp(ADC), Y) + op(0x98, DirectWriteImmediate, fp(ADC)) op(0x99, IndirectXWriteIndirectY, fp(ADC)) - op(0x9a, DirectPageReadWord, fp(SBW)) - op(0x9b, DirectPageXModify, fp(DEC)) + op(0x9a, DirectReadWord, fp(SBW)) + op(0x9b, DirectIndexedModify, fp(DEC), X) op(0x9c, ImpliedModify, fp(DEC), A) op(0x9d, Transfer, S, X) op(0x9e, DIV) @@ -167,46 +167,46 @@ auto SPC700::instruction() -> void { op(0xa1, JST, 10) op(0xa2, SET, 5) op(0xa3, BBS, 5) - op(0xa4, DirectPageRead, fp(SBC), A) + op(0xa4, DirectRead, fp(SBC), A) op(0xa5, AbsoluteRead, fp(SBC), A) op(0xa6, IndirectXRead, fp(SBC)) - op(0xa7, IndirectPageXRead, fp(SBC)) + op(0xa7, IndexedIndirectRead, fp(SBC), X) op(0xa8, ImmediateRead, fp(SBC), A) - op(0xa9, DirectPageWriteDirectPage, fp(SBC)) - op(0xaa, AbsoluteModifyBit, 5) - op(0xab, DirectPageModify, fp(INC)) + op(0xa9, DirectWriteDirect, fp(SBC)) + op(0xaa, AbsoluteBitModify, 5) + op(0xab, DirectModify, fp(INC)) op(0xac, AbsoluteModify, fp(INC)) op(0xad, ImmediateRead, fp(CMP), Y) op(0xae, Pull, A) - op(0xaf, STAIndirectXIncrement) + op(0xaf, IndirectXIncrementWrite, A) op(0xb0, Branch, CF == 1) op(0xb1, JST, 11) op(0xb2, CLR, 5) op(0xb3, BBC, 5) - op(0xb4, DirectPageIndexedRead, fp(SBC), A, X) + op(0xb4, DirectIndexedRead, fp(SBC), A, X) op(0xb5, AbsoluteIndexedRead, fp(SBC), X) op(0xb6, AbsoluteIndexedRead, fp(SBC), Y) - op(0xb7, IndirectPageYRead, fp(SBC)) - op(0xb8, DirectPageWriteImmediate, fp(SBC)) + op(0xb7, IndirectIndexedRead, fp(SBC), Y) + op(0xb8, DirectWriteImmediate, fp(SBC)) op(0xb9, IndirectXWriteIndirectY, fp(SBC)) - op(0xba, DirectPageReadWord, fp(LDW)) - op(0xbb, DirectPageXModify, fp(INC)) + op(0xba, DirectReadWord, fp(LDW)) + op(0xbb, DirectIndexedModify, fp(INC), X) op(0xbc, ImpliedModify, fp(INC), A) op(0xbd, Transfer, X, S) op(0xbe, DAS) - op(0xbf, LDAIndirectXIncrement) + op(0xbf, IndirectXIncrementRead, A) op(0xc0, FlagClear, IF) op(0xc1, JST, 12) op(0xc2, SET, 6) op(0xc3, BBS, 6) - op(0xc4, DirectPageWrite, A) + op(0xc4, DirectWrite, A) op(0xc5, AbsoluteWrite, A) - op(0xc6, STAIndirectX) - op(0xc7, STAIndirectPageX) + op(0xc6, IndirectXWrite, A) + op(0xc7, IndexedIndirectWrite, A, X) op(0xc8, ImmediateRead, fp(CMP), X) op(0xc9, AbsoluteWrite, X) - op(0xca, AbsoluteModifyBit, 6) - op(0xcb, DirectPageWrite, Y) + op(0xca, AbsoluteBitModify, 6) + op(0xcb, DirectWrite, Y) op(0xcc, AbsoluteWrite, Y) op(0xcd, ImmediateRead, fp(LD), X) op(0xce, Pull, X) @@ -215,30 +215,30 @@ auto SPC700::instruction() -> void { op(0xd1, JST, 13) op(0xd2, CLR, 6) op(0xd3, BBC, 6) - op(0xd4, DirectPageIndexedWrite, A, X) + op(0xd4, DirectIndexedWrite, A, X) op(0xd5, AbsoluteIndexedWrite, X) op(0xd6, AbsoluteIndexedWrite, Y) - op(0xd7, STAIndirectPageY) - op(0xd8, DirectPageWrite, X) - op(0xd9, DirectPageIndexedWrite, X, Y) - op(0xda, STWDirectPage) - op(0xdb, DirectPageIndexedWrite, Y, X) + op(0xd7, IndirectIndexedWrite, A, Y) + op(0xd8, DirectWrite, X) + op(0xd9, DirectIndexedWrite, X, Y) + op(0xda, STWDirect) + op(0xdb, DirectIndexedWrite, Y, X) op(0xdc, ImpliedModify, fp(DEC), Y) op(0xdd, Transfer, Y, A) - op(0xde, BNEDirectPageX) + op(0xde, BNEDirectX) op(0xdf, DAA) op(0xe0, CLV) op(0xe1, JST, 14) op(0xe2, SET, 7) op(0xe3, BBS, 7) - op(0xe4, DirectPageRead, fp(LD), A) + op(0xe4, DirectRead, fp(LD), A) op(0xe5, AbsoluteRead, fp(LD), A) op(0xe6, IndirectXRead, fp(LD)) - op(0xe7, IndirectPageXRead, fp(LD)) + op(0xe7, IndexedIndirectRead, fp(LD), X) op(0xe8, ImmediateRead, fp(LD), A) op(0xe9, AbsoluteRead, fp(LD), X) - op(0xea, AbsoluteModifyBit, 7) - op(0xeb, DirectPageRead, fp(LD), Y) + op(0xea, AbsoluteBitModify, 7) + op(0xeb, DirectRead, fp(LD), Y) op(0xec, AbsoluteRead, fp(LD), Y) op(0xed, CMC) op(0xee, Pull, Y) @@ -247,14 +247,14 @@ auto SPC700::instruction() -> void { op(0xf1, JST, 15) op(0xf2, CLR, 7) op(0xf3, BBC, 7) - op(0xf4, DirectPageIndexedRead, fp(LD), A, X) + op(0xf4, DirectIndexedRead, fp(LD), A, X) op(0xf5, AbsoluteIndexedRead, fp(LD), X) op(0xf6, AbsoluteIndexedRead, fp(LD), Y) - op(0xf7, IndirectPageYRead, fp(LD)) - op(0xf8, DirectPageRead, fp(LD), X) - op(0xf9, DirectPageIndexedRead, fp(LD), X, Y) - op(0xfa, DirectPageWriteDirectPage, fp(ST)) - op(0xfb, DirectPageIndexedRead, fp(LD), Y, X) + op(0xf7, IndirectIndexedRead, fp(LD), Y) + op(0xf8, DirectRead, fp(LD), X) + op(0xf9, DirectIndexedRead, fp(LD), X, Y) + op(0xfa, DirectWriteDirect, fp(ST)) + op(0xfb, DirectIndexedRead, fp(LD), Y, X) op(0xfc, ImpliedModify, fp(INC), Y) op(0xfd, Transfer, A, Y) op(0xfe, BNEYDecrement) diff --git a/higan/processor/spc700/instructions.cpp b/higan/processor/spc700/instructions.cpp index f591f1e4..904f197f 100644 --- a/higan/processor/spc700/instructions.cpp +++ b/higan/processor/spc700/instructions.cpp @@ -1,124 +1,4 @@ -auto SPC700::instructionImpliedModify(fps op, uint8& target) -> void { - idle(); - target = alu(target); -} - -auto SPC700::instructionAbsoluteModify(fps op) -> void { - uint16 absolute = fetch(); - absolute |= fetch() << 8; - uint8 data = read(absolute); - write(absolute, alu(data)); -} - -auto SPC700::instructionDirectPageModify(fps op) -> void { - uint8 direct = fetch(); - uint8 data = load(direct); - store(direct, alu(data)); -} - -auto SPC700::instructionDirectPageModifyWord(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::instructionDirectPageXModify(fps op) -> void { - uint8 direct = fetch(); - idle(); - uint8 data = load(direct + X); - store(direct + X, alu(data)); -} - -auto SPC700::instructionBranch(bool take) -> void { - uint8 data = fetch(); - if(!take) return; - idle(); - idle(); - PC += (int8)data; -} - -auto SPC700::instructionPull(uint8& data) -> void { - idle(); - idle(); - data = pull(); -} - -auto SPC700::instructionPush(uint8 data) -> void { - idle(); - idle(); - push(data); -} - -auto SPC700::instructionAbsoluteRead(fpb op, uint8& target) -> void { - uint16 absolute = fetch(); - absolute |= fetch() << 8; - uint8 data = read(absolute); - target = alu(target, data); -} - -auto SPC700::instructionAbsoluteIndexedRead(fpb op, uint8& index) -> void { - uint16 absolute = fetch(); - absolute |= fetch() << 8; - idle(); - uint8 data = read(absolute + index); - A = alu(A, data); -} - -auto SPC700::instructionImmediateRead(fpb op, uint8& target) -> void { - uint8 data = fetch(); - target = alu(target, data); -} - -auto SPC700::instructionDirectPageRead(fpb op, uint8& target) -> void { - uint8 direct = fetch(); - uint8 data = load(direct); - target = alu(target, data); -} - -auto SPC700::instructionDirectPageIndexedRead(fpb op, uint8& target, uint8& index) -> void { - uint8 direct = fetch(); - idle(); - uint8 data = load(direct + index); - target = alu(target, data); -} - -auto SPC700::instructionDirectPageReadWord(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::instructionIndirectPageXRead(fpb op) -> void { - uint8 direct = fetch() + X; - idle(); - uint16 absolute = load(direct++); - absolute |= load(direct++) << 8; - uint8 data = read(absolute); - A = alu(A, data); -} - -auto SPC700::instructionIndirectPageYRead(fpb op) -> void { - uint8 direct = fetch(); - idle(); - uint16 absolute = load(direct++); - absolute |= load(direct++) << 8; - uint8 data = read(absolute + Y); - A = alu(A, data); -} - -auto SPC700::instructionIndirectXRead(fpb op) -> void { - idle(); - uint8 data = load(X); - A = alu(A, data); -} - -auto SPC700::instructionAbsoluteModifyBit(uint3 mode) -> void { +auto SPC700::instructionAbsoluteBitModify(uint3 mode) -> void { uint16 absolute = fetch(); absolute |= fetch() << 8; uint3 bit = absolute >> 13; @@ -158,6 +38,127 @@ auto SPC700::instructionAbsoluteModifyBit(uint3 mode) -> void { } } +auto SPC700::instructionAbsoluteRead(fpb op, uint8& target) -> void { + uint16 absolute = fetch(); + absolute |= fetch() << 8; + uint8 data = read(absolute); + target = alu(target, data); +} + +auto SPC700::instructionAbsoluteModify(fps op) -> void { + uint16 absolute = fetch(); + absolute |= fetch() << 8; + uint8 data = read(absolute); + write(absolute, alu(data)); +} + +auto SPC700::instructionAbsoluteWrite(uint8& data) -> void { + uint16 absolute = fetch(); + absolute |= fetch() << 8; + read(absolute); + write(absolute, data); +} + +auto SPC700::instructionAbsoluteIndexedRead(fpb op, uint8& index) -> void { + uint16 absolute = fetch(); + absolute |= fetch() << 8; + idle(); + uint8 data = read(absolute + 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); +} + +auto SPC700::instructionBranch(bool take) -> void { + uint8 data = fetch(); + if(!take) return; + idle(); + idle(); + 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(); @@ -170,59 +171,76 @@ auto SPC700::instructionFlagSet(bool& flag) -> void { flag = 1; } -auto SPC700::instructionTransfer(uint8& from, uint8& to) -> void { - idle(); - to = from; - if(&to == &S) return; - ZF = to == 0; - NF = to & 0x80; +auto SPC700::instructionImmediateRead(fpb op, uint8& target) -> void { + uint8 data = fetch(); + target = alu(target, data); } -auto SPC700::instructionAbsoluteWrite(uint8& data) -> void { - uint16 absolute = fetch(); - absolute |= fetch() << 8; +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::instructionAbsoluteIndexedWrite(uint8& index) -> void { - uint16 absolute = fetch(); - absolute |= fetch() << 8; - idle(); - absolute += index; - read(absolute); - write(absolute, A); -} - -auto SPC700::instructionDirectPageWrite(uint8& data) -> void { +auto SPC700::instructionIndirectIndexedRead(fpb op, uint8& index) -> void { uint8 direct = fetch(); - load(direct); - store(direct, data); -} - -auto SPC700::instructionDirectPageIndexedWrite(uint8& data, uint8& index) -> void { - uint8 direct = fetch() + index; + uint16 absolute = load(direct++); + absolute |= load(direct++) << 8; idle(); - load(direct); - store(direct, data); + uint8 data = read(absolute + index); + A = alu(A, data); } -auto SPC700::instructionDirectPageWriteImmediate(fpb op) -> void { - uint8 immediate = fetch(); +auto SPC700::instructionIndirectIndexedWrite(uint8& data, uint8& index) -> void { uint8 direct = fetch(); - uint8 data = load(direct); - data = alu(data, immediate); - op != &SPC700::algorithmCMP ? store(direct, data) : idle(); + uint16 absolute = load(direct++); + absolute |= load(direct++) << 8; + idle(); + read(absolute + index); + write(absolute + index, data); } -auto SPC700::instructionDirectPageWriteDirectPage(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::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 { @@ -233,6 +251,26 @@ auto SPC700::instructionIndirectXWriteIndirectY(fpb op) -> void { 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 { @@ -257,7 +295,7 @@ auto SPC700::instructionBBS(uint3 bit) -> void { PC += (int8)displacement; } -auto SPC700::instructionBNEDirectPage() -> void { +auto SPC700::instructionBNEDirect() -> void { uint8 direct = fetch(); uint8 data = load(direct); uint8 displacement = fetch(); @@ -268,7 +306,7 @@ auto SPC700::instructionBNEDirectPage() -> void { PC += (int8)displacement; } -auto SPC700::instructionBNEDirectPageDecrement() -> void { +auto SPC700::instructionBNEDirectDecrement() -> void { uint8 direct = fetch(); uint8 data = load(direct); store(direct, --data); @@ -279,7 +317,7 @@ auto SPC700::instructionBNEDirectPageDecrement() -> void { PC += (int8)displacement; } -auto SPC700::instructionBNEDirectPageX() -> void { +auto SPC700::instructionBNEDirectX() -> void { uint8 direct = fetch(); idle(); uint8 data = load(direct + X); @@ -398,7 +436,7 @@ auto SPC700::instructionJMPAbsolute() -> void { PC = absolute; } -auto SPC700::instructionJMPIndirectAbsoluteX() -> void { +auto SPC700::instructionJMPIndirectX() -> void { uint16 absolute = fetch(); absolute |= fetch() << 8; idle(); @@ -408,7 +446,7 @@ auto SPC700::instructionJMPIndirectAbsoluteX() -> void { PC = pc; } -auto SPC700::instructionJSPDirectPage() -> void { +auto SPC700::instructionJSPDirect() -> void { uint8 direct = fetch(); idle(); idle(); @@ -440,14 +478,6 @@ auto SPC700::instructionJST(uint4 vector) -> void { PC = pc; } -auto SPC700::instructionLDAIndirectXIncrement() -> void { - idle(); - A = load(X++); - idle(); - ZF = A == 0; - NF = A & 0x80; -} - auto SPC700::instructionMUL() -> void { idle(); idle(); @@ -499,37 +529,6 @@ auto SPC700::instructionSET(uint3 bit) -> void { store(direct, data); } -auto SPC700::instructionSTAIndirectPageX() -> void { - uint8 direct = fetch() + X; - idle(); - uint16 absolute = load(direct++); - absolute |= load(direct++) << 8; - read(absolute); - write(absolute, A); -} - -auto SPC700::instructionSTAIndirectPageY() -> void { - uint8 direct = fetch(); - uint16 absolute = load(direct++); - absolute |= load(direct++) << 8; - idle(); - absolute += Y; - read(absolute); - write(absolute, A); -} - -auto SPC700::instructionSTAIndirectX() -> void { - idle(); - load(X); - store(X, A); -} - -auto SPC700::instructionSTAIndirectXIncrement() -> void { - idle(); - idle(); - store(X++, A); -} - auto SPC700::instructionSTP() -> void { r.stp = true; while(r.stp && !synchronizing()) { @@ -538,7 +537,7 @@ auto SPC700::instructionSTP() -> void { } } -auto SPC700::instructionSTWDirectPage() -> void { +auto SPC700::instructionSTWDirect() -> void { uint8 direct = fetch(); load(direct); store(direct++, A); diff --git a/higan/processor/spc700/memory.cpp b/higan/processor/spc700/memory.cpp index 91541f4e..85aea3c0 100644 --- a/higan/processor/spc700/memory.cpp +++ b/higan/processor/spc700/memory.cpp @@ -1,3 +1,7 @@ +auto SPC700::idle() -> void { + read(PC); +} + auto SPC700::fetch() -> uint8 { return read(PC++); } diff --git a/higan/processor/spc700/spc700.hpp b/higan/processor/spc700/spc700.hpp index e2106e38..01f9ca65 100644 --- a/higan/processor/spc700/spc700.hpp +++ b/higan/processor/spc700/spc700.hpp @@ -3,7 +3,6 @@ namespace Processor { struct SPC700 { - virtual auto idle() -> void = 0; virtual auto read(uint16 addr) -> uint8 = 0; virtual auto write(uint16 addr, uint8 data) -> void = 0; virtual auto synchronizing() const -> bool = 0; @@ -17,6 +16,7 @@ struct SPC700 { auto instruction() -> void; //memory.cpp + auto idle() -> void; auto fetch() -> uint8; auto pull() -> uint8; auto push(uint8 data) -> void; @@ -48,40 +48,45 @@ struct SPC700 { using fpb = auto (SPC700::*)(uint8, uint8) -> uint8; using fpw = auto (SPC700::*)(uint16, uint16) -> uint16; - auto instructionImpliedModify(fps, uint8&) -> void; - auto instructionAbsoluteModify(fps) -> void; - auto instructionDirectPageModify(fps) -> void; - auto instructionDirectPageModifyWord(int) -> void; - auto instructionDirectPageXModify(fps) -> void; - auto instructionBranch(bool) -> void; - auto instructionPull(uint8&) -> void; - auto instructionPush(uint8) -> void; + auto instructionAbsoluteBitModify(uint3) -> void; auto instructionAbsoluteRead(fpb, uint8&) -> void; + auto instructionAbsoluteModify(fps) -> void; + auto instructionAbsoluteWrite(uint8&) -> void; auto instructionAbsoluteIndexedRead(fpb, uint8&) -> void; - auto instructionImmediateRead(fpb, uint8&) -> void; - auto instructionDirectPageRead(fpb, uint8&) -> void; - auto instructionDirectPageIndexedRead(fpb, uint8&, uint8&) -> void; - auto instructionDirectPageReadWord(fpw) -> void; - auto instructionIndirectPageXRead(fpb) -> void; - auto instructionIndirectPageYRead(fpb) -> void; - auto instructionIndirectXRead(fpb) -> void; - auto instructionAbsoluteModifyBit(uint3) -> void; + auto instructionAbsoluteIndexedWrite(uint8&) -> void; + auto instructionBranch(bool) -> void; + auto instructionDirectRead(fpb, uint8&) -> void; + auto instructionDirectModify(fps) -> void; + auto instructionDirectWrite(uint8&) -> void; + auto instructionDirectWriteDirect(fpb) -> void; + auto instructionDirectWriteImmediate(fpb) -> void; + auto instructionDirectReadWord(fpw) -> void; + auto instructionDirectModifyWord(int) -> 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 instructionTransfer(uint8&, uint8&) -> void; - auto instructionAbsoluteWrite(uint8&) -> void; - auto instructionAbsoluteIndexedWrite(uint8&) -> void; - auto instructionDirectPageWrite(uint8&) -> void; - auto instructionDirectPageIndexedWrite(uint8&, uint8&) -> void; - auto instructionDirectPageWriteImmediate(fpb) -> void; - auto instructionDirectPageWriteDirectPage(fpb) -> void; + auto instructionImmediateRead(fpb, uint8&) -> void; + auto instructionImpliedModify(fps, uint8&) -> void; + auto instructionIndexedIndirectRead(fpb, uint8&) -> void; + auto instructionIndexedIndirectWrite(uint8&, uint8&) -> void; + auto instructionIndirectIndexedRead(fpb, uint8&) -> void; + auto instructionIndirectIndexedWrite(uint8&, uint8&) -> void; + auto instructionIndirectXRead(fpb) -> void; + auto instructionIndirectXWrite(uint8&) -> void; + auto instructionIndirectXIncrementRead(uint8&) -> void; + auto instructionIndirectXIncrementWrite(uint8&) -> void; auto instructionIndirectXWriteIndirectY(fpb) -> void; + auto instructionPull(uint8&) -> void; + auto instructionPush(uint8) -> void; + auto instructionTransfer(uint8&, uint8&) -> void; auto instructionBBC(uint3) -> void; auto instructionBBS(uint3) -> void; - auto instructionBNEDirectPage() -> void; - auto instructionBNEDirectPageDecrement() -> void; - auto instructionBNEDirectPageX() -> void; + auto instructionBNEDirect() -> void; + auto instructionBNEDirectDecrement() -> void; + auto instructionBNEDirectX() -> void; auto instructionBNEYDecrement() -> void; auto instructionBRK() -> void; auto instructionCLR(uint3) -> void; @@ -91,23 +96,18 @@ struct SPC700 { auto instructionDAS() -> void; auto instructionDIV() -> void; auto instructionJMPAbsolute() -> void; - auto instructionJMPIndirectAbsoluteX() -> void; - auto instructionJSPDirectPage() -> void; + auto instructionJMPIndirectX() -> void; + auto instructionJSPDirect() -> void; auto instructionJSRAbsolute() -> void; auto instructionJST(uint4) -> void; - auto instructionLDAIndirectXIncrement() -> void; auto instructionMUL() -> void; auto instructionNOP() -> void; auto instructionPLP() -> void; auto instructionRTI() -> void; auto instructionRTS() -> void; auto instructionSET(uint3) -> void; - auto instructionSTAIndirectPageX() -> void; - auto instructionSTAIndirectPageY() -> void; - auto instructionSTAIndirectX() -> void; - auto instructionSTAIndirectXIncrement() -> void; auto instructionSTP() -> void; - auto instructionSTWDirectPage() -> void; + auto instructionSTWDirect() -> void; auto instructionTRBAbsolute() -> void; auto instructionTSBAbsolute() -> void; auto instructionWAI() -> void; diff --git a/higan/processor/z80/instruction.cpp b/higan/processor/z80/instruction.cpp index 365610bd..e79f27b8 100644 --- a/higan/processor/z80/instruction.cpp +++ b/higan/processor/z80/instruction.cpp @@ -2,8 +2,8 @@ auto Z80::instruction() -> void { //todo: return instruction() could cause stack crash from recursion //but this is needed to prevent IRQs from firing between prefixes and opcodes auto code = opcode(); - if(code == 0xdd) { r.hlp = &r.ix; return instruction(); } - if(code == 0xfd) { r.hlp = &r.iy; return instruction(); } + if(code == 0xdd) { prefix = Prefix::ix; return instruction(); } + if(code == 0xfd) { prefix = Prefix::iy; return instruction(); } if(r.ei) { r.ei = 0; @@ -11,7 +11,7 @@ auto Z80::instruction() -> void { r.iff2 = 1; } - if(code == 0xcb && r.hlp != &r.hl) { + if(code == 0xcb && prefix != Prefix::hl) { uint16 addr = HL + (int8)operand(); wait(1); instructionCBd(addr, opcode()); @@ -23,7 +23,7 @@ auto Z80::instruction() -> void { instruction(code); } - r.hlp = &r.hl; + prefix = Prefix::hl; } #define op(id, name, ...) case id: return instruction##name(__VA_ARGS__); diff --git a/higan/processor/z80/registers.cpp b/higan/processor/z80/registers.cpp index 346b16aa..4d3fd99e 100644 --- a/higan/processor/z80/registers.cpp +++ b/higan/processor/z80/registers.cpp @@ -1,7 +1,7 @@ #define AF r.af.word #define BC r.bc.word #define DE r.de.word -#define HL r.hlp->word //virtual HL (overridden by IX/IY prefixes) +#define HL (prefix == Prefix::ix ? r.ix.word : prefix == Prefix::iy ? r.iy.word : r.hl.word) #define A r.af.byte.hi #define F r.af.byte.lo @@ -9,8 +9,8 @@ #define C r.bc.byte.lo #define D r.de.byte.hi #define E r.de.byte.lo -#define H r.hlp->byte.hi -#define L r.hlp->byte.lo +#define H (prefix == Prefix::ix ? r.ix.byte.hi : prefix == Prefix::iy ? r.iy.byte.hi : r.hl.byte.hi) +#define L (prefix == Prefix::ix ? r.ix.byte.lo : prefix == Prefix::iy ? r.iy.byte.lo : r.hl.byte.lo) #define _HL r.hl.word //true HL (ignores IX/IY prefixes) #define _H r.hl.byte.hi diff --git a/higan/processor/z80/serialization.cpp b/higan/processor/z80/serialization.cpp index 19cbea53..5051278d 100644 --- a/higan/processor/z80/serialization.cpp +++ b/higan/processor/z80/serialization.cpp @@ -17,8 +17,7 @@ auto Z80::serialize(serializer& s) -> void { s.integer(r.iff1); s.integer(r.iff2); s.integer(r.im); - - //todo: r.hlp is not serializable + s.integer((uint&)prefix); } auto Z80::Bus::serialize(serializer& s) -> void { diff --git a/higan/processor/z80/z80.cpp b/higan/processor/z80/z80.cpp index bcfbb359..abc40eb7 100644 --- a/higan/processor/z80/z80.cpp +++ b/higan/processor/z80/z80.cpp @@ -12,10 +12,8 @@ namespace Processor { #include "serialization.cpp" auto Z80::power() -> void { - memory::fill(&r, sizeof(Registers)); - r.hlp = &r.hl; - bus->request(false); - bus->grant(true); + r = {}; + prefix = Prefix::hl; } auto Z80::irq(bool maskable, uint16 pc, uint8 extbus) -> bool { diff --git a/higan/processor/z80/z80.hpp b/higan/processor/z80/z80.hpp index 6f823618..895471b3 100644 --- a/higan/processor/z80/z80.hpp +++ b/higan/processor/z80/z80.hpp @@ -242,10 +242,10 @@ struct Z80 { bool iff1; //interrupt flip-flop 1 bool iff2; //interrupt flip-flop 2 uint2 im; //interrupt mode (0-2) - - Pair* hlp = nullptr; } r; + enum class Prefix : uint { hl, ix, iy } prefix = Prefix::hl; + Bus* bus = nullptr; }; diff --git a/higan/sfc/smp/memory.cpp b/higan/sfc/smp/memory.cpp index a8fbe83c..09922e32 100644 --- a/higan/sfc/smp/memory.cpp +++ b/higan/sfc/smp/memory.cpp @@ -173,11 +173,6 @@ auto SMP::writeBus(uint16 addr, uint8 data) -> void { writeRAM(addr, data); //all writes, even to MMIO registers, appear on bus } -auto SMP::idle() -> void { - step(24); - cycleEdge(); -} - auto SMP::read(uint16 addr) -> uint8 { step(12); uint8 data = readBus(addr); diff --git a/higan/sfc/smp/smp.hpp b/higan/sfc/smp/smp.hpp index ecb9eeff..7f3f4dcf 100644 --- a/higan/sfc/smp/smp.hpp +++ b/higan/sfc/smp/smp.hpp @@ -52,7 +52,6 @@ private: auto readBus(uint16 addr) -> uint8; auto writeBus(uint16 addr, uint8 data) -> void; - auto idle() -> void override; auto read(uint16 addr) -> uint8 override; auto write(uint16 addr, uint8 data) -> void override; diff --git a/icarus/GNUmakefile b/icarus/GNUmakefile index 076078ec..f46c5a04 100644 --- a/icarus/GNUmakefile +++ b/icarus/GNUmakefile @@ -45,7 +45,7 @@ ifeq ($(platform),macosx) else ifneq ($(filter $(platform),linux bsd),) mkdir -p $(prefix)/share/$(name)/Database/ if [ -f out/$(name) ]; then cp out/$(name) $(prefix)/bin/$(name); fi - cp -R Database/ $(prefix)/share/$(name)/Database/ + cp -R Database/* $(prefix)/share/$(name)/Database/ endif uninstall: