powerpc-eabivle-gcc 不支持 e_and2i 指令

powerpc-eabivle-gcc does not support e_and2i instruction

我正在使用 NXP 的 GCC 4.9 VLE 编译器。我的目标是 e200z7 内核。我想禁用 MSR 寄存器的第 16 位。这是我正在使用的:

/* Disable MSR[EE] bit*/
        mfmsr   r6
        e_and2i r6,0x7fff
        mtmsr   r6

当我使用 powerpc_eabivle_4_9/bin/powerpc-eabivle-gcc 编译 .S 文件时,出现以下错误:

Error: unrecognized opcode: `e_and2i'

没有and指令如何设置为0?

更新:请参阅 了解 VLE(可变长度编码)。我的回答只是针对通用 PowerPC 的一个简单天真的回答,当紧凑的 16 位指令可用时,它并不是最佳的。

如果您对可以从 C 为您生成 VLE asm 的 NXP 版本的 GCC 应用相同的技术,

当您不知道 ISA 的每个窥视孔优化时,询问编译器的一般技术非常有用。


像往常一样,问编译器:

unsigned foo(unsigned x) {
    return x &= ~(1UL << 15);
}

compiles on Godbolt 与 GCC4.8.5 -O3 -mregnames

foo(unsigned int):
        rlwinm %r3,%r3,0,17,15
        blr

我认为 rlwinm 在每个 PowerPC 上都可用,或者至少不是特别新或罕见。它需要一个位范围(开始/结束可以回绕以只留下一个被屏蔽的位)和一个旋转计数(在这种情况下为零)。

这真的是 XY Problem。您最终会问如何将 e_and2i r6,0x7fff 替换为不使用 and 指令的内容。真正应该问的问题是 "why does e_and2i r6,0x7fff throw an "unrecognized opcode error?

答案很简单。您的目标是 e200z7 内核。该内核使用可变长度编码 (VLE)。指令的长度可以是 16 位或 32 位。前缀为 se_ 的指令长度为 16 位,前缀为 e_ 的指令长度为 32 位。以句点 (.) 结尾的指令更新条件寄存器 (CR).

如果您查看 Variable-Length Encoding (VLE) Programming Environments Manual,您会发现没有 2 操作数 e_and2i 指令,但有一个 e_and2i. 指令。对于 VLE,没有不更新 CRe_and2i 指令。如果您的代码不依赖 CR 被保留(可能是这种情况),您可以简单地将 e_and2i 更改为 e_and2i.。您的代码将如下所示:

mfmsr    r6
e_and2i. r6,0x7fff
mtmsr    r6

或者您可以使用不更新 CR 的 3 操作数形式 e_andi。它看起来像:

mfmsr    r6
e_andi   r6,r6,0x7fff
mtmsr    r6

e_and2i.e_andi 被编码为长度为 32 位的指令,但是有一个长度为 16 位的 VLE 指令可以完成您想要的工作并且不会更新 CR。该指令是 2 个操作数 位立即清除 se_bclri。您的代码可以写成:

mfmsr    r6
se_bclri r6,16          ; Clear the 16th bit (bit 0 is MSB and bit 31 is LSB)
mtmsr    r6

与 Peter Cordes 的回答相关,他建议如下:

rlwinm r6,r6,0,17,15

此指令无法正确编码为 VLE 指令。但是有 VLE 等价物:

e_rlwinm r6,r6,0,17,15