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

--- Comment #2 from Jeevitha <jeevitha at gcc dot gnu.org> ---
vec_srdb — Vector Shift Right Double Bit Immediate

r = vec_srdb (a, b, c)

Purpose:
Shifts a double-wide vector right by up to 7 bits and returns the rightmost 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 right by the number of bits specified by c. Then r is set to the
rightmost 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

vsrdbi 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[128-SH:255-SH]
---

Testcase:

vector unsigned int vresult_uint;
vector unsigned int expected_vresult_uint;
vector unsigned int src_va_uint;
vector unsigned int src_vb_uint;
unsigned int src_a_uint;
src_va_uint = (vector unsigned int) { 0, 20, 30, 40 };
src_vb_uint = (vector unsigned int) {
  128, 2*128, 4*128, 6*128
};
vresult_uint = (vector unsigned int) { 0, 0, 0, 0 };
expected_vresult_uint = (vector unsigned int) {
  1, 2, 4, 6
};
vresult_uint = vec_srdb (src_va_uint, src_vb_uint, 7);
---

vec_srdb generates: vsrdbi v0,v0,v1,7

On Big-endian:

Before executing vsrdbi:

p/x $v0
$1 = {uint128 = 0x140000001e00000028,
      v4_float = {0x0, 0x14, 0x1e, 0x28},
      v4_int32 = {0x0, 0x14, 0x1e, 0x28},
      v8_int16 = {0x0, 0x0, 0x0, 0x14,
                  0x0, 0x1e, 0x0, 0x28},
      v16_int8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14,
                  0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x28}}
p/x $v1
$2 = {uint128 = 0x80000001000000020000000300,
      v4_float = {0x80, 0x100, 0x200, 0x300},
      v4_int32 = {0x80, 0x100, 0x200, 0x300},
      v8_int16 = {0x0, 0x80, 0x0, 0x100,
                  0x0, 0x200, 0x0, 0x300},
      v16_int8 = {0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x1, 0x0,
                  0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x3, 0x0}}

After executing vsrdbi:
p/x $v0
$3 = {uint128 = 0x50000001000000020000000400000006,
      v4_float = {0x50000001, 0x2, 0x4, 0x6},
      v4_int32 = {0x50000001, 0x2, 0x4, 0x6},
      v8_int16 = {0x5000, 0x1, 0x0, 0x2,
                  0x0, 0x4, 0x0, 0x6},
      v16_int8 = {0x50, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2,
                  0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6}}

The concatenation is:
A CONCAT B:

0x0140000001e00000028
|
0x80000001000000020000000300

In binary:

A:
000101000000000000000000000000000001111000000000000000000000000000101000

B:
00000000000000000000000010000000000000000000000000000001000000000000000000000000000000100000000000000000000000000000001100000000

FOR SH = 7, the instruction selects:
vsrc.bit[121:248]

Therefore, the result contains:
bits 121:127   → 7 bits from A
bits 128:248   → 121 bits from B

The selected bits are:

[A] 0101000
[B]
0000000000000000000000001000000000000000000000000000000100000000000000000000000000000010000000000000000000000000000000110

which corresponds to:
0x50000001000000020000000400000006 -> v4_int32 = {1342177281, 2, 4, 6}
---

On Little-endian:

Before executing vsrdbi:

p/x $v0
$1 = {uint128 = 0x280000001e0000001400000000,
      v4_float = {0x0, 0x14, 0x1e, 0x28},
      v4_int32 = {0x0, 0x14, 0x1e, 0x28},
      v8_int16 = {0x0, 0x0, 0x14, 0x0,
                  0x1e, 0x0, 0x28, 0x0},
      v16_int8 = {0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0,
                  0x1e, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0}}
p/x $v1
$2 = {uint128 = 0x300000002000000010000000080,
      v4_float = {0x80, 0x100, 0x200, 0x300},
      v4_int32 = {0x80, 0x100, 0x200, 0x300},
      v8_int16 = {0x80, 0x0, 0x100, 0x0,
                  0x200, 0x0, 0x300, 0x0},
      v16_int8 = {0x80, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0,
                  0x0, 0x2, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0}}

After executing vsrdbi:
p/x $v0
$3 = {uint128 = 0x6000000040000000200000001,
      v4_float = {0x1, 0x2, 0x4, 0x6},
      v4_int32 = {0x1, 0x2, 0x4, 0x6},
      v8_int16 = {0x1, 0x0, 0x2, 0x0,
                  0x4, 0x0, 0x6, 0x0},
      v16_int8 = {0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0,
                  0x4, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0}}

The concatenation is:
A CONCAT B:

0x280000001e0000001400000000
|
0x300000002000000010000000080

In binary:

A:
0010100000000000000000000000000000011110000000000000000000000000010100000000000000000000000000000000

B:
001100000000000000000000000000000010000000000000000000000000000000010000000000000000000000000000000010000000

The selected bits are:
[A] 0000000
[B]
000000000000000000000000000000010000000000000000000000000000001000000000000000000000000000000010000000

which corresponds to:
0x6000000040000000200000001 -> v4_int32 = {0x1, 0x2, 0x4, 0x6}

which matches the expected value in the testcase, but does not match on BE.

Reply via email to