2012-06-21 44 views
5

我是PowerPC組裝的新手。我正在使用MPC8245(是的,舊學校)。這是一款603e家族處理器。PowerPC Assembly立即加載

我想知道如何創建一個立即的16位值爲'無符號'的立即加載指令。

實施例:LI r3,0xFC10

gcc的交叉編譯器,4.4.5,我使用不允許這種指令作爲值是不帶符號的常數。

是的,我可以使用減去2-s補碼,但是這使得閱讀和記錄代碼更加困難。裝載設備寄存器的位域時,指令中的確切位域更容易閱讀。

+0

-1008與0xFC10具有相同的2的補碼錶示。也許你可以寫(0xfc10-0x10000)? –

+0

或者手動將它擴展到0xFFFFFC10? –

+0

@tc - 有趣。即使li指令只接受16位值,li r3,0xFFFFFC10也是一條合法指令。 – KeithSmith

回答

10

li是一個僞操作碼,它實際上翻譯爲addi指令。

addi rD, rA, SIMM增加了當rA字段爲0,在這種情況下,它指定r0字面0代替符號立即SIMMrA,把結果放置在rD除了li rD, SIMM確實是addi rD, 0, SIMM

這對從0 - 0x7fff0xffff8000 - 0xffffffff加載值到寄存器,但不是其他值是好的。

立即按位操作操作碼(ori等)將16位立即數字段解釋爲無符號值。但是,它們沒有「r0」表示文字0addi的行爲。

您將需要使用兩個指令的0xfc10一個常數加載到寄存器:加載使用li 0寄存器(或lis,因爲如果你是加載任意的32位常數的上半​​部分),然後OR與無符號16位值ori

這正是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位的常數,例如半:

lis r3, [email protected]   /* => li r3, 0x1234  */ 
ori r3, r3, [email protected]  /* => ori r3, r3, 0x5678 */ 

您可以使用它來編寫自己的任意常數加載宏.. 。

$ cat test2.s 
     .macro load_const rD, const 
     .if (\const >= -0x8000) && (\const <= 0x7fff) 
     li  \rD, \const 
     .else 
     lis  \rD, \[email protected] 
     ori  \rD, \rD, \[email protected] 
     .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 
$ 
+0

馬特 - 感謝您的徹底解答。我使用的構建環境具有'lwi'宏。如上所述,當使用帶有'li'的無符號值時,gcc報告的錯誤是「錯誤:操作數超出範圍(0x00008000不在0xffff8000和0x00007fff之間)」。 – KeithSmith

0

您還可以通過使用操作ori加載未簽名的16位直接的,但可以肯定之前清除寄存器:

xor r3, r3, r3 
ori r3, r3, 0xFC10