Compare commits

...

3 Commits

15 changed files with 54511 additions and 138 deletions

View File

@ -220,3 +220,52 @@ 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
REM ================================================================================================
set listing_0053=listing_0053_add_loop_challenge
set build_dir_listing_0053=%build_dir%\%listing_0053%
copy /Y %script_dir%\%listing_0053% %build_dir% 1>NUL
copy /Y %script_dir%\%listing_0053%.txt %build_dir% 1>NUL
%build_dir%\sim8086.exe --exec --log-instruction-ptr %build_dir_listing_0053% > %build_dir_listing_0053%_disassembled.txt
%build_dir%\sim8086.exe %build_dir_listing_0053% > %build_dir_listing_0053%_disassembled.asm
nasm %build_dir_listing_0053%_disassembled.asm
fc /B %build_dir_listing_0053% %build_dir_listing_0053%_disassembled || exit /b 1
fc /N %build_dir_listing_0053%.txt %build_dir_listing_0053%_disassembled.txt || exit /b 1
REM ================================================================================================
set listing_0054=listing_0054_draw_rectangle
set build_dir_listing_0054=%build_dir%\%listing_0054%
copy /Y %script_dir%\%listing_0054% %build_dir% 1>NUL
copy /Y %script_dir%\%listing_0054%.txt %build_dir% 1>NUL
pushd %build_dir%
%build_dir%\sim8086.exe --exec --log-instruction-ptr --dump %build_dir_listing_0054% > %build_dir_listing_0054%_disassembled.txt
%build_dir%\sim8086.exe %build_dir_listing_0054% > %build_dir_listing_0054%_disassembled.asm
popd
nasm %build_dir_listing_0054%_disassembled.asm
fc /B %build_dir_listing_0054% %build_dir_listing_0054%_disassembled || exit /b 1
fc /N %build_dir_listing_0054%.txt %build_dir_listing_0054%_disassembled.txt || exit /b 1
REM ================================================================================================
set listing_0055=listing_0055_challenge_rectangle
set build_dir_listing_0055=%build_dir%\%listing_0055%
copy /Y %script_dir%\%listing_0055% %build_dir% 1>NUL
copy /Y %script_dir%\%listing_0055%.txt %build_dir% 1>NUL
pushd %build_dir%
%build_dir%\sim8086.exe --exec --log-instruction-ptr --dump %build_dir_listing_0055% > %build_dir_listing_0055%_disassembled.txt
%build_dir%\sim8086.exe %build_dir_listing_0055% > %build_dir_listing_0055%_disassembled.asm
popd
nasm %build_dir_listing_0055%_disassembled.asm
fc /B %build_dir_listing_0055% %build_dir_listing_0055%_disassembled || exit /b 1
fc /N %build_dir_listing_0055%.txt %build_dir_listing_0055%_disassembled.txt || exit /b 1

Binary file not shown.

View File

@ -0,0 +1,35 @@
; ========================================================================
;
; (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 53
; ========================================================================
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, dx
sub bp, 2
add_loop_start:
add bx, word [bp + si]
sub si, 2
jnz add_loop_start

View File

@ -0,0 +1,36 @@
--- test\listing_0053_add_loop_challenge 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, dx ; ip:0x15->0x17
sub bp, 2 ; bp:0x3e8->0x3e6 ip:0x17->0x1a flags:PZ->
add bx, [bp+si] ; bx:0x0->0x4 ip:0x1a->0x1c
sub si, 2 ; si:0x6->0x4 ip:0x1c->0x1f
jne $-5 ; ip:0x1f->0x1a
add bx, [bp+si] ; bx:0x4->0x6 ip:0x1a->0x1c flags:->P
sub si, 2 ; si:0x4->0x2 ip:0x1c->0x1f flags:P->
jne $-5 ; ip:0x1f->0x1a
add bx, [bp+si] ; ip:0x1a->0x1c flags:->P
sub si, 2 ; si:0x2->0x0 ip:0x1c->0x1f flags:P->PZ
jne $-5 ; ip:0x1f->0x21
Final registers:
bx: 0x0006 (6)
dx: 0x0006 (6)
bp: 0x03e6 (998)
ip: 0x0021 (33)
flags: PZ

Binary file not shown.

View File

@ -0,0 +1,43 @@
; ========================================================================
;
; (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 54
; ========================================================================
bits 16
; Start image after one row, to avoid overwriting our code!
mov bp, 64*4
mov dx, 0
y_loop_start:
mov cx, 0
x_loop_start:
; Fill pixel
mov word [bp + 0], cx ; Red
mov word [bp + 2], dx ; Blue
mov byte [bp + 3], 255 ; Alpha
; Advance pixel location
add bp, 4
; Advance X coordinate and loop
add cx, 1
cmp cx, 64
jnz x_loop_start
; Advance Y coordinate and loop
add dx, 1
cmp dx, 64
jnz y_loop_start

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,53 @@
; ========================================================================
;
; (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 55
; ========================================================================
bits 16
; Start image after one row, to avoid overwriting our code!
mov bp, 64*4
; Draw the solid rectangle red/blue/alpha
mov dx, 64
y_loop_start:
mov cx, 64
x_loop_start:
mov byte [bp + 0], cl ; Red
mov byte [bp + 1], 0 ; Green
mov byte [bp + 2], dl ; Blue
mov byte [bp + 3], 255 ; Alpha
add bp, 4
loop x_loop_start
sub dx, 1
jnz y_loop_start
; Add the line rectangle green
mov bp, 64*4 + 4*64 + 4
mov bx, bp
mov cx, 62
outline_loop_start:
mov byte [bp + 1], 255 ; Top line
mov byte [bp + 61*64*4 + 1], 255 ; Bottom line
mov byte [bx + 1], 255 ; Left line
mov byte [bx + 61*4 + 1], 255 ; Right line
add bp, 4
add bx, 4*64
loop outline_loop_start

File diff suppressed because it is too large Load Diff

View File

@ -231,19 +231,6 @@ void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src)
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;
@ -252,8 +239,8 @@ void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src)
else
S86_PrintFmt(" ");
if (wide_prefix)
S86_PrintFmt("%s ", opcode.wide ? "word" : "byte");
if (!src && opcode.word_byte_prefix != S86_WordBytePrefix_None)
S86_PrintFmt("%s ", opcode.word_byte_prefix == S86_WordBytePrefix_Word ? "word" : "byte");
if (effective_addr && opcode.seg_reg_prefix != S86_MnemonicOp_Invalid) {
S86_Str8 prefix = S86_MnemonicOpStr8(opcode.seg_reg_prefix);
@ -362,7 +349,6 @@ void S86_DecodeEffectiveAddr(S86_Opcode *opcode, S86_BufferIterator *buffer_it,
S86_Opcode S86_DecodeOpcode(S86_BufferIterator *buffer_it,
S86_OpDecode const *decode_table,
uint16_t decode_table_size,
uint16_t opcode_index,
bool *lock_prefix,
S86_MnemonicOp *seg_reg)
{
@ -844,10 +830,14 @@ S86_Opcode S86_DecodeOpcode(S86_BufferIterator *buffer_it,
if (op_decode_type != S86_OpDecodeType_SEGMENT)
*seg_reg = S86_MnemonicOp_Invalid;
if (result.effective_addr == S86_EffectiveAddress_Dest && result.effective_addr_loads_mem) {
result.word_byte_prefix = (result.wide || result.src >= S86_MnemonicOp_AX && result.src <= S86_MnemonicOp_BX)
? S86_WordBytePrefix_Word
: S86_WordBytePrefix_Byte;
}
size_t buffer_end_index = buffer_it->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.index = S86_CAST(uint16_t)opcode_index;
S86_ASSERT(result.immediate < S86_CAST(uint16_t)-1);
return result;
}
@ -858,39 +848,17 @@ typedef struct S86_MnemonicOpToRegisterFileMap {
S86_RegisterByte byte; ///< The 'byte' that the mnemonic operates on (hi, lo or nil e.g. word)
} S86_MnemonicOpToRegisterFileMap;
S86_Opcode *S86_OpcodeAtInstructionPtr(S86_Opcode *opcode_array,
size_t opcode_size,
S86_Opcode *prev_opcode,
uint16_t instruction_ptr)
{
S86_Opcode NIL_OPCODE = {0};
if (!prev_opcode)
prev_opcode = &NIL_OPCODE;
S86_Opcode *result = NULL;
if (instruction_ptr < prev_opcode->instruction_ptr) {
for (size_t index = prev_opcode->index - 1; !result && index < opcode_size; index--) {
if (opcode_array[index].instruction_ptr == instruction_ptr)
result = opcode_array + index;
}
} else {
for (size_t index = prev_opcode->index; !result && index < opcode_size; index++) {
if (opcode_array[index].instruction_ptr == instruction_ptr)
result = opcode_array + index;
}
}
return result;
}
char const CLI_ARG_EXEC[] = "--exec";
char const CLI_ARG_LOG_INSTRUCTION_PTR[] = "--log-instruction-ptr";
char const CLI_ARG_DUMP[] = "--dump";
#define PRINT_USAGE \
S86_PrintLnFmt("USAGE: sim8086.exe [%.*s] [%.*s] <binary asm file>", \
S86_ARRAY_UCOUNT(CLI_ARG_EXEC) - 1, \
CLI_ARG_EXEC, \
S86_ARRAY_UCOUNT(CLI_ARG_LOG_INSTRUCTION_PTR) - 1, \
CLI_ARG_LOG_INSTRUCTION_PTR)
CLI_ARG_LOG_INSTRUCTION_PTR, \
S86_ARRAY_UCOUNT(CLI_ARG_DUMP) - 1, \
CLI_ARG_DUMP)
int main(int argc, char **argv)
{
// NOTE: Argument handling
@ -902,9 +870,11 @@ int main(int argc, char **argv)
S86_Str8 CLI_ARG_EXEC_STR8 = (S86_Str8){(char *)CLI_ARG_EXEC, S86_ARRAY_UCOUNT(CLI_ARG_EXEC) - 1};
S86_Str8 CLI_ARG_LOG_INSTRUCTION_PTR_STR8 = (S86_Str8){(char *)CLI_ARG_LOG_INSTRUCTION_PTR, S86_ARRAY_UCOUNT(CLI_ARG_LOG_INSTRUCTION_PTR) - 1};
S86_Str8 CLI_ARG_DUMP_STR8 = (S86_Str8){(char *)CLI_ARG_DUMP, S86_ARRAY_UCOUNT(CLI_ARG_DUMP) - 1};
bool exec_mode = false;
bool log_instruction_ptr = false;
bool dump = false;
S86_Str8 file_path = {0};
for (int arg_index = 1; arg_index < argc; arg_index++) {
char const *arg_cstring = argv[arg_index];
@ -913,6 +883,8 @@ int main(int argc, char **argv)
exec_mode = true;
} else if (S86_Str8_Equals(arg_str8, CLI_ARG_LOG_INSTRUCTION_PTR_STR8)) {
log_instruction_ptr = true;
} else if (S86_Str8_Equals(arg_str8, CLI_ARG_DUMP_STR8)) {
dump = true;
} else {
if (file_path.size) {
S86_PrintLnFmt("ERROR: Only 1 ASM binary file is supported per invocation [file=\"%.*s\"]", S86_STR8_FMT(file_path));
@ -1236,8 +1208,10 @@ int main(int argc, char **argv)
else
S86_PrintLn(S86_STR8("bits 16"));
uint32_t const S86_MEMORY_SIZE = 1024 * 1024;
S86_RegisterFile register_file = {0};
uint8_t *memory = VirtualAlloc(0, 1024 * 1024, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
uint8_t *memory = VirtualAlloc(0, S86_MEMORY_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
memcpy(memory, buffer.data, buffer.size);
S86_MnemonicOpToRegisterFileMap mnemonic_op_to_register_file_map[] = {
{.mnemonic_op = S86_MnemonicOp_AX, .reg = &register_file.reg.file.ax, .byte = S86_RegisterByte_Nil},
@ -1272,56 +1246,22 @@ int main(int argc, char **argv)
{.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
// =========================================================================
S86_Opcode *opcode_array = NULL;
uint16_t opcode_size = 0;
{
bool lock_prefix = false;
S86_MnemonicOp seg_reg = S86_CAST(S86_MnemonicOp)0;
for (S86_BufferIterator it = S86_BufferIteratorInit(buffer);
S86_BufferIteratorHasMoreBytes(it);
opcode_size++) {
S86_DecodeOpcode(&it, DECODE_TABLE, S86_ARRAY_UCOUNT(DECODE_TABLE), opcode_size, &lock_prefix, &seg_reg);
}
if (opcode_size == 0)
return 0;
lock_prefix = false;
seg_reg = S86_CAST(S86_MnemonicOp)0;
opcode_array = VirtualAlloc(NULL, sizeof(*opcode_array) * opcode_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!opcode_array) {
S86_PrintLnFmt("ERROR: Failed to allocate memory for decoding opcode stream");
return -1;
}
uint16_t opcode_index = 0;
for (S86_BufferIterator it = S86_BufferIteratorInit(buffer); S86_BufferIteratorHasMoreBytes(it); opcode_index++) {
opcode_array[opcode_index] = S86_DecodeOpcode(&it, DECODE_TABLE, S86_ARRAY_UCOUNT(DECODE_TABLE), opcode_index, &lock_prefix, &seg_reg);
}
}
// NOTE: Execute the assembly
// =========================================================================
for (S86_Opcode *prev_opcode = NULL, *opcode = NULL;
register_file.instruction_ptr < buffer.size;
prev_opcode = opcode) {
opcode = S86_OpcodeAtInstructionPtr(opcode_array,
opcode_size,
prev_opcode,
register_file.instruction_ptr);
if (!opcode) {
S86_PrintLnFmt("ERROR: Could not find opcode with matching instruction pointer, execution failed! [file=\"%.*s\", prev_ip=0x%x, ip=0x%x]",
S86_STR8_FMT(file_path),
prev_opcode->instruction_ptr,
register_file.instruction_ptr);
return -1;
}
S86_Buffer instruction_buffer = {0};
instruction_buffer.data = (char *)&memory[register_file.instruction_ptr];
instruction_buffer.size = buffer.size;
S86_BufferIterator instruction_it = S86_BufferIteratorInit(instruction_buffer);
S86_PrintOpcode(*opcode);
register_file.instruction_ptr += opcode->byte_size;
if (opcode->mnemonic == S86_Mnemonic_LOCK || opcode->mnemonic == S86_Mnemonic_SEGMENT)
bool lock_prefix = false;
S86_MnemonicOp seg_reg = S86_CAST(S86_MnemonicOp)0;
for (uint16_t prev_ip = 0; register_file.instruction_ptr < buffer.size; prev_ip = register_file.instruction_ptr) {
instruction_it.index = register_file.instruction_ptr;
S86_Opcode opcode = S86_DecodeOpcode(&instruction_it, DECODE_TABLE, S86_ARRAY_UCOUNT(DECODE_TABLE), &lock_prefix, &seg_reg);
S86_PrintOpcode(opcode);
register_file.instruction_ptr += opcode.byte_size;
if (opcode.mnemonic == S86_Mnemonic_LOCK || opcode.mnemonic == S86_Mnemonic_SEGMENT)
continue;
if (!exec_mode) {
@ -1331,7 +1271,7 @@ int main(int argc, char **argv)
// NOTE: Simulate instruction ==============================================================
S86_RegisterFile prev_register_file = register_file;
switch (opcode->mnemonic) {
switch (opcode.mnemonic) {
case S86_Mnemonic_PUSH: /*FALLTHRU*/
case S86_Mnemonic_POP: /*FALLTHRU*/
case S86_Mnemonic_XCHG: /*FALLTHRU*/
@ -1390,7 +1330,6 @@ int main(int argc, char **argv)
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_JCXZ: /*FALLTHRU*/
case S86_Mnemonic_INT: /*FALLTHRU*/
@ -1411,26 +1350,27 @@ int main(int argc, char **argv)
case S86_Mnemonic_MOV: {
uint16_t src = 0;
bool byte_op = opcode->dest >= S86_MnemonicOp_AL && opcode->dest <= S86_MnemonicOp_BH;
if (opcode->src == S86_MnemonicOp_Immediate) {
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);
src = S86_CAST(uint8_t)opcode->immediate;
S86_ASSERT(opcode.immediate < S86_CAST(uint8_t)-1);
src = S86_CAST(uint8_t)opcode.immediate;
} else {
src = 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 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++) {
S86_MnemonicOpToRegisterFileMap const *item = mnemonic_op_to_register_file_map + index;
if (item->mnemonic_op == opcode->src)
if (item->mnemonic_op == opcode.src)
src_map = item;
}
if (src_map->mnemonic_op >= S86_MnemonicOp_BX_SI && src_map->mnemonic_op <= S86_MnemonicOp_BP_DI) {
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;
@ -1451,27 +1391,27 @@ int main(int argc, char **argv)
uint8_t *dest_lo = NULL;
uint8_t *dest_hi = NULL;
if (opcode->dest == S86_MnemonicOp_DirectAddress) {
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);
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);
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)
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 (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) {
@ -1506,40 +1446,50 @@ int main(int argc, char **argv)
S86_MnemonicOpToRegisterFileMap *dest_map = NULL;
for (size_t index = 0; !dest_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) {
S86_MnemonicOpToRegisterFileMap *item = mnemonic_op_to_register_file_map + index;
if (item->mnemonic_op == opcode->dest)
if (item->mnemonic_op == opcode.dest)
dest_map = item;
}
S86_ASSERT(dest_map);
bool subtract = opcode->mnemonic != S86_Mnemonic_ADD;
bool subtract = opcode.mnemonic != S86_Mnemonic_ADD;
S86_Register16 dest = *dest_map->reg;
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;
uint16_t src = 0;
if (opcode->src == S86_MnemonicOp_Immediate) {
if (opcode.src == S86_MnemonicOp_Immediate) {
if (byte_op) {
S86_ASSERT(opcode->immediate < S86_CAST(uint8_t)-1);
src = S86_CAST(uint8_t)opcode->immediate;
S86_ASSERT(opcode.immediate < S86_CAST(uint8_t)-1);
src = S86_CAST(uint8_t)opcode.immediate;
} else {
S86_ASSERT(opcode->immediate < S86_CAST(uint16_t)-1);
src = S86_CAST(uint16_t)opcode->immediate;
S86_ASSERT(opcode.immediate < S86_CAST(uint16_t)-1);
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++) {
S86_MnemonicOpToRegisterFileMap const *item = mnemonic_op_to_register_file_map + index;
if (item->mnemonic_op == opcode->src)
if (item->mnemonic_op == opcode.src)
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;
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;
}
@ -1611,34 +1561,40 @@ int main(int argc, char **argv)
int lo_bit_count = _mm_popcnt_u32(S86_CAST(uint32_t)dest.bytes[S86_RegisterByte_Lo]);
register_file.flags.parity = lo_bit_count % 2 == 0;
register_file.flags.zero = byte_op ? dest.bytes[dest_map->byte] == 0 : dest.word == 0;
if (opcode->mnemonic != S86_Mnemonic_CMP)
if (opcode.mnemonic != S86_Mnemonic_CMP)
*dest_map->reg = dest;
} break;
case S86_Mnemonic_JNE_JNZ: {
if (!register_file.flags.zero)
register_file.instruction_ptr += S86_CAST(int16_t)opcode->displacement;
register_file.instruction_ptr += S86_CAST(int16_t)opcode.displacement;
} break;
case S86_Mnemonic_JE_JZ: {
if (register_file.flags.zero)
register_file.instruction_ptr += S86_CAST(int16_t)opcode->displacement;
register_file.instruction_ptr += S86_CAST(int16_t)opcode.displacement;
} break;
case S86_Mnemonic_JP_JPE: {
if (register_file.flags.parity)
register_file.instruction_ptr += S86_CAST(int16_t)opcode->displacement;
register_file.instruction_ptr += S86_CAST(int16_t)opcode.displacement;
} break;
case S86_Mnemonic_JB_JNAE: {
if (register_file.flags.carry)
register_file.instruction_ptr += S86_CAST(int16_t)opcode->displacement;
register_file.instruction_ptr += S86_CAST(int16_t)opcode.displacement;
} break;
case S86_Mnemonic_LOOP: {
register_file.reg.file.cx.word -= 1;
if (register_file.reg.file.cx.word != 0)
register_file.instruction_ptr += S86_CAST(int16_t)opcode.displacement;
} break;
case S86_Mnemonic_LOOPNZ_LOOPNE: {
register_file.reg.file.cx.word -= 1;
if (register_file.reg.file.cx.word != 0 && !register_file.flags.zero)
register_file.instruction_ptr += S86_CAST(int16_t)opcode->displacement;
register_file.instruction_ptr += S86_CAST(int16_t)opcode.displacement;
} break;
}
@ -1663,7 +1619,7 @@ int main(int argc, char **argv)
// NOTE: Instruction Pointer
if (log_instruction_ptr)
S86_PrintFmt("ip:0x%x->0x%x ", opcode->instruction_ptr, register_file.instruction_ptr);
S86_PrintFmt("ip:0x%x->0x%x ", prev_ip, register_file.instruction_ptr);
// NOTE: Flags
if (!S86_RegisterFileFlagsEq(register_file.flags, prev_register_file.flags)) {
@ -1747,4 +1703,10 @@ int main(int argc, char **argv)
}
S86_Print(S86_STR8("\n"));
}
if (dump) {
char buf[1024];
snprintf(buf, sizeof(buf), "%s_mem_dump.data", file_name);
S86_FileWrite(buf, memory, S86_MEMORY_SIZE);
}
}

View File

@ -315,16 +315,21 @@ typedef enum S86_EffectiveAddress {
S86_EffectiveAddress_Dest,
} S86_EffectiveAddress;
typedef enum S86_WordBytePrefix {
S86_WordBytePrefix_None,
S86_WordBytePrefix_Byte,
S86_WordBytePrefix_Word,
} S86_WordBytePrefix;
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
uint16_t index; ///< Opcode index in the opcode array this was decoded from
S86_Mnemonic mnemonic; ///< Mnemonic type
S86_EffectiveAddress effective_addr; ///< Src/dest op is an effective address calculation
bool effective_addr_loads_mem; ///< Effective address uses '[]' notation to load address memory
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_WordBytePrefix word_byte_prefix; ///< Opcode has the 'word' or 'byte' prefix
S86_MnemonicOp src; ///< Source op for the mnemonic
S86_MnemonicOp dest; ///< Destination op for the mnemonic
int32_t displacement; ///< Opcode has displacement/data/offset

View File

@ -111,6 +111,42 @@ void S86_FileFree(S86_Buffer buffer)
VirtualFree(buffer.data, 0, MEM_RELEASE);
}
bool S86_FileWrite(char const *file_path, void const *buffer, size_t buffer_size)
{
bool result = false;
// NOTE: Open file
// =========================================================================
HANDLE file_handle = CreateFile(
/*LPCSTR lpFileName*/ file_path,
/*DWORD dwDesiredAccess*/ GENERIC_WRITE,
/*DWORD dwShareMode*/ 0,
/*LPSECURITY_ATTRIBUTES lpSecurityAttributes*/ NULL,
/*DWORD dwCreationDisposition*/ CREATE_ALWAYS,
/*DWORD dwFlagsAndAttributes*/ 0,
/*HANDLE hTemplateFile*/ NULL
);
if (file_handle == INVALID_HANDLE_VALUE)
return result;
// NOTE: Write file to disk
// =========================================================================
DWORD bytes_written = 0;
BOOL write_file_result = WriteFile(
/*HANDLE hFile*/ file_handle,
/*LPVOID lpBuffer*/ buffer,
/*DWORD nNumberOfBytesToWrite*/ S86_CAST(DWORD)buffer_size,
/*LPDWORD lpNumberOfBytesWrite*/ &bytes_written,
/*LPOVERLAPPED lpOverlapped*/ NULL
);
S86_ASSERT(bytes_written == buffer_size);
result = write_file_result && bytes_written == buffer_size;
CloseHandle(file_handle);
return result;
};
void S86_Print(S86_Str8 string)
{
if (s86_globals.stdout_handle == NULL) {

View File

@ -53,6 +53,7 @@ uint8_t S86_BufferIteratorNextByte(S86_BufferIterator *it);
// ============================================================================
S86_Buffer S86_FileRead(char const *file_path);
void S86_FileFree(S86_Buffer buffer);
bool S86_FileWrite(char const *file_path, void const *buffer, size_t buffer_size);
// NOTE: Print
// ============================================================================

Binary file not shown.