I have a problem when using ssubl
instruction in A64 instruction set.
I just want to subtract a constant value from an 8-byte SIMD vector. As the result might include a negative number, I use ssubl
to extend the data range and do the signed subtraction.
Here is my code:
mov w4, #127 // set a const
mov w5, #220 // set another const
dup v1.16b, w4 // move the const to a vector
dup v2.16b, w5 // move the const to a vector
ssubl v3.8h, v1.8b, v2.8b // long type vector subtraction, 127-220
I checked the result in the vector register v1, v2 and v3:
[127 - 220 = -93 (0xffa3), CORRECT]
I think the value in v3 should be 0xff5d, as it's a negative number. But why it's not?
Actually, after few tests, I found this problem is not related to the value in w5
, no matter it's 220 or 230 or other value. As long as the value in w4
is less or equal to 127, the subtraction result is not correct.
So, if we use the same code, but change w4 value to 128 or larger:
mov w4, #128 // set a const
mov w5, #220 // set another const
dup v1.16b, w4 // move the const to a vector
dup v2.16b, w5 // move the const to a vector
ssubl v3.8h, v1.8b, v2.8b // long type vector subtraction, 128-220
The results now are:
[128 - 220 = -92 (0xffa4), CORRECT]
Now the results are correct, and I also tried using 150, 250 in w5
, all results are correct. The problem is only related to the value in w4
.
Is there anyone can explain that?
Thanks!
(Posted solution on behalf of the OP).
Use usubl
rather than ssubl
to do the subtraction.
It seems like the usubl
and ssubl
only care about if the operands are signed/unsigned.