コード例 #1
0
ファイル: Emitter.cs プロジェクト: meikeric/DotCopter
        public void EmitLoadAddress(Format12OpCode opCode, LowRegister targetRegister, int target, bool thumbAdjustment)
        {
            var offset = target - ((CurrentAddress + 4) & ~2);

            if (offset >= 0)
            {
                Emit(opCode, targetRegister, target);
                if (thumbAdjustment)
                {
                    Emit(Format3OpCode.ADD, targetRegister, 1);
                }
            }
            else
            {
                //While the Format12 instruction will clear the 1 bit of the PC, this code does not
                var remainder = -(target - (CurrentAddress + 4));
                if (thumbAdjustment)
                {
                    --remainder;
                }
                Emit(Format5OpCode.MOV, targetRegister, Register.PC);
                while (remainder != 0)
                {
                    var amountToUse = Math.Min(remainder, 255);
                    Emit(Format3OpCode.SUB, targetRegister, (byte)remainder);
                    remainder -= amountToUse;
                }
            }
        }
コード例 #2
0
ファイル: Emitter.cs プロジェクト: meikeric/DotCopter
        public void Emit(Format1OpCode opCode, LowRegister rd, LowRegister rs, byte immediate)
        {
            CheckRange(immediate, 0, 31);
            var fluentComment = opCode.ToHumanReadable().MyConcat(" ", rd, ",", rs, ",#", immediate);

            EmitHelper(rd, 1, fluentComment, 0, 3, (int)opCode, 2, immediate, 5, rs.Index, 3, rd.Index, 3);
        }
コード例 #3
0
        private static LowRegister ProposeRegisterForValue(IReadable valueResult, LowRegister baseReg, LowRegister offsetReg)
        {
            var f        = FuncBuilder.Instance;
            var scratch0 = f.Scratch0;

            if (baseReg.Index != scratch0.Index)
            {
                return(scratch0);
            }

            var scratch1 = f.Scratch1;

            if (offsetReg.Index != scratch1.Index)
            {
                return(scratch1);
            }
            var reference = valueResult as IReference;

            if (reference != null)
            {
                var lowRegister = reference.GetRepresentation() as LowRegister;
                if (lowRegister != null)
                {
                    return(lowRegister);
                }
            }
            return(null);
        }
コード例 #4
0
ファイル: Emitter.cs プロジェクト: meikeric/DotCopter
        private void Format2Helper(Format2OpCode opCode, int immediateBit,
                                   LowRegister rd, LowRegister rs, int rnBits, string suffix)
        {
            var fluentComment = opCode.ToHumanReadable().MyConcat(" ", rd, ",", rs, ",", suffix);

            EmitHelper(rd, 2, fluentComment, 3, 5, immediateBit, 1, (int)opCode, 1, rnBits, 3, rs.Index, 3, rd.Index, 3);
        }
コード例 #5
0
ファイル: Emitter.cs プロジェクト: meikeric/DotCopter
        public void Emit(Format9OpCode opCode, LowRegister rsd, LowRegister rb, byte offset)
        {
            CheckRange(offset, 0, 31);
            var multiplier    = (opCode == Format9OpCode.LDR || opCode == Format9OpCode.STR) ? "*4" : "";
            var fluentComment = opCode.ToHumanReadable().MyConcat(" ", rsd, ",[", rb, ",#", offset + multiplier, "]");

            EmitHelper(rsd, 9, fluentComment, 3, 3, (int)opCode, 2, offset, 5, rb.Index, 3, rsd.Index, 3);
        }
コード例 #6
0
ファイル: Emitter.cs プロジェクト: meikeric/DotCopter
        public void Emit(Format11OpCode opCode, LowRegister rd, uint unsigned10BitOffset)
        {
            CheckRange((int)unsigned10BitOffset, 0, 1023, 3);
            var fluentComment = opCode.ToHumanReadable().MyConcat(" ", rd, ",[SP,#", unsigned10BitOffset, "]");
            var offsetBits    = (unsigned10BitOffset >> 2) & 0xff;

            EmitHelper(rd, 11, fluentComment, 9, 4, (int)opCode, 1, rd.Index, 3, (int)offsetBits, 8);
        }
コード例 #7
0
ファイル: Emitter.cs プロジェクト: meikeric/DotCopter
        public void Emit(Format12OpCode opCode, LowRegister rd, int target)
        {
            var offset = target - ((CurrentAddress + 4) & ~2);

            CheckRange(offset, 0, 1023, 3);
            var fluentComment = opCode.ToHumanReadable().MyConcat(" ", rd, ",#0x", ((short)target).ToHex());
            var offsetBits    = (offset >> 2) & 0xff;

            EmitHelper(rd, 12, fluentComment, 10, 4, (int)opCode, 1, rd.Index, 3, offsetBits, 8);
        }
コード例 #8
0
ファイル: Emitter.cs プロジェクト: meikeric/DotCopter
        public void Emit(Format6OpCode opCode, LowRegister rd, int target)
        {
            var offset = (uint)(target - ((CurrentAddress + 4) & ~2));

            CheckRange(target, 0, 1023, 3);
            var fluentComment = "LDR ".MyConcat(rd, ",[PC, #0x", ((short)target).ToHex(), "]");
            var offsetBits    = offset >> 2;

            EmitHelper(rd, 6, fluentComment, 9, 5, rd.Index, 3, (int)offsetBits, 8);
        }
コード例 #9
0
        public FuncBuilderHints RunOptimizer(bool scratch0Used, bool scratch1Used, out bool runAgain)
        {
            var liveLocalNonParameterVariableNames = new Hashtable();
            var usedRegisterMask = 0;

            foreach (TerminalName variableName in liveLocalVariableNames.Keys)
            {
                var rep = (Representation)pinnedVariables[variableName];
                if (rep == null)
                {
                    liveLocalNonParameterVariableNames.Add(variableName, null);
                }
                else
                {
                    var register = rep as Register;
                    if (register != null)
                    {
                        usedRegisterMask |= 1 << register.Index;
                    }
                }
            }
            var allocableRegisterMask = ((1 << Traits.NumAllocableRegisters) - 1) & ~usedRegisterMask;

            var result = VariableAllocator.Run(liveLocalNonParameterVariableNames.Keys,
                                               allocableRegisterMask,
                                               BuilderHints.VariableNameToRepresentation);

            var allUsedExcludingScratch = usedRegisterMask | result.UsedRegisterMask;

            //The reason for this is that scratch0 and scratch1 must not interfere with the calling convention
            var         startingPoint = externalMethodWasInvoked ? 4 : 0;
            LowRegister scratch0      = null;

            for (var i = startingPoint; i < Traits.NumLowRegisters; ++i)
            {
                if ((allUsedExcludingScratch & (1 << i)) == 0)
                {
                    var register = new LowRegister(i);
                    if (scratch0 == null)
                    {
                        scratch0 = register;
                    }
                    else
                    {
                        var pt = new PassTraits(this.externalMethodWasInvoked, scratch0, register,
                                                scratch0Used, scratch1Used, allUsedExcludingScratch, result.AllocatedVariableOffset);
                        runAgain = result.RunAgain || !pt.EqualTo(BuilderHints.PassTraits);
                        return(BuilderHints.CloneSetValues(liveLocalVariableNames.AsReadOnlyDictionary(),
                                                           result.VariableNameToRepresentation, pt));
                    }
                }
            }
            throw new Exception("never");
        }
コード例 #10
0
        public Label LookupOrCreateBranchTo(LowRegister register)
        {
            var regIndex = register.Index;
            var label    = registerIndexToLabelWhereItsBXInstructionIs[regIndex];

            if (label == null)
            {
                label = DeclareStaticLabel("bxTo" + register);
                registerIndexToLabelWhereItsBXInstructionIs[regIndex] = label;
            }
            return(label);
        }
コード例 #11
0
 private void EmitBXInstructions()
 {
     for (var registerIndex = 0; registerIndex < registerIndexToLabelWhereItsBXInstructionIs.Length; ++registerIndex)
     {
         var label = registerIndexToLabelWhereItsBXInstructionIs[registerIndex];
         if (label != null)
         {
             label.Mark();
             var register = new LowRegister(registerIndex);
             emitter.Emit(Format5OpCode.BX, null, register);
         }
     }
 }
コード例 #12
0
 private LowRegister AllocateRegisterIfPossible(LowRegister register)
 {
     if (numberOfRegistersLeft != 0)
     {
         if (register != null && TryAllocate(register.Index))
         {
             return(register);
         }
         for (var i = 0; i < 32; ++i)
         {
             if (TryAllocate(i))
             {
                 return(new LowRegister(i));
             }
         }
     }
     return(null);
 }
コード例 #13
0
ファイル: PassTraits.cs プロジェクト: meikeric/DotCopter
 public PassTraits(bool preserveLinkRegister, LowRegister scratch0, LowRegister scratch1, bool scratch0Used, bool scratch1Used,
                   int registerMaskExcludingScratch, int allocatedVariableOffset)
 {
     PreserveLinkRegister = preserveLinkRegister;
     Scratch0             = scratch0;
     Scratch1             = scratch1;
     Scratch0Used         = scratch0Used;
     Scratch1Used         = scratch1Used;
     RegisterMask         = registerMaskExcludingScratch;
     if (Scratch0Used)
     {
         RegisterMask |= 1 << (Scratch0.Index);
     }
     if (Scratch1Used)
     {
         RegisterMask |= 1 << (Scratch1.Index);
     }
     AllocatedVariableOffset = allocatedVariableOffset;
 }
コード例 #14
0
        public LowRegister ToRegisterHelper(LowRegister writeableReg)
        {
            var emitter = CodeGenerator.Emitter;

            if (value >= 0 && value < 256)
            {
                emitter.Emit(Format3OpCode.MOV, writeableReg, (byte)value);
            }
            else if (value < 0 && value > -256)
            {
                emitter.Emit(Format3OpCode.MOV, writeableReg, 0);
                emitter.Emit(Format3OpCode.SUB, writeableReg, (byte)(-value));
            }
            else
            {
                var label   = CodeGenerator.Instance.AllocateInlineConstant(value);
                var address = label.GetLabelAddressBestEffort();
                emitter.Emit(Format6OpCode.LDR, writeableReg, address);
            }
            return(writeableReg);
        }
コード例 #15
0
ファイル: Emitter.cs プロジェクト: meikeric/DotCopter
        public void Emit(Format4OpCode opCode, LowRegister rd, LowRegister rs)
        {
            var fluentComment = opCode.ToHumanReadable().MyConcat(" ", rd, ",", rs);

            EmitHelper(rd, 4, fluentComment, 16, 6, (int)opCode, 4, rs.Index, 3, rd.Index, 3);
        }
コード例 #16
0
ファイル: Emitter.cs プロジェクト: meikeric/DotCopter
        public void Emit(Format3OpCode opCode, LowRegister rd, byte value)
        {
            var fluentComment = opCode.ToHumanReadable().MyConcat(" ", rd, ",#", value);

            EmitHelper(rd, 3, fluentComment, 1, 3, (int)opCode, 2, rd.Index, 3, value, 8);
        }
コード例 #17
0
ファイル: MethodInvoker.cs プロジェクト: meikeric/DotCopter
        public void Invoke(FuncPointer fp, IReference optionalResult, params Expression[] arguments)
        {
            var callerCaresAboutResult = !ReferenceEquals(optionalResult, null) && !CanProveIsNeverRead(optionalResult);

            var g       = CodeGenerator.Instance;
            var emitter = CodeGenerator.Emitter;

            using (this.OpenScope("invokeMethod")) {
                this.externalMethodWasInvoked = true;

                //use the caller's storage (if any) as a place to evaluate the func pointer
                var temp       = this.Declare.Int("temp");
                var fpReadable = fp.EvaluateTo(optionalResult ?? temp);

                using (this.OpenScope("params")) {
                    //SUPER HACK: in order to participate in the function calling convention, I need to
                    //relocate any existing variable stored in R0-R3 to the stack
                    int registerMaskToSpill;
                    int registersToSpillStackConsumption;
                    localVariableToInfo.MigrateR0R3ToStack(out registerMaskToSpill, out registersToSpillStackConsumption);

                    //Spill the affected registers to the stack
                    emitter.EmitIfNecessary(Format14OpCode.PUSH, false, (byte)registerMaskToSpill);
                    StackPointer += registersToSpillStackConsumption;

                    //great!  Now make your parameters (which may further adjust the stack)
                    //we only need parameters up to our highest unused argument
                    var parameterLength = arguments.Length;
                    while (parameterLength > 0 && arguments[parameterLength - 1] == null)
                    {
                        --parameterLength;
                    }
                    var stackPointerBeforePush = StackPointer;
                    var parameters             = new IReference[parameterLength];
                    for (var i = parameterLength - 1; i >= 0; --i)
                    {
                        Representation representation;
                        if (i < 4)
                        {
                            representation = new LowRegister(i);
                        }
                        else
                        {
                            StackPointer  += -4;
                            representation = new StackWordRelativeToZero(StackPointer);
                        }
                        var vi       = new LocalVariableInfo(CreateTerminalName("param" + i), representation);
                        var variable = new IntVariable();

                        localVariableToInfo.Add(variable, vi);
                        parameters[i] = variable;
                    }

                    var additionalStackToAllocate = StackPointer - stackPointerBeforePush;
                    emitter.EmitIfNecessary(Format13OpCode.ADDSP, additionalStackToAllocate);

                    //Now move your arguments to the function parameters
                    for (var i = 0; i < parameterLength; ++i)
                    {
                        var parameter = parameters[i];
                        var argument  = arguments[i];
                        if (!ReferenceEquals(argument, null))
                        {
                            Assignment.SpecialAssignAny(parameter, arguments[i]);
                        }
                    }

                    //FIRE AWAY, BONGO
                    var branchTargetReg = fpReadable.ToRegister(Scratch0);
                    var targetLabel     = g.LookupOrCreateBranchTo(branchTargetReg);
                    var address         = targetLabel.GetLabelAddressBestEffort();
                    emitter.Emit(Format19OpCode.BL, address);

                    //woowee!  we are back
                    //R0 has a result... stash it in LR so that our pop logic can restore everything else
                    if (callerCaresAboutResult)
                    {
                        emitter.EmitRegisterMoveIfDifferent(Register.LR, Register.R0);
                    }

                    //fix your stack
                    emitter.EmitIfNecessary(Format13OpCode.ADDSP, -additionalStackToAllocate);
                    StackPointer -= additionalStackToAllocate;

                    //fix your registers
                    emitter.EmitIfNecessary(Format14OpCode.POP, false, (byte)registerMaskToSpill);
                    StackPointer -= registersToSpillStackConsumption;
                }
            }

            //if the caller cares about the result, provide it
            if (callerCaresAboutResult)
            {
                optionalResult.FromRegister(Register.LR);
            }
        }
コード例 #18
0
ファイル: Emitter.cs プロジェクト: meikeric/DotCopter
 public void Emit(Format2OpCode opCode, LowRegister rd, LowRegister rs, byte immediate3Bit)
 {
     CheckRange(immediate3Bit, 0, 7);
     Format2Helper(opCode, 1, rd, rs, immediate3Bit, "#" + immediate3Bit);
 }
コード例 #19
0
ファイル: Emitter.cs プロジェクト: meikeric/DotCopter
 public void Emit(Format2OpCode opCode, LowRegister rd, LowRegister rs, LowRegister rn)
 {
     Format2Helper(opCode, 0, rd, rs, rn.Index, rn.ToString());
 }
コード例 #20
0
 public RegisterOrByte(LowRegister register, byte b)
 {
     Register = register;
     Byte     = b;
 }
コード例 #21
0
 public static RegisterOrByte Create(LowRegister register)
 {
     return(new RegisterOrByte(register, 0));
 }
コード例 #22
0
 public RegisterOrByte ToRegisterOrUnsignedConstantHelper(LowRegister writeable, int exclusiveUpperBound)
 {
     return(value >= 0 && value < exclusiveUpperBound
 ? RegisterOrByte.Create((byte)value)
 : RegisterOrByte.Create(ToRegisterHelper(writeable)));
 }
コード例 #23
0
ファイル: Emitter.cs プロジェクト: meikeric/DotCopter
        public void Emit(Format8OpCode opCode, LowRegister rsd, LowRegister rb, LowRegister ro)
        {
            var fluentComment = opCode.ToHumanReadable().MyConcat(" ", rsd, ",[", rb, ",", ro, "]");

            EmitHelper(rsd, 7, fluentComment, 5, 4, (int)opCode, 2, 1, 1, ro.Index, 3, rb.Index, 3, rsd.Index, 3);
        }
コード例 #24
0
        private FuncBuilder(Namespace ns, FuncBuilderHints builderHints, ActionOnFuncBuilder action)
        {
            Instance = this;
            this.namespaceAndNextIndex = new NamespaceAndNextIndex(ns, 0);
            this.BuilderHints          = builderHints;

            var pt = builderHints.PassTraits;

            this.Scratch0 = pt.Scratch0;
            this.Scratch1 = pt.Scratch1;

            var emitter = CodeGenerator.Emitter;

            var passTraits     = BuilderHints.PassTraits;
            var preserveLr     = passTraits.PreserveLinkRegister;
            var regsToPreserve = passTraits.RegisterMask & 0xf0;

            emitter.EmitIfNecessary(Format14OpCode.PUSH, preserveLr, (byte)regsToPreserve);
            if (preserveLr)
            {
                StackPointer += -4;
            }
            while (regsToPreserve != 0)
            {
                StackPointer   += -4;
                regsToPreserve &= (regsToPreserve - 1);
            }
            this.EndOfVariableRegion = StackPointer;

            var avo = passTraits.AllocatedVariableOffset;

            emitter.EmitIfNecessary(Format13OpCode.ADDSP, avo);
            StackPointer += avo;

            this.TheExitLabel = DeclareLabel("leave");

            action(this);

            TheExitLabel.Mark();
            StackPointer += -avo;
            emitter.EmitIfNecessary(Format13OpCode.ADDSP, -avo);

            regsToPreserve = passTraits.RegisterMask & 0xf0;
            emitter.EmitIfNecessary(Format14OpCode.POP, false, (byte)regsToPreserve);

            Register bxRegister;

            if (passTraits.PreserveLinkRegister)
            {
                bxRegister = new LowRegister(1);
                emitter.EmitIfNecessary(Format14OpCode.POP, false, 1 << 1);
            }
            else
            {
                bxRegister = Register.LR;
            }
            emitter.Emit(Format5OpCode.BX, null, bxRegister);

            if (inflightUtterances.Count > 0)
            {
                var allUtterances = "";
                foreach (string utterance in inflightUtterances.Values)
                {
                    if (allUtterances.Length > 0)
                    {
                        allUtterances += ",";
                    }
                    allUtterances += utterance;
                }
                throw new Exception(allUtterances);
            }
        }
コード例 #25
0
ファイル: RegisterOrByte.cs プロジェクト: meikeric/DotCopter
 public static RegisterOrByte Create(LowRegister register)
 {
     return new RegisterOrByte(register, 0);
 }
コード例 #26
0
ファイル: RegisterOrByte.cs プロジェクト: meikeric/DotCopter
 public RegisterOrByte(LowRegister register, byte b)
 {
     Register=register;
       Byte=b;
 }