Registro de uso y convenios

La arquitectura de 32 bits de PowerPC® tiene 32 GPR y 32 FPR.

La arquitectura de 32 bits de PowerPC® tiene 32 GPR y 32 FPR. Cada GPR tiene 32 bits de ancho y cada FPR tiene 64 bits de ancho. También hay registros especiales para la ramificación, el manejo de excepciones y otros propósitos. La tabla de Convención de registro de propósito general muestra cómo se utilizan los GPRs.

Tabla 1. Convenios de registro general
Registro Estado Uso
GPR0 volatile En los prologs de función.
GPR1 dedicado Puntero de pila.
GPR2 dedicado Puntero de tabla de contenido (TOC).
GPR3 volatile Primera palabra de la lista de argumentos de una función; primera palabra de un retorno de función escalar.
GPR4 volatile Segunda palabra de la lista de argumentos de una función; segunda palabra de un retorno de función escalar.
GPR5 volatile Tercera palabra de la lista de argumentos de una función.
GPR6 volatile Cuarta palabra de la lista de argumentos de una función.
GPR7 volatile Quinta palabra de la lista de argumentos de una función.
GPR8 volatile Sexta palabra de la lista de argumentos de una función.
GPR9 volatile Séptima palabra de la lista de argumentos de una función.
GPR10 volatile Octava palabra de la lista de argumentos de una función.
GPR11 volatile En llamadas por puntero y como un puntero de entorno para idiomas que lo requieren (por ejemplo, PASCAL).
GPR12 volatile Para el manejo de excepciones especiales requerido por ciertos idiomas y en el código glink .
GPR13 Reservada Reservado bajo un entorno de 64 bits; no restaurado a través de llamadas del sistema.
GPR14:GPR31 no volátil Estos registros deben conservarse a través de una llamada de función.

El método preferido de utilizar los GPRs es utilizar primero los registros volátiles. A continuación, utilice los registros no volátiles en orden descendente, empezando por GPR31. GPR1 y GPR2 deben estar dedicados a punteros de área de pila y tabla de contenido (TOC), respectivamente. GPR1 y GPR2 deben aparecer para salvarse a través de una llamada y deben tener los mismos valores a la vuelta que cuando se realizó la llamada.

Los registros volátiles son registros reutilizables que se presume que se destruyen a través de una llamada y, por lo tanto, no son salvados por el callee. Los registros volátiles también se utilizan para fines específicos, como se muestra en la tabla anterior. Los registros no volátiles y dedicados deben guardarse y restaurarse si se modifican y, por lo tanto, se les garantiza que conserven sus valores en una llamada a función.

La tabla de Convenios de registro de coma flotante muestra cómo se utilizan los FPRs.

Cuadro 2. Convenios de registro de coma flotante
Registro Estado Uso
FPR0 volatile Como registro de scratch.
FPR1 volatile Primer parámetro de coma flotante; primeros 8 bytes de un retorno escalar de coma flotante.
FPR2 volatile Segundo parámetro de coma flotante; segundo 8 bytes de un retorno escalar de coma flotante.
FPR3 volatile Tercer parámetro de coma flotante; tercer 8 bytes de un retorno escalar de coma flotante.
FPR4 volatile Cuarto parámetro de coma flotante; cuarto 8 bytes de un retorno escalar de coma flotante.
FPR5 volatile Quinto parámetro de coma flotante.
FPR6 volatile Sexto parámetro de coma flotante.
FPR7 volatile Séptimo parámetro de coma flotante.
FPR8 volatile Octavo parámetro de coma flotante.
FPR9 volatile Noveno parámetro de coma flotante.
FPR10 volatile Décimo parámetro de coma flotante.
FPR11 volatile Undécimo parámetro de coma flotante.
FPR12 volatile Duodécimo parámetro de coma flotante.
FPR13 volatile Decimotercer parámetro de coma flotante.
FPR14:FPR31 no volátil Si se modifica, debe conservarse a través de una llamada.

El método preferido de utilizar FPRs es utilizar primero los registros volátiles. A continuación, los registros no volátiles se utilizan en orden descendente, empezando por FPR31 y procediendo a FPR14.

Sólo los escalares se devuelven en varios registros. El número de registros necesarios depende del tamaño y el tipo del escalar. Para valores de coma flotante, se producen los resultados siguientes:

  • Un valor de coma flotante de 128 bits devuelve los 64 bits de orden superior en FPR1 y los 64 bits de orden bajo en FPR2.
  • Un valor complejo de 8 bytes o 16 bytes devuelve la parte real en FPR1 y la parte imaginaria en FPR2.
  • Un valor complejo de 32 bytes devuelve la parte real como un valor de coma flotante de 128 bits en FPR1 y FPR2, con los 64 bits de orden superior en FPR1 y los 64 bits de orden bajo en FPR2. La parte imaginaria de un valor complejo de 32 bytes devuelve los 64 bits de orden superior en FPR3 y los 64 bits de orden bajo en FPR4.

Ejemplo de convenio de llamada para tipos complejos


complex double foo(complex double);
Los argumentos se pasan a fp1 y fp2 y los resultados se devuelven en fp1 y fp2. Los siguientes dos parámetros complejos se pasan en los dos registros disponibles siguientes, hasta fp13, utilizando pares pares o pares pares. Después de fp13 se pasan en un área de parámetros en la memoria ubicada en el principio del marco de pila del llamante.
Nota: Los registros omitidos no se utilizan para parámetros posteriores. Además, estos registros no son inicializados por el llamante y la función llamada no debe depender del valor almacenado dentro de los registros omitidos.

Un único complejo de precisión (flotador complejo) se pasa de la misma manera que la precisión doble con los valores ampliados a doble precisión.

El complejo de precisión doble y único (flotante complejo y complejo) se devuelve en fp1 y fp2 con valores de precisión simples se amplía a doble precisión.

En los próximos cuatro registros disponibles, de fp1 a fp13 y luego en el área de parámetros, se pasan cuatro parámetros complejos de precisión cuádruple (complejos largos complejos). El orden en que se llenan los registros es, la mitad superior de la parte real, la mitad inferior de la parte real, la mitad superior de la parte imaginaria, y la mitad inferior de la parte imaginaria.
Nota: En las estructuras AIX , las clases y los sindicatos se pasan en gprs (o memoria) y no en fprs. Esto es cierto incluso si las clases y los sindicatos contienen valores de coma flotante. En Linux en PPC la dirección de una copia en la memoria se pasa en el siguiente gpr disponible (o en la memoria). Los parámetros varargs se manejan específicamente y generalmente se pasan a ambos fprs y gprs.

Convenio de llamada para tipos de coma flotante decimal (_Decimal128)

Los parámetros de _Decimal64 se pasan en la siguiente fpr disponible y los resultados se devuelven en fp1.

Los parámetros de _Decimal32 se pasan en la mitad inferior de la siguiente fpr disponible y los resultados se devuelven en la mitad inferior de fp1, sin convertirse a _Decimal64.

Los parámetros de _Decimal128 se pasan en el siguiente par de fpr (o memoria) incluso impar, incluso si eso significa saltarse un registro y los resultados se devuelven en el par par-impar fpr2 y fpr3. La razón es que todas las instrucciones aritméticas requieren el uso de pares de registro pares impar.
Nota: Los registros omitidos no se utilizan para parámetros posteriores. Además, estos registros no son inicializados por el llamante y la función llamada no debe depender del valor almacenado dentro de los registros omitidos.

A diferencia de float o double, con DFP, siempre se requiere un prototipo de función. Por lo tanto, no es necesario ampliar _Decimal32 a _Decinmal64.

Ejemplo de convenio de llamada para el tipo de coma flotante decimal (_Decimal32)

#include <float.h>
#define DFP_ROUND_HALF_UP 4

_Decimal32 Add_GST_and_Ontario_PST_d32 (_Decimal32 price)
{
_Decimal32 gst;
_Decimal32 pst;
_Decimal32 total;
long original_rounding_mode = __dfp_get_rounding_mode ( );
__dfp_set_rounding_mode (DFP_ROUND_HALF_UP);
gst = price * 0.06dd;
pst = price * 0.08dd;
total = price + gst + pst;
__dfp_set_rounding_mode (original_rounding_mode);
return (total);
}

| 000000 PDEF Add_GST_and_Ontario_PST_d32
>> 0| PROC price,fp1
0| 000000 stw 93E1FFFC 1 ST4A #stack(gr1,-4)=gr31
0| 000004 stw 93C1FFF8 1 ST4A #stack(gr1,-8)=gr30
0| 000008 stwu 9421FF80 1 ST4U gr1,#stack(gr1,-128)=gr1
0| 00000C lwz 83C20004 1 L4A gr30=.+CONSTANT_AREA(gr2,0)
0| 000010 addi 38A00050 1 LI gr5=80
0| 000014 ori 60A30000 1 LR gr3=gr5
>> 0| 000018 stfiwx 7C211FAE 1 STDFS price(gr1,gr3,0)=fp1
9| 00001C mffs FC00048E 1 LFFSCR fp0=fcr
9| 000020 stfd D8010058 1 STFL #MX_SET1(gr1,88)=fp0
9| 000024 lwz 80010058 1 L4A gr0=#MX_SET1(gr1,88)
9| 000028 rlwinm 5400077E 1 RN4 gr0=gr0,0,0x7
9| 00002C stw 9001004C 1 ST4A original_rounding_mode(gr1,76)=gr0
10| 000030 mtfsfi FF81410C 1 SETDRND fcr=4,fcr
11| 000034 ori 60A30000 1 LR gr3=gr5
11| 000038 lfiwax 7C011EAE 1 LDFS fp0=price(gr1,gr3,0)
11| 00003C dctdp EC000204 1 CVDSDL fp0=fp0,fcr
11| 000040 lfd C83E0000 1 LDFL fp1=+CONSTANT_AREA(gr30,0)
11| 000044 dmul EC000844 1 MDFL fp0=fp0,fp1,fcr
11| 000048 drsp EC000604 1 CVDLDS fp0=fp0,fcr
11| 00004C addi 38600040 1 LI gr3=64
11| 000050 ori 60640000 1 LR gr4=gr3
11| 000054 stfiwx 7C0127AE 1 STDFS gst(gr1,gr4,0)=fp0
12| 000058 ori 60A40000 1 LR gr4=gr5
12| 00005C lfiwax 7C0126AE 1 LDFS fp0=price(gr1,gr4,0)
12| 000060 dctdp EC000204 1 CVDSDL fp0=fp0,fcr
12| 000064 lfd C83E0008 1 LDFL fp1=+CONSTANT_AREA(gr30,8)
12| 000068 dmul EC000844 1 MDFL fp0=fp0,fp1,fcr
12| 00006C drsp EC000604 1 CVDLDS fp0=fp0,fcr
12| 000070 addi 38800044 1 LI gr4=68
12| 000074 ori 60860000 1 LR gr6=gr4
12| 000078 stfiwx 7C0137AE 1 STDFS pst(gr1,gr6,0)=fp0
13| 00007C lfiwax 7C012EAE 1 LDFS fp0=price(gr1,gr5,0)
13| 000080 lfiwax 7C211EAE 1 LDFS fp1=gst(gr1,gr3,0)
13| 000084 dctdp EC000204 1 CVDSDL fp0=fp0,fcr
13| 000088 dctdp EC200A04 1 CVDSDL fp1=fp1,fcr
13| 00008C mffs FC40048E 1 LFFSCR fp2=fcr
13| 000090 stfd D8410058 1 STFL #MX_SET1(gr1,88)=fp2
13| 000094 lwz 80010058 1 L4A gr0=#MX_SET1(gr1,88)
13| 000098 rlwinm 5400077E 1 RN4 gr0=gr0,0,0x7
13| 00009C mtfsfi FF81710C 1 SETDRND fcr=7,fcr
13| 0000A0 dadd EC000804 1 ADFL fp0=fp0,fp1,fcr
13| 0000A4 stw 90010058 1 ST4A #MX_SET1(gr1,88)=gr0
13| 0000A8 lfd C8210058 1 LFL fp1=#MX_SET1(gr1,88)
13| 0000AC mtfsf FC030D8E 1 LFSCR8 fsr,fcr=fp1,1,1
13| 0000B0 addi 38000007 1 LI gr0=7
13| 0000B4 addi 38600000 1 LI gr3=0
13| 0000B8 stw 90610068 1 ST4A #MX_CONVF1_0(gr1,104)=gr3
13| 0000BC stw 9001006C 1 ST4A #MX_CONVF1_0(gr1,108)=gr0
13| 0000C0 lfd C8210068 1 LDFL fp1=#MX_CONVF1_0(gr1,104)
13| 0000C4 drrnd EC010646 1 RRDFL fp0=fp0,fp1,3,fcr
13| 0000C8 drsp EC000604 1 CVDLDS fp0=fp0,fcr
13| 0000CC lfiwax 7C2126AE 1 LDFS fp1=pst(gr1,gr4,0)
13| 0000D0 dctdp EC000204 1 CVDSDL fp0=fp0,fcr
13| 0000D4 dctdp EC200A04 1 CVDSDL fp1=fp1,fcr
13| 0000D8 mffs FC40048E 1 LFFSCR fp2=fcr
13| 0000DC stfd D8410058 1 STFL #MX_SET1(gr1,88)=fp2
13| 0000E0 lwz 80810058 1 L4A gr4=#MX_SET1(gr1,88)
13| 0000E4 rlwinm 5484077E 1 RN4 gr4=gr4,0,0x7
13| 0000E8 mtfsfi FF81710C 1 SETDRND fcr=7,fcr
13| 0000EC dadd EC000804 1 ADFL fp0=fp0,fp1,fcr
13| 0000F0 stw 90810058 1 ST4A #MX_SET1(gr1,88)=gr4
13| 0000F4 lfd C8210058 1 LFL fp1=#MX_SET1(gr1,88)
13| 0000F8 mtfsf FC030D8E 1 LFSCR8 fsr,fcr=fp1,1,1
13| 0000FC stw 90610068 1 ST4A #MX_CONVF1_0(gr1,104)=gr3
13| 000100 stw 9001006C 1 ST4A #MX_CONVF1_0(gr1,108)=gr0
13| 000104 lfd C8210068 1 LDFL fp1=#MX_CONVF1_0(gr1,104)
13| 000108 drrnd EC010646 1 RRDFL fp0=fp0,fp1,3,fcr
13| 00010C drsp EC000604 1 CVDLDS fp0=fp0,fcr
13| 000110 addi 38600048 1 LI gr3=72
13| 000114 ori 60640000 1 LR gr4=gr3
13| 000118 stfiwx 7C0127AE 1 STDFS total(gr1,gr4,0)=fp0
14| 00011C lwz 8001004C 1 L4A gr0=original_rounding_mode(gr1,76)
14| 000120 stw 90010058 1 ST4A #MX_SET1(gr1,88)=gr0
14| 000124 lfd C8010058 1 LFL fp0=#MX_SET1(gr1,88)
14| 000128 mtfsf FC03058E 1 LFSCR8 fsr,fcr=fp0,1,1
>> 15| 00012C lfiwax 7C211EAE 1 LDFS fp1=total(gr1,gr3,0)
16| CL.1:
16| 000130 lwz 83C10078 1 L4A gr30=#stack(gr1,120)
16| 000134 addi 38210080 1 AI gr1=gr1,128
16| 000138 bclr 4E800020 1 BA lr
Ejemplo de convenio de llamada para el tipo de coma flotante decimal (_Decimal64)

#include <float.h>
#define DFP_ROUND_HALF_UP 4

_Decimal64 Add_GST_and_Ontario_PST_d64 (_Decimal64 price)
{
_Decimal64 gst;
_Decimal64 pst;
_Decimal64 total;
long original_rounding_mode = __dfp_get_rounding_mode ( );
__dfp_set_rounding_mode (DFP_ROUND_HALF_UP);
gst = price * 0.06dd;
pst = price * 0.08dd;
total = price + gst + pst;
__dfp_set_rounding_mode (original_rounding_mode);
return (total);
}

| 000000 PDEF Add_GST_and_Ontario_PST_d64
>> 0| PROC price,fp1
0| 000000 stw 93E1FFFC 1 ST4A #stack(gr1,-4)=gr31
0| 000004 stw 93C1FFF8 1 ST4A #stack(gr1,-8)=gr30
0| 000008 stwu 9421FF80 1 ST4U gr1,#stack(gr1,-128)=gr1
0| 00000C lwz 83C20004 1 L4A gr30=.+CONSTANT_AREA(gr2,0)
>> 0| 000010 stfd D8210098 1 STDFL price(gr1,152)=fp1
9| 000014 mffs FC00048E 1 LFFSCR fp0=fcr
9| 000018 stfd D8010060 1 STFL #MX_SET1(gr1,96)=fp0
9| 00001C lwz 80010060 1 L4A gr0=#MX_SET1(gr1,96)
9| 000020 rlwinm 5400077E 1 RN4 gr0=gr0,0,0x7
9| 000024 stw 90010058 1 ST4A original_rounding_mode(gr1,88)=gr0
10| 000028 mtfsfi FF81410C 1 SETDRND fcr=4,fcr
11| 00002C lfd C8010098 1 LDFL fp0=price(gr1,152)
11| 000030 lfd C83E0000 1 LDFL fp1=+CONSTANT_AREA(gr30,0)
11| 000034 dmul EC000844 1 MDFL fp0=fp0,fp1,fcr
11| 000038 stfd D8010040 1 STDFL gst(gr1,64)=fp0
12| 00003C lfd C8010098 1 LDFL fp0=price(gr1,152)
12| 000040 lfd C83E0008 1 LDFL fp1=+CONSTANT_AREA(gr30,8)
12| 000044 dmul EC000844 1 MDFL fp0=fp0,fp1,fcr
12| 000048 stfd D8010048 1 STDFL pst(gr1,72)=fp0
13| 00004C lfd C8010098 1 LDFL fp0=price(gr1,152)
13| 000050 lfd C8210040 1 LDFL fp1=gst(gr1,64)
13| 000054 dadd EC000804 1 ADFL fp0=fp0,fp1,fcr
13| 000058 lfd C8210048 1 LDFL fp1=pst(gr1,72)
13| 00005C dadd EC000804 1 ADFL fp0=fp0,fp1,fcr
13| 000060 stfd D8010050 1 STDFL total(gr1,80)=fp0
14| 000064 lwz 80010058 1 L4A gr0=original_rounding_mode(gr1,88)
14| 000068 stw 90010060 1 ST4A #MX_SET1(gr1,96)=gr0
14| 00006C lfd C8010060 1 LFL fp0=#MX_SET1(gr1,96)
14| 000070 mtfsf FC03058E 1 LFSCR8 fsr,fcr=fp0,1,1
>> 15| 000074 lfd C8210050 1 LDFL fp1=total(gr1,80)
16| CL.1:
16| 000078 lwz 83C10078 1 L4A gr30=#stack(gr1,120)
16| 00007C addi 38210080 1 AI gr1=gr1,128
16| 000080 bclr 4E800020 1 BA lr
Ejemplo de convenio de llamada para el tipo de coma flotante decimal (_Decimal128)

include <float.h>
#define DFP_ROUND_HALF_UP 4

_Decimal128 Add_GST_and_Ontario_PST_d128 (_Decimal128 price)
{
_Decimal128 gst;
_Decimal128 pst;
_Decimal128 total;
long original_rounding_mode = __dfp_get_rounding_mode ( );
__dfp_set_rounding_mode (DFP_ROUND_HALF_UP);
gst = price * 0.06dd;
pst = price * 0.08dd;
total = price + gst + pst;
__dfp_set_rounding_mode (original_rounding_mode);
return (total);
}

| 000000 PDEF Add_GST_and_Ontario_PST_d128
>> 0| PROC price,fp2,fp3
0| 000000 stw 93E1FFFC 1 ST4A #stack(gr1,-4)=gr31
0| 000004 stw 93C1FFF8 1 ST4A #stack(gr1,-8)=gr30
0| 000008 stwu 9421FF70 1 ST4U gr1,#stack(gr1,-144)=gr1
0| 00000C lwz 83C20004 1 L4A gr30=.+CONSTANT_AREA(gr2,0)
>> 0| 000010 stfd D84100A8 1 STDFL price(gr1,168)=fp2
>> 0| 000014 stfd D86100B0 1 STDFL price(gr1,176)=fp3
9| 000018 mffs FC00048E 1 LFFSCR fp0=fcr
9| 00001C stfd D8010078 1 STFL #MX_SET1(gr1,120)=fp0
9| 000020 lwz 80010078 1 L4A gr0=#MX_SET1(gr1,120)
9| 000024 rlwinm 5400077E 1 RN4 gr0=gr0,0,0x7
9| 000028 stw 90010070 1 ST4A original_rounding_mode(gr1,112)=gr0
10| 00002C mtfsfi FF81410C 1 SETDRND fcr=4,fcr
11| 000030 lfd C80100A8 1 LDFL fp0=price(gr1,168)
11| 000034 lfd C82100B0 1 LDFL fp1=price(gr1,176)
11| 000038 lfd C85E0000 1 LDFL fp2=+CONSTANT_AREA(gr30,0)
11| 00003C lfd C87E0008 1 LDFL fp3=+CONSTANT_AREA(gr30,8)
11| 000040 dmulq FC001044 1 MDFE fp0,fp1=fp0-fp3,fcr
11| 000044 stfdp F4010040 1 STDFE gst(gr1,64)=fp0,fp1
12| 000048 lfd C80100A8 1 LDFL fp0=price(gr1,168)
12| 00004C lfd C82100B0 1 LDFL fp1=price(gr1,176)
12| 000050 lfd C85E0010 1 LDFL fp2=+CONSTANT_AREA(gr30,16)
12| 000054 lfd C87E0018 1 LDFL fp3=+CONSTANT_AREA(gr30,24)
12| 000058 dmulq FC001044 1 MDFE fp0,fp1=fp0-fp3,fcr
12| 00005C stfdp F4010050 1 STDFE pst(gr1,80)=fp0,fp1
13| 000060 lfd C80100A8 1 LDFL fp0=price(gr1,168)
13| 000064 lfd C82100B0 1 LDFL fp1=price(gr1,176)
13| 000068 lfd C8410040 1 LDFL fp2=gst(gr1,64)
13| 00006C lfd C8610048 1 LDFL fp3=gst(gr1,72)
13| 000070 daddq FC001004 1 ADFE fp0,fp1=fp0-fp3,fcr
13| 000074 lfd C8410050 1 LDFL fp2=pst(gr1,80)
13| 000078 lfd C8610058 1 LDFL fp3=pst(gr1,88)
13| 00007C daddq FC001004 1 ADFE fp0,fp1=fp0-fp3,fcr
13| 000080 stfdp F4010060 1 STDFE total(gr1,96)=fp0,fp1
14| 000084 lwz 80010070 1 L4A gr0=original_rounding_mode(gr1,112)
14| 000088 stw 90010078 1 ST4A #MX_SET1(gr1,120)=gr0
14| 00008C lfd C8010078 1 LFL fp0=#MX_SET1(gr1,120)
14| 000090 mtfsf FC03058E 1 LFSCR8 fsr,fcr=fp0,1,1
>> 15| 000094 lfd C8410060 1 LDFL fp2=total(gr1,96)
>> 15| 000098 lfd C8610068 1 LDFL fp3=total(gr1,104)
16| CL.1:
16| 00009C lwz 83C10088 1 L4A gr30=#stack(gr1,136)
16| 0000A0 addi 38210090 1 AI gr1=gr1,144
16| 0000A4 bclr 4E800020 1 BA lr