public void Add(InstructionElement el) { Type t = ValidateBinaryOp(el, false); VirtualRegister r1 = PopStack(_RTMP1); VirtualRegister r0 = PopStack(_RTMP0); VirtualRegister o = el.Register.RegisterNumber < 0 ? new TemporaryRegister(_RTMP2) : el.Register; if (t == typeof(int)) m_state.Instructions.Add(new SPEEmulator.OpCodes.a((uint)o.RegisterNumber, (uint)r1.RegisterNumber, (uint)r0.RegisterNumber)); else if (t == typeof(float)) m_state.Instructions.Add(new SPEEmulator.OpCodes.fa((uint)o.RegisterNumber, (uint)r1.RegisterNumber, (uint)r0.RegisterNumber)); else if (t == typeof(double)) m_state.Instructions.Add(new SPEEmulator.OpCodes.dfa((uint)o.RegisterNumber, (uint)r1.RegisterNumber, (uint)r0.RegisterNumber)); else if (t == typeof(long)) { m_state.RegisterConstantLoad(0x0405060780808080, 0x0c0d0e0f80808080); m_state.Instructions.AddRange(new SPEEmulator.OpCodes.Bases.Instruction[] { new SPEEmulator.OpCodes.lqr(_RTMP3, 0), //Load add mask new SPEEmulator.OpCodes.cg(_RTMP2, (uint)r1.RegisterNumber, (uint)r0.RegisterNumber), //Calculate carry new SPEEmulator.OpCodes.shufb(_RTMP2, _RTMP2, _RTMP2, _RTMP3), //Rotate the carry to the far right new SPEEmulator.OpCodes.addx(_RTMP2, (uint)r1.RegisterNumber, (uint)r0.RegisterNumber), //Add the two words new SPEEmulator.OpCodes.ori((uint)o.RegisterNumber, _RTMP2, 0), //Add the two words }); } else throw new InvalidProgramException(); PushStack(o); }
public InstructionElement(Mono.Cecil.MethodDefinition parentMethod, InstructionElement[] childnodes, Mono.Cecil.Cil.Instruction instruction) { this.Childnodes = childnodes ?? new InstructionElement[0]; this.Instruction = instruction; this.ParentMethod = parentMethod; foreach (InstructionElement c in this.Childnodes) { System.Diagnostics.Trace.Assert(c != null); c.Parent = this; } if (instruction != null) AssignReturnType(); }
/// <summary> /// Gets the number of elements that the instruction pops /// </summary> /// <param name="i">The instruction to examine</param> /// <returns>The number of elements poped</returns> public static int NumberOfElementsPoped(IR.InstructionElement i) { if (i.Instruction.OpCode.Code == Mono.Cecil.Cil.Code.Ret) { if (i.ParentMethod.ReturnType.ReturnType.FullName == "System.Void") { return(0); } else { return(1); } } return(NumberOfElementsPoped(i.Instruction.OpCode.StackBehaviourPop, i.Instruction.Operand)); }
public void Brfalse(InstructionElement el) { Brtrue(el); //Invert the branch instruction to use brz instead of brnz uint regno = ((SPEEmulator.OpCodes.brnz)m_state.Instructions[m_state.Instructions.Count - 1]).RT; m_state.Instructions[m_state.Instructions.Count - 1] = new SPEEmulator.OpCodes.brz(regno, 0xffff); }
private static IR.MethodEntry BuildIRTree(MethodDefinition mdef) { Stack<IR.InstructionElement> stack = new Stack<IR.InstructionElement>(); List<IR.InstructionElement> roots = new List<IR.InstructionElement>(); int returnElements = 1; if (mdef.ReturnType.ReturnType.FullName == "System.Void") returnElements = 0; foreach (Mono.Cecil.Cil.Instruction x in mdef.Body.Instructions) { IR.InstructionElement[] childnodes; if (x.OpCode.Code == Mono.Cecil.Cil.Code.Ret) childnodes = new IR.InstructionElement[returnElements]; else childnodes = new IR.InstructionElement[NumberOfElementsPoped(x.OpCode.StackBehaviourPop, x.Operand)]; for (int i = childnodes.Length - 1; i >= 0; i--) { System.Diagnostics.Trace.Assert(stack.Count > 0); childnodes[i] = stack.Pop(); } int elementsPushed = NumberOfElementsPushed(x.OpCode.StackBehaviourPush, x.Operand); if (elementsPushed == 0) { if (stack.Count != 0 && x.OpCode.FlowControl != Mono.Cecil.Cil.FlowControl.Next && x.OpCode.FlowControl != Mono.Cecil.Cil.FlowControl.Call) throw new InvalidProgramException(); roots.Add(new IR.InstructionElement(mdef, childnodes, x)); } else { IR.InstructionElement ins = new IR.InstructionElement(mdef, childnodes, x); for(int i = 0; i < elementsPushed; i++) stack.Push(ins); } } if (stack.Count != 0) throw new InvalidProgramException(); IR.MethodEntry m = new IR.MethodEntry(mdef) { Childnodes = roots.ToArray() }; m.ResetVirtualRegisters(); return m; }
/// <summary> /// Gets the number of elements the stack changes after the instruction. /// If the instruction only pops elements, this number will be negative. /// </summary> /// <param name="i">The instruction to examine</param> /// <returns>The size of the stack change</returns> public static int StackChangeCount(IR.InstructionElement i) { return(NumberOfElementsPushed(i) - NumberOfElementsPoped(i)); }
public void Brtrue(InstructionElement el) { VirtualRegister r = PopStack(_RTMP0); if (el.Childnodes[0].StorageClass == typeof(long)) { m_state.Instructions.Add(new SPEEmulator.OpCodes.rotqbyi(_RTMP1, (uint)r.RegisterNumber, 4)); m_state.Instructions.Add(new SPEEmulator.OpCodes.or(_RTMP0, _RTMP0, _RTMP1)); m_state.RegisterBranch(((Mono.Cecil.Cil.Instruction)el.Instruction.Operand)); m_state.Instructions.Add(new SPEEmulator.OpCodes.brnz(_RTMP0, 0xffff)); } else { m_state.RegisterBranch(((Mono.Cecil.Cil.Instruction)el.Instruction.Operand)); m_state.Instructions.Add(new SPEEmulator.OpCodes.brnz((uint)r.RegisterNumber, 0xffff)); } }
public void Ldc_I4(InstructionElement el) { VirtualRegister r = el.Register.RegisterNumber < 0 ? _VTMP0 : el.Register; uint reg = (uint)r.RegisterNumber; //TODO: Negative values can be loaded more efficiently, if they are < 0xffff uint opr = (uint)(int)el.Instruction.Operand; if (opr < 0x7fff) m_state.Instructions.Add(new SPEEmulator.OpCodes.il(reg, (uint)opr)); else if (opr < 0x40000) m_state.Instructions.Add(new SPEEmulator.OpCodes.ila(reg, (uint)opr)); else { ulong value = (ulong)((int) opr); m_state.RegisterConstantLoad((value << 32) | (value & 0xffffffff), (value << 32) | (value & 0xffffffff)); m_state.Instructions.Add(new SPEEmulator.OpCodes.lqr(reg, 0)); } PushStack(r); }
public void Ldc_I4_S(InstructionElement el) { VirtualRegister r = el.Register.RegisterNumber < 0 ? _VTMP0 : el.Register; uint reg = (uint)r.RegisterNumber; m_state.Instructions.Add(new SPEEmulator.OpCodes.il(reg, ((uint)(sbyte)el.Instruction.Operand) & 0xffff)); PushStack(r); }
public void Clt_un(InstructionElement el) { Type t = ValidateBinaryOp(el, false); VirtualRegister r1 = PopStack(_RTMP1); VirtualRegister r0 = PopStack(_RTMP0); VirtualRegister o = el.Register.RegisterNumber < 0 ? new TemporaryRegister(_RTMP0) : el.Register; //There are no clt_un instructions, so we use "not (clgt or ceq)" if (t == typeof(int)) m_state.Instructions.AddRange(new SPEEmulator.OpCodes.Bases.Instruction[] { new SPEEmulator.OpCodes.clgt(_RTMP2, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), //Greater than new SPEEmulator.OpCodes.ceq(_RTMP1, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), //Equal new SPEEmulator.OpCodes.or(_RTMP0, _RTMP2, _RTMP1), //Greater than _or_ equal new SPEEmulator.OpCodes.xori(_RTMP0, _RTMP0, 0x3ff), //Invert bitmask (not) new SPEEmulator.OpCodes.il(_RTMP1, 0x1), //Load a 0 or 1 mask new SPEEmulator.OpCodes.and((uint)o.RegisterNumber, _RTMP0, _RTMP1), //Make sure that the result is a word of either 0 (false) or 1 (true) }); else if (t == typeof(float)) throw new MissingMethodException("Floating unordered?"); else if (t == typeof(long)) { m_state.Instructions.AddRange(new SPEEmulator.OpCodes.Bases.Instruction[] { //Part1: cgt new SPEEmulator.OpCodes.ceq(_RTMP3, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), //This will compare words, giving 0xffffffff for equal than and 0 otherwise new SPEEmulator.OpCodes.clgt(_RTMP2, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), //This will compare words, giving 0xffffffff for logically greater than and 0 otherwise new SPEEmulator.OpCodes.rotqbyi(_RTMP2, _RTMP2, 4), //Prepare the tmp3 by an 8 byte rotate new SPEEmulator.OpCodes.and(_RTMP3, _RTMP2, _RTMP3), //And the results so we disregard the lower word unless the upper words are equal new SPEEmulator.OpCodes.clgt(_RTMP2, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), //This will compare words, giving 0xffffffff for greater than and 0 otherwise new SPEEmulator.OpCodes.or(_RTMP2, _RTMP2, _RTMP3), //Or the results so prefered word slot is either 0 or 0xffffffff //Part2: ceq new SPEEmulator.OpCodes.ceq(_RTMP1, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), //This will compare words, giving 0xffffffff for greater than and 0 otherwise new SPEEmulator.OpCodes.rotqbyi(_RTMP3, _RTMP1, 4), //Prepare the tmp1 by an 8 byte rotate new SPEEmulator.OpCodes.and(_RTMP1, _RTMP1, _RTMP3), //And the results so prefered word slot is either 0 or 0xffffffff //Combine new SPEEmulator.OpCodes.or(_RTMP0, _RTMP2, _RTMP1), //Greater than _or_ equal new SPEEmulator.OpCodes.xori(_RTMP0, _RTMP0, 0x3ff), //Invert bitmask (not) //Mask new SPEEmulator.OpCodes.il(_RTMP1, 0x1), //Load a 0 or 1 mask new SPEEmulator.OpCodes.and((uint)o.RegisterNumber, _RTMP0, _RTMP1), //Make sure that the result is a word of either 0 (false) or 1 (true) }); } else if (t == typeof(double)) throw new MissingMethodException("Double floating unordered?"); else throw new InvalidProgramException("clt for <" + el.Childnodes[0].StorageClass + "> ?"); PushStack(o); }
public void Conv_I4(InstructionElement el) { if (el.Childnodes == null || el.Childnodes.Length != 1) throw new InvalidProgramException(); if (el.Childnodes[0].StorageClass == typeof(int)) return; else if (el.Childnodes[0].StorageClass == typeof(long)) { VirtualRegister input = PopStack(_RTMP0); VirtualRegister output = el.Register.RegisterNumber < 0 ? _VTMP0 : el.Register; m_state.RegisterConstantLoad(0x0405060704050607, 0x0405060704050607); //This mask loads the lower word from the prefered doubleword slot m_state.Instructions.Add(new SPEEmulator.OpCodes.lqr(_RTMP1, 0)); m_state.Instructions.Add(new SPEEmulator.OpCodes.shufb((uint)output.RegisterNumber, (uint)input.RegisterNumber, (uint)input.RegisterNumber, _RTMP1)); PushStack(output); } else if (el.Childnodes[0].StorageClass == typeof(float)) { VirtualRegister input = PopStack(_RTMP0); VirtualRegister output = el.Register.RegisterNumber < 0 ? _VTMP0 : el.Register; m_state.Instructions.Add(new SPEEmulator.OpCodes.cflts((uint)output.RegisterNumber, (uint)input.RegisterNumber, 0)); PushStack(output); } else if (el.Childnodes[0].StorageClass == typeof(double)) { VirtualRegister input = PopStack(_RTMP0); VirtualRegister output = el.Register.RegisterNumber < 0 ? _VTMP0 : el.Register; m_state.Instructions.Add(new SPEEmulator.OpCodes.frds((uint)output.RegisterNumber, (uint)input.RegisterNumber)); //Convert to float m_state.Instructions.Add(new SPEEmulator.OpCodes.cflts((uint)output.RegisterNumber, (uint)output.RegisterNumber, 0)); //Convert to int PushStack(output); } }
public void Ceq(InstructionElement el) { Type t = ValidateBinaryOp(el, true); VirtualRegister r1 = PopStack(_RTMP1); VirtualRegister r0 = PopStack(_RTMP0); VirtualRegister o = el.Register.RegisterNumber < 0 ? new TemporaryRegister(_RTMP0) : el.Register; if (t == typeof(int) || t == typeof(IntPtr)) m_state.Instructions.AddRange(new SPEEmulator.OpCodes.Bases.Instruction[] { new SPEEmulator.OpCodes.ceq(_RTMP0, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), new SPEEmulator.OpCodes.il(_RTMP1, 0x1), //Load a 0 or 1 mask new SPEEmulator.OpCodes.and((uint)o.RegisterNumber, _RTMP0, _RTMP1), //Make sure that the result is a word of either 0 (false) or 1 (true) }); else if (t == typeof(float)) m_state.Instructions.AddRange(new SPEEmulator.OpCodes.Bases.Instruction[] { new SPEEmulator.OpCodes.fceq(_RTMP0, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), new SPEEmulator.OpCodes.il(_RTMP1, 0x1), //Load a 0 or 1 mask new SPEEmulator.OpCodes.and((uint)o.RegisterNumber, _RTMP0, _RTMP1), //Make sure that the result is a word of either 0 (false) or 1 (true) }); else if (t == typeof(long)) { //There is no ceqd, so we make our own m_state.Instructions.AddRange(new SPEEmulator.OpCodes.Bases.Instruction[] { new SPEEmulator.OpCodes.ceq(_RTMP0, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), //This will compare words, giving 0 for equal and 0xffffffff otherwise new SPEEmulator.OpCodes.rotqbyi(_RTMP1, _RTMP0, 4), //Prepare the tmp1 by an 8 byte rotate new SPEEmulator.OpCodes.and(_RTMP0, _RTMP0, _RTMP1), //Or the results so prefered word slot is either 0 or 0xffffffff new SPEEmulator.OpCodes.il(_RTMP1, 0x1), //Load a 0 or 1 mask new SPEEmulator.OpCodes.and((uint)o.RegisterNumber, _RTMP0, _RTMP1), //Make sure that the result is a word of either 0 (false) or 1 (true) }); } else if (t == typeof(double)) m_state.Instructions.AddRange(new SPEEmulator.OpCodes.Bases.Instruction[] { new SPEEmulator.OpCodes.dfceq(_RTMP0, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), new SPEEmulator.OpCodes.il(_RTMP1, 0x1), //Load a 0 or 1 mask new SPEEmulator.OpCodes.and((uint)o.RegisterNumber, _RTMP0, _RTMP1), //Make sure that the result is a word of either 0 or 1 }); else throw new InvalidProgramException("ceq for <" + el.Childnodes[0].StorageClass + "> ?"); PushStack(o); }
public void Cgt(InstructionElement el) { Type t = ValidateBinaryOp(el, false); VirtualRegister r1 = PopStack(_RTMP1); VirtualRegister r0 = PopStack(_RTMP0); VirtualRegister o = el.Register.RegisterNumber < 0 ? new TemporaryRegister(_RTMP0) : el.Register; if (t == typeof(int)) m_state.Instructions.AddRange(new SPEEmulator.OpCodes.Bases.Instruction[] { new SPEEmulator.OpCodes.cgt(_RTMP0, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), new SPEEmulator.OpCodes.il(_RTMP1, 0x1), //Load a 0 or 1 mask new SPEEmulator.OpCodes.and((uint)o.RegisterNumber, _RTMP0, _RTMP1), //Make sure that the result is a word of either 0 (false) or 1 (true) }); else if (t == typeof(float)) m_state.Instructions.AddRange(new SPEEmulator.OpCodes.Bases.Instruction[] { new SPEEmulator.OpCodes.fcgt(_RTMP0, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), new SPEEmulator.OpCodes.il(_RTMP1, 0x1), //Load a 0 or 1 mask new SPEEmulator.OpCodes.and((uint)o.RegisterNumber, _RTMP0, _RTMP1), //Make sure that the result is a word of either 0 (false) or 1 (true) }); else if (t == typeof(long)) { //There is no cgtd, so we make our own m_state.Instructions.AddRange(new SPEEmulator.OpCodes.Bases.Instruction[] { new SPEEmulator.OpCodes.ceq(_RTMP3, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), //This will compare words, giving 0xffffffff for equal than and 0 otherwise new SPEEmulator.OpCodes.clgt(_RTMP2, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), //This will compare words, giving 0xffffffff for logically greater than and 0 otherwise new SPEEmulator.OpCodes.rotqbyi(_RTMP2, _RTMP2, 4), //Prepare the tmp3 by an 8 byte rotate new SPEEmulator.OpCodes.and(_RTMP3, _RTMP2, _RTMP3), //And the results so we disregard the lower word unless the upper words are equal new SPEEmulator.OpCodes.cgt(_RTMP0, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), //This will compare words, giving 0xffffffff for greater than and 0 otherwise new SPEEmulator.OpCodes.or(_RTMP0, _RTMP0, _RTMP3), //Or the results so prefered word slot is either 0 or 0xffffffff new SPEEmulator.OpCodes.il(_RTMP1, 0x1), //Load a 0 or 1 mask new SPEEmulator.OpCodes.and((uint)o.RegisterNumber, _RTMP0, _RTMP1), //Make sure that the result is a word of either 0 (false) or 1 (true) }); } else if (t == typeof(double)) m_state.Instructions.AddRange(new SPEEmulator.OpCodes.Bases.Instruction[] { new SPEEmulator.OpCodes.dfcgt(_RTMP0, (uint)r0.RegisterNumber, (uint)r1.RegisterNumber), new SPEEmulator.OpCodes.il(_RTMP1, 0x1), //Load a 0 or 1 mask new SPEEmulator.OpCodes.and((uint)o.RegisterNumber, _RTMP0, _RTMP1), //Make sure that the result is a word of either 0 (false) or 1 (true) }); else throw new InvalidProgramException("cgt for <" + el.Childnodes[0].StorageClass + "> ?"); PushStack(o); }
public void Call(InstructionElement el) { Mono.Cecil.MethodReference mdef = (Mono.Cecil.MethodReference)el.Instruction.Operand; if (mdef.Parameters.Count > MAX_FUCTION_ARGUMENTS) throw new Exception("Too many arguments "); //Pop all required registers off stack and place them in call registers uint register = (uint)((_ARG0 + mdef.Parameters.Count) - 1); for (int i = 0; i < mdef.Parameters.Count; i++) PopStack((uint)(register - i), true); m_state.Instructions.Add(new SPEEmulator.OpCodes.il(_RTMP4, (uint)mdef.Parameters.Count)); //Signal parameter count for function m_state.RegisterCall(mdef); // i16 (set to 0xffff) should be replaced with correct value, when it is known! m_state.Instructions.Add(new SPEEmulator.OpCodes.brasl(0, 0xffff)); if (mdef.ReturnType.ReturnType.FullName != "System.Void") PushStack(new VirtualRegister(_ARG0)); }
public void Br_s(InstructionElement el) { Br(el); }
public void Brtrue_s(InstructionElement el) { Brtrue(el); }
public void Ldarg_3(InstructionElement el) { PushStack(new VirtualRegister((uint)(_LV0 + m_state.Method.Method.Body.Variables.Count + 3))); }
public void Conv_R8(InstructionElement el) { if (el.Childnodes == null || el.Childnodes.Length != 1) throw new InvalidProgramException(); if (el.Childnodes[0].StorageClass == typeof(double)) return; else if (el.Childnodes[0].StorageClass == typeof(int)) { VirtualRegister input = PopStack(_RTMP0); VirtualRegister output = el.Register.RegisterNumber < 0 ? _VTMP0 : el.Register; m_state.Instructions.Add(new SPEEmulator.OpCodes.csflt((uint)output.RegisterNumber, (uint)input.RegisterNumber, 155)); m_state.Instructions.Add(new SPEEmulator.OpCodes.fesd((uint)output.RegisterNumber, (uint)output.RegisterNumber)); PushStack(output); } else if (el.Childnodes[0].StorageClass == typeof(long)) { throw new MissingMethodException(); } else if (el.Childnodes[0].StorageClass == typeof(float)) { VirtualRegister input = PopStack(_RTMP0); VirtualRegister output = el.Register.RegisterNumber < 0 ? _VTMP0 : el.Register; m_state.Instructions.Add(new SPEEmulator.OpCodes.fesd((uint)output.RegisterNumber, (uint)input.RegisterNumber)); PushStack(output); } else throw new InvalidProgramException(); }
public void Ldarg_s(InstructionElement el) { int index = el.ParentMethod.Parameters.IndexOf(((Mono.Cecil.ParameterDefinition)el.Instruction.Operand)); PushStack(new VirtualRegister((uint)(_LV0 + m_state.Method.Method.Body.Variables.Count + index))); }
public void Ldc_r8(InstructionElement el) { VirtualRegister r = el.Register.RegisterNumber < 0 ? _VTMP0 : el.Register; double opr = (double)el.Instruction.Operand; byte[] data = BitConverter.GetBytes(opr); if (BitConverter.IsLittleEndian) Array.Reverse(data); m_state.RegisterConstantLoad(string.Format("{0:x2}{1:x2}{2:x2}{3:x2}{4:x2}{5:x2}{6:x2}{7:x2}{0:x2}{1:x2}{2:x2}{3:x2}{4:x2}{5:x2}{6:x2}{7:x2}", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7])); m_state.Instructions.Add(new SPEEmulator.OpCodes.lqr((uint)r.RegisterNumber, 0)); PushStack(r); }
public void Ldc_i4_m1(InstructionElement el) { VirtualRegister r = el.Register.RegisterNumber < 0 ? _VTMP0 : el.Register; m_state.Instructions.Add(new SPEEmulator.OpCodes.il((uint)r.RegisterNumber, 0xffff)); PushStack(r); }
public void Ldelem_common(InstructionElement el) { VirtualRegister elementIndex = PopStack(_RTMP0); VirtualRegister arrayPointer = PopStack(_RTMP1); VirtualRegister o = el.Register.RegisterNumber < 0 ? new TemporaryRegister(_RTMP0) : el.Register; if (el.Childnodes[1].StorageClass != typeof(int)) throw new Exception("Unexpected index type: " + el.Childnodes[1].StorageClass.ToString()); KnownObjectTypes[] arraytypes; switch (el.Instruction.OpCode.Code) { case Mono.Cecil.Cil.Code.Ldelem_I1: //case Mono.Cecil.Cil.Code.Ldelem_Bool: //Does not exist arraytypes = new KnownObjectTypes[] { KnownObjectTypes.SByte, KnownObjectTypes.Boolean }; break; case Mono.Cecil.Cil.Code.Ldelem_I2: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Short }; break; case Mono.Cecil.Cil.Code.Ldelem_I4: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Int }; break; case Mono.Cecil.Cil.Code.Ldelem_I8: //case Mono.Cecil.Cil.Code.Ldelem_U8: //Does not exist arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Long, KnownObjectTypes.ULong }; break; case Mono.Cecil.Cil.Code.Ldelem_R4: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Float }; break; case Mono.Cecil.Cil.Code.Ldelem_R8: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Double }; break; case Mono.Cecil.Cil.Code.Ldelem_U1: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Byte }; break; case Mono.Cecil.Cil.Code.Ldelem_U2: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.UShort }; break; case Mono.Cecil.Cil.Code.Ldelem_U4: arraytypes = new KnownObjectTypes[] { KnownObjectTypes.UInt }; break; default: throw new Exception("Unsupport array type: " + el.Instruction.OpCode.Code); } LoadElementAddress(el, arraytypes, (uint)elementIndex.RegisterNumber, (uint)arrayPointer.RegisterNumber, _RTMP0); LoadElement(arraytypes[0], _RTMP0, (uint)o.RegisterNumber); PushStack(o); }
public void Ldc_I8(InstructionElement el) { VirtualRegister r = el.Register.RegisterNumber < 0 ? _VTMP0 : el.Register; uint reg = (uint)r.RegisterNumber; ulong opr = (ulong)(long)el.Instruction.Operand; m_state.RegisterConstantLoad((ulong)opr, opr); m_state.Instructions.Add(new SPEEmulator.OpCodes.lqr(reg, 0)); PushStack(r); }
public void Brfalse_s(InstructionElement el) { Brfalse(el); }
public void Ldelema(InstructionElement el) { VirtualRegister elementIndex = PopStack(_RTMP0); VirtualRegister arrayPointer = PopStack(_RTMP1); VirtualRegister o = el.Register.RegisterNumber < 0 ? new TemporaryRegister(_RTMP0) : el.Register; if (el.Childnodes[1].StorageClass != typeof(int)) throw new Exception("Unexpected index type: " + el.Childnodes[1].StorageClass.ToString()); LoadElementAddress(el, new KnownObjectTypes[] { AccCIL.AccCIL.GetObjType(el.ReturnType) }, (uint)elementIndex.RegisterNumber, (uint)arrayPointer.RegisterNumber, (uint)o.RegisterNumber); PushStack(o); }
public void Conv_U1(InstructionElement el) { Conv_I1(el); }
public void Ldelem_i8(InstructionElement el) { Ldelem_common(el); }
public void Conv_U2(InstructionElement el) { Conv_I2(el); }
/// <summary> /// Gets the number of elements that the instruction pushes /// </summary> /// <param name="i">The instruction to examine</param> /// <returns>The number of elements pushed</returns> public static int NumberOfElementsPushed(IR.InstructionElement i) { return(NumberOfElementsPushed(i.Instruction.OpCode.StackBehaviourPush, i.Instruction.Operand)); }
public void Conv_U4(InstructionElement el) { Conv_I4(el); }
private static IR.MethodEntry BuildIRTree(MethodDefinition mdef) { Stack <IR.InstructionElement> stack = new Stack <IR.InstructionElement>(); List <IR.InstructionElement> roots = new List <IR.InstructionElement>(); int returnElements = 1; if (mdef.ReturnType.ReturnType.FullName == "System.Void") { returnElements = 0; } foreach (Mono.Cecil.Cil.Instruction x in mdef.Body.Instructions) { IR.InstructionElement[] childnodes; if (x.OpCode.Code == Mono.Cecil.Cil.Code.Ret) { childnodes = new IR.InstructionElement[returnElements]; } else { childnodes = new IR.InstructionElement[NumberOfElementsPoped(x.OpCode.StackBehaviourPop, x.Operand)]; } for (int i = childnodes.Length - 1; i >= 0; i--) { System.Diagnostics.Trace.Assert(stack.Count > 0); childnodes[i] = stack.Pop(); } int elementsPushed = NumberOfElementsPushed(x.OpCode.StackBehaviourPush, x.Operand); if (elementsPushed == 0) { if (stack.Count != 0 && x.OpCode.FlowControl != Mono.Cecil.Cil.FlowControl.Next && x.OpCode.FlowControl != Mono.Cecil.Cil.FlowControl.Call) { throw new InvalidProgramException(); } roots.Add(new IR.InstructionElement(mdef, childnodes, x)); } else { IR.InstructionElement ins = new IR.InstructionElement(mdef, childnodes, x); for (int i = 0; i < elementsPushed; i++) { stack.Push(ins); } } } if (stack.Count != 0) { throw new InvalidProgramException(); } IR.MethodEntry m = new IR.MethodEntry(mdef) { Childnodes = roots.ToArray() }; m.ResetVirtualRegisters(); return(m); }
public void Conv_U8(InstructionElement el) { if (el.Childnodes == null || el.Childnodes.Length != 1) throw new InvalidProgramException(); if (el.Childnodes[0].StorageClass == typeof(long)) return; else if (el.Childnodes[0].StorageClass == typeof(int)) { VirtualRegister input = PopStack(_RTMP0); VirtualRegister output = el.Register.RegisterNumber < 0 ? _VTMP0 : el.Register; //According to ECMA specs i4 -> u8 is always zero extended: http://jilc.sourceforge.net/ecma_p3_cil.shtml#Table7ConversionOperations m_state.RegisterConstantLoad(0x8080808000010203, 0x8080808000010203); m_state.Instructions.Add(new SPEEmulator.OpCodes.lqr(_RTMP1, 0)); m_state.Instructions.Add(new SPEEmulator.OpCodes.shufb((uint)output.RegisterNumber, (uint)input.RegisterNumber, (uint)input.RegisterNumber, _RTMP1)); PushStack(output); } else if (el.Childnodes[0].StorageClass == typeof(float)) { throw new MissingMethodException(); } else if (el.Childnodes[0].StorageClass == typeof(double)) { throw new MissingMethodException(); } else throw new InvalidProgramException(); }
public void Dup(InstructionElement el) { VirtualRegister i = PopStack(_RTMP0); VirtualRegister o1 = el.Register.RegisterNumber < 0 ? new TemporaryRegister(_RTMP0) : el.Register; VirtualRegister o2 = el.DupRegister.RegisterNumber < 0 ? new TemporaryRegister(_RTMP1) : el.DupRegister; if (i.RegisterNumber != o1.RegisterNumber) m_state.Instructions.Add(new SPEEmulator.OpCodes.ori((uint)o1.RegisterNumber, (uint)i.RegisterNumber, 0)); if (i.RegisterNumber != o2.RegisterNumber) m_state.Instructions.Add(new SPEEmulator.OpCodes.ori((uint)o2.RegisterNumber, (uint)i.RegisterNumber, 0)); PushStack(o2); PushStack(o1); }
public void Br(InstructionElement el) { m_state.RegisterBranch(((Mono.Cecil.Cil.Instruction)el.Instruction.Operand)); m_state.Instructions.Add(new SPEEmulator.OpCodes.br(_RTMP0, 0xffff)); }