diff --git a/part1/build.bat b/part1/build.bat index 1ca2ac3..83dfefb 100644 --- a/part1/build.bat +++ b/part1/build.bat @@ -190,3 +190,33 @@ nasm %build_dir_listing_0050%_disassembled.asm fc /B %build_dir_listing_0050% %build_dir_listing_0050%_disassembled || exit /b 1 fc /N %build_dir_listing_0050%.txt %build_dir_listing_0050%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0051=listing_0051_memory_mov +set build_dir_listing_0051=%build_dir%\%listing_0051% + +copy /Y %script_dir%\%listing_0051% %build_dir% 1>NUL +copy /Y %script_dir%\%listing_0051%.txt %build_dir% 1>NUL + +%build_dir%\sim8086.exe --exec --log-instruction-ptr %build_dir_listing_0051% > %build_dir_listing_0051%_disassembled.txt +%build_dir%\sim8086.exe %build_dir_listing_0051% > %build_dir_listing_0051%_disassembled.asm + +nasm %build_dir_listing_0051%_disassembled.asm + +fc /B %build_dir_listing_0051% %build_dir_listing_0051%_disassembled || exit /b 1 +fc /N %build_dir_listing_0051%.txt %build_dir_listing_0051%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0052=listing_0052_memory_add_loop +set build_dir_listing_0052=%build_dir%\%listing_0052% + +copy /Y %script_dir%\%listing_0052% %build_dir% 1>NUL +copy /Y %script_dir%\%listing_0052%.txt %build_dir% 1>NUL + +%build_dir%\sim8086.exe --exec --log-instruction-ptr %build_dir_listing_0052% > %build_dir_listing_0052%_disassembled.txt +%build_dir%\sim8086.exe %build_dir_listing_0052% > %build_dir_listing_0052%_disassembled.asm + +nasm %build_dir_listing_0052%_disassembled.asm + +fc /B %build_dir_listing_0052% %build_dir_listing_0052%_disassembled || exit /b 1 +fc /N %build_dir_listing_0052%.txt %build_dir_listing_0052%_disassembled.txt || exit /b 1 diff --git a/part1/listing_0051_memory_mov b/part1/listing_0051_memory_mov new file mode 100644 index 0000000..6907cff Binary files /dev/null and b/part1/listing_0051_memory_mov differ diff --git a/part1/listing_0051_memory_mov.asm b/part1/listing_0051_memory_mov.asm new file mode 100644 index 0000000..d27e348 --- /dev/null +++ b/part1/listing_0051_memory_mov.asm @@ -0,0 +1,30 @@ +; ======================================================================== +; +; (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 51 +; ======================================================================== + +bits 16 + +mov word [1000], 1 +mov word [1002], 2 +mov word [1004], 3 +mov word [1006], 4 + +mov bx, 1000 +mov word [bx + 4], 10 + +mov bx, word [1000] +mov cx, word [1002] +mov dx, word [1004] +mov bp, word [1006] diff --git a/part1/listing_0051_memory_mov.txt b/part1/listing_0051_memory_mov.txt new file mode 100644 index 0000000..e1ce4b0 --- /dev/null +++ b/part1/listing_0051_memory_mov.txt @@ -0,0 +1,19 @@ +--- test\listing_0051_memory_mov execution --- +mov word [+1000], 1 ; ip:0x0->0x6 +mov word [+1002], 2 ; ip:0x6->0xc +mov word [+1004], 3 ; ip:0xc->0x12 +mov word [+1006], 4 ; ip:0x12->0x18 +mov bx, 1000 ; bx:0x0->0x3e8 ip:0x18->0x1b +mov word [bx+4], 10 ; ip:0x1b->0x20 +mov bx, [+1000] ; bx:0x3e8->0x1 ip:0x20->0x24 +mov cx, [+1002] ; cx:0x0->0x2 ip:0x24->0x28 +mov dx, [+1004] ; dx:0x0->0xa ip:0x28->0x2c +mov bp, [+1006] ; bp:0x0->0x4 ip:0x2c->0x30 + +Final registers: + bx: 0x0001 (1) + cx: 0x0002 (2) + dx: 0x000a (10) + bp: 0x0004 (4) + ip: 0x0030 (48) + diff --git a/part1/listing_0052_memory_add_loop b/part1/listing_0052_memory_add_loop new file mode 100644 index 0000000..1f6d274 Binary files /dev/null and b/part1/listing_0052_memory_add_loop differ diff --git a/part1/listing_0052_memory_add_loop.asm b/part1/listing_0052_memory_add_loop.asm new file mode 100644 index 0000000..189ed32 --- /dev/null +++ b/part1/listing_0052_memory_add_loop.asm @@ -0,0 +1,36 @@ +; ======================================================================== +; +; (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 52 +; ======================================================================== + +bits 16 + +mov dx, 6 +mov bp, 1000 + +mov si, 0 +init_loop_start: + mov word [bp + si], si + add si, 2 + cmp si, dx + jnz init_loop_start + +mov bx, 0 +mov si, 0 +add_loop_start: + mov cx, word [bp + si] + add bx, cx + add si, 2 + cmp si, dx + jnz add_loop_start diff --git a/part1/listing_0052_memory_add_loop.txt b/part1/listing_0052_memory_add_loop.txt new file mode 100644 index 0000000..14da357 --- /dev/null +++ b/part1/listing_0052_memory_add_loop.txt @@ -0,0 +1,43 @@ +--- test\listing_0052_memory_add_loop execution --- +mov dx, 6 ; dx:0x0->0x6 ip:0x0->0x3 +mov bp, 1000 ; bp:0x0->0x3e8 ip:0x3->0x6 +mov si, 0 ; ip:0x6->0x9 +mov word [bp+si], si ; ip:0x9->0xb +add si, 2 ; si:0x0->0x2 ip:0xb->0xe +cmp si, dx ; ip:0xe->0x10 flags:->CPAS +jne $-7 ; ip:0x10->0x9 +mov word [bp+si], si ; ip:0x9->0xb +add si, 2 ; si:0x2->0x4 ip:0xb->0xe flags:CPAS-> +cmp si, dx ; ip:0xe->0x10 flags:->CAS +jne $-7 ; ip:0x10->0x9 +mov word [bp+si], si ; ip:0x9->0xb +add si, 2 ; si:0x4->0x6 ip:0xb->0xe flags:CAS->P +cmp si, dx ; ip:0xe->0x10 flags:P->PZ +jne $-7 ; ip:0x10->0x12 +mov bx, 0 ; ip:0x12->0x15 +mov si, 0 ; si:0x6->0x0 ip:0x15->0x18 +mov cx, [bp+si] ; ip:0x18->0x1a +add bx, cx ; ip:0x1a->0x1c +add si, 2 ; si:0x0->0x2 ip:0x1c->0x1f flags:PZ-> +cmp si, dx ; ip:0x1f->0x21 flags:->CPAS +jne $-9 ; ip:0x21->0x18 +mov cx, [bp+si] ; cx:0x0->0x2 ip:0x18->0x1a +add bx, cx ; bx:0x0->0x2 ip:0x1a->0x1c flags:CPAS-> +add si, 2 ; si:0x2->0x4 ip:0x1c->0x1f +cmp si, dx ; ip:0x1f->0x21 flags:->CAS +jne $-9 ; ip:0x21->0x18 +mov cx, [bp+si] ; cx:0x2->0x4 ip:0x18->0x1a +add bx, cx ; bx:0x2->0x6 ip:0x1a->0x1c flags:CAS->P +add si, 2 ; si:0x4->0x6 ip:0x1c->0x1f +cmp si, dx ; ip:0x1f->0x21 flags:P->PZ +jne $-9 ; ip:0x21->0x23 + +Final registers: + bx: 0x0006 (6) + cx: 0x0004 (4) + dx: 0x0006 (6) + bp: 0x03e8 (1000) + si: 0x0006 (6) + ip: 0x0023 (35) + flags: PZ + diff --git a/part1/sim8086.c b/part1/sim8086.c index e71d313..78fed17 100644 --- a/part1/sim8086.c +++ b/part1/sim8086.c @@ -228,12 +228,22 @@ void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src) // and then you can have one code path that just checks the flags on each op S86_MnemonicOp mnemonic_op = src ? opcode.src : opcode.dest; - bool wide_prefix = ( src && opcode.wide_prefix == S86_WidePrefix_Src) || - (!src && opcode.wide_prefix == S86_WidePrefix_Dest); - bool effective_addr = ( src && opcode.effective_addr == S86_EffectiveAddress_Src) || (!src && opcode.effective_addr == S86_EffectiveAddress_Dest); + bool wide_prefix = false; + if (opcode.effective_addr == S86_EffectiveAddress_Dest && opcode.effective_addr_loads_mem) { + if (opcode.src == S86_MnemonicOp_DirectAddress || + opcode.src == S86_MnemonicOp_Immediate || + opcode.src == S86_MnemonicOp_Invalid || + (opcode.src >= S86_MnemonicOp_AL && opcode.src <= S86_MnemonicOp_BH) || + (opcode.src == S86_MnemonicOp_SI)) { + // TODO: Not sure why SI needs the prefix as well, but, according + // to the reference decoder its being emitted here. + wide_prefix = (src == false); // NOTE: Only print on the dest op + } + } + if (mnemonic_op == S86_MnemonicOp_Invalid) return; @@ -255,7 +265,7 @@ void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src) if (mnemonic_op == S86_MnemonicOp_DirectAddress) { S86_PrintFmt("%s%d", - opcode.displacement >= 0 ? "" : "-", + opcode.displacement >= 0 ? "+" : "-", opcode.displacement >= 0 ? opcode.displacement : -opcode.displacement); } else if (mnemonic_op == S86_MnemonicOp_Jump) { // NOTE: Account for the opcode itself which is 2 bytes, e.g. we can print $+2-8 or just $-6 @@ -282,8 +292,8 @@ void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src) } if (effective_addr && opcode.displacement) { - S86_PrintFmt("%c%d", - opcode.displacement >= 0 ? '+' : '-', + S86_PrintFmt("%s%d", + opcode.displacement >= 0 ? "+" : "-", opcode.displacement >= 0 ? opcode.displacement : -opcode.displacement); } } @@ -449,8 +459,6 @@ S86_Opcode S86_DecodeOpcode(S86_BufferIterator *buffer_it, } S86_DecodeEffectiveAddr(&result, buffer_it, rm, mod, w); - result.wide_prefix = S86_WidePrefix_Dest; - // NOTE: Bit shifts use 'v' to indicate if shift distance should // come from cl register otherwise bitshift by 1 if (op_decode_type >= S86_OpDecodeType_SHL_SAL && op_decode_type <= S86_OpDecodeType_RCR) { @@ -643,10 +651,6 @@ S86_Opcode S86_DecodeOpcode(S86_BufferIterator *buffer_it, } result.src = S86_MnemonicOp_Immediate; - if (op_decode_type == S86_OpDecodeType_MOVImmediateToRegOrMem) - result.wide_prefix = S86_WidePrefix_Src; - else if (result.effective_addr_loads_mem) - result.wide_prefix = S86_WidePrefix_Dest; } break; // NOTE: Instruction Pattern => [0b0000'W00W | DATA-LO | DATA-HI] @@ -844,12 +848,12 @@ S86_Opcode S86_DecodeOpcode(S86_BufferIterator *buffer_it, result.byte_size = S86_CAST(uint8_t)(buffer_end_index - buffer_start_index); result.instruction_ptr = S86_CAST(uint16_t)buffer_start_index; result.index = S86_CAST(uint16_t)opcode_index; + S86_ASSERT(result.immediate < S86_CAST(uint16_t)-1); return result; } 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 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; @@ -1233,32 +1237,39 @@ int main(int argc, char **argv) S86_PrintLn(S86_STR8("bits 16")); S86_RegisterFile register_file = {0}; + uint8_t *memory = VirtualAlloc(0, 1024 * 1024, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + S86_MnemonicOpToRegisterFileMap mnemonic_op_to_register_file_map[] = { - {.mnemonic_op = S86_MnemonicOp_AX, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = ®ister_file.reg.file.ax, .byte = S86_RegisterByte_Nil}, - {.mnemonic_op = S86_MnemonicOp_AL, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = ®ister_file.reg.file.ax, .byte = S86_RegisterByte_Lo}, - {.mnemonic_op = S86_MnemonicOp_AH, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = ®ister_file.reg.file.ax, .byte = S86_RegisterByte_Hi}, + {.mnemonic_op = S86_MnemonicOp_AX, .reg = ®ister_file.reg.file.ax, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_AL, .reg = ®ister_file.reg.file.ax, .byte = S86_RegisterByte_Lo}, + {.mnemonic_op = S86_MnemonicOp_AH, .reg = ®ister_file.reg.file.ax, .byte = S86_RegisterByte_Hi}, - {.mnemonic_op = S86_MnemonicOp_CX, .mnemonic_op_reg16 = S86_MnemonicOp_CX, .reg = ®ister_file.reg.file.cx, .byte = S86_RegisterByte_Nil}, - {.mnemonic_op = S86_MnemonicOp_CL, .mnemonic_op_reg16 = S86_MnemonicOp_CX, .reg = ®ister_file.reg.file.cx, .byte = S86_RegisterByte_Lo}, - {.mnemonic_op = S86_MnemonicOp_CH, .mnemonic_op_reg16 = S86_MnemonicOp_CX, .reg = ®ister_file.reg.file.cx, .byte = S86_RegisterByte_Lo}, + {.mnemonic_op = S86_MnemonicOp_CX, .reg = ®ister_file.reg.file.cx, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_CL, .reg = ®ister_file.reg.file.cx, .byte = S86_RegisterByte_Lo}, + {.mnemonic_op = S86_MnemonicOp_CH, .reg = ®ister_file.reg.file.cx, .byte = S86_RegisterByte_Lo}, - {.mnemonic_op = S86_MnemonicOp_DX, .mnemonic_op_reg16 = S86_MnemonicOp_DX, .reg = ®ister_file.reg.file.dx, .byte = S86_RegisterByte_Nil}, - {.mnemonic_op = S86_MnemonicOp_DL, .mnemonic_op_reg16 = S86_MnemonicOp_DX, .reg = ®ister_file.reg.file.dx, .byte = S86_RegisterByte_Lo}, - {.mnemonic_op = S86_MnemonicOp_DH, .mnemonic_op_reg16 = S86_MnemonicOp_DX, .reg = ®ister_file.reg.file.dx, .byte = S86_RegisterByte_Hi}, + {.mnemonic_op = S86_MnemonicOp_DX, .reg = ®ister_file.reg.file.dx, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_DL, .reg = ®ister_file.reg.file.dx, .byte = S86_RegisterByte_Lo}, + {.mnemonic_op = S86_MnemonicOp_DH, .reg = ®ister_file.reg.file.dx, .byte = S86_RegisterByte_Hi}, - {.mnemonic_op = S86_MnemonicOp_BX, .mnemonic_op_reg16 = S86_MnemonicOp_BX, .reg = ®ister_file.reg.file.bx, .byte = S86_RegisterByte_Nil}, - {.mnemonic_op = S86_MnemonicOp_BL, .mnemonic_op_reg16 = S86_MnemonicOp_BX, .reg = ®ister_file.reg.file.bx, .byte = S86_RegisterByte_Lo}, - {.mnemonic_op = S86_MnemonicOp_BH, .mnemonic_op_reg16 = S86_MnemonicOp_BX, .reg = ®ister_file.reg.file.bx, .byte = S86_RegisterByte_Hi}, + {.mnemonic_op = S86_MnemonicOp_BX, .reg = ®ister_file.reg.file.bx, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_BL, .reg = ®ister_file.reg.file.bx, .byte = S86_RegisterByte_Lo}, + {.mnemonic_op = S86_MnemonicOp_BH, .reg = ®ister_file.reg.file.bx, .byte = S86_RegisterByte_Hi}, - {.mnemonic_op = S86_MnemonicOp_SP, .mnemonic_op_reg16 = S86_MnemonicOp_SP, .reg = ®ister_file.reg.file.sp, .byte = S86_RegisterByte_Nil}, - {.mnemonic_op = S86_MnemonicOp_BP, .mnemonic_op_reg16 = S86_MnemonicOp_BP, .reg = ®ister_file.reg.file.bp, .byte = S86_RegisterByte_Nil}, - {.mnemonic_op = S86_MnemonicOp_SI, .mnemonic_op_reg16 = S86_MnemonicOp_SI, .reg = ®ister_file.reg.file.si, .byte = S86_RegisterByte_Nil}, - {.mnemonic_op = S86_MnemonicOp_DI, .mnemonic_op_reg16 = S86_MnemonicOp_DI, .reg = ®ister_file.reg.file.di, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_SP, .reg = ®ister_file.reg.file.sp, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_BP, .reg = ®ister_file.reg.file.bp, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_SI, .reg = ®ister_file.reg.file.si, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_DI, .reg = ®ister_file.reg.file.di, .byte = S86_RegisterByte_Nil}, - {.mnemonic_op = S86_MnemonicOp_ES, .mnemonic_op_reg16 = S86_MnemonicOp_ES, .reg = ®ister_file.reg.file.es, .byte = S86_RegisterByte_Nil}, - {.mnemonic_op = S86_MnemonicOp_CS, .mnemonic_op_reg16 = S86_MnemonicOp_CS, .reg = ®ister_file.reg.file.cs, .byte = S86_RegisterByte_Nil}, - {.mnemonic_op = S86_MnemonicOp_SS, .mnemonic_op_reg16 = S86_MnemonicOp_SS, .reg = ®ister_file.reg.file.ss, .byte = S86_RegisterByte_Nil}, - {.mnemonic_op = S86_MnemonicOp_DS, .mnemonic_op_reg16 = S86_MnemonicOp_DS, .reg = ®ister_file.reg.file.ds, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_ES, .reg = ®ister_file.reg.file.es, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_CS, .reg = ®ister_file.reg.file.cs, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_SS, .reg = ®ister_file.reg.file.ss, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_DS, .reg = ®ister_file.reg.file.ds, .byte = S86_RegisterByte_Nil}, + + {.mnemonic_op = S86_MnemonicOp_BX_SI, .reg = ®ister_file.reg.file.bx, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_BX_DI, .reg = ®ister_file.reg.file.bx, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_BP_SI, .reg = ®ister_file.reg.file.bp, .byte = S86_RegisterByte_Nil}, + {.mnemonic_op = S86_MnemonicOp_BP_DI, .reg = ®ister_file.reg.file.bp, .byte = S86_RegisterByte_Nil}, }; // NOTE: Count opcodes, allocate then decode in 1 swoop @@ -1399,23 +1410,18 @@ int main(int argc, char **argv) case S86_Mnemonic_SEGMENT: break; 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->dest) - dest_map = item; - } - S86_ASSERT(dest_map); - - bool byte_op = opcode->dest >= S86_MnemonicOp_AL && opcode->dest <= S86_MnemonicOp_BH; + uint16_t src = 0; + 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; + src = 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; + src = S86_CAST(uint16_t)opcode->immediate; } + } else if (opcode->src == S86_MnemonicOp_DirectAddress) { + S86_ASSERT(opcode->displacement >= 0); + src = memory[opcode->displacement]; } 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++) { @@ -1424,11 +1430,74 @@ int main(int argc, char **argv) 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; + if (src_map->mnemonic_op >= S86_MnemonicOp_BX_SI && src_map->mnemonic_op <= S86_MnemonicOp_BP_DI) { + uint16_t address = 0; + if (src_map->mnemonic_op == S86_MnemonicOp_BX_SI) { + address = src_map->reg->word + register_file.reg.file.si.word; + } else if (src_map->mnemonic_op == S86_MnemonicOp_BX_DI) { + address = src_map->reg->word + register_file.reg.file.di.word; + } else if (src_map->mnemonic_op == S86_MnemonicOp_BP_SI) { + address = src_map->reg->word + register_file.reg.file.si.word; + } else if (src_map->mnemonic_op == S86_MnemonicOp_BP_DI) { + address = src_map->reg->word + register_file.reg.file.di.word; + } else { + S86_ASSERT(!"Invalid code path"); + } + src = *(uint16_t *)&memory[address]; + } else { + src = byte_op ? src_map->reg->bytes[src_map->byte] : src_map->reg->word; + } } + + uint8_t *dest_lo = NULL; + uint8_t *dest_hi = NULL; + if (opcode->dest == S86_MnemonicOp_DirectAddress) { + // NOTE: The 8086 doesn't support load to store directly + // memory to memory afaict + S86_ASSERT(opcode->dest != opcode->src); + S86_ASSERT(opcode->displacement >= 0); + + dest_lo = memory + opcode->displacement; + dest_hi = byte_op ? NULL : memory + (opcode->displacement + 1); + } else { + 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); + + // NOTE: Effective address means we're store/load from memory + // The opcode value is the address. + if (opcode->effective_addr == S86_EffectiveAddress_Dest && opcode->effective_addr_loads_mem) { + uint16_t address = dest_map->reg->word + S86_CAST(uint16_t)opcode->displacement; + if (dest_map->mnemonic_op == S86_MnemonicOp_BX_SI) { + address = dest_map->reg->word + register_file.reg.file.si.word; + } else if (dest_map->mnemonic_op == S86_MnemonicOp_BX_DI) { + address = dest_map->reg->word + register_file.reg.file.di.word; + } else if (dest_map->mnemonic_op == S86_MnemonicOp_BP_SI) { + address = dest_map->reg->word + register_file.reg.file.si.word; + } else if (dest_map->mnemonic_op == S86_MnemonicOp_BP_DI) { + address = dest_map->reg->word + register_file.reg.file.di.word; + } + dest_lo = memory + address; + dest_hi = byte_op ? NULL : memory + (address + 1); + + } else { + if (byte_op) { + dest_lo = &dest_map->reg->bytes[dest_map->byte]; + } else { + dest_lo = &dest_map->reg->bytes[0]; + dest_hi = &dest_map->reg->bytes[1]; + } + } + } + + if (dest_lo) + *dest_lo = S86_CAST(uint8_t)(src >> 0); + if (dest_hi) + *dest_hi = S86_CAST(uint8_t)(src >> 8); } break; case S86_Mnemonic_ADD: /*FALLTHRU*/ @@ -1462,7 +1531,18 @@ int main(int argc, char **argv) if (item->mnemonic_op == opcode->src) src_map = item; } - src = byte_op ? src_map->reg->bytes[src_map->byte] : src_map->reg->word; + + if (src_map->mnemonic_op == S86_MnemonicOp_BX_SI) { + src = src_map->reg->word + register_file.reg.file.si.word; + } else if (src_map->mnemonic_op == S86_MnemonicOp_BX_DI) { + src = src_map->reg->word + register_file.reg.file.di.word; + } else if (src_map->mnemonic_op == S86_MnemonicOp_BP_SI) { + src = src_map->reg->word + register_file.reg.file.si.word; + } else if (src_map->mnemonic_op == S86_MnemonicOp_BP_DI) { + src = src_map->reg->word + register_file.reg.file.di.word; + } else { + src = byte_op ? src_map->reg->bytes[src_map->byte] : src_map->reg->word; + } } // NOTE: Overflow if the sign masks were initially the same, diff --git a/part1/sim8086.h b/part1/sim8086.h index 32e651e..f21f14d 100644 --- a/part1/sim8086.h +++ b/part1/sim8086.h @@ -315,12 +315,6 @@ typedef enum S86_EffectiveAddress { S86_EffectiveAddress_Dest, } S86_EffectiveAddress; -typedef enum S86_WidePrefix { - S86_WidePrefix_None, - S86_WidePrefix_Src, - S86_WidePrefix_Dest, -} S86_WidePrefix; - typedef struct S86_Opcode { uint8_t byte_size; ///< Number of bytes used to encode this opcode uint16_t instruction_ptr; ///< The instruction pointer value at this opcode @@ -331,7 +325,6 @@ typedef struct S86_Opcode { bool lock_prefix; ///< Prefix the opcode with "lock" instruction bool rep_prefix; ///< Prefix the opcode with "rep" instruction bool wide; ///< Opcode has the 'w' flag set - S86_WidePrefix wide_prefix; ///< Mnemonic src/dest op requires a 'word' or 'byte' prefix (e.g. ambiguous immediate size) S86_MnemonicOp src; ///< Source op for the mnemonic S86_MnemonicOp dest; ///< Destination op for the mnemonic int32_t displacement; ///< Opcode has displacement/data/offset diff --git a/project.rdbg b/project.rdbg index 1aa0cfb..06891cc 100644 Binary files a/project.rdbg and b/project.rdbg differ