diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index d6e62493..2a49cb30 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.77"; + static const string Version = "106.78"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/higan/gba/ppu/background.cpp b/higan/gba/ppu/background.cpp index 82c6c05d..caa14c51 100644 --- a/higan/gba/ppu/background.cpp +++ b/higan/gba/ppu/background.cpp @@ -104,7 +104,7 @@ auto PPU::Background::affine(uint x, uint y) -> void { } uint screenSize = 16 << io.screenSize; - uint screenWrap = (1 << ternary(io.affineWrap, 7 + io.screenSize, 20)) - 1; + uint screenWrap = (1 << if(io.affineWrap, 7 + io.screenSize, 20)) - 1; uint cx = (fx >> 8) & screenWrap; uint cy = (fy >> 8) & screenWrap; @@ -148,7 +148,7 @@ auto PPU::Background::bitmap(uint x, uint y) -> void { uint height = io.mode == 5 ? 128 : 160; uint mode = depth ? Half : Byte; - uint baseAddress = ternary(io.mode == 3, 0, 0xa000 * io.frame); + uint baseAddress = if(io.mode == 3, 0, 0xa000 * io.frame); uint px = fx >> 8; uint py = fy >> 8; diff --git a/higan/gba/ppu/object.cpp b/higan/gba/ppu/object.cpp index 5ded8a27..870425fa 100644 --- a/higan/gba/ppu/object.cpp +++ b/higan/gba/ppu/object.cpp @@ -8,7 +8,7 @@ auto PPU::Objects::scanline(uint y) -> void { if(object.affine == 0 && object.affineSize == 1) continue; //hidden if(py >= object.height << object.affineSize) continue; //offscreen - uint rowSize = ternary(io.mapping == 0, 32 >> object.colors, object.width >> 3); + uint rowSize = if(io.mapping == 0, 32 >> object.colors, object.width >> 3); uint baseAddress = object.character << 5; if(object.mosaic && io.mosaicHeight) { diff --git a/higan/gba/ppu/ppu.cpp b/higan/gba/ppu/ppu.cpp index f601b051..89713e8d 100644 --- a/higan/gba/ppu/ppu.cpp +++ b/higan/gba/ppu/ppu.cpp @@ -1,4 +1,5 @@ #include +#include //pixel: 4 cycles diff --git a/higan/md/vdp/background.cpp b/higan/md/vdp/background.cpp index f5069834..3f86dba1 100644 --- a/higan/md/vdp/background.cpp +++ b/higan/md/vdp/background.cpp @@ -70,7 +70,7 @@ auto VDP::Background::run(uint x, uint y) -> void { uint16 tileData = vdp.vram.read(tileAddress); uint4 color = tileData >> (((pixelX & 3) ^ 3) << 2); - output.color = ternary(color, tileAttributes.bits(13,14) << 4 | color, 0); + output.color = if(color, tileAttributes.bits(13,14) << 4 | color, 0); output.priority = tileAttributes.bit(15); } diff --git a/higan/md/vdp/vdp.cpp b/higan/md/vdp/vdp.cpp index 9e79d715..23685782 100644 --- a/higan/md/vdp/vdp.cpp +++ b/higan/md/vdp/vdp.cpp @@ -1,4 +1,5 @@ #include +#include namespace MegaDrive { diff --git a/higan/md/ym2612/channel.cpp b/higan/md/ym2612/channel.cpp index d42ec54e..adf83390 100644 --- a/higan/md/ym2612/channel.cpp +++ b/higan/md/ym2612/channel.cpp @@ -27,7 +27,7 @@ auto YM2612::Channel::Operator::trigger(bool state) -> void { } auto YM2612::Channel::Operator::runEnvelope() -> void { - uint sustain = ternary(envelope.sustainLevel < 15, envelope.sustainLevel << 5, 0x3f0); + uint sustain = if(envelope.sustainLevel < 15, envelope.sustainLevel << 5, 0x3f0); if(ym2612.envelope.clock & (1 << envelope.divider) - 1) return; uint value = ym2612.envelope.clock >> envelope.divider; @@ -121,7 +121,7 @@ auto YM2612::Channel::Operator::updatePhase() -> void { phase.delta = pitch.value + (pm >> 10 - msb) << 6 >> 7 - octave.value; phase.delta = (!detune.bit(2) ? phase.delta + tuning : phase.delta - tuning) & 0x1ffff; - phase.delta = ternary(multiple, phase.delta * multiple, phase.delta >> 1) & 0xfffff; + phase.delta = if(multiple, phase.delta * multiple, phase.delta >> 1) & 0xfffff; } auto YM2612::Channel::Operator::updateLevel() -> void { diff --git a/higan/md/ym2612/ym2612.cpp b/higan/md/ym2612/ym2612.cpp index 7c70b0b8..d0725223 100644 --- a/higan/md/ym2612/ym2612.cpp +++ b/higan/md/ym2612/ym2612.cpp @@ -1,4 +1,5 @@ #include +#include namespace MegaDrive { @@ -64,7 +65,7 @@ auto YM2612::sample() -> void { auto wave = [&](uint n, uint modulation) -> int { int x = (modulation >> 1) + (op[n].phase.value >> 10); int y = sine[x & 0x3ff] + op[n].outputLevel; - return ternary(y < 0x2000, pow2[y & 0x1ff] << 2 >> (y >> 9), 0); + return if(y < 0x2000, pow2[y & 0x1ff] << 2 >> (y >> 9), 0); }; int feedback = modMask & op[0].output + op[0].prior >> 9 - channel.feedback; diff --git a/higan/processor/arm7tdmi/algorithms.cpp b/higan/processor/arm7tdmi/algorithms.cpp index 9ef47f63..ec321200 100644 --- a/higan/processor/arm7tdmi/algorithms.cpp +++ b/higan/processor/arm7tdmi/algorithms.cpp @@ -13,8 +13,8 @@ auto ARM7TDMI::ADD(uint32 source, uint32 modify, bool carry) -> uint32 { auto ARM7TDMI::ASR(uint32 source, uint8 shift) -> uint32 { carry = cpsr().c; if(shift == 0) return source; - carry = ternary(shift > 32, source & 1 << 31, source & 1 << shift - 1); - source = ternary(shift > 31, (int32)source >> 31, (int32)source >> shift); + carry = if(shift > 32, source & 1 << 31, source & 1 << shift - 1); + source = if(shift > 31, (int32)source >> 31, (int32)source >> shift); return source; } @@ -30,16 +30,16 @@ auto ARM7TDMI::BIT(uint32 result) -> uint32 { auto ARM7TDMI::LSL(uint32 source, uint8 shift) -> uint32 { carry = cpsr().c; if(shift == 0) return source; - carry = ternary(shift > 32, 0, source & 1 << 32 - shift); - source = ternary(shift > 31, 0, source << shift); + carry = if(shift > 32, 0, source & 1 << 32 - shift); + source = if(shift > 31, 0, source << shift); return source; } auto ARM7TDMI::LSR(uint32 source, uint8 shift) -> uint32 { carry = cpsr().c; if(shift == 0) return source; - carry = ternary(shift > 32, 0, source & 1 << shift - 1); - source = ternary(shift > 31, 0, source >> shift); + carry = if(shift > 32, 0, source & 1 << shift - 1); + source = if(shift > 31, 0, source >> shift); return source; } diff --git a/higan/processor/arm7tdmi/arm7tdmi.cpp b/higan/processor/arm7tdmi/arm7tdmi.cpp index e3dc0d28..1131c2d6 100644 --- a/higan/processor/arm7tdmi/arm7tdmi.cpp +++ b/higan/processor/arm7tdmi/arm7tdmi.cpp @@ -1,4 +1,5 @@ #include +#include #include "arm7tdmi.hpp" namespace Processor { diff --git a/higan/processor/spc700/instructions.cpp b/higan/processor/spc700/instructions.cpp index 2021e8b1..17fb4a32 100644 --- a/higan/processor/spc700/instructions.cpp +++ b/higan/processor/spc700/instructions.cpp @@ -570,7 +570,7 @@ auto SPC700::instructionTestSetBitsAbsolute(bool set) -> void { ZF = (A - data) == 0; NF = (A - data) & 0x80; read(address); - write(address, ternary(set, data | A, data & ~A)); + write(address, if(set, data | A, data & ~A)); } auto SPC700::instructionTransfer(uint8& from, uint8& to) -> void { diff --git a/higan/processor/spc700/spc700.cpp b/higan/processor/spc700/spc700.cpp index 69ec693c..9264eecb 100644 --- a/higan/processor/spc700/spc700.cpp +++ b/higan/processor/spc700/spc700.cpp @@ -1,4 +1,5 @@ #include +#include #include "spc700.hpp" namespace Processor { diff --git a/higan/processor/tlcs900h/algorithms.cpp b/higan/processor/tlcs900h/algorithms.cpp index 1ab8e03d..55781e16 100644 --- a/higan/processor/tlcs900h/algorithms.cpp +++ b/higan/processor/tlcs900h/algorithms.cpp @@ -23,13 +23,13 @@ template auto TLCS900H::algorithmAdd(T target, T source, uint1 carry T result = target + source + carry; T carries = target ^ source ^ result; T overflow = (target ^ result) & (source ^ result); - CF = T(carries ^ overflow).negative(); + CF = T(carries ^ overflow).bit(-1); NF = 0; - VF = overflow.negative(); + VF = overflow.bit(-1); HF = carries.bit(4); if constexpr(T::bits() == 32) HF = Undefined; - ZF = result.zero(); - SF = result.negative(); + ZF = result == 0; + SF = result.bit(-1); return result; } @@ -39,8 +39,8 @@ template auto TLCS900H::algorithmAnd(T target, T source) -> T { NF = 0; PF = parity(result); HF = 1; - ZF = result.zero(); - SF = result.negative(); + ZF = result == 0; + SF = result.bit(-1); return result; } @@ -48,10 +48,10 @@ 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(); + VF = T((target ^ source) & (target ^ result)).bit(-1); HF = T(target ^ source ^ result).bit(4); - ZF = result.zero(); - SF = result.negative(); + ZF = result == 0; + SF = result.bit(-1); } return result; } @@ -60,10 +60,10 @@ 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(); + VF = T((target ^ result) & (source ^ result)).bit(-1); HF = T(target ^ source ^ result).bit(4); - ZF = result.zero(); - SF = result.negative(); + ZF = result == 0; + SF = result.bit(-1); } return result; } @@ -74,8 +74,26 @@ template auto TLCS900H::algorithmOr(T target, T source) -> T { NF = 0; PF = parity(result); HF = 0; - ZF = result.zero(); - SF = result.negative(); + ZF = result == 0; + SF = result.bit(-1); + return result; +} + +template auto TLCS900H::algorithmRotated(T result) -> T { + NF = 0; + PF = parity(result); + HF = 0; + ZF = result == 0; + SF = result.bit(-1); + return result; +} + +template auto TLCS900H::algorithmShifted(T result) -> T { + NF = 0; + PF = parity(result); + HF = 0; + ZF = result == 0; + SF = result.bit(-1); return result; } @@ -83,13 +101,13 @@ template auto TLCS900H::algorithmSubtract(T target, T source, uint1 T result = target - source - carry; T carries = target ^ source ^ result; T overflow = (target ^ result) & (source ^ target); - CF = T(carries ^ overflow).negative(); + CF = T(carries ^ overflow).bit(-1); NF = 1; - VF = overflow.negative(); + VF = overflow.bit(-1); HF = carries.bit(4); if constexpr(T::bits() == 32) HF = Undefined; - ZF = result.zero(); - SF = result.negative(); + ZF = result == 0; + SF = result.bit(-1); return result; } @@ -99,7 +117,7 @@ template auto TLCS900H::algorithmXor(T target, T source) -> T { NF = 0; PF = parity(result); HF = 0; - ZF = result.zero(); - SF = result.negative(); + ZF = result == 0; + SF = result.bit(-1); return result; } diff --git a/higan/processor/tlcs900h/instruction.cpp b/higan/processor/tlcs900h/instruction.cpp index 448dadaa..d461481a 100644 --- a/higan/processor/tlcs900h/instruction.cpp +++ b/higan/processor/tlcs900h/instruction.cpp @@ -323,12 +323,63 @@ auto TLCS900H::instructionRegister(R register) -> void { case 0x1a: case 0x1b: return (void)Undefined; //case 0x1c: DJNZ r,d case 0x1d: case 0x1e: case 0x1f: return (void)Undefined; + case 0x20: + if constexpr(bits != 32) return instructionAndCarry(register, fetchImmediate()); + return (void)Undefined; + case 0x21: + if constexpr(bits != 32) return instructionOrCarry(register, fetchImmediate()); + return (void)Undefined; + case 0x22: + if constexpr(bits != 32) return instructionXorCarry(register, fetchImmediate()); + return (void)Undefined; + case 0x23: + if constexpr(bits != 32) return instructionLoadCarry(register, fetchImmediate()); + return (void)Undefined; + case 0x24: + if constexpr(bits != 32) return instructionStoreCarry(register, fetchImmediate()); + return (void)Undefined; case 0x25: case 0x26: case 0x27: return (void)Undefined; + case 0x28: + if constexpr(bits != 32) return instructionAndCarry(register, A); + return (void)Undefined; + case 0x29: + if constexpr(bits != 32) return instructionOrCarry(register, A); + return (void)Undefined; + case 0x2a: + if constexpr(bits != 32) return instructionXorCarry(register, A); + return (void)Undefined; + case 0x2b: + if constexpr(bits != 32) return instructionLoadCarry(register, A); + return (void)Undefined; + case 0x2c: + if constexpr(bits != 32) return instructionStoreCarry(register, A); + return (void)Undefined; case 0x2d: return (void)Undefined; case 0x2e: return instructionLoad(toControlRegister(data), register); case 0x2f: return instructionLoad(register, toControlRegister(data)); + case 0x30: + if constexpr(bits != 32) return instructionReset(register, fetchImmediate()); + return (void)Undefined; + case 0x31: + if constexpr(bits != 32) return instructionSet(register, fetchImmediate()); + return (void)Undefined; + case 0x32: + if constexpr(bits != 32) return instructionChange(register, fetchImmediate()); + return (void)Undefined; + case 0x33: + if constexpr(bits != 32) return instructionBit(register, fetchImmediate()); + return (void)Undefined; + case 0x34: + 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 0x3b: return (void)Undefined; +//case 0x3c: MDEC1 #,r +//case 0x3d: MDEC2 #,r +//case 0x3e: MDEC4 #,r 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); @@ -363,7 +414,7 @@ auto TLCS900H::instructionRegister(R register) -> void { case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: return instructionLoad(register, toImmediate((uint3)data)); case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: - return instructionSubtractCarry(toRegister3(data), register); + return instructionSubtractBorrow(toRegister3(data), register); case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: if constexpr(bits == 32) return (void)Undefined; return instructionExchange(toRegister3(data), register); @@ -372,7 +423,7 @@ auto TLCS900H::instructionRegister(R register) -> void { case 0xc8: return instructionAdd(register, fetchImmediate()); case 0xc9: return instructionAddCarry(register, fetchImmediate()); case 0xca: return instructionSubtract(register, fetchImmediate()); - case 0xcb: return instructionSubtractCarry(register, fetchImmediate()); + case 0xcb: return instructionSubtractBorrow(register, fetchImmediate()); case 0xcc: return instructionAnd(register, fetchImmediate()); case 0xcd: return instructionXor(register, fetchImmediate()); case 0xce: return instructionOr(register, fetchImmediate()); @@ -383,8 +434,24 @@ auto TLCS900H::instructionRegister(R register) -> void { return instructionCompare(register, toImmediate((uint3)data)); case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: return instructionOr(toRegister3(data), register); + case 0xe8: return instructionRotateLeftWithoutCarry(register, fetchImmediate()); + case 0xe9: return instructionRotateRightWithoutCarry(register, fetchImmediate()); + case 0xea: return instructionRotateLeft(register, fetchImmediate()); + case 0xeb: return instructionRotateRight(register, fetchImmediate()); + case 0xec: return instructionShiftLeftArithmetic(register, fetchImmediate()); + case 0xed: return instructionShiftRightArithmetic(register, fetchImmediate()); + case 0xee: return instructionShiftLeftLogical(register, fetchImmediate()); + case 0xef: return instructionShiftRightLogical(register, fetchImmediate()); case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: return instructionCompare(toRegister3(data), register); + case 0xf8: return instructionRotateLeftWithoutCarry(register, A); + case 0xf9: return instructionRotateRightWithoutCarry(register, A); + case 0xfa: return instructionRotateLeft(register, A); + case 0xfb: return instructionRotateRight(register, A); + case 0xfc: return instructionShiftLeftArithmetic(register, A); + case 0xfd: return instructionShiftRightArithmetic(register, A); + case 0xfe: return instructionShiftLeftLogical(register, A); + case 0xff: return instructionShiftRightLogical(register, A); } } @@ -400,7 +467,17 @@ 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 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 0x18: return (void)Undefined; case 0x19: if constexpr(bits == 32) return (void)Undefined; @@ -423,7 +500,7 @@ auto TLCS900H::instructionSourceMemory(M memory) -> void { return instructionSubtract(memory, fetchImmediate()); case 0x3b: if constexpr(bits == 32) return (void)Undefined; - return instructionSubtractCarry(memory, fetchImmediate()); + return instructionSubtractBorrow(memory, fetchImmediate()); case 0x3c: if constexpr(bits == 32) return (void)Undefined; return instructionAnd(memory, fetchImmediate()); @@ -453,6 +530,30 @@ auto TLCS900H::instructionSourceMemory(M memory) -> void { case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: 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 0x78: + if constexpr(bits != 32) return instructionRotateLeftWithoutCarry(memory, toImmediate(1)); + return (void)Undefined; + case 0x79: + if constexpr(bits != 32) return instructionRotateRightWithoutCarry(memory, toImmediate(1)); + return (void)Undefined; + case 0x7a: + if constexpr(bits != 32) return instructionRotateLeft(memory, toImmediate(1)); + return (void)Undefined; + case 0x7b: + if constexpr(bits != 32) return instructionRotateRight(memory, toImmediate(1)); + return (void)Undefined; + case 0x7c: + if constexpr(bits != 32) return instructionShiftLeftArithmetic(memory, toImmediate(1)); + return (void)Undefined; + case 0x7d: + if constexpr(bits != 32) return instructionShiftRightArithmetic(memory, toImmediate(1)); + return (void)Undefined; + case 0x7e: + if constexpr(bits != 32) return instructionShiftLeftLogical(memory, toImmediate(1)); + return (void)Undefined; + case 0x7f: + if constexpr(bits != 32) return instructionShiftRightLogical(memory, toImmediate(1)); + return (void)Undefined; case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: return instructionAdd(toRegister3(data), memory); case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: @@ -466,9 +567,9 @@ auto TLCS900H::instructionSourceMemory(M memory) -> void { case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: return instructionSubtract(memory, toRegister3(data)); case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: - return instructionSubtractCarry(toRegister3(data), memory); + return instructionSubtractBorrow(toRegister3(data), memory); case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: - return instructionSubtractCarry(memory, toRegister3(data)); + return instructionSubtractBorrow(memory, toRegister3(data)); case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: return instructionAnd(toRegister3(data), memory); case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: @@ -509,6 +610,11 @@ auto TLCS900H::instructionTargetMemory(uint32 address) -> void { case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: return (void)Undefined; case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: return instructionLoad(toRegister3(data), toMemory(address)); + case 0x28: return instructionAndCarry(toMemory(address), A); + case 0x29: return instructionOrCarry(toMemory(address), A); + case 0x2a: return instructionXorCarry(toMemory(address), A); + case 0x2b: return instructionLoadCarry(toMemory(address), A); + case 0x2c: return instructionStoreCarry(toMemory(address), A); case 0x2d: case 0x2e: case 0x2f: return (void)Undefined; case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: return instructionLoad(toRegister3(data), toMemory(address)); @@ -524,6 +630,26 @@ auto TLCS900H::instructionTargetMemory(uint32 address) -> void { case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: return (void)Undefined; case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: return (void)Undefined; case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: return (void)Undefined; + case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: + return instructionAndCarry(toMemory(address), toImmediate(data)); + case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: + return instructionOrCarry(toMemory(address), toImmediate(data)); + case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: + return instructionXorCarry(toMemory(address), toImmediate(data)); + case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: + return instructionLoadCarry(toMemory(address), toImmediate(data)); + case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: + return instructionStoreCarry(toMemory(address), toImmediate(data)); + case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: + return instructionTestSet(toMemory(address), toImmediate(data)); + case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: + return instructionReset(toMemory(address), toImmediate(data)); + case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: + return instructionSet(toMemory(address), toImmediate(data)); + case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: + return instructionChange(toMemory(address), toImmediate(data)); + case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: + return instructionBit(toMemory(address), toImmediate(data)); case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: return instructionJump((uint4)data, toMemory(address)); diff --git a/higan/processor/tlcs900h/instructions.cpp b/higan/processor/tlcs900h/instructions.cpp index 1c745acb..b0804af3 100644 --- a/higan/processor/tlcs900h/instructions.cpp +++ b/higan/processor/tlcs900h/instructions.cpp @@ -13,6 +13,21 @@ auto TLCS900H::instructionAnd(Target target, Source source) -> void { store(target, algorithmAnd(load(target), load(source))); } +template +auto TLCS900H::instructionAndCarry(Source source, Offset offset) -> void { + if constexpr(Source::bits == 8 && is_same_v>) { if(load(offset).bit(3)) return (void)Undefined; } + CF &= load(source).bit(load(offset) & Source::bits - 1); +} + +template +auto TLCS900H::instructionBit(Source source, Offset offset) -> void { + NF = 0; + VF = Undefined; + HF = 1; + ZF = !load(source).bit(load(offset) & Source::bits - 1); + SF = Undefined; +} + auto TLCS900H::instructionBitSearch1Backward(Register register) -> void { auto value = load(register); for(uint index : reverse(range(16))) { @@ -41,6 +56,13 @@ auto TLCS900H::instructionCallRelative(Source displacement) -> void { store(PC, load(PC) + load(displacement)); } +template +auto TLCS900H::instructionChange(Target target, Offset offset) -> void { + auto result = load(target); + result.bit(load(offset) & Target::bits - 1) ^= 1; + store(target, result); +} + template auto TLCS900H::instructionCompare(Target target, Source source) -> void { algorithmSubtract(load(target), load(source)); @@ -59,8 +81,8 @@ auto TLCS900H::instructionDecimalAdjustAccumulator(Register register) -> 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(); + ZF = value == 0; + SF = value.bit(-1); store(register, value); } @@ -139,6 +161,12 @@ auto TLCS900H::instructionLoad(Target target, Source source) -> void { store(target, load(source)); } +template +auto TLCS900H::instructionLoadCarry(Source source, Offset offset) -> void { + if constexpr(Source::bits == 8 && is_same_v>) { if(load(offset).bit(3)) return (void)Undefined; } + CF = load(source).bit(load(offset) & Source::bits - 1); +} + //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 { @@ -163,9 +191,9 @@ auto TLCS900H::instructionMultiplyAdd(Register register) -> void { store(XHL, load(XHL) - 2); auto result = load(expand(register)); - VF = uint32(~(target ^ source) & (target ^ result)).negative(); - ZF = result.zero(); - SF = result.negative(); + VF = uint32((target ^ result) & (source ^ result)).bit(-1); + ZF = result == 0; + SF = result.bit(-1); } template @@ -186,6 +214,12 @@ auto TLCS900H::instructionOr(Target target, Source source) -> void { store(target, algorithmOr(load(target), load(source))); } +template +auto TLCS900H::instructionOrCarry(Source source, Offset offset) -> void { + if constexpr(Source::bits == 8 && is_same_v>) { if(load(offset).bit(3)) return (void)Undefined; } + CF |= load(source).bit(load(offset) & Source::bits - 1); +} + template auto TLCS900H::instructionPop(Target target) -> void { pop(target); @@ -196,6 +230,13 @@ auto TLCS900H::instructionPush(Source source) -> void { push(source); } +template +auto TLCS900H::instructionReset(Target target, Offset offset) -> void { + auto result = load(target); + result.bit(load(offset) & Target::bits - 1) = 0; + store(target, result); +} + auto TLCS900H::instructionReturn(uint4 code) -> void { if(condition(code)) pop(PC); } @@ -212,6 +253,59 @@ auto TLCS900H::instructionReturnInterrupt() -> void { store(INTNEST, load(INTNEST) - 1); } +template +auto TLCS900H::instructionRotateLeft(Target target, Amount amount) -> void { + auto result = load(target); + uint count = (uint4)load(amount); + for(uint n : range(if(count, 16))) { + uint cf = result.bit(-1); + result = result << 1 | CF; + CF = cf; + } + store(target, algorithmRotated(result)); +} + +template +auto TLCS900H::instructionRotateLeftWithoutCarry(Target target, Amount amount) -> void { + auto result = load(target); + uint count = (uint4)load(amount); + for(uint n : range(if(count, 16))) { + CF = result.bit(-1); + result = result << 1 | CF; + } + store(target, algorithmRotated(result)); +} + +template +auto TLCS900H::instructionRotateRight(Target target, Amount amount) -> void { + auto result = load(target); + uint count = (uint4)load(amount); + for(uint n : range(if(count, 16))) { + uint cf = result.bit(0); + result = CF << Target::bits - 1 | result >> 1; + CF = cf; + } + store(target, algorithmRotated(result)); +} + +template +auto TLCS900H::instructionRotateRightWithoutCarry(Target target, Amount amount) -> void { + auto result = load(target); + uint count = (uint4)load(amount); + for(uint n : range(if(count, 16))) { + CF = result.bit(0); + result = CF << Target::bits - 1 | result >> 1; + } + store(target, algorithmRotated(result)); +} + +template +auto TLCS900H::instructionSet(Target target, Offset offset) -> void { + auto result = load(target); + result.bit(load(offset) & Target::bits - 1) = 1; + store(target, result); +} + template auto TLCS900H::instructionSetConditionCode(uint4 code, Target target) -> void { store(target, condition(code)); @@ -229,6 +323,59 @@ auto TLCS900H::instructionSetRegisterFilePointer(uint2 value) -> void { RFP = value; } +template +auto TLCS900H::instructionShiftLeftArithmetic(Target target, Amount amount) -> void { + auto result = load(target); + uint count = (uint4)load(amount); + for(uint n : range(if(count, 16))) { + CF = result.bit(-1); + result = result << 1; + } + store(target, algorithmShifted(result)); +} + +template +auto TLCS900H::instructionShiftLeftLogical(Target target, Amount amount) -> void { + auto result = load(target); + uint count = (uint4)load(amount); + for(uint n : range(if(count, 16))) { + CF = result.bit(-1); + result = result << 1; + } + store(target, algorithmShifted(result)); +} + +template +auto TLCS900H::instructionShiftRightArithmetic(Target target, Amount amount) -> void { + auto result = load(target); + uint count = (uint4)load(amount); + for(uint n : range(if(count, 16))) { + CF = result.bit(0); + result = result >> 1; + result.bit(-1) = result.bit(-2); + } + store(target, algorithmShifted(result)); +} + +template +auto TLCS900H::instructionShiftRightLogical(Target target, Amount amount) -> void { + auto result = load(target); + uint count = (uint4)load(amount); + for(uint n : range(if(count, 16))) { + CF = result.bit(0); + result = result >> 1; + } + store(target, algorithmShifted(result)); +} + +template +auto TLCS900H::instructionStoreCarry(Target target, Offset offset) -> void { + if constexpr(Target::bits == 8) { if(load(offset).bit(3)) return; } //unlike other *CF instructions, STCF behavior is defined + auto result = load(target); + result.bit(load(offset)) = CF; + store(target, result); +} + auto TLCS900H::instructionSoftwareInterrupt(uint3 interrupt) -> void { //TODO } @@ -238,12 +385,31 @@ auto TLCS900H::instructionSubtract(Target target, Source source) -> void { store(target, algorithmSubtract(load(target), load(source))); } +//note: the TLCS900/H manual states this is subtract-with-carry, but it isn't template -auto TLCS900H::instructionSubtractCarry(Target target, Source source) -> void { +auto TLCS900H::instructionSubtractBorrow(Target target, Source source) -> void { store(target, algorithmSubtract(load(target), load(source), CF)); } +template +auto TLCS900H::instructionTestSet(Target target, Offset offset) -> void { + auto result = load(target); + NF = 0; + VF = Undefined; + HF = 1; + ZF = result.bit(load(offset) & Target::bits - 1); + SF = Undefined; + result.bit(load(offset) & Target::bits - 1) = 1; + store(target, result); +} + template auto TLCS900H::instructionXor(Target target, Source source) -> void { store(target, algorithmXor(load(target), load(source))); } + +template +auto TLCS900H::instructionXorCarry(Source source, Offset offset) -> void { + if constexpr(Source::bits == 8 && is_same_v>) { if(load(offset).bit(3)) return (void)Undefined; } + CF ^= load(source).bit(load(offset) & Source::bits - 1); +} diff --git a/higan/processor/tlcs900h/tlcs900h.cpp b/higan/processor/tlcs900h/tlcs900h.cpp index a6dff50b..5bc38758 100644 --- a/higan/processor/tlcs900h/tlcs900h.cpp +++ b/higan/processor/tlcs900h/tlcs900h.cpp @@ -1,4 +1,5 @@ #include +#include #include "tlcs900h.hpp" namespace Processor { diff --git a/higan/processor/tlcs900h/tlcs900h.hpp b/higan/processor/tlcs900h/tlcs900h.hpp index 2b364cae..7860ffb8 100644 --- a/higan/processor/tlcs900h/tlcs900h.hpp +++ b/higan/processor/tlcs900h/tlcs900h.hpp @@ -8,6 +8,7 @@ * what happens during an LDX instruction when the three padding bytes aren't all 0x00? * what value is read back from a non-existent 8-bit register ID? (eg 0x40-0xcf) * many instructions are undefined, some are marked as dummy instructions ... what do each do? + * what happens when using (AND,OR,XOR,LD)CF (byte)source,A with A.bit(3) set? */ #pragma once @@ -73,6 +74,8 @@ struct TLCS900H { 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 algorithmRotated(T result) -> T; + template auto algorithmShifted(T result) -> T; template auto algorithmSubtract(T target, T source, uint1 carry = 0) -> T; template auto algorithmXor(T target, T source) -> T; @@ -92,10 +95,13 @@ struct TLCS900H { template auto instructionAdd(Target, Source) -> void; template auto instructionAddCarry(Target, Source) -> void; template auto instructionAnd(Target, Source) -> void; + template auto instructionAndCarry(Source, Offset) -> void; + template auto instructionBit(Source, Offset) -> void; auto instructionBitSearch1Backward(Register) -> void; auto instructionBitSearch1Forward(Register) -> void; template auto instructionCall(uint4 code, Source) -> void; template auto instructionCallRelative(Source) -> void; + template auto instructionChange(Target, Offset) -> void; template auto instructionCompare(Target, Source) -> void; template auto instructionComplement(Target) -> void; auto instructionDecimalAdjustAccumulator(Register) -> void; @@ -110,6 +116,7 @@ struct TLCS900H { template auto instructionJump(uint4 code, Source) -> void; template auto instructionJumpRelative(uint4 code, Source) -> void; template auto instructionLoad(Target, Source) -> void; + template auto instructionLoadCarry(Source, Offset) -> void; auto instructionMirror(Register) -> void; template auto instructionMultiply(Target, Source) -> void; auto instructionMultiplyAdd(Register) -> void; @@ -117,19 +124,33 @@ struct TLCS900H { template auto instructionNegate(Target) -> void; auto instructionNoOperation() -> void; template auto instructionOr(Target, Source) -> void; + template auto instructionOrCarry(Source, Offset) -> 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 instructionRotateLeft(Target, Amount) -> void; + template auto instructionRotateLeftWithoutCarry(Target, Amount) -> void; + template auto instructionRotateRight(Target, Amount) -> void; + template auto instructionRotateRightWithoutCarry(Target, Amount) -> void; + template auto instructionSet(Target, Offset) -> void; template auto instructionSetConditionCode(uint4 code, Target) -> void; auto instructionSetFlag(uint1& flag, uint1 value) -> void; auto instructionSetInterruptFlipFlop(uint3 value) -> void; auto instructionSetRegisterFilePointer(uint2 value) -> void; + template auto instructionShiftLeftArithmetic(Target, Amount) -> void; + template auto instructionShiftLeftLogical(Target, Amount) -> void; + template auto instructionShiftRightArithmetic(Target, Amount) -> void; + template auto instructionShiftRightLogical(Target, Amount) -> void; + template auto instructionStoreCarry(Target, Offset) -> void; auto instructionSoftwareInterrupt(uint3 interrupt) -> void; template auto instructionSubtract(Target, Source) -> void; - template auto instructionSubtractCarry(Target, Source) -> void; + template auto instructionSubtractBorrow(Target, Source) -> void; + template auto instructionTestSet(Target, Offset) -> void; template auto instructionXor(Target, Source) -> void; + template auto instructionXorCarry(Source, Offset) -> void; //serialization.cpp auto serialize(serializer&) -> void; diff --git a/higan/sfc/coprocessor/spc7110/dcu.cpp b/higan/sfc/coprocessor/spc7110/dcu.cpp index c4c72b65..c80e013b 100644 --- a/higan/sfc/coprocessor/spc7110/dcu.cpp +++ b/higan/sfc/coprocessor/spc7110/dcu.cpp @@ -18,7 +18,7 @@ auto SPC7110::dcuBeginTransfer() -> void { decompressor->initialize(dcuMode, dcuAddress); decompressor->decode(); - uint seek = ternary(r480b & 2, r4805 | r4806 << 8, 0); + uint seek = if(r480b & 2, r4805 | r4806 << 8, 0); while(seek--) decompressor->decode(); r480c |= 0x80; diff --git a/higan/sfc/coprocessor/spc7110/spc7110.cpp b/higan/sfc/coprocessor/spc7110/spc7110.cpp index 14425d8f..00ba4a71 100644 --- a/higan/sfc/coprocessor/spc7110/spc7110.cpp +++ b/higan/sfc/coprocessor/spc7110/spc7110.cpp @@ -1,4 +1,5 @@ #include +#include namespace SuperFamicom { diff --git a/higan/sfc/ppu-fast/background.cpp b/higan/sfc/ppu-fast/background.cpp index 7bd3b614..6a8f617c 100644 --- a/higan/sfc/ppu-fast/background.cpp +++ b/higan/sfc/ppu-fast/background.cpp @@ -26,7 +26,7 @@ auto PPU::Line::renderBackground(PPU::IO::Background& self, uint source) -> void uint hmask = (width << self.tileSize << self.screenSize.bit(0)) - 1; uint vmask = (width << self.tileSize << self.screenSize.bit(1)) - 1; - uint y = this->y - ternary(self.mosaicEnable, this->y % (1 + io.mosaicSize), 0); + uint y = this->y - if(self.mosaicEnable, this->y % (1 + io.mosaicSize), 0); if(hires) { hscroll <<= 1; if(io.interlace) y = y << 1 | ppu.field(); diff --git a/higan/sfc/ppu-fast/mode7.cpp b/higan/sfc/ppu-fast/mode7.cpp index ac8b33b7..95455244 100644 --- a/higan/sfc/ppu-fast/mode7.cpp +++ b/higan/sfc/ppu-fast/mode7.cpp @@ -1,6 +1,6 @@ auto PPU::Line::renderMode7(PPU::IO::Background& self, uint source) -> void { - int Y = this->y - ternary(self.mosaicEnable, this->y % (1 + io.mosaicSize), 0); - int y = !io.mode7.vflip ? Y : 255 - Y; + int Y = this->y - if(self.mosaicEnable, this->y % (1 + io.mosaicSize), 0); + int y = if(!io.mode7.vflip, Y, 255 - Y); int a = (int16)io.mode7.a; int b = (int16)io.mode7.b; diff --git a/higan/sfc/ppu-fast/ppu.cpp b/higan/sfc/ppu-fast/ppu.cpp index 76a270ff..e3cb1b2d 100644 --- a/higan/sfc/ppu-fast/ppu.cpp +++ b/higan/sfc/ppu-fast/ppu.cpp @@ -1,4 +1,5 @@ #include +#include namespace SuperFamicom { diff --git a/nall/algorithm.hpp b/nall/algorithm.hpp index 1e97d0b0..18a3b093 100644 --- a/nall/algorithm.hpp +++ b/nall/algorithm.hpp @@ -23,8 +23,8 @@ template auto max(const T& t, const U& u, return t > u ? max(t, forward

(p)...) : max(u, forward

(p)...); } -template auto ternary(bool test, const T& lhs, const U& rhs) -> T { - return test ? lhs : (T)rhs; -} +//template auto ternary(bool test, const T& lhs, const U& rhs) -> T { +// return test ? lhs : (T)rhs; +//} }} diff --git a/nall/inline-if.hpp b/nall/inline-if.hpp new file mode 100644 index 00000000..a8be4fe7 --- /dev/null +++ b/nall/inline-if.hpp @@ -0,0 +1,10 @@ +#pragma once + +#define if1(statement) if(statement) +#define if2(condition, false) ([](auto&& value) -> decltype(condition) { \ + return (bool)value ? value : (decltype(condition))false; \ +})(condition) +#define if3(condition, true, false) ((condition) ? (true) : (decltype(true))(false)) +#define if4(type, condition, true, false) ((condition) ? (type)(true) : (type)(false)) +#define if_(_1, _2, _3, _4, name, ...) name +#define if(...) if_(__VA_ARGS__, if4, if3, if2, if1)(__VA_ARGS__) diff --git a/nall/primitives/bit-range.hpp b/nall/primitives/bit-range.hpp index 208f2be8..a3ff2ec0 100644 --- a/nall/primitives/bit-range.hpp +++ b/nall/primitives/bit-range.hpp @@ -2,8 +2,8 @@ namespace nall { -template struct BitRange { - enum : uint { Precision = RequestedPrecision < 1 ? 1 : RequestedPrecision > 64 ? 64 : RequestedPrecision }; +template struct BitRange { + enum : uint { Precision = Requested < 1 ? 1 : Requested > 64 ? 64 : Requested }; static inline constexpr auto bits() -> uint { return Precision; } using type = typename conditional struct BitRange { void>::type>::type>::type>::type; static inline constexpr auto mask() -> type { return ~0ull >> 64 - bits(); } - inline BitRange(type& source, uint low, uint high) - : source(source), lo(low < high ? low : high), hi(high > low ? high : low) {} + inline BitRange(type& source, int lo, int hi) : source(source) { + if(lo < 0) lo = Precision + lo; + if(hi < 0) hi = Precision + hi; + if(lo > hi) swap(lo, hi); + this->lo = lo; + this->hi = hi; + } inline auto& operator=(BitRange& source) { return set(source.get()); } inline auto operator++(int) { auto value = get(); set(value + 1); return value; } @@ -23,7 +28,7 @@ template struct BitRange { inline auto& operator++() { return set(get() + 1); } inline auto& operator--() { return set(get() - 1); } - inline operator uint64_t() const { return get(); } + inline operator type() const { return get(); } template inline auto& operator =(const T& value) { return set( value); } template inline auto& operator *=(const T& value) { return set(get() * value); } template inline auto& operator /=(const T& value) { return set(get() / value); } @@ -37,7 +42,7 @@ template struct BitRange { template inline auto& operator |=(const T& value) { return set(get() | value); } private: - inline auto get() const -> uint64_t { + inline auto get() const -> type { const type rangeBits = hi - lo + 1; const type rangeMask = (1ull << rangeBits) - 1 << lo & mask(); return (source & rangeMask) >> lo; @@ -51,8 +56,8 @@ private: } type& source; - const uint lo; - const uint hi; + uint lo; + uint hi; }; } diff --git a/nall/primitives/integer.hpp b/nall/primitives/integer.hpp index 67114d36..adc5da1b 100644 --- a/nall/primitives/integer.hpp +++ b/nall/primitives/integer.hpp @@ -2,8 +2,8 @@ namespace nall { -template struct Integer { - enum : uint { Precision = RequestedPrecision < 1 ? 1 : RequestedPrecision > 64 ? 64 : RequestedPrecision }; +template struct Integer { + enum : uint { Precision = Requested < 1 ? 1 : Requested > 64 ? 64 : Requested }; static inline constexpr auto bits() -> uint { return Precision; } using type = typename conditional struct Integer { typename conditional::type>::type>::type>::type; - using utype = typename Natural::type; + using utype = typename Natural::type; static inline constexpr auto mask() -> utype { return ~0ull >> 64 - bits(); } static inline constexpr auto sign() -> utype { return 1ull << Precision - 1; } inline Integer() : data(0) {} template inline Integer(const T& value) { data = mask(value); } - explicit inline operator bool() const { return (bool)data; } inline operator type() const { return data; } inline auto operator++(int) { auto value = *this; data = mask(data + 1); return value; } @@ -48,36 +47,31 @@ template struct Integer { #undef lhs #undef rfs - inline auto serialize(serializer& s) { s(data); } + 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 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(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(uint lo, uint hi) -> BitRange { return {(utype&)data, lo, hi}; } - inline auto bit(uint index) -> BitRange { return {(utype&)data, index, index}; } - inline auto byte(uint index) -> BitRange { return {(utype&)data, index * 8 + 0, index * 8 + 7}; } - - inline auto bits(uint lo, uint hi) const -> const BitRange { return {(utype&)*this, lo, lo}; } - inline auto bit(uint index) const -> const BitRange { return {(utype&)*this, index, index}; } - inline auto byte(uint index) const -> const BitRange { return {(utype&)*this, index * 8 + 0, index * 8 + 7}; } - - inline auto clamp(uint bits) -> intmax { + inline auto clamp(uint bits) -> type { const intmax b = 1ull << (bits - 1); const intmax m = b - 1; return data > m ? m : data < -b ? -b : data; } - inline auto clip(uint bits) -> intmax { + inline auto clip(uint bits) -> type { const uintmax b = 1ull << (bits - 1); const uintmax m = b * 2 - 1; return ((data & m) ^ b) - b; } - inline auto natural() const -> Natural; + inline auto serialize(serializer& s) { s(data); } + inline auto natural() const -> Natural; private: - auto mask(type value) const -> type { + inline auto mask(type value) const -> type { return (value & mask() ^ sign()) - sign(); } diff --git a/nall/primitives/natural.hpp b/nall/primitives/natural.hpp index f90d7143..f2c87d22 100644 --- a/nall/primitives/natural.hpp +++ b/nall/primitives/natural.hpp @@ -2,8 +2,8 @@ namespace nall { -template struct Natural { - enum : uint { Precision = RequestedPrecision < 1 ? 1 : RequestedPrecision > 64 ? 64 : RequestedPrecision }; +template struct Natural { + enum : uint { Precision = Requested < 1 ? 1 : Requested > 64 ? 64 : Requested }; static inline constexpr auto bits() -> uint { return Precision; } using type = typename conditional struct Natural { inline Natural() : data(0) {} template inline Natural(const T& value) { data = mask(value); } - explicit inline operator bool() const { return (bool)data; } inline operator type() const { return data; } inline auto operator++(int) { auto value = *this; data = mask(data + 1); return value; } @@ -46,33 +45,28 @@ template struct Natural { #undef lhs #undef rhs - inline auto serialize(serializer& s) { s(data); } + 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}; } - 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(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}; } - inline auto bits(uint lo, uint hi) -> BitRange { return {(type&)data, lo, hi}; } - inline auto bit(uint index) -> BitRange { return {(type&)data, index, index}; } - inline auto byte(uint index) -> BitRange { return {(type&)data, index * 8 + 0, index * 8 + 7}; } - - inline auto bits(uint lo, uint hi) const -> const BitRange { return {(type&)data, lo, hi}; } - inline auto bit(uint index) const -> const BitRange { return {(type&)data, index, index}; } - inline auto byte(uint index) const -> const BitRange { return {(type&)data, index * 8 + 0, index * 8 + 7}; } - - inline auto clamp(uint bits) -> uintmax { + inline auto clamp(uint bits) -> type { const uintmax b = 1ull << (bits - 1); const uintmax m = b * 2 - 1; return data < m ? data : m; } - inline auto clip(uint bits) -> uintmax { + inline auto clip(uint bits) -> type { const uintmax b = 1ull << (bits - 1); const uintmax m = b * 2 - 1; return data & m; } - inline auto integer() const -> Integer; + inline auto serialize(serializer& s) { s(data); } + inline auto integer() const -> Integer; private: inline auto mask(type value) const -> type { diff --git a/nall/primitives/real.hpp b/nall/primitives/real.hpp index a944b12a..1a6b284e 100644 --- a/nall/primitives/real.hpp +++ b/nall/primitives/real.hpp @@ -2,8 +2,8 @@ namespace nall { -template struct Real { - enum : uint { Precision = RequestedPrecision <= 32 ? 32 : 64 }; +template struct Real { + enum : uint { Precision = Requested <= 32 ? 32 : 64 }; static inline constexpr auto bits() -> uint { return Precision; } using type = typename conditional struct Real { inline Real() : data(0.0) {} template inline Real(const T& value) : data((type)value) {} - explicit operator bool() const { return (bool)data; } inline operator type() const { return data; } inline auto operator++(int) { auto value = *this; ++data; return value; } @@ -23,11 +22,11 @@ template struct Real { inline auto& operator--() { data--; return *this; } template inline auto& operator =(const T& value) { data = value; return *this; } - template inline auto& operator+=(const T& value) { data = data + value; return *this; } - template inline auto& operator-=(const T& value) { data = data - value; return *this; } template inline auto& operator*=(const T& value) { data = data * value; return *this; } template inline auto& operator/=(const T& value) { data = data / value; return *this; } template inline auto& operator%=(const T& value) { data = data % value; return *this; } + template inline auto& operator+=(const T& value) { data = data + value; return *this; } + template inline auto& operator-=(const T& value) { data = data - value; return *this; } inline auto serialize(serializer& s) { s(data); } diff --git a/nall/traits.hpp b/nall/traits.hpp index 92a392ac..5dff1814 100644 --- a/nall/traits.hpp +++ b/nall/traits.hpp @@ -15,6 +15,7 @@ namespace nall { using std::enable_if_t; using std::false_type; using std::is_floating_point; + using std::is_floating_point_v; using std::forward; using std::initializer_list; using std::is_array; @@ -23,8 +24,11 @@ namespace nall { using std::is_integral; using std::is_integral_v; using std::is_same; + using std::is_same_v; using std::is_signed; + using std::is_signed_v; using std::is_unsigned; + using std::is_unsigned_v; using std::move; using std::nullptr_t; using std::remove_extent;