vec_sld字节序敏感吗?
Is vec_sld endian sensitive?
我正在使用内核加密的 PowerPC 机器上工作。我在使用内置函数将 AES 密钥扩展从大端移植到小端时遇到问题。大端有效,小端无效。
下面的算法是 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
= {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88,
0x9, 0xcf, 0x4f, 0x3c}
(gdb) p r5
= {0xd, 0xe, 0xf, 0xc, 0xd, 0xe, 0xf, 0xc, 0xd, 0xe, 0xf, 0xc, 0xd, 0xe,
0xf, 0xc}
然而,执行第 2 行后,r6
的值为:
小端机:
(gdb) p r6
= {0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x9, 0xcf, 0x4f, 0x3c,
0x0, 0x0, 0x0, 0x0}
(gdb) p $vs0
= {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
= {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
= void
(gdb) p $vs0
= {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 在两台机器上都存在问题,所以我无法执行诸如反汇编和打印向量寄存器之类的操作。
vec_sld
字节序敏感吗?还是有其他问题?
使用 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
您可能会发现这对涉及 horizontal/positional 操作或 narrowing/widening 的所有内在函数都有帮助,例如vec_merge
, vec_pack
等, vec_unpack
, vec_perm
, vec_mule
/vec_mulo
, vec_splat
、vec_lvsl
/vec_lvsr
、等等
我正在使用内核加密的 PowerPC 机器上工作。我在使用内置函数将 AES 密钥扩展从大端移植到小端时遇到问题。大端有效,小端无效。
下面的算法是 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
= {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88,
0x9, 0xcf, 0x4f, 0x3c}
(gdb) p r5
= {0xd, 0xe, 0xf, 0xc, 0xd, 0xe, 0xf, 0xc, 0xd, 0xe, 0xf, 0xc, 0xd, 0xe,
0xf, 0xc}
然而,执行第 2 行后,r6
的值为:
小端机:
(gdb) p r6
= {0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x9, 0xcf, 0x4f, 0x3c,
0x0, 0x0, 0x0, 0x0}
(gdb) p $vs0
= {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
= {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
= void
(gdb) p $vs0
= {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 在两台机器上都存在问题,所以我无法执行诸如反汇编和打印向量寄存器之类的操作。
vec_sld
字节序敏感吗?还是有其他问题?
使用 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
您可能会发现这对涉及 horizontal/positional 操作或 narrowing/widening 的所有内在函数都有帮助,例如vec_merge
, vec_pack
等, vec_unpack
, vec_perm
, vec_mule
/vec_mulo
, vec_splat
、vec_lvsl
/vec_lvsr
、等等