Suppose you have a value in an XMM register and you want to limit the bottom byte to a particular value and set all the other bytes to zero. (Yes, I needed to do this.)
One way to do this is to apply the two steps in sequence:
; value to truncate/limit is in xmm0 ; First, zero out the top 15 bytes pslldq xmm0, 15 psrldq xmm0, 15 ; Now limit the bottom byte to N mov al, N movd xmm1, eax pminub xmm0, xmm1
But you can do it all in one step by realizing that min(x, 0) = 0 for all unsigned values x.
; value to truncate/limit is in xmm0 mov eax, N movd xmm1, eax pminub xmm0, xmm1
In pictures:
xmm0 | xmm1 | xmm0 | ||
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
? | min | 0 | = | 0 |
x | min | N | = | min(x, N) |
In intrinsics:
__m128i min_low_byte_and_set_upper_bytes_to_zero(__m128i x, uint8_t N) { return _mm_min_epi8(x, _mm_cvtsi32_si128(N)); }
0 comments