#pragma once #include #include #include #define REGISTER1( NAME ) \ private: \ alignas(4) std::array NAME##_storage = {{0,0,0,0}}; \ public: \ uint32_t& e##NAME##x() { \ return *reinterpret_cast(NAME##_storage.data()); \ } \ \ uint16_t& NAME##x() { \ return *reinterpret_cast(NAME##_storage.data()); \ } \ \ uint8_t& NAME##h() { \ return *reinterpret_cast(NAME##_storage.data()+1); \ } \ \ uint8_t& NAME##l() { \ return *reinterpret_cast(NAME##_storage.data()); \ } \ #define REGISTER2( NAME ) \ private: \ alignas(4) std::array NAME##_storage = {{0,0,0,0}}; \ public: \ uint32_t& e##NAME() { \ return *reinterpret_cast(NAME##_storage.data()); \ } \ \ uint16_t& NAME() { \ return *reinterpret_cast(NAME##_storage.data()); \ } \ #define SEGMENT_REGISTER( NAME ) \ private: \ alignas(2) std::array NAME##_storage = {{0,0}}; \ public: \ uint16_t& NAME() { \ return *reinterpret_cast(NAME##_storage.data()); \ } \ #define EFLAGS \ private: \ alignas(8) std::bitset<32> storage = 2; \ public: \ using ref = std::bitset<32>::reference; \ ref cf() { return storage[0]; } \ ref pf() { return storage[2]; } \ ref af() { return storage[4]; } \ ref zf() { return storage[6]; } \ ref sf() { return storage[7]; } \ ref tf() { return storage[8]; } \ ref intf() { return storage[9]; } \ ref df() { return storage[10]; } \ ref of() { return storage[11]; } \ /*TODO: iopl*/ \ ref nt() { return storage[14]; } \ ref rf() { return storage[16]; } \ ref vm() { return storage[17]; } \ ref ac() { return storage[18]; } \ ref vif() { return storage[19]; } \ ref vip() { return storage[20]; } \ ref id() { return storage[21]; } \ struct CpuState { REGISTER2(ip) REGISTER1(a) REGISTER1(c) REGISTER1(d) REGISTER1(b) REGISTER2(sp) REGISTER2(bp) REGISTER2(si) REGISTER2(di) SEGMENT_REGISTER(cs) SEGMENT_REGISTER(ds) SEGMENT_REGISTER(es) SEGMENT_REGISTER(ss) SEGMENT_REGISTER(fs) SEGMENT_REGISTER(gs) EFLAGS }; #undef REGISTER1 #undef REGISTER2 #undef SEGMENT_REGISTER #undef EFLAGS std::ostream& operator<<(std::ostream& os, CpuState& cpu);