li
es un pseudo-opcode que realmente se traduce como una instrucción addi
.
addi rD, rA, SIMM
añade los firmaron inmediata SIMM
a rA
, colocando el resultado en rD
, excepto cuando el campo rA
es 0, en cuyo caso se especifica un literal 0 en lugar de r0
. li rD, SIMM
es realmente addi rD, 0, SIMM
.
Esto es bueno para los valores de carga de 0
-0x7fff
y 0xffff8000
-0xffffffff
en un registro, pero no otros valores.
Los códigos de operación de bit a bit inmediatos (ori
etc.) interpretan el campo inmediato de 16 bits como un valor sin signo. Sin embargo, no tienen el "r0
significa un comportamiento literal 0
" de addi
.
Usted tendrá que utilizar dos instrucciones para cargar una constante de 0xfc10
en un registro de: cargar el registro con 0 usando li
(o lis
, como si estuviera cargando la mitad superior de un arbitrario de 32 bits constante) y luego O en el valor de 16 bits sin firmar con ori
.
Esto es exactamente lo que hace gcc
bajo las circunstancias:
$ 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
$
yo no pensar el ensamblador GNU tiene ninguna manera de generar automáticamente dos instrucciones para cargar un valor tal partir de una sola fuente de instrucción cuando se ensambla para PowerPC. Sin embargo se pueden utilizar las @h
y @l
sufijos para extraer las mitades (sin firmar) de alto y bajo de 16 bits de una constante, por ejemplo:
lis r3, [email protected] /* => li r3, 0x1234 */
ori r3, r3, [email protected] /* => ori r3, r3, 0x5678 */
Usted podría utilizar esto para escribir su propia macro para la carga constante arbitraria .. .
$ 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
$
-1008 tiene la misma representación de complemento de 2 como 0xFC10.¿Tal vez podrías escribir (0xfc10-0x10000)? –
¿O firmar-extenderlo manualmente a 0xFFFFFC10? –
@tc - Interesante. Aunque la instrucción li solo acepta valores de 16 bits, li r3,0xFFFFFC10 es una instrucción legal. – KeithSmith