我需要帮助将此 ppc 指令翻译为 c++

问题描述 投票:0回答:2

有人可以给我看一个 C++ 的例子吗?我正在尝试练习我的汇编语言技能,从我得到的语言是 powerpc,我们正在寻找 44 位移到 r0 内部的右侧,从那里我们是提取前 8 位

extrdi    r0, r0, 8,44

c++ assembly bit-manipulation powerpc
2个回答
3
投票

ISA 说

extrdi
是“提取并右对齐立即数”,它是
rldicl
(“向左旋转双字立即数并向左清除”)的扩展助记符 - v2.07 pg 717。所以你的陈述是等效的到
rldicl r0, r0, 52, 56

因此,您想要提取从位置 44 开始的 8 位,然后对其进行右对齐,这将使其成为最低有效的 8 位。值得注意的是,IBM 位数字与您可能期望的相反:

conventional bit = 63 - IBM bit
。因此 IBM 位 44 到 51 是“常规”位编号 12 到 19。

我们只需向下移位,使位 12 变为位 0,位 19 变为位 7 - 移位 12 位。然后我们需要屏蔽它,这样我们只得到最低有效的 8 位。

unsigned long extrdi(unsigned long a) {
  return (a >> 12) & 0xff;
}

查看 godbolt.org:https://godbolt.org/z/rGe3EW,我们看到这确实是:

extrdi:
        rldicl 3,3,52,56
        blr
        .long 0
        .byte 0,0,0,0,0,0,0,0

(r3是参数和返回寄存器)


0
投票

根据PowerPC助记符文档

extrdi
表示从b位开始提取n位,然后右对齐

以8位整数来说明:

extrdi r0, r0, 2, 3

r0: A B C D E F G H
        |   |
        +---+
        2 2+3-1

After extraction:    0 0 C D E 0 0 0
After justification: 0 0 0 0 0 C D E

我们可以如下实现(64位):

unsigned long extrdi_soft(unsigned long ry, unsigned n, unsigned b) {
  unsigned offset = (64 - b - n);
  // Generate the n-bit mask beginning from position b
  unsigned mask = ((1UL << n) - 1) << offset;
  // Do mask and right-justify it
  return (ry & mask) >> offset;
}

与真实的比较

extrdi

unsigned long extrdi_hard(unsigned long rs) {
  unsigned long ra = 0;
  asm("extrdi %1, %0, 8, 44"
     :"=r"(ra)
     :"r"(rs));
  return ra;
}

// extrdi_hard(0x1234567UL) == extrdi_soft(0x1234567UL, 8, 44)

extrdi rs, ry, n, b
实际上是
rldicl rs, ry, b+n, 64-n
的助记符。该指令的意思是向左旋转然后向左清除。所以我们有另一种方式来实现
extrdi
:

unsigned long rotl64(unsigned long rs, unsigned n) {
  return (rs << n) | (rs >> (64-n));
}

unsigned long rldicl(unsigned long rs, unsigned sh, unsigned mb) {
  return rotl64(rs, sh) & ((1UL << (64 - mb)) - 1);
}

unsigned long extrdi(unsigned long ry, unsigned n, unsigned b) {
  return rldicl(ry, b+n, 64-n);
}
© www.soinside.com 2019 - 2024. All rights reserved.