Commit ca9449c1 authored by Russell Graves's avatar Russell Graves Committed by Michael R. Crusoe

Fix incorrect UQRSHL implementation.

UQRSHL was incorrect in several ways, and did not match hardware.
Shift checks for saturating were not modified from the signed
version, leading to incorrect behavior at (untested) edge cases.

Further, for the 32-bit and 64-bit versions, the rounding math was
incorrect with a -32 or -64 shift, and did not match hardware.  This
has been special cased to do the proper thing at the edge case.  The
core issue is overflowing the stock 32-bit or 64-bit types used at
the limit.

Tests have been modified with substantially increased test cases to
properly exercise these changes.  The new tests should cause failures
in the unsigned cases without the modified code, and should pass with
the changes.  Additional signed tests were added to handle the edge
cases, though no incorrect behavior was observed on those.

Test cases generated on a Google C4a ARMv8.4 machine.
parent 8d90b041
......@@ -207,7 +207,7 @@ simde_vqrshlb_u8(uint8_t a, int8_t b) {
r = (a >> -b) + ((a >> (-b - 1)) & 1);
} else if (b == 0) {
r = a;
} else if (b < 7) {
} else if (b < 8) {
r = HEDLEY_STATIC_CAST(uint8_t, a << b);
if ((r >> b) != a) {
r = UINT8_MAX;
......@@ -250,7 +250,7 @@ simde_vqrshlh_u16(uint16_t a, int16_t b) {
r = (a >> -b) + ((a >> (-b - 1)) & 1);
} else if (b == 0) {
r = a;
} else if (b < 15) {
} else if (b < 16) {
r = HEDLEY_STATIC_CAST(uint16_t, a << b);
if ((r >> b) != a) {
r = UINT16_MAX;
......@@ -290,10 +290,13 @@ simde_vqrshls_u32(uint32_t a, int32_t b) {
if (b < -32) {
r = 0;
} else if (b < 0) {
if (b == -32)
r = (a >> 31) & 1;
else
r = (a >> -b) + ((a >> (-b - 1)) & 1);
} else if (b == 0) {
r = a;
} else if (b < 31) {
} else if (b < 32) {
r = HEDLEY_STATIC_CAST(uint32_t, a << b);
if ((r >> b) != a) {
r = UINT32_MAX;
......@@ -333,10 +336,13 @@ simde_vqrshld_u64(uint64_t a, int64_t b) {
if (b < -64) {
r = 0;
} else if (b < 0) {
if (b == -64)
r = (a >> 63) & 1;
else
r = (a >> -b) + ((a >> (-b - 1)) & 1);
} else if (b == 0) {
r = a;
} else if (b < 63) {
} else if (b < 64) {
r = HEDLEY_STATIC_CAST(uint64_t, a << b);
if ((r >> b) != a) {
r = UINT64_MAX;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment