public static void EmitScalarUnaryOpF32(ArmEmitterContext context, Func1I emit) { OpCode32SimdS op = (OpCode32SimdS)context.CurrOp; OperandType type = (op.Size & 1) != 0 ? OperandType.FP64 : OperandType.FP32; Operand m = ExtractScalar(context, type, op.Vm); InsertScalar(context, op.Vd, emit(m)); }
private static void EmitFcvt___Gp(ArmEmitterContext context, Func1I emit, bool signed) { OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp; OperandType type = op.Size == 0 ? OperandType.FP32 : OperandType.FP64; Operand ne = context.VectorExtract(type, GetVec(op.Rn), 0); Operand res = signed ? EmitScalarFcvts(context, emit(ne), 0) : EmitScalarFcvtu(context, emit(ne), 0); SetIntOrZR(context, op.Rd, res); }
// Integer public static void EmitVectorUnaryOpI32(ArmEmitterContext context, Func1I emit, bool signed) { OpCode32Simd op = (OpCode32Simd)context.CurrOp; Operand res = GetVecA32(op.Qd); int elems = op.GetBytesCount() >> op.Size; for (int index = 0; index < elems; index++) { Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, signed); res = EmitVectorInsert(context, res, emit(me), op.Id + index, op.Size); } context.Copy(GetVecA32(op.Qd), res); }
public static void EmitScalarUnaryOpSimd32(ArmEmitterContext context, Func1I scalarFunc) { OpCode32SimdS op = (OpCode32SimdS)context.CurrOp; bool doubleSize = (op.Size & 1) != 0; int shift = doubleSize ? 1 : 2; Operand m = GetVecA32(op.Vm >> shift); Operand d = GetVecA32(op.Vd >> shift); m = EmitSwapScalar(context, m, op.Vm, doubleSize); Operand res = scalarFunc(m); // Insert scalar into vector. res = EmitScalarInsert(context, d, res, op.Vd, doubleSize); context.Copy(d, res); }
// Narrow public static void EmitVectorUnaryNarrowOp32(ArmEmitterContext context, Func1I emit, bool signed = false) { OpCode32Simd op = (OpCode32Simd)context.CurrOp; int elems = 8 >> op.Size; // Size contains the target element size. (for when it becomes a doubleword) Operand res = GetVecA32(op.Qd); int id = (op.Vd & 1) << (3 - op.Size); // Target doubleword base. for (int index = 0; index < elems; index++) { Operand m = EmitVectorExtract32(context, op.Qm, index, op.Size + 1, signed); res = EmitVectorInsert(context, res, emit(m), id + index, op.Size); } context.Copy(GetVecA32(op.Qd), res); }
public static void EmitVectorImmUnaryOp32(ArmEmitterContext context, Func1I emit) { IOpCode32SimdImm op = (IOpCode32SimdImm)context.CurrOp; Operand imm = Const(op.Immediate); int elems = op.Elems; (int index, int subIndex) = GetQuadwordAndSubindex(op.Vd, op.RegisterSize); Operand vec = GetVecA32(index); Operand res = vec; for (int item = 0; item < elems; item++) { res = EmitVectorInsert(context, res, emit(imm), item + subIndex * elems, op.Size); } context.Copy(vec, res); }
// Vector Operand Templates public static void EmitVectorUnaryOpSimd32(ArmEmitterContext context, Func1I vectorFunc) { OpCode32Simd op = (OpCode32Simd)context.CurrOp; Operand m = GetVecA32(op.Qm); Operand d = GetVecA32(op.Qd); if (!op.Q) // Register swap: move relevant doubleword to destination side. { m = EmitMoveDoubleWordToSide(context, m, op.Vm, op.Vd); } Operand res = vectorFunc(m); if (!op.Q) // Register insert. { res = EmitDoubleWordInsert(context, d, res, op.Vd); } context.Copy(d, res); }
public static void EmitVectorUnaryOpF32(ArmEmitterContext context, Func1I emit) { OpCode32Simd op = (OpCode32Simd)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 me = context.VectorExtract(type, GetVecA32(op.Qm), op.Fm + index); res = context.VectorInsert(res, emit(me), op.Fd + index); } context.Copy(GetVecA32(op.Qd), res); }
public static void EmitVectorUnaryOpZx32(ArmEmitterContext context, Func1I emit) { EmitVectorUnaryOpI32(context, emit, false); }
private static void EmitFcvt_u_Gp(ArmEmitterContext context, Func1I emit) { EmitFcvt___Gp(context, emit, signed: false); }