Dasm.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #include "Dasm.h"
  2. #include "DasmTables.h"
  3. #include "SymbolTable.h"
  4. #include <sstream>
  5. #include <iomanip>
  6. static char sign(unsigned char a)
  7. {
  8. return (a & 128) ? '-' : '+';
  9. }
  10. static int abs(unsigned char a)
  11. {
  12. return (a & 128) ? (256 - a) : a;
  13. }
  14. static std::string toHex(unsigned value, unsigned width)
  15. {
  16. std::ostringstream s;
  17. s << std::hex << std::setw(width) << std::setfill('0') << value;
  18. return s.str();
  19. }
  20. static std::string translateAddress(
  21. int address, MemoryLayout* memLayout, SymbolTable* symTable)
  22. {
  23. if (Symbol* label = symTable->getAddressSymbol(address, memLayout)) {
  24. return label->text().toStdString();
  25. } else {
  26. return '#' + toHex(address, 4);
  27. }
  28. }
  29. static int get16(const unsigned char* memBuf, int address)
  30. {
  31. return memBuf[address] + 256 * memBuf[address + 1];
  32. }
  33. void dasm(const unsigned char* membuf, unsigned short startAddr,
  34. unsigned short endAddr, DisasmLines& disasm,
  35. MemoryLayout* memLayout, SymbolTable* symTable, int currentPC)
  36. {
  37. int pc = startAddr;
  38. int labelCount = 0;
  39. Symbol* symbol = symTable->findFirstAddressSymbol(pc, memLayout);
  40. disasm.clear();
  41. while (pc <= int(endAddr)) {
  42. // check for a label
  43. while (symbol && symbol->value() == pc) {
  44. ++labelCount;
  45. DisasmRow destsym;
  46. destsym.rowType = DisasmRow::LABEL;
  47. destsym.numBytes = 0;
  48. destsym.infoLine = labelCount;
  49. destsym.addr = pc;
  50. destsym.instr = symbol->text().toStdString();
  51. disasm.push_back(destsym);
  52. symbol = symTable->findNextAddressSymbol(memLayout);
  53. }
  54. labelCount = 0;
  55. DisasmRow dest;
  56. dest.rowType = DisasmRow::INSTRUCTION;
  57. dest.addr = pc;
  58. dest.numBytes = 0;
  59. dest.infoLine = 0;
  60. dest.instr.clear();
  61. const char* s;
  62. const char* r = 0;
  63. switch (membuf[pc]) {
  64. case 0xCB:
  65. s = mnemonic_cb[membuf[pc + 1]];
  66. dest.numBytes = 2;
  67. break;
  68. case 0xED:
  69. s = mnemonic_ed[membuf[pc + 1]];
  70. dest.numBytes = 2;
  71. break;
  72. case 0xDD:
  73. case 0xFD:
  74. r = (membuf[pc] == 0xDD) ? "ix" : "iy";
  75. if (membuf[pc + 1] != 0xcb) {
  76. s = mnemonic_xx[membuf[pc + 1]];
  77. dest.numBytes = 2;
  78. } else {
  79. s = mnemonic_xx_cb[membuf[pc + 3]];
  80. dest.numBytes = 4;
  81. }
  82. break;
  83. default:
  84. s = mnemonic_main[membuf[pc]];
  85. dest.numBytes = 1;
  86. }
  87. for (int j = 0; s[j]; ++j) {
  88. switch (s[j]) {
  89. case 'A': {
  90. int address = get16(membuf, pc + dest.numBytes);
  91. dest.instr += translateAddress(address, memLayout, symTable);
  92. dest.numBytes += 2;
  93. break;
  94. }
  95. case 'B':
  96. dest.instr += '#' + toHex(membuf[pc + dest.numBytes], 2);
  97. dest.numBytes += 1;
  98. break;
  99. case 'R': {
  100. int address = (pc + 2 + (signed char)membuf[pc + dest.numBytes]) & 0xFFFF;
  101. dest.instr += translateAddress(address, memLayout, symTable);
  102. dest.numBytes += 1;
  103. break;
  104. }
  105. case 'W':
  106. dest.instr += '#' + toHex(get16(membuf, pc + dest.numBytes), 4);
  107. dest.numBytes += 2;
  108. break;
  109. case 'X': {
  110. unsigned char offset = membuf[pc + dest.numBytes];
  111. dest.instr += '(' + std::string(r) + sign(offset)
  112. + '#' + toHex(abs(offset), 2) + ')';
  113. dest.numBytes += 1;
  114. break;
  115. }
  116. case 'Y': {
  117. unsigned char offset = membuf[pc + 2];
  118. dest.instr += '(' + std::string(r) + sign(offset)
  119. + '#' + toHex(abs(offset), 2) + ')';
  120. break;
  121. }
  122. case 'I':
  123. dest.instr += r;
  124. break;
  125. case '!':
  126. dest.instr = "db #ED,#" + toHex(membuf[pc + 1], 2);
  127. dest.numBytes = 2;
  128. case '@':
  129. dest.instr = "db #" + toHex(membuf[pc], 2);
  130. dest.numBytes = 1;
  131. case '#':
  132. dest.instr = "db #" + toHex(membuf[pc + 0], 2) +
  133. "#CB,#" + toHex(membuf[pc + 2], 2);
  134. dest.numBytes = 2;
  135. case ' ': {
  136. dest.instr.resize(7, ' ');
  137. break;
  138. }
  139. default:
  140. dest.instr += s[j];
  141. break;
  142. }
  143. }
  144. // handle overflow at end or label
  145. int dataBytes = 0;
  146. if (symbol && pc + dest.numBytes > symbol->value()) {
  147. dataBytes = symbol->value() - pc;
  148. } else if (pc + dest.numBytes > endAddr) {
  149. dataBytes = endAddr - pc;
  150. } else if (pc + dest.numBytes > currentPC) {
  151. dataBytes = currentPC - pc;
  152. }
  153. switch (dataBytes) {
  154. case 1:
  155. dest.instr = "db #" + toHex(membuf[pc + 0], 2);
  156. dest.numBytes = 1;
  157. break;
  158. case 2:
  159. dest.instr = "db #" + toHex(membuf[pc + 0], 2) +
  160. ",#" + toHex(membuf[pc + 1], 2);
  161. dest.numBytes = 2;
  162. break;
  163. case 3:
  164. dest.instr = "db #" + toHex(membuf[pc + 0], 2) +
  165. ",#" + toHex(membuf[pc + 1], 2) +
  166. ",#" + toHex(membuf[pc + 2], 2);
  167. dest.numBytes = 3;
  168. break;
  169. default:
  170. break;
  171. }
  172. if (dest.instr.size() < 8) dest.instr.resize(8, ' ');
  173. disasm.push_back(dest);
  174. pc += dest.numBytes;
  175. }
  176. }