My bitfield below represents the 7 status flags for the 6502 CPU. I am trying to emulate the instruction php
, which pushes a copy of the status flags onto the stack.
struct Flags {
uint8_t C: 1;
uint8_t Z: 1;
uint8_t I: 1;
uint8_t D: 1;
uint8_t V: 1;
uint8_t N: 1;
uint8_t B: 2;
};
I need a way to pack each field into a single-byte datatype like uint8_t
so that I can push it to the stack. However, the code below gives this error: operand of type 'struct Flags' where arithmetic or pointer type is required
. How do I resolve this problem?
int main() {
struct Flags f = {0, 0, 0, 0, 1, 0, 0};
uint8_t f_as_byte = (uint8_t) f;
}
The problem with bitfields is that it is implementation-defined in what order the bits are laid out. This could be rather unacceptable for a 6502 emulator. The PHP
command must push the status word in the exact desired format, i.e. something like
uint8_t as_state = f.N << 7 | f.V << 6 | f.B << 4 | f.D << 3 | f.I << 2 | f.Z << 1 | f.C;
Your layout is wrong, the B
member is in wrong position. All in all considering the complex code like one above, maybe it would be easier to just consider the flags as a single uint8_t
and have access macros for it, something like
#define FLAG_N 0x80U
...
#define FLAG_C 0x1U
#define SET_FLAG(flag_var, flag) ((flag_var) |= (flag))
#define CLR_FLAG(flag_var, flag) ((flag_var) &= ~(flag))
#define GET_FLAG(flag_var, flag) ((_Bool)((flag_var) & (flag)))
uint8_t flags = 0;
SET_FLAG(flags, FLAG_C);
if (GET_FLAG(flags, FLAG_N)) { ... }
That way the PHP
instruction can be coded to just push flags
as is...
Except that the B
flag that is pushed is not a flag from the status register...