summaryrefslogtreecommitdiff
path: root/isa
diff options
context:
space:
mode:
Diffstat (limited to 'isa')
-rw-r--r--isa/checker.cpp44
-rw-r--r--isa/decode.cpp96
-rw-r--r--isa/isa.h44
3 files changed, 184 insertions, 0 deletions
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 @@
1#include <cassert>
2
3#include "isa/isa.h"
4
5void checker::execute() {
6 assert(!halt);
7 auto int_enable_delay = ctlregs[ctlreg::INT_ENABLE] >> 1;
8 if (ctlregs[ctlreg::INT_ENABLE] & 1) {
9 // check for interrupt
10 }
11 ctlregs[ctlreg::INT_ENABLE] = (int_enable_delay << 1) | int_enable_delay;
12 inst = decode(ctlregs[ctlreg::DATA_INSTRUCTION_FIELD_BUFFER],
13 pc,
14 mem.fetch(pc));
15 auto next_pc = inst.next_pc;
16 if (inst.need_indirect_load) {
17 auto addr = mem.fetch(inst.init_address.value());
18 if (inst.need_autoinc_store)
19 mem.store(*inst.init_address, (addr + 1) & 07777);
20 inst.final_address = addr;
21 } else {
22 assert(!inst.need_autoinc_store);
23 }
24 if (inst.need_exec_load)
25 inst.data = mem.fetch(inst.final_address.value());
26 if (inst.need_read_acc)
27 inst.acc = acc;
28 if (inst.need_read_link)
29 inst.link = link;
30 if (inst.read_ctlreg.has_value())
31 inst.ctlval = ctlregs[*inst.read_ctlreg];
32 inst.execute();
33 if (inst.need_write_acc)
34 acc = inst.acc.value();
35 if (inst.need_write_link)
36 link = inst.link.value();
37 if (inst.write_ctlreg.has_value())
38 ctlregs[*inst.write_ctlreg] = inst.ctlval.value();
39 if (inst.need_exec_store)
40 mem.store(inst.final_address.value(), inst.data.value());
41 assert(inst.next_pc == next_pc || inst.possibly_redirects);
42 pc = inst.next_pc;
43 halt = inst.halt;
44}
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 @@
1#include <cassert>
2
3#include "isa/isa.h"
4
5instruction_context decode(unsigned int dfifb, unsigned int pc, unsigned int bits)
6{
7 instruction_context inst;
8
9 auto df = dfifb >> 3;
10 auto ifb = dfifb & 00007;
11
12 inst.next_pc = (pc & ~07777) | ((pc + 1) & 07777);
13
14 switch (bits >> 9) {
15 case 0: // AND
16 inst.need_exec_load = true;
17 inst.need_read_acc = true;
18 inst.need_write_acc = true;
19 inst.ef = [](auto &ctx) {
20 ctx.acc = ctx.acc.value() & ctx.data.value();
21 };
22 break;
23 case 1: // TAD
24 inst.need_exec_load = true;
25 inst.need_read_acc = true;
26 inst.need_read_link = true;
27 inst.need_write_acc = true;
28 inst.need_write_link = true;
29 inst.ef = [](auto &ctx) {
30 unsigned int sum = (ctx.link.value() << 12) + ctx.acc.value() + ctx.data.value();
31 ctx.link = (sum >> 12) & 1;
32 ctx.acc = sum & 07777;
33 };
34 break;
35 case 2: // ISZ
36 inst.need_exec_load = true;
37 inst.need_exec_store = true;
38 inst.possibly_redirects = true;
39 inst.ef = [](auto &ctx) {
40 ctx.data = (ctx.data.value() + 1) & 07777;
41 if (*ctx.data)
42 ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777);
43 };
44 break;
45 case 3: // DCA
46 inst.need_read_acc = true;
47 inst.need_write_acc = true;
48 inst.need_exec_store = true;
49 inst.ef = [](auto &ctx) {
50 ctx.data = ctx.acc.value();
51 ctx.acc = 0;
52 };
53 break;
54 case 4: // JMS
55 inst.need_exec_store = true;
56 inst.possibly_redirects = true;
57 inst.ef = [ifb](auto &ctx) {
58 ctx.data = ctx.next_pc;
59 ctx.next_pc = (ifb << 12) | ((ctx.final_address.value() + 1) & 07777);
60 };
61 break;
62 case 5: // JMP
63 inst.possibly_redirects = true;
64 inst.ef = [ifb](auto &ctx) {
65 ctx.next_pc = (ifb << 12) | (ctx.final_address.value() & 07777);
66 };
67 break;
68 case 6: // IOT
69 inst.ef = [bits](auto &ctx) {
70 assert(false);
71 };
72 break;
73 case 7: // OPR
74 inst.ef = [bits](auto &ctx) {
75 assert(false);
76 };
77 break;
78 }
79
80 // Instructions with memory operands may be direct or indirect
81 if (inst.need_exec_load || inst.need_exec_store || inst.possibly_redirects) {
82 auto addr = (df << 12) | ((bits & 00200) ? (next_pc & 07600) : 0) | (bits & 00177);
83 if (bits & 00400) {
84 inst.need_indirect_load = true;
85 inst.init_address = addr;
86 } else {
87 inst.final_address = addr;
88 }
89 }
90
91 // Non-jump indirect memory operands may be autoincrementing depending on operand bits
92 if (!inst.possibly_redirects && inst.need_indirect_load && ((bits & 00170) == 00010))
93 inst.need_autoinc_store = true;
94
95 return inst;
96}
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 @@
1#pragma once
2
3#include <functional>
4#include <optional>
5
6#include "infra/pipetrace.h"
7
8enum class ctlreg {
9 DATA_INSTRUCTION_FIELD_BUFFER, // (df << 3) | if_buffer
10 DATA_INSTRUCTION_FIELD_SAVED, // (df_saved << 3) | if_saved
11 INT_ENABLE, // (int_enable_delay << 1) | int_enable
12};
13
14struct instruction_context {
15 infra::transaction transaction;
16
17 // Known statically at decode time
18 bool need_indirect_load = false; // final_address = mem[init_address]
19 bool need_autoinc_store = false; // mem[init_address] += 1
20 bool need_exec_load = false; // data = mem[final_address]
21 bool need_read_acc = false; // acc = %acc
22 bool need_read_link = false; // link = %link
23 std::optional<ctlreg> read_ctlreg; // ctlval = %[read_ctlreg]
24 bool need_write_acc = false; // %acc = acc
25 bool need_write_link = false; // %link = link
26 std::optional<ctlreg> write_ctlreg; // %[write_ctlreg] = ctlval
27 bool need_exec_store = false; // mem[final_address] = data
28 bool possibly_redirects = false; // %pc = next_pc
29
30 std::function<void(instruction_context &ctx)> ef;
31 void execute() { ef(*this); }
32
33 // May change over the lifetime of the instruction execution
34 unsigned int next_pc; // includes IF
35 std::optional<unsigned int> init_address; // includes DF
36 std::optional<unsigned int> final_address; // includes DF
37 std::optional<unsigned int> ctlval;
38 std::optional<unsigned int> data;
39 std::optional<unsigned int> acc;
40 std::optional<bool> link;
41 bool halt = false;
42};
43
44instruction_context decode(unsigned int df, unsigned int pc, unsigned int bits);