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,没有不更新 CR 的 e_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
我正在使用 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?
更新:请参阅
如果您对可以从 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,没有不更新 CR 的 e_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