https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127519

--- Comment #1 from Jeevitha <jeevitha at gcc dot gnu.org> ---
vec_xst_trunc:

Purpose: Truncate the value in a vector register and store it.

Operation: The rightmost element of a (using the element type specified by the
pointer type of c) is
stored to the address formed by adding b and c.

For the below testcase,
  vector signed __int128 store_data =
  {  (__int128) 0x8ACE000000000000 << 64 | (__int128) 0xfedcba9876543217ULL};

  signed long sl;
  signed int si[2];
  signed int *psi;
  psi = &si[0];

  sl = 1;
  si[0] = 0x21;
  expected_si = 0x54321721;
  vec_xst_trunc (store_data, sl, psi);

For this testcase, vec_xst_trunc is lowered to the Power10 stxvrwx instruction.

On BE this is what happens,

stxvrwx vs0,r10,r9
(gdb) p/x $vs0
$1 = {float128 = 0x8ace000000000000fedcba9876543217, uint128 =
0x8ace000000000000fedcba9876543217, v2_double = {
    0x8ace000000000000, 0xfedcba9876543217}, v4_float = {0x8ace0000, 0x0,
0xfedcba98, 0x76543217}, v4_int32 = {
    0x8ace0000, 0x0, 0xfedcba98, 0x76543217}, v8_int16 = {0x8ace, 0x0, 0x0,
0x0, 0xfedc, 0xba98, 0x7654, 0x3217},
  v16_int8 = {0x8a, 0xce, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0xdc, 0xba, 0x98,
0x76, 0x54, 0x32, 0x17}}
(gdb) p/x $r10
$2 = 0x3fffffffedb0
(gdb) p/x $r9
$3 = 0x1
Since we assigning   si[0] = 0x21;
(gdb) x/10wx 0x3fffffffedb0
0x3fffffffedb0: 0x00000021      0x00000318      0x00000000      0x00000001
0x3fffffffedc0: 0x00000000      0xf7ffc478      0x00000000      0x00000000
0x3fffffffedd0: 0x00000000      0x00000000
(gdb) x/10bx 0x3fffffffedb0
0x3fffffffedb0: 0x00    0x00    0x00    0x21    0x00    0x00    0x03    0x18
0x3fffffffedb8: 0x00    0x00
(gdb) si
After stxvrwx execution:
(gdb) x/10wx 0x3fffffffedb0
0x3fffffffedb0: 0x00765432      0x17000318      0x00000000      0x00000001
0x3fffffffedc0: 0x00000000      0xf7ffc478      0x00000000      0x00000000
0x3fffffffedd0: 0x00000000      0x00000000
(gdb) p/x expected_si
$5 = 0x54321721

On LE this is what happens,

stxvrwx vs0,r9,r2
(gdb) p/x $vs0
$1 = {float128 = 0x8ace000000000000fedcba9876543217, uint128 =
0x8ace000000000000fedcba9876543217, v2_double = {0xfedcba9876543217,
0x8ace000000000000}, v4_float = {0x76543217,
    0xfedcba98, 0x0, 0x8ace0000}, v4_int32 = {0x76543217, 0xfedcba98, 0x0,
0x8ace0000}, v8_int16 = {0x3217, 0x7654, 0xba98, 0xfedc, 0x0, 0x0, 0x0,
0x8ace}, v16_int8 = {0x17, 0x32,
    0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xce,
0x8a}}
(gdb) p/x $r9
$2 = 0x7fffffffe6b0
(gdb) p/x $r2
$3 = 0x1
Since we assigning   si[0] = 0x21;
(gdb) x/10wx 0x7fffffffe6b0
0x7fffffffe6b0: 0x00000021      0x00007fff      0x00000000      0x00000000
0x7fffffffe6c0: 0x00000000      0x00000000      0x00000000      0x00000000
0x7fffffffe6d0: 0x03d8f538      0x00000000
(gdb) x/10bx 0x7fffffffe6b0
0x7fffffffe6b0: 0x21    0x00    0x00    0x00    0xff    0x7f    0x00    0x00
0x7fffffffe6b8: 0x00    0x00
(gdb) si
After stxvrwx execution:
(gdb) x/10wx 0x7fffffffe6b0
0x7fffffffe6b0: 0x54321721      0x00007f76      0x00000000      0x00000000
0x7fffffffe6c0: 0x00000000      0x00000000      0x00000000      0x00000000
0x7fffffffe6d0: 0x03d8f538      0x00000000
(gdb) p/x expected_si
$5 = 0x54321721

Note: With psi = &si[0] and sl=1, EA = psi+1 = byte[1] of si[0]. On BE, byte[1]
is the second-most-significant byte; on LE it is the second-least-significant
byte.

Before: si[0] = 0x00000021

BE memory:  [0x00][0x00][0x00][0x21]   (MSB first)
LE memory:  [0x21][0x00][0x00][0x00]   (LSB first)

stxvrwx writes 4 bytes of word[3] = 0x76543217 at byte[1]:

BE: writes {0x76,0x54,0x32,0x17} MSB-first starting at byte[1]
    si[0] bytes become: [0x00][0x76][0x54][0x32]
    si[0] read as BE int = 0x00765432

LE: writes {0x17,0x32,0x54,0x76} LSB-first starting at byte[1]
    si[0] bytes become: [0x21][0x17][0x32][0x54]
    si[0] read as LE int = 0x54321721

Therefore, the testcase's hard-coded expected value 0x54321721 is LE-specific,
So on BE it fails.

Reply via email to