bsnes/nall/bit-field.hpp

143 lines
5.7 KiB
C++
Raw Normal View History

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.
2016-06-08 22:26:35 +00:00
#pragma once
Update to v106r77 release. byuu says: So this turned out to be a rather unproductive ten-hour rabbit hole, but ... I reworked nall/primitives.hpp a lot. And because the changes are massive, testing of this WIP for regressions is critically important. I really can't stress that enough, we're almost certainly going to have some hidden regressions here ... We now have a nall/primitives/ subfolder that splits up the classes into manageable components. The bit-field support is now shared between both Natural and Integer. All of the assignment operator overloads are now templated and take references instead of values. Things like the GSU::Register class are non-copyable on account of the function<> object inside of it, and previously only operator= would work with classes like that. The big change is nall/primitives/operators.hpp, which is a really elaborate system to compute the minimum number of bits needed for any operation, and to return a Natural<T> or Integer<T> when one or both of the arguments are such a type. Unfortunately, it doesn't really work yet ... Kirby's Dream Land 3 breaks if we include operators.hpp. Zelda 3 runs fine with this, but I had to make a huge amount of core changes, including introducing a new ternary(bool, lhs, rhs) function to nall/algorithm to get past Natural<X> and Natural<Y> not being equivalent (is_integral types get a special exemption to ternary ?: type equivalence, yet it's impossible to simulate with our own classes, which is bullshit.) The horrifying part is that ternary() will evaluate both lhs and rhs, unlike ?: I converted some of the functions to test ? uint(x) : uint(y), and others to ternary(test, x, y) ... I don't have a strong preference either way yet. But the part where things may have gotten broken is in the changes to where ternary() was placed. Some cases like in the GBA PPU renderer, it was rather unclear the order of evaluations, so I may have made a mistake somewhere. So again, please please test this if you can. Or even better, look over the diff. Longer-term, I'd really like the enable nall/primitives/operators.hpp, but right now I'm not sure why Kirby's Dream Land 3 is breaking. Help would be appreciated, but ... it's gonna be really complex and difficult to debug, so I'm probably gonna be on my own here ... sigh.
2019-01-13 06:25:14 +00:00
#include <nall/primitives.hpp>
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.
2016-06-08 22:26:35 +00:00
namespace nall {
template<typename Type, uint Bit> struct BooleanBitField {
enum : uint { bit = Bit };
enum : uint { mask = 1ull << bit };
using type = Type;
using utype = typename std::make_unsigned<type>::type;
static_assert(bit < sizeof(type) * 8, "");
inline BooleanBitField() = default;
inline BooleanBitField(const BooleanBitField& value) { set(value.get()); }
template<typename T> inline BooleanBitField(const bool value) { set(value); }
inline operator bool() const { return get(); }
inline auto& operator=(const BooleanBitField& 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); }
inline auto raise() { return get() == 0 ? set(1), true : false; }
inline auto lower() { return get() == 1 ? set(0), true : false; }
inline auto& invert() { return set(get() ^ 1); }
private:
utype data;
inline auto get() const -> bool {
return data & mask;
}
inline auto set(bool value) -> BooleanBitField& {
return data = (data & ~mask) | (value << bit), *this;
}
};
template<typename Type, uint Lo, uint Hi> struct NaturalBitField {
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.
2016-06-08 22:26:35 +00:00
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 };
using type = Type;
using utype = typename std::make_unsigned<type>::type;
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.
2016-06-08 22:26:35 +00:00
static_assert(hi < sizeof(type) * 8, "");
inline NaturalBitField() = default;
inline NaturalBitField(const NaturalBitField& value) { set(value.data); }
template<typename T> inline NaturalBitField(const T& value) { set(value << lo); }
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.
2016-06-08 22:26:35 +00:00
inline explicit operator bool() const { return data & mask; }
inline operator utype() const { return get(); }
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.
2016-06-08 22:26:35 +00:00
inline auto& operator=(const NaturalBitField& value) { return set(value.data); }
Update to v106r77 release. byuu says: So this turned out to be a rather unproductive ten-hour rabbit hole, but ... I reworked nall/primitives.hpp a lot. And because the changes are massive, testing of this WIP for regressions is critically important. I really can't stress that enough, we're almost certainly going to have some hidden regressions here ... We now have a nall/primitives/ subfolder that splits up the classes into manageable components. The bit-field support is now shared between both Natural and Integer. All of the assignment operator overloads are now templated and take references instead of values. Things like the GSU::Register class are non-copyable on account of the function<> object inside of it, and previously only operator= would work with classes like that. The big change is nall/primitives/operators.hpp, which is a really elaborate system to compute the minimum number of bits needed for any operation, and to return a Natural<T> or Integer<T> when one or both of the arguments are such a type. Unfortunately, it doesn't really work yet ... Kirby's Dream Land 3 breaks if we include operators.hpp. Zelda 3 runs fine with this, but I had to make a huge amount of core changes, including introducing a new ternary(bool, lhs, rhs) function to nall/algorithm to get past Natural<X> and Natural<Y> not being equivalent (is_integral types get a special exemption to ternary ?: type equivalence, yet it's impossible to simulate with our own classes, which is bullshit.) The horrifying part is that ternary() will evaluate both lhs and rhs, unlike ?: I converted some of the functions to test ? uint(x) : uint(y), and others to ternary(test, x, y) ... I don't have a strong preference either way yet. But the part where things may have gotten broken is in the changes to where ternary() was placed. Some cases like in the GBA PPU renderer, it was rather unclear the order of evaluations, so I may have made a mistake somewhere. So again, please please test this if you can. Or even better, look over the diff. Longer-term, I'd really like the enable nall/primitives/operators.hpp, but right now I'm not sure why Kirby's Dream Land 3 is breaking. Help would be appreciated, but ... it's gonna be really complex and difficult to debug, so I'm probably gonna be on my own here ... sigh.
2019-01-13 06:25:14 +00:00
template<typename T> inline auto& operator=(T value) { return set(value << lo); }
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.
2016-06-08 22:26:35 +00:00
inline auto operator++(int) { utype value = get(); set(data + (1 << lo)); return value; }
inline auto operator--(int) { utype value = get(); set(data - (1 << lo)); return value; }
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.
2016-06-08 22:26:35 +00:00
inline auto& operator++() { return set(data + (1 << lo)); }
inline auto& operator--() { return set(data - (1 << lo)); }
inline auto& operator &=(const utype value) { return set(data & (value << lo)); }
inline auto& operator |=(const utype value) { return set(data | (value << lo)); }
inline auto& operator ^=(const utype value) { return set(data ^ (value << lo)); }
inline auto& operator<<=(const utype value) { return set((data & mask) << value); }
inline auto& operator>>=(const utype value) { return set((data & mask) >> value); }
inline auto& operator +=(const utype value) { return set(data + (value << lo)); }
inline auto& operator -=(const utype value) { return set(data - (value << lo)); }
inline auto& operator *=(const utype value) { return set((get() * value) << lo); }
inline auto& operator /=(const utype value) { return set((get() / value) << lo); }
inline auto& operator %=(const utype value) { return set((get() % value) << lo); }
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.
2016-06-08 22:26:35 +00:00
private:
utype data;
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.
2016-06-08 22:26:35 +00:00
inline auto get() const -> utype {
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.
2016-06-08 22:26:35 +00:00
return (data & mask) >> lo;
}
inline auto set(utype value) -> NaturalBitField& {
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.
2016-06-08 22:26:35 +00:00
return data = (data & ~mask) | (value & mask), *this;
}
};
template<typename Type, uint Lo, uint Hi> struct IntegerBitField {
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 };
using type = Type;
using stype = typename std::make_signed<type>::type;
using utype = typename std::make_unsigned<type>::type;
static_assert(hi < sizeof(type) * 8, "");
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.
2016-06-08 22:26:35 +00:00
inline IntegerBitField() = default;
inline IntegerBitField(const IntegerBitField& value) { set(value.get()); }
template<typename T> inline IntegerBitField(const T& value) { set(value); }
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.
2016-06-08 22:26:35 +00:00
inline explicit operator bool() const { return data & mask; }
inline operator stype() const { return get(); }
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.
2016-06-08 22:26:35 +00:00
inline auto& operator=(const IntegerBitField& value) { return set(value.get()); }
template<typename T> inline auto& operator=(const T& value) { return set(value); }
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.
2016-06-08 22:26:35 +00:00
inline auto operator++(int) { stype value = get(); set(value + 1); return value; }
inline auto operator--(int) { stype value = get(); set(value - 1); return value; }
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.
2016-06-08 22:26:35 +00:00
inline auto& operator++() { return set(get() + 1); }
inline auto& operator--() { return set(get() - 1); }
inline auto& operator &=(const stype value) { return set(get() & value); }
inline auto& operator |=(const stype value) { return set(get() | value); }
inline auto& operator ^=(const stype value) { return set(get() ^ value); }
inline auto& operator<<=(const stype value) { return set(get() << value); }
inline auto& operator>>=(const stype value) { return set(get() >> value); }
inline auto& operator +=(const stype value) { return set(get() + value); }
inline auto& operator -=(const stype value) { return set(get() - value); }
inline auto& operator *=(const stype value) { return set(get() * value); }
inline auto& operator /=(const stype value) { return set(get() / value); }
inline auto& operator %=(const stype value) { return set(get() % value); }
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.
2016-06-08 22:26:35 +00:00
private:
utype data;
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.
2016-06-08 22:26:35 +00:00
inline auto get() const -> stype {
enum : utype { b = 1ull << (bits - 1) };
enum : utype { m = b * 2 - 1 };
return ((((data & mask) >> lo) & m) ^ b) - b;
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.
2016-06-08 22:26:35 +00:00
}
inline auto set(utype value) -> IntegerBitField& {
return data = (data & ~mask) | ((value << lo) & mask), *this;
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.
2016-06-08 22:26:35 +00:00
}
};
}