Next: Looping Patterns, Previous: Dependent Patterns, Up: Machine Desc
对于大多数机器,GCC假设该机器具有一个条件码。 比较insn根据给定操作数的有符号和无符号比较的结果来设定条件码。 单独的分支insn测试条件代码,并根据它的值进行分支跳转。 分支insn分为不同的有符号和无符号的。 许多通用机器,像VAX,68000和32000都按这种方式工作。
一些机器具有截然不同的有符号和无符号比较指令,并且只有一套条件分支指令。
处理这些机器最容易的方法为保持它们不变,直到最后写汇编代码的阶段。
这时,当输出比较指令的代码时,查看一下使用next_cc0_user (insn)
的分支。
()如果RTL得出其为一个无符号分支,则输出一个无符号比较;
否则输出一个有符号比较。当分支本身被输出时,你可以将有符号和无符号分支视为等同的。
之所以可以这样做,是因为GCC总是生成一对连续的RTL insn,
可能由note
insn分隔,一个用于设置条件代码,一个用于测试,
并保持这对insn不被改变,直到最后。
要使用该技术,你必须定义机器描述宏NOTICE_UPDATE_CC
,
来做CC_STATUS_INIT
;换句话说,没有多余的比较指令。
一些机器具有比较分支指令,并且没有条件码。对它们可以使用类似的技术。 当该要“输出”一个比较指令时,将它的操作数记录在两个静态变量中。 当输出随后的条件码分支指令时,实际上输出了一个使用已记录的操作数的比较分支指令。
它还用于定义比较分支指令的指令模式。在优化编译中, 比较和分支指令对将根据这些指令模式被组合。但是如果优化不要求的时候, 这是不会发生的。所以你必须针对你定义的任何特定指令模式额外使用上面的一种解决方式。
在许多RISC机器上,大多数指令不影响条件码,并且甚至会没有一个单独的条件码寄存器。 在这些机器上,限制条件码的定义和使用为邻近的insn是不必要的, 并且还会阻止一些重要的优化。例如,在IBM RS/6000上,对于分支将会有一个延迟, 除非条件码寄存器在条件分支的三条指令前被设置。 如果不允许将条件码寄存器的定义和使用分开,则指令调度器将无法执行该优化。
在这些机器上,不要使用(cc0)
,而是使用寄存器来表示条件代码。
如果该机器有一个特定的条件代码寄存器,则使用硬件寄存器。
如果条件代码或者比较结果可以被放在任意的通用寄存器中,
或者有多个条件寄存器,则使用伪寄存器。
在一些机器上,所生成的分支指令类型可以依赖于条件代码所产生的方式;
例如,在68k和SPARC上,直接从加法或减法指令来设置条件代码,
这并不像测试指令那样,不会清除溢出位,
所以不同的分支指令必须用于某些条件分支。对于使用(cc0)
的机器,
对条件代码的设置和使用必须是邻近的(只有note
insn分隔),
以允许在cc_status
中的标记被使用。(参见条件码)并且,
比较分支insn可以互相定位,通过使用函数prev_cc0_setter
和next_cc0_user
。
但是,这在不使用(cc0)
的机器上是不一样的。
在这些机器上,并不会假设比较分支指令是邻近的,上面的方法不可用。
替换的,我们使用条件码寄存器的机器模式来记录条件码寄存器的不同格式。
用于存储条件码值的寄存器应该具有MODE_CC
类别的一个机器模式。
通常,其为CCmode
。如果需要额外的机器模式
(正如上面提到的SPARC中加法例子),
则在machine-modes.def中定义它们(参见条件码)。
还要定义SELECT_CC_MODE
来选择给定比较操作数的机器模式。
如果知道在RTL生成过程中,将需要不同的机器模式 (例如,如果机器具有单独的比较指令,针对有符号和无符号), 则它们可以在那个时候被指定。
如果是在指令合成时需要不同的机器模式,
则宏SELECT_CC_MODE
用来确定哪个机器模式作为比较结果。
指令模式应该使用该模式来书写。要支持上面讨论的SPARC的加法,
我们具有指令模式