mirror of
https://github.com/ran-j/PS2Recomp.git
synced 2026-09-27 17:11:31 -04:00
feat: add SSE2 support and fix SSE4.1 paths for PADDSW and PSUBSW instructions (#141)
* feat: add sses2 support for PADDSW and PSUBSW instructions * Fixed SSE4.1 PADDSW/PSUBSW implementations
This commit is contained in:
@@ -2057,15 +2057,10 @@ namespace ps2recomp
|
||||
return fmt::format("SET_GPR_VEC(ctx, {}, PS2_PSUBB(GPR_VEC(ctx, {}), GPR_VEC(ctx, {})));", rd, rs, rt);
|
||||
case MMI0_PCGTB:
|
||||
return fmt::format("SET_GPR_VEC(ctx, {}, PS2_PCGTB(GPR_VEC(ctx, {}), GPR_VEC(ctx, {})));", rd, rs, rt);
|
||||
// thouse 2 require SSE4.1 now TODO implement on SSE2
|
||||
case MMI0_PADDSW:
|
||||
return fmt::format("SET_GPR_VEC(ctx, {}, _mm_min_epi32(_mm_max_epi32(_mm_add_epi32(GPR_VEC(ctx, {}), GPR_VEC(ctx, {})), "
|
||||
"_mm_set1_epi32(INT32_MIN)), _mm_set1_epi32(INT32_MAX)));",
|
||||
rd, rs, rt);
|
||||
return fmt::format("SET_GPR_VEC(ctx, {}, PS2_PADDSW(GPR_VEC(ctx, {}), GPR_VEC(ctx, {})));", rd, rs, rt);
|
||||
case MMI0_PSUBSW:
|
||||
return fmt::format("SET_GPR_VEC(ctx, {}, _mm_min_epi32(_mm_max_epi32(_mm_sub_epi32(GPR_VEC(ctx, {}), GPR_VEC(ctx, {})), "
|
||||
"_mm_set1_epi32(INT32_MIN)), _mm_set1_epi32(INT32_MAX)));",
|
||||
rd, rs, rt);
|
||||
return fmt::format("SET_GPR_VEC(ctx, {}, PS2_PSUBSW(GPR_VEC(ctx, {}), GPR_VEC(ctx, {})));", rd, rs, rt);
|
||||
case MMI0_PEXTLW:
|
||||
return fmt::format("SET_GPR_VEC(ctx, {}, PS2_PEXTLW(GPR_VEC(ctx, {}), GPR_VEC(ctx, {})));", rd, rs, rt);
|
||||
case MMI0_PPACW:
|
||||
|
||||
@@ -426,6 +426,60 @@ static inline void Ps2FastWrite128(uint8_t *rdram, uint32_t addr, __m128i value)
|
||||
#define PS2_PCGTH(a, b) _mm_cmpgt_epi16((__m128i)(a), (__m128i)(b))
|
||||
#define PS2_PCGTB(a, b) _mm_cmpgt_epi8((__m128i)(a), (__m128i)(b))
|
||||
|
||||
// Packed Add with Signed Saturation Word (PADDSW)
|
||||
inline __m128i ps2_paddsw(__m128i a, __m128i b)
|
||||
{
|
||||
|
||||
__m128i sum = _mm_add_epi32(a, b);
|
||||
// Check for over/underflow. Clamp to either INT32_MIN/INT32_MAX.
|
||||
__m128i overflow = _mm_and_si128(_mm_xor_si128(a, sum),
|
||||
_mm_xor_si128(b, sum));
|
||||
// Extract input sign.
|
||||
overflow = _mm_srai_epi32(overflow, 31);
|
||||
__m128i input_sign = _mm_srai_epi32(a, 31);
|
||||
// Select saturation value based on overflow sign.
|
||||
#if defined(__SSE4_1__)
|
||||
__m128i sat = _mm_blendv_epi8(
|
||||
_mm_set1_epi32(INT32_MAX),
|
||||
_mm_set1_epi32(INT32_MIN),
|
||||
input_sign);
|
||||
return _mm_blendv_epi8(sum, sat, overflow);
|
||||
#else
|
||||
__m128i sat = _mm_or_si128(_mm_and_si128(input_sign, _mm_set1_epi32(INT32_MIN)),
|
||||
_mm_andnot_si128(input_sign, _mm_set1_epi32(INT32_MAX)));
|
||||
return _mm_or_si128(_mm_and_si128(overflow, sat),
|
||||
_mm_andnot_si128(overflow, sum));
|
||||
#endif
|
||||
}
|
||||
#define PS2_PADDSW(a, b) ps2_paddsw((__m128i)(a), (__m128i)(b))
|
||||
|
||||
// Packed Subtract with Signed Saturation Word (PSUBSW)
|
||||
inline __m128i ps2_psubsw(__m128i a, __m128i b)
|
||||
{
|
||||
__m128i diff = _mm_sub_epi32(a, b);
|
||||
// Check for over/underflow. Clamp to either INT32_MIN/INT32_MAX.
|
||||
__m128i overflow = _mm_and_si128(_mm_xor_si128(a, b),
|
||||
_mm_xor_si128(a, diff));
|
||||
// Extract input sign.
|
||||
overflow = _mm_srai_epi32(overflow, 31);
|
||||
__m128i input_sign = _mm_srai_epi32(a, 31);
|
||||
// Select saturation value based on overflow sign.
|
||||
#if defined(__SSE4_1__)
|
||||
__m128i sat = _mm_blendv_epi8(
|
||||
_mm_set1_epi32(INT32_MAX),
|
||||
_mm_set1_epi32(INT32_MIN),
|
||||
input_sign);
|
||||
return _mm_blendv_epi8(diff, sat, overflow);
|
||||
#else
|
||||
__m128i sat = _mm_or_si128(_mm_and_si128(input_sign, _mm_set1_epi32(INT32_MIN)),
|
||||
_mm_andnot_si128(input_sign, _mm_set1_epi32(INT32_MAX)));
|
||||
return _mm_or_si128(_mm_and_si128(overflow, sat),
|
||||
_mm_andnot_si128(overflow, diff));
|
||||
#endif
|
||||
|
||||
}
|
||||
#define PS2_PSUBSW(a, b) ps2_psubsw((__m128i)(a), (__m128i)(b))
|
||||
|
||||
// Packed Compare Equal (PCEQ)
|
||||
#define PS2_PCEQW(a, b) _mm_cmpeq_epi32((__m128i)(a), (__m128i)(b))
|
||||
#define PS2_PCEQH(a, b) _mm_cmpeq_epi16((__m128i)(a), (__m128i)(b))
|
||||
|
||||
Reference in New Issue
Block a user