summaryrefslogtreecommitdiff
path: root/isa/decode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'isa/decode.cpp')
-rw-r--r--isa/decode.cpp150
1 files changed, 149 insertions, 1 deletions
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 @@
1#include <cassert> 1#include <cassert>
2#include <cstdint> 2#include <cstdint>
3#include <fmt/format.h>
3#include <iostream> 4#include <iostream>
5#include <sstream>
4 6
5#include "isa/isa.h" 7#include "isa/isa.h"
6 8
9void init_disasm_tables()
10{
11 for (unsigned int i = 0; i < 0377; ++i) {
12 auto &s = opr_disasm_group1[i];
13 bool cla = i & 0200;
14 bool cll = i & 0100;
15 bool cma = i & 0040;
16 bool cml = i & 0020;
17 bool rar = i & 0010;
18 bool ral = i & 0004;
19 bool bsw = i & 0002;
20 bool iac = i & 0001;
21 if (cla) s += "CLA ";
22 if (cll) s += "CLL ";
23 if (cma) s += "CMA ";
24 if (cml) s += "CML ";
25 if (iac) s += "IAC ";
26 if (rar) s += "RAR ";
27 if (ral) s += "RAL ";
28 if (bsw) s += "BSW ";
29 if (s.size())
30 s = s.substr(0, s.size() - 1);
31 else
32 s = "NOP";
33 }
34
35 for (unsigned int i = 0; i < 0366; ++i) {
36 auto &s = opr_disasm_group2_pos[i];
37 bool cla = i & 0200;
38 bool sma = i & 0100;
39 bool sza = i & 0040;
40 bool snl = i & 0020;
41 bool osr = i & 0004;
42 bool hlt = i & 0002;
43 if (sma) s += "SMA ";
44 if (sza) s += "SZA ";
45 if (snl) s += "SNL ";
46 if (cla) s += "CLA ";
47 if (osr) s += "OSR ";
48 if (hlt) s += "HLT ";
49 if (s.size())
50 s = s.substr(0, s.size() - 1);
51 else
52 s = "NOP";
53 }
54
55 for (unsigned int i = 0; i < 0366; ++i) {
56 auto &s = opr_disasm_group2_neg[i];
57 bool cla = i & 0200;
58 bool spa = i & 0100;
59 bool sna = i & 0040;
60 bool szl = i & 0020;
61 bool osr = i & 0004;
62 bool hlt = i & 0002;
63 if (spa) s += "SPA ";
64 if (sna) s += "SNA ";
65 if (szl) s += "SZL ";
66 if (cla) s += "CLA ";
67 if (osr) s += "OSR ";
68 if (hlt) s += "HLT ";
69 if (s.size())
70 s = s.substr(0, s.size() - 1);
71 else
72 s = "SKP";
73 }
74}
75
7instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned int bits, bool interrupt) 76instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned int bits, bool interrupt)
8{ 77{
9#pragma GCC diagnostic push 78#pragma GCC diagnostic push
@@ -19,6 +88,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
19#pragma GCC diagnostic pop 88#pragma GCC diagnostic pop
20 89
21 instruction_context inst; 90 instruction_context inst;
91 inst.bits = bits;
22 inst.next_pc = (pc & ~07777) | ((pc + 1) & 07777); 92 inst.next_pc = (pc & ~07777) | ((pc + 1) & 07777);
23 93
24 if (interrupt) { 94 if (interrupt) {
@@ -34,6 +104,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
34 inst.need_exec_load = true; 104 inst.need_exec_load = true;
35 inst.need_read_acc = true; 105 inst.need_read_acc = true;
36 inst.need_write_acc = true; 106 inst.need_write_acc = true;
107 inst.df = "AND %a";
37 inst.ef = [](auto &ctx) { 108 inst.ef = [](auto &ctx) {
38 ctx.acc = ctx.acc.value() & ctx.data.value() & 07777; 109 ctx.acc = ctx.acc.value() & ctx.data.value() & 07777;
39 }; 110 };
@@ -44,6 +115,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
44 inst.need_read_link = true; 115 inst.need_read_link = true;
45 inst.need_write_acc = true; 116 inst.need_write_acc = true;
46 inst.need_write_link = true; 117 inst.need_write_link = true;
118 inst.df = "TAD %a";
47 inst.ef = [](auto &ctx) { 119 inst.ef = [](auto &ctx) {
48 unsigned int sum = ctx.acc.value() + ctx.data.value(); 120 unsigned int sum = ctx.acc.value() + ctx.data.value();
49 ctx.link = ctx.link.value() ^ (sum >> 12); 121 ctx.link = ctx.link.value() ^ (sum >> 12);
@@ -54,6 +126,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
54 inst.need_exec_load = true; 126 inst.need_exec_load = true;
55 inst.need_exec_store = true; 127 inst.need_exec_store = true;
56 inst.possibly_redirects = true; 128 inst.possibly_redirects = true;
129 inst.df = "ISZ %a";
57 inst.ef = [](auto &ctx) { 130 inst.ef = [](auto &ctx) {
58 ctx.data = (ctx.data.value() + 1) & 07777; 131 ctx.data = (ctx.data.value() + 1) & 07777;
59 if (*ctx.data == 0) 132 if (*ctx.data == 0)
@@ -64,6 +137,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
64 inst.need_read_acc = true; 137 inst.need_read_acc = true;
65 inst.need_write_acc = true; 138 inst.need_write_acc = true;
66 inst.need_exec_store = true; 139 inst.need_exec_store = true;
140 inst.df = "DCA %a";
67 inst.ef = [](auto &ctx) { 141 inst.ef = [](auto &ctx) {
68 ctx.data = ctx.acc.value(); 142 ctx.data = ctx.acc.value();
69 ctx.acc = 0; 143 ctx.acc = 0;
@@ -72,6 +146,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
72 case 4: // JMS jump subroutine 146 case 4: // JMS jump subroutine
73 inst.need_exec_store = true; 147 inst.need_exec_store = true;
74 inst.possibly_redirects = true; 148 inst.possibly_redirects = true;
149 inst.df = "JMS %a";
75 inst.ef = [ifb](auto &ctx) { 150 inst.ef = [ifb](auto &ctx) {
76 ctx.data = ctx.next_pc; 151 ctx.data = ctx.next_pc;
77 ctx.next_pc = (ifb << 12) | ((ctx.final_address.value() + 1) & 07777); 152 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
79 break; 154 break;
80 case 5: // JMP jump 155 case 5: // JMP jump
81 inst.possibly_redirects = true; 156 inst.possibly_redirects = true;
157 inst.df = "JMP %a";
82 inst.ef = [ifb](auto &ctx) { 158 inst.ef = [ifb](auto &ctx) {
83 ctx.next_pc = (ifb << 12) | (ctx.final_address.value() & 07777); 159 ctx.next_pc = (ifb << 12) | (ctx.final_address.value() & 07777);
84 }; 160 };
@@ -91,6 +167,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
91 case 0: 167 case 0:
92 // SKON skip if interrupts enabled 168 // SKON skip if interrupts enabled
93 inst.possibly_redirects = true; 169 inst.possibly_redirects = true;
170 inst.df = "SKON";
94 inst.ef = [ie](auto &ctx) { 171 inst.ef = [ie](auto &ctx) {
95 if (ie) 172 if (ie)
96 ctx.next_pc = (ctx.next_pc & 07777) | ((ctx.next_pc + 1) & 07777); 173 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
99 case 1: 176 case 1:
100 // ION set int_enable_delay 177 // ION set int_enable_delay
101 inst.write_ctlreg = FLAGS; 178 inst.write_ctlreg = FLAGS;
179 inst.df = "ION";
102 inst.ef = [flags](auto &ctx) { 180 inst.ef = [flags](auto &ctx) {
103 ctx.ctlval = flags | FLAG_INT_ENABLE_DELAY; 181 ctx.ctlval = flags | FLAG_INT_ENABLE_DELAY;
104 }; 182 };
@@ -106,6 +184,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
106 case 2: 184 case 2:
107 // IOF clear int_enable and int_enable_delay 185 // IOF clear int_enable and int_enable_delay
108 inst.write_ctlreg = FLAGS; 186 inst.write_ctlreg = FLAGS;
187 inst.df = "IOF";
109 inst.ef = [flags](auto &ctx) { 188 inst.ef = [flags](auto &ctx) {
110 ctx.ctlval = flags & ~FLAG_INT_ENABLE_DELAY & ~FLAG_INT_ENABLE; 189 ctx.ctlval = flags & ~FLAG_INT_ENABLE_DELAY & ~FLAG_INT_ENABLE;
111 }; 190 };
@@ -113,6 +192,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
113 case 3: 192 case 3:
114 // SRQ skip if pending interrupt 193 // SRQ skip if pending interrupt
115 inst.possibly_redirects = true; 194 inst.possibly_redirects = true;
195 inst.df = "SRQ";
116 inst.ef = [ir](auto &ctx) { 196 inst.ef = [ir](auto &ctx) {
117 if (ir) 197 if (ir)
118 ctx.next_pc = (ctx.next_pc & 07777) | ((ctx.next_pc + 1) & 07777); 198 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
122 // GTF get flags 202 // GTF get flags
123 inst.read_ctlreg = FLAGS_SAVED; 203 inst.read_ctlreg = FLAGS_SAVED;
124 inst.need_read_link = true; 204 inst.need_read_link = true;
205 inst.df = "GTF";
125 inst.ef = [](auto &ctx) { 206 inst.ef = [](auto &ctx) {
126 auto flags = ctx.ctlval.value(); 207 auto flags = ctx.ctlval.value();
127 flags |= (unsigned int)ctx.link.value() << 11; 208 flags |= (unsigned int)ctx.link.value() << 11;
@@ -133,6 +214,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
133 inst.need_read_acc = true; 214 inst.need_read_acc = true;
134 inst.need_write_link = true; 215 inst.need_write_link = true;
135 inst.write_ctlreg = FLAGS; 216 inst.write_ctlreg = FLAGS;
217 inst.df = "RTF";
136 inst.ef = [ie](auto &ctx) { 218 inst.ef = [ie](auto &ctx) {
137 if (ie && (ctx.acc.value() & FLAG_INT_ENABLE)) { 219 if (ie && (ctx.acc.value() & FLAG_INT_ENABLE)) {
138 ctx.ctlval = ctx.acc.value() | FLAG_INT_ENABLE_DELAY; 220 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
147 break; 229 break;
148 case 6: 230 case 6:
149 // SGT skip if greater than 231 // SGT skip if greater than
232 inst.df = "SGT";
150 inst.ef = [](auto &ctx) { 233 inst.ef = [](auto &ctx) {
151 std::cerr << "unimplemented SGT\n"; 234 std::cerr << "unimplemented SGT\n";
152 assert(false); 235 assert(false);
@@ -154,6 +237,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
154 break; 237 break;
155 case 7: 238 case 7:
156 // CAF clear all flags 239 // CAF clear all flags
240 inst.df = "CAF";
157 inst.ef = [](auto &ctx) { 241 inst.ef = [](auto &ctx) {
158 std::cerr << "unimplemented CAF\n"; 242 std::cerr << "unimplemented CAF\n";
159 assert(false); 243 assert(false);
@@ -168,6 +252,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
168 // KSF skip if TTI flag is set 252 // KSF skip if TTI flag is set
169 inst.read_ctlreg = TT_BITS; 253 inst.read_ctlreg = TT_BITS;
170 inst.possibly_redirects = true; 254 inst.possibly_redirects = true;
255 inst.df = "KSF";
171 inst.ef = [](auto &ctx) { 256 inst.ef = [](auto &ctx) {
172 if (ctx.ctlval.value() & TTI_FLAG) 257 if (ctx.ctlval.value() & TTI_FLAG)
173 ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777); 258 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
177 // KIE set TT_FLAGS from the accumulator 262 // KIE set TT_FLAGS from the accumulator
178 inst.need_read_acc = true; 263 inst.need_read_acc = true;
179 inst.write_ctlreg = TT_FLAGS; 264 inst.write_ctlreg = TT_FLAGS;
265 inst.df = "KIE";
180 inst.ef = [](auto &ctx) { 266 inst.ef = [](auto &ctx) {
181 ctx.ctlval = ctx.acc.value(); 267 ctx.ctlval = ctx.acc.value();
182 }; 268 };
@@ -186,12 +272,14 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
186 inst.read_ctlreg = TT_BITS; 272 inst.read_ctlreg = TT_BITS;
187 inst.need_write_acc = true; 273 inst.need_write_acc = true;
188 inst.write_ctlreg = TT_BITS; 274 inst.write_ctlreg = TT_BITS;
275 inst.df = "KRB";
189 inst.ef = [](auto &ctx) { 276 inst.ef = [](auto &ctx) {
190 ctx.acc = (ctx.ctlval.value() & TTI_DATA) >> TTI_DATA_SHIFT; 277 ctx.acc = (ctx.ctlval.value() & TTI_DATA) >> TTI_DATA_SHIFT;
191 ctx.ctlval.value() &= ~TTI_FLAG; 278 ctx.ctlval.value() &= ~TTI_FLAG;
192 }; 279 };
193 break; 280 break;
194 default: 281 default:
282 inst.df = "IOT %b";
195 inst.ef = [bits](auto &ctx) { 283 inst.ef = [bits](auto &ctx) {
196 std::cerr << "unimplemented IOT KB suboperation " << (bits & 07) << "\n"; 284 std::cerr << "unimplemented IOT KB suboperation " << (bits & 07) << "\n";
197 assert(false); 285 assert(false);
@@ -205,6 +293,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
205 // TFL set TTO flag 293 // TFL set TTO flag
206 inst.read_ctlreg = TT_BITS; 294 inst.read_ctlreg = TT_BITS;
207 inst.write_ctlreg = TT_BITS; 295 inst.write_ctlreg = TT_BITS;
296 inst.df = "TFL";
208 inst.ef = [](auto &ctx) { 297 inst.ef = [](auto &ctx) {
209 ctx.ctlval.value() |= TTO_FLAG; 298 ctx.ctlval.value() |= TTO_FLAG;
210 }; 299 };
@@ -213,6 +302,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
213 // TSF skip if TTO flag is set 302 // TSF skip if TTO flag is set
214 inst.read_ctlreg = TT_BITS; 303 inst.read_ctlreg = TT_BITS;
215 inst.possibly_redirects = true; 304 inst.possibly_redirects = true;
305 inst.df = "TSF";
216 inst.ef = [](auto &ctx) { 306 inst.ef = [](auto &ctx) {
217 if (ctx.ctlval.value() & TTO_FLAG) 307 if (ctx.ctlval.value() & TTO_FLAG)
218 ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777); 308 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
222 // TCF clear TTO flag 312 // TCF clear TTO flag
223 inst.read_ctlreg = TT_BITS; 313 inst.read_ctlreg = TT_BITS;
224 inst.write_ctlreg = TT_BITS; 314 inst.write_ctlreg = TT_BITS;
315 inst.df = "TCF";
225 inst.ef = [](auto &ctx) { 316 inst.ef = [](auto &ctx) {
226 ctx.ctlval.value() &= ~TTO_FLAG; 317 ctx.ctlval.value() &= ~TTO_FLAG;
227 }; 318 };
@@ -231,6 +322,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
231 inst.need_read_acc = true; 322 inst.need_read_acc = true;
232 inst.read_ctlreg = TT_BITS; 323 inst.read_ctlreg = TT_BITS;
233 inst.write_ctlreg = TT_BITS; 324 inst.write_ctlreg = TT_BITS;
325 inst.df = "TPC";
234 inst.ef = [](auto &ctx) { 326 inst.ef = [](auto &ctx) {
235 auto &x = ctx.ctlval.value(); 327 auto &x = ctx.ctlval.value();
236 auto chr = ctx.acc.value(); 328 auto chr = ctx.acc.value();
@@ -243,6 +335,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
243 // TSK skip if TTO flag is set or TTI flag is set 335 // TSK skip if TTO flag is set or TTI flag is set
244 inst.read_ctlreg = TT_BITS; 336 inst.read_ctlreg = TT_BITS;
245 inst.possibly_redirects = true; 337 inst.possibly_redirects = true;
338 inst.df = "TSK";
246 inst.ef = [](auto &ctx) { 339 inst.ef = [](auto &ctx) {
247 if (ctx.ctlval.value() & (TTI_FLAG | TTO_FLAG)) 340 if (ctx.ctlval.value() & (TTI_FLAG | TTO_FLAG))
248 ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777); 341 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
253 inst.need_read_acc = true; 346 inst.need_read_acc = true;
254 inst.read_ctlreg = TT_BITS; 347 inst.read_ctlreg = TT_BITS;
255 inst.write_ctlreg = TT_BITS; 348 inst.write_ctlreg = TT_BITS;
349 inst.df = "TLS";
256 inst.ef = [](auto &ctx) { 350 inst.ef = [](auto &ctx) {
257 auto &x = ctx.ctlval.value(); 351 auto &x = ctx.ctlval.value();
258 auto chr = ctx.acc.value(); 352 auto chr = ctx.acc.value();
@@ -262,6 +356,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
262 }; 356 };
263 break; 357 break;
264 default: 358 default:
359 inst.df = "IOT %b";
265 inst.ef = [bits](auto &ctx) { 360 inst.ef = [bits](auto &ctx) {
266 std::cerr << "unimplemented IOT TT suboperation " << (bits & 07) << "\n"; 361 std::cerr << "unimplemented IOT TT suboperation " << (bits & 07) << "\n";
267 assert(false); 362 assert(false);
@@ -283,6 +378,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
283 case 01: 378 case 01:
284 // CDF change data field 379 // CDF change data field
285 inst.write_ctlreg = FLAGS; 380 inst.write_ctlreg = FLAGS;
381 inst.df = "CDF %f";
286 inst.ef = [flags, field](auto &ctx) { 382 inst.ef = [flags, field](auto &ctx) {
287 ctx.ctlval = (flags & ~FLAG_DF) | (field << FLAG_DF_SHIFT); 383 ctx.ctlval = (flags & ~FLAG_DF) | (field << FLAG_DF_SHIFT);
288 }; 384 };
@@ -293,12 +389,14 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
293 // RMF restore memory field 389 // RMF restore memory field
294 inst.read_ctlreg = FLAGS_SAVED; 390 inst.read_ctlreg = FLAGS_SAVED;
295 inst.write_ctlreg = FLAGS; 391 inst.write_ctlreg = FLAGS;
392 inst.df = "RMF";
296 inst.ef = [flags](auto &ctx) { 393 inst.ef = [flags](auto &ctx) {
297 ctx.ctlval.value() &= FLAG_DF | FLAG_IF | FLAG_USER_MODE; 394 ctx.ctlval.value() &= FLAG_DF | FLAG_IF | FLAG_USER_MODE;
298 ctx.ctlval.value() |= flags & ~(FLAG_DF | FLAG_IF | FLAG_USER_MODE); 395 ctx.ctlval.value() |= flags & ~(FLAG_DF | FLAG_IF | FLAG_USER_MODE);
299 }; 396 };
300 break; 397 break;
301 default: 398 default:
399 inst.df = "IOT %b";
302 inst.ef = [bits, field](auto &ctx) { 400 inst.ef = [bits, field](auto &ctx) {
303 std::cerr << "unimplemented IOT MEMORY suboperation " << (bits & 07) << " upon field " << field << "\n"; 401 std::cerr << "unimplemented IOT MEMORY suboperation " << (bits & 07) << " upon field " << field << "\n";
304 assert(false); 402 assert(false);
@@ -306,6 +404,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
306 } 404 }
307 break; 405 break;
308 default: 406 default:
407 inst.df = "IOT %b";
309 inst.ef = [bits, field](auto &ctx) { 408 inst.ef = [bits, field](auto &ctx) {
310 std::cerr << "unimplemented IOT MEMORY suboperation " << (bits & 07) << " upon field " << field << "\n"; 409 std::cerr << "unimplemented IOT MEMORY suboperation " << (bits & 07) << " upon field " << field << "\n";
311 assert(false); 410 assert(false);
@@ -314,6 +413,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
314 } 413 }
315 break; 414 break;
316 default: 415 default:
416 inst.df = "IOT %b";
317 inst.ef = [bits](auto &ctx) { 417 inst.ef = [bits](auto &ctx) {
318 std::cerr << "warning: unimplemented IOT device " << ((bits >> 6) & 07) << ((bits >> 3) & 07) << " suboperation " << (bits & 07) << "\n"; 418 std::cerr << "warning: unimplemented IOT device " << ((bits >> 6) & 07) << ((bits >> 3) & 07) << " suboperation " << (bits & 07) << "\n";
319 }; 419 };
@@ -333,6 +433,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
333 inst.need_read_link = cml || rar || ral || iac; 433 inst.need_read_link = cml || rar || ral || iac;
334 inst.need_write_acc = cla || cma || rar || ral || bsw || iac; 434 inst.need_write_acc = cla || cma || rar || ral || bsw || iac;
335 inst.need_write_link = cll || cml || rar || ral || iac; 435 inst.need_write_link = cll || cml || rar || ral || iac;
436 inst.df = opr_disasm_group1[bits & 0377].c_str();
336 inst.ef = [cla, cll, cma, cml, rar, ral, bsw, iac](auto &ctx) { 437 inst.ef = [cla, cll, cma, cml, rar, ral, bsw, iac](auto &ctx) {
337 if (cla) ctx.acc = 0; 438 if (cla) ctx.acc = 0;
338 if (cll) ctx.link = 0; 439 if (cll) ctx.link = 0;
@@ -374,6 +475,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
374 if (hlt) 475 if (hlt)
375 inst.write_ctlreg = HALTED; 476 inst.write_ctlreg = HALTED;
376 inst.possibly_redirects = true; 477 inst.possibly_redirects = true;
478 inst.df = opr_disasm_group2_pos[bits & 0366].c_str();
377 inst.ef = [cla, sma, sza, snl, osr, hlt](auto &ctx) { 479 inst.ef = [cla, sma, sza, snl, osr, hlt](auto &ctx) {
378 bool skip = false; 480 bool skip = false;
379 if (sma && (ctx.acc.value() & 04000)) skip = true; 481 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
398 if (hlt) 500 if (hlt)
399 inst.write_ctlreg = HALTED; 501 inst.write_ctlreg = HALTED;
400 inst.possibly_redirects = true; 502 inst.possibly_redirects = true;
503 inst.df = opr_disasm_group2_neg[bits & 0366].c_str();
401 inst.ef = [cla, spa, sna, szl, osr, hlt](auto &ctx) { 504 inst.ef = [cla, spa, sna, szl, osr, hlt](auto &ctx) {
402 bool skip = true; 505 bool skip = true;
403 if (spa && (ctx.acc.value() & 04000)) skip = false; 506 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
418 inst.need_read_mq = mqa; 521 inst.need_read_mq = mqa;
419 inst.need_write_acc = cla || mqa; 522 inst.need_write_acc = cla || mqa;
420 inst.need_write_mq = mql; 523 inst.need_write_mq = mql;
524 inst.df = opr_disasm_extended_arith[bits & 0376].c_str();
421 inst.ef = [cla, mqa, mql, extended_arith](auto &ctx) { 525 inst.ef = [cla, mqa, mql, extended_arith](auto &ctx) {
422 assert(!extended_arith); 526 assert(!extended_arith);
423 if (cla) ctx.acc = 0; 527 if (cla) ctx.acc = 0;
@@ -429,6 +533,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
429 ctx.mq = new_mq; 533 ctx.mq = new_mq;
430 }; 534 };
431 } else { 535 } else {
536 inst.df = "OPR %b";
432 inst.ef = [bits](auto &ctx) { 537 inst.ef = [bits](auto &ctx) {
433 std::cerr << "unimplemented OPR " << ((bits >> 6) & 07) << ((bits >> 3) & 07) << (bits & 07) << "\n"; 538 std::cerr << "unimplemented OPR " << ((bits >> 6) & 07) << ((bits >> 3) & 07) << (bits & 07) << "\n";
434 assert(false); 539 assert(false);
@@ -438,7 +543,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
438 } 543 }
439 544
440 // Instructions with memory operands may be direct or indirect 545 // Instructions with memory operands may be direct or indirect
441 if (inst.need_exec_load || inst.need_exec_store || inst.possibly_redirects) { 546 if (inst.need_exec_load || inst.need_exec_store || (bits & 06000) == 04000 /* JMS and JMP */) {
442 auto addr = (pc & 070000) | ((bits & 00200) ? (pc & 07600) : 0) | (bits & 00177); 547 auto addr = (pc & 070000) | ((bits & 00200) ? (pc & 07600) : 0) | (bits & 00177);
443 if (bits & 00400) { 548 if (bits & 00400) {
444 inst.need_indirect_load = true; 549 inst.need_indirect_load = true;
@@ -454,3 +559,46 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
454 559
455 return inst; 560 return inst;
456} 561}
562
563std::string instruction_context::disasm() const
564{
565 if (!df)
566 return "<null>";
567
568 std::ostringstream s;
569 for (const char *p = df; *p; ++p) {
570 if (*p != '%') {
571 s << *p;
572 continue;
573 }
574 switch (*++p) {
575 case '\0':
576 case '%':
577 s << '%';
578 break;
579 case 'a':
580 if (bits & 00400)
581 s << "I ";
582 if (~bits & 00200)
583 s << "Z ";
584 s << fmt::format("{:03o}", bits & 00177);
585 break;
586 case 'b':
587 s << fmt::format("{:04o}", bits);
588 break;
589 case 'f':
590 s << fmt::format("{:01o}", (bits & 00070) >> 3);
591 break;
592 default:
593 s << '%' << *p;
594 break;
595 }
596 }
597
598 if (init_address.has_value())
599 s << fmt::format(" [{:05o}] ->", *init_address);
600 if (final_address.has_value())
601 s << fmt::format(" [{:05o}]", *final_address);
602
603 return s.str();
604}