Next: Predicates, Previous: Output Template, Up: Machine Desc
经常,单个固定的模板字符串,不能够为单个指令模式所识别的所有情况都能产生正确, 有效的汇编代码。例如,操作码可以依赖于操作数类别;或者一些不适宜的操作数组合 可能需要额外的机器指令。
如果输出控制字符串起始于 ‘@’,则其实际为一系列模板,每一个单独一行。 (空行,以及开头的空格和tab被忽略掉。)这些模板对应于模式的各个constraint (参见Multi-Alternative)。例如,如果一个目标机有一个二址(two-address) 加法指令 ‘addr’相加到寄存器中,另外还有一个 ‘addm’ 将寄存器的值相加 到内存中,你可能会这样写模式:
(define_insn "addsi3" [(set (match_operand:SI 0 "general_operand" "=r,m") (plus:SI (match_operand:SI 1 "general_operand" "0,0") (match_operand:SI 2 "general_operand" "g,r")))] "" "@ addr %2,%0 addm %2,%0")
如果输出控制字符串起始于 ‘*’,则其不是一个输出模板,而是一个C程序片段并且
能够计算出一个模板。其应该执行一个 return
语句来返回你想要的模板字符串。
大多数这样的模板使用C字符串文字,需要用双引号包含起来。如果要在字符串中包含这
些双引号,可以在前面加上 ‘\’。
如果输出控制串写成一个花括号块,而不是双引号的字符串,则其被自动认为是C代码。 这种情况下,则不必要有的起始的星号,以及转义C字符串文字中的双引号。
操作数可以为数组 operands
,其C数据类型为 rtx []
。
一种常见的情况是,根据立即数是否在一个特定范围内来选择生成汇编代码的方式。在做
这种事情的时候要仔细,因为 INTVAL
的结果是一个主机上的整形。如果主机的
int
比目标机上的具有更多的位,则从 INTVAL
中的得到的一些位将会是
多余的。要得到正确的结果,必须仔细的忽视掉那些位的值。
有可能输出一个汇编指令,然后使用子程序 output_asm_insn
来继续输出或者计
算更多的。其接收两个参数:一个模板字符串和一个操作数向量。向量可以是
operands
,或者是另一个声明为局部的并且自己初始化的 rtx
数组。
当一个insn模式有多个可选择的constraint时,则汇编代码经常主要是由所匹配的constraint选择来决
定。如果是这样,C代码可以测试变量 which_alternative
,其为实际满足条件的
constraint选择的序号(0为第一个,1位第二个选择,以此类推)。
例如,假设有两个操作码来存储0,‘clrreg’ 用于寄存器,‘clrmem’ 用于内存 地址。这个模式实现了如何能够使用 ‘which_alternative’ 来选择它们:
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=r,m") (const_int 0))] "" { return (which_alternative == 0 ? "clrreg %0" : "clrmem %0"); })
对于上面的例子,要生成的汇编代码 只是 由alternative来决定,则还可以写成 如下形式,使用起始于 ‘@’ 的输出控制串:
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=r,m") (const_int 0))] "" "@ clrreg %0 clrmem %0")