diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/AddWithCarry.cs b/source/Tests/MathTest/Lost/JIT/AMD64/AddWithCarry.cs index c84fbb527..d7b98c065 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/AddWithCarry.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/AddWithCarry.cs @@ -48,5 +48,10 @@ namespace Lost.JIT.AMD64 { get { return 0x10; } } + + public override string OpCodeFASM + { + get { return "adc"; } + } } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/And.cs b/source/Tests/MathTest/Lost/JIT/AMD64/And.cs index 0c0ed5d05..94c09a164 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/And.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/And.cs @@ -49,5 +49,10 @@ namespace Lost.JIT.AMD64 { get { return 0x20; } } + + public override string OpCodeFASM + { + get { return "and"; } + } } } \ No newline at end of file diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/BreakPoint.cs b/source/Tests/MathTest/Lost/JIT/AMD64/BreakPoint.cs index c62461e7b..c80f9c07f 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/BreakPoint.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/BreakPoint.cs @@ -18,5 +18,14 @@ namespace Lost.JIT.AMD64 { destStream.WriteByte(0xCC); } + + public override string OpCodeFASM + { + get { return "int 3"; } + } + public override string ToFASM() + { + return OpCodeFASM; + } } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/Call.cs b/source/Tests/MathTest/Lost/JIT/AMD64/Call.cs index 982bd5a77..c643985b6 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/Call.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/Call.cs @@ -68,5 +68,15 @@ namespace Lost.JIT.AMD64 throw new NotImplementedException(); } + + public override string OpCodeFASM + { + get { return "call"; } + } + + public override string ToFASM() + { + return string.Format(Dest is MemoryOperand? "call qword {0}": "call {0}", Dest); + } } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/Compare.cs b/source/Tests/MathTest/Lost/JIT/AMD64/Compare.cs new file mode 100644 index 000000000..fc7f13f9c --- /dev/null +++ b/source/Tests/MathTest/Lost/JIT/AMD64/Compare.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +namespace Lost.JIT.AMD64 +{ + [Serializable] + public sealed class Compare : DestSourceInstruction + { + public Compare(InstructionOperand dest, InstructionOperand source) + : base(dest, source) + { + } + public Compare(InstructionOperand dest, byte source) + : base(dest, source) + { + } + public Compare(InstructionOperand dest, short source) + : base(dest, source) + { + } + public Compare(InstructionOperand dest, int source) + : base(dest, source) + { + } + public Compare(InstructionOperand dest, long source) + : base(dest, source) + { + } + + public override byte AccumulatorOpCode + { + get + { + return 0x3C; + } + } + public override byte ImmediateExt + { + get { return 0x07; } + } + public override byte ImmediateOpCode + { + get { return 0x80; } + } + public override byte RegisterOpCode + { + get { return 0x38; } + } + + public override string OpCodeFASM + { + get { return "cmp"; } + } + } +} diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/ConditionalJumpInstruction.cs b/source/Tests/MathTest/Lost/JIT/AMD64/ConditionalJumpInstruction.cs index 0ff7db17c..318d105ae 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/ConditionalJumpInstruction.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/ConditionalJumpInstruction.cs @@ -23,7 +23,7 @@ namespace Lost.JIT.AMD64 public override void Compile(Stream destStream) { - if (TargetOffset.FitsInByte()) + if (TargetOffset.FitsInSByte()) { destStream.WriteByte(OpcodeBase); destStream.WriteSByte(TargetOffset); @@ -37,5 +37,11 @@ namespace Lost.JIT.AMD64 } protected abstract int OpcodeBase { get; } + + public override string ToFASM() + { + return string.Format("{0} {1}", OpCodeFASM, + TargetOffset + (TargetOffset.FitsInSByte() ? 2 : 6)); + } } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/DestSourceInstruction.cs b/source/Tests/MathTest/Lost/JIT/AMD64/DestSourceInstruction.cs index 6ca2b6861..3c83d4be1 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/DestSourceInstruction.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/DestSourceInstruction.cs @@ -277,6 +277,11 @@ namespace Lost.JIT.AMD64 get { throw new NotImplementedException(); } } + public override string ToFASM() + { + return string.Format("{0} {1}, {2}", OpCodeFASM, Dest, Source); + } + /// /// INSTR accum, imm /// diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/GeneralPurposeRegister.cs b/source/Tests/MathTest/Lost/JIT/AMD64/GeneralPurposeRegister.cs index cbeda9e2a..91fd4ef22 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/GeneralPurposeRegister.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/GeneralPurposeRegister.cs @@ -6,7 +6,7 @@ using System.Text; namespace Lost.JIT.AMD64 { [Serializable] - public sealed class GeneralPurposeRegister: InstructionOperand + public sealed class GeneralPurposeRegister: InstructionOperand, IEquatable { public GeneralPurposeRegister(Registers register, int size) { @@ -17,6 +17,28 @@ namespace Lost.JIT.AMD64 public int Size { get; private set; } public Registers Register { get; private set; } + public override string ToString() + { + if (Register.IsNew() && (Size == 8)) return Register.ToString(); + if (!Register.IsNew()) + { + switch(Size) + { + case 2: + return Register.ToString(); + case 4: + return 'E' + Register.ToString(); + case 8: + return 'R' + Register.ToString(); + case 1: + return Register.ToString().Substring(0, 1)+ 'L'; + default: + throw new NotImplementedException(); + } + } + throw new NotImplementedException(); + } + public static readonly GeneralPurposeRegister RAX = new GeneralPurposeRegister(Registers.AX, 8); public static readonly GeneralPurposeRegister RBX = new GeneralPurposeRegister(Registers.BX, 8); public static readonly GeneralPurposeRegister RCX = new GeneralPurposeRegister(Registers.CX, 8); @@ -60,5 +82,15 @@ namespace Lost.JIT.AMD64 //public static readonly GeneralPurposeRegister DI = new GeneralPurposeRegister(Registers.DI, 1); //public static readonly GeneralPurposeRegister BP = new GeneralPurposeRegister(Registers.BP, 1); //public static readonly GeneralPurposeRegister SP = new GeneralPurposeRegister(Registers.SP, 1); + + #region IEquatable Members + + public bool Equals(GeneralPurposeRegister other) + { + if (other == null) return false; + return (other.Register == Register) && (other.Size == Size); + } + + #endregion } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/ImmediateOperand.cs b/source/Tests/MathTest/Lost/JIT/AMD64/ImmediateOperand.cs index b595241e6..6bd767256 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/ImmediateOperand.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/ImmediateOperand.cs @@ -32,5 +32,11 @@ namespace Lost.JIT.AMD64 public long Value { get; private set; } public int Size { get; private set; } + + public override string ToString() + { + string digs = (Size * 2).ToString(); + return "0x" + Value.ToString("X" + digs); + } } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/Jump.cs b/source/Tests/MathTest/Lost/JIT/AMD64/Jump.cs index bb36cbdf2..e156a63e5 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/Jump.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/Jump.cs @@ -40,5 +40,21 @@ namespace Lost.JIT.AMD64 throw new NotImplementedException(); } + + public override string OpCodeFASM + { + get { return "jmp"; } + } + + public override string ToFASM() + { + if (Dest is ImmediateOperand) + { + var dest = Dest as ImmediateOperand; + return string.Format("jmp {0}", dest.Value + (dest.Value.FitsInSByte()? 2: 5)); + } + + throw new NotImplementedException(); + } } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/JumpIfEqual.cs b/source/Tests/MathTest/Lost/JIT/AMD64/JumpIfEqual.cs index 98e22e895..606ced9eb 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/JumpIfEqual.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/JumpIfEqual.cs @@ -14,5 +14,10 @@ namespace Lost.JIT.AMD64 { get { return 0x74; } } + + public override string OpCodeFASM + { + get { return "je"; } + } } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/MemoryOperand.cs b/source/Tests/MathTest/Lost/JIT/AMD64/MemoryOperand.cs index 1392d577f..ec19b01df 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/MemoryOperand.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/MemoryOperand.cs @@ -44,5 +44,24 @@ namespace Lost.JIT.AMD64 } return Base != null; } + + public override string ToString() + { + if (RipBased) + return string.Format("[RIP + 0x{0}]", Displacement.ToString("X8")); + + var sb = new StringBuilder(); + sb.AppendFormat("[{0}", Base); + if (Index != null) + if (Scale > 1) + sb.AppendFormat(" + {0}*{1}", Index, Scale); + else + sb.AppendFormat(" + {0}", Index); + + if (Displacement != 0) + sb.AppendFormat(" + 0x{0}", Displacement.ToString("X16")); + sb.Append(']'); + return sb.ToString(); + } } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/Pop.cs b/source/Tests/MathTest/Lost/JIT/AMD64/Pop.cs index be06a70a4..967b4722b 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/Pop.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/Pop.cs @@ -52,5 +52,14 @@ namespace Lost.JIT.AMD64 } throw new InvalidProgramException(); } + + public override string OpCodeFASM + { + get { return "pop"; } + } + public override string ToFASM() + { + return string.Format(Dest is MemoryOperand? "pop qword {0}":"pop {0}", Dest); + } } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/ProcessorInstruction.cs b/source/Tests/MathTest/Lost/JIT/AMD64/ProcessorInstruction.cs index 7677465a0..e3d803f9a 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/ProcessorInstruction.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/ProcessorInstruction.cs @@ -13,8 +13,15 @@ namespace Lost.JIT.AMD64 public const byte AddressSizeOverride = 0x67; public abstract int? Size { get; } + public abstract string ToFASM(); + public abstract string OpCodeFASM { get; } public abstract void Compile(Stream destStream); + public override string ToString() + { + return ToFASM(); + } + public static Rex NeedsRex(MemoryOperand memory) { if (memory.RipBased) return Rex.None; diff --git a/source/Tests/MathTest/Lost/JIT/AMD64/Push.cs b/source/Tests/MathTest/Lost/JIT/AMD64/Push.cs index 04ea71ae0..4bdfef3ed 100644 --- a/source/Tests/MathTest/Lost/JIT/AMD64/Push.cs +++ b/source/Tests/MathTest/Lost/JIT/AMD64/Push.cs @@ -73,5 +73,14 @@ namespace Lost.JIT.AMD64 } } } + + public override string OpCodeFASM + { + get { return "push"; } + } + public override string ToFASM() + { + return string.Format(Source is MemoryOperand ? "push qword {0}" : "push {0}", Source); + } } } diff --git a/source/Tests/MathTest/Lost/JIT/AMD64OLD/Enumerations.cs b/source/Tests/MathTest/Lost/JIT/AMD64OLD/Enumerations.cs deleted file mode 100644 index 608ea556d..000000000 --- a/source/Tests/MathTest/Lost/JIT/AMD64OLD/Enumerations.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Lost.JIT.AMD64OLD -{ - [Flags] - enum Register: byte - { - Legacy = 0x07, - AX = 0x00, - BX = 0x03, - CX = 0x01, - DX = 0x02, - SP = 0x04, - BP = 0x05, - SI = 0x06, - DI = 0x07, - R8 = 0x08, - R9 = 0x09, - R10 = 0x0A, - R11 = 0x0B, - R12 = 0x0C, - R13 = 0x0D, - R14 = 0x0E, - R15 = 0x0F, - } - - [Flags] - public enum Rex : byte - { - None = 0x40, - /// - /// Use 64-bit operand size - /// - /// - /// Setting the REX.W bit to 1 specifies a 64-bit operand size. Like the - /// existing 66h operand-size prefix, the REX 64-bit operand-size override has no effect on byte - /// operations. For non-byte operations, the REX operand-size override takes precedence over the 66h - /// prefix. If a 66h prefix is used together with a REX prefix that has the REX.W bit set to 1, the 66h - /// prefix is ignored. However, if a 66h prefix is used together with a REX prefix that has the REX.W bit - /// cleared to 0, the 66h prefix is not ignored and the operand size becomes 16 bits. - /// - Wide = None | (1 << 3), - /// - /// Reg index from ModRM extension. - /// - /// - /// The REX.R bit adds a 1-bit (high) extension to the ModRM reg field (page 17) - /// when that field encodes a GPR, XMM, control, or debug register. REX.R does not modify ModRM reg - /// when that field specifies other registers or opcodes. REX.R is ignored in such cases. - /// - Reg = None | (1 << 2), - /// - /// SIB index register extension. - /// - Index = None | (1 << 1), - /// - /// SIB index register extension. - /// Use Index mnenonic instead. - /// - X = None | (1 << 1), - /// - /// Extension of the ModRM r/m field1, SIB base field, or opcode reg field, - /// - /// - /// The REX.B bit adds a 1-bit (high) extension to either the ModRM r/m field to specify - /// a GPR or XMM register, or to the SIB base field to specify a GPR. (See Table 2-2 on page 40 for more - /// about the REX.B bit.) - /// - B = None | (1 << 0), - } -} diff --git a/source/Tests/MathTest/Lost/JIT/AMD64OLD/ImmediateOperand.cs b/source/Tests/MathTest/Lost/JIT/AMD64OLD/ImmediateOperand.cs deleted file mode 100644 index 485b2e41a..000000000 --- a/source/Tests/MathTest/Lost/JIT/AMD64OLD/ImmediateOperand.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Lost.JIT.AMD64OLD -{ - [Obsolete("")] - class ImmediateOperand: InstructionOperand - { - internal ImmediateOperand(int size, ulong value):base(value.ToString(string.Format("0X{0}", size*2))) - { - switch (size) - { - case 1: - byte b = checked((byte)value); - break; - case 2: - ushort s = checked((ushort)value); - break; - case 4: - uint i = checked((uint)value); - break; - case 8: - break; - default: - throw new NotSupportedException("incorrect operand size"); - } - _size = size; - _value = (long)value; - } - - int _size; - long _value; - - /// - /// Size of immediate operand, in bytes - /// - public int Size - { - get { return _size; } - } - /// - /// Value of immediate operand - /// - public long Value - { - get { return _value; } - } - - public override string ToString() - { - var val = _value.ToString(string.Format("X{0}", Size*2)); - return string.Format("0{0}h", val); - } - } -} diff --git a/source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionLabel.cs b/source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionLabel.cs deleted file mode 100644 index 7bf7bccf6..000000000 --- a/source/Tests/MathTest/Lost/JIT/AMD64OLD/InstructionLabel.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; - -namespace Lost.JIT.AMD64OLD -{ - class InstructionLabel - { - internal InstructionLabel(string name) - { - _name = name; - -#warning TODO: check label for validity - } - - static readonly Regex _regex = new Regex( - @"^(\s*(?