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.
This commit is contained in:
Tim Allen 2019-01-19 12:34:17 +11:00
parent 2d9ce59e99
commit 37b610da53
48 changed files with 1213 additions and 915 deletions

View File

@ -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/";

View File

@ -1,4 +1,4 @@
processors += lr35902
processors += sm83
objects += gb-interface gb-system
objects += gb-memory gb-cartridge

View File

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

View File

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

View File

@ -1,5 +1,5 @@
auto CPU::serialize(serializer& s) -> void {
LR35902::serialize(s);
SM83::serialize(s);
Thread::serialize(s);
s.array(wram);

View File

@ -8,7 +8,7 @@
#include <emulator/scheduler.hpp>
#include <emulator/cheat.hpp>
#include <processor/lr35902/lr35902.hpp>
#include <processor/sm83/sm83.hpp>
namespace GameBoy {
#define platform Emulator::platform

View File

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

View File

@ -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) {

View File

@ -1,5 +1,4 @@
#include <gba/gba.hpp>
#include <nall/inline-if.hpp>
//pixel: 4 cycles

View File

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

View File

@ -1,5 +1,4 @@
#include <md/md.hpp>
#include <nall/inline-if.hpp>
namespace MegaDrive {

View File

@ -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 {

View File

@ -1,5 +1,4 @@
#include <md/md.hpp>
#include <nall/inline-if.hpp>
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;

View File

@ -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

View File

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

View File

@ -1,5 +1,4 @@
#include <processor/processor.hpp>
#include <nall/inline-if.hpp>
#include "arm7tdmi.hpp"
namespace Processor {

View File

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

View File

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

View File

@ -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) {

View File

@ -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) {

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
#include <processor/processor.hpp>
#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 = {};
}

View File

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

View File

@ -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 {

View File

@ -1,5 +1,4 @@
#include <processor/processor.hpp>
#include <nall/inline-if.hpp>
#include "spc700.hpp"
namespace Processor {

View File

@ -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<uint8>(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<uint16>(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<uint16>(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<uint32>(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<uint32>(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<uint16>(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<uint32>(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<uint32>(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<uint32>(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<uint32>(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<uint32>(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<uint32>(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<uint32>(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<uint32>(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<uint32>(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<uint8>(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<uint16>(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<uint32>(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<uint16>(data).id;
if(size == Long) return toRegister3<uint32>(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");

View File

@ -17,7 +17,7 @@ template<typename T> auto TLCS900H::toRegister8(uint8 code) const -> Register<T>
template<typename T> auto TLCS900H::toControlRegister(uint8 code) const -> ControlRegister<T> { return {code}; }
template<typename T> auto TLCS900H::toMemory(uint32 address) const -> Memory<T> { return {address}; }
template<typename T> auto TLCS900H::toImmediate(uint32 constant) const -> Immediate<T> { return {constant}; }
template<typename T> auto TLCS900H::toImmediate3(uint3 constant) const -> Immediate<T> { return {constant ? (uint)constant : 8u}; }
template<typename T> auto TLCS900H::toImmediate3(natural constant) const -> Immediate<T> { 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<T, T>(), memory);
return instructionLoad(fetchMemory<T, uint16>(), 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<T>(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<uint16>(data), toMemory<uint16>(address));
return instructionLoad(toRegister3<uint16>(data), toImmediate<uint16>(address));
case 0x28: return instructionAndCarry(toMemory<uint8>(address), A);
case 0x29: return instructionOrCarry(toMemory<uint8>(address), A);
case 0x2a: return instructionXorCarry(toMemory<uint8>(address), A);
@ -665,7 +665,7 @@ auto TLCS900H::instructionTargetMemory(uint32 address) -> void {
case 0x2c: return instructionStoreCarry(toMemory<uint8>(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<uint32>(data), toMemory<uint32>(address));
return instructionLoad(toRegister3<uint32>(data), toImmediate<uint32>(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<uint8>(address), toRegister3<uint8>(data));
@ -700,10 +700,10 @@ auto TLCS900H::instructionTargetMemory(uint32 address) -> void {
return instructionBit(toMemory<uint8>(address), toImmediate<uint3>(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<uint32>(address));
return instructionJump((uint4)data, toImmediate<uint32>(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<uint32>(address));
return instructionCall((uint4)data, toImmediate<uint32>(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);

View File

@ -158,7 +158,7 @@ auto TLCS900H::instructionExtendZero(Target target) -> void {
}
auto TLCS900H::instructionHalt() -> void {
setHalted(true);
r.halted = true;
}
template<typename Target, typename Source>
@ -349,8 +349,7 @@ auto TLCS900H::instructionRotateLeftDigit(LHS lhs, RHS rhs) -> void {
template<typename Target, typename Amount>
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<typename Target, typename Amount>
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<typename Target, typename Amount>
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<typename Target, typename Amount>
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<typename Target, typename Amount>
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<typename Target, typename Amount>
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<typename Target, typename Amount>
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<typename Target, typename Amount>
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;
}

View File

@ -1,5 +1,4 @@
#include <processor/processor.hpp>
#include <nall/inline-if.hpp>
#include "tlcs900h.hpp"
namespace Processor {

View File

@ -85,7 +85,7 @@ struct TLCS900H {
template<typename T> auto toControlRegister(uint8) const -> ControlRegister<T>;
template<typename T> auto toMemory(uint32 address) const -> Memory<T>;
template<typename T> auto toImmediate(uint32 constant) const -> Immediate<T>;
template<typename T> auto toImmediate3(uint3 constant) const -> Immediate<T>;
template<typename T> auto toImmediate3(natural constant) const -> Immediate<T>;
auto instruction() -> void;
template<typename Register> auto instructionRegister(Register) -> void;
template<typename Memory> 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};

View File

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

View File

@ -1,5 +1,4 @@
#include <sfc/sfc.hpp>
#include <nall/inline-if.hpp>
namespace SuperFamicom {

View File

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

View File

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

View File

@ -1,5 +1,4 @@
#include <sfc/sfc.hpp>
#include <nall/inline-if.hpp>
namespace SuperFamicom {

View File

@ -63,4 +63,22 @@ private:
T values[Size];
};
template<typename T, T... p> auto from_array(uint index) -> T {
static const array<T[sizeof...(p)]> table{p...};
struct out_of_bounds {};
#if defined(DEBUG)
if(index >= sizeof...(p)) throw out_of_bounds{};
#endif
return table[index];
}
template<int64_t... p> auto from_array(uint index) -> int64_t {
static const array<int64_t[sizeof...(p)]> table{p...};
struct out_of_bounds {};
#if defined(DEBUG)
if(index >= sizeof...(p)) throw out_of_bounds{};
#endif
return table[index];
}
}

View File

@ -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) { \

View File

@ -5,8 +5,8 @@
namespace nall {
struct Boolean;
template<int Precision> struct Natural;
template<int Precision> struct Integer;
template<uint Precision> struct Natural;
template<uint Precision> struct Integer;
}
#include <nall/primitives/bit-range.hpp>
@ -18,6 +18,6 @@ namespace nall {
#include <nall/primitives/literals.hpp>
namespace nall {
template<int Bits> auto Natural<Bits>::integer() const -> Integer<Bits> { return Integer<Bits>(*this); }
template<int Bits> auto Integer<Bits>::natural() const -> Natural<Bits> { return Natural<Bits>(*this); }
template<uint Bits> auto Natural<Bits>::integer() const -> Integer<Bits> { return Integer<Bits>(*this); }
template<uint Bits> auto Integer<Bits>::natural() const -> Natural<Bits> { return Natural<Bits>(*this); }
}

View File

@ -2,18 +2,18 @@
namespace nall {
template<int Requested> struct BitRange {
enum : uint { Precision = Requested < 1 ? 1 : Requested > 64 ? 64 : Requested };
template<int Precision> struct BitRange {
static_assert(Precision >= 1 && Precision <= 64);
static inline constexpr auto bits() -> uint { return Precision; }
using type =
using utype =
typename conditional<bits() <= 8, uint8_t,
typename conditional<bits() <= 16, uint16_t,
typename conditional<bits() <= 32, uint32_t,
typename conditional<bits() <= 64, uint64_t,
void>::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<int Requested> 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<typename T> inline auto& operator =(const T& value) { return set( value); }
template<typename T> inline auto& operator *=(const T& value) { return set(get() * value); }
template<typename T> inline auto& operator /=(const T& value) { return set(get() / value); }
@ -42,20 +42,20 @@ template<int Requested> struct BitRange {
template<typename T> 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;
};

View File

@ -2,15 +2,15 @@
namespace nall {
template<int Precision> struct Integer {
template<uint Precision = 64> struct Integer {
static_assert(Precision >= 1 && Precision <= 64);
static inline constexpr auto bits() -> uint { return Precision; }
using stype =
typename conditional<bits() <= 8, int8_t,
typename conditional<bits() <= 16, int16_t,
typename conditional<bits() <= 32, int32_t,
typename conditional<bits() <= 64, int64_t,
void>::type>::type>::type>::type;
conditional_t<bits() <= 8, int8_t,
conditional_t<bits() <= 16, int16_t,
conditional_t<bits() <= 32, int32_t,
conditional_t<bits() <= 64, int64_t,
void>>>>;
using utype = typename Natural<Precision>::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<int Precision> 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<int Precision> struct Integer {
#undef lhs
#undef rhs
//warning: this does not and cannot short-circuit; value is always evaluated
template<typename T> inline auto orElse(const T& value) { return Integer<>{data ? data : value}; }
inline auto bits(int lo, int hi) -> BitRange<Precision> { return {(utype&)data, lo, hi}; }
inline auto bit(int index) -> BitRange<Precision> { return {(utype&)data, index, index}; }
inline auto byte(int index) -> BitRange<Precision> { return {(utype&)data, index * 8 + 0, index * 8 + 7}; }
@ -62,16 +65,19 @@ template<int Precision> struct Integer {
inline auto bit(int index) const -> const BitRange<Precision> { return {(utype&)*this, index, index}; }
inline auto byte(int index) const -> const BitRange<Precision> { 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<int LHS, int RHS> inline auto operator *(Integer<LHS> l, Integer<RHS> r) { return Integer<64>{lhs * rhs}; }
template<int LHS, int RHS> inline auto operator /(Integer<LHS> l, Integer<RHS> r) { return Integer<64>{lhs / rhs}; }
template<int LHS, int RHS> inline auto operator %(Integer<LHS> l, Integer<RHS> r) { return Integer<64>{lhs % rhs}; }
template<int LHS, int RHS> inline auto operator +(Integer<LHS> l, Integer<RHS> r) { return Integer<64>{lhs + rhs}; }
template<int LHS, int RHS> inline auto operator -(Integer<LHS> l, Integer<RHS> r) { return Integer<64>{lhs - rhs}; }
template<int LHS, int RHS> inline auto operator<<(Integer<LHS> l, Integer<RHS> r) { return Integer<64>{lhs << rhs}; }
template<int LHS, int RHS> inline auto operator>>(Integer<LHS> l, Integer<RHS> r) { return Integer<64>{lhs >> rhs}; }
template<int LHS, int RHS> inline auto operator &(Integer<LHS> l, Integer<RHS> r) { return Integer<64>{lhs & rhs}; }
template<int LHS, int RHS> inline auto operator ^(Integer<LHS> l, Integer<RHS> r) { return Integer<64>{lhs ^ rhs}; }
template<int LHS, int RHS> inline auto operator |(Integer<LHS> l, Integer<RHS> r) { return Integer<64>{lhs | rhs}; }
template<int LHS, int RHS> inline auto operator *(Integer<LHS> l, Integer<RHS> r) { return Integer{lhs * rhs}; }
template<int LHS, int RHS> inline auto operator /(Integer<LHS> l, Integer<RHS> r) { return Integer{lhs / rhs}; }
template<int LHS, int RHS> inline auto operator %(Integer<LHS> l, Integer<RHS> r) { return Integer{lhs % rhs}; }
template<int LHS, int RHS> inline auto operator +(Integer<LHS> l, Integer<RHS> r) { return Integer{lhs + rhs}; }
template<int LHS, int RHS> inline auto operator -(Integer<LHS> l, Integer<RHS> r) { return Integer{lhs - rhs}; }
template<int LHS, int RHS> inline auto operator<<(Integer<LHS> l, Integer<RHS> r) { return Integer{lhs << rhs}; }
template<int LHS, int RHS> inline auto operator>>(Integer<LHS> l, Integer<RHS> r) { return Integer{lhs >> rhs}; }
template<int LHS, int RHS> inline auto operator &(Integer<LHS> l, Integer<RHS> r) { return Integer{lhs & rhs}; }
template<int LHS, int RHS> inline auto operator ^(Integer<LHS> l, Integer<RHS> r) { return Integer{lhs ^ rhs}; }
template<int LHS, int RHS> inline auto operator |(Integer<LHS> l, Integer<RHS> r) { return Integer{lhs | rhs}; }
#undef lhs
#undef rhs

View File

@ -2,15 +2,15 @@
namespace nall {
template<int Precision> struct Natural {
template<uint Precision = 64> struct Natural {
static_assert(Precision >= 1 && Precision <= 64);
static inline constexpr auto bits() -> uint { return Precision; }
using utype =
typename conditional<bits() <= 8, uint8_t,
typename conditional<bits() <= 16, uint16_t,
typename conditional<bits() <= 32, uint32_t,
typename conditional<bits() <= 64, uint64_t,
void>::type>::type>::type>::type;
conditional_t<bits() <= 8, uint8_t,
conditional_t<bits() <= 16, uint16_t,
conditional_t<bits() <= 32, uint32_t,
conditional_t<bits() <= 64, uint64_t,
void>>>>;
static inline constexpr auto mask() -> utype { return ~0ull >> 64 - bits(); }
inline Natural() : data(0) {}
@ -28,8 +28,8 @@ template<int Precision> 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<int Precision> struct Natural {
#undef lhs
#undef rhs
//work in progress: we want natural<op>primitive and primitive<op>natural 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<typename T> inline auto operator *(const T& value) { return Natural<64>{lhs * rhs}; }
template<typename T> inline auto operator /(const T& value) { return Natural<64>{lhs / rhs}; }
template<typename T> inline auto operator %(const T& value) { return Natural<64>{lhs % rhs}; }
template<typename T> inline auto operator +(const T& value) { return Natural<64>{lhs + rhs}; }
template<typename T> inline auto operator -(const T& value) { return Natural<64>{lhs - rhs}; }
template<typename T> inline auto operator<<(const T& value) { return Natural<64>{lhs << rhs}; }
template<typename T> inline auto operator>>(const T& value) { return Natural<64>{lhs >> rhs}; }
template<typename T> inline auto operator &(const T& value) { return Natural<64>{lhs & rhs}; }
template<typename T> inline auto operator ^(const T& value) { return Natural<64>{lhs ^ rhs}; }
template<typename T> inline auto operator |(const T& value) { return Natural<64>{lhs | rhs}; }
#undef lhs
#undef rhs
#define lhs l
#define rhs (uint64_t)r
template<typename T> friend inline auto operator *(const T& l, Natural r) { return Natural<64>{lhs * rhs}; }
template<typename T> friend inline auto operator %(const T& l, Natural r) { return Natural<64>{lhs / rhs}; }
template<typename T> friend inline auto operator /(const T& l, Natural r) { return Natural<64>{lhs % rhs}; }
template<typename T> friend inline auto operator +(const T& l, Natural r) { return Natural<64>{lhs + rhs}; }
template<typename T> friend inline auto operator -(const T& l, Natural r) { return Natural<64>{lhs - rhs}; }
template<typename T> friend inline auto operator<<(const T& l, Natural r) { return Natural<64>{lhs << rhs}; }
template<typename T> friend inline auto operator>>(const T& l, Natural r) { return Natural<64>{lhs >> rhs}; }
template<typename T> friend inline auto operator &(const T& l, Natural r) { return Natural<64>{lhs & rhs}; }
template<typename T> friend inline auto operator ^(const T& l, Natural r) { return Natural<64>{lhs ^ rhs}; }
template<typename T> 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<typename T> inline auto orElse(const T& value) { return Natural<>{data ? data : value}; }
inline auto bits(int lo, int hi) -> BitRange<Precision> { return {(utype&)data, lo, hi}; }
inline auto bit(int index) -> BitRange<Precision> { return {(utype&)data, index, index}; }
@ -90,16 +58,19 @@ template<int Precision> struct Natural {
inline auto bit(int index) const -> const BitRange<Precision> { return {(utype&)data, index, index}; }
inline auto byte(int index) const -> const BitRange<Precision> { 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<int LHS, int RHS> inline auto operator *(Natural<LHS> l, Natural<RHS> r) { return Natural<64>{lhs * rhs}; }
template<int LHS, int RHS> inline auto operator /(Natural<LHS> l, Natural<RHS> r) { return Natural<64>{lhs / rhs}; }
template<int LHS, int RHS> inline auto operator %(Natural<LHS> l, Natural<RHS> r) { return Natural<64>{lhs % rhs}; }
template<int LHS, int RHS> inline auto operator +(Natural<LHS> l, Natural<RHS> r) { return Natural<64>{lhs + rhs}; }
template<int LHS, int RHS> inline auto operator -(Natural<LHS> l, Natural<RHS> r) { return Natural<64>{lhs - rhs}; }
template<int LHS, int RHS> inline auto operator<<(Natural<LHS> l, Natural<RHS> r) { return Natural<64>{lhs << rhs}; }
template<int LHS, int RHS> inline auto operator>>(Natural<LHS> l, Natural<RHS> r) { return Natural<64>{lhs >> rhs}; }
template<int LHS, int RHS> inline auto operator &(Natural<LHS> l, Natural<RHS> r) { return Natural<64>{lhs & rhs}; }
template<int LHS, int RHS> inline auto operator ^(Natural<LHS> l, Natural<RHS> r) { return Natural<64>{lhs ^ rhs}; }
template<int LHS, int RHS> inline auto operator |(Natural<LHS> l, Natural<RHS> r) { return Natural<64>{lhs | rhs}; }
#define rhs r
template<int LHS, int RHS> inline auto operator *(Natural<LHS> l, Natural<RHS> r) { return Natural{lhs * rhs}; }
template<int LHS, int RHS> inline auto operator /(Natural<LHS> l, Natural<RHS> r) { return Natural{lhs / rhs}; }
template<int LHS, int RHS> inline auto operator %(Natural<LHS> l, Natural<RHS> r) { return Natural{lhs % rhs}; }
template<int LHS, int RHS> inline auto operator +(Natural<LHS> l, Natural<RHS> r) { return Natural{lhs + rhs}; }
template<int LHS, int RHS> inline auto operator -(Natural<LHS> l, Natural<RHS> r) { return Natural{lhs - rhs}; }
template<int LHS, int RHS> inline auto operator<<(Natural<LHS> l, Natural<RHS> r) { return Natural{lhs << rhs}; }
template<int LHS, int RHS> inline auto operator>>(Natural<LHS> l, Natural<RHS> r) { return Natural{lhs >> rhs}; }
template<int LHS, int RHS> inline auto operator &(Natural<LHS> l, Natural<RHS> r) { return Natural{lhs & rhs}; }
template<int LHS, int RHS> inline auto operator ^(Natural<LHS> l, Natural<RHS> r) { return Natural{lhs ^ rhs}; }
template<int LHS, int RHS> inline auto operator |(Natural<LHS> l, Natural<RHS> r) { return Natural{lhs | rhs}; }
#undef lhs
#undef rhs

View File

@ -2,13 +2,13 @@
namespace nall {
template<int Precision> struct Real {
template<uint Precision = 64> struct Real {
static_assert(Precision == 32 || Precision == 64);
static inline constexpr auto bits() -> uint { return Precision; }
using ftype =
typename conditional<bits() == 32, float32_t,
typename conditional<bits() == 64, float64_t,
void>::type>::type;
conditional_t<bits() == 32, float32_t,
conditional_t<bits() == 64, float64_t,
void>>;
inline Real() : data(0.0) {}
template<int Bits> inline Real(Real<Bits> value) : data((ftype)value) {}
@ -38,11 +38,11 @@ private:
#define lhs (float64_t)(typename Real<LHS>::type)l
#define rhs (typename Real<RHS>::type)r
template<int LHS, int RHS> inline auto operator*(Real<LHS> l, Real<RHS> r) { return Real<64>{lhs * rhs}; }
template<int LHS, int RHS> inline auto operator/(Real<LHS> l, Real<RHS> r) { return Real<64>{lhs / rhs}; }
template<int LHS, int RHS> inline auto operator%(Real<LHS> l, Real<RHS> r) { return Real<64>{lhs % rhs}; }
template<int LHS, int RHS> inline auto operator+(Real<LHS> l, Real<RHS> r) { return Real<64>{lhs + rhs}; }
template<int LHS, int RHS> inline auto operator-(Real<LHS> l, Real<RHS> r) { return Real<64>{lhs - rhs}; }
template<int LHS, int RHS> inline auto operator*(Real<LHS> l, Real<RHS> r) { return Real<>{lhs * rhs}; }
template<int LHS, int RHS> inline auto operator/(Real<LHS> l, Real<RHS> r) { return Real<>{lhs / rhs}; }
template<int LHS, int RHS> inline auto operator%(Real<LHS> l, Real<RHS> r) { return Real<>{lhs % rhs}; }
template<int LHS, int RHS> inline auto operator+(Real<LHS> l, Real<RHS> r) { return Real<>{lhs + rhs}; }
template<int LHS, int RHS> inline auto operator-(Real<LHS> l, Real<RHS> r) { return Real<>{lhs - rhs}; }
#undef lhs
#undef rhs

View File

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

View File

@ -76,7 +76,7 @@ template<> struct stringify<int128_t> {
};
#endif
template<int Bits> struct stringify<Integer<Bits>> {
template<uint Bits> struct stringify<Integer<Bits>> {
stringify(Integer<Bits> 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<uint128_t> {
};
#endif
template<int Bits> struct stringify<Natural<Bits>> {
template<uint Bits> struct stringify<Natural<Bits>> {
stringify(Natural<Bits> source) { fromNatural(_data, source); }
auto data() const -> const char* { return _data; }
auto size() const -> uint { return strlen(_data); }

View File

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