示例#1
0
        /// <summary>
        /// Adds an ABI compliant SPE method epilouge to the instruction stream
        /// </summary>
        private static List <SPEEmulator.OpCodes.Bases.Instruction> GenerateEpilouge(CompiledMethod state)
        {
            List <SPEEmulator.OpCodes.Bases.Instruction> tmplist = new List <SPEEmulator.OpCodes.Bases.Instruction>();

            uint stackDepth = state.MaxStackDepth + 2;

            if (stackDepth * REGISTER_SIZE <= 0x1FF)
            {
                tmplist.Add(new SPEEmulator.OpCodes.ai(_SP, _SP, stackDepth * REGISTER_SIZE));
            }
            else if (stackDepth * REGISTER_SIZE <= 0x7FFF)
            {
                tmplist.Add(new SPEEmulator.OpCodes.il(_TMP0, stackDepth * (REGISTER_SIZE)));
                tmplist.Add(new SPEEmulator.OpCodes.a(_SP, _SP, _TMP0));
            }
            else
            {
                throw new Exception("Stack space is larger than 0x7fff");
            }

            tmplist.Add(new SPEEmulator.OpCodes.lqd(_LR, _SP, 1));
            tmplist.Add(new SPEEmulator.OpCodes.bi(_LR, _LR));

            int size = state.Prolouge.Count + state.Instructions.Count + tmplist.Count;

            while (size % 4 != 0)
            {
                tmplist.Add(new SPEEmulator.OpCodes.nop());
                size++;
            }

            return(tmplist);
        }
示例#2
0
        private static void RecursiveTranslate(CompiledMethod state, SPEOpCodeMapper mapper, AccCIL.IR.InstructionElement el, Dictionary <AccCIL.IR.InstructionElement, string> compiled)
        {
            if (compiled.ContainsKey(el))
            {
                System.Diagnostics.Debug.Assert(el.Instruction.OpCode.Code == Mono.Cecil.Cil.Code.Dup);
                return;
            }

            compiled.Add(el, null);

            foreach (AccCIL.IR.InstructionElement els in el.Childnodes)
            {
                RecursiveTranslate(state, mapper, els, compiled);
            }

            int stackdepth = state.VirtualStackDepth;

            System.Reflection.MethodInfo translator;
            if (!_opTranslations.TryGetValue(el.Instruction.OpCode.Code, out translator))
            {
                throw new Exception(string.Format("Missing a translator for CIL code {0}", el.Instruction.OpCode.Code));
            }

            state.StartInstruction(el.Instruction);
            translator.Invoke(mapper, new object[] { el });
            state.EndInstruction();

            //Verify that the instruction handler managed to handle the stack
            System.Diagnostics.Debug.Assert(state.VirtualStackDepth == stackdepth + AccCIL.AccCIL.StackChangeCount(el));
        }
示例#3
0
        /// <summary>
        /// Adds an ABI compliant SPE method prolouge to the instruction stream
        /// </summary>
        private static List <SPEEmulator.OpCodes.Bases.Instruction> GenerateProlouge(CompiledMethod state)
        {
            List <SPEEmulator.OpCodes.Bases.Instruction> tmplist = new List <SPEEmulator.OpCodes.Bases.Instruction>();

            tmplist.Add(new SPEEmulator.OpCodes.stqd(_LR, _SP, 1));

            uint stackDepth = state.MaxStackDepth + 2;

            if (stackDepth * (REGISTER_SIZE / 16) <= 0x1FF)
            {
                tmplist.Add(new SPEEmulator.OpCodes.stqd(_SP, _SP, (uint)((-(stackDepth * (REGISTER_SIZE / 16))) & 0x3ff)));
            }
            else if (stackDepth * (REGISTER_SIZE / 16) <= 0x7FFF)
            {
                tmplist.Add(new SPEEmulator.OpCodes.il(_TMP0, (uint)((-(stackDepth * (REGISTER_SIZE / 16))) & 0xFFFF)));
                tmplist.Add(new SPEEmulator.OpCodes.a(_TMP0, _SP, _TMP0));
                tmplist.Add(new SPEEmulator.OpCodes.stqd(_SP, _TMP0, 0));
            }
            else
            {
                //Note if this restraint is removed, beware that all code that uses "lqd $target, _SP(index)" won't work
                throw new Exception("Stack space is larger than 0x7fff");
            }

            if (stackDepth * (REGISTER_SIZE) <= 0x1FF)
            {
                tmplist.Add(new SPEEmulator.OpCodes.ai(_SP, _SP, (uint)((-(stackDepth * (REGISTER_SIZE))) & 0x3ff)));
            }
            else if (stackDepth * (REGISTER_SIZE) <= 0x7FFF)
            {
                tmplist.Add(new SPEEmulator.OpCodes.il(_TMP0, (uint)((-(stackDepth * (REGISTER_SIZE))) & 0xFFFF)));
                tmplist.Add(new SPEEmulator.OpCodes.a(_SP, _SP, _TMP0));
            }
            else
            {
                throw new Exception("Stack space is larger than 0x7fff");
            }

            return(tmplist);
        }
示例#4
0
        public ICompiledMethod JIT(AccCIL.IR.MethodEntry method)
        {
            //First we execute all IR/CIL optimizations, except the register allocator
            IRegisterAllocator allocator = null;

            foreach (IOptimizer o in m_optimizers)
            {
                if (this.OptimizationLevel >= o.IncludeLevel)
                {
                    if (o is IRegisterAllocator)
                    {
                        allocator = (IRegisterAllocator)o;
                        continue;
                    }
                    else
                    {
                        o.Optimize(method, this.OptimizationLevel);
                    }
                }
            }

            CompiledMethod  state  = new CompiledMethod(method);
            SPEOpCodeMapper mapper = new SPEOpCodeMapper(state);

            state.StartFunction();

            //We store the local variables in the permanent registers followed by the function arguments
            int locals   = method.Method.Body.Variables.Count;
            int args     = method.Method.Parameters.Count;
            int permRegs = locals + args;

            //TODO: Handle this case by storing the extra data on the stack
            if (permRegs > MAX_LV_REGISTERS)
            {
                throw new Exception("Too many locals+arguments");
            }

            //Make sure the register usage is clean
            method.ResetVirtualRegisters();

            //TODO: should be able to re-use registers used by the arguments, which frees appx 70 extra registers
            List <int> usedRegs =
                this.OptimizationLevel > AccCIL.OptimizationLevel.None ?
                new RegisterAllocator().AllocateRegisters(_LV0 + permRegs, allocator, method) :
                new List <int>();

            //new AccCILVisualizer.Visualizer(new AccCIL.IR.MethodEntry[] { method }).ShowDialog();

            //If we need to store locals, we must preserve the local variable registers
            for (int i = 0; i < permRegs; i++)
            {
                mapper.PushStack(new TemporaryRegister((uint)(_LV0 + i)));
                usedRegs.Remove(_LV0 + i);
            }

            //All remaining used registers must also be preserved
            foreach (int i in usedRegs.Reverse <int>())
            {
                if (i > _LV0)
                {
                    mapper.PushStack(new TemporaryRegister((uint)(i)));
                }
            }

            //Clear as required
            if (method.Method.Body.InitLocals)
            {
                for (int i = 0; i < locals; i++)
                {
                    mapper.ClearRegister((uint)(_LV0 + i));
                }
            }

            //Now copy over the arguments
            for (int i = 0; i < args; i++)
            {
                mapper.CopyRegister((uint)(_ARG0 + i), (uint)(_LV0 + locals + i));
            }

            int requiredStackDepth = state.StackDepth;

            //Now add each parsed subtree
            foreach (AccCIL.IR.InstructionElement el in method.Childnodes)
            {
                System.Diagnostics.Debug.Assert(state.VirtualStackDepth == requiredStackDepth);
                RecursiveTranslate(state, mapper, el, new Dictionary <AccCIL.IR.InstructionElement, string>());
                System.Diagnostics.Debug.Assert(state.VirtualStackDepth == requiredStackDepth);

                System.Diagnostics.Trace.Assert(state.StackDepth >= requiredStackDepth);
            }

            state.EndFunction();

            System.Diagnostics.Trace.Assert(state.StackDepth == requiredStackDepth);

            //All used registers must be preserved
            foreach (int i in usedRegs)
            {
                if (i > _LV0)
                {
                    mapper.PopStack((uint)(i), true);
                }
            }

            //If we had to store locals, we must restore the local variable registers
            for (int i = 0; i < permRegs; i++)
            {
                mapper.PopStack((uint)(_LV0 + (permRegs - i - 1)), true);
            }


            System.Diagnostics.Trace.Assert(state.StackDepth == 0);

            return(state);
        }
示例#5
0
        private static void RecursiveTranslate(CompiledMethod state, SPEOpCodeMapper mapper, AccCIL.IR.InstructionElement el, Dictionary<AccCIL.IR.InstructionElement, string> compiled)
        {
            if (compiled.ContainsKey(el))
            {
                System.Diagnostics.Debug.Assert(el.Instruction.OpCode.Code == Mono.Cecil.Cil.Code.Dup);
                return;
            }

            compiled.Add(el, null);

            foreach (AccCIL.IR.InstructionElement els in el.Childnodes)
                RecursiveTranslate(state, mapper, els, compiled);

            int stackdepth = state.VirtualStackDepth;
            System.Reflection.MethodInfo translator;
            if (!_opTranslations.TryGetValue(el.Instruction.OpCode.Code, out translator))
                throw new Exception(string.Format("Missing a translator for CIL code {0}", el.Instruction.OpCode.Code));

            state.StartInstruction(el.Instruction);
            translator.Invoke(mapper, new object[] { el });
            state.EndInstruction();

            //Verify that the instruction handler managed to handle the stack
            System.Diagnostics.Debug.Assert(state.VirtualStackDepth == stackdepth + AccCIL.AccCIL.StackChangeCount(el));
        }
示例#6
0
        /// <summary>
        /// Adds an ABI compliant SPE method prolouge to the instruction stream
        /// </summary>
        private static List<SPEEmulator.OpCodes.Bases.Instruction> GenerateProlouge(CompiledMethod state)
        {
            List<SPEEmulator.OpCodes.Bases.Instruction> tmplist = new List<SPEEmulator.OpCodes.Bases.Instruction>();

            tmplist.Add(new SPEEmulator.OpCodes.stqd(_LR, _SP, 1));

            uint stackDepth = state.MaxStackDepth + 2;

            if (stackDepth * (REGISTER_SIZE / 16) <= 0x1FF)
                tmplist.Add(new SPEEmulator.OpCodes.stqd(_SP, _SP, (uint)((-(stackDepth * (REGISTER_SIZE / 16))) & 0x3ff)));
            else if (stackDepth * (REGISTER_SIZE / 16) <= 0x7FFF)
            {
                tmplist.Add(new SPEEmulator.OpCodes.il(_TMP0, (uint)((-(stackDepth * (REGISTER_SIZE / 16))) & 0xFFFF)));
                tmplist.Add(new SPEEmulator.OpCodes.a(_TMP0, _SP, _TMP0));
                tmplist.Add(new SPEEmulator.OpCodes.stqd(_SP, _TMP0, 0));
            }
            else
            {
                //Note if this restraint is removed, beware that all code that uses "lqd $target, _SP(index)" won't work
                throw new Exception("Stack space is larger than 0x7fff");
            }

            if (stackDepth * (REGISTER_SIZE) <= 0x1FF)
                tmplist.Add(new SPEEmulator.OpCodes.ai(_SP, _SP, (uint)((-(stackDepth * (REGISTER_SIZE))) & 0x3ff)));
            else if (stackDepth * (REGISTER_SIZE) <= 0x7FFF)
            {
                tmplist.Add(new SPEEmulator.OpCodes.il(_TMP0, (uint)((-(stackDepth * (REGISTER_SIZE))) & 0xFFFF)));
                tmplist.Add(new SPEEmulator.OpCodes.a(_SP, _SP, _TMP0));
            }
            else
                throw new Exception("Stack space is larger than 0x7fff");

            return tmplist;
        }
示例#7
0
        /// <summary>
        /// Adds an ABI compliant SPE method epilouge to the instruction stream
        /// </summary>
        private static List<SPEEmulator.OpCodes.Bases.Instruction> GenerateEpilouge(CompiledMethod state)
        {
            List<SPEEmulator.OpCodes.Bases.Instruction> tmplist = new List<SPEEmulator.OpCodes.Bases.Instruction>();

            uint stackDepth = state.MaxStackDepth + 2;

            if (stackDepth * REGISTER_SIZE <= 0x1FF)
                tmplist.Add(new SPEEmulator.OpCodes.ai(_SP, _SP, stackDepth * REGISTER_SIZE));
            else if (stackDepth * REGISTER_SIZE <= 0x7FFF)
            {
                tmplist.Add(new SPEEmulator.OpCodes.il(_TMP0, stackDepth * (REGISTER_SIZE)));
                tmplist.Add(new SPEEmulator.OpCodes.a(_SP, _SP, _TMP0));
            }
            else
                throw new Exception("Stack space is larger than 0x7fff");

            tmplist.Add(new SPEEmulator.OpCodes.lqd(_LR, _SP, 1));
            tmplist.Add(new SPEEmulator.OpCodes.bi(_LR, _LR));

            int size = state.Prolouge.Count + state.Instructions.Count + tmplist.Count;

            while (size % 4 != 0)
            {
                tmplist.Add(new SPEEmulator.OpCodes.nop());
                size++;
            }

            return tmplist;
        }
示例#8
0
        public ICompiledMethod JIT(AccCIL.IR.MethodEntry method)
        {
            //First we execute all IR/CIL optimizations, except the register allocator
            IRegisterAllocator allocator = null;

            foreach (IOptimizer o in m_optimizers)
                if (this.OptimizationLevel >= o.IncludeLevel)
                {
                    if (o is IRegisterAllocator)
                    {
                        allocator = (IRegisterAllocator)o;
                        continue;
                    }
                    else
                        o.Optimize(method, this.OptimizationLevel);
                }

            CompiledMethod state = new CompiledMethod(method);
            SPEOpCodeMapper mapper = new SPEOpCodeMapper(state);

            state.StartFunction();

            //We store the local variables in the permanent registers followed by the function arguments
            int locals = method.Method.Body.Variables.Count;
            int args = method.Method.Parameters.Count;
            int permRegs = locals + args;

            //TODO: Handle this case by storing the extra data on the stack
            if (permRegs > MAX_LV_REGISTERS)
                throw new Exception("Too many locals+arguments");

            //Make sure the register usage is clean
            method.ResetVirtualRegisters();

            //TODO: should be able to re-use registers used by the arguments, which frees appx 70 extra registers
            List<int> usedRegs =
                this.OptimizationLevel > AccCIL.OptimizationLevel.None ?
                new RegisterAllocator().AllocateRegisters(_LV0 + permRegs, allocator, method) :
                new List<int>();

            //new AccCILVisualizer.Visualizer(new AccCIL.IR.MethodEntry[] { method }).ShowDialog();

            //If we need to store locals, we must preserve the local variable registers
            for (int i = 0; i < permRegs; i++)
            {
                mapper.PushStack(new TemporaryRegister((uint)(_LV0 + i)));
                usedRegs.Remove(_LV0 + i);
            }

            //All remaining used registers must also be preserved
            foreach (int i in usedRegs.Reverse<int>())
                if (i > _LV0)
                    mapper.PushStack(new TemporaryRegister((uint)(i)));

            //Clear as required
            if (method.Method.Body.InitLocals)
                for (int i = 0; i < locals; i++)
                    mapper.ClearRegister((uint)(_LV0 + i));

            //Now copy over the arguments
            for (int i = 0; i < args; i++)
                mapper.CopyRegister((uint)(_ARG0 + i), (uint)(_LV0 + locals + i));

            int requiredStackDepth = state.StackDepth;

            //Now add each parsed subtree
            foreach (AccCIL.IR.InstructionElement el in method.Childnodes)
            {
                System.Diagnostics.Debug.Assert(state.VirtualStackDepth == requiredStackDepth);
                RecursiveTranslate(state, mapper, el, new Dictionary<AccCIL.IR.InstructionElement,string>());
                System.Diagnostics.Debug.Assert(state.VirtualStackDepth == requiredStackDepth);

                System.Diagnostics.Trace.Assert(state.StackDepth >= requiredStackDepth);
            }

            state.EndFunction();

            System.Diagnostics.Trace.Assert(state.StackDepth == requiredStackDepth);

            //All used registers must be preserved
            foreach (int i in usedRegs)
                if (i > _LV0)
                    mapper.PopStack((uint)(i), true);

            //If we had to store locals, we must restore the local variable registers
            for (int i = 0; i < permRegs; i++)
                mapper.PopStack((uint)(_LV0 + (permRegs - i - 1)), true);

            System.Diagnostics.Trace.Assert(state.StackDepth == 0);

            return state;
        }
示例#9
0
 public SPEOpCodeMapper(CompiledMethod state)
 {
     m_state = state;
 }