public static void EmitVectorsByScalarOpSimd32(ArmEmitterContext context, Func3I vectorFunc) { OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp; Operand n = GetVecA32(op.Qn); Operand d = GetVecA32(op.Qd); Operand initialD = d; int index = op.Vm & 3; int dupeMask = (index << 6) | (index << 4) | (index << 2) | index; Operand m = GetVecA32(op.Vm >> 2); m = context.AddIntrinsic(Intrinsic.X86Shufps, m, m, Const(dupeMask)); if (!op.Q) // Register swap: move relevant doubleword to destination side. { n = EmitMoveDoubleWordToSide(context, n, op.Vn, op.Vd); } Operand res = vectorFunc(d, n, m); if (!op.Q) // Register insert. { res = EmitDoubleWordInsert(context, initialD, res, op.Vd); } context.Copy(initialD, res); }
public static void EmitVectorTernaryLongOpI32(ArmEmitterContext context, Func3I emit, bool signed) { OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; Operand res = context.VectorZero(); int elems = op.GetBytesCount() >> op.Size; for (int index = 0; index < elems; index++) { Operand de = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size + 1, signed); Operand ne = EmitVectorExtract32(context, op.Qn, op.In + index, op.Size, signed); Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, signed); if (op.Size == 2) { ne = signed ? context.SignExtend32(OperandType.I64, ne) : context.ZeroExtend32(OperandType.I64, ne); me = signed ? context.SignExtend32(OperandType.I64, me) : context.ZeroExtend32(OperandType.I64, me); } res = EmitVectorInsert(context, res, emit(de, ne, me), index, op.Size + 1); } context.Copy(GetVecA32(op.Qd), res); }
public static void EmitScalarTernaryOpF32(ArmEmitterContext context, Func3I emit) { OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp; OperandType type = (op.Size & 1) != 0 ? OperandType.FP64 : OperandType.FP32; Operand a = ExtractScalar(context, type, op.Vd); Operand n = ExtractScalar(context, type, op.Vn); Operand m = ExtractScalar(context, type, op.Vm); InsertScalar(context, op.Vd, emit(a, n, m)); }
public static void EmitVectorTernaryOpI32(ArmEmitterContext context, Func3I emit, bool signed) { OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; Operand res = GetVecA32(op.Qd); int elems = op.GetBytesCount() >> op.Size; for (int index = 0; index < elems; index++) { Operand de = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size, signed); Operand ne = EmitVectorExtract32(context, op.Qn, op.In + index, op.Size, signed); Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, signed); res = EmitVectorInsert(context, res, emit(de, ne, me), op.Id + index, op.Size); } context.Copy(GetVecA32(op.Qd), res); }
public static void EmitVectorsByScalarOpI32(ArmEmitterContext context, Func3I emit, bool signed) { OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp; Operand m = EmitVectorExtract32(context, op.Vm >> (4 - op.Size), op.Vm & ((1 << (4 - op.Size)) - 1), op.Size, signed); Operand res = GetVecA32(op.Qd); int elems = op.GetBytesCount() >> op.Size; for (int index = 0; index < elems; index++) { Operand de = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size, signed); Operand ne = EmitVectorExtract32(context, op.Qn, op.In + index, op.Size, signed); res = EmitVectorInsert(context, res, emit(de, ne, m), op.Id + index, op.Size); } context.Copy(GetVecA32(op.Qd), res); }
public static void EmitScalarTernaryOpSimd32(ArmEmitterContext context, Func3I scalarFunc) { OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp; bool doubleSize = (op.Size & 1) != 0; int shift = doubleSize ? 1 : 2; Operand n = GetVecA32(op.Vn >> shift); Operand m = GetVecA32(op.Vm >> shift); Operand d = GetVecA32(op.Vd >> shift); Operand initialD = d; n = EmitSwapScalar(context, n, op.Vn, doubleSize); m = EmitSwapScalar(context, m, op.Vm, doubleSize); d = EmitSwapScalar(context, d, op.Vd, doubleSize); Operand res = scalarFunc(d, n, m); // Insert scalar into vector. res = EmitScalarInsert(context, initialD, res, op.Vd, doubleSize); context.Copy(initialD, res); }
public static void EmitVectorTernaryOpF32(ArmEmitterContext context, Func3I emit) { OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; int sizeF = op.Size & 1; OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32; int elems = op.GetBytesCount() >> sizeF + 2; Operand res = GetVecA32(op.Qd); for (int index = 0; index < elems; index++) { Operand de = context.VectorExtract(type, GetVecA32(op.Qd), op.Fd + index); Operand ne = context.VectorExtract(type, GetVecA32(op.Qn), op.Fn + index); Operand me = context.VectorExtract(type, GetVecA32(op.Qm), op.Fm + index); res = context.VectorInsert(res, emit(de, ne, me), op.Fd + index); } context.Copy(GetVecA32(op.Qd), res); }
public static void EmitVectorTernaryOpSimd32(ArmEmitterContext context, Func3I vectorFunc) { OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; Operand n = GetVecA32(op.Qn); Operand m = GetVecA32(op.Qm); Operand d = GetVecA32(op.Qd); Operand initialD = d; if (!op.Q) // Register swap: move relevant doubleword to destination side. { n = EmitMoveDoubleWordToSide(context, n, op.Vn, op.Vd); m = EmitMoveDoubleWordToSide(context, m, op.Vm, op.Vd); } Operand res = vectorFunc(d, n, m); if (!op.Q) // Register insert. { res = EmitDoubleWordInsert(context, initialD, res, op.Vd); } context.Copy(initialD, res); }
public static void EmitVectorTernaryOpZx32(ArmEmitterContext context, Func3I emit) { EmitVectorTernaryOpI32(context, emit, false); }
public static void EmitVectorPairwiseTernaryLongOpI32(ArmEmitterContext context, Func3I emit, bool signed) { OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; int elems = op.GetBytesCount() >> op.Size; int pairs = elems >> 1; Operand res = GetVecA32(op.Qd); for (int index = 0; index < pairs; index++) { int pairIndex = index * 2; Operand m1 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex, op.Size, signed); Operand m2 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex + 1, op.Size, signed); if (op.Size == 2) { m1 = signed ? context.SignExtend32(OperandType.I64, m1) : context.ZeroExtend32(OperandType.I64, m1); m2 = signed ? context.SignExtend32(OperandType.I64, m2) : context.ZeroExtend32(OperandType.I64, m2); } Operand d1 = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size + 1, signed); res = EmitVectorInsert(context, res, emit(m1, m2, d1), op.Id + index, op.Size + 1); } context.Copy(GetVecA32(op.Qd), res); }