注册使用和约定

PowerPC® 32 位体系结构具有 32 个 GPRS 和 32 个 FPR。

PowerPC® 32 位体系结构具有 32 个 GPRS 和 32 个 FPR。 每个 GPR 为 32 位宽,每个 FPR 为 64 位宽。 另外,还存在用于分支,异常处理和其他目的的专用寄存器。 "通用注册公约" 表显示了如何使用 GPR。

表 1. 普通用途注册公约
寄存器 状态 使用
GPR0 volatile 在函数 prolog 中。
GPR1 专用 堆栈指针。
GPR2 专用 "目录" (TOC) 指针。
GPR3 volatile 函数的自变量列表的第一个词; 标量函数的第一个词返回。
GPR4 volatile 函数的自变量列表的第二个词; 标量函数的第二个词返回。
GPR5 volatile 函数的自变量列表的第三个词。
GPR6 volatile 函数的自变量列表的第四个词。
GPR7 volatile 函数的参数列表的第五个字。
GPR8 volatile 函数的自变量列表的第六个词。
GPR9 volatile 函数的自变量列表的第七个单词。
GPR10 volatile 函数的自变量列表的第八个单词。
GPR11 volatile 在指针调用中,作为需要它的语言 (例如, PACAL) 的环境指针。
GPR12 volatile 对于某些语言和 格连克 代码所需要的特殊异常处理。
GPR13 保留的 在 64 位环境下保留; 未在系统调用之间复原。
GPR14:GPR31 非易失性 必须在函数调用中保留这些寄存器。

使用 GPR 的首选方法是先使用易失性寄存器。 接下来,从 GPR31开始,按降序使用非易失性寄存器。 GPR1 和 GPR2 必须分别作为堆栈和目录 (TOC) 区域指针来专用。 GPR1 和 GPR2 必须显示为通过调用进行保存,并且在返回时必须具有与进行调用时相同的值。

易失性寄存器 (Volatile register) 是临时寄存器,被认为是在呼叫过程中被破坏的,因此不会被被被呼叫方保存。 易失性寄存器也用于特定用途,如上表中所示。 如果更改了非易失性寄存器和专用寄存器,那么它们需要保存和恢复,从而保证在函数调用中保留它们的值。

"浮点寄存器约定" 表显示了如何使用 FPR。

表 2. 浮点型寄存器约定
寄存器 状态 使用
FPR0 volatile 作为临时寄存器。
FPR1 volatile 第一个浮点参数; 浮点标量返回的前 8 个字节。
FPR2 volatile 第二个浮点参数; 浮点标量 8 的第二个 8 字节。
FPR3 volatile 第三个浮点参数; 浮点标量返回的第三个 8 字节。
FPR4 volatile 第四个浮点参数; 浮点标量返回的第四个 8 字节。
FPR5 volatile 第五个浮点参数。
FPR6 volatile 第六个浮点参数。
FPR7 volatile 第七个浮点参数。
FPR8 volatile 第八个浮点参数。
FPR9 volatile 第九个浮点参数。
FPR10 volatile 第十个浮点参数。
FPR11 volatile 第十一个浮点参数。
FPR12 volatile 第十二个浮点参数。
FPR13 volatile 第十三个浮点参数。
FPR14:FPR31 非易失性 如果已修改,那么必须在整个调用中保留。

使用 FPR 的首选方法是首先使用易失性寄存器。 接下来,将按降序使用非易失性寄存器,从 FPR31 开始,向下继续到 FPR14。

在多个寄存器中仅返回黄牛。 所需要的寄存器数取决于标量的大小和类型。 对于浮点值,将出现以下结果:

  • 128 位浮点值在 FPR1 中返回高阶 64 位,在 FPR2中返回低阶 64 位。
  • 8 个字节或 16 个字节的复杂值将返回 FPR1 中的实部分,并返回 FPR2中的虚部分。
  • 32 个字节的复杂值在 FPR1 和 FPR2中以 128 位浮点值形式返回实际部分,在 FPR1 中返回高阶 64 位,在 FPR2中返回低阶 64 位。 32 个字节的复数值的虚部分返回 FPR3 中的高位 64 位和 FPR4中的低位 64 位。

针对复杂类型调用约定的示例


complex double foo(complex double);
参数将传递到 fp1 和 fp2 ,结果将在 fp1 和 fp2中返回。 通过使用奇数对或奇数对,在接下来的两个可用寄存器中传递后续复杂双精度参数,最多可达 fp13个。 在 fp13 之后,它们将在位于调用者堆栈帧开头的内存中的参数区域中传递。
注: 跳过的寄存器不用于稍后的参数。 此外,这些寄存器不是由调用程序初始化的,并且被调用函数不能依赖于存储在跳过的寄存器中的值。

单精度复合体 (复杂浮点) 的传递方式与双精度的传递方式相同,并且值加宽为双精度。

在 fp1 和 fp2 中返回双精度和单精度复合体 (复杂双精度和复杂浮点) ,并将单精度值加宽到双精度。

在接下来的四个可用的寄存器中,从 fp1 传递到 fp13 ,然后在参数区域中传递四倍精度复杂 (复杂长整型双精度) 参数。 寄存器填充的顺序为: 实部的上半部分,实部的下半部分,虚部的上半部分以及虚部的下半部分。
注: 在 AIX 结构中,类和并集在 gprs (或内存) 而不是 fprs 中传递。 即使类和并集包含浮点值,也会如此。 在 PPC 上的 Linux 中,内存中副本的地址将在下一个可用的 gpr (或内存中) 中传递。 varargs 参数是专门处理的,通常同时传递给 fprs 和 gprs。

十进制浮点类型的调用约定 (_Decimal128)

_Decimal64 参数在下一个可用 fpr 中传递,结果在 fp1中返回。

_Decimal32 参数在下一个可用 fpr 的下半部分中传递,结果在 fp1的下半部分返回,而不会转换为 _Decimal64。

_Decimal128 参数将在下一个可用的双奇数 fpr 对 (或内存) 中传递,即使这意味着跳过寄存器并且在双奇数对 fpr2 和 fpr3中返回结果也是如此。 原因是所有算术指令都需要使用偶数-奇数寄存器对。
注: 跳过的寄存器不用于稍后的参数。 此外,这些寄存器不是由调用程序初始化的,并且被调用函数不能依赖于存储在跳过的寄存器中的值。

与浮点型或双精度型不同,对于 DFP ,始终需要函数原型。 因此,不需要将 _Decimal32 拓宽到 _Decinmal64。

对十进制浮点类型 (_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
对十进制浮点类型 (_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
对十进制浮点类型 (_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