diff --git a/source2/Compiler/Cosmos.XSharp/Generator.cs b/source2/Compiler/Cosmos.XSharp/Generator.cs index 424b5a4d6..9fe9a48ba 100644 --- a/source2/Compiler/Cosmos.XSharp/Generator.cs +++ b/source2/Compiler/Cosmos.XSharp/Generator.cs @@ -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); + } } } diff --git a/source2/Compiler/Cosmos.XSharp/Parser.cs b/source2/Compiler/Cosmos.XSharp/Parser.cs index 388777bf3..e9d0eadfe 100644 --- a/source2/Compiler/Cosmos.XSharp/Parser.cs +++ b/source2/Compiler/Cosmos.XSharp/Parser.cs @@ -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", diff --git a/source2/Compiler/Cosmos.XSharp/TokenPatterns.cs b/source2/Compiler/Cosmos.XSharp/TokenPatterns.cs index 393acf85c..834fd977c 100644 --- a/source2/Compiler/Cosmos.XSharp/TokenPatterns.cs +++ b/source2/Compiler/Cosmos.XSharp/TokenPatterns.cs @@ -8,6 +8,8 @@ namespace Cosmos.Compiler.XSharp { public delegate string CodeFunc(TokenList aTokens); protected Dictionary mPatterns = new Dictionary(); protected Dictionary mKeywords = new Dictionary(); + 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()); } diff --git a/source2/Users/Matthijs/MatthijsPlayground/Playground.Matthijs.Test.csproj b/source2/Users/Matthijs/MatthijsPlayground/Playground.Matthijs.Test.csproj index 385d0beaa..7c28ea669 100644 --- a/source2/Users/Matthijs/MatthijsPlayground/Playground.Matthijs.Test.csproj +++ b/source2/Users/Matthijs/MatthijsPlayground/Playground.Matthijs.Test.csproj @@ -42,6 +42,11 @@ + + True + True + Test.xs + @@ -76,6 +81,7 @@ CosmosXSharpGenerator + Test.cs diff --git a/source2/Users/Matthijs/MatthijsPlayground/Test.cs b/source2/Users/Matthijs/MatthijsPlayground/Test.cs new file mode 100644 index 000000000..582a7a3ed --- /dev/null +++ b/source2/Users/Matthijs/MatthijsPlayground/Test.cs @@ -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(); + } + } +} diff --git a/source2/Users/Matthijs/MatthijsPlayground/Test.xs b/source2/Users/Matthijs/MatthijsPlayground/Test.xs index 78ff94834..c6508b365 100644 --- a/source2/Users/Matthijs/MatthijsPlayground/Test.xs +++ b/source2/Users/Matthijs/MatthijsPlayground/Test.xs @@ -64,6 +64,4 @@ InterruptHandler TracerEntry { # Temp disabled, see comment on LockOrExit above # Unlock - -#IRet }