From 82cc71261d3d32012d33d3bebe56ca5e3b0bcdbd Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sun, 2 Oct 2022 15:32:49 -0700 Subject: Initial commit. --- isa/checker.cpp | 44 ++++++++++++++++++++++++++ isa/decode.cpp | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ isa/isa.h | 44 ++++++++++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 isa/checker.cpp create mode 100644 isa/decode.cpp create mode 100644 isa/isa.h (limited to 'isa') diff --git a/isa/checker.cpp b/isa/checker.cpp new file mode 100644 index 0000000..cd802a8 --- /dev/null +++ b/isa/checker.cpp @@ -0,0 +1,44 @@ +#include + +#include "isa/isa.h" + +void checker::execute() { + assert(!halt); + auto int_enable_delay = ctlregs[ctlreg::INT_ENABLE] >> 1; + if (ctlregs[ctlreg::INT_ENABLE] & 1) { + // check for interrupt + } + ctlregs[ctlreg::INT_ENABLE] = (int_enable_delay << 1) | int_enable_delay; + inst = decode(ctlregs[ctlreg::DATA_INSTRUCTION_FIELD_BUFFER], + pc, + mem.fetch(pc)); + auto next_pc = inst.next_pc; + if (inst.need_indirect_load) { + auto addr = mem.fetch(inst.init_address.value()); + if (inst.need_autoinc_store) + mem.store(*inst.init_address, (addr + 1) & 07777); + inst.final_address = addr; + } else { + assert(!inst.need_autoinc_store); + } + if (inst.need_exec_load) + inst.data = mem.fetch(inst.final_address.value()); + if (inst.need_read_acc) + inst.acc = acc; + if (inst.need_read_link) + inst.link = link; + if (inst.read_ctlreg.has_value()) + inst.ctlval = ctlregs[*inst.read_ctlreg]; + inst.execute(); + if (inst.need_write_acc) + acc = inst.acc.value(); + if (inst.need_write_link) + link = inst.link.value(); + if (inst.write_ctlreg.has_value()) + ctlregs[*inst.write_ctlreg] = inst.ctlval.value(); + if (inst.need_exec_store) + mem.store(inst.final_address.value(), inst.data.value()); + assert(inst.next_pc == next_pc || inst.possibly_redirects); + pc = inst.next_pc; + halt = inst.halt; +} diff --git a/isa/decode.cpp b/isa/decode.cpp new file mode 100644 index 0000000..8a85d41 --- /dev/null +++ b/isa/decode.cpp @@ -0,0 +1,96 @@ +#include + +#include "isa/isa.h" + +instruction_context decode(unsigned int dfifb, unsigned int pc, unsigned int bits) +{ + instruction_context inst; + + auto df = dfifb >> 3; + auto ifb = dfifb & 00007; + + inst.next_pc = (pc & ~07777) | ((pc + 1) & 07777); + + switch (bits >> 9) { + case 0: // AND + inst.need_exec_load = true; + inst.need_read_acc = true; + inst.need_write_acc = true; + inst.ef = [](auto &ctx) { + ctx.acc = ctx.acc.value() & ctx.data.value(); + }; + break; + case 1: // TAD + inst.need_exec_load = true; + inst.need_read_acc = true; + inst.need_read_link = true; + inst.need_write_acc = true; + inst.need_write_link = true; + inst.ef = [](auto &ctx) { + unsigned int sum = (ctx.link.value() << 12) + ctx.acc.value() + ctx.data.value(); + ctx.link = (sum >> 12) & 1; + ctx.acc = sum & 07777; + }; + break; + case 2: // ISZ + inst.need_exec_load = true; + inst.need_exec_store = true; + inst.possibly_redirects = true; + inst.ef = [](auto &ctx) { + ctx.data = (ctx.data.value() + 1) & 07777; + if (*ctx.data) + ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777); + }; + break; + case 3: // DCA + inst.need_read_acc = true; + inst.need_write_acc = true; + inst.need_exec_store = true; + inst.ef = [](auto &ctx) { + ctx.data = ctx.acc.value(); + ctx.acc = 0; + }; + break; + case 4: // JMS + inst.need_exec_store = true; + inst.possibly_redirects = true; + inst.ef = [ifb](auto &ctx) { + ctx.data = ctx.next_pc; + ctx.next_pc = (ifb << 12) | ((ctx.final_address.value() + 1) & 07777); + }; + break; + case 5: // JMP + inst.possibly_redirects = true; + inst.ef = [ifb](auto &ctx) { + ctx.next_pc = (ifb << 12) | (ctx.final_address.value() & 07777); + }; + break; + case 6: // IOT + inst.ef = [bits](auto &ctx) { + assert(false); + }; + break; + case 7: // OPR + inst.ef = [bits](auto &ctx) { + assert(false); + }; + break; + } + + // Instructions with memory operands may be direct or indirect + if (inst.need_exec_load || inst.need_exec_store || inst.possibly_redirects) { + auto addr = (df << 12) | ((bits & 00200) ? (next_pc & 07600) : 0) | (bits & 00177); + if (bits & 00400) { + inst.need_indirect_load = true; + inst.init_address = addr; + } else { + inst.final_address = addr; + } + } + + // Non-jump indirect memory operands may be autoincrementing depending on operand bits + if (!inst.possibly_redirects && inst.need_indirect_load && ((bits & 00170) == 00010)) + inst.need_autoinc_store = true; + + return inst; +} diff --git a/isa/isa.h b/isa/isa.h new file mode 100644 index 0000000..3effb5b --- /dev/null +++ b/isa/isa.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +#include "infra/pipetrace.h" + +enum class ctlreg { + DATA_INSTRUCTION_FIELD_BUFFER, // (df << 3) | if_buffer + DATA_INSTRUCTION_FIELD_SAVED, // (df_saved << 3) | if_saved + INT_ENABLE, // (int_enable_delay << 1) | int_enable +}; + +struct instruction_context { + infra::transaction transaction; + + // 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 + std::optional read_ctlreg; // ctlval = %[read_ctlreg] + bool need_write_acc = false; // %acc = acc + bool need_write_link = false; // %link = link + 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; + bool halt = false; +}; + +instruction_context decode(unsigned int df, unsigned int pc, unsigned int bits); -- cgit v1.2.3