Here is an answer that will work, be portable, and not cause undefined behavior on any compiler and be optimized efficiently enough:
struct instruction { typedef unsigned int uint_t; explicit instruction(uint_t val) : val_(val) {} instruction(uint_t op_code, uint_t reg_dest, uint_t reg_s1, uint_t offset) : val_((op_code & 0x3fu << 26) | (reg_dest & 0x1fu << 21) | (reg_s1 & 0x1fu << 16) | (offset & 0xffffu)) { } uint_t op_code() const { return (val_ >> 26) & 0x3fu; } void op_code(uint_t newval) { val_ = (newval & 0x3fu << 26) | (val_ & 0x3ffffffu); } uint_t reg_dest() const { return (val_ >> 21) & 0x1fu; } void reg_dest(uint_t newval) { val_ = (newval & 0x1fu << 21) | (val_ & 0xfc1fffffu); } uint_t reg_s1() const { return (val_ >> 16) & 0x1fu; } void reg_s1(uint_t newval) { val_ = (newval & 0x1fu) << 16) | (val_ & 0xffe0ffffu); } uint_t offset() const { return (val_ >> 16) & 0xffffu; } void offset(uint_t newval) const { val_ = (newval & 0xffffu) | (val & 0xffff0000u); } uint_t &int_ref() { return val_; } uint_t int_ref() const { return val_; } private: uint_t val_; };
This allows access to all bit fields with very convenient notation. I think this is also a POD, which allows you to use it in several interesting ways. And a good compiler will do a pretty decent job of optimizing bit-sorting operations, especially if you have several calls to convenience functions in a string.
This is almost as good as having an overlay bit field. Firstly, this is a little more to determine.
Also, I changed the type to unsigned int
, because if you play with bits, you really need just a represented number without a signed bit or something like that. Ideally, you should include the <cstdint>
header and use ::std::uint32_t
or something in the typedef at the top.
Omnifarious
source share