diff options
Diffstat (limited to 'src/code')
| -rwxr-xr-x | src/code/build.sh | 42 | ||||
| -rw-r--r-- | src/code/reference_decoder/sim86.h | 27 | ||||
| -rw-r--r-- | src/code/reference_decoder/sim86_decode.cpp | 303 | ||||
| -rw-r--r-- | src/code/reference_decoder/sim86_decode.h | 35 | ||||
| -rw-r--r-- | src/code/reference_decoder/sim86_instruction.cpp | 84 | ||||
| -rw-r--r-- | src/code/reference_decoder/sim86_instruction.h | 109 | ||||
| -rw-r--r-- | src/code/reference_decoder/sim86_instruction_table.cpp | 27 | ||||
| -rw-r--r-- | src/code/reference_decoder/sim86_instruction_table.h | 60 | ||||
| -rw-r--r-- | src/code/reference_decoder/sim86_instruction_table.inl | 250 | ||||
| -rw-r--r-- | src/code/reference_decoder/sim86_lib.cpp | 73 | ||||
| -rw-r--r-- | src/code/reference_decoder/sim86_memory.cpp | 66 | ||||
| -rw-r--r-- | src/code/reference_decoder/sim86_memory.h | 28 | ||||
| -rw-r--r-- | src/code/reference_decoder/sim86_text_table.cpp | 57 | ||||
| -rw-r--r-- | src/code/shared_library_test.cpp | 69 | ||||
| -rw-r--r-- | src/code/sim86.cpp | 375 | ||||
| -rw-r--r-- | src/code/sim86.h | 53 | ||||
| -rw-r--r-- | src/code/sim86_shared.h | 285 |
17 files changed, 0 insertions, 1943 deletions
diff --git a/src/code/build.sh b/src/code/build.sh deleted file mode 100755 index 87a5b85..0000000 --- a/src/code/build.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh - -ThisDir="$(dirname "$(readlink -f "$0")")" -cd "$ThisDir" - -Compiler="clang" - -CompilerFlags=" --g --fdiagnostics-absolute-paths --nostdinc++ --DSIM86_INTERNAL --fsanitize=undefined -" - -WarningFlags=" --Wall --Wextra --Wno-unused-label --Wno-unused-variable --Wno-unused-function --Wno-unused-but-set-variable --Wno-missing-field-initializers --Wno-write-strings -" - -Libs="./reference_decoder/sim86_lib.cpp" - -if false -then - Source="./shared_library_test.cpp" - printf '%s\n' "$Source" - $Compiler $CompilerFlags $WarningFlags \ - -o ../build/shared_library_test \ - $Libs $Source -fi - -Source="sim86.cpp" -printf '%s\n' "$Source" -$Compiler $CompilerFlags $WarningFlags \ - -o ../build/sim86 \ - $Libs $Source diff --git a/src/code/reference_decoder/sim86.h b/src/code/reference_decoder/sim86.h deleted file mode 100644 index b065a0e..0000000 --- a/src/code/reference_decoder/sim86.h +++ /dev/null @@ -1,27 +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 more information - - ======================================================================== */ - -typedef char unsigned u8; -typedef short unsigned u16; -typedef int unsigned u32; -typedef long long unsigned u64; - -typedef char s8; -typedef short s16; -typedef int s32; -typedef long long s64; - -typedef s32 b32; - -#define ArrayCount(Array) (sizeof(Array) / sizeof((Array)[0])) - -static u32 const SIM86_VERSION = 4; diff --git a/src/code/reference_decoder/sim86_decode.cpp b/src/code/reference_decoder/sim86_decode.cpp deleted file mode 100644 index dc084d5..0000000 --- a/src/code/reference_decoder/sim86_decode.cpp +++ /dev/null @@ -1,303 +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 more information - - ======================================================================== */ - -struct decode_context -{ - u32 DefaultSegment; - u32 AdditionalFlags; -}; - -static instruction_operand GetRegOperand(u32 IntelRegIndex, b32 Wide) -{ - // NOTE(casey): This maps Intel's REG and RM field encodings for registers to our encoding for registers. - register_access RegTable[][2] = - { - {{Register_a, 0, 1}, {Register_a, 0, 2}}, - {{Register_c, 0, 1}, {Register_c, 0, 2}}, - {{Register_d, 0, 1}, {Register_d, 0, 2}}, - {{Register_b, 0, 1}, {Register_b, 0, 2}}, - {{Register_a, 1, 1}, {Register_sp, 0, 2}}, - {{Register_c, 1, 1}, {Register_bp, 0, 2}}, - {{Register_d, 1, 1}, {Register_si, 0, 2}}, - {{Register_b, 1, 1}, {Register_di, 0, 2}}, - }; - - instruction_operand Result = {}; - Result.Type = Operand_Register; - Result.Register = RegTable[IntelRegIndex & 0x7][(Wide != 0)]; - - return Result; -} - -// NOTE(casey): ParseDataValue is not a real function, it's basically just a macro that is used in -// TryParse. It should never be called otherwise, but that is not something you can do in C++. -// In other languages it would be a "local function". -static u32 ParseDataValue(segmented_access *Access, b32 Exists, b32 Wide, b32 SignExtended) -{ - u32 Result = {}; - - if(Exists) - { - if(Wide) - { - u8 D0 = *AccessMemory(*Access, 0); - u8 D1 = *AccessMemory(*Access, 1); - Result = (D1 << 8) | D0; - Access->SegmentOffset += 2; - } - else - { - Result = *AccessMemory(*Access); - if(SignExtended) - { - Result = (s32)*(s8 *)&Result; - } - Access->SegmentOffset += 1; - } - } - - return Result; -} - -static instruction TryDecode(decode_context *Context, instruction_encoding *Inst, segmented_access At) -{ - instruction Dest = {}; - b32 Has[Bits_Count] = {}; - u32 Bits[Bits_Count] = {}; - b32 Valid = true; - - u64 StartingAddress = GetAbsoluteAddressOf(At); - - u8 BitsPendingCount = 0; - u8 BitsPending = 0; - for(u32 BitsIndex = 0; Valid && (BitsIndex < ArrayCount(Inst->Bits)); ++BitsIndex) - { - instruction_bits TestBits = Inst->Bits[BitsIndex]; - if(TestBits.Usage == Bits_End) - { - // NOTE(casey): That's the end of the instruction format. - break; - } - - u32 ReadBits = TestBits.Value; - if(TestBits.BitCount != 0) - { - if(BitsPendingCount == 0) - { - BitsPendingCount = 8; - BitsPending = *AccessMemory(At); - ++At.SegmentOffset; - } - - // NOTE(casey): If this assert fires, it means we have an error in our table, - // since there are no 8086 instructions that have bit values straddling a - // byte boundary. - assert(TestBits.BitCount <= BitsPendingCount); - - BitsPendingCount -= TestBits.BitCount; - ReadBits = BitsPending; - ReadBits >>= BitsPendingCount; - ReadBits &= ~(0xff << TestBits.BitCount); - } - - if(TestBits.Usage == Bits_Literal) - { - // NOTE(casey): This is a "required" sequence - Valid = Valid && (ReadBits == TestBits.Value); - } - else - { - Bits[TestBits.Usage] |= (ReadBits << TestBits.Shift); - Has[TestBits.Usage] = true; - } - } - - if(Valid) - { - u32 Mod = Bits[Bits_MOD]; - u32 RM = Bits[Bits_RM]; - u32 W = Bits[Bits_W]; - b32 S = Bits[Bits_S]; - b32 D = Bits[Bits_D]; - - b32 HasDirectAddress = ((Mod == 0b00) && (RM == 0b110)); - Has[Bits_Disp] = ((Has[Bits_Disp]) || (Mod == 0b10) || (Mod == 0b01) || HasDirectAddress); - - b32 DisplacementIsW = ((Bits[Bits_DispAlwaysW]) || (Mod == 0b10) || HasDirectAddress); - b32 DataIsW = ((Bits[Bits_WMakesDataW]) && !S && W); - - Bits[Bits_Disp] |= ParseDataValue(&At, Has[Bits_Disp], DisplacementIsW, (!DisplacementIsW)); - Bits[Bits_Data] |= ParseDataValue(&At, Has[Bits_Data], DataIsW, S); - - Dest.Op = Inst->Op; - Dest.Flags = Context->AdditionalFlags; - Dest.Address = StartingAddress; - Dest.Size = GetAbsoluteAddressOf(At) - StartingAddress; - Dest.SegmentOverride = Context->DefaultSegment; - - if(W) - { - Dest.Flags |= Inst_Wide; - } - - if(Bits[Bits_Far]) - { - Dest.Flags |= Inst_Far; - } - - if(Bits[Bits_Z]) - { - Dest.Flags |= Inst_RepNE; - } - - u32 Disp = Bits[Bits_Disp]; - s16 Displacement = (s16)Disp; - - instruction_operand *RegOperand = &Dest.Operands[D ? 0 : 1]; - instruction_operand *ModOperand = &Dest.Operands[D ? 1 : 0]; - - if(Has[Bits_SR]) - { - *RegOperand = RegisterOperand(Register_es + (Bits[Bits_SR] & 0x3), 2); - } - - if(Has[Bits_REG]) - { - *RegOperand = GetRegOperand(Bits[Bits_REG], W); - } - - if(Has[Bits_MOD]) - { - if(Mod == 0b11) - { - *ModOperand = GetRegOperand(RM, W || (Bits[Bits_RMRegAlwaysW])); - } - else - { - register_mapping_8086 IntelTerm0[8] = { Register_b, Register_b, Register_bp, Register_bp, Register_si, Register_di, Register_bp, Register_b}; - register_mapping_8086 IntelTerm1[8] = {Register_si, Register_di, Register_si, Register_di}; - - u32 I = RM&0x7; - register_mapping_8086 Term0 = IntelTerm0[I]; - register_mapping_8086 Term1 = IntelTerm1[I]; - if((Mod == 0b00) && (RM == 0b110)) - { - Term0 = {}; - Term1 = {}; - } - - *ModOperand = EffectiveAddressOperand(RegisterAccess(Term0, 0, 2), RegisterAccess(Term1, 0, 2), Displacement); - } - } - - if(Has[Bits_Data] && Has[Bits_Disp] && !Has[Bits_MOD]) - { - Dest.Operands[0] = IntersegmentAddressOperand(Bits[Bits_Data], Bits[Bits_Disp]); - } - else - { - // - // NOTE(casey): Because there are some strange opcodes that do things like have an immediate as - // a _destination_ ("out", for example), I define immediates and other "additional operands" to - // go in "whatever slot was not used by the reg and mod fields". - // - - instruction_operand *LastOperand = &Dest.Operands[0]; - if(LastOperand->Type) - { - LastOperand = &Dest.Operands[1]; - } - - if(Bits[Bits_RelJMPDisp]) - { - *LastOperand = ImmediateOperand(Displacement, Immediate_RelativeJumpDisplacement); - } - else if(Has[Bits_Data]) - { - *LastOperand = ImmediateOperand(Bits[Bits_Data]); - } - else if(Has[Bits_V]) - { - if(Bits[Bits_V]) - { - *LastOperand = RegisterOperand(Register_c, 1); - } - else - { - *LastOperand = ImmediateOperand(1); - } - } - } - } - - return Dest; -} - -static instruction DecodeInstruction(instruction_table Table, segmented_access At) -{ - /* TODO(casey): Hmm. It seems like this is a very inefficient way to parse - instructions, isn't it? For every instruction, we check every entry in the - table until we find a match. Is this bad design? Or did the person who wrote - it know what they were doing, and has a plan for how it can be optimized - later? Only time will tell... :) */ - - decode_context Context = {}; - instruction Result = {}; - - u32 StartingAddress = GetAbsoluteAddressOf(At); - u32 TotalSize = 0; - while(TotalSize < Table.MaxInstructionByteCount) - { - Result = {}; - for(u32 Index = 0; Index < Table.EncodingCount; ++Index) - { - instruction_encoding Inst = Table.Encodings[Index]; - Result = TryDecode(&Context, &Inst, At); - if(Result.Op) - { - At.SegmentOffset += Result.Size; - TotalSize += Result.Size; - break; - } - } - - if(Result.Op == Op_lock) - { - Context.AdditionalFlags |= Inst_Lock; - } - else if(Result.Op == Op_rep) - { - Context.AdditionalFlags |= Inst_Rep | (Result.Flags & Inst_RepNE); - } - else if(Result.Op == Op_segment) - { - Context.AdditionalFlags |= Inst_Segment; - Context.DefaultSegment = Result.Operands[1].Register.Index; - } - else - { - break; - } - } - - if(TotalSize <= Table.MaxInstructionByteCount) - { - Result.Address = StartingAddress; - Result.Size = TotalSize; - } - else - { - Result = {}; - } - - return Result; -} diff --git a/src/code/reference_decoder/sim86_decode.h b/src/code/reference_decoder/sim86_decode.h deleted file mode 100644 index 534ce2d..0000000 --- a/src/code/reference_decoder/sim86_decode.h +++ /dev/null @@ -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 more information - - ======================================================================== */ - -enum register_mapping_8086 -{ - Register_none, - - Register_a, - Register_b, - Register_c, - Register_d, - Register_sp, - Register_bp, - Register_si, - Register_di, - Register_es, - Register_cs, - Register_ss, - Register_ds, - Register_ip, - Register_flags, - - Register_count, -}; - -static instruction DecodeInstruction(instruction_table Table, segmented_access At); diff --git a/src/code/reference_decoder/sim86_instruction.cpp b/src/code/reference_decoder/sim86_instruction.cpp deleted file mode 100644 index 34fcf1f..0000000 --- a/src/code/reference_decoder/sim86_instruction.cpp +++ /dev/null @@ -1,84 +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 more information - - ======================================================================== */ - -static b32 OperandIsType(instruction Instruction, u32 Index, operand_type Type) -{ - b32 Result = (Instruction.Operands[Index].Type == Type); - return Result; -} - -static instruction_operand GetOperand(instruction Instruction, u32 Index) -{ - assert(Index < ArrayCount(Instruction.Operands)); - instruction_operand Result = Instruction.Operands[Index]; - return Result; -} - -static register_access RegisterAccess(u32 Index, u32 Offset, u32 Count) -{ - register_access Result = {}; - - Result.Index = Index; - Result.Offset = Offset; - Result.Count = Count; - - return Result; -} - -static instruction_operand IntersegmentAddressOperand(u32 Segment, s32 Displacement) -{ - instruction_operand Result = {}; - - Result.Type = Operand_Memory; - Result.Address.ExplicitSegment = Segment; - Result.Address.Displacement = Displacement; - Result.Address.Flags = Address_ExplicitSegment; - - return Result; -} - -static instruction_operand EffectiveAddressOperand(register_access Term0, register_access Term1, s32 Displacement) -{ - instruction_operand Result = {}; - - Result.Type = Operand_Memory; - Result.Address.Terms[0].Register = Term0; - Result.Address.Terms[0].Scale = 1; - Result.Address.Terms[1].Register = Term1; - Result.Address.Terms[1].Scale = 1; - Result.Address.Displacement = Displacement; - - return Result; -} - -static instruction_operand RegisterOperand(u32 Index, u32 Count) -{ - instruction_operand Result = {}; - - Result.Type = Operand_Register; - Result.Register.Index = Index; - Result.Register.Offset = 0; - Result.Register.Count = Count; - - return Result; -} - -static instruction_operand ImmediateOperand(u32 Value, u32 Flags = 0) -{ - instruction_operand Result = {}; - - Result.Type = Operand_Immediate; - Result.Immediate.Value = Value; - Result.Immediate.Flags = Flags; - - return Result; -} diff --git a/src/code/reference_decoder/sim86_instruction.h b/src/code/reference_decoder/sim86_instruction.h deleted file mode 100644 index 191635a..0000000 --- a/src/code/reference_decoder/sim86_instruction.h +++ /dev/null @@ -1,109 +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 more information - - ======================================================================== */ - -typedef u32 register_index; - -// NOTE(casey): To make it easier to compile with languages which do not -// have auto-typedef'ing (like C, etc.), all types are manually typedef'd here. -typedef struct register_access register_access; -typedef struct effective_address_term effective_address_term; -typedef struct effective_address_expression effective_address_expression; -typedef struct immediate immediate; -typedef struct instruction_operand instruction_operand; -typedef struct instruction instruction; - -typedef enum operation_type : u32 -{ - Op_None, - -#define INST(Mnemonic, ...) Op_##Mnemonic, -#define INSTALT(...) -#include "sim86_instruction_table.inl" - - Op_Count, -} operation_type; - -enum instruction_flag -{ - Inst_Lock = 0x1, - Inst_Rep = 0x2, - Inst_Segment = 0x4, - Inst_Wide = 0x8, - Inst_Far = 0x10, - Inst_RepNE = 0x20, // NOTE(casey): For user convenience, this will be set _in addition to_ Inst_Rep for REPNE/REPNZ -}; - -struct register_access -{ - register_index Index; - u32 Offset; - u32 Count; -}; - -struct effective_address_term -{ - register_access Register; - s32 Scale; -}; - -enum effective_address_flag -{ - Address_ExplicitSegment = 0x1, -}; -struct effective_address_expression -{ - effective_address_term Terms[2]; - u32 ExplicitSegment; - s32 Displacement; - u32 Flags; -}; - -enum immediate_flag -{ - Immediate_RelativeJumpDisplacement = 0x1, -}; -struct immediate -{ - s32 Value; - u32 Flags; -}; - -typedef enum operand_type : u32 -{ - Operand_None, - Operand_Register, - Operand_Memory, - Operand_Immediate, -} operand_type; -struct instruction_operand -{ - operand_type Type; - union - { - effective_address_expression Address; - register_access Register; - immediate Immediate; - }; -}; - -struct instruction -{ - u32 Address; - u32 Size; - - operation_type Op; - u32 Flags; - - instruction_operand Operands[2]; - - register_index SegmentOverride; -}; diff --git a/src/code/reference_decoder/sim86_instruction_table.cpp b/src/code/reference_decoder/sim86_instruction_table.cpp deleted file mode 100644 index be3ec82..0000000 --- a/src/code/reference_decoder/sim86_instruction_table.cpp +++ /dev/null @@ -1,27 +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 more information - - ======================================================================== */ - -static instruction_encoding InstructionTable8086[] = -{ -#include "sim86_instruction_table.inl" -}; - -static instruction_table Get8086InstructionTable() -{ - instruction_table Result = {}; - - Result.EncodingCount = ArrayCount(InstructionTable8086); - Result.Encodings = InstructionTable8086; - Result.MaxInstructionByteCount = 15; // NOTE(casey): This is the "Intel-specified" maximum length of an instruction, including prefixes - - return Result; -} diff --git a/src/code/reference_decoder/sim86_instruction_table.h b/src/code/reference_decoder/sim86_instruction_table.h deleted file mode 100644 index ed8aea8..0000000 --- a/src/code/reference_decoder/sim86_instruction_table.h +++ /dev/null @@ -1,60 +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 more information - - ======================================================================== */ - -enum instruction_bits_usage : u8 -{ - Bits_End, // NOTE(casey): The 0 value, indicating the end of the instruction encoding array - - Bits_Literal, // NOTE(casey): These are opcode bits that identify instructions - - // NOTE(casey): These bits correspond directly to the 8086 instruction manual - Bits_D, - Bits_S, - Bits_W, - Bits_V, - Bits_Z, - Bits_MOD, - Bits_REG, - Bits_RM, - Bits_SR, - Bits_Disp, - Bits_Data, - - Bits_DispAlwaysW, // NOTE(casey): Tag for instructions where the displacement is always 16 bits - Bits_WMakesDataW, // NOTE(casey): Tag for instructions where SW=01 makes the data field become 16 bits - Bits_RMRegAlwaysW, // NOTE(casey): Tag for instructions where the register encoded in RM is always 16-bit width - Bits_RelJMPDisp, // NOTE(casey): Tag for instructions that require address adjustment to go through NASM properly - Bits_Far, // NOTE(casey): Tag for instructions that require a "far" keyword in their ASM to select the right opcode - - Bits_Count, -}; - -struct instruction_bits -{ - instruction_bits_usage Usage; - u8 BitCount; - u8 Shift; - u8 Value; -}; - -struct instruction_encoding -{ - operation_type Op; - instruction_bits Bits[16]; -}; - -struct instruction_table -{ - instruction_encoding *Encodings; - u32 EncodingCount; - u32 MaxInstructionByteCount; -}; diff --git a/src/code/reference_decoder/sim86_instruction_table.inl b/src/code/reference_decoder/sim86_instruction_table.inl deleted file mode 100644 index 576c0f6..0000000 --- a/src/code/reference_decoder/sim86_instruction_table.inl +++ /dev/null @@ -1,250 +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 more information - - ======================================================================== */ - -/* - NOTE(casey): This instruction table is a direct translation of table 4-12 in the Intel 8086 manual. - The macros are designed to allow direct transcription, without changing the order or manner - of specification in the table in any way. Additional "implicit" versions of the macros are provided - so that hard-coded fields can be supplied uniformly. - - The table is also designed to allow you to include it multiple times to "pull out" other things - from the table, such as opcode mnemonics as strings or enums, etc. -*/ - -#ifndef INST -#define INST(Mnemonic, ...) {Op_##Mnemonic, __VA_ARGS__}, -#endif - -#ifndef INSTALT -#define INSTALT INST -#endif - -#define B(Bits) {Bits_Literal, sizeof(#Bits)-1, 0, 0b##Bits} -#define D {Bits_D, 1} -#define S {Bits_S, 1} -#define W {Bits_W, 1} -#define V {Bits_V, 1} -#define Z {Bits_Z, 1} - -#define XXX {Bits_Data, 3, 0} -#define YYY {Bits_Data, 3, 3} -#define RM {Bits_RM, 3} -#define MOD {Bits_MOD, 2} -#define REG {Bits_REG, 3} -#define SR {Bits_SR, 2} - -#define ImpW(Value) {Bits_W, 0, 0, Value} -#define ImpREG(Value) {Bits_REG, 0, 0, Value} -#define ImpMOD(Value) {Bits_MOD, 0, 0, Value} -#define ImpRM(Value) {Bits_RM, 0, 0, Value} -#define ImpD(Value) {Bits_D, 0, 0, Value} -#define ImpS(Value) {Bits_S, 0, 0, Value} - -#define DISP {Bits_Disp, 0, 0, 0} -#define ADDR {Bits_Disp, 0, 0, 0}, {Bits_DispAlwaysW, 0, 0, 1} -#define DATA {Bits_Data, 0, 0, 0} -#define DATA_IF_W {Bits_WMakesDataW, 0, 0, 1} -#define Flags(F) {F, 0, 0, 1} - -INST(mov, {B(100010), D, W, MOD, REG, RM}) -INSTALT(mov, {B(1100011), W, MOD, B(000), RM, DATA, DATA_IF_W, ImpD(0)}) -INSTALT(mov, {B(1011), W, REG, DATA, DATA_IF_W, ImpD(1)}) -INSTALT(mov, {B(1010000), W, ADDR, ImpREG(0), ImpMOD(0), ImpRM(0b110), ImpD(1)}) -INSTALT(mov, {B(1010001), W, ADDR, ImpREG(0), ImpMOD(0), ImpRM(0b110), ImpD(0)}) -INSTALT(mov, {B(100011), D, B(0), MOD, B(0), SR, RM, ImpW(1)}) // NOTE(casey): This collapses 2 entries in the 8086 table by adding an explicit D bit - -INST(push, {B(11111111), MOD, B(110), RM, ImpW(1), ImpD(1)}) -INSTALT(push, {B(01010), REG, ImpW(1), ImpD(1)}) -INSTALT(push, {B(000), SR, B(110), ImpW(1), ImpD(1)}) - -INST(pop, {B(10001111), MOD, B(000), RM, ImpW(1), ImpD(1)}) -INSTALT(pop, {B(01011), REG, ImpW(1), ImpD(1)}) -INSTALT(pop, {B(000), SR, B(111), ImpW(1), ImpD(1)}) - -INST(xchg, {B(1000011), W, MOD, REG, RM, ImpD(1)}) -INSTALT(xchg, {B(10010), REG, ImpMOD(0b11), ImpW(1), ImpRM(0)}) - -INST(in, {B(1110010), W, DATA, ImpREG(0), ImpD(1)}) -INSTALT(in, {B(1110110), W, ImpREG(0), ImpD(1), ImpMOD(0b11), ImpRM(2), Flags(Bits_RMRegAlwaysW)}) -INST(out, {B(1110011), W, DATA, ImpREG(0), ImpD(0)}) -INSTALT(out, {B(1110111), W, ImpREG(0), ImpD(0), ImpMOD(0b11), ImpRM(2), Flags(Bits_RMRegAlwaysW)}) - -INST(xlat, {B(11010111)}) -INST(lea, {B(10001101), MOD, REG, RM, ImpD(1), ImpW(1)}) -INST(lds, {B(11000101), MOD, REG, RM, ImpD(1), ImpW(1)}) -INST(les, {B(11000100), MOD, REG, RM, ImpD(1), ImpW(1)}) -INST(lahf, {B(10011111)}) -INST(sahf, {B(10011110)}) -INST(pushf, {B(10011100)}) -INST(popf, {B(10011101)}) - -INST(add, {B(000000), D, W, MOD, REG, RM}) -INSTALT(add, {B(100000), S, W, MOD, B(000), RM, DATA, DATA_IF_W}) -INSTALT(add, {B(0000010), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)}) - -INST(adc, {B(000100), D, W, MOD, REG, RM}) -INSTALT(adc, {B(100000), S, W, MOD, B(010), RM, DATA, DATA_IF_W}) -INSTALT(adc, {B(0001010), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)}) - -INST(inc, {B(1111111), W, MOD, B(000), RM, ImpD(1)}) -INSTALT(inc, {B(01000), REG, ImpW(1), ImpD(1)}) - -INST(aaa, {B(00110111)}) -INST(daa, {B(00100111)}) - -INST(sub, {B(001010), D, W, MOD, REG, RM}) -INSTALT(sub, {B(100000), S, W, MOD, B(101), RM, DATA, DATA_IF_W}) -INSTALT(sub, {B(0010110), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)}) - -INST(sbb, {B(000110), D, W, MOD, REG, RM}) -INSTALT(sbb, {B(100000), S, W, MOD, B(011), RM, DATA, DATA_IF_W}) -INSTALT(sbb, {B(0001110), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)}) - -INST(dec, {B(1111111), W, MOD, B(001), RM, ImpD(1)}) -INSTALT(dec, {B(01001), REG, ImpW(1), ImpD(1)}) - -INST(neg, {B(1111011), W, MOD, B(011), RM}) - -INST(cmp, {B(001110), D, W, MOD, REG, RM}) -INSTALT(cmp, {B(100000), S, W, MOD, B(111), RM, DATA, DATA_IF_W}) -INSTALT(cmp, {B(0011110), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)}) // NOTE(casey): The manual table suggests this data is only 8-bit, but wouldn't it be 16 as well? - -INST(aas, {B(00111111)}) -INST(das, {B(00101111)}) -INST(mul, {B(1111011), W, MOD, B(100), RM, ImpS(0)}) -INST(imul, {B(1111011), W, MOD, B(101), RM, ImpS(1)}) -INST(aam, {B(11010100), B(00001010)}) // NOTE(casey): The manual says this has a DISP... but how could it? What for?? -INST(div, {B(1111011), W, MOD, B(110), RM, ImpS(0)}) -INST(idiv, {B(1111011), W, MOD, B(111), RM, ImpS(1)}) -INST(aad, {B(11010101), B(00001010)}) -INST(cbw, {B(10011000)}) -INST(cwd, {B(10011001)}) - -INST(not, {B(1111011), W, MOD, B(010), RM}) -INST(shl, {B(110100), V, W, MOD, B(100), RM}) -INST(shr, {B(110100), V, W, MOD, B(101), RM}) -INST(sar, {B(110100), V, W, MOD, B(111), RM}) -INST(rol, {B(110100), V, W, MOD, B(000), RM}) -INST(ror, {B(110100), V, W, MOD, B(001), RM}) -INST(rcl, {B(110100), V, W, MOD, B(010), RM}) -INST(rcr, {B(110100), V, W, MOD, B(011), RM}) - -INST(and, {B(001000), D, W, MOD, REG, RM}) -INSTALT(and, {B(1000000), W, MOD, B(100), RM, DATA, DATA_IF_W}) -INSTALT(and, {B(0010010), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)}) - -INST(test, {B(1000010), W, MOD, REG, RM}) // NOTE(casey): The manual suggests there is a D flag here, but it doesn't appear to be true (it would conflict with xchg if it did) -INSTALT(test, {B(1111011), W, MOD, B(000), RM, DATA, DATA_IF_W}) -INSTALT(test, {B(1010100), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)}) // NOTE(casey): The manual table suggests this data is only 8-bit, but it seems like it could be 16 too? - -INST(or, {B(000010), D, W, MOD, REG, RM}) -INSTALT(or, {B(1000000), W, MOD, B(001), RM, DATA, DATA_IF_W}) -INSTALT(or, {B(0000110), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)}) - -INST(xor, {B(001100), D, W, MOD, REG, RM}) -INSTALT(xor, {B(1000000), W, MOD, B(110), RM, DATA, DATA_IF_W}) // NOTE(casey): The manual has conflicting information about this encoding, but I believe this is the correct binary pattern. -INSTALT(xor, {B(0011010), W, DATA, DATA_IF_W, ImpREG(0), ImpD(1)}) - -INST(rep, {B(1111001), Z}) -INST(movs, {B(1010010), W}) -INST(cmps, {B(1010011), W}) -INST(scas, {B(1010111), W}) -INST(lods, {B(1010110), W}) -INST(stos, {B(1010101), W}) - -INST(call, {B(11101000), ADDR, Flags(Bits_RelJMPDisp)}) -INSTALT(call, {B(11111111), MOD, B(010), RM, ImpW(1)}) -INSTALT(call, {B(10011010), ADDR, DATA, DATA_IF_W, ImpW(1), Flags(Bits_Far)}) -INSTALT(call, {B(11111111), MOD, B(011), RM, ImpW(1), Flags(Bits_Far)}) - -INST(jmp, {B(11101001), ADDR, Flags(Bits_RelJMPDisp)}) -INSTALT(jmp, {B(11101011), DISP, Flags(Bits_RelJMPDisp)}) -INSTALT(jmp, {B(11111111), MOD, B(100), RM, ImpW(1)}) -INSTALT(jmp, {B(11101010), ADDR, DATA, DATA_IF_W, ImpW(1), Flags(Bits_Far)}) -INSTALT(jmp, {B(11111111), MOD, B(101), RM, ImpW(1), Flags(Bits_Far)}) - -// NOTE(casey): The actual Intel manual does not distinguish mnemonics RET and RETF, -// but NASM needs this to reassemble properly, so we do. -INST(ret, {B(11000011)}) -INSTALT(ret, {B(11000010), DATA, DATA_IF_W, ImpW(1)}) -INST(retf, {B(11001011), Flags(Bits_Far)}) -INSTALT(retf, {B(11001010), DATA, DATA_IF_W, ImpW(1), Flags(Bits_Far)}) - -INST(je, {B(01110100), DISP, Flags(Bits_RelJMPDisp)}) -INST(jl, {B(01111100), DISP, Flags(Bits_RelJMPDisp)}) -INST(jle, {B(01111110), DISP, Flags(Bits_RelJMPDisp)}) -INST(jb, {B(01110010), DISP, Flags(Bits_RelJMPDisp)}) -INST(jbe, {B(01110110), DISP, Flags(Bits_RelJMPDisp)}) -INST(jp, {B(01111010), DISP, Flags(Bits_RelJMPDisp)}) -INST(jo, {B(01110000), DISP, Flags(Bits_RelJMPDisp)}) -INST(js, {B(01111000), DISP, Flags(Bits_RelJMPDisp)}) -INST(jne, {B(01110101), DISP, Flags(Bits_RelJMPDisp)}) -INST(jnl, {B(01111101), DISP, Flags(Bits_RelJMPDisp)}) -INST(jg, {B(01111111), DISP, Flags(Bits_RelJMPDisp)}) -INST(jnb, {B(01110011), DISP, Flags(Bits_RelJMPDisp)}) -INST(ja, {B(01110111), DISP, Flags(Bits_RelJMPDisp)}) -INST(jnp, {B(01111011), DISP, Flags(Bits_RelJMPDisp)}) -INST(jno, {B(01110001), DISP, Flags(Bits_RelJMPDisp)}) -INST(jns, {B(01111001), DISP, Flags(Bits_RelJMPDisp)}) -INST(loop, {B(11100010), DISP, Flags(Bits_RelJMPDisp)}) -INST(loopz, {B(11100001), DISP, Flags(Bits_RelJMPDisp)}) -INST(loopnz, {B(11100000), DISP, Flags(Bits_RelJMPDisp)}) -INST(jcxz, {B(11100011), DISP, Flags(Bits_RelJMPDisp)}) - -INST(int, {B(11001101), DATA}) -INST(int3, {B(11001100)}) // TODO(casey): The manual does not suggest that this intrinsic has an "int3" mnemonic, but NASM thinks so - -INST(into, {B(11001110)}) -INST(iret, {B(11001111)}) - -INST(clc, {B(11111000)}) -INST(cmc, {B(11110101)}) -INST(stc, {B(11111001)}) -INST(cld, {B(11111100)}) -INST(std, {B(11111101)}) -INST(cli, {B(11111010)}) -INST(sti, {B(11111011)}) -INST(hlt, {B(11110100)}) -INST(wait, {B(10011011)}) -INST(esc, {B(11011), XXX, MOD, YYY, RM}) -INST(lock, {B(11110000)}) -INST(segment, {B(001), SR, B(110)}) - -#undef INST -#undef INSTALT - -#undef B -#undef D -#undef S -#undef W -#undef V -#undef Z - -#undef XXX -#undef YYY -#undef RM -#undef MOD -#undef REG -#undef SR - -#undef ImpW -#undef ImpREG -#undef ImpMOD -#undef ImpRM -#undef ImpD -#undef ImpS - -#undef DISP -#undef ADDR -#undef DATA -#undef DATA_IF_W -#undef Flags diff --git a/src/code/reference_decoder/sim86_lib.cpp b/src/code/reference_decoder/sim86_lib.cpp deleted file mode 100644 index 6971eb2..0000000 --- a/src/code/reference_decoder/sim86_lib.cpp +++ /dev/null @@ -1,73 +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 more information - - ======================================================================== */ - -#define assert(...) - -#include "sim86.h" - -#include "sim86_instruction.h" -#include "sim86_instruction_table.h" -#include "sim86_memory.h" -#include "sim86_decode.h" - -#include "sim86_instruction.cpp" -#include "sim86_instruction_table.cpp" -#include "sim86_memory.cpp" -#include "sim86_decode.cpp" -#include "sim86_text_table.cpp" - -extern "C" u32 Sim86_GetVersion(void) -{ - u32 Result = SIM86_VERSION; - return Result; -} - -extern "C" void Sim86_Decode8086Instruction(u32 SourceSize, u8 *Source, instruction *Dest) -{ - instruction_table Table = Get8086InstructionTable(); - - // NOTE(casey): The 8086 decoder requires the ability to read up to 15 bytes (the maximum - // allowable instruction size) - assert(Table.MaxInstructionByteCount == 15); - u8 GuardBuffer[16] = {}; - if(SourceSize < Table.MaxInstructionByteCount) - { - // NOTE(casey): I replaced the memcpy here with a manual copy to make it easier for - // people compiling on things like WebAssembly who do not want to use Emscripten. - for(u32 I = 0; I < SourceSize; ++I) - { - GuardBuffer[I] = Source[I]; - } - - Source = GuardBuffer; - } - - segmented_access At = FixedMemoryPow2(4, Source); - *Dest = DecodeInstruction(Table, At); -} - -extern "C" char const *Sim86_RegisterNameFromOperand(register_access *RegAccess) -{ - char const *Result = GetRegName(*RegAccess); - return Result; -} - -extern "C" char const *Sim86_MnemonicFromOperationType(operation_type Type) -{ - char const *Result = GetMnemonic(Type); - return Result; -} - -extern "C" void Sim86_Get8086InstructionTable(instruction_table *Dest) -{ - *Dest = Get8086InstructionTable(); -}
\ No newline at end of file diff --git a/src/code/reference_decoder/sim86_memory.cpp b/src/code/reference_decoder/sim86_memory.cpp deleted file mode 100644 index 1d58ede..0000000 --- a/src/code/reference_decoder/sim86_memory.cpp +++ /dev/null @@ -1,66 +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 more information - - ======================================================================== */ - -static u32 GetHighestAddress(segmented_access SegMem) -{ - u32 Result = SegMem.Mask; - return Result; -} - -static u32 GetAbsoluteAddressOf(u32 Mask, u16 SegmentBase, u16 SegmentOffset, u16 AdditionalOffset) -{ - u32 Result = (((u32)SegmentBase << 4) + (u32)(SegmentOffset + AdditionalOffset)) & Mask; - return Result; -} - -static u32 GetAbsoluteAddressOf(segmented_access SegMem, u16 Offset) -{ - u32 Result = GetAbsoluteAddressOf(SegMem.Mask, SegMem.SegmentBase, SegMem.SegmentOffset, Offset); - return Result; -} - -static segmented_access MoveBaseBy(segmented_access Access, s32 Offset) -{ - Access.SegmentOffset += Offset; - - segmented_access Result = Access; - - Result.SegmentBase += (Result.SegmentOffset >> 4); - Result.SegmentOffset &= 0xf; - - assert(GetAbsoluteAddressOf(Result, 0) == GetAbsoluteAddressOf(Access, 0)); - - return Result; -} - -static u8 *AccessMemory(segmented_access SegMem, u16 Offset) -{ - u32 AbsAddr = GetAbsoluteAddressOf(SegMem, Offset); - u8 *Result = SegMem.Memory + AbsAddr; - return Result; -} - -static b32 IsValid(segmented_access SegMem) -{ - b32 Result = (SegMem.Mask != 0); - return Result; -} - -static segmented_access FixedMemoryPow2(u32 SizePow2, u8 *Memory) -{ - segmented_access Result = {}; - - Result.Memory = Memory; - Result.Mask = (1 << SizePow2) - 1; - - return Result; -} diff --git a/src/code/reference_decoder/sim86_memory.h b/src/code/reference_decoder/sim86_memory.h deleted file mode 100644 index 4e790dc..0000000 --- a/src/code/reference_decoder/sim86_memory.h +++ /dev/null @@ -1,28 +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 more information - - ======================================================================== */ - -struct segmented_access -{ - u8 *Memory; - u32 Mask; - u16 SegmentBase; - u16 SegmentOffset; -}; - -static u32 GetHighestAddress(segmented_access SegMem); -static u32 GetAbsoluteAddressOf(segmented_access SegMem, u16 Offset = 0); -static segmented_access MoveBaseBy(segmented_access Access, s32 Offset); - -static u8 *AccessMemory(segmented_access SegMem, u16 Offset = 0); - -static b32 IsValid(segmented_access SegMem); -static segmented_access FixedMemoryPow2(u32 SizePow2, u8 *Memory); diff --git a/src/code/reference_decoder/sim86_text_table.cpp b/src/code/reference_decoder/sim86_text_table.cpp deleted file mode 100644 index e90a649..0000000 --- a/src/code/reference_decoder/sim86_text_table.cpp +++ /dev/null @@ -1,57 +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 more information - - ======================================================================== */ - -char const *OpcodeMnemonics[] = -{ - "", - -#define INST(Mnemonic, ...) #Mnemonic, -#define INSTALT(...) -#include "sim86_instruction_table.inl" -}; - -static char const *GetMnemonic(operation_type Op) -{ - char const *Result = ""; - if(Op < Op_Count) - { - Result = OpcodeMnemonics[Op]; - } - - return Result; -} - -static char const *GetRegName(register_access Reg) -{ - char const *Names[][3] = - { - {"", "", ""}, - {"al", "ah", "ax"}, - {"bl", "bh", "bx"}, - {"cl", "ch", "cx"}, - {"dl", "dh", "dx"}, - {"sp", "sp", "sp"}, - {"bp", "bp", "bp"}, - {"si", "si", "si"}, - {"di", "di", "di"}, - {"es", "es", "es"}, - {"cs", "cs", "cs"}, - {"ss", "ss", "ss"}, - {"ds", "ds", "ds"}, - {"ip", "ip", "ip"}, - {"flags", "flags", "flags"}, - {"", "", ""} - }; - - char const *Result = Names[Reg.Index % ArrayCount(Names)][(Reg.Count == 2) ? 2 : Reg.Offset&1]; - return Result; -} diff --git a/src/code/shared_library_test.cpp b/src/code/shared_library_test.cpp deleted file mode 100644 index aef4fa1..0000000 --- a/src/code/shared_library_test.cpp +++ /dev/null @@ -1,69 +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 more information - - ======================================================================== */ - -#include <stdio.h> - -#include "sim86_shared.h" - -unsigned char ExampleDisassembly[247] = -{ - 0x03, 0x18, 0x03, 0x5E, 0x00, 0x83, 0xC6, 0x02, 0x83, 0xC5, 0x02, 0x83, 0xC1, 0x08, 0x03, 0x5E, - 0x00, 0x03, 0x4F, 0x02, 0x02, 0x7A, 0x04, 0x03, 0x7B, 0x06, 0x01, 0x18, 0x01, 0x5E, 0x00, 0x01, - 0x5E, 0x00, 0x01, 0x4F, 0x02, 0x00, 0x7A, 0x04, 0x01, 0x7B, 0x06, 0x80, 0x07, 0x22, 0x83, 0x82, - 0xE8, 0x03, 0x1D, 0x03, 0x46, 0x00, 0x02, 0x00, 0x01, 0xD8, 0x00, 0xE0, 0x05, 0xE8, 0x03, 0x04, - 0xE2, 0x04, 0x09, 0x2B, 0x18, 0x2B, 0x5E, 0x00, 0x83, 0xEE, 0x02, 0x83, 0xED, 0x02, 0x83, 0xE9, - 0x08, 0x2B, 0x5E, 0x00, 0x2B, 0x4F, 0x02, 0x2A, 0x7A, 0x04, 0x2B, 0x7B, 0x06, 0x29, 0x18, 0x29, - 0x5E, 0x00, 0x29, 0x5E, 0x00, 0x29, 0x4F, 0x02, 0x28, 0x7A, 0x04, 0x29, 0x7B, 0x06, 0x80, 0x2F, - 0x22, 0x83, 0x29, 0x1D, 0x2B, 0x46, 0x00, 0x2A, 0x00, 0x29, 0xD8, 0x28, 0xE0, 0x2D, 0xE8, 0x03, - 0x2C, 0xE2, 0x2C, 0x09, 0x3B, 0x18, 0x3B, 0x5E, 0x00, 0x83, 0xFE, 0x02, 0x83, 0xFD, 0x02, 0x83, - 0xF9, 0x08, 0x3B, 0x5E, 0x00, 0x3B, 0x4F, 0x02, 0x3A, 0x7A, 0x04, 0x3B, 0x7B, 0x06, 0x39, 0x18, - 0x39, 0x5E, 0x00, 0x39, 0x5E, 0x00, 0x39, 0x4F, 0x02, 0x38, 0x7A, 0x04, 0x39, 0x7B, 0x06, 0x80, - 0x3F, 0x22, 0x83, 0x3E, 0xE2, 0x12, 0x1D, 0x3B, 0x46, 0x00, 0x3A, 0x00, 0x39, 0xD8, 0x38, 0xE0, - 0x3D, 0xE8, 0x03, 0x3C, 0xE2, 0x3C, 0x09, 0x75, 0x02, 0x75, 0xFC, 0x75, 0xFA, 0x75, 0xFC, 0x74, - 0xFE, 0x7C, 0xFC, 0x7E, 0xFA, 0x72, 0xF8, 0x76, 0xF6, 0x7A, 0xF4, 0x70, 0xF2, 0x78, 0xF0, 0x75, - 0xEE, 0x7D, 0xEC, 0x7F, 0xEA, 0x73, 0xE8, 0x77, 0xE6, 0x7B, 0xE4, 0x71, 0xE2, 0x79, 0xE0, 0xE2, - 0xDE, 0xE1, 0xDC, 0xE0, 0xDA, 0xE3, 0xD8 -}; - -int main(void) -{ - u32 Version = Sim86_GetVersion(); - printf("Sim86 Version: %u (expected %u)\n", Version, SIM86_VERSION); - if(Version != SIM86_VERSION) - { - printf("ERROR: Header file version doesn't match DLL.\n"); - return -1; - } - - instruction_table Table; - Sim86_Get8086InstructionTable(&Table); - printf("8086 Instruction Instruction Encoding Count: %u\n", Table.EncodingCount); - - u32 Offset = 0; - while(Offset < sizeof(ExampleDisassembly)) - { - instruction Decoded; - Sim86_Decode8086Instruction(sizeof(ExampleDisassembly) - Offset, ExampleDisassembly + Offset, &Decoded); - if(Decoded.Op) - { - Offset += Decoded.Size; - printf("Size:%u Op:%s Flags:0x%x\n", Decoded.Size, Sim86_MnemonicFromOperationType(Decoded.Op), Decoded.Flags); - } - else - { - printf("Unrecognized instruction\n"); - break; - } - } - - return 0; -} diff --git a/src/code/sim86.cpp b/src/code/sim86.cpp deleted file mode 100644 index 1e4ddfa..0000000 --- a/src/code/sim86.cpp +++ /dev/null @@ -1,375 +0,0 @@ -#include <stdio.h> -#include <string.h> - -#include "sim86.h" -#include "sim86_shared.h" - -global_variable u8 FlagToCharMapping[] = "CPAZSOIDT"; -global_variable u8 GlobalMemory[1*1024*1024] = {}; - -internal void -SetOrUnsetFlag(u32 *FlagsRegister, b32 Condition, flags_8086 Flag) -{ - if(Condition) - { - *FlagsRegister |= Flag; - } - else - { - *FlagsRegister &= (~Flag); - } -} - -internal u32 -FlagsToString(char *Buffer, u32 Flags) -{ - u32 Length = 0; - - for(u32 MappingIndex = 0; - MappingIndex < ArrayCount(FlagToCharMapping); - MappingIndex++) - { - u8 Char = FlagToCharMapping[MappingIndex]; - b32 IsBitSet = (Flags & 1); - Flags >>= 1; - if(IsBitSet) - { - Buffer[Length++] = Char; - } - } - - return Length; -} - -internal void -FlagsFromValue(u32 *FlagsRegister, u32 InstructionFlags, s32 Value) -{ - u32 OldFlagsRegister = *FlagsRegister; - - u32 SignMask = (1 << ((InstructionFlags & Inst_Wide) ? 15 : 7)); - SetOrUnsetFlag(FlagsRegister, (Value & SignMask), Flag_Sign); - SetOrUnsetFlag(FlagsRegister, (Value == 0), Flag_Zero); - - // NOTE(luca): Parity flag is set when in lower 8 bits have an even number of set bits. - u32 OneBitsCount = 0; - for(u32 BitsIndex = 0; - BitsIndex < 8; - BitsIndex++) - { - OneBitsCount += (Value & 1); - Value >>= 1; - } - SetOrUnsetFlag(FlagsRegister, (!(OneBitsCount & 1)), Flag_Parity); - - // TODO(luca): Overflow flag - // Were we adding positive numbers but produced a negative number? - - // TODO(luca): Carry flag - // When twot numbers are added and the 17th bit would be set? - - // TODO(luca): Auxiliary carry flag - // Carry for bottom 8 bits - if(*FlagsRegister != OldFlagsRegister) - { - char OldFlagsString[ArrayCount(FlagToCharMapping)] = {}; - char FlagsString[ArrayCount(FlagToCharMapping)] = {}; - FlagsToString(OldFlagsString, OldFlagsRegister); - FlagsToString(FlagsString, *FlagsRegister); - - printf(" flags:%s->%s", OldFlagsString, FlagsString); - } -} - -internal s32 * -OperandToValue(s32 *Registers, u8 *Memory, instruction_operand *Operand) -{ - s32 *Result = 0; - - if(0) {} - else if(Operand->Type == Operand_Register) - { - Result = Registers + Operand->Register.Index; - } - else if(Operand->Type == Operand_Memory) - { - s32 CompleteDisplacement = Operand->Address.Displacement; - Assert(Operand->Address.Terms[0].Register.Count == Operand->Address.Terms[1].Register.Count); - - u32 Count = Operand->Address.Terms[0].Register.Count; - u32 Mask = ((u32)((-1)) >> (16 + (16 - Count*8))); - - CompleteDisplacement += - (Registers[Operand->Address.Terms[0].Register.Index] & Mask) + - (Registers[Operand->Address.Terms[1].Register.Index] & Mask); - - Result = (s32 *)((u8 *)Memory + CompleteDisplacement); - } - else if(Operand->Type == Operand_Immediate) - { - Result = &Operand->Immediate.Value; - } - else if(Operand->Type != Operand_None) - { - Assert(0); - } - - return Result; -} - -internal void -Run8086(psize MemorySize, u8 *Memory) -{ - s32 Registers[Register_count] = {}; - u32 FlagsRegister = 0; - u32 IPRegister = 0; - - while(IPRegister < MemorySize) - { - instruction Decoded; - Sim86_Decode8086Instruction(MemorySize - IPRegister, Memory + IPRegister, &Decoded); - if(Decoded.Op) - { - u32 OldIPRegister = IPRegister; - IPRegister += Decoded.Size; - -#if SIM86_INTERNAL - printf("Size:%u Op:%s Flags:0x%x ;", Decoded.Size, Sim86_MnemonicFromOperationType(Decoded.Op), Decoded.Flags); -#endif - - instruction_operand *DestinationOperand = Decoded.Operands + 0; - instruction_operand *SourceOperand = Decoded.Operands + 1; - - s32 *Destination = OperandToValue(Registers, Memory, DestinationOperand); - s32 *Source = OperandToValue(Registers, Memory, SourceOperand); - - if(0) {} - else if(Decoded.Op == Op_int3) - { - Assert(0); - } - else if(Decoded.Op == Op_mov) - { - s32 Old = *Destination; - if(Decoded.Flags & Inst_Wide) - { - *(u16 *)Destination = *(u16 *)Source; - } - else - { - Assert((SourceOperand->Type == Operand_Immediate || - SourceOperand->Type == Operand_Memory) && - (SourceOperand->Register.Offset == 0)); - Assert((DestinationOperand->Type == Operand_Immediate || DestinationOperand->Type == Operand_Memory) && (DestinationOperand->Register.Offset == 0)); - - u8 *SourceByte = (u8 *)Source + SourceOperand->Register.Offset; - u8 *DestByte = (u8 *)Destination + DestinationOperand->Register.Offset; - - *DestByte = *SourceByte; - } - -#if SIM86_INTERNAL - if(DestinationOperand->Type == Operand_Register) - { - printf(" %s:0x%x->0x%x", Sim86_RegisterNameFromOperand(&DestinationOperand->Register), - Old, *Destination); - } -#endif - } - else if(Decoded.Op == Op_cmp) - { - Assert(DestinationOperand->Type == Operand_Register); - Assert(SourceOperand->Type == Operand_Register || SourceOperand->Type == Operand_Immediate); - - s32 Value = ((Decoded.Flags & Inst_Wide) ? - (u16)((u16)*Destination - ((u16)*Source)) : - (u8)((u8)*Destination - ((u8)*Source))); - - FlagsFromValue(&FlagsRegister, Decoded.Flags, Value); - } - else if(Decoded.Op == Op_sub) - { - Assert(DestinationOperand->Type == Operand_Register); - Assert(SourceOperand->Type == Operand_Register || SourceOperand->Type == Operand_Immediate); - - s32 Old = *Destination; - *Destination = ((Decoded.Flags & Inst_Wide) ? - (u16)((u16)*Destination - ((u16)*Source)) : - (u8)((u8)*Destination - ((u8)*Source))); - - printf(" %s:0x%x->0x%x", - Sim86_RegisterNameFromOperand(&DestinationOperand->Register), - Old, *Destination); - - FlagsFromValue(&FlagsRegister, Decoded.Flags, *Destination); - - } - else if(Decoded.Op == Op_add) - { - Assert(DestinationOperand->Type == Operand_Register); - - s32 Old = *Destination; - - *Destination = ((Decoded.Flags & Inst_Wide) ? - (u16)((u16)*Destination + ((u16)*Source)) : - (u8)((u8)*Destination + ((u8)*Source))); - - printf(" %s:0x%x->0x%x", - Sim86_RegisterNameFromOperand(&DestinationOperand->Register), - Old, *Destination); - - FlagsFromValue(&FlagsRegister, Decoded.Flags, *Destination); - } - else if(Decoded.Op == Op_jne) - { - if(!(FlagsRegister & Flag_Zero)) - { - IPRegister += *Destination; - } - } - else if(Decoded.Op == Op_je) - { - if((FlagsRegister & Flag_Zero)) - { - IPRegister += *Destination; - } - } - else - { - Assert(0 && "Op not implemented yet."); - } - -#if SIM86_INTERNAL - printf(" ip:0x%x->0x%x", OldIPRegister, IPRegister); -#endif - - } - else - { - printf("Unrecognized instruction\n"); - break; - } - -#if SIM86_INTERNAL - printf("\n"); -#endif - - } - - printf("Final registers:\n"); - for(u32 RegisterIndex = Register_a; - RegisterIndex < Register_ds + 1; - RegisterIndex++) - { - register_access Register = {}; - Register.Index = RegisterIndex; - Register.Offset = 0; - Register.Count = 2; - - u32 Value = Registers[RegisterIndex]; - if(Value > 0) - { - printf(" %s: 0x%0x (%d)\n", - Sim86_RegisterNameFromOperand(&Register), - Value, Value); - } - } - printf(" ip: 0x%04x (%d)\n", IPRegister, IPRegister); - - if(FlagsRegister) - { - char FlagsString[ArrayCount(FlagToCharMapping)] = {}; - FlagsToString(FlagsString, FlagsRegister); - printf(" flags: %s\n", FlagsString); - } -} - -void PrintUsage(char *ExePath) -{ - printf("usage: %s [-exec] <assembly>\n", ExePath); -} - -int main(int ArgsCount, char *Args[]) -{ - u32 Version = Sim86_GetVersion(); - -#if SIM86_INTERNAL - printf("Sim86 Version: %u (expected %u)\n", Version, SIM86_VERSION); -#endif - - if(Version != SIM86_VERSION) - { - printf("ERROR: Header file version doesn't match DLL.\n"); - return -1; - } - - instruction_table Table; - Sim86_Get8086InstructionTable(&Table); - -#if SIM86_INTERNAL - printf("8086 Instruction Instruction Encoding Count: %u\n", Table.EncodingCount); -#endif - - // print (default) - // -exec (also execute the disassembled instructinos) - - b32 Execute = false; - b32 Dump = false; - char *FileName = 0; - for(s32 ArgsIndex = 1; - ArgsIndex < ArgsCount; - ArgsIndex++) - { - char *Command = Args[ArgsIndex]; - if(0) {} - else if(!strcmp(Command, "-exec")) - { - Execute = true; - } - else if(!strcmp(Command, "-dump")) - { - Dump = true; - } - else - { - FileName = Command; - } - } - - if(FileName) - { - FILE *File = fopen(FileName, "rb"); - if(File) - { - psize BytesWritten = fread(GlobalMemory, 1, sizeof(GlobalMemory), File); - fclose(File); - - if(Execute) - { - printf("--- %s execution ---\n", FileName); - - Run8086(BytesWritten, GlobalMemory); - - if(Dump) - { - // NOTE(luca): We have to add ".data" or Gimp will throw an error. - FILE *DumpFile = fopen("sim86_memory_0.data", "wb"); - fwrite(GlobalMemory, 1, sizeof(GlobalMemory), DumpFile); - fclose(DumpFile); - } - - } - else - { - printf("ERROR: Disassembling not implemented yet.\n"); - } - - } - else - { - printf("ERROR: Unable to open %s.\n", FileName); - PrintUsage(Args[0]); - } - } - - return 0; -} diff --git a/src/code/sim86.h b/src/code/sim86.h deleted file mode 100644 index 4778573..0000000 --- a/src/code/sim86.h +++ /dev/null @@ -1,53 +0,0 @@ -/* date = August 13th 2025 1:51 pm */ - -#ifndef SIM86_H -#define SIM86_H - -#define internal static -#define global_variable static -#define local_persist static - -typedef size_t psize; - -#define Assert(Expression) if(!(Expression)) { __asm__ volatile("int3"); } -#define ArrayCount(Array) (sizeof(Array) / sizeof((Array)[0])) - -//~ Stolen from the decoder. -enum register_mapping_8086 -{ - Register_none, - - Register_a, - Register_b, - Register_c, - Register_d, - Register_sp, - Register_bp, - Register_si, - Register_di, - Register_es, - Register_cs, - Register_ss, - Register_ds, - Register_ip, - Register_flags, - - Register_count, -}; - -enum flags_8086 -{ - Flag_None = 0, - Flag_Carry =(1 << 0), - Flag_Parity =(1 << 1), - Flag_AuxiliaryCarry =(1 << 2), - Flag_Zero =(1 << 3), - Flag_Sign =(1 << 4), - Flag_Overflow =(1 << 5), - Flag_Interrupt =(1 << 6), - Flag_Direction =(1 << 7), - Flag_Trap =(1 << 8), - Flag_Count = 11, -}; - -#endif //SIM86_H diff --git a/src/code/sim86_shared.h b/src/code/sim86_shared.h deleted file mode 100644 index 7a54beb..0000000 --- a/src/code/sim86_shared.h +++ /dev/null @@ -1,285 +0,0 @@ -typedef char unsigned u8; -typedef short unsigned u16; -typedef int unsigned u32; -typedef long long unsigned u64; - -typedef char s8; -typedef short s16; -typedef int s32; -typedef long long s64; - -typedef s32 b32; - -static u32 const SIM86_VERSION = 4; -typedef u32 register_index; - -typedef struct register_access register_access; -typedef struct effective_address_term effective_address_term; -typedef struct effective_address_expression effective_address_expression; -typedef struct immediate immediate; -typedef struct instruction_operand instruction_operand; -typedef struct instruction instruction; - -typedef enum operation_type : u32 -{ - Op_None, - - Op_mov, - - Op_push, - - Op_pop, - - Op_xchg, - - Op_in, - - Op_out, - - Op_xlat, - Op_lea, - Op_lds, - Op_les, - Op_lahf, - Op_sahf, - Op_pushf, - Op_popf, - - Op_add, - - Op_adc, - - Op_inc, - - Op_aaa, - Op_daa, - - Op_sub, - - Op_sbb, - - Op_dec, - - Op_neg, - - Op_cmp, - - Op_aas, - Op_das, - Op_mul, - Op_imul, - Op_aam, - Op_div, - Op_idiv, - Op_aad, - Op_cbw, - Op_cwd, - - Op_not, - Op_shl, - Op_shr, - Op_sar, - Op_rol, - Op_ror, - Op_rcl, - Op_rcr, - - Op_and, - - Op_test, - - Op_or, - - Op_xor, - - Op_rep, - Op_movs, - Op_cmps, - Op_scas, - Op_lods, - Op_stos, - - Op_call, - - Op_jmp, - - Op_ret, - - Op_retf, - - Op_je, - Op_jl, - Op_jle, - Op_jb, - Op_jbe, - Op_jp, - Op_jo, - Op_js, - Op_jne, - Op_jnl, - Op_jg, - Op_jnb, - Op_ja, - Op_jnp, - Op_jno, - Op_jns, - Op_loop, - Op_loopz, - Op_loopnz, - Op_jcxz, - - Op_int, - Op_int3, - - Op_into, - Op_iret, - - Op_clc, - Op_cmc, - Op_stc, - Op_cld, - Op_std, - Op_cli, - Op_sti, - Op_hlt, - Op_wait, - Op_esc, - Op_lock, - Op_segment, - - Op_Count, -} operation_type; - -enum instruction_flag -{ - Inst_Lock = 0x1, - Inst_Rep = 0x2, - Inst_Segment = 0x4, - Inst_Wide = 0x8, - Inst_Far = 0x10, - Inst_RepNE = 0x20, -}; - -struct register_access -{ - register_index Index; - u32 Offset; - u32 Count; -}; - -struct effective_address_term -{ - register_access Register; - s32 Scale; -}; - -enum effective_address_flag -{ - Address_ExplicitSegment = 0x1, -}; -struct effective_address_expression -{ - effective_address_term Terms[2]; - u32 ExplicitSegment; - s32 Displacement; - u32 Flags; -}; - -enum immediate_flag -{ - Immediate_RelativeJumpDisplacement = 0x1, -}; -struct immediate -{ - s32 Value; - u32 Flags; -}; - -typedef enum operand_type : u32 -{ - Operand_None, - Operand_Register, - Operand_Memory, - Operand_Immediate, -} operand_type; -struct instruction_operand -{ - operand_type Type; - union { - effective_address_expression Address; - register_access Register; - immediate Immediate; - }; -}; - -struct instruction -{ - u32 Address; - u32 Size; - - operation_type Op; - u32 Flags; - - instruction_operand Operands[2]; - - register_index SegmentOverride; -}; -enum instruction_bits_usage : u8 -{ - Bits_End, - - Bits_Literal, - - Bits_D, - Bits_S, - Bits_W, - Bits_V, - Bits_Z, - Bits_MOD, - Bits_REG, - Bits_RM, - Bits_SR, - Bits_Disp, - Bits_Data, - - Bits_DispAlwaysW, - Bits_WMakesDataW, - Bits_RMRegAlwaysW, - Bits_RelJMPDisp, - Bits_Far, - - Bits_Count, -}; - -struct instruction_bits -{ - instruction_bits_usage Usage; - u8 BitCount; - u8 Shift; - u8 Value; -}; - -struct instruction_encoding -{ - operation_type Op; - instruction_bits Bits[16]; -}; - -struct instruction_table -{ - instruction_encoding *Encodings; - u32 EncodingCount; - u32 MaxInstructionByteCount; -}; -#ifdef __cplusplus -extern "C" -{ -#endif - u32 Sim86_GetVersion(void); - void Sim86_Decode8086Instruction(u32 SourceSize, u8 *Source, instruction *Dest); - char const *Sim86_RegisterNameFromOperand(register_access *RegAccess); - char const *Sim86_MnemonicFromOperationType(operation_type Type); - void Sim86_Get8086InstructionTable(instruction_table *Dest); -#ifdef __cplusplus -} -#endif |
