Arrays of enum's packed into bit fields in MSVC++ - c++

Unsing MS Studio 2022 I am trying to pack two items into a union of size 16 bits but I am having problems with the correct syntax.
The first item is an unsigned short int so no problems there. The other is an array of 5 items, all two bits long. So imagine:
enum States {unused, on, off};
// Should be able to store this in a 2 bit field
then I want
States myArray[5];
// Should be able to fit in 10 bits and
// be unioned with my unsigned short
Unfortunatly I am completely failing to work out the correct syntax which leads to my array fitting into 16 bits. Any ideas?

You can't do that. An array is an array, not some packed bits.
What you can do is using manual bit manipulation:
#include <iostream>
#include <cstdint>
#include <bitset>
#include <climits>
enum status {
on = 0x03,
off = 0x01,
unused = 0x00
};
constexpr std::uint8_t status_bit_width = 2;
std::uint16_t encode(status s,std::uint8_t id, std::uint16_t status_vec) {
if(id >= (CHAR_BIT * sizeof(std::uint16_t)) / status_bit_width) {
std::cout << "illegal id" << std::endl;
return status_vec;
}
std::uint8_t bit_value = s;
status_vec |= bit_value << (id*status_bit_width);
return status_vec;
};
int main(void) {
std::uint16_t bits = 0;
bits = encode(on,1,bits);
std::cout << std::bitset<16>(bits) << std::endl;
bits = encode(off,2,bits);
std::cout << std::bitset<16>(bits) << std::endl;
bits = encode(unused,3,bits);
std::cout << std::bitset<16>(bits) << std::endl;
bits = encode(off,4,bits);
std::cout << std::bitset<16>(bits) << std::endl;
bits = encode(off,7,bits);
std::cout << std::bitset<16>(bits) << std::endl;
bits = encode(on,8,bits);
}

Related

How to store Processor Status flags' values with corresponding enum for 6502

I'm working on 6502 emulator in C++ as a part of my thesis. It has 6 registers, most of them just hold values but there's one special - Processor Status. It's 8 bit wide and each bit means a different flag. The best choice for me seemed to make it std::bitset<8> and create a corresponding enum class to map its values to the real bits as follow:
enum class PSFlags : uint8_t
{
Carry = 0,
Zero = 1,
InterruptDisable = 2,
Decimal = 3,
Break = 4,
Unknown = 5,
Overflow = 6,
Negative = 7
};
struct Registers
{
int8_t A;
int8_t X;
int8_t Y;
uint8_t SP;
uint16_t PC;
static constexpr uint8_t PSSize = 8;
std::bitset<PSSize> PS;
constexpr Registers() noexcept :
A(0),
X(0),
Y(0),
SP(0xFF),
PS(0b00100100),
PC(0)
{
}
};
And now, if I want to refer to one of three: size of PS, the flag number or the bitset itself I have:
Registers::PSSize; // size
PSFlags::Carry; // flag number
Registers r; r.PS; // bitset itself
Where every call accesses the value in a very different way. I'd like to have it more consistent, e.g.
Registers::PS::value; // for the bitset itself
Registers::PS::size; // for the size
Registers::PS::flags::Carry; // for the name of flag
Do you have any good ideas on how to achieve such (or similar) consistency without creating some crazy or ugly constructs in the code?
What OP wants (or something acceptable similar) can be achieved using nested structs.
Just for fun, I tried to model what OP intended:
#include <bitset>
struct Registers
{
int8_t A;
int8_t X;
int8_t Y;
uint8_t SP;
static constexpr uint8_t PSSize = 8;
struct PS: std::bitset<PSSize> {
enum Flags {
Carry = 0,
Zero = 1,
InterruptDisable = 2,
Decimal = 3,
Break = 4,
Unknown = 5,
Overflow = 6,
Negative = 7
};
static constexpr unsigned Size = PSSize;
constexpr PS(std::uint8_t value):
std::bitset<PSSize>((unsigned long long)value)
{ }
std::uint8_t value() const { return (std::uint8_t)to_ulong(); }
} PS;
uint16_t PC;
constexpr Registers() noexcept :
A(0),
X(0),
Y(0),
SP(0xFF),
PS(0x24),//PS(0b00100100),
PC(0)
{
}
} r;
A small test to show this in action:
#include <iomanip>
#include <iostream>
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
std::cout << std::hex << std::setfill('0');
DEBUG(std::cout << Registers::PS::Flags::Carry << '\n');
DEBUG(std::cout << r.PS[Registers::PS::Flags::Carry] << '\n');
DEBUG(std::cout << Registers::PS::Flags::InterruptDisable << '\n');
DEBUG(std::cout << r.PS[Registers::PS::Flags::InterruptDisable] << '\n');
DEBUG(std::cout << Registers::PS::Flags::Break << '\n');
DEBUG(std::cout << r.PS[Registers::PS::Flags::Break] << '\n');
DEBUG(std::cout << Registers::PS::Size << '\n');
DEBUG(std::cout << "0x" << std::setw(2) << (unsigned)r.PS.value() << '\n');
// done
return 0;
}
Output:
std::cout << Registers::PS::Flags::Carry << '\n';
0
std::cout << r.PS[Registers::PS::Flags::Carry] << '\n';
0
std::cout << Registers::PS::Flags::InterruptDisable << '\n';
2
std::cout << r.PS[Registers::PS::Flags::InterruptDisable] << '\n';
1
std::cout << Registers::PS::Flags::Break << '\n';
4
std::cout << r.PS[Registers::PS::Flags::Break] << '\n';
0
std::cout << Registers::PS::Size << '\n';
8
std::cout << "0x" << std::setw(2) << (unsigned)r.PS.value() << '\n';
0x24
Note:
About naming the nested struct Registers::PS and the member Registers::PS with same name is I was expecting to work. Though, usually I use uppercase start character for type identifiers and lowercase start characters for variables. Hence, I don't have this issue usually.
As being in doubt about this, I tested the struct Registers against various compilers (though I wouldn't count this as proof against the standard): Compiler Explorer
Deriving from std::containers should be done with care (i.e. better not). Probably for performance reasons, none of the std::containers provides a virtual destructor with the respective consequences. In the above code, this shouldn't be a problem.
6502 reminded me to the Commodore 64 where I made my first attempts on (although the C64 had the even more modern 6510 CPU). However, that's looong ago... ;-)

Why are the bit patterns not matching with the use of std::bitset [duplicate]

This question already has answers here:
Is the order of initialization guaranteed by the standard?
(5 answers)
Closed 3 years ago.
While I was unit testing my class and its constructors I noticed something peculiar with my outputs.
#include <bitset>
#include <cstdint>
#include <iostream>
#include <vector>
typedef std::uint8_t u8;
typedef std::uint16_t u16;
typedef std::uint32_t u32;
typedef std::uint64_t u64;
struct Reg8 {
std::bitset<8> bits;
u8 value;
Reg8() : value{0}, bits{value} {}
explicit Reg8( u8 val) : value{val}, bits{value} {}
explicit Reg8(u16 val) : value{static_cast<u8>(val)}, bits{value} {}
explicit Reg8(u32 val) : value{static_cast<u8>(val)}, bits{value} {}
explicit Reg8(u64 val) : value{static_cast<u8>(val)}, bits{value} {}
};
int main() {
u8 val8 = 24;
u16 val16 = 24;
u32 val32 = 24;
u64 val64 = 24;
Reg8 r8a(val8);
Reg8 r8b(val16);
Reg8 r8c(val32);
Reg8 r8d(val64);
std::cout << "Reg8(u8) r8a value = " << +r8a.value << '\n';
std::cout << "Reg8(u8) r8a bits = " << r8a.bits << "\n\n";
std::cout << "Reg8(u16) r8b value = " << +r8b.value << '\n';
std::cout << "Reg8(u16) r8b bits = " << r8b.bits << "\n\n";
std::cout << "Reg8(u32) r8c value = " << +r8c.value << '\n';
std::cout << "Reg8(u32) r8c bits = " << r8c.bits << "\n\n";
std::cout << "Reg8(u64) r8d value = " << +r8d.value << '\n';
std::cout << "Reg8(u64) r8d bits = " << r8d.bits << "\n\n";
std::bitset<8> bitsA{ val8 };
std::cout << "bits value = " << bitsA.to_ullong() << '\n';
std::cout << "bits binary = " << bitsA << "\n\n";
std::bitset<8> bitsB{ val16 };
std::cout << "bits value = " << bitsB.to_ullong() << '\n';
std::cout << "bits binary = " << bitsB << "\n\n";
std::bitset<8> bitsC{ val32 };
std::cout << "bits value = " << bitsC.to_ullong() << '\n';
std::cout << "bits binary = " << bitsC << "\n\n";
std::bitset<8> bitsD{ val64 };
std::cout << "bits value = " << bitsD.to_ullong() << '\n';
std::cout << "bits binary = " << bitsD << "\n\n";
return EXIT_SUCCESS;
}
Here is my output coming from a little endian machine and
Intel Quad Core Extreme running Windows 7 x64 and using
Visual Studio 2017 CE in x64 debug mode with compiler language options set to c++ latest draft standard. All other compiler flags - optimizations etc Visual Studio's defaults.
Reg8(u8) r8a value = 24
Reg8(u8) r8a bits = 11001100
Reg8(u16) r8b value = 24
Reg8(u16) r8b bits = 11001100
Reg8(u32) r8c value = 24
Reg8(u32) r8c bits = 11001100
Reg8(u64) r8d value = 24
Reg8(u64) r8d bits = 11001100
bits value = 24
bits binary = 00011000
bits value = 24
bits binary = 00011000
bits value = 24
bits binary = 00011000
bits value = 24
bits binary = 00011000
So why do the bit patterns from the class construction not match that of the ones declared in main?
I'm using the same variable types and values to initialize the bitset that is in main as well as the one in my class yet their bit patterns don't match up. All of the ones in the class are the same, all the ones outside of the class are the same.
What I'm expecting to see and my desired values should be that of the ones seen in main. When I look at the bottom half of the output these bitset variables in main have the value of 24
and their bit patterns match that of 24 for 8 bits.
0001 1000 = 24
However the bit pattern that is stored in the bitset within my class does not match but contains the appropriate value. The bitset stored in my class has bitt pattern
1100 1100 ... doesn't = 24 in binary
What is going on here?
Remember that a member initialization list initializes in declaration order. Meaning that for:
struct Reg8 {
std::bitset<8> bits; // <- first to be initialized in mem-init-list
u8 value; // <- second
};
And taking this constructor as an example:
explicit Reg8(u16 val) : value{static_cast<u8>(val)}, bits{value} {}
The order of the initialization list doesn't matter. bits comes before value in the declaration so bits will be initialized first. It will be initialized to value which is still uninitialized as value{static_cast<u8>(val)} comes after the initialization of bits.
To fix this, swap the declaration around:
struct Reg8 {
u8 value;
std::bitset<8> bits;
};
Side note: You're missing a stdint include in your code.

Why can't I pack these ints together?

I have the following code. The goal is to combine the two uint32_ts into a single uint64_t and then retrieve the values.
#include <iostream>
#include <cstdint>
int main()
{
uint32_t first = 5;
uint32_t second = 6;
uint64_t combined = (first << 32) | second;
uint32_t firstR = combined >> 32;
uint32_t secondR = combined & 0xffffffff;
std::cout << "F: " << firstR << " S: " << secondR << std::endl;
}
It outputs
F: 0 S: 7
How do I successfully retrieve the values correctly?
first is a 32-bit type and you bit-shift it by 32 bits. This is technically undefined behaviour, but probably the most likely outcome is that the result of the expression is 0. You need to cast it to a larger type before bit-shifting it.
uint64_t combined = (static_cast<uint64_t>(first) << 32) | second;
When you perform first << 32, you are shifting 32 bits within the space of 32 bits, so there are no bits remaining after the shift. The result of the shift is 0. You need to convert the first value to 64 bits before you shift it:
uint64_t combined = (uint64_t(first) << 32) | second;
As per the comments:
#include <iostream>
#include <cstdint>
int main()
{
uint32_t first = 5;
uint32_t second = 6;
uint64_t combined = (uint64_t(first) << 32) | second;
uint32_t firstR = combined >> 32;
uint32_t secondR = combined & 0xffffffff;
std::cout << "F: " << firstR << " S: " << secondR << std::endl;
}
The bit manipulation operators return a type of the first parameter. So you need to cast it to uint64_t in order for it to have room for the second value.

How to store randomly generated unsigned int numbers in a bitset

I have a bitset in which I need to store a # of randomly generated integers (store its bit representation of course). So, the thing is that I am confuse on how to do that.
i.e suppose that I generate the integers (all unsigned int) 8, 15 , 20, one at a time. How can I store the recently generated integer in my existing bit set.
Say that I start by generating "8" and store in the bitset, then I generate "15" and store it in the bitset.
I don't know or don't understand how to store those values within the bitset.
Note: I know in advance the size of the bitset, the size is based on the number of integers that I am going to generate, and that I know too. So, at the end what I need is a bitset with all the bits set matching the bits of all the generated integers.
I'll Appreciate your help.
How can I store the recently generated integer in my existing bit set.
You can generate a temporary bitset form the integer and then assign values between the two bitsets.
Example program:
#include <iostream>
#include <bitset>
#include <cstdlib>
int main()
{
const int size = sizeof(int)*8;
std::bitset<2*size> res;
std::bitset<size> res1(rand());
std::bitset<size> res2(rand());
for ( size_t i = 0; i < size; ++i )
{
res[i] = res1[i];
res[size+i] = res2[i];
}
std::cout << "res1: " << res1 << std::endl;
std::cout << "res2: " << res2 << std::endl;
std::cout << "res: " << res << std::endl;
return 0;
}
Output:
res1: 01101011100010110100010101100111
res2: 00110010011110110010001111000110
res: 0011001001111011001000111100011001101011100010110100010101100111
Update
A function to set the bitset values given an integer can be used to avoid the cost of creating temporary bitsets.
#include <iostream>
#include <bitset>
#include <cstdlib>
#include <climits>
const int size = sizeof(int)*8;
void setBitsetValue(std::bitset<2*size>& res,
int num,
size_t bitsetIndex,
size_t numIndex)
{
if ( numIndex < size )
{
res[bitsetIndex] = (num >> numIndex) & 0x1;
setBitsetValue(res, num, bitsetIndex+1, numIndex+1);
}
}
int main()
{
std::bitset<2*size> res;
int num1 = rand()%INT_MAX;
int num2 = rand()%INT_MAX;
std::bitset<size> res1(num1);
std::bitset<size> res2(num2);
std::cout << "res1: " << res1 << std::endl;
std::cout << "res2: " << res2 << std::endl;
setBitsetValue(res, num1, 0, 0);
setBitsetValue(res, num2, size, 0);
std::cout << "res: " << res << std::endl;
return 0;
}

How to initialize bitfields with a C++ Constructor?

First off, I’m not concerned with portability, and can safely assume that the endianness will not change. Assuming I read a hardware register value, I would like to overlay that register value over bitfields so that I can refer to the individual fields in the register without using bit masks.
EDIT: Fixed problems pointed out by GMan, and adjusted the code so it's clearer for future readers.
SEE: Anders K. & Michael J's answers below for a more eloquent solution.
#include <iostream>
/// \class HardwareRegister
/// Abstracts out bitfields in a hardware register.
/// \warning This is non-portable code.
class HardwareRegister
{
public:
/// Constructor.
/// \param[in] registerValue - the value of the entire register. The
/// value will be overlayed onto the bitfields
/// defined in this class.
HardwareRegister(unsigned long registerValue = 0)
{
/// Lots of casting to get registerValue to overlay on top of the
/// bitfields
*this = *(reinterpret_cast<HardwareRegister*>(&registerValue));
}
/// Bitfields of this register.
/// The data type of this field should be the same size as the register
/// unsigned short for 16 bit register
/// unsigned long for 32 bit register.
///
/// \warning Remember endianess! Order of the following bitfields are
/// important.
/// Big Endian - Start with the most signifcant bits first.
/// Little Endian - Start with the least signifcant bits first.
unsigned long field1: 8;
unsigned long field2:16;
unsigned long field3: 8;
}; //end class Hardware
int main()
{
unsigned long registerValue = 0xFFFFFF00;
HardwareRegister testRegister(registerValue);
// Prints out for little endianess machine
// Field 1 = 0
// Field 2 = 65535
// Field 3 = 255
std::cout << "Field 1 = " << testRegister.field1 << std::endl;
std::cout << "Field 2 = " << testRegister.field2 << std::endl;
std::cout << "Field 3 = " << testRegister.field3 << std::endl;
}
don't do this
*this = *(reinterpret_cast<HW_Register*>(&registerValue));
the 'this' pointer shouldn't be fiddled with in that way:
HW_Register reg(val)
HW_Register *reg = new HW_Register(val)
here 'this' is in two different places in memory
instead have an internal union/struct to hold the value, that way its easy to convert
back and forth (since you are not interested in portability)
e.g.
union
{
struct {
unsigned short field1:2;
unsigned short field2:4;
unsigned short field3:2;
...
} bits;
unsigned short value;
} reg
edit: true enough with the name 'register'
Bitfields don't work that way. You can't assign a scalar value to a struct full of bitfields. It looks like you already know this since you used reinterpret_cast, but since reinterpret_cast isn't guaranteed to do very much, it's just rolling the dice.
You need to encode and decode the values if you want to translate between bitfield structs and scalars.
HW_Register(unsigned char value)
: field1( value & 3 ),
field2( value >> 2 & 3 ),
field3( value >> 4 & 7 )
{}
Edit: The reason you don't get any output is that the ASCII characters corresponding to the numbers in the fields are non-printing. Try this:
std::cout << "Field 1 = " << (int) testRegister.field1 << std::endl;
std::cout << "Field 2 = " << (int) testRegister.field2 << std::endl;
std::cout << "Field 3 = " << (int) testRegister.field3 << std::endl;
Try this:
class HW_Register
{
public:
HW_Register(unsigned char nRegisterValue=0)
{
Init(nRegisterValue);
}
~HW_Register(void){};
void Init(unsigned char nRegisterValue)
{
nVal = nRegisterValue;
}
unsigned Field1() { return nField1; }
unsigned Field2() { return nField2; }
unsigned Field3() { return nField3; }
private:
union
{
struct
{
unsigned char nField1:2;
unsigned char nField2:4;
unsigned char nField3:2;
};
unsigned char nVal;
};
};
int main()
{
unsigned char registerValue = 0xFF;
HW_Register testRegister(registerValue);
std::cout << "Field 1 = " << testRegister.Field1() << std::endl;
std::cout << "Field 2 = " << testRegister.Field2() << std::endl;
std::cout << "Field 3 = " << testRegister.Field3() << std::endl;
return 0;
}
HW_Register(unsigned char registerValue) : field1(0), field2(0), field3(0)