From 764a824a68ef2477fb4e9b8303fa9d6f8cfe1a64 Mon Sep 17 00:00:00 2001
From: Misha <106913236+MishaProductions@users.noreply.github.com>
Date: Mon, 4 Dec 2023 10:09:44 -0500
Subject: [PATCH] x64 support
---
.../XSharp/XSharp/Assembler/Gen1/Assembler.cs | 31 +-
.../Assembler/Gen1/x86/JumpToSegment.cs | 136 +-
.../XSharp/XSharp/Assembler/Gen1/x86/Push.cs | 20 +-
.../XSharp/Assembler/Gen1/x86/Registers.cs | 9 +-
.../Assembler/Gen1/x86/SSE2/ConvertSI2SD.cs | 18 +-
.../XSharp/Assembler/Gen1/x86/SignExtendAX.cs | 51 +-
.../Assembler/Gen1/x86/_Infra/Extensions.cs | 231 +-
.../Assembler/Gen1/x86/_Infra/Instruction.cs | 108 +-
.../InstructionWithDestinationAndSize.cs | 69 +-
.../InstructionWithDestinationAndSource.cs | 18 +-
...tructionWithDestinationAndSourceAndSize.cs | 5 +-
.../XSharp/XSharp/Assembler/x86/Register.cs | 246 +-
source/XSharp/XSharp/Gen1/Parser.cs | 782 +++---
source/XSharp/XSharp/Gen1/TokenPatterns.cs | 2320 ++++++++---------
source/XSharp/XSharp/Gen1/XS.FPU.cs | 326 +--
source/XSharp/XSharp/Gen1/XS.SSE.cs | 394 +--
source/XSharp/XSharp/Gen1/XS.SSE2.cs | 248 +-
source/XSharp/XSharp/Gen1/XS.cs | 80 +-
source/XSharp/XSharp/Gen1/XSRegisters.cs | 40 +-
source/XSharp/XSharp/XSharp.csproj | 1 +
20 files changed, 2576 insertions(+), 2557 deletions(-)
diff --git a/source/XSharp/XSharp/Assembler/Gen1/Assembler.cs b/source/XSharp/XSharp/Assembler/Gen1/Assembler.cs
index b5391550..cc7dee1d 100644
--- a/source/XSharp/XSharp/Assembler/Gen1/Assembler.cs
+++ b/source/XSharp/XSharp/Assembler/Gen1/Assembler.cs
@@ -173,7 +173,7 @@ public void Add(params Instruction[] aReaders)
}
// Allows to emit footers to the code and datamember sections
- protected virtual void OnBeforeFlush()
+ protected virtual void OnBeforeFlush(TextWriter output)
{
}
@@ -188,43 +188,20 @@ public string GetIdentifier(string aPrefix)
private bool mFlushInitializationDone = false;
- protected void BeforeFlush()
+ protected void BeforeFlush(TextWriter output)
{
if (mFlushInitializationDone)
{
return;
}
mFlushInitializationDone = true;
- OnBeforeFlush();
+ OnBeforeFlush(output);
//MergeAllElements();
}
- public virtual void FlushBinary(Stream aOutput, ulong aBaseAddress)
- {
- BeforeFlush();
- var xMax = AllAssemblerElementCount;
- var xCurrentAddresss = aBaseAddress;
- for (int i = 0; i < xMax; i++)
- {
- GetAssemblerElement(i).UpdateAddress(this, ref xCurrentAddresss);
- }
- aOutput.SetLength(aOutput.Length + (long) (xCurrentAddresss - aBaseAddress));
- for (int i = 0; i < xMax; i++)
- {
- var xItem = GetAssemblerElement(i);
- if (!xItem.IsComplete(this))
- {
- throw new Exception("Incomplete element encountered.");
- }
- //var xBuff = xItem.GetData(this);
- //aOutput.Write(xBuff, 0, xBuff.Length);
- xItem.WriteData(this, aOutput);
- }
- }
-
public virtual void FlushText(TextWriter aOutput)
{
- BeforeFlush();
+ BeforeFlush(aOutput);
BeforeFlushText(aOutput);
// Write out data declarations
aOutput.WriteLine();
diff --git a/source/XSharp/XSharp/Assembler/Gen1/x86/JumpToSegment.cs b/source/XSharp/XSharp/Assembler/Gen1/x86/JumpToSegment.cs
index aa5275dc..48882da9 100644
--- a/source/XSharp/XSharp/Assembler/Gen1/x86/JumpToSegment.cs
+++ b/source/XSharp/XSharp/Assembler/Gen1/x86/JumpToSegment.cs
@@ -1,66 +1,70 @@
-using System;
-
-namespace XSharp.Assembler.x86
-{
- [XSharp.Assembler.OpCode("jmp")]
- public class JumpToSegment : Instruction {
- public XSharp.Assembler.ElementReference DestinationRef {
- get;
- set;
- }
-
- public ushort Segment {
- get;
- set;
- }
-
- public override void WriteText( XSharp.Assembler.Assembler aAssembler, System.IO.TextWriter aOutput )
- {
- if (DestinationRef != null) {
- aOutput.Write("jmp ");
- aOutput.Write(Segment);
- aOutput.Write(":");
- aOutput.Write(DestinationRef.ToString());
- } else {
- aOutput.Write("jmp ");
- aOutput.Write(Segment);
- aOutput.Write(":0x0");
- }
- }
-
- public string DestinationLabel {
- get {
- if (DestinationRef != null) {
- return DestinationRef.Name;
- }
- return String.Empty;
- }
- set {
- DestinationRef = XSharp.Assembler.ElementReference.New(value);
- }
- }
-
- public override bool IsComplete( XSharp.Assembler.Assembler aAssembler )
- {
- ulong xAddress;
- return DestinationRef == null || DestinationRef.Resolve(aAssembler, out xAddress);
- }
-
- public override void UpdateAddress(XSharp.Assembler.Assembler aAssembler, ref ulong aAddress) {
- base.UpdateAddress(aAssembler, ref aAddress);
- aAddress += 7;
- }
-
- //public override byte[] GetData(Assembler aAssembler) {
- public override void WriteData( XSharp.Assembler.Assembler aAssembler, System.IO.Stream aOutput )
- {
- aOutput.WriteByte(0xEA);
- ulong xAddress = 0;
- if (DestinationRef != null && DestinationRef.Resolve(aAssembler, out xAddress)) {
- xAddress = (ulong)(((long)xAddress) + DestinationRef.Offset);
- }
- aOutput.Write(BitConverter.GetBytes((uint)(xAddress)), 0, 4);
- aOutput.Write(BitConverter.GetBytes(Segment), 0, 2);
- }
- }
-}
\ No newline at end of file
+using System;
+
+namespace XSharp.Assembler.x86
+{
+ [XSharp.Assembler.OpCode("jmp")]
+ public class JumpToSegment : Instruction {
+ public XSharp.Assembler.ElementReference DestinationRef {
+ get;
+ set;
+ }
+
+ public ushort Segment {
+ get;
+ set;
+ }
+
+ public JumpToSegment()
+ {
+ ;
+ }
+ public override void WriteText( XSharp.Assembler.Assembler aAssembler, System.IO.TextWriter aOutput )
+ {
+ if (DestinationRef != null) {
+ aOutput.Write("jmp ");
+ aOutput.Write(Segment);
+ aOutput.Write(":");
+ aOutput.Write(DestinationRef.ToString());
+ } else {
+ aOutput.Write("jmp ");
+ aOutput.Write(Segment);
+ aOutput.Write(":0x0");
+ }
+ }
+
+ public string DestinationLabel {
+ get {
+ if (DestinationRef != null) {
+ return DestinationRef.Name;
+ }
+ return String.Empty;
+ }
+ set {
+ DestinationRef = XSharp.Assembler.ElementReference.New(value);
+ }
+ }
+
+ public override bool IsComplete( XSharp.Assembler.Assembler aAssembler )
+ {
+ ulong xAddress;
+ return DestinationRef == null || DestinationRef.Resolve(aAssembler, out xAddress);
+ }
+
+ public override void UpdateAddress(XSharp.Assembler.Assembler aAssembler, ref ulong aAddress) {
+ base.UpdateAddress(aAssembler, ref aAddress);
+ aAddress += 7;
+ }
+
+ //public override byte[] GetData(Assembler aAssembler) {
+ public override void WriteData( XSharp.Assembler.Assembler aAssembler, System.IO.Stream aOutput )
+ {
+ aOutput.WriteByte(0xEA);
+ ulong xAddress = 0;
+ if (DestinationRef != null && DestinationRef.Resolve(aAssembler, out xAddress)) {
+ xAddress = (ulong)(((long)xAddress) + DestinationRef.Offset);
+ }
+ aOutput.Write(BitConverter.GetBytes((uint)(xAddress)), 0, 4);
+ aOutput.Write(BitConverter.GetBytes(Segment), 0, 2);
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Assembler/Gen1/x86/Push.cs b/source/XSharp/XSharp/Assembler/Gen1/x86/Push.cs
index 64e4f1f4..0affe574 100644
--- a/source/XSharp/XSharp/Assembler/Gen1/x86/Push.cs
+++ b/source/XSharp/XSharp/Assembler/Gen1/x86/Push.cs
@@ -1,10 +1,10 @@
-namespace XSharp.Assembler.x86
-{
- [XSharp.Assembler.OpCode("push")]
- public class Push : InstructionWithDestinationAndSize {
-
- public Push():base("push") {
- Size = 32;
- }
- }
-}
+namespace XSharp.Assembler.x86
+{
+ [XSharp.Assembler.OpCode("push")]
+ public class Push : InstructionWithDestinationAndSize {
+
+ public Push():base("push") {
+ Size = 64;
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Assembler/Gen1/x86/Registers.cs b/source/XSharp/XSharp/Assembler/Gen1/x86/Registers.cs
index b925ea90..fd62931e 100644
--- a/source/XSharp/XSharp/Assembler/Gen1/x86/Registers.cs
+++ b/source/XSharp/XSharp/Assembler/Gen1/x86/Registers.cs
@@ -324,7 +324,8 @@ public static string GetRegisterName(RegistersEnum aRegister)
public static byte GetSize(RegistersEnum aRegister) {
if (Is128Bit(aRegister)) { return 128; }
- if (Is80Bit(aRegister)) { return 80; }
+ if (Is64Bit(aRegister)) { return 64; }
+ if (Is80Bit(aRegister)) { return 80; }
if (Is32Bit(aRegister)) { return 32; }
if (Is16Bit(aRegister)) { return 16; }
if (Is8Bit(aRegister)) { return 8; }
@@ -369,6 +370,12 @@ public static bool IsSegment(RegistersEnum aRegister)
return aRegister == RegistersEnum.CS || aRegister == RegistersEnum.DS || aRegister == RegistersEnum.ES || aRegister == RegistersEnum.FS || aRegister == RegistersEnum.GS || aRegister == RegistersEnum.SS;
}
+ public static bool Is64Bit(RegistersEnum aRegister)
+ {
+ return aRegister == RegistersEnum.RAX || aRegister == RegistersEnum.RBX || aRegister == RegistersEnum.RCX || aRegister == RegistersEnum.RDX || aRegister == RegistersEnum.RSP || aRegister == RegistersEnum.RBP || aRegister == RegistersEnum.RSI || aRegister == RegistersEnum.RDI || aRegister == RegistersEnum.CR0 || aRegister == RegistersEnum.CR1 || aRegister == RegistersEnum.CR2 || aRegister == RegistersEnum.CR3 || aRegister == RegistersEnum.CR4
+ || aRegister == RegistersEnum.RIP || aRegister == RegistersEnum.R9 || aRegister == RegistersEnum.R10 || aRegister == RegistersEnum.R11 || aRegister == RegistersEnum.R12 || aRegister == RegistersEnum.R13 || aRegister == RegistersEnum.R14 || aRegister == RegistersEnum.R15;
+ }
+
public static bool Is32Bit(RegistersEnum aRegister)
{
return aRegister == RegistersEnum.EAX || aRegister == RegistersEnum.EBX || aRegister == RegistersEnum.ECX || aRegister == RegistersEnum.EDX || aRegister == RegistersEnum.ESP || aRegister == RegistersEnum.EBP || aRegister == RegistersEnum.ESI || aRegister == RegistersEnum.EDI || aRegister == RegistersEnum.CR0 || aRegister == RegistersEnum.CR1 || aRegister == RegistersEnum.CR2 || aRegister == RegistersEnum.CR3 || aRegister == RegistersEnum.CR4
diff --git a/source/XSharp/XSharp/Assembler/Gen1/x86/SSE2/ConvertSI2SD.cs b/source/XSharp/XSharp/Assembler/Gen1/x86/SSE2/ConvertSI2SD.cs
index 0fe104e0..4e6c83d9 100644
--- a/source/XSharp/XSharp/Assembler/Gen1/x86/SSE2/ConvertSI2SD.cs
+++ b/source/XSharp/XSharp/Assembler/Gen1/x86/SSE2/ConvertSI2SD.cs
@@ -1,7 +1,11 @@
-namespace XSharp.Assembler.x86.SSE
-{
- [XSharp.Assembler.OpCode("cvtsi2sd")]
- public class ConvertSI2SD : InstructionWithDestinationAndSource
- {
- }
-}
\ No newline at end of file
+namespace XSharp.Assembler.x86.SSE
+{
+ [XSharp.Assembler.OpCode("cvtsi2sd")]
+ public class ConvertSI2SD : InstructionWithDestinationAndSource
+ {
+ public ConvertSI2SD()
+ {
+ SourceRequiresSize = true;
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Assembler/Gen1/x86/SignExtendAX.cs b/source/XSharp/XSharp/Assembler/Gen1/x86/SignExtendAX.cs
index 2b128020..75fc40d8 100644
--- a/source/XSharp/XSharp/Assembler/Gen1/x86/SignExtendAX.cs
+++ b/source/XSharp/XSharp/Assembler/Gen1/x86/SignExtendAX.cs
@@ -1,24 +1,27 @@
-using System;
-
-namespace XSharp.Assembler.x86
-{
- [XSharp.Assembler.OpCode("cdq")]
- public class SignExtendAX : InstructionWithSize {
- public override void WriteText( XSharp.Assembler.Assembler aAssembler, System.IO.TextWriter aOutput )
- {
- switch (Size) {
- case 32:
- aOutput.Write("cdq");
- return;
- case 16:
- aOutput.Write("cwde");
- return;
- case 8:
- aOutput.Write("cbw");
- return;
- default:
- throw new NotSupportedException();
- }
- }
- }
-}
\ No newline at end of file
+using System;
+
+namespace XSharp.Assembler.x86
+{
+ [XSharp.Assembler.OpCode("cdq")]
+ public class SignExtendAX : InstructionWithSize {
+ public override void WriteText( XSharp.Assembler.Assembler aAssembler, System.IO.TextWriter aOutput )
+ {
+ switch (Size) {
+ case 64:
+ aOutput.Write("cqo");
+ return;
+ case 32:
+ aOutput.Write("cdq");
+ return;
+ case 16:
+ aOutput.Write("cwde");
+ return;
+ case 8:
+ aOutput.Write("cbw");
+ return;
+ default:
+ throw new NotSupportedException();
+ }
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/Extensions.cs b/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/Extensions.cs
index 4c2b85c8..fae25108 100644
--- a/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/Extensions.cs
+++ b/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/Extensions.cs
@@ -1,112 +1,119 @@
-using System;
-
-namespace XSharp.Assembler.x86
-{
- public static class InfraExtensions
- {
- public static string GetDestinationAsString(this IInstructionWithDestination aThis)
- {
- string xDest = string.Empty;
- if ((aThis.DestinationValue.HasValue || aThis.DestinationRef != null) &&
- aThis.DestinationIsIndirect &&
- aThis.DestinationReg != null && aThis.DestinationDisplacement > 0)
- {
- throw new Exception("[Scale*index+base] style addressing not supported at the moment");
- }
- if (aThis.DestinationRef != null)
- {
- xDest = aThis.DestinationRef.ToString();
- }
- else
- {
- if (aThis.DestinationReg != null)
- {
- xDest = Registers.GetRegisterName(aThis.DestinationReg.Value);
- }
- else
- {
- if (aThis.DestinationValue.HasValue)
- xDest = "0x" + aThis.DestinationValue.GetValueOrDefault().ToString("X").ToUpperInvariant();
- }
- }
- if (aThis.DestinationDisplacement != null && aThis.DestinationDisplacement != 0)
- {
- if (aThis.DestinationDisplacement > 255)
- {
- xDest += " + 0x" + aThis.DestinationDisplacement.Value.ToString("X");
- }
- else
- {
- xDest += (aThis.DestinationDisplacement < 0 ? " - " : " + ") + Math.Abs(aThis.DestinationDisplacement.Value);
- }
- }
- if (aThis.DestinationIsIndirect)
- {
- return "[" + xDest + "]";
- }
- return xDest;
- }
-
- public static void DetermineSize(this IInstructionWithDestination aThis, IInstructionWithSize aThis2, byte aSize)
- {
- if (aSize == 0)
- {
- if (aThis.DestinationReg != null && !aThis.DestinationIsIndirect)
- {
- aThis2.Size = Registers.GetSize(aThis.DestinationReg.Value);
- return;
- }
- if (aThis.DestinationRef != null && !aThis.DestinationIsIndirect)
- {
- aThis2.Size = 32;
- return;
- }
- }
- }
-
- public static string GetMnemonic(this ConditionalTestEnum aThis)
- {
- switch (aThis)
- {
- case ConditionalTestEnum.Overflow:
- return "o";
- case ConditionalTestEnum.NoOverflow:
- return "no";
- case ConditionalTestEnum.Below:
- return "b";
- case ConditionalTestEnum.NotBelow:
- return "nb";
- case ConditionalTestEnum.Equal:
- return "e";
- case ConditionalTestEnum.NotEqual:
- return "ne";
- case ConditionalTestEnum.BelowOrEqual:
- return "be";
- case ConditionalTestEnum.NotBelowOrEqual:
- return "nbe";
- case ConditionalTestEnum.Sign:
- return "s";
- case ConditionalTestEnum.NotSign:
- return "ns";
- case ConditionalTestEnum.Parity:
- return "p";
- case ConditionalTestEnum.NotParity:
- return "np";
- case ConditionalTestEnum.LessThan:
- return "l";
- case ConditionalTestEnum.NotLessThan:
- return "nl";
- case ConditionalTestEnum.LessThanOrEqualTo:
- return "le";
- case ConditionalTestEnum.NotLessThanOrEqualTo:
- return "nle";
- case ConditionalTestEnum.CXRegisterEqualOrZeroTo:
- return "cxe";
- case ConditionalTestEnum.ECXRegisterEqualOrZeroTo:
- return "ecxe";
- default:
- throw new NotImplementedException();
- }
- }
- }
-}
+using System;
+
+namespace XSharp.Assembler.x86
+{
+ public static class InfraExtensions
+ {
+ public static string GetDestinationAsString(this IInstructionWithDestination aThis)
+ {
+ string xDest = string.Empty;
+ if ((aThis.DestinationValue.HasValue || aThis.DestinationRef != null) &&
+ aThis.DestinationIsIndirect &&
+ aThis.DestinationReg != null && aThis.DestinationDisplacement > 0)
+ {
+ throw new Exception("[Scale*index+base] style addressing not supported at the moment");
+ }
+ if (aThis.DestinationRef != null)
+ {
+ if (aThis.DestinationIsIndirect)
+ {
+ xDest = "rel " + aThis.DestinationRef.ToString();
+ }
+ else
+ {
+ xDest = aThis.DestinationRef.ToString();
+ }
+ }
+ else
+ {
+ if (aThis.DestinationReg != null)
+ {
+ xDest = Registers.GetRegisterName(aThis.DestinationReg.Value);
+ }
+ else
+ {
+ if (aThis.DestinationValue.HasValue)
+ xDest = "0x" + aThis.DestinationValue.GetValueOrDefault().ToString("X").ToUpperInvariant();
+ }
+ }
+ if (aThis.DestinationDisplacement != null && aThis.DestinationDisplacement != 0)
+ {
+ if (aThis.DestinationDisplacement > 255)
+ {
+ xDest += " + 0x" + aThis.DestinationDisplacement.Value.ToString("X");
+ }
+ else
+ {
+ xDest += (aThis.DestinationDisplacement < 0 ? " - " : " + ") + Math.Abs(aThis.DestinationDisplacement.Value);
+ }
+ }
+ if (aThis.DestinationIsIndirect)
+ {
+ return "[" + xDest + "]";
+ }
+ return xDest;
+ }
+
+ public static void DetermineSize(this IInstructionWithDestination aThis, IInstructionWithSize aThis2, byte aSize)
+ {
+ if (aSize == 0)
+ {
+ if (aThis.DestinationReg != null && !aThis.DestinationIsIndirect)
+ {
+ aThis2.Size = Registers.GetSize(aThis.DestinationReg.Value);
+ return;
+ }
+ if (aThis.DestinationRef != null && !aThis.DestinationIsIndirect)
+ {
+ aThis2.Size = 64;
+ return;
+ }
+ }
+ }
+
+ public static string GetMnemonic(this ConditionalTestEnum aThis)
+ {
+ switch (aThis)
+ {
+ case ConditionalTestEnum.Overflow:
+ return "o";
+ case ConditionalTestEnum.NoOverflow:
+ return "no";
+ case ConditionalTestEnum.Below:
+ return "b";
+ case ConditionalTestEnum.NotBelow:
+ return "nb";
+ case ConditionalTestEnum.Equal:
+ return "e";
+ case ConditionalTestEnum.NotEqual:
+ return "ne";
+ case ConditionalTestEnum.BelowOrEqual:
+ return "be";
+ case ConditionalTestEnum.NotBelowOrEqual:
+ return "nbe";
+ case ConditionalTestEnum.Sign:
+ return "s";
+ case ConditionalTestEnum.NotSign:
+ return "ns";
+ case ConditionalTestEnum.Parity:
+ return "p";
+ case ConditionalTestEnum.NotParity:
+ return "np";
+ case ConditionalTestEnum.LessThan:
+ return "l";
+ case ConditionalTestEnum.NotLessThan:
+ return "nl";
+ case ConditionalTestEnum.LessThanOrEqualTo:
+ return "le";
+ case ConditionalTestEnum.NotLessThanOrEqualTo:
+ return "nle";
+ case ConditionalTestEnum.CXRegisterEqualOrZeroTo:
+ return "cxe";
+ case ConditionalTestEnum.ECXRegisterEqualOrZeroTo:
+ return "ecxe";
+ default:
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/Instruction.cs b/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/Instruction.cs
index f7ac1091..020a0360 100644
--- a/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/Instruction.cs
+++ b/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/Instruction.cs
@@ -1,54 +1,54 @@
-using System;
-
-namespace XSharp.Assembler.x86
-{
- // todo: cache the EncodingOption and InstructionData instances..
- public abstract class Instruction : XSharp.Assembler.Instruction {
-
- [Flags]
- public enum InstructionSizes {
- None,
- Byte = 8,
- Word = 16,
- DWord = 32,
- QWord = 64,
- All = Byte | Word | DWord
- }
-
- public enum InstructionSize {
- None = 0,
- Byte = 8,
- Word = 16,
- DWord = 32,
- QWord = 64
- }
-
- [Flags]
- public enum OperandMemoryKinds {
- Default = Address | IndirectReg | IndirectRegOffset,
- Address = 1,
- IndirectReg = 2,
- IndirectRegOffset = 4
- }
-
- protected Instruction(string mnemonic = null) { }
- protected Instruction(bool aAddToAssembler, string mnemonic = null):base(aAddToAssembler, mnemonic) { }
-
- protected static string SizeToString(byte aSize) {
- switch (aSize) {
- case 8:
- return "byte";
- case 16:
- return "word";
- case 32:
- return "dword";
- case 64:
- return "qword";
- case 80:
- return string.Empty;
- default:
- return "dword";
- }
- }
- }
-}
+using System;
+
+namespace XSharp.Assembler.x86
+{
+ // todo: cache the EncodingOption and InstructionData instances..
+ public abstract class Instruction : XSharp.Assembler.Instruction {
+
+ [Flags]
+ public enum InstructionSizes {
+ None,
+ Byte = 8,
+ Word = 16,
+ DWord = 32,
+ QWord = 64,
+ All = Byte | Word | DWord
+ }
+
+ public enum InstructionSize {
+ None = 0,
+ Byte = 8,
+ Word = 16,
+ DWord = 32,
+ QWord = 64
+ }
+
+ [Flags]
+ public enum OperandMemoryKinds {
+ Default = Address | IndirectReg | IndirectRegOffset,
+ Address = 1,
+ IndirectReg = 2,
+ IndirectRegOffset = 4
+ }
+
+ protected Instruction(string mnemonic = null) { }
+ protected Instruction(bool aAddToAssembler, string mnemonic = null):base(aAddToAssembler, mnemonic) { }
+
+ protected static string SizeToString(byte aSize) {
+ switch (aSize) {
+ case 8:
+ return "byte";
+ case 16:
+ return "word";
+ case 32:
+ return "dword";
+ case 64:
+ return "qword";
+ case 80:
+ return string.Empty;
+ default:
+ return "dword";
+ }
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/InstructionWithDestinationAndSize.cs b/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/InstructionWithDestinationAndSize.cs
index 8c63f74c..f9bb9328 100644
--- a/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/InstructionWithDestinationAndSize.cs
+++ b/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/InstructionWithDestinationAndSize.cs
@@ -1,34 +1,35 @@
-namespace XSharp.Assembler.x86
-{
- public abstract class InstructionWithDestinationAndSize : InstructionWithDestination, IInstructionWithSize {
- public InstructionWithDestinationAndSize(string mnemonic = null) : base(mnemonic)
- {
- }
-
- private byte mSize;
- public byte Size {
- get {
- this.DetermineSize(this, mSize);
- return mSize;
- }
- set {
- if (value > 0) {
- SizeToString(value);
- }
- mSize = value;
- }
- }
-
- public override void WriteText( XSharp.Assembler.Assembler aAssembler, System.IO.TextWriter aOutput )
-{
- aOutput.Write(mMnemonic);
- aOutput.Write(" ");
- aOutput.Write(SizeToString(Size));
- if (!DestinationEmpty)
- {
- aOutput.Write(" ");
- aOutput.Write(this.GetDestinationAsString());
- }
- }
- }
-}
+namespace XSharp.Assembler.x86
+{
+ public abstract class InstructionWithDestinationAndSize : InstructionWithDestination, IInstructionWithSize {
+ public InstructionWithDestinationAndSize(string mnemonic = null) : base(mnemonic)
+ {
+ }
+
+ private byte mSize;
+ public byte Size {
+ get {
+ this.DetermineSize(this, mSize);
+ return mSize;
+ }
+ set {
+ if (value > 0) {
+ SizeToString(value);
+ }
+ mSize = value;
+ }
+ }
+
+ public override void WriteText( XSharp.Assembler.Assembler aAssembler, System.IO.TextWriter aOutput )
+{
+ aOutput.Write(mMnemonic);
+ aOutput.Write(" ");
+ if (DestinationIsIndirect)
+ aOutput.Write(SizeToString(Size));
+ if (!DestinationEmpty)
+ {
+ aOutput.Write(" ");
+ aOutput.Write(this.GetDestinationAsString());
+ }
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/InstructionWithDestinationAndSource.cs b/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/InstructionWithDestinationAndSource.cs
index 09151452..fdb8dcf7 100644
--- a/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/InstructionWithDestinationAndSource.cs
+++ b/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/InstructionWithDestinationAndSource.cs
@@ -36,6 +36,8 @@ public bool SourceIsIndirect {
set;
}
+ public bool SourceRequiresSize { get; set; }
+
public int? SourceDisplacement {
get;
set;
@@ -53,7 +55,8 @@ protected string GetSourceAsString() {
// throw new Exception("[Scale*index+base] style addressing not supported at the moment");
//}
if (SourceRef != null) {
- xDest = SourceRef.ToString();
+ SourceIsIndirect = true;
+ xDest = " rel "+SourceRef.ToString();
} else {
if (SourceReg != null) {
xDest = Registers.GetRegisterName(SourceReg.Value);
@@ -65,9 +68,16 @@ protected string GetSourceAsString() {
if (SourceDisplacement != null && SourceDisplacement != 0) {
xDest += (SourceDisplacement < 0 ? " - " : " + ") + Math.Abs(SourceDisplacement.Value);
}
- if (SourceIsIndirect) {
- return "[" + xDest + "]";
- } else {
+ if (SourceIsIndirect && SourceRequiresSize)
+ {
+ return SizeToString(64) + " [" + xDest + "]";
+ }
+ else if (SourceIsIndirect)
+ {
+ return " [" + xDest + "]"; ;
+ }
+ else
+ {
return xDest;
}
}
diff --git a/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/InstructionWithDestinationAndSourceAndSize.cs b/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/InstructionWithDestinationAndSourceAndSize.cs
index 0117569a..e4a62f8b 100644
--- a/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/InstructionWithDestinationAndSourceAndSize.cs
+++ b/source/XSharp/XSharp/Assembler/Gen1/x86/_Infra/InstructionWithDestinationAndSourceAndSize.cs
@@ -56,7 +56,7 @@ protected virtual void DetermineSize()
}
if ((SourceRef != null && !SourceIsIndirect) || (DestinationRef != null && !DestinationIsIndirect))
{
- Size = 32;
+ Size = 64;
return;
}
}
@@ -67,8 +67,7 @@ public override void WriteText(Assembler aAssembler, System.IO.TextWriter aOutpu
{
if (Size == 0)
{
- Size = 32;
- //Console.WriteLine("ERRROR no size set for Instruction - set to 4 InstructionWithDestinationAndSourceAndSize") ;
+ Size = 64;
}
aOutput.Write(mMnemonic);
diff --git a/source/XSharp/XSharp/Assembler/x86/Register.cs b/source/XSharp/XSharp/Assembler/x86/Register.cs
index ef6eea4c..5850505e 100644
--- a/source/XSharp/XSharp/Assembler/x86/Register.cs
+++ b/source/XSharp/XSharp/Assembler/x86/Register.cs
@@ -1,120 +1,126 @@
-using System;
-using System.Linq;
-
-namespace XSharp.x86
-{
- public class Register
- {
- public static class Names
- {
- public static readonly string[] Reg08 = "AH,AL,BH,BL,CH,CL,DH,DL".Split(',');
- public static readonly string[] Reg16 = "AX,BX,CX,DX".Split(',');
- public static readonly string[] Reg32 = "EAX,EBX,ECX,EDX,ESP,EBP,ESI,EDI".Split(',');
- }
-
- // These statics are not used much now but will be used even with NASM
- // and will become far important wtih binary assembler.
- public static readonly Register EAX = new Register("EAX");
-
- public static readonly Register EBX = new Register("EBX");
- public static readonly Register ECX = new Register("ECX");
- public static readonly Register EDX = new Register("EDX");
- public static readonly Register ESP = new Register("ESP");
- public static readonly Register EBP = new Register("EBP");
- public static readonly Register ESI = new Register("ESI");
-
- public static readonly Register EDI = new Register("EDI");
-
- //
- public static readonly Register AX = new Register("AX");
-
- public static readonly Register BX = new Register("BX");
- public static readonly Register CX = new Register("CX");
-
- public static readonly Register DX = new Register("DX");
-
- //
- public static readonly Register AH = new Register("AH");
-
- public static readonly Register AL = new Register("AL");
- public static readonly Register BH = new Register("BH");
- public static readonly Register BL = new Register("BL");
- public static readonly Register CH = new Register("CH");
- public static readonly Register CL = new Register("CL");
- public static readonly Register DH = new Register("DH");
- public static readonly Register DL = new Register("DL");
-
- public bool IsGenPurpose { get; }
- public string Name { get; }
- public int Size { get; }
-
- public Register(string aName)
- {
- Name = aName.ToUpper();
-
- //TODO Add special registers and leave IsGenPurpose = false
- if (Names.Reg32.Contains(Name))
- {
- IsGenPurpose = true;
- Size = 32;
- }
- else if (Names.Reg16.Contains(Name))
- {
- IsGenPurpose = true;
- Size = 16;
- }
- else if (Names.Reg08.Contains(Name))
- {
- IsGenPurpose = true;
- Size = 8;
- }
- else
- {
- throw new Exception(aName + " is not a recognized register name.");
- }
- }
-
- public bool CheckIs(string aValidRegs, bool throwException = false)
- {
- if (!(aValidRegs + ",").Contains(Name + ","))
- {
- if (throwException)
- {
- throw new Exception("Invalid register: {Name}.\r\nMust be one of: {aValidRegs}");
- }
-
- return false;
- }
- return true;
- }
-
- public void CheckIsDX()
- {
- CheckIs("DX", true);
- }
-
- public void CheckIsAccumulator()
- {
- CheckIs("EAX,AX,AL", true);
- }
-
- public bool IsReg08 => Names.Reg08.Contains(Name);
-
- public bool IsReg16 => Names.Reg16.Contains(Name);
-
- public bool IsReg32 => Names.Reg32.Contains(Name);
-
- public string RegSize => IsReg08
- ? "byte"
- : IsReg16
- ? "word"
- : IsReg32
- ? "dword"
- : throw new NotSupportedException("Unknown register size");
-
- public override string ToString()
- {
- return Name;
- }
- }
-}
+using System;
+using System.Linq;
+
+namespace XSharp.x86
+{
+ public class Register
+ {
+ public static class Names
+ {
+ public static readonly string[] Reg08 = "AH,AL,BH,BL,CH,CL,DH,DL".Split(',');
+ public static readonly string[] Reg16 = "AX,BX,CX,DX".Split(',');
+ public static readonly string[] Reg32 = "EAX,EBX,ECX,EDX,ESP,EBP,ESI,EDI".Split(',');
+ public static readonly string[] Reg64 = "RAX,RBX,RCX,RDX,RSP,RBP,RSI,RDI".Split(',');
+ }
+
+ // These statics are not used much now but will be used even with NASM
+ // and will become far important wtih binary assembler.
+ public static readonly Register EAX = new Register("EAX");
+
+ public static readonly Register EBX = new Register("EBX");
+ public static readonly Register ECX = new Register("ECX");
+ public static readonly Register EDX = new Register("EDX");
+ public static readonly Register ESP = new Register("ESP");
+ public static readonly Register EBP = new Register("EBP");
+ public static readonly Register ESI = new Register("ESI");
+
+ public static readonly Register EDI = new Register("EDI");
+
+ //
+ public static readonly Register AX = new Register("AX");
+
+ public static readonly Register BX = new Register("BX");
+ public static readonly Register CX = new Register("CX");
+
+ public static readonly Register DX = new Register("DX");
+
+ //
+ public static readonly Register AH = new Register("AH");
+
+ public static readonly Register AL = new Register("AL");
+ public static readonly Register BH = new Register("BH");
+ public static readonly Register BL = new Register("BL");
+ public static readonly Register CH = new Register("CH");
+ public static readonly Register CL = new Register("CL");
+ public static readonly Register DH = new Register("DH");
+ public static readonly Register DL = new Register("DL");
+
+ public bool IsGenPurpose { get; }
+ public string Name { get; }
+ public int Size { get; }
+
+ public Register(string aName)
+ {
+ Name = aName.ToUpper();
+
+ //TODO Add special registers and leave IsGenPurpose = false
+ if (Names.Reg64.Contains(Name))
+ {
+ IsGenPurpose = true;
+ Size = 64;
+ }
+ else if (Names.Reg32.Contains(Name))
+ {
+ IsGenPurpose = true;
+ Size = 32;
+ }
+ else if (Names.Reg16.Contains(Name))
+ {
+ IsGenPurpose = true;
+ Size = 16;
+ }
+ else if (Names.Reg08.Contains(Name))
+ {
+ IsGenPurpose = true;
+ Size = 8;
+ }
+ else
+ {
+ throw new Exception(aName + " is not a recognized register name.");
+ }
+ }
+
+ public bool CheckIs(string aValidRegs, bool throwException = false)
+ {
+ if (!(aValidRegs + ",").Contains(Name + ","))
+ {
+ if (throwException)
+ {
+ throw new Exception("Invalid register: {Name}.\r\nMust be one of: {aValidRegs}");
+ }
+
+ return false;
+ }
+ return true;
+ }
+
+ public void CheckIsDX()
+ {
+ CheckIs("DX", true);
+ }
+
+ public void CheckIsAccumulator()
+ {
+ CheckIs("EAX,AX,AL", true);
+ }
+
+ public bool IsReg08 => Names.Reg08.Contains(Name);
+
+ public bool IsReg16 => Names.Reg16.Contains(Name);
+
+ public bool IsReg32 => Names.Reg32.Contains(Name);
+
+ public string RegSize => IsReg08
+ ? "byte"
+ : IsReg16
+ ? "word"
+ : IsReg32
+ ? "dword"
+ : throw new NotSupportedException("Unknown register size");
+
+ public override string ToString()
+ {
+ return Name;
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Gen1/Parser.cs b/source/XSharp/XSharp/Gen1/Parser.cs
index 230fd0e4..ac939e68 100644
--- a/source/XSharp/XSharp/Gen1/Parser.cs
+++ b/source/XSharp/XSharp/Gen1/Parser.cs
@@ -1,391 +1,391 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace XSharp {
- ///
- /// Parser recognizes the following tokens:
- /// - _123 -> Number
- /// - _REG -> All registers
- /// - _REGADDR -> All 32-bit registers
- /// - 1 -> Number as well
- /// - _ABC -> Random label, used indirectly (ie, used as a field)
- /// - #_ABC -> Random label, used for the value (ie, pointer to the field)
- ///
- public class Parser {
- /// Index in of the first yet unconsumed character.
- protected int mStart = 0;
-
- /// Initial text provided as a constructor parameter.
- protected string mData;
-
- /// true if whitespace tokens should be kept and propagated to the next parsing
- /// stage.
- protected bool mIncludeWhiteSpace;
-
- /// true while every token encountered until so far by this parser are whitespace
- /// tokens.
- protected bool mAllWhitespace;
-
- /// true if the parser supports patterns recognition.
- protected bool mAllowPatterns;
-
- /// Tokens retrieved so far by the parser.
- protected TokenList mTokens;
-
- /// Get a list of tokens that has been built at class instanciation.
- public TokenList Tokens {
- get { return mTokens; }
- }
-
- protected static readonly char[] mComma = new char[] { ',' };
- protected static readonly char[] mSpace = new char[] { ' ' };
-
- public static string[] mKeywords = (
- "As,All"
- + ",BYTE"
- + ",CALL,CONST"
- + ",DWORD"
- + ",exit"
- + ",function"
- + ",goto"
- + ",IF,INTERRUPT,iret"
- + ",namespace"
- + ",PORT"
- + ",return,ret,REPEAT"
- + ",times"
- + ",var"
- + ",word,while"
- ).ToUpper().Split(mComma);
-
- public static readonly Dictionary Registers;
- public static readonly Dictionary RegistersAddr;
- public static readonly Dictionary Registers8;
- public static readonly Dictionary Registers16;
- public static readonly Dictionary Registers32;
- public static readonly Dictionary RegistersIdx;
- public static readonly string[] RegisterPatterns = "_REG,_REG8,_REG16,_REG32,_REGIDX,_REGADDR".Split(mComma);
-
- public static readonly string[] Delimiters = ",".Split(mSpace);
-
- // _.$ are AlphaNum. See comments in Parser
- // # is comment and literal, but could be reused when not first char
- // string[] is used instead of string because operators can be multi char, != >= etc
- public static readonly string[] Operators =
- "( ) () ! = != >= <= [ [- ] + - * : { } < > ?= ?& @ ~> <~ >> << ++ -- # +# & | ^".Split(mSpace);
-
- static Parser() {
- Registers8 = new Dictionary()
- {
- {"AL", XSRegisters.AL},
- {"AH", XSRegisters.AH},
- {"BL", XSRegisters.BL},
- {"BH", XSRegisters.BH},
- {"CL", XSRegisters.CL},
- {"CH", XSRegisters.CH},
- {"DL", XSRegisters.DL},
- {"DH", XSRegisters.DH},
- };
-
- Registers16 = new Dictionary()
- {
- {"AX", XSRegisters.AX},
- {"BX", XSRegisters.BX},
- {"CX", XSRegisters.CX},
- {"DX", XSRegisters.DX},
- };
-
- Registers32 = new Dictionary()
- {
- {"EAX", XSRegisters.EAX},
- {"EBX", XSRegisters.EBX},
- {"ECX", XSRegisters.ECX},
- {"EDX", XSRegisters.EDX},
- };
-
- RegistersIdx = new Dictionary()
- {
- {"ESI", XSRegisters.ESI},
- {"EDI", XSRegisters.EDI},
- {"ESP", XSRegisters.ESP},
- {"EBP", XSRegisters.EBP},
- };
-
- var xRegisters = new Dictionary();
- xRegisters.AddRange(Registers8);
- xRegisters.AddRange(Registers16);
- xRegisters.AddRange(Registers32);
- xRegisters.AddRange(RegistersIdx);
- Registers = xRegisters;
-
- var xRegistersAddr = new Dictionary();
- xRegistersAddr.AddRange(Registers32);
- xRegistersAddr.AddRange(RegistersIdx);
- RegistersAddr = xRegistersAddr;
- }
-
- /// Parse next token from currently parsed line, starting at given position and
- /// add the retrieved token at end of given token list.
- /// The token list where to add the newly recognized token.
- /// Line number for diagnostics and debugging purpose.
- /// The index in current source code line of the first not yet consumed
- /// character. On return this parameter will be updated to account for characters that would
- /// have been consumed.
- protected void NextToken(TokenList aList, ref int rPos) {
- #region Pattern Notes
-
- // All patterns start with _, this makes them reserved. User can use too, but at own risk of conflict.
- //
- // Wildcards
- // -_REG or ??X
- // -_REG8 or ?H,?L
- // -_REG16 or ?X
- // -_REG32 or E?X
- // - ? based ones are ugly and less clear
- // -_Keyword
- // -_ABC
- //
- //
- // Multiple Options (All caps only) - Registers only
- // Used to suport EAX,EBX - ie lists. But found out wasnt really needed. May add again later.
- //
- // -AX/AL - Conflict if we ever use /
- // -AX|AL - Conflict if we ever use |
- // -AX,AL - , is unlikely to ever be used as an operator and is logical as a separator. Method calls might use, but likely better to use a space
- // since we will only allow simple arguments, not compound.
- // -_REG:AX|AL - End terminator issue
- // -_REG[AX|AL] - Conflict with existing indirect access. Is indirect access always numeric? I think x86 has some register based ones too.
- //
- //
- // Specific: Register, Keyword, AlphaNum
- // -EAX
-
- #endregion
-
- string xString = null;
- char xChar1 = mData[mStart];
- var xToken = new Token();
-
- // Directives and literal assembler code.
- if (mAllWhitespace) {
- if (xChar1 == '!' || xChar1 == '/') {
- rPos = mData.Length; // This will account for the dummy whitespace at the end.
- xString = mData.Substring(mStart + 1, rPos - mStart - 1).Trim();
- // So ToString/Format wont generate error
- xString = xString.Replace("{", "{{");
- xString = xString.Replace("}", "}}");
-
- // Fix issue #15662 with string length check.
- // Fix issue #15663 with comparing from mData and not from xString anymore.
- if (xChar1 == '!') {
- // Literal assembler code.
- xToken.Type = TokenType.Line_LiteralAsm;
- } else if (xString.Length > 0) {
- char xChar2 = xString[0];
- xString = xString.Substring(1);
- if (xChar2 == '/') {
- xToken.Type = TokenType.Line_Comment;
- } else if (xChar2 == '!') {
- xToken.Type = TokenType.Line_Directive;
- }
- }
- }
- }
-
- if (xToken.Type == TokenType.Unknown) {
- xString = mData.Substring(mStart, rPos - mStart);
-
- if (string.IsNullOrWhiteSpace(xString) && xString.Length > 0) {
- xToken.Type = TokenType.WhiteSpace;
-
- } else if (xChar1 == '\'') {
- xToken.Type = TokenType.ValueString;
- xString = xString.Substring(1, xString.Length - 2);
-
- } else if (char.IsDigit(xChar1)) {
- xToken.Type = TokenType.ValueInt;
- if (xString.StartsWith("0x")) {
- xToken.SetIntValue(Convert.ToUInt32(xString, 16));
- } else {
- xToken.SetIntValue(uint.Parse(xString));
- }
- } else if (xChar1 == '$') {
- xToken.Type = TokenType.ValueInt;
- // Remove surrounding '
- xString = "0x" + xString.Substring(1);
- if (xString.StartsWith("0x")) {
- xToken.SetIntValue(Convert.ToUInt32(xString, 16));
- } else {
- xToken.SetIntValue(uint.Parse(xString));
- }
- } else if (IsAlphaNum(xChar1)) {
- // This must be after check for ValueInt
- string xUpper = xString.ToUpper();
-
- // Special parsing when in pattern mode. We recognize some special strings
- // which would otherwise be considered as simple AlphaNum token otherwise.
- if (mAllowPatterns) {
- if (RegisterPatterns.Contains(xUpper)) {
- xToken.Type = TokenType.Register;
- } else if (xUpper == "_KEYWORD") {
- xToken.Type = TokenType.Keyword;
- xString = null;
- } else if (xUpper == "_ABC") {
- xToken.Type = TokenType.AlphaNum;
- xString = null;
- } else if (xUpper == "_PCALL") {
- xString = null;
- xToken.Type = TokenType.Call;
- }
- }
-
- if (xToken.Type == TokenType.Unknown) {
- XSRegisters.Register xRegister;
- if (Registers.TryGetValue(xUpper, out xRegister)) {
- xToken.Type = TokenType.Register;
- xToken.SetRegister(xRegister);
- } else if (mKeywords.Contains(xUpper)) {
- xToken.Type = TokenType.Keyword;
- } else if (xString.Contains("(") && xString.Contains(")") && IsAlphaNum(xChar1)) {
- xToken.Type = TokenType.Call;
- } else {
- xToken.Type = TokenType.AlphaNum;
- }
- }
-
- } else if (Delimiters.Contains(xString)) {
- xToken.Type = TokenType.Delimiter;
- } else if (Operators.Contains(xString)) {
- xToken.Type = TokenType.Operator;
- }
- }
-
- xToken.RawValue = xString;
- xToken.SrcPosStart = mStart;
- xToken.SrcPosEnd = xToken.Type == TokenType.Call ? rPos : rPos - 1;
- if (mAllWhitespace && (xToken.Type != TokenType.WhiteSpace)) {
- mAllWhitespace = false;
- }
- mStart = xToken.Type == TokenType.Call ? rPos + 1 : rPos;
-
- if (mIncludeWhiteSpace || (xToken.Type != TokenType.WhiteSpace)) {
- aList.Add(xToken);
- }
- }
-
- protected enum CharType {
- WhiteSpace,
- Identifier,
- Symbol,
- String
- };
-
- protected bool IsAlphaNum(char aChar) {
- return char.IsLetterOrDigit(aChar) || aChar == '_' || aChar == '.' || aChar == '$';
- }
-
- /// Consume text that has been provided to the class constructor, splitting it into
- /// a list of tokens.
- /// Line number for diagnostics and debugging.
- /// The resulting tokens list.
- protected TokenList Parse() {
- // Save in comment, might be useful in future. Already had to dig it out of TFS once
- //var xRegex = new System.Text.RegularExpressions.Regex(@"(\W)");
-
- var xResult = new TokenList();
- CharType xLastCharType = CharType.WhiteSpace;
- CharType xCharType = CharType.WhiteSpace;
- int i = 0;
- for (i = 0; i < mData.Length; i++) {
- char xChar = mData[i];
- // Extract string literal (surrounded with single quote characters).
- if (xChar == '\'') {
- // Take data before the ' as a token.
- NextToken(xResult, ref i);
- // Now scan to the next ' taking into account escaped single quotes.
- bool escapedCharacter = false;
- for (i = i + 1; i < mData.Length; i++) {
- bool done = false;
- switch (mData[i]) {
- case '\'':
- if (!escapedCharacter) {
- done = true;
- }
- break;
- case '\\':
- escapedCharacter = !escapedCharacter;
- break;
- default:
- escapedCharacter = false;
- break;
- }
- if (done) {
- break;
- }
- }
- if (i == mData.Length) {
- throw new Exception("Unterminated string.");
- }
- i++;
- xCharType = CharType.String;
- } else if (xChar == '(') {
- for (i += 1; i < mData.Length; i++) {
- if (mData[i] == ')' && mData.LastIndexOf(")") <= i) {
- i++;
- NextToken(xResult, ref i);
- break;
- }
- }
- } else if (char.IsWhiteSpace(xChar)) {
- xCharType = CharType.WhiteSpace;
- } else if (IsAlphaNum(xChar)) {
- // _ and . were never likely to stand on their own. ie ESP _ 2 and ESP . 2 are never likely to be used.
- // Having them on their own required a lot of code
- // to treat them as a single unit where we did use them. So we treat them as AlphaNum.
- xCharType = CharType.Identifier;
- } else {
- xCharType = CharType.Symbol;
- }
-
- // i > 0 - Never do NewToken on first char. i = 0 is just a pass to get char and set lastchar.
- // But its faster as the second short circuit rather than a separate if.
- if ((xCharType != xLastCharType) && (0 < i)) {
- NextToken(xResult, ref i);
- }
-
- xLastCharType = xCharType;
- }
-
- // Last token
- if (mStart < mData.Length) {
- NextToken(xResult, ref i);
- }
-
- return xResult;
- }
-
- /// Create a new Parser instance and immediately consume the given
- /// string. On return the property is available for enumeration.
- /// The text to be parsed. WARNING : This is expected to be a single full line
- /// of text. The parser can be create with a special "pattern recognition" mode.
- ///
- /// True if is a pattern and thus the parsing
- /// should be performed specifically.
- /// At least one unrecognized token has been parsed.
- public Parser(string aData, bool aIncludeWhiteSpace, bool aAllowPatterns) {
- mData = aData;
- mIncludeWhiteSpace = aIncludeWhiteSpace;
- mAllowPatterns = aAllowPatterns;
- mAllWhitespace = true;
-
- mTokens = Parse();
- if (mTokens.Count(q => q.Type == TokenType.Unknown) > 0) {
- foreach (var xToken in mTokens) {
- if (xToken.Type == TokenType.Unknown) {
- throw new Exception(string.Format("Unknown token '{0}' found at {1}.", xToken.RawValue ?? "NULL", xToken.SrcPosStart));
- }
- }
- }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace XSharp {
+ ///
+ /// Parser recognizes the following tokens:
+ /// - _123 -> Number
+ /// - _REG -> All registers
+ /// - _REGADDR -> All 32-bit registers
+ /// - 1 -> Number as well
+ /// - _ABC -> Random label, used indirectly (ie, used as a field)
+ /// - #_ABC -> Random label, used for the value (ie, pointer to the field)
+ ///
+ public class Parser {
+ /// Index in of the first yet unconsumed character.
+ protected int mStart = 0;
+
+ /// Initial text provided as a constructor parameter.
+ protected string mData;
+
+ /// true if whitespace tokens should be kept and propagated to the next parsing
+ /// stage.
+ protected bool mIncludeWhiteSpace;
+
+ /// true while every token encountered until so far by this parser are whitespace
+ /// tokens.
+ protected bool mAllWhitespace;
+
+ /// true if the parser supports patterns recognition.
+ protected bool mAllowPatterns;
+
+ /// Tokens retrieved so far by the parser.
+ protected TokenList mTokens;
+
+ /// Get a list of tokens that has been built at class instanciation.
+ public TokenList Tokens {
+ get { return mTokens; }
+ }
+
+ protected static readonly char[] mComma = new char[] { ',' };
+ protected static readonly char[] mSpace = new char[] { ' ' };
+
+ public static string[] mKeywords = (
+ "As,All"
+ + ",BYTE"
+ + ",CALL,CONST"
+ + ",DWORD"
+ + ",exit"
+ + ",function"
+ + ",goto"
+ + ",IF,INTERRUPT,iret"
+ + ",namespace"
+ + ",PORT"
+ + ",return,ret,REPEAT"
+ + ",times"
+ + ",var"
+ + ",word,while"
+ ).ToUpper().Split(mComma);
+
+ public static readonly Dictionary Registers;
+ public static readonly Dictionary RegistersAddr;
+ public static readonly Dictionary Registers8;
+ public static readonly Dictionary Registers16;
+ public static readonly Dictionary Registers32;
+ public static readonly Dictionary RegistersIdx;
+ public static readonly string[] RegisterPatterns = "_REG,_REG8,_REG16,_REG32,_REGIDX,_REGADDR".Split(mComma);
+
+ public static readonly string[] Delimiters = ",".Split(mSpace);
+
+ // _.$ are AlphaNum. See comments in Parser
+ // # is comment and literal, but could be reused when not first char
+ // string[] is used instead of string because operators can be multi char, != >= etc
+ public static readonly string[] Operators =
+ "( ) () ! = != >= <= [ [- ] + - * : { } < > ?= ?& @ ~> <~ >> << ++ -- # +# & | ^".Split(mSpace);
+
+ static Parser() {
+ Registers8 = new Dictionary()
+ {
+ {"AL", XSRegisters.AL},
+ {"AH", XSRegisters.AH},
+ {"BL", XSRegisters.BL},
+ {"BH", XSRegisters.BH},
+ {"CL", XSRegisters.CL},
+ {"CH", XSRegisters.CH},
+ {"DL", XSRegisters.DL},
+ {"DH", XSRegisters.DH},
+ };
+
+ Registers16 = new Dictionary()
+ {
+ {"AX", XSRegisters.AX},
+ {"BX", XSRegisters.BX},
+ {"CX", XSRegisters.CX},
+ {"DX", XSRegisters.DX},
+ };
+
+ Registers32 = new Dictionary()
+ {
+ {"EAX", XSRegisters.RAX},
+ {"EBX", XSRegisters.RBX},
+ {"ECX", XSRegisters.RCX},
+ {"EDX", XSRegisters.RDX},
+ };
+
+ RegistersIdx = new Dictionary()
+ {
+ {"ESI", XSRegisters.RSI},
+ {"EDI", XSRegisters.RDI},
+ {"ESP", XSRegisters.RSP},
+ {"EBP", XSRegisters.RBP},
+ };
+
+ var xRegisters = new Dictionary();
+ xRegisters.AddRange(Registers8);
+ xRegisters.AddRange(Registers16);
+ xRegisters.AddRange(Registers32);
+ xRegisters.AddRange(RegistersIdx);
+ Registers = xRegisters;
+
+ var xRegistersAddr = new Dictionary();
+ xRegistersAddr.AddRange(Registers32);
+ xRegistersAddr.AddRange(RegistersIdx);
+ RegistersAddr = xRegistersAddr;
+ }
+
+ /// Parse next token from currently parsed line, starting at given position and
+ /// add the retrieved token at end of given token list.
+ /// The token list where to add the newly recognized token.
+ /// Line number for diagnostics and debugging purpose.
+ /// The index in current source code line of the first not yet consumed
+ /// character. On return this parameter will be updated to account for characters that would
+ /// have been consumed.
+ protected void NextToken(TokenList aList, ref int rPos) {
+ #region Pattern Notes
+
+ // All patterns start with _, this makes them reserved. User can use too, but at own risk of conflict.
+ //
+ // Wildcards
+ // -_REG or ??X
+ // -_REG8 or ?H,?L
+ // -_REG16 or ?X
+ // -_REG32 or E?X
+ // - ? based ones are ugly and less clear
+ // -_Keyword
+ // -_ABC
+ //
+ //
+ // Multiple Options (All caps only) - Registers only
+ // Used to suport EAX,EBX - ie lists. But found out wasnt really needed. May add again later.
+ //
+ // -AX/AL - Conflict if we ever use /
+ // -AX|AL - Conflict if we ever use |
+ // -AX,AL - , is unlikely to ever be used as an operator and is logical as a separator. Method calls might use, but likely better to use a space
+ // since we will only allow simple arguments, not compound.
+ // -_REG:AX|AL - End terminator issue
+ // -_REG[AX|AL] - Conflict with existing indirect access. Is indirect access always numeric? I think x86 has some register based ones too.
+ //
+ //
+ // Specific: Register, Keyword, AlphaNum
+ // -EAX
+
+ #endregion
+
+ string xString = null;
+ char xChar1 = mData[mStart];
+ var xToken = new Token();
+
+ // Directives and literal assembler code.
+ if (mAllWhitespace) {
+ if (xChar1 == '!' || xChar1 == '/') {
+ rPos = mData.Length; // This will account for the dummy whitespace at the end.
+ xString = mData.Substring(mStart + 1, rPos - mStart - 1).Trim();
+ // So ToString/Format wont generate error
+ xString = xString.Replace("{", "{{");
+ xString = xString.Replace("}", "}}");
+
+ // Fix issue #15662 with string length check.
+ // Fix issue #15663 with comparing from mData and not from xString anymore.
+ if (xChar1 == '!') {
+ // Literal assembler code.
+ xToken.Type = TokenType.Line_LiteralAsm;
+ } else if (xString.Length > 0) {
+ char xChar2 = xString[0];
+ xString = xString.Substring(1);
+ if (xChar2 == '/') {
+ xToken.Type = TokenType.Line_Comment;
+ } else if (xChar2 == '!') {
+ xToken.Type = TokenType.Line_Directive;
+ }
+ }
+ }
+ }
+
+ if (xToken.Type == TokenType.Unknown) {
+ xString = mData.Substring(mStart, rPos - mStart);
+
+ if (string.IsNullOrWhiteSpace(xString) && xString.Length > 0) {
+ xToken.Type = TokenType.WhiteSpace;
+
+ } else if (xChar1 == '\'') {
+ xToken.Type = TokenType.ValueString;
+ xString = xString.Substring(1, xString.Length - 2);
+
+ } else if (char.IsDigit(xChar1)) {
+ xToken.Type = TokenType.ValueInt;
+ if (xString.StartsWith("0x")) {
+ xToken.SetIntValue(Convert.ToUInt32(xString, 16));
+ } else {
+ xToken.SetIntValue(uint.Parse(xString));
+ }
+ } else if (xChar1 == '$') {
+ xToken.Type = TokenType.ValueInt;
+ // Remove surrounding '
+ xString = "0x" + xString.Substring(1);
+ if (xString.StartsWith("0x")) {
+ xToken.SetIntValue(Convert.ToUInt32(xString, 16));
+ } else {
+ xToken.SetIntValue(uint.Parse(xString));
+ }
+ } else if (IsAlphaNum(xChar1)) {
+ // This must be after check for ValueInt
+ string xUpper = xString.ToUpper();
+
+ // Special parsing when in pattern mode. We recognize some special strings
+ // which would otherwise be considered as simple AlphaNum token otherwise.
+ if (mAllowPatterns) {
+ if (RegisterPatterns.Contains(xUpper)) {
+ xToken.Type = TokenType.Register;
+ } else if (xUpper == "_KEYWORD") {
+ xToken.Type = TokenType.Keyword;
+ xString = null;
+ } else if (xUpper == "_ABC") {
+ xToken.Type = TokenType.AlphaNum;
+ xString = null;
+ } else if (xUpper == "_PCALL") {
+ xString = null;
+ xToken.Type = TokenType.Call;
+ }
+ }
+
+ if (xToken.Type == TokenType.Unknown) {
+ XSRegisters.Register xRegister;
+ if (Registers.TryGetValue(xUpper, out xRegister)) {
+ xToken.Type = TokenType.Register;
+ xToken.SetRegister(xRegister);
+ } else if (mKeywords.Contains(xUpper)) {
+ xToken.Type = TokenType.Keyword;
+ } else if (xString.Contains("(") && xString.Contains(")") && IsAlphaNum(xChar1)) {
+ xToken.Type = TokenType.Call;
+ } else {
+ xToken.Type = TokenType.AlphaNum;
+ }
+ }
+
+ } else if (Delimiters.Contains(xString)) {
+ xToken.Type = TokenType.Delimiter;
+ } else if (Operators.Contains(xString)) {
+ xToken.Type = TokenType.Operator;
+ }
+ }
+
+ xToken.RawValue = xString;
+ xToken.SrcPosStart = mStart;
+ xToken.SrcPosEnd = xToken.Type == TokenType.Call ? rPos : rPos - 1;
+ if (mAllWhitespace && (xToken.Type != TokenType.WhiteSpace)) {
+ mAllWhitespace = false;
+ }
+ mStart = xToken.Type == TokenType.Call ? rPos + 1 : rPos;
+
+ if (mIncludeWhiteSpace || (xToken.Type != TokenType.WhiteSpace)) {
+ aList.Add(xToken);
+ }
+ }
+
+ protected enum CharType {
+ WhiteSpace,
+ Identifier,
+ Symbol,
+ String
+ };
+
+ protected bool IsAlphaNum(char aChar) {
+ return char.IsLetterOrDigit(aChar) || aChar == '_' || aChar == '.' || aChar == '$';
+ }
+
+ /// Consume text that has been provided to the class constructor, splitting it into
+ /// a list of tokens.
+ /// Line number for diagnostics and debugging.
+ /// The resulting tokens list.
+ protected TokenList Parse() {
+ // Save in comment, might be useful in future. Already had to dig it out of TFS once
+ //var xRegex = new System.Text.RegularExpressions.Regex(@"(\W)");
+
+ var xResult = new TokenList();
+ CharType xLastCharType = CharType.WhiteSpace;
+ CharType xCharType = CharType.WhiteSpace;
+ int i = 0;
+ for (i = 0; i < mData.Length; i++) {
+ char xChar = mData[i];
+ // Extract string literal (surrounded with single quote characters).
+ if (xChar == '\'') {
+ // Take data before the ' as a token.
+ NextToken(xResult, ref i);
+ // Now scan to the next ' taking into account escaped single quotes.
+ bool escapedCharacter = false;
+ for (i = i + 1; i < mData.Length; i++) {
+ bool done = false;
+ switch (mData[i]) {
+ case '\'':
+ if (!escapedCharacter) {
+ done = true;
+ }
+ break;
+ case '\\':
+ escapedCharacter = !escapedCharacter;
+ break;
+ default:
+ escapedCharacter = false;
+ break;
+ }
+ if (done) {
+ break;
+ }
+ }
+ if (i == mData.Length) {
+ throw new Exception("Unterminated string.");
+ }
+ i++;
+ xCharType = CharType.String;
+ } else if (xChar == '(') {
+ for (i += 1; i < mData.Length; i++) {
+ if (mData[i] == ')' && mData.LastIndexOf(")") <= i) {
+ i++;
+ NextToken(xResult, ref i);
+ break;
+ }
+ }
+ } else if (char.IsWhiteSpace(xChar)) {
+ xCharType = CharType.WhiteSpace;
+ } else if (IsAlphaNum(xChar)) {
+ // _ and . were never likely to stand on their own. ie ESP _ 2 and ESP . 2 are never likely to be used.
+ // Having them on their own required a lot of code
+ // to treat them as a single unit where we did use them. So we treat them as AlphaNum.
+ xCharType = CharType.Identifier;
+ } else {
+ xCharType = CharType.Symbol;
+ }
+
+ // i > 0 - Never do NewToken on first char. i = 0 is just a pass to get char and set lastchar.
+ // But its faster as the second short circuit rather than a separate if.
+ if ((xCharType != xLastCharType) && (0 < i)) {
+ NextToken(xResult, ref i);
+ }
+
+ xLastCharType = xCharType;
+ }
+
+ // Last token
+ if (mStart < mData.Length) {
+ NextToken(xResult, ref i);
+ }
+
+ return xResult;
+ }
+
+ /// Create a new Parser instance and immediately consume the given
+ /// string. On return the property is available for enumeration.
+ /// The text to be parsed. WARNING : This is expected to be a single full line
+ /// of text. The parser can be create with a special "pattern recognition" mode.
+ ///
+ /// True if is a pattern and thus the parsing
+ /// should be performed specifically.
+ /// At least one unrecognized token has been parsed.
+ public Parser(string aData, bool aIncludeWhiteSpace, bool aAllowPatterns) {
+ mData = aData;
+ mIncludeWhiteSpace = aIncludeWhiteSpace;
+ mAllowPatterns = aAllowPatterns;
+ mAllWhitespace = true;
+
+ mTokens = Parse();
+ if (mTokens.Count(q => q.Type == TokenType.Unknown) > 0) {
+ foreach (var xToken in mTokens) {
+ if (xToken.Type == TokenType.Unknown) {
+ throw new Exception(string.Format("Unknown token '{0}' found at {1}.", xToken.RawValue ?? "NULL", xToken.SrcPosStart));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Gen1/TokenPatterns.cs b/source/XSharp/XSharp/Gen1/TokenPatterns.cs
index 9e548493..be38ec5b 100644
--- a/source/XSharp/XSharp/Gen1/TokenPatterns.cs
+++ b/source/XSharp/XSharp/Gen1/TokenPatterns.cs
@@ -1,1160 +1,1160 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using XSharp.Assembler.x86;
-
-namespace XSharp
-{
- /// This class is able to translate a single X# source code line into one or more
- /// target assembler source code and data lines. The class is a group of pattern each of
- /// which defines a transformation function from the X# syntax to the target assembler
- /// syntax.
- public class TokenPatterns {
- /// Describe a single pattern with its list of tokens that might include pattern
- /// reserved syntax token and a transformation function. For ease of search and performance
- /// an hashcode value is computed on the tokens list content and later used for searching
- /// a pattern matching an actual line of X# code source.
- protected class Pattern {
- public readonly TokenList Tokens;
- public readonly int Hash;
- public readonly CodeFunc Code;
- public readonly string PatternString;
-
- public Pattern(TokenList aTokens, CodeFunc aCode, string patternString) {
- Tokens = aTokens;
- Hash = aTokens.GetHashCode();
- Code = aCode;
- PatternString = patternString;
- }
- }
-
- /// The set of blocks for the currently assembled function. Each time we begin
- /// assembling a new function this blocks collection is reset to an empty state.
- protected Blocks mBlocks = new Blocks();
-
- protected class Blocks : List {
- protected int mCurrentLabelID = 0;
-
- public void Reset() {
- mCurrentLabelID = 0;
- }
-
- public Block Current() {
- return base[Count - 1];
- }
-
- public void Start(TokenList aTokens, bool aIsCollector) {
- var xBlock = new Block();
- mCurrentLabelID++;
- xBlock.LabelID = mCurrentLabelID;
- xBlock.StartTokens = aTokens;
-
- // Last because we use Current() above
- Add(xBlock);
- xBlock.ParentAssembler = Assembler.Assembler.CurrentInstance;
- new Assembler.Assembler();
- }
-
- public void End() {
- Assembler.Assembler.ClearCurrentInstance();
- RemoveAt(Count - 1);
- }
- }
- protected class Block {
- public TokenList StartTokens;
- public int LabelID;
-
- public Assembler.Assembler ParentAssembler;
-
- public void AddContentsToParentAssembler() {
- ParentAssembler.Instructions.AddRange(Assembler.Assembler.CurrentInstance.Instructions);
- }
- }
-
- protected string mFuncName = null;
- protected bool mFuncExitFound = false;
-
- public bool EmitUserComments = true;
- public delegate void CodeFunc(TokenList aTokens);
- protected List mPatterns = new List();
- protected bool mInIntHandler;
- protected string[] mCompareOps;
- protected List mCompares = new List();
-
- protected string mNamespace = null;
- protected string GetNamespace() {
- if (mNamespace == null) {
- throw new Exception("A namespace has not been defined.");
- }
- return mNamespace;
- }
-
- public TokenPatterns() {
- mCompareOps = "< > = != <= >= 0 !0".Split(' ');
- var xSizes = "byte , word , dword ".Split(',').ToList();
- // We must add this empty size so that we allow constructs where the size is not
- // explicitly defined in source code. For example : while eax < 0
- // otherwise we would have to write : while dword eax < 0
- xSizes.Add("");
- foreach (var xSize in xSizes) {
- foreach (var xComparison in mCompareOps) {
- // Skip 0 and !0
- if (!xComparison.Contains("0")) {
- mCompares.Add(xSize + "_REG " + xComparison + " 123");
- mCompares.Add(xSize + "_REG " + xComparison + " _REG");
- mCompares.Add(xSize + "_REG " + xComparison + " _REGADDR[1]");
- mCompares.Add(xSize + "_REG " + xComparison + " _REGADDR[-1]");
- mCompares.Add(xSize + "_REG " + xComparison + " _ABC");
- mCompares.Add(xSize + "_REG " + xComparison + " #_ABC");
- //
- mCompares.Add(xSize + "_REGADDR[1] " + xComparison + " 123");
- mCompares.Add(xSize + "_REGADDR[-1] " + xComparison + " 123");
- mCompares.Add(xSize + "_REGADDR[1] " + xComparison + " _REG");
- mCompares.Add(xSize + "_REGADDR[-1] " + xComparison + " _REG");
- mCompares.Add(xSize + "_REGADDR[1] " + xComparison + " #_ABC");
- mCompares.Add(xSize + "_REGADDR[-1] " + xComparison + " #_ABC");
- //
- mCompares.Add(xSize + "_ABC " + xComparison + " 123");
- mCompares.Add(xSize + "_ABC " + xComparison + " _REG");
- mCompares.Add(xSize + "_ABC " + xComparison + " #_ABC");
- }
- }
- }
-
- AddPatterns();
- }
-
- /// Builds a label that is suitable to denote a constant which name is given by the
- /// token.
- ///
- ///
- protected string ConstLabel(Token aToken) {
- return GroupLabel("Const_" + aToken);
- }
-
- /// Builds a label at namespace level having the given name.
- /// Local label name at namespace level.
- /// The label name
- protected string GroupLabel(string aLabel) {
- return GetNamespace() + "_" + aLabel;
- }
-
- /// Builds a label at function level having the given name.
- /// Local label name at function level.
- /// The label name
- protected string FuncLabel(string aLabel) {
- return GetNamespace() + "_" + mFuncName + "_" + aLabel;
- }
-
- /// Builds a label having the given name at current function block level.
- /// Local label name at function block level.
- /// The label name.
- protected string BlockLabel(string aLabel) {
- return FuncLabel("Block" + mBlocks.Current().LabelID + "_" + aLabel);
- }
-
- /// Build a label name for the given token. This method enforce the rule for .
- /// and .. prefixes and build the label at appropriate level.
- ///
- ///
- protected string GetLabel(Token aToken) {
- if ((aToken.Type != TokenType.AlphaNum) && !aToken.Matches("exit")) {
- throw new Exception("Label must be AlphaNum.");
- }
-
- string xValue = aToken.RawValue;
- if (!InFunctionBody) {
- if (xValue.StartsWith(".")) {
- return xValue.Substring(1);
- }
- return GroupLabel(xValue);
- } else {
- if (xValue.StartsWith("..")) {
- return xValue.Substring(2);
- } else if (xValue.StartsWith(".")) {
- return GroupLabel(xValue.Substring(1));
- }
- return FuncLabel(xValue);
- }
- }
-
- /// Get a flag that tell if we are in a function body or not. This is used by the
- /// assembler generator when end of source file is reached to make sure the last function
- /// or interrupt handler is properly closed (see issue #15666)
- internal bool InFunctionBody {
- get { return !string.IsNullOrEmpty(mFuncName); }
- }
-
- /// Start a new function having the given name. The current blocks collection is
- /// reset to an empty state and the function name is saved for later reuse in local to function
- /// labels' name construction.
- /// Function name.
- protected void StartFunc(string aName) {
- if (InFunctionBody) {
- throw new Exception(
- "Found a function/interrupt handler definition embedded inside another function/interrupt handler.");
- }
- mFuncName = aName;
- mFuncExitFound = false;
- mBlocks.Reset();
- }
-
- /// Terminate assembling current function. If a local to function exit label has not
- /// been explicitly defined a new one is automatically created. This is because some "return"
- /// keyword might have been used in function X# code. This keyword requires an exit label to
- /// be defined at function level. This method also automatically insert an IRET or RET instruction
- /// depending on whether the function is an interrupt handler or a standard function.
- protected void EndFunc() {
- if (null == mFuncName) {
- throw new Exception("Found a closing curly brace that doesn't match an opening curly brace.");
- }
- if (!mFuncExitFound) {
- XS.Label(GetNamespace() + "_" + mFuncName + "_Exit");
- }
- if (mInIntHandler) {
- XS.InterruptReturn();
- } else {
- // TODO: this shouldn't be here
- XS.Set("INTs_LastKnownAddress", GetNamespace() + "_" + mFuncName + "_Exit", destinationIsIndirect: true, size: XSRegisters.RegisterSize.Int32);
- XS.Return();
- }
- mFuncName = null;
- }
-
- protected string GetSimpleRef(Token aToken) {
- return GetLabel(aToken);
- }
-
- private static XSRegisters.RegisterSize GetSize(Token aToken) {
- return GetSize(aToken.RawValue);
- }
-
- private static XSRegisters.RegisterSize GetSize(string value) {
- switch (value) {
- case "byte":
- return XSRegisters.RegisterSize.Byte8;
- case "word":
- return XSRegisters.RegisterSize.Short16;
- case "dword":
- return XSRegisters.RegisterSize.Int32;
- default:
- throw new Exception($"Invalid size '{value}'");
- }
- }
-
- private static string GetSizeString(XSRegisters.RegisterSize size) {
- switch (size) {
- case XSRegisters.RegisterSize.Byte8:
- return "byte";
- case XSRegisters.RegisterSize.Short16:
- return "word";
- case XSRegisters.RegisterSize.Int32:
- return "dword";
- default:
- throw new ArgumentOutOfRangeException(nameof(size), size, null);
- }
- }
-
- protected string GetRef(List aTokens, ref int rIdx, bool onlySingleTokenRefs = false) {
- var xToken1 = aTokens[rIdx];
- Token xToken2 = null;
- if (rIdx + 1 < aTokens.Count
- && !onlySingleTokenRefs) {
- xToken2 = aTokens[rIdx + 1];
- }
- if (xToken1.Type == TokenType.Register) {
- if (xToken2 != null
- && xToken2.RawValue == "[") {
- if (aTokens[rIdx + 2].RawValue == "-") {
- rIdx += 5;
- return "[" + xToken1 + " - " + aTokens[rIdx - 2] + "]";
- }
- rIdx += 4;
- return "[" + xToken1 + " + " + aTokens[rIdx - 2] + "]";
- }
- rIdx += 1;
- return xToken1.RawValue;
- } else if (xToken1.Type == TokenType.AlphaNum) {
- rIdx += 1;
- return "[" + GetLabel(xToken1) + "]";
- } else if (xToken1.Type == TokenType.ValueInt) {
- rIdx += 1;
- return xToken1.RawValue;
- } else if (xToken1.Type == TokenType.Call) {
- rIdx += 1;
- return "@ret_on_stack@";
- } else if (xToken1.RawValue == "#") {
- rIdx += 2;
- return ConstLabel(xToken2);
- } else {
- throw new Exception("Cannot determine reference");
- }
- }
-
- protected ConditionalTestEnum GetJump(string aComparison, bool aInvert = false) {
- if (aInvert) {
- if (aComparison == "<") {
- aComparison = ">=";
- } else if (aComparison == ">") {
- aComparison = "<=";
- } else if (aComparison == "=") {
- aComparison = "!=";
- } else if (aComparison == "0") {
- // Same as JE, but implies intent in .asm better
- aComparison = "!0";
- } else if (aComparison == "!0") {
- // Same as JE, but implies intent in .asm better
- aComparison = "0";
- } else if (aComparison == "!=") {
- aComparison = "=";
- } else if (aComparison == "<=") {
- aComparison = ">";
- } else if (aComparison == ">=") {
- aComparison = "<";
- } else {
- throw new Exception("Unrecognized symbol in conditional: " + aComparison);
- }
- }
-
- if (aComparison == "<") {
- return ConditionalTestEnum.Below; // unsigned
- } else if (aComparison == ">") {
- return ConditionalTestEnum.Above; // unsigned
- } else if (aComparison == "=") {
- return ConditionalTestEnum.Equal;
- } else if (aComparison == "0") {
- // Same as JE, but implies intent in .asm better
- return ConditionalTestEnum.Zero;
- } else if (aComparison == "!=") {
- return ConditionalTestEnum.NotEqual;
- } else if (aComparison == "!0") {
- // Same as JNE, but implies intent in .asm better
- return ConditionalTestEnum.NotZero;
- } else if (aComparison == "<=") {
- return ConditionalTestEnum.BelowOrEqual; // unsigned
- } else if (aComparison == ">=") {
- return ConditionalTestEnum.AboveOrEqual; // unsigned
- } else {
- throw new Exception("Unrecognized symbol in conditional: " + aComparison);
- }
- }
-
- protected void HandleIf(TokenList aTokens, string xComparison) {
- string xLabel;
- var xLast = aTokens.Last();
- if (xLast.RawValue == "{") {
- mBlocks.Start(aTokens, false);
- XS.Jump(GetJump(xComparison, true), BlockLabel("End"));
- } else {
- if (xLast.Matches("return")) {
- xLabel = FuncLabel("Exit");
- } else {
- xLabel = GetLabel(xLast);
- }
-
- XS.Jump(GetJump(xComparison), xLabel);
- }
- }
-
- protected void AddPatterns() {
- AddPattern("! Mov EAX, 0", delegate (TokenList aTokens) {
- XS.LiteralCode(aTokens[0].RawValue);
- });
-
- AddPattern("// Comment", delegate (TokenList aTokens) {
- if (EmitUserComments) {
- string xValue = aTokens[0].RawValue;
- xValue = xValue.Replace("\"", "\\\"");
- XS.Comment(xValue);
- }
- });
-
- // The value function returns a token containing the comparison
- var xCompares = new Dictionary>();
- var xSizes = new[]
- {
- "", "byte", "word", "dword"
- };
- #region Handle all comparisons
- foreach (var xSize in xSizes) {
- foreach (var xComparison in mCompareOps) {
- var xComparisonToken = new Token();
- xComparisonToken.RawValue = xComparison;
- // Skip 0 and !0
- if (!xComparison.Contains("0")) {
- xCompares.Add(xSize + " _REG " + xComparison + " 123",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- XSRegisters.RegisterSize? xTypedSize = null;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xTypedSize = GetSize(tokenList[xOffset]);
- xOffset += 1;
- }
- XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].IntValue, size: xTypedSize);
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _REG " + xComparison + " _REG",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- XSRegisters.RegisterSize? xTypedSize = null;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xTypedSize = GetSize(tokenList[xOffset]);
- xOffset += 1;
- }
- XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].Register);
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _REG " + xComparison + " _REGADDR[1]",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xOffset += 1;
- }
- XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].Register, sourceDisplacement: (int)tokenList[xOffset + 3].IntValue);
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _REG " + xComparison + " _REGADDR[-1]",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xOffset += 1;
- }
- XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].Register, sourceDisplacement: -(int)tokenList[xOffset + 3].IntValue);
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _REG " + xComparison + " _ABC",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xOffset += 1;
- }
- XS.Compare(tokenList[xOffset + 0].Register, GetLabel(tokenList[xOffset + 2]), sourceIsIndirect: true);
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _REG " + xComparison + " #_ABC",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xOffset += 1;
- }
- XS.Compare(tokenList[xOffset + 0].Register, ConstLabel(tokenList[xOffset + 3]));
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _REGADDR[1] " + xComparison + " 123",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- XSRegisters.RegisterSize? xTypedSize = null;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xTypedSize = GetSize(tokenList[xOffset]);
- xOffset += 1;
- }
- XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 5].IntValue, destinationDisplacement: (int)tokenList[xOffset + 2].IntValue, size: xTypedSize);
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _REGADDR[-1] " + xComparison + " 123",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- XSRegisters.RegisterSize? xTypedSize = null;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xTypedSize = GetSize(tokenList[xOffset]);
- xOffset += 1;
- }
- XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].IntValue, destinationDisplacement: -(int)tokenList[xOffset + 1].IntValue, size: xTypedSize);
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _REGADDR[1] " + xComparison + " _REG",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xOffset += 1;
- }
- XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].Register, destinationDisplacement: (int)tokenList[xOffset + 1].IntValue);
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _REGADDR[-1] " + xComparison + " _REG",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xOffset += 1;
- }
- XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].Register, destinationDisplacement: -(int)tokenList[xOffset + 1].IntValue);
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _REGADDR[1] " + xComparison + " #_ABC",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- XSRegisters.RegisterSize? xTypedSize = null;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xTypedSize = GetSize(tokenList[xOffset]);
- xOffset += 1;
- }
- XS.Compare(tokenList[xOffset + 0].Register, ConstLabel(tokenList[xOffset + 2]), destinationDisplacement: (int)tokenList[xOffset + 1].IntValue, sourceIsIndirect: true, size: xTypedSize);
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _REGADDR[-1] " + xComparison + " #_ABC",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- XSRegisters.RegisterSize? xTypedSize = null;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xTypedSize = GetSize(tokenList[xOffset]);
- xOffset += 1;
- }
- XS.Compare(tokenList[xOffset + 0].Register, ConstLabel(tokenList[xOffset + 2]), destinationDisplacement: (int)tokenList[xOffset + 1].IntValue, size: xTypedSize);
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _ABC " + xComparison + " 123",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- XSRegisters.RegisterSize? xTypedSize = null;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xTypedSize = GetSize(tokenList[xOffset]);
- xOffset += 1;
- }
- XS.Compare(GetLabel(tokenList[xOffset + 0]), tokenList[xOffset + 2].IntValue, destinationIsIndirect: true, size: xTypedSize.GetValueOrDefault(XSRegisters.RegisterSize.Int32));
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _ABC " + xComparison + " _REG",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- if (tokenList[xOffset + 2].Type != TokenType.Register) {
- xOffset += 1;
- }
- XS.Compare(GetSimpleRef(tokenList[xOffset + 0]), tokenList[xOffset + 2].Register, destinationIsIndirect: true);
- return xComparisonToken;
- });
- xCompares.Add(xSize + " _ABC " + xComparison + " #_ABC",
- (tokenOffset, tokenList) => {
- var xOffset = tokenOffset;
- XSRegisters.RegisterSize? xTypedSize = null;
- if (tokenList[xOffset].Type != TokenType.Register) {
- xTypedSize = GetSize(tokenList[xOffset]);
- xOffset += 1;
- }
- XS.Compare(GetSimpleRef(tokenList[xOffset + 0]), ConstLabel(tokenList[xOffset + 3]), destinationIsIndirect: true, size: xTypedSize.GetValueOrDefault(XSRegisters.RegisterSize.Int32));
- return xComparisonToken;
- });
- }
- }
- }
- #endregion Handle all comparisons
- // Labels
- // Local and proc level are used most, so designed to make their syntax shortest.
- // Think of the dots like a directory, . is current group, .. is above that.
- // ..Name: - Global level. Emitted exactly as is.
- // .Name: - Group level. Group_Name
- // Name: - Function level. Group_ProcName_Name
-
- // The Exit label is a special one that is used as a target for the return instruction.
- // It deserve special handling.
- AddPattern("Exit:", delegate (TokenList aTokens) {
- XS.Label(GetLabel(aTokens[0]));
- mFuncExitFound = true;
- });
-
- // Regular label recognition.
- AddPattern("_ABC:", delegate (TokenList aTokens) {
- XS.Label(GetLabel(aTokens[0]));
- });
-
- AddPattern("Call _ABC", delegate (TokenList aTokens) {
- XS.Call(GetLabel(aTokens[1]));
- });
- AddPattern("_PCALL", delegate (TokenList aTokens) {
- if (aTokens.Count != 1
- || aTokens[0].Type != TokenType.Call) {
- throw new Exception("Error occured in parametrized call parsing");
- } else {
- List mparts = aTokens[0].RawValue.Remove(aTokens[0].RawValue.Length - 1).Split('(').ToList();
- if (mparts.Count < 2) {
- throw new Exception("Error occured in parametrized call parsing");
- }
- string fname = mparts[0];
- mparts.RemoveAt(0);
- aTokens[0].RawValue = String.Join("(", mparts).Trim();
- string val = "";
- int idx;
-
- var xParams = new List();
- int level = 0;
- foreach (char c in aTokens[0].RawValue) {
- switch (c) {
- case ',':
- if (level == 0) {
- xParams.Add(val.Trim());
- val = "";
- }
- break;
- case '(':
- level++;
- val += c;
- break;
- case ')':
- level--;
- val += c;
- break;
- default:
- val += c;
- break;
- }
- }
- if (!String.IsNullOrEmpty(val.Trim())) {
- xParams.Add(val);
- }
- if (level != 0) {
- throw new Exception("'(' occured without closing equivalent ')' in parametrized function call");
- }
-
- Parser xParser;
- xParams.Reverse();
- foreach (string p in xParams) {
- xParser = new Parser(p, false, false);
- idx = 0;
- val = GetRef(xParser.Tokens, ref idx);
- if (val != "@ret_on_stack@") {
- //XS.PushLiteral(val);
- throw new Exception();
- } else {
- //aAsm += GetPatternCode(xParser.Tokens).GetCode(false);
- throw new NotImplementedException("Didn't get converted yet!");
- }
- }
- XS.Call(GroupLabel(fname));
- }
- });
-
- AddPattern("Goto _ABC", delegate (TokenList aTokens) {
- XS.Jump(GetLabel(aTokens[1]));
- });
-
- // Defines a constant having the given name and initial value.
- AddPattern("const _ABC = 123", delegate (TokenList aTokens) {
- XS.Const(ConstLabel(aTokens[1]), aTokens[3].IntValue.ToString());
- });
-
- // Declare a double word variable having the given name and initialized to 0. The
- // variable is declared at namespace level.
- AddPattern("var _ABC", delegate (TokenList aTokens) {
- XS.DataMember(GetLabel(aTokens[1]));
- });
-
- // Declare a doubleword variable having the given name and an explicit initial value. The
- // variable is declared at namespace level.
- AddPattern("var _ABC = 123", delegate (TokenList aTokens) {
- XS.DataMember(GetLabel(aTokens[1]), aTokens[3].IntValue);
- });
-
- // Declare a textual variable having the given name and value. The variable is defined at
- // namespace level and a null terminating byte is automatically added after the textual
- // value.
- AddPattern("var _ABC = 'Text'", delegate (TokenList aTokens) {
- // Fix issue #15660 by using backquotes for string surrounding and escaping embedded
- // back quotes.
- XS.DataMember(GetLabel(aTokens[1]), EscapeBackQuotes(aTokens[3].RawValue));
- });
-
- // Declare a one-dimension array of bytes, words or doublewords. All members are initialized to 0.
- // _ABC is array name. 123 is the total number of items in the array.
- AddPattern(new string[]
- {
- "var _ABC byte[123]", "var _ABC word[123]", "var _ABC dword[123]"
- }, delegate (TokenList aTokens) {
- string xSize;
- if (aTokens[2].Matches("byte")) {
- xSize = "db";
- } else if (aTokens[2].Matches("word")) {
- xSize = "dw";
- } else if (aTokens[2].Matches("dword")) {
- xSize = "dd";
- } else {
- throw new Exception("Unknown size specified");
- }
- XS.DataMember(GetLabel(aTokens[1]), aTokens[4].IntValue, xSize, "0");
- });
-
- foreach (var xCompare in xCompares) {
- // 0 1 2 3 4
- AddPattern("while " + xCompare.Key + " {", delegate (TokenList aTokens) {
- mBlocks.Start(aTokens, false);
- XS.Label(BlockLabel("Begin"));
-
- Token xComparison = xCompare.Value(1, aTokens);
-
- XS.Jump(GetJump(xComparison.RawValue, true), BlockLabel("End"));
- });
- }
-
- foreach (var xTail in "goto _ABC|return|{".Split('|')) {
- // if 0 exit, etc
- foreach (var xComparison in mCompareOps) {
- AddPattern("if " + xComparison + " " + xTail, delegate (TokenList aTokens) {
- string xOp = aTokens[1].RawValue;
-
- // !0 is 2 tokens
- if (aTokens[1].RawValue + aTokens[2].RawValue == "!0") {
- xOp = "!0";
- }
-
- HandleIf(aTokens, xOp);
- });
- }
-
- // if reg = x exit, etc
- foreach (var xCompare in xCompares) {
- // 0 1 2 3 4
- AddPattern("if " + xCompare.Key + " " + xTail,
- delegate (TokenList aTokens) {
- Token xComparison = xCompare.Value(1, aTokens);
-
- HandleIf(aTokens, xComparison.RawValue);
- });
- }
- }
-
- AddPattern("_REG ?= 123", delegate (TokenList aTokens) {
- XS.Compare(aTokens[0].Register, aTokens[2].IntValue);
- });
- AddPattern("_REG ?= _ABC", delegate (TokenList aTokens) {
- XS.Compare(aTokens[0].Register, GetSimpleRef(aTokens[2]), sourceIsIndirect: true);
- });
- AddPattern("_REG ?= #_ABC", delegate (TokenList aTokens) {
- XS.Compare(aTokens[0].Register, ConstLabel(aTokens[2]));
- });
-
- AddPattern("_REG ?& 123", delegate (TokenList aTokens) {
- XS.Test(aTokens[0].Register, aTokens[2].IntValue);
- });
- AddPattern("_REG ?& _ABC", delegate (TokenList aTokens) {
- XS.Test(aTokens[0].Register, GetLabel(aTokens[2]), sourceIsIndirect: true);
- });
- AddPattern("_REG ?& #_ABC", delegate (TokenList aTokens) {
- XS.Test(aTokens[0].Register, GetLabel(aTokens[2]), sourceIsIndirect: true);
- });
-
- AddPattern("_REG ~> 123", delegate (TokenList aTokens) {
- XS.RotateRight(aTokens[0].Register, aTokens[2].IntValue);
- });
- AddPattern("_REG <~ 123", delegate (TokenList aTokens) {
- XS.RotateLeft(aTokens[0].Register, aTokens[2].IntValue);
- });
- AddPattern("_REG >> 123", delegate (TokenList aTokens) {
- if (aTokens[2].IntValue > 255) {
- throw new IndexOutOfRangeException("Value is too large to be used as bitcount!");
- }
- XS.ShiftRight(aTokens[0].Register, (byte)aTokens[2].IntValue);
- });
- AddPattern("_REG << 123", delegate (TokenList aTokens) {
- if (aTokens[2].IntValue > 255) {
- throw new IndexOutOfRangeException("Value is too large to be used as bitcount!");
- }
- XS.ShiftLeft(aTokens[0].Register, (byte)aTokens[2].IntValue);
- });
-
- AddPattern("_REG = 123", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[2].IntValue);
- });
- AddPattern("_REGADDR[1] = 123", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[5].IntValue, destinationDisplacement: (int)aTokens[2].IntValue, size: XSRegisters.RegisterSize.Int32);
- });
- AddPattern("_REGADDR[-1] = 123", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[5].IntValue, destinationDisplacement: -(int)aTokens[2].IntValue, size: XSRegisters.RegisterSize.Int32);
- });
-
- AddPattern("_REG = #_ABC", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, ConstLabel(aTokens[3]));
- });
- AddPattern("_REGADDR[1] = #_ABC", delegate (TokenList aTokens) {
- //XS.Set(RegisterSize.Int32, aTokens[0].IntValue, aTokens[2].IntValue, ConstLabel(aTokens[5]));
- throw new NotImplementedException("");
- });
- AddPattern("_REGADDR[-1] = #_ABC", delegate (TokenList aTokens) {
- var xFirst = GetSimpleRef(aTokens[0]);
- var xSecond = GetSimpleRef(aTokens[2]);
-
- //XS.SetLiteral("dword [" + xFirst + " - " + xSecond + "]", ConstLabel(aTokens[5]));
- throw new NotImplementedException("");
- });
-
- AddPattern("_REG = _REG", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[2].Register);
- });
- AddPattern("_REGADDR[1] = _REG", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[5].Register, destinationDisplacement: (int)aTokens[2].IntValue);
- });
- AddPattern("_REGADDR[-1] = _REG", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[5].Register, destinationDisplacement: -(int)aTokens[2].IntValue);
- });
- AddPattern("_REG = _REGADDR[1]", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[2].Register, sourceDisplacement: (int)aTokens[4].IntValue);
- });
- AddPattern("_REG = _REGADDR[-1]", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[2].Register, sourceDisplacement: -(int)aTokens[4].IntValue);
- });
-
- AddPattern("_REG = [_REG]", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[3].Register, sourceIsIndirect: true);
- });
- AddPattern("_REG = [_REG + 1]", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[3].Register, sourceDisplacement: (int?)aTokens[5].IntValue);
- });
- AddPattern("_REG = [_REG - 1]", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[3].Register, sourceDisplacement: -(int)aTokens[5].IntValue);
- });
- AddPattern("[_REG] = _REG", delegate (TokenList aTokens) {
- XS.Set(aTokens[1].Register, aTokens[4].Register, destinationIsIndirect: true);
- });
- AddPattern("[_REG + 1] = _REG", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[3].Register, destinationDisplacement: (int)aTokens[5].IntValue);
- });
- AddPattern("[_REG - 1] = _REG", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, aTokens[3].Register, destinationDisplacement: -(int)aTokens[5].IntValue);
- });
-
- AddPattern("_REG = _ABC", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, GetLabel(aTokens[2]), sourceIsIndirect: true);
- });
-
- // why not [var] like registers? Because its less frequent to access the ptr
- // and it is like a reg.. without [] to get the value...
- AddPattern("_REG = @_ABC", delegate (TokenList aTokens) {
- XS.Set(aTokens[0].Register, GetLabel(aTokens[3]));
- });
-
- AddPattern(new string[]
- {
- "Port[DX] = AL", "Port[DX] = AX", "Port[DX] = EAX"
- }, delegate (TokenList aTokens) {
- XS.WriteToPortDX(aTokens[5].Register);
- });
- AddPattern(new string[]
- {
- "AL = Port[DX]", "AX = Port[DX]", "EAX = Port[DX]"
- }, delegate (TokenList aTokens) {
- XS.ReadFromPortDX(aTokens[0].Register);
- });
-
- AddPattern("+123", delegate (TokenList aTokens) {
- XS.Push(aTokens[0].IntValue, size: XSRegisters.RegisterSize.Int32);
- });
- AddPattern(new string[]
- {
- "+123 as byte", "+123 as word", "+123 as dword"
- }, delegate (TokenList aTokens) {
- var xSize = GetSize(aTokens[1]);
- XS.Push(aTokens[1].IntValue, size: xSize);
- });
- AddPattern("+_REG", delegate (TokenList aTokens) {
- XS.Push(aTokens[1].Register);
- });
- AddPattern(new string[]
- {
- //0 1 2 3
- "+#_ABC", "+#_ABC as byte", "+#_ABC as word", "+#_ABC as dword"
- }, delegate (TokenList aTokens) {
- XSRegisters.RegisterSize xSize = XSRegisters.RegisterSize.Int32;
- if (aTokens.Count > 2) {
- xSize = GetSize(aTokens[3]);
- }
- XS.Push(ConstLabel(aTokens[1]), size: xSize);
- });
- AddPattern("+All", delegate (TokenList aTokens) {
- XS.PushAllRegisters();
- });
- AddPattern("-All", delegate (TokenList aTokens) {
- XS.PopAllRegisters();
- });
- AddPattern("-_REG", delegate (TokenList aTokens) {
- XS.Pop(aTokens[1].Register);
- });
-
- AddPattern("_ABC = _REG", delegate (TokenList aTokens) {
- XS.Set(GetLabel(aTokens[0]), aTokens[2].Register, destinationIsIndirect: true);
- });
- AddPattern("_ABC = #_ABC", delegate (TokenList aTokens) {
- XS.Set(GetLabel(aTokens[0]), ConstLabel(aTokens[3]), destinationIsIndirect: true, size: XSRegisters.RegisterSize.Int32);
- });
- AddPattern("_ABC = 123", delegate (TokenList aTokens) {
- XS.Set(GetLabel(aTokens[0]), aTokens[2].IntValue, destinationIsIndirect: true);
- });
- AddPattern(new string[]
- {
- "_ABC = 123 as byte", "_ABC = 123 as word", "_ABC = 123 as dword"
- }, delegate (TokenList aTokens) {
- XS.Set(GetLabel(aTokens[0]), aTokens[2].IntValue, size: GetSize(aTokens[4]));
- });
-
- AddPattern(new string[]
- {
- "_REG + 1",
- }, delegate (TokenList aTokens) {
- XS.Add(aTokens[0].Register, aTokens[2].IntValue);
- });
-
- AddPattern(new string[]
- {
- "_REG + _REG"
- }, delegate (TokenList aTokens) {
- XS.Add(aTokens[0].Register, aTokens[2].Register);
- });
- AddPattern(new string[]
- {
- "_REG - 1",
- }, delegate (TokenList aTokens) {
- XS.Sub(aTokens[0].Register, aTokens[2].IntValue);
- });
- AddPattern(new string[]
- {
- "_REG - _REG"
- }, delegate (TokenList aTokens) {
- XS.Sub(aTokens[0].Register, aTokens[2].Register);
- });
- AddPattern(new string[]
- {
- "_REG * 1",
- }, delegate (TokenList aTokens) {
- XS.IntegerMultiply(aTokens[0].Register, aTokens[2].IntValue);
- });
- AddPattern(new string[]
- {
- "_REG * _REG"
- }, delegate (TokenList aTokens) {
- XS.IntegerMultiply(aTokens[0].Register, aTokens[2].Register);
- });
- AddPattern("_REG++", delegate (TokenList aTokens) {
- XS.Increment(aTokens[0].Register);
- });
- AddPattern("_REG--", delegate (TokenList aTokens) {
- XS.Decrement(aTokens[0].Register);
- });
-
- AddPattern(new string[]
- {
- "_REG & 1",
- }, delegate (TokenList aTokens) {
- XS.And(aTokens[0].Register, aTokens[2].IntValue);
- });
- AddPattern(new string[]
- {
- "_REG & _REG"
- }, delegate (TokenList aTokens) {
- XS.And(aTokens[0].Register, aTokens[2].Register);
- });
- AddPattern(new string[]
- {
- "_REG | 1",
- }, delegate (TokenList aTokens) {
- XS.Or(aTokens[0].Register, aTokens[2].IntValue);
- });
- AddPattern(new string[]
- {
- "_REG | _REG"
- }, delegate (TokenList aTokens) {
- XS.Or(aTokens[0].Register, aTokens[2].Register);
- });
- AddPattern(new string[]
- {
- "_REG ^ 1",
- }, delegate (TokenList aTokens) {
- XS.Xor(aTokens[0].Register, aTokens[2].IntValue);
- });
- AddPattern(new string[]
- {
- "_REG ^ _REG"
- }, delegate (TokenList aTokens) {
- XS.Xor(aTokens[0].Register, aTokens[2].Register);
- });
-
- // End block. This handle both terminating a standard block as well as a function or an
- // interrupt handler.
- AddPattern("}", delegate (TokenList aTokens) {
- if (mBlocks.Count == 0) {
- EndFunc();
- } else {
- var xBlock = mBlocks.Current();
- var xToken1 = xBlock.StartTokens[0];
- if (xToken1.Matches("repeat")) {
- var xCount = xBlock.StartTokens[1].IntValue;
- for (var i = 1; i <= xCount; i++) {
- xBlock.AddContentsToParentAssembler();
- }
- } else if (xToken1.Matches("while")) {
- XS.Jump(BlockLabel("Begin"));
- XS.Label(BlockLabel("End"));
- xBlock.AddContentsToParentAssembler();
- } else if (xToken1.Matches("if")) {
- XS.Label(BlockLabel("End"));
- xBlock.AddContentsToParentAssembler();
- } else {
- throw new Exception("Unknown block starter.");
- }
- mBlocks.End();
- }
- });
-
- AddPattern("namespace _ABC", delegate (TokenList aTokens) {
- mNamespace = aTokens[1].RawValue;
- });
-
- AddPattern("Return", delegate {
- XS.Jump(FuncLabel("Exit"));
- });
-
- AddPattern("Repeat 4 times {", delegate (TokenList aTokens) {
- mBlocks.Start(aTokens, true);
- });
-
- AddPattern("Interrupt _ABC {", delegate (TokenList aTokens) {
- StartFunc(aTokens[1].RawValue);
- mInIntHandler = true;
- XS.Label(GetNamespace() + "_" + aTokens[1].RawValue);
- });
-
- // This needs to be different from return.
- // return jumps to exit, ret does raw x86 ret
- AddPattern("Ret", delegate (TokenList aTokens) {
- XS.Return();
- });
- AddPattern("IRet", delegate (TokenList aTokens) {
- XS.InterruptReturn();
- });
-
- AddPattern("Function _ABC {", delegate (TokenList aTokens) {
- StartFunc(aTokens[1].RawValue);
- mInIntHandler = false;
- XS.Label(GetNamespace() + "_" + aTokens[1].RawValue);
- });
-
- AddPattern("Checkpoint 'Text'", delegate (TokenList aTokens) {
- // This method emits a lot of ASM, but thats what we want becuase
- // at this point we need ASM as simple as possible and completely transparent.
- // No stack changes, no register mods, no calls, no jumps, etc.
-
- // TODO: Add an option on the debug project properties to turn this off.
- // Also see WriteDebugVideo in CosmosAssembler.cs
- var xPreBootLogging = true;
- if (xPreBootLogging) {
- UInt32 xVideo = 0xB8000;
- for (UInt32 i = xVideo; i < xVideo + 80 * 2; i = i + 2) {
- XS.SetByte(i, 0);
- XS.SetByte(i + 1, 2);
- }
-
- foreach (var xChar in aTokens[1].RawValue) {
- XS.SetByte(xVideo, (byte)xChar);
- xVideo = xVideo + 2;
- }
- }
- });
- }
-
- /// Fix issue #15660. This method escapes double quotes in the candidate string.
- /// The string to be sanitized.
- /// The original string with escaped double quotes.
- private static string EscapeBackQuotes(string from) {
- StringBuilder builder = new StringBuilder();
- bool sanitized = false;
- bool escaped = false;
- foreach (char scannedCharacter in from) {
- switch (scannedCharacter) {
- case '\\':
- escaped = !escaped;
- break;
- case '`':
- if (!escaped) {
- sanitized = true;
- builder.Append('\\');
- }
- escaped = false;
- break;
- default:
- escaped = false;
- break;
- }
- builder.Append(scannedCharacter);
- }
- return (sanitized) ? builder.ToString() : from;
- }
-
- protected Pattern FindMatch(TokenList aTokens) {
- int xHash = aTokens.GetPatternHashCode();
-
- // Get a list of matching hashes, but then we have to
- // search for exact pattern match because it is possible
- // to have duplicate hashes. Hashes just provide us a quick way
- // to reduce the search.
- foreach (var xPattern in mPatterns.Where(q => q.Hash == xHash)) {
- if (xPattern.Tokens.PatternMatches(aTokens)) {
- return xPattern;
- }
- }
- return null;
- }
-
- public bool GetPatternCode(TokenList aTokens) {
- var xPattern = FindMatch(aTokens);
- if (xPattern == null) {
- return false;
- }
-
- xPattern.Code(aTokens);
-
- //// Apply {0} etc into string
- //// This happens twice for block code, but its ok because the first pass
- //// strips out all tags.
- //for (int i = 0; i < xResult.Code.Count; i++) {
- // xResult.Code[i] = string.Format(xResult.Code[i], aTokens.ToArray());
- //}
- return true;
- }
-
- public void Assemble(string aLine) {
- var xParser = new Parser(aLine, false, false);
- var xTokens = xParser.Tokens;
-
- if (GetPatternCode(xTokens) == false) {
- if (xTokens.Count == 0) {
- throw new Exception("Parsing error: " + aLine);
- }
-
- var xFirst = xTokens[0];
- var xLast = xTokens[xTokens.Count - 1];
-
- // Find match and emit X#
- if (xTokens.Count == 2
- && xFirst.Type == TokenType.AlphaNum
- && xLast.Matches("()")) {
- // () could be handled by pattern, but best to keep in one place for future
- //xResult += "Call " + GroupLabel(aTokens[0].Value);
- XS.Call(GroupLabel(xTokens[0].RawValue));
- }
- }
- }
-
- /// Register a single pattern with its associated transformation handler.
- /// A single line of X# code that define the pattern optionally using
- /// pattern reserved syntax.
- /// The associated code transformation handler.
- protected void AddPattern(string aPattern, CodeFunc aCode) {
- Parser xParser = null;
- try {
- xParser = new Parser(aPattern, false, true);
- } catch (Exception e) {
- throw new Exception(string.Format("Invalid pattern '{0}'", aPattern ?? "NULL"), e);
- }
- var xPattern = new Pattern(xParser.Tokens, aCode, aPattern);
- mPatterns.Add(xPattern);
- }
-
- /// Register a collection of patterns that share a single transformation handler.
- ///
- /// A collection of X# lines of code. Each line of code define a
- /// pattern optionally using the pattern reserved syntax.
- /// The code transformation handler that is common abmongst all the
- /// patterns from the collection.
- protected void AddPattern(string[] aPatterns, CodeFunc aCode) {
- foreach (var xPattern in aPatterns) {
- AddPattern(xPattern, aCode);
- }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using XSharp.Assembler.x86;
+
+namespace XSharp
+{
+ /// This class is able to translate a single X# source code line into one or more
+ /// target assembler source code and data lines. The class is a group of pattern each of
+ /// which defines a transformation function from the X# syntax to the target assembler
+ /// syntax.
+ public class TokenPatterns {
+ /// Describe a single pattern with its list of tokens that might include pattern
+ /// reserved syntax token and a transformation function. For ease of search and performance
+ /// an hashcode value is computed on the tokens list content and later used for searching
+ /// a pattern matching an actual line of X# code source.
+ protected class Pattern {
+ public readonly TokenList Tokens;
+ public readonly int Hash;
+ public readonly CodeFunc Code;
+ public readonly string PatternString;
+
+ public Pattern(TokenList aTokens, CodeFunc aCode, string patternString) {
+ Tokens = aTokens;
+ Hash = aTokens.GetHashCode();
+ Code = aCode;
+ PatternString = patternString;
+ }
+ }
+
+ /// The set of blocks for the currently assembled function. Each time we begin
+ /// assembling a new function this blocks collection is reset to an empty state.
+ protected Blocks mBlocks = new Blocks();
+
+ protected class Blocks : List {
+ protected int mCurrentLabelID = 0;
+
+ public void Reset() {
+ mCurrentLabelID = 0;
+ }
+
+ public Block Current() {
+ return base[Count - 1];
+ }
+
+ public void Start(TokenList aTokens, bool aIsCollector) {
+ var xBlock = new Block();
+ mCurrentLabelID++;
+ xBlock.LabelID = mCurrentLabelID;
+ xBlock.StartTokens = aTokens;
+
+ // Last because we use Current() above
+ Add(xBlock);
+ xBlock.ParentAssembler = Assembler.Assembler.CurrentInstance;
+ new Assembler.Assembler();
+ }
+
+ public void End() {
+ Assembler.Assembler.ClearCurrentInstance();
+ RemoveAt(Count - 1);
+ }
+ }
+ protected class Block {
+ public TokenList StartTokens;
+ public int LabelID;
+
+ public Assembler.Assembler ParentAssembler;
+
+ public void AddContentsToParentAssembler() {
+ ParentAssembler.Instructions.AddRange(Assembler.Assembler.CurrentInstance.Instructions);
+ }
+ }
+
+ protected string mFuncName = null;
+ protected bool mFuncExitFound = false;
+
+ public bool EmitUserComments = true;
+ public delegate void CodeFunc(TokenList aTokens);
+ protected List mPatterns = new List();
+ protected bool mInIntHandler;
+ protected string[] mCompareOps;
+ protected List mCompares = new List();
+
+ protected string mNamespace = null;
+ protected string GetNamespace() {
+ if (mNamespace == null) {
+ throw new Exception("A namespace has not been defined.");
+ }
+ return mNamespace;
+ }
+
+ public TokenPatterns() {
+ mCompareOps = "< > = != <= >= 0 !0".Split(' ');
+ var xSizes = "byte , word , dword ".Split(',').ToList();
+ // We must add this empty size so that we allow constructs where the size is not
+ // explicitly defined in source code. For example : while eax < 0
+ // otherwise we would have to write : while dword eax < 0
+ xSizes.Add("");
+ foreach (var xSize in xSizes) {
+ foreach (var xComparison in mCompareOps) {
+ // Skip 0 and !0
+ if (!xComparison.Contains("0")) {
+ mCompares.Add(xSize + "_REG " + xComparison + " 123");
+ mCompares.Add(xSize + "_REG " + xComparison + " _REG");
+ mCompares.Add(xSize + "_REG " + xComparison + " _REGADDR[1]");
+ mCompares.Add(xSize + "_REG " + xComparison + " _REGADDR[-1]");
+ mCompares.Add(xSize + "_REG " + xComparison + " _ABC");
+ mCompares.Add(xSize + "_REG " + xComparison + " #_ABC");
+ //
+ mCompares.Add(xSize + "_REGADDR[1] " + xComparison + " 123");
+ mCompares.Add(xSize + "_REGADDR[-1] " + xComparison + " 123");
+ mCompares.Add(xSize + "_REGADDR[1] " + xComparison + " _REG");
+ mCompares.Add(xSize + "_REGADDR[-1] " + xComparison + " _REG");
+ mCompares.Add(xSize + "_REGADDR[1] " + xComparison + " #_ABC");
+ mCompares.Add(xSize + "_REGADDR[-1] " + xComparison + " #_ABC");
+ //
+ mCompares.Add(xSize + "_ABC " + xComparison + " 123");
+ mCompares.Add(xSize + "_ABC " + xComparison + " _REG");
+ mCompares.Add(xSize + "_ABC " + xComparison + " #_ABC");
+ }
+ }
+ }
+
+ AddPatterns();
+ }
+
+ /// Builds a label that is suitable to denote a constant which name is given by the
+ /// token.
+ ///
+ ///
+ protected string ConstLabel(Token aToken) {
+ return GroupLabel("Const_" + aToken);
+ }
+
+ /// Builds a label at namespace level having the given name.
+ /// Local label name at namespace level.
+ /// The label name
+ protected string GroupLabel(string aLabel) {
+ return GetNamespace() + "_" + aLabel;
+ }
+
+ /// Builds a label at function level having the given name.
+ /// Local label name at function level.
+ /// The label name
+ protected string FuncLabel(string aLabel) {
+ return GetNamespace() + "_" + mFuncName + "_" + aLabel;
+ }
+
+ /// Builds a label having the given name at current function block level.
+ /// Local label name at function block level.
+ /// The label name.
+ protected string BlockLabel(string aLabel) {
+ return FuncLabel("Block" + mBlocks.Current().LabelID + "_" + aLabel);
+ }
+
+ /// Build a label name for the given token. This method enforce the rule for .
+ /// and .. prefixes and build the label at appropriate level.
+ ///
+ ///
+ protected string GetLabel(Token aToken) {
+ if ((aToken.Type != TokenType.AlphaNum) && !aToken.Matches("exit")) {
+ throw new Exception("Label must be AlphaNum.");
+ }
+
+ string xValue = aToken.RawValue;
+ if (!InFunctionBody) {
+ if (xValue.StartsWith(".")) {
+ return xValue.Substring(1);
+ }
+ return GroupLabel(xValue);
+ } else {
+ if (xValue.StartsWith("..")) {
+ return xValue.Substring(2);
+ } else if (xValue.StartsWith(".")) {
+ return GroupLabel(xValue.Substring(1));
+ }
+ return FuncLabel(xValue);
+ }
+ }
+
+ /// Get a flag that tell if we are in a function body or not. This is used by the
+ /// assembler generator when end of source file is reached to make sure the last function
+ /// or interrupt handler is properly closed (see issue #15666)
+ internal bool InFunctionBody {
+ get { return !string.IsNullOrEmpty(mFuncName); }
+ }
+
+ /// Start a new function having the given name. The current blocks collection is
+ /// reset to an empty state and the function name is saved for later reuse in local to function
+ /// labels' name construction.
+ /// Function name.
+ protected void StartFunc(string aName) {
+ if (InFunctionBody) {
+ throw new Exception(
+ "Found a function/interrupt handler definition embedded inside another function/interrupt handler.");
+ }
+ mFuncName = aName;
+ mFuncExitFound = false;
+ mBlocks.Reset();
+ }
+
+ /// Terminate assembling current function. If a local to function exit label has not
+ /// been explicitly defined a new one is automatically created. This is because some "return"
+ /// keyword might have been used in function X# code. This keyword requires an exit label to
+ /// be defined at function level. This method also automatically insert an IRET or RET instruction
+ /// depending on whether the function is an interrupt handler or a standard function.
+ protected void EndFunc() {
+ if (null == mFuncName) {
+ throw new Exception("Found a closing curly brace that doesn't match an opening curly brace.");
+ }
+ if (!mFuncExitFound) {
+ XS.Label(GetNamespace() + "_" + mFuncName + "_Exit");
+ }
+ if (mInIntHandler) {
+ XS.InterruptReturn();
+ } else {
+ // TODO: this shouldn't be here
+ XS.Set("INTs_LastKnownAddress", GetNamespace() + "_" + mFuncName + "_Exit", destinationIsIndirect: true, size: XSRegisters.RegisterSize.Long64);
+ XS.Return();
+ }
+ mFuncName = null;
+ }
+
+ protected string GetSimpleRef(Token aToken) {
+ return GetLabel(aToken);
+ }
+
+ private static XSRegisters.RegisterSize GetSize(Token aToken) {
+ return GetSize(aToken.RawValue);
+ }
+
+ private static XSRegisters.RegisterSize GetSize(string value) {
+ switch (value) {
+ case "byte":
+ return XSRegisters.RegisterSize.Byte8;
+ case "word":
+ return XSRegisters.RegisterSize.Short16;
+ case "dword":
+ return XSRegisters.RegisterSize.Int32;
+ default:
+ throw new Exception($"Invalid size '{value}'");
+ }
+ }
+
+ private static string GetSizeString(XSRegisters.RegisterSize size) {
+ switch (size) {
+ case XSRegisters.RegisterSize.Byte8:
+ return "byte";
+ case XSRegisters.RegisterSize.Short16:
+ return "word";
+ case XSRegisters.RegisterSize.Int32:
+ return "dword";
+ default:
+ throw new ArgumentOutOfRangeException(nameof(size), size, null);
+ }
+ }
+
+ protected string GetRef(List aTokens, ref int rIdx, bool onlySingleTokenRefs = false) {
+ var xToken1 = aTokens[rIdx];
+ Token xToken2 = null;
+ if (rIdx + 1 < aTokens.Count
+ && !onlySingleTokenRefs) {
+ xToken2 = aTokens[rIdx + 1];
+ }
+ if (xToken1.Type == TokenType.Register) {
+ if (xToken2 != null
+ && xToken2.RawValue == "[") {
+ if (aTokens[rIdx + 2].RawValue == "-") {
+ rIdx += 5;
+ return "[" + xToken1 + " - " + aTokens[rIdx - 2] + "]";
+ }
+ rIdx += 4;
+ return "[" + xToken1 + " + " + aTokens[rIdx - 2] + "]";
+ }
+ rIdx += 1;
+ return xToken1.RawValue;
+ } else if (xToken1.Type == TokenType.AlphaNum) {
+ rIdx += 1;
+ return "[" + GetLabel(xToken1) + "]";
+ } else if (xToken1.Type == TokenType.ValueInt) {
+ rIdx += 1;
+ return xToken1.RawValue;
+ } else if (xToken1.Type == TokenType.Call) {
+ rIdx += 1;
+ return "@ret_on_stack@";
+ } else if (xToken1.RawValue == "#") {
+ rIdx += 2;
+ return ConstLabel(xToken2);
+ } else {
+ throw new Exception("Cannot determine reference");
+ }
+ }
+
+ protected ConditionalTestEnum GetJump(string aComparison, bool aInvert = false) {
+ if (aInvert) {
+ if (aComparison == "<") {
+ aComparison = ">=";
+ } else if (aComparison == ">") {
+ aComparison = "<=";
+ } else if (aComparison == "=") {
+ aComparison = "!=";
+ } else if (aComparison == "0") {
+ // Same as JE, but implies intent in .asm better
+ aComparison = "!0";
+ } else if (aComparison == "!0") {
+ // Same as JE, but implies intent in .asm better
+ aComparison = "0";
+ } else if (aComparison == "!=") {
+ aComparison = "=";
+ } else if (aComparison == "<=") {
+ aComparison = ">";
+ } else if (aComparison == ">=") {
+ aComparison = "<";
+ } else {
+ throw new Exception("Unrecognized symbol in conditional: " + aComparison);
+ }
+ }
+
+ if (aComparison == "<") {
+ return ConditionalTestEnum.Below; // unsigned
+ } else if (aComparison == ">") {
+ return ConditionalTestEnum.Above; // unsigned
+ } else if (aComparison == "=") {
+ return ConditionalTestEnum.Equal;
+ } else if (aComparison == "0") {
+ // Same as JE, but implies intent in .asm better
+ return ConditionalTestEnum.Zero;
+ } else if (aComparison == "!=") {
+ return ConditionalTestEnum.NotEqual;
+ } else if (aComparison == "!0") {
+ // Same as JNE, but implies intent in .asm better
+ return ConditionalTestEnum.NotZero;
+ } else if (aComparison == "<=") {
+ return ConditionalTestEnum.BelowOrEqual; // unsigned
+ } else if (aComparison == ">=") {
+ return ConditionalTestEnum.AboveOrEqual; // unsigned
+ } else {
+ throw new Exception("Unrecognized symbol in conditional: " + aComparison);
+ }
+ }
+
+ protected void HandleIf(TokenList aTokens, string xComparison) {
+ string xLabel;
+ var xLast = aTokens.Last();
+ if (xLast.RawValue == "{") {
+ mBlocks.Start(aTokens, false);
+ XS.Jump(GetJump(xComparison, true), BlockLabel("End"));
+ } else {
+ if (xLast.Matches("return")) {
+ xLabel = FuncLabel("Exit");
+ } else {
+ xLabel = GetLabel(xLast);
+ }
+
+ XS.Jump(GetJump(xComparison), xLabel);
+ }
+ }
+
+ protected void AddPatterns() {
+ AddPattern("! Mov EAX, 0", delegate (TokenList aTokens) {
+ XS.LiteralCode(aTokens[0].RawValue);
+ });
+
+ AddPattern("// Comment", delegate (TokenList aTokens) {
+ if (EmitUserComments) {
+ string xValue = aTokens[0].RawValue;
+ xValue = xValue.Replace("\"", "\\\"");
+ XS.Comment(xValue);
+ }
+ });
+
+ // The value function returns a token containing the comparison
+ var xCompares = new Dictionary>();
+ var xSizes = new[]
+ {
+ "", "byte", "word", "dword"
+ };
+ #region Handle all comparisons
+ foreach (var xSize in xSizes) {
+ foreach (var xComparison in mCompareOps) {
+ var xComparisonToken = new Token();
+ xComparisonToken.RawValue = xComparison;
+ // Skip 0 and !0
+ if (!xComparison.Contains("0")) {
+ xCompares.Add(xSize + " _REG " + xComparison + " 123",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ XSRegisters.RegisterSize? xTypedSize = null;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xTypedSize = GetSize(tokenList[xOffset]);
+ xOffset += 1;
+ }
+ XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].IntValue, size: xTypedSize);
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _REG " + xComparison + " _REG",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ XSRegisters.RegisterSize? xTypedSize = null;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xTypedSize = GetSize(tokenList[xOffset]);
+ xOffset += 1;
+ }
+ XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].Register);
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _REG " + xComparison + " _REGADDR[1]",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xOffset += 1;
+ }
+ XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].Register, sourceDisplacement: (int)tokenList[xOffset + 3].IntValue);
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _REG " + xComparison + " _REGADDR[-1]",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xOffset += 1;
+ }
+ XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].Register, sourceDisplacement: -(int)tokenList[xOffset + 3].IntValue);
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _REG " + xComparison + " _ABC",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xOffset += 1;
+ }
+ XS.Compare(tokenList[xOffset + 0].Register, GetLabel(tokenList[xOffset + 2]), sourceIsIndirect: true);
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _REG " + xComparison + " #_ABC",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xOffset += 1;
+ }
+ XS.Compare(tokenList[xOffset + 0].Register, ConstLabel(tokenList[xOffset + 3]));
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _REGADDR[1] " + xComparison + " 123",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ XSRegisters.RegisterSize? xTypedSize = null;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xTypedSize = GetSize(tokenList[xOffset]);
+ xOffset += 1;
+ }
+ XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 5].IntValue, destinationDisplacement: (int)tokenList[xOffset + 2].IntValue, size: xTypedSize);
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _REGADDR[-1] " + xComparison + " 123",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ XSRegisters.RegisterSize? xTypedSize = null;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xTypedSize = GetSize(tokenList[xOffset]);
+ xOffset += 1;
+ }
+ XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].IntValue, destinationDisplacement: -(int)tokenList[xOffset + 1].IntValue, size: xTypedSize);
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _REGADDR[1] " + xComparison + " _REG",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xOffset += 1;
+ }
+ XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].Register, destinationDisplacement: (int)tokenList[xOffset + 1].IntValue);
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _REGADDR[-1] " + xComparison + " _REG",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xOffset += 1;
+ }
+ XS.Compare(tokenList[xOffset + 0].Register, tokenList[xOffset + 2].Register, destinationDisplacement: -(int)tokenList[xOffset + 1].IntValue);
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _REGADDR[1] " + xComparison + " #_ABC",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ XSRegisters.RegisterSize? xTypedSize = null;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xTypedSize = GetSize(tokenList[xOffset]);
+ xOffset += 1;
+ }
+ XS.Compare(tokenList[xOffset + 0].Register, ConstLabel(tokenList[xOffset + 2]), destinationDisplacement: (int)tokenList[xOffset + 1].IntValue, sourceIsIndirect: true, size: xTypedSize);
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _REGADDR[-1] " + xComparison + " #_ABC",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ XSRegisters.RegisterSize? xTypedSize = null;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xTypedSize = GetSize(tokenList[xOffset]);
+ xOffset += 1;
+ }
+ XS.Compare(tokenList[xOffset + 0].Register, ConstLabel(tokenList[xOffset + 2]), destinationDisplacement: (int)tokenList[xOffset + 1].IntValue, size: xTypedSize);
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _ABC " + xComparison + " 123",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ XSRegisters.RegisterSize? xTypedSize = null;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xTypedSize = GetSize(tokenList[xOffset]);
+ xOffset += 1;
+ }
+ XS.Compare(GetLabel(tokenList[xOffset + 0]), tokenList[xOffset + 2].IntValue, destinationIsIndirect: true, size: xTypedSize.GetValueOrDefault(XSRegisters.RegisterSize.Int32));
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _ABC " + xComparison + " _REG",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ if (tokenList[xOffset + 2].Type != TokenType.Register) {
+ xOffset += 1;
+ }
+ XS.Compare(GetSimpleRef(tokenList[xOffset + 0]), tokenList[xOffset + 2].Register, destinationIsIndirect: true);
+ return xComparisonToken;
+ });
+ xCompares.Add(xSize + " _ABC " + xComparison + " #_ABC",
+ (tokenOffset, tokenList) => {
+ var xOffset = tokenOffset;
+ XSRegisters.RegisterSize? xTypedSize = null;
+ if (tokenList[xOffset].Type != TokenType.Register) {
+ xTypedSize = GetSize(tokenList[xOffset]);
+ xOffset += 1;
+ }
+ XS.Compare(GetSimpleRef(tokenList[xOffset + 0]), ConstLabel(tokenList[xOffset + 3]), destinationIsIndirect: true, size: xTypedSize.GetValueOrDefault(XSRegisters.RegisterSize.Int32));
+ return xComparisonToken;
+ });
+ }
+ }
+ }
+ #endregion Handle all comparisons
+ // Labels
+ // Local and proc level are used most, so designed to make their syntax shortest.
+ // Think of the dots like a directory, . is current group, .. is above that.
+ // ..Name: - Global level. Emitted exactly as is.
+ // .Name: - Group level. Group_Name
+ // Name: - Function level. Group_ProcName_Name
+
+ // The Exit label is a special one that is used as a target for the return instruction.
+ // It deserve special handling.
+ AddPattern("Exit:", delegate (TokenList aTokens) {
+ XS.Label(GetLabel(aTokens[0]));
+ mFuncExitFound = true;
+ });
+
+ // Regular label recognition.
+ AddPattern("_ABC:", delegate (TokenList aTokens) {
+ XS.Label(GetLabel(aTokens[0]));
+ });
+
+ AddPattern("Call _ABC", delegate (TokenList aTokens) {
+ XS.Call(GetLabel(aTokens[1]));
+ });
+ AddPattern("_PCALL", delegate (TokenList aTokens) {
+ if (aTokens.Count != 1
+ || aTokens[0].Type != TokenType.Call) {
+ throw new Exception("Error occured in parametrized call parsing");
+ } else {
+ List mparts = aTokens[0].RawValue.Remove(aTokens[0].RawValue.Length - 1).Split('(').ToList();
+ if (mparts.Count < 2) {
+ throw new Exception("Error occured in parametrized call parsing");
+ }
+ string fname = mparts[0];
+ mparts.RemoveAt(0);
+ aTokens[0].RawValue = String.Join("(", mparts).Trim();
+ string val = "";
+ int idx;
+
+ var xParams = new List();
+ int level = 0;
+ foreach (char c in aTokens[0].RawValue) {
+ switch (c) {
+ case ',':
+ if (level == 0) {
+ xParams.Add(val.Trim());
+ val = "";
+ }
+ break;
+ case '(':
+ level++;
+ val += c;
+ break;
+ case ')':
+ level--;
+ val += c;
+ break;
+ default:
+ val += c;
+ break;
+ }
+ }
+ if (!String.IsNullOrEmpty(val.Trim())) {
+ xParams.Add(val);
+ }
+ if (level != 0) {
+ throw new Exception("'(' occured without closing equivalent ')' in parametrized function call");
+ }
+
+ Parser xParser;
+ xParams.Reverse();
+ foreach (string p in xParams) {
+ xParser = new Parser(p, false, false);
+ idx = 0;
+ val = GetRef(xParser.Tokens, ref idx);
+ if (val != "@ret_on_stack@") {
+ //XS.PushLiteral(val);
+ throw new Exception();
+ } else {
+ //aAsm += GetPatternCode(xParser.Tokens).GetCode(false);
+ throw new NotImplementedException("Didn't get converted yet!");
+ }
+ }
+ XS.Call(GroupLabel(fname));
+ }
+ });
+
+ AddPattern("Goto _ABC", delegate (TokenList aTokens) {
+ XS.Jump(GetLabel(aTokens[1]));
+ });
+
+ // Defines a constant having the given name and initial value.
+ AddPattern("const _ABC = 123", delegate (TokenList aTokens) {
+ XS.Const(ConstLabel(aTokens[1]), aTokens[3].IntValue.ToString());
+ });
+
+ // Declare a double word variable having the given name and initialized to 0. The
+ // variable is declared at namespace level.
+ AddPattern("var _ABC", delegate (TokenList aTokens) {
+ XS.DataMember(GetLabel(aTokens[1]));
+ });
+
+ // Declare a doubleword variable having the given name and an explicit initial value. The
+ // variable is declared at namespace level.
+ AddPattern("var _ABC = 123", delegate (TokenList aTokens) {
+ XS.DataMember(GetLabel(aTokens[1]), aTokens[3].IntValue);
+ });
+
+ // Declare a textual variable having the given name and value. The variable is defined at
+ // namespace level and a null terminating byte is automatically added after the textual
+ // value.
+ AddPattern("var _ABC = 'Text'", delegate (TokenList aTokens) {
+ // Fix issue #15660 by using backquotes for string surrounding and escaping embedded
+ // back quotes.
+ XS.DataMember(GetLabel(aTokens[1]), EscapeBackQuotes(aTokens[3].RawValue));
+ });
+
+ // Declare a one-dimension array of bytes, words or doublewords. All members are initialized to 0.
+ // _ABC is array name. 123 is the total number of items in the array.
+ AddPattern(new string[]
+ {
+ "var _ABC byte[123]", "var _ABC word[123]", "var _ABC dword[123]"
+ }, delegate (TokenList aTokens) {
+ string xSize;
+ if (aTokens[2].Matches("byte")) {
+ xSize = "db";
+ } else if (aTokens[2].Matches("word")) {
+ xSize = "dw";
+ } else if (aTokens[2].Matches("dword")) {
+ xSize = "dd";
+ } else {
+ throw new Exception("Unknown size specified");
+ }
+ XS.DataMember(GetLabel(aTokens[1]), aTokens[4].IntValue, xSize, "0");
+ });
+
+ foreach (var xCompare in xCompares) {
+ // 0 1 2 3 4
+ AddPattern("while " + xCompare.Key + " {", delegate (TokenList aTokens) {
+ mBlocks.Start(aTokens, false);
+ XS.Label(BlockLabel("Begin"));
+
+ Token xComparison = xCompare.Value(1, aTokens);
+
+ XS.Jump(GetJump(xComparison.RawValue, true), BlockLabel("End"));
+ });
+ }
+
+ foreach (var xTail in "goto _ABC|return|{".Split('|')) {
+ // if 0 exit, etc
+ foreach (var xComparison in mCompareOps) {
+ AddPattern("if " + xComparison + " " + xTail, delegate (TokenList aTokens) {
+ string xOp = aTokens[1].RawValue;
+
+ // !0 is 2 tokens
+ if (aTokens[1].RawValue + aTokens[2].RawValue == "!0") {
+ xOp = "!0";
+ }
+
+ HandleIf(aTokens, xOp);
+ });
+ }
+
+ // if reg = x exit, etc
+ foreach (var xCompare in xCompares) {
+ // 0 1 2 3 4
+ AddPattern("if " + xCompare.Key + " " + xTail,
+ delegate (TokenList aTokens) {
+ Token xComparison = xCompare.Value(1, aTokens);
+
+ HandleIf(aTokens, xComparison.RawValue);
+ });
+ }
+ }
+
+ AddPattern("_REG ?= 123", delegate (TokenList aTokens) {
+ XS.Compare(aTokens[0].Register, aTokens[2].IntValue);
+ });
+ AddPattern("_REG ?= _ABC", delegate (TokenList aTokens) {
+ XS.Compare(aTokens[0].Register, GetSimpleRef(aTokens[2]), sourceIsIndirect: true);
+ });
+ AddPattern("_REG ?= #_ABC", delegate (TokenList aTokens) {
+ XS.Compare(aTokens[0].Register, ConstLabel(aTokens[2]));
+ });
+
+ AddPattern("_REG ?& 123", delegate (TokenList aTokens) {
+ XS.Test(aTokens[0].Register, aTokens[2].IntValue);
+ });
+ AddPattern("_REG ?& _ABC", delegate (TokenList aTokens) {
+ XS.Test(aTokens[0].Register, GetLabel(aTokens[2]), sourceIsIndirect: true);
+ });
+ AddPattern("_REG ?& #_ABC", delegate (TokenList aTokens) {
+ XS.Test(aTokens[0].Register, GetLabel(aTokens[2]), sourceIsIndirect: true);
+ });
+
+ AddPattern("_REG ~> 123", delegate (TokenList aTokens) {
+ XS.RotateRight(aTokens[0].Register, aTokens[2].IntValue);
+ });
+ AddPattern("_REG <~ 123", delegate (TokenList aTokens) {
+ XS.RotateLeft(aTokens[0].Register, aTokens[2].IntValue);
+ });
+ AddPattern("_REG >> 123", delegate (TokenList aTokens) {
+ if (aTokens[2].IntValue > 255) {
+ throw new IndexOutOfRangeException("Value is too large to be used as bitcount!");
+ }
+ XS.ShiftRight(aTokens[0].Register, (byte)aTokens[2].IntValue);
+ });
+ AddPattern("_REG << 123", delegate (TokenList aTokens) {
+ if (aTokens[2].IntValue > 255) {
+ throw new IndexOutOfRangeException("Value is too large to be used as bitcount!");
+ }
+ XS.ShiftLeft(aTokens[0].Register, (byte)aTokens[2].IntValue);
+ });
+
+ AddPattern("_REG = 123", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[2].IntValue);
+ });
+ AddPattern("_REGADDR[1] = 123", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[5].IntValue, destinationDisplacement: (int)aTokens[2].IntValue, size: XSRegisters.RegisterSize.Int32);
+ });
+ AddPattern("_REGADDR[-1] = 123", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[5].IntValue, destinationDisplacement: -(int)aTokens[2].IntValue, size: XSRegisters.RegisterSize.Int32);
+ });
+
+ AddPattern("_REG = #_ABC", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, ConstLabel(aTokens[3]));
+ });
+ AddPattern("_REGADDR[1] = #_ABC", delegate (TokenList aTokens) {
+ //XS.Set(RegisterSize.Int32, aTokens[0].IntValue, aTokens[2].IntValue, ConstLabel(aTokens[5]));
+ throw new NotImplementedException("");
+ });
+ AddPattern("_REGADDR[-1] = #_ABC", delegate (TokenList aTokens) {
+ var xFirst = GetSimpleRef(aTokens[0]);
+ var xSecond = GetSimpleRef(aTokens[2]);
+
+ //XS.SetLiteral("dword [" + xFirst + " - " + xSecond + "]", ConstLabel(aTokens[5]));
+ throw new NotImplementedException("");
+ });
+
+ AddPattern("_REG = _REG", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[2].Register);
+ });
+ AddPattern("_REGADDR[1] = _REG", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[5].Register, destinationDisplacement: (int)aTokens[2].IntValue);
+ });
+ AddPattern("_REGADDR[-1] = _REG", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[5].Register, destinationDisplacement: -(int)aTokens[2].IntValue);
+ });
+ AddPattern("_REG = _REGADDR[1]", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[2].Register, sourceDisplacement: (int)aTokens[4].IntValue);
+ });
+ AddPattern("_REG = _REGADDR[-1]", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[2].Register, sourceDisplacement: -(int)aTokens[4].IntValue);
+ });
+
+ AddPattern("_REG = [_REG]", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[3].Register, sourceIsIndirect: true);
+ });
+ AddPattern("_REG = [_REG + 1]", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[3].Register, sourceDisplacement: (int?)aTokens[5].IntValue);
+ });
+ AddPattern("_REG = [_REG - 1]", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[3].Register, sourceDisplacement: -(int)aTokens[5].IntValue);
+ });
+ AddPattern("[_REG] = _REG", delegate (TokenList aTokens) {
+ XS.Set(aTokens[1].Register, aTokens[4].Register, destinationIsIndirect: true);
+ });
+ AddPattern("[_REG + 1] = _REG", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[3].Register, destinationDisplacement: (int)aTokens[5].IntValue);
+ });
+ AddPattern("[_REG - 1] = _REG", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, aTokens[3].Register, destinationDisplacement: -(int)aTokens[5].IntValue);
+ });
+
+ AddPattern("_REG = _ABC", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, GetLabel(aTokens[2]), sourceIsIndirect: true);
+ });
+
+ // why not [var] like registers? Because its less frequent to access the ptr
+ // and it is like a reg.. without [] to get the value...
+ AddPattern("_REG = @_ABC", delegate (TokenList aTokens) {
+ XS.Set(aTokens[0].Register, GetLabel(aTokens[3]));
+ });
+
+ AddPattern(new string[]
+ {
+ "Port[DX] = AL", "Port[DX] = AX", "Port[DX] = EAX"
+ }, delegate (TokenList aTokens) {
+ XS.WriteToPortDX(aTokens[5].Register);
+ });
+ AddPattern(new string[]
+ {
+ "AL = Port[DX]", "AX = Port[DX]", "EAX = Port[DX]"
+ }, delegate (TokenList aTokens) {
+ XS.ReadFromPortDX(aTokens[0].Register);
+ });
+
+ AddPattern("+123", delegate (TokenList aTokens) {
+ XS.Push(aTokens[0].IntValue, size: XSRegisters.RegisterSize.Int32);
+ });
+ AddPattern(new string[]
+ {
+ "+123 as byte", "+123 as word", "+123 as dword"
+ }, delegate (TokenList aTokens) {
+ var xSize = GetSize(aTokens[1]);
+ XS.Push(aTokens[1].IntValue, size: xSize);
+ });
+ AddPattern("+_REG", delegate (TokenList aTokens) {
+ XS.Push(aTokens[1].Register);
+ });
+ AddPattern(new string[]
+ {
+ //0 1 2 3
+ "+#_ABC", "+#_ABC as byte", "+#_ABC as word", "+#_ABC as dword"
+ }, delegate (TokenList aTokens) {
+ XSRegisters.RegisterSize xSize = XSRegisters.RegisterSize.Int32;
+ if (aTokens.Count > 2) {
+ xSize = GetSize(aTokens[3]);
+ }
+ XS.Push(ConstLabel(aTokens[1]), size: xSize);
+ });
+ AddPattern("+All", delegate (TokenList aTokens) {
+ XS.PushAllRegisters();
+ });
+ AddPattern("-All", delegate (TokenList aTokens) {
+ XS.PopAllRegisters();
+ });
+ AddPattern("-_REG", delegate (TokenList aTokens) {
+ XS.Pop(aTokens[1].Register);
+ });
+
+ AddPattern("_ABC = _REG", delegate (TokenList aTokens) {
+ XS.Set(GetLabel(aTokens[0]), aTokens[2].Register, destinationIsIndirect: true);
+ });
+ AddPattern("_ABC = #_ABC", delegate (TokenList aTokens) {
+ XS.Set(GetLabel(aTokens[0]), ConstLabel(aTokens[3]), destinationIsIndirect: true, size: XSRegisters.RegisterSize.Int32);
+ });
+ AddPattern("_ABC = 123", delegate (TokenList aTokens) {
+ XS.Set(GetLabel(aTokens[0]), aTokens[2].IntValue, destinationIsIndirect: true);
+ });
+ AddPattern(new string[]
+ {
+ "_ABC = 123 as byte", "_ABC = 123 as word", "_ABC = 123 as dword"
+ }, delegate (TokenList aTokens) {
+ XS.Set(GetLabel(aTokens[0]), aTokens[2].IntValue, size: GetSize(aTokens[4]));
+ });
+
+ AddPattern(new string[]
+ {
+ "_REG + 1",
+ }, delegate (TokenList aTokens) {
+ XS.Add(aTokens[0].Register, aTokens[2].IntValue);
+ });
+
+ AddPattern(new string[]
+ {
+ "_REG + _REG"
+ }, delegate (TokenList aTokens) {
+ XS.Add(aTokens[0].Register, aTokens[2].Register);
+ });
+ AddPattern(new string[]
+ {
+ "_REG - 1",
+ }, delegate (TokenList aTokens) {
+ XS.Sub(aTokens[0].Register, aTokens[2].IntValue);
+ });
+ AddPattern(new string[]
+ {
+ "_REG - _REG"
+ }, delegate (TokenList aTokens) {
+ XS.Sub(aTokens[0].Register, aTokens[2].Register);
+ });
+ AddPattern(new string[]
+ {
+ "_REG * 1",
+ }, delegate (TokenList aTokens) {
+ XS.IntegerMultiply(aTokens[0].Register, aTokens[2].IntValue);
+ });
+ AddPattern(new string[]
+ {
+ "_REG * _REG"
+ }, delegate (TokenList aTokens) {
+ XS.IntegerMultiply(aTokens[0].Register, aTokens[2].Register);
+ });
+ AddPattern("_REG++", delegate (TokenList aTokens) {
+ XS.Increment(aTokens[0].Register);
+ });
+ AddPattern("_REG--", delegate (TokenList aTokens) {
+ XS.Decrement(aTokens[0].Register);
+ });
+
+ AddPattern(new string[]
+ {
+ "_REG & 1",
+ }, delegate (TokenList aTokens) {
+ XS.And(aTokens[0].Register, aTokens[2].IntValue);
+ });
+ AddPattern(new string[]
+ {
+ "_REG & _REG"
+ }, delegate (TokenList aTokens) {
+ XS.And(aTokens[0].Register, aTokens[2].Register);
+ });
+ AddPattern(new string[]
+ {
+ "_REG | 1",
+ }, delegate (TokenList aTokens) {
+ XS.Or(aTokens[0].Register, aTokens[2].IntValue);
+ });
+ AddPattern(new string[]
+ {
+ "_REG | _REG"
+ }, delegate (TokenList aTokens) {
+ XS.Or(aTokens[0].Register, aTokens[2].Register);
+ });
+ AddPattern(new string[]
+ {
+ "_REG ^ 1",
+ }, delegate (TokenList aTokens) {
+ XS.Xor(aTokens[0].Register, aTokens[2].IntValue);
+ });
+ AddPattern(new string[]
+ {
+ "_REG ^ _REG"
+ }, delegate (TokenList aTokens) {
+ XS.Xor(aTokens[0].Register, aTokens[2].Register);
+ });
+
+ // End block. This handle both terminating a standard block as well as a function or an
+ // interrupt handler.
+ AddPattern("}", delegate (TokenList aTokens) {
+ if (mBlocks.Count == 0) {
+ EndFunc();
+ } else {
+ var xBlock = mBlocks.Current();
+ var xToken1 = xBlock.StartTokens[0];
+ if (xToken1.Matches("repeat")) {
+ var xCount = xBlock.StartTokens[1].IntValue;
+ for (var i = 1; i <= xCount; i++) {
+ xBlock.AddContentsToParentAssembler();
+ }
+ } else if (xToken1.Matches("while")) {
+ XS.Jump(BlockLabel("Begin"));
+ XS.Label(BlockLabel("End"));
+ xBlock.AddContentsToParentAssembler();
+ } else if (xToken1.Matches("if")) {
+ XS.Label(BlockLabel("End"));
+ xBlock.AddContentsToParentAssembler();
+ } else {
+ throw new Exception("Unknown block starter.");
+ }
+ mBlocks.End();
+ }
+ });
+
+ AddPattern("namespace _ABC", delegate (TokenList aTokens) {
+ mNamespace = aTokens[1].RawValue;
+ });
+
+ AddPattern("Return", delegate {
+ XS.Jump(FuncLabel("Exit"));
+ });
+
+ AddPattern("Repeat 4 times {", delegate (TokenList aTokens) {
+ mBlocks.Start(aTokens, true);
+ });
+
+ AddPattern("Interrupt _ABC {", delegate (TokenList aTokens) {
+ StartFunc(aTokens[1].RawValue);
+ mInIntHandler = true;
+ XS.Label(GetNamespace() + "_" + aTokens[1].RawValue);
+ });
+
+ // This needs to be different from return.
+ // return jumps to exit, ret does raw x86 ret
+ AddPattern("Ret", delegate (TokenList aTokens) {
+ XS.Return();
+ });
+ AddPattern("IRet", delegate (TokenList aTokens) {
+ XS.InterruptReturn();
+ });
+
+ AddPattern("Function _ABC {", delegate (TokenList aTokens) {
+ StartFunc(aTokens[1].RawValue);
+ mInIntHandler = false;
+ XS.Label(GetNamespace() + "_" + aTokens[1].RawValue);
+ });
+
+ AddPattern("Checkpoint 'Text'", delegate (TokenList aTokens) {
+ // This method emits a lot of ASM, but thats what we want becuase
+ // at this point we need ASM as simple as possible and completely transparent.
+ // No stack changes, no register mods, no calls, no jumps, etc.
+
+ // TODO: Add an option on the debug project properties to turn this off.
+ // Also see WriteDebugVideo in CosmosAssembler.cs
+ var xPreBootLogging = true;
+ if (xPreBootLogging) {
+ UInt32 xVideo = 0xB8000;
+ for (UInt32 i = xVideo; i < xVideo + 80 * 2; i = i + 2) {
+ XS.SetByte(i, 0);
+ XS.SetByte(i + 1, 2);
+ }
+
+ foreach (var xChar in aTokens[1].RawValue) {
+ XS.SetByte(xVideo, (byte)xChar);
+ xVideo = xVideo + 2;
+ }
+ }
+ });
+ }
+
+ /// Fix issue #15660. This method escapes double quotes in the candidate string.
+ /// The string to be sanitized.
+ /// The original string with escaped double quotes.
+ private static string EscapeBackQuotes(string from) {
+ StringBuilder builder = new StringBuilder();
+ bool sanitized = false;
+ bool escaped = false;
+ foreach (char scannedCharacter in from) {
+ switch (scannedCharacter) {
+ case '\\':
+ escaped = !escaped;
+ break;
+ case '`':
+ if (!escaped) {
+ sanitized = true;
+ builder.Append('\\');
+ }
+ escaped = false;
+ break;
+ default:
+ escaped = false;
+ break;
+ }
+ builder.Append(scannedCharacter);
+ }
+ return (sanitized) ? builder.ToString() : from;
+ }
+
+ protected Pattern FindMatch(TokenList aTokens) {
+ int xHash = aTokens.GetPatternHashCode();
+
+ // Get a list of matching hashes, but then we have to
+ // search for exact pattern match because it is possible
+ // to have duplicate hashes. Hashes just provide us a quick way
+ // to reduce the search.
+ foreach (var xPattern in mPatterns.Where(q => q.Hash == xHash)) {
+ if (xPattern.Tokens.PatternMatches(aTokens)) {
+ return xPattern;
+ }
+ }
+ return null;
+ }
+
+ public bool GetPatternCode(TokenList aTokens) {
+ var xPattern = FindMatch(aTokens);
+ if (xPattern == null) {
+ return false;
+ }
+
+ xPattern.Code(aTokens);
+
+ //// Apply {0} etc into string
+ //// This happens twice for block code, but its ok because the first pass
+ //// strips out all tags.
+ //for (int i = 0; i < xResult.Code.Count; i++) {
+ // xResult.Code[i] = string.Format(xResult.Code[i], aTokens.ToArray());
+ //}
+ return true;
+ }
+
+ public void Assemble(string aLine) {
+ var xParser = new Parser(aLine, false, false);
+ var xTokens = xParser.Tokens;
+
+ if (GetPatternCode(xTokens) == false) {
+ if (xTokens.Count == 0) {
+ throw new Exception("Parsing error: " + aLine);
+ }
+
+ var xFirst = xTokens[0];
+ var xLast = xTokens[xTokens.Count - 1];
+
+ // Find match and emit X#
+ if (xTokens.Count == 2
+ && xFirst.Type == TokenType.AlphaNum
+ && xLast.Matches("()")) {
+ // () could be handled by pattern, but best to keep in one place for future
+ //xResult += "Call " + GroupLabel(aTokens[0].Value);
+ XS.Call(GroupLabel(xTokens[0].RawValue));
+ }
+ }
+ }
+
+ /// Register a single pattern with its associated transformation handler.
+ /// A single line of X# code that define the pattern optionally using
+ /// pattern reserved syntax.
+ /// The associated code transformation handler.
+ protected void AddPattern(string aPattern, CodeFunc aCode) {
+ Parser xParser = null;
+ try {
+ xParser = new Parser(aPattern, false, true);
+ } catch (Exception e) {
+ throw new Exception(string.Format("Invalid pattern '{0}'", aPattern ?? "NULL"), e);
+ }
+ var xPattern = new Pattern(xParser.Tokens, aCode, aPattern);
+ mPatterns.Add(xPattern);
+ }
+
+ /// Register a collection of patterns that share a single transformation handler.
+ ///
+ /// A collection of X# lines of code. Each line of code define a
+ /// pattern optionally using the pattern reserved syntax.
+ /// The code transformation handler that is common abmongst all the
+ /// patterns from the collection.
+ protected void AddPattern(string[] aPatterns, CodeFunc aCode) {
+ foreach (var xPattern in aPatterns) {
+ AddPattern(xPattern, aCode);
+ }
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Gen1/XS.FPU.cs b/source/XSharp/XSharp/Gen1/XS.FPU.cs
index b00c3f2a..74a64ce4 100644
--- a/source/XSharp/XSharp/Gen1/XS.FPU.cs
+++ b/source/XSharp/XSharp/Gen1/XS.FPU.cs
@@ -1,163 +1,163 @@
-using System;
-using XSharp.Assembler.x86.x87;
-
-namespace XSharp
-{
- public partial class XS
- {
- public static class FPU
- {
- public static void FloatCompareAndSet(XSRegisters.RegisterFPU register)
- {
- new FloatCompareAndSet
- {
- DestinationReg = register.RegEnum
- };
- }
-
- public static void FloatStoreAndPop(XSRegisters.Register32 register, bool isIndirect = false, int? displacement = null, XSRegisters.RegisterSize? size = null)
- {
- if (displacement != null)
- {
- isIndirect = true;
- if (displacement == 0)
- {
- displacement = null;
- }
- }
-
- if (size == null)
- {
- if (isIndirect)
- {
- throw new InvalidOperationException("No size specified!");
- }
- size = register.Size;
- }
-
- new FloatStoreAndPop
- {
- DestinationReg = register.RegEnum,
- DestinationIsIndirect = isIndirect,
- DestinationDisplacement = displacement,
- Size = (byte)size
- };
- }
-
- public static void FloatStoreAndPop(XSRegisters.RegisterFPU register)
- {
- new FloatStoreAndPop
- {
- DestinationReg = register.RegEnum
- };
- }
-
- public static void FloatLoad(XSRegisters.Register32 register, bool destinationIsIndirect = false, int? displacement = null, XSRegisters.RegisterSize? size = null)
- {
- Do(register, isIndirect: destinationIsIndirect, displacement: displacement, size: size);
- }
-
- public static void FloatAbs()
- {
- new FloatABS();
- }
-
- public static void FloatInit()
- {
- new FloatInit();
- }
-
- public static void FloatNegate()
- {
- new FloatNegate();
- }
-
- public static void FloatRound()
- {
- new FloatRound();
- }
-
- public static void FloatCosine()
- {
- new FloatCosine();
- }
-
- public static void FloatSine()
- {
- new FloatSine();
- }
-
- public static void FloatTan()
- {
- new FloatTan();
- }
-
- public static void FloatPop()
- {
- new FloatPop();
- }
-
- public static void FloatAdd(XSRegisters.Register32 destination, bool isIndirect = false, XSRegisters.RegisterSize? size = null)
- {
- if (size == null)
- {
- if (isIndirect)
- {
- throw new InvalidOperationException("No size specified!");
- }
- size = destination.Size;
- }
-
- new FloatAdd
- {
- DestinationReg = destination,
- DestinationIsIndirect = isIndirect,
- Size = (byte)size.Value
- };
- }
-
- public static void IntLoad(XSRegisters.Register32 destination, bool isIndirect = false, int? displacement = null, XSRegisters.RegisterSize? size = null)
- {
- if (size == null)
- {
- if (isIndirect)
- {
- throw new InvalidOperationException("No size specified!");
- }
- size = destination.Size;
- }
-
- if (displacement != null)
- {
- isIndirect = true;
- }
-
- new IntLoad
- {
- DestinationReg = destination,
- DestinationIsIndirect = isIndirect,
- Size = (byte)size.Value
- };
- }
-
- public static void IntStoreWithTruncate(XSRegisters.Register32 destination, bool isIndirect = false, XSRegisters.RegisterSize? size = null)
- {
- if (size == null)
- {
- if (isIndirect)
- {
- throw new InvalidOperationException("No size specified!");
- }
- size = destination.Size;
- }
-
- new IntStoreWithTrunc
- {
- DestinationReg = destination,
- DestinationIsIndirect = isIndirect,
- Size = (byte)size.Value
- };
- }
- }
- }
-}
+using System;
+using XSharp.Assembler.x86.x87;
+
+namespace XSharp
+{
+ public partial class XS
+ {
+ public static class FPU
+ {
+ public static void FloatCompareAndSet(XSRegisters.RegisterFPU register)
+ {
+ new FloatCompareAndSet
+ {
+ DestinationReg = register.RegEnum
+ };
+ }
+
+ public static void FloatStoreAndPop(XSRegisters.Register64 register, bool isIndirect = false, int? displacement = null, XSRegisters.RegisterSize? size = null)
+ {
+ if (displacement != null)
+ {
+ isIndirect = true;
+ if (displacement == 0)
+ {
+ displacement = null;
+ }
+ }
+
+ if (size == null)
+ {
+ if (isIndirect)
+ {
+ throw new InvalidOperationException("No size specified!");
+ }
+ size = register.Size;
+ }
+
+ new FloatStoreAndPop
+ {
+ DestinationReg = register.RegEnum,
+ DestinationIsIndirect = isIndirect,
+ DestinationDisplacement = displacement,
+ Size = (byte)size
+ };
+ }
+
+ public static void FloatStoreAndPop(XSRegisters.RegisterFPU register)
+ {
+ new FloatStoreAndPop
+ {
+ DestinationReg = register.RegEnum
+ };
+ }
+
+ public static void FloatLoad(XSRegisters.Register64 register, bool destinationIsIndirect = false, int? displacement = null, XSRegisters.RegisterSize? size = null)
+ {
+ Do(register, isIndirect: destinationIsIndirect, displacement: displacement, size: size);
+ }
+
+ public static void FloatAbs()
+ {
+ new FloatABS();
+ }
+
+ public static void FloatInit()
+ {
+ new FloatInit();
+ }
+
+ public static void FloatNegate()
+ {
+ new FloatNegate();
+ }
+
+ public static void FloatRound()
+ {
+ new FloatRound();
+ }
+
+ public static void FloatCosine()
+ {
+ new FloatCosine();
+ }
+
+ public static void FloatSine()
+ {
+ new FloatSine();
+ }
+
+ public static void FloatTan()
+ {
+ new FloatTan();
+ }
+
+ public static void FloatPop()
+ {
+ new FloatPop();
+ }
+
+ public static void FloatAdd(XSRegisters.Register64 destination, bool isIndirect = false, XSRegisters.RegisterSize? size = null)
+ {
+ if (size == null)
+ {
+ if (isIndirect)
+ {
+ throw new InvalidOperationException("No size specified!");
+ }
+ size = destination.Size;
+ }
+
+ new FloatAdd
+ {
+ DestinationReg = destination,
+ DestinationIsIndirect = isIndirect,
+ Size = (byte)size.Value
+ };
+ }
+
+ public static void IntLoad(XSRegisters.Register64 destination, bool isIndirect = false, int? displacement = null, XSRegisters.RegisterSize? size = null)
+ {
+ if (size == null)
+ {
+ if (isIndirect)
+ {
+ throw new InvalidOperationException("No size specified!");
+ }
+ size = destination.Size;
+ }
+
+ if (displacement != null)
+ {
+ isIndirect = true;
+ }
+
+ new IntLoad
+ {
+ DestinationReg = destination,
+ DestinationIsIndirect = isIndirect,
+ Size = (byte)size.Value
+ };
+ }
+
+ public static void IntStoreWithTruncate(XSRegisters.Register64 destination, bool isIndirect = false, XSRegisters.RegisterSize? size = null)
+ {
+ if (size == null)
+ {
+ if (isIndirect)
+ {
+ throw new InvalidOperationException("No size specified!");
+ }
+ size = destination.Size;
+ }
+
+ new IntStoreWithTrunc
+ {
+ DestinationReg = destination,
+ DestinationIsIndirect = isIndirect,
+ Size = (byte)size.Value
+ };
+ }
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Gen1/XS.SSE.cs b/source/XSharp/XSharp/Gen1/XS.SSE.cs
index 7a7e7bd3..99082bc8 100644
--- a/source/XSharp/XSharp/Gen1/XS.SSE.cs
+++ b/source/XSharp/XSharp/Gen1/XS.SSE.cs
@@ -1,197 +1,197 @@
-using System;
-
-using XSharp.Assembler.x86.SSE;
-using XSharp.Assembler.x86.x87;
-
-namespace XSharp
-{
- using static XSRegisters;
-
- partial class XS
- {
- public static class SSE
- {
- public static void SSEInit()
- {
- XS.Comment("BEGIN - SSE Init");
-
- // CR4[bit 9]=1, CR4[bit 10]=1, CR0[bit 2]=0, CR0[bit 1]=1
-
- XS.Set(EAX, CR4);
- XS.Or(EAX, 0x100);
- XS.Set(CR4, EAX);
- XS.Set(EAX, CR4);
- XS.Or(EAX, 0x200);
- XS.Set(CR4, EAX);
- XS.Set(EAX, CR0);
- XS.And(EAX, 0xfffffffd);
- XS.Set(CR0, EAX);
- XS.Set(EAX, CR0);
-
- XS.And(EAX, 1);
- XS.Set(CR0, EAX);
- XS.Comment("END - SSE Init");
- }
-
- public static void AddSS(RegisterXMM destination, RegisterXMM source)
- {
- DoDestinationSource(destination, source);
- }
-
- public static void MulSS(RegisterXMM destination, RegisterXMM source)
- {
- DoDestinationSource(destination, source);
- }
-
- public static void SubSS(RegisterXMM destination, RegisterXMM source)
- {
- DoDestinationSource(destination, source);
- }
-
- public static void XorPS(RegisterXMM destination, RegisterXMM source)
- {
- DoDestinationSource(destination, source);
- }
-
- public static void CompareSS(RegisterXMM destination, RegisterXMM source, ComparePseudoOpcodes comparision)
- {
- new CompareSS()
- {
- DestinationReg = destination,
- SourceReg = source,
- pseudoOpcode = (byte) comparision
- };
- }
-
- public static void ConvertSI2SS(RegisterXMM destination, Register32 source, bool sourceIsIndirect = false)
- {
- new ConvertSI2SS()
- {
- DestinationReg = destination,
- SourceReg = source,
- SourceIsIndirect = sourceIsIndirect
- };
- }
-
- public static void MoveSS(RegisterXMM destination, RegisterXMM source)
- {
- DoDestinationSource(destination, source);
- }
-
- public static void MoveSS(RegisterXMM destination, Register32 source, bool sourceIsIndirect = false)
- {
- new MoveSS()
- {
- DestinationReg = destination,
- SourceReg = source,
- SourceIsIndirect = sourceIsIndirect
- };
- }
-
- public static void MoveSS(Register32 destination, RegisterXMM source, bool destinationIsIndirect = false)
- {
- new MoveSS()
- {
- DestinationReg = destination,
- DestinationIsIndirect = destinationIsIndirect,
- SourceReg = source
- };
- }
-
- public static void MoveSS(RegisterXMM destination, String sourceLabel, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
- {
- DoDestinationSource(destination, sourceLabel, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
- }
-
- public static void MoveUPS(Register32 destination, RegisterXMM source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
- {
- DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
- }
-
- public static void MoveDQA(RegisterXMM destination, Register32 source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
- {
- DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
- }
-
- public static void MoveDQA(Register32 destination, RegisterXMM source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
- {
- DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
- }
-
- public static void MoveDQU(RegisterXMM destination, Register32 source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
- {
- DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
- }
-
- public static void MoveDQU(Register32 destination, RegisterXMM source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
- {
- DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
- }
-
- public static void MoveAPS(Register32 destination, RegisterXMM source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
- {
- DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
- }
-
- public static void MoveAPS(RegisterXMM destination, Register32 source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
- {
- DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
- }
-
- public static void ConvertSS2SIAndTruncate(Register32 destination, RegisterXMM source)
- {
- new ConvertSS2SIAndTruncate
- {
- DestinationReg = destination,
- SourceReg = source
- };
- }
-
- public static void DivPS(RegisterXMM destination, RegisterXMM source)
- {
- new DivPS
- {
- DestinationReg = destination,
- SourceReg = source
- };
- }
-
- public static void DivSS(RegisterXMM destination, RegisterXMM source)
- {
- new DivSS
- {
- DestinationReg = destination,
- SourceReg = source
- };
- }
-
- public static void FXSave(Register32 destination, bool isIndirect)
- {
- new FXSave
- {
- DestinationReg = destination,
- DestinationIsIndirect = isIndirect
- };
- }
-
- public static void FXRestore(Register32 destination, bool isIndirect)
- {
- new FXStore()
- {
- DestinationReg = destination,
- DestinationIsIndirect = isIndirect
- };
- }
-
- public static void Shufps(RegisterXMM destination, RegisterXMM source, int bitmask)
- {
- new Shufps()
- {
- DestinationReg = destination,
- SourceReg = source,
- pseudoOpcode = (byte)bitmask
- };
- }
- }
- }
-}
+using System;
+
+using XSharp.Assembler.x86.SSE;
+using XSharp.Assembler.x86.x87;
+
+namespace XSharp
+{
+ using static XSRegisters;
+
+ partial class XS
+ {
+ public static class SSE
+ {
+ public static void SSEInit()
+ {
+ XS.Comment("BEGIN - SSE Init");
+
+ // CR4[bit 9]=1, CR4[bit 10]=1, CR0[bit 2]=0, CR0[bit 1]=1
+
+ XS.Set(RAX, CR4);
+ XS.Or(RAX, 0x100);
+ XS.Set(CR4, RAX);
+ XS.Set(RAX, CR4);
+ XS.Or(RAX, 0x200);
+ XS.Set(CR4, RAX);
+ XS.Set(RAX, CR0);
+ XS.And(RAX, 0xfffffffd);
+ XS.Set(CR0, RAX);
+ XS.Set(RAX, CR0);
+
+ XS.And(RAX, 1);
+ XS.Set(CR0, RAX);
+ XS.Comment("END - SSE Init");
+ }
+
+ public static void AddSS(RegisterXMM destination, RegisterXMM source)
+ {
+ DoDestinationSource(destination, source);
+ }
+
+ public static void MulSS(RegisterXMM destination, RegisterXMM source)
+ {
+ DoDestinationSource(destination, source);
+ }
+
+ public static void SubSS(RegisterXMM destination, RegisterXMM source)
+ {
+ DoDestinationSource(destination, source);
+ }
+
+ public static void XorPS(RegisterXMM destination, RegisterXMM source)
+ {
+ DoDestinationSource(destination, source);
+ }
+
+ public static void CompareSS(RegisterXMM destination, RegisterXMM source, ComparePseudoOpcodes comparision)
+ {
+ new CompareSS()
+ {
+ DestinationReg = destination,
+ SourceReg = source,
+ pseudoOpcode = (byte) comparision
+ };
+ }
+
+ public static void ConvertSI2SS(RegisterXMM destination, Register64 source, bool sourceIsIndirect = false)
+ {
+ new ConvertSI2SS()
+ {
+ DestinationReg = destination,
+ SourceReg = source,
+ SourceIsIndirect = sourceIsIndirect
+ };
+ }
+
+ public static void MoveSS(RegisterXMM destination, RegisterXMM source)
+ {
+ DoDestinationSource(destination, source);
+ }
+
+ public static void MoveSS(RegisterXMM destination, Register64 source, bool sourceIsIndirect = false)
+ {
+ new MoveSS()
+ {
+ DestinationReg = destination,
+ SourceReg = source,
+ SourceIsIndirect = sourceIsIndirect
+ };
+ }
+
+ public static void MoveSS(Register64 destination, RegisterXMM source, bool destinationIsIndirect = false)
+ {
+ new MoveSS()
+ {
+ DestinationReg = destination,
+ DestinationIsIndirect = destinationIsIndirect,
+ SourceReg = source
+ };
+ }
+
+ public static void MoveSS(RegisterXMM destination, String sourceLabel, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
+ {
+ DoDestinationSource(destination, sourceLabel, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
+ }
+
+ public static void MoveUPS(Register64 destination, RegisterXMM source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
+ {
+ DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
+ }
+
+ public static void MoveDQA(RegisterXMM destination, Register64 source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
+ {
+ DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
+ }
+
+ public static void MoveDQA(Register64 destination, RegisterXMM source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
+ {
+ DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
+ }
+
+ public static void MoveDQU(RegisterXMM destination, Register64 source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
+ {
+ DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
+ }
+
+ public static void MoveDQU(Register64 destination, RegisterXMM source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
+ {
+ DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
+ }
+
+ public static void MoveAPS(Register64 destination, RegisterXMM source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
+ {
+ DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
+ }
+
+ public static void MoveAPS(RegisterXMM destination, Register64 source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
+ {
+ DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
+ }
+
+ public static void ConvertSS2SIAndTruncate(Register64 destination, RegisterXMM source)
+ {
+ new ConvertSS2SIAndTruncate
+ {
+ DestinationReg = destination,
+ SourceReg = source
+ };
+ }
+
+ public static void DivPS(RegisterXMM destination, RegisterXMM source)
+ {
+ new DivPS
+ {
+ DestinationReg = destination,
+ SourceReg = source
+ };
+ }
+
+ public static void DivSS(RegisterXMM destination, RegisterXMM source)
+ {
+ new DivSS
+ {
+ DestinationReg = destination,
+ SourceReg = source
+ };
+ }
+
+ public static void FXSave(Register64 destination, bool isIndirect)
+ {
+ new FXSave
+ {
+ DestinationReg = destination,
+ DestinationIsIndirect = isIndirect
+ };
+ }
+
+ public static void FXRestore(Register64 destination, bool isIndirect)
+ {
+ new FXStore()
+ {
+ DestinationReg = destination,
+ DestinationIsIndirect = isIndirect
+ };
+ }
+
+ public static void Shufps(RegisterXMM destination, RegisterXMM source, int bitmask)
+ {
+ new Shufps()
+ {
+ DestinationReg = destination,
+ SourceReg = source,
+ pseudoOpcode = (byte)bitmask
+ };
+ }
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Gen1/XS.SSE2.cs b/source/XSharp/XSharp/Gen1/XS.SSE2.cs
index 464e1f56..62877f5a 100644
--- a/source/XSharp/XSharp/Gen1/XS.SSE2.cs
+++ b/source/XSharp/XSharp/Gen1/XS.SSE2.cs
@@ -1,124 +1,124 @@
-using System;
-
-using XSharp.Assembler.x86.SSE;
-using static XSharp.XSRegisters;
-
-namespace XSharp
-{
- partial class XS
- {
- public static class SSE2
- {
- public static void AddSD(RegisterXMM destination, RegisterXMM source)
- {
- DoDestinationSource(destination, source);
- }
-
- public static void DivSD(RegisterXMM destination, RegisterXMM source)
- {
- new DivSD
- {
- DestinationReg = destination,
- SourceReg = source
- };
- }
-
- public static void MulSD(RegisterXMM destination, RegisterXMM source)
- {
- DoDestinationSource(destination, source);
- }
-
- public static void SubSD(RegisterXMM destination, RegisterXMM source)
- {
- DoDestinationSource(destination, source);
- }
-
- public static void CompareSD(RegisterXMM destination, RegisterXMM source, ComparePseudoOpcodes comparision)
- {
- new CompareSD()
- {
- DestinationReg = destination,
- SourceReg = source,
- pseudoOpcode = (byte)comparision
- };
- }
-
- public static void ConvertSD2SIAndTruncate(Register32 destination, RegisterXMM source)
- {
- new ConvertSD2SIAndTruncate
- {
- DestinationReg = destination,
- SourceReg = source
- };
- }
-
- public static void ConvertSS2SD(RegisterXMM destination, Register32 source, bool sourceIsIndirect = false)
- {
- new ConvertSS2SD()
- {
- DestinationReg = destination,
- SourceReg = source,
- SourceIsIndirect = sourceIsIndirect
- };
- }
-
- public static void ConvertSD2SS(RegisterXMM destination, Register32 source, bool sourceIsIndirect = false)
- {
- new ConvertSD2SS()
- {
- DestinationReg = destination,
- SourceReg = source,
- SourceIsIndirect = sourceIsIndirect
- };
- }
-
- public static void ConvertSI2SD(RegisterXMM destination, Register32 source, bool sourceIsIndirect = false, int? sourceDisplacement = null, bool destinationIsIndirect = false, int? destinationDisplacement = null)
- {
- new ConvertSI2SD()
- {
- DestinationReg = destination,
- DestinationIsIndirect = destinationIsIndirect,
- DestinationDisplacement = destinationDisplacement,
- SourceReg = source,
- SourceIsIndirect = sourceIsIndirect,
- SourceDisplacement = sourceDisplacement
- };
- }
-
- public static void MoveSD(RegisterXMM destination, RegisterXMM source)
- {
- DoDestinationSource(destination, source);
- }
-
- public static void MoveSD(RegisterXMM destination, Register32 source, bool sourceIsIndirect = false)
- {
- new MoveSD()
- {
- DestinationReg = destination,
- SourceReg = source,
- SourceIsIndirect = sourceIsIndirect
- };
- }
-
- public static void MoveSD(Register32 destination, RegisterXMM source, bool destinationIsIndirect = false)
- {
- new MoveSD()
- {
- DestinationReg = destination,
- DestinationIsIndirect = destinationIsIndirect,
- SourceReg = source
- };
- }
-
- public static void XorPD(RegisterXMM destination, RegisterXMM source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
- {
- DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
- }
-
- public static void XorPD(RegisterXMM destination, String sourceLabel, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
- {
- DoDestinationSource(destination, sourceLabel, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
- }
- }
- }
-}
+using System;
+
+using XSharp.Assembler.x86.SSE;
+using static XSharp.XSRegisters;
+
+namespace XSharp
+{
+ partial class XS
+ {
+ public static class SSE2
+ {
+ public static void AddSD(RegisterXMM destination, RegisterXMM source)
+ {
+ DoDestinationSource(destination, source);
+ }
+
+ public static void DivSD(RegisterXMM destination, RegisterXMM source)
+ {
+ new DivSD
+ {
+ DestinationReg = destination,
+ SourceReg = source
+ };
+ }
+
+ public static void MulSD(RegisterXMM destination, RegisterXMM source)
+ {
+ DoDestinationSource(destination, source);
+ }
+
+ public static void SubSD(RegisterXMM destination, RegisterXMM source)
+ {
+ DoDestinationSource(destination, source);
+ }
+
+ public static void CompareSD(RegisterXMM destination, RegisterXMM source, ComparePseudoOpcodes comparision)
+ {
+ new CompareSD()
+ {
+ DestinationReg = destination,
+ SourceReg = source,
+ pseudoOpcode = (byte)comparision
+ };
+ }
+
+ public static void ConvertSD2SIAndTruncate(Register64 destination, RegisterXMM source)
+ {
+ new ConvertSD2SIAndTruncate
+ {
+ DestinationReg = destination,
+ SourceReg = source
+ };
+ }
+
+ public static void ConvertSS2SD(RegisterXMM destination, Register64 source, bool sourceIsIndirect = false)
+ {
+ new ConvertSS2SD()
+ {
+ DestinationReg = destination,
+ SourceReg = source,
+ SourceIsIndirect = sourceIsIndirect
+ };
+ }
+
+ public static void ConvertSD2SS(RegisterXMM destination, Register64 source, bool sourceIsIndirect = false)
+ {
+ new ConvertSD2SS()
+ {
+ DestinationReg = destination,
+ SourceReg = source,
+ SourceIsIndirect = sourceIsIndirect
+ };
+ }
+
+ public static void ConvertSI2SD(RegisterXMM destination, Register64 source, bool sourceIsIndirect = false, int? sourceDisplacement = null, bool destinationIsIndirect = false, int? destinationDisplacement = null)
+ {
+ new ConvertSI2SD()
+ {
+ DestinationReg = destination,
+ DestinationIsIndirect = false, //must be indirect in long mode
+ DestinationDisplacement = destinationDisplacement,
+ SourceReg = source,
+ SourceIsIndirect = true,
+ SourceDisplacement = sourceDisplacement
+ };
+ }
+
+ public static void MoveSD(RegisterXMM destination, RegisterXMM source)
+ {
+ DoDestinationSource(destination, source);
+ }
+
+ public static void MoveSD(RegisterXMM destination, Register64 source, bool sourceIsIndirect = false)
+ {
+ new MoveSD()
+ {
+ DestinationReg = destination,
+ SourceReg = source,
+ SourceIsIndirect = sourceIsIndirect
+ };
+ }
+
+ public static void MoveSD(Register64 destination, RegisterXMM source, bool destinationIsIndirect = false)
+ {
+ new MoveSD()
+ {
+ DestinationReg = destination,
+ DestinationIsIndirect = destinationIsIndirect,
+ SourceReg = source
+ };
+ }
+
+ public static void XorPD(RegisterXMM destination, RegisterXMM source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
+ {
+ DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
+ }
+
+ public static void XorPD(RegisterXMM destination, String sourceLabel, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
+ {
+ DoDestinationSource(destination, sourceLabel, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
+ }
+ }
+ }
+}
diff --git a/source/XSharp/XSharp/Gen1/XS.cs b/source/XSharp/XSharp/Gen1/XS.cs
index 4df8ab7f..af0970b3 100644
--- a/source/XSharp/XSharp/Gen1/XS.cs
+++ b/source/XSharp/XSharp/Gen1/XS.cs
@@ -74,7 +74,7 @@ private static void Do(string destination, Register source, bool destinationI
};
}
- private static void Do(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ private static void Do(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
where T : InstructionWithDestinationAndSourceAndSize, new()
{
if (destinationDisplacement != null)
@@ -110,7 +110,7 @@ private static void Do(string destination, UInt32 value, bool destinationIsIn
};
}
- private static void Do(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ private static void Do(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
where T : InstructionWithDestinationAndSourceAndSize, new()
{
if (destinationDisplacement != null)
@@ -212,7 +212,7 @@ private static void Do(Register destination, uint value, bool destinationIsIn
{
if (destinationIsIndirect)
{
- size = RegisterSize.Int32;
+ size = RegisterSize.Long64;
}
else
{
@@ -287,7 +287,7 @@ private static void Do(Register destination, Register source, bool destinatio
#region InstructionWithDestinationAndSize
- private static void Do(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ private static void Do(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
where T : InstructionWithDestinationAndSize, new()
{
if (displacement != null)
@@ -336,7 +336,7 @@ private static void Do(Register register, bool isIndirect = false, int? displ
};
}
- private static void Do(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ private static void Do(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
where T : InstructionWithDestinationAndSize, new()
{
if (displacement != null)
@@ -578,12 +578,12 @@ public static void Set(string destination, Register source, bool destinationIsIn
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void Set(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Set(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void Set(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Set(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
@@ -617,12 +617,12 @@ public static void Lea(string destination, Register source, bool destinationIsIn
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void Lea(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Lea(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void Lea(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Lea(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
@@ -667,7 +667,7 @@ public static void Call(string target)
new Call { DestinationLabel = target };
}
- public static void Call(Register32 register)
+ public static void Call(Register64 register)
{
new Call { DestinationReg = register.RegEnum };
}
@@ -741,7 +741,7 @@ public static void ShiftLeft(Register destination, byte bitCount)
Do(destination, bitCount);
}
- public static void ShiftLeft(Register destination, Register8 bitCount, bool destinationIsIndirect = false, RegisterSize size = RegisterSize.Int32)
+ public static void ShiftLeft(Register destination, Register8 bitCount, bool destinationIsIndirect = false, RegisterSize size = RegisterSize.Long64)
{
if (bitCount != CL)
{
@@ -771,7 +771,7 @@ public static void ShiftLeftArithmetic(Register destination, byte bitCount)
Do(destination, bitCount);
}
- public static void ShiftLeftArithmetic(Register destination, Register8 bitCount, bool destinationIsIndirect = false, RegisterSize size = RegisterSize.Int32)
+ public static void ShiftLeftArithmetic(Register destination, Register8 bitCount, bool destinationIsIndirect = false, RegisterSize size = RegisterSize.Long64)
{
if (bitCount != CL)
{
@@ -796,19 +796,19 @@ public static void ReadFromPortDX(Register value)
};
}
- public static void Push(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Push(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destinationValue, isIndirect, displacement, size);
}
- public static void Push(Register register, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Push(Register register, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(register, isIndirect, displacement, size);
}
- public static void Push(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Push(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
- Do(label, isIndirect, displacement, size);
+ Do(label, true, displacement, size);
}
public static void Pushfd()
@@ -871,7 +871,7 @@ public static void SubWithCarry(Register register, Register valueToAdd, bool des
Do(register, valueToAdd, destinationDisplacement: destinationDisplacement, destinationIsIndirect: destinationIsIndirect);
}
- public static void And(Register register, uint value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void And(Register register, uint value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(register, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size: size);
}
@@ -886,12 +886,12 @@ public static void Xor(string destination, Register source, bool destinationIsIn
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void Xor(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Xor(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void Xor(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Xor(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
@@ -928,12 +928,12 @@ public static void Compare(string destination, Register source, bool destination
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void Compare(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Compare(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void Compare(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Compare(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
@@ -996,7 +996,7 @@ public static void Test(Register destination, Register sourceReg, bool sourceIsI
};
}
- public static void Divide(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Divide(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destinationValue, isIndirect, displacement, size);
}
@@ -1006,12 +1006,12 @@ public static void Divide(Register register, bool isIndirect = false, int? displ
Do(register, isIndirect, displacement, size);
}
- public static void Divide(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Divide(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(label, isIndirect, displacement, size);
}
- public static void IntegerDivide(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void IntegerDivide(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destinationValue, isIndirect, displacement, size);
}
@@ -1021,27 +1021,27 @@ public static void IntegerDivide(Register register, bool isIndirect = false, int
Do(register, isIndirect, displacement, size);
}
- public static void IntegerDivide(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void IntegerDivide(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(label, isIndirect, displacement, size);
}
- public static void Multiply(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Multiply(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destinationValue, isIndirect, displacement, size);
}
- public static void Multiply(Register register, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Multiply(Register register, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(register, isIndirect, displacement, size);
}
- public static void Multiply(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Multiply(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(label, isIndirect, displacement, size);
}
- public static void Negate(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Negate(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destinationValue, isIndirect, displacement, size);
}
@@ -1051,12 +1051,12 @@ public static void Negate(Register register, bool isIndirect = false, int? displ
Do(register, isIndirect, displacement, size);
}
- public static void Negate(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Negate(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(label, isIndirect, displacement, size);
}
- public static void Not(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Not(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destinationValue, isIndirect, displacement, size);
}
@@ -1066,7 +1066,7 @@ public static void Not(Register register, bool isIndirect = false, int? displace
Do(register, isIndirect, displacement, size);
}
- public static void Not(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Not(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(label, isIndirect, displacement, size);
}
@@ -1076,12 +1076,12 @@ public static void AddWithCarry(string destination, Register source, bool destin
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void AddWithCarry(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void AddWithCarry(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void AddWithCarry(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void AddWithCarry(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
@@ -1106,12 +1106,12 @@ public static void Or(string destination, Register source, bool destinationIsInd
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void Or(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Or(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void Or(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void Or(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
@@ -1246,7 +1246,7 @@ public static void StoreDwordInString()
};
}
- public static void LoadGdt(Register32 destination, bool isIndirect = false)
+ public static void LoadGdt(Register64 destination, bool isIndirect = false)
{
new Lgdt
{
@@ -1255,7 +1255,7 @@ public static void LoadGdt(Register32 destination, bool isIndirect = false)
};
}
- public static void LoadIdt(Register32 destination, bool isIndirect = false)
+ public static void LoadIdt(Register64 destination, bool isIndirect = false)
{
new Lidt
{
@@ -1269,12 +1269,12 @@ public static void RotateThroughCarryRight(string destination, Register source,
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void RotateThroughCarryRight(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void RotateThroughCarryRight(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
- public static void RotateThroughCarryRight(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
+ public static void RotateThroughCarryRight(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Long64)
{
Do(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
diff --git a/source/XSharp/XSharp/Gen1/XSRegisters.cs b/source/XSharp/XSharp/Gen1/XSRegisters.cs
index dbe66069..7d6c700f 100644
--- a/source/XSharp/XSharp/Gen1/XSRegisters.cs
+++ b/source/XSharp/XSharp/Gen1/XSRegisters.cs
@@ -73,7 +73,7 @@ public Register16(string name, RegistersEnum regEnum) : base(name, regEnum, Regi
public class Register32 : Register
{
- public Register32(string name, RegistersEnum regEnum) : base(name, regEnum, RegisterSize.Int32)
+ public Register32(string name, RegistersEnum regEnum) : base(name, regEnum, RegisterSize.FPU)
{
}
}
@@ -110,35 +110,35 @@ public RegisterSegment(string name, RegistersEnum regEnum) : base(name, regEnum,
public static readonly Register8 AH = new Register8(nameof(AH), RegistersEnum.AH);
public static readonly Register16 AX = new Register16(nameof(AX), RegistersEnum.AX);
public static readonly Register32 EAX = new Register32(nameof(EAX), RegistersEnum.EAX);
+ public static readonly Register64 RAX = new Register64(nameof(RAX), RegistersEnum.RAX);
public static readonly Register8 BL = new Register8(nameof(BL), RegistersEnum.BL);
public static readonly Register8 BH = new Register8(nameof(BH), RegistersEnum.BH);
public static readonly Register16 BX = new Register16(nameof(BX), RegistersEnum.BX);
- public static readonly Register32 EBX = new Register32(nameof(EBX), RegistersEnum.EBX);
+ public static readonly Register64 RBX = new Register64(nameof(RBX), RegistersEnum.RBX);
public static readonly Register8 CL = new Register8(nameof(CL), RegistersEnum.CL);
public static readonly Register8 CH = new Register8(nameof(CH), RegistersEnum.CH);
public static readonly Register16 CX = new Register16(nameof(CX), RegistersEnum.CX);
- public static readonly Register32 ECX = new Register32(nameof(ECX), RegistersEnum.ECX);
+ public static readonly Register64 RCX = new Register64(nameof(RCX), RegistersEnum.RCX);
public static readonly Register8 DL = new Register8(nameof(DL), RegistersEnum.DL);
public static readonly Register8 DH = new Register8(nameof(DH), RegistersEnum.DH);
public static readonly Register16 DX = new Register16(nameof(DX), RegistersEnum.DX);
- public static readonly Register32 EDX = new Register32(nameof(EDX), RegistersEnum.EDX);
-
- public static readonly Register32 EBP = new Register32(nameof(EBP), RegistersEnum.EBP);
- public static readonly Register32 ESP = new Register32(nameof(ESP), RegistersEnum.ESP);
- public static readonly Register32 ESI = new Register32(nameof(ESI), RegistersEnum.ESI);
- public static readonly Register32 EDI = new Register32(nameof(EDI), RegistersEnum.EDI);
-
- public static readonly Register64 RAX = new Register64(nameof(RAX), RegistersEnum.RAX);
- public static readonly Register64 RBX = new Register64(nameof(RBX), RegistersEnum.RBX);
- public static readonly Register64 RCX = new Register64(nameof(RCX), RegistersEnum.RCX);
public static readonly Register64 RDX = new Register64(nameof(RDX), RegistersEnum.RDX);
+
+ public static readonly Register64 RBP = new Register64(nameof(RBP), RegistersEnum.RBP);
+ public static readonly Register64 RSP = new Register64(nameof(RSP), RegistersEnum.RSP);
public static readonly Register64 RSI = new Register64(nameof(RSI), RegistersEnum.RSI);
public static readonly Register64 RDI = new Register64(nameof(RDI), RegistersEnum.RDI);
- public static readonly Register64 RSP = new Register64(nameof(RSP), RegistersEnum.RSP);
- public static readonly Register64 RBP = new Register64(nameof(RBP), RegistersEnum.RBP);
+
+ //
+
+
+
+
+
+
public static readonly Register64 R8 = new Register64(nameof(R8), RegistersEnum.R8);
public static readonly Register64 R9 = new Register64(nameof(R9), RegistersEnum.R9);
public static readonly Register64 R10 = new Register64(nameof(R10), RegistersEnum.R10);
@@ -176,10 +176,10 @@ public RegisterSegment(string name, RegistersEnum regEnum) : base(name, regEnum,
public static readonly RegisterXMM XMM7 = new RegisterXMM(nameof(XMM7), RegistersEnum.XMM7);
// Control Registers
- public static readonly Register32 CR0 = new Register32(nameof(CR0), RegistersEnum.CR0);
- public static readonly Register32 CR1 = new Register32(nameof(CR1), RegistersEnum.CR1);
- public static readonly Register32 CR2 = new Register32(nameof(CR2), RegistersEnum.CR2);
- public static readonly Register32 CR3 = new Register32(nameof(CR3), RegistersEnum.CR3);
- public static readonly Register32 CR4 = new Register32(nameof(CR4), RegistersEnum.CR4);
+ public static readonly Register64 CR0 = new Register64(nameof(CR0), RegistersEnum.CR0);
+ public static readonly Register64 CR1 = new Register64(nameof(CR1), RegistersEnum.CR1);
+ public static readonly Register64 CR2 = new Register64(nameof(CR2), RegistersEnum.CR2);
+ public static readonly Register64 CR3 = new Register64(nameof(CR3), RegistersEnum.CR3);
+ public static readonly Register64 CR4 = new Register64(nameof(CR4), RegistersEnum.CR4);
}
}
diff --git a/source/XSharp/XSharp/XSharp.csproj b/source/XSharp/XSharp/XSharp.csproj
index dec1613c..64f45047 100644
--- a/source/XSharp/XSharp/XSharp.csproj
+++ b/source/XSharp/XSharp/XSharp.csproj
@@ -5,6 +5,7 @@
True
CA1716;CA1801;CA1822;$(NoWarn)
AnyCPU;x86
+ 10.0.0