fork(1) download
  1. #include <stdbool.h>
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6.  
  7. typedef struct instruction {
  8. size_t offset;
  9. unsigned int opcode;
  10. unsigned int mode;
  11. unsigned int rdest;
  12. unsigned int rsrc;
  13. uint16_t imm;
  14. } instruction;
  15.  
  16. static instruction instructions[16384];
  17. size_t num_instructions = 0;
  18.  
  19. static const char *op_names[] = {
  20. "MOVE", "OR", "XOR", "AND", "NOT", "ADD", "SUB", "MUL", "SHL", "SHR",
  21. "INC", "DEC", "PUSH", "POP", "CMP", "JNZ", "JZ",
  22. };
  23.  
  24. static void create_instructions(const uint8_t *code, size_t length)
  25. {
  26. for (size_t i = 0; i < length; i += 2) {
  27. unsigned int opt = code[i + 1];
  28.  
  29. instruction insn = {
  30. .offset = i,
  31. .opcode = code[i],
  32. .mode = opt & 15,
  33. .rdest = (opt >> 4) & 3,
  34. .rsrc = (opt >> 6) & 3,
  35. .imm = 0xbaadU,
  36. };
  37.  
  38. if (insn.opcode >= sizeof(op_names) / sizeof(op_names[0])) {
  39. fprintf(stderr, "Wrong opcode %u at %.8zx\n", insn.opcode, insn.offset);
  40. exit(1);
  41. }
  42.  
  43. if (insn.mode >= 4) {
  44. fprintf(stderr, "Wrong mode %u at %.8zx\n", insn.mode, insn.offset);
  45. exit(1);
  46. }
  47.  
  48. if (insn.mode == 0 || insn.mode == 2) {
  49. i += 2;
  50. insn.imm = code[i] | code[i + 1] << 8;
  51. }
  52. instructions[num_instructions++] = insn;
  53. }
  54. }
  55.  
  56. static void read_code(const char *filename)
  57. {
  58. static uint8_t code[65536];
  59.  
  60. FILE *fp = fopen(filename, "rb");
  61. if (!fp) {
  62. perror(filename);
  63. exit(1);
  64. }
  65.  
  66. size_t length = fread(code, 1, sizeof(code), fp);
  67. fclose(fp);
  68.  
  69. create_instructions(code, length);
  70. }
  71.  
  72. static void write_response(const char *filename, const uint16_t *regs)
  73. {
  74. FILE *fp = fopen(filename, "wb");
  75. if (!fp) {
  76. perror(filename);
  77. exit(1);
  78. }
  79. fprintf(fp, "%.4x %.4x %.4x %.4x\n", regs[0], regs[1], regs[2], regs[3]);
  80. fclose(fp);
  81. }
  82.  
  83. int main(int argc, char *argv[])
  84. {
  85. if (argc != 3) {
  86. fprintf(stderr, "usage: %s <input file> <output file>", argv[0]);
  87. return -1;
  88. }
  89.  
  90. read_code(argv[1]);
  91.  
  92. size_t ip = 0;
  93. uint16_t regs[4] = { 0 };
  94. uint16_t stack[256];
  95. size_t stackptr = 0;
  96. bool zf = false;
  97.  
  98. while (ip < num_instructions) {
  99. instruction *insn = &instructions[ip];
  100. uint16_t *dest = NULL;
  101. uint16_t *src = NULL;
  102. uint16_t imm = insn->imm;
  103.  
  104. printf("%.4zx: %s\t", ip, op_names[insn->opcode]);
  105.  
  106. switch (insn->mode) {
  107. case 0: // IMM.
  108. dest = &imm;
  109. printf("%.4x ", insn->imm);
  110. break;
  111. case 1: // REG.
  112. dest = &regs[insn->rdest];
  113. printf("r%u ", insn->rdest);
  114. break;
  115. case 2: // REG, IMM.
  116. dest = &regs[insn->rdest];
  117. src = &imm;
  118. printf("r%u, %.4x", insn->rdest, insn->imm);
  119. break;
  120. case 3: // REG, REG.
  121. dest = &regs[insn->rdest];
  122. src = &regs[insn->rsrc];
  123. printf("r%u, r%u ", insn->rdest, insn->rsrc);
  124. break;
  125. }
  126.  
  127. printf(" ; ");
  128. ++ip;
  129.  
  130. switch (insn->opcode) {
  131. case 0: // MOVE.
  132. *dest = *src;
  133. break;
  134. case 1: // OR.
  135. *dest = *dest | *src;
  136. break;
  137. case 2: // XOR.
  138. *dest = *dest ^ *src;
  139. break;
  140. case 3: // AND.
  141. *dest = *dest & *src;
  142. break;
  143. case 4: // NOT.
  144. *dest = ~*dest;
  145. break;
  146. case 5: // ADD.
  147. *dest += *src;
  148. break;
  149. case 6: // SUB.
  150. *dest -= *src;
  151. break;
  152. case 7: // MUL.
  153. *dest = *dest * *src;
  154. break;
  155. case 8: // SHL.
  156. *dest <<= *src;
  157. break;
  158. case 9: // SHR.
  159. *dest >>= *src;
  160. break;
  161. case 10: // INC.
  162. *dest += 1;
  163. break;
  164. case 11: // DEC.
  165. *dest -= 1;
  166. break;
  167. case 12: // PUSH.
  168. if (stackptr >= sizeof(stack) / sizeof(stack[0])) {
  169. fprintf(stderr, "Stack overflow\n");
  170. return 2;
  171. }
  172. stack[stackptr++] = *dest;
  173. break;
  174. case 13: // POP
  175. if (stackptr == 0) {
  176. fprintf(stderr, "Stack underflow\n");
  177. return 2;
  178. }
  179. *dest = stack[--stackptr];
  180. break;
  181. case 14: // CMP.
  182. zf = (*dest - *src) == 0;
  183. break;
  184. case 15: // JNZ.
  185. if (!zf) {
  186. ip = *dest;
  187. }
  188. break;
  189. case 16: // JZ.
  190. if (zf) {
  191. ip = *dest;
  192. }
  193. break;
  194. }
  195.  
  196. // Set ZF for arithmetical and logical instructions (except CMP).
  197. if (insn->opcode >= 1 && insn->opcode <= 11) {
  198. zf = *dest == 0;
  199. }
  200.  
  201. printf(" r0 = %.4x, r1 = %.4x, r2 = %.4x, r3 = %.4x, zf = %u\n",
  202. regs[0], regs[1], regs[2], regs[3], zf);
  203. }
  204.  
  205. write_response(argv[2], regs);
  206. return 0;
  207. }
  208.  
Runtime error #stdin #stdout #stderr 0s 9864KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
usage: ./prog <input file> <output file>