This commit is contained in:
kudzu_cp 2012-06-14 02:31:53 +00:00
parent f444a4f08e
commit 5faebb9614
6 changed files with 130 additions and 43 deletions

View file

@ -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);
}
}
}

View file

@ -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",

View file

@ -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());
}

View file

@ -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" />

View 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();
}
}
}

View file

@ -64,6 +64,4 @@ InterruptHandler TracerEntry {
# Temp disabled, see comment on LockOrExit above
# Unlock
#IRet
}