diff options
Diffstat (limited to 'isa/decode.cpp')
| -rw-r--r-- | isa/decode.cpp | 96 |
1 files changed, 96 insertions, 0 deletions
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 | |||
| 5 | instruction_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 | } | ||
