From 25145f59cc27221a42e941c433129829f8817e81 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Wed, 16 Jan 2019 00:09:50 +1100 Subject: [PATCH] Update to v106r80 release. byuu says: Any usage of natural and integer cast to 64-bit math operations now. Hopefully this will be the last of the major changes for a bit on nall/primitives, at least until serious work begins on removing implicit conversion to primitive types. I also completed the initial TLCS900H core, sans SWI (kind of a ways off from support interrupts.) I really shouldn't say completed, though. The micro DMA unit is missing, interrupt priority handling is missing, there's no debugger, and, of course, there's surely dozens of absolutely critical CPU bugs that are going to be an absolute hellscape nightmare to track down. It was a damn shame, right up until the very last eight instructions, [CP|LD][I|D](R), the instruction encoding was consistent. Of course, there could be other inconsistencies that I missed. In fact, that's somewhat likely ... sigh. --- higan/emulator/emulator.hpp | 2 +- higan/processor/m68k/m68k.hpp | 2 +- higan/processor/tlcs900h/instruction.cpp | 90 +++++++++++++---- higan/processor/tlcs900h/instructions.cpp | 115 ++++++++++++++++++++++ higan/processor/tlcs900h/tlcs900h.hpp | 13 +++ higan/sfc/ppu-fast/ppu.hpp | 6 +- nall/primitives/integer.hpp | 75 +++++++------- nall/primitives/natural.hpp | 105 ++++++++++++-------- nall/primitives/real.hpp | 16 +-- nall/string.hpp | 2 +- nall/string/transform/dml.hpp | 4 +- 11 files changed, 314 insertions(+), 116 deletions(-) diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 234ab16f..15340dca 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.79"; + static const string Version = "106.80"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/higan/processor/m68k/m68k.hpp b/higan/processor/m68k/m68k.hpp index 32593654..5fc075a6 100644 --- a/higan/processor/m68k/m68k.hpp +++ b/higan/processor/m68k/m68k.hpp @@ -90,7 +90,7 @@ struct M68K { //effective-address.cpp struct EffectiveAddress { - explicit EffectiveAddress(uint mode_, uint reg_) : mode(mode_), reg(reg_) { + explicit EffectiveAddress(uint4 mode_, uint3 reg_) : mode(mode_), reg(reg_) { if(mode == 7) mode += reg; //optimization: convert modes {7; 0-4} to {8-11} } diff --git a/higan/processor/tlcs900h/instruction.cpp b/higan/processor/tlcs900h/instruction.cpp index d461481a..9845b1f4 100644 --- a/higan/processor/tlcs900h/instruction.cpp +++ b/higan/processor/tlcs900h/instruction.cpp @@ -25,7 +25,7 @@ template auto TLCS900H::toImmediate3(uint3 constant) const -> Immedi auto TLCS900H::instruction() -> void { auto data = fetch(); - switch(data) { + switch(r.prefix = data) { case 0x00: return instructionNoOperation(); case 0x01: return (void)Undefined; case 0x02: return instructionPush(SR); @@ -293,8 +293,12 @@ auto TLCS900H::instructionRegister(R register) -> void { case 0x0b: if constexpr(bits != 32) return instructionDivideSigned(register, fetchImmediate()); return (void)Undefined; -//case 0x0c: LINK r,dd -//case 0x0d: UNLK r + case 0x0c: + if constexpr(bits == 32) return instructionLink(register, fetchImmediate()); + return (void)Undefined; + case 0x0d: + if constexpr(bits == 32) return instructionUnlink(register); + return (void)Undefined; case 0x0e: if constexpr(bits == 16) return instructionBitSearch1Forward(register); return (void)Undefined; @@ -311,7 +315,9 @@ auto TLCS900H::instructionRegister(R register) -> void { case 0x13: if constexpr(bits != 8) return instructionExtendSign(register); return (void)Undefined; -//case 0x14: PAA r + case 0x14: + if constexpr(bits != 8) return instructionPointerAdjustAccumulator(register); + return (void)Undefined; case 0x15: return (void)Undefined; case 0x16: if constexpr(bits == 16) return instructionMirror(register); @@ -321,7 +327,9 @@ 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 0x1c: + if constexpr(bits != 32) return instructionDecrementJumpNotZero(register, fetchImmediate()); + return (void)Undefined; case 0x1d: case 0x1e: case 0x1f: return (void)Undefined; case 0x20: if constexpr(bits != 32) return instructionAndCarry(register, fetchImmediate()); @@ -373,13 +381,25 @@ auto TLCS900H::instructionRegister(R register) -> void { if constexpr(bits != 32) return instructionTestSet(register, fetchImmediate()); return (void)Undefined; case 0x35: case 0x36: case 0x37: return (void)Undefined; -//case 0x38: MINC1 #,r -//case 0x39: MINC2 #,r -//case 0x3a: MINC4 #,r + case 0x38: + if constexpr(bits == 16) return instructionModuloIncrement<1>(register, fetchImmediate()); + return (void)Undefined; + case 0x39: + if constexpr(bits == 16) return instructionModuloIncrement<2>(register, fetchImmediate()); + return (void)Undefined; + case 0x3a: + if constexpr(bits == 16) return instructionModuloIncrement<4>(register, fetchImmediate()); + return (void)Undefined; case 0x3b: return (void)Undefined; -//case 0x3c: MDEC1 #,r -//case 0x3d: MDEC2 #,r -//case 0x3e: MDEC4 #,r + case 0x3c: + if constexpr(bits == 16) return instructionModuloDecrement<1>(register, fetchImmediate()); + return (void)Undefined; + case 0x3d: + if constexpr(bits == 16) return instructionModuloDecrement<2>(register, fetchImmediate()); + return (void)Undefined; + case 0x3e: + if constexpr(bits == 16) return instructionModuloDecrement<4>(register, fetchImmediate()); + 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 instructionMultiply(toRegister3(data), register); @@ -467,17 +487,45 @@ auto TLCS900H::instructionSourceMemory(M memory) -> void { if constexpr(bits == 32) return (void)Undefined; return instructionPush(memory); case 0x05: return (void)Undefined; -//case 0x06: RLD A,(mem) -//case 0x07: RRD A,(mem) + case 0x06: + if constexpr(bits == 8) return instructionRotateLeftDigit(A, memory); + return (void)Undefined; + case 0x07: + if constexpr(bits == 8) return instructionRotateRightDigit(A, memory); + return (void)Undefined; case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: return (void)Undefined; -//case 0x10: LDI -//case 0x11: LDIR -//case 0x12: LDIR -//case 0x13: LDDR -//case 0x14: CPI -//case 0x15: CPIR -//case 0x16: CPD -//case 0x17: CPDR + case 0x10: + if constexpr(bits == 8) return instructionLoad(); + if constexpr(bits == 16) return instructionLoad(); + return (void)Undefined; + case 0x11: + if constexpr(bits == 8) return instructionLoadRepeat(); + if constexpr(bits == 16) return instructionLoadRepeat(); + return (void)Undefined; + case 0x12: + if constexpr(bits == 8) return instructionLoad(); + if constexpr(bits == 16) return instructionLoad(); + return (void)Undefined; + case 0x13: + if constexpr(bits == 8) return instructionLoadRepeat(); + if constexpr(bits == 16) return instructionLoadRepeat(); + return (void)Undefined; + case 0x14: + if constexpr(bits == 8) return instructionCompare(A); + if constexpr(bits == 16) return instructionCompare(WA); + return (void)Undefined; + case 0x15: + if constexpr(bits == 8) return instructionCompareRepeat(A); + if constexpr(bits == 16) return instructionCompareRepeat(WA); + return (void)Undefined; + case 0x16: + if constexpr(bits == 8) return instructionCompare(A); + if constexpr(bits == 16) return instructionCompare(WA); + return (void)Undefined; + case 0x17: + if constexpr(bits == 8) return instructionCompareRepeat(A); + if constexpr(bits == 16) return instructionCompareRepeat(WA); + return (void)Undefined; case 0x18: return (void)Undefined; case 0x19: if constexpr(bits == 32) return (void)Undefined; diff --git a/higan/processor/tlcs900h/instructions.cpp b/higan/processor/tlcs900h/instructions.cpp index f1c03eee..b69b975d 100644 --- a/higan/processor/tlcs900h/instructions.cpp +++ b/higan/processor/tlcs900h/instructions.cpp @@ -63,6 +63,22 @@ auto TLCS900H::instructionChange(Target target, Offset offset) -> void { store(target, result); } +template +auto TLCS900H::instructionCompare(Target target) -> void { + auto source = toRegister3(r.prefix); + auto cf = CF; //CF is not modified; but algorithmSubtract will modify it + algorithmSubtract(load(target), load(toMemory(load(source)))); + store(source, load(source) + Adjust); + store(BC, load(BC) - 1); + CF = cf; + VF = load(BC) == 0; +} + +template +auto TLCS900H::instructionCompareRepeat(Target target) -> void { + do { instructionCompare(target); } while(VF && !ZF); +} + template auto TLCS900H::instructionCompare(Target target, Source source) -> void { algorithmSubtract(load(target), load(source)); @@ -93,6 +109,13 @@ auto TLCS900H::instructionDecrement(Target target, Source source) -> void { store(target, algorithmDecrement(load(target), immediate)); } +template +auto TLCS900H::instructionDecrementJumpNotZero(Target target, Offset offset) -> void { + auto result = load(target); + store(target, --result); + if(result) store(PC, load(PC) + load(offset)); +} + template auto TLCS900H::instructionDivide(Target target, Source source) -> void { using T = typename Target::type; @@ -156,6 +179,13 @@ auto TLCS900H::instructionJumpRelative(uint4 code, Source displacement) -> void if(condition(code)) store(PC, load(PC) + load(displacement)); } +template +auto TLCS900H::instructionLink(Target target, Offset offset) -> void { + push(target); + store(target, load(XSP)); + store(XSP, load(XSP) + load(offset)); +} + template auto TLCS900H::instructionLoad(Target target, Source source) -> void { store(target, load(source)); @@ -167,6 +197,22 @@ auto TLCS900H::instructionLoadCarry(Source source, Offset offset) -> void { CF = load(source).bit(load(offset) & Source::bits - 1); } +template auto TLCS900H::instructionLoad() -> void { + auto target = (uint3)r.prefix == 5 ? XIX : XDE; + auto source = (uint3)r.prefix == 5 ? XIY : XHL; + store(toMemory(load(target)), load(toMemory(load(source)))); + store(target, load(target) + Adjust); + store(source, load(source) + Adjust); + store(BC, load(BC) - 1); + NF = 0; + VF = load(BC) == 0; + HF = 0; +} + +template auto TLCS900H::instructionLoadRepeat() -> void { + do { instructionLoad(); } while(VF); +} + //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 { @@ -177,6 +223,28 @@ auto TLCS900H::instructionMirror(Register register) -> void { store(register, data << 8 | data >> 8); } +template +auto TLCS900H::instructionModuloDecrement(Target target, Source source) -> void { + auto result = load(target); + auto number = load(source); + if(result % number == 0) { + store(target, result + (number - Modulo)); + } else { + store(target, result - Modulo); + } +} + +template +auto TLCS900H::instructionModuloIncrement(Target target, Source source) -> void { + auto result = load(target); + auto number = load(source); + if(result % number == number - Modulo) { + store(target, result - (number - Modulo)); + } else { + store(target, result + Modulo); + } +} + template auto TLCS900H::instructionMultiply(Target target, Source source) -> void { store(expand(target), load(target) * load(source)); @@ -221,6 +289,13 @@ auto TLCS900H::instructionOrCarry(Source source, Offset offset) -> void { CF |= load(source).bit(load(offset) & Source::bits - 1); } +//increments odd addresses only to ensure they are even (16-bit aligned) +template +auto TLCS900H::instructionPointerAdjustAccumulator(Target target) -> void { + auto result = load(target); + store(target, result + result.bit(0)); +} + template auto TLCS900H::instructionPop(Target target) -> void { pop(target); @@ -254,6 +329,23 @@ auto TLCS900H::instructionReturnInterrupt() -> void { store(INTNEST, load(INTNEST) - 1); } +template +auto TLCS900H::instructionRotateLeftDigit(LHS lhs, RHS rhs) -> void { + auto lvalue = load(lhs); + auto rvalue = load(rhs); + auto Lvalue = lvalue; + lvalue.bits(0,3) = rvalue.bits(4,7); + rvalue.bits(4,7) = rvalue.bits(0,3); + rvalue.bits(0,3) = Lvalue.bits(0,3); + store(lhs, lvalue); + store(rhs, rvalue); + NF = 0; + PF = parity(lvalue); + HF = 0; + ZF = lvalue == 0; + SF = lvalue.bit(-1); +} + template auto TLCS900H::instructionRotateLeft(Target target, Amount amount) -> void { auto result = load(target); @@ -277,6 +369,23 @@ auto TLCS900H::instructionRotateLeftWithoutCarry(Target target, Amount amount) - store(target, algorithmRotated(result)); } +template +auto TLCS900H::instructionRotateRightDigit(LHS lhs, RHS rhs) -> void { + auto lvalue = load(lhs); + auto rvalue = load(rhs); + auto Rvalue = rvalue; + rvalue.bits(0,3) = rvalue.bits(4,7); + rvalue.bits(4,7) = lvalue.bits(0,3); + lvalue.bits(0,3) = Rvalue.bits(0,3); + store(lhs, lvalue); + store(rhs, rvalue); + NF = 0; + PF = parity(lvalue); + HF = 0; + ZF = lvalue == 0; + SF = lvalue.bit(-1); +} + template auto TLCS900H::instructionRotateRight(Target target, Amount amount) -> void { auto result = load(target); @@ -404,6 +513,12 @@ auto TLCS900H::instructionTestSet(Target target, Offset offset) -> void { store(target, result); } +template +auto TLCS900H::instructionUnlink(Target target) -> void { + store(XSP, load(target)); + pop(target); +} + template auto TLCS900H::instructionXor(Target target, Source source) -> void { store(target, algorithmXor(load(target), load(source))); diff --git a/higan/processor/tlcs900h/tlcs900h.hpp b/higan/processor/tlcs900h/tlcs900h.hpp index 7860ffb8..59a83c80 100644 --- a/higan/processor/tlcs900h/tlcs900h.hpp +++ b/higan/processor/tlcs900h/tlcs900h.hpp @@ -102,10 +102,13 @@ struct TLCS900H { template auto instructionCall(uint4 code, Source) -> void; template auto instructionCallRelative(Source) -> void; template auto instructionChange(Target, Offset) -> void; + template auto instructionCompare(Target) -> void; + template auto instructionCompareRepeat(Target) -> void; template auto instructionCompare(Target, Source) -> void; template auto instructionComplement(Target) -> void; auto instructionDecimalAdjustAccumulator(Register) -> void; template auto instructionDecrement(Target, Source) -> void; + template auto instructionDecrementJumpNotZero(Target, Offset) -> void; template auto instructionDivide(Target, Source) -> void; template auto instructionDivideSigned(Target, Source) -> void; template auto instructionExchange(Target, Source) -> void; @@ -115,8 +118,13 @@ struct TLCS900H { template auto instructionIncrement(Target, Source) -> void; template auto instructionJump(uint4 code, Source) -> void; template auto instructionJumpRelative(uint4 code, Source) -> void; + template auto instructionLink(Target, Offset) -> void; template auto instructionLoad(Target, Source) -> void; template auto instructionLoadCarry(Source, Offset) -> void; + template auto instructionLoad() -> void; + template auto instructionLoadRepeat() -> void; + template auto instructionModuloDecrement(Target, Source) -> void; + template auto instructionModuloIncrement(Target, Source) -> void; auto instructionMirror(Register) -> void; template auto instructionMultiply(Target, Source) -> void; auto instructionMultiplyAdd(Register) -> void; @@ -125,14 +133,17 @@ struct TLCS900H { auto instructionNoOperation() -> void; template auto instructionOr(Target, Source) -> void; template auto instructionOrCarry(Source, Offset) -> void; + template auto instructionPointerAdjustAccumulator(Target) -> void; template auto instructionPop(Target) -> void; template auto instructionPush(Source) -> void; template auto instructionReset(Target, Offset) -> void; auto instructionReturn(uint4 code) -> void; template auto instructionReturnDeallocate(Source) -> void; auto instructionReturnInterrupt() -> void; + template auto instructionRotateLeftDigit(LHS, RHS) -> void; template auto instructionRotateLeft(Target, Amount) -> void; template auto instructionRotateLeftWithoutCarry(Target, Amount) -> void; + template auto instructionRotateRightDigit(LHS, RHS) -> void; template auto instructionRotateRight(Target, Amount) -> void; template auto instructionRotateRightWithoutCarry(Target, Amount) -> void; template auto instructionSet(Target, Offset) -> void; @@ -149,6 +160,7 @@ struct TLCS900H { template auto instructionSubtract(Target, Source) -> void; template auto instructionSubtractBorrow(Target, Source) -> void; template auto instructionTestSet(Target, Offset) -> void; + template auto instructionUnlink(Target) -> void; template auto instructionXor(Target, Source) -> void; template auto instructionXorCarry(Source, Offset) -> void; @@ -188,6 +200,7 @@ struct TLCS900H { uint3 iff = 7; //interrupt mask flip-flop uint1 halted; + uint8 prefix; //first opcode byte; needed for [CP|LD][ID](R) instructions } r; auto halted() const -> bool { return r.halted; } diff --git a/higan/sfc/ppu-fast/ppu.hpp b/higan/sfc/ppu-fast/ppu.hpp index c98009a7..24ac6eb0 100644 --- a/higan/sfc/ppu-fast/ppu.hpp +++ b/higan/sfc/ppu-fast/ppu.hpp @@ -223,9 +223,9 @@ public: }; struct Pixel { - uint source; - uint priority; - uint color; + uint source; + uint priority; + uint15 color; }; //io.cpp diff --git a/nall/primitives/integer.hpp b/nall/primitives/integer.hpp index f5c677f9..d6e5a77a 100644 --- a/nall/primitives/integer.hpp +++ b/nall/primitives/integer.hpp @@ -2,16 +2,16 @@ namespace nall { -template struct Integer { - enum : uint { Precision = Requested < 1 ? 1 : Requested > 64 ? 64 : Requested }; +template struct Integer { + static_assert(Precision >= 1 && Precision <= 64); static inline constexpr auto bits() -> uint { return Precision; } - using type = + using stype = typename conditional::type>::type>::type>::type; - using utype = typename Natural::type; + using utype = typename Natural::utype; static inline constexpr auto mask() -> utype { return ~0ull >> 64 - bits(); } static inline constexpr auto sign() -> utype { return 1ull << Precision - 1; } @@ -20,7 +20,7 @@ template struct Integer { template inline Integer(const T& value) { data = mask(value); } explicit inline operator bool() const { return data; } - inline operator type() const { return data; } + inline operator int64_t() const { return data; } inline auto operator++(int) { auto value = *this; data = mask(data + 1); return value; } inline auto operator--(int) { auto value = *this; data = mask(data - 1); return value; } @@ -49,59 +49,54 @@ template struct Integer { #undef lhs #undef rhs - inline auto bits(int lo, int hi) -> BitRange { return {(utype&)data, lo, hi}; } - inline auto bit(int index) -> BitRange { return {(utype&)data, index, index}; } - inline auto byte(int index) -> BitRange { return {(utype&)data, index * 8 + 0, index * 8 + 7}; } + #define lhs (int64_t)data + #define rhs value + #undef lhs + #undef rhs - inline auto bits(int lo, int hi) const -> const BitRange { return {(utype&)*this, lo, lo}; } - inline auto bit(int index) const -> const BitRange { return {(utype&)*this, index, index}; } - inline auto byte(int index) const -> const BitRange { return {(utype&)*this, index * 8 + 0, index * 8 + 7}; } + inline auto bits(int lo, int hi) -> BitRange { return {(utype&)data, lo, hi}; } + inline auto bit(int index) -> BitRange { return {(utype&)data, index, index}; } + inline auto byte(int index) -> BitRange { return {(utype&)data, index * 8 + 0, index * 8 + 7}; } - inline auto clamp(uint bits) -> type { + inline auto bits(int lo, int hi) const -> const BitRange { return {(utype&)*this, lo, lo}; } + inline auto bit(int index) const -> const BitRange { return {(utype&)*this, index, index}; } + inline auto byte(int index) const -> const BitRange { return {(utype&)*this, index * 8 + 0, index * 8 + 7}; } + + inline auto clamp(uint bits) { const intmax b = 1ull << (bits - 1); const intmax m = b - 1; - return data > m ? m : data < -b ? -b : data; + return Integer<64>{data > m ? m : data < -b ? -b : data}; } - inline auto clip(uint bits) -> type { + inline auto clip(uint bits) { const uintmax b = 1ull << (bits - 1); const uintmax m = b * 2 - 1; - return ((data & m) ^ b) - b; + return Integer<64>{(data & m ^ b) - b}; } inline auto serialize(serializer& s) { s(data); } - inline auto natural() const -> Natural; + inline auto natural() const -> Natural; private: - inline auto mask(type value) const -> type { + inline auto mask(stype value) const -> stype { return (value & mask() ^ sign()) - sign(); } - type data; + stype data; }; -#define ALL 64 -#define ADD 64 //LHS + RHS -#define INC 64 //1 + (LHS >= RHS ? LHS : RHS) -#define MAX 64 //LHS >= RHS ? LHS : RHS -#define MIN 64 //LHS <= RHS ? LHS : RHS -#define lhs (int64_t)(typename Integer::type)l -#define rhs (typename Integer::type)r -template inline auto operator *(Integer l, Integer r) { return Integer{lhs * rhs}; } -template inline auto operator /(Integer l, Integer r) { return Integer{lhs / rhs}; } -template inline auto operator %(Integer l, Integer r) { return Integer{lhs % rhs}; } -template inline auto operator +(Integer l, Integer r) { return Integer{lhs + rhs}; } -template inline auto operator -(Integer l, Integer r) { return Integer{lhs - rhs}; } -template inline auto operator<<(Integer l, Integer r) { return Integer{lhs << rhs}; } -template inline auto operator>>(Integer l, Integer r) { return Integer{lhs >> rhs}; } -template inline auto operator &(Integer l, Integer r) { return Integer{lhs & rhs}; } -template inline auto operator ^(Integer l, Integer r) { return Integer{lhs ^ rhs}; } -template inline auto operator |(Integer l, Integer r) { return Integer{lhs | rhs}; } -#undef ALL -#undef ADD -#undef INC -#undef MAX -#undef MIN +#define lhs (int64_t)l +#define rhs r +template inline auto operator *(Integer l, Integer r) { return Integer<64>{lhs * rhs}; } +template inline auto operator /(Integer l, Integer r) { return Integer<64>{lhs / rhs}; } +template inline auto operator %(Integer l, Integer r) { return Integer<64>{lhs % rhs}; } +template inline auto operator +(Integer l, Integer r) { return Integer<64>{lhs + rhs}; } +template inline auto operator -(Integer l, Integer r) { return Integer<64>{lhs - rhs}; } +template inline auto operator<<(Integer l, Integer r) { return Integer<64>{lhs << rhs}; } +template inline auto operator>>(Integer l, Integer r) { return Integer<64>{lhs >> rhs}; } +template inline auto operator &(Integer l, Integer r) { return Integer<64>{lhs & rhs}; } +template inline auto operator ^(Integer l, Integer r) { return Integer<64>{lhs ^ rhs}; } +template inline auto operator |(Integer l, Integer r) { return Integer<64>{lhs | rhs}; } #undef lhs #undef rhs diff --git a/nall/primitives/natural.hpp b/nall/primitives/natural.hpp index 191d41a8..285839b3 100644 --- a/nall/primitives/natural.hpp +++ b/nall/primitives/natural.hpp @@ -2,23 +2,23 @@ namespace nall { -template struct Natural { - enum : uint { Precision = Requested < 1 ? 1 : Requested > 64 ? 64 : Requested }; +template struct Natural { + static_assert(Precision >= 1 && Precision <= 64); static inline constexpr auto bits() -> uint { return Precision; } - using type = + using utype = typename conditional::type>::type>::type>::type; - static inline constexpr auto mask() -> type { return ~0ull >> 64 - bits(); } + static inline constexpr auto mask() -> utype { return ~0ull >> 64 - bits(); } inline Natural() : data(0) {} template inline Natural(Natural value) { data = mask(value); } template inline Natural(const T& value) { data = mask(value); } explicit inline operator bool() const { return data; } - inline operator type() const { return data; } + inline operator uint64_t() const { return data; } inline auto operator++(int) { auto value = *this; data = mask(data + 1); return value; } inline auto operator--(int) { auto value = *this; data = mask(data - 1); return value; } @@ -47,59 +47,84 @@ template struct Natural { #undef lhs #undef rhs - inline auto bits(int lo, int hi) -> BitRange { return {(type&)data, lo, hi}; } - inline auto bit(int index) -> BitRange { return {(type&)data, index, index}; } - inline auto byte(int index) -> BitRange { return {(type&)data, index * 8 + 0, index * 8 + 7}; } + //work in progress: we want naturalprimitive and primitivenatural to result in natural<64> ... + //however, these operators will create ambiguous overloads unless operator uint64_t() is explicit. + //a large volume of existing code will need to be updated before this will be possible. + #if 0 + #define lhs (uint64_t)data + #define rhs value + template inline auto operator *(const T& value) { return Natural<64>{lhs * rhs}; } + template inline auto operator /(const T& value) { return Natural<64>{lhs / rhs}; } + template inline auto operator %(const T& value) { return Natural<64>{lhs % rhs}; } + template inline auto operator +(const T& value) { return Natural<64>{lhs + rhs}; } + template inline auto operator -(const T& value) { return Natural<64>{lhs - rhs}; } + template inline auto operator<<(const T& value) { return Natural<64>{lhs << rhs}; } + template inline auto operator>>(const T& value) { return Natural<64>{lhs >> rhs}; } + template inline auto operator &(const T& value) { return Natural<64>{lhs & rhs}; } + template inline auto operator ^(const T& value) { return Natural<64>{lhs ^ rhs}; } + template inline auto operator |(const T& value) { return Natural<64>{lhs | rhs}; } + #undef lhs + #undef rhs - inline auto bits(int lo, int hi) const -> const BitRange { return {(type&)data, lo, hi}; } - inline auto bit(int index) const -> const BitRange { return {(type&)data, index, index}; } - inline auto byte(int index) const -> const BitRange { return {(type&)data, index * 8 + 0, index * 8 + 7}; } + #define lhs l + #define rhs (uint64_t)r + template friend inline auto operator *(const T& l, Natural r) { return Natural<64>{lhs * rhs}; } + template friend inline auto operator %(const T& l, Natural r) { return Natural<64>{lhs / rhs}; } + template friend inline auto operator /(const T& l, Natural r) { return Natural<64>{lhs % rhs}; } + template friend inline auto operator +(const T& l, Natural r) { return Natural<64>{lhs + rhs}; } + template friend inline auto operator -(const T& l, Natural r) { return Natural<64>{lhs - rhs}; } + template friend inline auto operator<<(const T& l, Natural r) { return Natural<64>{lhs << rhs}; } + template friend inline auto operator>>(const T& l, Natural r) { return Natural<64>{lhs >> rhs}; } + template friend inline auto operator &(const T& l, Natural r) { return Natural<64>{lhs & rhs}; } + template friend inline auto operator ^(const T& l, Natural r) { return Natural<64>{lhs ^ rhs}; } + template friend inline auto operator |(const T& l, Natural r) { return Natural<64>{lhs | rhs}; } + #undef lhs + #undef rhs + #endif - inline auto clamp(uint bits) -> type { + inline auto bits(int lo, int hi) -> BitRange { return {(utype&)data, lo, hi}; } + inline auto bit(int index) -> BitRange { return {(utype&)data, index, index}; } + inline auto byte(int index) -> BitRange { return {(utype&)data, index * 8 + 0, index * 8 + 7}; } + + inline auto bits(int lo, int hi) const -> const BitRange { return {(utype&)data, lo, hi}; } + inline auto bit(int index) const -> const BitRange { return {(utype&)data, index, index}; } + inline auto byte(int index) const -> const BitRange { return {(utype&)data, index * 8 + 0, index * 8 + 7}; } + + inline auto clamp(uint bits) { const uintmax b = 1ull << (bits - 1); const uintmax m = b * 2 - 1; - return data < m ? data : m; + return Natural<64>{data < m ? data : m}; } - inline auto clip(uint bits) -> type { + inline auto clip(uint bits) { const uintmax b = 1ull << (bits - 1); const uintmax m = b * 2 - 1; - return data & m; + return Natural<64>{data & m}; } inline auto serialize(serializer& s) { s(data); } - inline auto integer() const -> Integer; + inline auto integer() const -> Integer; private: - inline auto mask(type value) const -> type { + inline auto mask(utype value) const -> utype { return value & mask(); } - type data; + utype data; }; -#define ALL 64 -#define ADD 64 //LHS + RHS -#define INC 64 //1 + (LHS >= RHS ? LHS : RHS) -#define MAX 64 //LHS >= RHS ? LHS : RHS -#define MIN 64 //LHS <= RHS ? LHS : RHS -#define lhs (uint64_t)(typename Natural::type)l -#define rhs (typename Natural::type)r -template inline auto operator *(Natural l, Natural r) { return Natural{lhs * rhs}; } -template inline auto operator /(Natural l, Natural r) { return Natural{lhs / rhs}; } -template inline auto operator %(Natural l, Natural r) { return Natural{lhs % rhs}; } -template inline auto operator +(Natural l, Natural r) { return Natural{lhs + rhs}; } -template inline auto operator -(Natural l, Natural r) { return Natural{lhs - rhs}; } -template inline auto operator<<(Natural l, Natural r) { return Natural{lhs << rhs}; } -template inline auto operator>>(Natural l, Natural r) { return Natural{lhs >> rhs}; } -template inline auto operator &(Natural l, Natural r) { return Natural{lhs & rhs}; } -template inline auto operator ^(Natural l, Natural r) { return Natural{lhs ^ rhs}; } -template inline auto operator |(Natural l, Natural r) { return Natural{lhs | rhs}; } -#undef ALL -#undef ADD -#undef INC -#undef MAX -#undef MIN +#define lhs (uint64_t)l +#define rhs (uint64_t)r +template inline auto operator *(Natural l, Natural r) { return Natural<64>{lhs * rhs}; } +template inline auto operator /(Natural l, Natural r) { return Natural<64>{lhs / rhs}; } +template inline auto operator %(Natural l, Natural r) { return Natural<64>{lhs % rhs}; } +template inline auto operator +(Natural l, Natural r) { return Natural<64>{lhs + rhs}; } +template inline auto operator -(Natural l, Natural r) { return Natural<64>{lhs - rhs}; } +template inline auto operator<<(Natural l, Natural r) { return Natural<64>{lhs << rhs}; } +template inline auto operator>>(Natural l, Natural r) { return Natural<64>{lhs >> rhs}; } +template inline auto operator &(Natural l, Natural r) { return Natural<64>{lhs & rhs}; } +template inline auto operator ^(Natural l, Natural r) { return Natural<64>{lhs ^ rhs}; } +template inline auto operator |(Natural l, Natural r) { return Natural<64>{lhs | rhs}; } #undef lhs #undef rhs diff --git a/nall/primitives/real.hpp b/nall/primitives/real.hpp index ba8fa763..286835af 100644 --- a/nall/primitives/real.hpp +++ b/nall/primitives/real.hpp @@ -2,18 +2,20 @@ namespace nall { -template struct Real { - enum : uint { Precision = Requested <= 32 ? 32 : 64 }; +template struct Real { + static_assert(Precision == 32 || Precision == 64); static inline constexpr auto bits() -> uint { return Precision; } - using type = + using ftype = typename conditional::type>::type; inline Real() : data(0.0) {} - template inline Real(const T& value) : data((type)value) {} + template inline Real(Real value) : data((ftype)value) {} + template inline Real(const T& value) : data((ftype)value) {} - inline operator type() const { return data; } + explicit inline operator bool() const { return data; } + inline operator float64_t() const { return data; } inline auto operator++(int) { auto value = *this; ++data; return value; } inline auto operator--(int) { auto value = *this; --data; return value; } @@ -31,10 +33,10 @@ template struct Real { inline auto serialize(serializer& s) { s(data); } private: - type data; + ftype data; }; -#define lhs (long double)(typename Real::type)l +#define lhs (float64_t)(typename Real::type)l #define rhs (typename Real::type)r template inline auto operator*(Real l, Real r) { return Real<64>{lhs * rhs}; } template inline auto operator/(Real l, Real r) { return Real<64>{lhs / rhs}; } diff --git a/nall/string.hpp b/nall/string.hpp index 53c9d404..dd2d6244 100644 --- a/nall/string.hpp +++ b/nall/string.hpp @@ -362,4 +362,4 @@ inline auto operator"" _s(const char* value, std::size_t) -> string { return {va #include #include -//#include +#include diff --git a/nall/string/transform/dml.hpp b/nall/string/transform/dml.hpp index 046b58d0..31d6ae86 100644 --- a/nall/string/transform/dml.hpp +++ b/nall/string/transform/dml.hpp @@ -213,8 +213,8 @@ auto DML::markup(const string& s) -> string { boolean deletion; boolean code; - natural link, linkBase; - natural embed, embedBase; + uint link, linkBase; + uint embed, embedBase; for(uint n = 0; n < s.size();) { char a = s[n];