diff options
Diffstat (limited to 'Assembler')
| -rw-r--r-- | Assembler/Assembler.cs | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/Assembler/Assembler.cs b/Assembler/Assembler.cs new file mode 100644 index 0000000..14a33fd --- /dev/null +++ b/Assembler/Assembler.cs @@ -0,0 +1,106 @@ +namespace Q1Emu.Assembler; + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +public class Assembler +{ + public readonly BinaryWriter Writer; + public readonly StringReader Reader; + + public Assembler(StringReader reader, BinaryWriter writer) + { + this.Reader = reader; + this.Writer = writer; + } + + public void Assemble() + { + while (this.Reader.ReadLine() is { } line) + { + string trimmedLine = line.Trim(); + if (string.IsNullOrEmpty(trimmedLine) || trimmedLine.StartsWith(';')) + continue; + + this.ParseInstruction(trimmedLine); + } + } + + private void ParseInstruction(string instruction) + { + string[] parts = instruction.Split(' ', 2); + string opcode = parts[0].ToUpperInvariant(); + + parts = parts.Length > 1 ? parts[1].Split(',') : []; + if (parts.Length > 2) + throw new ArgumentException($"Invalid instruction format: {instruction}"); + + u8 m1 = 0, m2 = 0; + if (parts.Length > 0) + { + m1 = this.ParseOperand(parts[0]); + if (parts.Length > 1) + m2 = this.ParseOperand(parts[1]); + } + + switch (opcode) + { + case "NOP": + this.Writer.Write((u8) 0x00); + break; + + default: + throw new NotSupportedException($"Unsupported opcode: {opcode}"); + } + } + + private u8 ParseOperand(string operand) + { + operand = operand.Trim(); + + bool IsRegister(string text) + { + if (text.Length > 1 && text[0] == 'V') + return true; + + string[] hardcodedRegisters = + [ + "AX", + "AH", + "AL", + "DX", + "DH", + "DL", + "LX", + "PC", + "SP", + ]; + + return hardcodedRegisters.Contains(text); + } + + if (operand.StartsWith("@")) + { + return 0x03; // Indirect + } + + if (operand.StartsWith("[") && operand.EndsWith("]")) + { + string inner = operand[1..^1].Trim(); + if (inner.Contains("+")) + return 0x07; // Register indirect with offset + + if (IsRegister(inner)) + return 0x06; // Register indirect + + return 0x02; // Direct + } + + if (IsRegister(operand)) + return 0x05; // Register + + return 0x01; // Immediate + } +}
\ No newline at end of file |
