Compare commits
No commits in common. "d888968ce01dfccf6bcc5cbf98c7ba9f5b1af158" and "39ec4213d6c0f76b75788673d964ac23596267a9" have entirely different histories.
d888968ce0
...
39ec4213d6
@ -220,52 +220,3 @@ 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.
@ -1,35 +0,0 @@
|
||||
; ========================================================================
|
||||
;
|
||||
; (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
|
@ -1,36 +0,0 @@
|
||||
--- 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.
@ -1,43 +0,0 @@
|
||||
; ========================================================================
|
||||
;
|
||||
; (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.
@ -1,53 +0,0 @@
|
||||
; ========================================================================
|
||||
;
|
||||
; (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
234
part1/sim8086.c
234
part1/sim8086.c
@ -231,6 +231,19 @@ 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;
|
||||
|
||||
@ -239,8 +252,8 @@ void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src)
|
||||
else
|
||||
S86_PrintFmt(" ");
|
||||
|
||||
if (!src && opcode.word_byte_prefix != S86_WordBytePrefix_None)
|
||||
S86_PrintFmt("%s ", opcode.word_byte_prefix == S86_WordBytePrefix_Word ? "word" : "byte");
|
||||
if (wide_prefix)
|
||||
S86_PrintFmt("%s ", opcode.wide ? "word" : "byte");
|
||||
|
||||
if (effective_addr && opcode.seg_reg_prefix != S86_MnemonicOp_Invalid) {
|
||||
S86_Str8 prefix = S86_MnemonicOpStr8(opcode.seg_reg_prefix);
|
||||
@ -349,6 +362,7 @@ 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)
|
||||
{
|
||||
@ -830,14 +844,10 @@ 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;
|
||||
}
|
||||
@ -848,17 +858,39 @@ 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, \
|
||||
S86_ARRAY_UCOUNT(CLI_ARG_DUMP) - 1, \
|
||||
CLI_ARG_DUMP)
|
||||
CLI_ARG_LOG_INSTRUCTION_PTR)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// NOTE: Argument handling
|
||||
@ -870,11 +902,9 @@ 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];
|
||||
@ -883,8 +913,6 @@ 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));
|
||||
@ -1208,10 +1236,8 @@ 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, S86_MEMORY_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
memcpy(memory, buffer.data, buffer.size);
|
||||
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, .reg = ®ister_file.reg.file.ax, .byte = S86_RegisterByte_Nil},
|
||||
@ -1246,22 +1272,56 @@ int main(int argc, char **argv)
|
||||
{.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
|
||||
// =========================================================================
|
||||
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
|
||||
// =========================================================================
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
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) {
|
||||
@ -1271,7 +1331,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*/
|
||||
@ -1330,6 +1390,7 @@ 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*/
|
||||
@ -1350,27 +1411,26 @@ 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;
|
||||
@ -1391,27 +1451,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) {
|
||||
@ -1446,50 +1506,40 @@ 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_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];
|
||||
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;
|
||||
}
|
||||
@ -1561,40 +1611,34 @@ 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;
|
||||
} 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;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1619,7 +1663,7 @@ int main(int argc, char **argv)
|
||||
|
||||
// NOTE: Instruction Pointer
|
||||
if (log_instruction_ptr)
|
||||
S86_PrintFmt("ip:0x%x->0x%x ", prev_ip, register_file.instruction_ptr);
|
||||
S86_PrintFmt("ip:0x%x->0x%x ", opcode->instruction_ptr, register_file.instruction_ptr);
|
||||
|
||||
// NOTE: Flags
|
||||
if (!S86_RegisterFileFlagsEq(register_file.flags, prev_register_file.flags)) {
|
||||
@ -1703,10 +1747,4 @@ 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);
|
||||
}
|
||||
}
|
||||
|
@ -315,21 +315,16 @@ 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
|
||||
|
@ -111,42 +111,6 @@ 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) {
|
||||
|
@ -53,7 +53,6 @@ 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
|
||||
// ============================================================================
|
||||
|
BIN
project.rdbg
BIN
project.rdbg
Binary file not shown.
Loading…
Reference in New Issue
Block a user