gpt4 book ai didi

x86 - 如何在 xmm 寄存器中旋转压缩四字?

转载 作者:行者123 更新时间:2023-12-01 03:09:21 25 4
gpt4 key购买 nike

给定一个 128 位 xmm包含两个四字(即两个 64 位整数)的寄存器:

     ╭──────────────────┬──────────────────╮
xmm0 │ ffeeddccbbaa9988 │ 7766554433221100 │
╰──────────────────┴──────────────────╯

如何对单个四字执行旋转?例如:
prorqw xmm0, 32   // rotate right packed quadwords

╭──────────────────┬──────────────────╮
xmm0 │ bbaa9988ffeeddcc │ 3322110077665544 │
╰──────────────────┴──────────────────╯

我知道 SSE2 提供:
  • PSHUFW : 洗牌包装 (16 位)
  • PSHUFD : 洗牌包装 双字 (32 位)

  • 虽然我不知道指令是做什么的,也没有 四字 (64 位)版本。

    奖金问题

    你会如何执行 RORxmm注册 - 假设其他大小的打包数据?
  • 右旋包装双字按 16 位:
         ╭──────────┬──────────┬──────────┬──────────╮
    xmm0 │ ffeeddcc │ bbaa9988 │ 77665544 │ 33221100 │
    ╰──────────┴──────────┴──────────┴──────────╯

    ╭──────────┬──────────┬──────────┬──────────╮
    xmm0 │ ddccffee │ 9988bbaa │ 55447766 │ 11003322 │
    ╰──────────┴──────────┴──────────┴──────────╯
  • 右旋包装按 8 位:
         ╭──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────╮
    xmm0 │ ffee │ ddcc │ bbaa │ 9988 │ 7766 │ 5544 │ 3322 │ 1100 │
    ╰──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────╯

    ╭──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────╮
    xmm0 │ eeff │ ccdd │ aabb │ 8899 │ 6677 │ 4455 │ 2233 │ 0011 │
    ╰──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────╯

  • 额外奖励问题

    如果是 256 位 ymm,您将如何执行上述操作登记?
         ╭──────────────────────────────────┬──────────────────────────────────╮
    ymm0 │ 2f2e2d2c2b2a29282726252423222120 │ ffeeddccbbaa99887766554433221100 │ packed doublequadwords
    ╰──────────────────────────────────┴──────────────────────────────────╯
    ╭──────────────────┬──────────────────┬──────────────────┬──────────────────╮
    ymm0 │ 2f2e2d2c2b2a2928 │ 2726252423222120 │ ffeeddccbbaa9988 │ 7766554433221100 │ packed quadwords
    ╰──────────────────┴──────────────────┴──────────────────┴──────────────────╯
    ╭──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────╮
    ymm0 │ 2f2e2d2c │ 2b2a2928 │ 27262524 │ 23222120 │ ffeeddcc │ bbaa9988 │ 77665544 │ 33221100 │ packed doublewords
    ╰──────────┴──────────┴──────────┴──────────┴──────────┴──────────┴──────────┴──────────╯
    ╭──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────╮
    ymm0 │ 2f2e │ 2d2c │ 2b2a │ 2928 │ 2726 │ 2524 │ 2322 │ 2120 │ ffee │ ddcc │ bbaa │ 9988 │ 7766 │ 5544 │ 3322 │ 1100 │ packed words
    ╰──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────╯

    奖励阅读
  • Intel Intrinsics Guide
  • X86 Opcode and Instruction Reference Home
  • Rotation or Shifting with x86/x64 Assembly
  • PSHUFW explanation?
  • 最佳答案

    如果旋转计数是 8 的倍数,则可以使用字节洗牌。 SSSE3 pshufb 使用控制掩码可以在一条指令中处理任何其他 8 的倍数。

    SSE2 pshufd 可以处理 count=32,交换每个 qword 的两半:_MM_SHUFFLE(2,3, 0,1) ,或在 asm pshufd xmm0, xmm0, 0b10_11_00_01 (NASM 支持 _ 作为可选的分隔符,就像 C++11 的数字文字一样。)

    SSE2 pshuflw + pshufhw 对于没有 SSSE3 的函数版本来说,对于 16 个计数的倍数来说还不错,但是您需要对低/高 qword 进行单独的洗牌。 (一个 imm8 控制字节仅包含四个 2 位字段。)或者使用 AVX2,用于每个 channel 内的奇数/偶数 qword。

    如果旋转计数不是 8 的倍数 , 有 AVX512F vprolq zmm0, zmm1, 13 vprorq .也可用于可变计数版本,每个元素计数来自另一个向量而不是立即数。 vprolvq/vprorvq .也可用于双字粒度,但不能用于字或字节。

    否则,只有 SSE2 且计数不是 16 的倍数,您需要左移+右移 + OR 在 asm 中实际实现在 C 中表达旋转的常用方法为 (x << n) | (x >> (64-n)) . ( Best practices for circular shift (rotate) operations in C++ 指出了从超出范围的移位计数中解决潜在 C UB 的方法,这对内在函数或 asm 不是问题,因为 asm 和内在函数的行为由英特尔明确定义:SIMD 移位使移位饱和计数,而不是像标量偏移那样掩盖它。)

    SSE2 具有小至 16 位粒度的移位,因此您可以直接执行此操作。

    对于字节粒度,您需要额外的掩码以将字中字节之间移位的位清零。 Efficient way of rotating a byte inside an AVX register .或者使用像 pmullw 这样的技巧具有 2 次幂元素的向量,允许每个元素的可变计数。 (其中 AVX2 通常只有 dword/qword 的可变计数移位)。

    关于x86 - 如何在 xmm 寄存器中旋转压缩四字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53643628/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com