mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-20 04:48:53 +00:00
X#
This commit is contained in:
parent
f444a4f08e
commit
5faebb9614
6 changed files with 130 additions and 43 deletions
|
|
@ -63,7 +63,10 @@ namespace Cosmos.Compiler.XSharp {
|
|||
}
|
||||
var xParser = new Parser(aLine, false);
|
||||
string xCode = mPatterns.GetCode(xParser.Tokens);
|
||||
mOutput.WriteLine("\t\t\t" + xCode);
|
||||
// Some keywords like Group are processe but not output
|
||||
if (xCode != "") {
|
||||
mOutput.WriteLine("\t\t\t" + xCode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@ namespace Cosmos.Compiler.XSharp {
|
|||
"CALL"
|
||||
, "END"
|
||||
, "GROUP"
|
||||
, "IRET", "INTERRUPTHANDLER"
|
||||
, "INTERRUPTHANDLER"
|
||||
, "POPALL", "PUSHALL", "PROCEDURE"
|
||||
, "RETURN", "RETURNINTERRUPT"
|
||||
};
|
||||
protected static string[] mRegisters = new string[] {
|
||||
"EAX", "AX", "AH", "AL",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ namespace Cosmos.Compiler.XSharp {
|
|||
public delegate string CodeFunc(TokenList aTokens);
|
||||
protected Dictionary<TokenPattern, CodeFunc> mPatterns = new Dictionary<TokenPattern, CodeFunc>();
|
||||
protected Dictionary<string, CodeFunc> mKeywords = new Dictionary<string, CodeFunc>();
|
||||
protected string mGroup;
|
||||
protected bool mInIntHandler;
|
||||
|
||||
public TokenPatterns() {
|
||||
AddPatterns();
|
||||
|
|
@ -17,15 +19,46 @@ namespace Cosmos.Compiler.XSharp {
|
|||
protected void AddKeywords() {
|
||||
AddKeyword("Call", delegate(TokenList aTokens) {
|
||||
if (aTokens.Pattern == "Call ABC") {
|
||||
return "new Call {{ DestinationLabel = {1} }};";
|
||||
return "new Call {{ DestinationLabel = \"{1}\" }};";
|
||||
} else if (aTokens.Pattern == "Call .ABC") {
|
||||
return "new Call {{ DestinationLabel = {1} }};";
|
||||
return "new Call {{ DestinationLabel = \"" + mGroup + "_{2}\" }};";
|
||||
}
|
||||
throw new Exception("Unrecognized syntax for keyword: " + aTokens[0].Value);
|
||||
return null;
|
||||
});
|
||||
AddKeyword("IRet", "new IRet();");
|
||||
|
||||
AddKeyword("Group", delegate(TokenList aTokens) {
|
||||
if (aTokens.Pattern == "Group ABC") {
|
||||
mGroup = aTokens[1].Value;
|
||||
return "";
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
|
||||
AddKeyword("InterruptHandler", delegate(TokenList aTokens) {
|
||||
mInIntHandler = true;
|
||||
if (aTokens.Pattern == "InterruptHandler ABC {") {
|
||||
return "new Label(\"{1}\");";
|
||||
} else if (aTokens.Pattern == "InterruptHandler .ABC {") {
|
||||
return "new Label(\"" + mGroup + "_{2}\");";
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
AddKeyword("Return", "new Ret();");
|
||||
AddKeyword("ReturnInterrupt", "new IRET();");
|
||||
AddKeyword("PopAll", "new Popad();");
|
||||
AddKeyword("PushAll", "new Pushad();");
|
||||
|
||||
AddKeyword("Procedure", delegate(TokenList aTokens) {
|
||||
mInIntHandler = false;
|
||||
if (aTokens.Pattern == "Procedure ABC {") {
|
||||
return "new Label(\"{1}\");";
|
||||
} else if (aTokens.Pattern == "Procedure .ABC {") {
|
||||
return "new Label(\"" + mGroup + "_{2}\");";
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
protected void AddKeyword(string aKeyword, CodeFunc aCode) {
|
||||
|
|
@ -64,12 +97,8 @@ namespace Cosmos.Compiler.XSharp {
|
|||
|
||||
AddPattern("Variable = EAX",
|
||||
"new Mov {{"
|
||||
+ " DestinationRef = Cosmos.Assembler.ElementReference.New(RegistersEnum.{0})"
|
||||
+ " , DestinationIsIndirect = true"
|
||||
+ " , SourceValue = value.Value.GetValueOrDefault()"
|
||||
+ " , SourceRef = value.Reference"
|
||||
+ " , SourceReg = value.Register"
|
||||
+ " , SourceIsIndirect = value.IsIndirect"
|
||||
+ " DestinationRef = Cosmos.Assembler.ElementReference.New(\"{0}\")"
|
||||
+ " , SourceReg = RegistersEnum.{2}"
|
||||
+ " }};"
|
||||
);
|
||||
|
||||
|
|
@ -90,46 +119,33 @@ namespace Cosmos.Compiler.XSharp {
|
|||
}
|
||||
});
|
||||
|
||||
AddPattern("}",
|
||||
""
|
||||
);
|
||||
|
||||
AddPattern(new TokenType[] { TokenType.Keyword, TokenType.AlphaNum }, delegate(TokenList aTokens) {
|
||||
string xOp = aTokens[0].Value.ToUpper();
|
||||
if (xOp == "CALL") {
|
||||
return "new Call {{ DestinationLabel = {1} }};";
|
||||
} else if (xOp == "GROUP") {
|
||||
return "";
|
||||
AddPattern("}", delegate(TokenList aTokens) {
|
||||
if (mInIntHandler) {
|
||||
return "new IRET();";
|
||||
} else {
|
||||
throw new Exception("Unrecognized keyword: " + aTokens[0].Value);
|
||||
}
|
||||
});
|
||||
|
||||
AddPattern(new TokenType[] { TokenType.Keyword, TokenType.AlphaNum, TokenType.CurlyLeft }, delegate(TokenList aTokens) {
|
||||
string xOp = aTokens[0].Value.ToUpper();
|
||||
if (xOp == "INTERRUPTHANDLER") {
|
||||
return "";
|
||||
} else if (xOp == "PROCEDURE") {
|
||||
return "";
|
||||
} else {
|
||||
throw new Exception("Unrecognized keyword: " + aTokens[0].Value);
|
||||
return "new Ret();";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public string GetCode(TokenList aTokens) {
|
||||
CodeFunc xAction = null;
|
||||
string xResult = null;
|
||||
if (aTokens[0].Type == TokenType.Keyword) {
|
||||
mKeywords.TryGetValue(aTokens[0].Value.ToUpper(), out xAction);
|
||||
}
|
||||
if (xAction == null) {
|
||||
mPatterns.TryGetValue(aTokens.Pattern, out xAction);
|
||||
if (xAction == null) {
|
||||
throw new Exception("Token pattern not found.");
|
||||
if (mKeywords.TryGetValue(aTokens[0].Value.ToUpper(), out xAction)) {
|
||||
xResult = xAction(aTokens);
|
||||
if (xResult == null) {
|
||||
throw new Exception("Unrecognized syntax for keyword: " + aTokens[0].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (xAction == null) {
|
||||
if (!mPatterns.TryGetValue(aTokens.Pattern, out xAction)) {
|
||||
throw new Exception("Token pattern not found.");
|
||||
}
|
||||
xResult = xAction(aTokens);
|
||||
}
|
||||
|
||||
string xResult = xAction(aTokens);
|
||||
return string.Format(xResult, aTokens.Select(c => c.Value).ToArray());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="Kernel.cs" />
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Test.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Test.xs</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Cosmos.Assembler.X86\Cosmos.Assembler.x86.csproj">
|
||||
|
|
@ -76,6 +81,7 @@
|
|||
<ItemGroup>
|
||||
<None Include="Test.xs">
|
||||
<Generator>CosmosXSharpGenerator</Generator>
|
||||
<LastGenOutput>Test.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
|
|
|||
63
source2/Users/Matthijs/MatthijsPlayground/Test.cs
Normal file
63
source2/Users/Matthijs/MatthijsPlayground/Test.cs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Cosmos.Assembler;
|
||||
using Cosmos.Assembler.x86;
|
||||
|
||||
namespace MatthijsPlayground
|
||||
{
|
||||
public class Test : Cosmos.Assembler.Code {
|
||||
public override void Assemble() {
|
||||
new Comment("From Entry.CS");
|
||||
new Comment("We need to make sure Int3 can never run more than one instance at a time.");
|
||||
new Comment("We are not threaded yet, when we are we have to change stuff to thread vars and a lot of other stuff.");
|
||||
new Comment("Two Int3 calls currently can never happen at the same time normally, but IRQs can happen while the DebugStub is");
|
||||
new Comment("running. We also need to make sure IRQs are allowed to run during DebugStub as DebugStub can wait for");
|
||||
new Comment("a long time on commands.");
|
||||
new Comment("So we need to disable interrupts immediately and set a flag, then reenable interrupts if they were enabled");
|
||||
new Comment("when we disabled them. Later this can be replaced by some kind of critical section / lock around this code.");
|
||||
new Comment("Currently IRQs are disabled - we need to fix DS before we can reenable them and add support for critical sections / locks here.");
|
||||
new Comment("-http:#www.codemaestro.com/reviews/8");
|
||||
new Comment("-http:#en.wikipedia.org/wiki/Spinlock - Uses a register which is a problem for us");
|
||||
new Comment("-http:#wiki.osdev.org/Spinlock");
|
||||
new Comment("-Looks good and also allows testing intead of waiting");
|
||||
new Comment("-Wont require us to disable / enable IRQs");
|
||||
new Label("TracerEntry");
|
||||
new Comment("This code is temporarily disabled as IRQs are not enabled right now.");
|
||||
new Comment("LockOrExit");
|
||||
new Comment("EBP is restored by PopAll, but SendFrame uses it. Could");
|
||||
new Comment("get it from the PushAll data, but this is easier.");
|
||||
new Mov { DestinationRef = Cosmos.Assembler.ElementReference.New("CallerEBP") , SourceReg = RegistersEnum.EBP };
|
||||
new Comment("Could get ESP from PushAll but this is easier.");
|
||||
new Comment("Also allows us to use the stack before PushAll if we ever need it.");
|
||||
new Comment("We cant modify any registers since we havent done PushAll yet");
|
||||
new Comment("Maybe we could do a sub(4) on memory direct..");
|
||||
new Comment("But for now we remove from ESP which the Int3 produces,");
|
||||
new Comment("store ESP, then restore ESP so we don't cause stack corruption.");
|
||||
new Comment("12 bytes for EFLAGS, CS, EIP");
|
||||
new Add { DestinationReg = RegistersEnum.ESP, SourceValue = 12 };
|
||||
new Mov { DestinationRef = Cosmos.Assembler.ElementReference.New("CallerESP") , SourceReg = RegistersEnum.ESP };
|
||||
new Sub { DestinationReg = RegistersEnum.ESP, SourceValue = 12 };
|
||||
new Pushad();
|
||||
new Comment("Save current ESP so we can look at the results of PushAll later");
|
||||
new Mov { DestinationRef = Cosmos.Assembler.ElementReference.New("PushAllPtr") , SourceReg = RegistersEnum.ESP };
|
||||
new Comment("Get current ESP and add 32. This will skip over the PushAll and point");
|
||||
new Comment("us at the call data from Int3.");
|
||||
new Mov{ DestinationReg = RegistersEnum.EBP, SourceReg = RegistersEnum.ESP };
|
||||
new Add { DestinationReg = RegistersEnum.EBP, SourceValue = 32 };
|
||||
new Comment("Caller EIP");
|
||||
new Mov { DestinationReg = RegistersEnum.EAX, SourceReg = RegistersEnum.EBP, SourceIsIndirect = true, SourceDisplacement = 0};
|
||||
new Comment("EIP is pointer to op after our call. Int3 is 1 byte so we subtract 1.");
|
||||
new Comment("Note - when we used call it was 5 (size of our call + address)");
|
||||
new Comment("so we get the EIP as IL2CPU records it. Its also useful for when we");
|
||||
new Comment("wil be changing ops that call this stub.");
|
||||
new Dec { DestinationReg = RegistersEnum.EAX };
|
||||
new Comment("Store it for later use.");
|
||||
new Mov { DestinationRef = Cosmos.Assembler.ElementReference.New("CallerEIP") , SourceReg = RegistersEnum.EAX };
|
||||
new Call { DestinationLabel = DebugStub_"Executing" };
|
||||
new Popad();
|
||||
new Comment("Temp disabled, see comment on LockOrExit above");
|
||||
new Comment("Unlock");
|
||||
new IRET();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -64,6 +64,4 @@ InterruptHandler TracerEntry {
|
|||
|
||||
# Temp disabled, see comment on LockOrExit above
|
||||
# Unlock
|
||||
|
||||
#IRet
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue