1 /** 2 Copyright: Copyright (c) 2013-2014 Andrey Penechko. 3 License: a$(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module emulator.dcpu.disassembler; 8 9 import std.algorithm : joiner; 10 import std.conv : to; 11 import std..string : format; 12 import std.range : repeat; 13 14 import emulator.dcpu.constants; 15 import emulator.dcpu.instruction; 16 import emulator.dcpu.memoryanalyzer; 17 18 enum indentStr = " "; 19 20 string[] disassembleSome(ushort[] memory, MemoryMap memMap, ushort location = 0, ushort count = 0) 21 { 22 uint pointer = location; 23 ushort numInstructions = 0; 24 25 ushort nextWord() 26 { 27 if (pointer >= memory.length) 28 return 0; 29 else 30 return memory[pointer++]; 31 } 32 33 string[] lines; 34 35 ushort prevInstr = 0; 36 37 uint indentLevel; 38 uint conditionIndentLevel; 39 40 auto indent() 41 { 42 return indentStr.repeat(indentLevel + conditionIndentLevel).joiner; 43 } 44 45 void processInstr() 46 { 47 string instrStr; 48 49 uint address = pointer; 50 ushort instr = memory[pointer++]; 51 52 string literalDecoder(ushort literal) 53 { 54 if (auto transition = find!"a.from == b"(memMap.transitions, address)) 55 { 56 if (transition.length && transition[0].target.position == literal) 57 { 58 return to!string(*(transition[0].target)); 59 } 60 } 61 62 return plainLitDecoder(literal); 63 } 64 65 // Place label if there is at current position 66 if (auto labels = find!"(*a).position == b"(memMap.labels, address)) 67 { 68 if (labels.length) 69 { 70 lines ~= ""; 71 lines ~= format("%04x %s:", address, *labels[0]); 72 73 indentLevel = 1; 74 } 75 } 76 77 if (instr == 0) 78 { 79 prevInstr = 0; 80 indentLevel = 0; 81 conditionIndentLevel = 0; 82 return; 83 } 84 85 if (prevInstr >= 0x10 && prevInstr <= 0x17) 86 { 87 ++conditionIndentLevel; 88 } 89 90 if ((instr & 0x1F) != 0) 91 { 92 string a = decodeOperand!true(instr >> 10, nextWord(), &literalDecoder); 93 string b = decodeOperand!false((instr >> 5) & 0x1F, nextWord(), &literalDecoder); 94 95 instrStr = format("%04x %s%s %s, %s", address, indent, basicOpcodeNames[instr & 0x1F], b, a); 96 97 prevInstr = instr & 0x1F; 98 } 99 else if (((instr >> 5) & 0x1F) != 0) 100 { 101 instrStr = format("%04x %s%s %s", address, 102 indent, 103 specialOpcodeNames[(instr >> 5) & 0x1F], 104 decodeOperand!true(instr >> 10, nextWord(), &literalDecoder)); 105 106 prevInstr = 0; 107 } 108 else 109 { 110 instrStr = format("%04x %s%#02x %#02x, %#02x", address, indent, instr & 0x1F, (instr >> 5) & 0x1F, instr >> 10); 111 112 prevInstr = 0; 113 } 114 115 if (prevInstr < 0x10 || prevInstr > 0x17) 116 { 117 conditionIndentLevel = 0; 118 } 119 120 lines ~= instrStr; 121 ++numInstructions; 122 } 123 124 if (count > 0) 125 { 126 while(numInstructions < count && pointer < memory.length) 127 { 128 processInstr(); 129 } 130 } 131 else 132 { 133 while(pointer < memory.length) 134 { 135 processInstr(); 136 } 137 } 138 139 return lines; 140 }