Example #1
0
        public AsmCode(PascalProgram program)
        {
            GenerateSubprogramHeader(program.Block);
            var mainLabel = new AsmLabel("main");

            Add(mainLabel);
            program.Block.Generate(this);
            Add(new AsmSpecial("exit"));
            GenerateSubprograms(program.Block);
            Add(new AsmSpecial($"END {mainLabel.ToArgString()}"));
        }
Example #2
0
        private AsmLabel PushParams(FieldInfo l, FieldInfo r, LoadClasses load, out AsmLabel trueLabel,
                                    out AsmLabel returnLabel)
        {
            trueLabel   = new AsmLabel("{asm3}");
            returnLabel = new AsmLabel("{ret}" + CPUUInt.u);
            pushParam(load, l.Handle, true, IsSigned(l.Return), l.Return == Assembly.Long);

            if (r.Return != Assembly.Long)
            {
                pushParam(load, r.Handle, false, IsSigned(r.Return), false);
            }
            return(new AsmLabel("{asm1}"));
        }
Example #3
0
        public override void Generate(AsmCode asmCode, SymTable symTable)
        {
            long id = asmCode.CurrentID++;

            StartLabel = new AsmLabel($"Cycle{id}Start");
            EndLabel   = new AsmLabel($"Cycle{id}End");
            AsmLabel bodyLabel = new AsmLabel($"Cycle{id}Body");
            var      v         = (VarSymbol)symTable.LookUp(Childs[0].Value.ToString());

            Childs[1].Generate(asmCode, symTable);                    // Initial value
            ((IdentNode)Childs[0]).GenerateLValue(asmCode, symTable); // Cycle counter
            asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Eax);
            asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Ebx);

            asmCode.Add(AsmCmd.Cmd.Sub, AsmReg.Reg.Ebx, 1);

            asmCode.Add(
                AsmCmd.Cmd.Mov,
                new AsmOffset(0, v.Type.Size, AsmReg.Reg.Eax),
                AsmReg.Reg.Ebx);
            // Value initialized
            asmCode.Add(AsmCmd.Cmd.Jmp, StartLabel);
            asmCode.Add(bodyLabel);
            asmCode.LoopStack.Push(this);
            Childs[3].Generate(asmCode, symTable); // Cycle body
            asmCode.LoopStack.Pop();

            asmCode.Add(StartLabel);

            ((IdentNode)Childs[0]).GenerateLValue(asmCode, symTable);
            asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Eax);
            asmCode.Add(AsmCmd.Cmd.Inc, new AsmOffset(0, v.Type.Size, AsmReg.Reg.Eax));


            Childs[2].Generate(asmCode, symTable); // Cycle counter target

            ((IdentNode)Childs[0]).GenerateLValue(asmCode, symTable);
            asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Eax);

            asmCode.Add(
                AsmCmd.Cmd.Mov,
                AsmReg.Reg.Eax,
                new AsmOffset(0, v.Type.Size, AsmReg.Reg.Eax));
            asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Ebx);
            asmCode.Add(AsmCmd.Cmd.Cmp, AsmReg.Reg.Eax, AsmReg.Reg.Ebx);
            asmCode.Add(AsmCmd.Cmd.Jle, bodyLabel);
            asmCode.Add(EndLabel);
        }
Example #4
0
        private static void Return(FieldInfo ret, LoadClasses load, AsmLabel returnTrue, AsmLabel returnFalse, AsmLabel @return, bool OrEqual)
        {
//Return True
            load.Optimum.SetLabel(returnTrue);
            load.Add("mov", RegInfo.eax, ConstInfo.True);
//Return False
            load.Optimum.SetLabel(returnFalse);
            load.Add("xor", RegInfo.eax, RegInfo.eax);
            load.Optimum.SetGoto("jmp", @return);
//Return
            load.Optimum.SetLabel(@return);
            if (OrEqual)
            {
                load.Add("test", RegInfo.eax, RegInfo.eax);
                load.Add("sete", RegInfo.eax);
            }
            load.Add("mov", ret, RegInfo.eax);
        }
Example #5
0
        public override void Generate(AsmCode asmCode, SymTable symTable)
        {
            long id = asmCode.CurrentID++;

            StartLabel = new AsmLabel($"Cycle{id}Start");
            EndLabel   = new AsmLabel($"Cycle{id}End");
            asmCode.Add(StartLabel);
            asmCode.LoopStack.Push(this);
            foreach (var child in Childs)
            {
                child.Generate(asmCode, symTable);
            }
            asmCode.LoopStack.Pop();
            Condition.Generate(asmCode, symTable);
            asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Eax);
            asmCode.Add(AsmCmd.Cmd.Cmp, AsmReg.Reg.Eax, 0);
            asmCode.Add(AsmCmd.Cmd.Je, StartLabel);
            asmCode.Add(EndLabel);
        }
Example #6
0
        public override void Generate(AsmCode asmCode, SymTable symTable)
        {
            long id        = asmCode.CurrentID++;
            var  elseLabel = new AsmLabel($"Condtion{id}Else");
            var  endLabel  = new AsmLabel($"Condtion{id}End");

            Childs[0].Generate(asmCode, symTable);
            asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Eax);
            asmCode.Add(AsmCmd.Cmd.Cmp, AsmReg.Reg.Eax, 0);
            asmCode.Add(AsmCmd.Cmd.Je, elseLabel);
            Childs[1].Generate(asmCode, symTable);
            asmCode.Add(AsmCmd.Cmd.Jmp, endLabel);
            asmCode.Add(elseLabel);
            if (Childs.Count > 2)
            {
                Childs[2].Generate(asmCode, symTable);
            }
            asmCode.Add(endLabel);
        }
Example #7
0
        private static FieldInfo lt_gt(FieldInfo ret, FieldInfo l, FieldInfo r, LoadClasses load, bool is_lt_gt)
        {
            string jm1, jm2, jm3;

            if (is_lt_gt)
            {
                jm1 = "jg";
                jm2 = "jl";
                jm3 = "jb";
            }
            else
            {
                jm1 = "jl";
                jm2 = "jg";
                jm3 = "ja";
            }
            AsmLabel falseLabel  = new AsmLabel("{asm1}"),
                     trueLabel   = new AsmLabel("{asm3}"),
                     returnLabel = new AsmLabel("{ret}" + CPUUInt.u);

            var r_islong = r.Return == Assembly.Long;

            pushParam(load, l.Handle, true, IsSigned(l.Return), l.Return == Assembly.Long);
            if (!r_islong)
            {
                pushParam(load, r.Handle, false, IsSigned(r.Return), false);
            }

            load.Add("cmp", Reg.edx, !r_islong ? Reg.ebx : r.GetHandle(4));
            load.Optimum.SetGoto(jm1, trueLabel, load, cByte.Clone());
            load.Optimum.SetGoto(jm2, falseLabel, load, cByte.Clone());
            load.Add("cmp", RegInfo.eax, !r_islong ? RegInfo.ecx : r);
            load.Optimum.SetGoto(jm3, trueLabel, load, cByte.Clone());
            load.Optimum.SetLabel(falseLabel);
            load.Add("xor", RegInfo.eax, RegInfo.eax);
            load.Optimum.SetGoto("jmp", returnLabel, load, new Operand(0xFF, DataType.Byte));
            load.Optimum.SetLabel(trueLabel);
            load.Add("mov", Reg.eax, new Operand(1, DataType.Byte));
            load.Optimum.SetLabel(returnLabel);
            load.Add("mov", ret, RegInfo.eax);
            return(ret);
        }
Example #8
0
        public override void Generate(AsmCode asmCode, SymTable symTable)
        {
            long id = asmCode.CurrentID++;

            StartLabel = new AsmLabel($"Cycle{id}Start");
            EndLabel   = new AsmLabel($"Cycle{id}End");
            AsmLabel bodyLabel = new AsmLabel($"Cycle{id}Body");

            asmCode.Add(AsmCmd.Cmd.Jmp, StartLabel);
            asmCode.Add(bodyLabel);
            asmCode.LoopStack.Push(this);
            Childs[0].Generate(asmCode, symTable);
            asmCode.LoopStack.Pop();
            asmCode.Add(StartLabel);
            Condition.Generate(asmCode, symTable);
            asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Eax);
            asmCode.Add(AsmCmd.Cmd.Cmp, AsmReg.Reg.Eax, 0);
            asmCode.Add(AsmCmd.Cmd.Jne, bodyLabel);
            asmCode.Add(EndLabel);
        }
Example #9
0
 private static void FPReturn(FieldInfo ret, LoadClasses load, string cn, AsmLabel returnTrue, AsmLabel returnFalse, AsmLabel @return, bool OrEqual)
 {
     load.Add("cmp", RegInfo.eax, RegInfo.ecx);
     load.Optimum.SetGoto(cn, returnTrue);
     Return(ret, load, returnTrue, returnFalse, @return, OrEqual);
 }
Example #10
0
 private static FieldInfo Compile(FieldInfo ret, FieldInfo l, FieldInfo r, LoadClasses load, string o, AsmLabel returnFalse, string oc, AsmLabel returnTrue, string cn, AsmLabel @return, bool orEqual, bool IsEquality = false)
 {
     PushParams(load, l, r);
     load.Add("cmp", RegInfo.edx, RegInfo.ebx);
     load.Optimum.SetGoto(o, returnFalse);
     if (!IsEquality)
     {
         load.Optimum.SetGoto(oc, returnTrue);
     }
     FPReturn(ret, load, cn, returnTrue, returnFalse, @return, orEqual);
     return(ret);
 }
Example #11
0
        protected override FieldInfo BeginCompile(MethodInfo method, FieldInfo ret, FieldInfo l, FieldInfo r,
                                                  LoadClasses load, Scop scop)
        {
            var    lsigned = IsSigned(l);
            var    rsigned = IsSigned(r);
            var    returnTrue = new AsmLabel("{lasm" + u++ + "}");
            var    returnFalse = new AsmLabel("{lasm" + u++ + "}");
            var    @return = new AsmLabel("{lasm" + u++ + "}");
            string o = "", oc = "";
            var    cnc = "";

            switch (method.Name)
            {
                #region +-&^|
            case "opers":
                return(UintSOperation(ret, l, r, load, o, oc));

            case "+":
                o  = "add";
                oc = "adc";
                goto case "opers";

            case "-":
                o  = "sub";
                oc = "sbb";
                goto case "opers";

            case "&":
                oc = o = "and";
                goto case "opers";

            case "^":
                oc = o = "xor";
                goto case "opers";

            case "|":
                oc = o = "or";
                goto case "opers";
                #endregion

                #region */

            case "*":
                o = "imul";
                goto case "*/";

            case "/":
                o = "idiv";
                goto case "*/";

            case "*/":
                if (lsigned == rsigned)
                {
                    load.Add(o, l, r);
                    load.Add("mov", ret, RegInfo.eax);
                    return(ret);
                }
                if (lsigned)
                {
                    CallManager.swap(ref l, ref r);
                }
                ConvertToLong(load, l, true);
                load.Add("push", RegInfo.edx);
                load.Add("push", RegInfo.eax);
                ConvertToLong(load, r, true);
                load.Add("push", RegInfo.edx);
                load.Add("push", RegInfo.eax);
                load.Optimum.Call(method);
                Move(load, ret, Reg.eax, Reg.eax);
                break;

                #endregion

                #region none

            case ">>":
                break;

            case "<<":
                break;

            case "++":
            case "--":
                load.Add("mov", RegInfo.eax, l);
                load.Add(method.Name == "++" ? "inc" : "dec", RegInfo.eax);
                load.Add("mov", l, RegInfo.eax);
                return(ret);

                #endregion

                #region       ==  !=
            case "==!=":
                if (lsigned != rsigned)
                {
                    return(Compile(ret, l, r, load, o, returnFalse, oc, returnTrue, "je", @return, false, true));
                }
                load.Add("mov", RegInfo.eax, l);
                load.Add("cmp", RegInfo.eax, r);
                load.Add(cnc, RegInfo.eax);
                load.Add("mov", ret, RegInfo.eax);
                return(ret);

            case "==":
                cnc = "sete";
                o   = "jne";
                goto case "==!=";

            case "!=":
                o   = "je";
                cnc = "setne";
                goto case "==!=";

                #endregion
                #region <==>
            case ">=":

                cnc = "sete";
                if (lsigned != rsigned)
                {
                    return(Compile(ret, l, r, load, "jg", returnFalse, "jl", returnTrue, "jb", @return, true));
                }
                goto case "<==>";

            case "<==>":
                load.Add("mov", RegInfo.eax, l);
                load.Add("cmp", RegInfo.eax, r);
                if (cnc == "sete")
                {
                    load.Add("sbb", RegInfo.eax, RegInfo.eax);
                }
                load.Add(cnc, RegInfo.eax);
                load.Add("mov", ret, RegInfo.eax);
                break;

            case "<=":
                cnc = "setbe";
                if (lsigned != rsigned)
                {
                    return(Compile(ret, l, r, load, "jl", returnFalse, "jb", returnTrue, "ja", @return, true));
                }
                goto case "<==>";

                #endregion
            case ">":
                #region >
                if (lsigned == rsigned)
                {
                    load.Add("mov", RegInfo.eax, l);
                    load.Add("cmp", RegInfo.eax, r);
                    load.Add("seta", RegInfo.eax);
                    load.Add("mov", ret, RegInfo.eax);
                    return(ret);
                }
                return(Compile(ret, l, r, load, "jl", returnFalse, "jg", returnTrue, "ja", @return, false));

                #endregion

            case "<":
                #region >
                if (lsigned == rsigned)
                {
                    load.Add("mov", RegInfo.eax, l);
                    load.Add("cmp", RegInfo.eax, r);
                    load.Add("sbb", RegInfo.eax, RegInfo.eax);
                    load.Add("neg", RegInfo.eax);
                    load.Add("mov", ret, RegInfo.eax);
                    return(ret);
                }
                return(Compile(ret, l, r, load, "jg", returnFalse, "jl", returnTrue, "jb", @return, false));

                #endregion
            }
            return(ret);
        }
        private void RunJumpTestProgram(OpCode aOp,
                                        JumpType aType,
                                        bool aInvert,
                                        bool aUseLabel)
        {
            const Registers ac = Registers.AC;
            const Registers r1 = Registers.R1;
            const Registers r2 = Registers.R2;

            var expected = aInvert ? 0x321 : 0x123;

            var program = new List <CompilerIns>
            {
                // Set the accumulator to be zero.
                // This isn't strictly required as it
                // will default to zero, but just to be
                // safe.
                new CompilerIns(OpCode.MOV_LIT_REG,
                                new object[] { 0, ac })
            };

            // Calculate the value required value to ensure
            // that the jump condition is or isn't taken.
            var value = aType switch
            {
                JumpType.EQ => aInvert ? 1 : 0,
                JumpType.NEQ => aInvert ? 0 : 1,
                JumpType.LT => aInvert ? 1 : -1,
                JumpType.GT => aInvert ? -1 : 1,
                JumpType.LTE => aInvert  ? 2 : -2,
                JumpType.GTE => aInvert ? -2 : 2,
                _ => 0
            };

            object arg;
            var    argTypes = _instructionCache[aOp].ArgumentTypes;

            if (argTypes[0] == typeof(Registers))
            {
                // Set the register to the required value.
                program.Add
                (
                    new CompilerIns(OpCode.MOV_LIT_REG,
                                    new object[] { value, r1 })
                );

                // This will become the jump instruction
                // condition argument below.
                arg = r1;
            }
            else
            {
                // This will become the jump instruction
                // condition argument below.
                arg = value;
            }

            var labels = new AsmLabel[2];

            if (aUseLabel)
            {
                labels[1] = new AsmLabel("GOOD", 1);
            }

            // If we are not using labels then we will go back and
            // update the jump position below.
            // Insert a placeholder value here for the time being.
            program.Add
            (
                new CompilerIns(aOp,
                                new [] { arg, 0 },
                                labels)
            );

            // In the jump not taken (inverted) case
            // this should execute.
            program.Add
            (
                new CompilerIns(OpCode.MOV_LIT_REG,
                                new object[] { 0x321, r2 })
            );

            // Add a halt instruction to block execution
            // of the success instruction.
            program.Add(new CompilerIns(OpCode.HLT));

            if (aUseLabel)
            {
                program.Add
                (
                    new CompilerIns(OpCode.LABEL,
                                    new object[] { "GOOD" })
                );
            }
            else
            {
                // Calculate the address of the current instruction.
                // This effectively acts as a label.
                var jumpAddress =
                    CalculateDestinationAddress(program);

                // Go back and update the jump address in the instruction
                // from which the jump should or shouldn't occur.
                foreach (var entry in program)
                {
                    if (entry.Op != aOp)
                    {
                        continue;
                    }

                    entry.Args[1] = jumpAddress;
                    break;
                }
            }

            // In the jump is taken (normal) case this should execute.
            program.Add
            (
                new CompilerIns(OpCode.MOV_LIT_REG,
                                new object[] { 0x123, r2 })
            );

            // Run the test program.
            Vm.Run(QuickCompile.RawCompile(program.ToArray()));

            // Check the result.
            Assert.IsTrue
            (
                Vm.Cpu.Registers[r2] == expected,
                $"Test OpCode '{aOp}'. " +
                $"Inverted = {aInvert}, Use Label = {aUseLabel} failed " +
                "to yield the correct result."
            );
        }
Example #13
0
 public void Add(AsmCmd.Cmd cmd, AsmLabel label)
 {
     Add(new AsmJump(cmd, label));
 }
Example #14
0
 public AsmGoto(int gotoLocation, AsmLabel label)
 {
     GotoLocation = gotoLocation;
     Label        = label;
 }