Next: , Previous: Constraints, Up: Machine Desc


16.9 用于生成的标准指令模式名

这里有一个在编译器的RTL生成过程中有意义的指令名称表,在指令模式中给定这些名字中的一个,则告诉RTL生成过程,其可以使用该指令模式来完成一个特定的任务。

movm
这里m表示一个两字母的机器模式名字,小写。该指令模式将那种机器模式的数据从操作数1移送到操作数0。例如‘movsi’移送整字数据。

如果操作数0为一个寄存器的subreg,机器模式为m,寄存器自己的机器模式比m更宽,则该指令的效果是将指定的值存储在寄存器的对应于机器模式m的部分。m之外,且与subreg在同一个目标字中的位,为未定义。目标字以外的位保持不变。

这类指令模式有几处特别的地方。首先,每个这些直到整字大小的名字,包括整字大小的,必须被定义,因为没有其它方式来从一个地方将数据复制到另一个地方。如果有接受更大机器模式的操作数的指令模式,则必须为那些大小的整数机器模式定义‘movm’。

第二,这些指令模式不仅用在RTL生成过程。甚至重载过程可以生成move insn将值从栈槽复制到临时寄存器中。当这样的时候,其中一个操作数为硬件寄存器,另一个为需要被重载到寄存器中的操作数。

因此,当给定这样一对操作数时,指令模式必须生成不需要重载,并且不需要临时寄存器的RTL。例如,如果你使用一个define_expand来支持该指令模式,则这种情况下,define_expand一定不能调用force_reg或者任何其它可能生成新的伪寄存器的函数。

甚至对于在RISC机器上的子字机器模式,从内存中获取这些机器模式通常需要多个insn和一些临时变量,该要求也存在。

重载过程中,具有无效地址的内存引用可以被作为操作数。这样的地址将在重载过程的后面被替换成有效地址。这种情况下,可能对地址没有做任何事情,而只是使用它。如果其被复制,则将无法使用有效的地址进行替换。不要尝试将这样的地址变成有效的地址。注意,general_operand当应用到这样的地址的时候将会失败。

全局变量reload_in_progress(其必须被显式的声明)可以用来确定是否需要这样的特殊的处理。

需要进行重载的操作数的种类取决于机器描述的其余部分,不过通常在RISC机器上,只有那些没有获得硬件寄存器的伪寄存器,而在其它机器上,显式的内存引用也有可能需要进行重载。

如果一个scratch寄存器,被需要用来将一个对象与内存之间进行移送,则其可以活跃分析之前,使用gen_reg_rtx来进行分配。

如果在重载过程中,或者之后,有需要scratch寄存器的情况,则你必须提供一个适当的secondary_reload目标钩子。

can_create_pseudo_p可以用来确定创建一个新的伪寄存器是否不安全。如果该变量为非零,则调用gen_reg_rtx来分配一个新的伪寄存器是不安全的。

movm’上的约束必须允许将任何硬件寄存器移送到任何其它硬件寄存器上,假设HARD_REGNO_MODE_OK在两个寄存器上都允许机器模式m,并且REGISTER_MOVE_COST应用到它们的类别上返回值2。

必须提供浮点‘movm’指令,用于任何可以存放定点值的寄存器,因为联合体和结构体(具有机器模式SImodeDImode)可以在那些寄存器中,并且它们可以具有浮点成员。

还需要支持定点‘movm’指令,用于浮点寄存器。不幸的是,我忘了为什么要这样,并且不知道这是否还是真的。如果HARD_REGNO_MODE_OK排斥在浮点寄存器中的定点值,则定点‘movm’指令的约束必须被设计成,避免尝试重载到一个浮点寄存器。


reload_inm
reload_outm
这些命名指令模式已经被目标钩子secondary_reload废弃。

类似‘movm’,不过用于当需要使用scratch寄存器在操作数0和操作数1之间移送的时候。操作数2描述scratch寄存器。参见Register Classes中对SECONDARY_RELOAD_CLASS宏的讨论。

这些指令模式中的match_operand的形式,有一些特殊的限制。首先,只有重载操作数的断言才被检查,即reload_in检查操作数1,而不检查操作数0和2。第二,在约束中只能有一个可选项。第三,约束只能使用单个寄存器类别字母;后续的约束字母都被忽略。一个例外是,空的约束字符串匹配ALL_REGS寄存器类别。这可以减轻后端为这些指令模式定义ALL_REGS约束字母的负担。


movstrictm
类似‘movm’,只不过,如果操作数0为一个寄存器的机器模式为msubreg,且寄存器的自然机器模式是较宽的,则‘movstrictm’指令保证不会修改属于机器模式m之外的寄存器的任何部分。


movmisalignm
该move指令模式的变体,被设计为从没有与其机器模式自然对齐的内存地址中加载和存储值。对于存储,内存将在操作数0中;对于加载,内存将在操作数1中。其它操作数保证不为内存,所以容易判别是加载还是存储。

该指令模式用于向量化,当展开MISALIGNED_INDIRECT_REF表达式的时候。


load_multiple
将多个连续的内存位置加载到连续的寄存器中。操作数0为连续寄存器中的第一个,操作数1为第一个内存位置,操作数2为一个常量:连续寄存器的数目。

只有当目标机器确实具有这样指令的时候才定义该指令模式;如果将内存加载到连续寄存器的最有效的方式,是每次加载一个,则 不用定义该指令模式。

在一些机器上,对于哪些连续寄存器可以存储到内存中,会有一些限制,例如特定的起始寄存器或者结尾寄存器的编号,或者一个有效范围。对于那些机器,使用define_expand (参见Expander Definitions),并当不符合限制的时候,将指令模式变成失败。

将生成的insn写成一个parallel,其元素为一个从适当内存位置到寄存器的set(可能还需要use或元素clobber)。使用match_parallel (参见RTL Template)来识别insn。关于使用该insn模式的例子,可以参见rs6000.md


store_multiple
类似于‘load_multiple’,不过是将多个连续的寄存器存储到连续的内存位置。操作数0为连续内存位置的第一个,操作数1为第一个寄存器,操作数2为常量:连续寄存器的数目。


vec_setm
设置向量中给定的域。操作数0为要修改的向量,操作数1为域的新值,操作数2指定了域的索引。


vec_extractm
从向量中抽取给定的域。操作数1为向量,操作数2指定了域索引,操作数0为存放值的地方。


vec_extract_evenm
从输入向量(操作数1和2)中,抽取偶数元素。操作数2的偶数元素按照它们原来的顺序,连结到操作数1的偶数元素后面。结果存储在操作数0中。输出和输入向量应该具有相同的模式。


vec_extract_oddm
从输入向量(操作数1和2)中,抽取奇数元素。操作数2的奇数元素按照它们原来的顺序,连结到操作数1的奇数元素后面。结果存储在操作数0中。输出和输入向量应该具有相同的模式。


vec_interleave_highm
将两个输入向量的高部分元素合并到输入向量中。输出和输入向量应该具有相同的模式(N个元素)。第一个输入向量的高N/2个元素被第二个输入向量的高N/2个元素交错的插入。


vec_interleave_lowm
将两个输入向量的低部分元素合并到输入向量中。输出和输入向量应该具有相同的模式(N个元素)。第一个输入向量的低N/2个元素被第二个输入向量的低N/2个元素交错的插入。


vec_initm
将向量初始化为给定的值。操作数0为要初始化的向量,操作数1并行的包含每个域的值。


pushm1
输出一个push指令。操作数0是压栈的值。只有当PUSH_ROUNDING被定义时,才被使用。出于历史原因,该指令模式可以缺失,这种情况下使用mov扩展来替代,并用MEM表达式来形成压栈运算。mov扩展方法不被推荐。


addm3
操作数2加上操作数1,将结果存储在操作数0中。所有操作数必须具有机器模式m。这也可以用于两地址机器上,通过约束来要求操作数1和0为相同的位置。


ssaddm3’, ‘usaddm3
subm3’, ‘sssubm3’, ‘ussubm3
mulm3’, ‘ssmulm3’, ‘usmulm3
divm3’, ‘ssdivm3
udivm3’, ‘usdivm3
modm3’, ‘umodm3
uminm3’, ‘umaxm3
andm3’, ‘iorm3’, ‘xorm3
类似的,用于其它算术运算。


sminm3’, ‘smaxm3
有符号的最小值和最大值运算。当用于浮点,如果两个操作数都为零,或者有一个为NaN,则没有明确指定哪个操作数作为结果返回。


reduc_smin_m’, ‘reduc_smax_m
查找向量的有符号最小/最大元素。向量为操作数1,标量结果存放在操作数0(也是一个向量)的最小有效位。输出和输入向量应该具有相同的模式。


reduc_umin_m’, ‘reduc_umax_m
查找向量的无符号最小/最大元素。向量为操作数1,标量结果存放在操作数0(也是一个向量)的最小有效位。输出和输入向量应该具有相同的模式。


reduc_splus_m
计算向量的有符号元素的和。向量为操作数1,标量结果存放在操作数0(也是一个向量)的最小有效位。输出和输入向量应该具有相同的模式。


reduc_uplus_m
计算向量的无符号元素的和。向量为操作数1,标量结果存放在操作数0(也是一个向量)的最小有效位。输出和输入向量应该具有相同的模式。


sdot_prodm

udot_prodm
计算两个有符号/无符号元素乘积的和。操作数1和2为相同的模式。它们的乘积,为一个宽的模式,被计算并增加到操作数3上。操作数3的机器模式等于或宽于乘积的机器模式。结果被放在操作数0上,其与操作数3具有相同的机器模式。


ssum_widenm3

usum_widenm3
操作数0和2具有相同的机器模式,其比操作数1的宽。将操作数1加上操作数2,并将加宽的结果放在操作数0中。(这用于表示元素累加到一个更宽模式的累加器中)


vec_shl_m’, ‘vec_shr_m
整个向量向左/向右移位。操作数1为被移位的向量。操作数2为移位的位数。操作数0为移位后的结果向量被存储的地方。输出和输入向量应该具有相同的模式。


vec_pack_trunc_m
变窄(降级)并合并两个向量的元素。操作数1和2为具有相同机器模式,N个,大小为S的整数或者浮点元素的向量。操作数0为结果向量,通过使用截取的方式,将它们变窄并连接成,2×N个大小为N/2的元素。


vec_pack_ssat_m’, ‘vec_pack_usat_m
变窄(降级)并合并两个向量的元素。操作数1和2为具有相同机器模式,N个,大小为S的整数元素的向量。操作数0为结果向量,通过使用有符号/无符号饱和算术的方式,将它们变窄并连接成。


vec_pack_sfix_trunc_m’, ‘vec_pack_ufix_trunc_m
将两个向量的元素变窄,转成有符号/无符号整数类型并合并。操作数1和2为具有相同机器模式,N个,大小为S的浮点元素的向量。操作数0为结果向量,由2×N个大小为N/2的元素连接而成。


vec_unpacks_hi_m’, ‘vec_unpacks_lo_m
抽取并变宽(提升),具有有符号整数或浮点元素的,向量的高/低部分。输入向量(操作数1)具有N个大小为S的元素。使用有符号或者浮点扩展,将向量的高/低元素进行变宽(提升),并将结果,N/2个大小为2*S的值,放在输出向量(操作数0)中。


vec_unpacku_hi_m’, ‘vec_unpacku_lo_m
抽取并变宽(提升),具有无符号整数元素的,向量的高/低部分。输入向量(操作数1)具有N个大小为S的元素。使用零扩展,将向量的高/低元素进行变宽(提升),并将结果,N/2个大小为2*S的值,放在输出向量(操作数0)中。


vec_unpacks_float_hi_m’, ‘vec_unpacks_float_lo_m
vec_unpacku_float_hi_m’, ‘vec_unpacku_float_lo_m
抽取具有有符号/无符号整数元素的,向量的高/低部分,并转换成浮点类型。输入向量(操作数1)具有N个大小为S的元素。使用浮点转换,将向量的高/低元素进行转换,并将结果,N/2个大小为2*S的值,放在输出向量(操作数0)中。


vec_widen_umult_hi_m’, ‘vec_widen_umult_lo_m
vec_widen_smult_hi_m’, ‘vec_widen_smult_lo_m
有符号/无符号加宽乘法。两个输入(操作数1和2)为,N个大小为S的有符号/无符号元素的向量。将两个向量的高/低元素相乘,并将N/2个大小为2×S的乘积放在输出向量(操作数0)中。


mulhisi3
机器模式为HImode的操作数1和2相乘,并将SImode乘积放在操作数0中。


mulqihi3’, ‘mulsidi3
类似的其它宽度的加宽乘法指令。


umulqihi3’, ‘umulhisi3’, ‘umulsidi3
类似的加宽乘法指令,进行无符号乘法。


usmulqihi3’, ‘usmulhisi3’, ‘usmulsidi3
类似的加宽乘法指令,将第一个操作数解析为无符号的,第二个为有符号的,然后进行有符号乘法。


smulm3_highpart
对机器模式为m的操作数1和2进行有符号乘法,并将乘积的最高有效的一半放在操作数0中。乘积的最低有效的一半被丢弃。


umulm3_highpart
类似的,只不过乘法是无符号的。


maddmn4
将操作数1和2进行相乘,有符号扩展成机器模式n,加上操作数3,并将结果存放在操作数0中。操作数1和2具有机器模式m,操作数0和3具有机器模式n。两种机器模式必须都为整数或者浮点模式,并且n必须为m的两倍大小。

换句话说,maddmn4类似于mulmn3,只不过其还加上操作数3。

这些指令不允许执行FAIL


umaddmn4
类似maddmn4,只不过零扩展乘法操作数,而不是有符号扩展它们。


ssmaddmn4
类似maddmn4,不过所有的运算都必须是有符号饱和的。


usmaddmn4
类似umaddmn4,不过所有的运算都必须是无符号饱和的。


msubmn4
将操作数1和2相乘,有符号扩展为机器模式n,减去操作数3,并将结果存放在操作数0中。操作数1和2具有机器模式m,操作数0和3具有机器模式n。两种机器模式必须都为整数或者浮点模式,并且n必须为m的两倍大小。

换句话说,msubmn4类似于mulmn3,只不过其还减去操作数3。

这些指令不允许执行FAIL


umsubmn4
类似msubmn4,不过零扩展乘法操作数,而不是有符号扩展它们。


ssmsubmn4
类似msubmn4,不过所有的运算都必须是有符号饱和的。


usmsubmn4
类似umsubmn4,不过所有的运算都必须是无符号饱和的。


divmodm4
有符号除法,同时产生商和余数。操作数1被操作数2除,产生商存储在操作数0中,余数存储在操作数3中。

对于具有同时产生商和余数的指令的机器,提供‘divmodm4’指令模式,但不要提供‘divm3’ 和 ‘modm3’。这使得当商和余数都被计算的时候,可以优化成相对常见的情况。

如果存在只产生商或者余数的指令,并且比都产生的指令更有效,则将‘divmodm4’的输出例程写成调用find_reg_note,查看商或者余数的REG_UNUSED注解,来产生适当的指令。


udivmodm4
类似的,不过进行无符号除法。


ashlm3’, ‘ssashlm3’, ‘usashlm3
将操作数1向左算术移位,左移位数由操作数2指定,将结果存储在操作数0中。这里m为操作数0和1的机器模式;操作数2的机器模式通过指令模式来指定,编译器会在生成指令之前,将操作数转换成该模式。超出范围的移位数目的含义,可以通过TARGET_SHIFT_TRUNCATION_MASK来指定。参见TARGET_SHIFT_TRUNCATION_MASK. 操作数2总是一个标量类型。


ashrm3’, ‘lshrm3’, ‘rotlm3’, ‘rotrm3
其它移位或者旋转指令,类似于ashlm3指令。操作数2总是一个标量类型。


vashlm3’, ‘vashrm3’, ‘vlshrm3’, ‘vrotlm3’, ‘vrotrm3
向量移位和旋转指令,操作数2为向量,而不是标量类型。


negm2’, ‘ssnegm2’, ‘usnegm2
对操作数1求负,并将结果存放在操作数0中。


absm2
将操作数1的绝对值存放在操作数0中。


sqrtm2
将操作数1的平方根存储在操作数0中。

sqrt内建C函数,总是使用对应于C数据类型double的机器模式,sqrtf内建函数使用对应于C数据类型float的机器模式。


fmodm3
将操作数1除以操作数2的余数,存储在操作数0中,并向零方向舍入为整数。

fmod内建C函数总是使用对应于C数据类型double的机器模式,fmodf内建函数使用对应于C数据类型float的机器模式。


remainderm3
将操作数1除以操作数2的余数,存储在操作数0中,并舍入为最接近的整数。

remainder内建C函数总是使用对应于C数据类型double的机器模式,remainderf内建函数使用对应于C数据类型float的机器模式。


cosm2
将操作数1的余弦存放在操作数0中。

cos内建C函数总是使用对应于C数据类型double的机器模式,cosf内建函数使用对应于C数据类型float的机器模式。


sinm2
将操作数1的正弦存放在操作数0中。

sin内建C函数总是使用对应于C数据类型double的机器模式,sinf内建函数使用对应于C数据类型float的机器模式。


expm2
将操作数1的幂存放在操作数0中。

exp内建C函数总是使用对应于C数据类型double的机器模式,expf内建函数使用对应于C数据类型float的机器模式。


logm2
将操作数1的自然对数存放在操作数0中。

log内建C函数总是使用对应于C数据类型double的机器模式,logf内建函数使用对应于C数据类型float的机器模式。


powm3
将操作数1的,指数为操作数2的幂值存放在操作数0中

pow内建C函数总是使用对应于C数据类型double的机器模式,powf内建函数使用对应于C数据类型float的机器模式。


atan2m3
将操作数1除以操作数2的反正切,存放在操作数0中,使用两个参数的正负符号来确定结果的商。

atan2内建C函数总是使用对应于C数据类型double的机器模式,atan2f内建函数使用对应于C数据类型float的机器模式。


floorm2
存储不大于参数的最大整数值。

floor内建C函数总是使用对应于C数据类型double的机器模式,floorf内建函数使用对应于C数据类型float的机器模式。


btruncm2
存储将参数向零方向舍入的整数。

trunc内建C函数总是使用对应于C数据类型double的机器模式,truncf内建函数使用对应于C数据类型float的机器模式。


roundm2
存储将参数向远离零的方向舍入的整数。

round内建C函数总是使用对应于C数据类型double的机器模式,roundf内建函数使用对应于C数据类型float的机器模式。


ceilm2
存储将参数向远离零的方向舍入的整数。

ceil内建C函数总是使用对应于C数据类型double的机器模式,ceilf内建函数使用对应于C数据类型float的机器模式。


nearbyintm2
将参数根据缺省的舍入模式,舍入为整数。

nearbyint内建C函数总是使用对应于C数据类型double的机器模式,nearbyintf内建函数使用对应于C数据类型float的机器模式。


rintm2
将参数根据缺省的舍入模式,舍入为整数,并且当结果与参数的值不同的时候,抛出不精确异常。

rint内建C函数总是使用对应于C数据类型double的机器模式,rintf内建函数使用对应于C数据类型float的机器模式。


lrintmn2
将操作数1(对于浮点模式m有效)转换成定点机器模式n,作为有符号数,根据当前的舍入模式,并存储在操作数0(具有机器模式n)中。


lroundm2
将操作数1(对于浮点模式m有效)转换成定点机器模式n,舍入到最近的,远离零方向的有符号数,并存储在操作数0(具有机器模式n)中。


lfloorm2
将操作数1(对于浮点模式m有效)转换成定点机器模式n,向下舍入成有符号数,并存储在操作数0(具有机器模式n)中。


lceilm2
将操作数1(对于浮点模式m有效)转换成定点机器模式n,向上舍入成有符号数,并存储在操作数0(具有机器模式n)中。


copysignm3
将操作数1的数量级和操作数的符号组成的值,存放在操作数0中。

copysign内建C函数总是使用对应于C数据类型double的机器模式,copysignf内建函数使用对应于C数据类型float的机器模式。


ffsm2
将操作数1的最小有效,置1的位的索引,加上1,存放在操作数0中。如果操作数1为零,则存储零。m为操作数0的机器模式;操作数1的机器模式由指令模式指定,编译器会在生成指令之前,将操作数转成该机器模式。

ffs内建C函数总是使用对应于C数据类型int的机器模式。


clzm2
x中,从最高有效位开始,起始处置0的位的数目,存放在操作数0中。如果x为0,则CLZ_DEFINED_VALUE_AT_ZERO (参见Misc)宏定义了结果是否为未定义或者一个有用的值。m为操作数0的机器模式;操作数1的机器模式由指令模式指定,编译器会在生成指令之前,将操作数转成该机器模式。


ctzm2
x中,从最小有效位开始,结尾处置0的位的数目,存放在操作数0中。如果x为0,则CTZ_DEFINED_VALUE_AT_ZERO (参见Misc)宏定义了结果是否为未定义或者一个有用的值。m为操作数0的机器模式;操作数1的机器模式由指令模式指定,编译器会在生成指令之前,将操作数转成该机器模式。


popcountm2
x中置1的位的数目,存放在操作数0中。m为操作数0的机器模式;操作数1的机器模式由指令模式指定,编译器会在生成指令之前,将操作数转成该机器模式。


paritym2
x的奇偶校验存放在操作数0中,即:x中置1的位数对2求模。m为操作数0的机器模式;操作数1的机器模式由指令模式指定,编译器会在生成指令之前,将操作数转成该机器模式。


one_cmplm2
对操作数1进行按位求补,并存放在操作数0中。


cmpm
比较操作数0和1,并设置条件代码。RTL指令模式应该像这样:
          (set (cc0) (compare (match_operand:m 0 ...)
                              (match_operand:m 1 ...)))


tstm
将操作数0与零进行比较,并设置条件码。RTL指令模式应该像这样:
          (set (cc0) (match_operand:m 0 ...))

tstm’指令模式不应该为不使用(cc0)的机器定义。这样做会使得编译器变得迷惑,因为其将会不清楚哪一个set操作为比较。应该使用‘cmpm’。


movmemm
块移动指令。内存的目的块和源块为前两个操作数,都为地址是Pmodemem:BLK

要移动的字节数为第三个操作数,机器模式为m。通常,你会将m指定为word_mode。然而,如果你可以生成更好的代码,知道有效长度的范围比一整个字要小,则你应该提供一个指令模式,其机器模式对应于你可以更有效的处理的值的范围(例如,QImode对于范围0–127;注意我们回避了负数),并且一个使用word_mode的指令模式。

第四个操作数为已知的源和目的的共享对齐,形式为一个const_int rtx。因此,如果编译器知道源和目的都是字对齐的,则其可以为该操作数提供值4。

可选的操作数5和6,分别指定了期望的对齐方式和块的大小。期望的对齐方式不同于操作数4中的对齐方式,块并不要求所有的情况下都按照这样对齐。期望的对齐方式也是以字节为单位,类似于操作数4。期望的大小,当不知道的时候,被设置为(const_int -1)

描述多个movmemm指令模式,只有当对于更小的机器模式的指令模式,对操作数1,2,4具有更少限制的时候,才会获利。注意movmemm中的机器模式m不对块中单独的被移动的数据单元的机器模式做任何限制。

这些指令模式不需要对源和目的可能重叠的情况,进行特殊的考虑。


movstr
字符串复制指令,具有stpcpy的语义。操作数0为输出操作数,机器模式为Pmode。目的字符串和源字符串的地址为操作数1和2,都是地址为Pmodemem:BLK。对该指令模式的执行,应该将地址存放在操作数0中,其中NUL终结符存放在目标字符串中。


setmemm
块设置指令。目的字符串为第一个操作数,作为一个mem:BLK,其地址的机器模式为Pmode。被设置的字节的数目是第二个操作数,机器模式为m。用于初始化内存的值为第三个操作数。只支持清空内存的目标机应该拒绝任何不为常数0的值。关于对机器模式选择的讨论,参见‘movmemm’。

第四个操作数为目标的已知对齐方式,形式为const_int rtx。因此,如果编译器知道目的操作数是字对齐的,则其可以为该操作数提供值4。

可选的操作数5和6,分别指定了期望的对齐方式和块的大小。期望的对齐方式不同于操作数4中的对齐方式,块并不要求所有的情况下都按照这样对齐。期望的对齐方式也是以字节为单位,类似于操作数4。期望的大小,当不知道的时候,被设置为(const_int -1)

对多个setmemm的使用,类似于movmemm


cmpstrnm
字符串比较指令,有5个操作数。操作数0为输出,机器模式为m。剩下的4个操作数类似于‘movmemm’的操作数。两个指定的内存块按字节来进行比较,按照字典顺序,从每个字符串的起始处开始。指令不允许一次取多个字节,因为每个字符串都可能在第一个字节中终止,读取后面的字节可能会访问一个无效的页或者段,并产生一个缺失。该指令的效果是将值存放在操作数0中,其符号表示了比较的结果。


cmpstrm
字符串比较指令,不知道最大的长度。操作数0为输出,机器模式为m。第二个和第三个操作数为被比较的内存块;都是机器模式为Pmodemem:BLK

第四个操作数为源和目的的已知共享的对齐方式,形式为const_int rtx。因此,如果编译器知道源和目的都是字对齐的,则其可以为该操作数提供值4。

两个指定的内存块按字节来进行比较,按照字典顺序,从每个字符串的起始处开始。指令不允许一次取多个字节,因为每个字符串都可能在第一个字节中终止,读取后面的字节可能会访问一个无效的页或者段,并产生一个缺失。该指令的效果是将值存放在操作数0中,其符号表示了比较的结果。


cmpmemm
块比较指令,这5个操作数类似于‘cmpstrm’。两个指定的内存块按字节来进行比较,按照字典顺序,从每个字符串的起始处开始。不像‘cmpstrm’,该指令可以在两个内存块中取任意个字节。该指令的效果是将值存放在操作数0中,其符号表示了比较的结果。


strlenm
计算字符串的长度,有3个操作数。操作数0为结果(机器模式为m),操作数1为一个mem,指出字符串的第一个字符,操作数2为要查找的字符(通常为零),操作数3为一个常量,描述了字符串起始处的已知对齐方式。


floatmn2
将有符号整数,操作数1(对于定点机器模式m有效),转换成浮点机器模式n,并存放在操作数0(机器模式为n)中。


floatunsmn2
将无符号整数,操作数1(对于定点机器模式m有效),转换成浮点机器模式n,并存放在操作数0(机器模式为n)中。


fixmn2
将操作数1(对于浮点机器模式m有效),转换成定点机器模式n,作为一个有符号数并存放在操作数0(机器模式为n)中。该指令的结果,只有当操作数1的值为整数时,才被定义。

如果机器描述定义了该指令模式,则其还需要定义ftrunc指令模式。


fixunsmn2
将操作数1(对于浮点机器模式m有效),转换成定点机器模式n,作为一个无符号数并存放在操作数0(机器模式为n)中。该指令的结果,只有当操作数1的值为整数时,才被定义。


ftruncm2
将操作数1(对于浮点机器模式m有效),转换成整数值,仍按照浮点机器模式m来表示,并存放在操作数0(对于浮点机器模式m有效)中。


fix_truncmn2
类似于‘fixmn2’,不过工作于,将任意机器模式为m的浮点值,转换成整数。


fixuns_truncmn2
类似‘fixunsmn2’,不过工作于,将任意机器模式为m的浮点值,转换成整数。


truncmn2
将操作数1(对机器模式m有效),截取为机器模式n,并存放在操作数0(机器模式为n)中。两个机器模式都必须同为定点的或者浮点的。


extendmn2
将操作数1(对机器模式m有效)符号扩展成机器模式n,并存放在操作数0(机器模式为n)中。两个机器模式都必须同为定点的或者浮点的。


zero_extendmn2
将操作数1(对机器模式m有效)零扩展成机器模式n,并存放在操作数0(机器模式为n)中。两个机器模式都必须同为定点的或者浮点的。


fractmn2
将机器模式为m的操作数1,转换成机器模式n,并存放在操作数0(机器模式为n)中。机器模式mn可以为定点到定点,有符号整数到定点,定点到有符号整数,浮点到浮点,或者定点到浮点。当发生溢出时,结果未定义。


satfractmn2
将机器模式为m的操作数1,转换成机器模式n,并存放在操作数0(机器模式为n)中。机器模式mn可以为定点到定点,有符号整数到定点,或者浮点到定点。当发生溢出时,指令将结果饱和为最大或最小值。


fractunsmn2
将机器模式为m的操作数1,转换成机器模式n,并存放在操作数0(机器模式为n)中。机器模式mn可以为无符号整数到定点,或者定点到无符号整数。当发生溢出时,结果未定义。


satfractunsmn2
将机器模式为m的,无符号整数,操作数1,转换成定点机器模式n,并存放在操作数0(机器模式为n)中。当发生溢出时,指令将结果饱和为最大或最小值。


extv
从操作数1(寄存器或者内存操作数)中抽取一个位域,其中操作数2指定了宽度,按位为单位,操作数3为起始位,并将结果存放在操作数0中。操作数0必须具有机器模式word_mode。操作数1可以具有机器模式byte_modeword_mode;通常word_mode只允许用于寄存器。操作数2和3必须对word_mode有效。

RTL生成过程,生成的该指令,操作数2和3为常量,并且对于操作数2,常量不为零。

位域的值,在存放到操作数0之前,被有符号扩展为一整个字的整数。


extzv
类似‘extv’,只不过位域的值被零扩展。


insv
将操作数3(必须对word_mode有效)存储到操作数0中的位域,其中操作数1指定了位宽,操作数2指定了起始位。操作数0可以具有机器模式byte_modeword_mode;通常word_mode只允许用于寄存器。操作数1和2必须对word_mode有效。

RTL生成过程,生成的该指令,操作数1和2为常量,并且对于操作数1,常量不为零。


movmodecc
根据对操作数1的比较,有条件的将操作数2或者3移送到操作数0中。如果比较为真,则操作数2被移送到操作数0中,否则操作数3被移送。

操作数的机器模式不需要与被移送的操作数的相同。一些机器,例如sparc64,具有可以根据浮点条件码,条件移送整数值的指令,以及相反的指令。

如果机器没有条件移送指令,则不要定义这些指令模式。


addmodecc
类似于‘movmodecc’,不过是条件加法。根据在操作数1中的比较,条件性的将操作数2或者(操作数2 + 操作数3),移送到操作数0中。如果比较为真,则操作数2被移送到操作数0中,否则(操作数2 + 操作数3)被移送。


scond
根据条件码将零或者非零存放在操作数中。当且仅当条件cond为真时,存储的值才为非零。cond为一个比较运算表达式代码的名字,例如eq, ltleu

当书写match_operand表达式的时候,你来指定操作数必须具有的机器模式。编译器自动的查看你使用的机器模式,并提供那个机器模式的操作数。

对于条件为真时所存储的值,其低位必须为1,不然必须为负。否则,指令就不适合,你应该从机器描述中将其去掉。你可以通过定义宏STORE_FLAG_VALUE (参见Misc),来描述哪个值被存放。如果不能找到一个用于所有‘scond’指令模式的描述,则你应该从机器描述中去掉这些操作。

这些操作可以失败,但应该只在相对不常见的情况下这样做;如果它们对于常见的情况,包括整数比较,会失败,则最好去掉这些指令模式。

如果这些操作被去掉,则编译器通常会生成,将常量复制到目标,并在将零赋值给目标的语句附近进行分支跳转。如果这样的代码比用于‘scond’模式的指令,后面跟着需要将结果转成SImode的1或者零的的指令,更有效,则你应该从机器描述中去掉‘scond’操作。


bcond
条件分支指令。操作数0为一个label_ref指出要跳转到的标号。如果条件码符合条件cond则跳转。

一些机器不遵循这里假设的模型,即一个比较指令,跟随一个条件跳转指令。那种情况下,‘cmpm’ (和 ‘tstm’)指令模式,应该简单的将操作数存放开,并在define_expand (参见Expander Definitions)中为条件分支操作,生成所有需要的insn。所有对扩展‘bcond’指令模式的调用,都会立即优先执行对扩展‘cmpm’或者‘tstm’的调用。

对条件代码值使用伪寄存器的,或者用于比较的机器模式取决于被测试的条件的机器,也应该使用上面的机制。参见Jump Patterns.

上面的讨论也应用在‘movmodecc’和‘scond’指令模式上。


cbranchmode4
条件分支指令,结合一个比较指令。操作数0为比较运算符。操作数1和2分别为比较运算的第一个和第二个操作数。操作数3为一个label_ref,指出了跳转的标号。


jump
函数内部跳转;无条件分支。操作数0为一个label_ref,指出了跳转的标号。该指令模式名在所有机器上都是强制必须的。


call
没有返回值的子程序调用指令。操作数0为调用的函数;操作数1为压栈的参数的字节数,为一个const_int;操作数2为用作操作数的寄存器数目。

在大多机器上,操作数2没有被实际存放在RTL模式中。提供它是出于安全考虑,一些RISC机器需要将该信息放到汇编代码中;它们可以将其放在RTL中,而不是操作数1中。

操作数0应该为一个mem RTX,其地址为函数的地址。然而注意,该地址可以为一个symbol_ref表达式,即使其在目标机器上可能不是一个合法的内存地址。如果其也不是调用指令的有效参数,则该操作的指令模式应该为一个define_expand (参见Expander Definitions),其将地址放入寄存器中,并在调用指令中使用寄存器。


call_value
有返回值的子程序调用指令。操作数0为硬件寄存器,存放返回值。还有三个操作数,与‘call’指令相同(只不过将编号加一)。

返回 BLKmode对象的子程序,使用‘call’ insn。


call_pop’, ‘call_value_pop
类似于‘call’ 和 ‘call_value’,只不过用于其被定义,并且RETURN_POPS_ARGS为非零的时候。它们应该生成一个 parallel,包含函数调用和一个set,来指示对帧指针的调整。

对于RETURN_POPS_ARGS可以为非零的机器,使用这些指令模式可以增加帧指针被消除掉的函数的数目。


untyped_call
返回一个任意类型的值的子函数调用指令。操作数0为调用的函数;操作数1为内存位置,存放调用函数后的结果;操作数2为一个parallel表达式,其中每个元素都为一个set表达式,用来指示将函数返回值保存到结果块中。

该指令模式应该被定义,来支持__builtin_apply,在一些机器上,需要特殊的指令来调用一个具有任意参数的子程序,或者将返回值保存。在具有多个寄存器,可以存放一个返回值(即FUNCTION_VALUE_REGNO_P对多个寄存器都为真)的机器上,需要该指令模式。


return
子程序返回指令。该指令模式名应该只有当,单个指令可以做从函数中返回时的所有工作的时候,才被定义。

类似‘movm’指令模式,该指令模式也在RTL生成阶段之后被使用。这种情况下,其用来支持一些机器,从函数中返回通常需要多个指令,但是某些类别的函数只需要一条指令来实现返回。通常,可以适用的函数为那些不需要保存任何寄存器或者分配栈空间的函数。

对于这样的机器,该指令模式中指定的条件,应该只有当reload_completed为非零的时候才为真,并且函数的尾声应该只为一单个指令。对于有寄存器窗口的机器,例程leaf_function_p可以用来确定是否需要对寄存器窗口压栈。

具有条件性返回指令的机器,应该将指令模式定义成

          (define_insn ""
            [(set (pc)
                  (if_then_else (match_operator
                                   0 "comparison_operator"
                                   [(cc0) (const_int 0)])
                                (return)
                                (pc)))]
            "condition"
            "...")

其中condition通常为,在‘return’指令模式中指定的相同的条件。


untyped_return
未定义类型的子程序返回指令。该指令模式应该被定义,来支持__builtin_return,在一些机器上,需要特殊的指令来返回一个任意类型的值。

操作数0为一个内存位置,存放使用__builtin_apply调用函数的结果;操作数1为一个parallel表达式,每个元素都是一个set表达式,指示了从结果块中恢复函数的返回值。


nop
空操作指令。该指令模式名应该总是被定义,用来在汇编代码中输出一个no-op。(const_int 0)将作为一个RTL指令模式。


indirect_jump
一个指令,跳转到操作数0表示的地址。该指令模式名在所有机器上都必须存在。


casesi
通过派遣表进行跳转的指令,包括边界检查。该指令接受五个操作数:
  1. 派遣的索引,具有机器模式SImode
  2. 表中索引的较低边界,一个整数常量。
  3. 表中索引的整个范围—最大索引减去最小的。
  4. 位于表之前的标号。
  5. 一个标号,如果索引值超出边界,则跳转到该地方。

表为jump_insn中的一个addr_vecaddr_diff_vec。表中的元素个数为一加上上界和下界的差。


tablejump
跳转到一个可变地址的指令。这是一个低级别的能力,可以用来实现一个派遣表,当没有‘casesi’指令模式的时候。

该指令模式需要两个操作数:地址或偏移量,以及一个标号,其直接位于跳转表的前面。如果宏CASE_VECTOR_PC_RELATIVE求值为一个非零值,则第一个操作数为一个偏移量,其从表的地址开始计算;否则,其为一个跳转的绝对地址。这两种情况下,第一个操作数都为Pmode

tablejump’ insn总是其使用的跳转表之前的最后一个insn。其汇编代码通常不需要用到第二个操作数,但是你应该在RTL指令模式中包含它,使得跳转优化不会将表作为不可到达代码删除。


decrement_and_branch_until_zero
条件分支指令,递减一个寄存器并且如果寄存器非零则跳转。操作数0为递减并测试的寄存器;操作数1为如果寄存器非零,则跳转的标号。参见Looping Patterns.

该可选的指令模式只用于合并器,通常被循环优化器使用,当启动强度消减的时候。


doloop_end
条件分支指令,递减一个寄存器,并且如果寄存器非零则跳转。该指令接受五个操作数:操作数0是用来递减和测试的寄存器;操作数1是循环迭代的次数,为一个const_int,或者如果直到运行时才能确定,则为const0_rtx;操作数2为实际的或者估算的最大迭代数,为一个const_int;操作数3为被包含的循环数,为一个const_int(最内层循环的值为1);操作数4为如果寄存器非零,要跳转的标号。参见Looping Patterns.

该可选的指令模式应该为,具有低开销循环指令的机器定义,循环优化器会尝试修改合适的循环来利用它。如果不支持嵌套的低开销循环,则使用define_expand (参见Expander Definitions),并如果操作数3不为const1_rtx,则使得指令模式失败。类似的,如果实际的或者估算的最大迭代数目对于该指令来说太大,则使其失败。


doloop_begin
doloop_end成套的指令,被用于需要执行一些初始化的机器,例如加载用于低开销循环指令中的特定寄存器。如果初始化insn不总是需要被生成,则使用define_expand (参见Expander Definitions),并使其失败。


canonicalize_funcptr_for_compare
正规化操作数1中的函数指针,并将结果存放在操作数0中。

操作数0总是一个reg,并具有机器模式Pmode;操作数1可以为一个reg, mem, symbol_ref, const_int等等,也具有机器模式Pmode

正规化一个函数指针,通常涉及到计算函数的地址,该函数指针用在间接调用中。

只有当目标机器上,对于函数指针可以有不同的值,但是当在间接调用的时候,其还是调用相同的函数的时候,才定义该指令模式。


save_stack_block
save_stack_function
save_stack_nonlocal
restore_stack_block
restore_stack_function
restore_stack_nonlocal
大多数机器用来保存和恢复栈指针的方式,是通过将其复制到一个机器模式为Pmode的对象。不要在这样的机器上定义这些指令模式。

一些机器要求对栈指针的保存和恢复,进行特殊的处理。在那些机器上,根据非标准的情况来定义指令模式,使用define_expand (参见Expander Definitions)来产生要求的insn。三种保存和恢复类型:

  1. save_stack_block’将栈指针存放在用来分配可变大小的对象块的起始处,‘restore_stack_block’当退出块的时候恢复栈指针。
  2. save_stack_function’ 和 ‘restore_stack_function’为函数最外层的快做类似的工作,并用于当函数分配可变大小的对象或者调用alloca的时候。只有尾声使用被恢复的栈指针,这使得在一些机器上,可以有更简单的保存或恢复序列。
  3. save_stack_nonlocal’用在包含嵌套函数分支跳转标号的函数中。其保存栈指针的方式为,最内层函数可以使用‘restore_stack_nonlocal’来恢复栈指针。编译器生成代码,用来恢复帧寄存器和参数指针寄存器,但是一些机器要求保存和恢复额外的数据,例如寄存器窗口信息或者栈后退链。在这些指令模式中放置保存和恢复这些要求的数据的insn。

当保存栈指针时,操作数0是保存区域,操作数1是栈指针。用于分配保存区域的机器模式缺省为Pmode,不过你可以通过定义STACK_SAVEAREA_MODE宏(参见Storage Layout)来覆盖该选择。你必须指定一个整数机器模式,或者VOIDmode,如果对于特定的类型不需要保存区域(或者因为没有需要保存的,或者因为可以使用机器特定的保存区域)。操作数0为栈指针,操作数1为用于恢复操作的保存区域。如果‘save_stack_block’被定义,则操作数0一定不能为VOIDmode,因为这些保存操作数可以被任意的嵌套。

当栈指针被保存,是用于非局部goto,则保存区域为一个mem,为一个相对于virtual_stack_vars_rtx的常量偏移,其它两种情况下,保存区域为一个reg


allocate_stack
从栈指针中减去(或者增加,如果STACK_GROWS_DOWNWARD未定义)操作数1,来为动态分配的数据创建空间。将由此产生的指向该空间的指针存放在操作数0中。如果你是从主栈中分配空间,则可以通过生成一个insn,将virtual_stack_dynamic_rtx复制到操作数0中。如果你是从其它地方分配空间,则可以生成将该空间的位置复制到操作数0中的代码。对于后者情况,你必须确保该空间当主栈中对应的空间被释放的时候,其也被释放。

如果所有需要做的事情只是减法操作,则不用定义该指令模式。一些机器还要求其它的操作,例如栈探测,或者维护后向链。定义该指令模式除了更新栈指针之外的,来生成那些操作。


check_stack
如果在你的系统上,不能通过使用加载或者存储指令(参见Stack Checking)探测栈,从而进行栈检查,则定义该指令模式来执行所需要的检查,并且如果栈已经溢出则产生一个错误信号。有单个操作数,为栈中从当前栈指针开始,最远的栈位置。通常,在需要该指令模式的机器上,你将从一个全局的或者线程特定的变量或者寄存器中获得栈的限制。


nonlocal_goto
生成产生一个非局部goto的代码,例如,从一个函数跳转到一个外部函数的标号。该指令模式有四个参数,每个参数表示一个在跳转中用到的值。第一个参数被加载到帧指针中,第二个为分支跳转的地址,第三个为栈被保存的地址,最后一个为标号的地址,放在静态链中。

在大多上机器上,你不需要定义该指令模式,因为GCC会产生正确的代码,用来加载帧指针和静态链,恢复栈(使用‘restore_stack_nonlocal’指令模式,如果定义),并间接跳转。你只有当该代码在你的机器上不工作的情况下,才需定义该指令模式。


nonlocal_goto_receiver
该指令模式,如果定义,包含了非局部goto的目标处所需要的代码。通常不需要定义该指令模式。通常需要该指令模式的原因是,如果一些值,例如全局表的指针,必须在帧指针被恢复的时候,其也被恢复。注意,非局部goto,只出现在一个转换单元中,所以被给定模块的所有函数共享的全局表指针,不需要被恢复。该指令模式没有参数。


exception_receiver
该指令模式,如果被定义,包含了在一个异常处理的地方所需要的代码,其在非局部goto的地方不需要。通常你不需要定义该指令模式。一个典型的,你可以需要定义该指令模式的原因是,如果某个值,例如指向全局表的指针,必须在控制流分支跳转到异常处理之后,被恢复。该指令模式没有参数。


builtin_setjmp_setup
该指令模式,如果被定义,则包含了需要初始化jmp_buf的代码。你通常不需要定义该指令模式。一个典型的,你可以需要定义该指令模式的原因是,如果某个值,例如指向全局表的指针,必须被恢复。尽管如此,还是推荐指针值如果可能(例如,给定一个标号的地址),则应被重新计算。有一单个操作数,


builtin_setjmp_receiver
该指令模式,如果被定义,包含了在内建setjmp的地方,并且在非局部goto的地方不需要的代码。你通常不需要定义该指令模式。一个典型的,你可以需要定义该指令模式的原因是,如果某个值,例如指向全局表的指针,必须被恢复。其接受一个参数,为builtin_longjmp将控制转出的标号;该指令模式可以被生成为对于标号的一个小的偏移。


builtin_longjmp
该指令模式,如果被定义,则执行整个longjmp动作。你通常不需要定义该指令模式,除非你还定义了builtin_setjmp_setup。单个操作数为指向jmp_buf的指针。


eh_return
该指令模式,如果被定义,则影响__builtin_eh_return的方式,并且调用帧异常处理库函数会被建立。其用于处理异常返回路径所需要的非平凡的动作。

函数应该返回的异常处理的地址,被作为操作数传给该指令模式。其通常需要被指令模式复制到某个特定的寄存器或者内存位置。如果该指令模式需要确定目标调用帧的位置,则可以使用EH_RETURN_STACKADJ_RTX

如果该指令模式没有被定义,缺省的动作为简单的将返回地址复制给EH_RETURN_HANDLER_RTX。或者宏,或者该指令模式,应该被定义,如果使用了调用帧异常处理。


prologue
该指令模式,如果被定义,用来产生函数的入口RTL。函数入口负责设置栈帧,初始化帧指针寄存器,保存被调用者需要保存的寄存器,等等。

使用一个序言指令模式,通常的方式为定义TARGET_ASM_FUNCTION_PROLOGUE来产生序言的汇编代码。

prologue指令模式对于执行指令调度的目标机尤其有用。


epilogue
该指令模式为函数的出口生成RTL。函数出口负责撤销栈帧的分配,恢复被调用者所保存的寄存器,并产生返回指令。

使用尾声指令模式,通常的方式为定义TARGET_ASM_FUNCTION_EPILOGUE,来产生尾声的汇编代码。

prologue指令模式对于执行指令调度的,或者它们的返回指令具有延迟槽的目标机,尤其有用。


sibcall_epilogue
该指令模式,如果被定义,产生一个函数的出口RTL,并且最终不分支跳转会到调用函数。该指令模式将在任何兄弟调用(即尾调用)地点之前被产生。

sibcall_epilogue指令模式一定不能破坏任何用于传递的参数,或者用于传给当前函数的参数的栈槽。


trap
该指令模式,如果被定义,则会发射一个错误信号。在其它地方,其被Java前端使用,来发射“无效的数组索引”异常信号。


conditional_trap
条件陷阱指令。操作数0为执行比较的RTL。操作数1为陷阱代码,为一个整数。

典型的conditional_trap指令模式型如:

          (define_insn "conditional_trap"
            [(trap_if (match_operator 0 "trap_operator"
                       [(cc0) (const_int 0)])
                      (match_operand 1 "const_int_operand" "i"))]
            ""
            "...")


prefetch
该指令模式,如果被定义,则产生无故障的数据预取指令代码。操作数0为预取的内存地址。操作数1为常量1,如果预取打算去写一个内存地址,否则为常量0。操作数2为数据的时间局部性的等级,值在0和3之间。0意味着数据没有时间局部性,所以在访问之后不需要留在缓存中;3意味着数据具有高等级的时间局部性,应该尽可能的留在所有级别的缓存中;1和2分别意味着,低等级和中等级的时间局部性。

不支持写预取或者局部性暗示的目标机,可以忽略操作数1和2的值。


blockage
该指令模式定义了一个伪insn,用来阻止指令调度器将指令跨越所定义的insn块边界进行移动。通常为一个UNSPEC_VOLATILE指令模式。


memory_barrier
如果目标机内存模型不完全同步,则该指令模式应该被定义为一条指令,在期望进行加载和存储的指令之前。该指令模式没有操作数。


sync_compare_and_swapmode
该指令模式,如果被定义,产生一个比较并交换的原子操作代码。操作数1为执行原子操作的内存。操作数2为,与当前内存位置的内容进行比较的“旧”值。操作数3为,如果比较成功存放在内存中的“新”值。如果比较成功,其当然为对操作数2的一个复制。

该指令模式必须同时显示出操作数0和1被修改。

该指令模式必须产生内存栅栏指令,使得在原子操作之前的所有内存操作,都在原子操作之前发生,所有在原子操作之后的内存操作,都在原子操作之后发生。


sync_compare_and_swap_ccmode
该指令模式与sync_compare_and_swapmode类似,除了其比较和交换的比较部分就好像是通过cmpm来发出的。该比较只与EQNE分支跳转,以及setcc操作一起使用。

一些目标机确实是通过状态标记来暴露比较并交换操作的成功或失败。理想的,我们不需要一个单独的命名指令模式来利用该特性,但是合并过程无法处理具有多个set的指令模式,而这正是定义sync_compare_and_swapmode所需要的。


sync_addmode’, ‘sync_submode
sync_iormode’, ‘sync_andmode
sync_xormode’, ‘sync_nandmode
该指令模式产生一个在内存上进行原子操作的代码。操作数0为进行原子操作的内存。操作数1为二元操作符的第二个操作数。

“nand”运算为~op0 & op1

该指令模式必须产生内存栅栏指令,使得在原子操作之前的所有内存操作,都在原子操作之前发生,所有在原子操作之后的内存操作,都在原子操作之后发生。

如果这些指令模式没有被定义,则操作将通过一个比较并交换操作,如果定义,来构建。


sync_old_addmode’, ‘sync_old_submode
sync_old_iormode’, ‘sync_old_andmode
sync_old_xormode’, ‘sync_old_nandmode
这些指令模式产生在内存上的原子操作代码,并且返回操作之前内存中的值。操作数0为结果值,操作数1为执行原子操作的内存,操作数2为二元操作的第二个操作数。

该指令模式必须产生内存栅栏指令,使得在原子操作之前的所有内存操作,都在原子操作之前发生,所有在原子操作之后的内存操作,都在原子操作之后发生。

如果这些指令模式没有被定义,则操作将通过一个比较并交换操作,如果定义,来构建。


sync_new_addmode’, ‘sync_new_submode
sync_new_iormode’, ‘sync_new_andmode
sync_new_xormode’, ‘sync_new_nandmode
这些指令模式类似于sync_old_op所对应的指令模式,除了它们返回操作之后内存位置中存在的值,而不是操作之前。


sync_lock_test_and_setmode
该指令模式根据目标机的能力,可以接受两种形式。两种情况下,操作数0为结果操作数,操作数1为执行原子操作的内存,操作数2为在锁中设置的值。

理想的情况下,该操作为一个原子交换操作,内存操作数中之前的值被复制到结果操作数中,值操作数被保存在内存操作数中。

对于能力差些的目标机,任何不为常量1的值操作数,将使用FAIL进行拒绝。这种情况下,目标机可以使用一个原子的测试并置位操作。结果操作数应该包含1,如果该位在之前被设置,或者为0,如果该位在之前被清空。内存操作数的真实内容由实现来定义。

该指令模式必须产生内存栅栏指令,使得在原子操作之前的所有内存操作,都在原子操作之前发生,所有在原子操作之后的内存操作,都在原子操作之后发生。

如果这些指令模式没有被定义,则操作将通过一个比较并交换操作,如果定义,来构建。


sync_lock_releasemode
该指令模式,如果被定义,释放由sync_lock_test_and_setmode设置的锁。操作数0为包含锁的内存;操作数1为存放在锁中的值。

如果目标机没有实现sync_lock_test_and_setmode的完整语义,则任何不是常量0的值操作数将使用FAIL来拒绝,内存操作数的真实内容由实现来定义。

该指令模式必须产生内存栅栏指令,使得在原子操作之前的所有内存操作,都在原子操作之前发生,所有在原子操作之后的内存操作,都在原子操作之后发生。

如果这些指令模式没有被定义,则会产生一个memory_barrier指令模式,紧跟一个将值存储到内存操作数的操作。


stack_protect_set
该指令模式,如果被定义,将内存操作数1中的Pmode值移送到内存操作数0中,并在之后不将该值留在寄存器中。这避免在某处泄露该值,从而使得攻击者用来重写栈保护槽。

如果该指令模式没有被定义,则生成一个普通的move指令模式。


stack_protect_test
该指令模式,如果被定义,比较内存操作数1和内存操作数0中的Pmode值,在之后不将该值留在寄存器中,并且如果值不等,则分支跳转到操作数2。

如果该指令模式没有被定义,则使用一个普通的比较和条件分支指令模式。


clear_cache
该指令模式,如果被定义,刷新一个内存区域的缓存。该区域的界限由操作数0(包含)和操作数1(不包含)中的Pmode指针界定。

如果该指令模式没有被定义,则使用对库函数__clear_cache的一个调用。