diff --git a/higan/data/higan.Manifest b/higan/data/higan.Manifest index 2796a434..095d34fa 100644 --- a/higan/data/higan.Manifest +++ b/higan/data/higan.Manifest @@ -6,4 +6,9 @@ + + + false + + diff --git a/higan/data/higan.plist b/higan/data/higan.plist index 53d81b52..6d59f131 100644 --- a/higan/data/higan.plist +++ b/higan/data/higan.plist @@ -11,7 +11,7 @@ CFBundleIconFile higan.icns NSHighResolutionCapable - + NSSupportsAutomaticGraphicsSwitching diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index d1a2855a..c13bff9e 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.26"; + static const string Version = "103.27"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/gba/GNUmakefile b/higan/gba/GNUmakefile index 31c9c3e8..df590008 100644 --- a/higan/gba/GNUmakefile +++ b/higan/gba/GNUmakefile @@ -1,4 +1,4 @@ -processors += arm +processors += arm arm7tdmi objects += gba-memory gba-interface gba-system objects += gba-cartridge gba-player diff --git a/higan/gba/cpu/bus.cpp b/higan/gba/cpu/bus.cpp index 962e4637..fb6b8d96 100644 --- a/higan/gba/cpu/bus.cpp +++ b/higan/gba/cpu/bus.cpp @@ -1,8 +1,8 @@ -auto CPU::_idle() -> void { +auto CPU::sleep() -> void { prefetchStep(1); } -auto CPU::_read(uint mode, uint32 addr) -> uint32 { +auto CPU::get(uint mode, uint32 addr) -> uint32 { uint clocks = _wait(mode, addr); uint word = pipeline.fetch.instruction; @@ -35,7 +35,7 @@ auto CPU::_read(uint mode, uint32 addr) -> uint32 { return word; } -auto CPU::_write(uint mode, uint32 addr, uint32 word) -> void { +auto CPU::set(uint mode, uint32 addr, uint32 word) -> void { uint clocks = _wait(mode, addr); if(addr >= 0x1000'0000) { diff --git a/higan/gba/cpu/cpu.hpp b/higan/gba/cpu/cpu.hpp index 8d3e3870..344e7756 100644 --- a/higan/gba/cpu/cpu.hpp +++ b/higan/gba/cpu/cpu.hpp @@ -38,9 +38,9 @@ struct CPU : Processor::ARM, Thread, IO { auto prefetchRead() -> uint16; //bus.cpp - auto _idle() -> void override; - auto _read(uint mode, uint32 addr) -> uint32 override; - auto _write(uint mode, uint32 addr, uint32 word) -> void override; + auto sleep() -> void override; + auto get(uint mode, uint32 addr) -> uint32 override; + auto set(uint mode, uint32 addr, uint32 word) -> void override; auto _wait(uint mode, uint32 addr) -> uint; //io.cpp diff --git a/higan/gba/cpu/dma.cpp b/higan/gba/cpu/dma.cpp index 25dc6f18..2fe7a8e2 100644 --- a/higan/gba/cpu/dma.cpp +++ b/higan/gba/cpu/dma.cpp @@ -27,7 +27,7 @@ auto CPU::DMA::transfer() -> void { uint32 addr = latch.source; if(mode & Word) addr &= ~3; if(mode & Half) addr &= ~1; - data = cpu._read(mode, addr); + data = cpu.get(mode, addr); } if(latch.target < 0x0200'0000) { @@ -36,7 +36,7 @@ auto CPU::DMA::transfer() -> void { uint32 addr = latch.target; if(mode & Word) addr &= ~3; if(mode & Half) addr &= ~1; - cpu._write(mode, addr, data); + cpu.set(mode, addr, data); } switch(sourceMode) { diff --git a/higan/gba/gba.hpp b/higan/gba/gba.hpp index dab846e6..287e9d62 100644 --- a/higan/gba/gba.hpp +++ b/higan/gba/gba.hpp @@ -8,6 +8,7 @@ #include #include +#include namespace GameBoyAdvance { #define platform Emulator::platform diff --git a/higan/processor/GNUmakefile b/higan/processor/GNUmakefile index aa3da06c..6e961afd 100644 --- a/higan/processor/GNUmakefile +++ b/higan/processor/GNUmakefile @@ -1,6 +1,7 @@ processors := $(call unique,$(processors)) objects += $(if $(findstring arm,$(processors)),processor-arm) +objects += $(if $(findstring arm7tdmi,$(processors)),processor-arm7tdmi) objects += $(if $(findstring gsu,$(processors)),processor-gsu) objects += $(if $(findstring hg51b,$(processors)),processor-hg51b) objects += $(if $(findstring huc6280,$(processors)),processor-huc6280) @@ -13,15 +14,16 @@ objects += $(if $(findstring v30mz,$(processors)),processor-v30mz) objects += $(if $(findstring wdc65816,$(processors)),processor-wdc65816) objects += $(if $(findstring z80,$(processors)),processor-z80) -obj/processor-arm.o: processor/arm/arm.cpp $(call rwildcard,processor/arm) -obj/processor-gsu.o: processor/gsu/gsu.cpp $(call rwildcard,processor/gsu) -obj/processor-hg51b.o: processor/hg51b/hg51b.cpp $(call rwildcard,processor/hg51b) -obj/processor-huc6280.o: processor/huc6280/huc6280.cpp $(call rwildcard,processor/huc6280) -obj/processor-lr35902.o: processor/lr35902/lr35902.cpp $(call rwildcard,processor/lr35902) -obj/processor-m68k.o: processor/m68k/m68k.cpp $(call rwildcard,processor/m68k) -obj/processor-mos6502.o: processor/mos6502/mos6502.cpp $(call rwildcard,processor/mos6502) -obj/processor-spc700.o: processor/spc700/spc700.cpp $(call rwildcard,processor/spc700) -obj/processor-upd96050.o: processor/upd96050/upd96050.cpp $(call rwildcard,processor/upd96050) -obj/processor-v30mz.o: processor/v30mz/v30mz.cpp $(call rwildcard,processor/v30mz) -obj/processor-wdc65816.o: processor/wdc65816/wdc65816.cpp $(call rwildcard,processor/wdc65816) -obj/processor-z80.o: processor/z80/z80.cpp $(call rwildcard,processor/z80) +obj/processor-arm.o: processor/arm/arm.cpp $(call rwildcard,processor/arm/) +obj/processor-arm7tdmi.o: processor/arm7tdmi/arm7tdmi.cpp $(call rwildcard,processor/arm7tdmi/) +obj/processor-gsu.o: processor/gsu/gsu.cpp $(call rwildcard,processor/gsu/) +obj/processor-hg51b.o: processor/hg51b/hg51b.cpp $(call rwildcard,processor/hg51b/) +obj/processor-huc6280.o: processor/huc6280/huc6280.cpp $(call rwildcard,processor/huc6280/) +obj/processor-lr35902.o: processor/lr35902/lr35902.cpp $(call rwildcard,processor/lr35902/) +obj/processor-m68k.o: processor/m68k/m68k.cpp $(call rwildcard,processor/m68k/) +obj/processor-mos6502.o: processor/mos6502/mos6502.cpp $(call rwildcard,processor/mos6502/) +obj/processor-spc700.o: processor/spc700/spc700.cpp $(call rwildcard,processor/spc700/) +obj/processor-upd96050.o: processor/upd96050/upd96050.cpp $(call rwildcard,processor/upd96050/) +obj/processor-v30mz.o: processor/v30mz/v30mz.cpp $(call rwildcard,processor/v30mz/) +obj/processor-wdc65816.o: processor/wdc65816/wdc65816.cpp $(call rwildcard,processor/wdc65816/) +obj/processor-z80.o: processor/z80/z80.cpp $(call rwildcard,processor/z80/) diff --git a/higan/processor/arm/arm.cpp b/higan/processor/arm/arm.cpp index 9727929c..346497f5 100644 --- a/higan/processor/arm/arm.cpp +++ b/higan/processor/arm/arm.cpp @@ -13,7 +13,7 @@ namespace Processor { auto ARM::power() -> void { processor.power(); - vector(0x00000000, Processor::Mode::SVC); + interrupt(Processor::Mode::SVC, 0x00); pipeline.reload = true; pipeline.nonsequential = true; crash = false; @@ -31,16 +31,16 @@ auto ARM::exec() -> void { auto ARM::idle() -> void { pipeline.nonsequential = true; - return _idle(); + return sleep(); } auto ARM::read(uint mode, uint32 addr) -> uint32 { - return _read(mode, addr); + return get(mode, addr); } auto ARM::load(uint mode, uint32 addr) -> uint32 { pipeline.nonsequential = true; - uint32 word = _read(Load | mode, addr); + uint32 word = get(Load | mode, addr); if(mode & Half) { addr &= 1; @@ -64,7 +64,7 @@ auto ARM::load(uint mode, uint32 addr) -> uint32 { auto ARM::write(uint mode, uint32 addr, uint32 word) -> void { pipeline.nonsequential = true; - return _write(mode, addr, word); + return set(mode, addr, word); } auto ARM::store(uint mode, uint32 addr, uint32 word) -> void { @@ -73,10 +73,10 @@ auto ARM::store(uint mode, uint32 addr, uint32 word) -> void { if(mode & Half) { word &= 0xffff; word |= word << 16; } if(mode & Byte) { word &= 0xff; word |= word << 8; word |= word << 16; } - return _write(Store | mode, addr, word); + return set(Store | mode, addr, word); } -auto ARM::vector(uint32 addr, Processor::Mode mode) -> void { +auto ARM::interrupt(Processor::Mode mode, uint32 addr) -> void { auto psr = cpsr(); processor.setMode(mode); spsr() = psr; diff --git a/higan/processor/arm/arm.hpp b/higan/processor/arm/arm.hpp index 7538d1aa..7f531041 100644 --- a/higan/processor/arm/arm.hpp +++ b/higan/processor/arm/arm.hpp @@ -25,9 +25,9 @@ struct ARM { #include "disassembler.hpp" virtual auto step(uint clocks) -> void = 0; - virtual auto _idle() -> void = 0; - virtual auto _read(uint mode, uint32 addr) -> uint32 = 0; - virtual auto _write(uint mode, uint32 addr, uint32 word) -> void = 0; + virtual auto sleep() -> void = 0; + virtual auto get(uint mode, uint32 addr) -> uint32 = 0; + virtual auto set(uint mode, uint32 addr, uint32 word) -> void = 0; //arm.cpp auto power() -> void; @@ -37,7 +37,7 @@ struct ARM { auto load(uint mode, uint32 addr) -> uint32; auto write(uint mode, uint32 addr, uint32 word) -> void; auto store(uint mode, uint32 addr, uint32 word) -> void; - auto vector(uint32 addr, Processor::Mode mode) -> void; + auto interrupt(Processor::Mode mode, uint32 addr) -> void; //algorithms.cpp auto condition(uint4 condition) -> bool; diff --git a/higan/processor/arm/instructions-arm.cpp b/higan/processor/arm/instructions-arm.cpp index 7697a1d6..df17e33f 100644 --- a/higan/processor/arm/instructions-arm.cpp +++ b/higan/processor/arm/instructions-arm.cpp @@ -598,5 +598,5 @@ auto ARM::arm_op_branch() { auto ARM::arm_op_software_interrupt() { uint24 immediate = instruction(); - vector(0x00000008, Processor::Mode::SVC); + interrupt(Processor::Mode::SVC, 0x08); } diff --git a/higan/processor/arm/instructions-thumb.cpp b/higan/processor/arm/instructions-thumb.cpp index f012b825..b22a445a 100644 --- a/higan/processor/arm/instructions-thumb.cpp +++ b/higan/processor/arm/instructions-thumb.cpp @@ -328,7 +328,7 @@ auto ARM::thumb_op_move_multiple() { auto ARM::thumb_op_software_interrupt() { uint8 immediate = instruction(); - vector(0x00000008, Processor::Mode::SVC); + interrupt(Processor::Mode::SVC, 0x08); } //b{condition} diff --git a/higan/processor/arm/registers.hpp b/higan/processor/arm/registers.hpp index 724f9682..8b1ed074 100644 --- a/higan/processor/arm/registers.hpp +++ b/higan/processor/arm/registers.hpp @@ -55,13 +55,18 @@ struct Pipeline { struct Processor { enum class Mode : uint { - USR = 0x10, //user - FIQ = 0x11, //fast interrupt request - IRQ = 0x12, //interrupt request - SVC = 0x13, //supervisor (software interrupt) - ABT = 0x17, //abort - UND = 0x1b, //undefined - SYS = 0x1f, //system + USR26 = 0x00, //26-bit user + FIQ26 = 0x01, //26-bit fast-interrupt + IRQ26 = 0x02, //26-bit interrupt + SVC26 = 0x03, //26-bit service + + USR = 0x10, //user + FIQ = 0x11, //fast-interrupt + IRQ = 0x12, //interrupt + SVC = 0x13, //service + ABT = 0x17, //abort + UND = 0x1b, //undefined + SYS = 0x1f, //system }; GPR r0, r1, r2, r3, r4, r5, r6, r7; diff --git a/higan/processor/arm/step.cpp b/higan/processor/arm/step.cpp index b6d4eb28..acbef5a9 100644 --- a/higan/processor/arm/step.cpp +++ b/higan/processor/arm/step.cpp @@ -33,7 +33,7 @@ auto ARM::stepARM() -> void { stepPipeline(); if(processor.irqline && cpsr().i == 0) { - vector(0x00000018, Processor::Mode::IRQ); + interrupt(Processor::Mode::IRQ, 0x18); return; } @@ -90,8 +90,8 @@ auto ARM::stepTHUMB() -> void { stepPipeline(); if(processor.irqline && cpsr().i == 0) { - vector(0x00000018, Processor::Mode::IRQ); - r(14) += 2; + interrupt(Processor::Mode::IRQ, 0x18); + r(14).data += 2; return; } diff --git a/higan/processor/arm7tdmi/algorithms.cpp b/higan/processor/arm7tdmi/algorithms.cpp new file mode 100644 index 00000000..c97bbbec --- /dev/null +++ b/higan/processor/arm7tdmi/algorithms.cpp @@ -0,0 +1,96 @@ +auto ARM7TDMI::ADD(uint32 source, uint32 modify, bool carry, bool updateFlags) -> uint32 { + uint32 result = source + modify + carry; + if(updateFlags) { + uint32 overflow = ~(source ^ modify) & (source ^ result); + cpsr().v = 1 << 31 & (overflow); + cpsr().c = 1 << 31 & (overflow ^ source ^ modify ^ result); + cpsr().z = result == 0; + cpsr().n = result.bit(31); + } + return result; +} + +auto ARM7TDMI::ASR(uint32 source, uint8 shift) -> uint32 { + carry = cpsr().c; + if(shift == 0) return source; + carry = shift > 32 ? source & 1 << 31 : source & 1 << shift - 1; + source = shift > 31 ? (int32)source >> 31 : (int32)source >> shift; + return source; +} + +auto ARM7TDMI::BIT(uint32 result, bool updateFlags) -> uint32 { + if(updateFlags) { + cpsr().c = carry; + cpsr().z = result == 0; + cpsr().n = result.bit(31); + } + return result; +} + +auto ARM7TDMI::LSL(uint32 source, uint8 shift) -> uint32 { + carry = cpsr().c; + if(shift == 0) return source; + carry = shift > 32 ? 0 : source & 1 << 32 - shift; + source = shift > 31 ? 0 : source << shift; + return source; +} + +auto ARM7TDMI::LSR(uint32 source, uint8 shift) -> uint32 { + carry = cpsr().c; + if(shift == 0) return source; + carry = shift > 32 ? 0 : source & 1 << shift - 1; + source = shift > 31 ? 0 : source >> shift; + return source; +} + +auto ARM7TDMI::MUL(uint32 product, uint32 multiplicand, uint32 multiplier, bool updateFlags) -> uint32 { + idle(); + if(multiplier >> 8 && multiplier >> 8 != 0xffffff) idle(); + if(multiplier >> 16 && multiplier >> 16 != 0xffff) idle(); + if(multiplier >> 24 && multiplier >> 24 != 0xff) idle(); + product += multiplicand * multiplier; + if(updateFlags) { + cpsr().z = product == 0; + cpsr().n = product.bit(31); + } + return product; +} + +auto ARM7TDMI::ROR(uint32 source, uint8 shift) -> uint32 { + carry = cpsr().c; + if(shift == 0) return source; + if(shift &= 31) source = source << 32 - shift | source >> shift; + carry = source & 1 << 31; + return source; +} + +auto ARM7TDMI::RRX(uint32 source) -> uint32 { + carry = source.bit(0); + return cpsr().c << 31 | source >> 1; +} + +auto ARM7TDMI::SUB(uint32 source, uint32 modify, bool carry, bool updateFlags) -> uint32 { + return ADD(source, ~modify, carry, updateFlags); +} + +auto ARM7TDMI::TST(uint4 mode) -> bool { + switch(mode) { + case 0: return cpsr().z == 1; //EQ (equal) + case 1: return cpsr().z == 0; //NE (not equal) + case 2: return cpsr().c == 1; //CS (carry set) + case 3: return cpsr().c == 0; //CC (carry clear) + case 4: return cpsr().n == 1; //MI (negative) + case 5: return cpsr().n == 0; //PL (positive) + case 6: return cpsr().v == 1; //VS (overflow) + case 7: return cpsr().v == 0; //VC (no overflow) + case 8: return cpsr().c == 1 && cpsr().z == 0; //HI (unsigned higher) + case 9: return cpsr().c == 0 || cpsr().z == 1; //LS (unsigned lower or same) + case 10: return cpsr().n == cpsr().v; //GE (signed greater than or equal) + case 11: return cpsr().n != cpsr().v; //LT (signed less than) + case 12: return cpsr().z == 0 && cpsr().n == cpsr().v; //GT (signed greater than) + case 13: return cpsr().z == 1 || cpsr().n != cpsr().v; //LE (signed less than or equal) + case 14: return true; //AL (always) + case 15: return false; //NV (never) + } + unreachable; +} diff --git a/higan/processor/arm7tdmi/arm7tdmi.cpp b/higan/processor/arm7tdmi/arm7tdmi.cpp new file mode 100644 index 00000000..e4532f49 --- /dev/null +++ b/higan/processor/arm7tdmi/arm7tdmi.cpp @@ -0,0 +1,23 @@ +#include +#include "arm7tdmi.hpp" + +namespace Processor { + +#include "registers.cpp" +#include "memory.cpp" +#include "algorithms.cpp" +#include "instruction.cpp" +#include "instructions-arm.cpp" +#include "instructions-thumb.cpp" +#include "serialization.cpp" + +auto ARM7TDMI::power() -> void { + processor = {}; + interrupt(PSR::SVC, 0x00); + processor.r15.modify = [&] { pipeline.reload = true; }; + pipeline = {}; + carry = 0; + irq = 0; +} + +} diff --git a/higan/processor/arm7tdmi/arm7tdmi.hpp b/higan/processor/arm7tdmi/arm7tdmi.hpp new file mode 100644 index 00000000..e92aa535 --- /dev/null +++ b/higan/processor/arm7tdmi/arm7tdmi.hpp @@ -0,0 +1,180 @@ +//ARMv3 (ARM60) +//ARMv4 (ARM7TDMI) + +#pragma once + +namespace Processor { + +struct ARM7TDMI { + enum : uint { + Nonsequential = 1 << 0, //N cycle + Sequential = 1 << 1, //S cycle + Prefetch = 1 << 2, //instruction fetch + Byte = 1 << 3, // 8-bit access + Half = 1 << 4, //16-bit access + Word = 1 << 5, //32-bit access + Load = 1 << 6, //load operation + Store = 1 << 7, //store operation + Signed = 1 << 8, //sign-extend + }; + + virtual auto step(uint clocks) -> void = 0; + virtual auto sleep() -> void = 0; + virtual auto get(uint mode, uint32 address) -> uint32 = 0; + virtual auto set(uint mode, uint32 address, uint32 word) -> void = 0; + + //arm7tdmi.cpp + auto power() -> void; + + //registers.cpp + struct GPR; + struct PSR; + inline auto r(uint4) -> GPR&; + inline auto u(uint4) -> GPR&; + inline auto cpsr() -> PSR&; + inline auto spsr() -> PSR&; + inline auto privileged() const -> bool; + inline auto exception() const -> bool; + + //memory.cpp + auto idle() -> void; + auto read(uint mode, uint32 address) -> uint32; + auto load(uint mode, uint32 address) -> uint32; + auto write(uint mode, uint32 address, uint32 word) -> void; + auto store(uint mode, uint32 address, uint32 word) -> void; + + //algorithms.cpp + auto ADD(uint32, uint32, bool, bool = true) -> uint32; + auto ASR(uint32, uint8) -> uint32; + auto BIT(uint32, bool = true) -> uint32; + auto LSL(uint32, uint8) -> uint32; + auto LSR(uint32, uint8) -> uint32; + auto MUL(uint32, uint32, uint32, bool = true) -> uint32; + auto ROR(uint32, uint8) -> uint32; + auto RRX(uint32) -> uint32; + auto SUB(uint32, uint32, bool, bool = true) -> uint32; + auto TST(uint4) -> bool; + + //instruction.cpp + auto fetch() -> void; + auto instruction() -> void; + auto interrupt(uint mode, uint32 address) -> void; + + //instructions-arm.cpp + auto armALU(uint4 mode, uint4 target, uint4 source, uint32 data, bool save) -> void; + + //instructions-thumb.cpp + auto thumbALU(uint4 mode, uint4 target, uint4 source) -> void; + + //serialization.cpp + auto serialize(serializer&) -> void; + + struct GPR { + inline operator uint32_t() const { + return data; + } + + inline auto operator=(uint32 value) -> GPR& { + data = value; + if(modify) modify(); + return *this; + } + + uint32 data; + function void> modify; + }; + + struct PSR { + enum : uint { + USR = 0x10, //user + FIQ = 0x11, //fast interrupt request + IRQ = 0x12, //interrupt request + SVC = 0x13, //supervisor (software interrupt) + ABT = 0x17, //abort + UND = 0x1b, //undefined + SYS = 0x1f, //system + }; + + inline operator uint32_t() const { + return m << 0 | t << 5 | f << 6 | i << 7 | v << 28 | c << 29 | z << 30 | n << 31; + } + + inline auto operator=(uint32 data) -> PSR& { + m = data.bits(0,4); + t = data.bit(5); + f = data.bit(6); + i = data.bit(7); + v = data.bit(28); + c = data.bit(29); + z = data.bit(30); + n = data.bit(31); + return *this; + } + + //serialization.cpp + auto serialize(serializer&) -> void; + + uint5 m; //mode + uint1 t; //thumb + uint1 f; //fiq + uint1 i; //irq + uint1 v; //overflow + uint1 c; //carry + uint1 z; //zero + uint1 n; //negative + }; + + struct Processor { + //serialization.cpp + auto serialize(serializer&) -> void; + + GPR r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15; + PSR cpsr; + + struct FIQ { + GPR r8, r9, r10, r11, r12, r13, r14; + PSR spsr; + } fiq; + + struct IRQ { + GPR r13, r14; + PSR spsr; + } irq; + + struct SVC { + GPR r13, r14; + PSR spsr; + } svc; + + struct ABT { + GPR r13, r14; + PSR spsr; + } abt; + + struct UND { + GPR r13, r14; + PSR spsr; + } und; + } processor; + + struct Pipeline { + //serialization.cpp + auto serialize(serializer&) -> void; + + struct Instruction { + uint32 address; + uint32 instruction; + }; + + uint1 reload = 1; + uint1 nonsequential = 1; + Instruction fetch; + Instruction decode; + Instruction execute; + } pipeline; + + boolean carry; + boolean irq; +}; + +} diff --git a/higan/processor/arm7tdmi/instruction.cpp b/higan/processor/arm7tdmi/instruction.cpp new file mode 100644 index 00000000..fabbb47e --- /dev/null +++ b/higan/processor/arm7tdmi/instruction.cpp @@ -0,0 +1,53 @@ +auto ARM7TDMI::fetch() -> void { + pipeline.execute = pipeline.decode; + pipeline.decode = pipeline.fetch; + + uint sequential = Sequential; + if(pipeline.nonsequential) { + pipeline.nonsequential = false; + sequential = Nonsequential; + } + + uint mask = !cpsr().t ? 3 : 1; + uint size = !cpsr().t ? Word : Half; + + r(15).data += size >> 3; + pipeline.fetch.address = r(15) & ~mask; + pipeline.fetch.instruction = read(Prefetch | size | sequential, pipeline.fetch.address); +} + +auto ARM7TDMI::instruction() -> void { + uint mask = !cpsr().t ? 3 : 1; + uint size = !cpsr().t ? Word : Half; + + if(pipeline.reload) { + pipeline.reload = false; + r(15).data &= ~mask; + pipeline.fetch.address = r(15) & ~mask; + pipeline.fetch.instruction = read(Prefetch | size | Nonsequential, pipeline.fetch.address); + fetch(); + } + fetch(); + + if(irq && !cpsr().i) { + interrupt(PSR::IRQ, 0x18); + if(cpsr().t) r(14).data += 2; + return; + } + + if(!cpsr().t) { + if(!TST(pipeline.execute.instruction.bits(28,31))) return; + } else { + } +} + +auto ARM7TDMI::interrupt(uint mode, uint32 address) -> void { + auto psr = cpsr(); + cpsr().m = 0x10 | mode; + spsr() = psr; + cpsr().t = 0; + if(cpsr().m == PSR::FIQ) cpsr().f = 1; + cpsr().i = 1; + r(14) = pipeline.decode.address; + r(15) = address; +} diff --git a/higan/processor/arm7tdmi/instructions-arm.cpp b/higan/processor/arm7tdmi/instructions-arm.cpp new file mode 100644 index 00000000..38813a4f --- /dev/null +++ b/higan/processor/arm7tdmi/instructions-arm.cpp @@ -0,0 +1,24 @@ +auto ARM7TDMI::armALU(uint4 mode, uint4 target, uint4 source, uint32 data, bool save) -> void { + switch(mode) { + case 0: r(target) = BIT(r(source) & data, save); break; //AND + case 1: r(target) = BIT(r(source) ^ data, save); break; //EOR + case 2: r(target) = SUB(r(source), data, 1, save); break; //SUB + case 3: r(target) = SUB(data, r(source), 1, save); break; //RSB + case 4: r(target) = ADD(r(source), data, 0, save); break; //ADD + case 5: r(target) = ADD(r(source), data, cpsr().c, save); break; //ADC + case 6: r(target) = SUB(r(source), data, cpsr().c, save); break; //SBC + case 7: r(target) = SUB(data, r(source), cpsr().c, save); break; //RSC + case 8: BIT(r(source) & data, save); break; //TST + case 9: BIT(r(source) ^ data, save); break; //TEQ + case 10: SUB(r(source), data, 1, save); break; //CMP + case 11: ADD(r(source), data, 0, save); break; //CMN + case 12: r(target) = BIT(r(source) | data, save); break; //ORR + case 13: r(target) = BIT(data, save); break; //MOV + case 14: r(target) = BIT(r(source) & ~data, save); break; //BIC + case 15: r(target) = BIT(~data, save); break; //MVN + } + + if(exception() && target == 15 && save) { + cpsr() = spsr(); + } +} diff --git a/higan/processor/arm7tdmi/instructions-thumb.cpp b/higan/processor/arm7tdmi/instructions-thumb.cpp new file mode 100644 index 00000000..cad99109 --- /dev/null +++ b/higan/processor/arm7tdmi/instructions-thumb.cpp @@ -0,0 +1,20 @@ +auto ARM7TDMI::thumbALU(uint4 mode, uint4 target, uint4 source) -> void { + switch(mode) { + case 0: r(target) = BIT(r(target) & r(source)); break; //AND + case 1: r(target) = BIT(r(target) ^ r(source)); break; //EOR + case 2: r(target) = BIT(LSL(r(target), r(source))); break; //LSL + case 3: r(target) = BIT(LSR(r(target), r(source))); break; //LSR + case 4: r(target) = BIT(ASR(r(target), r(source))); break; //ASR + case 5: r(target) = ADD(r(target), r(source), cpsr().c); break; //ADC + case 6: r(target) = SUB(r(target), r(source), cpsr().c); break; //SBC + case 7: r(target) = BIT(ROR(r(target), r(source))); break; //ROR + case 8: BIT(r(target) & r(source)); break; //TST + case 9: r(target) = SUB(0, r(source), 1); break; //NEG + case 10: SUB(r(target), r(source), 1); break; //CMP + case 11: ADD(r(target), r(source), 0); break; //CMN + case 12: r(target) = BIT(r(target) | r(source)); break; //ORR + case 13: r(target) = MUL(0, r(source), r(target)); break; //MUL + case 14: r(target) = BIT(r(target) & ~r(source)); break; //BIC + case 15: r(target) = BIT(~r(source)); break; //MVN + } +} diff --git a/higan/processor/arm7tdmi/memory.cpp b/higan/processor/arm7tdmi/memory.cpp new file mode 100644 index 00000000..267d2d8b --- /dev/null +++ b/higan/processor/arm7tdmi/memory.cpp @@ -0,0 +1,40 @@ +auto ARM7TDMI::idle() -> void { + pipeline.nonsequential = true; + sleep(); +} + +auto ARM7TDMI::read(uint mode, uint32 address) -> uint32 { + return get(mode, address); +} + +auto ARM7TDMI::load(uint mode, uint32 address) -> uint32 { + pipeline.nonsequential = true; + auto word = get(Load | mode, address); + if(mode & Half) { + address &= 1; + word = mode & Signed ? (uint16)(int16)word : (uint16)word; + } + if(mode & Byte) { + address &= 0; + word = mode & Signed ? (uint8)(int8)word : (uint8)word; + } + if(mode & Signed) { + word = ASR(word, address.bits(0,1) << 3); + } else { + word = ROR(word, address.bits(0,1) << 3); + } + idle(); + return word; +} + +auto ARM7TDMI::write(uint mode, uint32 address, uint32 word) -> void { + pipeline.nonsequential = true; + return set(mode, address, word); +} + +auto ARM7TDMI::store(uint mode, uint32 address, uint32 word) -> void { + pipeline.nonsequential = true; + if(mode & Half) { word &= 0xffff; word |= word << 16; } + if(mode & Byte) { word &= 0xff; word |= word << 8; word |= word << 16; } + return set(Store | mode, address, word); +} diff --git a/higan/processor/arm7tdmi/registers.cpp b/higan/processor/arm7tdmi/registers.cpp new file mode 100644 index 00000000..24af3793 --- /dev/null +++ b/higan/processor/arm7tdmi/registers.cpp @@ -0,0 +1,80 @@ +auto ARM7TDMI::r(uint4 index) -> GPR& { + switch(index) { + case 0: return processor.r0; + case 1: return processor.r1; + case 2: return processor.r2; + case 3: return processor.r3; + case 4: return processor.r4; + case 5: return processor.r5; + case 6: return processor.r6; + case 7: return processor.r7; + case 8: return processor.cpsr.m == PSR::FIQ ? processor.fiq.r8 : processor.r8; + case 9: return processor.cpsr.m == PSR::FIQ ? processor.fiq.r9 : processor.r9; + case 10: return processor.cpsr.m == PSR::FIQ ? processor.fiq.r10 : processor.r10; + case 11: return processor.cpsr.m == PSR::FIQ ? processor.fiq.r11 : processor.r11; + case 12: return processor.cpsr.m == PSR::FIQ ? processor.fiq.r12 : processor.r12; + case 13: switch(processor.cpsr.m) { + case PSR::FIQ: return processor.fiq.r13; + case PSR::IRQ: return processor.irq.r13; + case PSR::SVC: return processor.svc.r13; + case PSR::ABT: return processor.abt.r13; + case PSR::UND: return processor.und.r13; + default: return processor.r13; + } + case 14: switch(processor.cpsr.m) { + case PSR::FIQ: return processor.fiq.r14; + case PSR::IRQ: return processor.irq.r14; + case PSR::SVC: return processor.svc.r14; + case PSR::ABT: return processor.abt.r14; + case PSR::UND: return processor.und.r14; + default: return processor.r14; + } + case 15: return processor.r15; + } + unreachable; +} + +auto ARM7TDMI::u(uint4 index) -> GPR& { + switch(index) { + case 0: return processor.r0; + case 1: return processor.r1; + case 2: return processor.r2; + case 3: return processor.r3; + case 4: return processor.r4; + case 5: return processor.r5; + case 6: return processor.r6; + case 7: return processor.r7; + case 8: return processor.r8; + case 9: return processor.r9; + case 10: return processor.r10; + case 11: return processor.r11; + case 12: return processor.r12; + case 13: return processor.r13; + case 14: return processor.r14; + case 15: return processor.r15; + } + unreachable; +} + +auto ARM7TDMI::cpsr() -> PSR& { + return processor.cpsr; +} + +auto ARM7TDMI::spsr() -> PSR& { + switch(processor.cpsr.m) { + case PSR::FIQ: return processor.fiq.spsr; + case PSR::IRQ: return processor.irq.spsr; + case PSR::SVC: return processor.svc.spsr; + case PSR::ABT: return processor.abt.spsr; + case PSR::UND: return processor.und.spsr; + } + throw; +} + +auto ARM7TDMI::privileged() const -> bool { + return processor.cpsr.m != PSR::USR; +} + +auto ARM7TDMI::exception() const -> bool { + return privileged() && processor.cpsr.m != PSR::SYS; +} diff --git a/higan/processor/arm7tdmi/serialization.cpp b/higan/processor/arm7tdmi/serialization.cpp new file mode 100644 index 00000000..b623c274 --- /dev/null +++ b/higan/processor/arm7tdmi/serialization.cpp @@ -0,0 +1,68 @@ +auto ARM7TDMI::serialize(serializer& s) -> void { + processor.serialize(s); + pipeline.serialize(s); + s.boolean(carry); + s.boolean(irq); +} + +auto ARM7TDMI::Processor::serialize(serializer& s) -> void { + s.integer(r0.data); + s.integer(r1.data); + s.integer(r2.data); + s.integer(r3.data); + s.integer(r4.data); + s.integer(r5.data); + s.integer(r6.data); + s.integer(r7.data); + s.integer(r8.data); + s.integer(r9.data); + s.integer(r10.data); + s.integer(r11.data); + s.integer(r12.data); + s.integer(r13.data); + s.integer(r14.data); + s.integer(r15.data); + cpsr.serialize(s); + s.integer(fiq.r8.data); + s.integer(fiq.r9.data); + s.integer(fiq.r10.data); + s.integer(fiq.r11.data); + s.integer(fiq.r12.data); + s.integer(fiq.r13.data); + s.integer(fiq.r14.data); + fiq.spsr.serialize(s); + s.integer(irq.r13.data); + s.integer(irq.r14.data); + irq.spsr.serialize(s); + s.integer(svc.r13.data); + s.integer(svc.r14.data); + svc.spsr.serialize(s); + s.integer(abt.r13.data); + s.integer(abt.r14.data); + abt.spsr.serialize(s); + s.integer(und.r13.data); + s.integer(und.r14.data); + und.spsr.serialize(s); +} + +auto ARM7TDMI::PSR::serialize(serializer& s) -> void { + s.integer(m); + s.integer(t); + s.integer(f); + s.integer(i); + s.integer(v); + s.integer(c); + s.integer(z); + s.integer(n); +} + +auto ARM7TDMI::Pipeline::serialize(serializer& s) -> void { + s.integer(reload); + s.integer(nonsequential); + s.integer(fetch.address); + s.integer(fetch.instruction); + s.integer(decode.address); + s.integer(decode.instruction); + s.integer(execute.address); + s.integer(execute.instruction); +} diff --git a/higan/processor/lr35902-legacy/disassembler.cpp b/higan/processor/lr35902-legacy/disassembler.cpp deleted file mode 100644 index c59f998e..00000000 --- a/higan/processor/lr35902-legacy/disassembler.cpp +++ /dev/null @@ -1,533 +0,0 @@ -auto LR35902::disassemble(uint16 pc) -> string { - return { - hex(pc, 4L), " ", - pad(disassembleOpcode(pc), -16, ' '), " ", - " AF:", hex(r[AF], 4L), - " BC:", hex(r[BC], 4L), - " DE:", hex(r[DE], 4L), - " HL:", hex(r[HL], 4L), - " SP:", hex(r[SP], 4L) - }; -} - -auto LR35902::disassembleOpcode(uint16 pc) -> string { - auto opcode = readDebugger(pc); - auto lo = readDebugger(pc + 1); - auto hi = readDebugger(pc + 2); - auto word = hi << 8 | lo << 0; - - switch(opcode) { - case 0x00: return {"nop"}; - case 0x01: return {"ld bc,$", hex(word, 4L)}; - case 0x02: return {"ld (bc),a"}; - case 0x03: return {"inc bc"}; - case 0x04: return {"inc b"}; - case 0x05: return {"dec b"}; - case 0x06: return {"ld b,$", hex(lo, 2L)}; - case 0x07: return {"rlca"}; - case 0x08: return {"ld ($", hex(word, 4L), "),sp"}; - case 0x09: return {"add hl,bc"}; - case 0x0a: return {"ld a,(bc)"}; - case 0x0b: return {"dec bc"}; - case 0x0c: return {"inc c"}; - case 0x0d: return {"dec c"}; - case 0x0e: return {"ld c,$", hex(lo, 2L)}; - case 0x0f: return {"rrca"}; - case 0x10: return {"stop"}; - case 0x11: return {"ld de,$", hex(word, 4L)}; - case 0x12: return {"ld (de),a"}; - case 0x13: return {"inc de"}; - case 0x14: return {"inc d"}; - case 0x15: return {"dec d"}; - case 0x16: return {"ld d,$", hex(lo, 2L)}; - case 0x17: return {"rla"}; - case 0x18: return {"jr $", hex(pc + 2 + (int8)lo, 4L)}; - case 0x19: return {"add hl,de"}; - case 0x1a: return {"ld a,(de)"}; - case 0x1b: return {"dec de"}; - case 0x1c: return {"inc e"}; - case 0x1d: return {"dec e"}; - case 0x1e: return {"ld e,$", hex(lo, 2L)}; - case 0x1f: return {"rra"}; - case 0x20: return {"jr nz,$", hex(pc + 2 + (int8)lo, 4L)}; - case 0x21: return {"ld hl,$", hex(word, 4L)}; - case 0x22: return {"ldi (hl),a"}; - case 0x23: return {"inc hl"}; - case 0x24: return {"inc h"}; - case 0x25: return {"dec h"}; - case 0x26: return {"ld h,$", hex(lo, 2L)}; - case 0x27: return {"daa"}; - case 0x28: return {"jr z,$", hex(pc + 2 + (int8)lo, 4L)}; - case 0x29: return {"add hl,hl"}; - case 0x2a: return {"ldi a,(hl)"}; - case 0x2b: return {"dec hl"}; - case 0x2c: return {"inc l"}; - case 0x2d: return {"dec l"}; - case 0x2e: return {"ld l,$", hex(lo, 2L)}; - case 0x2f: return {"cpl"}; - case 0x30: return {"jr nc,$", hex(pc + 2 + (int8)lo, 4L)}; - case 0x31: return {"ld sp,$", hex(word, 4L)}; - case 0x32: return {"ldd (hl),a"}; - case 0x33: return {"inc sp"}; - case 0x34: return {"inc (hl)"}; - case 0x35: return {"dec (hl)"}; - case 0x36: return {"ld (hl),$", hex(lo, 2L)}; - case 0x37: return {"scf"}; - case 0x38: return {"jr c,$", hex(pc + 2 + (int8)lo, 4L)}; - case 0x39: return {"add hl,sp"}; - case 0x3a: return {"ldd a,(hl)"}; - case 0x3b: return {"dec sp"}; - case 0x3c: return {"inc a"}; - case 0x3d: return {"dec a"}; - case 0x3e: return {"ld a,$", hex(lo, 2L)}; - case 0x3f: return {"ccf"}; - case 0x40: return {"ld b,b"}; - case 0x41: return {"ld b,c"}; - case 0x42: return {"ld b,d"}; - case 0x43: return {"ld b,e"}; - case 0x44: return {"ld b,h"}; - case 0x45: return {"ld b,l"}; - case 0x46: return {"ld b,(hl)"}; - case 0x47: return {"ld b,a"}; - case 0x48: return {"ld c,b"}; - case 0x49: return {"ld c,c"}; - case 0x4a: return {"ld c,d"}; - case 0x4b: return {"ld c,e"}; - case 0x4c: return {"ld c,h"}; - case 0x4d: return {"ld c,l"}; - case 0x4e: return {"ld c,(hl)"}; - case 0x4f: return {"ld c,a"}; - case 0x50: return {"ld d,b"}; - case 0x51: return {"ld d,c"}; - case 0x52: return {"ld d,d"}; - case 0x53: return {"ld d,e"}; - case 0x54: return {"ld d,h"}; - case 0x55: return {"ld d,l"}; - case 0x56: return {"ld d,(hl)"}; - case 0x57: return {"ld d,a"}; - case 0x58: return {"ld e,b"}; - case 0x59: return {"ld e,c"}; - case 0x5a: return {"ld e,d"}; - case 0x5b: return {"ld e,e"}; - case 0x5c: return {"ld e,h"}; - case 0x5d: return {"ld e,l"}; - case 0x5e: return {"ld e,(hl)"}; - case 0x5f: return {"ld e,a"}; - case 0x60: return {"ld h,b"}; - case 0x61: return {"ld h,c"}; - case 0x62: return {"ld h,d"}; - case 0x63: return {"ld h,e"}; - case 0x64: return {"ld h,h"}; - case 0x65: return {"ld h,l"}; - case 0x66: return {"ld h,(hl)"}; - case 0x67: return {"ld h,a"}; - case 0x68: return {"ld l,b"}; - case 0x69: return {"ld l,c"}; - case 0x6a: return {"ld l,d"}; - case 0x6b: return {"ld l,e"}; - case 0x6c: return {"ld l,h"}; - case 0x6d: return {"ld l,l"}; - case 0x6e: return {"ld l,(hl)"}; - case 0x6f: return {"ld l,a"}; - case 0x70: return {"ld (hl),b"}; - case 0x71: return {"ld (hl),c"}; - case 0x72: return {"ld (hl),d"}; - case 0x73: return {"ld (hl),e"}; - case 0x74: return {"ld (hl),h"}; - case 0x75: return {"ld (hl),l"}; - case 0x76: return {"halt"}; - case 0x77: return {"ld (hl),a"}; - case 0x78: return {"ld a,b"}; - case 0x79: return {"ld a,c"}; - case 0x7a: return {"ld a,d"}; - case 0x7b: return {"ld a,e"}; - case 0x7c: return {"ld a,h"}; - case 0x7d: return {"ld a,l"}; - case 0x7e: return {"ld a,(hl)"}; - case 0x7f: return {"ld a,a"}; - case 0x80: return {"add a,b"}; - case 0x81: return {"add a,c"}; - case 0x82: return {"add a,d"}; - case 0x83: return {"add a,e"}; - case 0x84: return {"add a,h"}; - case 0x85: return {"add a,l"}; - case 0x86: return {"add a,(hl)"}; - case 0x87: return {"add a,a"}; - case 0x88: return {"adc a,b"}; - case 0x89: return {"adc a,c"}; - case 0x8a: return {"adc a,d"}; - case 0x8b: return {"adc a,e"}; - case 0x8c: return {"adc a,h"}; - case 0x8d: return {"adc a,l"}; - case 0x8e: return {"adc a,(hl)"}; - case 0x8f: return {"adc a,a"}; - case 0x90: return {"sub a,b"}; - case 0x91: return {"sub a,c"}; - case 0x92: return {"sub a,d"}; - case 0x93: return {"sub a,e"}; - case 0x94: return {"sub a,h"}; - case 0x95: return {"sub a,l"}; - case 0x96: return {"sub a,(hl)"}; - case 0x97: return {"sub a,a"}; - case 0x98: return {"sbc a,b"}; - case 0x99: return {"sbc a,c"}; - case 0x9a: return {"sbc a,d"}; - case 0x9b: return {"sbc a,e"}; - case 0x9c: return {"sbc a,h"}; - case 0x9d: return {"sbc a,l"}; - case 0x9e: return {"sbc a,(hl)"}; - case 0x9f: return {"sbc a,a"}; - case 0xa0: return {"and a,b"}; - case 0xa1: return {"and a,c"}; - case 0xa2: return {"and a,d"}; - case 0xa3: return {"and a,e"}; - case 0xa4: return {"and a,h"}; - case 0xa5: return {"and a,l"}; - case 0xa6: return {"and a,(hl)"}; - case 0xa7: return {"and a,a"}; - case 0xa8: return {"xor a,b"}; - case 0xa9: return {"xor a,c"}; - case 0xaa: return {"xor a,d"}; - case 0xab: return {"xor a,e"}; - case 0xac: return {"xor a,h"}; - case 0xad: return {"xor a,l"}; - case 0xae: return {"xor a,(hl)"}; - case 0xaf: return {"xor a,a"}; - case 0xb0: return {"or a,b"}; - case 0xb1: return {"or a,c"}; - case 0xb2: return {"or a,d"}; - case 0xb3: return {"or a,e"}; - case 0xb4: return {"or a,h"}; - case 0xb5: return {"or a,l"}; - case 0xb6: return {"or a,(hl)"}; - case 0xb7: return {"or a,a"}; - case 0xb8: return {"cp a,b"}; - case 0xb9: return {"cp a,c"}; - case 0xba: return {"cp a,d"}; - case 0xbb: return {"cp a,e"}; - case 0xbc: return {"cp a,h"}; - case 0xbd: return {"cp a,l"}; - case 0xbe: return {"cp a,(hl)"}; - case 0xbf: return {"cp a,a"}; - case 0xc0: return {"ret nz"}; - case 0xc1: return {"pop bc"}; - case 0xc2: return {"jp nz,$", hex(word, 4L)}; - case 0xc3: return {"jp $", hex(word, 4L)}; - case 0xc4: return {"call nz,$", hex(word, 4L)}; - case 0xc5: return {"push bc"}; - case 0xc6: return {"add a,$", hex(lo, 2L)}; - case 0xc7: return {"rst $0000"}; - case 0xc8: return {"ret z"}; - case 0xc9: return {"ret"}; - case 0xca: return {"jp z,$", hex(word, 4L)}; - case 0xcb: return disassembleOpcodeCB(pc + 1); - case 0xcc: return {"call z,$", hex(word, 4L)}; - case 0xcd: return {"call $", hex(word, 4L)}; - case 0xce: return {"adc a,$", hex(lo, 2L)}; - case 0xcf: return {"rst $0008"}; - case 0xd0: return {"ret nc"}; - case 0xd1: return {"pop de"}; - case 0xd2: return {"jp nc,$", hex(word, 4L)}; - case 0xd4: return {"call nc,$", hex(word, 4L)}; - case 0xd5: return {"push de"}; - case 0xd6: return {"sub a,$", hex(lo, 2L)}; - case 0xd7: return {"rst $0010"}; - case 0xd8: return {"ret c"}; - case 0xd9: return {"reti"}; - case 0xda: return {"jp c,$", hex(word, 4L)}; - case 0xdc: return {"call c,$", hex(word, 4L)}; - case 0xde: return {"sbc a,$", hex(lo, 2L)}; - case 0xdf: return {"rst $0018"}; - case 0xe0: return {"ldh ($ff", hex(lo, 2L), "),a"}; - case 0xe1: return {"pop hl"}; - case 0xe2: return {"ldh ($ff00+c),a"}; - case 0xe5: return {"push hl"}; - case 0xe6: return {"and a,$", hex(lo, 2L)}; - case 0xe7: return {"rst $0020"}; - case 0xe8: return {"add sp,$", hex((int8)lo, 4L)}; - case 0xe9: return {"jp hl"}; - case 0xea: return {"ld ($", hex(word, 4L), "),a"}; - case 0xee: return {"xor a,$", hex(lo, 2L)}; - case 0xef: return {"rst $0028"}; - case 0xf0: return {"ldh a,($ff", hex(lo, 2L), ")"}; - case 0xf1: return {"pop af"}; - case 0xf2: return {"ldh a,($ff00+c)"}; - case 0xf3: return {"di"}; - case 0xf5: return {"push af"}; - case 0xf6: return {"or a,$", hex(lo, 2L)}; - case 0xf7: return {"rst $0030"}; - case 0xf8: return {"ld hl,sp+$", hex((int8)lo, 4L)}; - case 0xf9: return {"ld sp,hl"}; - case 0xfa: return {"ld a,($", hex(word, 4L), ")"}; - case 0xfb: return {"ei"}; - case 0xfe: return {"cp a,$", hex(lo, 2L)}; - case 0xff: return {"rst $0038"}; - } - - return "xx"; -} - -auto LR35902::disassembleOpcodeCB(uint16 pc) -> string { - auto opcode = readDebugger(pc); - - switch(opcode) { - case 0x00: return {"rlc b"}; - case 0x01: return {"rlc c"}; - case 0x02: return {"rlc d"}; - case 0x03: return {"rlc e"}; - case 0x04: return {"rlc h"}; - case 0x05: return {"rlc l"}; - case 0x06: return {"rlc (hl)"}; - case 0x07: return {"rlc a"}; - case 0x08: return {"rrc b"}; - case 0x09: return {"rrc c"}; - case 0x0a: return {"rrc d"}; - case 0x0b: return {"rrc e"}; - case 0x0c: return {"rrc h"}; - case 0x0d: return {"rrc l"}; - case 0x0e: return {"rrc (hl)"}; - case 0x0f: return {"rrc a"}; - case 0x10: return {"rl b"}; - case 0x11: return {"rl c"}; - case 0x12: return {"rl d"}; - case 0x13: return {"rl e"}; - case 0x14: return {"rl h"}; - case 0x15: return {"rl l"}; - case 0x16: return {"rl (hl)"}; - case 0x17: return {"rl a"}; - case 0x18: return {"rr b"}; - case 0x19: return {"rr c"}; - case 0x1a: return {"rr d"}; - case 0x1b: return {"rr e"}; - case 0x1c: return {"rr h"}; - case 0x1d: return {"rr l"}; - case 0x1e: return {"rr (hl)"}; - case 0x1f: return {"rr a"}; - case 0x20: return {"sla b"}; - case 0x21: return {"sla c"}; - case 0x22: return {"sla d"}; - case 0x23: return {"sla e"}; - case 0x24: return {"sla h"}; - case 0x25: return {"sla l"}; - case 0x26: return {"sla (hl)"}; - case 0x27: return {"sla a"}; - case 0x28: return {"sra b"}; - case 0x29: return {"sra c"}; - case 0x2a: return {"sra d"}; - case 0x2b: return {"sra e"}; - case 0x2c: return {"sra h"}; - case 0x2d: return {"sra l"}; - case 0x2e: return {"sra (hl)"}; - case 0x2f: return {"sra a"}; - case 0x30: return {"swap b"}; - case 0x31: return {"swap c"}; - case 0x32: return {"swap d"}; - case 0x33: return {"swap e"}; - case 0x34: return {"swap h"}; - case 0x35: return {"swap l"}; - case 0x36: return {"swap (hl)"}; - case 0x37: return {"swap a"}; - case 0x38: return {"srl b"}; - case 0x39: return {"srl c"}; - case 0x3a: return {"srl d"}; - case 0x3b: return {"srl e"}; - case 0x3c: return {"srl h"}; - case 0x3d: return {"srl l"}; - case 0x3e: return {"srl (hl)"}; - case 0x3f: return {"srl a"}; - case 0x40: return {"bit 0,b"}; - case 0x41: return {"bit 0,c"}; - case 0x42: return {"bit 0,d"}; - case 0x43: return {"bit 0,e"}; - case 0x44: return {"bit 0,h"}; - case 0x45: return {"bit 0,l"}; - case 0x46: return {"bit 0,(hl)"}; - case 0x47: return {"bit 0,a"}; - case 0x48: return {"bit 1,b"}; - case 0x49: return {"bit 1,c"}; - case 0x4a: return {"bit 1,d"}; - case 0x4b: return {"bit 1,e"}; - case 0x4c: return {"bit 1,h"}; - case 0x4d: return {"bit 1,l"}; - case 0x4e: return {"bit 1,(hl)"}; - case 0x4f: return {"bit 1,a"}; - case 0x50: return {"bit 2,b"}; - case 0x51: return {"bit 2,c"}; - case 0x52: return {"bit 2,d"}; - case 0x53: return {"bit 2,e"}; - case 0x54: return {"bit 2,h"}; - case 0x55: return {"bit 2,l"}; - case 0x56: return {"bit 2,(hl)"}; - case 0x57: return {"bit 2,a"}; - case 0x58: return {"bit 3,b"}; - case 0x59: return {"bit 3,c"}; - case 0x5a: return {"bit 3,d"}; - case 0x5b: return {"bit 3,e"}; - case 0x5c: return {"bit 3,h"}; - case 0x5d: return {"bit 3,l"}; - case 0x5e: return {"bit 3,(hl)"}; - case 0x5f: return {"bit 3,a"}; - case 0x60: return {"bit 4,b"}; - case 0x61: return {"bit 4,c"}; - case 0x62: return {"bit 4,d"}; - case 0x63: return {"bit 4,e"}; - case 0x64: return {"bit 4,h"}; - case 0x65: return {"bit 4,l"}; - case 0x66: return {"bit 4,(hl)"}; - case 0x67: return {"bit 4,a"}; - case 0x68: return {"bit 5,b"}; - case 0x69: return {"bit 5,c"}; - case 0x6a: return {"bit 5,d"}; - case 0x6b: return {"bit 5,e"}; - case 0x6c: return {"bit 5,h"}; - case 0x6d: return {"bit 5,l"}; - case 0x6e: return {"bit 5,(hl)"}; - case 0x6f: return {"bit 5,a"}; - case 0x70: return {"bit 6,b"}; - case 0x71: return {"bit 6,c"}; - case 0x72: return {"bit 6,d"}; - case 0x73: return {"bit 6,e"}; - case 0x74: return {"bit 6,h"}; - case 0x75: return {"bit 6,l"}; - case 0x76: return {"bit 6,(hl)"}; - case 0x77: return {"bit 6,a"}; - case 0x78: return {"bit 7,b"}; - case 0x79: return {"bit 7,c"}; - case 0x7a: return {"bit 7,d"}; - case 0x7b: return {"bit 7,e"}; - case 0x7c: return {"bit 7,h"}; - case 0x7d: return {"bit 7,l"}; - case 0x7e: return {"bit 7,(hl)"}; - case 0x7f: return {"bit 7,a"}; - case 0x80: return {"res 0,b"}; - case 0x81: return {"res 0,c"}; - case 0x82: return {"res 0,d"}; - case 0x83: return {"res 0,e"}; - case 0x84: return {"res 0,h"}; - case 0x85: return {"res 0,l"}; - case 0x86: return {"res 0,(hl)"}; - case 0x87: return {"res 0,a"}; - case 0x88: return {"res 1,b"}; - case 0x89: return {"res 1,c"}; - case 0x8a: return {"res 1,d"}; - case 0x8b: return {"res 1,e"}; - case 0x8c: return {"res 1,h"}; - case 0x8d: return {"res 1,l"}; - case 0x8e: return {"res 1,(hl)"}; - case 0x8f: return {"res 1,a"}; - case 0x90: return {"res 2,b"}; - case 0x91: return {"res 2,c"}; - case 0x92: return {"res 2,d"}; - case 0x93: return {"res 2,e"}; - case 0x94: return {"res 2,h"}; - case 0x95: return {"res 2,l"}; - case 0x96: return {"res 2,(hl)"}; - case 0x97: return {"res 2,a"}; - case 0x98: return {"res 3,b"}; - case 0x99: return {"res 3,c"}; - case 0x9a: return {"res 3,d"}; - case 0x9b: return {"res 3,e"}; - case 0x9c: return {"res 3,h"}; - case 0x9d: return {"res 3,l"}; - case 0x9e: return {"res 3,(hl)"}; - case 0x9f: return {"res 3,a"}; - case 0xa0: return {"res 4,b"}; - case 0xa1: return {"res 4,c"}; - case 0xa2: return {"res 4,d"}; - case 0xa3: return {"res 4,e"}; - case 0xa4: return {"res 4,h"}; - case 0xa5: return {"res 4,l"}; - case 0xa6: return {"res 4,(hl)"}; - case 0xa7: return {"res 4,a"}; - case 0xa8: return {"res 5,b"}; - case 0xa9: return {"res 5,c"}; - case 0xaa: return {"res 5,d"}; - case 0xab: return {"res 5,e"}; - case 0xac: return {"res 5,h"}; - case 0xad: return {"res 5,l"}; - case 0xae: return {"res 5,(hl)"}; - case 0xaf: return {"res 5,a"}; - case 0xb0: return {"res 6,b"}; - case 0xb1: return {"res 6,c"}; - case 0xb2: return {"res 6,d"}; - case 0xb3: return {"res 6,e"}; - case 0xb4: return {"res 6,h"}; - case 0xb5: return {"res 6,l"}; - case 0xb6: return {"res 6,(hl)"}; - case 0xb7: return {"res 6,a"}; - case 0xb8: return {"res 7,b"}; - case 0xb9: return {"res 7,c"}; - case 0xba: return {"res 7,d"}; - case 0xbb: return {"res 7,e"}; - case 0xbc: return {"res 7,h"}; - case 0xbd: return {"res 7,l"}; - case 0xbe: return {"res 7,(hl)"}; - case 0xbf: return {"res 7,a"}; - case 0xc0: return {"set 0,b"}; - case 0xc1: return {"set 0,c"}; - case 0xc2: return {"set 0,d"}; - case 0xc3: return {"set 0,e"}; - case 0xc4: return {"set 0,h"}; - case 0xc5: return {"set 0,l"}; - case 0xc6: return {"set 0,(hl)"}; - case 0xc7: return {"set 0,a"}; - case 0xc8: return {"set 1,b"}; - case 0xc9: return {"set 1,c"}; - case 0xca: return {"set 1,d"}; - case 0xcb: return {"set 1,e"}; - case 0xcc: return {"set 1,h"}; - case 0xcd: return {"set 1,l"}; - case 0xce: return {"set 1,(hl)"}; - case 0xcf: return {"set 1,a"}; - case 0xd0: return {"set 2,b"}; - case 0xd1: return {"set 2,c"}; - case 0xd2: return {"set 2,d"}; - case 0xd3: return {"set 2,e"}; - case 0xd4: return {"set 2,h"}; - case 0xd5: return {"set 2,l"}; - case 0xd6: return {"set 2,(hl)"}; - case 0xd7: return {"set 2,a"}; - case 0xd8: return {"set 3,b"}; - case 0xd9: return {"set 3,c"}; - case 0xda: return {"set 3,d"}; - case 0xdb: return {"set 3,e"}; - case 0xdc: return {"set 3,h"}; - case 0xdd: return {"set 3,l"}; - case 0xde: return {"set 3,(hl)"}; - case 0xdf: return {"set 3,a"}; - case 0xe0: return {"set 4,b"}; - case 0xe1: return {"set 4,c"}; - case 0xe2: return {"set 4,d"}; - case 0xe3: return {"set 4,e"}; - case 0xe4: return {"set 4,h"}; - case 0xe5: return {"set 4,l"}; - case 0xe6: return {"set 4,(hl)"}; - case 0xe7: return {"set 4,a"}; - case 0xe8: return {"set 5,b"}; - case 0xe9: return {"set 5,c"}; - case 0xea: return {"set 5,d"}; - case 0xeb: return {"set 5,e"}; - case 0xec: return {"set 5,h"}; - case 0xed: return {"set 5,l"}; - case 0xee: return {"set 5,(hl)"}; - case 0xef: return {"set 5,a"}; - case 0xf0: return {"set 6,b"}; - case 0xf1: return {"set 6,c"}; - case 0xf2: return {"set 6,d"}; - case 0xf3: return {"set 6,e"}; - case 0xf4: return {"set 6,h"}; - case 0xf5: return {"set 6,l"}; - case 0xf6: return {"set 6,(hl)"}; - case 0xf7: return {"set 6,a"}; - case 0xf8: return {"set 7,b"}; - case 0xf9: return {"set 7,c"}; - case 0xfa: return {"set 7,d"}; - case 0xfb: return {"set 7,e"}; - case 0xfc: return {"set 7,h"}; - case 0xfd: return {"set 7,l"}; - case 0xfe: return {"set 7,(hl)"}; - case 0xff: return {"set 7,a"}; - } - - unreachable; -} diff --git a/higan/processor/lr35902-legacy/instruction.cpp b/higan/processor/lr35902-legacy/instruction.cpp deleted file mode 100644 index 7856eedf..00000000 --- a/higan/processor/lr35902-legacy/instruction.cpp +++ /dev/null @@ -1,531 +0,0 @@ -auto LR35902::interrupt(uint16 vector) -> void { - io(); - io(); - io(); - r.ime = 0; - write(--r[SP], r[PC] >> 8); - write(--r[SP], r[PC] >> 0); - r[PC] = vector; -} - -auto LR35902::instruction() -> void { - switch(auto opcode = read(r[PC]++)) { - case 0x00: return op_nop(); - case 0x01: return op_ld_rr_nn(BC); - case 0x02: return op_ld_rr_a(BC); - case 0x03: return op_inc_rr(BC); - case 0x04: return op_inc_r(B); - case 0x05: return op_dec_r(B); - case 0x06: return op_ld_r_n(B); - case 0x07: return op_rlca(); - case 0x08: return op_ld_nn_sp(); - case 0x09: return op_add_hl_rr(BC); - case 0x0a: return op_ld_a_rr(BC); - case 0x0b: return op_dec_rr(BC); - case 0x0c: return op_inc_r(C); - case 0x0d: return op_dec_r(C); - case 0x0e: return op_ld_r_n(C); - case 0x0f: return op_rrca(); - case 0x10: return op_stop(); - case 0x11: return op_ld_rr_nn(DE); - case 0x12: return op_ld_rr_a(DE); - case 0x13: return op_inc_rr(DE); - case 0x14: return op_inc_r(D); - case 0x15: return op_dec_r(D); - case 0x16: return op_ld_r_n(D); - case 0x17: return op_rla(); - case 0x18: return op_jr_n(); - case 0x19: return op_add_hl_rr(DE); - case 0x1a: return op_ld_a_rr(DE); - case 0x1b: return op_dec_rr(DE); - case 0x1c: return op_inc_r(E); - case 0x1d: return op_dec_r(E); - case 0x1e: return op_ld_r_n(E); - case 0x1f: return op_rra(); - case 0x20: return op_jr_f_n(ZF, 0); - case 0x21: return op_ld_rr_nn(HL); - case 0x22: return op_ldi_hl_a(); - case 0x23: return op_inc_rr(HL); - case 0x24: return op_inc_r(H); - case 0x25: return op_dec_r(H); - case 0x26: return op_ld_r_n(H); - case 0x27: return op_daa(); - case 0x28: return op_jr_f_n(ZF, 1); - case 0x29: return op_add_hl_rr(HL); - case 0x2a: return op_ldi_a_hl(); - case 0x2b: return op_dec_rr(HL); - case 0x2c: return op_inc_r(L); - case 0x2d: return op_dec_r(L); - case 0x2e: return op_ld_r_n(L); - case 0x2f: return op_cpl(); - case 0x30: return op_jr_f_n(CF, 0); - case 0x31: return op_ld_rr_nn(SP); - case 0x32: return op_ldd_hl_a(); - case 0x33: return op_inc_rr(SP); - case 0x34: return op_inc_hl(); - case 0x35: return op_dec_hl(); - case 0x36: return op_ld_hl_n(); - case 0x37: return op_scf(); - case 0x38: return op_jr_f_n(CF, 1); - case 0x39: return op_add_hl_rr(SP); - case 0x3a: return op_ldd_a_hl(); - case 0x3b: return op_dec_rr(SP); - case 0x3c: return op_inc_r(A); - case 0x3d: return op_dec_r(A); - case 0x3e: return op_ld_r_n(A); - case 0x3f: return op_ccf(); - case 0x40: return op_ld_r_r(B, B); - case 0x41: return op_ld_r_r(B, C); - case 0x42: return op_ld_r_r(B, D); - case 0x43: return op_ld_r_r(B, E); - case 0x44: return op_ld_r_r(B, H); - case 0x45: return op_ld_r_r(B, L); - case 0x46: return op_ld_r_hl(B); - case 0x47: return op_ld_r_r(B, A); - case 0x48: return op_ld_r_r(C, B); - case 0x49: return op_ld_r_r(C, C); - case 0x4a: return op_ld_r_r(C, D); - case 0x4b: return op_ld_r_r(C, E); - case 0x4c: return op_ld_r_r(C, H); - case 0x4d: return op_ld_r_r(C, L); - case 0x4e: return op_ld_r_hl(C); - case 0x4f: return op_ld_r_r(C, A); - case 0x50: return op_ld_r_r(D, B); - case 0x51: return op_ld_r_r(D, C); - case 0x52: return op_ld_r_r(D, D); - case 0x53: return op_ld_r_r(D, E); - case 0x54: return op_ld_r_r(D, H); - case 0x55: return op_ld_r_r(D, L); - case 0x56: return op_ld_r_hl(D); - case 0x57: return op_ld_r_r(D, A); - case 0x58: return op_ld_r_r(E, B); - case 0x59: return op_ld_r_r(E, C); - case 0x5a: return op_ld_r_r(E, D); - case 0x5b: return op_ld_r_r(E, E); - case 0x5c: return op_ld_r_r(E, H); - case 0x5d: return op_ld_r_r(E, L); - case 0x5e: return op_ld_r_hl(E); - case 0x5f: return op_ld_r_r(E, A); - case 0x60: return op_ld_r_r(H, B); - case 0x61: return op_ld_r_r(H, C); - case 0x62: return op_ld_r_r(H, D); - case 0x63: return op_ld_r_r(H, E); - case 0x64: return op_ld_r_r(H, H); - case 0x65: return op_ld_r_r(H, L); - case 0x66: return op_ld_r_hl(H); - case 0x67: return op_ld_r_r(H, A); - case 0x68: return op_ld_r_r(L, B); - case 0x69: return op_ld_r_r(L, C); - case 0x6a: return op_ld_r_r(L, D); - case 0x6b: return op_ld_r_r(L, E); - case 0x6c: return op_ld_r_r(L, H); - case 0x6d: return op_ld_r_r(L, L); - case 0x6e: return op_ld_r_hl(L); - case 0x6f: return op_ld_r_r(L, A); - case 0x70: return op_ld_hl_r(B); - case 0x71: return op_ld_hl_r(C); - case 0x72: return op_ld_hl_r(D); - case 0x73: return op_ld_hl_r(E); - case 0x74: return op_ld_hl_r(H); - case 0x75: return op_ld_hl_r(L); - case 0x76: return op_halt(); - case 0x77: return op_ld_hl_r(A); - case 0x78: return op_ld_r_r(A, B); - case 0x79: return op_ld_r_r(A, C); - case 0x7a: return op_ld_r_r(A, D); - case 0x7b: return op_ld_r_r(A, E); - case 0x7c: return op_ld_r_r(A, H); - case 0x7d: return op_ld_r_r(A, L); - case 0x7e: return op_ld_r_hl(A); - case 0x7f: return op_ld_r_r(A, A); - case 0x80: return op_add_a_r(B); - case 0x81: return op_add_a_r(C); - case 0x82: return op_add_a_r(D); - case 0x83: return op_add_a_r(E); - case 0x84: return op_add_a_r(H); - case 0x85: return op_add_a_r(L); - case 0x86: return op_add_a_hl(); - case 0x87: return op_add_a_r(A); - case 0x88: return op_adc_a_r(B); - case 0x89: return op_adc_a_r(C); - case 0x8a: return op_adc_a_r(D); - case 0x8b: return op_adc_a_r(E); - case 0x8c: return op_adc_a_r(H); - case 0x8d: return op_adc_a_r(L); - case 0x8e: return op_adc_a_hl(); - case 0x8f: return op_adc_a_r(A); - case 0x90: return op_sub_a_r(B); - case 0x91: return op_sub_a_r(C); - case 0x92: return op_sub_a_r(D); - case 0x93: return op_sub_a_r(E); - case 0x94: return op_sub_a_r(H); - case 0x95: return op_sub_a_r(L); - case 0x96: return op_sub_a_hl(); - case 0x97: return op_sub_a_r(A); - case 0x98: return op_sbc_a_r(B); - case 0x99: return op_sbc_a_r(C); - case 0x9a: return op_sbc_a_r(D); - case 0x9b: return op_sbc_a_r(E); - case 0x9c: return op_sbc_a_r(H); - case 0x9d: return op_sbc_a_r(L); - case 0x9e: return op_sbc_a_hl(); - case 0x9f: return op_sbc_a_r(A); - case 0xa0: return op_and_a_r(B); - case 0xa1: return op_and_a_r(C); - case 0xa2: return op_and_a_r(D); - case 0xa3: return op_and_a_r(E); - case 0xa4: return op_and_a_r(H); - case 0xa5: return op_and_a_r(L); - case 0xa6: return op_and_a_hl(); - case 0xa7: return op_and_a_r(A); - case 0xa8: return op_xor_a_r(B); - case 0xa9: return op_xor_a_r(C); - case 0xaa: return op_xor_a_r(D); - case 0xab: return op_xor_a_r(E); - case 0xac: return op_xor_a_r(H); - case 0xad: return op_xor_a_r(L); - case 0xae: return op_xor_a_hl(); - case 0xaf: return op_xor_a_r(A); - case 0xb0: return op_or_a_r(B); - case 0xb1: return op_or_a_r(C); - case 0xb2: return op_or_a_r(D); - case 0xb3: return op_or_a_r(E); - case 0xb4: return op_or_a_r(H); - case 0xb5: return op_or_a_r(L); - case 0xb6: return op_or_a_hl(); - case 0xb7: return op_or_a_r(A); - case 0xb8: return op_cp_a_r(B); - case 0xb9: return op_cp_a_r(C); - case 0xba: return op_cp_a_r(D); - case 0xbb: return op_cp_a_r(E); - case 0xbc: return op_cp_a_r(H); - case 0xbd: return op_cp_a_r(L); - case 0xbe: return op_cp_a_hl(); - case 0xbf: return op_cp_a_r(A); - case 0xc0: return op_ret_f(ZF, 0); - case 0xc1: return op_pop_rr(BC); - case 0xc2: return op_jp_f_nn(ZF, 0); - case 0xc3: return op_jp_nn(); - case 0xc4: return op_call_f_nn(ZF, 0); - case 0xc5: return op_push_rr(BC); - case 0xc6: return op_add_a_n(); - case 0xc7: return op_rst_n(0x00); - case 0xc8: return op_ret_f(ZF, 1); - case 0xc9: return op_ret(); - case 0xca: return op_jp_f_nn(ZF, 1); - case 0xcb: return op_cb(); - case 0xcc: return op_call_f_nn(ZF, 1); - case 0xcd: return op_call_nn(); - case 0xce: return op_adc_a_n(); - case 0xcf: return op_rst_n(0x08); - case 0xd0: return op_ret_f(CF, 0); - case 0xd1: return op_pop_rr(DE); - case 0xd2: return op_jp_f_nn(CF, 0); - case 0xd3: return op_xx(); - case 0xd4: return op_call_f_nn(CF, 0); - case 0xd5: return op_push_rr(DE); - case 0xd6: return op_sub_a_n(); - case 0xd7: return op_rst_n(0x10); - case 0xd8: return op_ret_f(CF, 1); - case 0xd9: return op_reti(); - case 0xda: return op_jp_f_nn(CF, 1); - case 0xdb: return op_xx(); - case 0xdc: return op_call_f_nn(CF, 1); - case 0xdd: return op_xx(); - case 0xde: return op_sbc_a_n(); - case 0xdf: return op_rst_n(0x18); - case 0xe0: return op_ld_ffn_a(); - case 0xe1: return op_pop_rr(HL); - case 0xe2: return op_ld_ffc_a(); - case 0xe3: return op_xx(); - case 0xe4: return op_xx(); - case 0xe5: return op_push_rr(HL); - case 0xe6: return op_and_a_n(); - case 0xe7: return op_rst_n(0x20); - case 0xe8: return op_add_sp_n(); - case 0xe9: return op_jp_hl(); - case 0xea: return op_ld_nn_a(); - case 0xeb: return op_xx(); - case 0xec: return op_xx(); - case 0xed: return op_xx(); - case 0xee: return op_xor_a_n(); - case 0xef: return op_rst_n(0x28); - case 0xf0: return op_ld_a_ffn(); - case 0xf1: return op_pop_rr(AF); - case 0xf2: return op_ld_a_ffc(); - case 0xf3: return op_di(); - case 0xf4: return op_xx(); - case 0xf5: return op_push_rr(AF); - case 0xf6: return op_or_a_n(); - case 0xf7: return op_rst_n(0x30); - case 0xf8: return op_ld_hl_sp_n(); - case 0xf9: return op_ld_sp_hl(); - case 0xfa: return op_ld_a_nn(); - case 0xfb: return op_ei(); - case 0xfc: return op_xx(); - case 0xfd: return op_xx(); - case 0xfe: return op_cp_a_n(); - case 0xff: return op_rst_n(0x38); - } -} - -auto LR35902::instructionCB() -> void { - switch(auto opcode = read(r[PC]++)) { - case 0x00: return op_rlc_r(B); - case 0x01: return op_rlc_r(C); - case 0x02: return op_rlc_r(D); - case 0x03: return op_rlc_r(E); - case 0x04: return op_rlc_r(H); - case 0x05: return op_rlc_r(L); - case 0x06: return op_rlc_hl(); - case 0x07: return op_rlc_r(A); - case 0x08: return op_rrc_r(B); - case 0x09: return op_rrc_r(C); - case 0x0a: return op_rrc_r(D); - case 0x0b: return op_rrc_r(E); - case 0x0c: return op_rrc_r(H); - case 0x0d: return op_rrc_r(L); - case 0x0e: return op_rrc_hl(); - case 0x0f: return op_rrc_r(A); - case 0x10: return op_rl_r(B); - case 0x11: return op_rl_r(C); - case 0x12: return op_rl_r(D); - case 0x13: return op_rl_r(E); - case 0x14: return op_rl_r(H); - case 0x15: return op_rl_r(L); - case 0x16: return op_rl_hl(); - case 0x17: return op_rl_r(A); - case 0x18: return op_rr_r(B); - case 0x19: return op_rr_r(C); - case 0x1a: return op_rr_r(D); - case 0x1b: return op_rr_r(E); - case 0x1c: return op_rr_r(H); - case 0x1d: return op_rr_r(L); - case 0x1e: return op_rr_hl(); - case 0x1f: return op_rr_r(A); - case 0x20: return op_sla_r(B); - case 0x21: return op_sla_r(C); - case 0x22: return op_sla_r(D); - case 0x23: return op_sla_r(E); - case 0x24: return op_sla_r(H); - case 0x25: return op_sla_r(L); - case 0x26: return op_sla_hl(); - case 0x27: return op_sla_r(A); - case 0x28: return op_sra_r(B); - case 0x29: return op_sra_r(C); - case 0x2a: return op_sra_r(D); - case 0x2b: return op_sra_r(E); - case 0x2c: return op_sra_r(H); - case 0x2d: return op_sra_r(L); - case 0x2e: return op_sra_hl(); - case 0x2f: return op_sra_r(A); - case 0x30: return op_swap_r(B); - case 0x31: return op_swap_r(C); - case 0x32: return op_swap_r(D); - case 0x33: return op_swap_r(E); - case 0x34: return op_swap_r(H); - case 0x35: return op_swap_r(L); - case 0x36: return op_swap_hl(); - case 0x37: return op_swap_r(A); - case 0x38: return op_srl_r(B); - case 0x39: return op_srl_r(C); - case 0x3a: return op_srl_r(D); - case 0x3b: return op_srl_r(E); - case 0x3c: return op_srl_r(H); - case 0x3d: return op_srl_r(L); - case 0x3e: return op_srl_hl(); - case 0x3f: return op_srl_r(A); - case 0x40: return op_bit_n_r(0, B); - case 0x41: return op_bit_n_r(0, C); - case 0x42: return op_bit_n_r(0, D); - case 0x43: return op_bit_n_r(0, E); - case 0x44: return op_bit_n_r(0, H); - case 0x45: return op_bit_n_r(0, L); - case 0x46: return op_bit_n_hl(0); - case 0x47: return op_bit_n_r(0, A); - case 0x48: return op_bit_n_r(1, B); - case 0x49: return op_bit_n_r(1, C); - case 0x4a: return op_bit_n_r(1, D); - case 0x4b: return op_bit_n_r(1, E); - case 0x4c: return op_bit_n_r(1, H); - case 0x4d: return op_bit_n_r(1, L); - case 0x4e: return op_bit_n_hl(1); - case 0x4f: return op_bit_n_r(1, A); - case 0x50: return op_bit_n_r(2, B); - case 0x51: return op_bit_n_r(2, C); - case 0x52: return op_bit_n_r(2, D); - case 0x53: return op_bit_n_r(2, E); - case 0x54: return op_bit_n_r(2, H); - case 0x55: return op_bit_n_r(2, L); - case 0x56: return op_bit_n_hl(2); - case 0x57: return op_bit_n_r(2, A); - case 0x58: return op_bit_n_r(3, B); - case 0x59: return op_bit_n_r(3, C); - case 0x5a: return op_bit_n_r(3, D); - case 0x5b: return op_bit_n_r(3, E); - case 0x5c: return op_bit_n_r(3, H); - case 0x5d: return op_bit_n_r(3, L); - case 0x5e: return op_bit_n_hl(3); - case 0x5f: return op_bit_n_r(3, A); - case 0x60: return op_bit_n_r(4, B); - case 0x61: return op_bit_n_r(4, C); - case 0x62: return op_bit_n_r(4, D); - case 0x63: return op_bit_n_r(4, E); - case 0x64: return op_bit_n_r(4, H); - case 0x65: return op_bit_n_r(4, L); - case 0x66: return op_bit_n_hl(4); - case 0x67: return op_bit_n_r(4, A); - case 0x68: return op_bit_n_r(5, B); - case 0x69: return op_bit_n_r(5, C); - case 0x6a: return op_bit_n_r(5, D); - case 0x6b: return op_bit_n_r(5, E); - case 0x6c: return op_bit_n_r(5, H); - case 0x6d: return op_bit_n_r(5, L); - case 0x6e: return op_bit_n_hl(5); - case 0x6f: return op_bit_n_r(5, A); - case 0x70: return op_bit_n_r(6, B); - case 0x71: return op_bit_n_r(6, C); - case 0x72: return op_bit_n_r(6, D); - case 0x73: return op_bit_n_r(6, E); - case 0x74: return op_bit_n_r(6, H); - case 0x75: return op_bit_n_r(6, L); - case 0x76: return op_bit_n_hl(6); - case 0x77: return op_bit_n_r(6, A); - case 0x78: return op_bit_n_r(7, B); - case 0x79: return op_bit_n_r(7, C); - case 0x7a: return op_bit_n_r(7, D); - case 0x7b: return op_bit_n_r(7, E); - case 0x7c: return op_bit_n_r(7, H); - case 0x7d: return op_bit_n_r(7, L); - case 0x7e: return op_bit_n_hl(7); - case 0x7f: return op_bit_n_r(7, A); - case 0x80: return op_res_n_r(0, B); - case 0x81: return op_res_n_r(0, C); - case 0x82: return op_res_n_r(0, D); - case 0x83: return op_res_n_r(0, E); - case 0x84: return op_res_n_r(0, H); - case 0x85: return op_res_n_r(0, L); - case 0x86: return op_res_n_hl(0); - case 0x87: return op_res_n_r(0, A); - case 0x88: return op_res_n_r(1, B); - case 0x89: return op_res_n_r(1, C); - case 0x8a: return op_res_n_r(1, D); - case 0x8b: return op_res_n_r(1, E); - case 0x8c: return op_res_n_r(1, H); - case 0x8d: return op_res_n_r(1, L); - case 0x8e: return op_res_n_hl(1); - case 0x8f: return op_res_n_r(1, A); - case 0x90: return op_res_n_r(2, B); - case 0x91: return op_res_n_r(2, C); - case 0x92: return op_res_n_r(2, D); - case 0x93: return op_res_n_r(2, E); - case 0x94: return op_res_n_r(2, H); - case 0x95: return op_res_n_r(2, L); - case 0x96: return op_res_n_hl(2); - case 0x97: return op_res_n_r(2, A); - case 0x98: return op_res_n_r(3, B); - case 0x99: return op_res_n_r(3, C); - case 0x9a: return op_res_n_r(3, D); - case 0x9b: return op_res_n_r(3, E); - case 0x9c: return op_res_n_r(3, H); - case 0x9d: return op_res_n_r(3, L); - case 0x9e: return op_res_n_hl(3); - case 0x9f: return op_res_n_r(3, A); - case 0xa0: return op_res_n_r(4, B); - case 0xa1: return op_res_n_r(4, C); - case 0xa2: return op_res_n_r(4, D); - case 0xa3: return op_res_n_r(4, E); - case 0xa4: return op_res_n_r(4, H); - case 0xa5: return op_res_n_r(4, L); - case 0xa6: return op_res_n_hl(4); - case 0xa7: return op_res_n_r(4, A); - case 0xa8: return op_res_n_r(5, B); - case 0xa9: return op_res_n_r(5, C); - case 0xaa: return op_res_n_r(5, D); - case 0xab: return op_res_n_r(5, E); - case 0xac: return op_res_n_r(5, H); - case 0xad: return op_res_n_r(5, L); - case 0xae: return op_res_n_hl(5); - case 0xaf: return op_res_n_r(5, A); - case 0xb0: return op_res_n_r(6, B); - case 0xb1: return op_res_n_r(6, C); - case 0xb2: return op_res_n_r(6, D); - case 0xb3: return op_res_n_r(6, E); - case 0xb4: return op_res_n_r(6, H); - case 0xb5: return op_res_n_r(6, L); - case 0xb6: return op_res_n_hl(6); - case 0xb7: return op_res_n_r(6, A); - case 0xb8: return op_res_n_r(7, B); - case 0xb9: return op_res_n_r(7, C); - case 0xba: return op_res_n_r(7, D); - case 0xbb: return op_res_n_r(7, E); - case 0xbc: return op_res_n_r(7, H); - case 0xbd: return op_res_n_r(7, L); - case 0xbe: return op_res_n_hl(7); - case 0xbf: return op_res_n_r(7, A); - case 0xc0: return op_set_n_r(0, B); - case 0xc1: return op_set_n_r(0, C); - case 0xc2: return op_set_n_r(0, D); - case 0xc3: return op_set_n_r(0, E); - case 0xc4: return op_set_n_r(0, H); - case 0xc5: return op_set_n_r(0, L); - case 0xc6: return op_set_n_hl(0); - case 0xc7: return op_set_n_r(0, A); - case 0xc8: return op_set_n_r(1, B); - case 0xc9: return op_set_n_r(1, C); - case 0xca: return op_set_n_r(1, D); - case 0xcb: return op_set_n_r(1, E); - case 0xcc: return op_set_n_r(1, H); - case 0xcd: return op_set_n_r(1, L); - case 0xce: return op_set_n_hl(1); - case 0xcf: return op_set_n_r(1, A); - case 0xd0: return op_set_n_r(2, B); - case 0xd1: return op_set_n_r(2, C); - case 0xd2: return op_set_n_r(2, D); - case 0xd3: return op_set_n_r(2, E); - case 0xd4: return op_set_n_r(2, H); - case 0xd5: return op_set_n_r(2, L); - case 0xd6: return op_set_n_hl(2); - case 0xd7: return op_set_n_r(2, A); - case 0xd8: return op_set_n_r(3, B); - case 0xd9: return op_set_n_r(3, C); - case 0xda: return op_set_n_r(3, D); - case 0xdb: return op_set_n_r(3, E); - case 0xdc: return op_set_n_r(3, H); - case 0xdd: return op_set_n_r(3, L); - case 0xde: return op_set_n_hl(3); - case 0xdf: return op_set_n_r(3, A); - case 0xe0: return op_set_n_r(4, B); - case 0xe1: return op_set_n_r(4, C); - case 0xe2: return op_set_n_r(4, D); - case 0xe3: return op_set_n_r(4, E); - case 0xe4: return op_set_n_r(4, H); - case 0xe5: return op_set_n_r(4, L); - case 0xe6: return op_set_n_hl(4); - case 0xe7: return op_set_n_r(4, A); - case 0xe8: return op_set_n_r(5, B); - case 0xe9: return op_set_n_r(5, C); - case 0xea: return op_set_n_r(5, D); - case 0xeb: return op_set_n_r(5, E); - case 0xec: return op_set_n_r(5, H); - case 0xed: return op_set_n_r(5, L); - case 0xee: return op_set_n_hl(5); - case 0xef: return op_set_n_r(5, A); - case 0xf0: return op_set_n_r(6, B); - case 0xf1: return op_set_n_r(6, C); - case 0xf2: return op_set_n_r(6, D); - case 0xf3: return op_set_n_r(6, E); - case 0xf4: return op_set_n_r(6, H); - case 0xf5: return op_set_n_r(6, L); - case 0xf6: return op_set_n_hl(6); - case 0xf7: return op_set_n_r(6, A); - case 0xf8: return op_set_n_r(7, B); - case 0xf9: return op_set_n_r(7, C); - case 0xfa: return op_set_n_r(7, D); - case 0xfb: return op_set_n_r(7, E); - case 0xfc: return op_set_n_r(7, H); - case 0xfd: return op_set_n_r(7, L); - case 0xfe: return op_set_n_hl(7); - case 0xff: return op_set_n_r(7, A); - } -} diff --git a/higan/processor/lr35902-legacy/instructions.cpp b/higan/processor/lr35902-legacy/instructions.cpp deleted file mode 100644 index 8f636218..00000000 --- a/higan/processor/lr35902-legacy/instructions.cpp +++ /dev/null @@ -1,668 +0,0 @@ -auto LR35902::op_xx() { -} - -auto LR35902::op_cb() { - instructionCB(); -} - -//8-bit load commands - -auto LR35902::op_ld_r_r(uint x, uint y) { - r[x] = r[y]; -} - -auto LR35902::op_ld_r_n(uint x) { - r[x] = read(r[PC]++); -} - -auto LR35902::op_ld_r_hl(uint x) { - r[x] = read(r[HL]); -} - -auto LR35902::op_ld_hl_r(uint x) { - write(r[HL], r[x]); -} - -auto LR35902::op_ld_hl_n() { - write(r[HL], read(r[PC]++)); -} - -auto LR35902::op_ld_a_rr(uint x) { - r[A] = read(r[x]); -} - -auto LR35902::op_ld_a_nn() { - uint8 lo = read(r[PC]++); - uint8 hi = read(r[PC]++); - r[A] = read((hi << 8) | (lo << 0)); -} - -auto LR35902::op_ld_rr_a(uint x) { - write(r[x], r[A]); -} - -auto LR35902::op_ld_nn_a() { - uint8 lo = read(r[PC]++); - uint8 hi = read(r[PC]++); - write((hi << 8) | (lo << 0), r[A]); -} - -auto LR35902::op_ld_a_ffn() { - r[A] = read(0xff00 + read(r[PC]++)); -} - -auto LR35902::op_ld_ffn_a() { - write(0xff00 + read(r[PC]++), r[A]); -} - -auto LR35902::op_ld_a_ffc() { - r[A] = read(0xff00 + r[C]); -} - -auto LR35902::op_ld_ffc_a() { - write(0xff00 + r[C], r[A]); -} - -auto LR35902::op_ldi_hl_a() { - write(r[HL], r[A]); - r[HL]++; -} - -auto LR35902::op_ldi_a_hl() { - r[A] = read(r[HL]); - r[HL]++; -} - -auto LR35902::op_ldd_hl_a() { - write(r[HL], r[A]); - r[HL]--; -} - -auto LR35902::op_ldd_a_hl() { - r[A] = read(r[HL]); - r[HL]--; -} - -//16-bit load commands - -auto LR35902::op_ld_rr_nn(uint x) { - r[x] = read(r[PC]++) << 0; - r[x] |= read(r[PC]++) << 8; -} - -auto LR35902::op_ld_nn_sp() { - uint16 addr = read(r[PC]++) << 0; - addr |= read(r[PC]++) << 8; - write(addr + 0, r[SP] >> 0); - write(addr + 1, r[SP] >> 8); -} - -auto LR35902::op_ld_sp_hl() { - r[SP] = r[HL]; - io(); -} - -auto LR35902::op_push_rr(uint x) { - io(); - write(--r[SP], r[x] >> 8); - write(--r[SP], r[x] >> 0); -} - -auto LR35902::op_pop_rr(uint x) { - r[x] = read(r[SP]++) << 0; - r[x] |= read(r[SP]++) << 8; -} - -//8-bit arithmetic commands - -auto LR35902::opi_add_a(uint8 x) { - uint16 rh = r[A] + x; - uint16 rl = (r[A] & 0x0f) + (x & 0x0f); - r[A] = rh; - r.f.z = (uint8)rh == 0; - r.f.n = 0; - r.f.h = rl > 0x0f; - r.f.c = rh > 0xff; -} - -auto LR35902::op_add_a_r(uint x) { opi_add_a(r[x]); } -auto LR35902::op_add_a_n() { opi_add_a(read(r[PC]++)); } -auto LR35902::op_add_a_hl() { opi_add_a(read(r[HL])); } - -auto LR35902::opi_adc_a(uint8 x) { - uint16 rh = r[A] + x + r.f.c; - uint16 rl = (r[A] & 0x0f) + (x & 0x0f) + r.f.c; - r[A] = rh; - r.f.z = (uint8)rh == 0; - r.f.n = 0; - r.f.h = rl > 0x0f; - r.f.c = rh > 0xff; -} - -auto LR35902::op_adc_a_r(uint x) { opi_adc_a(r[x]); } -auto LR35902::op_adc_a_n() { opi_adc_a(read(r[PC]++)); } -auto LR35902::op_adc_a_hl() { opi_adc_a(read(r[HL])); } - -auto LR35902::opi_sub_a(uint8 x) { - uint16 rh = r[A] - x; - uint16 rl = (r[A] & 0x0f) - (x & 0x0f); - r[A] = rh; - r.f.z = (uint8)rh == 0; - r.f.n = 1; - r.f.h = rl > 0x0f; - r.f.c = rh > 0xff; -} - -auto LR35902::op_sub_a_r(uint x) { opi_sub_a(r[x]); } -auto LR35902::op_sub_a_n() { opi_sub_a(read(r[PC]++)); } -auto LR35902::op_sub_a_hl() { opi_sub_a(read(r[HL])); } - -auto LR35902::opi_sbc_a(uint8 x) { - uint16 rh = r[A] - x - r.f.c; - uint16 rl = (r[A] & 0x0f) - (x & 0x0f) - r.f.c; - r[A] = rh; - r.f.z = (uint8)rh == 0; - r.f.n = 1; - r.f.h = rl > 0x0f; - r.f.c = rh > 0xff; -} - -auto LR35902::op_sbc_a_r(uint x) { opi_sbc_a(r[x]); } -auto LR35902::op_sbc_a_n() { opi_sbc_a(read(r[PC]++)); } -auto LR35902::op_sbc_a_hl() { opi_sbc_a(read(r[HL])); } - -auto LR35902::opi_and_a(uint8 x) { - r[A] &= x; - r.f.z = r[A] == 0; - r.f.n = 0; - r.f.h = 1; - r.f.c = 0; -} - -auto LR35902::op_and_a_r(uint x) { opi_and_a(r[x]); } -auto LR35902::op_and_a_n() { opi_and_a(read(r[PC]++)); } -auto LR35902::op_and_a_hl() { opi_and_a(read(r[HL])); } - -auto LR35902::opi_xor_a(uint8 x) { - r[A] ^= x; - r.f.z = r[A] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = 0; -} - -auto LR35902::op_xor_a_r(uint x) { opi_xor_a(r[x]); } -auto LR35902::op_xor_a_n() { opi_xor_a(read(r[PC]++)); } -auto LR35902::op_xor_a_hl() { opi_xor_a(read(r[HL])); } - -auto LR35902::opi_or_a(uint8 x) { - r[A] |= x; - r.f.z = r[A] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = 0; -} - -auto LR35902::op_or_a_r(uint x) { opi_or_a(r[x]); } -auto LR35902::op_or_a_n() { opi_or_a(read(r[PC]++)); } -auto LR35902::op_or_a_hl() { opi_or_a(read(r[HL])); } - -auto LR35902::opi_cp_a(uint8 x) { - uint16 rh = r[A] - x; - uint16 rl = (r[A] & 0x0f) - (x & 0x0f); - r.f.z = (uint8)rh == 0; - r.f.n = 1; - r.f.h = rl > 0x0f; - r.f.c = rh > 0xff; -} - -auto LR35902::op_cp_a_r(uint x) { opi_cp_a(r[x]); } -auto LR35902::op_cp_a_n() { opi_cp_a(read(r[PC]++)); } -auto LR35902::op_cp_a_hl() { opi_cp_a(read(r[HL])); } - -auto LR35902::op_inc_r(uint x) { - r[x]++; - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = (r[x] & 0x0f) == 0x00; -} - -auto LR35902::op_inc_hl() { - uint8 n = read(r[HL]); - write(r[HL], ++n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = (n & 0x0f) == 0x00; -} - -auto LR35902::op_dec_r(uint x) { - r[x]--; - r.f.z = r[x] == 0; - r.f.n = 1; - r.f.h = (r[x] & 0x0f) == 0x0f; -} - -auto LR35902::op_dec_hl() { - uint8 n = read(r[HL]); - write(r[HL], --n); - r.f.z = n == 0; - r.f.n = 1; - r.f.h = (n & 0x0f) == 0x0f; -} - -auto LR35902::op_daa() { - uint16 a = r[A]; - if(r.f.n == 0) { - if(r.f.h || (a & 0x0f) > 0x09) a += 0x06; - if(r.f.c || (a ) > 0x9f) a += 0x60; - } else { - if(r.f.h) { - a -= 0x06; - if(r.f.c == 0) a &= 0xff; - } - if(r.f.c) a -= 0x60; - } - r[A] = a; - r.f.z = r[A] == 0; - r.f.h = 0; - r.f.c |= a & 0x100; -} - -auto LR35902::op_cpl() { - r[A] ^= 0xff; - r.f.n = 1; - r.f.h = 1; -} - -//16-bit arithmetic commands - -auto LR35902::op_add_hl_rr(uint x) { - io(); - uint32 rb = (r[HL] + r[x]); - uint32 rn = (r[HL] & 0xfff) + (r[x] & 0xfff); - r[HL] = rb; - r.f.n = 0; - r.f.h = rn > 0x0fff; - r.f.c = rb > 0xffff; -} - -auto LR35902::op_inc_rr(uint x) { - io(); - r[x]++; -} - -auto LR35902::op_dec_rr(uint x) { - io(); - r[x]--; -} - -auto LR35902::op_add_sp_n() { - int n = (int8)read(r[PC]++); - r.f.z = 0; - r.f.n = 0; - r.f.h = ((r[SP] & 0x0f) + (n & 0x0f)) > 0x0f; - r.f.c = ((r[SP] & 0xff) + (n & 0xff)) > 0xff; - r[SP] += n; - io(); - io(); -} - -auto LR35902::op_ld_hl_sp_n() { - int n = (int8)read(r[PC]++); - r.f.z = 0; - r.f.n = 0; - r.f.h = ((r[SP] & 0x0f) + (n & 0x0f)) > 0x0f; - r.f.c = ((r[SP] & 0xff) + (n & 0xff)) > 0xff; - r[HL] = r[SP] + n; - io(); -} - -//rotate/shift commands - -auto LR35902::op_rlca() { - r[A] = (r[A] << 1) | (r[A] >> 7); - r.f.z = 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = r[A] & 0x01; -} - -auto LR35902::op_rla() { - bool c = r[A] & 0x80; - r[A] = (r[A] << 1) | (r.f.c << 0); - r.f.z = 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -auto LR35902::op_rrca() { - r[A] = (r[A] >> 1) | (r[A] << 7); - r.f.z = 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = r[A] & 0x80; -} - -auto LR35902::op_rra() { - bool c = r[A] & 0x01; - r[A] = (r[A] >> 1) | (r.f.c << 7); - r.f.z = 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -auto LR35902::op_rlc_r(uint x) { - r[x] = (r[x] << 1) | (r[x] >> 7); - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = r[x] & 0x01; -} - -auto LR35902::op_rlc_hl() { - uint8 n = read(r[HL]); - n = (n << 1) | (n >> 7); - write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = n & 0x01; -} - -auto LR35902::op_rl_r(uint x) { - bool c = r[x] & 0x80; - r[x] = (r[x] << 1) | (r.f.c << 0); - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -auto LR35902::op_rl_hl() { - uint8 n = read(r[HL]); - bool c = n & 0x80; - n = (n << 1) | (r.f.c << 0); - write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -auto LR35902::op_rrc_r(uint x) { - r[x] = (r[x] >> 1) | (r[x] << 7); - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = r[x] & 0x80; -} - -auto LR35902::op_rrc_hl() { - uint8 n = read(r[HL]); - n = (n >> 1) | (n << 7); - write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = n & 0x80; -} - -auto LR35902::op_rr_r(uint x) { - bool c = r[x] & 0x01; - r[x] = (r[x] >> 1) | (r.f.c << 7); - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -auto LR35902::op_rr_hl() { - uint8 n = read(r[HL]); - bool c = n & 0x01; - n = (n >> 1) | (r.f.c << 7); - write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -auto LR35902::op_sla_r(uint x) { - bool c = r[x] & 0x80; - r[x] <<= 1; - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -auto LR35902::op_sla_hl() { - uint8 n = read(r[HL]); - bool c = n & 0x80; - n <<= 1; - write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -auto LR35902::op_swap_r(uint x) { - r[x] = (r[x] << 4) | (r[x] >> 4); - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = 0; -} - -auto LR35902::op_swap_hl() { - uint8 n = read(r[HL]); - n = (n << 4) | (n >> 4); - write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = 0; -} - -auto LR35902::op_sra_r(uint x) { - bool c = r[x] & 0x01; - r[x] = (int8)r[x] >> 1; - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -auto LR35902::op_sra_hl() { - uint8 n = read(r[HL]); - bool c = n & 0x01; - n = (int8)n >> 1; - write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -auto LR35902::op_srl_r(uint x) { - bool c = r[x] & 0x01; - r[x] >>= 1; - r.f.z = r[x] == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -auto LR35902::op_srl_hl() { - uint8 n = read(r[HL]); - bool c = n & 0x01; - n >>= 1; - write(r[HL], n); - r.f.z = n == 0; - r.f.n = 0; - r.f.h = 0; - r.f.c = c; -} - -//single-bit commands - -auto LR35902::op_bit_n_r(uint b, uint x) { - r.f.z = (r[x] & (1 << b)) == 0; - r.f.n = 0; - r.f.h = 1; -} - -auto LR35902::op_bit_n_hl(uint b) { - uint8 n = read(r[HL]); - r.f.z = (n & (1 << b)) == 0; - r.f.n = 0; - r.f.h = 1; -} - -auto LR35902::op_set_n_r(uint b, uint x) { - r[x] |= 1 << b; -} - -auto LR35902::op_set_n_hl(uint b) { - uint8 n = read(r[HL]); - n |= 1 << b; - write(r[HL], n); -} - -auto LR35902::op_res_n_r(uint b, uint x) { - r[x] &= ~(1 << b); -} - -auto LR35902::op_res_n_hl(uint b) { - uint n = read(r[HL]); - n &= ~(1 << b); - write(r[HL], n); -} - -//control commands - -auto LR35902::op_ccf() { - r.f.n = 0; - r.f.h = 0; - r.f.c = !r.f.c; -} - -auto LR35902::op_scf() { - r.f.n = 0; - r.f.h = 0; - r.f.c = 1; -} - -auto LR35902::op_nop() { -} - -auto LR35902::op_halt() { - r.halt = true; - while(r.halt) io(); -} - -auto LR35902::op_stop() { - if(stop()) return; - r.stop = true; - while(r.stop) io(); -} - -auto LR35902::op_di() { - r.ime = 0; -} - -auto LR35902::op_ei() { - r.ei = true; -//r.ime = 1; -} - -//jump commands - -auto LR35902::op_jp_nn() { - uint8 lo = read(r[PC]++); - uint8 hi = read(r[PC]++); - r[PC] = (hi << 8) | (lo << 0); - io(); -} - -auto LR35902::op_jp_hl() { - r[PC] = r[HL]; -} - -auto LR35902::op_jp_f_nn(uint x, bool y) { - uint8 lo = read(r[PC]++); - uint8 hi = read(r[PC]++); - if(r.f[x] == y) { - r[PC] = (hi << 8) | (lo << 0); - io(); - } -} - -auto LR35902::op_jr_n() { - int8 n = read(r[PC]++); - r[PC] += n; - io(); -} - -auto LR35902::op_jr_f_n(uint x, bool y) { - int8 n = read(r[PC]++); - if(r.f[x] == y) { - r[PC] += n; - io(); - } -} - -auto LR35902::op_call_nn() { - uint8 lo = read(r[PC]++); - uint8 hi = read(r[PC]++); - io(); - write(--r[SP], r[PC] >> 8); - write(--r[SP], r[PC] >> 0); - r[PC] = (hi << 8) | (lo << 0); -} - -auto LR35902::op_call_f_nn(uint x, bool y) { - uint8 lo = read(r[PC]++); - uint8 hi = read(r[PC]++); - if(r.f[x] == y) { - io(); - write(--r[SP], r[PC] >> 8); - write(--r[SP], r[PC] >> 0); - r[PC] = (hi << 8) | (lo << 0); - } -} - -auto LR35902::op_ret() { - uint8 lo = read(r[SP]++); - uint8 hi = read(r[SP]++); - r[PC] = (hi << 8) | (lo << 0); - io(); -} - -auto LR35902::op_ret_f(uint x, bool y) { - io(); - if(r.f[x] == y) { - uint8 lo = read(r[SP]++); - uint8 hi = read(r[SP]++); - r[PC] = (hi << 8) | (lo << 0); - io(); - } -} - -auto LR35902::op_reti() { - uint8 lo = read(r[SP]++); - uint8 hi = read(r[SP]++); - r[PC] = (hi << 8) | (lo << 0); - io(); - r.ime = 1; -} - -auto LR35902::op_rst_n(uint n) { - io(); - write(--r[SP], r[PC] >> 8); - write(--r[SP], r[PC] >> 0); - r[PC] = n; -} diff --git a/higan/processor/lr35902-legacy/lr35902.cpp b/higan/processor/lr35902-legacy/lr35902.cpp deleted file mode 100644 index c37e705c..00000000 --- a/higan/processor/lr35902-legacy/lr35902.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include "lr35902.hpp" - -namespace Processor { - -#include "instructions.cpp" -#include "instruction.cpp" -#include "serialization.cpp" -#include "disassembler.cpp" - -auto LR35902::power() -> void { - r[AF] = 0x0000; - r[BC] = 0x0000; - r[DE] = 0x0000; - r[HL] = 0x0000; - r[SP] = 0x0000; - r[PC] = 0x0000; - - r.halt = false; - r.stop = false; - r.ei = false; - r.ime = false; -} - -} diff --git a/higan/processor/lr35902-legacy/lr35902.hpp b/higan/processor/lr35902-legacy/lr35902.hpp deleted file mode 100644 index 0535d1ef..00000000 --- a/higan/processor/lr35902-legacy/lr35902.hpp +++ /dev/null @@ -1,174 +0,0 @@ -//Sharp LR35902 (Game Boy Z80-derivative) - -#pragma once - -namespace Processor { - -struct LR35902 { - virtual auto idle() -> void = 0; - virtual auto read(uint16 addr) -> uint8 = 0; - virtual auto write(uint16 addr, uint8 data) -> void = 0; - virtual auto stop() -> bool = 0; - - auto io() -> void { idle(); } - - //lr35902.cpp - auto power() -> void; - - //instruction.cpp - auto interrupt(uint16 vector) -> void; - auto instruction() -> void; - auto instructionCB() -> void; - - //serialization.cpp - auto serialize(serializer&) -> void; - - //disassembler.cpp - virtual auto readDebugger(uint16 addr) -> uint8 { return 0; } - auto disassemble(uint16 pc) -> string; - - #include "registers.hpp" - -private: - auto op_xx(); - auto op_cb(); - - //8-bit load commands - auto op_ld_r_r(uint x, uint y); - auto op_ld_r_n(uint x); - auto op_ld_r_hl(uint x); - auto op_ld_hl_r(uint x); - auto op_ld_hl_n(); - auto op_ld_a_rr(uint x); - auto op_ld_a_nn(); - auto op_ld_rr_a(uint x); - auto op_ld_nn_a(); - auto op_ld_a_ffn(); - auto op_ld_ffn_a(); - auto op_ld_a_ffc(); - auto op_ld_ffc_a(); - auto op_ldi_hl_a(); - auto op_ldi_a_hl(); - auto op_ldd_hl_a(); - auto op_ldd_a_hl(); - - //16-bit load commands - auto op_ld_rr_nn(uint x); - auto op_ld_nn_sp(); - auto op_ld_sp_hl(); - auto op_push_rr(uint x); - auto op_pop_rr(uint x); - - //8-bit arithmetic commands - auto opi_add_a(uint8 x); - auto op_add_a_r(uint x); - auto op_add_a_n(); - auto op_add_a_hl(); - - auto opi_adc_a(uint8 x); - auto op_adc_a_r(uint x); - auto op_adc_a_n(); - auto op_adc_a_hl(); - - auto opi_sub_a(uint8 x); - auto op_sub_a_r(uint x); - auto op_sub_a_n(); - auto op_sub_a_hl(); - - auto opi_sbc_a(uint8 x); - auto op_sbc_a_r(uint x); - auto op_sbc_a_n(); - auto op_sbc_a_hl(); - - auto opi_and_a(uint8 x); - auto op_and_a_r(uint x); - auto op_and_a_n(); - auto op_and_a_hl(); - - auto opi_xor_a(uint8 x); - auto op_xor_a_r(uint x); - auto op_xor_a_n(); - auto op_xor_a_hl(); - - auto opi_or_a(uint8 x); - auto op_or_a_r(uint x); - auto op_or_a_n(); - auto op_or_a_hl(); - - auto opi_cp_a(uint8 x); - auto op_cp_a_r(uint x); - auto op_cp_a_n(); - auto op_cp_a_hl(); - - auto op_inc_r(uint x); - auto op_inc_hl(); - auto op_dec_r(uint x); - auto op_dec_hl(); - auto op_daa(); - auto op_cpl(); - - //16-bit arithmetic commands - auto op_add_hl_rr(uint x); - auto op_inc_rr(uint x); - auto op_dec_rr(uint x); - auto op_add_sp_n(); - auto op_ld_hl_sp_n(); - - //rotate/shift commands - auto op_rlca(); - auto op_rla(); - auto op_rrca(); - auto op_rra(); - auto op_rlc_r(uint x); - auto op_rlc_hl(); - auto op_rl_r(uint x); - auto op_rl_hl(); - auto op_rrc_r(uint x); - auto op_rrc_hl(); - auto op_rr_r(uint x); - auto op_rr_hl(); - auto op_sla_r(uint x); - auto op_sla_hl(); - auto op_swap_r(uint x); - auto op_swap_hl(); - auto op_sra_r(uint x); - auto op_sra_hl(); - auto op_srl_r(uint x); - auto op_srl_hl(); - - //single-bit commands - auto op_bit_n_r(uint b, uint x); - auto op_bit_n_hl(uint b); - auto op_set_n_r(uint b, uint x); - auto op_set_n_hl(uint b); - auto op_res_n_r(uint b, uint x); - auto op_res_n_hl(uint b); - - //control commands - auto op_ccf(); - auto op_scf(); - auto op_nop(); - auto op_halt(); - auto op_stop(); - auto op_di(); - auto op_ei(); - - //jump commands - auto op_jp_nn(); - auto op_jp_hl(); - auto op_jp_f_nn(uint x, bool y); - auto op_jr_n(); - auto op_jr_f_n(uint x, bool y); - auto op_call_nn(); - auto op_call_f_nn(uint x, bool y); - auto op_ret(); - auto op_ret_f(uint x, bool y); - auto op_reti(); - auto op_rst_n(uint n); - - //disassembler.cpp - auto disassembleOpcode(uint16 pc) -> string; - auto disassembleOpcodeCB(uint16 pc) -> string; -}; - -} diff --git a/higan/processor/lr35902-legacy/registers.hpp b/higan/processor/lr35902-legacy/registers.hpp deleted file mode 100644 index 785ce77b..00000000 --- a/higan/processor/lr35902-legacy/registers.hpp +++ /dev/null @@ -1,107 +0,0 @@ -enum { - A, F, AF, - B, C, BC, - D, E, DE, - H, L, HL, - SP, PC, -}; - -enum { - ZF, NF, HF, CF, -}; - -//register base class -//the idea here is to have all registers derive from a single base class. -//this allows construction of opcodes that can take any register as input or output, -//despite the fact that behind-the-scenes, special handling is done for eg: F, AF, HL, etc. -//registers can also be chained together: eg af = 0x0000 writes both a and f. -struct Register { - virtual operator uint() const = 0; - virtual auto operator=(uint x) -> uint = 0; - auto operator=(const Register& x) -> Register& { operator=((uint)x); return *this; } - - auto operator++(int) -> uint { uint r = *this; operator=(*this + 1); return r; } - auto operator--(int) -> uint { uint r = *this; operator=(*this - 1); return r; } - auto operator++() -> uint { return operator=(*this + 1); } - auto operator--() -> uint { return operator=(*this - 1); } - - auto operator |=(uint x) -> uint { return operator=(*this | x); } - auto operator ^=(uint x) -> uint { return operator=(*this ^ x); } - auto operator &=(uint x) -> uint { return operator=(*this & x); } - - auto operator<<=(uint x) -> uint { return operator=(*this << x); } - auto operator>>=(uint x) -> uint { return operator=(*this >> x); } - - auto operator +=(uint x) -> uint { return operator=(*this + x); } - auto operator -=(uint x) -> uint { return operator=(*this - x); } - auto operator *=(uint x) -> uint { return operator=(*this * x); } - auto operator /=(uint x) -> uint { return operator=(*this / x); } - auto operator %=(uint x) -> uint { return operator=(*this % x); } -}; - -struct Register8 : Register { - uint8 data; - operator uint() const { return data; } - auto operator=(uint x) -> uint { return data = x; } -}; - -struct RegisterF : Register { - bool z, n, h, c; - operator uint() const { return (z << 7) | (n << 6) | (h << 5) | (c << 4); } - auto operator=(uint x) -> uint { z = x & 0x80; n = x & 0x40; h = x & 0x20; c = x & 0x10; return *this; } - bool& operator[](uint r) { - static bool* table[] = {&z, &n, &h, &c}; - return *table[r]; - } -}; - -struct Register16 : Register { - uint16 data; - operator uint() const { return data; } - auto operator=(uint x) -> uint { return data = x; } -}; - -struct RegisterAF : Register { - Register8& hi; - RegisterF& lo; - operator uint() const { return (hi << 8) | (lo << 0); } - auto operator=(uint x) -> uint { hi = x >> 8; lo = x >> 0; return *this; } - RegisterAF(Register8& hi, RegisterF& lo) : hi(hi), lo(lo) {} -}; - -struct RegisterW : Register { - Register8& hi; - Register8& lo; - operator uint() const { return (hi << 8) | (lo << 0); } - auto operator=(uint x) -> uint { hi = x >> 8; lo = x >> 0; return *this; } - RegisterW(Register8& hi, Register8& lo) : hi(hi), lo(lo) {} -}; - -struct Registers { - Register8 a; - RegisterF f; - RegisterAF af; - Register8 b; - Register8 c; - RegisterW bc; - Register8 d; - Register8 e; - RegisterW de; - Register8 h; - Register8 l; - RegisterW hl; - Register16 sp; - Register16 pc; - - bool halt; - bool stop; - bool ei; - bool ime; - - auto operator[](uint r) -> Register& { - static Register* const table[] = {&a, &f, &af, &b, &c, &bc, &d, &e, &de, &h, &l, &hl, &sp, &pc}; - return *table[r]; - } - - Registers() : af(a, f), bc(b, c), de(d, e), hl(h, l) {} -} r; diff --git a/higan/processor/lr35902-legacy/serialization.cpp b/higan/processor/lr35902-legacy/serialization.cpp deleted file mode 100644 index 63beee28..00000000 --- a/higan/processor/lr35902-legacy/serialization.cpp +++ /dev/null @@ -1,20 +0,0 @@ -auto LR35902::serialize(serializer& s) -> void { - s.integer(r.a.data); - s.integer(r.f.z); - s.integer(r.f.n); - s.integer(r.f.h); - s.integer(r.f.c); - s.integer(r.b.data); - s.integer(r.c.data); - s.integer(r.d.data); - s.integer(r.e.data); - s.integer(r.h.data); - s.integer(r.l.data); - s.integer(r.sp.data); - s.integer(r.pc.data); - - s.integer(r.halt); - s.integer(r.stop); - s.integer(r.ei); - s.integer(r.ime); -} diff --git a/higan/sfc/coprocessor/armdsp/armdsp.hpp b/higan/sfc/coprocessor/armdsp/armdsp.hpp index 8786caed..b5cbd6c0 100644 --- a/higan/sfc/coprocessor/armdsp/armdsp.hpp +++ b/higan/sfc/coprocessor/armdsp/armdsp.hpp @@ -11,9 +11,9 @@ struct ArmDSP : Processor::ARM, Thread { auto main() -> void; auto step(uint clocks) -> void override; - auto _idle() -> void override; - auto _read(uint mode, uint32 addr) -> uint32 override; - auto _write(uint mode, uint32 addr, uint32 word) -> void override; + auto sleep() -> void override; + auto get(uint mode, uint32 addr) -> uint32 override; + auto set(uint mode, uint32 addr, uint32 word) -> void override; auto read(uint24 addr, uint8 data) -> uint8; auto write(uint24 addr, uint8 data) -> void; diff --git a/higan/sfc/coprocessor/armdsp/memory.cpp b/higan/sfc/coprocessor/armdsp/memory.cpp index ceb0d4ee..48e237f8 100644 --- a/higan/sfc/coprocessor/armdsp/memory.cpp +++ b/higan/sfc/coprocessor/armdsp/memory.cpp @@ -1,11 +1,11 @@ //note: timings are completely unverified //due to the ST018 chip design (on-die ROM), testing is nearly impossible -auto ArmDSP::_idle() -> void { +auto ArmDSP::sleep() -> void { step(1); } -auto ArmDSP::_read(uint mode, uint32 addr) -> uint32 { +auto ArmDSP::get(uint mode, uint32 addr) -> uint32 { step(1); static auto memory = [&](const uint8* memory, uint mode, uint32 addr) -> uint32 { @@ -46,7 +46,7 @@ auto ArmDSP::_read(uint mode, uint32 addr) -> uint32 { return 0; } -auto ArmDSP::_write(uint mode, uint32 addr, uint32 word) -> void { +auto ArmDSP::set(uint mode, uint32 addr, uint32 word) -> void { step(1); static auto memory = [](uint8* memory, uint mode, uint32 addr, uint32 word) { diff --git a/hiro/windows/hiro.Manifest b/hiro/windows/hiro.Manifest index a7e39c8d..5f6ac40d 100644 --- a/hiro/windows/hiro.Manifest +++ b/hiro/windows/hiro.Manifest @@ -8,7 +8,7 @@ - true + false diff --git a/icarus/icarus.plist b/icarus/icarus.plist index 5caaab81..67833d77 100644 --- a/icarus/icarus.plist +++ b/icarus/icarus.plist @@ -13,7 +13,7 @@ icarus.icns --> NSHighResolutionCapable - + NSSupportsAutomaticGraphicsSwitching diff --git a/ruby/video/cgl.cpp b/ruby/video/cgl.cpp index c6b63c8b..d7f705b7 100644 --- a/ruby/video/cgl.cpp +++ b/ruby/video/cgl.cpp @@ -78,7 +78,7 @@ struct VideoCGL : Video, OpenGL { if(!ready()) return; @autoreleasepool { if([view lockFocusIfCanDraw]) { - auto area = [view frame]; + auto area = [view convertRectToBacking:[view bounds]]; OpenGL::outputWidth = area.size.width; OpenGL::outputHeight = area.size.height; OpenGL::output(); @@ -110,6 +110,7 @@ private: [view setOpenGLContext:context]; [view setFrame:NSMakeRect(0, 0, size.width, size.height)]; [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + [view setWantsBestResolutionOpenGLSurface:YES]; [_context addSubview:view]; [context setView:view];