perfaware/part1: Build ASM for exec files and test, move prototype to header

This commit is contained in:
doyle 2023-04-16 21:22:00 +10:00
parent 2a5b3461e3
commit 20be5d0892
6 changed files with 254 additions and 113 deletions

View File

@ -1,94 +1,162 @@
@echo off @echo off
REM Setup REM Setup ==========================================================================================
REM ===========================================================================
set script_dir_backslash=%~dp0 set script_dir_backslash=%~dp0
set script_dir=%script_dir_backslash:~0,-1% set script_dir=%script_dir_backslash:~0,-1%
set build_dir=%script_dir%\build set build_dir=%script_dir%\Build
if not exist %build_dir% mkdir %build_dir% if not exist %build_dir% mkdir %build_dir%
REM Build REM Build ==========================================================================================
REM ===========================================================================
pushd %build_dir% pushd %build_dir%
cl %script_dir%\sim8086.c /W4 /WX /Z7 /nologo || exit /b 1 cl %script_dir%\sim8086.c /W4 /WX /Z7 /nologo || exit /b 1
popd popd
REM Tests REM Tests ==========================================================================================
REM ===========================================================================
set listing_0037=listing_0037_single_register_mov set listing_0037=listing_0037_single_register_mov
copy /Y %script_dir%\%listing_0037% %build_dir% 1>NUL
set build_dir_listing_0037=%build_dir%\%listing_0037% set build_dir_listing_0037=%build_dir%\%listing_0037%
copy /Y %script_dir%\%listing_0037% %build_dir% 1>NUL
%build_dir%\sim8086.exe %build_dir_listing_0037% > %build_dir_listing_0037%_disassembled.asm %build_dir%\sim8086.exe %build_dir_listing_0037% > %build_dir_listing_0037%_disassembled.asm
nasm %build_dir_listing_0037%_disassembled.asm nasm %build_dir_listing_0037%_disassembled.asm
fc /B %build_dir_listing_0037% %build_dir_listing_0037%_disassembled || exit /b 1 fc /B %build_dir_listing_0037% %build_dir_listing_0037%_disassembled || exit /b 1
REM ================================================================================================
set listing_0038=listing_0038_many_register_mov set listing_0038=listing_0038_many_register_mov
copy /Y %script_dir%\%listing_0038% %build_dir% 1>NUL
set build_dir_listing_0038=%build_dir%\%listing_0038% set build_dir_listing_0038=%build_dir%\%listing_0038%
copy /Y %script_dir%\%listing_0038% %build_dir% 1>NUL
%build_dir%\sim8086.exe %build_dir_listing_0038% > %build_dir_listing_0038%_disassembled.asm %build_dir%\sim8086.exe %build_dir_listing_0038% > %build_dir_listing_0038%_disassembled.asm
nasm %build_dir_listing_0038%_disassembled.asm nasm %build_dir_listing_0038%_disassembled.asm
fc /B %build_dir_listing_0038% %build_dir_listing_0038%_disassembled || exit /b 1 fc /B %build_dir_listing_0038% %build_dir_listing_0038%_disassembled || exit /b 1
REM ================================================================================================
set listing_0039=listing_0039_more_movs set listing_0039=listing_0039_more_movs
copy /Y %script_dir%\%listing_0039% %build_dir% 1>NUL
set build_dir_listing_0039=%build_dir%\%listing_0039% set build_dir_listing_0039=%build_dir%\%listing_0039%
copy /Y %script_dir%\%listing_0039% %build_dir% 1>NUL
%build_dir%\sim8086.exe %build_dir_listing_0039% > %build_dir_listing_0039%_disassembled.asm %build_dir%\sim8086.exe %build_dir_listing_0039% > %build_dir_listing_0039%_disassembled.asm
nasm %build_dir_listing_0039%_disassembled.asm nasm %build_dir_listing_0039%_disassembled.asm
fc /B %build_dir_listing_0039% %build_dir_listing_0039%_disassembled || exit /b 1 fc /B %build_dir_listing_0039% %build_dir_listing_0039%_disassembled || exit /b 1
REM ================================================================================================
set listing_0040=listing_0040_challenge_movs set listing_0040=listing_0040_challenge_movs
copy /Y %script_dir%\%listing_0040% %build_dir% 1>NUL
set build_dir_listing_0040=%build_dir%\%listing_0040% set build_dir_listing_0040=%build_dir%\%listing_0040%
copy /Y %script_dir%\%listing_0040% %build_dir% 1>NUL
%build_dir%\sim8086.exe %build_dir_listing_0040% > %build_dir_listing_0040%_disassembled.asm %build_dir%\sim8086.exe %build_dir_listing_0040% > %build_dir_listing_0040%_disassembled.asm
nasm %build_dir_listing_0040%_disassembled.asm nasm %build_dir_listing_0040%_disassembled.asm
fc /B %build_dir_listing_0040% %build_dir_listing_0040%_disassembled || exit /b 1 fc /B %build_dir_listing_0040% %build_dir_listing_0040%_disassembled || exit /b 1
REM ================================================================================================
set listing_0041=listing_0041_add_sub_cmp_jnz set listing_0041=listing_0041_add_sub_cmp_jnz
copy /Y %script_dir%\%listing_0041% %build_dir% 1>NUL
set build_dir_listing_0041=%build_dir%\%listing_0041% set build_dir_listing_0041=%build_dir%\%listing_0041%
copy /Y %script_dir%\%listing_0041% %build_dir% 1>NUL
%build_dir%\sim8086.exe %build_dir_listing_0041% > %build_dir_listing_0041%_disassembled.asm %build_dir%\sim8086.exe %build_dir_listing_0041% > %build_dir_listing_0041%_disassembled.asm
nasm %build_dir_listing_0041%_disassembled.asm nasm %build_dir_listing_0041%_disassembled.asm
fc /B %build_dir_listing_0041% %build_dir_listing_0041%_disassembled || exit /b 1 fc /B %build_dir_listing_0041% %build_dir_listing_0041%_disassembled || exit /b 1
REM ================================================================================================
set listing_0042=listing_0042_completionist_decode set listing_0042=listing_0042_completionist_decode
copy /Y %script_dir%\%listing_0042% %build_dir% 1>NUL
set build_dir_listing_0042=%build_dir%\%listing_0042% set build_dir_listing_0042=%build_dir%\%listing_0042%
copy /Y %script_dir%\%listing_0042% %build_dir% 1>NUL
%build_dir%\sim8086.exe %build_dir_listing_0042% > %build_dir_listing_0042%_disassembled.asm %build_dir%\sim8086.exe %build_dir_listing_0042% > %build_dir_listing_0042%_disassembled.asm
nasm %build_dir_listing_0042%_disassembled.asm nasm %build_dir_listing_0042%_disassembled.asm
fc /B %build_dir_listing_0042% %build_dir_listing_0042%_disassembled || exit /b 1 fc /B %build_dir_listing_0042% %build_dir_listing_0042%_disassembled || exit /b 1
REM ================================================================================================
set listing_0043=listing_0043_immediate_movs set listing_0043=listing_0043_immediate_movs
set build_dir_listing_0043=%build_dir%\%listing_0043%
copy /Y %script_dir%\%listing_0043% %build_dir% 1>NUL copy /Y %script_dir%\%listing_0043% %build_dir% 1>NUL
copy /Y %script_dir%\%listing_0043%.txt %build_dir% 1>NUL copy /Y %script_dir%\%listing_0043%.txt %build_dir% 1>NUL
set build_dir_listing_0043=%build_dir%\%listing_0043%
%build_dir%\sim8086.exe %build_dir_listing_0043% > %build_dir_listing_0043%_disassembled.asm
%build_dir%\sim8086.exe --exec %build_dir_listing_0043% > %build_dir_listing_0043%_disassembled.txt %build_dir%\sim8086.exe --exec %build_dir_listing_0043% > %build_dir_listing_0043%_disassembled.txt
nasm %build_dir_listing_0043%_disassembled.asm
fc /B %build_dir_listing_0043% %build_dir_listing_0043%_disassembled || exit /b 1
fc /N %build_dir_listing_0043%.txt %build_dir_listing_0043%_disassembled.txt || exit /b 1 fc /N %build_dir_listing_0043%.txt %build_dir_listing_0043%_disassembled.txt || exit /b 1
REM ================================================================================================
set listing_0044=listing_0044_register_movs set listing_0044=listing_0044_register_movs
set build_dir_listing_0044=%build_dir%\%listing_0044%
copy /Y %script_dir%\%listing_0044% %build_dir% 1>NUL copy /Y %script_dir%\%listing_0044% %build_dir% 1>NUL
copy /Y %script_dir%\%listing_0044%.txt %build_dir% 1>NUL copy /Y %script_dir%\%listing_0044%.txt %build_dir% 1>NUL
set build_dir_listing_0044=%build_dir%\%listing_0044%
%build_dir%\sim8086.exe --exec %build_dir_listing_0044% > %build_dir_listing_0044%_disassembled.txt %build_dir%\sim8086.exe --exec %build_dir_listing_0044% > %build_dir_listing_0044%_disassembled.txt
%build_dir%\sim8086.exe %build_dir_listing_0044% > %build_dir_listing_0044%_disassembled.asm
nasm %build_dir_listing_0044%_disassembled.asm
fc /B %build_dir_listing_0044% %build_dir_listing_0044%_disassembled || exit /b 1
fc /N %build_dir_listing_0044%.txt %build_dir_listing_0044%_disassembled.txt || exit /b 1 fc /N %build_dir_listing_0044%.txt %build_dir_listing_0044%_disassembled.txt || exit /b 1
REM ================================================================================================
set listing_0045=listing_0045_challenge_register_movs set listing_0045=listing_0045_challenge_register_movs
set build_dir_listing_0045=%build_dir%\%listing_0045%
copy /Y %script_dir%\%listing_0045% %build_dir% 1>NUL copy /Y %script_dir%\%listing_0045% %build_dir% 1>NUL
copy /Y %script_dir%\%listing_0045%.txt %build_dir% 1>NUL copy /Y %script_dir%\%listing_0045%.txt %build_dir% 1>NUL
set build_dir_listing_0045=%build_dir%\%listing_0045%
%build_dir%\sim8086.exe --exec %build_dir_listing_0045% > %build_dir_listing_0045%_disassembled.txt
fc /N %build_dir_listing_0045%.txt %build_dir_listing_0045%_disassembled.txt || exit /b 1
set listing_0045=listing_0045_challenge_register_movs
%build_dir%\sim8086.exe --exec %build_dir_listing_0045% > %build_dir_listing_0045%_disassembled.txt
%build_dir%\sim8086.exe %build_dir_listing_0045% > %build_dir_listing_0045%_disassembled.asm
nasm %build_dir_listing_0045%_disassembled.asm
fc /B %build_dir_listing_0045% %build_dir_listing_0045%_disassembled || exit /b 1
fc /N %build_dir_listing_0045%.txt %build_dir_listing_0045%_disassembled.txt || exit /b 1
REM ================================================================================================
set listing_0046=listing_0046_add_sub_cmp set listing_0046=listing_0046_add_sub_cmp
set build_dir_listing_0046=%build_dir%\%listing_0046%
copy /Y %script_dir%\%listing_0046% %build_dir% 1>NUL copy /Y %script_dir%\%listing_0046% %build_dir% 1>NUL
copy /Y %script_dir%\%listing_0046%.txt %build_dir% 1>NUL copy /Y %script_dir%\%listing_0046%.txt %build_dir% 1>NUL
set build_dir_listing_0046=%build_dir%\%listing_0046%
%build_dir%\sim8086.exe --exec %build_dir_listing_0046% > %build_dir_listing_0046%_disassembled.txt %build_dir%\sim8086.exe --exec %build_dir_listing_0046% > %build_dir_listing_0046%_disassembled.txt
%build_dir%\sim8086.exe %build_dir_listing_0046% > %build_dir_listing_0046%_disassembled.asm
nasm %build_dir_listing_0046%_disassembled.asm
fc /B %build_dir_listing_0046% %build_dir_listing_0046%_disassembled || exit /b 1
fc /N %build_dir_listing_0046%.txt %build_dir_listing_0046%_disassembled.txt || exit /b 1 fc /N %build_dir_listing_0046%.txt %build_dir_listing_0046%_disassembled.txt || exit /b 1
REM ================================================================================================
set listing_0047=listing_0047_challenge_flags set listing_0047=listing_0047_challenge_flags
set build_dir_listing_0047=%build_dir%\%listing_0047%
copy /Y %script_dir%\%listing_0047% %build_dir% 1>NUL copy /Y %script_dir%\%listing_0047% %build_dir% 1>NUL
copy /Y %script_dir%\%listing_0047%.txt %build_dir% 1>NUL copy /Y %script_dir%\%listing_0047%.txt %build_dir% 1>NUL
set build_dir_listing_0047=%build_dir%\%listing_0047%
%build_dir%\sim8086.exe --exec %build_dir_listing_0047% > %build_dir_listing_0047%_disassembled.txt %build_dir%\sim8086.exe --exec %build_dir_listing_0047% > %build_dir_listing_0047%_disassembled.txt
%build_dir%\sim8086.exe %build_dir_listing_0047% > %build_dir_listing_0047%_disassembled.asm
nasm %build_dir_listing_0047%_disassembled.asm
fc /B %build_dir_listing_0047% %build_dir_listing_0047%_disassembled || exit /b 1
fc /N %build_dir_listing_0047%.txt %build_dir_listing_0047%_disassembled.txt || exit /b 1 fc /N %build_dir_listing_0047%.txt %build_dir_listing_0047%_disassembled.txt || exit /b 1
REM ================================================================================================
set listing_0048=listing_0048_ip_register
set build_dir_listing_0048=%build_dir%\%listing_0048%
copy /Y %script_dir%\%listing_0048% %build_dir% 1>NUL
copy /Y %script_dir%\%listing_0048%.txt %build_dir% 1>NUL
%build_dir%\sim8086.exe --exec %build_dir_listing_0048% > %build_dir_listing_0048%_disassembled.txt
%build_dir%\sim8086.exe %build_dir_listing_0048% > %build_dir_listing_0048%_disassembled.asm
nasm %build_dir_listing_0048%_disassembled.asm
fc /B %build_dir_listing_0048% %build_dir_listing_0048%_disassembled || exit /b 1
fc /N %build_dir_listing_0048%.txt %build_dir_listing_0048%_disassembled.txt || exit /b 1

Binary file not shown.

View File

@ -0,0 +1,23 @@
; ========================================================================
;
; (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 48
; ========================================================================
bits 16
mov cx, 200
mov bx, cx
add cx, 1000
mov bx, 2000
sub cx, bx

View File

@ -0,0 +1,13 @@
--- test\listing_0048_ip_register execution ---
mov cx, 200 ; cx:0x0->0xc8 ip:0x0->0x3
mov bx, cx ; bx:0x0->0xc8 ip:0x3->0x5
add cx, 1000 ; cx:0xc8->0x4b0 ip:0x5->0x9 flags:->A
mov bx, 2000 ; bx:0xc8->0x7d0 ip:0x9->0xc
sub cx, bx ; cx:0x4b0->0xfce0 ip:0xc->0xe flags:A->CS
Final registers:
bx: 0x07d0 (2000)
cx: 0xfce0 (64736)
ip: 0x000e (14)
flags: CS

View File

@ -13,46 +13,6 @@
#include "sim8086_stdlib.c" #include "sim8086_stdlib.c"
typedef enum S86_RegisterByte {
S86_RegisterByte_Lo,
S86_RegisterByte_Hi,
S86_RegisterByte_Count,
S86_RegisterByte_Nil,
} S86_RegisterByte;
typedef union S86_Register16 {
uint16_t word;
uint8_t bytes[S86_RegisterByte_Count];
} S86_Register16;
typedef struct S86_RegisterFileFlags {
bool carry;
bool zero;
bool sign;
bool overflow;
bool parity;
bool auxiliary_carry;
} S86_RegisterFileFlags;
typedef struct S86_RegisterFile {
S86_RegisterFileFlags flags;
S86_Register16 ax;
S86_Register16 bx;
S86_Register16 cx;
S86_Register16 dx;
S86_Register16 sp;
S86_Register16 bp;
S86_Register16 si;
S86_Register16 di;
S86_Register16 es;
S86_Register16 cs;
S86_Register16 ss;
S86_Register16 ds;
} S86_RegisterFile;
bool S86_RegisterFileFlagsEq(S86_RegisterFileFlags lhs, S86_RegisterFileFlags rhs) bool S86_RegisterFileFlagsEq(S86_RegisterFileFlags lhs, S86_RegisterFileFlags rhs)
{ {
bool result = lhs.carry == rhs.carry && bool result = lhs.carry == rhs.carry &&
@ -865,42 +825,57 @@ typedef struct S86_MnemonicOpToRegisterFileMap {
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;
#define PRINT_USAGE S86_PrintLn(S86_STR8("usage: sim8086.exe [--exec] <binary asm file>")) char const CLI_ARG_EXEC[] = "--exec";
char const CLI_ARG_LOG_INSTRUCTION_PTR[] = "--log-instruction-ptr";
#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)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// NOTE: Argument handling // NOTE: Argument handling
// ========================================================================= // =========================================================================
if (argc != 2 && argc != 3) { if (argc < 2) {
PRINT_USAGE; PRINT_USAGE;
return -1; return -1;
} }
bool exec_mode = false; S86_Str8 CLI_ARG_EXEC_STR8 = (S86_Str8){(char *)CLI_ARG_EXEC, S86_ARRAY_UCOUNT(CLI_ARG_EXEC) - 1};
char const *file_path = NULL; 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};
if (argc == 3) {
S86_Str8 exec_mode_str8 = {argv[1], strlen(argv[1])}; bool exec_mode = false;
file_path = argv[2]; bool log_instruction_ptr = false;
if (!S86_Str8_Equals(exec_mode_str8, S86_STR8("--exec"))) { S86_Str8 file_path = {0};
PRINT_USAGE; for (int arg_index = 1; arg_index < argc; arg_index++) {
return -1; char const *arg_cstring = argv[arg_index];
S86_Str8 arg_str8 = (S86_Str8){(char *)arg_cstring, strlen(arg_cstring)};
if (S86_Str8_Equals(arg_str8, CLI_ARG_EXEC_STR8)) {
exec_mode = true;
} else if (S86_Str8_Equals(arg_str8, CLI_ARG_LOG_INSTRUCTION_PTR_STR8)) {
log_instruction_ptr = 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));
PRINT_USAGE;
return -1;
}
file_path = arg_str8;
} }
exec_mode = true;
} else {
file_path = argv[1];
} }
char const *file_name = file_path; char const *file_name = file_path.data;
size_t file_path_size = strlen(file_path); for (size_t index = file_path.size - 1; index < file_path.size; index--) {
for (size_t index = file_path_size - 1; index < file_path_size; index--) { if (file_path.data[index] == '\\' || file_path.data[index] == '/') {
if (file_path[index] == '\\' || file_path[index] == '/') { file_name = file_path.data + index + 1;
file_name = file_path + index + 1;
break; break;
} }
} }
S86_Buffer buffer = S86_FileRead(file_path); S86_Buffer buffer = S86_FileRead(file_path.data);
if (!S86_BufferIsValid(buffer)) { if (!S86_BufferIsValid(buffer)) {
S86_PrintLnFmt("File read failed [path=\"%s\"]", argv[1], buffer.size); S86_PrintLnFmt("ERROR: Failed to read file [path=\"%.*s\"]", S86_STR8_FMT(file_path));
return -1; return -1;
} }
@ -1204,10 +1179,6 @@ 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};
S86_BufferIterator buffer_it = S86_BufferIteratorInit(buffer);
S86_MnemonicOp seg_reg = {0};
bool lock_prefix = false;
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.ax, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_AX, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = &register_file.ax, .byte = S86_RegisterByte_Nil},
{.mnemonic_op = S86_MnemonicOp_AL, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = &register_file.ax, .byte = S86_RegisterByte_Lo}, {.mnemonic_op = S86_MnemonicOp_AL, .mnemonic_op_reg16 = S86_MnemonicOp_AX, .reg = &register_file.ax, .byte = S86_RegisterByte_Lo},
@ -1236,14 +1207,39 @@ int main(int argc, char **argv)
{.mnemonic_op = S86_MnemonicOp_DS, .mnemonic_op_reg16 = S86_MnemonicOp_DS, .reg = &register_file.ds, .byte = S86_RegisterByte_Nil}, {.mnemonic_op = S86_MnemonicOp_DS, .mnemonic_op_reg16 = S86_MnemonicOp_DS, .reg = &register_file.ds, .byte = S86_RegisterByte_Nil},
}; };
while (S86_BufferIteratorHasMoreBytes(buffer_it)) { S86_Opcode *opcode_array = NULL;
S86_Opcode opcode = S86_DecodeOpcode(&buffer_it, size_t opcode_size = 0;
DECODE_TABLE, {
S86_ARRAY_UCOUNT(DECODE_TABLE), bool lock_prefix = false;
&lock_prefix, S86_MnemonicOp seg_reg = S86_CAST(S86_MnemonicOp)0;
&seg_reg); for (S86_BufferIterator it = S86_BufferIteratorInit(buffer);
S86_PrintOpcode(opcode); S86_BufferIteratorHasMoreBytes(it);
if (opcode.mnemonic == S86_Mnemonic_LOCK || opcode.mnemonic == S86_Mnemonic_SEGMENT) opcode_size++) {
S86_DecodeOpcode(&it, DECODE_TABLE, S86_ARRAY_UCOUNT(DECODE_TABLE), &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;
}
size_t opcode_index = 0;
for (S86_BufferIterator it = S86_BufferIteratorInit(buffer); S86_BufferIteratorHasMoreBytes(it);) {
opcode_array[opcode_index++] = S86_DecodeOpcode(&it, DECODE_TABLE, S86_ARRAY_UCOUNT(DECODE_TABLE), &lock_prefix, &seg_reg);
}
}
for (size_t opcode_index = 0; opcode_index < opcode_size; opcode_index++) {
S86_Opcode *opcode = opcode_array + opcode_index;
S86_PrintOpcode(*opcode);
if (opcode->mnemonic == S86_Mnemonic_LOCK || opcode->mnemonic == S86_Mnemonic_SEGMENT)
continue; continue;
if (!exec_mode) { if (!exec_mode) {
@ -1252,7 +1248,7 @@ int main(int argc, char **argv)
} }
S86_RegisterFileFlags prev_flags = register_file.flags; S86_RegisterFileFlags prev_flags = register_file.flags;
switch (opcode.mnemonic) { switch (opcode->mnemonic) {
case S86_Mnemonic_PUSH: /*FALLTHRU*/ case S86_Mnemonic_PUSH: /*FALLTHRU*/
case S86_Mnemonic_POP: /*FALLTHRU*/ case S86_Mnemonic_POP: /*FALLTHRU*/
case S86_Mnemonic_XCHG: /*FALLTHRU*/ case S86_Mnemonic_XCHG: /*FALLTHRU*/
@ -1339,26 +1335,26 @@ int main(int argc, char **argv)
S86_MnemonicOpToRegisterFileMap const *dest_map = NULL; S86_MnemonicOpToRegisterFileMap const *dest_map = NULL;
for (size_t index = 0; !dest_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { 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; 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; dest_map = item;
} }
S86_ASSERT(dest_map); S86_ASSERT(dest_map);
uint16_t prev_dest = dest_map->reg->word; uint16_t prev_dest = dest_map->reg->word;
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; dest_map->reg->bytes[dest_map->byte] = S86_CAST(uint8_t)opcode->immediate;
} else { } else {
S86_ASSERT(opcode.immediate < S86_CAST(uint16_t)-1); S86_ASSERT(opcode->immediate < S86_CAST(uint16_t)-1);
dest_map->reg->word = S86_CAST(uint16_t)opcode.immediate; dest_map->reg->word = S86_CAST(uint16_t)opcode->immediate;
} }
} 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++) {
S86_MnemonicOpToRegisterFileMap const *item = 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; src_map = item;
} }
@ -1378,30 +1374,30 @@ int main(int argc, char **argv)
S86_MnemonicOpToRegisterFileMap *dest_map = NULL; S86_MnemonicOpToRegisterFileMap *dest_map = NULL;
for (size_t index = 0; !dest_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { 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; 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; dest_map = item;
} }
S86_ASSERT(dest_map); S86_ASSERT(dest_map);
bool subtract = opcode.mnemonic != S86_Mnemonic_ADD; bool subtract = opcode->mnemonic != S86_Mnemonic_ADD;
S86_Register16 dest = *dest_map->reg; S86_Register16 dest = *dest_map->reg;
S86_Register16 prev_dest = dest; S86_Register16 prev_dest = dest;
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; uint16_t src = 0;
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);
src = S86_CAST(uint8_t)opcode.immediate; src = S86_CAST(uint8_t)opcode->immediate;
} else { } else {
S86_ASSERT(opcode.immediate < S86_CAST(uint16_t)-1); S86_ASSERT(opcode->immediate < S86_CAST(uint16_t)-1);
src = S86_CAST(uint16_t)opcode.immediate; src = S86_CAST(uint16_t)opcode->immediate;
} }
} 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++) {
S86_MnemonicOpToRegisterFileMap const *item = 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; src_map = item;
} }
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;
@ -1473,10 +1469,10 @@ int main(int argc, char **argv)
int lo_bit_count = _mm_popcnt_u32(S86_CAST(uint32_t)dest.bytes[S86_RegisterByte_Lo]); 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.parity = lo_bit_count % 2 == 0;
register_file.flags.zero = false; register_file.flags.zero = false;
if (opcode.mnemonic == S86_Mnemonic_ADD || opcode.mnemonic == S86_Mnemonic_SUB) if (opcode->mnemonic == S86_Mnemonic_ADD || opcode->mnemonic == S86_Mnemonic_SUB)
register_file.flags.zero = byte_op ? dest.bytes[dest_map->byte] == 0 : dest.word == 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) {
S86_PrintFmt(" ; "); S86_PrintFmt(" ; ");
} else { } else {
S86_Str8 dest_reg16 = S86_MnemonicOpStr8(dest_map->mnemonic_op_reg16); S86_Str8 dest_reg16 = S86_MnemonicOpStr8(dest_map->mnemonic_op_reg16);

View File

@ -337,6 +337,47 @@ typedef struct S86_Opcode {
S86_MnemonicOp seg_reg_prefix; ///< Segment register that should prefix the upcoming instruction S86_MnemonicOp seg_reg_prefix; ///< Segment register that should prefix the upcoming instruction
} S86_Opcode; } S86_Opcode;
typedef enum S86_RegisterByte {
S86_RegisterByte_Lo,
S86_RegisterByte_Hi,
S86_RegisterByte_Count,
S86_RegisterByte_Nil,
} S86_RegisterByte;
typedef union S86_Register16 {
uint16_t word;
uint8_t bytes[S86_RegisterByte_Count];
} S86_Register16;
typedef struct S86_RegisterFileFlags {
bool carry;
bool zero;
bool sign;
bool overflow;
bool parity;
bool auxiliary_carry;
} S86_RegisterFileFlags;
typedef struct S86_RegisterFile {
S86_RegisterFileFlags flags;
S86_Register16 ax;
S86_Register16 bx;
S86_Register16 cx;
S86_Register16 dx;
S86_Register16 sp;
S86_Register16 bp;
S86_Register16 si;
S86_Register16 di;
S86_Register16 es;
S86_Register16 cs;
S86_Register16 ss;
S86_Register16 ds;
} S86_RegisterFile;
bool S86_RegisterFileFlagsEq (S86_RegisterFileFlags lhs, S86_RegisterFileFlags rhs);
S86_Str8 S86_MnemonicStr8 (S86_Mnemonic type); S86_Str8 S86_MnemonicStr8 (S86_Mnemonic type);
S86_MnemonicOp S86_MnemonicOpFromWReg (bool w, uint8_t reg); S86_MnemonicOp S86_MnemonicOpFromWReg (bool w, uint8_t reg);
S86_MnemonicOp S86_MnemonicOpFromSR (uint8_t sr); S86_MnemonicOp S86_MnemonicOpFromSR (uint8_t sr);