Beispiel #1
0
        private void RewritePush()
        {
            RegisterOperand reg = instrCur.op1 as RegisterOperand;

            if (reg != null && reg.Register == Registers.cs)
            {
                if (dasm.Peek(1).code == Opcode.call &&
                    dasm.Peek(1).op1.Width == PrimitiveType.Word16)
                {
                    dasm.MoveNext();
                    m.Assign(StackPointer(), m.ISub(StackPointer(), reg.Register.DataType.Size));
                    RewriteCall(dasm.Current.op1, dasm.Current.op1.Width);
                    this.len = (byte)(this.len + dasm.Current.Length);
                    return;
                }

                if (
                    dasm.Peek(1).code == Opcode.push && (dasm.Peek(1).op1 is ImmediateOperand) &&
                    dasm.Peek(2).code == Opcode.push && (dasm.Peek(2).op1 is ImmediateOperand) &&
                    dasm.Peek(3).code == Opcode.jmp && (dasm.Peek(3).op1 is X86AddressOperand))
                {
                    // That's actually a far call, but the callee thinks its a near call.
                    RewriteCall(dasm.Peek(3).op1, instrCur.op1.Width);
                    dasm.MoveNext();
                    dasm.MoveNext();
                    dasm.MoveNext();
                    return;
                }
            }
            var imm   = instrCur.op1 as ImmediateOperand;
            var value = SrcOp(dasm.Current.op1, arch.StackRegister.DataType);

            Debug.Assert(
                value.DataType.Size == 2 ||
                value.DataType.Size == 4 ||
                value.DataType.Size == 8,
                string.Format("Unexpected size {0}", dasm.Current.dataWidth));
            RewritePush(PrimitiveType.CreateWord(value.DataType.Size), value);
        }
Beispiel #2
0
        /// <summary>
        /// Visitation function for <see cref="IR.IIRVisitor.IntegerCompareInstruction"/> instruction.
        /// </summary>
        /// <param name="ctx">The context.</param>
        void IR.IIRVisitor.IntegerCompareInstruction(Context ctx)
        {
            EmitOperandConstants(ctx);

            IR.ConditionCode condition = ctx.ConditionCode;

            ctx.SetInstruction(CPUx86.Instruction.CmpInstruction, ctx.Result, ctx.Operand1);

            if (IsUnsigned(ctx.Operand1) || IsUnsigned(ctx.Result))
            {
                ctx.AppendInstruction(CPUx86.Instruction.SetccInstruction, GetUnsignedConditionCode(condition), ctx.Result);
            }
            else
            {
                ctx.AppendInstruction(CPUx86.Instruction.SetccInstruction, condition, ctx.Result);
            }

            if (ctx.Result is RegisterOperand)
            {
                RegisterOperand rop = new RegisterOperand(new SigType(CilElementType.U1), ((RegisterOperand)ctx.Result).Register);
                ctx.AppendInstruction(CPUx86.Instruction.MovzxInstruction, rop, rop);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Visitation function for <see cref="CIL.ICILVisitor.Ret"/>.
        /// </summary>
        /// <param name="ctx">The context.</param>
        void CIL.ICILVisitor.Ret(Context ctx)
        {
            bool eax = false;

            if (ctx.OperandCount != 0 && ctx.Operand1 != null)
            {
                Operand retval = ctx.Operand1;
                if (retval.IsRegister)
                {
                    // Do not move, if return value is already in EAX
                    RegisterOperand rop = (RegisterOperand)retval;
                    if (System.Object.ReferenceEquals(rop.Register, GeneralPurposeRegister.EAX))
                    {
                        eax = true;
                    }
                }

                if (!eax)
                {
                    ctx.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(new SigType(CilElementType.I), GeneralPurposeRegister.EAX), retval);
                }
            }
        }
        private int CompareOperands(MachineOperand opA, MachineOperand opB)
        {
            if (!opA.GetType().IsAssignableFrom(opB.GetType()))
            {
                return(-1);
            }

            RegisterOperand regOpA = opA as RegisterOperand;

            if (regOpA != null)
            {
                RegisterOperand regOpB = (RegisterOperand)opB;
                return((int)regOpB.Register.Number - (int)regOpA.Register.Number);
            }
            ImmediateOperand immOpA = opA as ImmediateOperand;

            if (immOpA != null)
            {
                ImmediateOperand immOpB = (ImmediateOperand)opB;
                return(0);                                      // disregard immediate values.
            }
            throw new NotImplementedException("NYI");
        }
        /// <summary>
        /// Visitation function for <see cref="CPUx86.IX86Visitor.Call"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        void CPUx86.IX86Visitor.Call(Context context)
        {
            Operand destinationOperand = context.Operand1;

            if (destinationOperand == null)
            {
                return;
            }

            if (destinationOperand is SymbolOperand)
            {
                return;
            }

            if (!(destinationOperand is RegisterOperand))
            {
                Context         before = context.InsertBefore();
                RegisterOperand eax    = new RegisterOperand(BuiltInSigType.IntPtr, GeneralPurposeRegister.EAX);

                before.SetInstruction(CPUx86.Instruction.MovInstruction, eax, destinationOperand);
                context.Operand1 = eax;
            }
        }
Beispiel #6
0
        /*
         * if (i < 2)
         *  return tc;
         * if (instrs[i-1].code != Opcode.test)
         *  return tc;
         * var ah = instrs[i-1].op1 as RegisterOperand;
         * if (ah == null || ah.Register != Registers.ah)
         *  return tc;
         * var m = instrs[i-1].op2 as ImmediateOperand;
         * if (m == null)
         *  return tc;
         *
         * if (instrs[i-2].code != Opcode.fstsw)
         *  return tc;
         * int mask = m.Value.ToInt32();
         *
         * var fpuf = orw.FlagGroup(FlagM.FPUF);
         * switch (cc)
         * {
         * case ConditionCode.PE:
         *  if (mask == 0x05) return new TestCondition(ConditionCode.LE, fpuf);
         *  if (mask == 0x41) return new TestCondition(ConditionCode.GE, fpuf);
         *  if (mask == 0x44) return new TestCondition(ConditionCode.NE, fpuf);
         *  break;
         * case ConditionCode.PO:
         *  if (mask == 0x44) return new TestCondition(ConditionCode.EQ, fpuf);
         *  if (mask == 0x41) return new TestCondition(ConditionCode.GE, fpuf);
         *  if (mask == 0x05) return new TestCondition(ConditionCode.GT, fpuf);
         *  break;
         * case ConditionCode.EQ:
         *  if (mask == 0x40) return new TestCondition(ConditionCode.NE, fpuf);
         *  if (mask == 0x41) return new TestCondition(ConditionCode.LT, fpuf);
         *  break;
         * case ConditionCode.NE:
         *  if (mask == 0x40) return new TestCondition(ConditionCode.EQ, fpuf);
         *  if (mask == 0x41) return new TestCondition(ConditionCode.GE, fpuf);
         *  if (mask == 0x01) return new TestCondition(ConditionCode.GT, fpuf);
         *  break;
         * }
         * throw new NotImplementedException(string.Format(
         *  "FSTSW/TEST AH,0x{0:X2}/J{1} not implemented.", mask, cc));
         */

        private void RewriteCall(MachineOperand callTarget, PrimitiveType opsize)
        {
            Address addr = OperandAsCodeAddress(callTarget);

            if (addr != null)
            {
                if (addr.ToLinear() == (dasm.Current.Address + dasm.Current.Length).ToLinear())
                {
                    // Calling the following address. Is the call followed by a
                    // pop?
                    var             next = dasm.Peek(1);
                    RegisterOperand reg  = next.op1 as RegisterOperand;
                    if (next.code == Opcode.pop && reg != null)
                    {
                        // call $+5,pop<reg> idiom
                        dasm.MoveNext();
                        m.Assign(
                            orw.AluRegister(reg),
                            addr);
                        this.len += 1;
                        return;
                    }
                }
                m.Call(addr, (byte)opsize.Size);
            }
            else
            {
                var target = SrcOp(callTarget);
                if (target.DataType.Size == 2)
                {
                    var seg = Constant.Create(PrimitiveType.SegmentSelector, instrCur.Address.Selector.Value);
                    target = m.Seq(seg, target);
                }
                m.Call(target, (byte)opsize.Size);
            }
            rtlc = RtlClass.Transfer | RtlClass.Call;
        }
        /*
         * if (i < 2)
         *  return tc;
         * if (instrs[i-1].code != Opcode.test)
         *  return tc;
         * var ah = instrs[i-1].op1 as RegisterOperand;
         * if (ah == null || ah.Register != Registers.ah)
         *  return tc;
         * var m = instrs[i-1].op2 as ImmediateOperand;
         * if (m == null)
         *  return tc;
         *
         * if (instrs[i-2].code != Opcode.fstsw)
         *  return tc;
         * int mask = m.Value.ToInt32();
         *
         * var fpuf = orw.FlagGroup(FlagM.FPUF);
         * switch (cc)
         * {
         * case ConditionCode.PE:
         *  if (mask == 0x05) return new TestCondition(ConditionCode.LE, fpuf);
         *  if (mask == 0x41) return new TestCondition(ConditionCode.GE, fpuf);
         *  if (mask == 0x44) return new TestCondition(ConditionCode.NE, fpuf);
         *  break;
         * case ConditionCode.PO:
         *  if (mask == 0x44) return new TestCondition(ConditionCode.EQ, fpuf);
         *  if (mask == 0x41) return new TestCondition(ConditionCode.GE, fpuf);
         *  if (mask == 0x05) return new TestCondition(ConditionCode.GT, fpuf);
         *  break;
         * case ConditionCode.EQ:
         *  if (mask == 0x40) return new TestCondition(ConditionCode.NE, fpuf);
         *  if (mask == 0x41) return new TestCondition(ConditionCode.LT, fpuf);
         *  break;
         * case ConditionCode.NE:
         *  if (mask == 0x40) return new TestCondition(ConditionCode.EQ, fpuf);
         *  if (mask == 0x41) return new TestCondition(ConditionCode.GE, fpuf);
         *  if (mask == 0x01) return new TestCondition(ConditionCode.GT, fpuf);
         *  break;
         * }
         * throw new NotImplementedException(string.Format(
         *  "FSTSW/TEST AH,0x{0:X2}/J{1} not implemented.", mask, cc));
         */

        private void RewriteCall(MachineOperand callTarget, PrimitiveType opsize)
        {
            Address addr = OperandAsCodeAddress(callTarget);

            if (addr != null)
            {
                if (addr.ToLinear() == (dasm.Current.Address + dasm.Current.Length).ToLinear())
                {
                    // Calling the following address. Is the call followed by a
                    // pop?
                    var             next = dasm.Peek(1);
                    RegisterOperand reg  = next.op1 as RegisterOperand;
                    if (next.code == Opcode.pop && reg != null)
                    {
                        // call $+5,pop<reg> idiom
                        dasm.MoveNext();
                        emitter.Assign(
                            orw.AluRegister(reg),
                            addr);
                        ric.Length += 1;
                        return;
                    }
                }
                emitter.Call(addr, (byte)opsize.Size);
                ric.Class = RtlClass.Transfer;
            }
            else
            {
                var target = SrcOp(callTarget);
                if (target.DataType.Size == 2)
                {
                    target = emitter.Seq(orw.AluRegister(Registers.cs), target);
                }
                emitter.Call(target, (byte)opsize.Size);
                ric.Class = RtlClass.Transfer;
            }
        }
Beispiel #8
0
        /// <summary>
        /// Replaces the instrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem)
        {
            MemoryOperand operand = new MemoryOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EAX, new System.IntPtr(0));

            context.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EAX), context.Operand1);
            context.AppendInstruction(CPUx86.Instruction.LgdtInstruction, null, operand);

            RegisterOperand ax = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), GeneralPurposeRegister.EAX);
            RegisterOperand ds = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.DS);
            RegisterOperand es = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.ES);
            RegisterOperand fs = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.FS);
            RegisterOperand gs = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.GS);
            RegisterOperand ss = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.SS);

            context.AppendInstruction(CPUx86.Instruction.MovInstruction, ax, new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), (int)0x00000010));
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, ds, ax);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, es, ax);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, fs, ax);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, gs, ax);
            context.AppendInstruction(CPUx86.Instruction.MovInstruction, ss, ax);
            context.AppendInstruction(CPUx86.Instruction.FarJmpInstruction);
            context.AppendInstruction(CPUx86.Instruction.NopInstruction);
            context.Previous.SetBranch(context.Offset);
        }
Beispiel #9
0
        /// <summary>
        /// Expands the given invoke instruction to perform the method call.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <returns>
        /// A single instruction or an array of instructions, which appropriately represent the method call.
        /// </returns>
        void ICallingConvention.Expand(Context ctx)
        {
            /*
             * Calling convention is right-to-left, pushed on the stack. Return value in EAX for integral
             * types 4 bytes or less, XMM0 for floating point and EAX:EDX for 64-bit. If this is a method
             * of a type, the this argument is moved to ECX right before the call.
             *
             */

            Runtime.Vm.RuntimeMethod invokeTarget = ctx.InvokeTarget;
            Operand result   = ctx.Result;
            Operand operand1 = ctx.Operand1;

            List <Operand> operands = new List <Operand> ();

            operands.AddRange(ctx.Operands);

            int resultCount  = ctx.ResultCount;
            int operandCount = ctx.OperandCount;

            SigType         I         = new SigType(CilElementType.I);
            RegisterOperand esp       = new RegisterOperand(I, GeneralPurposeRegister.ESP);
            int             stackSize = CalculateStackSizeForParameters(operands, invokeTarget.Signature.HasThis);

            ctx.SetInstruction(CPUx86.Instruction.NopInstruction);
            if (stackSize != 0)
            {
                ctx.AppendInstruction(CPUx86.Instruction.SubInstruction, esp, new ConstantOperand(I, stackSize));
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(_architecture.NativeType, GeneralPurposeRegister.EDX), esp);

                Stack <Operand> operandStack = GetOperandStackFromInstruction(operands, operandCount, invokeTarget.Signature.HasThis);

                int space = stackSize;
                CalculateRemainingSpace(ctx, operandStack, ref space);
            }

            if (invokeTarget.Signature.HasThis)
            {
                RegisterOperand ecx = new RegisterOperand(I, GeneralPurposeRegister.ECX);
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, operand1);
            }

            ctx.AppendInstruction(IR.Instruction.CallInstruction);
            ctx.InvokeTarget = invokeTarget;

            if (stackSize != 0)
            {
                ctx.AppendInstruction(CPUx86.Instruction.AddInstruction, esp, new ConstantOperand(I, stackSize));
            }

            if (resultCount > 0)
            {
                if (result.StackType == StackTypeCode.Int64)
                {
                    MoveReturnValueTo64Bit(result, ctx);
                }
                else
                {
                    MoveReturnValueTo32Bit(result, ctx);
                }
            }

            //ctx.Remove();
        }
Beispiel #10
0
        private Pdp11Instruction DecodeOperands(ushort wOpcode, Opcode opcode, string fmt)
        {
            List <MachineOperand> ops = new List <MachineOperand>(2);
            int i = 0;

            dataWidth = PrimitiveType.Word16;
            if (fmt.Length == 0)
            {
                return(new Pdp11Instruction
                {
                    Opcode = opcode,
                });
            }
            switch (fmt[i])
            {
            case 'b': dataWidth = PrimitiveType.Byte; i += 2; break;

            case 'w': dataWidth = PrimitiveType.Word16; i += 2; break;
            }
            while (i != fmt.Length)
            {
                if (fmt[i] == ',')
                {
                    ++i;
                }
                MachineOperand op;
                switch (fmt[i++])
                {
                case 'E': op = this.DecodeOperand(wOpcode); break;

                case 'e': op = this.DecodeOperand(wOpcode >> 6); break;

                case 'r': op = new RegisterOperand(arch.GetRegister((wOpcode >> 6) & 7)); break;

                case 'I': op = Imm6(wOpcode); break;

                case 'F': op = this.DecodeOperand(wOpcode, true); break;

                case 'f': op = FpuAccumulator(wOpcode); break;

                default: throw new NotImplementedException();
                }
                if (op == null)
                {
                    return new Pdp11Instruction {
                               Opcode = Opcode.illegal
                    }
                }
                ;
                ops.Add(op);
            }
            var instr = new Pdp11Instruction
            {
                Opcode    = opcode,
                DataWidth = dataWidth,
                op1       = ops.Count > 0 ? ops[0] : null,
                op2       = ops.Count > 1 ? ops[1] : null,
            };

            return(instr);
        }
Beispiel #11
0
        private Tms7000Instruction Decode(Opcode opcode, string format)
        {
            int iOp   = 0;
            var instr = new Tms7000Instruction
            {
                Opcode = opcode,
            };

            for (int i = 0; i < format.Length; ++i)
            {
                MachineOperand op;
                byte           b;
                ushort         w;
                switch (format[i])
                {
                case ',': continue;

                case 'A':
                    op = new RegisterOperand(arch.a);
                    break;

                case 'B':
                    op = new RegisterOperand(arch.b);
                    break;

                case 'R':
                    if (!rdr.TryReadByte(out b))
                    {
                        return(Invalid());
                    }
                    op = new RegisterOperand(arch.GpRegs[b]);
                    break;

                case 'P':
                    if (!rdr.TryReadByte(out b))
                    {
                        return(Invalid());
                    }
                    op = new RegisterOperand(arch.Ports[b]);
                    break;

                case 'S':
                    ;                   op = new RegisterOperand(arch.st);
                    break;

                case 'i':
                    if (!rdr.TryReadByte(out b))
                    {
                        return(Invalid());
                    }
                    op = ImmediateOperand.Byte(b);
                    break;

                case 'I':
                    if (!rdr.TryReadBeUInt16(out w))
                    {
                        return(Invalid());
                    }
                    op = ImmediateOperand.Word16(w);
                    break;

                case 'j':   // short PC-relative jump
                    if (!rdr.TryReadByte(out b))
                    {
                        return(Invalid());
                    }
                    op = AddressOperand.Create(rdr.Address + (sbyte)b);
                    break;

                case 'D':  // direct, absolute address
                    if (!rdr.TryReadBeUInt16(out w))
                    {
                        return(Invalid());
                    }
                    if (i < format.Length - 1 && format[i + 1] == 'B')
                    {
                        ++i;
                        op = MemoryOperand.Indexed(Address.Ptr16(w), arch.b);
                    }
                    else
                    {
                        op = MemoryOperand.Direct(Address.Ptr16(w));
                    }
                    break;

                case '*': // indirect
                    if (!rdr.TryReadByte(out b))
                    {
                        return(Invalid());
                    }
                    op = MemoryOperand.Indirect(arch.GpRegs[b]);
                    break;

                default: throw new NotImplementedException($"Addressing mode {format[i]}");
                }
                switch (iOp++)
                {
                case 0: instr.op1 = op; break;

                case 1: instr.op2 = op; break;

                case 2: instr.op3 = op; break;
                }
            }
            return(instr);
        }
Beispiel #12
0
 public void Stbu(RegisterOperand rS, short offset, RegisterOperand rA)
 {
     Add(new PowerPcInstruction(Opcode.stbu, rS, Mem(rA, offset), null, false));
 }
Beispiel #13
0
 public void Mtctr(RegisterOperand r)
 {
     Add(new PowerPcInstruction(Opcode.mtctr, r, null, null, false));
 }
Beispiel #14
0
 public void Oris(RegisterOperand rA, RegisterOperand rS, ushort val)
 {
     Add(new PowerPcInstruction(Opcode.oris, rA, rS, new ImmediateOperand(Constant.Word16(val)), false));
 }
Beispiel #15
0
        /// <summary>
        /// Floatings the point compare instruction.
        /// </summary>
        /// <param name="ctx">The context.</param>
        void IR.IIRVisitor.FloatingPointCompareInstruction(Context ctx)
        {
            Operand op0   = ctx.Result;
            Operand left  = EmitConstant(ctx.Operand1);
            Operand right = EmitConstant(ctx.Operand2);

            //ctx.Remove();
            ctx.Operand1 = left;
            ctx.Operand2 = right;


            // Swap the operands if necessary...
            if (left is MemoryOperand && right is RegisterOperand)
            {
                SwapComparisonOperands(ctx);
                left  = ctx.Operand1;
                right = ctx.Operand2;
            }

            IR.ConditionCode setcc = IR.ConditionCode.Equal;
            IR.ConditionCode code  = ctx.ConditionCode;

            ctx.SetInstruction(CPUx86.Instruction.NopInstruction);

            // x86 is messed up :(
            switch (code)
            {
            case IR.ConditionCode.Equal:
                break;

            case IR.ConditionCode.NotEqual:
                break;

            case IR.ConditionCode.UnsignedGreaterOrEqual:
                setcc = IR.ConditionCode.GreaterOrEqual;
                break;

            case IR.ConditionCode.UnsignedGreaterThan:
                setcc = IR.ConditionCode.GreaterThan;
                break;

            case IR.ConditionCode.UnsignedLessOrEqual:
                setcc = IR.ConditionCode.LessOrEqual;
                break;

            case IR.ConditionCode.UnsignedLessThan:
                setcc = IR.ConditionCode.LessThan;
                break;

            case IR.ConditionCode.GreaterOrEqual:
                setcc = IR.ConditionCode.UnsignedGreaterOrEqual;
                break;

            case IR.ConditionCode.GreaterThan:
                setcc = IR.ConditionCode.UnsignedGreaterThan;
                break;

            case IR.ConditionCode.LessOrEqual:
                setcc = IR.ConditionCode.UnsignedLessOrEqual;
                break;

            case IR.ConditionCode.LessThan:
                setcc = IR.ConditionCode.UnsignedLessThan;
                break;
            }

            if (!(left is RegisterOperand))
            {
                RegisterOperand xmm2 = new RegisterOperand(left.Type, SSE2Register.XMM2);
                if (left.Type.Type == CilElementType.R4)
                {
                    ctx.AppendInstruction(CPUx86.Instruction.MovssInstruction, xmm2, left);
                }
                else
                {
                    ctx.AppendInstruction(CPUx86.Instruction.MovsdInstruction, xmm2, left);
                }
                left = xmm2;
            }

            // Compare using the smallest precision
            if (left.Type.Type == CilElementType.R4 && right.Type.Type == CilElementType.R8)
            {
                RegisterOperand rop = new RegisterOperand(new SigType(CilElementType.R4), SSE2Register.XMM4);
                ctx.AppendInstruction(CPUx86.Instruction.Cvtsd2ssInstruction, rop, right);
                right = rop;
            }
            if (left.Type.Type == CilElementType.R8 && right.Type.Type == CilElementType.R4)
            {
                RegisterOperand rop = new RegisterOperand(new SigType(CilElementType.R4), SSE2Register.XMM3);
                ctx.AppendInstruction(CPUx86.Instruction.Cvtsd2ssInstruction, rop, left);
                left = rop;
            }

            if (left.Type.Type == CilElementType.R4)
            {
                switch (code)
                {
                case IR.ConditionCode.Equal:
                    ctx.AppendInstruction(CPUx86.Instruction.UcomissInstruction, left, right);
                    break;

                case IR.ConditionCode.NotEqual:
                    goto case IR.ConditionCode.Equal;

                case IR.ConditionCode.UnsignedGreaterOrEqual:
                    goto case IR.ConditionCode.Equal;

                case IR.ConditionCode.UnsignedGreaterThan:
                    goto case IR.ConditionCode.Equal;

                case IR.ConditionCode.UnsignedLessOrEqual:
                    goto case IR.ConditionCode.Equal;

                case IR.ConditionCode.UnsignedLessThan:
                    goto case IR.ConditionCode.Equal;

                case IR.ConditionCode.GreaterOrEqual:
                    ctx.AppendInstruction(CPUx86.Instruction.ComissInstruction, left, right);
                    break;

                case IR.ConditionCode.GreaterThan:
                    goto case IR.ConditionCode.GreaterOrEqual;

                case IR.ConditionCode.LessOrEqual:
                    goto case IR.ConditionCode.GreaterOrEqual;

                case IR.ConditionCode.LessThan:
                    goto case IR.ConditionCode.GreaterOrEqual;
                }
            }


            else
            {
                switch (code)
                {
                case IR.ConditionCode.Equal:
                    ctx.AppendInstruction(CPUx86.Instruction.UcomisdInstruction, left, right);
                    break;

                case IR.ConditionCode.NotEqual:
                    goto case IR.ConditionCode.Equal;

                case IR.ConditionCode.UnsignedGreaterOrEqual:
                    goto case IR.ConditionCode.Equal;

                case IR.ConditionCode.UnsignedGreaterThan:
                    goto case IR.ConditionCode.Equal;

                case IR.ConditionCode.UnsignedLessOrEqual:
                    goto case IR.ConditionCode.Equal;

                case IR.ConditionCode.UnsignedLessThan:
                    goto case IR.ConditionCode.Equal;

                case IR.ConditionCode.GreaterOrEqual:
                    ctx.AppendInstruction(CPUx86.Instruction.ComisdInstruction, left, right);
                    break;

                case IR.ConditionCode.GreaterThan:
                    goto case IR.ConditionCode.GreaterOrEqual;

                case IR.ConditionCode.LessOrEqual:
                    goto case IR.ConditionCode.GreaterOrEqual;

                case IR.ConditionCode.LessThan:
                    goto case IR.ConditionCode.GreaterOrEqual;
                }
            }

            // Determine the result
            ctx.AppendInstruction(CPUx86.Instruction.SetccInstruction, setcc, op0);

            // Extend this to the full register, if we're storing it in a register
            if (op0 is RegisterOperand)
            {
                RegisterOperand rop = new RegisterOperand(new SigType(CilElementType.U1), ((RegisterOperand)op0).Register);
                ctx.AppendInstruction(CPUx86.Instruction.MovzxInstruction, op0, rop);
            }
        }
 public virtual string FormatOperand(RegisterOperand operand)
 {
     StringBuilder sb = new StringBuilder(10);
     FormatRegister(sb, operand.Register);
     return sb.ToString();
 }
        /// <summary>
        /// Writes an effective address operand.
        /// </summary>
        /// <returns>The number of characters written.</returns>
        private int WriteOperand(RegisterOperand operand, bool writeSize)
        {
            #region Contract
            if (operand == null) return 0;
            #endregion
            int length = 0;

            if (writeSize)
            {
                switch (operand.RequestedSize)
                {
                    case DataSize.Bit8:
                        Writer.Write("byte ");
                        length += 5;
                        break;
                    case DataSize.Bit16:
                        Writer.Write("word ");
                        length += 5;
                        break;
                    case DataSize.Bit32:
                        Writer.Write("dword ");
                        length += 6;
                        break;
                    case DataSize.Bit64:
                        Writer.Write("qword ");
                        length += 6;
                        break;
                    case DataSize.None:
                        break;
                    default:
                        throw new LanguageException(ExceptionStrings.UnknownRequestedSize);
                }
            }

            string str = Enum.GetName(typeof(Register), operand.Register);
            length += str.Length;
            Writer.Write(str);
            return length;
        }
Beispiel #18
0
        public bool MatchesFstswSequence()
        {
            var nextInstr = dasm.Peek(1);

            if (nextInstr.Mnemonic == Mnemonic.sahf)
            {
                this.len += nextInstr.Length;
                dasm.Skip(1);
                m.Assign(
                    orw.FlagGroup(FlagM.ZF | FlagM.CF | FlagM.SF | FlagM.OF),
                    orw.AluRegister(Registers.FPUF));
                return(true);
            }
            if (nextInstr.Mnemonic == Mnemonic.test)
            {
                RegisterOperand  acc = nextInstr.Operands[0] as RegisterOperand;
                ImmediateOperand imm = nextInstr.Operands[1] as ImmediateOperand;
                if (imm == null || acc == null)
                {
                    return(false);
                }
                int mask = imm.Value.ToInt32();
                if (acc.Register == Registers.ax || acc.Register == Registers.eax)
                {
                    mask >>= 8;
                }
                else if (acc.Register != Registers.ah)
                {
                    return(false);
                }
                this.len += nextInstr.Length;
                m.Assign(
                    orw.FlagGroup(FlagM.ZF | FlagM.CF | FlagM.SF | FlagM.OF),
                    orw.AluRegister(Registers.FPUF));

                // Advance past the 'test' instruction.
                dasm.Skip(1);
                while (dasm.MoveNext())
                {
                    instrCur  = dasm.Current;
                    this.len += instrCur.Length;

                    /* fcom/fcomp/fcompp Results:
                     *  Condition      C3  C2  C0
                     *  ST(0) > SRC     0   0   0
                     *  ST(0) < SRC     0   0   1
                     *  ST(0) = SRC     1   0   0
                     *  Unordered       1   1   1
                     *
                     * Masks:
                     *  Mask   Flags
                     *  0x01   C0
                     *  0x04   C2
                     *  0x40   C3
                     *  0x05   C2 and C0
                     *  0x41   C3 and C0
                     *  0x44   C3 and C2
                     *
                     * Masks && jump operations:
                     *  Mnem   Mask Condition
                     *  jpe    0x05    >=
                     *  jpe    0x41    >
                     *  jpe    0x44    !=
                     *  jpo    0x05    <
                     *  jpo    0x41    <=
                     *  jpo    0x44    =
                     *  jz     0x01    >=
                     *  jz     0x40    !=
                     *  jz     0x41    >
                     *  jnz    0x01    <
                     *  jnz    0x40    =
                     *  jnz    0x41    <=
                     */

                    switch (instrCur.Mnemonic)
                    {
                    //$TODO The following instructions are being added on an ad-hoc
                    // basis, since they don't affect the x86 flags register.
                    // The long term fix is to implement an architecture-specific
                    // condition code elimination pass as described elsewhere.
                    case Mnemonic.mov: RewriteMov(); break;

                    case Mnemonic.fstp: RewriteFst(true); break;

                    case Mnemonic.push: RewritePush(); break;

                    case Mnemonic.lea: RewriteLea(); break;

                    case Mnemonic.jpe:
                        if (mask == 0x05)
                        {
                            Branch(ConditionCode.GE, instrCur.Operands[0]); return(true);
                        }
                        if (mask == 0x41)
                        {
                            Branch(ConditionCode.GT, instrCur.Operands[0]); return(true);
                        }
                        if (mask == 0x44)
                        {
                            Branch(ConditionCode.NE, instrCur.Operands[0]); return(true);
                        }
                        throw new AddressCorrelatedException(instrCur.Address, "Unexpected {0} fstsw mask for {1} mnemonic.", mask, instrCur.Mnemonic);

                    case Mnemonic.jpo:
                        if (mask == 0x44)
                        {
                            Branch(ConditionCode.EQ, instrCur.Operands[0]); return(true);
                        }
                        if (mask == 0x41)
                        {
                            Branch(ConditionCode.LE, instrCur.Operands[0]); return(true);
                        }
                        if (mask == 0x05)
                        {
                            Branch(ConditionCode.LT, instrCur.Operands[0]); return(true);
                        }
                        throw new AddressCorrelatedException(instrCur.Address, "Unexpected {0} fstsw mask for {1} mnemonic.", mask, instrCur.Mnemonic);

                    case Mnemonic.jz:
                        if (mask == 0x40)
                        {
                            Branch(ConditionCode.NE, instrCur.Operands[0]); return(true);
                        }
                        if (mask == 0x41)
                        {
                            Branch(ConditionCode.GT, instrCur.Operands[0]); return(true);
                        }
                        if (mask == 0x01)
                        {
                            Branch(ConditionCode.GE, instrCur.Operands[0]); return(true);
                        }
                        throw new AddressCorrelatedException(instrCur.Address, "Unexpected {0} fstsw mask for {1} mnemonic.", mask, instrCur.Mnemonic);

                    case Mnemonic.jnz:
                        if (mask == 0x40)
                        {
                            Branch(ConditionCode.EQ, instrCur.Operands[0]); return(true);
                        }
                        if (mask == 0x41)
                        {
                            Branch(ConditionCode.LE, instrCur.Operands[0]); return(true);
                        }
                        if (mask == 0x01)
                        {
                            Branch(ConditionCode.LT, instrCur.Operands[0]); return(true);
                        }
                        throw new AddressCorrelatedException(instrCur.Address, "Unexpected {0} fstsw mask for {1} mnemonic.", mask, instrCur.Mnemonic);

                    default:
                        throw new AddressCorrelatedException(instrCur.Address, "Unexpected instruction {0} after fstsw", instrCur);
                    }
                }
                throw new AddressCorrelatedException(instrCur.Address, "Expected branch instruction after fstsw;test {0},{1}.", acc.Register, imm.Value);
            }
            return(false);
        }
Beispiel #19
0
 public CallPtrInstruction(IOperand target, RegisterOperand returnAddressTarget)
 {
     operands = returnAddressTarget == null ? new[] { target } : new[] { target, returnAddressTarget };
 }
Beispiel #20
0
 public void Lis(RegisterOperand r, ushort uimm)
 {
     Add(new PowerPcInstruction(Opcode.oris, r, r, new ImmediateOperand(Constant.Word16(uimm)), false));
 }
Beispiel #21
0
 public void Add_(RegisterOperand rT, RegisterOperand rA, RegisterOperand rB)
 {
     Add(new PowerPcInstruction(Opcode.add, rT, rA, rB, true));
 }
Beispiel #22
0
 public Identifier AluRegister(RegisterOperand reg)
 {
     return(binder.EnsureRegister(reg.Register));
 }
Beispiel #23
0
 public void Lwz(RegisterOperand rD, short offset, RegisterOperand rA)
 {
     Add(new PowerPcInstruction(Opcode.lwz, rD, new MemoryOperand(rD.Register.DataType, rA.Register, Constant.Int16(offset)), null, false));
 }
Beispiel #24
0
        public bool MatchesFstswSequence()
        {
            var nextInstr = dasm.Peek(1);

            if (nextInstr.code == Opcode.sahf)
            {
                ric.Length += (byte)nextInstr.Length;
                dasm.Skip(1);
                emitter.Assign(
                    orw.FlagGroup(FlagM.ZF | FlagM.CF | FlagM.SF | FlagM.OF),
                    orw.FlagGroup(FlagM.FPUF));
                return(true);
            }
            if (nextInstr.code == Opcode.test)
            {
                RegisterOperand  acc = nextInstr.op1 as RegisterOperand;
                ImmediateOperand imm = nextInstr.op2 as ImmediateOperand;
                if (imm == null || acc == null)
                {
                    return(false);
                }
                int mask = imm.Value.ToInt32();
                if (acc.Register == Registers.ax || acc.Register == Registers.eax)
                {
                    mask >>= 8;
                }
                else if (acc.Register != Registers.ah)
                {
                    return(false);
                }
                ric.Length += (byte)nextInstr.Length;
                dasm.Skip(1);
                emitter.Assign(
                    orw.FlagGroup(FlagM.ZF | FlagM.CF | FlagM.SF | FlagM.OF), orw.FlagGroup(FlagM.FPUF));
                if (!dasm.MoveNext())
                {
                    throw new AddressCorrelatedException(nextInstr.Address, "Expected instruction after fstsw;test {0},{1}.", acc.Register, imm.Value);
                }
                nextInstr   = dasm.Current;
                ric.Length += (byte)nextInstr.Length;
                //var r = new RtlInstructionCluster(nextInstr.Address, nextInstr.Length);
                //r.Instructions.AddRange(ric.Instructions);
                //emitter = new RtlEmitter(r.Instructions);
                //ric = r;
                switch (nextInstr.code)
                {
                case Opcode.jpe:
                    if (mask == 0x05)
                    {
                        Branch(ConditionCode.LE, nextInstr.op1); return(true);
                    }
                    if (mask == 0x41)
                    {
                        Branch(ConditionCode.GE, nextInstr.op1); return(true);
                    }
                    if (mask == 0x44)
                    {
                        Branch(ConditionCode.NE, nextInstr.op1); return(true);
                    }
                    break;

                case Opcode.jpo:
                    if (mask == 0x44)
                    {
                        Branch(ConditionCode.EQ, nextInstr.op1); return(true);
                    }
                    if (mask == 0x41)
                    {
                        Branch(ConditionCode.GE, nextInstr.op1); return(true);
                    }
                    if (mask == 0x05)
                    {
                        Branch(ConditionCode.LT, nextInstr.op1); return(true);
                    }
                    break;

                case Opcode.jz:
                    if (mask == 0x40)
                    {
                        Branch(ConditionCode.NE, nextInstr.op1); return(true);
                    }
                    if (mask == 0x41)
                    {
                        Branch(ConditionCode.LT, nextInstr.op1); return(true);
                    }
                    break;

                case Opcode.jnz:
                    if (mask == 0x40)
                    {
                        Branch(ConditionCode.EQ, nextInstr.op1); return(true);
                    }
                    if (mask == 0x41)
                    {
                        Branch(ConditionCode.GE, nextInstr.op1); return(true);
                    }
                    if (mask == 0x01)
                    {
                        Branch(ConditionCode.GT, nextInstr.op1); return(true);
                    }
                    break;
                }

                return(false);
            }
            return(false);
        }
Beispiel #25
0
 public void Stbux(RegisterOperand rS, RegisterOperand rA, RegisterOperand rB)
 {
     Add(new PowerPcInstruction(Opcode.stbux, rS, rA, rB, false));
 }
        /// <summary>
        /// Calculates the value of the modR/M byte and SIB bytes.
        /// </summary>
        /// <param name="regField">The modR/M regfield value.</param>
        /// <param name="op1">The destination operand.</param>
        /// <param name="op2">The source operand.</param>
        /// <param name="sib">A potential SIB byte to emit.</param>
        /// <param name="displacement">An immediate displacement to emit.</param>
        /// <returns>The value of the modR/M byte.</returns>
        private static byte?CalculateModRM(byte?regField, Operand op1, Operand op2, out byte?sib, out Operand displacement)
        {
            byte?modRM = null;

            displacement = null;

            // FIXME: Handle the SIB byte
            sib = null;

            RegisterOperand rop1 = op1 as RegisterOperand, rop2 = op2 as RegisterOperand;
            MemoryOperand   mop1 = op1 as MemoryOperand, mop2 = op2 as MemoryOperand;

            // Normalize the operand order
            if (rop1 == null && rop2 != null)
            {
                // Swap the memory operands
                rop1 = rop2; rop2 = null;
                mop2 = mop1; mop1 = null;
            }

            if (regField != null)
            {
                modRM = (byte)(regField.Value << 3);
            }

            if (rop1 != null && rop2 != null)
            {
                // mod = 11b, reg = rop1, r/m = rop2
                modRM = (byte)((3 << 6) | (rop1.Register.RegisterCode << 3) | rop2.Register.RegisterCode);
            }
            // Check for register/memory combinations
            else if (mop2 != null && mop2.Base != null)
            {
                // mod = 10b, reg = rop1, r/m = mop2
                modRM = (byte)(modRM.GetValueOrDefault() | (2 << 6) | (byte)mop2.Base.RegisterCode);
                if (rop1 != null)
                {
                    modRM |= (byte)(rop1.Register.RegisterCode << 3);
                }
                displacement = mop2;
                if (mop2.Base.RegisterCode == 4)
                {
                    sib = 0xA4;
                }
            }
            else if (mop2 != null)
            {
                // mod = 10b, r/m = mop1, reg = rop2
                modRM = (byte)(modRM.GetValueOrDefault() | 5);
                if (rop1 != null)
                {
                    modRM |= (byte)(rop1.Register.RegisterCode << 3);
                }
                displacement = mop2;
            }
            else if (mop1 != null && mop1.Base != null)
            {
                // mod = 10b, r/m = mop1, reg = rop2
                modRM = (byte)(modRM.GetValueOrDefault() | (2 << 6) | mop1.Base.RegisterCode);
                if (rop2 != null)
                {
                    modRM |= (byte)(rop2.Register.RegisterCode << 3);
                }
                displacement = mop1;
                if (mop1.Base.RegisterCode == 4)
                {
                    sib = 0xA4;
                }
            }
            else if (mop1 != null)
            {
                // mod = 10b, r/m = mop1, reg = rop2
                modRM = (byte)(modRM.GetValueOrDefault() | 5);
                if (rop2 != null)
                {
                    modRM |= (byte)(rop2.Register.RegisterCode << 3);
                }
                displacement = mop1;
            }
            else if (rop1 != null)
            {
                modRM = (byte)(modRM.GetValueOrDefault() | (3 << 6) | rop1.Register.RegisterCode);
                //if (op2 is SymbolOperand)
                //    displacement = op2;
            }

            return(modRM);
        }
Beispiel #27
0
 private MemoryOperand Mem(RegisterOperand baseReg, short offset)
 {
     return(new MemoryOperand(baseReg.Register.DataType, baseReg.Register, Constant.Int16(offset)));
 }
Beispiel #28
0
        private bool TryParseOperandInner(ushort uInstr, byte addressMode, byte operandBits, PrimitiveType dataWidth, EndianImageReader rdr, out MachineOperand op)
        {
            Constant offset;

            switch (addressMode)
            {
            case 0: // Data register direct.
                op = DataRegisterOperand(operandBits, 0);
                return(true);

            case 1: // Address register direct
                op = new RegisterOperand(AddressRegister(operandBits, 0));
                return(true);

            case 2:  // Address register indirect
                op = MemoryOperand.Indirect(dataWidth, AddressRegister(operandBits, 0));
                return(true);

            case 3:  // Address register indirect with postincrement.
                op = MemoryOperand.PostIncrement(dataWidth, AddressRegister(operandBits, 0));
                return(true);

            case 4:  // Address register indirect with predecrement.
                op = MemoryOperand.PreDecrement(dataWidth, AddressRegister(operandBits, 0));
                return(true);

            case 5: // Address register indirect with displacement.
                if (!rdr.TryReadBe(PrimitiveType.Int16, out offset))
                {
                    op = null;
                    return(false);
                }
                op = MemoryOperand.Indirect(dataWidth, AddressRegister(operandBits, 0), offset);
                return(true);

            case 6: // Address register indirect with index
                return(TryAddressRegisterIndirectWithIndex(uInstr, dataWidth, rdr, out op));

            case 7:
                switch (operandBits)
                {
                case 0: // Absolute short address
                    ushort usAddr;
                    if (!rdr.TryReadBeUInt16(out usAddr))
                    {
                        op = null; return(false);
                    }
                    op = new M68kAddressOperand(usAddr);
                    return(true);

                case 1: // Absolute long address
                    uint uAddr;
                    if (!rdr.TryReadBeUInt32(out uAddr))
                    {
                        op = null; return(false);
                    }
                    op = new M68kAddressOperand(uAddr);
                    return(true);

                case 2: // Program counter with displacement
                    var   off = rdr.Address - dasm.instr.Address;
                    short sOffset;
                    if (!rdr.TryReadBeInt16(out sOffset))
                    {
                        op = null; return(false);
                    }
                    off += sOffset;
                    op   = new MemoryOperand(dataWidth, Registers.pc, Constant.Int16((short)off));
                    return(true);

                case 3:
                    // Program counter with index
                    var    addrExt = rdr.Address;
                    ushort extension;
                    if (!rdr.TryReadBeUInt16(out extension))
                    {
                        op = null; return(false);
                    }

                    if (EXT_FULL(extension))
                    {
                        if (EXT_EFFECTIVE_ZERO(extension))
                        {
                            op = new M68kImmediateOperand(Constant.Word32(0));
                            return(true);
                        }
                        Constant @base = null;
                        Constant outer = null;
                        if (EXT_BASE_DISPLACEMENT_PRESENT(extension))
                        {
                            @base = EXT_BASE_DISPLACEMENT_LONG(extension)
                                ? rdr.ReadBe(PrimitiveType.Word32)
                                : rdr.ReadBe(PrimitiveType.Int16);
                        }
                        if (EXT_OUTER_DISPLACEMENT_PRESENT(extension))
                        {
                            outer = EXT_OUTER_DISPLACEMENT_LONG(extension)
                                ? rdr.ReadBe(PrimitiveType.Word32)
                                : rdr.ReadBe(PrimitiveType.Int16);
                        }
                        RegisterStorage base_reg = EXT_BASE_REGISTER_PRESENT(extension)
                            ? Registers.pc
                            : null;
                        RegisterStorage index_reg   = null;
                        PrimitiveType   index_width = null;
                        int             index_scale = 0;
                        if (EXT_INDEX_REGISTER_PRESENT(extension))
                        {
                            index_reg = EXT_INDEX_AR(extension)
                                ? Registers.AddressRegister((int)EXT_INDEX_REGISTER(extension))
                                : Registers.DataRegister((int)EXT_INDEX_REGISTER(extension));
                            index_width = EXT_INDEX_LONG(extension) ? PrimitiveType.Word32 : PrimitiveType.Int16;
                            index_scale = (EXT_INDEX_SCALE(extension) != 0)
                                ? 1 << EXT_INDEX_SCALE(extension)
                                : 0;
                        }
                        op = new IndexedOperand(dataWidth, @base, outer, base_reg, index_reg, index_width, index_scale,
                                                (extension & 7) > 0 && (extension & 7) < 4,
                                                (extension & 7) > 4);
                        return(true);
                    }
                    op = new IndirectIndexedOperand(
                        dataWidth,
                        EXT_8BIT_DISPLACEMENT(extension),
                        Registers.pc,
                        EXT_INDEX_AR(extension)
                            ? Registers.AddressRegister((int)EXT_INDEX_REGISTER(extension))
                            : Registers.DataRegister((int)EXT_INDEX_REGISTER(extension)),
                        EXT_INDEX_LONG(extension)
                            ? PrimitiveType.Word32
                            : PrimitiveType.Int16,
                        1 << EXT_INDEX_SCALE(extension));
                    return(true);

                case 4:
                    //  Immediate
                    if (dataWidth.Size == 1)        // don't want the instruction stream to get misaligned!
                    {
                        rdr.Offset += 1;
                    }
                    Constant coff;
                    if (!rdr.TryReadBe(dataWidth, out coff))
                    {
                        op = null; return(false);
                    }
                    op = new M68kImmediateOperand(coff);
                    return(true);

                default:
                    op = null;
                    return(false);
                }

            default:
                throw new NotImplementedException(string.Format("Address mode {0:X1} not implemented.", addressMode));
            }
        }
        /// <summary>
        /// Converts the given instruction from three address format to a two address format.
        /// </summary>
        /// <param name="ctx">The conversion context.</param>
        private static void ThreeTwoAddressConversion(Context ctx)
        {
            Operand result = ctx.Result;
            Operand op1    = ctx.Operand1;
            Operand op2    = ctx.Operand2;

            if (ctx.Instruction is IR.IntegerCompareInstruction ||
                ctx.Instruction is IR.FloatingPointCompareInstruction ||
                ctx.Instruction is IR.LoadInstruction ||
                ctx.Instruction is IR.StoreInstruction)
            {
                return;
            }

            if (ctx.Instruction is CIL.MulInstruction)
            {
                if (!(op1 is ConstantOperand) && (op2 is ConstantOperand))
                {
                    Operand temp = op1;
                    op1 = op2;
                    op2 = temp;
                }
            }

            // Create registers for different data types
            RegisterOperand eax          = new RegisterOperand(op1.Type, op1.StackType == StackTypeCode.F ? (Register)SSE2Register.XMM0 : GeneralPurposeRegister.EAX);
            RegisterOperand storeOperand = new RegisterOperand(result.Type, result.StackType == StackTypeCode.F ? (Register)SSE2Register.XMM0 : GeneralPurposeRegister.EAX);

            //    RegisterOperand eaxL = new RegisterOperand(op1.Type, GeneralPurposeRegister.EAX);

            ctx.Result       = storeOperand;
            ctx.Operand1     = op2;
            ctx.Operand2     = null;
            ctx.OperandCount = 1;

            if (op1.StackType != StackTypeCode.F)
            {
                if (IsSigned(op1) && !(op1 is ConstantOperand))
                {
                    ctx.InsertBefore().SetInstruction(IR.Instruction.SignExtendedMoveInstruction, eax, op1);
                }
                else if (IsUnsigned(op1) && !(op1 is ConstantOperand))
                {
                    ctx.InsertBefore().SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, eax, op1);
                }
                else
                {
                    ctx.InsertBefore().SetInstruction(CPUx86.Instruction.MovInstruction, eax, op1);
                }
            }
            else
            {
                if (op1.Type.Type == CilElementType.R4)
                {
                    if (op1 is ConstantOperand)
                    {
                        Context before = ctx.InsertBefore();
                        before.SetInstruction(CPUx86.Instruction.MovInstruction, eax, op1);
                        before.AppendInstruction(CPUx86.Instruction.Cvtss2sdInstruction, eax, eax);
                    }
                    else
                    {
                        ctx.InsertBefore().SetInstruction(CPUx86.Instruction.Cvtss2sdInstruction, eax, op1);
                    }
                }
                else
                {
                    ctx.InsertBefore().SetInstruction(CPUx86.Instruction.MovInstruction, eax, op1);
                }
            }

            ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, result, eax);
        }
Beispiel #30
0
        /// <summary>
        /// Moves the return value to 32 bit.
        /// </summary>
        /// <param name="resultOperand">The result operand.</param>
        /// <param name="ctx">The context.</param>
        private static void MoveReturnValueTo32Bit(Operand resultOperand, Context ctx)
        {
            RegisterOperand eax = new RegisterOperand(resultOperand.Type, GeneralPurposeRegister.EAX);

            ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, resultOperand, eax);
        }
Beispiel #31
0
        private bool TryDecodeOperand(PrimitiveType width, out MachineOperand op)
        {
            op = null;
            byte   b;
            byte   bSpecifier;
            ushort w;
            uint   dw;

            if (!rdr.TryReadByte(out bSpecifier))
            {
                return(false);
            }
            var reg = arch.GetRegister(bSpecifier & 0xF);

            switch (bSpecifier >> 4)
            {
            case 0: // Literal mode
            case 1:
            case 2:
            case 3:
                op = LiteralOperand(width, bSpecifier);
                break;

            case 4: // Index mode
                op = IndexOperand(width, reg);
                break;

            case 5: // Register mode
                op = new RegisterOperand(reg);
                break;

            case 6: // Register deferred
                op = new MemoryOperand(width)
                {
                    Base = reg
                };
                break;

            case 7: // Autodecrement mode
                op = new MemoryOperand(width)
                {
                    Base          = reg,
                    AutoDecrement = true,
                };
                break;

            case 8: // Autoincrement mode
                if (reg.Number == 0x0F)
                {
                    op = ImmediateOperand(width);
                }
                else
                {
                    op = new MemoryOperand(width)
                    {
                        Base          = reg,
                        AutoIncrement = true,
                    };
                }
                break;

            case 9: // Deferred Autoincrement mode
                op = new MemoryOperand(width)
                {
                    Base          = reg,
                    AutoIncrement = true,
                    Deferred      = true,
                };
                break;

            case 0xA: // Displacement mode
            case 0xD:
                if (!rdr.TryReadByte(out b))
                {
                    return(false);
                }
                op = DisplacementOperand(width, reg, Constant.SByte((sbyte)b), bSpecifier);
                break;

            case 0xB:
            case 0xE:
                if (!rdr.TryReadUInt16(out w))
                {
                    return(false);
                }
                op = DisplacementOperand(width, reg, Constant.Int16((short)w), bSpecifier);
                break;

            case 0xC:
            case 0xF:
                if (!rdr.TryReadUInt32(out dw))
                {
                    return(false);
                }
                op = DisplacementOperand(width, reg, Constant.Word32(dw), bSpecifier);
                break;

            default:
                throw new InvalidCastException("Impossiburu!");
            }
            return(true);
        }
Beispiel #32
0
        /// <summary>
        /// Pushes the specified instructions.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="op">The op.</param>
        /// <param name="stackSize">Size of the stack.</param>
        private void Push(Context ctx, Operand op, int stackSize)
        {
            if (op is MemoryOperand)
            {
                RegisterOperand rop;
                switch (op.StackType)
                {
                case StackTypeCode.O:
                    goto case StackTypeCode.N;

                case StackTypeCode.Ptr:
                    goto case StackTypeCode.N;

                case StackTypeCode.Int32:
                    goto case StackTypeCode.N;

                case StackTypeCode.N:
                    rop = new RegisterOperand(op.Type, GeneralPurposeRegister.EAX);
                    break;

                case StackTypeCode.F:
                    rop = new RegisterOperand(op.Type, SSE2Register.XMM0);
                    break;

                case StackTypeCode.Int64:
                {
                    SigType       I4  = new SigType(CilElementType.I4);
                    MemoryOperand mop = op as MemoryOperand;
                    Debug.Assert(null != mop, "I8/U8 arg is not in a memory operand.");
                    RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX);
                    Operand         opL, opH;
                    LongOperandTransformationStage.SplitLongOperand(mop, out opL, out opH);
                    //MemoryOperand opL = new MemoryOperand(I4, mop.Base, mop.Offset);
                    //MemoryOperand opH = new MemoryOperand(I4, mop.Base, new IntPtr(mop.Offset.ToInt64() + 4));

                    ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, opL);
                    ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(op.Type, GeneralPurposeRegister.EDX, new IntPtr(stackSize)), eax);
                    ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, opH);
                    ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(op.Type, GeneralPurposeRegister.EDX, new IntPtr(stackSize + 4)), eax);
                }
                    return;

                default:

                    throw new NotSupportedException();
                }

                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, rop, op);
                op = rop;
            }
            else if (op is ConstantOperand && op.StackType == StackTypeCode.Int64)
            {
                Operand         opL, opH;
                SigType         I4  = new SigType(CilElementType.I4);
                RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX);
                LongOperandTransformationStage.SplitLongOperand(op, out opL, out opH);

                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, opL);
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(I4, GeneralPurposeRegister.EDX, new IntPtr(stackSize)), eax);
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, opH);
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(I4, GeneralPurposeRegister.EDX, new IntPtr(stackSize + 4)), eax);

                return;
            }

            ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(op.Type, GeneralPurposeRegister.EDX, new IntPtr(stackSize)), op);
        }