예제 #1
0
        private static void EmitCmpOp(ArmEmitterContext context, Func2I emitCmp, bool scalar)
        {
            OpCodeSimd op = (OpCodeSimd)context.CurrOp;

            Operand res = context.VectorZero();

            int elems = !scalar?op.GetBytesCount() >> op.Size : 1;

            ulong szMask = ulong.MaxValue >> (64 - (8 << op.Size));

            for (int index = 0; index < elems; index++)
            {
                Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
                Operand me;

                if (op is OpCodeSimdReg binOp)
                {
                    me = EmitVectorExtractSx(context, binOp.Rm, index, op.Size);
                }
                else
                {
                    me = Const(0L);
                }

                Operand isTrue = emitCmp(ne, me);

                Operand mask = context.ConditionalSelect(isTrue, Const(szMask), Const(0L));

                res = EmitVectorInsert(context, res, mask, index, op.Size);
            }

            context.Copy(GetVec(op.Rd), res);
        }
예제 #2
0
        private static void EmitVectorCvtf(ArmEmitterContext context, bool signed)
        {
            OpCodeSimd op = (OpCodeSimd)context.CurrOp;

            Operand res = context.VectorZero();

            int sizeF = op.Size & 1;
            int sizeI = sizeF + 2;

            int fBits = GetFBits(context);

            int elems = op.GetBytesCount() >> sizeI;

            for (int index = 0; index < elems; index++)
            {
                Operand ne = EmitVectorLongExtract(context, op.Rn, index, sizeI);

                Operand e = EmitFPConvert(context, ne, sizeF, signed);

                e = EmitI2fFBitsMul(context, e, fBits);

                res = context.VectorInsert(res, e, index);
            }

            context.Copy(GetVec(op.Rd), res);
        }
예제 #3
0
        private static void EmitFcvtz(ArmEmitterContext context, bool signed, bool scalar)
        {
            OpCodeSimd op = (OpCodeSimd)context.CurrOp;

            Operand res = context.VectorZero();

            Operand n = GetVec(op.Rn);

            int sizeF = op.Size & 1;
            int sizeI = sizeF + 2;

            OperandType type = sizeF == 0 ? OperandType.FP32 : OperandType.FP64;

            int fBits = GetFBits(context);

            int elems = !scalar?op.GetBytesCount() >> sizeI : 1;

            for (int index = 0; index < elems; index++)
            {
                Operand ne = context.VectorExtract(type, n, index);

                Operand e = EmitF2iFBitsMul(context, ne, fBits);

                if (sizeF == 0)
                {
                    Delegate dlg = signed
                        ? (Delegate) new _S32_F32(SoftFallback.SatF32ToS32)
                        : (Delegate) new _U32_F32(SoftFallback.SatF32ToU32);

                    e = context.Call(dlg, e);

                    e = context.ZeroExtend32(OperandType.I64, e);
                }
                else /* if (sizeF == 1) */
                {
                    Delegate dlg = signed
                        ? (Delegate) new _S64_F64(SoftFallback.SatF64ToS64)
                        : (Delegate) new _U64_F64(SoftFallback.SatF64ToU64);

                    e = context.Call(dlg, e);
                }

                res = EmitVectorInsert(context, res, e, index, sizeI);
            }

            context.Copy(GetVec(op.Rd), res);
        }
예제 #4
0
        private static void EmitCmpOpF(
            ArmEmitterContext context,
            _F32_F32_F32 f32,
            _F64_F64_F64 f64,
            bool scalar,
            bool absolute = false)
        {
            OpCodeSimd op = (OpCodeSimd)context.CurrOp;

            Operand res = context.VectorZero();

            int sizeF = op.Size & 1;

            OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32;

            int elems = !scalar?op.GetBytesCount() >> sizeF + 2 : 1;

            for (int index = 0; index < elems; index++)
            {
                Operand ne = context.VectorExtract(type, GetVec(op.Rn), index);
                Operand me;

                if (op is OpCodeSimdReg binOp)
                {
                    me = context.VectorExtract(type, GetVec(binOp.Rm), index);
                }
                else
                {
                    me = sizeF == 0 ? ConstF(0f) : ConstF(0d);
                }

                if (absolute)
                {
                    ne = EmitUnaryMathCall(context, MathF.Abs, Math.Abs, ne);
                    me = EmitUnaryMathCall(context, MathF.Abs, Math.Abs, me);
                }

                Operand e = EmitSoftFloatCall(context, f32, f64, ne, me);

                res = context.VectorInsert(res, e, index);
            }

            context.Copy(GetVec(op.Rd), res);
        }
예제 #5
0
        private static void EmitRev_V(ArmEmitterContext context, int containerSize)
        {
            OpCodeSimd op = (OpCodeSimd)context.CurrOp;

            Operand res = context.VectorZero();

            int elems = op.GetBytesCount() >> op.Size;

            int containerMask = (1 << (containerSize - op.Size)) - 1;

            for (int index = 0; index < elems; index++)
            {
                int revIndex = index ^ containerMask;

                Operand ne = EmitVectorExtractZx(context, op.Rn, revIndex, op.Size);

                res = EmitVectorInsert(context, res, ne, index, op.Size);
            }

            context.Copy(GetVec(op.Rd), res);
        }