+global char* registers[] = {
+ "al", "cl", "dl", "bl",
+ "ah", "ch", "dh", "bh",
+ "ax", "cx", "dx", "bx",
+ "sp", "bp", "si", "di",
+};
+
+global char* eac[] = {
+ "bx + si",
+ "bx + di",
+ "bp + si",
+ "bp + di",
+ "si",
+ "di",
+ "bp",
+ "bx",
+};
+
+global u8 *code = 0;
+
+fn usize inst_move_regmem_tofrom_reg(void) {
+ u8 *lcode = code;
+ u8 d = (*lcode & 0b10) >> 1;
+ u8 w = *lcode & 0b1;
+ lcode += 1;
+ u8 mod = *lcode >> 6;
+ u8 reg = (*lcode >> 3) & (0b111);
+ u8 rm = *lcode & (0b111);
+ lcode += 1;
+
+ printf("mov ");
+ switch (mod) {
+ case 0b00: {
+ char *dest = registers[(w << 3) | reg];
+ if (rm == 0b110) {
+ if (d) {
+ if (w) {
+ printf("%s, [%u]\n", dest, (*lcode) | (*(lcode + 1) << 8));
+ lcode += 2;
+ } else {
+ printf("%s, [%u]\n", dest, *lcode);
+ lcode += 1;
+ }
+ } else {
+ if (w) {
+ printf("[%u], %s\n", (*lcode) | (*(lcode + 1) << 8), dest);
+ lcode += 2;
+ } else {
+ printf("[%u], %s\n", *lcode, dest);
+ lcode += 1;
+ }
+ }
+ } else {
+ if (d) {
+ printf("%s, [%s]\n", dest, eac[rm]);
+ } else {
+ printf("[%s], %s\n", eac[rm], dest);
+ }
+ }
+ } break;
+ case 0b01: {
+ char *dest = registers[(w << 3) | reg];
+ i8 disp = *lcode; // in displacement calculations values are signed
+ char sign = (disp < 0 ? '-' : '+');
+ disp = Abs(disp);
+ if (d) {
+ printf("%s, [%s %c %d]\n", dest, eac[rm], sign, disp);
+ } else {
+ printf("[%s %c %d], %s\n", eac[rm], sign, disp, dest);
+ }
+ lcode += 1;
+ } break;
+ case 0b10: {
+ char *dest = registers[(w << 3) | reg];
+ // in displacement calculations values are signed
+ i16 disp = *lcode | ((*(lcode + 1)) << 8);
+ char sign = (disp < 0 ? '-' : '+');
+ disp = Abs(disp);
+ if (d) {
+ printf("%s, [%s %c %u]\n", dest, eac[rm], sign, disp);
+ } else {
+ printf("[%s %c %u], %s\n", eac[rm], sign, disp, dest);
+ }
+ lcode += 2;
+ } break;
+ case 0b11: {
+ char *dest = d ? registers[(w << 3) | reg] : registers[(w << 3) | rm];
+ char *source = d ? registers[(w << 3) | rm] : registers[(w << 3) | reg];
+ printf("%s, %s\n", dest, source);
+ } break;
+ }
+
+ usize res = lcode - code;
+ code = lcode;
+ return res;
+}
+
+fn usize inst_move_imm_to_reg(void) {
+ u8 *lcode = code;
+ u8 w = (*lcode >> 3) & 0b1;
+ u8 reg = *lcode & 0b111;
+ lcode += 1;
+ printf("mov %s, ", registers[(w << 3) | reg]);
+ if (w) {
+ printf("%u\n", lcode[0] | (lcode[1] << 8));
+ lcode += 2;
+ } else {
+ printf("%u\n", *lcode++);
+ }
+ usize res = lcode - code;
+ code = lcode;
+ return res;
+}
+
+fn usize inst_move_imm_to_regmem(void) {
+ u8 *lcode = code;
+ u8 w = *lcode & 0b1;
+ lcode += 1;
+ u8 mod = *lcode >> 6;
+ u8 rm = *lcode & 0b111;
+ lcode += 1;
+
+ printf("mov ");
+ switch (mod) {
+ case 0b00: {
+ if (rm == 0b110) {
+ u8 *ofos_fset = lcode;
+ if (w) {
+ lcode += 1;
+ printf("[%u], word %u\n", *ofos_fset, *lcode | ((*(lcode + 1)) << 8));
+ } else {
+ printf("[%u], byte %u\n", *ofos_fset, *lcode);
+ }
+ } else {
+ if (w) {
+ printf("[%s], word %u\n", eac[rm], *lcode | ((*(lcode + 1)) << 8));
+ lcode += 2;
+ } else {
+ printf("[%s], byte %u\n", eac[rm], *lcode);
+ lcode += 1;
+ }
+ }
+ } break;
+ case 0b01: {
+ i8 disp = *lcode; // in displacement calculations values are signed
+ char sign = (disp < 0 ? '-' : '+');
+ disp = Abs(disp);
+ if (w) {
+ printf("[%s %c %d], word %d\n", eac[rm], sign, disp,
+ *lcode | ((*(lcode + 1)) << 8));
+ lcode += 2;
+ } else {
+ printf("[%s %c %d], byte %d\n", eac[rm], sign, disp, *lcode);
+ lcode += 1;
+ }
+ } break;
+ case 0b10: {
+ // in displacement calculations values are signed
+ i16 disp = *lcode | ((*(lcode + 1)) << 8);
+ lcode += 2;
+ char sign = (disp < 0 ? '-' : '+');
+ disp = Abs(disp);
+ if (w) {
+ printf("[%s %c %u], word %d\n", eac[rm], sign, disp,
+ *lcode | ((*(lcode + 1)) << 8));
+ lcode += 2;
+ } else {
+ printf("[%s %c %u], byte %d\n", eac[rm], sign, disp, *lcode);
+ lcode += 1;
+ }
+ } break;
+ case 0b11: {
+ if (w) {
+ printf("%s, %d\n", registers[(w << 3) | rm],
+ *lcode | ((*(lcode + 1)) << 8));
+ lcode += 2;
+ } else {
+ printf("%s, %d\n", registers[(w << 3) | rm], *lcode);
+ lcode += 1;
+ }
+ } break;
+ }
+ usize res = lcode - code;
+ code = lcode;
+ return res;
+}
+
+fn usize inst_move_mem_to_accum(u8 d) {
+ u8 *lcode = code;
+ u8 w = *lcode & 0b1;
+ lcode += 1;
+ if (d) {
+ if (w) {
+ printf("mov ax, [%u]\n", *lcode | (*(lcode + 1) << 8));
+ lcode += 2;
+ } else {
+ printf("mov al, [%u]\n", *lcode);
+ lcode += 1;
+ }
+ } else {
+ if (w) {
+ printf("mov [%u], ax\n", *lcode | (*(lcode + 1) << 8));
+ lcode += 2;
+ } else {
+ printf("mov [%u], al\n", *lcode);
+ lcode += 1;
+ }
+ }
+ usize res = lcode - code;
+ code = lcode;
+ return res;
+}
+
+inline fn i8 get_byte_displacement(void) {
+ code += 1;
+ i8 res = *code;
+ code += 1;
+ return res;
+}
+