/// <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); }
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)); }
/// <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); }
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); }
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)); }
/// <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; }
/// <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; }
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; }
public SPEOpCodeMapper(CompiledMethod state) { m_state = state; }