perfaware/part1: Support listing 0051 & 0052

This commit is contained in:
doyle 2023-04-17 23:33:31 +10:00
parent bd3dc5f2bc
commit 39ec4213d6
10 changed files with 288 additions and 57 deletions

View File

@ -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 /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 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

Binary file not shown.

View File

@ -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]

View File

@ -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)

Binary file not shown.

View File

@ -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

View File

@ -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

View File

@ -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 // 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; 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) || bool effective_addr = ( src && opcode.effective_addr == S86_EffectiveAddress_Src) ||
(!src && opcode.effective_addr == S86_EffectiveAddress_Dest); (!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) if (mnemonic_op == S86_MnemonicOp_Invalid)
return; return;
@ -255,7 +265,7 @@ void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src)
if (mnemonic_op == S86_MnemonicOp_DirectAddress) { if (mnemonic_op == S86_MnemonicOp_DirectAddress) {
S86_PrintFmt("%s%d", S86_PrintFmt("%s%d",
opcode.displacement >= 0 ? "" : "-", opcode.displacement >= 0 ? "+" : "-",
opcode.displacement >= 0 ? opcode.displacement : -opcode.displacement); opcode.displacement >= 0 ? opcode.displacement : -opcode.displacement);
} else if (mnemonic_op == S86_MnemonicOp_Jump) { } 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 // 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) { if (effective_addr && opcode.displacement) {
S86_PrintFmt("%c%d", S86_PrintFmt("%s%d",
opcode.displacement >= 0 ? '+' : '-', opcode.displacement >= 0 ? "+" : "-",
opcode.displacement >= 0 ? opcode.displacement : -opcode.displacement); 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); 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 // NOTE: Bit shifts use 'v' to indicate if shift distance should
// come from cl register otherwise bitshift by 1 // come from cl register otherwise bitshift by 1
if (op_decode_type >= S86_OpDecodeType_SHL_SAL && op_decode_type <= S86_OpDecodeType_RCR) { 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; 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; } break;
// NOTE: Instruction Pattern => [0b0000'W00W | DATA-LO | DATA-HI] // 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.byte_size = S86_CAST(uint8_t)(buffer_end_index - buffer_start_index);
result.instruction_ptr = S86_CAST(uint16_t)buffer_start_index; result.instruction_ptr = S86_CAST(uint16_t)buffer_start_index;
result.index = S86_CAST(uint16_t)opcode_index; result.index = S86_CAST(uint16_t)opcode_index;
S86_ASSERT(result.immediate < S86_CAST(uint16_t)-1);
return result; return result;
} }
typedef struct S86_MnemonicOpToRegisterFileMap { typedef struct S86_MnemonicOpToRegisterFileMap {
S86_MnemonicOp mnemonic_op; ///< Register/op that the mnemonic is using 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_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_RegisterByte byte; ///< The 'byte' that the mnemonic operates on (hi, lo or nil e.g. word)
} S86_MnemonicOpToRegisterFileMap; } S86_MnemonicOpToRegisterFileMap;
@ -1233,32 +1237,39 @@ int main(int argc, char **argv)
S86_PrintLn(S86_STR8("bits 16")); S86_PrintLn(S86_STR8("bits 16"));
S86_RegisterFile register_file = {0}; 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[] = { S86_MnemonicOpToRegisterFileMap mnemonic_op_to_register_file_map[] = {
{.mnemonic_op = S86_MnemonicOp_AX, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = &register_file.reg.file.ax, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_AX, .reg = &register_file.reg.file.ax, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_AL, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = &register_file.reg.file.ax, .byte = S86_RegisterByte_Lo}, {.mnemonic_op = S86_MnemonicOp_AL, .reg = &register_file.reg.file.ax, .byte = S86_RegisterByte_Lo},
{.mnemonic_op = S86_MnemonicOp_AH, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = &register_file.reg.file.ax, .byte = S86_RegisterByte_Hi}, {.mnemonic_op = S86_MnemonicOp_AH, .reg = &register_file.reg.file.ax, .byte = S86_RegisterByte_Hi},
{.mnemonic_op = S86_MnemonicOp_CX, .mnemonic_op_reg16 = S86_MnemonicOp_CX, .reg = &register_file.reg.file.cx, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_CX, .reg = &register_file.reg.file.cx, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_CL, .mnemonic_op_reg16 = S86_MnemonicOp_CX, .reg = &register_file.reg.file.cx, .byte = S86_RegisterByte_Lo}, {.mnemonic_op = S86_MnemonicOp_CL, .reg = &register_file.reg.file.cx, .byte = S86_RegisterByte_Lo},
{.mnemonic_op = S86_MnemonicOp_CH, .mnemonic_op_reg16 = S86_MnemonicOp_CX, .reg = &register_file.reg.file.cx, .byte = S86_RegisterByte_Lo}, {.mnemonic_op = S86_MnemonicOp_CH, .reg = &register_file.reg.file.cx, .byte = S86_RegisterByte_Lo},
{.mnemonic_op = S86_MnemonicOp_DX, .mnemonic_op_reg16 = S86_MnemonicOp_DX, .reg = &register_file.reg.file.dx, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_DX, .reg = &register_file.reg.file.dx, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_DL, .mnemonic_op_reg16 = S86_MnemonicOp_DX, .reg = &register_file.reg.file.dx, .byte = S86_RegisterByte_Lo}, {.mnemonic_op = S86_MnemonicOp_DL, .reg = &register_file.reg.file.dx, .byte = S86_RegisterByte_Lo},
{.mnemonic_op = S86_MnemonicOp_DH, .mnemonic_op_reg16 = S86_MnemonicOp_DX, .reg = &register_file.reg.file.dx, .byte = S86_RegisterByte_Hi}, {.mnemonic_op = S86_MnemonicOp_DH, .reg = &register_file.reg.file.dx, .byte = S86_RegisterByte_Hi},
{.mnemonic_op = S86_MnemonicOp_BX, .mnemonic_op_reg16 = S86_MnemonicOp_BX, .reg = &register_file.reg.file.bx, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_BX, .reg = &register_file.reg.file.bx, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_BL, .mnemonic_op_reg16 = S86_MnemonicOp_BX, .reg = &register_file.reg.file.bx, .byte = S86_RegisterByte_Lo}, {.mnemonic_op = S86_MnemonicOp_BL, .reg = &register_file.reg.file.bx, .byte = S86_RegisterByte_Lo},
{.mnemonic_op = S86_MnemonicOp_BH, .mnemonic_op_reg16 = S86_MnemonicOp_BX, .reg = &register_file.reg.file.bx, .byte = S86_RegisterByte_Hi}, {.mnemonic_op = S86_MnemonicOp_BH, .reg = &register_file.reg.file.bx, .byte = S86_RegisterByte_Hi},
{.mnemonic_op = S86_MnemonicOp_SP, .mnemonic_op_reg16 = S86_MnemonicOp_SP, .reg = &register_file.reg.file.sp, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_SP, .reg = &register_file.reg.file.sp, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_BP, .mnemonic_op_reg16 = S86_MnemonicOp_BP, .reg = &register_file.reg.file.bp, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_BP, .reg = &register_file.reg.file.bp, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_SI, .mnemonic_op_reg16 = S86_MnemonicOp_SI, .reg = &register_file.reg.file.si, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_SI, .reg = &register_file.reg.file.si, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_DI, .mnemonic_op_reg16 = S86_MnemonicOp_DI, .reg = &register_file.reg.file.di, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_DI, .reg = &register_file.reg.file.di, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_ES, .mnemonic_op_reg16 = S86_MnemonicOp_ES, .reg = &register_file.reg.file.es, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_ES, .reg = &register_file.reg.file.es, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_CS, .mnemonic_op_reg16 = S86_MnemonicOp_CS, .reg = &register_file.reg.file.cs, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_CS, .reg = &register_file.reg.file.cs, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_SS, .mnemonic_op_reg16 = S86_MnemonicOp_SS, .reg = &register_file.reg.file.ss, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_SS, .reg = &register_file.reg.file.ss, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_DS, .mnemonic_op_reg16 = S86_MnemonicOp_DS, .reg = &register_file.reg.file.ds, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_DS, .reg = &register_file.reg.file.ds, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_BX_SI, .reg = &register_file.reg.file.bx, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_BX_DI, .reg = &register_file.reg.file.bx, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_BP_SI, .reg = &register_file.reg.file.bp, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_BP_DI, .reg = &register_file.reg.file.bp, .byte = S86_RegisterByte_Nil},
}; };
// NOTE: Count opcodes, allocate then decode in 1 swoop // 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_SEGMENT: break;
case S86_Mnemonic_MOV: { case S86_Mnemonic_MOV: {
S86_MnemonicOpToRegisterFileMap const *dest_map = NULL; uint16_t src = 0;
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; bool byte_op = opcode->dest >= S86_MnemonicOp_AL && opcode->dest <= S86_MnemonicOp_BH;
if (opcode->src == S86_MnemonicOp_Immediate) { if (opcode->src == S86_MnemonicOp_Immediate) {
if (byte_op) { if (byte_op) {
S86_ASSERT(opcode->immediate < S86_CAST(uint8_t)-1); 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 { } else {
S86_ASSERT(opcode->immediate < S86_CAST(uint16_t)-1); src = S86_CAST(uint16_t)opcode->immediate;
dest_map->reg->word = S86_CAST(uint16_t)opcode->immediate;
} }
} else if (opcode->src == S86_MnemonicOp_DirectAddress) {
S86_ASSERT(opcode->displacement >= 0);
src = memory[opcode->displacement];
} else { } else {
S86_MnemonicOpToRegisterFileMap const *src_map = NULL; S86_MnemonicOpToRegisterFileMap const *src_map = NULL;
for (size_t index = 0; !src_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { 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; src_map = item;
} }
if (byte_op) if (src_map->mnemonic_op >= S86_MnemonicOp_BX_SI && src_map->mnemonic_op <= S86_MnemonicOp_BP_DI) {
dest_map->reg->bytes[dest_map->byte] = src_map->reg->bytes[src_map->byte]; uint16_t address = 0;
else if (src_map->mnemonic_op == S86_MnemonicOp_BX_SI) {
dest_map->reg->word = src_map->reg->word; 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; } break;
case S86_Mnemonic_ADD: /*FALLTHRU*/ case S86_Mnemonic_ADD: /*FALLTHRU*/
@ -1462,8 +1531,19 @@ int main(int argc, char **argv)
if (item->mnemonic_op == opcode->src) if (item->mnemonic_op == opcode->src)
src_map = item; src_map = item;
} }
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; src = byte_op ? src_map->reg->bytes[src_map->byte] : src_map->reg->word;
} }
}
// NOTE: Overflow if the sign masks were initially the same, // NOTE: Overflow if the sign masks were initially the same,
// but, after the operation the sign masked changed. // but, after the operation the sign masked changed.

View File

@ -315,12 +315,6 @@ typedef enum S86_EffectiveAddress {
S86_EffectiveAddress_Dest, S86_EffectiveAddress_Dest,
} S86_EffectiveAddress; } S86_EffectiveAddress;
typedef enum S86_WidePrefix {
S86_WidePrefix_None,
S86_WidePrefix_Src,
S86_WidePrefix_Dest,
} S86_WidePrefix;
typedef struct S86_Opcode { typedef struct S86_Opcode {
uint8_t byte_size; ///< Number of bytes used to encode this opcode uint8_t byte_size; ///< Number of bytes used to encode this opcode
uint16_t instruction_ptr; ///< The instruction pointer value at 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 lock_prefix; ///< Prefix the opcode with "lock" instruction
bool rep_prefix; ///< Prefix the opcode with "rep" instruction bool rep_prefix; ///< Prefix the opcode with "rep" instruction
bool wide; ///< Opcode has the 'w' flag set 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 src; ///< Source op for the mnemonic
S86_MnemonicOp dest; ///< Destination op for the mnemonic S86_MnemonicOp dest; ///< Destination op for the mnemonic
int32_t displacement; ///< Opcode has displacement/data/offset int32_t displacement; ///< Opcode has displacement/data/offset

Binary file not shown.