1 module dcpu16.asm_.decode;
2 
3 import dcpu16.emulator: Memory;
4 import dcpu16.emulator.cpu;
5 
6 pure:
7 
8 private string explainRegisterOfOperand(ushort operand)
9 {
10     switch(operand)
11     {
12         case 0: return "A";
13         case 1: return "B";
14         case 2: return "C";
15         case 3: return "X";
16         case 4: return "Y";
17         case 5: return "Z";
18         case 6: return "I";
19         case 7: return "J";
20         default: assert(false);
21     }
22 }
23 
24 private string explainOperand(in Memory mem, ref ushort pc, ushort operand, bool isA) pure
25 {
26     if(operand > 0x3f)
27         throw new Exception("Unknown operand "~operand.fmt, __FILE__, __LINE__);
28 
29     switch(operand)
30     {
31         case 0x00: .. case 0x07: // register
32             return explainRegisterOfOperand(operand);
33 
34         case 0x08: .. case 0x0f: // [register]
35             return "["~explainRegisterOfOperand(operand & 7)~"]";
36 
37         case 0x10: .. case 0x17: // [register + next word]
38             return "["~explainRegisterOfOperand(operand & 7)~" + "~mem[pc+1].fmt~"]";
39 
40         case 0x18:
41             return isA ? "POP" : "PUSH";
42 
43         case 0x19:
44             return "PEEK";
45 
46         case 0x1a:
47             return "PICK "~mem[pc+1].fmt;
48 
49         case 0x1b:
50             return "SP";
51 
52         case 0x1c:
53             return "PC";
54 
55         case 0x1d:
56             return "EX";
57 
58         case 0x1e: // [next word]
59             return "["~mem[++pc].fmt~"]";
60 
61         case 0x1f: // next word (literal)
62             return mem[++pc].fmt;
63 
64         default: // literal values
65             assert(isA, "Bigger than 5 bit b operand");
66             operand -= 0x21;
67             return operand.fmt;
68     }
69 }
70 
71 import std.string: format;
72 
73 private string explainBasicInstruction(in Memory mem, ushort pc, in Instruction ins)
74 {
75     string a = explainOperand(mem, pc, ins.a, true);
76     string b = explainOperand(mem, pc, ins.b, false);
77 
78     import std.conv: to;
79 
80     return format("%s %s, %s", ins.basic_opcode.to!string, b, a);
81 }
82 
83 private string explainSpecialInstruction(in Memory mem, ushort pc, in Instruction ins)
84 {
85     import std.conv: to;
86 
87     string a = explainOperand(mem, pc, ins.a, true);
88 
89     return format("%s %s", ins.spec_opcode.to!string, a);
90 }
91 
92 private string fmt(T)(T v)
93 {
94     return format("%04#x", v);
95 }
96 
97 string explainInstruction(in Memory mem, ushort pc, in Instruction ins)
98 {
99     if(!ins.isSpecialOpcode)
100         return explainBasicInstruction(mem, pc, ins);
101     else
102         return explainSpecialInstruction(mem, pc, ins);
103 }