Advertisement
uaa

[wip:20220619] uxn disassembler

uaa
Jun 19th, 2022
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.62 KB | None | 0 0
  1. // SPDX-License-Identifier: ISC
  2. // copyright (C) 2022 SASANO Takayoshi <[email protected]>
  3.  
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <stdint.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9.  
  10. static uint8_t *buf;
  11. static size_t filesize;
  12.  
  13. static char *opecodeX[] = {
  14. NULL, "INC", "POP", "NIP", "SWP", "ROT", "DUP", "OVR",
  15. "EQU", "NEQ", "GTH", "LTH", "JMP", "JCN", "JSR", "STH",
  16. "LDZ", "STZ", "LDR", "STR", "LDA", "STA", "DEI", "DEO",
  17. "ADD", "SUB", "MUL", "DIV", "AND", "ORA", "EOR", "SFT",
  18. };
  19.  
  20. static char *opecode0[] = {
  21. "BRK", "20 ", "40 ", "60 ", "LIT", "LIT", "LIT", "LIT",
  22. };
  23.  
  24. #define HEXDUMP_WIDTH 3
  25. #define INSTRUCTION_STRING_LEN 3
  26. #define MODIFIER_STRING_LEN 3
  27. #define OFFSET 0x100
  28.  
  29. static int put_space(char *out, int len)
  30. {
  31. int i;
  32.  
  33. /* simply put space (for padding) */
  34. for (i = 0; i < len; i++)
  35. *out++ = ' ';
  36.  
  37. *out = '\0';
  38.  
  39. return i;
  40. }
  41.  
  42. /* hex values should use lower-case */
  43. static int put_hex8(char *out, uint8_t value)
  44. {
  45. return sprintf(out, "%02x ", value);
  46. }
  47.  
  48. static int put_hex16(char *out, uint16_t value)
  49. {
  50. return sprintf(out, "%04x ", value);
  51. }
  52.  
  53. static int put_hexdump(char *out, uint8_t *bin, int len)
  54. {
  55. int i, n, l;
  56.  
  57. n = 0;
  58. for (i = 0; i < len; i++) {
  59. l = put_hex8(out, *bin++);
  60. n += l;
  61. out += l;
  62. }
  63.  
  64. return n;
  65. }
  66.  
  67. static int put_asciidump(char *out, uint8_t *bin, int len)
  68. {
  69. int i;
  70.  
  71. for (i = 0; i < len; i++) {
  72. /* avoid comment identifier, '(' and ')' */
  73. *out++ = (isascii(*bin) && !iscntrl(*bin) &&
  74. (*bin != '(') && (*bin != ')')) ?
  75. *bin : '.';
  76. bin++;
  77. }
  78.  
  79. *out = '\0';
  80.  
  81. return i;
  82. }
  83.  
  84. static int get_immediate_size(uint8_t opecode)
  85. {
  86. if ((opecode & 0x9f) == 0x80) {
  87. /* LIT */
  88. return (opecode & 0x20) ? 2 : 1;
  89. } else {
  90. /* others */
  91. return 0;
  92. }
  93. }
  94.  
  95. static int put_instruction(char *p, uint8_t opecode)
  96. {
  97. int op;
  98. char *p0, *m;
  99.  
  100. p0 = p;
  101.  
  102. op = opecode & 0x1f;
  103. if (op) {
  104. m = opecodeX[op];
  105. } else {
  106. m = opecode0[opecode >> 5];
  107.  
  108. if (opecode & 0x80) {
  109. /* LIT: k modifier is no need to display */
  110. opecode &= ~0x80;
  111. } else {
  112. /* BRK/reserved instructions: no modifier */
  113. opecode &= ~0xe0;
  114. }
  115. }
  116.  
  117. strcpy(p, m);
  118. p += strlen(m);
  119.  
  120. if (opecode & 0x20) *p++ = '2';
  121. if (opecode & 0x80) *p++ = 'k';
  122. if (opecode & 0x40) *p++ = 'r';
  123. *p = '\0';
  124.  
  125. return p - p0;
  126. }
  127.  
  128. static void put_disassemble(char *line, uint8_t *code, int immediate_size)
  129. {
  130. char *p;
  131.  
  132. /* instruction */
  133. p = line;
  134. line += put_instruction(line, *code);
  135.  
  136. /* immediate (if needed) */
  137. if (immediate_size) {
  138. line += put_space(line,
  139. INSTRUCTION_STRING_LEN +
  140. MODIFIER_STRING_LEN + 1 - (line - p));
  141. switch (immediate_size) {
  142. case 1:
  143. line += put_hex8(line, *(code + 1));
  144. break;
  145. case 2:
  146. line += put_hex16(line,
  147. (*(code + 1) << 8) | *(code + 2));
  148. break;
  149. default:
  150. break;
  151. }
  152. }
  153. }
  154.  
  155. static void put_dump(char *line, uint8_t *code, int len)
  156. {
  157. int i;
  158.  
  159. for (i = 0; i < len; i++)
  160. line += put_hex8(line, code[i]);
  161. }
  162.  
  163. static int build_line(char *line, uint16_t address, uint8_t *code, int remain)
  164. {
  165. int len, dump;
  166. char *p;
  167.  
  168. len = get_immediate_size(*code) + 1;
  169. dump = 0;
  170.  
  171. /* if remains is not enough, use hex dump instead of disassemble */
  172. if (remain < len) {
  173. len = remain;
  174. dump = 1;
  175. }
  176.  
  177. /* address, hex dump and ascii dump is commented-out */
  178. line += sprintf(line, "( ");
  179. line += put_hex16(line, address + OFFSET);
  180.  
  181. p = line;
  182. line += put_hexdump(line, code, len);
  183. line += put_space(line, (HEXDUMP_WIDTH * 3) - (line - p));
  184.  
  185. p = line;
  186. line += put_asciidump(line, code, len);
  187. line += put_space(line, HEXDUMP_WIDTH - (line - p));
  188. line += sprintf(line, " )\t");
  189.  
  190. if (dump)
  191. put_dump(line, code, len);
  192. else
  193. put_disassemble(line, code, len - 1);
  194.  
  195. /* the result of put_xxxx() terminates with '\0' */
  196.  
  197. return len;
  198. }
  199.  
  200. static void disassemble_all(void)
  201. {
  202. int i;
  203. char line[128];
  204.  
  205. printf("|%04x\n", OFFSET);
  206.  
  207. for (i = 0; i < filesize;) {
  208. i += build_line(line, i, &buf[i], filesize - i);
  209. printf("%s\n", line);
  210. }
  211. }
  212.  
  213. static int loadfile(char *filename)
  214. {
  215. int v = -1;
  216. FILE *fp;
  217.  
  218. fp = fopen(filename, "r");
  219. if (fp == NULL)
  220. goto fin0;
  221.  
  222. fseek(fp, 0, SEEK_END);
  223. filesize = ftell(fp);
  224. fseek(fp, 0, SEEK_SET);
  225.  
  226. buf = malloc(filesize);
  227. if (buf == NULL)
  228. goto fin1;
  229.  
  230. fread(buf, filesize, 1, fp);
  231. v = 0;
  232.  
  233. fin1:
  234. fclose(fp);
  235. fin0:
  236. return v;
  237. }
  238.  
  239. int main(int argc, char *argv[])
  240. {
  241. if (argc < 2) {
  242. printf("%s [filename]\n", argv[0]);
  243. goto fin0;
  244. }
  245.  
  246. if (loadfile(argv[1])) {
  247. printf("file open error\n");
  248. goto fin0;
  249. }
  250.  
  251. disassemble_all();
  252.  
  253. fin0:
  254. return 0;
  255. }
  256.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement