From 68bdebd8cae39c30acc384664faa136aeaa9bb84 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sat, 5 Nov 2022 16:59:17 -0700 Subject: Add initial uarch model --- isa/decode.cpp | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) (limited to 'isa/decode.cpp') diff --git a/isa/decode.cpp b/isa/decode.cpp index 745e529..2151e2b 100644 --- a/isa/decode.cpp +++ b/isa/decode.cpp @@ -1,9 +1,78 @@ #include #include +#include #include +#include #include "isa/isa.h" +void init_disasm_tables() +{ + for (unsigned int i = 0; i < 0377; ++i) { + auto &s = opr_disasm_group1[i]; + bool cla = i & 0200; + bool cll = i & 0100; + bool cma = i & 0040; + bool cml = i & 0020; + bool rar = i & 0010; + bool ral = i & 0004; + bool bsw = i & 0002; + bool iac = i & 0001; + if (cla) s += "CLA "; + if (cll) s += "CLL "; + if (cma) s += "CMA "; + if (cml) s += "CML "; + if (iac) s += "IAC "; + if (rar) s += "RAR "; + if (ral) s += "RAL "; + if (bsw) s += "BSW "; + if (s.size()) + s = s.substr(0, s.size() - 1); + else + s = "NOP"; + } + + for (unsigned int i = 0; i < 0366; ++i) { + auto &s = opr_disasm_group2_pos[i]; + bool cla = i & 0200; + bool sma = i & 0100; + bool sza = i & 0040; + bool snl = i & 0020; + bool osr = i & 0004; + bool hlt = i & 0002; + if (sma) s += "SMA "; + if (sza) s += "SZA "; + if (snl) s += "SNL "; + if (cla) s += "CLA "; + if (osr) s += "OSR "; + if (hlt) s += "HLT "; + if (s.size()) + s = s.substr(0, s.size() - 1); + else + s = "NOP"; + } + + for (unsigned int i = 0; i < 0366; ++i) { + auto &s = opr_disasm_group2_neg[i]; + bool cla = i & 0200; + bool spa = i & 0100; + bool sna = i & 0040; + bool szl = i & 0020; + bool osr = i & 0004; + bool hlt = i & 0002; + if (spa) s += "SPA "; + if (sna) s += "SNA "; + if (szl) s += "SZL "; + if (cla) s += "CLA "; + if (osr) s += "OSR "; + if (hlt) s += "HLT "; + if (s.size()) + s = s.substr(0, s.size() - 1); + else + s = "SKP"; + } +} + instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned int bits, bool interrupt) { #pragma GCC diagnostic push @@ -19,6 +88,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i #pragma GCC diagnostic pop instruction_context inst; + inst.bits = bits; inst.next_pc = (pc & ~07777) | ((pc + 1) & 07777); if (interrupt) { @@ -34,6 +104,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i inst.need_exec_load = true; inst.need_read_acc = true; inst.need_write_acc = true; + inst.df = "AND %a"; inst.ef = [](auto &ctx) { ctx.acc = ctx.acc.value() & ctx.data.value() & 07777; }; @@ -44,6 +115,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i inst.need_read_link = true; inst.need_write_acc = true; inst.need_write_link = true; + inst.df = "TAD %a"; inst.ef = [](auto &ctx) { unsigned int sum = ctx.acc.value() + ctx.data.value(); ctx.link = ctx.link.value() ^ (sum >> 12); @@ -54,6 +126,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i inst.need_exec_load = true; inst.need_exec_store = true; inst.possibly_redirects = true; + inst.df = "ISZ %a"; inst.ef = [](auto &ctx) { ctx.data = (ctx.data.value() + 1) & 07777; if (*ctx.data == 0) @@ -64,6 +137,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i inst.need_read_acc = true; inst.need_write_acc = true; inst.need_exec_store = true; + inst.df = "DCA %a"; inst.ef = [](auto &ctx) { ctx.data = ctx.acc.value(); ctx.acc = 0; @@ -72,6 +146,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i case 4: // JMS jump subroutine inst.need_exec_store = true; inst.possibly_redirects = true; + inst.df = "JMS %a"; inst.ef = [ifb](auto &ctx) { ctx.data = ctx.next_pc; ctx.next_pc = (ifb << 12) | ((ctx.final_address.value() + 1) & 07777); @@ -79,6 +154,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i break; case 5: // JMP jump inst.possibly_redirects = true; + inst.df = "JMP %a"; inst.ef = [ifb](auto &ctx) { ctx.next_pc = (ifb << 12) | (ctx.final_address.value() & 07777); }; @@ -91,6 +167,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i case 0: // SKON skip if interrupts enabled inst.possibly_redirects = true; + inst.df = "SKON"; inst.ef = [ie](auto &ctx) { if (ie) ctx.next_pc = (ctx.next_pc & 07777) | ((ctx.next_pc + 1) & 07777); @@ -99,6 +176,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i case 1: // ION set int_enable_delay inst.write_ctlreg = FLAGS; + inst.df = "ION"; inst.ef = [flags](auto &ctx) { ctx.ctlval = flags | FLAG_INT_ENABLE_DELAY; }; @@ -106,6 +184,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i case 2: // IOF clear int_enable and int_enable_delay inst.write_ctlreg = FLAGS; + inst.df = "IOF"; inst.ef = [flags](auto &ctx) { ctx.ctlval = flags & ~FLAG_INT_ENABLE_DELAY & ~FLAG_INT_ENABLE; }; @@ -113,6 +192,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i case 3: // SRQ skip if pending interrupt inst.possibly_redirects = true; + inst.df = "SRQ"; inst.ef = [ir](auto &ctx) { if (ir) ctx.next_pc = (ctx.next_pc & 07777) | ((ctx.next_pc + 1) & 07777); @@ -122,6 +202,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i // GTF get flags inst.read_ctlreg = FLAGS_SAVED; inst.need_read_link = true; + inst.df = "GTF"; inst.ef = [](auto &ctx) { auto flags = ctx.ctlval.value(); flags |= (unsigned int)ctx.link.value() << 11; @@ -133,6 +214,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i inst.need_read_acc = true; inst.need_write_link = true; inst.write_ctlreg = FLAGS; + inst.df = "RTF"; inst.ef = [ie](auto &ctx) { if (ie && (ctx.acc.value() & FLAG_INT_ENABLE)) { ctx.ctlval = ctx.acc.value() | FLAG_INT_ENABLE_DELAY; @@ -147,6 +229,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i break; case 6: // SGT skip if greater than + inst.df = "SGT"; inst.ef = [](auto &ctx) { std::cerr << "unimplemented SGT\n"; assert(false); @@ -154,6 +237,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i break; case 7: // CAF clear all flags + inst.df = "CAF"; inst.ef = [](auto &ctx) { std::cerr << "unimplemented CAF\n"; assert(false); @@ -168,6 +252,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i // KSF skip if TTI flag is set inst.read_ctlreg = TT_BITS; inst.possibly_redirects = true; + inst.df = "KSF"; inst.ef = [](auto &ctx) { if (ctx.ctlval.value() & TTI_FLAG) ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777); @@ -177,6 +262,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i // KIE set TT_FLAGS from the accumulator inst.need_read_acc = true; inst.write_ctlreg = TT_FLAGS; + inst.df = "KIE"; inst.ef = [](auto &ctx) { ctx.ctlval = ctx.acc.value(); }; @@ -186,12 +272,14 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i inst.read_ctlreg = TT_BITS; inst.need_write_acc = true; inst.write_ctlreg = TT_BITS; + inst.df = "KRB"; inst.ef = [](auto &ctx) { ctx.acc = (ctx.ctlval.value() & TTI_DATA) >> TTI_DATA_SHIFT; ctx.ctlval.value() &= ~TTI_FLAG; }; break; default: + inst.df = "IOT %b"; inst.ef = [bits](auto &ctx) { std::cerr << "unimplemented IOT KB suboperation " << (bits & 07) << "\n"; assert(false); @@ -205,6 +293,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i // TFL set TTO flag inst.read_ctlreg = TT_BITS; inst.write_ctlreg = TT_BITS; + inst.df = "TFL"; inst.ef = [](auto &ctx) { ctx.ctlval.value() |= TTO_FLAG; }; @@ -213,6 +302,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i // TSF skip if TTO flag is set inst.read_ctlreg = TT_BITS; inst.possibly_redirects = true; + inst.df = "TSF"; inst.ef = [](auto &ctx) { if (ctx.ctlval.value() & TTO_FLAG) ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777); @@ -222,6 +312,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i // TCF clear TTO flag inst.read_ctlreg = TT_BITS; inst.write_ctlreg = TT_BITS; + inst.df = "TCF"; inst.ef = [](auto &ctx) { ctx.ctlval.value() &= ~TTO_FLAG; }; @@ -231,6 +322,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i inst.need_read_acc = true; inst.read_ctlreg = TT_BITS; inst.write_ctlreg = TT_BITS; + inst.df = "TPC"; inst.ef = [](auto &ctx) { auto &x = ctx.ctlval.value(); auto chr = ctx.acc.value(); @@ -243,6 +335,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i // TSK skip if TTO flag is set or TTI flag is set inst.read_ctlreg = TT_BITS; inst.possibly_redirects = true; + inst.df = "TSK"; inst.ef = [](auto &ctx) { if (ctx.ctlval.value() & (TTI_FLAG | TTO_FLAG)) ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777); @@ -253,6 +346,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i inst.need_read_acc = true; inst.read_ctlreg = TT_BITS; inst.write_ctlreg = TT_BITS; + inst.df = "TLS"; inst.ef = [](auto &ctx) { auto &x = ctx.ctlval.value(); auto chr = ctx.acc.value(); @@ -262,6 +356,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i }; break; default: + inst.df = "IOT %b"; inst.ef = [bits](auto &ctx) { std::cerr << "unimplemented IOT TT suboperation " << (bits & 07) << "\n"; assert(false); @@ -283,6 +378,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i case 01: // CDF change data field inst.write_ctlreg = FLAGS; + inst.df = "CDF %f"; inst.ef = [flags, field](auto &ctx) { ctx.ctlval = (flags & ~FLAG_DF) | (field << FLAG_DF_SHIFT); }; @@ -293,12 +389,14 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i // RMF restore memory field inst.read_ctlreg = FLAGS_SAVED; inst.write_ctlreg = FLAGS; + inst.df = "RMF"; inst.ef = [flags](auto &ctx) { ctx.ctlval.value() &= FLAG_DF | FLAG_IF | FLAG_USER_MODE; ctx.ctlval.value() |= flags & ~(FLAG_DF | FLAG_IF | FLAG_USER_MODE); }; break; default: + inst.df = "IOT %b"; inst.ef = [bits, field](auto &ctx) { std::cerr << "unimplemented IOT MEMORY suboperation " << (bits & 07) << " upon field " << field << "\n"; assert(false); @@ -306,6 +404,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i } break; default: + inst.df = "IOT %b"; inst.ef = [bits, field](auto &ctx) { std::cerr << "unimplemented IOT MEMORY suboperation " << (bits & 07) << " upon field " << field << "\n"; assert(false); @@ -314,6 +413,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i } break; default: + inst.df = "IOT %b"; inst.ef = [bits](auto &ctx) { std::cerr << "warning: unimplemented IOT device " << ((bits >> 6) & 07) << ((bits >> 3) & 07) << " suboperation " << (bits & 07) << "\n"; }; @@ -333,6 +433,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i inst.need_read_link = cml || rar || ral || iac; inst.need_write_acc = cla || cma || rar || ral || bsw || iac; inst.need_write_link = cll || cml || rar || ral || iac; + inst.df = opr_disasm_group1[bits & 0377].c_str(); inst.ef = [cla, cll, cma, cml, rar, ral, bsw, iac](auto &ctx) { if (cla) ctx.acc = 0; if (cll) ctx.link = 0; @@ -374,6 +475,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i if (hlt) inst.write_ctlreg = HALTED; inst.possibly_redirects = true; + inst.df = opr_disasm_group2_pos[bits & 0366].c_str(); inst.ef = [cla, sma, sza, snl, osr, hlt](auto &ctx) { bool skip = false; if (sma && (ctx.acc.value() & 04000)) skip = true; @@ -398,6 +500,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i if (hlt) inst.write_ctlreg = HALTED; inst.possibly_redirects = true; + inst.df = opr_disasm_group2_neg[bits & 0366].c_str(); inst.ef = [cla, spa, sna, szl, osr, hlt](auto &ctx) { bool skip = true; if (spa && (ctx.acc.value() & 04000)) skip = false; @@ -418,6 +521,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i inst.need_read_mq = mqa; inst.need_write_acc = cla || mqa; inst.need_write_mq = mql; + inst.df = opr_disasm_extended_arith[bits & 0376].c_str(); inst.ef = [cla, mqa, mql, extended_arith](auto &ctx) { assert(!extended_arith); if (cla) ctx.acc = 0; @@ -429,6 +533,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i ctx.mq = new_mq; }; } else { + inst.df = "OPR %b"; inst.ef = [bits](auto &ctx) { std::cerr << "unimplemented OPR " << ((bits >> 6) & 07) << ((bits >> 3) & 07) << (bits & 07) << "\n"; assert(false); @@ -438,7 +543,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i } // Instructions with memory operands may be direct or indirect - if (inst.need_exec_load || inst.need_exec_store || inst.possibly_redirects) { + if (inst.need_exec_load || inst.need_exec_store || (bits & 06000) == 04000 /* JMS and JMP */) { auto addr = (pc & 070000) | ((bits & 00200) ? (pc & 07600) : 0) | (bits & 00177); if (bits & 00400) { inst.need_indirect_load = true; @@ -454,3 +559,46 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i return inst; } + +std::string instruction_context::disasm() const +{ + if (!df) + return ""; + + std::ostringstream s; + for (const char *p = df; *p; ++p) { + if (*p != '%') { + s << *p; + continue; + } + switch (*++p) { + case '\0': + case '%': + s << '%'; + break; + case 'a': + if (bits & 00400) + s << "I "; + if (~bits & 00200) + s << "Z "; + s << fmt::format("{:03o}", bits & 00177); + break; + case 'b': + s << fmt::format("{:04o}", bits); + break; + case 'f': + s << fmt::format("{:01o}", (bits & 00070) >> 3); + break; + default: + s << '%' << *p; + break; + } + } + + if (init_address.has_value()) + s << fmt::format(" [{:05o}] ->", *init_address); + if (final_address.has_value()) + s << fmt::format(" [{:05o}]", *final_address); + + return s.str(); +} -- cgit v1.2.3