Next: , Previous: Output Template, Up: Machine Desc


16.6 用于汇编输出的C语句

经常,单个固定的模板字符串,不能够为单个指令模式所识别的所有情况都能产生正确, 有效的汇编代码。例如,操作码可以依赖于操作数类别;或者一些不适宜的操作数组合 可能需要额外的机器指令。

如果输出控制字符串起始于 ‘@’,则其实际为一系列模板,每一个单独一行。 (空行,以及开头的空格和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")