perfaware/part1: Support listing 0051 & 0052
This commit is contained in:
parent
bd3dc5f2bc
commit
39ec4213d6
@ -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
|
||||||
|
BIN
part1/listing_0051_memory_mov
Normal file
BIN
part1/listing_0051_memory_mov
Normal file
Binary file not shown.
30
part1/listing_0051_memory_mov.asm
Normal file
30
part1/listing_0051_memory_mov.asm
Normal 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]
|
19
part1/listing_0051_memory_mov.txt
Normal file
19
part1/listing_0051_memory_mov.txt
Normal 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)
|
||||||
|
|
BIN
part1/listing_0052_memory_add_loop
Normal file
BIN
part1/listing_0052_memory_add_loop
Normal file
Binary file not shown.
36
part1/listing_0052_memory_add_loop.asm
Normal file
36
part1/listing_0052_memory_add_loop.asm
Normal 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
|
43
part1/listing_0052_memory_add_loop.txt
Normal file
43
part1/listing_0052_memory_add_loop.txt
Normal 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
|
||||||
|
|
176
part1/sim8086.c
176
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
|
// 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 = ®ister_file.reg.file.ax, .byte = S86_RegisterByte_Nil},
|
{.mnemonic_op = 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_AL, .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_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_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_CL, .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_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_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_DL, .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_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_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_BL, .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_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_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_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_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_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_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_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_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_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
|
// 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.
|
||||||
|
@ -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
|
||||||
|
BIN
project.rdbg
BIN
project.rdbg
Binary file not shown.
Loading…
Reference in New Issue
Block a user