From 498f293c8af4cefc03bb44cfcb033a2c5a6544f7 Mon Sep 17 00:00:00 2001 From: LostTheBlack_cp Date: Mon, 31 Mar 2008 06:59:34 +0000 Subject: [PATCH] Added OO-based basic parts of AMD64 jitter: [+] Registers enumeration (only GPRs) [+] Basic class ProcessorInstruction [+] Base class InstructionOperand it's child GeneralPurposeRegister [+] Added some abstraction to DestSourceInstruction [+] Added stub for first instruction - AddWithCarry --- .../MathTest/Lost/JIT/AMD64/AddWithCarry.cs | 25 +++ .../Lost/JIT/AMD64/DestSourceInstruction.cs | 20 ++ .../Lost/JIT/AMD64/GeneralPurposeRegister.cs | 20 ++ .../Lost/JIT/AMD64/InstructionOperand.cs | 101 +-------- .../Lost/JIT/AMD64/ProcessorInstruction.cs | 194 +---------------- .../MathTest/Lost/JIT/AMD64/Registers.cs | 45 ++++ .../JIT/{AMD64 => AMD64OLD}/Enumerations.cs | 2 +- .../{AMD64 => AMD64OLD}/ImmediateOperand.cs | 2 +- .../{AMD64 => AMD64OLD}/InstructionLabel.cs | 2 +- .../Lost/JIT/AMD64OLD/InstructionOperand.cs | 109 ++++++++++ .../{AMD64 => AMD64OLD}/InstructionPrefix.cs | 2 +- .../Lost/JIT/{AMD64 => AMD64OLD}/ModRM.cs | 2 +- .../Lost/JIT/AMD64OLD/ProcessorInstruction.cs | 201 ++++++++++++++++++ source/Tests/MathTest/Lost/Lost.csproj | 16 +- source/Tests/MathTest/Lost/LostTest.cs | 18 +- 15 files changed, 451 insertions(+), 308 deletions(-) create mode 100644 source/Tests/MathTest/Lost/JIT/AMD64/AddWithCarry.cs create mode 100644 source/Tests/MathTest/Lost/JIT/AMD64/DestSourceInstruction.cs create mode 100644 source/Tests/MathTest/Lost/JIT/AMD64/GeneralPurposeRegister.cs create mode 100644 source/Tests/MathTest/Lost/JIT/AMD64/Registers.cs rename source/Tests/MathTest/Lost/JIT/{AMD64 => AMD64OLD}/Enumerations.cs (95%) rename source/Tests/MathTest/Lost/JIT/{AMD64 => AMD64OLD}/ImmediateOperand.cs (92%) rename source/Tests/MathTest/Lost/JIT/{AMD64 => AMD64OLD}/InstructionLabel.cs (93%) create mode 100644 source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionOperand.cs rename source/Tests/MathTest/Lost/JIT/{AMD64 => AMD64OLD}/InstructionPrefix.cs (93%) rename source/Tests/MathTest/Lost/JIT/{AMD64 => AMD64OLD}/ModRM.cs (92%) create mode 100644 source/Tests/MathTest/Lost/JIT/AMD64OLD/ProcessorInstruction.cs diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/AddWithCarry.cs b/source/Tests/MathTest/Lost/JIT/AMD64/AddWithCarry.cs new file mode 100644 index 000000000..65a9e149a --- /dev/null +++ b/source/Tests/MathTest/Lost/JIT/AMD64/AddWithCarry.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +namespace Lost.JIT.AMD64 +{ + [Serializable] + public sealed class AddWithCarry: DestSourceInstruction + { + public AddWithCarry(InstructionOperand dest, InstructionOperand source): base(dest, source) + { + } + + public override void Compile(Stream dest) + { + throw new NotImplementedException(); + } + public override int? Size + { + get { throw new NotImplementedException(); } + } + } +} diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/DestSourceInstruction.cs b/source/Tests/MathTest/Lost/JIT/AMD64/DestSourceInstruction.cs new file mode 100644 index 000000000..82b64f6ba --- /dev/null +++ b/source/Tests/MathTest/Lost/JIT/AMD64/DestSourceInstruction.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Lost.JIT.AMD64 +{ + [Serializable] + public abstract class DestSourceInstruction: ProcessorInstruction + { + public DestSourceInstruction(InstructionOperand dest, InstructionOperand source) + { + this.Dest = dest; + this.Source = source; + } + + public InstructionOperand Dest { get; private set; } + public InstructionOperand Source { get; private set; } + } +} diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/GeneralPurposeRegister.cs b/source/Tests/MathTest/Lost/JIT/AMD64/GeneralPurposeRegister.cs new file mode 100644 index 000000000..34ec24c39 --- /dev/null +++ b/source/Tests/MathTest/Lost/JIT/AMD64/GeneralPurposeRegister.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Lost.JIT.AMD64 +{ + [Serializable] + public sealed class GeneralPurposeRegister: InstructionOperand + { + public GeneralPurposeRegister(Registers register, int size) + { + this.Register = register; + this.Size = size; + } + + public int Size { get; private set; } + public Registers Register { get; private set; } + } +} diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/InstructionOperand.cs b/source/Tests/MathTest/Lost/JIT/AMD64/InstructionOperand.cs index 86e0456bc..1c21e5393 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/InstructionOperand.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/InstructionOperand.cs @@ -2,108 +2,11 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Text.RegularExpressions; -using System.IO; -using System.Diagnostics; namespace Lost.JIT.AMD64 { - class InstructionOperand + [Serializable] + public class InstructionOperand { - public InstructionOperand(string value) - { - _stringValue = value; - } - - static readonly Regex _regex = new Regex( - @"^(\s*(?(\w|\[|\]|\+|\-)+)\s*\,)*\s*$", - RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); - - internal static InstructionOperand[] GetOperands(string code) - { - if (code.Trim() != "") code += ","; - var match = _regex.Match(code); - - var result = new InstructionOperand[match.Groups["operand"].Captures.Count]; - for (int i = 0; i < result.Length; i++) - result[i] = InstructionOperand.Parse(match.Groups["operand"].Captures[i].Value); - - return result; - } - - private static InstructionOperand Parse(string operand) - { - return new InstructionOperand(operand); - } - - string _stringValue; - - public override string ToString() - { - return _stringValue; - } - - #region Parsing stuff - public bool IsGeneralPurposeRegister - { - get - { - if (_isGeneralPurposeRegister == null) - throw new NotImplementedException(); - return _isGeneralPurposeRegister.Value; - } - } bool? _isGeneralPurposeRegister; - - public int Size - { - get - { - if (_size == null) - throw new NotImplementedException(); - - return _size.Value; - } - } int? _size; - public ulong Value - { - get - { - if (_value == null) throw new NotImplementedException(); - - return _value.Value; - } - } ulong? _value; - - public Register Register - { - get - { - if (_register == null) - throw new NotImplementedException(); - - return _register.Value; - } - } Register? _register; - - public bool IsImmediate - { - get - { - if (_immediate == null) - throw new NotImplementedException(); - - return _immediate.Value; - } - } bool? _immediate; - - public void WriteTo(Stream dest) - { - Debug.Assert(IsImmediate); - - ulong value = Value; - for (int i = 0; i < Size; i++, value >>= 8) - dest.WriteByte((byte)(value & 0xFF)); - } - #endregion } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/ProcessorInstruction.cs b/source/Tests/MathTest/Lost/JIT/AMD64/ProcessorInstruction.cs index 12d43b5df..b9ee2ca28 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/ProcessorInstruction.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/ProcessorInstruction.cs @@ -2,200 +2,14 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Text.RegularExpressions; using System.IO; -using System.Diagnostics; namespace Lost.JIT.AMD64 { - class ProcessorInstruction + [Serializable] + public abstract class ProcessorInstruction { - const byte Lock = 0xF0; - const byte OperandSizeOverride = 0x66; - const byte AddressSizeOverride = 0x67; - const byte Rep = 0xF3; - const byte RepE = 0xF3; - const byte RepNE = 0xF2; - - internal ProcessorInstruction() - { - _labels = new HashSet(); - _prefixes = new HashSet(); - } - - internal ProcessorInstruction(string opCode, InstructionOperand[] operands, InstructionLabel[] labels, InstructionPrefix[] prefixes, string comments) - { - _opCode = opCode; - _operands = new List(operands); - _labels = new HashSet(labels); - _prefixes = new HashSet(prefixes); - _comments = comments; - } - - ICollection Labels - { - get { return _labels; } - } HashSet _labels; - ICollection Prefixes - { - get { return _prefixes; } - } HashSet _prefixes; - IList Operands - { - get { return _operands; } - } List _operands; - string OpCode - { - get { return _opCode; } - } string _opCode; - string Comments - { - get { return _comments; } - } string _comments; - - #region Encoding - InstructionOperand Dest - { - get { return _operands[0]; } - } - InstructionOperand Source - { - get { return _operands[1]; } - } - - #region Instructions - void AddWithCarry(Stream dest) - { - if (Dest.IsGeneralPurposeRegister) - if (Dest.Register == Register.AX && Source.IsImmediate) - { - switch (Dest.Size) - { - case 1: - if (Source.Size != null) - Debug.Assert(Source.Size == 1); - - dest.WriteByte(0x14); - break; - case 2: - if (Source.Size != null) - Debug.Assert(Source.Size == 2); - - dest.WriteByte(OperandSizeOverride); - dest.WriteByte(0x15); - break; - case 4: - if (Source.Size != null) - Debug.Assert(Source.Size == 4); - - dest.WriteByte(0x15); - break; - case 8: - if (Source.Size != null) - Debug.Assert(Source.Size == 4); - - dest.WriteByte((byte)Rex.Wide); - dest.WriteByte(0x15); - break; - default: - throw new NotSupportedException(); - } - Source.WriteTo(dest); - return; - } //adc al/ax/etc, imm - if (Source.IsImmediate) - { - switch (Dest.Size) - { - case 1: - if (Source.Size != null) - Debug.Assert(Source.Size == 4); - - dest.WriteByte(AddressSizeOverride); - dest.WriteByte(0x80); - dest.EncodeIndirectMemory(2, Dest.Register); - break; - } - Source.WriteTo(dest); - return; - } - Debug.Assert(false); - } - #endregion - - public void Encode(Stream dest) - { - switch (_opCode) - { - case "adc": - AddWithCarry(dest); - break; - default: - throw new NotSupportedException(_opCode); - } - } - - static void EncodeRegisterRegister(Rex rex, Register dest, Register source, byte opcode, Stream stream) - { - if (rex != Rex.None) stream.WriteByte((byte)rex); - stream.WriteByte(opcode); - - stream.EncodeRegisters(dest, source); - } - static void EncodeRegister(Rex rex, Register dest, byte opcode, Stream stream) - { - if (rex != Rex.None) stream.WriteByte((byte)rex); - - dest &= Register.Legacy; - Debug.Assert((opcode | (byte)Register.Legacy) == 0); - opcode |= (byte)dest; - - stream.WriteByte(opcode); - } - #endregion - - #region Parsing - public static ProcessorInstruction Parse(string code) - { - var labels = InstructionLabel.ExtractLabels(ref code); - var prefixes = InstructionPrefix.ExtractPrefixes(ref code); - var instr = ExtractInstruction(ref code); - var comments = ExtractComments(ref code); - var operands = InstructionOperand.GetOperands(code); - - var result = new ProcessorInstruction(instr.ToUpper(), operands, labels, prefixes, comments); - - return result; - } - - static readonly Regex _regexComments = new Regex( - @"^(?.*)\/\/\s*(?.*)\s*$", - RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); - private static string ExtractComments(ref string code) - { - var match = _regexComments.Match(code); - if (match == null) return null; - if (!match.Success) return null; - - var value = match.Groups["comments"].Value; - code = match.Groups["rest"].Value; - - return value; - } - - static readonly Regex _regexInstruction = new Regex( - @"^\s*(?\w+)(?.*$)", - RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); - - private static string ExtractInstruction(ref string code) - { - var match = _regexInstruction.Match(code); - - var value = match.Groups["instr"].Value; - code = match.Groups["rest"].Value; - - return value; - } - #endregion + public abstract int? Size { get; } + public abstract void Compile(Stream dest); } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/Registers.cs b/source/Tests/MathTest/Lost/JIT/AMD64/Registers.cs new file mode 100644 index 000000000..55a8398fa --- /dev/null +++ b/source/Tests/MathTest/Lost/JIT/AMD64/Registers.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Lost.JIT.AMD64 +{ + [Flags, Serializable] + public enum Registers + { + AX = 1 << 0, + BX = 1 << 3, + CX = 1 << 1, + DX = 1 << 2, + SI = 1 << 6, + DI = 1 << 7, + SP = 1 << 4, + BP = 1 << 5, + R8 = 1 << 8, + R9 = 1 << 9, + R10 = 1 << 10, + R11 = 1 << 11, + R12 = 1 << 12, + R13 = 1 << 13, + R14 = 1 << 14, + R15 = 1 << 15, + OldRegsMask = AX | BX | CX | DX | SI | DI | SP | BP, + } + + public static class RegistersExtensions + { + static readonly Dictionary regIndex = new Dictionary(); + static RegistersExtensions() + { + for (int i = 0; i < 16; i++) + regIndex.Add(1 << i, i); + } + + public static int GetIndex(this Registers register) + { + register &= Registers.OldRegsMask; + return regIndex[(int)register]; + } + } +} diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/Enumerations.cs b/source/Tests/MathTest/Lost/JIT/AMD64OLD/Enumerations.cs similarity index 95% rename from source/Tests/MathTest/Lost/JIT/AMD64/Enumerations.cs rename to source/Tests/MathTest/Lost/JIT/AMD64OLD/Enumerations.cs index 388c7c18e..608ea556d 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/Enumerations.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64OLD/Enumerations.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -namespace Lost.JIT.AMD64 +namespace Lost.JIT.AMD64OLD { [Flags] enum Register: byte diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/ImmediateOperand.cs b/source/Tests/MathTest/Lost/JIT/AMD64OLD/ImmediateOperand.cs similarity index 92% rename from source/Tests/MathTest/Lost/JIT/AMD64/ImmediateOperand.cs rename to source/Tests/MathTest/Lost/JIT/AMD64OLD/ImmediateOperand.cs index a41da1d22..485b2e41a 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/ImmediateOperand.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64OLD/ImmediateOperand.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -namespace Lost.JIT.AMD64 +namespace Lost.JIT.AMD64OLD { [Obsolete("")] class ImmediateOperand: InstructionOperand diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/InstructionLabel.cs b/source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionLabel.cs similarity index 93% rename from source/Tests/MathTest/Lost/JIT/AMD64/InstructionLabel.cs rename to source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionLabel.cs index c0df58331..7bf7bccf6 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/InstructionLabel.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionLabel.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; -namespace Lost.JIT.AMD64 +namespace Lost.JIT.AMD64OLD { class InstructionLabel { diff --git a/source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionOperand.cs b/source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionOperand.cs new file mode 100644 index 000000000..9c06bd87b --- /dev/null +++ b/source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionOperand.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.IO; +using System.Diagnostics; + +namespace Lost.JIT.AMD64OLD +{ + class InstructionOperand + { + public InstructionOperand(string value) + { + _stringValue = value; + } + + static readonly Regex _regex = new Regex( + @"^(\s*(?(\w|\[|\]|\+|\-)+)\s*\,)*\s*$", + RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); + + internal static InstructionOperand[] GetOperands(string code) + { + if (code.Trim() != "") code += ","; + var match = _regex.Match(code); + + var result = new InstructionOperand[match.Groups["operand"].Captures.Count]; + for (int i = 0; i < result.Length; i++) + result[i] = InstructionOperand.Parse(match.Groups["operand"].Captures[i].Value); + + return result; + } + + private static InstructionOperand Parse(string operand) + { + return new InstructionOperand(operand); + } + + string _stringValue; + + public override string ToString() + { + return _stringValue; + } + + #region Parsing stuff + public bool IsGeneralPurposeRegister + { + get + { + if (_isGeneralPurposeRegister == null) + throw new NotImplementedException(); + return _isGeneralPurposeRegister.Value; + } + } bool? _isGeneralPurposeRegister; + + public int Size + { + get + { + if (_size == null) + throw new NotImplementedException(); + + return _size.Value; + } + } int? _size; + public ulong Value + { + get + { + if (_value == null) throw new NotImplementedException(); + + return _value.Value; + } + } ulong? _value; + + public Register Register + { + get + { + if (_register == null) + throw new NotImplementedException(); + + return _register.Value; + } + } Register? _register; + + public bool IsImmediate + { + get + { + if (_immediate == null) + throw new NotImplementedException(); + + return _immediate.Value; + } + } bool? _immediate; + + public void WriteTo(Stream dest) + { + Debug.Assert(IsImmediate); + + ulong value = Value; + for (int i = 0; i < Size; i++, value >>= 8) + dest.WriteByte((byte)(value & 0xFF)); + } + #endregion + } +} diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/InstructionPrefix.cs b/source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionPrefix.cs similarity index 93% rename from source/Tests/MathTest/Lost/JIT/AMD64/InstructionPrefix.cs rename to source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionPrefix.cs index c9d442901..d4830031f 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/InstructionPrefix.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionPrefix.cs @@ -5,7 +5,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Diagnostics; -namespace Lost.JIT.AMD64 +namespace Lost.JIT.AMD64OLD { class InstructionPrefix { diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/ModRM.cs b/source/Tests/MathTest/Lost/JIT/AMD64OLD/ModRM.cs similarity index 92% rename from source/Tests/MathTest/Lost/JIT/AMD64/ModRM.cs rename to source/Tests/MathTest/Lost/JIT/AMD64OLD/ModRM.cs index 5b9dd0e04..a7cee3ed3 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/ModRM.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64OLD/ModRM.cs @@ -5,7 +5,7 @@ using System.Text; using System.Diagnostics; using System.IO; -namespace Lost.JIT.AMD64 +namespace Lost.JIT.AMD64OLD { static class ModRM { diff --git a/source/Tests/MathTest/Lost/JIT/AMD64OLD/ProcessorInstruction.cs b/source/Tests/MathTest/Lost/JIT/AMD64OLD/ProcessorInstruction.cs new file mode 100644 index 000000000..9861a556a --- /dev/null +++ b/source/Tests/MathTest/Lost/JIT/AMD64OLD/ProcessorInstruction.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.IO; +using System.Diagnostics; + +namespace Lost.JIT.AMD64OLD +{ + class ProcessorInstruction + { + const byte Lock = 0xF0; + const byte OperandSizeOverride = 0x66; + const byte AddressSizeOverride = 0x67; + const byte Rep = 0xF3; + const byte RepE = 0xF3; + const byte RepNE = 0xF2; + + internal ProcessorInstruction() + { + _labels = new HashSet(); + _prefixes = new HashSet(); + } + + internal ProcessorInstruction(string opCode, InstructionOperand[] operands, InstructionLabel[] labels, InstructionPrefix[] prefixes, string comments) + { + _opCode = opCode; + _operands = new List(operands); + _labels = new HashSet(labels); + _prefixes = new HashSet(prefixes); + _comments = comments; + } + + ICollection Labels + { + get { return _labels; } + } HashSet _labels; + ICollection Prefixes + { + get { return _prefixes; } + } HashSet _prefixes; + IList Operands + { + get { return _operands; } + } List _operands; + string OpCode + { + get { return _opCode; } + } string _opCode; + string Comments + { + get { return _comments; } + } string _comments; + + #region Encoding + InstructionOperand Dest + { + get { return _operands[0]; } + } + InstructionOperand Source + { + get { return _operands[1]; } + } + + #region Instructions + void AddWithCarry(Stream dest) + { + if (Dest.IsGeneralPurposeRegister) + if (Dest.Register == Register.AX && Source.IsImmediate) + { + switch (Dest.Size) + { + case 1: + if (Source.Size != null) + Debug.Assert(Source.Size == 1); + + dest.WriteByte(0x14); + break; + case 2: + if (Source.Size != null) + Debug.Assert(Source.Size == 2); + + dest.WriteByte(OperandSizeOverride); + dest.WriteByte(0x15); + break; + case 4: + if (Source.Size != null) + Debug.Assert(Source.Size == 4); + + dest.WriteByte(0x15); + break; + case 8: + if (Source.Size != null) + Debug.Assert(Source.Size == 4); + + dest.WriteByte((byte)Rex.Wide); + dest.WriteByte(0x15); + break; + default: + throw new NotSupportedException(); + } + Source.WriteTo(dest); + return; + } //adc al/ax/etc, imm + if (Source.IsImmediate) + { + switch (Dest.Size) + { + case 1: + if (Source.Size != null) + Debug.Assert(Source.Size == 4); + + dest.WriteByte(AddressSizeOverride); + dest.WriteByte(0x80); + dest.EncodeIndirectMemory(2, Dest.Register); + break; + } + Source.WriteTo(dest); + return; + } + Debug.Assert(false); + } + #endregion + + public void Encode(Stream dest) + { + switch (_opCode) + { + case "adc": + AddWithCarry(dest); + break; + default: + throw new NotSupportedException(_opCode); + } + } + + static void EncodeRegisterRegister(Rex rex, Register dest, Register source, byte opcode, Stream stream) + { + if (rex != Rex.None) stream.WriteByte((byte)rex); + stream.WriteByte(opcode); + + stream.EncodeRegisters(dest, source); + } + static void EncodeRegister(Rex rex, Register dest, byte opcode, Stream stream) + { + if (rex != Rex.None) stream.WriteByte((byte)rex); + + dest &= Register.Legacy; + Debug.Assert((opcode | (byte)Register.Legacy) == 0); + opcode |= (byte)dest; + + stream.WriteByte(opcode); + } + #endregion + + #region Parsing + public static ProcessorInstruction Parse(string code) + { + var labels = InstructionLabel.ExtractLabels(ref code); + var prefixes = InstructionPrefix.ExtractPrefixes(ref code); + var instr = ExtractInstruction(ref code); + var comments = ExtractComments(ref code); + var operands = InstructionOperand.GetOperands(code); + + var result = new ProcessorInstruction(instr.ToUpper(), operands, labels, prefixes, comments); + + return result; + } + + static readonly Regex _regexComments = new Regex( + @"^(?.*)\/\/\s*(?.*)\s*$", + RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); + private static string ExtractComments(ref string code) + { + var match = _regexComments.Match(code); + if (match == null) return null; + if (!match.Success) return null; + + var value = match.Groups["comments"].Value; + code = match.Groups["rest"].Value; + + return value; + } + + static readonly Regex _regexInstruction = new Regex( + @"^\s*(?\w+)(?.*$)", + RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); + + private static string ExtractInstruction(ref string code) + { + var match = _regexInstruction.Match(code); + + var value = match.Groups["instr"].Value; + code = match.Groups["rest"].Value; + + return value; + } + #endregion + } +} diff --git a/source/Tests/MathTest/Lost/Lost.csproj b/source/Tests/MathTest/Lost/Lost.csproj index 63685bb4b..c0e1f9c95 100644 --- a/source/Tests/MathTest/Lost/Lost.csproj +++ b/source/Tests/MathTest/Lost/Lost.csproj @@ -50,12 +50,18 @@ - - - + + + + + + + + + + + - - diff --git a/source/Tests/MathTest/Lost/LostTest.cs b/source/Tests/MathTest/Lost/LostTest.cs index 2b574aa3f..25529626c 100644 --- a/source/Tests/MathTest/Lost/LostTest.cs +++ b/source/Tests/MathTest/Lost/LostTest.cs @@ -13,15 +13,15 @@ namespace Lost [STAThread] static void Main(string[] args) { - using (var source = new StreamReader(args[0])) - { - string srcLine; - while ((srcLine = source.ReadLine()) != null) - { - var op = ProcessorInstruction.Parse(srcLine); - Console.WriteLine(op); - } - } + //using (var source = new StreamReader(args[0])) + //{ + // string srcLine; + // while ((srcLine = source.ReadLine()) != null) + // { + // var op = ProcessorInstruction.Parse(srcLine); + // Console.WriteLine(op); + // } + //} Console.ReadKey(); }