C 中的 PowerPC extsb
PowerPC extsb in C
我正在尝试将 PowerPC asm 片段转换为 C++。这是我到目前为止所做的:
PPC:
lis r11, ((dword_83EEF800+0x10000)@h)
lis r10, 0x20 # 0x207E90
addi r11, r11, -0x800 # dword_83EEF800
ori r10, r10, 0x7E90 # 0x207E90
lis r9, 4 # 0x46E80
ori r9, r9, 0x6E80 # 0x46E80
lwzx r11, r11, r10
subf r11, r11, r28
divw r11, r11, r9
extsb r3, r11 // Problem
C++:
DWORD r11 = 0x83EEF800 + 0x10000;
r11 += -0x800;
DWORD r10 = 0x207E90;
DWORD r9 = 0x46E80;
r11 = *(DWORD*)(r11 + r10);
r11 -= r28;
r11 /= r9;
现在我的问题是,我将如何用 C++ 编写 "extsb" 代码?文档说在这种情况下它采用 r11 的最低有效字节并将其存储到 r3 的低 8 位。然后它将位 56(在本例中为 24,因为它是一个 32 位寄存器)放入 r3 的剩余位。要获得 r11 的最低有效字节,我会这样做:
r11 & 0xFF
但我不确定如何获取第 24 位并用它来填充 r3 的剩余位。我只能使用原生C++!如果有人知道我如何将此 ppc 操作转换为 c++,请告诉我(如果我发布的转换后的 ppc 代码中存在任何重大错误,也请告诉我)。提前致谢!
最简单的 C 等效项是通过 int8_t
:
的转换
r3 = (int32_t) (int8_t) r11;
extsb
says the mnemonic is short for Extend Sign Byte. i.e. perform 2's complement sign-extension.
的文档条目的标题
看起来PowerPC docs number bits从左边开始,所以高位是bit 0,低位是bit 31,所以低8位的符号位是bit 24,这条指令就是表演 sign-extension.
#include <stdint.h>
int32_t sign_extend_8(int src) {
return (int32_t) (int8_t) src;
}
编译为(gcc4.8 for PowerPC, -O3 -std=c++03
,因为 Godbolt 没有安装较新的 PPC gcc):
extsb %r3,%r3
blr
这个也是,所以我们知道他们都是对的:
// requires 2's complement arithmetic right shifts
int32_t extsb_manual(uint32_t src) {
src <<= 24;
return ((int32_t)src) >> 24; // signed right shift.
}
ISO C++ 说它是 implementation-dependent 当你移动一个负数时会发生什么,但大多数实现(和一些方言,例如 GNU C++)保证 2 的补码 sign-extension 用于右移。 IE。移动高位的副本。
这使您可以通过算术右移来广播位。例如foo >> 31
产生 0 或 -1(在 2 的补码系统中)。
i'm sorry, but im can't use c++11 :
#include <cstdint>
或 stdint.h
不需要 C++11。它至少从 C++03 开始就存在,如果不是更早的话。 (Godbolt 的 PPC gcc4.8 似乎部分损坏,#include <cstdint>
出错,可能是因为它来自较新的 gcc。这就是为什么即使在 C++ 中我也使用 C <stdint.h>
header。)
起初我假设 "the low 8 bits" 是 0-7,就像我见过的所有其他架构一样,第 24 位是高字节的一部分。这将是一条非常奇怪的指令,但您可以通过以下方式实现它(再次使用算术右移):
// requires 2's complement arithmetic right shifts
uint32_t extsb_wrong(uint32_t src) {
int32_t signbits = src << (31-24); // move bit 24 to the top (bit 31)
signbits >>= 31; // broadcast the sign bit
// replace the low 8 of the 0 / -1 with the low 8 of the src
return ((uint32_t)signbits & ~0xFFU) | (src & 0xFFU);
}
这当然不会编译为 extsb
。这是一堆实际的移位和 AND / ORing。
我正在尝试将 PowerPC asm 片段转换为 C++。这是我到目前为止所做的:
PPC:
lis r11, ((dword_83EEF800+0x10000)@h)
lis r10, 0x20 # 0x207E90
addi r11, r11, -0x800 # dword_83EEF800
ori r10, r10, 0x7E90 # 0x207E90
lis r9, 4 # 0x46E80
ori r9, r9, 0x6E80 # 0x46E80
lwzx r11, r11, r10
subf r11, r11, r28
divw r11, r11, r9
extsb r3, r11 // Problem
C++:
DWORD r11 = 0x83EEF800 + 0x10000;
r11 += -0x800;
DWORD r10 = 0x207E90;
DWORD r9 = 0x46E80;
r11 = *(DWORD*)(r11 + r10);
r11 -= r28;
r11 /= r9;
现在我的问题是,我将如何用 C++ 编写 "extsb" 代码?文档说在这种情况下它采用 r11 的最低有效字节并将其存储到 r3 的低 8 位。然后它将位 56(在本例中为 24,因为它是一个 32 位寄存器)放入 r3 的剩余位。要获得 r11 的最低有效字节,我会这样做:
r11 & 0xFF
但我不确定如何获取第 24 位并用它来填充 r3 的剩余位。我只能使用原生C++!如果有人知道我如何将此 ppc 操作转换为 c++,请告诉我(如果我发布的转换后的 ppc 代码中存在任何重大错误,也请告诉我)。提前致谢!
最简单的 C 等效项是通过 int8_t
:
r3 = (int32_t) (int8_t) r11;
extsb
says the mnemonic is short for Extend Sign Byte. i.e. perform 2's complement sign-extension.
看起来PowerPC docs number bits从左边开始,所以高位是bit 0,低位是bit 31,所以低8位的符号位是bit 24,这条指令就是表演 sign-extension.
#include <stdint.h>
int32_t sign_extend_8(int src) {
return (int32_t) (int8_t) src;
}
编译为(gcc4.8 for PowerPC, -O3 -std=c++03
,因为 Godbolt 没有安装较新的 PPC gcc):
extsb %r3,%r3
blr
这个也是,所以我们知道他们都是对的:
// requires 2's complement arithmetic right shifts
int32_t extsb_manual(uint32_t src) {
src <<= 24;
return ((int32_t)src) >> 24; // signed right shift.
}
ISO C++ 说它是 implementation-dependent 当你移动一个负数时会发生什么,但大多数实现(和一些方言,例如 GNU C++)保证 2 的补码 sign-extension 用于右移。 IE。移动高位的副本。
这使您可以通过算术右移来广播位。例如foo >> 31
产生 0 或 -1(在 2 的补码系统中)。
i'm sorry, but im can't use c++11 :
#include <cstdint>
或 stdint.h
不需要 C++11。它至少从 C++03 开始就存在,如果不是更早的话。 (Godbolt 的 PPC gcc4.8 似乎部分损坏,#include <cstdint>
出错,可能是因为它来自较新的 gcc。这就是为什么即使在 C++ 中我也使用 C <stdint.h>
header。)
起初我假设 "the low 8 bits" 是 0-7,就像我见过的所有其他架构一样,第 24 位是高字节的一部分。这将是一条非常奇怪的指令,但您可以通过以下方式实现它(再次使用算术右移):
// requires 2's complement arithmetic right shifts
uint32_t extsb_wrong(uint32_t src) {
int32_t signbits = src << (31-24); // move bit 24 to the top (bit 31)
signbits >>= 31; // broadcast the sign bit
// replace the low 8 of the 0 / -1 with the low 8 of the src
return ((uint32_t)signbits & ~0xFFU) | (src & 0xFFU);
}
这当然不会编译为 extsb
。这是一堆实际的移位和 AND / ORing。