From 37b610da53e22e5df8fe66adc40cc46cd50f6a19 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sat, 19 Jan 2019 12:34:17 +1100 Subject: [PATCH] Update to v106r83 release. byuu says: Changelog: - reverted nall/inline-if.hpp usage for now, since the nall/primitives.hpp math operators still cast to (u)int64_t - improved nall/primitives.hpp more; integer8 x = -128; print(-x) will now print 128 (unary operator+ and - cast to (u)int64_t) - renamed processor/lr35902 to processor/sm83; after the Sharp SM83 CPU core [gekkio discovered the name] - a few bugfixes to the TLCS900H CPU core - completed the disassembler for the TLCS900H core As a result of reverting most of the inline if stuff, I guess the testing priority has been reduced. Which is probably a good thing, considering I seem to have a smaller pool of testers these days. Indeed, the TLCS900H core has ended up at 131KiB compared to the M68000 core at 128KiB. So it's now the largest CPU core in all of higan. It's even more ridiculous because the M68000 core would ordinarily be quite a bit smaller, had I not gone overboard with the extreme templating to reduce instruction decoding overhead (you kind of have to do this for RISC CPUs, and the inverted design of the TLCS900H kind of makes it infeasible to do the same there.) This CPU core is bound to have dozens of extremely difficult CPU bugs, and there's no easy way for me to test them. I would greatly appreciate any help in looking over the core for bugs. A fresh pair of eyes to spot a mistake could save me up to several days of tedious debugging work. The core still isn't ready to actually be tested: I have to hook up cartridge loading, a memory bus, interrupts, timers, and the micro DMA controller before it's likely that anything happens at all. --- higan/emulator/emulator.hpp | 2 +- higan/gb/GNUmakefile | 2 +- higan/gb/cpu/cpu.cpp | 2 +- higan/gb/cpu/cpu.hpp | 2 +- higan/gb/cpu/serialization.cpp | 2 +- higan/gb/gb.hpp | 2 +- higan/gba/ppu/background.cpp | 4 +- higan/gba/ppu/object.cpp | 2 +- higan/gba/ppu/ppu.cpp | 1 - higan/md/vdp/background.cpp | 2 +- higan/md/vdp/vdp.cpp | 1 - higan/md/ym2612/channel.cpp | 4 +- higan/md/ym2612/ym2612.cpp | 3 +- higan/processor/GNUmakefile | 4 +- higan/processor/arm7tdmi/algorithms.cpp | 12 +- higan/processor/arm7tdmi/arm7tdmi.cpp | 1 - higan/processor/lr35902/instructions.cpp | 462 ---------- .../{lr35902 => sm83}/algorithms.cpp | 34 +- .../{lr35902 => sm83}/disassembler.cpp | 6 +- .../{lr35902 => sm83}/instruction.cpp | 6 +- higan/processor/sm83/instructions.cpp | 462 ++++++++++ higan/processor/{lr35902 => sm83}/memory.cpp | 12 +- .../processor/{lr35902 => sm83}/registers.cpp | 0 .../{lr35902 => sm83}/serialization.cpp | 2 +- .../{lr35902/lr35902.cpp => sm83/sm83.cpp} | 4 +- .../{lr35902/lr35902.hpp => sm83/sm83.hpp} | 8 +- higan/processor/spc700/instructions.cpp | 2 +- higan/processor/spc700/spc700.cpp | 1 - higan/processor/tlcs900h/disassembler.cpp | 802 ++++++++++++------ higan/processor/tlcs900h/instruction.cpp | 12 +- higan/processor/tlcs900h/instructions.cpp | 26 +- higan/processor/tlcs900h/tlcs900h.cpp | 1 - higan/processor/tlcs900h/tlcs900h.hpp | 7 +- higan/sfc/coprocessor/spc7110/dcu.cpp | 2 +- higan/sfc/coprocessor/spc7110/spc7110.cpp | 1 - higan/sfc/ppu-fast/background.cpp | 2 +- higan/sfc/ppu-fast/mode7.cpp | 4 +- higan/sfc/ppu-fast/ppu.cpp | 1 - nall/array.hpp | 18 + nall/inline-if.hpp | 1 + nall/primitives.hpp | 8 +- nall/primitives/bit-range.hpp | 26 +- nall/primitives/integer.hpp | 54 +- nall/primitives/natural.hpp | 89 +- nall/primitives/real.hpp | 18 +- nall/primitives/types.hpp | 6 +- nall/string/cast.hpp | 4 +- nall/traits.hpp | 1 + 48 files changed, 1213 insertions(+), 915 deletions(-) delete mode 100644 higan/processor/lr35902/instructions.cpp rename higan/processor/{lr35902 => sm83}/algorithms.cpp (69%) rename higan/processor/{lr35902 => sm83}/disassembler.cpp (99%) rename higan/processor/{lr35902 => sm83}/instruction.cpp (98%) create mode 100644 higan/processor/sm83/instructions.cpp rename higan/processor/{lr35902 => sm83}/memory.cpp (58%) rename higan/processor/{lr35902 => sm83}/registers.cpp (100%) rename higan/processor/{lr35902 => sm83}/serialization.cpp (82%) rename higan/processor/{lr35902/lr35902.cpp => sm83/sm83.cpp} (82%) rename higan/processor/{lr35902/lr35902.hpp => sm83/sm83.hpp} (96%) diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 00223575..dd3357aa 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -30,7 +30,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "106.82"; + static const string Version = "106.83"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/higan/gb/GNUmakefile b/higan/gb/GNUmakefile index 378853bc..652e17a3 100644 --- a/higan/gb/GNUmakefile +++ b/higan/gb/GNUmakefile @@ -1,4 +1,4 @@ -processors += lr35902 +processors += sm83 objects += gb-interface gb-system objects += gb-memory gb-cartridge diff --git a/higan/gb/cpu/cpu.cpp b/higan/gb/cpu/cpu.cpp index 7af4f813..bc1d96e3 100644 --- a/higan/gb/cpu/cpu.cpp +++ b/higan/gb/cpu/cpu.cpp @@ -86,7 +86,7 @@ auto CPU::stop() -> bool { auto CPU::power() -> void { create(Enter, 4 * 1024 * 1024); - LR35902::power(); + SM83::power(); for(uint n = 0xc000; n <= 0xdfff; n++) bus.mmio[n] = this; //WRAM for(uint n = 0xe000; n <= 0xfdff; n++) bus.mmio[n] = this; //WRAM (mirror) diff --git a/higan/gb/cpu/cpu.hpp b/higan/gb/cpu/cpu.hpp index 8c0e499e..76cdb349 100644 --- a/higan/gb/cpu/cpu.hpp +++ b/higan/gb/cpu/cpu.hpp @@ -1,4 +1,4 @@ -struct CPU : Processor::LR35902, Thread, MMIO { +struct CPU : Processor::SM83, Thread, MMIO { enum class Interrupt : uint { Vblank, Stat, Timer, Serial, Joypad }; static auto Enter() -> void; diff --git a/higan/gb/cpu/serialization.cpp b/higan/gb/cpu/serialization.cpp index c15bd527..17fc7767 100644 --- a/higan/gb/cpu/serialization.cpp +++ b/higan/gb/cpu/serialization.cpp @@ -1,5 +1,5 @@ auto CPU::serialize(serializer& s) -> void { - LR35902::serialize(s); + SM83::serialize(s); Thread::serialize(s); s.array(wram); diff --git a/higan/gb/gb.hpp b/higan/gb/gb.hpp index c0ba694b..35eb3253 100644 --- a/higan/gb/gb.hpp +++ b/higan/gb/gb.hpp @@ -8,7 +8,7 @@ #include #include -#include +#include namespace GameBoy { #define platform Emulator::platform diff --git a/higan/gba/ppu/background.cpp b/higan/gba/ppu/background.cpp index caa14c51..06afbe82 100644 --- a/higan/gba/ppu/background.cpp +++ b/higan/gba/ppu/background.cpp @@ -104,7 +104,7 @@ auto PPU::Background::affine(uint x, uint y) -> void { } uint screenSize = 16 << io.screenSize; - uint screenWrap = (1 << if(io.affineWrap, 7 + io.screenSize, 20)) - 1; + uint screenWrap = (1 << (io.affineWrap ? 7 + io.screenSize : 20)) - 1; uint cx = (fx >> 8) & screenWrap; uint cy = (fy >> 8) & screenWrap; @@ -148,7 +148,7 @@ auto PPU::Background::bitmap(uint x, uint y) -> void { uint height = io.mode == 5 ? 128 : 160; uint mode = depth ? Half : Byte; - uint baseAddress = if(io.mode == 3, 0, 0xa000 * io.frame); + uint baseAddress = io.mode == 3 ? 0 : 0xa000 * io.frame; uint px = fx >> 8; uint py = fy >> 8; diff --git a/higan/gba/ppu/object.cpp b/higan/gba/ppu/object.cpp index 870425fa..b194d99b 100644 --- a/higan/gba/ppu/object.cpp +++ b/higan/gba/ppu/object.cpp @@ -8,7 +8,7 @@ auto PPU::Objects::scanline(uint y) -> void { if(object.affine == 0 && object.affineSize == 1) continue; //hidden if(py >= object.height << object.affineSize) continue; //offscreen - uint rowSize = if(io.mapping == 0, 32 >> object.colors, object.width >> 3); + uint rowSize = io.mapping == 0 ? 32 >> object.colors : object.width >> 3; uint baseAddress = object.character << 5; if(object.mosaic && io.mosaicHeight) { diff --git a/higan/gba/ppu/ppu.cpp b/higan/gba/ppu/ppu.cpp index 89713e8d..f601b051 100644 --- a/higan/gba/ppu/ppu.cpp +++ b/higan/gba/ppu/ppu.cpp @@ -1,5 +1,4 @@ #include -#include //pixel: 4 cycles diff --git a/higan/md/vdp/background.cpp b/higan/md/vdp/background.cpp index 3f86dba1..d7288347 100644 --- a/higan/md/vdp/background.cpp +++ b/higan/md/vdp/background.cpp @@ -70,7 +70,7 @@ auto VDP::Background::run(uint x, uint y) -> void { uint16 tileData = vdp.vram.read(tileAddress); uint4 color = tileData >> (((pixelX & 3) ^ 3) << 2); - output.color = if(color, tileAttributes.bits(13,14) << 4 | color, 0); + output.color = color ? tileAttributes.bits(13,14) << 4 | color : 0; output.priority = tileAttributes.bit(15); } diff --git a/higan/md/vdp/vdp.cpp b/higan/md/vdp/vdp.cpp index 23685782..9e79d715 100644 --- a/higan/md/vdp/vdp.cpp +++ b/higan/md/vdp/vdp.cpp @@ -1,5 +1,4 @@ #include -#include namespace MegaDrive { diff --git a/higan/md/ym2612/channel.cpp b/higan/md/ym2612/channel.cpp index adf83390..1f35ce13 100644 --- a/higan/md/ym2612/channel.cpp +++ b/higan/md/ym2612/channel.cpp @@ -27,7 +27,7 @@ auto YM2612::Channel::Operator::trigger(bool state) -> void { } auto YM2612::Channel::Operator::runEnvelope() -> void { - uint sustain = if(envelope.sustainLevel < 15, envelope.sustainLevel << 5, 0x3f0); + uint sustain = envelope.sustainLevel < 15 ? envelope.sustainLevel << 5 : 0x3f0; if(ym2612.envelope.clock & (1 << envelope.divider) - 1) return; uint value = ym2612.envelope.clock >> envelope.divider; @@ -121,7 +121,7 @@ auto YM2612::Channel::Operator::updatePhase() -> void { phase.delta = pitch.value + (pm >> 10 - msb) << 6 >> 7 - octave.value; phase.delta = (!detune.bit(2) ? phase.delta + tuning : phase.delta - tuning) & 0x1ffff; - phase.delta = if(multiple, phase.delta * multiple, phase.delta >> 1) & 0xfffff; + phase.delta = (multiple ? phase.delta * multiple : phase.delta >> 1) & 0xfffff; } auto YM2612::Channel::Operator::updateLevel() -> void { diff --git a/higan/md/ym2612/ym2612.cpp b/higan/md/ym2612/ym2612.cpp index d0725223..888cb22c 100644 --- a/higan/md/ym2612/ym2612.cpp +++ b/higan/md/ym2612/ym2612.cpp @@ -1,5 +1,4 @@ #include -#include namespace MegaDrive { @@ -65,7 +64,7 @@ auto YM2612::sample() -> void { auto wave = [&](uint n, uint modulation) -> int { int x = (modulation >> 1) + (op[n].phase.value >> 10); int y = sine[x & 0x3ff] + op[n].outputLevel; - return if(y < 0x2000, pow2[y & 0x1ff] << 2 >> (y >> 9), 0); + return y < 0x2000 ? pow2[y & 0x1ff] << 2 >> (y >> 9) : 0; }; int feedback = modMask & op[0].output + op[0].prior >> 9 - channel.feedback; diff --git a/higan/processor/GNUmakefile b/higan/processor/GNUmakefile index 4c01a103..b03eb0b2 100644 --- a/higan/processor/GNUmakefile +++ b/higan/processor/GNUmakefile @@ -4,9 +4,9 @@ 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) -objects += $(if $(findstring lr35902,$(processors)),processor-lr35902) objects += $(if $(findstring m68k,$(processors)),processor-m68k) objects += $(if $(findstring mos6502,$(processors)),processor-mos6502) +objects += $(if $(findstring sm83,$(processors)),processor-sm83) objects += $(if $(findstring spc700,$(processors)),processor-spc700) objects += $(if $(findstring tlcs900h,$(processors)),processor-tlcs900h) objects += $(if $(findstring upd96050,$(processors)),processor-upd96050) @@ -18,9 +18,9 @@ obj/processor-arm7tdmi.o: processor/arm7tdmi/arm7tdmi.cpp obj/processor-gsu.o: processor/gsu/gsu.cpp obj/processor-hg51b.o: processor/hg51b/hg51b.cpp obj/processor-huc6280.o: processor/huc6280/huc6280.cpp -obj/processor-lr35902.o: processor/lr35902/lr35902.cpp obj/processor-m68k.o: processor/m68k/m68k.cpp obj/processor-mos6502.o: processor/mos6502/mos6502.cpp +obj/processor-sm83.o: processor/sm83/sm83.cpp obj/processor-spc700.o: processor/spc700/spc700.cpp obj/processor-tlcs900h.o: processor/tlcs900h/tlcs900h.cpp obj/processor-upd96050.o: processor/upd96050/upd96050.cpp diff --git a/higan/processor/arm7tdmi/algorithms.cpp b/higan/processor/arm7tdmi/algorithms.cpp index ec321200..15c0db41 100644 --- a/higan/processor/arm7tdmi/algorithms.cpp +++ b/higan/processor/arm7tdmi/algorithms.cpp @@ -13,8 +13,8 @@ auto ARM7TDMI::ADD(uint32 source, uint32 modify, bool carry) -> uint32 { auto ARM7TDMI::ASR(uint32 source, uint8 shift) -> uint32 { carry = cpsr().c; if(shift == 0) return source; - carry = if(shift > 32, source & 1 << 31, source & 1 << shift - 1); - source = if(shift > 31, (int32)source >> 31, (int32)source >> shift); + carry = shift > 32 ? source & 1 << 31 : source & 1 << shift - 1; + source = shift > 31 ? (int32)source >> 31 : (int32)source >> shift; return source; } @@ -30,16 +30,16 @@ auto ARM7TDMI::BIT(uint32 result) -> uint32 { auto ARM7TDMI::LSL(uint32 source, uint8 shift) -> uint32 { carry = cpsr().c; if(shift == 0) return source; - carry = if(shift > 32, 0, source & 1 << 32 - shift); - source = if(shift > 31, 0, source << shift); + 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 = if(shift > 32, 0, source & 1 << shift - 1); - source = if(shift > 31, 0, source >> shift); + carry = shift > 32 ? 0 : source & 1 << shift - 1; + source = shift > 31 ? 0 : source >> shift; return source; } diff --git a/higan/processor/arm7tdmi/arm7tdmi.cpp b/higan/processor/arm7tdmi/arm7tdmi.cpp index 1131c2d6..e3dc0d28 100644 --- a/higan/processor/arm7tdmi/arm7tdmi.cpp +++ b/higan/processor/arm7tdmi/arm7tdmi.cpp @@ -1,5 +1,4 @@ #include -#include #include "arm7tdmi.hpp" namespace Processor { diff --git a/higan/processor/lr35902/instructions.cpp b/higan/processor/lr35902/instructions.cpp deleted file mode 100644 index 8050c2c5..00000000 --- a/higan/processor/lr35902/instructions.cpp +++ /dev/null @@ -1,462 +0,0 @@ -auto LR35902::instructionADC_Direct_Data(uint8& target) -> void { - target = ADD(target, operand(), CF); -} - -auto LR35902::instructionADC_Direct_Direct(uint8& target, uint8& source) -> void { - target = ADD(target, source, CF); -} - -auto LR35902::instructionADC_Direct_Indirect(uint8& target, uint16& source) -> void { - target = ADD(target, read(source), CF); -} - -auto LR35902::instructionADD_Direct_Data(uint8& target) -> void { - target = ADD(target, operand()); -} - -auto LR35902::instructionADD_Direct_Direct(uint8& target, uint8& source) -> void { - target = ADD(target, source); -} - -auto LR35902::instructionADD_Direct_Direct(uint16& target, uint16& source) -> void { - idle(); - uint32 x = target + source; - uint32 y = (uint12)target + (uint12)source; - target = x; - CF = x > 0xffff; - HF = y > 0x0fff; - NF = 0; -} - -auto LR35902::instructionADD_Direct_Indirect(uint8& target, uint16& source) -> void { - target = ADD(target, read(source)); -} - -auto LR35902::instructionADD_Direct_Relative(uint16& target) -> void { - auto data = operand(); - idle(); - idle(); - CF = (uint8)target + (uint8)data > 0xff; - HF = (uint4)target + (uint4)data > 0x0f; - NF = ZF = 0; - target += (int8)data; -} - -auto LR35902::instructionAND_Direct_Data(uint8& target) -> void { - target = AND(target, operand()); -} - -auto LR35902::instructionAND_Direct_Direct(uint8& target, uint8& source) -> void { - target = AND(target, source); -} - -auto LR35902::instructionAND_Direct_Indirect(uint8& target, uint16& source) -> void { - target = AND(target, read(source)); -} - -auto LR35902::instructionBIT_Index_Direct(uint3 index, uint8& data) -> void { - BIT(index, data); -} - -auto LR35902::instructionBIT_Index_Indirect(uint3 index, uint16& address) -> void { - auto data = read(address); - BIT(index, data); -} - -auto LR35902::instructionCALL_Condition_Address(bool take) -> void { - auto address = operands(); - if(!take) return; - idle(); - push(PC); - PC = address; -} - -auto LR35902::instructionCCF() -> void { - CF = !CF; - HF = NF = 0; -} - -auto LR35902::instructionCP_Direct_Data(uint8& target) -> void { - CP(target, operand()); -} - -auto LR35902::instructionCP_Direct_Direct(uint8& target, uint8& source) -> void { - CP(target, source); -} - -auto LR35902::instructionCP_Direct_Indirect(uint8& target, uint16& source) -> void { - CP(target, read(source)); -} - -auto LR35902::instructionCPL() -> void { - A = ~A; - HF = NF = 1; -} - -auto LR35902::instructionDAA() -> void { - uint16 a = A; - if(!NF) { - if(HF || (uint4)a > 0x09) a += 0x06; - if(CF || (uint8)a > 0x9f) a += 0x60; - } else { - if(HF) { - a -= 0x06; - if(!CF) a &= 0xff; - } - if(CF) a -= 0x60; - } - A = a; - CF |= a.bit(8); - HF = 0; - ZF = A == 0; -} - -auto LR35902::instructionDEC_Direct(uint8& data) -> void { - data = DEC(data); -} - -auto LR35902::instructionDEC_Direct(uint16& data) -> void { - idle(); - data--; -} - -auto LR35902::instructionDEC_Indirect(uint16& address) -> void { - auto data = read(address); - write(address, DEC(data)); -} - -auto LR35902::instructionDI() -> void { - r.ime = 0; -} - -auto LR35902::instructionEI() -> void { - r.ei = 1; -} - -auto LR35902::instructionHALT() -> void { - r.halt = 1; - while(r.halt) idle(); -} - -auto LR35902::instructionINC_Direct(uint8& data) -> void { - data = INC(data); -} - -auto LR35902::instructionINC_Direct(uint16& data) -> void { - idle(); - data++; -} - -auto LR35902::instructionINC_Indirect(uint16& address) -> void { - auto data = read(address); - write(address, INC(data)); -} - -auto LR35902::instructionJP_Condition_Address(bool take) -> void { - auto address = operands(); - if(!take) return; - idle(); - PC = address; -} - -auto LR35902::instructionJP_Direct(uint16& data) -> void { - PC = data; -} - -auto LR35902::instructionJR_Condition_Relative(bool take) -> void { - auto data = operand(); - if(!take) return; - idle(); - PC += (int8)data; -} - -auto LR35902::instructionLD_Address_Direct(uint8& data) -> void { - write(operands(), data); -} - -auto LR35902::instructionLD_Address_Direct(uint16& data) -> void { - store(operands(), data); -} - -auto LR35902::instructionLD_Direct_Address(uint8& data) -> void { - data = read(operands()); -} - -auto LR35902::instructionLD_Direct_Data(uint8& target) -> void { - target = operand(); -} - -auto LR35902::instructionLD_Direct_Data(uint16& target) -> void { - target = operands(); -} - -auto LR35902::instructionLD_Direct_Direct(uint8& target, uint8& source) -> void { - target = source; -} - -auto LR35902::instructionLD_Direct_Direct(uint16& target, uint16& source) -> void { - idle(); - target = source; -} - -auto LR35902::instructionLD_Direct_DirectRelative(uint16& target, uint16& source) -> void { - auto data = operand(); - idle(); - CF = (uint8)source + (uint8)data > 0xff; - HF = (uint4)source + (uint4)data > 0x0f; - NF = ZF = 0; - target = source + (int8)data; -} - -auto LR35902::instructionLD_Direct_Indirect(uint8& target, uint16& source) -> void { - target = read(source); -} - -auto LR35902::instructionLD_Direct_IndirectDecrement(uint8& target, uint16& source) -> void { - target = read(source--); -} - -auto LR35902::instructionLD_Direct_IndirectIncrement(uint8& target, uint16& source) -> void { - target = read(source++); -} - -auto LR35902::instructionLD_Indirect_Data(uint16& target) -> void { - write(target, operand()); -} - -auto LR35902::instructionLD_Indirect_Direct(uint16& target, uint8& source) -> void { - write(target, source); -} - -auto LR35902::instructionLD_IndirectDecrement_Direct(uint16& target, uint8& source) -> void { - write(target--, source); -} - -auto LR35902::instructionLD_IndirectIncrement_Direct(uint16& target, uint8& source) -> void { - write(target++, source); -} - -auto LR35902::instructionLDH_Address_Direct(uint8& data) -> void { - write(0xff00 | operand(), data); -} - -auto LR35902::instructionLDH_Direct_Address(uint8& data) -> void { - data = read(0xff00 | operand()); -} - -auto LR35902::instructionLDH_Direct_Indirect(uint8& target, uint8& source) -> void { - target = read(0xff00 | source); -} - -auto LR35902::instructionLDH_Indirect_Direct(uint8& target, uint8& source) -> void { - write(0xff00 | target, source); -} - -auto LR35902::instructionNOP() -> void { -} - -auto LR35902::instructionOR_Direct_Data(uint8& target) -> void { - target = OR(target, operand()); -} - -auto LR35902::instructionOR_Direct_Direct(uint8& target, uint8& source) -> void { - target = OR(target, source); -} - -auto LR35902::instructionOR_Direct_Indirect(uint8& target, uint16& source) -> void { - target = OR(target, read(source)); -} - -auto LR35902::instructionPOP_Direct(uint16& data) -> void { - data = pop(); -} - -auto LR35902::instructionPUSH_Direct(uint16& data) -> void { - idle(); - push(data); -} - -auto LR35902::instructionRES_Index_Direct(uint3 index, uint8& data) -> void { - data.bit(index) = 0; -} - -auto LR35902::instructionRES_Index_Indirect(uint3 index, uint16& address) -> void { - auto data = read(address); - data.bit(index) = 0; - write(address, data); -} - -auto LR35902::instructionRET() -> void { - auto address = pop(); - idle(); - PC = address; -} - -auto LR35902::instructionRET_Condition(bool take) -> void { - idle(); - if(!take) return; - PC = pop(); - idle(); -} - -auto LR35902::instructionRETI() -> void { - auto address = pop(); - idle(); - PC = address; - r.ime = 1; -} - -auto LR35902::instructionRL_Direct(uint8& data) -> void { - data = RL(data); -} - -auto LR35902::instructionRL_Indirect(uint16& address) -> void { - auto data = read(address); - write(address, RL(data)); -} - -auto LR35902::instructionRLA() -> void { - A = RL(A); - ZF = 0; -} - -auto LR35902::instructionRLC_Direct(uint8& data) -> void { - data = RLC(data); -} - -auto LR35902::instructionRLC_Indirect(uint16& address) -> void { - auto data = read(address); - write(address, RLC(data)); -} - -auto LR35902::instructionRLCA() -> void { - A = RLC(A); - ZF = 0; -} - -auto LR35902::instructionRR_Direct(uint8& data) -> void { - data = RR(data); -} - -auto LR35902::instructionRR_Indirect(uint16& address) -> void { - auto data = read(address); - write(address, RR(data)); -} - -auto LR35902::instructionRRA() -> void { - A = RR(A); - ZF = 0; -} - -auto LR35902::instructionRRC_Direct(uint8& data) -> void { - data = RRC(data); -} - -auto LR35902::instructionRRC_Indirect(uint16& address) -> void { - auto data = read(address); - write(address, RRC(data)); -} - -auto LR35902::instructionRRCA() -> void { - A = RRC(A); - ZF = 0; -} - -auto LR35902::instructionRST_Implied(uint8 vector) -> void { - idle(); - push(PC); - PC = vector; -} - -auto LR35902::instructionSBC_Direct_Data(uint8& target) -> void { - target = SUB(target, operand(), CF); -} - -auto LR35902::instructionSBC_Direct_Direct(uint8& target, uint8& source) -> void { - target = SUB(target, source, CF); -} - -auto LR35902::instructionSBC_Direct_Indirect(uint8& target, uint16& source) -> void { - target = SUB(target, read(source), CF); -} - -auto LR35902::instructionSCF() -> void { - CF = 1; - HF = NF = 0; -} - -auto LR35902::instructionSET_Index_Direct(uint3 index, uint8& data) -> void { - data.bit(index) = 1; -} - -auto LR35902::instructionSET_Index_Indirect(uint3 index, uint16& address) -> void { - auto data = read(address); - data.bit(index) = 1; - write(address, data); -} - -auto LR35902::instructionSLA_Direct(uint8& data) -> void { - data = SLA(data); -} - -auto LR35902::instructionSLA_Indirect(uint16& address) -> void { - auto data = read(address); - write(address, SLA(data)); -} - -auto LR35902::instructionSRA_Direct(uint8& data) -> void { - data = SRA(data); -} - -auto LR35902::instructionSRA_Indirect(uint16& address) -> void { - auto data = read(address); - write(address, SRA(data)); -} - -auto LR35902::instructionSRL_Direct(uint8& data) -> void { - data = SRL(data); -} - -auto LR35902::instructionSRL_Indirect(uint16& address) -> void { - auto data = read(address); - write(address, SRL(data)); -} - -auto LR35902::instructionSTOP() -> void { - if(stop()) return; - r.stop = 1; - while(r.stop) idle(); -} - -auto LR35902::instructionSUB_Direct_Data(uint8& target) -> void { - target = SUB(target, operand()); -} - -auto LR35902::instructionSUB_Direct_Direct(uint8& target, uint8& source) -> void { - target = SUB(target, source); -} - -auto LR35902::instructionSUB_Direct_Indirect(uint8& target, uint16& source) -> void { - target = SUB(target, read(source)); -} - -auto LR35902::instructionSWAP_Direct(uint8& data) -> void { - data = SWAP(data); -} - -auto LR35902::instructionSWAP_Indirect(uint16& address) -> void { - auto data = read(address); - write(address, SWAP(data)); -} - -auto LR35902::instructionXOR_Direct_Data(uint8& target) -> void { - target = XOR(target, operand()); -} - -auto LR35902::instructionXOR_Direct_Direct(uint8& target, uint8& source) -> void { - target = XOR(target, source); -} - -auto LR35902::instructionXOR_Direct_Indirect(uint8& target, uint16& source) -> void { - target = XOR(target, read(source)); -} diff --git a/higan/processor/lr35902/algorithms.cpp b/higan/processor/sm83/algorithms.cpp similarity index 69% rename from higan/processor/lr35902/algorithms.cpp rename to higan/processor/sm83/algorithms.cpp index 54805f66..d14acd21 100644 --- a/higan/processor/lr35902/algorithms.cpp +++ b/higan/processor/sm83/algorithms.cpp @@ -1,4 +1,4 @@ -auto LR35902::ADD(uint8 target, uint8 source, bool carry) -> uint8 { +auto SM83::ADD(uint8 target, uint8 source, bool carry) -> uint8 { uint16 x = target + source + carry; uint16 y = (uint4)target + (uint4)source + carry; CF = x > 0xff; @@ -8,7 +8,7 @@ auto LR35902::ADD(uint8 target, uint8 source, bool carry) -> uint8 { return x; } -auto LR35902::AND(uint8 target, uint8 source) -> uint8 { +auto SM83::AND(uint8 target, uint8 source) -> uint8 { target &= source; CF = 0; HF = 1; @@ -17,13 +17,13 @@ auto LR35902::AND(uint8 target, uint8 source) -> uint8 { return target; } -auto LR35902::BIT(uint3 index, uint8 target) -> void { +auto SM83::BIT(uint3 index, uint8 target) -> void { HF = 1; NF = 0; ZF = target.bit(index) == 0; } -auto LR35902::CP(uint8 target, uint8 source) -> void { +auto SM83::CP(uint8 target, uint8 source) -> void { uint16 x = target - source; uint16 y = (uint4)target - (uint4)source; CF = x > 0xff; @@ -32,7 +32,7 @@ auto LR35902::CP(uint8 target, uint8 source) -> void { ZF = (uint8)x == 0; } -auto LR35902::DEC(uint8 target) -> uint8 { +auto SM83::DEC(uint8 target) -> uint8 { target--; HF = (uint4)target == 0x0f; NF = 1; @@ -40,7 +40,7 @@ auto LR35902::DEC(uint8 target) -> uint8 { return target; } -auto LR35902::INC(uint8 target) -> uint8 { +auto SM83::INC(uint8 target) -> uint8 { target++; HF = (uint4)target == 0x00; NF = 0; @@ -48,14 +48,14 @@ auto LR35902::INC(uint8 target) -> uint8 { return target; } -auto LR35902::OR(uint8 target, uint8 source) -> uint8 { +auto SM83::OR(uint8 target, uint8 source) -> uint8 { target |= source; CF = HF = NF = 0; ZF = target == 0; return target; } -auto LR35902::RL(uint8 target) -> uint8 { +auto SM83::RL(uint8 target) -> uint8 { bool carry = target.bit(7); target = target << 1 | CF; CF = carry; @@ -64,7 +64,7 @@ auto LR35902::RL(uint8 target) -> uint8 { return target; } -auto LR35902::RLC(uint8 target) -> uint8 { +auto SM83::RLC(uint8 target) -> uint8 { target = target << 1 | target >> 7; CF = target.bit(0); HF = NF = 0; @@ -72,7 +72,7 @@ auto LR35902::RLC(uint8 target) -> uint8 { return target; } -auto LR35902::RR(uint8 target) -> uint8 { +auto SM83::RR(uint8 target) -> uint8 { bool carry = target.bit(0); target = CF << 7 | target >> 1; CF = carry; @@ -81,7 +81,7 @@ auto LR35902::RR(uint8 target) -> uint8 { return target; } -auto LR35902::RRC(uint8 target) -> uint8 { +auto SM83::RRC(uint8 target) -> uint8 { target = target << 7 | target >> 1; CF = target.bit(7); HF = NF = 0; @@ -89,7 +89,7 @@ auto LR35902::RRC(uint8 target) -> uint8 { return target; } -auto LR35902::SLA(uint8 target) -> uint8 { +auto SM83::SLA(uint8 target) -> uint8 { bool carry = target.bit(7); target <<= 1; CF = carry; @@ -98,7 +98,7 @@ auto LR35902::SLA(uint8 target) -> uint8 { return target; } -auto LR35902::SRA(uint8 target) -> uint8 { +auto SM83::SRA(uint8 target) -> uint8 { bool carry = target.bit(0); target = (int8)target >> 1; CF = carry; @@ -107,7 +107,7 @@ auto LR35902::SRA(uint8 target) -> uint8 { return target; } -auto LR35902::SRL(uint8 target) -> uint8 { +auto SM83::SRL(uint8 target) -> uint8 { bool carry = target.bit(0); target >>= 1; CF = carry; @@ -116,7 +116,7 @@ auto LR35902::SRL(uint8 target) -> uint8 { return target; } -auto LR35902::SUB(uint8 target, uint8 source, bool carry) -> uint8 { +auto SM83::SUB(uint8 target, uint8 source, bool carry) -> uint8 { uint16 x = target - source - carry; uint16 y = (uint4)target - (uint4)source - carry; CF = x > 0xff; @@ -126,14 +126,14 @@ auto LR35902::SUB(uint8 target, uint8 source, bool carry) -> uint8 { return x; } -auto LR35902::SWAP(uint8 target) -> uint8 { +auto SM83::SWAP(uint8 target) -> uint8 { target = target << 4 | target >> 4; CF = HF = NF = 0; ZF = target == 0; return target; } -auto LR35902::XOR(uint8 target, uint8 source) -> uint8 { +auto SM83::XOR(uint8 target, uint8 source) -> uint8 { target ^= source; CF = HF = NF = 0; ZF = target == 0; diff --git a/higan/processor/lr35902/disassembler.cpp b/higan/processor/sm83/disassembler.cpp similarity index 99% rename from higan/processor/lr35902/disassembler.cpp rename to higan/processor/sm83/disassembler.cpp index 0a1540e1..ed081644 100644 --- a/higan/processor/lr35902/disassembler.cpp +++ b/higan/processor/sm83/disassembler.cpp @@ -1,4 +1,4 @@ -auto LR35902::disassemble(uint16 pc) -> string { +auto SM83::disassemble(uint16 pc) -> string { return { hex(pc, 4L), " ", pad(disassembleOpcode(pc), -16, ' '), " ", @@ -10,7 +10,7 @@ auto LR35902::disassemble(uint16 pc) -> string { }; } -auto LR35902::disassembleOpcode(uint16 pc) -> string { +auto SM83::disassembleOpcode(uint16 pc) -> string { auto opcode = readDebugger(pc); auto lo = readDebugger(pc + 1); auto hi = readDebugger(pc + 2); @@ -267,7 +267,7 @@ auto LR35902::disassembleOpcode(uint16 pc) -> string { return {"xx"}; } -auto LR35902::disassembleOpcodeCB(uint16 pc) -> string { +auto SM83::disassembleOpcodeCB(uint16 pc) -> string { auto opcode = readDebugger(pc); switch(opcode) { diff --git a/higan/processor/lr35902/instruction.cpp b/higan/processor/sm83/instruction.cpp similarity index 98% rename from higan/processor/lr35902/instruction.cpp rename to higan/processor/sm83/instruction.cpp index dc803e0d..8b7c3abc 100644 --- a/higan/processor/lr35902/instruction.cpp +++ b/higan/processor/sm83/instruction.cpp @@ -1,4 +1,4 @@ -auto LR35902::interrupt(uint16 vector) -> void { +auto SM83::interrupt(uint16 vector) -> void { idle(); idle(); idle(); @@ -9,7 +9,7 @@ auto LR35902::interrupt(uint16 vector) -> void { #define op(id, name, ...) case id: return instruction##name(__VA_ARGS__); -auto LR35902::instruction() -> void { +auto SM83::instruction() -> void { auto opcode = operand(); switch(opcode) { @@ -261,7 +261,7 @@ auto LR35902::instruction() -> void { } } -auto LR35902::instructionCB() -> void { +auto SM83::instructionCB() -> void { auto opcode = operand(); switch(opcode) { diff --git a/higan/processor/sm83/instructions.cpp b/higan/processor/sm83/instructions.cpp new file mode 100644 index 00000000..d28d2ffc --- /dev/null +++ b/higan/processor/sm83/instructions.cpp @@ -0,0 +1,462 @@ +auto SM83::instructionADC_Direct_Data(uint8& target) -> void { + target = ADD(target, operand(), CF); +} + +auto SM83::instructionADC_Direct_Direct(uint8& target, uint8& source) -> void { + target = ADD(target, source, CF); +} + +auto SM83::instructionADC_Direct_Indirect(uint8& target, uint16& source) -> void { + target = ADD(target, read(source), CF); +} + +auto SM83::instructionADD_Direct_Data(uint8& target) -> void { + target = ADD(target, operand()); +} + +auto SM83::instructionADD_Direct_Direct(uint8& target, uint8& source) -> void { + target = ADD(target, source); +} + +auto SM83::instructionADD_Direct_Direct(uint16& target, uint16& source) -> void { + idle(); + uint32 x = target + source; + uint32 y = (uint12)target + (uint12)source; + target = x; + CF = x > 0xffff; + HF = y > 0x0fff; + NF = 0; +} + +auto SM83::instructionADD_Direct_Indirect(uint8& target, uint16& source) -> void { + target = ADD(target, read(source)); +} + +auto SM83::instructionADD_Direct_Relative(uint16& target) -> void { + auto data = operand(); + idle(); + idle(); + CF = (uint8)target + (uint8)data > 0xff; + HF = (uint4)target + (uint4)data > 0x0f; + NF = ZF = 0; + target += (int8)data; +} + +auto SM83::instructionAND_Direct_Data(uint8& target) -> void { + target = AND(target, operand()); +} + +auto SM83::instructionAND_Direct_Direct(uint8& target, uint8& source) -> void { + target = AND(target, source); +} + +auto SM83::instructionAND_Direct_Indirect(uint8& target, uint16& source) -> void { + target = AND(target, read(source)); +} + +auto SM83::instructionBIT_Index_Direct(uint3 index, uint8& data) -> void { + BIT(index, data); +} + +auto SM83::instructionBIT_Index_Indirect(uint3 index, uint16& address) -> void { + auto data = read(address); + BIT(index, data); +} + +auto SM83::instructionCALL_Condition_Address(bool take) -> void { + auto address = operands(); + if(!take) return; + idle(); + push(PC); + PC = address; +} + +auto SM83::instructionCCF() -> void { + CF = !CF; + HF = NF = 0; +} + +auto SM83::instructionCP_Direct_Data(uint8& target) -> void { + CP(target, operand()); +} + +auto SM83::instructionCP_Direct_Direct(uint8& target, uint8& source) -> void { + CP(target, source); +} + +auto SM83::instructionCP_Direct_Indirect(uint8& target, uint16& source) -> void { + CP(target, read(source)); +} + +auto SM83::instructionCPL() -> void { + A = ~A; + HF = NF = 1; +} + +auto SM83::instructionDAA() -> void { + uint16 a = A; + if(!NF) { + if(HF || (uint4)a > 0x09) a += 0x06; + if(CF || (uint8)a > 0x9f) a += 0x60; + } else { + if(HF) { + a -= 0x06; + if(!CF) a &= 0xff; + } + if(CF) a -= 0x60; + } + A = a; + CF |= a.bit(8); + HF = 0; + ZF = A == 0; +} + +auto SM83::instructionDEC_Direct(uint8& data) -> void { + data = DEC(data); +} + +auto SM83::instructionDEC_Direct(uint16& data) -> void { + idle(); + data--; +} + +auto SM83::instructionDEC_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, DEC(data)); +} + +auto SM83::instructionDI() -> void { + r.ime = 0; +} + +auto SM83::instructionEI() -> void { + r.ei = 1; +} + +auto SM83::instructionHALT() -> void { + r.halt = 1; + while(r.halt) idle(); +} + +auto SM83::instructionINC_Direct(uint8& data) -> void { + data = INC(data); +} + +auto SM83::instructionINC_Direct(uint16& data) -> void { + idle(); + data++; +} + +auto SM83::instructionINC_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, INC(data)); +} + +auto SM83::instructionJP_Condition_Address(bool take) -> void { + auto address = operands(); + if(!take) return; + idle(); + PC = address; +} + +auto SM83::instructionJP_Direct(uint16& data) -> void { + PC = data; +} + +auto SM83::instructionJR_Condition_Relative(bool take) -> void { + auto data = operand(); + if(!take) return; + idle(); + PC += (int8)data; +} + +auto SM83::instructionLD_Address_Direct(uint8& data) -> void { + write(operands(), data); +} + +auto SM83::instructionLD_Address_Direct(uint16& data) -> void { + store(operands(), data); +} + +auto SM83::instructionLD_Direct_Address(uint8& data) -> void { + data = read(operands()); +} + +auto SM83::instructionLD_Direct_Data(uint8& target) -> void { + target = operand(); +} + +auto SM83::instructionLD_Direct_Data(uint16& target) -> void { + target = operands(); +} + +auto SM83::instructionLD_Direct_Direct(uint8& target, uint8& source) -> void { + target = source; +} + +auto SM83::instructionLD_Direct_Direct(uint16& target, uint16& source) -> void { + idle(); + target = source; +} + +auto SM83::instructionLD_Direct_DirectRelative(uint16& target, uint16& source) -> void { + auto data = operand(); + idle(); + CF = (uint8)source + (uint8)data > 0xff; + HF = (uint4)source + (uint4)data > 0x0f; + NF = ZF = 0; + target = source + (int8)data; +} + +auto SM83::instructionLD_Direct_Indirect(uint8& target, uint16& source) -> void { + target = read(source); +} + +auto SM83::instructionLD_Direct_IndirectDecrement(uint8& target, uint16& source) -> void { + target = read(source--); +} + +auto SM83::instructionLD_Direct_IndirectIncrement(uint8& target, uint16& source) -> void { + target = read(source++); +} + +auto SM83::instructionLD_Indirect_Data(uint16& target) -> void { + write(target, operand()); +} + +auto SM83::instructionLD_Indirect_Direct(uint16& target, uint8& source) -> void { + write(target, source); +} + +auto SM83::instructionLD_IndirectDecrement_Direct(uint16& target, uint8& source) -> void { + write(target--, source); +} + +auto SM83::instructionLD_IndirectIncrement_Direct(uint16& target, uint8& source) -> void { + write(target++, source); +} + +auto SM83::instructionLDH_Address_Direct(uint8& data) -> void { + write(0xff00 | operand(), data); +} + +auto SM83::instructionLDH_Direct_Address(uint8& data) -> void { + data = read(0xff00 | operand()); +} + +auto SM83::instructionLDH_Direct_Indirect(uint8& target, uint8& source) -> void { + target = read(0xff00 | source); +} + +auto SM83::instructionLDH_Indirect_Direct(uint8& target, uint8& source) -> void { + write(0xff00 | target, source); +} + +auto SM83::instructionNOP() -> void { +} + +auto SM83::instructionOR_Direct_Data(uint8& target) -> void { + target = OR(target, operand()); +} + +auto SM83::instructionOR_Direct_Direct(uint8& target, uint8& source) -> void { + target = OR(target, source); +} + +auto SM83::instructionOR_Direct_Indirect(uint8& target, uint16& source) -> void { + target = OR(target, read(source)); +} + +auto SM83::instructionPOP_Direct(uint16& data) -> void { + data = pop(); +} + +auto SM83::instructionPUSH_Direct(uint16& data) -> void { + idle(); + push(data); +} + +auto SM83::instructionRES_Index_Direct(uint3 index, uint8& data) -> void { + data.bit(index) = 0; +} + +auto SM83::instructionRES_Index_Indirect(uint3 index, uint16& address) -> void { + auto data = read(address); + data.bit(index) = 0; + write(address, data); +} + +auto SM83::instructionRET() -> void { + auto address = pop(); + idle(); + PC = address; +} + +auto SM83::instructionRET_Condition(bool take) -> void { + idle(); + if(!take) return; + PC = pop(); + idle(); +} + +auto SM83::instructionRETI() -> void { + auto address = pop(); + idle(); + PC = address; + r.ime = 1; +} + +auto SM83::instructionRL_Direct(uint8& data) -> void { + data = RL(data); +} + +auto SM83::instructionRL_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, RL(data)); +} + +auto SM83::instructionRLA() -> void { + A = RL(A); + ZF = 0; +} + +auto SM83::instructionRLC_Direct(uint8& data) -> void { + data = RLC(data); +} + +auto SM83::instructionRLC_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, RLC(data)); +} + +auto SM83::instructionRLCA() -> void { + A = RLC(A); + ZF = 0; +} + +auto SM83::instructionRR_Direct(uint8& data) -> void { + data = RR(data); +} + +auto SM83::instructionRR_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, RR(data)); +} + +auto SM83::instructionRRA() -> void { + A = RR(A); + ZF = 0; +} + +auto SM83::instructionRRC_Direct(uint8& data) -> void { + data = RRC(data); +} + +auto SM83::instructionRRC_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, RRC(data)); +} + +auto SM83::instructionRRCA() -> void { + A = RRC(A); + ZF = 0; +} + +auto SM83::instructionRST_Implied(uint8 vector) -> void { + idle(); + push(PC); + PC = vector; +} + +auto SM83::instructionSBC_Direct_Data(uint8& target) -> void { + target = SUB(target, operand(), CF); +} + +auto SM83::instructionSBC_Direct_Direct(uint8& target, uint8& source) -> void { + target = SUB(target, source, CF); +} + +auto SM83::instructionSBC_Direct_Indirect(uint8& target, uint16& source) -> void { + target = SUB(target, read(source), CF); +} + +auto SM83::instructionSCF() -> void { + CF = 1; + HF = NF = 0; +} + +auto SM83::instructionSET_Index_Direct(uint3 index, uint8& data) -> void { + data.bit(index) = 1; +} + +auto SM83::instructionSET_Index_Indirect(uint3 index, uint16& address) -> void { + auto data = read(address); + data.bit(index) = 1; + write(address, data); +} + +auto SM83::instructionSLA_Direct(uint8& data) -> void { + data = SLA(data); +} + +auto SM83::instructionSLA_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, SLA(data)); +} + +auto SM83::instructionSRA_Direct(uint8& data) -> void { + data = SRA(data); +} + +auto SM83::instructionSRA_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, SRA(data)); +} + +auto SM83::instructionSRL_Direct(uint8& data) -> void { + data = SRL(data); +} + +auto SM83::instructionSRL_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, SRL(data)); +} + +auto SM83::instructionSTOP() -> void { + if(stop()) return; + r.stop = 1; + while(r.stop) idle(); +} + +auto SM83::instructionSUB_Direct_Data(uint8& target) -> void { + target = SUB(target, operand()); +} + +auto SM83::instructionSUB_Direct_Direct(uint8& target, uint8& source) -> void { + target = SUB(target, source); +} + +auto SM83::instructionSUB_Direct_Indirect(uint8& target, uint16& source) -> void { + target = SUB(target, read(source)); +} + +auto SM83::instructionSWAP_Direct(uint8& data) -> void { + data = SWAP(data); +} + +auto SM83::instructionSWAP_Indirect(uint16& address) -> void { + auto data = read(address); + write(address, SWAP(data)); +} + +auto SM83::instructionXOR_Direct_Data(uint8& target) -> void { + target = XOR(target, operand()); +} + +auto SM83::instructionXOR_Direct_Direct(uint8& target, uint8& source) -> void { + target = XOR(target, source); +} + +auto SM83::instructionXOR_Direct_Indirect(uint8& target, uint16& source) -> void { + target = XOR(target, read(source)); +} diff --git a/higan/processor/lr35902/memory.cpp b/higan/processor/sm83/memory.cpp similarity index 58% rename from higan/processor/lr35902/memory.cpp rename to higan/processor/sm83/memory.cpp index ba24d86c..2833f4d0 100644 --- a/higan/processor/lr35902/memory.cpp +++ b/higan/processor/sm83/memory.cpp @@ -1,28 +1,28 @@ -auto LR35902::operand() -> uint8 { +auto SM83::operand() -> uint8 { return read(PC++); } -auto LR35902::operands() -> uint16 { +auto SM83::operands() -> uint16 { uint16 data = read(PC++) << 0; return data | read(PC++) << 8; } -auto LR35902::load(uint16 address) -> uint16 { +auto SM83::load(uint16 address) -> uint16 { uint16 data = read(address++) << 0; return data | read(address++) << 8; } -auto LR35902::store(uint16 address, uint16 data) -> void { +auto SM83::store(uint16 address, uint16 data) -> void { write(address++, data >> 0); write(address++, data >> 8); } -auto LR35902::pop() -> uint16 { +auto SM83::pop() -> uint16 { uint16 data = read(SP++) << 0; return data | read(SP++) << 8; } -auto LR35902::push(uint16 data) -> void { +auto SM83::push(uint16 data) -> void { write(--SP, data >> 8); write(--SP, data >> 0); } diff --git a/higan/processor/lr35902/registers.cpp b/higan/processor/sm83/registers.cpp similarity index 100% rename from higan/processor/lr35902/registers.cpp rename to higan/processor/sm83/registers.cpp diff --git a/higan/processor/lr35902/serialization.cpp b/higan/processor/sm83/serialization.cpp similarity index 82% rename from higan/processor/lr35902/serialization.cpp rename to higan/processor/sm83/serialization.cpp index cc74a382..e75cd8b3 100644 --- a/higan/processor/lr35902/serialization.cpp +++ b/higan/processor/sm83/serialization.cpp @@ -1,4 +1,4 @@ -auto LR35902::serialize(serializer& s) -> void { +auto SM83::serialize(serializer& s) -> void { s.integer(r.af.word); s.integer(r.bc.word); s.integer(r.de.word); diff --git a/higan/processor/lr35902/lr35902.cpp b/higan/processor/sm83/sm83.cpp similarity index 82% rename from higan/processor/lr35902/lr35902.cpp rename to higan/processor/sm83/sm83.cpp index c16ef803..7ecf5338 100644 --- a/higan/processor/lr35902/lr35902.cpp +++ b/higan/processor/sm83/sm83.cpp @@ -1,5 +1,5 @@ #include -#include "lr35902.hpp" +#include "sm83.hpp" namespace Processor { @@ -11,7 +11,7 @@ namespace Processor { #include "serialization.cpp" #include "disassembler.cpp" -auto LR35902::power() -> void { +auto SM83::power() -> void { r = {}; } diff --git a/higan/processor/lr35902/lr35902.hpp b/higan/processor/sm83/sm83.hpp similarity index 96% rename from higan/processor/lr35902/lr35902.hpp rename to higan/processor/sm83/sm83.hpp index 323e431c..d608c984 100644 --- a/higan/processor/lr35902/lr35902.hpp +++ b/higan/processor/sm83/sm83.hpp @@ -1,10 +1,14 @@ -//Sharp LR35902 +//Sharp SM83 + +//the Game Boy SoC is commonly referred to as the Sharp LR35902 +//SM83 is most likely the internal CPU core, based on strong datasheet similarities +//as such, this CPU core could serve as a foundation for any SM83xx SoC #pragma once namespace Processor { -struct LR35902 { +struct SM83 { virtual auto idle() -> void = 0; virtual auto read(uint16 address) -> uint8 = 0; virtual auto write(uint16 address, uint8 data) -> void = 0; diff --git a/higan/processor/spc700/instructions.cpp b/higan/processor/spc700/instructions.cpp index 17fb4a32..610eb7fb 100644 --- a/higan/processor/spc700/instructions.cpp +++ b/higan/processor/spc700/instructions.cpp @@ -570,7 +570,7 @@ auto SPC700::instructionTestSetBitsAbsolute(bool set) -> void { ZF = (A - data) == 0; NF = (A - data) & 0x80; read(address); - write(address, if(set, data | A, data & ~A)); + write(address, set ? data | A : data & ~A); } auto SPC700::instructionTransfer(uint8& from, uint8& to) -> void { diff --git a/higan/processor/spc700/spc700.cpp b/higan/processor/spc700/spc700.cpp index 9264eecb..69ec693c 100644 --- a/higan/processor/spc700/spc700.cpp +++ b/higan/processor/spc700/spc700.cpp @@ -1,5 +1,4 @@ #include -#include #include "spc700.hpp" namespace Processor { diff --git a/higan/processor/tlcs900h/disassembler.cpp b/higan/processor/tlcs900h/disassembler.cpp index 6b7ecca0..4744cfbd 100644 --- a/higan/processor/tlcs900h/disassembler.cpp +++ b/higan/processor/tlcs900h/disassembler.cpp @@ -6,376 +6,692 @@ auto TLCS900H::disassemble() -> string { uint8 op[8] = {}, ops = 0; - auto read8 = [&]() -> uint8 { return op[ops++] = disassembleRead(pc++); }; + auto read8 = [&]() -> uint8 { return op[ops++] = disassembleRead(pc++); }; auto read16 = [&]() -> uint16 { uint16 data = read8(); return data | read8() << 8; }; - auto read24 = [&]() -> uint32 { uint24 data = read8(); data |= read8() << 8; return data | read8() << 16; }; + auto read24 = [&]() -> uint24 { uint24 data = read8(); data |= read8() << 8; return data | read8() << 16; }; + auto read32 = [&]() -> uint32 { uint32 data = read8(); data |= read8() << 8; data |= read8() << 16; return data | read8() << 24; }; enum : uint { - Undefined, - Text, - Implied, - Immediate, //#i - ImmediateByteRegister, //immediate:byte,register:size - ControlRegisterRegister, //controlRegister:size,register:size - RegisterControlRegister, //register:size,controlRegister:size - Register, - RegisterImmediate, - RegisterImmediateByte, //register:size,immediate:byte - RegisterImmediateWord, //register:size,immediate:word - RegisterDisplacementByte, //register:size,displacement:byte - RegisterDisplacementWord, //register:size,displacement:word - RegisterWordImmediate, //r16,#is - RegisterRegisterAlt, //register:size,registerAlt:size - RegisterAltRegister, //registerAlt:size,register:size - RegisterAltByteRegister, //registerAlt:byte,register:size - Address, //as - Displacement, - DisplacementPC, //(pc+ds) - ConditionDisplacementPC, //c,(pc+ds) - ConditionRegister, //condition,register:size - IndirectRegister, //(r32) - IndirectRegisterDecrement, //(-r32) - IndirectRegisterIncrement, //(r32+) - IndirectRegisterRegisterByte, //(r32+r8) - IndirectRegisterRegisterWord, //(r32+r16) - IndirectRegisterDisplacementByte, //(r32+d8) - IndirectRegisterDisplacementWord, //(r32+d16) - IndirectAddressByte, //(a8) - IndirectAddressWord, //(a16) - IndirectAddressLong, //(a32) - IndirectImmediateImmediate, //(#8),# + Null, + Text, //text + Condition, //condition + Register, //register.size + Control, //register.size + Immediate, //immediate.size + Displacement, //displacement.size + DisplacementPC, //pc+displacement.size + IndirectRegister, //op.size (r32) + IndirectRegisterDecrement, //op.size (-r32) + IndirectRegisterIncrement, //op.size (r32+) + IndirectRegisterRegister8, //op.size (r32+r8) + IndirectRegisterRegister16, //op.size (r32+r16) + IndirectRegisterDisplacement8, //op.size (r32+d8) + IndirectRegisterDisplacement16, //op.size (r32+d16) + IndirectImmediate8, //(i8) + IndirectImmediate16, //(i16) + IndirectImmediate24, //(i24) }; - enum : uint { - Byte, - Word, - Long, - Unknown, - }; + //name [lhs[,rhs]] + string name; + struct Operand { + explicit operator bool() const { return _mode != Null; } - string name; - string text; - natural mode; - natural size; - natural controlRegister; - natural register; - natural registerAlt; - natural immediate; - natural indirectImmediate; - natural condition; - natural address; - natural addressSize; - integer displacement; + auto mode() const { return _mode; } + auto size() const { return _size; } + auto text() const { return _text; } + auto condition() const { return _condition; } + auto register() const { return _register; } + auto registerAdd() const { return _registerAdd; } + auto immediate() const { return _immediate; } + auto displacement() const { return _displacement; } + + auto mode(natural mode_) -> void { _mode = mode_; } + auto size(natural size_) -> void { _size = size_; } + + auto null() -> void { mode(Null); } + auto text(string text_) -> void { mode(Text); _text = text_; } + auto condition(uint4 condition_) -> void { mode(Condition); _condition = condition_; } + auto register(natural size_, uint8 register_) -> void { mode(Register); size(size_); _register = register_; } + auto register3(natural size_, uint3 register_) -> void { mode(Register); size(size_); _register = lookup(size_, register_); } + auto control(natural size_, uint8 register_) -> void { mode(Control); size(size_); _register = register_; } + auto immediate(natural size_, natural immediate_) -> void { mode(Immediate); size(size_); _immediate = immediate_; } + auto displacement(natural size_, natural displacement_) -> void { mode(Displacement); size(size_); _displacement = displacement_; } + auto displacementPC(natural size_, natural displacement_) -> void { mode(DisplacementPC); size(size_); _displacement = displacement_; } + + auto indirectRegister(natural size_, uint8 register_) -> void { mode(IndirectRegister); size(size_); _register = register_; } + auto indirectRegister3(natural size_, uint3 register_) -> void { mode(IndirectRegister); size(size_); _register = lookup(32, register_); } + auto indirectRegisterDecrement(natural size_, uint8 register_) -> void { mode(IndirectRegisterDecrement); size(size_); _register = register_; } + auto indirectRegisterIncrement(natural size_, uint8 register_) -> void { mode(IndirectRegisterIncrement); size(size_); _register = register_; } + auto indirectRegister3Increment(natural size_, uint3 register_) -> void { mode(IndirectRegisterIncrement); size(size_); _register = lookup(32, register_); } + auto indirectRegisterRegister8(natural size_, uint8 register32, uint8 register8) -> void { mode(IndirectRegisterRegister8); size(size_); _register = register32; _registerAdd = register8; } + auto indirectRegisterRegister16(natural size_, uint8 register32, uint8 register16) -> void { mode(IndirectRegisterRegister16); size(size_); _register = register32; _registerAdd = register16; } + auto indirectRegister3Displacement8(natural size_, uint3 register_, uint8 displacement_) -> void { mode(IndirectRegisterDisplacement8); size(size_); _register = lookup(32, register_); _displacement = displacement_; } + auto indirectRegisterDisplacement16(natural size_, uint8 register_, uint16 displacement_) -> void { mode(IndirectRegisterDisplacement16); size(size_); _register = register_; _displacement = displacement_; } + auto indirectImmediate8(natural size_, uint8 immediate_) -> void { mode(IndirectImmediate8); size(size_); _immediate = immediate_; } + auto indirectImmediate16(natural size_, uint16 immediate_) -> void { mode(IndirectImmediate16); size(size_); _immediate = immediate_; } + auto indirectImmediate24(natural size_, uint24 immediate_) -> void { mode(IndirectImmediate24); size(size_); _immediate = immediate_; } + + private: + natural _mode = Null; + natural _size; + string _text; + natural _condition; + natural _register; + natural _registerAdd; + natural _immediate; + natural _displacement; + + static auto lookup(natural size, uint3 register) -> uint8 { + if(size == 8) return from_array<0xe1, 0xe0, 0xe5, 0xe4, 0xe9, 0xe8, 0xed, 0xec>(register); + if(size == 16) return from_array<0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf4, 0xf8, 0xfc>(register); + if(size == 32) return from_array<0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf4, 0xf8, 0xfc>(register); + return 0; + } + } lhs, rhs; boolean opRegister; boolean opSourceMemory; boolean opTargetMemory; - switch(read8()) { + static const natural opcodeSizes[] = {8, 16, 32, 0}; //0xc0 - 0xf5 + + switch(auto fetch = read8()) { case 0x00: name = "nop"; break; case 0x01: break; - case 0x02: name = "push"; mode = Text; text = "sr"; break; - case 0x03: name = "pop"; mode = Text; text = "sr"; break; + case 0x02: name = "push"; lhs.text("sr"); break; + case 0x03: name = "pop"; lhs.text("sr"); break; case 0x04: break; case 0x05: name = "halt"; break; - case 0x06: name = "ei"; mode = Immediate; size = Byte; immediate = (uint3)read8(); break; + case 0x06: name = "ei"; lhs.immediate(3, (uint3)read8()); if(lhs.immediate() == 7) name = "di", lhs.null(); break; case 0x07: name = "reti"; break; - case 0x08: - name = "ld"; mode = IndirectImmediateImmediate; size = Byte; - indirectImmediate = read8(); immediate = read8(); break; - case 0x09: name = "push"; mode = Immediate; size = Byte; immediate = read8(); break; - case 0x0a: - name = "ldx"; mode = IndirectImmediateImmediate; size = Byte; - indirectImmediate = read8(); immediate = read16(); break; - case 0x0b: name = "pushw"; mode = Immediate; size = Word; immediate = read16(); break; + case 0x08: name = "ld"; lhs.indirectImmediate8(8, read8()); rhs.immediate(8, read8()); break; + case 0x09: name = "push"; lhs.immediate(8, read8()); break; + case 0x0a: name = "ldw"; lhs.indirectImmediate8(8, read8()); rhs.immediate(16, read16()); break; + case 0x0b: name = "pushw"; lhs.immediate(16, read16()); break; case 0x0c: name = "incf"; break; case 0x0d: name = "decf"; break; case 0x0e: name = "ret"; break; - case 0x0f: name = "retd"; mode = Displacement; size = Word; displacement = (int16)read16(); break; + case 0x0f: name = "retd"; lhs.displacement(16, read16()); break; case 0x10: name = "rcf"; break; case 0x11: name = "scf"; break; case 0x12: name = "ccf"; break; case 0x13: name = "zcf"; break; - case 0x14: name = "push"; mode = Text; text = "a"; break; - case 0x15: name = "pop"; mode = Text; text = "a"; break; - case 0x16: name = "ex"; mode = Text; text = "f,f'"; break; - case 0x17: name = "ldf"; mode = Immediate; size = Byte; immediate = read8(); break; - case 0x18: name = "push"; mode = Text; text = "f"; break; - case 0x19: name = "pop"; mode = Text; text = "f"; break; - case 0x1a: name = "jp"; mode = Address; size = Word; address = read16(); break; - case 0x1b: name = "jp"; mode = Address; size = Long; address = read24(); break; - case 0x1c: name = "call"; mode = Address; size = Word; address = read16(); break; - case 0x1d: name = "call"; mode = Address; size = Long; address = read24(); break; - case 0x1e: name = "calr"; mode = DisplacementPC; size = Word; displacement = (int16)read16(); break; + case 0x14: name = "push"; lhs.register3(8, A.id); break; + case 0x15: name = "pop"; lhs.register3(8, A.id); break; + case 0x16: name = "ex"; lhs.text("f"); rhs.text("f'"); break; + case 0x17: name = "ldf"; lhs.immediate(2, (uint2)read8()); break; + case 0x18: name = "push"; lhs.text("f"); break; + case 0x19: name = "pop"; lhs.text("f"); break; + case 0x1a: name = "jp"; lhs.immediate(16, read16()); break; + case 0x1b: name = "jp"; lhs.immediate(24, read24()); break; + case 0x1c: name = "call"; lhs.immediate(16, read16()); break; + case 0x1d: name = "call"; lhs.immediate(24, read24()); break; + case 0x1e: name = "calr"; lhs.displacementPC(16, read16()); break; case 0x1f: break; case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: - name = "ld"; mode = RegisterImmediate; size = Byte; - register = toRegister3(op[0]).id; immediate = read8(); break; + name = "ld"; lhs.register3(8, fetch); rhs.immediate(8, read8()); break; case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: - name = "push"; mode = Register; size = Word; - register = toRegister3(op[0]).id; break; + name = "push"; lhs.register3(16, fetch); break; case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: - name = "ld"; mode = RegisterImmediate; size = Word; - register = toRegister3(op[0]).id; immediate = read16(); break; + name = "ld"; lhs.register3(16, fetch); rhs.immediate(16, read16()); break; case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: - name = "push"; mode = Register; size = Long; - register = toRegister3(op[0]).id; break; + name = "push"; lhs.register3(32, fetch); break; case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: - name = "ld"; mode = RegisterImmediate; size = Long; - register = toRegister3(op[0]).id; immediate = read24(); break; + name = "ld"; lhs.register3(32, fetch); rhs.immediate(32, read32()); break; case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: - name = "pop"; mode = Register; size = Word; - register = toRegister3(op[0]).id; break; + name = "pop"; lhs.register3(16, fetch); break; case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: break; case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: - name = "pop"; mode = Register; size = Long; - register = toRegister3(op[0]).id; break; + name = "pop"; lhs.register3(32, fetch); break; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: - name = "jr"; mode = ConditionDisplacementPC; size = Byte; - condition = (uint4)op[0]; displacement = (int8)read8(); break; + name = "jr"; lhs.condition(fetch); rhs.displacementPC(8, read8()); break; case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: - name = "jrl"; mode = ConditionDisplacementPC; size = Word; - condition = (uint4)op[0]; displacement = (int16)read16(); break; + name = "jrl"; lhs.condition(fetch); rhs.displacementPC(16, read16()); break; case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: - opSourceMemory = true; mode = IndirectRegister; size = Byte; - register = toRegister3(op[0]).id; break; + opSourceMemory = true; lhs.indirectRegister3(8, fetch); break; case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: - opSourceMemory = true; mode = IndirectRegisterDisplacementByte; size = Byte; - register = toRegister3(op[0]).id; displacement = (int8)read8(); break; + opSourceMemory = true; lhs.indirectRegister3Displacement8(8, fetch, read8()); case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: - opSourceMemory = true; mode = IndirectRegister; size = Word; - register = toRegister3(op[0]).id; break; + opSourceMemory = true; lhs.indirectRegister3(16, fetch); break; case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: - opSourceMemory = true; mode = IndirectRegisterDisplacementByte; size = Word; - register = toRegister3(op[0]).id; displacement = (int8)read8(); break; + opSourceMemory = true; lhs.indirectRegister3Displacement8(16, fetch, read8()); break; case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: - opSourceMemory = true; mode = IndirectRegister; size = Long; - register = toRegister3(op[0]).id; break; + opSourceMemory = true; lhs.indirectRegister3(32, fetch); break; case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: - opSourceMemory = true; mode = IndirectRegisterDisplacementByte; size = Long; - register = toRegister3(op[0]).id; displacement = (int8)read8(); break; + opSourceMemory = true; lhs.indirectRegister3Displacement8(32, fetch, read8()); break; case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: - opTargetMemory = true; mode = IndirectRegister; - register = toRegister3(op[0]).id; break; + opTargetMemory = true; lhs.indirectRegister3(0, fetch); break; case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: - opTargetMemory = true; mode = IndirectRegisterDisplacementByte; - register = toRegister3(op[0]).id; displacement = (int8)read8(); break; + opTargetMemory = true; lhs.indirectRegister3Displacement8(0, fetch, read8()); break; case 0xc0: case 0xd0: case 0xe0: case 0xf0: - opSourceMemory = op[0] < 0xf0; opTargetMemory = !opSourceMemory; mode = IndirectAddressByte; size = op[0] >> 4; - address = read8(); break; + opSourceMemory = fetch < 0xf0; opTargetMemory = !opSourceMemory; + lhs.indirectImmediate8(opcodeSizes[fetch >> 4], read8()); break; case 0xc1: case 0xd1: case 0xe1: case 0xf1: - opSourceMemory = op[0] < 0xf0; opTargetMemory = !opSourceMemory; mode = IndirectAddressWord; size = op[0] >> 4; - address = read16(); break; + opSourceMemory = fetch < 0xf0; opTargetMemory = !opSourceMemory; + lhs.indirectImmediate16(opcodeSizes[fetch >> 4], read16()); break; case 0xc2: case 0xd2: case 0xe2: case 0xf2: - opSourceMemory = op[0] < 0xf0; opTargetMemory = !opSourceMemory; mode = IndirectAddressLong; size = op[0] >> 4; - address = read24(); break; - case 0xc3: case 0xd3: case 0xe3: case 0xf3: - opSourceMemory = op[0] < 0xf0; opTargetMemory = !opSourceMemory; - read8(); - if((op[1] & 3) == 0) { mode = IndirectRegister; register = read8(); } - if((op[1] & 3) == 1) { mode = IndirectRegisterDisplacementWord; register = read8(); displacement = (int16)read16(); } - if(op[1] == 0x03) { mode = IndirectRegisterRegisterByte; register = read8(); registerAlt = read8(); } - if(op[1] == 0x07) { mode = IndirectRegisterRegisterWord; register = read8(); registerAlt = read16(); } - break; + opSourceMemory = fetch < 0xf0; opTargetMemory = !opSourceMemory; + lhs.indirectImmediate24(opcodeSizes[fetch >> 4], read24()); break; + case 0xc3: case 0xd3: case 0xe3: case 0xf3: { + opSourceMemory = fetch < 0xf0; opTargetMemory = !opSourceMemory; + auto data = read8(); + if((uint2)data == 0) lhs.indirectRegister(opcodeSizes[fetch >> 4], data); + if((uint2)data == 1) lhs.indirectRegisterDisplacement16(opcodeSizes[fetch >> 4], data, read16()); + if(data == 0x03) { auto r32 = read8(); lhs.indirectRegisterRegister8(opcodeSizes[fetch >> 4], r32, read8()); } + if(data == 0x07) { auto r32 = read8(); lhs.indirectRegisterRegister16(opcodeSizes[fetch >> 4], r32, read16()); } + } break; case 0xc4: case 0xd4: case 0xe4: case 0xf4: - opSourceMemory = op[0] < 0xf0; opTargetMemory = !opSourceMemory; mode = IndirectRegisterDecrement; size = op[0] >> 4; - register = read8(); break; + opSourceMemory = fetch < 0xf0; opTargetMemory = !opSourceMemory; + lhs.indirectRegisterDecrement(opcodeSizes[fetch >> 4], read8()); break; case 0xc5: case 0xd5: case 0xe5: case 0xf5: - opSourceMemory = op[0] < 0xf0; opTargetMemory = !opSourceMemory; mode = IndirectRegisterIncrement; size = op[0] >> 4; - register = read8(); break; + opSourceMemory = fetch < 0xf0; opTargetMemory = !opSourceMemory; + lhs.indirectRegisterIncrement(opcodeSizes[fetch >> 4], read8()); break; case 0xc6: case 0xd6: case 0xe6: case 0xf6: break; case 0xc7: case 0xd7: case 0xe7: - opRegister = true; mode = Register; size = op[0] >> 4; - register = read8(); break; + opRegister = true; + lhs.indirectRegister(opcodeSizes[fetch >> 4], read8()); break; case 0xf7: - name = "ldx"; mode = IndirectImmediateImmediate; size = Byte; - read8(); indirectImmediate = read8(); read8(); immediate = read8(); read8(); break; + name = "ldx"; + read8(); lhs.indirectImmediate8(8, read8()); + read8(); rhs.immediate(8, read8()); + read8(); break; case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: - opRegister = true; mode = Register; size = Byte; - register = toRegister3(op[0]).id; break; + opRegister = true; lhs.register3(8, fetch); break; case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: - opRegister = true; mode = Register; size = Word; - register = toRegister3(op[0]).id; break; + opRegister = true; lhs.register3(16, fetch); break; case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: - opRegister = true; mode = Register; size = Long; - register = toRegister3(op[0]).id; break; + opRegister = true; lhs.register3(32, fetch); break; case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: - name = "swi"; mode = Immediate; size = Byte; - immediate = (uint3)op[0]; break; + name = "swi"; lhs.immediate(3, (uint3)fetch); break; } - auto reads = [&]() -> uint32 { - if(size == Byte) return read8(); - if(size == Word) return read16(); - if(size == Long) return read24(); - return 0; - }; - - auto toRegister3s = [&](uint3 data) -> uint8 { - if(size == Byte) return toRegister3< uint8>(data).id; - if(size == Word) return toRegister3(data).id; - if(size == Long) return toRegister3(data).id; + auto reads = [&](uint size) -> uint32 { + if(size == 8) return read8(); + if(size == 16) return read16(); + if(size == 24) return read24(); + if(size == 32) return read32(); return 0; }; //size defined if(opRegister) - switch(read8()) { + switch(auto fetch = read8()) { case 0x00: case 0x01: case 0x02: break; - case 0x03: name = "ld"; mode = RegisterImmediate; immediate = reads(); break; - case 0x04: name = "push"; mode = Register; break; - case 0x05: name = "pop"; mode = Register; break; - case 0x06: name = "cpl"; mode = Register; break; - case 0x07: name = "neg"; mode = Register; break; - case 0x08: name = "mul"; mode = RegisterWordImmediate; immediate = reads(); break; - case 0x09: name = "muls"; mode = RegisterWordImmediate; immediate = reads(); break; - case 0x0a: name = "div"; mode = RegisterWordImmediate; immediate = reads(); break; - case 0x0b: name = "divs"; mode = RegisterWordImmediate; immediate = reads(); break; - case 0x0c: name = "link"; mode = RegisterDisplacementWord; displacement = (int16)read16(); break; - case 0x0d: name = "unlk"; mode = Register; break; - case 0x0e: name = "bs1f"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0x0f: name = "bs1b"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0x10: name = "daa"; mode = Register; break; + case 0x03: name = "ld"; rhs.immediate(lhs.size(), reads(lhs.size())); break; + case 0x04: name = "push"; break; + case 0x05: name = "pop"; break; + case 0x06: name = "cpl"; break; + case 0x07: name = "neg"; break; + case 0x08: name = "mul"; rhs.immediate(lhs.size(), reads(lhs.size())); lhs.register3(16, op[0]); break; + case 0x09: name = "muls"; rhs.immediate(lhs.size(), reads(lhs.size())); lhs.register3(16, op[0]); break; + case 0x0a: name = "div"; rhs.immediate(lhs.size(), reads(lhs.size())); lhs.register3(16, op[0]); break; + case 0x0b: name = "divs"; rhs.immediate(lhs.size(), reads(lhs.size())); lhs.register3(16, op[0]); break; + case 0x0c: name = "link"; rhs.displacement(16, read16()); break; + case 0x0d: name = "unlk"; break; + case 0x0e: name = "bs1f"; rhs = lhs; lhs.register(8, A.id); break; + case 0x0f: name = "bs1b"; rhs = lhs; lhs.register(8, A.id); break; + case 0x10: name = "daa"; break; case 0x11: break; - case 0x12: name = "extz"; mode = Register; break; - case 0x13: name = "exts"; mode = Register; break; - case 0x14: name = "paa"; mode = Register; break; + case 0x12: name = "extz"; break; + case 0x13: name = "exts"; break; + case 0x14: name = "paa"; break; case 0x15: break; - case 0x16: name = "mirr"; mode = Register; break; + case 0x16: name = "mirr"; break; case 0x17: case 0x18: break; - case 0x19: name = "mula"; mode = Register; break; + case 0x19: name = "mula"; break; case 0x1a: case 0x1b: break; - case 0x1c: name = "djnz"; mode = RegisterDisplacementByte; displacement = (int8)read8(); break; + case 0x1c: name = "djnz"; rhs.displacement(8, read8()); break; case 0x1d: case 0x1e: case 0x1f: break; - case 0x20: name = "andcf"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0x21: name = "orcf"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0x22: name = "xorcf"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0x23: name = "ldcf"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0x24: name = "stcf"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; + case 0x20: name = "andcf"; rhs.immediate(4, (uint4)read8()); break; + case 0x21: name = "orcf"; rhs.immediate(4, (uint4)read8()); break; + case 0x22: name = "xorcf"; rhs.immediate(4, (uint4)read8()); break; + case 0x23: name = "ldcf"; rhs.immediate(4, (uint4)read8()); break; + case 0x24: name = "stcf"; rhs.immediate(4, (uint4)read8()); break; case 0x25: case 0x26: case 0x27: break; - case 0x28: name = "andcf"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0x29: name = "orcf"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0x2a: name = "xorcf"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0x2b: name = "ldcf"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0x2c: name = "stcf"; mode = RegisterAltByteRegister; registerAlt = A.id; break; + case 0x28: name = "andcf"; rhs.register(8, A.id); break; + case 0x29: name = "orcf"; rhs.register(8, A.id); break; + case 0x2a: name = "xorcf"; rhs.register(8, A.id); break; + case 0x2b: name = "ldcf"; rhs.register(8, A.id); break; + case 0x2c: name = "stcf"; rhs.register(8, A.id); break; case 0x2d: break; - case 0x2e: name = "ldc"; mode = ControlRegisterRegister; controlRegister = read8(); break; - case 0x2f: name = "ldc"; mode = RegisterControlRegister; controlRegister = read8(); break; - case 0x30: name = "res"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0x31: name = "set"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0x32: name = "chg"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0x33: name = "bit"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0x34: name = "tset"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; + case 0x2e: name = "ldc"; rhs = lhs; lhs.control(rhs.size(), read8()); break; + case 0x2f: name = "ldc"; rhs.control(lhs.size(), read8()); break; + case 0x30: name = "res"; rhs.immediate(4, (uint4)read8()); break; + case 0x31: name = "set"; rhs.immediate(4, (uint4)read8()); break; + case 0x32: name = "chg"; rhs.immediate(4, (uint4)read8()); break; + case 0x33: name = "bit"; rhs.immediate(4, (uint4)read8()); break; + case 0x34: name = "tset"; rhs.immediate(4, (uint4)read8()); break; case 0x35: case 0x36: case 0x37: break; - case 0x38: name = "minc1"; mode = RegisterImmediateWord; immediate = read16(); break; - case 0x39: name = "minc2"; mode = RegisterImmediateWord; immediate = read16(); break; - case 0x3a: name = "minc4"; mode = RegisterImmediateWord; immediate = read16(); break; + case 0x38: name = "minc1"; rhs.immediate(16, read16()); break; + case 0x39: name = "minc2"; rhs.immediate(16, read16()); break; + case 0x3a: name = "minc4"; rhs.immediate(16, read16()); break; case 0x3b: break; - case 0x3c: name = "mdec1"; mode = RegisterImmediateWord; immediate = read16(); break; - case 0x3d: name = "mdec2"; mode = RegisterImmediateWord; immediate = read16(); break; - case 0x3e: name = "mdec4"; mode = RegisterImmediateWord; immediate = read16(); break; + case 0x3c: name = "mdec1"; rhs.immediate(16, read16()); break; + case 0x3d: name = "mdec2"; rhs.immediate(16, read16()); break; + case 0x3e: name = "mdec4"; rhs.immediate(16, read16()); break; case 0x3f: break; case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: - name = "mul"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; + name = "mul"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: - name = "muls"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; + name = "muls"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: - name = "div"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; + name = "div"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: - name = "divs"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; + name = "divs"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: - name = "inc"; mode = ImmediateByteRegister; immediate = (uint3)op[1]; if(!immediate) immediate = 8; break; + name = "inc"; rhs.immediate(4, fetch ? natural((uint3)fetch) : 8_n); break; case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: - name = "dec"; mode = ImmediateByteRegister; immediate = (uint3)op[1]; if(!immediate) immediate = 8; break; + name = "dec"; rhs.immediate(4, fetch ? natural((uint3)fetch) : 8_n); break; case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: - name = "scc"; mode = ConditionRegister; condition = (uint4)op[1]; break; + name = "scc"; rhs = lhs; lhs.condition(fetch); break; case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: - name = "add"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; + name = "add"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: - name = "ld"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; + name = "ld"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: - name = "adc"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; + name = "adc"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: - name = "ld"; mode = RegisterRegisterAlt; registerAlt = toRegister3s(op[1]); break; + name = "ld"; rhs.register3(lhs.size(), fetch); break; case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: - name = "sub"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; + name = "sub"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: - name = "ld"; mode = RegisterImmediateByte; immediate = (uint3)op[1]; break; + name = "ld"; rhs.immediate(3, (uint3)fetch); break; case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: - name = "sbb"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; + name = "sbb"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: - name = "ex"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; + name = "ex"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: - name = "and"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; - case 0xc8: name = "add"; mode = RegisterImmediate; immediate = reads(); break; - case 0xc9: name = "adc"; mode = RegisterImmediate; immediate = reads(); break; - case 0xca: name = "sub"; mode = RegisterImmediate; immediate = reads(); break; - case 0xcb: name = "sbb"; mode = RegisterImmediate; immediate = reads(); break; - case 0xcc: name = "and"; mode = RegisterImmediate; immediate = reads(); break; - case 0xcd: name = "xor"; mode = RegisterImmediate; immediate = reads(); break; - case 0xce: name = "or"; mode = RegisterImmediate; immediate = reads(); break; - case 0xcf: name = "cp"; mode = RegisterImmediate; immediate = reads(); break; + name = "and"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0xc8: name = "add"; rhs.immediate(lhs.size(), reads(lhs.size())); break; + case 0xc9: name = "adc"; rhs.immediate(lhs.size(), reads(lhs.size())); break; + case 0xca: name = "sub"; rhs.immediate(lhs.size(), reads(lhs.size())); break; + case 0xcb: name = "sbb"; rhs.immediate(lhs.size(), reads(lhs.size())); break; + case 0xcc: name = "and"; rhs.immediate(lhs.size(), reads(lhs.size())); break; + case 0xcd: name = "xor"; rhs.immediate(lhs.size(), reads(lhs.size())); break; + case 0xce: name = "or"; rhs.immediate(lhs.size(), reads(lhs.size())); break; + case 0xcf: name = "cp"; rhs.immediate(lhs.size(), reads(lhs.size())); break; case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: - name = "xor"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; + name = "xor"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: - name = "cp"; mode = RegisterImmediateByte; immediate = (uint3)op[1]; break; + name = "cp"; rhs.immediate(3, (uint3)fetch); break; case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: - name = "or"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; - case 0xe8: name = "rlc"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0xe9: name = "rrc"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0xea: name = "rl"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0xeb: name = "rr"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0xec: name = "sla"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0xed: name = "sra"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0xee: name = "sll"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; - case 0xef: name = "srl"; mode = RegisterImmediateByte; immediate = (uint4)read8(); break; + name = "or"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0xe8: name = "rlc"; { auto data = read8(); rhs.immediate(5, data ? natural(data) : 16_n); } break; + case 0xe9: name = "rrc"; { auto data = read8(); rhs.immediate(5, data ? natural(data) : 16_n); } break; + case 0xea: name = "rl"; { auto data = read8(); rhs.immediate(5, data ? natural(data) : 16_n); } break; + case 0xeb: name = "rr"; { auto data = read8(); rhs.immediate(5, data ? natural(data) : 16_n); } break; + case 0xec: name = "sla"; { auto data = read8(); rhs.immediate(5, data ? natural(data) : 16_n); } break; + case 0xed: name = "sra"; { auto data = read8(); rhs.immediate(5, data ? natural(data) : 16_n); } break; + case 0xee: name = "sll"; { auto data = read8(); rhs.immediate(5, data ? natural(data) : 16_n); } break; + case 0xef: name = "srl"; { auto data = read8(); rhs.immediate(5, data ? natural(data) : 16_n); } break; case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: - name = "cp"; mode = RegisterAltRegister; registerAlt = toRegister3s(op[1]); break; - case 0xf8: name = "rlc"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0xf9: name = "rrc"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0xfa: name = "rl"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0xfb: name = "rr"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0xfc: name = "sla"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0xfd: name = "sra"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0xfe: name = "sll"; mode = RegisterAltByteRegister; registerAlt = A.id; break; - case 0xff: name = "srl"; mode = RegisterAltByteRegister; registerAlt = A.id; break; + name = "cp"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0xf8: name = "rlc"; rhs.register(8, A.id); break; + case 0xf9: name = "rrc"; rhs.register(8, A.id); break; + case 0xfa: name = "rl"; rhs.register(8, A.id); break; + case 0xfb: name = "rr"; rhs.register(8, A.id); break; + case 0xfc: name = "sla"; rhs.register(8, A.id); break; + case 0xfd: name = "sra"; rhs.register(8, A.id); break; + case 0xfe: name = "sll"; rhs.register(8, A.id); break; + case 0xff: name = "srl"; rhs.register(8, A.id); break; } //size defined if(opSourceMemory) - switch(read8()) { + switch(auto fetch = read8()) { case 0x00: case 0x01: case 0x02: case 0x03: break; + case 0x04: name = "push"; break; case 0x05: break; + case 0x06: name = "rld"; rhs = lhs; lhs.register(8, A.id); break; + case 0x07: name = "rrd"; rhs = lhs; lhs.register(8, A.id); break; case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: break; + case 0x10: + name = lhs.size() == 8 ? "ldi" : "ldiw"; + lhs.indirectRegisterIncrement(32, (uint3)op[0] != 5 ? XDE.id : XIX.id); + rhs.indirectRegisterIncrement(32, (uint3)op[0] != 5 ? XHL.id : XIY.id); + break; + case 0x11: + name = lhs.size() == 8 ? "ldir" : "ldirw"; + lhs.indirectRegisterIncrement(32, (uint3)op[0] != 5 ? XDE.id : XIX.id); + rhs.indirectRegisterIncrement(32, (uint3)op[0] != 5 ? XHL.id : XIY.id); + break; + case 0x12: + name = lhs.size() == 8 ? "ldd" : "lddw"; + lhs.indirectRegisterIncrement(32, (uint3)op[0] != 5 ? XDE.id : XIX.id); + rhs.indirectRegisterIncrement(32, (uint3)op[0] != 5 ? XHL.id : XIY.id); + break; + case 0x13: + name = lhs.size() == 8 ? "lddr" : "lddrw"; + lhs.indirectRegisterIncrement(32, (uint3)op[0] != 5 ? XDE.id : XIX.id); + rhs.indirectRegisterIncrement(32, (uint3)op[0] != 5 ? XHL.id : XIY.id); + break; + case 0x14: + name = lhs.size() == 8 ? "cpi" : "cpiw"; + lhs.indirectRegister3Increment(32, op[0]); + rhs.register(lhs.size(), lhs.size() == 8 ? A.id : WA.id); + break; + case 0x15: + name = lhs.size() == 8 ? "cpir" : "cpirw"; + lhs.indirectRegister3Increment(32, op[0]); + rhs.register(lhs.size(), lhs.size() == 8 ? A.id : WA.id); + break; + case 0x16: + name = lhs.size() == 8 ? "cpd" : "cpdw"; + lhs.indirectRegister3Increment(32, op[0]); + rhs.register(lhs.size(), lhs.size() == 8 ? A.id : WA.id); + break; + case 0x17: + name = lhs.size() == 8 ? "cpdr" : "cpdrw"; + lhs.indirectRegister3Increment(32, op[0]); + rhs.register(lhs.size(), lhs.size() == 8 ? A.id : WA.id); + break; case 0x18: break; + case 0x19: name = "ld"; rhs = lhs; lhs.indirectImmediate16(16, read16()); break; case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: break; + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + name = "ld"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: break; + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: + name = "ex"; rhs.register3(lhs.size(), fetch); break; + case 0x38: name = "add"; rhs.immediate(3, (uint3)fetch); break; + case 0x39: name = "adc"; rhs.immediate(3, (uint3)fetch); break; + case 0x3a: name = "sub"; rhs.immediate(3, (uint3)fetch); break; + case 0x3b: name = "sbb"; rhs.immediate(3, (uint3)fetch); break; + case 0x3c: name = "and"; rhs.immediate(3, (uint3)fetch); break; + case 0x3d: name = "xor"; rhs.immediate(3, (uint3)fetch); break; + case 0x3e: name = "or"; rhs.immediate(3, (uint3)fetch); break; + case 0x3f: name = "cp"; rhs.immediate(3, (uint3)fetch); break; + case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: + name = "mul"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: + name = "muls"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: + name = "div"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: + name = "divs"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: + name = "inc"; rhs.immediate(4, (uint3)fetch ? natural((uint3)fetch) : 8_n); break; + case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: + name = "dec"; rhs.immediate(4, (uint3)fetch ? natural((uint3)fetch) : 8_n); break; case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: break; + case 0x78: name = "rlc"; break; + case 0x79: name = "rrc"; break; + case 0x7a: name = "rl"; break; + case 0x7b: name = "rr"; break; + case 0x7c: name = "sla"; break; + case 0x7d: name = "sra"; break; + case 0x7e: name = "sll"; break; + case 0x7f: name = "srl"; break; + case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: + name = "add"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: + name = "add"; rhs.register3(lhs.size(), fetch); break; + case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: + name = "adc"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: + name = "adc"; rhs.register3(lhs.size(), fetch); break; + case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: + name = "sub"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: + name = "sub"; rhs.register3(lhs.size(), fetch); break; + case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: + name = "sbb"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: + name = "sbb"; rhs.register3(lhs.size(), fetch); break; + case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: + name = "and"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: + name = "and"; rhs.register3(lhs.size(), fetch); break; + case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: + name = "xor"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: + name = "xor"; rhs.register3(lhs.size(), fetch); break; + case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: + name = "or"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: + name = "or"; rhs.register3(lhs.size(), fetch); break; + case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: + name = "cp"; rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: + name = "cp"; rhs.register3(lhs.size(), fetch); break; } //size undefined if(opTargetMemory) - switch(read8()) { + switch(auto fetch = read8()) { + case 0x00: name = "ld"; lhs.size(8); rhs.immediate(8, read8()); break; case 0x01: break; + case 0x02: name = "ld"; lhs.size(16); rhs.immediate(16, read16()); break; case 0x03: break; + case 0x04: name = "pop"; lhs.size(8); break; case 0x05: break; + case 0x06: name = "pop"; lhs.size(16); break; case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: break; case 0x10: case 0x11: case 0x12: case 0x13: break; + case 0x14: name = "ld"; lhs.size(8); rhs.indirectImmediate16(16, read16()); break; case 0x15: break; + case 0x16: name = "ld"; lhs.size(16); rhs.indirectImmediate16(16, read16()); break; case 0x17: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: break; + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + name = "lda"; lhs.size(16); rhs = lhs; lhs.register3(rhs.size(), fetch); break; + case 0x28: name = "andcf"; rhs.register3(8, A.id); break; + case 0x29: name = "orcf"; rhs.register3(8, A.id); break; + case 0x2a: name = "xorcf"; rhs.register3(8, A.id); break; + case 0x2b: name = "ldcf"; rhs.register3(8, A.id); break; + case 0x2c: name = "stcf"; rhs.register3(8, A.id); break; case 0x2d: case 0x2e: case 0x2f: break; + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: + name = "lda"; lhs.size(32); rhs = lhs; lhs.register3(rhs.size(), fetch); break; case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: break; + case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: + name = "ld"; lhs.size(8); rhs.register3(lhs.size(), fetch); break; case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: break; + case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: + name = "ld"; lhs.size(16); rhs.register3(lhs.size(), fetch); break; case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: break; + case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: + name = "ld"; lhs.size(32); rhs.register3(lhs.size(), fetch); break; case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: break; case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: break; case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: break; + case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: + name = "andcf"; lhs.size(8); rhs.immediate(3, (uint3)fetch); break; + case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: + name = "orcf"; lhs.size(8); rhs.immediate(3, (uint3)fetch); break; + case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: + name = "xorcf"; lhs.size(8); rhs.immediate(3, (uint3)fetch); break; + case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: + name = "ldcf"; lhs.size(8); rhs.immediate(3, (uint3)fetch); break; + case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: + name = "stcf"; lhs.size(8); rhs.immediate(3, (uint3)fetch); break; + case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: + name = "tset"; lhs.size(8); rhs.immediate(3, (uint3)fetch); break; + case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: + name = "res"; lhs.size(8); rhs.immediate(3, (uint3)fetch); break; + case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: + name = "set"; lhs.size(8); rhs.immediate(3, (uint3)fetch); break; + case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: + name = "chg"; lhs.size(8); rhs.immediate(3, (uint3)fetch); break; + case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: + name = "bit"; lhs.size(8); rhs.immediate(3, (uint3)fetch); break; + case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: + name = "jp"; rhs = lhs; lhs.condition(fetch); break; + case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: + name = "call"; rhs = lhs; lhs.condition(fetch); break; + case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: + name = "ret"; lhs.condition(fetch); break; + } + + auto operand = [&](Operand& operand) -> string { + static const string registers8[] = { + "ra0", "rw0", "qa0", "qw0", "rc0", "rb0", "qc0", "qb0", "re0", "rd0", "qe0", "qd0", "rl0", "rh0", "ql0", "qh0", //00-1f + "ra1", "rw1", "qa1", "qw1", "rc1", "rb1", "qc1", "qb1", "re1", "rd1", "qe1", "qd1", "rl1", "rh1", "ql1", "qh1", //10-1f + "ra2", "rw2", "qa2", "qw2", "rc2", "rb2", "qc2", "qb2", "re2", "rd2", "qe2", "qd2", "rl2", "rh2", "ql2", "qh2", //20-2f + "ra3", "rw3", "qa3", "qw3", "rc3", "rb3", "qc3", "qb3", "re3", "rd3", "qe3", "qd3", "rl3", "rh3", "ql3", "qh3", //30-3f + "a'", "w'", "qa'", "qw'", "c'", "b'", "qc'", "qb'", "e'", "d'", "qe'", "qd'", "l'", "h'", "ql'", "qh'", //d0-df + "a", "w", "qa", "qw", "c", "b", "qc", "qb", "e", "d", "eq", "qd", "l", "h", "ql", "qh", //e0-ef + "ixl", "ixh", "qixl","qixh","iyl", "iyh", "qiyl","qiyh","izl", "izh", "qizl","qizh","spl", "sph", "qspl","qsph", //f0-ff + }; + auto register8 = [](uint8 register) -> string { + if(register < 0x40) return registers8[register]; + if(register >= 0xd0) return registers8[register - 0x80]; + return "rb?"; + }; + + static const string registers16[] = { + "rwa0", "qwa0", "rbc0", "qbc0", "rde0", "qde0", "rhl0", "qhl0", //00-0f + "rwa1", "qwa1", "rbc1", "qbc1", "rde1", "qde1", "rhl1", "qhl1", //10-1f + "rwa2", "qwa2", "rbc2", "qbc2", "rde2", "qde2", "rhl2", "qhl2", //20-2f + "rwa3", "qwa3", "rbc3", "qbc3", "rde3", "qde3", "rhl3", "qhl3", //30-3f + "rwa'", "qwa'", "rbc'", "qbc'", "rde'", "qde'", "rhl'", "qhl'", //d0-df + "rwa", "qwa", "rbc", "qbc", "rde", "qde", "rhl", "qhl", //e0-ef + "ix", "qix", "iy", "qiy", "iz", "qiz", "sp", "qsp", //f0-ff + }; + auto register16 = [](uint8 register) -> string { + if(register < 0x40) return registers16[register >> 1]; + if(register >= 0xd0) return registers16[register - 0x80 >> 1]; + return "rw?"; + }; + + static const string registers32[] = { + "xwa0", "xbc0", "xde0", "xhl0", //00-0f + "xwa1", "xbc1", "xde1", "xhl1", //10-1f + "xwa2", "xbc2", "xde2", "xhl2", //20-2f + "xwa3", "xbc3", "xde3", "xhl3", //30-3f + "xwa'", "xbc'", "xde'", "xhl'", //d0-df + "xwa", "xbc", "xde", "xhl", //e0-ef + "xix", "xiy", "xiz", "xsp", //f0-ff + }; + auto register32 = [&](uint8 register) -> string { + if(register < 0x40) return registers32[register >> 2]; + if(register >= 0xd0) return registers32[register - 0x80 >> 2]; + return "rl?"; + }; + + //there are no names for byte-accesses to control registers + auto control8 = [](uint8 register) -> string { + return {"c", hex(register, 2L)}; + }; + + static string controls16[] = { + "dmas0l", "dmas0h", "dmas1l", "dmas1h", "dmas2l", "dmas2h", "dmas3l", "dmas3h", //00-0f + "dmad0l", "dmad0h", "dmad1l", "dmad1h", "dmad2l", "dmad2h", "dmad3l", "dmad3h", //10-1f + "dmac0", "dmac0h", "dmac1", "dmac1h", "dmac2", "dmac2h", "dmac3", "dmac3h", //20-2f + }; + auto control16 = [](uint8 register) -> string { + if(register < 0x30) return controls16[register >> 1]; + if(register >= 0x3c || register <= 0x3d) return "intnest"; + return "cw?"; + }; + + static string controls32[] = { + "dmas0", "dmas1", "dmas2", "dmas3", //00-0f + "dmad0", "dmad1", "dmad2", "dmad3", //10-1f + "dmam0", "dmam1", "dmam2", "dmam3", //20-2f + }; + auto control32 = [](uint8 register) -> string { + if(register < 0x30) return controls32[register >> 2]; + if(register >= 0x3c && register <= 0x3f) return "intnest"; + return "cl?"; + }; + + if(operand.mode() == Text) return operand.text(); + if(operand.mode() == Condition) { + static const string conditions[] = { + "f", "lt", "le", "ule", "ov", "mi", "eq", "ult", + "t", "ge", "gt", "ugt", "nov", "pl", "ne", "uge", + }; + return conditions[operand.condition()]; + } + if(operand.mode() == Register) { + if(operand.size() == 8) return register8(operand.register()); + if(operand.size() == 16) return register16(operand.register()); + if(operand.size() == 32) return register32(operand.register()); + } + if(operand.mode() == Control) { + if(operand.size() == 8) return control8(operand.register()); + if(operand.size() == 16) return control16(operand.register()); + if(operand.size() == 32) return control32(operand.register()); + } + if(operand.mode() == Immediate) { + if(operand.size() <= 7) return {operand.immediate()}; + if(operand.size() == 8) return {"0x", hex(operand.immediate(), 2L)}; + if(operand.size() == 16) return {"0x", hex(operand.immediate(), 4L)}; + if(operand.size() == 24) return {"0x", hex(operand.immediate(), 6L)}; + if(operand.size() == 32) return {"0x", hex(operand.immediate(), 8L)}; + } + if(operand.mode() == Displacement) { + if(operand.size() == 8) { + integer displacement = (int8)operand.displacement(); + if(displacement < 0) return {"-0x", hex(-displacement, 2L)}; + return {"+0x", hex(displacement, 2L)}; + } + if(operand.size() == 16) { + integer displacement = (int8)operand.displacement(); + if(displacement < 0) return {"-0x", hex(-displacement, 4L)}; + return {"+0x", hex(displacement, 4L)}; + } + } + if(operand.mode() == DisplacementPC) { + if(operand.size() == 8) { + natural displacement = pc + (int8)operand.displacement(); + return {"0x", hex(displacement, 6L)}; + } + if(operand.size() == 16) { + natural displacement = pc + (int16)operand.displacement(); + return {"0x", hex(displacement, 6L)}; + } + } + if(operand.mode() == IndirectRegister) return {"(", register32(operand.register()), ")"}; + if(operand.mode() == IndirectRegisterDecrement) return {"(-", register32(operand.register()), ")"}; + if(operand.mode() == IndirectRegisterIncrement) return {"(", register32(operand.register()), "+)"}; + if(operand.mode() == IndirectRegisterRegister8) return {"(", register32(operand.register()), "+", register8(operand.registerAdd()), ")"}; + if(operand.mode() == IndirectRegisterRegister16) return {"(", register32(operand.register()), "+", register16(operand.registerAdd()), ")"}; + if(operand.mode() == IndirectRegisterDisplacement8) { + integer displacement = (int8)operand.displacement(); + if(displacement < 0) return {"(", register32(operand.register()), "-0x", hex(-displacement, 2L), ")"}; + return {"(", register32(operand.register()), "+0x", hex(displacement, 2L), ")"}; + } + if(operand.mode() == IndirectRegisterDisplacement16) { + integer displacement = (int16)operand.displacement(); + if(displacement < 0) return {"(", register32(operand.register()), "-0x", hex(-displacement, 4L), ")"}; + return {"(", register32(operand.register()), "+0x", hex(displacement, 4L), ")"}; + } + if(operand.mode() == IndirectImmediate8) return {"(0x", hex(operand.immediate(), 2L), ")"}; + if(operand.mode() == IndirectImmediate16) return {"(0x", hex(operand.immediate(), 4L), ")"}; + if(operand.mode() == IndirectImmediate24) return {"(0x", hex(operand.immediate(), 6L), ")"}; + return {}; + }; + + if(name) { + output.append(pad(name, -6)); + if(lhs) { + output.append(operand(lhs), ","); + if(rhs) { + output.append(operand(rhs)); + } + } + } else { + output.append(pad("???", -6)); + for(auto byte : range(ops)) output.append(hex(op[byte], 2L), " "); } output.size(-48); + output.append("XWA:", hex(r.xwa[r.rfp].l.l0, 8L), " "); + output.append("XBC:", hex(r.xbc[r.rfp].l.l0, 8L), " "); + output.append("XDE:", hex(r.xde[r.rfp].l.l0, 8L), " "); + output.append("XHL:", hex(r.xhl[r.rfp].l.l0, 8L), " "); + output.append("XIX:", hex(r.xix.l.l0, 8L), " "); + output.append("XIY:", hex(r.xiy.l.l0, 8L), " "); + output.append("XIZ:", hex(r.xiz.l.l0, 8L), " "); + output.append("XSP:", hex(r.xsp.l.l0, 8L), " "); output.append("I", r.iff); output.append("R", r.rfp); output.append(r.s ? "S" : "s"); diff --git a/higan/processor/tlcs900h/instruction.cpp b/higan/processor/tlcs900h/instruction.cpp index 9845b1f4..a2234953 100644 --- a/higan/processor/tlcs900h/instruction.cpp +++ b/higan/processor/tlcs900h/instruction.cpp @@ -17,7 +17,7 @@ template auto TLCS900H::toRegister8(uint8 code) const -> Register template auto TLCS900H::toControlRegister(uint8 code) const -> ControlRegister { return {code}; } template auto TLCS900H::toMemory(uint32 address) const -> Memory { return {address}; } template auto TLCS900H::toImmediate(uint32 constant) const -> Immediate { return {constant}; } -template auto TLCS900H::toImmediate3(uint3 constant) const -> Immediate { return {constant ? (uint)constant : 8u}; } +template auto TLCS900H::toImmediate3(natural constant) const -> Immediate { return {constant.clip(3).orElse(8)}; } //note: much of this code is split to multiple statements due to C++ not guaranteeing //the order of evaluations of function arguments. fetch() ordering is critical. @@ -529,7 +529,7 @@ auto TLCS900H::instructionSourceMemory(M memory) -> void { case 0x18: return (void)Undefined; case 0x19: if constexpr(bits == 32) return (void)Undefined; - return instructionLoad(fetchMemory(), memory); + return instructionLoad(fetchMemory(), memory); case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: return (void)Undefined; case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: return instructionLoad(toRegister3(data), memory); @@ -657,7 +657,7 @@ auto TLCS900H::instructionTargetMemory(uint32 address) -> void { case 0x17: return (void)Undefined; case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: return (void)Undefined; case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: - return instructionLoad(toRegister3(data), toMemory(address)); + return instructionLoad(toRegister3(data), toImmediate(address)); case 0x28: return instructionAndCarry(toMemory(address), A); case 0x29: return instructionOrCarry(toMemory(address), A); case 0x2a: return instructionXorCarry(toMemory(address), A); @@ -665,7 +665,7 @@ auto TLCS900H::instructionTargetMemory(uint32 address) -> void { case 0x2c: return instructionStoreCarry(toMemory(address), A); case 0x2d: case 0x2e: case 0x2f: return (void)Undefined; case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: - return instructionLoad(toRegister3(data), toMemory(address)); + return instructionLoad(toRegister3(data), toImmediate(address)); case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: return (void)Undefined; case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: return instructionLoad(toMemory(address), toRegister3(data)); @@ -700,10 +700,10 @@ auto TLCS900H::instructionTargetMemory(uint32 address) -> void { return instructionBit(toMemory(address), toImmediate(data)); case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: - return instructionJump((uint4)data, toMemory(address)); + return instructionJump((uint4)data, toImmediate(address)); case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: - return instructionCall((uint4)data, toMemory(address)); + return instructionCall((uint4)data, toImmediate(address)); case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: return instructionReturn((uint4)data); diff --git a/higan/processor/tlcs900h/instructions.cpp b/higan/processor/tlcs900h/instructions.cpp index b69b975d..7d82ade7 100644 --- a/higan/processor/tlcs900h/instructions.cpp +++ b/higan/processor/tlcs900h/instructions.cpp @@ -158,7 +158,7 @@ auto TLCS900H::instructionExtendZero(Target target) -> void { } auto TLCS900H::instructionHalt() -> void { - setHalted(true); + r.halted = true; } template @@ -349,8 +349,7 @@ auto TLCS900H::instructionRotateLeftDigit(LHS lhs, RHS rhs) -> void { template auto TLCS900H::instructionRotateLeft(Target target, Amount amount) -> void { auto result = load(target); - uint count = (uint4)load(amount); - for(uint n : range(if(count, 16))) { + for(uint n : range(load(amount).clip(4).orElse(16))) { uint cf = result.bit(-1); result = result << 1 | CF; CF = cf; @@ -361,8 +360,7 @@ auto TLCS900H::instructionRotateLeft(Target target, Amount amount) -> void { template auto TLCS900H::instructionRotateLeftWithoutCarry(Target target, Amount amount) -> void { auto result = load(target); - uint count = (uint4)load(amount); - for(uint n : range(if(count, 16))) { + for(uint n : range(load(amount).clip(4).orElse(16))) { CF = result.bit(-1); result = result << 1 | CF; } @@ -389,8 +387,7 @@ auto TLCS900H::instructionRotateRightDigit(LHS lhs, RHS rhs) -> void { template auto TLCS900H::instructionRotateRight(Target target, Amount amount) -> void { auto result = load(target); - uint count = (uint4)load(amount); - for(uint n : range(if(count, 16))) { + for(uint n : range(load(amount).clip(4).orElse(16))) { uint cf = result.bit(0); result = CF << Target::bits - 1 | result >> 1; CF = cf; @@ -401,8 +398,7 @@ auto TLCS900H::instructionRotateRight(Target target, Amount amount) -> void { template auto TLCS900H::instructionRotateRightWithoutCarry(Target target, Amount amount) -> void { auto result = load(target); - uint count = (uint4)load(amount); - for(uint n : range(if(count, 16))) { + for(uint n : range(load(amount).clip(4).orElse(16))) { CF = result.bit(0); result = CF << Target::bits - 1 | result >> 1; } @@ -436,8 +432,7 @@ auto TLCS900H::instructionSetRegisterFilePointer(uint2 value) -> void { template auto TLCS900H::instructionShiftLeftArithmetic(Target target, Amount amount) -> void { auto result = load(target); - uint count = (uint4)load(amount); - for(uint n : range(if(count, 16))) { + for(uint n : range(load(amount).clip(4).orElse(16))) { CF = result.bit(-1); result = result << 1; } @@ -447,8 +442,7 @@ auto TLCS900H::instructionShiftLeftArithmetic(Target target, Amount amount) -> v template auto TLCS900H::instructionShiftLeftLogical(Target target, Amount amount) -> void { auto result = load(target); - uint count = (uint4)load(amount); - for(uint n : range(if(count, 16))) { + for(uint n : range(load(amount).clip(4).orElse(16))) { CF = result.bit(-1); result = result << 1; } @@ -458,8 +452,7 @@ auto TLCS900H::instructionShiftLeftLogical(Target target, Amount amount) -> void template auto TLCS900H::instructionShiftRightArithmetic(Target target, Amount amount) -> void { auto result = load(target); - uint count = (uint4)load(amount); - for(uint n : range(if(count, 16))) { + for(uint n : range(load(amount).clip(4).orElse(16))) { CF = result.bit(0); result = result >> 1; result.bit(-1) = result.bit(-2); @@ -470,8 +463,7 @@ auto TLCS900H::instructionShiftRightArithmetic(Target target, Amount amount) -> template auto TLCS900H::instructionShiftRightLogical(Target target, Amount amount) -> void { auto result = load(target); - uint count = (uint4)load(amount); - for(uint n : range(if(count, 16))) { + for(uint n : range(load(amount).clip(4).orElse(16))) { CF = result.bit(0); result = result >> 1; } diff --git a/higan/processor/tlcs900h/tlcs900h.cpp b/higan/processor/tlcs900h/tlcs900h.cpp index bc39d244..e50461b8 100644 --- a/higan/processor/tlcs900h/tlcs900h.cpp +++ b/higan/processor/tlcs900h/tlcs900h.cpp @@ -1,5 +1,4 @@ #include -#include #include "tlcs900h.hpp" namespace Processor { diff --git a/higan/processor/tlcs900h/tlcs900h.hpp b/higan/processor/tlcs900h/tlcs900h.hpp index e2692725..27398710 100644 --- a/higan/processor/tlcs900h/tlcs900h.hpp +++ b/higan/processor/tlcs900h/tlcs900h.hpp @@ -85,7 +85,7 @@ struct TLCS900H { template auto toControlRegister(uint8) const -> ControlRegister; template auto toMemory(uint32 address) const -> Memory; template auto toImmediate(uint32 constant) const -> Immediate; - template auto toImmediate3(uint3 constant) const -> Immediate; + template auto toImmediate3(natural constant) const -> Immediate; auto instruction() -> void; template auto instructionRegister(Register) -> void; template auto instructionSourceMemory(Memory) -> void; @@ -199,13 +199,10 @@ struct TLCS900H { uint2 rfp; //register file pointer uint3 iff = 7; //interrupt mask flip-flop - uint1 halted; + uint1 halted; //set if halt instruction executed; waits for an interrupt to resume uint8 prefix; //first opcode byte; needed for [CP|LD][ID](R) instructions } r; - auto halted() const -> bool { return r.halted; } - auto setHalted(bool value) -> void { r.halted = value; } - static inline const Register< uint8> A{0xe0}; static inline const Register< uint8> W{0xe1}; static inline const Register< uint8> C{0xe4}; diff --git a/higan/sfc/coprocessor/spc7110/dcu.cpp b/higan/sfc/coprocessor/spc7110/dcu.cpp index c80e013b..b91f2b63 100644 --- a/higan/sfc/coprocessor/spc7110/dcu.cpp +++ b/higan/sfc/coprocessor/spc7110/dcu.cpp @@ -18,7 +18,7 @@ auto SPC7110::dcuBeginTransfer() -> void { decompressor->initialize(dcuMode, dcuAddress); decompressor->decode(); - uint seek = if(r480b & 2, r4805 | r4806 << 8, 0); + uint seek = r480b & 2 ? r4805 | r4806 << 8 : 0; while(seek--) decompressor->decode(); r480c |= 0x80; diff --git a/higan/sfc/coprocessor/spc7110/spc7110.cpp b/higan/sfc/coprocessor/spc7110/spc7110.cpp index 00ba4a71..14425d8f 100644 --- a/higan/sfc/coprocessor/spc7110/spc7110.cpp +++ b/higan/sfc/coprocessor/spc7110/spc7110.cpp @@ -1,5 +1,4 @@ #include -#include namespace SuperFamicom { diff --git a/higan/sfc/ppu-fast/background.cpp b/higan/sfc/ppu-fast/background.cpp index 6a8f617c..6fa0abb2 100644 --- a/higan/sfc/ppu-fast/background.cpp +++ b/higan/sfc/ppu-fast/background.cpp @@ -26,7 +26,7 @@ auto PPU::Line::renderBackground(PPU::IO::Background& self, uint source) -> void uint hmask = (width << self.tileSize << self.screenSize.bit(0)) - 1; uint vmask = (width << self.tileSize << self.screenSize.bit(1)) - 1; - uint y = this->y - if(self.mosaicEnable, this->y % (1 + io.mosaicSize), 0); + uint y = this->y - self.mosaicEnable ? this->y % (1 + io.mosaicSize) : 0; if(hires) { hscroll <<= 1; if(io.interlace) y = y << 1 | ppu.field(); diff --git a/higan/sfc/ppu-fast/mode7.cpp b/higan/sfc/ppu-fast/mode7.cpp index 95455244..eeb3dc16 100644 --- a/higan/sfc/ppu-fast/mode7.cpp +++ b/higan/sfc/ppu-fast/mode7.cpp @@ -1,6 +1,6 @@ auto PPU::Line::renderMode7(PPU::IO::Background& self, uint source) -> void { - int Y = this->y - if(self.mosaicEnable, this->y % (1 + io.mosaicSize), 0); - int y = if(!io.mode7.vflip, Y, 255 - Y); + int Y = this->y - self.mosaicEnable ? this->y % (1 + io.mosaicSize) : 0; + int y = !io.mode7.vflip ? Y : 255 - Y; int a = (int16)io.mode7.a; int b = (int16)io.mode7.b; diff --git a/higan/sfc/ppu-fast/ppu.cpp b/higan/sfc/ppu-fast/ppu.cpp index e3cb1b2d..76a270ff 100644 --- a/higan/sfc/ppu-fast/ppu.cpp +++ b/higan/sfc/ppu-fast/ppu.cpp @@ -1,5 +1,4 @@ #include -#include namespace SuperFamicom { diff --git a/nall/array.hpp b/nall/array.hpp index 598e9b46..c3bd3ea5 100644 --- a/nall/array.hpp +++ b/nall/array.hpp @@ -63,4 +63,22 @@ private: T values[Size]; }; +template auto from_array(uint index) -> T { + static const array table{p...}; + struct out_of_bounds {}; + #if defined(DEBUG) + if(index >= sizeof...(p)) throw out_of_bounds{}; + #endif + return table[index]; +} + +template auto from_array(uint index) -> int64_t { + static const array table{p...}; + struct out_of_bounds {}; + #if defined(DEBUG) + if(index >= sizeof...(p)) throw out_of_bounds{}; + #endif + return table[index]; +} + } diff --git a/nall/inline-if.hpp b/nall/inline-if.hpp index a8be4fe7..34473b97 100644 --- a/nall/inline-if.hpp +++ b/nall/inline-if.hpp @@ -1,4 +1,5 @@ #pragma once +#warning "these defines break if statements with multiple parameters to templates" #define if1(statement) if(statement) #define if2(condition, false) ([](auto&& value) -> decltype(condition) { \ diff --git a/nall/primitives.hpp b/nall/primitives.hpp index 86dfcccc..f954e4e0 100644 --- a/nall/primitives.hpp +++ b/nall/primitives.hpp @@ -5,8 +5,8 @@ namespace nall { struct Boolean; - template struct Natural; - template struct Integer; + template struct Natural; + template struct Integer; } #include @@ -18,6 +18,6 @@ namespace nall { #include namespace nall { - template auto Natural::integer() const -> Integer { return Integer(*this); } - template auto Integer::natural() const -> Natural { return Natural(*this); } + template auto Natural::integer() const -> Integer { return Integer(*this); } + template auto Integer::natural() const -> Natural { return Natural(*this); } } diff --git a/nall/primitives/bit-range.hpp b/nall/primitives/bit-range.hpp index a3ff2ec0..80b1be8d 100644 --- a/nall/primitives/bit-range.hpp +++ b/nall/primitives/bit-range.hpp @@ -2,18 +2,18 @@ namespace nall { -template struct BitRange { - enum : uint { Precision = Requested < 1 ? 1 : Requested > 64 ? 64 : Requested }; +template struct BitRange { + static_assert(Precision >= 1 && Precision <= 64); static inline constexpr auto bits() -> uint { return Precision; } - using type = + using utype = typename conditional::type>::type>::type>::type; - static inline constexpr auto mask() -> type { return ~0ull >> 64 - bits(); } + static inline constexpr auto mask() -> utype { return ~0ull >> 64 - bits(); } - inline BitRange(type& source, int lo, int hi) : source(source) { + inline BitRange(utype& source, int lo, int hi) : source(source) { if(lo < 0) lo = Precision + lo; if(hi < 0) hi = Precision + hi; if(lo > hi) swap(lo, hi); @@ -28,7 +28,7 @@ template struct BitRange { inline auto& operator++() { return set(get() + 1); } inline auto& operator--() { return set(get() - 1); } - inline operator type() const { return get(); } + inline operator utype() const { return get(); } template inline auto& operator =(const T& value) { return set( value); } template inline auto& operator *=(const T& value) { return set(get() * value); } template inline auto& operator /=(const T& value) { return set(get() / value); } @@ -42,20 +42,20 @@ template struct BitRange { template inline auto& operator |=(const T& value) { return set(get() | value); } private: - inline auto get() const -> type { - const type rangeBits = hi - lo + 1; - const type rangeMask = (1ull << rangeBits) - 1 << lo & mask(); + inline auto get() const -> utype { + const utype rangeBits = hi - lo + 1; + const utype rangeMask = (1ull << rangeBits) - 1 << lo & mask(); return (source & rangeMask) >> lo; } - inline auto& set(const type& value) { - const type rangeBits = hi - lo + 1; - const type rangeMask = (1ull << rangeBits) - 1 << lo & mask(); + inline auto& set(const utype& value) { + const utype rangeBits = hi - lo + 1; + const utype rangeMask = (1ull << rangeBits) - 1 << lo & mask(); source = source & ~rangeMask | value << lo & rangeMask; return *this; } - type& source; + utype& source; uint lo; uint hi; }; diff --git a/nall/primitives/integer.hpp b/nall/primitives/integer.hpp index d6e5a77a..39c0c57d 100644 --- a/nall/primitives/integer.hpp +++ b/nall/primitives/integer.hpp @@ -2,15 +2,15 @@ namespace nall { -template struct Integer { +template struct Integer { static_assert(Precision >= 1 && Precision <= 64); static inline constexpr auto bits() -> uint { return Precision; } using stype = - typename conditional::type>::type>::type>::type; + conditional_t>>>; using utype = typename Natural::utype; static inline constexpr auto mask() -> utype { return ~0ull >> 64 - bits(); } static inline constexpr auto sign() -> utype { return 1ull << Precision - 1; } @@ -30,8 +30,8 @@ template struct Integer { inline auto operator!() const { return Integer{!data}; } inline auto operator~() const { return Integer{~data}; } - inline auto operator+() const { return Integer{+data}; } - inline auto operator-() const { return Integer{-data}; } + inline auto operator+() const { return Integer<>{+(int64_t)data}; } + inline auto operator-() const { return Integer<>{-(int64_t)data}; } #define lhs data #define rhs value @@ -54,6 +54,9 @@ template struct Integer { #undef lhs #undef rhs + //warning: this does not and cannot short-circuit; value is always evaluated + template inline auto orElse(const T& value) { return Integer<>{data ? data : value}; } + inline auto bits(int lo, int hi) -> BitRange { return {(utype&)data, lo, hi}; } inline auto bit(int index) -> BitRange { return {(utype&)data, index, index}; } inline auto byte(int index) -> BitRange { return {(utype&)data, index * 8 + 0, index * 8 + 7}; } @@ -62,16 +65,19 @@ template struct Integer { inline auto bit(int index) const -> const BitRange { return {(utype&)*this, index, index}; } inline auto byte(int index) const -> const BitRange { return {(utype&)*this, index * 8 + 0, index * 8 + 7}; } + inline auto slice(int index) const { return Natural<>{bit(index)}; } + inline auto slice(int lo, int hi) const { return Natural<>{bit(lo, hi)}; } + inline auto clamp(uint bits) { - const intmax b = 1ull << (bits - 1); - const intmax m = b - 1; - return Integer<64>{data > m ? m : data < -b ? -b : data}; + const int64_t b = 1ull << (bits - 1); + const int64_t m = b - 1; + return Integer<>{data > m ? m : data < -b ? -b : data}; } inline auto clip(uint bits) { - const uintmax b = 1ull << (bits - 1); - const uintmax m = b * 2 - 1; - return Integer<64>{(data & m ^ b) - b}; + const uint64_t b = 1ull << (bits - 1); + const uint64_t m = b * 2 - 1; + return Integer<>{(data & m ^ b) - b}; } inline auto serialize(serializer& s) { s(data); } @@ -87,16 +93,16 @@ private: #define lhs (int64_t)l #define rhs r -template inline auto operator *(Integer l, Integer r) { return Integer<64>{lhs * rhs}; } -template inline auto operator /(Integer l, Integer r) { return Integer<64>{lhs / rhs}; } -template inline auto operator %(Integer l, Integer r) { return Integer<64>{lhs % rhs}; } -template inline auto operator +(Integer l, Integer r) { return Integer<64>{lhs + rhs}; } -template inline auto operator -(Integer l, Integer r) { return Integer<64>{lhs - rhs}; } -template inline auto operator<<(Integer l, Integer r) { return Integer<64>{lhs << rhs}; } -template inline auto operator>>(Integer l, Integer r) { return Integer<64>{lhs >> rhs}; } -template inline auto operator &(Integer l, Integer r) { return Integer<64>{lhs & rhs}; } -template inline auto operator ^(Integer l, Integer r) { return Integer<64>{lhs ^ rhs}; } -template inline auto operator |(Integer l, Integer r) { return Integer<64>{lhs | rhs}; } +template inline auto operator *(Integer l, Integer r) { return Integer{lhs * rhs}; } +template inline auto operator /(Integer l, Integer r) { return Integer{lhs / rhs}; } +template inline auto operator %(Integer l, Integer r) { return Integer{lhs % rhs}; } +template inline auto operator +(Integer l, Integer r) { return Integer{lhs + rhs}; } +template inline auto operator -(Integer l, Integer r) { return Integer{lhs - rhs}; } +template inline auto operator<<(Integer l, Integer r) { return Integer{lhs << rhs}; } +template inline auto operator>>(Integer l, Integer r) { return Integer{lhs >> rhs}; } +template inline auto operator &(Integer l, Integer r) { return Integer{lhs & rhs}; } +template inline auto operator ^(Integer l, Integer r) { return Integer{lhs ^ rhs}; } +template inline auto operator |(Integer l, Integer r) { return Integer{lhs | rhs}; } #undef lhs #undef rhs diff --git a/nall/primitives/natural.hpp b/nall/primitives/natural.hpp index 285839b3..55c823fb 100644 --- a/nall/primitives/natural.hpp +++ b/nall/primitives/natural.hpp @@ -2,15 +2,15 @@ namespace nall { -template struct Natural { +template struct Natural { static_assert(Precision >= 1 && Precision <= 64); static inline constexpr auto bits() -> uint { return Precision; } using utype = - typename conditional::type>::type>::type>::type; + conditional_t>>>; static inline constexpr auto mask() -> utype { return ~0ull >> 64 - bits(); } inline Natural() : data(0) {} @@ -28,8 +28,8 @@ template struct Natural { inline auto operator!() const { return Natural{!data}; } inline auto operator~() const { return Natural{~data}; } - inline auto operator+() const { return Natural{+data}; } - inline auto operator-() const { return Natural{-data}; } + inline auto operator+() const { return Natural<>{+(uint64_t)data}; } + inline auto operator-() const { return Natural<>{-(uint64_t)data}; } #define lhs data #define rhs value @@ -47,40 +47,8 @@ template struct Natural { #undef lhs #undef rhs - //work in progress: we want naturalprimitive and primitivenatural to result in natural<64> ... - //however, these operators will create ambiguous overloads unless operator uint64_t() is explicit. - //a large volume of existing code will need to be updated before this will be possible. - #if 0 - #define lhs (uint64_t)data - #define rhs value - template inline auto operator *(const T& value) { return Natural<64>{lhs * rhs}; } - template inline auto operator /(const T& value) { return Natural<64>{lhs / rhs}; } - template inline auto operator %(const T& value) { return Natural<64>{lhs % rhs}; } - template inline auto operator +(const T& value) { return Natural<64>{lhs + rhs}; } - template inline auto operator -(const T& value) { return Natural<64>{lhs - rhs}; } - template inline auto operator<<(const T& value) { return Natural<64>{lhs << rhs}; } - template inline auto operator>>(const T& value) { return Natural<64>{lhs >> rhs}; } - template inline auto operator &(const T& value) { return Natural<64>{lhs & rhs}; } - template inline auto operator ^(const T& value) { return Natural<64>{lhs ^ rhs}; } - template inline auto operator |(const T& value) { return Natural<64>{lhs | rhs}; } - #undef lhs - #undef rhs - - #define lhs l - #define rhs (uint64_t)r - template friend inline auto operator *(const T& l, Natural r) { return Natural<64>{lhs * rhs}; } - template friend inline auto operator %(const T& l, Natural r) { return Natural<64>{lhs / rhs}; } - template friend inline auto operator /(const T& l, Natural r) { return Natural<64>{lhs % rhs}; } - template friend inline auto operator +(const T& l, Natural r) { return Natural<64>{lhs + rhs}; } - template friend inline auto operator -(const T& l, Natural r) { return Natural<64>{lhs - rhs}; } - template friend inline auto operator<<(const T& l, Natural r) { return Natural<64>{lhs << rhs}; } - template friend inline auto operator>>(const T& l, Natural r) { return Natural<64>{lhs >> rhs}; } - template friend inline auto operator &(const T& l, Natural r) { return Natural<64>{lhs & rhs}; } - template friend inline auto operator ^(const T& l, Natural r) { return Natural<64>{lhs ^ rhs}; } - template friend inline auto operator |(const T& l, Natural r) { return Natural<64>{lhs | rhs}; } - #undef lhs - #undef rhs - #endif + //warning: this does not and cannot short-circuit; value is always evaluated + template inline auto orElse(const T& value) { return Natural<>{data ? data : value}; } inline auto bits(int lo, int hi) -> BitRange { return {(utype&)data, lo, hi}; } inline auto bit(int index) -> BitRange { return {(utype&)data, index, index}; } @@ -90,16 +58,19 @@ template struct Natural { inline auto bit(int index) const -> const BitRange { return {(utype&)data, index, index}; } inline auto byte(int index) const -> const BitRange { return {(utype&)data, index * 8 + 0, index * 8 + 7}; } + inline auto slice(int index) const { return Natural<>{bit(index)}; } + inline auto slice(int lo, int hi) const { return Natural<>{bits(lo, hi)}; } + inline auto clamp(uint bits) { - const uintmax b = 1ull << (bits - 1); - const uintmax m = b * 2 - 1; - return Natural<64>{data < m ? data : m}; + const uint64_t b = 1ull << (bits - 1); + const uint64_t m = b * 2 - 1; + return Natural<>{data < m ? data : m}; } inline auto clip(uint bits) { - const uintmax b = 1ull << (bits - 1); - const uintmax m = b * 2 - 1; - return Natural<64>{data & m}; + const uint64_t b = 1ull << (bits - 1); + const uint64_t m = b * 2 - 1; + return Natural<>{data & m}; } inline auto serialize(serializer& s) { s(data); } @@ -114,17 +85,17 @@ private: }; #define lhs (uint64_t)l -#define rhs (uint64_t)r -template inline auto operator *(Natural l, Natural r) { return Natural<64>{lhs * rhs}; } -template inline auto operator /(Natural l, Natural r) { return Natural<64>{lhs / rhs}; } -template inline auto operator %(Natural l, Natural r) { return Natural<64>{lhs % rhs}; } -template inline auto operator +(Natural l, Natural r) { return Natural<64>{lhs + rhs}; } -template inline auto operator -(Natural l, Natural r) { return Natural<64>{lhs - rhs}; } -template inline auto operator<<(Natural l, Natural r) { return Natural<64>{lhs << rhs}; } -template inline auto operator>>(Natural l, Natural r) { return Natural<64>{lhs >> rhs}; } -template inline auto operator &(Natural l, Natural r) { return Natural<64>{lhs & rhs}; } -template inline auto operator ^(Natural l, Natural r) { return Natural<64>{lhs ^ rhs}; } -template inline auto operator |(Natural l, Natural r) { return Natural<64>{lhs | rhs}; } +#define rhs r +template inline auto operator *(Natural l, Natural r) { return Natural{lhs * rhs}; } +template inline auto operator /(Natural l, Natural r) { return Natural{lhs / rhs}; } +template inline auto operator %(Natural l, Natural r) { return Natural{lhs % rhs}; } +template inline auto operator +(Natural l, Natural r) { return Natural{lhs + rhs}; } +template inline auto operator -(Natural l, Natural r) { return Natural{lhs - rhs}; } +template inline auto operator<<(Natural l, Natural r) { return Natural{lhs << rhs}; } +template inline auto operator>>(Natural l, Natural r) { return Natural{lhs >> rhs}; } +template inline auto operator &(Natural l, Natural r) { return Natural{lhs & rhs}; } +template inline auto operator ^(Natural l, Natural r) { return Natural{lhs ^ rhs}; } +template inline auto operator |(Natural l, Natural r) { return Natural{lhs | rhs}; } #undef lhs #undef rhs diff --git a/nall/primitives/real.hpp b/nall/primitives/real.hpp index 286835af..99870024 100644 --- a/nall/primitives/real.hpp +++ b/nall/primitives/real.hpp @@ -2,13 +2,13 @@ namespace nall { -template struct Real { +template struct Real { static_assert(Precision == 32 || Precision == 64); static inline constexpr auto bits() -> uint { return Precision; } using ftype = - typename conditional::type>::type; + conditional_t>; inline Real() : data(0.0) {} template inline Real(Real value) : data((ftype)value) {} @@ -38,11 +38,11 @@ private: #define lhs (float64_t)(typename Real::type)l #define rhs (typename Real::type)r -template inline auto operator*(Real l, Real r) { return Real<64>{lhs * rhs}; } -template inline auto operator/(Real l, Real r) { return Real<64>{lhs / rhs}; } -template inline auto operator%(Real l, Real r) { return Real<64>{lhs % rhs}; } -template inline auto operator+(Real l, Real r) { return Real<64>{lhs + rhs}; } -template inline auto operator-(Real l, Real r) { return Real<64>{lhs - rhs}; } +template inline auto operator*(Real l, Real r) { return Real<>{lhs * rhs}; } +template inline auto operator/(Real l, Real r) { return Real<>{lhs / rhs}; } +template inline auto operator%(Real l, Real r) { return Real<>{lhs % rhs}; } +template inline auto operator+(Real l, Real r) { return Real<>{lhs + rhs}; } +template inline auto operator-(Real l, Real r) { return Real<>{lhs - rhs}; } #undef lhs #undef rhs diff --git a/nall/primitives/types.hpp b/nall/primitives/types.hpp index 9a111f6c..74ca6a6a 100644 --- a/nall/primitives/types.hpp +++ b/nall/primitives/types.hpp @@ -2,9 +2,9 @@ namespace nall { using boolean = Boolean; - using natural = Natural<64>; - using integer = Integer<64>; - using real = Real<64>; + using natural = Natural<>; + using integer = Integer<>; + using real = Real<>; using natural1 = Natural< 1>; using natural2 = Natural< 2>; using natural3 = Natural< 3>; using natural4 = Natural< 4>; using natural5 = Natural< 5>; using natural6 = Natural< 6>; using natural7 = Natural< 7>; using natural8 = Natural< 8>; diff --git a/nall/string/cast.hpp b/nall/string/cast.hpp index 42f7008d..da915eed 100644 --- a/nall/string/cast.hpp +++ b/nall/string/cast.hpp @@ -76,7 +76,7 @@ template<> struct stringify { }; #endif -template struct stringify> { +template struct stringify> { stringify(Integer source) { fromInteger(_data, source); } auto data() const -> const char* { return _data; } auto size() const -> uint { return strlen(_data); } @@ -129,7 +129,7 @@ template<> struct stringify { }; #endif -template struct stringify> { +template struct stringify> { stringify(Natural source) { fromNatural(_data, source); } auto data() const -> const char* { return _data; } auto size() const -> uint { return strlen(_data); } diff --git a/nall/traits.hpp b/nall/traits.hpp index 5dff1814..0263b86f 100644 --- a/nall/traits.hpp +++ b/nall/traits.hpp @@ -9,6 +9,7 @@ namespace nall { using std::add_const; using std::conditional; + using std::conditional_t; using std::decay; using std::declval; using std::enable_if;