mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-09 23:31:43 +02:00
Update to v098r19 release.
byuu says: Changelog: - added nall/bit-field.hpp - updated all CPU cores (sans LR35902 due to some complexities) to use BitFields instead of bools - updated as many CPU cores as I could to use BitFields instead of union { struct { uint8_t ... }; }; pairs The speed changes are mostly a wash for this. In some instances, I noticed a ~2-3% speedup (eg SNES emulation), and in others a 2-3% slowdown (eg Famicom emulation.) It's within the margin of error, so it's safe to say it has no impact. This does give us a lot of new useful things, however: - no more manual reconstruction of flag values from lots of left shifts and ORs - no more manual deconstruction of flag values from lots of ANDs - ability to get completely free aliases to flag groups (eg GSU can provide alt2, alt1 and also alt (which is alt2,alt1 combined) - removes the need for the nasty order_lsbN macro hack (eventually will make higan 100% endian independent) - saves us from insane compilers that try and do nasty things with alignment on union-structs - saves us from insane compilers that try to store bit-field bits in reverse order - will allow some really novel new use cases (I'm planning an instant-decode ARM opcode function, for instance.) - reduces code size (we can serialize flag registers in one line instead of one for each flag) However, I probably won't use it for super critical code that's constantly reading out register values (eg PPU MMIO registers.) I think there we would end up with a performance penalty.
This commit is contained in:
128
nall/bit-field.hpp
Normal file
128
nall/bit-field.hpp
Normal file
@@ -0,0 +1,128 @@
|
||||
#pragma once
|
||||
|
||||
namespace nall {
|
||||
|
||||
template<typename type> struct BitFieldReference {
|
||||
BitFieldReference(type& data, uint lo, uint hi)
|
||||
: data(data), lo(lo), hi(hi), bits(hi + lo - 1), mask((~0ull >> (64 - bits)) << lo) {
|
||||
}
|
||||
|
||||
inline explicit operator bool() const { return data & mask; }
|
||||
inline operator type() const { return get(); }
|
||||
|
||||
inline auto& operator=(const BitFieldReference& value) { return set(value.data); }
|
||||
template<typename T> inline auto& operator=(const T& value) { return set(value << lo); }
|
||||
|
||||
inline auto operator++(int) { type value = get(); set(data + (1 << lo)); return value; }
|
||||
inline auto operator--(int) { type value = get(); set(data - (1 << lo)); return value; }
|
||||
|
||||
inline auto& operator++() { return set(data + (1 << lo)); }
|
||||
inline auto& operator--() { return set(data - (1 << lo)); }
|
||||
|
||||
inline auto& operator &=(const type value) { return set(data & (value << lo)); }
|
||||
inline auto& operator |=(const type value) { return set(data | (value << lo)); }
|
||||
inline auto& operator ^=(const type value) { return set(data ^ (value << lo)); }
|
||||
inline auto& operator<<=(const type value) { return set((data & mask) << value); }
|
||||
inline auto& operator>>=(const type value) { return set((data & mask) >> value); }
|
||||
inline auto& operator +=(const type value) { return set(data + (value << lo)); }
|
||||
inline auto& operator -=(const type value) { return set(data - (value << lo)); }
|
||||
inline auto& operator *=(const type value) { return set((get() * value) << lo); }
|
||||
inline auto& operator /=(const type value) { return set((get() / value) << lo); }
|
||||
inline auto& operator %=(const type value) { return set((get() % value) << lo); }
|
||||
|
||||
const uint lo;
|
||||
const uint hi;
|
||||
const uint bits;
|
||||
const uint mask;
|
||||
|
||||
private:
|
||||
type& data;
|
||||
|
||||
inline auto get() const -> type {
|
||||
return (data & mask) >> lo;
|
||||
}
|
||||
|
||||
inline auto set(type value) -> BitFieldReference& {
|
||||
return data = (data & ~mask) | (value & mask), *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename type, uint Lo, uint Hi = ~0> struct BitField {
|
||||
enum : uint { lo = Lo <= Hi ? Lo : Hi };
|
||||
enum : uint { hi = Hi >= Lo ? Hi : Lo };
|
||||
enum : uint { bits = hi - lo + 1 };
|
||||
enum : uint { mask = (~0ull >> (64 - bits)) << lo };
|
||||
static_assert(hi < sizeof(type) * 8, "");
|
||||
|
||||
inline BitField() = default;
|
||||
inline BitField(const BitField& value) { set(value.data); }
|
||||
template<typename T> inline BitField(const T& value) { set(value << lo); }
|
||||
|
||||
inline explicit operator bool() const { return data & mask; }
|
||||
inline operator type() const { return get(); }
|
||||
inline operator BitFieldReference<type>() { return {data, lo, hi}; }
|
||||
|
||||
inline auto& operator=(const BitField& value) { return set(value.data); }
|
||||
template<typename T> inline auto& operator=(const T& value) { return set(value << lo); }
|
||||
|
||||
inline auto operator++(int) { type value = get(); set(data + (1 << lo)); return value; }
|
||||
inline auto operator--(int) { type value = get(); set(data - (1 << lo)); return value; }
|
||||
|
||||
inline auto& operator++() { return set(data + (1 << lo)); }
|
||||
inline auto& operator--() { return set(data - (1 << lo)); }
|
||||
|
||||
inline auto& operator &=(const type value) { return set(data & (value << lo)); }
|
||||
inline auto& operator |=(const type value) { return set(data | (value << lo)); }
|
||||
inline auto& operator ^=(const type value) { return set(data ^ (value << lo)); }
|
||||
inline auto& operator<<=(const type value) { return set((data & mask) << value); }
|
||||
inline auto& operator>>=(const type value) { return set((data & mask) >> value); }
|
||||
inline auto& operator +=(const type value) { return set(data + (value << lo)); }
|
||||
inline auto& operator -=(const type value) { return set(data - (value << lo)); }
|
||||
inline auto& operator *=(const type value) { return set((get() * value) << lo); }
|
||||
inline auto& operator /=(const type value) { return set((get() / value) << lo); }
|
||||
inline auto& operator %=(const type value) { return set((get() % value) << lo); }
|
||||
|
||||
private:
|
||||
type data;
|
||||
|
||||
inline auto get() const -> type {
|
||||
return (data & mask) >> lo;
|
||||
}
|
||||
|
||||
inline auto set(type value) -> BitField& {
|
||||
return data = (data & ~mask) | (value & mask), *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename type, uint Bit> struct BitField<type, Bit, ~0> {
|
||||
enum : uint { bit = Bit };
|
||||
enum : uint { mask = 1ull << bit };
|
||||
static_assert(bit < sizeof(type) * 8, "");
|
||||
|
||||
inline BitField() = default;
|
||||
inline BitField(const BitField& value) { set(value.get()); }
|
||||
template<typename T> inline BitField(const bool value) { set(value); }
|
||||
|
||||
inline operator bool() const { return get(); }
|
||||
inline operator BitFieldReference<type>() { return {data, bit, bit}; }
|
||||
|
||||
inline auto& operator=(const BitField& value) { return set(value.get()); }
|
||||
inline auto& operator=(const bool value) { return set(value); }
|
||||
|
||||
inline auto& operator&=(const bool value) { return set(get() & value); }
|
||||
inline auto& operator|=(const bool value) { return set(get() | value); }
|
||||
inline auto& operator^=(const bool value) { return set(get() ^ value); }
|
||||
|
||||
private:
|
||||
type data;
|
||||
|
||||
inline auto get() const -> bool {
|
||||
return data & mask;
|
||||
}
|
||||
|
||||
inline auto set(bool value) -> BitField& {
|
||||
return data = (data & ~mask) | (value << bit), *this;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@@ -17,7 +17,8 @@
|
||||
#include <nall/any.hpp>
|
||||
#include <nall/atoi.hpp>
|
||||
#include <nall/bit.hpp>
|
||||
#include <nall/bitvector.hpp>
|
||||
#include <nall/bit-field.hpp>
|
||||
#include <nall/bit-vector.hpp>
|
||||
#include <nall/config.hpp>
|
||||
#include <nall/directory.hpp>
|
||||
#include <nall/dl.hpp>
|
||||
|
@@ -5,52 +5,6 @@
|
||||
|
||||
namespace nall {
|
||||
|
||||
template<typename Type, uint Lo, uint Hi> struct BitField {
|
||||
static_assert(Lo <= Hi, "");
|
||||
static_assert(Hi < sizeof(Type) * 8, "");
|
||||
|
||||
inline BitField() = default;
|
||||
inline BitField(const BitField& value) { set(value.data); }
|
||||
template<typename T> inline BitField(const T& value) { set(value << Lo); }
|
||||
|
||||
//inline explicit operator bool() const { return data & Mask; }
|
||||
inline operator Type() const { return get(); }
|
||||
|
||||
inline auto& operator=(const BitField& value) { return set(value.data); }
|
||||
template<typename T> inline auto& operator=(const T& value) { return set(value << Lo); }
|
||||
|
||||
inline auto operator++(int) { Type value = get(); set(data + (1 << Lo)); return value; }
|
||||
inline auto operator--(int) { Type value = get(); set(data - (1 << Lo)); return value; }
|
||||
|
||||
inline auto& operator++() { return set(data + (1 << Lo)); }
|
||||
inline auto& operator--() { return set(data - (1 << Lo)); }
|
||||
|
||||
inline auto& operator &=(const Type value) { return set(data & (value << Lo)); }
|
||||
inline auto& operator |=(const Type value) { return set(data | (value << Lo)); }
|
||||
inline auto& operator ^=(const Type value) { return set(data ^ (value << Lo)); }
|
||||
inline auto& operator<<=(const Type value) { return set(data << value); }
|
||||
inline auto& operator>>=(const Type value) { return set(data >> value); }
|
||||
inline auto& operator +=(const Type value) { return set(data + (value << Lo)); }
|
||||
inline auto& operator -=(const Type value) { return set(data - (value << Lo)); }
|
||||
inline auto& operator *=(const Type value) { return set((get() * value) << Lo); }
|
||||
inline auto& operator /=(const Type value) { return set((get() / value) << Lo); }
|
||||
inline auto& operator %=(const Type value) { return set((get() % value) << Lo); }
|
||||
|
||||
private:
|
||||
enum : uint { Bits = Hi - Lo + 1 };
|
||||
enum : uint { Mask = ((1ull << Bits) - 1) << Lo };
|
||||
Type data;
|
||||
|
||||
inline auto get() const -> Type {
|
||||
return (data & Mask) >> Lo;
|
||||
}
|
||||
|
||||
inline auto set(Type value) -> BitField& {
|
||||
data = (data & ~Mask) | (value & Mask);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct Boolean {
|
||||
inline Boolean() : data(false) {}
|
||||
template<typename T> inline Boolean(const T& value) : data(value) {}
|
||||
|
Reference in New Issue
Block a user