Beispiel #1
0
        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);
        }
Beispiel #2
0
        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();
        }
Beispiel #3
0
 /// <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));
 }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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;
        }
Beispiel #6
0
 /// <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));
 }
Beispiel #7
0
        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));
            }
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
        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);
            }
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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);
        }
Beispiel #14
0
        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));
        }
Beispiel #15
0
 public void Br_s(InstructionElement el)
 {
     Br(el);
 }
Beispiel #16
0
 public void Brtrue_s(InstructionElement el)
 {
     Brtrue(el);
 }
Beispiel #17
0
 public void Ldarg_3(InstructionElement el)
 {
     PushStack(new VirtualRegister((uint)(_LV0 + m_state.Method.Method.Body.Variables.Count + 3)));
 }
Beispiel #18
0
        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();
        }
Beispiel #19
0
 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)));
 }
Beispiel #20
0
 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);
 }
Beispiel #21
0
 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);
 }
Beispiel #22
0
        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);
        }
Beispiel #23
0
        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);
        }
Beispiel #24
0
 public void Brfalse_s(InstructionElement el)
 {
     Brfalse(el);
 }
Beispiel #25
0
        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);
        }
Beispiel #26
0
 public void Conv_U1(InstructionElement el)
 {
     Conv_I1(el);
 }
Beispiel #27
0
 public void Ldelem_i8(InstructionElement el)
 {
     Ldelem_common(el);
 }
Beispiel #28
0
 public void Conv_U2(InstructionElement el)
 {
     Conv_I2(el);
 }
Beispiel #29
0
 /// <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));
 }
Beispiel #30
0
 public void Conv_U4(InstructionElement el)
 {
     Conv_I4(el);
 }
Beispiel #31
0
        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);
        }
Beispiel #32
0
        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();
        }
Beispiel #33
0
        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);
        }
Beispiel #34
0
 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));
 }