summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/rsp/clamp.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/rsp/clamp.h')
-rw-r--r--src/devices/cpu/rsp/clamp.h37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/devices/cpu/rsp/clamp.h b/src/devices/cpu/rsp/clamp.h
new file mode 100644
index 00000000000..5b69b746a7d
--- /dev/null
+++ b/src/devices/cpu/rsp/clamp.h
@@ -0,0 +1,37 @@
+// license:BSD-3-Clause
+// copyright-holders:Tyler J. Stachecki,Ryan Holtz
+
+static inline rsp_vec_t sclamp_acc_to_mid(rsp_vec_t acc_mid, rsp_vec_t acc_hi)
+{
+ return _mm_packs_epi32(
+ _mm_unpacklo_epi16(acc_mid, acc_hi),
+ _mm_unpackhi_epi16(acc_mid, acc_hi)
+ );
+}
+
+static inline rsp_vec_t uclamp_acc(rsp_vec_t val, rsp_vec_t acc_mid, rsp_vec_t acc_hi, rsp_vec_t zero)
+{
+ rsp_vec_t hi_negative = _mm_srai_epi16(acc_hi, 15); // 0x0000
+ rsp_vec_t mid_negative = _mm_srai_epi16(acc_mid, 15); // 0xffff
+
+ // We don't have to clamp if the HI part of the
+ // accumulator is sign-extended down to the MD part.
+ rsp_vec_t hi_sign_check = _mm_cmpeq_epi16(hi_negative, acc_hi); // 0x0000
+ rsp_vec_t mid_sign_check = _mm_cmpeq_epi16(hi_negative, mid_negative); // 0x0000
+ rsp_vec_t clamp_mask = _mm_and_si128(mid_sign_check, hi_sign_check); // 0x0000
+
+ // Generate the value in the event we need to clamp.
+ // * hi_negative, mid_sign => xxxx
+ // * hi_negative, !mid_sign => 0000
+ // * !hi_negative, mid_sign => FFFF
+ // * !hi_negative, !mid_sign => xxxx
+ rsp_vec_t clamped_val = _mm_cmpeq_epi16(hi_negative, zero); // 0xffff
+
+#if (defined(__SSE4_1__) || defined(_MSC_VER))
+ return _mm_blendv_epi8(clamped_val, val, clamp_mask);
+#else
+ clamped_val = _mm_and_si128(clamp_mask, val);
+ val = _mm_andnot_si128(clamp_mask, clamped_val);
+ return _mm_or_si128(val, clamped_val);
+#endif
+}