[x64/Linux] More return __m128i by value in xmm0 rather than pointer

This commit is contained in:
Herman S.
2025-10-15 16:22:22 +09:00
parent 0921a4fb04
commit 7e66a85f43
2 changed files with 57 additions and 28 deletions

View File

@@ -2744,11 +2744,15 @@ struct PACK : Sequence<PACK, I<OPCODE_PACK, V128Op, V128Op, V128Op>> {
// http://blogs.msdn.com/b/chuckw/archive/2012/09/11/directxmath-f16c-and-fma.aspx
// dest = [(src1.x | src1.y), 0, 0, 0]
if (i.src1.is_constant) {
e.lea(e.GetNativeParam(0), e.StashConstantXmm(0, i.src1.constant()));
} else {
e.lea(e.GetNativeParam(0), e.StashXmm(0, i.src1));
}
auto src1 = GetInputRegOrConstant(e, i.src1, e.xmm3);
#if XE_PLATFORM_WIN32
// Windows x64 ABI: __m128 is passed by implicit pointer
e.lea(e.GetNativeParam(0), e.StashXmm(0, src1));
#else
// Linux/Mac System V ABI: __m128 passed in xmm0, return in xmm0
e.vmovaps(e.xmm0, src1);
#endif
e.CallNativeSafe(reinterpret_cast<void*>(EmulateFLOAT16_2));
e.vmovaps(i.dest, e.xmm0);
}
@@ -2922,26 +2926,36 @@ struct PACK : Sequence<PACK, I<OPCODE_PACK, V128Op, V128Op, V128Op>> {
if (IsPackOutUnsigned(flags)) {
if (IsPackOutSaturate(flags)) {
// unsigned -> unsigned + saturate
if (i.src1.is_constant) {
e.lea(e.GetNativeParam(0),
e.StashConstantXmm(0, i.src1.constant()));
} else {
e.lea(e.GetNativeParam(0), e.StashXmm(0, i.src1));
}
if (i.src2.is_constant) {
e.lea(e.GetNativeParam(1),
e.StashConstantXmm(1, i.src2.constant()));
} else {
e.lea(e.GetNativeParam(1), e.StashXmm(1, i.src2));
}
auto src1 = GetInputRegOrConstant(e, i.src1, e.xmm3);
auto src2 = GetInputRegOrConstant(e, i.src2, e.xmm4);
#if XE_PLATFORM_WIN32
// Windows x64 ABI: __m128i is passed by implicit pointer
e.lea(e.GetNativeParam(0), e.StashXmm(0, src1));
e.lea(e.GetNativeParam(1), e.StashXmm(1, src2));
#else
// Linux/Mac System V ABI: __m128i passed in xmm0/xmm1, return in xmm0
e.vmovaps(e.xmm0, src1);
e.vmovaps(e.xmm1, src2);
#endif
e.CallNativeSafe(
reinterpret_cast<void*>(EmulatePack8_IN_16_UN_UN_SAT));
e.vmovaps(i.dest, e.xmm0);
e.vpshufb(i.dest, i.dest, e.GetXmmConstPtr(XMMByteOrderMask));
} else {
// unsigned -> unsigned
e.lea(e.GetNativeParam(1), e.StashXmm(1, i.src2));
e.lea(e.GetNativeParam(0), e.StashXmm(0, i.src1));
auto src1 = GetInputRegOrConstant(e, i.src1, e.xmm3);
auto src2 = GetInputRegOrConstant(e, i.src2, e.xmm4);
#if XE_PLATFORM_WIN32
// Windows x64 ABI: __m128i is passed by implicit pointer
e.lea(e.GetNativeParam(0), e.StashXmm(0, src1));
e.lea(e.GetNativeParam(1), e.StashXmm(1, src2));
#else
// Linux/Mac System V ABI: __m128i passed in xmm0/xmm1, return in xmm0
e.vmovaps(e.xmm0, src1);
e.vmovaps(e.xmm1, src2);
#endif
e.CallNativeSafe(reinterpret_cast<void*>(EmulatePack8_IN_16_UN_UN));
e.vmovaps(i.dest, e.xmm0);
e.vpshufb(i.dest, i.dest, e.GetXmmConstPtr(XMMByteOrderMask));
@@ -3176,11 +3190,15 @@ struct UNPACK : Sequence<UNPACK, I<OPCODE_UNPACK, V128Op, V128Op>> {
// Also zero out the high end.
// TODO(benvanik): special case constant unpacks that just get 0/1/etc.
if (i.src1.is_constant) {
e.lea(e.GetNativeParam(0), e.StashConstantXmm(0, i.src1.constant()));
} else {
e.lea(e.GetNativeParam(0), e.StashXmm(0, i.src1));
}
auto src1 = GetInputRegOrConstant(e, i.src1, e.xmm3);
#if XE_PLATFORM_WIN32
// Windows x64 ABI: __m128i is passed by implicit pointer
e.lea(e.GetNativeParam(0), e.StashXmm(0, src1));
#else
// Linux/Mac System V ABI: __m128i passed in xmm0, return in xmm0
e.vmovaps(e.xmm0, src1);
#endif
e.CallNativeSafe(reinterpret_cast<void*>(EmulateFLOAT16_2));
e.vmovaps(i.dest, e.xmm0);
}

View File

@@ -2225,9 +2225,15 @@ struct POW2_V128 : Sequence<POW2_V128, I<OPCODE_POW2, V128Op, V128Op>> {
}
static void Emit(X64Emitter& e, const EmitArgType& i) {
e.ChangeMxcsrMode(MXCSRMode::Vmx);
Xmm src1 = GetInputRegOrConstant(e, i.src1, e.xmm0);
e.lea(e.GetNativeParam(0), e.StashXmm(0, src1));
Xmm src1 = GetInputRegOrConstant(e, i.src1, e.xmm3);
#if XE_PLATFORM_WIN32
// Windows x64 ABI: __m128 is passed by implicit pointer
e.lea(e.GetNativeParam(0), e.StashXmm(0, src1));
#else
// Linux/Mac System V ABI: __m128 passed in xmm0, return in xmm0
e.vmovaps(e.xmm0, src1);
#endif
e.CallNativeSafe(reinterpret_cast<void*>(EmulatePow2));
e.vmovaps(i.dest, e.xmm0);
}
@@ -2261,10 +2267,15 @@ struct LOG2_V128 : Sequence<LOG2_V128, I<OPCODE_LOG2, V128Op, V128Op>> {
}
static void Emit(X64Emitter& e, const EmitArgType& i) {
e.ChangeMxcsrMode(MXCSRMode::Vmx);
Xmm src1 = GetInputRegOrConstant(e, i.src1, e.xmm0);
Xmm src1 = GetInputRegOrConstant(e, i.src1, e.xmm3);
#if XE_PLATFORM_WIN32
// Windows x64 ABI: __m128 is passed by implicit pointer
e.lea(e.GetNativeParam(0), e.StashXmm(0, src1));
#else
// Linux/Mac System V ABI: __m128 passed in xmm0, return in xmm0
e.vmovaps(e.xmm0, src1);
#endif
e.CallNativeSafe(reinterpret_cast<void*>(EmulateLog2));
e.vmovaps(i.dest, e.xmm0);
}