#pragma once #include #include enum ctlreg { DATA_INSTRUCTION_FIELD_BUFFER, // (df << 3) | if_buffer DATA_INSTRUCTION_FIELD_SAVED, // (df_saved << 3) | if_saved HALTED, INT_ENABLE, // (int_enable_delay << 1) | int_enable INT_PENDING, // only meaningful if interrupts disabled TT_BITS, // see below TT[IO]_* consts TT_INPUT_INT_ENABLE, TT_OUTPUT_INT_ENABLE, NUM_CTLREGS, }; // TT_BITS static constexpr unsigned int TTI_FLAG = 1 << 0; static constexpr unsigned int TTO_TX = 1 << 1; static constexpr unsigned int TTO_FLAG = 1 << 2; static constexpr unsigned int TTO_FLAG_OLD = 1 << 3; static constexpr unsigned int TTI_DATA_SHIFT = 8; static constexpr unsigned int TTO_DATA_SHIFT = 16; static constexpr unsigned int TTI_DATA = 0xff << TTI_DATA_SHIFT; static constexpr unsigned int TTO_DATA = 0xff << TTO_DATA_SHIFT; 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; std::optional data; std::optional acc; std::optional link; std::optional mq; }; instruction_context decode(unsigned int df, unsigned int pc, unsigned int bits, bool interrupt);