summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/rsp/clamp.h
blob: 5b69b746a7d692a1b36c4663aea97cb0695421c8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
}