c - vec_sld endian 敏感吗?

标签 c endianness simd powerpc altivec

我正在使用带有内核加密的 PowerPC 机器。我在使用内置函数将 AES key 扩展从大端移植到小端时遇到问题。 Big endian 有效,但 little endian 无效。

下面的算法是 IBM blog article 中呈现的片段.我认为我将问题隔离到下面的第 2 行:

typedef __vector unsigned char  uint8x16_p8;
uint8x64_p8 r0 = {0};

r3 = vec_perm(r1, r1, r5);       /* line  1 */
r6 = vec_sld(r0, r1, 12);        /* line  2 */
r3 = vcipherlast(r3, r4);        /* line  3 */

r1 = vec_xor(r1, r6);            /* line  4 */
r6 = vec_sld(r0, r6, 12);        /* line  5 */
r1 = vec_xor(r1, r6);            /* line  6 */
r6 = vec_sld(r0, r6, 12);        /* line  7 */
r1 = vec_xor(r1, r6);            /* line  8 */
r4 = vec_add(r4, r4);            /* line  9 */

// r1 is ready for next round
r1 = vec_xor(r1, r3);            /* line 10 */

进入函数后,big endian和little endian都有如下参数:

(gdb) p r1
$1 = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88,
  0x9, 0xcf, 0x4f, 0x3c}
(gdb) p r5
$2 = {0xd, 0xe, 0xf, 0xc, 0xd, 0xe, 0xf, 0xc, 0xd, 0xe, 0xf, 0xc, 0xd, 0xe,
  0xf, 0xc}

但是,执行第 2 行后,r6 的值为:

小端机:

(gdb) p r6
$3 = {0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x9, 0xcf, 0x4f, 0x3c,
  0x0, 0x0, 0x0, 0x0}

(gdb) p $vs0
$3 = {uint128 = 0x8815f7aba6d2ae28000000003c4fcf09, v2_double = {
    4.9992689728788323e-315, -1.0395462025288474e-269}, v4_float = {
    0.0126836384, 0, -1.46188823e-15, -4.51291888e-34}, v4_int32 = {
    0x3c4fcf09, 0x0, 0xa6d2ae28, 0x8815f7ab}, v8_int16 = {0xcf09, 0x3c4f, 0x0,
    0x0, 0xae28, 0xa6d2, 0xf7ab, 0x8815}, v16_int8 = {0x9, 0xcf, 0x4f, 0x3c,
    0x0, 0x0, 0x0, 0x0, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88}}

大端机器:

(gdb) p r6
$4 = {0x0, 0x0, 0x0, 0x0, 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
  0xab, 0xf7, 0x15, 0x88}

注意小端机器上的奇数旋转。

当我在第 2 行执行后在小端机器上反汇编时:

 (gdb) disass $pc
 <skip multiple pages>

    0x0000000010000dc8 <+168>:   lxvd2x  vs12,r31,r9
    0x0000000010000dcc <+172>:   xxswapd vs12,vs12
    0x0000000010000dd0 <+176>:   xxlor   vs32,vs0,vs0
    0x0000000010000dd4 <+180>:   xxlor   vs33,vs12,vs12
    0x0000000010000dd8 <+184>:   vsldoi  v0,v0,v1,12
    0x0000000010000ddc <+188>:   xxlor   vs0,vs32,vs32
    0x0000000010000de0 <+192>:   xxswapd vs0,vs0
    0x0000000010000de4 <+196>:   li      r9,64
    0x0000000010000de8 <+200>:   stxvd2x vs0,r31,r9
 => 0x0000000010000dec <+204>:   li      r9,48
    0x0000000010000df0 <+208>:   lxvd2x  vs0,r31,r9
    0x0000000010000df4 <+212>:   xxswapd vs34,vs0

(gdb) p $v0
$5 = void

(gdb) p $vs0
$4 = {uint128 = 0x8815f7aba6d2ae28000000003c4fcf09, v2_double = {
    4.9992689728788323e-315, -1.0395462025288474e-269}, v4_float = {
    0.0126836384, 0, -1.46188823e-15, -4.51291888e-34}, v4_int32 = {
    0x3c4fcf09, 0x0, 0xa6d2ae28, 0x8815f7ab}, v8_int16 = {0xcf09, 0x3c4f, 0x0,
    0x0, 0xae28, 0xa6d2, 0xf7ab, 0x8815}, v16_int8 = {0x9, 0xcf, 0x4f, 0x3c,
    0x0, 0x0, 0x0, 0x0, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88}}

我不知道为什么 r6 不是预期值。理想情况下,我会检查两台机器上的 vsx 寄存器。不幸的是,GDB 在两台机器上都存在问题,因此我无法执行反汇编和打印 vector 寄存器等操作。

vec_sld endian 敏感吗?还是有其他问题?

最佳答案

PowerPC/AltiVec 的 Little endian 有时会让人费解 - 如果您需要让您的代码同时使用 big endian 和 little endian,那么它有助于定义一些可移植性宏,例如对于 vec_sld:

#ifdef __BIG_ENDIAN__
  #define VEC_SLD(va, vb, shift) vec_sld(va, vb, shift)
#else
  #define VEC_SLD(va, vb, shift) vec_sld(vb, va, 16 - (shift))
#endif

您可能会发现这对涉及水平/位置操作或缩小/扩大的所有内在函数都有帮助,例如vec_mergevec_pack vec_unpackvec_permvec_mule/vec_mulo, vec_splat, vec_lvsl/vec_lvsr

关于c - vec_sld endian 敏感吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46341923/

相关文章:

C 指针 : When you dereference a char pointer and try to store an int, 会存储整个 int 吗?

c++ - 为什么函数以相反的顺序显示十六进制代码?

ruby - 在 Ruby 中解压签名的小端

xor - IPv6 的 STUN 服务器 xoring

assembly - aarch64 xtn2 清除下半部分

c++ - 如何在 SSE2 中为 8 位和 16 位整数实现 vector 右移和左移?

CBC-MAC 在 C 中的实现

c - 使用指针扫描指针数组

c - Arduino 可变大小数组声明

c++ - 如何正确地从水平阵列垂直读取数据?