示例#1
0
        public List <Instruction> CodeGen()
        {
            var code = new List <Instruction>();

            var srcreg = source.AsReg();
            var tgtreg = target.AsReg();

            if (srcreg == null || (srcreg != null && tgtreg != null))
            {
                code.AddRange(source.FetchToReg(tgtreg ?? RegVRef.rScratchTab));
            }
            if (tgtreg == null)
            {
                code.AddRange(target.PutFromReg(srcreg ?? RegVRef.rScratchTab));
            }

            return(code);
        }
示例#2
0
        public List <Instruction> FetchToReg(RegVRef dest)
        {
            var code = new List <Instruction>();
            var cmd  = Command.AsReg();

            if (cmd == null)
            {
                cmd = RegVRef.rScratchTab;
                code.AddRange(Command.FetchToReg(cmd));
            }

            var data = Data.AsReg();

            if (data == null)
            {
                data = cmd == RegVRef.rScratchTab ? RegVRef.rScratchInts : RegVRef.rScratchTab;
                if (data == RegVRef.rScratchInts)
                {
                    FieldSRef.ResetScratchInts();
                }
                code.AddRange(Data.FetchToReg(data));
            }

            code.Add(new Instruction
            {
                opcode = Opcode.ConMan,
                op1    = cmd,
                op2    = data,
                dest   = dest,
            });

            if (data == RegVRef.rScratchInts)
            {
                code.AddRange(data.PutFromReg(RegVRef.rNull));
            }

            return(code);
        }
示例#3
0
        public List <Instruction> CodeGen(int truejump, int falsejump)
        {
            if (Op == CompSpec.Equal)
            {
                var b = new List <Instruction>();

                b.AddRange(V1.FetchToReg(RegVRef.rScratchTab));

                var r2 = V2.AsReg();
                if (r2 == null)
                {
                    // if V2 isn't already a register, borrow rScratchInts temporarily to fetch it
                    r2 = RegVRef.rScratchInts;
                    b.Add(new Push(RegVRef.rScratchInts));
                    b.AddRange(V2.FetchToReg(r2));
                }

                b.Add(new Instruction
                {
                    opcode = Opcode.EachMulV,
                    acc    = true,
                    dest   = RegVRef.rScratchTab,
                    op1    = r2,
                    op2    = FieldSRef.Imm2(),
                    imm2   = new IntSExpr(-1),
                });

                // restore rScratchInts if needed
                if (r2 == RegVRef.rScratchInts)
                {
                    b.Add(new Pop(RegVRef.rScratchInts));
                }
                var flag = FieldSRef.ScratchInt();

                // ensure flag is clear, in case this branch is used in a loop and is coming around again to reuse it
                b.Add(new Clear(flag));

                // set flag if every=0
                b.Add(new Instruction
                {
                    opcode = Opcode.EveryEqS2S1,
                    op1    = RegVRef.rScratchTab,
                    dest   = flag,
                    acc    = true,
                });


                b.Add(new Instruction
                {
                    opcode = Opcode.Branch,
                    op1    = flag,
                    rjmpeq = falsejump,
                    rjmplt = falsejump,                     // lt shouldn't happen at all, but...
                    rjmpgt = truejump,
                });

                return(b);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
示例#4
0
        public List <Instruction> FetchToReg(RegVRef dest)
        {
            var     code = new List <Instruction>();
            RegVRef other;

            if (dest == V1.AsReg())
            {
                other = V2.AsReg();
                if (other == null)
                {
                    other = RegVRef.rScratchTab;
                    code.AddRange(V2.FetchToReg(other));
                }
            }
            else if (dest == V2.AsReg())
            {
                other = V1.AsReg();
                if (other == null)
                {
                    other = RegVRef.rScratchTab;
                    code.AddRange(V1.FetchToReg(other));
                }
            }
            else
            {
                code.AddRange(V1.FetchToReg(dest));
                other = V2.AsReg();
                if (other == null)
                {
                    other = RegVRef.rScratchTab;
                    code.AddRange(V2.FetchToReg(other));
                }
            }

            switch (Op)
            {
            case ArithSpec.Add:
                code.Add(new Instruction {
                    opcode = Opcode.EachAddV, acc = true, op1 = other, dest = dest
                });
                break;

            case ArithSpec.Subtract:
                code.Add(new Instruction {
                    opcode = Opcode.EachMulV, acc = true, op1 = other, op2 = FieldSRef.Imm2(), imm2 = new IntSExpr(-1), dest = dest
                });
                break;

            case ArithSpec.Multiply:
                code.Add(new Instruction {
                    opcode = Opcode.VMul, op1 = dest, op2 = other, dest = dest
                });
                break;

            case ArithSpec.Divide:
                code.Add(new Instruction {
                    opcode = Opcode.VDiv, op1 = dest, op2 = other, dest = dest
                });
                break;

            default:
                throw new NotImplementedException();
            }

            return(code);
        }