#pragma once #include #include #include #include #include enum ctlreg { #define REG(N) N, #include "ctlreg.def" #undef REG NUM_CTLREGS, }; const char * const ctlreg_names[] = { #define REG(N) #N, #include "ctlreg.def" #undef REG }; const std::map ctlreg_map = { #define REG(N) { #N, N }, #include "ctlreg.def" #undef REG }; // FLAGS and FLAGS_SAVED static constexpr unsigned int FLAG_DF_SHIFT = 0; static constexpr std::uint_fast32_t FLAG_DF = 07 << FLAG_DF_SHIFT; static constexpr unsigned int FLAG_IF_SHIFT = 3; static constexpr std::uint_fast32_t FLAG_IF = 07 << FLAG_IF_SHIFT; // In FLAGS this is IFB, not IF static constexpr std::uint_fast32_t FLAG_USER_MODE = 1 << 6; static constexpr std::uint_fast32_t FLAG_INT_ENABLE = 1 << 7; static constexpr std::uint_fast32_t FLAG_INT_INHIBIT = 1 << 8; static constexpr std::uint_fast32_t FLAG_INT_REQUEST = 1 << 9; static constexpr std::uint_fast32_t FLAG_GREATER_THAN = 1 << 10; static constexpr std::uint_fast32_t FLAG_INT_ENABLE_DELAY = 1 << 12; // n.b. this is not a "visible" flag // TT_BITS static constexpr std::uint_fast32_t TTI_FLAG = 1 << 0; static constexpr std::uint_fast32_t TTO_TX = 1 << 1; static constexpr std::uint_fast32_t TTO_FLAG = 1 << 2; static constexpr unsigned int TTI_DATA_SHIFT = 8; static constexpr std::uint_fast32_t TTI_DATA = 0xff << TTI_DATA_SHIFT; static constexpr unsigned int TTO_DATA_SHIFT = 16; static constexpr std::uint_fast32_t TTO_DATA = 0xff << TTO_DATA_SHIFT; // TT_FLAGS static constexpr std::uint_fast32_t TTF_INT_ENABLE = 1 << 0; static constexpr std::uint_fast32_t TTF_STATUS_ENABLE = 1 << 1; struct instruction_context { // Known statically at decode time bool need_indirect_load = false; // final_address = mem[init_address] bool need_autoinc_store = false; // mem[init_address] += 1 bool need_exec_load = false; // data = mem[final_address] bool need_read_acc = false; // acc = %acc bool need_read_link = false; // link = %link bool need_read_mq = false; // mq = %mq std::optional read_ctlreg; // ctlval = %[read_ctlreg] bool need_write_acc = false; // %acc = acc bool need_write_link = false; // %link = link bool need_write_mq = false; // %mq = mq std::optional write_ctlreg; // %[write_ctlreg] = ctlval bool need_exec_store = false; // mem[final_address] = data bool possibly_redirects = false; // %pc = next_pc std::function ef; void execute() { ef(*this); } // May change over the lifetime of the instruction execution unsigned int next_pc; // includes IF std::optional init_address; // includes DF std::optional final_address; // includes DF std::optional ctlval; // control registers may be larger than 16 bits (e.g. TT_BITS) std::optional data; std::optional acc; std::optional link; std::optional mq; }; instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned int bits, bool interrupt);