2012-06-21 16 views
5

Soy nuevo en el ensamblaje de PowerPC. Estoy trabajando con un MPC8245 (sí, en la vieja escuela). Este es un procesador familiar 603e.PowerPC Assembly Load Inmediato

Me gustaría saber cómo crear una instrucción de carga inmediata donde el valor inmediato de 16 bits es 'unsigned'.

Ejemplo: li r3,0xFC10

El gcc compilador cruzado, 4.4.5, estoy utilizando no permite esta instrucción como el valor no es una constante firmado.

Sí, podría usar menos el complemento de 2 s, pero esto hace que leer y documentar el código sea más difícil. Al cargar campos de bits para registros de dispositivos, es mucho más fácil leer los campos exactos de los bits en las instrucciones.

+0

-1008 tiene la misma representación de complemento de 2 como 0xFC10.¿Tal vez podrías escribir (0xfc10-0x10000)? –

+0

¿O firmar-extenderlo manualmente a 0xFFFFFC10? –

+0

@tc - Interesante. Aunque la instrucción li solo acepta valores de 16 bits, li r3,0xFFFFFC10 es una instrucción legal. – KeithSmith

Respuesta

10

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 
$ 
+0

Matt - Gracias por la respuesta completa. El entorno de compilación que estoy usando tiene la macro 'lwi'. El error informado por gcc cuando se utiliza un valor sin signo con 'li' es" Error: operando fuera del rango (0x00008000 no está entre 0xffff8000 y 0x00007fff) "como se mencionó anteriormente. – KeithSmith

0

también puede cargar un sin signo de 16 bits inmediata mediante el operador ori, pero asegúrese de limpiar su registro antes:

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