我是PowerPC组装的新手。我正在使用MPC8245(是的,老学校)。这是一款603e系列处理器。
我想知道如何创建一个加载立即指令,其中立即的16位值是'unsigned'。
示例:li r3,0xFC10
我正在使用的gcc交叉编译器4.4.5不允许使用此指令,因为该值不是有符号常量。
是的,我可以使用减去2-s补码,但这使得阅读和记录代码更加困难。当加载器件寄存器的位域时,在指令中具有精确的位字段更容易阅读。
答案 0 :(得分:14)
li
是伪操作码,实际上转换为addi
指令。
addi rD, rA, SIMM
将签名后的SIMM
添加到rA
,将结果放在rD
,除时rA
字段是0,在这种情况下,它指定文字0而不是r0
。 li rD, SIMM
确实是addi rD, 0, SIMM
。
这适用于将0
- 0x7fff
和0xffff8000
- 0xffffffff
的值加载到寄存器中,而不是其他值。
立即按位操作操作码(ori
等)确实将16位立即数字解释为无符号值。但是,他们没有r0
表示0
的文字addi
“行为。
您需要使用两条指令将0xfc10
的常量加载到寄存器中:使用li
(或lis
将寄存器加载为0,就像加载顶部一样任意32位常数的一半)然后在带有ori
的无符号16位值中进行OR运算。
这正是gcc
在这种情况下所做的事情:
$ cat test.c
unsigned int test(void)
{
return 0xfc10;
}
$ gcc -O2 -c test.c
$ objdump -d test.o
test.o: file format elf32-powerpc
Disassembly of section .text:
00000000 <test>:
0: 38 60 00 00 li r3,0
4: 60 63 fc 10 ori r3,r3,64528
8: 4e 80 00 20 blr
c: 60 00 00 00 nop
$
我不认为 GNU汇编程序有任何方法可以自动生成两条指令,以便在组装PowerPC时从单个源指令加载这样的值。但是,您可以使用@h
和@l
后缀来提取常量的(无符号)高16位和低16位,例如:
lis r3, 0x12345678@h /* => li r3, 0x1234 */
ori r3, r3, 0x12345678@l /* => ori r3, r3, 0x5678 */
您可以使用它来编写自己的宏来进行任意常量加载......
$ cat test2.s
.macro load_const rD, const
.if (\const >= -0x8000) && (\const <= 0x7fff)
li \rD, \const
.else
lis \rD, \const@h
ori \rD, \rD, \const@l
.endif
.endm
load_const r3, 0
load_const r4, 1
load_const r5, -1
load_const r6, 0x7fff
load_const r7, 0x8000
load_const r8, -32767
load_const r9, -32768
load_const r10, -32769
load_const r11, 0xfc10
$ as -mregnames -o test2.o test2.s
$ objdump -d test2.o
test2.o: file format elf32-powerpc
Disassembly of section .text:
00000000 <.text>:
0: 38 60 00 00 li r3,0
4: 38 80 00 01 li r4,1
8: 38 a0 ff ff li r5,-1
c: 38 c0 7f ff li r6,32767
10: 3c e0 00 00 lis r7,0
14: 60 e7 80 00 ori r7,r7,32768
18: 39 00 80 01 li r8,-32767
1c: 39 20 80 00 li r9,-32768
20: 3d 40 ff ff lis r10,-1
24: 61 4a 7f ff ori r10,r10,32767
28: 3d 60 00 00 lis r11,0
2c: 61 6b fc 10 ori r11,r11,64528
$
答案 1 :(得分:0)
您也可以使用运算符ori
立即加载无符号16位,但请务必在注册之前清除您的寄存器:
xor r3, r3, r3
ori r3, r3, 0xFC10