From c9f7c6c4be021946221a34329b4022aa6f41fa42 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Fri, 11 Jan 2019 12:51:18 +1100 Subject: [PATCH] Update to v106r76 release. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit byuu says: I added some useful new functions to nall/primitives: auto Natural::integer() const -> Integer; auto Integer::natural() const -> Natural; These let you cast between signed and unsigned representation without having to care about the value of T (eg if you take a Natural as a template parameter.) So for instance when you're given an unsigned type but it's supposed to be a sign-extended type (example: signed multiplication), eg Natural → Integer, you can just say: x = y.integer() * z.integer(); The TLCS900H core gained some more pesky instructions such as DAA, BS1F, BS1B. I stole an optimization from RACE for calculating the overflow flag on addition. Assuming: z = x + y + c; Before: ~(x ^ y) & (x ^ z) & signBit; After: (x ^ z) & (y ^ z) & signBit; Subtraction stays the same. Assuming: z = x - y - c; Same: (x ^ y) & (x ^ z) & signBit; However, taking a speed penalty, I've implemented the carry computation in a way that doesn't require an extra bit. Adding before: uint9 z = x + y + c; c = z & 0x100; Subtracting before: uint9 z = x - y - c; c = z & 0x100; Adding after: uint8 z = x + y + c; c = z < x || z == x && c; Subtracting after: uint8 z = x - y - c; c = z > x || z == x && c; I haven't been able to code golf the new carry computation to be any shorter, unless I include an extra bit, eg for adding: c = z < x + c; But that defeats the entire point of the change. I want the computation to work even when T is uintmax_t. If anyone can come up with a faster method, please let me know. Anyway ... I also had to split off INC and DEC because they compute flags differently (word and long modes don't set flags at all, byte mode doesn't set carry at all.) I also added division by zero support, although I don't know if it's actually hardware accurate. It's what other emulators do, though. --- higan/emulator/emulator.hpp | 2 +- higan/processor/tlcs900h/algorithms.cpp | 42 ++++++++-- .../processor/tlcs900h/control-registers.cpp | 12 +-- higan/processor/tlcs900h/instruction.cpp | 75 ++++++++++------- higan/processor/tlcs900h/instructions.cpp | 82 ++++++++++++++++--- higan/processor/tlcs900h/registers.cpp | 22 ++--- higan/processor/tlcs900h/tlcs900h.hpp | 74 ++++++----------- nall/primitives.hpp | 18 ++++ 8 files changed, 211 insertions(+), 116 deletions(-) diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index c477d834..082d9c29 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.75"; + static const string Version = "106.76"; 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 10fa24e7..449054c2 100644 --- a/higan/processor/tlcs900h/algorithms.cpp +++ b/higan/processor/tlcs900h/algorithms.cpp @@ -20,13 +20,13 @@ template<> auto TLCS900H::parity(uint32 data) const -> bool { // template auto TLCS900H::algorithmAdd(T target, T source, uint1 carry) -> T { - uint64 result = target + source + carry; - CF = result.bit(T::bits()); + T result = target + source + carry; + CF = result < target || result == target && carry; NF = 0; - VF = T(~(target ^ source) & (target ^ result)).negative(); + VF = T((target ^ result) & (source ^ result)).negative(); HF = T(target ^ source ^ result).bit(4); - if constexpr(is_same::value) HF = Undefined; - ZF = T(result).zero(); + if constexpr(T::bits() == 32) HF = Undefined; + ZF = result.zero(); SF = result.negative(); return result; } @@ -42,6 +42,30 @@ template auto TLCS900H::algorithmAnd(T target, T source) -> T { return result; } +template auto TLCS900H::algorithmDecrement(T target, T source) -> T { + T result = target - source; + if constexpr(T::bits() == 8) { + NF = 1; + VF = T((target ^ source) & (target ^ result)).negative(); + HF = T(target ^ source ^ result).bit(4); + ZF = result.zero(); + SF = result.negative(); + } + return result; +} + +template auto TLCS900H::algorithmIncrement(T target, T source) -> T { + T result = target + source; + if constexpr(T::bits() == 8) { + NF = 0; + VF = T((target ^ result) & (source ^ result)).negative(); + HF = T(target ^ source ^ result).bit(4); + ZF = result.zero(); + SF = result.negative(); + } + return result; +} + template auto TLCS900H::algorithmOr(T target, T source) -> T { T result = target | source; CF = 0; @@ -54,13 +78,13 @@ template auto TLCS900H::algorithmOr(T target, T source) -> T { } template auto TLCS900H::algorithmSubtract(T target, T source, uint1 carry) -> T { - uint64 result = target - source - carry; - CF = result.bit(T::bits()); + T result = target - source - carry; + CF = result > target || result == target && carry; NF = 1; VF = T((target ^ source) & (target ^ result)).negative(); HF = T(target ^ source ^ result).bit(4); - if constexpr(is_same::value) HF = Undefined; - ZF = T(result).zero(); + if constexpr(T::bits() == 32) HF = Undefined; + ZF = result.zero(); SF = result.negative(); return result; } diff --git a/higan/processor/tlcs900h/control-registers.cpp b/higan/processor/tlcs900h/control-registers.cpp index 58270507..3ddccfdb 100644 --- a/higan/processor/tlcs900h/control-registers.cpp +++ b/higan/processor/tlcs900h/control-registers.cpp @@ -1,4 +1,4 @@ -template<> auto TLCS900H::map(ControlRegister register) -> maybe { +template<> auto TLCS900H::map(ControlRegister register) const -> maybe { switch(register.id) { #define r(id, name) case id: return r.name; r(0x00, dmas[0].b.b0) r(0x01, dmas[0].b.b1) r(0x02, dmas[0].b.b2) r(0x03, dmas[0].b.b3) @@ -19,7 +19,7 @@ template<> auto TLCS900H::map(ControlRegister register) -> maybe return nothing; } -template<> auto TLCS900H::map(ControlRegister register) -> maybe { +template<> auto TLCS900H::map(ControlRegister register) const -> maybe { switch(register.id & ~1) { #define r(id, name) case id: return r.name; r(0x00, dmas[0].w.w0) r(0x02, dmas[0].w.w1) @@ -40,7 +40,7 @@ template<> auto TLCS900H::map(ControlRegister register) -> maybe auto TLCS900H::map(ControlRegister register) -> maybe { +template<> auto TLCS900H::map(ControlRegister register) const -> maybe { switch(register.id & ~1) { #define r(id, name) case id: return r.name; r(0x00, dmas[0].l.l0) @@ -61,9 +61,9 @@ template<> auto TLCS900H::map(ControlRegister register) -> maybe auto TLCS900H::load< uint8>(ControlRegister< uint8> register) -> uint8 { return map(register)(Undefined); } -template<> auto TLCS900H::load(ControlRegister register) -> uint16 { return map(register)(Undefined); } -template<> auto TLCS900H::load(ControlRegister register) -> uint32 { return map(register)(Undefined); } +template<> auto TLCS900H::load< uint8>(ControlRegister< uint8> register) const -> uint8 { return map(register)(Undefined); } +template<> auto TLCS900H::load(ControlRegister register) const -> uint16 { return map(register)(Undefined); } +template<> auto TLCS900H::load(ControlRegister register) const -> uint32 { return map(register)(Undefined); } template<> auto TLCS900H::store(ControlRegister register, uint32 data) -> void { if(auto r = map(register)) r() = data; diff --git a/higan/processor/tlcs900h/instruction.cpp b/higan/processor/tlcs900h/instruction.cpp index 597f2f46..448dadaa 100644 --- a/higan/processor/tlcs900h/instruction.cpp +++ b/higan/processor/tlcs900h/instruction.cpp @@ -282,18 +282,36 @@ auto TLCS900H::instructionRegister(R register) -> void { if constexpr(bits == 32) return (void)Undefined; return instructionNegate(register); case 0x08: - if constexpr(bits == 32) return (void)Undefined; - return instructionMultiply(register, fetchImmediate()); + if constexpr(bits != 32) return instructionMultiply(register, fetchImmediate()); + return (void)Undefined; case 0x09: - if constexpr(bits == 32) return (void)Undefined; - return instructionMultiplySigned(register, fetchImmediate()); + if constexpr(bits != 32) return instructionMultiplySigned(register, fetchImmediate()); + return (void)Undefined; case 0x0a: - if constexpr(bits == 32) return (void)Undefined; - return instructionDivide(register, fetchImmediate()); + if constexpr(bits != 32) return instructionDivide(register, fetchImmediate()); + return (void)Undefined; case 0x0b: - if constexpr(bits == 32) return (void)Undefined; - return instructionDivideSigned(register, fetchImmediate()); + if constexpr(bits != 32) return instructionDivideSigned(register, fetchImmediate()); + return (void)Undefined; +//case 0x0c: LINK r,dd +//case 0x0d: UNLK r + case 0x0e: + if constexpr(bits == 16) return instructionBitSearch1Forward(register); + return (void)Undefined; + case 0x0f: + if constexpr(bits == 16) return instructionBitSearch1Backward(register); + return (void)Undefined; + case 0x10: + if constexpr(bits == 8) return instructionDecimalAdjustAccumulator(register); + return (void)Undefined; case 0x11: return (void)Undefined; + case 0x12: + if constexpr(bits != 8) return instructionExtendZero(register); + return (void)Undefined; + case 0x13: + if constexpr(bits != 8) return instructionExtendSign(register); + return (void)Undefined; +//case 0x14: PAA r case 0x15: return (void)Undefined; case 0x16: if constexpr(bits == 16) return instructionMirror(register); @@ -303,6 +321,7 @@ auto TLCS900H::instructionRegister(R register) -> void { if constexpr(bits == 16) return instructionMultiplyAdd(register); return (void)Undefined; case 0x1a: case 0x1b: return (void)Undefined; +//case 0x1c: DJNZ r,d case 0x1d: case 0x1e: case 0x1f: return (void)Undefined; case 0x25: case 0x26: case 0x27: return (void)Undefined; case 0x2d: return (void)Undefined; @@ -312,21 +331,21 @@ auto TLCS900H::instructionRegister(R register) -> void { case 0x3b: return (void)Undefined; case 0x3f: return (void)Undefined; case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: - if constexpr(bits == 32) return (void)Undefined; - return instructionMultiply(toRegister3(data), register); + if constexpr(bits != 32) return instructionMultiply(toRegister3(data), register); + return (void)Undefined; case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: - if constexpr(bits == 32) return (void)Undefined; - return instructionMultiplySigned(toRegister3(data), register); + if constexpr(bits != 32) return instructionMultiplySigned(toRegister3(data), register); + return (void)Undefined; case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: - if constexpr(bits == 32) return (void)Undefined; - return instructionDivide(toRegister3(data), register); + if constexpr(bits != 32) return instructionDivide(toRegister3(data), register); + return (void)Undefined; case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: - if constexpr(bits == 32) return (void)Undefined; - return instructionDivideSigned(toRegister3(data), register); + if constexpr(bits != 32) return instructionDivideSigned(toRegister3(data), register); + return (void)Undefined; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: - return instructionAdd(register, toImmediate3(data)); + return instructionIncrement(register, toImmediate((uint3)data)); case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: - return instructionSubtract(register, toImmediate3(data)); + return instructionDecrement(register, toImmediate((uint3)data)); 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: if constexpr(bits == 32) return (void)Undefined; @@ -418,21 +437,21 @@ auto TLCS900H::instructionSourceMemory(M memory) -> void { if constexpr(bits == 32) return (void)Undefined; return instructionCompare(memory, fetchImmediate()); case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: - if constexpr(bits == 32) return (void)Undefined; - return instructionMultiply(toRegister3(data), memory); + if constexpr(bits != 32) return instructionMultiply(toRegister3(data), memory); + return (void)Undefined; case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: - if constexpr(bits == 32) return (void)Undefined; - return instructionMultiplySigned(toRegister3(data), memory); + if constexpr(bits != 32) return instructionMultiplySigned(toRegister3(data), memory); + return (void)Undefined; case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: - if constexpr(bits == 32) return (void)Undefined; - return instructionDivide(toRegister3(data), memory); + if constexpr(bits != 32) return instructionDivide(toRegister3(data), memory); + return (void)Undefined; case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: - if constexpr(bits == 32) return (void)Undefined; - return instructionDivideSigned(toRegister3(data), memory); + if constexpr(bits != 32) return instructionDivideSigned(toRegister3(data), memory); + return (void)Undefined; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: - return instructionAdd(memory, toImmediate3(data)); + return instructionIncrement(memory, toImmediate((uint3)data)); case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: - return instructionSubtract(memory, toImmediate3(data)); + return instructionDecrement(memory, toImmediate((uint3)data)); case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: return (void)Undefined; case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: return instructionAdd(toRegister3(data), memory); diff --git a/higan/processor/tlcs900h/instructions.cpp b/higan/processor/tlcs900h/instructions.cpp index 4772320e..1c745acb 100644 --- a/higan/processor/tlcs900h/instructions.cpp +++ b/higan/processor/tlcs900h/instructions.cpp @@ -1,11 +1,3 @@ -template -auto TLCS900H::toSigned(Target target) -> int32 { - if constexpr(Target::bits() == 8) return (int8)target; - if constexpr(Target::bits() == 16) return (int16)target; - if constexpr(Target::bits() == 32) return (int32)target; - return Undefined; -} - template auto TLCS900H::instructionAdd(Target target, Source source) -> void { store(target, algorithmAdd(load(target), load(source))); @@ -21,6 +13,22 @@ auto TLCS900H::instructionAnd(Target target, Source source) -> void { store(target, algorithmAnd(load(target), load(source))); } +auto TLCS900H::instructionBitSearch1Backward(Register register) -> void { + auto value = load(register); + for(uint index : reverse(range(16))) { + if(value.bit(index)) return VF = 1, store(A, index); + } + VF = 0; +} + +auto TLCS900H::instructionBitSearch1Forward(Register register) -> void { + auto value = load(register); + for(uint index : range(16)) { + if(value.bit(index)) return VF = 1, store(A, index); + } + VF = 0; +} + template auto TLCS900H::instructionCall(uint4 code, Source source) -> void { auto address = load(source); @@ -45,16 +53,46 @@ auto TLCS900H::instructionComplement(Target target) -> void { HF = 1; } +auto TLCS900H::instructionDecimalAdjustAccumulator(Register register) -> void { + auto value = load(register); + if(CF || (uint8)value > 0x99) value += NF ? -0x60 : 0x60, CF = 1; + if(HF || (uint4)value > 0x09) value += NF ? -0x06 : 0x06; + PF = parity(value); + HF = uint8(value ^ load(register)).bit(4); + ZF = value.zero(); + SF = value.negative(); + store(register, value); +} + +template +auto TLCS900H::instructionDecrement(Target target, Source source) -> void { + auto immediate = load(source); + if(!immediate) immediate = 8; + store(target, algorithmDecrement(load(target), immediate)); +} + template auto TLCS900H::instructionDivide(Target target, Source source) -> void { - //TODO: division by zero - store(expand(target), load(target) / load(source)); + using T = typename Target::type; + using E = Natural<2 * T::bits()>; + auto dividend = load(expand(target)); + auto divisor = load(source); + auto quotient = divisor ? E(dividend / divisor) : E(T(~(dividend >> T::bits()))); + auto remainder = divisor ? E(dividend % divisor) : E(T(dividend)); + store(expand(target), T(remainder) << T::bits() | T(quotient)); + VF = !divisor || remainder >> T::bits(); } template auto TLCS900H::instructionDivideSigned(Target target, Source source) -> void { - //TODO: division by zero - store(expand(target), toSigned(load(target)) / toSigned(load(source))); + using T = typename Target::type; + using E = Natural<2 * T::bits()>; + auto dividend = load(expand(target)).integer(); + auto divisor = load(source).integer(); + auto quotient = divisor ? E(dividend / divisor) : E(T(~(dividend >> T::bits()))); + auto remainder = divisor ? E(dividend % divisor) : E(T(dividend)); + store(expand(target), T(remainder) << T::bits() | T(quotient)); + VF = !divisor || remainder >> T::bits(); } template @@ -64,10 +102,27 @@ auto TLCS900H::instructionExchange(Target target, Source source) -> void { store(source, data); } +template +auto TLCS900H::instructionExtendSign(Target target) -> void { + store(target, load(shrink(target)).integer()); +} + +template +auto TLCS900H::instructionExtendZero(Target target) -> void { + store(target, load(shrink(target))); +} + auto TLCS900H::instructionHalt() -> void { setHalted(true); } +template +auto TLCS900H::instructionIncrement(Target target, Source source) -> void { + auto immediate = load(source); + if(!immediate) immediate = 8; + store(target, algorithmIncrement(load(target), immediate)); +} + template auto TLCS900H::instructionJump(uint4 code, Source source) -> void { auto address = load(source); @@ -85,6 +140,7 @@ auto TLCS900H::instructionLoad(Target target, Source source) -> void { } //reverse all bits in a 16-bit register +//note: an 8-bit lookup table is faster (when in L1/L2 cache), but much more code auto TLCS900H::instructionMirror(Register register) -> void { auto data = load(register); uint8 lo = (data.byte(0) * 0x80200802ull & 0x884422110ull) * 0x101010101ull >> 32; @@ -114,7 +170,7 @@ auto TLCS900H::instructionMultiplyAdd(Register register) -> void { template auto TLCS900H::instructionMultiplySigned(Target target, Source source) -> void { - store(expand(target), toSigned(load(target)) * toSigned(load(source))); + store(expand(target), load(target).integer() * load(source).integer()); } template diff --git a/higan/processor/tlcs900h/registers.cpp b/higan/processor/tlcs900h/registers.cpp index 5e2bb59a..e69ffc61 100644 --- a/higan/processor/tlcs900h/registers.cpp +++ b/higan/processor/tlcs900h/registers.cpp @@ -1,7 +1,7 @@ #define a RFP #define p RFP - 1 & 3 -template<> auto TLCS900H::map(Register register) -> maybe { +template<> auto TLCS900H::map(Register register) const -> maybe { switch(register.id) { #define r(id, name) case id: return r.name; r(0x00, xwa[0].b.b0) r(0x01, xwa[0].b.b1) r(0x02, xwa[0].b.b2) r(0x03, xwa[0].b.b3) @@ -37,7 +37,7 @@ template<> auto TLCS900H::map(Register register) -> maybe { return nothing; } -template<> auto TLCS900H::map(Register register) -> maybe { +template<> auto TLCS900H::map(Register register) const -> maybe { switch(register.id & ~1) { #define r(id, name) case id: return r.name; r(0x00, xwa[0].w.w0) r(0x02, xwa[0].w.w1) r(0x04, xbc[0].w.w0) r(0x06, xbc[0].w.w1) @@ -59,7 +59,7 @@ template<> auto TLCS900H::map(Register register) -> maybe { return nothing; } -template<> auto TLCS900H::map(Register register) -> maybe { +template<> auto TLCS900H::map(Register register) const -> maybe { switch(register.id & ~3) { #define r(id, name) case id: return r.name; r(0x00, xwa[0].l.l0) r(0x04, xbc[0].l.l0) r(0x08, xde[0].l.l0) r(0x0c, xhl[0].l.l0) @@ -77,9 +77,9 @@ template<> auto TLCS900H::map(Register register) -> maybe { #undef a #undef p -template<> auto TLCS900H::load< uint8>(Register< uint8> register) -> uint8 { return map(register)(Undefined); } -template<> auto TLCS900H::load(Register register) -> uint16 { return map(register)(Undefined); } -template<> auto TLCS900H::load(Register register) -> uint32 { return map(register)(Undefined); } +template<> auto TLCS900H::load< uint8>(Register< uint8> register) const -> uint8 { return map(register)(Undefined); } +template<> auto TLCS900H::load(Register register) const -> uint16 { return map(register)(Undefined); } +template<> auto TLCS900H::load(Register register) const -> uint32 { return map(register)(Undefined); } template<> auto TLCS900H::store< uint8>(Register< uint8> register, uint32 data) -> void { if(auto r = map(register)) r() = data; } template<> auto TLCS900H::store(Register register, uint32 data) -> void { if(auto r = map(register)) r() = data; } @@ -87,9 +87,11 @@ template<> auto TLCS900H::store(Register register, uint32 data) auto TLCS900H::expand(Register< uint8> register) const -> Register { return {register.id & ~1}; } auto TLCS900H::expand(Register register) const -> Register { return {register.id & ~3}; } -auto TLCS900H::expand(Register register) const -> Register { return {Undefined}; } -auto TLCS900H::load(FlagRegister f) -> uint8 { +auto TLCS900H::shrink(Register register) const -> Register { return {register.id}; } +auto TLCS900H::shrink(Register register) const -> Register< uint8> { return {register.id}; } + +auto TLCS900H::load(FlagRegister f) const -> uint8 { switch(f.id) { case 0: return r.c << 0 | r.n << 1 | r.v << 2 | r.h << 4 | r.z << 6 | r.s << 7; case 1: return r.cp << 0 | r.np << 1 | r.vp << 2 | r.hp << 4 | r.zp << 6 | r.sp << 7; @@ -103,7 +105,7 @@ auto TLCS900H::store(FlagRegister f, uint8 data) -> void { } unreachable; } -auto TLCS900H::load(StatusRegister) -> uint16 { +auto TLCS900H::load(StatusRegister) const -> uint16 { return load(F) | r.rfp << 8 | 1 << 11 | r.iff << 12 | 1 << 15; } @@ -113,5 +115,5 @@ auto TLCS900H::store(StatusRegister, uint16 data) -> void { r.iff = data.bits(12,14); } -auto TLCS900H::load(ProgramCounter) -> uint32 { return r.pc.l.l0; } +auto TLCS900H::load(ProgramCounter) const -> uint32 { return r.pc.l.l0; } auto TLCS900H::store(ProgramCounter, uint32 data) -> void { r.pc.l.l0 = data; } diff --git a/higan/processor/tlcs900h/tlcs900h.hpp b/higan/processor/tlcs900h/tlcs900h.hpp index 063cc6f7..2b364cae 100644 --- a/higan/processor/tlcs900h/tlcs900h.hpp +++ b/higan/processor/tlcs900h/tlcs900h.hpp @@ -20,45 +20,13 @@ struct TLCS900H { TLCS900H(); - struct FlagRegister { - using type = uint8; - enum : uint { bits = 8 }; - uint1 id; - }; - - struct StatusRegister { - using type = uint16; - enum : uint { bits = 16 }; - }; - - struct ProgramCounter { - using type = uint32; - enum : uint { bits = 32 }; - }; - - template struct ControlRegister { - using type = T; - enum : uint { bits = 8 * sizeof(T) }; - uint8 id; - }; - - template struct Register { - using type = T; - enum : uint { bits = 8 * sizeof(T) }; - uint8 id; - }; - - template struct Memory { - using type = T; - enum : uint { bits = 8 * sizeof(T) }; - T address; - }; - - template struct Immediate { - using type = T; - enum : uint { bits = 8 * sizeof(T) }; - T constant; - }; + struct FlagRegister { using type = uint8; enum : uint { bits = 8 }; uint1 id; }; + struct StatusRegister { using type = uint16; enum : uint { bits = 16 }; }; + struct ProgramCounter { using type = uint32; enum : uint { bits = 32 }; }; + template struct ControlRegister { using type = T; enum : uint { bits = 8 * sizeof(T) }; uint8 id; }; + template struct Register { using type = T; enum : uint { bits = 8 * sizeof(T) }; uint8 id; }; + template struct Memory { using type = T; enum : uint { bits = 8 * sizeof(T) }; T address; }; + template struct Immediate { using type = T; enum : uint { bits = 8 * sizeof(T) }; T constant; }; template auto load(Immediate immediate) const -> T { return immediate.constant; } @@ -66,22 +34,23 @@ struct TLCS900H { auto power() -> void; //registers.cpp - template auto map(Register) -> maybe; - template auto load(Register) -> T; + template auto map(Register) const -> maybe; + template auto load(Register) const -> T; template auto store(Register, uint32) -> void; auto expand(Register< uint8>) const -> Register; auto expand(Register) const -> Register; - auto expand(Register) const -> Register; - auto load(FlagRegister) -> uint8; + auto shrink(Register) const -> Register; + auto shrink(Register) const -> Register< uint8>; + auto load(FlagRegister) const -> uint8; auto store(FlagRegister, uint8) -> void; - auto load(StatusRegister) -> uint16; + auto load(StatusRegister) const -> uint16; auto store(StatusRegister, uint16) -> void; - auto load(ProgramCounter) -> uint32; + auto load(ProgramCounter) const -> uint32; auto store(ProgramCounter, uint32) -> void; //control-registers.cpp - template auto map(ControlRegister) -> maybe; - template auto load(ControlRegister) -> T; + template auto map(ControlRegister) const -> maybe; + template auto load(ControlRegister) const -> T; template auto store(ControlRegister, uint32) -> void; //memory.cpp @@ -101,6 +70,8 @@ struct TLCS900H { template auto parity(T) const -> bool; template auto algorithmAdd(T target, T source, uint1 carry = 0) -> T; template auto algorithmAnd(T target, T source) -> T; + template auto algorithmDecrement(T target, T source) -> T; + template auto algorithmIncrement(T target, T source) -> T; template auto algorithmOr(T target, T source) -> T; template auto algorithmSubtract(T target, T source, uint1 carry = 0) -> T; template auto algorithmXor(T target, T source) -> T; @@ -118,19 +89,24 @@ struct TLCS900H { auto instructionTargetMemory(uint32 address) -> void; //instructions.cpp - template auto toSigned(Target) -> int32; - template auto instructionAdd(Target, Source) -> void; template auto instructionAddCarry(Target, Source) -> void; template auto instructionAnd(Target, Source) -> void; + auto instructionBitSearch1Backward(Register) -> void; + auto instructionBitSearch1Forward(Register) -> void; template auto instructionCall(uint4 code, Source) -> void; template auto instructionCallRelative(Source) -> void; template auto instructionCompare(Target, Source) -> void; template auto instructionComplement(Target) -> void; + auto instructionDecimalAdjustAccumulator(Register) -> void; + template auto instructionDecrement(Target, Source) -> void; template auto instructionDivide(Target, Source) -> void; template auto instructionDivideSigned(Target, Source) -> void; template auto instructionExchange(Target, Source) -> void; + template auto instructionExtendSign(Target) -> void; + template auto instructionExtendZero(Target) -> void; auto instructionHalt() -> void; + template auto instructionIncrement(Target, Source) -> void; template auto instructionJump(uint4 code, Source) -> void; template auto instructionJumpRelative(uint4 code, Source) -> void; template auto instructionLoad(Target, Source) -> void; diff --git a/nall/primitives.hpp b/nall/primitives.hpp index 95fe6154..79132fb5 100644 --- a/nall/primitives.hpp +++ b/nall/primitives.hpp @@ -5,6 +5,10 @@ namespace nall { +struct Boolean; +template struct Natural; +template struct Integer; + struct Boolean { inline Boolean() : data(false) {} template inline Boolean(const T& value) : data(value) {} @@ -127,6 +131,8 @@ template struct Natural { return data & m; } + inline auto integer() const -> Integer; + private: auto set(type value) -> void { data = value & Mask; @@ -237,6 +243,8 @@ template struct Integer { return ((data & m) ^ b) - b; } + inline auto natural() const -> Natural; + private: auto set(type value) -> void { data = ((value & Mask) ^ Sign) - Sign; @@ -245,6 +253,16 @@ private: type data; }; +//cast an unsigned type to a signed type with the same number of bits +template auto Natural::integer() const -> Integer { + return Integer(*this); +} + +//cast a signed type to an unsigned type with the same number of bits +template auto Integer::natural() const -> Natural { + return Natural(*this); +} + template struct Real { using type = typename conditional