diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 321de702..a6d1ff24 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -30,7 +30,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "106.71"; + static const string Version = "106.72"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/higan/processor/tlcs900h/algorithms.cpp b/higan/processor/tlcs900h/algorithms.cpp index 863cd687..b3475fc3 100644 --- a/higan/processor/tlcs900h/algorithms.cpp +++ b/higan/processor/tlcs900h/algorithms.cpp @@ -1,32 +1,77 @@ -template<> auto TLCS900H::algorithmAdd(uint8 target, uint8 source, uint1 carry) -> uint8 { +template<> auto TLCS900H::parity(Byte data) const -> bool { + data ^= data >> 4; + data ^= data >> 2; + data ^= data >> 1; + return !(data & 1); +} + +template<> auto TLCS900H::parity(Word data) const -> bool { + data ^= data >> 8; + data ^= data >> 4; + data ^= data >> 2; + data ^= data >> 1; + return !(data & 1); +} + +template<> auto TLCS900H::parity(Long data) const -> bool { + return Undefined; +} + +// + +template auto TLCS900H::algorithmAdd(Size target, Size source, uint1 carry) -> Size { uint64 result = target + source + carry; - CF = result.bit(8); + CF = result.bit(Size::bits()); NF = 0; - VF = uint8(~(target ^ source) & (target ^ result)).bit(7); - HF = uint8(target ^ source ^ result).bit(4); - ZF = uint8(result) == 0; - SF = result.bit(7); + VF = Size(~(target ^ source) & (target ^ result)).negative(); + HF = Size(target ^ source ^ result).bit(4); + if constexpr(isLong()) HF = Undefined; + ZF = Size(result).zero(); + SF = result.negative(); return result; } -template<> auto TLCS900H::algorithmAdd(uint16 target, uint16 source, uint1 carry) -> uint16 { - uint64 result = target + source + carry; - CF = result.bit(16); +template auto TLCS900H::algorithmAnd(Size target, Size source) -> Size { + Size result = target & source; + CF = 0; NF = 0; - VF = uint16(~(target ^ source) & (target ^ result)).bit(15); - HF = uint16(target ^ source ^ result).bit(4); - ZF = uint16(result) == 0; - SF = result.bit(15); + VF = parity(result); + HF = 1; + ZF = result.zero(); + SF = result.negative(); return result; } -template<> auto TLCS900H::algorithmAdd(uint32 target, uint32 source, uint1 carry) -> uint32 { - uint64 result = target + source + carry; - CF = result.bit(32); +template auto TLCS900H::algorithmOr(Size target, Size source) -> Size { + Size result = target | source; + CF = 0; NF = 0; - VF = uint32(~(target ^ source) & (target ^ result)).bit(31); - HF = undefined; - ZF = uint32(result) == 0; - SF = result.bit(31); + VF = parity(result); + HF = 0; + ZF = result.zero(); + SF = result.negative(); + return result; +} + +template auto TLCS900H::algorithmSubtract(Size target, Size source, uint1 carry) -> Size { + uint64 result = target - source - carry; + CF = result.bit(Size::bits()); + NF = 1; + VF = Size((target ^ source) & (target ^ result)).negative(); + HF = Size(target ^ source ^ result).bit(4); + if constexpr(isLong()) HF = Undefined; + ZF = Size(result).zero(); + SF = result.negative(); + return result; +} + +template auto TLCS900H::algorithmXor(Size target, Size source) -> Size { + Size result = target ^ source; + CF = 0; + NF = 0; + VF = parity(result); + HF = 0; + ZF = result.zero(); + SF = result.negative(); return result; } diff --git a/higan/processor/tlcs900h/conditions.cpp b/higan/processor/tlcs900h/conditions.cpp new file mode 100644 index 00000000..1785cdaf --- /dev/null +++ b/higan/processor/tlcs900h/conditions.cpp @@ -0,0 +1,20 @@ +auto TLCS900H::condition(uint4 code) -> bool { + switch(code) { + case 0: return 0 == 1; //F (false) + case 1: return (SF ^ VF) == 1; //LT (signed less than) + case 2: return (ZF | (SF ^ VF)) == 1; //LE (signed less than or equal) + case 3: return (CF | ZF) == 1; //ULE (unsigned less than or equal) + case 4: return VF == 1; //OV (overflow) + case 5: return SF == 1; //MI (minus) + case 6: return ZF == 1; //EQ (equal) + case 7: return CF == 1; //ULT (unsigned less than) + case 8: return 0 == 0; //T (true) + case 9: return (SF ^ VF) == 0; //GE (signed greater than or equal) + case 10: return (ZF | (SF ^ VF)) == 0; //GT (signed greater than) + case 11: return (CF | ZF) == 0; //UGT (unsigned greater than) + case 12: return VF == 0; //NOV (no overflow) + case 13: return SF == 0; //PL (plus) + case 14: return ZF == 0; //NE (not equal) + case 15: return CF == 0; //UGE (unsigned greater than or equal) + } unreachable; +} diff --git a/higan/processor/tlcs900h/instruction.cpp b/higan/processor/tlcs900h/instruction.cpp index 97069814..ad6f7896 100644 --- a/higan/processor/tlcs900h/instruction.cpp +++ b/higan/processor/tlcs900h/instruction.cpp @@ -1,14 +1,45 @@ +template<> auto TLCS900H::registerLookup(uint3 code) -> Register { + return {0xe0 | code >> 1 << 2 | code & 1 ^ 1}; //W, A, B, C, D, E, H, L +} + +template<> auto TLCS900H::registerLookup(uint3 code) -> Register { + return {0xe0 | code << 2}; //WA, BC, DE, HL, IX, IY, IZ, SP +} + +template<> auto TLCS900H::registerLookup(uint3 code) -> Register { + return {0xe0 | code << 2}; //XWA, XBC, XDE, XHL, XIX, XIY, XIZ, XSP +} + auto TLCS900H::instruction() -> void { auto data = fetch(); - static const Register registers[] = {W, A, B, C, D, E, H, L}; Register register; Memory memory; switch(data) { case 0x00: return instructionNoOperation(); - case 0x04: return; //undefined + case 0x02: return instructionPush(r.sr); + case 0x03: return instructionPop(r.sr); + case 0x04: return (void)Undefined; + case 0x09: return instructionPush(Immediate{fetch()}); + case 0x0b: return instructionPush(Immediate{fetch()}); case 0x12: return instructionComplementCarry(); - case 0x1f: return; //undefined + case 0x14: return instructionPush(A); + case 0x15: return instructionPop(A); + case 0x18: return instructionPush(r.sr.f); + case 0x19: return instructionPop(r.sr.f); + case 0x1f: return (void)Undefined; + + case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: + return instructionPush(registerLookup(data)); + + case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: + return instructionPush(registerLookup(data)); + + case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: + return instructionPop(registerLookup(data)); + + case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: + return instructionPop(registerLookup(data)); case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: memory = {read(register)}; @@ -53,36 +84,37 @@ auto TLCS900H::instruction() -> void { return instructionSourceMemory(memory); case 0xc3: data = fetch(); - memory = {read(Register{data & ~3})}; + memory = {read(Register{data})}; if((data & 3) == 1) memory.value += (int16)fetch(); if((data & 3) == 2) memory.value += (int8)read(Register{fetch()}); - if((data & 3) == 3) memory.value += (int16)read(Register{fetch() & ~1}); + if((data & 3) == 3) memory.value += (int16)read(Register{fetch()}); return instructionSourceMemory(memory); case 0xc4: data = fetch(); - register = {data & ~3}; + register = {data}; if((data & 3) == 0) write(register, read(register) - 1); if((data & 3) == 1) write(register, read(register) - 2); if((data & 3) == 2) write(register, read(register) - 4); + if((data & 3) == 3) Undefined; memory = {read(register)}; return instructionSourceMemory(memory); case 0xc5: data = fetch(); - register = {data & ~3}; + register = {data}; memory = {read(register)}; instructionSourceMemory(memory); if((data & 3) == 0) write(register, read(register) + 1); if((data & 3) == 1) write(register, read(register) + 2); if((data & 3) == 2) write(register, read(register) + 4); + if((data & 3) == 3) Undefined; return; case 0xc6: - //undefined - return; + return (void)Undefined; case 0xc7: register = {fetch()}; return instructionRegister(register); case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: - register = registers[data & 7]; + register = registerLookup(data); return instructionRegister(register); case 0xd0: @@ -96,36 +128,37 @@ auto TLCS900H::instruction() -> void { return instructionSourceMemory(memory); case 0xd3: data = fetch(); - memory = {read(Register{data & ~3})}; + memory = {read(Register{data})}; if((data & 3) == 1) memory.value += (int16)fetch(); if((data & 3) == 2) memory.value += (int8)read(Register{fetch()}); - if((data & 3) == 3) memory.value += (int16)read(Register{fetch() & ~1}); + if((data & 3) == 3) memory.value += (int16)read(Register{fetch()}); return instructionSourceMemory(memory); case 0xd4: data = fetch(); - register = {data & ~3}; + register = {data}; if((data & 3) == 0) write(register, read(register) - 1); if((data & 3) == 1) write(register, read(register) - 2); if((data & 3) == 2) write(register, read(register) - 4); + if((data & 3) == 3) Undefined; memory = {read(register)}; return instructionSourceMemory(memory); case 0xd5: data = fetch(); - register = {data & ~3}; + register = {data}; memory = {read(register)}; instructionSourceMemory(memory); if((data & 3) == 0) write(register, read(register) + 1); if((data & 3) == 1) write(register, read(register) + 2); if((data & 3) == 2) write(register, read(register) + 4); + if((data & 3) == 3) Undefined; return; case 0xd6: - //undefined - return; + return (void)Undefined; case 0xd7: - register = {fetch() & ~1}; + register = {fetch()}; return instructionRegister(register); case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: - register = registers[data & 7]; + register = registerLookup(data); return instructionRegister(register); case 0xe0: @@ -139,36 +172,37 @@ auto TLCS900H::instruction() -> void { return instructionSourceMemory(memory); case 0xe3: data = fetch(); - memory = {read(Register{data & ~3})}; + memory = {read(Register{data})}; if((data & 3) == 1) memory.value += (int16)fetch(); if((data & 3) == 2) memory.value += (int8)read(Register{fetch()}); - if((data & 3) == 3) memory.value += (int16)read(Register{fetch() & ~1}); + if((data & 3) == 3) memory.value += (int16)read(Register{fetch()}); return instructionSourceMemory(memory); case 0xe4: data = fetch(); - register = {data & ~3}; + register = {data}; if((data & 3) == 0) write(register, read(register) - 1); if((data & 3) == 1) write(register, read(register) - 2); if((data & 3) == 2) write(register, read(register) - 4); + if((data & 3) == 3) Undefined; memory = {read(register)}; return instructionSourceMemory(memory); case 0xe5: data = fetch(); - register = {data & ~3}; + register = {data}; memory = {read(register)}; instructionSourceMemory(memory); if((data & 3) == 0) write(register, read(register) + 1); if((data & 3) == 1) write(register, read(register) + 2); if((data & 3) == 2) write(register, read(register) + 4); + if((data & 3) == 3) Undefined; return; case 0xe6: - //undefined - return; + return (void)Undefined; case 0xe7: - register = {fetch() & ~3}; + register = {fetch()}; return instructionRegister(register); case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: - register = registers[data & 7]; + register = registerLookup(data); return instructionRegister(register); case 0xf0: @@ -182,31 +216,32 @@ auto TLCS900H::instruction() -> void { return instructionTargetMemory(memory); case 0xf3: data = fetch(); - memory = {read(Register{data & ~3})}; + memory = {read(Register{data})}; if((data & 3) == 1) memory.value += (int16)fetch(); if((data & 3) == 2) memory.value += (int8)read(Register{fetch()}); - if((data & 3) == 3) memory.value += (int16)read(Register{fetch() & ~1}); + if((data & 3) == 3) memory.value += (int16)read(Register{fetch()}); return instructionTargetMemory(memory); case 0xf4: data = fetch(); - register = {data & ~3}; + register = {data}; if((data & 3) == 0) write(register, read(register) - 1); if((data & 3) == 1) write(register, read(register) - 2); if((data & 3) == 2) write(register, read(register) - 4); + if((data & 3) == 3) Undefined; memory = {read(register)}; return instructionTargetMemory(memory); case 0xf5: data = fetch(); - register = {data & ~3}; + register = {data}; memory = {read(register)}; instructionTargetMemory(memory); if((data & 3) == 0) write(register, read(register) + 1); if((data & 3) == 1) write(register, read(register) + 2); if((data & 3) == 2) write(register, read(register) + 4); + if((data & 3) == 3) Undefined; return; case 0xf6: case 0xf7: - //undefined - return; + return (void)Undefined; case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: return instructionSoftwareInterrupt(Immediate{data.bits(0,2)}); @@ -214,38 +249,102 @@ auto TLCS900H::instruction() -> void { } template -auto TLCS900H::instructionRegister(Register input) -> void { +auto TLCS900H::instructionRegister(Register register) -> void { auto data = fetch(); - static const Register registers[] = {W, A, B, C, D, E, H, L}; - Register register = registers[data.bits(0,2)]; switch(data) { + case 0x04: return instructionPush(register); + case 0x05: return instructionPop(register); + case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: - return instructionAdd(register, input); + return instructionAdd(registerLookup(data), register); case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: - return instructionAddCarry(register, input); + return instructionAddCarry(registerLookup(data), register); + case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: + return instructionSubtract(registerLookup(data), register); + case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: + return instructionSubtractCarry(registerLookup(data), register); + case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: + return instructionAnd(registerLookup(data), register); + case 0xc8: return instructionAdd(register, Immediate{fetch()}); + case 0xc9: return instructionAddCarry(register, Immediate{fetch()}); + case 0xca: return instructionSubtract(register, Immediate{fetch()}); + case 0xcb: return instructionSubtractCarry(register, Immediate{fetch()}); + case 0xcc: return instructionAnd(register, Immediate{fetch()}); + case 0xcd: return instructionXor(register, Immediate{fetch()}); + case 0xce: return instructionOr(register, Immediate{fetch()}); + case 0xcf: return instructionCompare(register, Immediate{fetch()}); + case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: + return instructionXor(registerLookup(data), register); + case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: + return instructionCompare(register, Immediate{data & 7}); + case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: + return instructionOr(registerLookup(data), register); + case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: + return instructionCompare(registerLookup(data), register); } } template -auto TLCS900H::instructionSourceMemory(Memory input) -> void { +auto TLCS900H::instructionSourceMemory(Memory memory) -> void { auto data = fetch(); - static const Register registers[] = {W, A, B, C, D, E, H, L}; - Register register = registers[data.bits(0,2)]; switch(data) { + case 0x04: + if constexpr(isLong()) return (void)Undefined; + return instructionPush(memory); + case 0x38: + if constexpr(isLong()) return (void)Undefined; + return instructionAdd(memory, Immediate{fetch()}); + case 0x39: + if constexpr(isLong()) return (void)Undefined; + return instructionAddCarry(memory, Immediate{fetch()}); + case 0x3a: + if constexpr(isLong()) return (void)Undefined; + return instructionSubtract(memory, Immediate{fetch()}); + case 0x3b: + if constexpr(isLong()) return (void)Undefined; + return instructionSubtractCarry(memory, Immediate{fetch()}); case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: - return instructionAdd(register, input); + return instructionAdd(registerLookup(data), memory); + case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: + return instructionAdd(memory, registerLookup(data)); case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: - return instructionAddCarry(register, input); + return instructionAddCarry(registerLookup(data), memory); + case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: + return instructionAddCarry(memory, registerLookup(data)); + case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: + return instructionSubtract(registerLookup(data), memory); + case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: + return instructionSubtract(memory, registerLookup(data)); + case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: + return instructionSubtractCarry(registerLookup(data), memory); + case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: + return instructionSubtractCarry(memory, registerLookup(data)); + case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: + return instructionAnd(registerLookup(data), memory); + case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: + return instructionAnd(memory, registerLookup(data)); + case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: + return instructionXor(registerLookup(data), memory); + case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: + return instructionXor(memory, registerLookup(data)); + case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: + return instructionOr(registerLookup(data), memory); + case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: + return instructionOr(memory, registerLookup(data)); + case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: + return instructionCompare(registerLookup(data), memory); + case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: + return instructionCompare(memory, registerLookup(data)); } } -auto TLCS900H::instructionTargetMemory(Memory input) -> void { +auto TLCS900H::instructionTargetMemory(Memory memory) -> void { auto data = fetch(); - static const Register registers[] = {W, A, B, C, D, E, H, L}; - Register register = registers[data.bits(0,2)]; switch(data) { + case 0x04: return instructionPop(memory); + case 0x06: return instructionPop(memory); } } diff --git a/higan/processor/tlcs900h/instructions.cpp b/higan/processor/tlcs900h/instructions.cpp index a4341e52..7c2a2a7e 100644 --- a/higan/processor/tlcs900h/instructions.cpp +++ b/higan/processor/tlcs900h/instructions.cpp @@ -1,11 +1,27 @@ +#define read read +#define write write +#define push push +#define pop pop +#define algorithm(name, ...) algorithm##name(__VA_ARGS__) + template auto TLCS900H::instructionAdd(Target target, Source source) -> void { - write(target, algorithmAdd(read(target), read(source))); + write(target, algorithm(Add, read(target), read(source))); } template auto TLCS900H::instructionAddCarry(Target target, Source source) -> void { - write(target, algorithmAdd(read(target), read(source), CF)); + write(target, algorithm(Add, read(target), read(source), CF)); +} + +template +auto TLCS900H::instructionAnd(Target target, Source source) -> void { + write(target, algorithm(And, read(target), read(source))); +} + +template +auto TLCS900H::instructionCompare(Target target, Source source) -> void { + algorithm(Subtract, read(target), read(source)); } auto TLCS900H::instructionComplementCarry() -> void { @@ -15,5 +31,41 @@ auto TLCS900H::instructionComplementCarry() -> void { auto TLCS900H::instructionNoOperation() -> void { } +template +auto TLCS900H::instructionOr(Target target, Source source) -> void { + write(target, algorithm(Or, read(target), read(source))); +} + +template +auto TLCS900H::instructionPop(Target target) -> void { + write(target, pop()); +} + +template +auto TLCS900H::instructionPush(Source source) -> void { + push(read(source)); +} + auto TLCS900H::instructionSoftwareInterrupt(Immediate interrupt) -> void { } + +template +auto TLCS900H::instructionSubtract(Target target, Source source) -> void { + write(target, algorithm(Subtract, read(target), read(source))); +} + +template +auto TLCS900H::instructionSubtractCarry(Target target, Source source) -> void { + write(target, algorithm(Subtract, read(target), read(source), CF)); +} + +template +auto TLCS900H::instructionXor(Target target, Source source) -> void { + write(target, algorithm(Xor, read(target), read(source))); +} + +#undef read +#undef write +#undef push +#undef pop +#undef algorithm diff --git a/higan/processor/tlcs900h/memory.cpp b/higan/processor/tlcs900h/memory.cpp index af3d71d0..e0918128 100644 --- a/higan/processor/tlcs900h/memory.cpp +++ b/higan/processor/tlcs900h/memory.cpp @@ -10,16 +10,58 @@ template<> auto TLCS900H::fetch() -> uint16 { template<> auto TLCS900H::fetch() -> uint24 { uint24 data = fetch(); data |= fetch() << 8; - return data | fetch() << 16; + return data |= fetch() << 16; } template<> auto TLCS900H::fetch() -> uint32 { uint32 data = fetch(); data |= fetch() << 8; data |= fetch() << 16; - return data | fetch() << 24; + return data |= fetch() << 24; } +// + +#define XSP r.xsp.l.l0 + +template<> auto TLCS900H::push(Byte data) -> void { + write(--XSP, data); +} + +template<> auto TLCS900H::push(Word data) -> void { + write(--XSP, data >> 0); + write(--XSP, data >> 8); +} + +template<> auto TLCS900H::push(Long data) -> void { + write(--XSP, data >> 0); + write(--XSP, data >> 8); + write(--XSP, data >> 16); + write(--XSP, data >> 24); +} + +// + +template<> auto TLCS900H::pop() -> Byte { + return read(XSP++); +} + +template<> auto TLCS900H::pop() -> Word { + uint16 data = read(XSP++) << 0; + return data | read(XSP++) << 8; +} + +template<> auto TLCS900H::pop() -> Long { + uint32 data = read(XSP++) << 0; + data |= read(XSP++) << 8; + data |= read(XSP++) << 16; + return data |= read(XSP++) << 24; +} + +#undef XSP + +// + template<> auto TLCS900H::read(Memory memory) -> uint8 { uint32 address = memory.value; return read(address); @@ -36,7 +78,7 @@ template<> auto TLCS900H::read(Memory memory) -> uint32 { uint32 data = read(address + 0) << 0; data |= read(address + 1) << 8; data |= read(address + 2) << 16; - return data | read(address + 3) << 24; + return data |= read(address + 3) << 24; } template<> auto TLCS900H::write(Memory memory, uint8 data) -> void { diff --git a/higan/processor/tlcs900h/registers.cpp b/higan/processor/tlcs900h/registers.cpp index d4043d57..a042df74 100644 --- a/higan/processor/tlcs900h/registers.cpp +++ b/higan/processor/tlcs900h/registers.cpp @@ -1,11 +1,11 @@ -#define PC r.pc.l.l0 +#define PC r.pc.l.l0 -#define CF r.sr.f.c -#define NF r.sr.f.n -#define VF r.sr.f.v -#define HF r.sr.f.h -#define ZF r.sr.f.z -#define SF r.sr.f.s +#define CF r.sr.f.c +#define NF r.sr.f.n +#define VF r.sr.f.v +#define HF r.sr.f.h +#define ZF r.sr.f.z +#define SF r.sr.f.s #define RFP r.sr.rfp #define RFPP r.sr.rfpp @@ -14,74 +14,74 @@ #define a RFP #define p RFPP -template<> auto TLCS900H::map(Register register) -> maybe { +template<> auto TLCS900H::map(Register register) -> maybe { switch(register.value) { #define r(id, name) case id: return r.name; - r(RA0, xwa[0].b.b0) r(RW0, xwa[0].b.b1) r(QA0, xwa[0].b.b2) r(QW0, xwa[0].b.b3) - r(RC0, xbc[0].b.b0) r(RB0, xbc[0].b.b1) r(QC0, xbc[0].b.b2) r(QB0, xbc[0].b.b3) - r(RE0, xde[0].b.b0) r(RD0, xde[0].b.b1) r(QE0, xde[0].b.b2) r(QD0, xde[0].b.b3) - r(RL0, xhl[0].b.b0) r(RH0, xhl[0].b.b1) r(QL0, xhl[0].b.b2) r(QH0, xhl[0].b.b3) - r(RA1, xwa[1].b.b0) r(RW1, xwa[1].b.b1) r(QA1, xwa[1].b.b2) r(QW1, xwa[1].b.b3) - r(RC1, xbc[1].b.b0) r(RB1, xbc[1].b.b1) r(QC1, xbc[1].b.b2) r(QB1, xbc[1].b.b3) - r(RE1, xde[1].b.b0) r(RD1, xde[1].b.b1) r(QE1, xde[1].b.b2) r(QD1, xde[1].b.b3) - r(RL1, xhl[1].b.b0) r(RH1, xhl[1].b.b1) r(QL1, xhl[1].b.b2) r(QH1, xhl[1].b.b3) - r(RA2, xwa[2].b.b0) r(RW2, xwa[2].b.b1) r(QA2, xwa[2].b.b2) r(QW2, xwa[2].b.b3) - r(RC2, xbc[2].b.b0) r(RB2, xbc[2].b.b1) r(QC2, xbc[2].b.b2) r(QB2, xbc[2].b.b3) - r(RE2, xde[2].b.b0) r(RD2, xde[2].b.b1) r(QE2, xde[2].b.b2) r(QD2, xde[2].b.b3) - r(RL2, xhl[2].b.b0) r(RH2, xhl[2].b.b1) r(QL2, xhl[2].b.b2) r(QH2, xhl[2].b.b3) - r(RA3, xwa[3].b.b0) r(RW3, xwa[3].b.b1) r(QA3, xwa[3].b.b2) r(QW3, xwa[3].b.b3) - r(RC3, xbc[3].b.b0) r(RB3, xbc[3].b.b1) r(QC3, xbc[3].b.b2) r(QB3, xbc[3].b.b3) - r(RE3, xde[3].b.b0) r(RD3, xde[3].b.b1) r(QE3, xde[3].b.b2) r(QD3, xde[3].b.b3) - r(RL3, xhl[3].b.b0) r(RH3, xhl[3].b.b1) r(QL3, xhl[3].b.b2) r(QH3, xhl[3].b.b3) - r( AP, xwa[p].b.b0) r( WP, xwa[p].b.b1) r(QAP, xwa[p].b.b2) r(QWP, xwa[p].b.b3) - r( CP, xbc[p].b.b0) r( BP, xbc[p].b.b1) r(QCP, xbc[p].b.b2) r(QBP, xbc[p].b.b3) - r( EP, xde[p].b.b0) r( DP, xde[p].b.b1) r(QEP, xde[p].b.b2) r(QDP, xde[p].b.b3) - r( LP, xhl[p].b.b0) r( HP, xhl[p].b.b1) r(QLP, xhl[p].b.b2) r(QHP, xhl[p].b.b3) - r( A, xwa[a].b.b0) r( W, xwa[a].b.b1) r(QA, xwa[a].b.b2) r(QW, xwa[a].b.b3) - r( C, xbc[a].b.b0) r( B, xbc[a].b.b1) r(QC, xbc[a].b.b2) r(QB, xbc[a].b.b3) - r( E, xde[a].b.b0) r( D, xde[a].b.b1) r(QE, xde[a].b.b2) r(QD, xde[a].b.b3) - r( L, xhl[a].b.b0) r( H, xhl[a].b.b1) r(QL, xhl[a].b.b2) r(QH, xhl[a].b.b3) - r(IXL, xix.b.b0) r(IXH, xix.b.b1) r(QIXL, xix.b.b2) r(QIXH, xix.b.b3) - r(IYL, xiy.b.b0) r(IYH, xiy.b.b1) r(QIYL, xiy.b.b2) r(QIYH, xiy.b.b3) - r(IZL, xiz.b.b0) r(IZH, xiz.b.b1) r(QIZL, xiz.b.b2) r(QIZH, xiz.b.b3) - r(SPL, xsp.b.b0) r(SPH, xsp.b.b1) r(QSPL, xsp.b.b2) r(QSPH, xsp.b.b3) + r(0x00, xwa[0].b.b0) r(0x01, xwa[0].b.b1) r(0x02, xwa[0].b.b2) r(0x03, xwa[0].b.b3) + r(0x04, xbc[0].b.b0) r(0x05, xbc[0].b.b1) r(0x06, xbc[0].b.b2) r(0x07, xbc[0].b.b3) + r(0x08, xde[0].b.b0) r(0x09, xde[0].b.b1) r(0x0a, xde[0].b.b2) r(0x0b, xde[0].b.b3) + r(0x0c, xhl[0].b.b0) r(0x0d, xhl[0].b.b1) r(0x0e, xhl[0].b.b2) r(0x0f, xhl[0].b.b3) + r(0x10, xwa[1].b.b0) r(0x11, xwa[1].b.b1) r(0x12, xwa[1].b.b2) r(0x13, xwa[1].b.b3) + r(0x14, xbc[1].b.b0) r(0x15, xbc[1].b.b1) r(0x16, xbc[1].b.b2) r(0x17, xbc[1].b.b3) + r(0x18, xde[1].b.b0) r(0x19, xde[1].b.b1) r(0x1a, xde[1].b.b2) r(0x1b, xde[1].b.b3) + r(0x1c, xhl[1].b.b0) r(0x1d, xhl[1].b.b1) r(0x1e, xhl[1].b.b2) r(0x1f, xhl[1].b.b3) + r(0x20, xwa[2].b.b0) r(0x21, xwa[2].b.b1) r(0x22, xwa[2].b.b2) r(0x23, xwa[2].b.b3) + r(0x24, xbc[2].b.b0) r(0x25, xbc[2].b.b1) r(0x26, xbc[2].b.b2) r(0x27, xbc[2].b.b3) + r(0x28, xde[2].b.b0) r(0x29, xde[2].b.b1) r(0x2a, xde[2].b.b2) r(0x2b, xde[2].b.b3) + r(0x2c, xhl[2].b.b0) r(0x2d, xhl[2].b.b1) r(0x2e, xhl[2].b.b2) r(0x2f, xhl[2].b.b3) + r(0x30, xwa[3].b.b0) r(0x31, xwa[3].b.b1) r(0x32, xwa[3].b.b2) r(0x33, xwa[3].b.b3) + r(0x34, xbc[3].b.b0) r(0x35, xbc[3].b.b1) r(0x36, xbc[3].b.b2) r(0x37, xbc[3].b.b3) + r(0x38, xde[3].b.b0) r(0x39, xde[3].b.b1) r(0x3a, xde[3].b.b2) r(0x3b, xde[3].b.b3) + r(0x3c, xhl[3].b.b0) r(0x3d, xhl[3].b.b1) r(0x3e, xhl[3].b.b2) r(0x3f, xhl[3].b.b3) + r(0xd0, xwa[p].b.b0) r(0xd1, xwa[p].b.b1) r(0xd2, xwa[p].b.b2) r(0xd3, xwa[p].b.b3) + r(0xd4, xbc[p].b.b0) r(0xd5, xbc[p].b.b1) r(0xd6, xbc[p].b.b2) r(0xd7, xbc[p].b.b3) + r(0xd8, xde[p].b.b0) r(0xd9, xde[p].b.b1) r(0xda, xde[p].b.b2) r(0xdb, xde[p].b.b3) + r(0xdc, xhl[p].b.b0) r(0xdd, xhl[p].b.b1) r(0xde, xhl[p].b.b2) r(0xdf, xhl[p].b.b3) + r(0xe0, xwa[a].b.b0) r(0xe1, xwa[a].b.b1) r(0xe2, xwa[a].b.b2) r(0xe3, xwa[a].b.b3) + r(0xe4, xbc[a].b.b0) r(0xe5, xbc[a].b.b1) r(0xe6, xbc[a].b.b2) r(0xe7, xbc[a].b.b3) + r(0xe8, xde[a].b.b0) r(0xe9, xde[a].b.b1) r(0xea, xde[a].b.b2) r(0xeb, xde[a].b.b3) + r(0xec, xhl[a].b.b0) r(0xed, xhl[a].b.b1) r(0xee, xhl[a].b.b2) r(0xef, xhl[a].b.b3) + r(0xf0, xix .b.b0) r(0xf1, xix .b.b1) r(0xf2, xix .b.b2) r(0xf3, xix .b.b3) + r(0xf4, xiy .b.b0) r(0xf5, xiy .b.b1) r(0xf6, xiy .b.b2) r(0xf7, xiy .b.b3) + r(0xf8, xiz .b.b0) r(0xf9, xiz .b.b1) r(0xfa, xiz .b.b2) r(0xfb, xiz .b.b3) + r(0xfc, xsp .b.b0) r(0xfd, xsp .b.b1) r(0xfe, xsp .b.b2) r(0xff, xsp .b.b3) #undef r } return nothing; } -template<> auto TLCS900H::map(Register register) -> maybe { - switch(register.value) { +template<> auto TLCS900H::map(Register register) -> maybe { + switch(register.value & ~1) { #define r(id, name) case id: return r.name; - r(RWA0, xwa[0].w.w0) r(QWA0, xwa[0].w.w1) r(RBC0, xbc[0].w.w0) r(QBC0, xbc[0].w.w1) - r(RDE0, xde[0].w.w0) r(QDE0, xde[0].w.w1) r(RHL0, xhl[0].w.w0) r(QHL0, xhl[0].w.w1) - r(RWA1, xwa[1].w.w0) r(QWA1, xwa[1].w.w1) r(RBC1, xbc[1].w.w0) r(QBC1, xbc[1].w.w1) - r(RDE1, xde[1].w.w0) r(QDE1, xde[1].w.w1) r(RHL1, xhl[1].w.w0) r(QHL1, xhl[1].w.w1) - r(RWA2, xwa[2].w.w0) r(QWA2, xwa[2].w.w1) r(RBC2, xbc[2].w.w0) r(QBC2, xbc[2].w.w1) - r(RDE2, xde[2].w.w0) r(QDE2, xde[2].w.w1) r(RHL2, xhl[2].w.w0) r(QHL2, xhl[2].w.w1) - r(RWA3, xwa[3].w.w0) r(QWA3, xwa[3].w.w1) r(RBC3, xbc[3].w.w0) r(QBC3, xbc[3].w.w1) - r(RDE3, xde[3].w.w0) r(QDE3, xde[3].w.w1) r(RHL3, xhl[3].w.w0) r(QHL3, xhl[3].w.w1) - r( WAP, xwa[p].w.w0) r(QWAP, xwa[p].w.w1) r( BCP, xbc[p].w.w0) r(QBCP, xbc[p].w.w1) - r( DEP, xde[p].w.w0) r(QDEP, xde[p].w.w1) r( HLP, xhl[p].w.w0) r(QHLP, xhl[p].w.w1) - r( WA, xwa[p].w.w0) r(QWA, xwa[p].w.w1) r( BC, xbc[p].w.w0) r(QBC, xbc[p].w.w1) - r( DE, xde[p].w.w0) r(QDE, xde[p].w.w1) r( HL, xhl[p].w.w0) r(QHL, xhl[p].w.w1) - r(IX, xix.w.w0) r(QIX, xix.w.w1) r(IY, xiy.w.w0) r(QIY, xiy.w.w1) - r(IZ, xiz.w.w0) r(QIZ, xiz.w.w1) r(SP, xsp.w.w0) r(QSP, xsp.w.w0) + r(0x00, xwa[0].w.w0) r(0x02, xwa[0].w.w1) r(0x04, xbc[0].w.w0) r(0x06, xbc[0].w.w1) + r(0x08, xde[0].w.w0) r(0x0a, xde[0].w.w1) r(0x0c, xhl[0].w.w0) r(0x0e, xhl[0].w.w1) + r(0x10, xwa[1].w.w0) r(0x12, xwa[1].w.w1) r(0x14, xbc[1].w.w0) r(0x16, xbc[1].w.w1) + r(0x18, xde[1].w.w0) r(0x1a, xde[1].w.w1) r(0x1c, xhl[1].w.w0) r(0x1e, xhl[1].w.w1) + r(0x20, xwa[2].w.w0) r(0x22, xwa[2].w.w1) r(0x24, xbc[2].w.w0) r(0x26, xbc[2].w.w1) + r(0x28, xde[2].w.w0) r(0x2a, xde[2].w.w1) r(0x2c, xhl[2].w.w0) r(0x2e, xhl[2].w.w1) + r(0x30, xwa[3].w.w0) r(0x32, xwa[3].w.w1) r(0x34, xbc[3].w.w0) r(0x36, xbc[3].w.w1) + r(0x38, xde[3].w.w0) r(0x3a, xde[3].w.w1) r(0x3c, xhl[3].w.w0) r(0x3e, xhl[3].w.w1) + r(0xd0, xwa[p].w.w0) r(0xd2, xwa[p].w.w1) r(0xd4, xbc[p].w.w0) r(0xd6, xbc[p].w.w1) + r(0xd8, xde[p].w.w0) r(0xda, xde[p].w.w1) r(0xdc, xhl[p].w.w0) r(0xde, xhl[p].w.w1) + r(0xe0, xwa[p].w.w0) r(0xe2, xwa[p].w.w1) r(0xe4, xbc[p].w.w0) r(0xe6, xbc[p].w.w1) + r(0xe8, xde[p].w.w0) r(0xea, xde[p].w.w1) r(0xec, xhl[p].w.w0) r(0xee, xhl[p].w.w1) + r(0xf0, xix .w.w0) r(0xf2, xix .w.w1) r(0xf4, xiy .w.w0) r(0xf6, xiy .w.w1) + r(0xf8, xiz .w.w0) r(0xfa, xiz .w.w1) r(0xfc, xsp .w.w0) r(0xfe, xsp .w.w0) #undef r } return nothing; } -template<> auto TLCS900H::map(Register register) -> maybe { - switch(register.value) { +template<> auto TLCS900H::map(Register register) -> maybe { + switch(register.value & ~3) { #define r(id, name) case id: return r.name; - r(XWA0, xwa[0].l.l0) r(XBC0, xbc[0].l.l0) r(XDE0, xde[0].l.l0) r(XHL0, xhl[0].l.l0) - r(XWA1, xwa[1].l.l0) r(XBC1, xbc[1].l.l0) r(XDE1, xde[1].l.l0) r(XHL1, xhl[1].l.l0) - r(XWA2, xwa[2].l.l0) r(XBC2, xbc[2].l.l0) r(XDE2, xde[2].l.l0) r(XHL2, xhl[2].l.l0) - r(XWA3, xwa[3].l.l0) r(XBC3, xbc[3].l.l0) r(XDE3, xde[3].l.l0) r(XHL3, xhl[3].l.l0) - r(XWAP, xwa[p].l.l0) r(XBCP, xbc[p].l.l0) r(XDEP, xde[p].l.l0) r(XHLP, xhl[p].l.l0) - r(XWA, xwa[a].l.l0) r(XBC, xbc[a].l.l0) r(XDE, xde[a].l.l0) r(XHL, xhl[a].l.l0) - r(XIX, xix.l.l0) r(XIY, xiy.l.l0) r(XIZ, xiz.l.l0) r(XSP, xsp.l.l0) + r(0x00, xwa[0].l.l0) r(0x04, xbc[0].l.l0) r(0x08, xde[0].l.l0) r(0x0c, xhl[0].l.l0) + r(0x10, xwa[1].l.l0) r(0x14, xbc[1].l.l0) r(0x18, xde[1].l.l0) r(0x1c, xhl[1].l.l0) + r(0x20, xwa[2].l.l0) r(0x24, xbc[2].l.l0) r(0x28, xde[2].l.l0) r(0x2c, xhl[2].l.l0) + r(0x30, xwa[3].l.l0) r(0x34, xbc[3].l.l0) r(0x38, xde[3].l.l0) r(0x3c, xhl[3].l.l0) + r(0xd0, xwa[p].l.l0) r(0xd4, xbc[p].l.l0) r(0xd8, xde[p].l.l0) r(0xdc, xhl[p].l.l0) + r(0xe0, xwa[a].l.l0) r(0xe4, xbc[a].l.l0) r(0xe8, xde[a].l.l0) r(0xec, xhl[a].l.l0) + r(0xf0, xix .l.l0) r(0xf4, xiy .l.l0) r(0xf8, xiz .l.l0) r(0xfc, xsp .l.l0) #undef r } return nothing; @@ -90,26 +90,64 @@ template<> auto TLCS900H::map(Register register) -> maybe { #undef a #undef p -template<> auto TLCS900H::read(Register register) -> uint8 { +template<> auto TLCS900H::read(Register register) -> Byte { return map(register)(0); } -template<> auto TLCS900H::read(Register register) -> uint16 { +template<> auto TLCS900H::read(Register register) -> Word { return map(register)(0); } -template<> auto TLCS900H::read(Register register) -> uint32 { +template<> auto TLCS900H::read(Register register) -> Long { return map(register)(0); } -template<> auto TLCS900H::write(Register register, uint8 data) -> void { +template<> auto TLCS900H::write(Register register, Byte data) -> void { if(auto r = map(register)) r() = data; } -template<> auto TLCS900H::write(Register register, uint16 data) -> void { +template<> auto TLCS900H::write(Register register, Word data) -> void { if(auto r = map(register)) r() = data; } -template<> auto TLCS900H::write(Register register, uint32 data) -> void { - if(auto r = map(register)) r() = data; +template<> auto TLCS900H::write(Register register, Long data) -> void { + if(auto r = map(register)) r() = data; +} + +// + +//todo: this is pretty hacky ... the templates pass by-value, but we need to modify the status register +//since there's only one, we ignore the parameter and access the underlying register directly instead + +template<> auto TLCS900H::read(StatusRegister) -> Word { + return r.sr.f.c << 0 | r.sr.f.n << 1 | r.sr.f.v << 2 | r.sr.f.h << 4 | r.sr.f.z << 6 | r.sr.f.s << 7 + | r.sr.rfp << 8 | 1 << 11 | r.sr.iff << 12 | 1 << 15; +} + +template<> auto TLCS900H::write(StatusRegister, Word data) -> void { + r.sr.f.c = data.bit(0); + r.sr.f.n = data.bit(1); + r.sr.f.v = data.bit(2); + r.sr.f.h = data.bit(4); + r.sr.f.z = data.bit(6); + r.sr.f.s = data.bit(7); + r.sr.rfp = data.bits(8,9); + r.sr.iff = data.bits(12,14); + + r.sr.rfpp = r.sr.rfp - 1; +} + +//todo: the same thing for the flag register + +template<> auto TLCS900H::read(FlagRegister) -> Byte { + return r.sr.f.c << 0 | r.sr.f.n << 1 | r.sr.f.v << 2 | r.sr.f.h << 4 | r.sr.f.z << 6 | r.sr.f.s << 7; +} + +template<> auto TLCS900H::write(FlagRegister, Byte data) -> void { + r.sr.f.c = data.bit(0); + r.sr.f.n = data.bit(1); + r.sr.f.v = data.bit(2); + r.sr.f.h = data.bit(4); + r.sr.f.z = data.bit(6); + r.sr.f.s = data.bit(7); } diff --git a/higan/processor/tlcs900h/tlcs900h.cpp b/higan/processor/tlcs900h/tlcs900h.cpp index 3bff03a2..898a518d 100644 --- a/higan/processor/tlcs900h/tlcs900h.cpp +++ b/higan/processor/tlcs900h/tlcs900h.cpp @@ -3,12 +3,18 @@ namespace Processor { +//todo: these defines should not be necessary; yet ADL doesn't work without them ... why not? #define Byte uint8 #define Word uint16 #define Long uint32 +template static constexpr auto isByte() -> bool { return is_same::value; } +template static constexpr auto isWord() -> bool { return is_same::value; } +template static constexpr auto isLong() -> bool { return is_same::value; } + #include "registers.cpp" #include "memory.cpp" +#include "conditions.cpp" #include "algorithms.cpp" #include "instruction.cpp" #include "instructions.cpp" diff --git a/higan/processor/tlcs900h/tlcs900h.hpp b/higan/processor/tlcs900h/tlcs900h.hpp index 06b6aae4..8ccb57e8 100644 --- a/higan/processor/tlcs900h/tlcs900h.hpp +++ b/higan/processor/tlcs900h/tlcs900h.hpp @@ -1,5 +1,12 @@ //Toshiba TLCS900/H +/* open questions: + * + * what happens when a prohibited instruction operand size is used? (eg adc.l (memory),#immediate) + * what happens when %11 is used for pre-decrement and post-increment addressing? + * what happens when using 8-bit register indexing and d0 is set (Word) or d1/d0 is set (Long)? + */ + #pragma once namespace Processor { @@ -13,43 +20,6 @@ struct TLCS900H { struct Memory { Long value; }; struct Immediate { Long value; }; - virtual auto read(uint32 address) -> uint8 = 0; - virtual auto write(uint32 address, uint8 data) -> void = 0; - - template auto read(Immediate immediate) -> Size { return immediate.value; } - - //tlcs900h.cpp - auto power() -> void; - - //registers.cpp - template auto map(Register register) -> maybe; - template auto read(Register) -> Size; - template auto write(Register, Size data) -> void; - - //memory.cpp - template auto fetch() -> Size; - template auto read(Memory memory) -> Size; - template auto write(Memory memory, Size data) -> void; - - //algorithms.cpp - template auto algorithmAdd(Size target, Size source, uint1 carry = 0) -> Size; - - //instruction.cpp - auto instruction() -> void; - template auto instructionRegister(Register input) -> void; - template auto instructionSourceMemory(Memory input) -> void; - auto instructionTargetMemory(Memory input) -> void; - - //instructions.cpp - template auto instructionAdd(Target target, Source source) -> void; - template auto instructionAddCarry(Target target, Source source) -> void; - auto instructionComplementCarry() -> void; - auto instructionNoOperation() -> void; - auto instructionSoftwareInterrupt(Immediate interrupt) -> void; - - //serialization.cpp - auto serialize(serializer&) -> void; - struct DataRegister { union { struct { Long order_lsb1(l0); } l; @@ -75,6 +45,67 @@ struct TLCS900H { FlagRegister fp; }; + virtual auto read(uint32 address) -> uint8 = 0; + virtual auto write(uint32 address, uint8 data) -> void = 0; + + template auto read(Immediate immediate) -> Size { return immediate.value; } + + //tlcs900h.cpp + auto power() -> void; + + //registers.cpp + template auto map(Register register) -> maybe; + template auto read(Register) -> Size; + template auto write(Register, Size data) -> void; + template auto read(StatusRegister) -> Size; + template auto write(StatusRegister, Size) -> void; + template auto read(FlagRegister) -> Size; + template auto write(FlagRegister, Size) -> void; + + //memory.cpp + template auto fetch() -> Size; + template auto push(Size) -> void; + template auto pop() -> Size; + template auto read(Memory memory) -> Size; + template auto write(Memory memory, Size data) -> void; + + //conditions.cpp + auto condition(uint4 code) -> bool; + + //algorithms.cpp + template auto parity(Size) const -> bool; + template auto algorithmAdd(Size target, Size source, uint1 carry = 0) -> Size; + template auto algorithmAnd(Size target, Size source) -> Size; + template auto algorithmOr(Size target, Size source) -> Size; + template auto algorithmSubtract(Size target, Size source, uint1 carry = 0) -> Size; + template auto algorithmXor(Size target, Size source) -> Size; + + //instruction.cpp + template auto registerLookup(uint3 code) -> Register; + + auto instruction() -> void; + template auto instructionRegister(Register) -> void; + template auto instructionSourceMemory(Memory) -> void; + auto instructionTargetMemory(Memory) -> void; + + //instructions.cpp + template auto instructionAdd(Target target, Source source) -> void; + template auto instructionAddCarry(Target target, Source source) -> void; + template auto instructionAnd(Target target, Source source) -> void; + template auto instructionCompare(Target target, Source source) -> void; + auto instructionComplementCarry() -> void; + auto instructionNoOperation() -> void; + template auto instructionOr(Target target, Source source) -> void; + template auto instructionPop(Target target) -> void; + template auto instructionPush(Source source) -> void; + auto instructionSoftwareInterrupt(Immediate interrupt) -> void; + template auto instructionSubtract(Target target, Source source) -> void; + template auto instructionSubtractCarry(Target target, Source source) -> void; + template auto instructionXor(Target target, Source source) -> void; + + //serialization.cpp + auto serialize(serializer&) -> void; + struct Registers { DataRegister xwa[4]; DataRegister xbc[4]; @@ -88,37 +119,34 @@ struct TLCS900H { StatusRegister sr; } r; - enum : uint { - RA0, RW0, QA0, QW0, RC0, RB0, QC0, QB0, RE0, RD0, QE0, QD0, RL0, RH0, QL0, QH0, - RA1, RW1, QA1, QW1, RC1, RB1, QC1, QB1, RE1, RD1, QE1, QD1, RL1, RH1, QL1, QH1, - RA2, RW2, QA2, QW2, RC2, RB2, QC2, QB2, RE2, RD2, QE2, QD2, RL2, RH2, QL2, QH2, - RA3, RW3, QA3, QW3, RC3, RB3, QC3, QB3, RE3, RD3, QE3, QD3, RL3, RH3, QL3, QH3, SPC = 0xcf, //AP = 0xd0 - AP, WP, QAP, QWP, CP, BP, QCP, QBP, EP, DP, QEP, QDP, LP, HP, QLP, QHP, - A, W, QA, QW, C, B, QC, QB, E, D, QE, QD, L, H, QL, QH, - IXL, IXH, QIXL,QIXH,IYL, IYH, QIYL,QIYH,IZL, IZH, QIZL,QIZH,SPL, SPH, QSPL,QSPH, - }; + static inline const Register A{0xe0}; + static inline const Register W{0xe1}; + static inline const Register C{0xe4}; + static inline const Register B{0xe5}; + static inline const Register E{0xe8}; + static inline const Register D{0xe9}; + static inline const Register L{0xec}; + static inline const Register H{0xed}; - enum : uint { - RWA0 = 0x00, QWA0 = 0x02, RBC0 = 0x04, QBC0 = 0x06, RDE0 = 0x08, QDE0 = 0x0a, RHL0 = 0x0c, QHL0 = 0x0e, - RWA1 = 0x10, QWA1 = 0x12, RBC1 = 0x14, QBC1 = 0x16, RDE1 = 0x18, QDE1 = 0x1a, RHL1 = 0x1c, QHL1 = 0x1e, - RWA2 = 0x20, QWA2 = 0x22, RBC2 = 0x24, QBC2 = 0x26, RDE2 = 0x28, QDE2 = 0x2a, RHL2 = 0x2c, QHL2 = 0x2e, - RWA3 = 0x30, QWA3 = 0x32, RBC3 = 0x34, QBC3 = 0x36, RDE3 = 0x38, QDE3 = 0x3a, RHL3 = 0x3c, QHL3 = 0x3e, - WAP = 0xd0, QWAP = 0xd2, BCP = 0xd4, QBCP = 0xd6, DEP = 0xd8, QDEP = 0xda, HLP = 0xdc, QHLP = 0xde, - WA = 0xe0, QWA = 0xe2, BC = 0xe4, QBC = 0xe6, DE = 0xe8, QDE = 0xea, HL = 0xec, QHL = 0xee, - IX = 0xf0, QIX = 0xf2, IY = 0xf4, QIY = 0xf6, IZ = 0xf8, QIZ = 0xfa, SP = 0xfc, QSP = 0xfe, - }; + static inline const Register WA{0xe0}; + static inline const Register BC{0xe4}; + static inline const Register DE{0xe8}; + static inline const Register HL{0xec}; + static inline const Register IX{0xf0}; + static inline const Register IY{0xf4}; + static inline const Register IZ{0xf8}; + static inline const Register SP{0xfc}; - enum : uint { - XWA0 = 0x00, XBC0 = 0x04, XDE0 = 0x08, XHL0 = 0x0c, - XWA1 = 0x10, XBC1 = 0x14, XDE1 = 0x18, XHL1 = 0x1c, - XWA2 = 0x20, XBC2 = 0x24, XDE2 = 0x28, XHL2 = 0x2c, - XWA3 = 0x30, XBC3 = 0x34, XDE3 = 0x38, XHL3 = 0x3c, - XWAP = 0xd0, XBCP = 0xd4, XDEP = 0xd8, XHLP = 0xdc, - XWA = 0xe0, XBC = 0xe4, XDE = 0xe8, XHL = 0xec, - XIX = 0xf0, XIY = 0xf4, XIZ = 0xf8, XSP = 0xfc, - }; + static inline const Register XWA{0xe0}; + static inline const Register XBC{0xe4}; + static inline const Register XDE{0xe8}; + static inline const Register XHL{0xec}; + static inline const Register XIX{0xf0}; + static inline const Register XIY{0xf4}; + static inline const Register XIZ{0xf8}; + static inline const Register XSP{0xfc}; - const uint1 undefined = 0; + static inline const uint1 Undefined = 0; }; } diff --git a/nall/primitives.hpp b/nall/primitives.hpp index b31ca689..95fe6154 100644 --- a/nall/primitives.hpp +++ b/nall/primitives.hpp @@ -36,6 +36,8 @@ template struct Natural { enum : type { Mask = ~0ull >> (64 - Bits) }; + static inline constexpr auto bits() -> uint { return Bits; } + inline Natural() : data(0) {} template inline Natural(const T& value) { set(value); } @@ -101,6 +103,10 @@ template struct Natural { const type Hi; }; + inline auto zero() const -> bool { return data == 0; } + inline auto positive() const -> bool { return (data >> bits() - 1) == 0; } + inline auto negative() const -> bool { return (data >> bits() - 1) == 1; } + inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; } inline auto bit(uint index) -> Reference { return {*this, index, index}; } inline auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; } @@ -140,6 +146,8 @@ template struct Integer { enum : utype { Mask = ~0ull >> (64 - Bits), Sign = 1ull << (Bits - 1) }; + static inline constexpr auto bits() -> uint { return Bits; } + inline Integer() : data(0) {} template inline Integer(const T& value) { set(value); } @@ -205,6 +213,10 @@ template struct Integer { const uint Hi; }; + inline auto zero() const -> bool { return data == 0; } + inline auto positive() const -> bool { return data >= 0; } + inline auto negative() const -> bool { return data < 0; } + inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; } inline auto bit(uint index) -> Reference { return {*this, index, index}; } inline auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; } @@ -239,6 +251,8 @@ template struct Real { typename conditional::type>::type; + static inline constexpr auto bits() -> uint { return Bits; } + inline Real() : data(0.0) {} template inline Real(const T& value) : data((type)value) {}