summaryrefslogtreecommitdiff
path: root/archived/less_old_sim8086/code/sim8086.cpp
diff options
context:
space:
mode:
authorRaymaekers Luca <luca@spacehb.net>2025-08-23 16:22:13 +0200
committerRaymaekers Luca <luca@spacehb.net>2025-08-23 16:22:13 +0200
commitea20bd9b5bcff9db1d86d83188e1e899799f324b (patch)
tree615e2f00e385e93061524c9647b64010ba7df3dd /archived/less_old_sim8086/code/sim8086.cpp
checkpoint
Diffstat (limited to 'archived/less_old_sim8086/code/sim8086.cpp')
-rw-r--r--archived/less_old_sim8086/code/sim8086.cpp855
1 files changed, 855 insertions, 0 deletions
diff --git a/archived/less_old_sim8086/code/sim8086.cpp b/archived/less_old_sim8086/code/sim8086.cpp
new file mode 100644
index 0000000..be6a1f2
--- /dev/null
+++ b/archived/less_old_sim8086/code/sim8086.cpp
@@ -0,0 +1,855 @@
+/*
+
+Instruction have 6 bytes that define what type of instruction it is.
+
+ Each instruction has zero, one or two operands.
+ The operands can be switched depending on the D bit.
+
+ The MOD field indicates if a displacement follows.
+Except when R/M is 110.
+
+The D and W bits are always in the first byte.
+
+Data is always required.
+
+Reg can happen in the first byte.
+
+Some expressions have a second 3bit field that stores the "sub-kind" of instruction.
+*/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "sim8086.h"
+
+#define Assert(Expression) \
+if(!(Expression)) \
+{ \
+*(char *)0 = 0; \
+}
+
+#if SIM8086_INTERNAL
+#define DebugLabel(Name) Name:
+#else
+#define DebugLabel(Name)
+#endif
+
+#define Swap(Type, First, Second) \
+{ \
+Type Temp; \
+Temp = First; \
+First = Second; \
+Second = Temp; \
+}
+
+#define JE 0b01110100
+#define JL 0b01111100
+#define JLE 0b01111110
+#define JB 0b01110010
+#define JBE 0b01110110
+#define JP 0b01111010
+#define JO 0b01110000
+#define JS 0b01111000
+#define JNL 0b01111101
+#define JG 0b01111111
+#define JNB 0b01110011
+#define JA 0b01110111
+#define JNP 0b01111011
+#define JNO 0b01110001
+#define JNS 0b01111001
+#define JNZ 0b01110101
+#define LOOP 0b11100010
+#define LOOPZ 0b11100001
+#define LOOPNZ 0b11100000
+#define JCXZ 0b11100011
+
+#define ADD 0b000
+#define SUB 0b101
+#define CMP 0b111
+
+// Can be indexed by R/M or reg field.
+// Also if the W bit is set it can be used to index and get the wide name.
+global_variable char *RegistersNames[][2] =
+{
+ [0b000] = { "al", "ax" },
+ [0b001] = { "cl", "cx" },
+ [0b010] = { "dl", "dx" },
+ [0b011] = { "bl", "bx" },
+ [0b100] = { "ah", "sp" },
+ [0b101] = { "ch", "bp" },
+ [0b110] = { "dh", "si" },
+ [0b111] = { "bh", "di" }
+};
+#define ACCUMULATOR 0b000
+
+global_variable char *DisplacementsNames[] =
+{
+ [0b000] = "bx + si",
+ [0b001] = "bx + di",
+ [0b010] = "bp + si",
+ [0b011] = "bp + di",
+ [0b100] = "si",
+ [0b101] = "di",
+ [0b110] = "bp",
+ [0b111] = "bx"
+};
+
+global_variable char *SegmentRegistersNames[] =
+{
+ [0b000] = "ss",
+ [0b001] = "cs",
+ [0b010] = "ds",
+ [0b011] = "es",
+};
+
+global_variable char GlobalBinaryTempString[9];
+
+inline
+void MemoryCopy(char *To, char *From, size_t Count)
+{
+ while(Count--) *To++ = *From++;
+}
+
+inline
+void CStringCopy(char *To, char *From)
+{
+ while((*To++ = *From++));
+}
+
+inline
+u32 CStringLength(char *Src)
+{
+ u32 Result = 0;
+ while(Src[Result]) Result++;
+ return Result;
+}
+
+char *PrefixString(char *Dest, char *Prefix)
+{
+ u32 PrefixLength = CStringLength(Prefix);
+ u32 DestLen = CStringLength(Dest);
+
+ // Move the string over by the prefix length
+ for(s32 CharAt = DestLen;
+ CharAt >= 0;
+ CharAt--)
+ {
+ Dest[PrefixLength + CharAt] = Dest[CharAt];
+ }
+
+ // Copy the prefix over
+ MemoryCopy(Dest, Prefix, 5);
+
+ return Dest;
+}
+
+int ReadBytesFromFile(int File, u8 **Dest, size_t Count)
+{
+ int BytesRead = read(File, *Dest, Count);
+ *Dest += BytesRead;
+ Assert(BytesRead == (int)Count || BytesRead == 0);
+ return BytesRead;
+}
+
+char *ByteToBinaryString(u8 Byte)
+{
+ char *Result = GlobalBinaryTempString;
+
+ int Count = 8;
+ while(Count--)
+ {
+ *Result++ = '0' + (Byte >> 7);
+ Byte <<= 1;
+ }
+ *Result = 0;
+
+ return GlobalBinaryTempString;
+}
+
+void SetBitFromBitAt(b32 *Bit, u8 Byte, u32 BitAt)
+{
+ if(BitAt)
+ {
+ *Bit = ((Byte & (1 << (BitAt - 1))) != 0);
+ }
+}
+
+u8 ExtractBitsFromByte(u8 Byte, u8 Bits, u8 BitAt)
+{
+ u8 Result = 0;
+
+ u8 ShiftValue = BitAt - 1;
+ u8 Mask = (Bits << ShiftValue);
+ Result = ((Byte & Mask) >> ShiftValue);
+
+ return Result;
+}
+
+int main(int ArgCount, char *Args[])
+{
+ u8 Bytes[255] = {};
+ instruction InstructionsBuffer[256] = {};
+ instruction_table Table = {};
+ Table.Instructions = InstructionsBuffer;
+ Table.Size = (sizeof(InstructionsBuffer)/sizeof(InstructionsBuffer[0])) - 1;
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "mov",
+ .Description = "Register/memory to/from register",
+ .OperandsCount = 2,
+ .BytesCount = 2,
+ .Bytes =
+ {
+ {
+ .Op = 0b10001000,
+ .OpMask = 0b11111100,
+ .WBitAt = 1,
+ .DBitAt = 2,
+ },
+ {
+ .ModBitsAt = 7,
+ .RegBitsAt = 4,
+ .RMBitsAt = 1
+ }
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "mov",
+ .Description = "Immediate to register/memory",
+ .OperandsCount = 2,
+ .HasImmediate = true,
+ .BytesCount = 1,
+ .Bytes =
+ {
+ {
+ .Op = 0b10000110,
+ .OpMask = 0b11111110,
+ .WBitAt = 1,
+ .ModBitsAt = 7,
+ .RMBitsAt = 1
+ }
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "mov",
+ .Description = "Immediate to register",
+ .OperandsCount = 2,
+ .HasImmediate = true,
+ .BytesCount = 1,
+ .Bytes = {
+ {
+ .Op = 0b10110000,
+ .OpMask = 0b11110000,
+ .WBitAt = 4,
+ .RegBitsAt = 1,
+ }
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "mov",
+ .Description = "Immediate to register/memory",
+ .OperandsCount = 2,
+ .HasImmediate = true,
+ .BytesCount = 2,
+ .Bytes =
+ {
+ {
+ .Op = 0b11000110,
+ .OpMask = 0b11111110,
+ .WBitAt = 1,
+ },
+ {
+ .ModBitsAt = 7,
+ .RMBitsAt = 1,
+ }
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "mov",
+ .Description = "Memory to accumulator",
+ .OperandsCount = 2,
+ .HasAddress = true,
+ .ToAccumulator = true,
+ .BytesCount = 1,
+ .Bytes =
+ {
+ {
+ .Op = 0b10100000,
+ .OpMask = 0b11111110,
+ .WBitAt = 1
+ }
+ }
+ };
+
+ // NOTE(luca): This is the same instruction as the previous one with the D bit always set to true...
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "mov",
+ .Description = "Accumulator to memory",
+ .OperandsCount = 2,
+ .HasAddress = true,
+ .ToAccumulator = true,
+ .FlipOperands = true,
+ .BytesCount = 1,
+ .Bytes =
+ {
+ {
+ .Op = 0b10100010,
+ .OpMask = 0b11111110,
+ .WBitAt = 1
+ }
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "nil",
+ .Description = "Reg/Memory with register to either",
+ .OperandsCount = 2,
+ .BytesCount = 2,
+ .Bytes =
+ {
+ {
+ .Op = 0b00000000,
+ .OpMask = 0b11000100,
+ .SubOpMask = 0b111 << 3,
+ .WBitAt = 1,
+ .DBitAt = 2,
+ },
+ {
+ .ModBitsAt = 7,
+ .RegBitsAt = 4,
+ .RMBitsAt = 1,
+ }
+ },
+ .SubInstructionsCount = 5,
+ .SubInstructions =
+ {
+ { 0b000 << 3, "add" },
+ { 0b010 << 3, "adc" },
+ { 0b101 << 3, "sub" },
+ { 0b011 << 3, "sbb" },
+ { 0b111 << 3, "cmp" },
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "nil",
+ .Description = "Immediate to register/memory",
+ .OperandsCount = 2,
+ .HasImmediate = true,
+ .BytesCount = 2,
+ .Bytes =
+ {
+ {
+ .Op = 0b10000000,
+ .OpMask = 0b11000100,
+ .WBitAt = 1,
+ .SBitAt = 2,
+ },
+ {
+ .SubOpMask = 0b00111000,
+ .ModBitsAt = 7,
+ .RMBitsAt = 1,
+ }
+ },
+ .SubInstructionsCount = 5,
+ .SubInstructions =
+ {
+ { 0b000 << 3, "add" },
+ { 0b010 << 3, "adc" },
+ { 0b101 << 3, "sub" },
+ { 0b011 << 3, "sbb" },
+ { 0b111 << 3, "cmp" },
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "nil",
+ .Description = "Immediate to accumulator",
+ .OperandsCount = 2,
+ .HasImmediate = true,
+ .ToAccumulator = true,
+ .BytesCount = 1,
+ .Bytes =
+ {
+ {
+ .Op = 0b00000100,
+ .OpMask = 0b11000110,
+ .SubOpMask = 0b111 << 3,
+ .WBitAt = 1,
+ },
+ },
+ .SubInstructionsCount = 5,
+ .SubInstructions =
+ {
+ { 0b000 << 3, "add" },
+ { 0b010 << 3, "adc" },
+ { 0b101 << 3, "sub" },
+ { 0b011 << 3, "sbb" },
+ { 0b111 << 3, "cmp" },
+ }
+ };
+
+#define ByteJump(InsName, InsDescription, InsOp) \
+{ \
+.Name = InsName, \
+.Description = InsDescription, \
+.OperandsCount = 1, \
+.IsByteJump = true, \
+.BytesCount = 1, \
+.Bytes = \
+{ \
+{ \
+.Op = InsOp, \
+.OpMask = 0b11111111, \
+} \
+} \
+}
+ Table.Instructions[Table.Count++] = ByteJump("jz", "Jump on zero", 0b01110100);
+ Table.Instructions[Table.Count++] = ByteJump("jl", "Jump on less", 0b01111100);
+ Table.Instructions[Table.Count++] = ByteJump("jle", "Jump on less or equal", 0b01111110);
+ Table.Instructions[Table.Count++] = ByteJump("jb", "Jump on below", 0b01110010);
+ Table.Instructions[Table.Count++] = ByteJump("jbe", "Jump on below or equal", 0b01110110);
+ Table.Instructions[Table.Count++] = ByteJump("jp", "Jump on parity", 0b01111010);
+ Table.Instructions[Table.Count++] = ByteJump("jo", "Jump on overflow", 0b01110000);
+ Table.Instructions[Table.Count++] = ByteJump("js", "Jump on sign", 0b01111000);
+ Table.Instructions[Table.Count++] = ByteJump("jnz", "Jump on not zero", 0b01110101);
+ Table.Instructions[Table.Count++] = ByteJump("jnl", "Jump on not less", 0b01111101);
+ Table.Instructions[Table.Count++] = ByteJump("jnle", "Jump on not less or equal", 0b01111111);
+ Table.Instructions[Table.Count++] = ByteJump("jnb", "Jump on not below", 0b01110011);
+ Table.Instructions[Table.Count++] = ByteJump("jnbe", "Jump on not below or equal", 0b01110111);
+ Table.Instructions[Table.Count++] = ByteJump("jnp", "Jump on not par", 0b01111011);
+ Table.Instructions[Table.Count++] = ByteJump("jno", "Jump on not overflow", 0b01110001);
+ Table.Instructions[Table.Count++] = ByteJump("jns", "Jump on not sign", 0b01111001);
+ Table.Instructions[Table.Count++] = ByteJump("loop", "Loop CX times", 0b11100010);
+ Table.Instructions[Table.Count++] = ByteJump("loopz", "Loop while zero", 0b11100001);
+ Table.Instructions[Table.Count++] = ByteJump("loopnz", "Loop while not zero", 0b11100000);
+ Table.Instructions[Table.Count++] = ByteJump("jcxz", "Jump on CX zero", 0b11100011);
+#undef ByteJump
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "push",
+ .Description = "Register/memory",
+ .OperandsCount = 1,
+ .BytesCount = 2,
+ .Bytes =
+ {
+ {
+ .Op = 0b11111111,
+ .OpMask = 0b11111111,
+ },
+ {
+ .Op = 0b00110000,
+ .OpMask = 0b00111000,
+ .ModBitsAt = 7,
+ .RMBitsAt = 1,
+ }
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "push",
+ .Description = "Register",
+ .OperandsCount = 1,
+ .BytesCount = 1,
+ .Bytes =
+ {
+ {
+ .Op = 0b01010000,
+ .OpMask = 0b11111000,
+ .RegBitsAt = 1,
+ },
+ }
+ };
+
+ Table.Instructions[Table.Count++] =
+ {
+ .Name = "push",
+ .Description = "Segment register",
+ .OperandsCount = 1,
+ .HasSegmentRegister = true,
+ .BytesCount = 1,
+ .Bytes =
+ {
+ {
+ .Op = 0b00000110,
+ .OpMask = 0b11000111,
+ .RegBitsAt = 4,
+ },
+ }
+ };
+
+ if(ArgCount > 1)
+ {
+ int File = open(Args[1], O_RDONLY);
+ if(File != -1)
+ {
+ int BytesRead = 0;
+
+ printf("bits 16\n\n");
+
+ int KeepReading = true;
+ while(KeepReading)
+ {
+ u8 *ByteAt = Bytes;
+ BytesRead = ReadBytesFromFile(File, &ByteAt, 1);
+
+ if(BytesRead == 1)
+ {
+ for(u32 InstructionIndex = 0;
+ InstructionIndex < Table.Count;
+ InstructionIndex++)
+ {
+ instruction InsAt = Table.Instructions[InstructionIndex];
+
+ if((Bytes[0] & InsAt.Bytes[0].OpMask) == InsAt.Bytes[0].Op)
+ {
+ DebugLabel(ByteFound);
+ BytesRead = ReadBytesFromFile(File, &ByteAt, InsAt.BytesCount - BytesRead);
+
+ b32 HasMode = false;
+ b32 HasDisplacement = false;
+ b32 HasRegister = false;
+ b32 MemoryMode = false;
+ b32 RegisterMode = false;
+ b32 EffectiveAddressMode = false;
+ b32 Displacement8Bit = false;
+ b32 Displacement16Bit = false;
+ b32 DBitSet = false;
+ b32 SBitSet = false;
+ b32 VBitSet = false;
+ b32 WBitSet = false;
+ u8 RegBits = 0;
+ u8 ModBits = 0;
+ u8 RMBits = 0;
+ s16 DisplacementValue = 0;
+ s16 DataValue = 0;
+ s8 IncrementValue = 0;
+
+ char *InstructionName = InsAt.Name;
+#define OP_DEST 0
+#define OP_SOURCE 1
+ char Operands[2][255] = {};
+ char *SourceOperand = Operands[1];
+ char *DestOperand = Operands[0];
+ u32 NextOperand = OP_DEST;
+
+ if(InsAt.ToAccumulator)
+ {
+ NextOperand = OP_SOURCE;
+ }
+
+ for(u32 BytesIndex = 0;
+ BytesIndex < InsAt.BytesCount;
+ BytesIndex++)
+ {
+ u8 CurrentByte = Bytes[BytesIndex];
+ instruction_byte CurrentInsByte = InsAt.Bytes[BytesIndex];
+
+ if(CurrentInsByte.OpMask)
+ {
+ Assert((CurrentByte & CurrentInsByte.OpMask) == CurrentInsByte.Op);
+ }
+
+ SetBitFromBitAt(&DBitSet, CurrentByte, CurrentInsByte.DBitAt);
+ SetBitFromBitAt(&WBitSet, CurrentByte, CurrentInsByte.WBitAt);
+ SetBitFromBitAt(&SBitSet, CurrentByte, CurrentInsByte.SBitAt);
+ SetBitFromBitAt(&VBitSet, CurrentByte, CurrentInsByte.VBitAt);
+
+ if(CurrentInsByte.SubOpMask)
+ {
+ Assert(InsAt.SubInstructionsCount);
+
+ u8 SubInsBits = (CurrentByte & CurrentInsByte.SubOpMask);
+
+ b32 FoundSubInstruction = false;
+ sub_instruction ScanSubIns = {};
+ for(u32 SubInstructionsIndex = 0;
+ (SubInstructionsIndex < InsAt.SubInstructionsCount) && !FoundSubInstruction;
+ SubInstructionsIndex++)
+ {
+ ScanSubIns = InsAt.SubInstructions[SubInstructionsIndex];
+ FoundSubInstruction = (ScanSubIns.Op == SubInsBits);
+ }
+ Assert(FoundSubInstruction);
+
+ InstructionName = ScanSubIns.Name;
+ }
+
+ if(CurrentInsByte.ModBitsAt)
+ {
+ HasMode = true;
+ ModBits = ExtractBitsFromByte(CurrentByte, 0b11, CurrentInsByte.ModBitsAt);
+
+ if(ModBits == 0b00)
+ {
+ MemoryMode = true;
+ }
+ else if(ModBits == 0b01)
+ {
+ HasDisplacement = true;
+ Displacement8Bit = true;
+ }
+ else if(ModBits == 0b10)
+ {
+ HasDisplacement = true;
+ Displacement16Bit = true;
+ }
+ else if(ModBits == 0b11)
+ {
+ RegisterMode = true;
+ }
+ }
+
+ if(CurrentInsByte.RegBitsAt)
+ {
+ RegBits = ExtractBitsFromByte(CurrentByte, 0b111, CurrentInsByte.RegBitsAt);
+ HasRegister = true;
+ }
+
+ if(CurrentInsByte.RMBitsAt)
+ {
+ RMBits = ExtractBitsFromByte(CurrentByte, 0b111, CurrentInsByte.RMBitsAt);
+
+ if(MemoryMode && RMBits == 0b110)
+ {
+ MemoryMode = false;
+ EffectiveAddressMode = true;
+ }
+ }
+
+ } // for
+
+ DebugLabel(Parsed);
+
+ if(InsAt.HasAddress)
+ {
+ HasMode = true;
+ WBitSet = true;
+ EffectiveAddressMode = true;
+ }
+
+ if(HasRegister)
+ {
+ b32 IsWide = (WBitSet || InsAt.OperandsCount == 1);
+ u32 TargetOperand = OP_DEST;
+ char *OperandName = 0;
+
+ if(!InsAt.HasSegmentRegister)
+ {
+ OperandName = RegistersNames[RegBits][IsWide];
+ }
+ else
+ {
+ OperandName = SegmentRegistersNames[RegBits];
+ }
+
+ b32 OperandIsDest = (DBitSet ||
+ InsAt.HasImmediate ||
+ (InsAt.OperandsCount == 1));
+ TargetOperand = (OperandIsDest) ? OP_DEST : OP_SOURCE;
+ NextOperand = (OperandIsDest) ? OP_SOURCE : OP_DEST;
+
+ CStringCopy(Operands[TargetOperand], OperandName);
+ }
+
+
+ if(HasMode)
+ {
+ if(MemoryMode)
+ {
+ if(InsAt.OperandsCount == 1)
+ {
+ sprintf(Operands[NextOperand++], "%s [%s]", WBitSet ? "byte" : "word", DisplacementsNames[RMBits]);
+ }
+ else
+ {
+ sprintf(Operands[NextOperand++], "[%s]", DisplacementsNames[RMBits]);
+ }
+ }
+ else if(RegisterMode)
+ {
+ CStringCopy(Operands[NextOperand++], RegistersNames[RMBits][WBitSet]);
+ }
+ else if(HasDisplacement)
+ {
+ if(Displacement8Bit)
+ {
+ ReadBytesFromFile(File, &ByteAt, 1);
+ DisplacementValue = (s8)ByteAt[-1];
+ }
+ else if(Displacement16Bit)
+ {
+ ReadBytesFromFile(File, &ByteAt, 2);
+ DisplacementValue = ((s16)ByteAt[-1] << 8) | (s16)ByteAt[-2];
+ }
+ else
+ {
+ Assert(0);
+ }
+
+ if(DisplacementValue != 0)
+ {
+ if(InsAt.OperandsCount == 1)
+ {
+ b32 IsNegative = (DisplacementValue < 0);
+ sprintf(Operands[NextOperand++], "word [%s %c %d]",
+ DisplacementsNames[RMBits],
+ IsNegative ? '-' : '+',
+ IsNegative ? DisplacementValue * -1 : DisplacementValue);
+ }
+ else
+ {
+ b32 IsNegative = (DisplacementValue < 0);
+ sprintf(Operands[NextOperand++], "[%s %c %d]",
+ DisplacementsNames[RMBits],
+ IsNegative ? '-' : '+',
+ IsNegative ? DisplacementValue * -1 : DisplacementValue);
+ }
+ }
+ else
+ {
+ if(InsAt.OperandsCount == 1)
+ {
+ sprintf(Operands[OP_DEST], "%s [%s]", WBitSet ? "word" : "byte", DisplacementsNames[RMBits]);
+ }
+ else
+ {
+ sprintf(Operands[NextOperand++], "[%s]", DisplacementsNames[RMBits]);
+ }
+ }
+
+ }
+ else if(EffectiveAddressMode)
+ {
+ // NOTE(luca): Data is always 16-bit displacement, read 2 bytes.
+ ReadBytesFromFile(File, &ByteAt, 2);
+ DataValue = ((s16)ByteAt[-1] << 8) | (s16)ByteAt[-2];
+
+ if(InsAt.HasImmediate || InsAt.OperandsCount == 1)
+ {
+ sprintf(Operands[OP_DEST], "word [%d]", DataValue);
+ }
+ else
+ {
+ sprintf(Operands[NextOperand++], "[%d]", DataValue);
+ }
+
+ }
+ else
+ {
+ Assert(0);
+ }
+ }
+
+ if(InsAt.HasImmediate)
+ {
+ if(WBitSet && !SBitSet)
+ {
+ ReadBytesFromFile(File, &ByteAt, 2);
+ DataValue = (ByteAt[-1] << 8) | ByteAt[-2];
+ }
+ else
+ {
+ ReadBytesFromFile(File, &ByteAt, 1);
+ DataValue = ByteAt[-1];
+ }
+
+ if(MemoryMode || HasDisplacement)
+ {
+ sprintf(Operands[OP_SOURCE], "%s %d", WBitSet ? "word" : "byte", DataValue);
+ }
+ else
+ {
+ sprintf(Operands[OP_SOURCE], "%d", DataValue);
+ }
+ }
+
+ if(InsAt.ToAccumulator)
+ {
+ sprintf(Operands[OP_DEST], "%s", RegistersNames[ACCUMULATOR][WBitSet]);
+ }
+
+ if(InsAt.IsByteJump)
+ {
+ ReadBytesFromFile(File, &ByteAt, 1);
+ IncrementValue = (s8)ByteAt[-1];
+ IncrementValue += InsAt.BytesCount + 1;
+ b32 IsNegative = (IncrementValue < 0);
+ sprintf(Operands[NextOperand++], "$%c%d",
+ IsNegative ? '-' : '+',
+ IsNegative ? IncrementValue *= -1 : IncrementValue);
+ }
+
+ if(InsAt.FlipOperands)
+ {
+ Assert(InsAt.OperandsCount == 2);
+ Swap(char *, SourceOperand, DestOperand);
+ }
+
+ if(InsAt.OperandsCount == 2)
+ {
+ printf("%s %s, %s\n", InstructionName, DestOperand, SourceOperand);
+ }
+ else if(InsAt.OperandsCount == 1)
+ {
+ printf("%s %s\n", InstructionName, DestOperand);
+ }
+ else if(InsAt.OperandsCount == 0)
+ {
+ printf("%s\n", InstructionName);
+ }
+ else
+ {
+ Assert(0);
+ }
+
+ break;
+ } // if op
+ } // for ins
+ } // if bytesread
+ else if(BytesRead == -1)
+ {
+ fprintf(stderr, "Error while reading.\n");
+ KeepReading = false;
+ }
+ else if(BytesRead == 0)
+ {
+ KeepReading = false;
+ }
+ else
+ {
+ fprintf(stderr, "Read too many bytes.\n");
+ KeepReading = false;
+ }
+ } // while
+ } // if file
+ else
+ {
+ fprintf(stderr, "Could not open file.\n");
+ }
+ } // if argcount
+ else
+ {
+ fprintf(stderr, "Missing argument.\n"
+ "Usage: %s <assembly>\n", Args[0]);
+ }
+
+ return 0;
+} \ No newline at end of file