mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-01 22:23:22 +02:00
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. Adding before: uint9 z = x + y + c; c = z & 0x100; Subtracting before: uint9 z = x - y - c; c = z & 0x100; Adding after: uint8 z = x + y + c; c = z < x || z == x && c; Subtracting after: uint8 z = x - y - c; c = z > x || z == x && c; I haven't been able to code golf the new carry computation to be any shorter, unless I include an extra bit, eg for adding: c = z < x + c; But that defeats the entire point of the change. I want the computation to work even when T is uintmax_t. If anyone can come up with a faster method, please let me know. Anyway ... I also had to split off INC and DEC because they compute flags differently (word and long modes don't set flags at all, byte mode doesn't set carry at all.) I also added division by zero support, although I don't know if it's actually hardware accurate. It's what other emulators do, though.
This commit is contained in:
@@ -5,6 +5,10 @@
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct Boolean;
|
||||
template<uint Bits> struct Natural;
|
||||
template<uint Bits> struct Integer;
|
||||
|
||||
struct Boolean {
|
||||
inline Boolean() : data(false) {}
|
||||
template<typename T> inline Boolean(const T& value) : data(value) {}
|
||||
@@ -127,6 +131,8 @@ template<uint Bits> struct Natural {
|
||||
return data & m;
|
||||
}
|
||||
|
||||
inline auto integer() const -> Integer<Bits>;
|
||||
|
||||
private:
|
||||
auto set(type value) -> void {
|
||||
data = value & Mask;
|
||||
@@ -237,6 +243,8 @@ template<uint Bits> struct Integer {
|
||||
return ((data & m) ^ b) - b;
|
||||
}
|
||||
|
||||
inline auto natural() const -> Natural<Bits>;
|
||||
|
||||
private:
|
||||
auto set(type value) -> void {
|
||||
data = ((value & Mask) ^ Sign) - Sign;
|
||||
@@ -245,6 +253,16 @@ private:
|
||||
type data;
|
||||
};
|
||||
|
||||
//cast an unsigned type to a signed type with the same number of bits
|
||||
template<uint Bits> auto Natural<Bits>::integer() const -> Integer<Bits> {
|
||||
return Integer<Bits>(*this);
|
||||
}
|
||||
|
||||
//cast a signed type to an unsigned type with the same number of bits
|
||||
template<uint Bits> auto Integer<Bits>::natural() const -> Natural<Bits> {
|
||||
return Natural<Bits>(*this);
|
||||
}
|
||||
|
||||
template<uint Bits> struct Real {
|
||||
using type =
|
||||
typename conditional<Bits == 32, float32_t,
|
||||
|
Reference in New Issue
Block a user