armneonarm64armasm

NEON SSUBL instruction has wrong result? 127-220 = 0x00a3(should be 0xffa3)


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!


Solution

  • (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.