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

--- Comment #1 from Jeevitha <jeevitha at gcc dot gnu.org> ---
vec_sldb — Vector Shift Left Double Bit Immediate

r = vec_sldb (a, b, c)

Purpose:
Shifts a double-wide vector left by up to 7 bits and returns the leftmost 128
bits of the result.

Result value:
Let v be the concatenation of a and b, with a on the left. Let w be v shifted
left by the number of bits specified by c. Then r is set to the leftmost 128
bits of w.

Endian considerations:
The semantics of this built-in function differ for big-endian and little-endian
targets, since the concatenation of a and b is done in big-endian fashion (left
to right).

Instruction semantics

vsldbi VRT,VRA,VRB,SH

if MSR.VEC=0 then Vector_Unavailable()

vsrc.qword[0] ← VSR[VRA+32]
vsrc.qword[1] ← VSR[VRB+32]

VSR[VRT+32] ← vsrc.bit[SH:SH+127]

---
Testcase:

vector signed char vresult_char;
vector signed char expected_vresult_char;
vector signed char src_va_char;
vector signed char src_vb_char;

src_va_char =
  (vector signed char) { 0, 2, 4, 6, 8, 10, 12, 14,
                         16, 18, 20, 22, 24, 26, 28, 30 };

src_vb_char =
  (vector signed char) { 10, 20, 30, 40, 50, 60, 70, 80,
                         90, 100, 110, 120, 130, 140, 150, 160 };

vresult_char =
  (vector signed char) { 0, 0, 0, 0, 0, 0, 0, 0,
                         0, 0, 0, 0, 0, 0, 0, 0 };

expected_vresult_char =
  (vector signed char) { 80, 0, 1, 2, 3, 4, 5, 6,
                         7, 8, 9, 10, 11, 12, 13, 14 };

vresult_char = vec_sldb (src_va_char, src_vb_char, 7);

vec_sldb generates: vsldbi v0,v0,v1,7

On Big-endian:

Before executing vsldbi:

p/x $v0
$1 = {uint128 = 0x20406080a0c0e10121416181a1c1e,
      v4_float = {0x20406, 0x80a0c0e, 0x10121416, 0x181a1c1e},
      v4_int32 = {0x20406, 0x80a0c0e, 0x10121416, 0x181a1c1e},
      v8_int16 = {0x2, 0x406, 0x80a, 0xc0e,
                  0x1012, 0x1416, 0x181a, 0x1c1e},
      v16_int8 = {0x0, 0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xe,
                  0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e}}
p/x $v1
$2 = {uint128 = 0xa141e28323c46505a646e78828c96a0,
      v4_float = {0xa141e28, 0x323c4650, 0x5a646e78, 0x828c96a0},
      v4_int32 = {0xa141e28, 0x323c4650, 0x5a646e78, 0x828c96a0},
      v8_int16 = {0xa14, 0x1e28, 0x323c, 0x4650,
                  0x5a64, 0x6e78, 0x828c, 0x96a0},
      v16_int8 = {0xa, 0x14, 0x1e, 0x28, 0x32, 0x3c, 0x46, 0x50,
                  0x5a, 0x64, 0x6e, 0x78, 0x82, 0x8c, 0x96, 0xa0}}
After:
vsldbi v0,v0,v1,7
we get:

p/x $v0
$3 = {uint128 = 0x102030405060708090a0b0c0d0e0f05,
      v4_float = {0x1020304, 0x5060708, 0x90a0b0c, 0xd0e0f05},
      v4_int32 = {0x1020304, 0x5060708, 0x90a0b0c, 0xd0e0f05},
      v8_int16 = {0x102, 0x304, 0x506, 0x708,
                  0x90a, 0xb0c, 0xd0e, 0xf05},
      v16_int8 = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
                  0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x5}}

The concatenation is:

A CONCAT B:

0x20406080a0c0e10121416181a1c1e
|
0xa141e28323c46505a646e78828c96a0

In binary:

00100000010000000110000010000000101000001100000011100001000000010010000101000001011000011000000110100001110000011110
concat
00001010000101000001111000101000001100100011110001000110010100000101101001100100011011100111100010000010100011001001011010100000

For SH=7

the instruction selects: vsrc.bit[7:134]

Therefore, it takes:
bits 7:127   from A
bits 128:134 from B


The resulting 128 bits are:

[A]001000000010000001100000010000000101000001100000011100000100000001001000010100000101100001100000011010000111000001111010
 [B] 0000101

which corresponds to: 0x102030405060708090A0B0C0D0E0F05


On Little-endian

Before executing vsldbi:

p/x $v0
$1 = {uint128 = 0x1e1c1a18161412100e0c0a0806040200,
      v4_float = {0x6040200, 0xe0c0a08, 0x16141210, 0x1e1c1a18},
      v4_int32 = {0x6040200, 0xe0c0a08, 0x16141210, 0x1e1c1a18},
      v8_int16 = {0x200, 0x604, 0xa08, 0xe0c,
                  0x1210, 0x1614, 0x1a18, 0x1e1c},
      v16_int8 = {0x0, 0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xe,
                  0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e}}

p/x $v1
$2 = {uint128 = 0xa0968c82786e645a50463c32281e140a,
      v4_float = {0x281e140a, 0x50463c32, 0x786e645a, 0xa0968c82},
      v4_int32 = {0x281e140a, 0x50463c32, 0x786e645a, 0xa0968c82},
      v8_int16 = {0x140a, 0x281e, 0x3c32, 0x5046,
                  0x645a, 0x786e, 0x8c82, 0xa096},
      v16_int8 = {0xa, 0x14, 0x1e, 0x28, 0x32, 0x3c, 0x46, 0x50,
                  0x5a, 0x64, 0x6e, 0x78, 0x82, 0x8c, 0x96, 0xa0}}

The concatenation is:

A CONCAT B:

0x1e1c1a18161412100e0c0a0806040200
|
0xa0968c82786e645a50463c32281e140a

In binary:

00011110000111000001101000011000000101100001010000010010000100000000111000001100000010100000100000000110000001000000001000000000
concat
10100000100101101000110010000010011110000110111001100100010110100101000001000110001111000011001000101000000111100001010000001010

The selected bits are:

[A]0000111000001101000011000000101100001010000010010000100000000111000001100000010100000100000000110000001000000001000000000
[B]1010000

which gives:
0xE0D0C0B0A0908070605040302010050


Hence, the tests fails on big-endian PowerPC because its expected value assumes
the little-endian representation of the vector.

Reply via email to