diff --git a/source2/Compiler/Cosmos.Compiler.DebugStub/CmdSend.cs b/source2/Compiler/Cosmos.Compiler.DebugStub/CmdSend.cs index e711319d3..7fcb704d8 100644 --- a/source2/Compiler/Cosmos.Compiler.DebugStub/CmdSend.cs +++ b/source2/Compiler/Cosmos.Compiler.DebugStub/CmdSend.cs @@ -40,11 +40,12 @@ namespace Cosmos.Debug.DebugStub { new LiteralAssemblerCode("Sub EAX, ESI"); new LiteralAssemblerCode("Call DebugStub_ComWriteAX"); new LiteralAssemblerCode("Mov ESI, [DebugStub_CallerESP]"); - new LiteralAssemblerCode("DebugStub_SendStack_SendByte:"); + new LiteralAssemblerCode("DebugStub_SendStack_Block1Begin:"); new LiteralAssemblerCode("Cmp ESI, [DebugStub_CallerEBP]"); - new LiteralAssemblerCode("JE DebugStub_SendStack_Exit"); + new LiteralAssemblerCode("JE DebugStub_SendStack_Block1End"); new LiteralAssemblerCode("Call DebugStub_ComWrite8"); - new LiteralAssemblerCode("Jmp DebugStub_SendStack_SendByte"); + new LiteralAssemblerCode("jmp DebugStub_SendStack_Block1Begin"); + new LiteralAssemblerCode("DebugStub_SendStack_Block1End:"); new LiteralAssemblerCode("DebugStub_SendStack_Exit:"); new LiteralAssemblerCode("Ret"); new LiteralAssemblerCode("DebugStub_SendMethodContext:"); @@ -56,13 +57,13 @@ namespace Cosmos.Debug.DebugStub { new LiteralAssemblerCode("Call DebugStub_ComReadEAX"); new LiteralAssemblerCode("Mov ESI, [DebugStub_CallerEBP]"); new LiteralAssemblerCode("Add ESI, EAX"); - new LiteralAssemblerCode("DebugStub_SendMethodContext_SendByte:"); + new LiteralAssemblerCode("DebugStub_SendMethodContext_Block2Begin:"); new LiteralAssemblerCode("Cmp ECX, 0"); - new LiteralAssemblerCode("JE DebugStub_SendMethodContext_AfterSendByte"); + new LiteralAssemblerCode("JE DebugStub_SendMethodContext_Block2End"); new LiteralAssemblerCode("Call DebugStub_ComWrite8"); new LiteralAssemblerCode("Dec ECX"); - new LiteralAssemblerCode("Jmp DebugStub_SendMethodContext_SendByte"); - new LiteralAssemblerCode("DebugStub_SendMethodContext_AfterSendByte:"); + new LiteralAssemblerCode("jmp DebugStub_SendMethodContext_Block2Begin"); + new LiteralAssemblerCode("DebugStub_SendMethodContext_Block2End:"); new LiteralAssemblerCode("DebugStub_SendMethodContext_Exit:"); new LiteralAssemblerCode("Popad"); new LiteralAssemblerCode("Ret"); @@ -74,13 +75,13 @@ namespace Cosmos.Debug.DebugStub { new LiteralAssemblerCode("Call DebugStub_ComWriteAL"); new LiteralAssemblerCode("Call DebugStub_ComReadEAX"); new LiteralAssemblerCode("Mov ESI, EAX"); - new LiteralAssemblerCode("DebugStub_SendMemory_SendByte:"); + new LiteralAssemblerCode("DebugStub_SendMemory_Block3Begin:"); new LiteralAssemblerCode("Cmp ECX, 0"); - new LiteralAssemblerCode("JE DebugStub_SendMemory_AfterSendByte"); + new LiteralAssemblerCode("JE DebugStub_SendMemory_Block3End"); new LiteralAssemblerCode("Call DebugStub_ComWrite8"); new LiteralAssemblerCode("Dec ECX"); - new LiteralAssemblerCode("Jmp DebugStub_SendMemory_SendByte"); - new LiteralAssemblerCode("DebugStub_SendMemory_AfterSendByte:"); + new LiteralAssemblerCode("jmp DebugStub_SendMemory_Block3Begin"); + new LiteralAssemblerCode("DebugStub_SendMemory_Block3End:"); new LiteralAssemblerCode("DebugStub_SendMemory_Exit:"); new LiteralAssemblerCode("Popad"); new LiteralAssemblerCode("Ret"); diff --git a/source2/Compiler/Cosmos.Compiler.DebugStub/CmdSend.xs b/source2/Compiler/Cosmos.Compiler.DebugStub/CmdSend.xs index bf092d684..1c4cd4fc8 100644 --- a/source2/Compiler/Cosmos.Compiler.DebugStub/CmdSend.xs +++ b/source2/Compiler/Cosmos.Compiler.DebugStub/CmdSend.xs @@ -44,11 +44,9 @@ function SendStack { // // Need to reload ESI, WriteAXToCompPort modifies it ESI = .CallerESP - //TODO While -SendByte: - if ESI = .CallerEBP return - ComWrite8() - goto SendByte + while ESI != .CallerEBP { + ComWrite8() + } } // sends a stack value @@ -72,13 +70,10 @@ function SendMethodContext { ESI = .CallerEBP ESI + EAX - // TODO While -SendByte: - if ECX = 0 goto AfterSendByte - ComWrite8() - ECX-- - goto SendByte -AfterSendByte: + while ECX != 0 { + ComWrite8() + ECX-- + } Exit: -All @@ -103,15 +98,12 @@ function SendMemory { ComReadEAX() ESI = EAX -// TODO - Make this a method and use it in above function too // now ECX contains size of data (count) // ESI contains address -SendByte: - if ECX = 0 goto AfterSendByte - ComWrite8() - ECX-- - goto SendByte -AfterSendByte: + while ECX != 0 { + ComWrite8() + ECX-- + } Exit: -All diff --git a/source2/Compiler/Cosmos.Compiler.DebugStub/Screen.cs b/source2/Compiler/Cosmos.Compiler.DebugStub/Screen.cs index ff8079e67..ce66c418a 100644 --- a/source2/Compiler/Cosmos.Compiler.DebugStub/Screen.cs +++ b/source2/Compiler/Cosmos.Compiler.DebugStub/Screen.cs @@ -9,14 +9,13 @@ namespace Cosmos.Debug.DebugStub { public Screen(Assembler.Assembler aAssembler) : base(aAssembler) {} public override void Assemble() { + new LiteralAssemblerCode("DebugStub_Const_VidBase equ 0xB8000"); new LiteralAssemblerCode("DebugStub_Cls:"); - new LiteralAssemblerCode("Mov ESI, 0xB8000"); + new LiteralAssemblerCode("Mov ESI, DebugStub_Const_VidBase"); new LiteralAssemblerCode("DebugStub_Cls_BeginLoop:"); - new LiteralAssemblerCode("Mov AL, 0x00"); - new LiteralAssemblerCode("Mov [ESI + 0], AL"); + new LiteralAssemblerCode("Mov dword [ESI + 0], 0x00"); new LiteralAssemblerCode("Inc ESI"); - new LiteralAssemblerCode("Mov AL, 0x0A"); - new LiteralAssemblerCode("Mov [ESI + 0], AL"); + new LiteralAssemblerCode("Mov dword [ESI + 0], 0x0A"); new LiteralAssemblerCode("Inc ESI"); new LiteralAssemblerCode("Cmp ESI, 0xB8FA0"); new LiteralAssemblerCode("JB DebugStub_Cls_BeginLoop"); @@ -24,16 +23,18 @@ namespace Cosmos.Debug.DebugStub { new LiteralAssemblerCode("Ret"); new LiteralAssemblerCode("DebugStub_DisplayWaitMsg:"); new LiteralAssemblerCode("Mov ESI, DebugWaitMsg"); - new LiteralAssemblerCode("Mov EDI, 0xB8000"); + new LiteralAssemblerCode("Mov EDI, DebugStub_Const_VidBase"); new LiteralAssemblerCode("Add EDI, 1640"); - new LiteralAssemblerCode("DebugStub_DisplayWaitMsg_ReadChar:"); - new LiteralAssemblerCode("Mov AL, [ESI + 0]"); + new LiteralAssemblerCode("Mov AL, 1"); + new LiteralAssemblerCode("DebugStub_DisplayWaitMsg_Block1Begin:"); new LiteralAssemblerCode("Cmp AL, 0"); - new LiteralAssemblerCode("JE DebugStub_DisplayWaitMsg_Exit"); - new LiteralAssemblerCode("Inc ESI"); + new LiteralAssemblerCode("JE DebugStub_DisplayWaitMsg_Block1End"); + new LiteralAssemblerCode("Mov AL, [ESI + 0]"); new LiteralAssemblerCode("Mov [EDI + 0], AL"); + new LiteralAssemblerCode("Inc ESI"); new LiteralAssemblerCode("Add EDI, 2"); - new LiteralAssemblerCode("Jmp DebugStub_DisplayWaitMsg_ReadChar"); + new LiteralAssemblerCode("jmp DebugStub_DisplayWaitMsg_Block1Begin"); + new LiteralAssemblerCode("DebugStub_DisplayWaitMsg_Block1End:"); new LiteralAssemblerCode("DebugStub_DisplayWaitMsg_Exit:"); new LiteralAssemblerCode("Ret"); } diff --git a/source2/Compiler/Cosmos.Compiler.DebugStub/Screen.xs b/source2/Compiler/Cosmos.Compiler.DebugStub/Screen.xs index 70105a46c..bbabef422 100644 --- a/source2/Compiler/Cosmos.Compiler.DebugStub/Screen.xs +++ b/source2/Compiler/Cosmos.Compiler.DebugStub/Screen.xs @@ -1,18 +1,18 @@ Group DebugStub +const VidBase = $B8000 + function Cls { // VidBase - ESI = $B8000 + ESI = #VidBase BeginLoop: // Text - AL = $00 - ESI[0] = AL + ESI[0] = $00 ESI++ // Colour - AL = $0A - ESI[0] = AL + ESI[0] = $0A ESI++ // End of Video Area @@ -27,17 +27,17 @@ function DisplayWaitMsg { ESI = @..DebugWaitMsg - // VidBase - EDI = $B8000 + EDI = #VidBase // 10 lines down, 20 cols in (10 * 80 + 20) * 2) EDI + 1640 // Read and copy string till 0 terminator -ReadChar: - AL = ESI[0] - if AL = 0 return - ESI++ - EDI[0] = AL - EDI + 2 - Goto ReadChar + AL = 1 + while AL != 0 { + //while ESI[0] != 0 { + AL = ESI[0] + EDI[0] = AL + ESI++ + EDI + 2 + } } diff --git a/source2/Compiler/Cosmos.XSharp/Parser.cs b/source2/Compiler/Cosmos.XSharp/Parser.cs index 239c0b435..7202454a1 100644 --- a/source2/Compiler/Cosmos.XSharp/Parser.cs +++ b/source2/Compiler/Cosmos.XSharp/Parser.cs @@ -30,9 +30,9 @@ namespace Cosmos.Compiler.XSharp { + ",JUMP" + ",PORT" + ",RETURN,RETURNINTERRUPT,REPEAT" - + ",TIMES" - + ",VAR" - + ",WORD" + + ",times" + + ",var" + + ",word,while" ).ToUpper().Split(mComma); public static readonly string[] Registers; diff --git a/source2/Compiler/Cosmos.XSharp/TokenPatterns.cs b/source2/Compiler/Cosmos.XSharp/TokenPatterns.cs index cd5bfe9c6..e52d0baac 100644 --- a/source2/Compiler/Cosmos.XSharp/TokenPatterns.cs +++ b/source2/Compiler/Cosmos.XSharp/TokenPatterns.cs @@ -27,10 +27,25 @@ namespace Cosmos.Compiler.XSharp { protected List mPatterns = new List(); protected string mGroup; protected bool mInIntHandler; + protected string[] mCompareOps; + protected List mCompares = new List(); + protected TokenList mBlockStarter = null; protected List mBlock = null; + protected int mBlockLabel = 0; public TokenPatterns() { + mCompareOps = "< > = != <= >= 0".Split(" ".ToCharArray()); + foreach (var xComparison in mCompareOps) { + if (xComparison != "0") { + mCompares.Add("_REG " + xComparison + " 123"); + mCompares.Add("_REG " + xComparison + " _REG"); + mCompares.Add("_REG " + xComparison + " _ABC"); + mCompares.Add("_REG " + xComparison + " #_ABC"); + mCompares.Add("_ABC " + xComparison + " #_ABC"); + } + } + AddPatterns(); } @@ -55,6 +70,9 @@ namespace Cosmos.Compiler.XSharp { protected string FuncLabel(string aLabel) { return mGroup + "_" + mFuncName + "_" + aLabel; } + protected string BlockLabel(string aLabel) { + return FuncLabel("Block" + mBlockLabel + aLabel); + } protected string GetLabel(Token aToken) { if (aToken.Type != TokenType.AlphaNum && !aToken.Matches("Exit")) { throw new Exception("Label must be AlphaNum."); @@ -81,6 +99,14 @@ namespace Cosmos.Compiler.XSharp { mFuncExitFound = false; } + protected void StartBlock(TokenList aTokens, bool aIsCollector) { + mBlockStarter = aTokens; + if (aIsCollector) { + mBlock = new List(); + } + mBlockLabel++; + } + protected void EndFunc(ref List rCode) { if (!mFuncExitFound) { rCode.Add(mGroup + "_" + mFuncName + "_Exit:"); @@ -121,30 +147,73 @@ namespace Cosmos.Compiler.XSharp { return xResult; } + protected string GetCompare(TokenList aTokens, int aStart) { + string xLeft = aTokens[1].Value; + if (aTokens[1].Type == TokenType.AlphaNum) { + // Hardcoded to dword for now + xLeft = "dword [" + GetLabel(aTokens[1]) + "]"; + } + + string xRight = aTokens[3].Value; + if (aTokens[3].Type == TokenType.AlphaNum) { + xRight = "[" + GetLabel(aTokens[3]) + "]"; + } else if (aTokens[3].Value == "#") { + xRight = ConstLabel(aTokens[4]); + } + return "Cmp " + xLeft + ", " + xRight; + } + protected string GetJump(Token aToken) { - if (aToken.Value == "<") { + return GetJump(aToken, false); + } + protected string GetJump(Token aToken, bool aInvert) { + string xOp = aToken.Value; + + if (aInvert) { + if (xOp == "<") { + xOp = ">="; + } else if (xOp == ">") { + xOp = "<="; + } else if (xOp == "=") { + xOp = "!="; + } else if (xOp == "0") { + // Same as JE, but implies intent in .asm better + xOp = "!0"; + } else if (xOp == "!=") { + xOp = "="; + } else if (xOp == "<=") { + xOp = ">"; + } else if (xOp == ">=") { + xOp = "<"; + } else { + throw new Exception("Unrecognized symbol in conditional: " + xOp); + } + } + + if (xOp == "<") { return "JB"; // unsigned - } else if (aToken.Value == ">") { + } else if (xOp == ">") { return "JA"; // unsigned - } else if (aToken.Value == "=") { + } else if (xOp == "=") { return "JE"; - } else if (aToken.Value == "0") { + } else if (xOp == "0") { // Same as JE, but implies intent in .asm better return "JZ"; - } else if (aToken.Value == "!=") { + } else if (xOp == "!=") { return "JNE"; - } else if (aToken.Value == "<=") { + } else if (xOp == "!0") { + // Same as JNE, but implies intent in .asm better + return "JNZ"; + } else if (xOp == "<=") { return "JBE"; // unsigned - } else if (aToken.Value == ">=") { + } else if (xOp == ">=") { return "JAE"; // unsigned } else { - throw new Exception("Unrecognized symbol in conditional: " + aToken.Value); + throw new Exception("Unrecognized symbol in conditional: " + xOp); } } protected void AddPatterns() { - var xSpace = " ".ToCharArray(); - AddPattern("! Move EAX, 0", "{0}"); AddPattern("// Comment", delegate(TokenList aTokens, ref List rCode) { @@ -194,6 +263,16 @@ namespace Cosmos.Compiler.XSharp { rCode.Add("mAssembler.DataMembers.Add(new DataMember(" + Quoted(GetLabel(aTokens[1])) + ", new " + aTokens[2].Value + "[" + aTokens[4].Value + "]));"); }); + foreach (var xCompare in mCompares) { + // 0 1 2 3 4 + AddPattern("while " + xCompare + " {", delegate(TokenList aTokens, ref List rCode) { + StartBlock(aTokens, false); + rCode.Add(BlockLabel("Begin") + ":"); + rCode.Add(GetCompare(aTokens, 1)); + rCode.Add(GetJump(aTokens[2], true) + " " + BlockLabel("End")); + }); + } + // Must test separate since !0 is two tokens AddPattern("if !0 goto _ABC", delegate(TokenList aTokens, ref List rCode) { rCode.Add("JNZ " + GetLabel(aTokens[4])); @@ -201,45 +280,8 @@ namespace Cosmos.Compiler.XSharp { AddPattern("if !0 return", delegate(TokenList aTokens, ref List rCode) { rCode.Add("JNZ " + FuncLabel("Exit")); }); - foreach (var xComparison in "< > = != <= >= 0".Split(xSpace)) { - foreach (var xTail in "goto _ABC|return".Split("|".ToCharArray())) { - if (xComparison != "0") { - AddPattern(new string[] { - //0 1 2 3 4 - "if _REG " + xComparison + " 123 " + xTail, - "if _REG " + xComparison + " _REG " + xTail, - "if _REG " + xComparison + " _ABC " + xTail, - // 3 4 5 - "if _REG " + xComparison + " #_ABC " + xTail, - "if _ABC " + xComparison + " #_ABC " + xTail, - }, delegate(TokenList aTokens, ref List rCode) { - int xTailIdx = 4; - - string xLeft = aTokens[1].Value; - if (aTokens[1].Type == TokenType.AlphaNum) { - // Hardcoded to dword for now - xLeft = "dword [" + GetLabel(aTokens[1]) + "]"; - } - - string xRight = aTokens[3].Value; - if (aTokens[3].Type == TokenType.AlphaNum) { - xRight = "[" + GetLabel(aTokens[3]) + "]"; - } else if (aTokens[3].Value == "#") { - xRight = ConstLabel(aTokens[4]); - xTailIdx = 5; - } - rCode.Add("Cmp " + xLeft + ", " + xRight); - - string xLabel; - if (aTokens[xTailIdx].Matches("return")) { - xLabel = FuncLabel("Exit"); - } else { - xLabel = GetLabel(aTokens[xTailIdx + 1]); - } - - rCode.Add(GetJump(aTokens[2]) + " " + xLabel); - }); - } + foreach (var xTail in "goto _ABC|return".Split("|".ToCharArray())) { + foreach (var xComparison in mCompareOps) { AddPattern("if " + xComparison + " " + xTail, delegate(TokenList aTokens, ref List rCode) { string xLabel; if (string.Equals(aTokens[2].Value, "exit", StringComparison.InvariantCultureIgnoreCase)) { @@ -250,6 +292,22 @@ namespace Cosmos.Compiler.XSharp { rCode.Add(GetJump(aTokens[1]) + " " + xLabel); }); } + foreach (var xCompare in mCompares) { + // 0 1 2 3 4 + AddPattern("if " + xCompare + " " + xTail, delegate(TokenList aTokens, ref List rCode) { + int xTailIdx = aTokens[3].Value == "#" ? 5 : 4; + rCode.Add(GetCompare(aTokens, 1)); + + string xLabel; + if (aTokens[xTailIdx].Matches("return")) { + xLabel = FuncLabel("Exit"); + } else { + xLabel = GetLabel(aTokens[xTailIdx + 1]); + } + + rCode.Add(GetJump(aTokens[2]) + " " + xLabel); + }); + } } AddPattern("_REG ?= 123", "Cmp {0}, {2}"); @@ -405,19 +463,27 @@ namespace Cosmos.Compiler.XSharp { AddPattern("_REG--", "Dec {0}"); AddPattern("}", delegate(TokenList aTokens, ref List rCode) { - if (mBlock == null) { + // Use mBlockStarter, not mBlock because not all blocks use mBlock to collect + // (repeat does for example, but while does not) + if (mBlockStarter == null) { EndFunc(ref rCode); } else { - if (mBlockStarter.PatternMatches("repeat 4 times {")) { + if (mBlockStarter[0].Matches("repeat")) { int xCount = int.Parse(mBlockStarter[1].Value); for (int i = 1; i <= xCount; i++) { rCode.AddRange(mBlock); } - mBlockStarter = null; - mBlock = null; + + } else if (mBlockStarter[0].Matches("while")) { + rCode.Add("jmp " + BlockLabel("Begin")); + rCode.Add(BlockLabel("End") + ":"); + } else { throw new Exception("Unknown block starter."); } + + mBlockStarter = null; + mBlock = null; } }); @@ -430,8 +496,7 @@ namespace Cosmos.Compiler.XSharp { }); AddPattern("Repeat 4 times {", delegate(TokenList aTokens, ref List rCode) { - mBlockStarter = aTokens; - mBlock = new List(); + StartBlock(aTokens, true); }); AddPattern("Interrupt _ABC {", delegate(TokenList aTokens, ref List rCode) { diff --git a/source2/Users/Kudzu/Kudzu-Notes.html b/source2/Users/Kudzu/Kudzu-Notes.html index e8e33ce53..7364b14d3 100644 --- a/source2/Users/Kudzu/Kudzu-Notes.html +++ b/source2/Users/Kudzu/Kudzu-Notes.html @@ -42,11 +42,18 @@
  • Complete X# Port
      -
    • PreserveRegisters
    • -
    • look for todo in cmdsend.xs
    • -
    • AL = ComRead8()
    • -
    • ComWrite(AL)
    • +
    • Screen.XS
        +
      • Loop in top
      • +
      • //while ESI[0] != 0 {
      +
    • +
    • Builder restores
    • +
    +
      +
    • PreserveRegisters
    • +
    • AL = ComRead8()
    • +
    • ComWrite(AL)
    • +
    • X# ProcessCmds.CS, ProcessCmdBatch - #TODO Make this a do while loop. Test