【问题标题】:Is vec_sld endian sensitive?vec_sld 字节序敏感吗?
【发布时间】:2018-03-02 16:30:15
【问题描述】:

我正在使用内核加密的 PowerPC 机器。我在使用内置插件将 AES 密钥扩展从大端移植到小端时遇到问题。大端有效,但小端无效。

下面的算法是IBM blog article 中的 sn-p。我认为我的问题与下面的第 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 */

进入函数后,大端和小端都有以下参数:

(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 在两台机器上也有问题,所以我不能做诸如反汇编和打印向量寄存器之类的事情。

vec_sld 字节序敏感吗?还是有其他问题?

【问题讨论】:

    标签: c endianness simd powerpc altivec


    【解决方案1】:

    使用 PowerPC/AltiVec 的小端有时会让人有点费解——如果您需要让代码同时使用大端和小端,那么定义一些可移植宏会有所帮助,例如对于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_packvec_unpackvec_permvec_mule/vec_mulovec_splatvec_lvsl/vec_lvsr

    【讨论】:

    • 谢谢保罗。 IBM 文档没有提及vec_sld(或朋友)对字节序敏感。如果你不介意我问,你有参考吗?或者这是来之不易的经历?作为参考,这是vec_sld 上的 IBM 文档。
    • 这是来之不易的经验 - 很久以前,我用 AltiVec 做了很多嵌入式工作,包括大端和小端目标。我希望我能给你所有的可移植宏,它们可以减轻很多痛苦,但是 IP 问题阻止了这一点,但是上述方法应该有助于引导你走向正确的方向。如果您遇到任何其他问题,请使用altivec 标签发布一个新问题,如果可以,我会尽力提供帮助。
    • P.S.您可能会发现获取摩托罗拉 AltiVec 文档很有帮助 - 它们不涵盖更现代的东西,如加密,但我认为您可能会发现它们对所有一般的东西都有帮助 - 只是谷歌的“AltiVec PIM”和“AltiVec PEM” - 你会想要两者(一个用于组装,另一个用于内在函数)。
    • IBM 到底是如何设法编写一个特定于字节序的位移函数的?
    • @Lundin:我认为这是 SIMD 的固有问题 - 对于双端架构,您必须能够选择在加载/存储时对所有向量进行字节反转,或者在 SIMD 中对 SIMD 数据通道进行字节反转ALU 路径,这两种路径都需要大量不必要的硅。通常你只使用一种或另一种字节序,所以你只需相应地编码(我有幸编写需要支持两种字节序的代码,这就是乐趣的开始。)
    猜你喜欢
    • 2011-01-15
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 2018-04-08
    • 1970-01-01
    • 2017-03-22
    • 1970-01-01
    相关资源
    最近更新 更多