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.