diff options
| author | Raymaekers Luca <luca@spacehb.net> | 2025-10-16 12:09:23 +0200 |
|---|---|---|
| committer | Raymaekers Luca <luca@spacehb.net> | 2025-10-16 12:09:23 +0200 |
| commit | f121522cbd0adf02ed6b8e2dc56450d8289c2991 (patch) | |
| tree | c2bed8b88449756bb38f70ecd688d570c2306c5c /src/code | |
| parent | 7fd4a8d8627b7cd7044b390751eda66208edf1eb (diff) | |
checkpoint
Diffstat (limited to 'src/code')
| -rw-r--r-- | src/code/sim86.cpp | 266 | ||||
| -rw-r--r-- | src/code/sim86.h | 22 |
2 files changed, 179 insertions, 109 deletions
diff --git a/src/code/sim86.cpp b/src/code/sim86.cpp index 75e1e93..b6fb57b 100644 --- a/src/code/sim86.cpp +++ b/src/code/sim86.cpp @@ -1,26 +1,140 @@ -/* ======================================================================== - - (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 <string.h> #include "sim86.h" #include "sim86_shared.h" +global_variable u8 FlagToCharMapping[] = "CPAZSOIDT"; + +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 the lower 8 bits the number of set bits is even. + 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); + } +} + +struct operands_to_values_result +{ + s32 *Destination; + s32 *Source; +}; +internal operands_to_values_result +OperandsToValues(s32 *Registers, + instruction_operand *DestinationOperand, instruction_operand *SourceOperand) +{ + operands_to_values_result Result = {}; + + if(0) {} + else if(DestinationOperand->Type == Operand_Register) + { + Result.Destination = Registers + DestinationOperand->Register.Index; + } + else if(DestinationOperand->Type == Operand_Memory) + { + Assert(0 && "not implemented yet."); + } + else if(DestinationOperand->Type == Operand_Immediate) + { + Assert(0 && "not implemented yet."); + } + else + { + Assert(0); + } + + if(0) {} + else if(SourceOperand->Type == Operand_Register) + { + Result.Source = Registers + SourceOperand->Register.Index; + } + else if(SourceOperand->Type == Operand_Immediate) + { + Result.Source = &SourceOperand->Immediate.Value; + } + else if(SourceOperand->Type == Operand_Memory) + { + Assert(0 && "not implemented yet."); + } + else + { + Assert(0); + } + + return Result; +} + + internal void Run8086(psize DisassemblySize, u8 *Disassembly) { s32 Registers[Register_count] = {}; - u32 Flags = 0; + u32 FlagsRegister = 0; u32 Offset = 0; while(Offset < DisassemblySize) @@ -32,49 +146,20 @@ Run8086(psize DisassemblySize, u8 *Disassembly) Offset += Decoded.Size; #if SIM86_INTERNAL - printf("Size:%u Op:%s Flags:0x%x", Decoded.Size, Sim86_MnemonicFromOperationType(Decoded.Op), Decoded.Flags); + printf("Size:%u Op:%s Flags:0x%x ;", Decoded.Size, Sim86_MnemonicFromOperationType(Decoded.Op), Decoded.Flags); #endif + + instruction_operand *DestinationOperand = Decoded.Operands; + instruction_operand *SourceOperand = Decoded.Operands + 1; + operands_to_values_result OperandsValues = OperandsToValues(Registers, DestinationOperand, SourceOperand); + s32 *Destination = OperandsValues.Destination; + s32 *Source = OperandsValues.Source; + if(0) {} else if(Decoded.Op == Op_mov) { - s32 *Destination = 0; - s32 *Source = 0; - - if(0) {} - else if(Decoded.Operands[0].Type == Operand_Register) - { - Destination = &Registers[Decoded.Operands[0].Register.Index]; - } - else if(Decoded.Operands[0].Type == Operand_Memory) - { - Assert(0 && "mov to memory not implemented yet."); - } - else if(Decoded.Operands[0].Type == Operand_Immediate) - { - Assert(0 && "Cannot move to immediate value."); - } - else - { - Assert(0); - } - - if(0) {} - else if(Decoded.Operands[1].Type == Operand_Register) - { - Source = &Registers[Decoded.Operands[1].Register.Index]; - } - else if(Decoded.Operands[1].Type == Operand_Immediate) - { - Source = &Decoded.Operands[1].Immediate.Value; - } - else if(Decoded.Operands[1].Type == Operand_Memory) - { - Assert(0 && "mov from memory not implemented yet."); - } - else - { - Assert(0); - } + Assert(DestinationOperand->Type == Operand_Register); + Assert(SourceOperand->Type == Operand_Register || SourceOperand->Type == Operand_Immediate); s32 Old = *Destination; if(Decoded.Flags & Inst_Wide) @@ -84,8 +169,8 @@ Run8086(psize DisassemblySize, u8 *Disassembly) else { // NOTE(luca): We assume that an immediate will have an Offset of 0. - u32 DestOffset = Decoded.Operands[0].Register.Offset; - u32 SourceOffset = Decoded.Operands[1].Register.Offset; + u32 DestOffset = DestinationOperand->Register.Offset; + u32 SourceOffset = SourceOperand->Register.Offset; u8 *SourceByte = (u8 *)Source + SourceOffset; u8 *DestByte = (u8 *)Destination + DestOffset; @@ -94,64 +179,46 @@ Run8086(psize DisassemblySize, u8 *Disassembly) } #if SIM86_INTERNAL - printf(" ; %s:0x%x->0x%x", Sim86_RegisterNameFromOperand(&Decoded.Operands[0].Register), + printf(" %s:0x%x->0x%x", Sim86_RegisterNameFromOperand(&DestinationOperand->Register), Old, *Destination); #endif } else if(Decoded.Op == Op_cmp) { - Assert(0 && "cmp has not been implemented yet"); + Assert(DestinationOperand->Type == Operand_Register); + Assert(SourceOperand->Type == Operand_Register || SourceOperand->Type == Operand_Immediate); + + s32 Value = (u16)((u16)(*Destination) - ((u16)(*Source))); + + FlagsFromValue(&FlagsRegister, Decoded.Flags, Value); } else if(Decoded.Op == Op_sub) { - s32 *Destination = 0; - s32 *Source = 0; + Assert(DestinationOperand->Type == Operand_Register); + Assert(SourceOperand->Type == Operand_Register || SourceOperand->Type == Operand_Immediate); - if(0) {} - else if(Decoded.Operands[0].Type == Operand_Register) - { - Destination = Registers + Decoded.Operands[0].Register.Index; - } - else - { - Assert(0 && "Destination must be a register"); - } - - if(0) {} - else if(Decoded.Operands[1].Type == Operand_Register) - { - Source = Registers + Decoded.Operands[1].Register.Index; - } - else if(Decoded.Operands[1].Type == Operand_Immediate) - { - Source = &Decoded.Operands[1].Immediate.Value; - } - else - { - Assert(1 && "Substraction from memory address is not implemented yet."); - } - - Assert(0 && "sub has not been implemented yet"); + s32 Old = *Destination; + u32 OldFlags = FlagsRegister; *Destination = (u16)((u16)(*Destination) - ((u16)(*Source))); + printf(" %s:0x%x->0x%x", + Sim86_RegisterNameFromOperand(&DestinationOperand->Register), + Old, *Destination); - if(*Destination & (1 << 15)) - { - Flags |= Flag_Sign; - } - - if(*Destination == 0) - { - Flags |= Flag_Zero; - } - else - { - Flags &= (~Flag_Zero); - } + FlagsFromValue(&FlagsRegister, Decoded.Flags, *Destination); } else if(Decoded.Op == Op_add) { - Assert(0 && "add has not been implemented yet"); + Assert(DestinationOperand->Type == Operand_Register); + Assert(SourceOperand->Type == Operand_Register || SourceOperand->Type == Operand_Immediate); + + s32 Old = *Destination; + *Destination = (u16)((u16)(*Destination) + ((u16)(*Source))); + printf(" %s:0x%x->0x%x", + Sim86_RegisterNameFromOperand(&DestinationOperand->Register), + Old, *Destination); + + FlagsFromValue(&FlagsRegister, Decoded.Flags, *Destination); } else { @@ -184,11 +251,14 @@ Run8086(psize DisassemblySize, u8 *Disassembly) u32 Value = Registers[RegisterIndex]; if(Value > 0) { - printf(" %s: 0x%04x (%d)\n", + printf(" %s: 0x%0x (%d)\n", Sim86_RegisterNameFromOperand(&Register), Value, Value); } } + char FlagsString[ArrayCount(FlagToCharMapping)] = {}; + FlagsToString(FlagsString, FlagsRegister); + printf(" flags: %s", FlagsString); } void PrintUsage(char *ExePath) diff --git a/src/code/sim86.h b/src/code/sim86.h index 3ed472e..4778573 100644 --- a/src/code/sim86.h +++ b/src/code/sim86.h @@ -37,17 +37,17 @@ enum register_mapping_8086 enum flags_8086 { - Flag_Carry, - Flag_Parity, - Flag_AuxiliaryCarry, - Flag_Zero, - Flag_Sign, - Flag_Overflow, - Flag_Interrupt, - Flag_Direction, - Flag_Trap, - Flag_Count + 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 |
