From 5ae2cc3a566ef891e9fda1b48fa79f4ad611a2d9 Mon Sep 17 00:00:00 2001 From: doyle Date: Sun, 16 Apr 2023 12:18:39 +1000 Subject: [PATCH] perfaware/part1: Support listing 0046 --- part1/build.bat | 8 + part1/listing_0046_add_sub_cmp | 1 + part1/listing_0046_add_sub_cmp.asm | 29 ++ part1/listing_0046_add_sub_cmp.txt | 16 ++ part1/sim8086.c | 418 +++++++++++++++++++++++------ project.rdbg | Bin 1934 -> 1991 bytes 6 files changed, 394 insertions(+), 78 deletions(-) create mode 100644 part1/listing_0046_add_sub_cmp create mode 100644 part1/listing_0046_add_sub_cmp.asm create mode 100644 part1/listing_0046_add_sub_cmp.txt diff --git a/part1/build.bat b/part1/build.bat index 96b1faa..d539379 100644 --- a/part1/build.bat +++ b/part1/build.bat @@ -77,3 +77,11 @@ copy /Y %script_dir%\%listing_0045%.txt %build_dir% 1>NUL set build_dir_listing_0045=%build_dir%\%listing_0045% %build_dir%\sim8086.exe --exec %build_dir_listing_0045% > %build_dir_listing_0045%_disassembled.txt fc /N %build_dir_listing_0045%.txt %build_dir_listing_0045%_disassembled.txt || exit /b 1 +set listing_0045=listing_0045_challenge_register_movs + +set listing_0046=listing_0046_add_sub_cmp +copy /Y %script_dir%\%listing_0046% %build_dir% 1>NUL +copy /Y %script_dir%\%listing_0046%.txt %build_dir% 1>NUL +set build_dir_listing_0046=%build_dir%\%listing_0046% +%build_dir%\sim8086.exe --exec %build_dir_listing_0046% > %build_dir_listing_0046%_disassembled.txt +fc /N %build_dir_listing_0046%.txt %build_dir_listing_0046%_disassembled.txt || exit /b 1 diff --git a/part1/listing_0046_add_sub_cmp b/part1/listing_0046_add_sub_cmp new file mode 100644 index 0000000..ba7e73d --- /dev/null +++ b/part1/listing_0046_add_sub_cmp @@ -0,0 +1 @@ +)˼9 \ No newline at end of file diff --git a/part1/listing_0046_add_sub_cmp.asm b/part1/listing_0046_add_sub_cmp.asm new file mode 100644 index 0000000..287e958 --- /dev/null +++ b/part1/listing_0046_add_sub_cmp.asm @@ -0,0 +1,29 @@ +; ======================================================================== +; +; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved. +; +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. +; +; Please see https://computerenhance.com for further information +; +; ======================================================================== + +; ======================================================================== +; LISTING 46 +; ======================================================================== + +bits 16 + +mov bx, -4093 +mov cx, 3841 +sub bx, cx + +mov sp, 998 +mov bp, 999 +cmp bp, sp + +add bp, 1027 +sub bp, 2026 + diff --git a/part1/listing_0046_add_sub_cmp.txt b/part1/listing_0046_add_sub_cmp.txt new file mode 100644 index 0000000..4b27dba --- /dev/null +++ b/part1/listing_0046_add_sub_cmp.txt @@ -0,0 +1,16 @@ +--- test\listing_0046_add_sub_cmp execution --- +mov bx, 61443 ; bx:0x0->0xf003 +mov cx, 3841 ; cx:0x0->0xf01 +sub bx, cx ; bx:0xf003->0xe102 flags:->S +mov sp, 998 ; sp:0x0->0x3e6 +mov bp, 999 ; bp:0x0->0x3e7 +cmp bp, sp ; flags:S-> +add bp, 1027 ; bp:0x3e7->0x7ea +sub bp, 2026 ; bp:0x7ea->0x0 flags:->PZ + +Final registers: + bx: 0xe102 (57602) + cx: 0x0f01 (3841) + sp: 0x03e6 (998) + flags: PZ + diff --git a/part1/sim8086.c b/part1/sim8086.c index e3206e3..515ea21 100644 --- a/part1/sim8086.c +++ b/part1/sim8086.c @@ -3,22 +3,40 @@ #include "sim8086_stdlib.c" -typedef struct RegisterFile { - uint16_t ax; - uint16_t cx; - uint16_t dx; - uint16_t bx; +typedef enum S86_RegisterByte { + S86_RegisterByte_Lo, + S86_RegisterByte_Hi, + S86_RegisterByte_Count, + S86_RegisterByte_Nil, +} S86_RegisterByte; - uint16_t sp; - uint16_t bp; - uint16_t si; - uint16_t di; +typedef union S86_Register16 { + uint16_t word; + struct { uint8_t lo; uint8_t hi; } byte; + uint8_t bytes[S86_RegisterByte_Count]; +} S86_Register16; - uint16_t es; - uint16_t cs; - uint16_t ss; - uint16_t ds; -} RegisterFile; +typedef struct S86_RegisterFile { + bool zero_flag; + bool sign_flag; + bool parity_flag; + bool overflow_flag; + + S86_Register16 ax; + S86_Register16 bx; + S86_Register16 cx; + S86_Register16 dx; + + S86_Register16 sp; + S86_Register16 bp; + S86_Register16 si; + S86_Register16 di; + + S86_Register16 es; + S86_Register16 cs; + S86_Register16 ss; + S86_Register16 ds; +} S86_RegisterFile; S86_Str8 S86_MnemonicStr8(S86_Mnemonic type) { @@ -298,7 +316,7 @@ void S86_DecodeEffectiveAddr(S86_Opcode *opcode, S86_BufferIterator *buffer_it, opcode->dest = S86_MnemonicOpFromWReg(w, rm); } else { // NOTE: Effective address calculation w/ displacement - // ========================================================================= + // ===================================================================== opcode->effective_addr_loads_mem = true; if (direct_address) { opcode->dest = S86_MnemonicOp_DirectAddress; @@ -799,12 +817,10 @@ S86_Opcode S86_DecodeOpcode(S86_BufferIterator *buffer_it, typedef struct S86_MnemonicOpToRegisterFileMap { S86_MnemonicOp mnemonic_op; ///< Register/op that the mnemonic is using S86_MnemonicOp mnemonic_op_reg16; ///< 16 bit register for the mnemonic op - uint16_t mask; ///< Mask for the bits that the mnemonic op is using (hi/lo/full bit coverage) - uint16_t r_shift; ///< Shift amount for isolating the masked value - uint16_t *reg; ///< Pointer to the register memory this mnemonic op is using + S86_Register16 *reg; ///< Pointer to the register memory this mnemonic op is using + S86_RegisterByte byte; ///< The 'byte' that the mnemonic operates on (hi, lo or nil e.g. word) } S86_MnemonicOpToRegisterFileMap; - #define PRINT_USAGE S86_PrintLn(S86_STR8("usage: sim8086.exe [--exec] ")) int main(int argc, char **argv) { @@ -1143,37 +1159,37 @@ int main(int argc, char **argv) else S86_PrintLn(S86_STR8("bits 16")); - RegisterFile register_file = {0}; - S86_BufferIterator buffer_it = S86_BufferIteratorInit(buffer); - S86_MnemonicOp seg_reg = {0}; - bool lock_prefix = false; + S86_RegisterFile register_file = {0}; + S86_BufferIterator buffer_it = S86_BufferIteratorInit(buffer); + S86_MnemonicOp seg_reg = {0}; + bool lock_prefix = false; S86_MnemonicOpToRegisterFileMap mnemonic_op_to_register_file_map[] = { - {.mnemonic_op = S86_MnemonicOp_AX, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = ®ister_file.ax, .mask = 0xFFFF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_AL, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = ®ister_file.ax, .mask = 0x00FF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_AH, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = ®ister_file.ax, .mask = 0xFF00, .r_shift = 8}, + {.mnemonic_op = S86_MnemonicOp_AX, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = ®ister_file.ax, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_AL, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = ®ister_file.ax, .byte = S86_RegisterByte_Lo}, + {.mnemonic_op = S86_MnemonicOp_AH, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = ®ister_file.ax, .byte = S86_RegisterByte_Hi}, - {.mnemonic_op = S86_MnemonicOp_CX, .mnemonic_op_reg16 = S86_MnemonicOp_CX, .reg = ®ister_file.cx, .mask = 0xFFFF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_CL, .mnemonic_op_reg16 = S86_MnemonicOp_CX, .reg = ®ister_file.cx, .mask = 0x00FF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_CH, .mnemonic_op_reg16 = S86_MnemonicOp_CX, .reg = ®ister_file.cx, .mask = 0xFF00, .r_shift = 8}, + {.mnemonic_op = S86_MnemonicOp_CX, .mnemonic_op_reg16 = S86_MnemonicOp_CX, .reg = ®ister_file.cx, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_CL, .mnemonic_op_reg16 = S86_MnemonicOp_CX, .reg = ®ister_file.cx, .byte = S86_RegisterByte_Lo}, + {.mnemonic_op = S86_MnemonicOp_CH, .mnemonic_op_reg16 = S86_MnemonicOp_CX, .reg = ®ister_file.cx, .byte = S86_RegisterByte_Lo}, - {.mnemonic_op = S86_MnemonicOp_DX, .mnemonic_op_reg16 = S86_MnemonicOp_DX, .reg = ®ister_file.dx, .mask = 0xFFFF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_DL, .mnemonic_op_reg16 = S86_MnemonicOp_DX, .reg = ®ister_file.dx, .mask = 0x00FF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_DH, .mnemonic_op_reg16 = S86_MnemonicOp_DX, .reg = ®ister_file.dx, .mask = 0xFF00, .r_shift = 8}, + {.mnemonic_op = S86_MnemonicOp_DX, .mnemonic_op_reg16 = S86_MnemonicOp_DX, .reg = ®ister_file.dx, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_DL, .mnemonic_op_reg16 = S86_MnemonicOp_DX, .reg = ®ister_file.dx, .byte = S86_RegisterByte_Lo}, + {.mnemonic_op = S86_MnemonicOp_DH, .mnemonic_op_reg16 = S86_MnemonicOp_DX, .reg = ®ister_file.dx, .byte = S86_RegisterByte_Hi}, - {.mnemonic_op = S86_MnemonicOp_BX, .mnemonic_op_reg16 = S86_MnemonicOp_BX, .reg = ®ister_file.bx, .mask = 0xFFFF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_BL, .mnemonic_op_reg16 = S86_MnemonicOp_BX, .reg = ®ister_file.bx, .mask = 0x00FF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_BH, .mnemonic_op_reg16 = S86_MnemonicOp_BX, .reg = ®ister_file.bx, .mask = 0xFF00, .r_shift = 8}, + {.mnemonic_op = S86_MnemonicOp_BX, .mnemonic_op_reg16 = S86_MnemonicOp_BX, .reg = ®ister_file.bx, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_BL, .mnemonic_op_reg16 = S86_MnemonicOp_BX, .reg = ®ister_file.bx, .byte = S86_RegisterByte_Lo}, + {.mnemonic_op = S86_MnemonicOp_BH, .mnemonic_op_reg16 = S86_MnemonicOp_BX, .reg = ®ister_file.bx, .byte = S86_RegisterByte_Hi}, - {.mnemonic_op = S86_MnemonicOp_SP, .mnemonic_op_reg16 = S86_MnemonicOp_SP, .reg = ®ister_file.sp, .mask = 0xFFFF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_BP, .mnemonic_op_reg16 = S86_MnemonicOp_BP, .reg = ®ister_file.bp, .mask = 0xFFFF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_SI, .mnemonic_op_reg16 = S86_MnemonicOp_SI, .reg = ®ister_file.si, .mask = 0xFFFF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_DI, .mnemonic_op_reg16 = S86_MnemonicOp_DI, .reg = ®ister_file.di, .mask = 0xFFFF, .r_shift = 0}, + {.mnemonic_op = S86_MnemonicOp_SP, .mnemonic_op_reg16 = S86_MnemonicOp_SP, .reg = ®ister_file.sp, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_BP, .mnemonic_op_reg16 = S86_MnemonicOp_BP, .reg = ®ister_file.bp, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_SI, .mnemonic_op_reg16 = S86_MnemonicOp_SI, .reg = ®ister_file.si, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_DI, .mnemonic_op_reg16 = S86_MnemonicOp_DI, .reg = ®ister_file.di, .byte = S86_RegisterByte_Nil}, - {.mnemonic_op = S86_MnemonicOp_ES, .mnemonic_op_reg16 = S86_MnemonicOp_ES, .reg = ®ister_file.es, .mask = 0xFFFF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_CS, .mnemonic_op_reg16 = S86_MnemonicOp_CS, .reg = ®ister_file.cs, .mask = 0xFFFF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_SS, .mnemonic_op_reg16 = S86_MnemonicOp_SS, .reg = ®ister_file.ss, .mask = 0xFFFF, .r_shift = 0}, - {.mnemonic_op = S86_MnemonicOp_DS, .mnemonic_op_reg16 = S86_MnemonicOp_DS, .reg = ®ister_file.ds, .mask = 0xFFFF, .r_shift = 0}, + {.mnemonic_op = S86_MnemonicOp_ES, .mnemonic_op_reg16 = S86_MnemonicOp_ES, .reg = ®ister_file.es, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_CS, .mnemonic_op_reg16 = S86_MnemonicOp_CS, .reg = ®ister_file.cs, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_SS, .mnemonic_op_reg16 = S86_MnemonicOp_SS, .reg = ®ister_file.ss, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_DS, .mnemonic_op_reg16 = S86_MnemonicOp_DS, .reg = ®ister_file.ds, .byte = S86_RegisterByte_Nil}, }; while (S86_BufferIteratorHasMoreBytes(buffer_it)) { @@ -1186,56 +1202,302 @@ int main(int argc, char **argv) if (opcode.mnemonic == S86_Mnemonic_LOCK || opcode.mnemonic == S86_Mnemonic_SEGMENT) continue; - if (exec_mode && opcode.mnemonic == S86_Mnemonic_MOV) { - S86_MnemonicOpToRegisterFileMap const *dest_map = NULL; - for (size_t index = 0; !dest_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { - S86_MnemonicOpToRegisterFileMap const *item = mnemonic_op_to_register_file_map + index; - if (item->mnemonic_op == opcode.dest) - dest_map = item; - } + if (!exec_mode) { + S86_Print(S86_STR8("\n")); + continue; + } - S86_ASSERT(dest_map); - uint16_t *dest = dest_map->reg; - uint16_t src = 0; + bool prev_sign_flag = register_file.sign_flag; + bool prev_zero_flag = register_file.zero_flag; + switch (opcode.mnemonic) { + case S86_Mnemonic_PUSH: /*FALLTHRU*/ + case S86_Mnemonic_POP: /*FALLTHRU*/ + case S86_Mnemonic_XCHG: /*FALLTHRU*/ + case S86_Mnemonic_IN: /*FALLTHRU*/ + case S86_Mnemonic_OUT: /*FALLTHRU*/ + case S86_Mnemonic_XLAT: /*FALLTHRU*/ + case S86_Mnemonic_LEA: /*FALLTHRU*/ + case S86_Mnemonic_LDS: /*FALLTHRU*/ + case S86_Mnemonic_LES: /*FALLTHRU*/ + case S86_Mnemonic_LAHF: /*FALLTHRU*/ + case S86_Mnemonic_SAHF: /*FALLTHRU*/ + case S86_Mnemonic_PUSHF: /*FALLTHRU*/ + case S86_Mnemonic_POPF: /*FALLTHRU*/ + case S86_Mnemonic_ADC: /*FALLTHRU*/ + case S86_Mnemonic_INC: /*FALLTHRU*/ + case S86_Mnemonic_AAA: /*FALLTHRU*/ + case S86_Mnemonic_DAA: /*FALLTHRU*/ + case S86_Mnemonic_SBB: /*FALLTHRU*/ + case S86_Mnemonic_DEC: /*FALLTHRU*/ + case S86_Mnemonic_NEG: /*FALLTHRU*/ + case S86_Mnemonic_AAS: /*FALLTHRU*/ + case S86_Mnemonic_DAS: /*FALLTHRU*/ + case S86_Mnemonic_MUL: /*FALLTHRU*/ + case S86_Mnemonic_IMUL: /*FALLTHRU*/ + case S86_Mnemonic_AAM: /*FALLTHRU*/ + case S86_Mnemonic_DIV: /*FALLTHRU*/ + case S86_Mnemonic_IDIV: /*FALLTHRU*/ + case S86_Mnemonic_AAD: /*FALLTHRU*/ + case S86_Mnemonic_CBW: /*FALLTHRU*/ + case S86_Mnemonic_CWD: /*FALLTHRU*/ + case S86_Mnemonic_NOT: /*FALLTHRU*/ + case S86_Mnemonic_SHL_SAL: /*FALLTHRU*/ + case S86_Mnemonic_SHR: /*FALLTHRU*/ + case S86_Mnemonic_SAR: /*FALLTHRU*/ + case S86_Mnemonic_ROL: /*FALLTHRU*/ + case S86_Mnemonic_ROR: /*FALLTHRU*/ + case S86_Mnemonic_RCL: /*FALLTHRU*/ + case S86_Mnemonic_RCR: /*FALLTHRU*/ + case S86_Mnemonic_AND: /*FALLTHRU*/ + case S86_Mnemonic_TEST: /*FALLTHRU*/ + case S86_Mnemonic_OR: /*FALLTHRU*/ + case S86_Mnemonic_XOR: /*FALLTHRU*/ + case S86_Mnemonic_REP: /*FALLTHRU*/ + case S86_Mnemonic_CALL: /*FALLTHRU*/ + case S86_Mnemonic_JMP: /*FALLTHRU*/ + case S86_Mnemonic_RET: /*FALLTHRU*/ + case S86_Mnemonic_JE_JZ: /*FALLTHRU*/ + case S86_Mnemonic_JL_JNGE: /*FALLTHRU*/ + case S86_Mnemonic_JLE_JNG: /*FALLTHRU*/ + case S86_Mnemonic_JB_JNAE: /*FALLTHRU*/ + case S86_Mnemonic_JBE_JNA: /*FALLTHRU*/ + case S86_Mnemonic_JP_JPE: /*FALLTHRU*/ + case S86_Mnemonic_JO: /*FALLTHRU*/ + case S86_Mnemonic_JS: /*FALLTHRU*/ + case S86_Mnemonic_JNE_JNZ: /*FALLTHRU*/ + case S86_Mnemonic_JNL_JGE: /*FALLTHRU*/ + case S86_Mnemonic_JNLE_JG: /*FALLTHRU*/ + case S86_Mnemonic_JNB_JAE: /*FALLTHRU*/ + case S86_Mnemonic_JNBE_JA: /*FALLTHRU*/ + case S86_Mnemonic_JNP_JO: /*FALLTHRU*/ + case S86_Mnemonic_JNO: /*FALLTHRU*/ + case S86_Mnemonic_JNS: /*FALLTHRU*/ + case S86_Mnemonic_LOOP: /*FALLTHRU*/ + case S86_Mnemonic_LOOPZ_LOOPE: /*FALLTHRU*/ + case S86_Mnemonic_LOOPNZ_LOOPNE: /*FALLTHRU*/ + case S86_Mnemonic_JCXZ: /*FALLTHRU*/ + case S86_Mnemonic_INT: /*FALLTHRU*/ + case S86_Mnemonic_INT3: /*FALLTHRU*/ + case S86_Mnemonic_INTO: /*FALLTHRU*/ + case S86_Mnemonic_IRET: /*FALLTHRU*/ + case S86_Mnemonic_CLC: /*FALLTHRU*/ + case S86_Mnemonic_CMC: /*FALLTHRU*/ + case S86_Mnemonic_STC: /*FALLTHRU*/ + case S86_Mnemonic_CLD: /*FALLTHRU*/ + case S86_Mnemonic_STD: /*FALLTHRU*/ + case S86_Mnemonic_CLI: /*FALLTHRU*/ + case S86_Mnemonic_STI: /*FALLTHRU*/ + case S86_Mnemonic_HLT: /*FALLTHRU*/ + case S86_Mnemonic_WAIT: /*FALLTHRU*/ + case S86_Mnemonic_LOCK: /*FALLTHRU*/ + case S86_Mnemonic_SEGMENT: break; - if (opcode.src == S86_MnemonicOp_Immediate) { - src = (uint16_t)opcode.immediate; - } else if ((opcode.src >= S86_MnemonicOp_AL && opcode.src <= S86_MnemonicOp_DI) || - (opcode.src >= S86_MnemonicOp_ES && opcode.src <= S86_MnemonicOp_DS)) { - S86_MnemonicOpToRegisterFileMap const *src_map = NULL; - for (size_t index = 0; !src_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { + case S86_Mnemonic_MOV: { + S86_MnemonicOpToRegisterFileMap const *dest_map = NULL; + for (size_t index = 0; !dest_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { S86_MnemonicOpToRegisterFileMap const *item = mnemonic_op_to_register_file_map + index; - if (item->mnemonic_op == opcode.src) - src_map = item; + if (item->mnemonic_op == opcode.dest) + dest_map = item; + } + S86_ASSERT(dest_map); + + uint16_t prev_dest = dest_map->reg->word; + bool byte_op = opcode.dest >= S86_MnemonicOp_AL && opcode.dest <= S86_MnemonicOp_BH; + if (opcode.src == S86_MnemonicOp_Immediate) { + if (byte_op) { + S86_ASSERT(opcode.immediate < S86_CAST(uint8_t)-1); + dest_map->reg->bytes[dest_map->byte] = S86_CAST(uint8_t)opcode.immediate; + } else { + S86_ASSERT(opcode.immediate < S86_CAST(uint16_t)-1); + dest_map->reg->word = S86_CAST(uint16_t)opcode.immediate; + } + } else { + S86_MnemonicOpToRegisterFileMap const *src_map = NULL; + for (size_t index = 0; !src_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { + S86_MnemonicOpToRegisterFileMap const *item = mnemonic_op_to_register_file_map + index; + if (item->mnemonic_op == opcode.src) + src_map = item; + } + + if (byte_op) + dest_map->reg->bytes[dest_map->byte] = src_map->reg->bytes[src_map->byte]; + else + dest_map->reg->word = src_map->reg->word; } - src = (*src_map->reg & src_map->mask) >> src_map->r_shift; - } + S86_Str8 dest_reg16 = S86_MnemonicOpStr8(dest_map->mnemonic_op_reg16); + S86_PrintFmt(" ; %.*s:0x%x->0x%x ", S86_STR8_FMT(dest_reg16), prev_dest, dest_map->reg->word); + } break; - S86_Str8 dest_reg16 = S86_MnemonicOpStr8(dest_map->mnemonic_op_reg16); - uint16_t new_dest = (*dest & ~dest_map->mask) | (src << dest_map->r_shift); - S86_PrintFmt(" ; %.*s:0x%x->0x%x ", S86_STR8_FMT(dest_reg16), *dest, new_dest); - *dest = new_dest; + case S86_Mnemonic_ADD: { + S86_MnemonicOpToRegisterFileMap const *dest_map = NULL; + for (size_t index = 0; !dest_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { + S86_MnemonicOpToRegisterFileMap const *item = mnemonic_op_to_register_file_map + index; + if (item->mnemonic_op == opcode.dest) + dest_map = item; + } + S86_ASSERT(dest_map); + + uint16_t prev_dest = dest_map->reg->word; + bool byte_op = opcode.dest >= S86_MnemonicOp_AL && opcode.dest <= S86_MnemonicOp_BH; + if (opcode.src == S86_MnemonicOp_Immediate) { + if (byte_op) { + S86_ASSERT(opcode.immediate < S86_CAST(uint8_t)-1); + dest_map->reg->bytes[dest_map->byte] += S86_CAST(uint8_t)opcode.immediate; + } else { + S86_ASSERT(opcode.immediate < S86_CAST(uint16_t)-1); + dest_map->reg->word += S86_CAST(uint16_t)opcode.immediate; + } + } else { + S86_MnemonicOpToRegisterFileMap const *src_map = NULL; + for (size_t index = 0; !src_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { + S86_MnemonicOpToRegisterFileMap const *item = mnemonic_op_to_register_file_map + index; + if (item->mnemonic_op == opcode.src) + src_map = item; + } + + if (byte_op) + dest_map->reg->bytes[dest_map->byte] += src_map->reg->bytes[src_map->byte]; + else + dest_map->reg->word += src_map->reg->word; + } + + S86_Str8 dest_reg16 = S86_MnemonicOpStr8(dest_map->mnemonic_op_reg16); + + register_file.sign_flag = dest_map->reg->word & (byte_op ? 0b0000'0000'1000'0000 : 0b1000'0000'0000'0000); + S86_PrintFmt(" ; %.*s:0x%x->0x%x ", S86_STR8_FMT(dest_reg16), prev_dest, dest_map->reg->word); + } break; + + case S86_Mnemonic_SUB: { + S86_MnemonicOpToRegisterFileMap const *dest_map = NULL; + for (size_t index = 0; !dest_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { + S86_MnemonicOpToRegisterFileMap const *item = mnemonic_op_to_register_file_map + index; + if (item->mnemonic_op == opcode.dest) + dest_map = item; + } + S86_ASSERT(dest_map); + + uint16_t prev_dest = dest_map->reg->word; + bool byte_op = opcode.dest >= S86_MnemonicOp_AL && opcode.dest <= S86_MnemonicOp_BH; + if (opcode.src == S86_MnemonicOp_Immediate) { + if (byte_op) { + S86_ASSERT(opcode.immediate < S86_CAST(uint8_t)-1); + dest_map->reg->bytes[dest_map->byte] -= S86_CAST(uint8_t)opcode.immediate; + } else { + S86_ASSERT(opcode.immediate < S86_CAST(uint16_t)-1); + dest_map->reg->word -= S86_CAST(uint16_t)opcode.immediate; + } + } else { + S86_MnemonicOpToRegisterFileMap const *src_map = NULL; + for (size_t index = 0; !src_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { + S86_MnemonicOpToRegisterFileMap const *item = mnemonic_op_to_register_file_map + index; + if (item->mnemonic_op == opcode.src) + src_map = item; + } + + if (byte_op) + dest_map->reg->bytes[dest_map->byte] -= src_map->reg->bytes[src_map->byte]; + else + dest_map->reg->word -= src_map->reg->word; + } + + S86_Str8 dest_reg16 = S86_MnemonicOpStr8(dest_map->mnemonic_op_reg16); + + register_file.zero_flag = byte_op ? dest_map->reg->bytes[dest_map->byte] == 0 : dest_map->reg->word == 0; + register_file.sign_flag = dest_map->reg->word & (byte_op ? 0b0000'0000'1000'0000 : 0b1000'0000'0000'0000); + S86_PrintFmt(" ; %.*s:0x%x->0x%x ", S86_STR8_FMT(dest_reg16), prev_dest, dest_map->reg->word); + } break; + + case S86_Mnemonic_CMP: { + S86_MnemonicOpToRegisterFileMap const *dest_map = NULL; + for (size_t index = 0; !dest_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { + S86_MnemonicOpToRegisterFileMap const *item = mnemonic_op_to_register_file_map + index; + if (item->mnemonic_op == opcode.dest) + dest_map = item; + } + S86_ASSERT(dest_map); + + S86_Register16 dest_copy = *dest_map->reg; + S86_Register16 *dest = &dest_copy; + + bool byte_op = opcode.dest >= S86_MnemonicOp_AL && opcode.dest <= S86_MnemonicOp_BH; + if (opcode.src == S86_MnemonicOp_Immediate) { + if (byte_op) { + S86_ASSERT(opcode.immediate < S86_CAST(uint8_t)-1); + dest->bytes[dest_map->byte] -= S86_CAST(uint8_t)opcode.immediate; + } else { + S86_ASSERT(opcode.immediate < S86_CAST(uint16_t)-1); + dest->word -= S86_CAST(uint16_t)opcode.immediate; + } + } else { + S86_MnemonicOpToRegisterFileMap const *src_map = NULL; + for (size_t index = 0; !src_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { + S86_MnemonicOpToRegisterFileMap const *item = mnemonic_op_to_register_file_map + index; + if (item->mnemonic_op == opcode.src) + src_map = item; + } + + if (byte_op) + dest->bytes[dest_map->byte] -= src_map->reg->bytes[src_map->byte]; + else + dest->word -= src_map->reg->word; + } + + register_file.sign_flag = dest_map->reg->word & (byte_op ? 0b0000'0000'1000'0000 : 0b1000'0000'0000'0000); + S86_PrintFmt(" ; "); + } break; + } + + if (register_file.sign_flag != prev_sign_flag) { + if (register_file.sign_flag) { + S86_PrintFmt("flags:->S "); + } else { + S86_PrintFmt("flags:S-> "); + } + } + + if (register_file.zero_flag != prev_zero_flag) { + if (register_file.zero_flag) { + S86_PrintFmt("flags:->PZ "); + } else { + S86_PrintFmt("flags:PZ-> "); + } } S86_Print(S86_STR8("\n")); } if (exec_mode) { S86_PrintLn(S86_STR8("\nFinal registers:")); - S86_PrintLnFmt(" ax: 0x%04x (%u)", register_file.ax, register_file.ax); - S86_PrintLnFmt(" bx: 0x%04x (%u)", register_file.bx, register_file.bx); - S86_PrintLnFmt(" cx: 0x%04x (%u)", register_file.cx, register_file.cx); - S86_PrintLnFmt(" dx: 0x%04x (%u)", register_file.dx, register_file.dx); - S86_PrintLnFmt(" sp: 0x%04x (%u)", register_file.sp, register_file.sp); - S86_PrintLnFmt(" bp: 0x%04x (%u)", register_file.bp, register_file.bp); - S86_PrintLnFmt(" si: 0x%04x (%u)", register_file.si, register_file.si); - S86_PrintLnFmt(" di: 0x%04x (%u)", register_file.di, register_file.di); - if (register_file.es) + if (register_file.ax.word) + S86_PrintLnFmt(" ax: 0x%04x (%u)", register_file.ax.word, register_file.ax.word); + if (register_file.bx.word) + S86_PrintLnFmt(" bx: 0x%04x (%u)", register_file.bx.word, register_file.bx.word); + if (register_file.cx.word) + S86_PrintLnFmt(" cx: 0x%04x (%u)", register_file.cx.word, register_file.cx.word); + if (register_file.dx.word) + S86_PrintLnFmt(" dx: 0x%04x (%u)", register_file.dx.word, register_file.dx.word); + if (register_file.sp.word) + S86_PrintLnFmt(" sp: 0x%04x (%u)", register_file.sp.word, register_file.sp.word); + if (register_file.bp.word) + S86_PrintLnFmt(" bp: 0x%04x (%u)", register_file.bp.word, register_file.bp.word); + if (register_file.si.word) + S86_PrintLnFmt(" si: 0x%04x (%u)", register_file.si.word, register_file.si.word); + if (register_file.di.word) + S86_PrintLnFmt(" di: 0x%04x (%u)", register_file.di.word, register_file.di.word); + if (register_file.es.word) S86_PrintLnFmt(" es: 0x%04x (%u)", register_file.es, register_file.es); - if (register_file.ss) + if (register_file.ss.word) S86_PrintLnFmt(" ss: 0x%04x (%u)", register_file.ss, register_file.ss); - if (register_file.ds) + if (register_file.ds.word) S86_PrintLnFmt(" ds: 0x%04x (%u)", register_file.ds, register_file.ds); + if (register_file.zero_flag || register_file.sign_flag) { + S86_PrintFmt(" flags:"); + if (register_file.zero_flag) + S86_PrintFmt(" PZ"); + if (register_file.sign_flag) + S86_PrintFmt(" S"); + S86_Print(S86_STR8("\n")); + } S86_Print(S86_STR8("\n")); } } diff --git a/project.rdbg b/project.rdbg index 4d5acbb623b36e4b195630193fe32b6f14c9912f..9768cde715feebcf7e809e4dc2fea658f4f84549 100644 GIT binary patch delta 173 zcmeC zPoBx@Vki$(sH>Y=k(#WKlUZDnnU@}KU|?bvpO}&oUtF3LpPX9&Q~?2;K#F~GBbz)g s$aoND1Og_Yh`KNrlm`-FWaI$yK;jy#3?PZgg6!gxkFcEr(h`hj0QwRprT_o{ delta 146 zcmX@k-^V{;10(CkjjoInb6m`Ju`n<&F)%Q20C7rcaY=k`VgW0VotBxGm;++4asNC5 z!Xkz5SAwu~>65>#lMC5o7&#{=vbb+