gccint: Output Statement

1 
1 17.6 C Statements for Assembler Output
1 ======================================
1 
1 Often a single fixed template string cannot produce correct and
1 efficient assembler code for all the cases that are recognized by a
1 single instruction pattern.  For example, the opcodes may depend on the
1 kinds of operands; or some unfortunate combinations of operands may
1 require extra machine instructions.
1 
1  If the output control string starts with a '@', then it is actually a
1 series of templates, each on a separate line.  (Blank lines and leading
1 spaces and tabs are ignored.)  The templates correspond to the pattern's
1 constraint alternatives (⇒Multi-Alternative).  For example, if a
1 target machine has a two-address add instruction 'addr' to add into a
1 register and another 'addm' to add a register to memory, you might write
1 this pattern:
1 
1      (define_insn "addsi3"
1        [(set (match_operand:SI 0 "general_operand" "=r,m")
1              (plus:SI (match_operand:SI 1 "general_operand" "0,0")
1                       (match_operand:SI 2 "general_operand" "g,r")))]
1        ""
1        "@
1         addr %2,%0
1         addm %2,%0")
1 
1  If the output control string starts with a '*', then it is not an
1 output template but rather a piece of C program that should compute a
1 template.  It should execute a 'return' statement to return the
1 template-string you want.  Most such templates use C string literals,
1 which require doublequote characters to delimit them.  To include these
1 doublequote characters in the string, prefix each one with '\'.
1 
1  If the output control string is written as a brace block instead of a
1 double-quoted string, it is automatically assumed to be C code.  In that
1 case, it is not necessary to put in a leading asterisk, or to escape the
1 doublequotes surrounding C string literals.
1 
1  The operands may be found in the array 'operands', whose C data type is
1 'rtx []'.
1 
1  It is very common to select different ways of generating assembler code
1 based on whether an immediate operand is within a certain range.  Be
1 careful when doing this, because the result of 'INTVAL' is an integer on
1 the host machine.  If the host machine has more bits in an 'int' than
1 the target machine has in the mode in which the constant will be used,
1 then some of the bits you get from 'INTVAL' will be superfluous.  For
1 proper results, you must carefully disregard the values of those bits.
1 
1  It is possible to output an assembler instruction and then go on to
1 output or compute more of them, using the subroutine 'output_asm_insn'.
1 This receives two arguments: a template-string and a vector of operands.
1 The vector may be 'operands', or it may be another array of 'rtx' that
1 you declare locally and initialize yourself.
1 
1  When an insn pattern has multiple alternatives in its constraints,
1 often the appearance of the assembler code is determined mostly by which
1 alternative was matched.  When this is so, the C code can test the
1 variable 'which_alternative', which is the ordinal number of the
1 alternative that was actually satisfied (0 for the first, 1 for the
1 second alternative, etc.).
1 
1  For example, suppose there are two opcodes for storing zero, 'clrreg'
1 for registers and 'clrmem' for memory locations.  Here is how a pattern
1 could use 'which_alternative' to choose between them:
1 
1      (define_insn ""
1        [(set (match_operand:SI 0 "general_operand" "=r,m")
1              (const_int 0))]
1        ""
1        {
1        return (which_alternative == 0
1                ? "clrreg %0" : "clrmem %0");
1        })
1 
1  The example above, where the assembler code to generate was _solely_
1 determined by the alternative, could also have been specified as
1 follows, having the output control string start with a '@':
1 
1      (define_insn ""
1        [(set (match_operand:SI 0 "general_operand" "=r,m")
1              (const_int 0))]
1        ""
1        "@
1         clrreg %0
1         clrmem %0")
1 
1  If you just need a little bit of C code in one (or a few) alternatives,
1 you can use '*' inside of a '@' multi-alternative template:
1 
1      (define_insn ""
1        [(set (match_operand:SI 0 "general_operand" "=r,<,m")
1              (const_int 0))]
1        ""
1        "@
1         clrreg %0
1         * return stack_mem_p (operands[0]) ? \"push 0\" : \"clrmem %0\";
1         clrmem %0")
1