Commit c9f7c6c4 by Tim Allen

### Update to v106r76 release.

```byuu says:

I added some useful new functions to nall/primitives:

auto Natural<T>::integer() const -> Integer<T>;
auto Integer<T>::natural() const -> Natural<T>;

These let you cast between signed and unsigned representation without
having to care about the value of T (eg if you take a Natural<T> 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<T> → Integer<T>, 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.

uint9 z = x + y + c;
c = z & 0x100;

Subtracting before:

uint9 z = x - y - c;
c = z & 0x100;

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.```
parent 95d00202
Pipeline #42940162 passed with stage
in 12 minutes and 49 seconds
 ... ... @@ -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/"; ... ...
 ... ... @@ -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; } ... ...
 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; ... ...
 ... ... @@ -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); ... ...