--- gcc/c-parse.in.orig Sat Feb 7 14:11:46 1998 +++ gcc/c-parse.in Sat Feb 7 14:04:25 1998 @@ -2204,6 +2204,8 @@ nonnull_asm_operands: asm_operand: STRING '(' expr ')' { $$ = build_tree_list ($1, $3); } + | STRING + { $$ = build_tree_list ($1, NULL_TREE); } ; asm_clobbers: --- gcc/c-typeck.c.orig Sat Sep 27 13:46:33 1997 +++ gcc/c-typeck.c Fri Feb 6 23:50:00 1998 @@ -6519,7 +6519,7 @@ c_expand_asm_operands (string, outputs, } /* Detect modification of read-only values. (Otherwise done by build_modify_expr.) */ - else + else if (o[i] != NULL_TREE) { tree type = TREE_TYPE (o[i]); if (TREE_READONLY (o[i]) --- gcc/stmt.c.orig Fri Feb 6 21:25:08 1998 +++ gcc/stmt.c Sat Feb 7 14:03:09 1998 @@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA. */ #include "insn-config.h" #include "insn-codes.h" #include "expr.h" +#include "regs.h" #include "hard-reg-set.h" #include "obstack.h" #include "loop.h" @@ -1383,6 +1384,38 @@ expand_asm (body) last_expr_type = 0; } +/* Choose a mode that might be suitable for a constraint. + If the constraint is too tricky, this can get it wrong. */ +static enum machine_mode +choose_constraint_mode(constraint) + char *constraint; +{ + for (;;) + switch (*constraint++) + { + case '0': case ',': + /* Wild guess. This is why you shouldn't use this facility + to (for instance) provide a memory location. */ + return byte_mode; + case 'r': case 'g': + /* Assume that general registers can at least hold a byte. */ + return byte_mode; + default: + { + enum reg_class class = REG_CLASS_FROM_LETTER (constraint[-1]); + int regno; + + if (class == NO_REGS) + continue; + + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) + if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno)) + return reg_raw_mode[regno]; + continue; + } + } +} + /* Generate RTL for an asm statement with arguments. STRING is the instruction template. OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs. @@ -1455,15 +1488,18 @@ expand_asm_operands (string, outputs, in for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) { tree val = TREE_VALUE (tail); - tree type = TREE_TYPE (val); + tree type; tree val1; int j; int found_equal = 0; int found_plus = 0; int allows_reg = 0; + if (val != NULL_TREE) + type = TREE_TYPE (val); + /* If there's an erroneous arg, emit no insn. */ - if (TREE_TYPE (val) == error_mark_node) + if (val != NULL_TREE && type == error_mark_node) return; /* Make sure constraint has `=' and does not have `+'. Also, see @@ -1519,17 +1555,29 @@ expand_asm_operands (string, outputs, in return; } + if (found_plus && val == NULL_TREE) + { + error ("inout operand to `asm' should have value"); + return; + } /* If an output operand is not a decl or indirect ref and our constraint allows a register, make a temporary to act as an intermediate. Make the asm insn write into that, then our caller will copy it to - the real output operand. Likewise for promoted variables. */ + the real output operand. Likewise for promoted variables, + and for when we ignore the output (but then we don't want to have + the caller copy it anywhere). */ - if (TREE_CODE (val) == INDIRECT_REF - || (TREE_CODE_CLASS (TREE_CODE (val)) == 'd' - && ! (GET_CODE (DECL_RTL (val)) == REG - && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))) - || ! allows_reg - || found_plus) + if (val == NULL_TREE) + { + char *constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail)); + output_rtx[i] = gen_reg_rtx (choose_constraint_mode(constraint)); + } + else if (TREE_CODE (val) == INDIRECT_REF + || (TREE_CODE_CLASS (TREE_CODE (val)) == 'd' + && ! (GET_CODE (DECL_RTL (val)) == REG + && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))) + || ! allows_reg + || found_plus) { if (! allows_reg) mark_addressable (TREE_VALUE (tail)); @@ -1579,6 +1627,13 @@ expand_asm_operands (string, outputs, in { int j; int allows_reg = 0; + + /* Null inputs make little sense. */ + if (TREE_VALUE (tail) == NULL_TREE) + { + error ("input operand to `asm' should have value"); + return; + } /* If there's an erroneous arg, emit no insn, because the ASM_INPUT would get VOIDmode --- gcc/cp/parse.y.orig Sat Feb 7 14:12:50 1998 +++ gcc/cp/parse.y Sat Feb 7 14:12:33 1998 @@ -4065,6 +4065,8 @@ nonnull_asm_operands: asm_operand: STRING '(' expr ')' { $$ = build_tree_list ($$, $3); } + | STRING + { $$ = build_tree_list ($1, NULL_TREE); } ; asm_clobbers: --- gcc/ChangeLog~ Sun Jan 25 00:35:52 1998 +++ gcc/ChangeLog Sat Feb 7 14:21:05 1998 @@ -1,3 +1,12 @@ +Fri Feb 6 22:15:24 1998 Geoff Keating (geoffk@ozemail.com.au) + + * c-parse.in (asm_operand): Add new `ignore output' syntax. + * c-typeck.c (c_expand_asm_operands): If we are ignoring the + output, don't copy it anywhere. + * stmt.c (choose_constraint_mode): New function. + (expand_asm_operands): Handle `ignore output' syntax by creating a + dummy pseudo to output to. + Fri Jan 2 23:40:09 1998 Jim Wilson (wilson@cygnus.com) Jeffrey A Law (law@cygnus.com) --- gcc/cp/ChangeLog~ Sun Jan 25 00:36:04 1998 +++ gcc/cp/ChangeLog Sat Feb 7 14:21:35 1998 @@ -1,3 +1,7 @@ +Fri Feb 6 22:21:27 1998 Geoff Keating + + * parse.y (asm_operand): Add new `ignore output' syntax. + Sat Dec 20 13:00:30 1997 Jason Merrill * pt.c (instantiate_decl): Defer all templates but inline functions. --- gcc/extend.texi.orig Sat Feb 7 14:50:39 1998 +++ gcc/extend.texi Sat Feb 7 15:33:02 1998 @@ -2430,6 +2430,28 @@ and therefore they cannot take account of them when deciding how to optimize. +In some of these more complex @code{asm} statements, you need temporary +registers. You could just choose a register at random (and specify it +as clobbered), but it is usually better to instead make the temporary an +`output' of the @code{asm}; that way the register allocator can pick the +most convenient temporary. There is a special syntax to simplify using +such temporaries: if you omit the C expression specifying the output +destination, the output will be ignored. For instance, the following +example implements test-and-set on RS6000, using a temporary +condition code register: + +@example +asm volatile("0: lwarx %0,0,%3;" + " cmpwi %1,%0,0;" + " bne %1,1f;" + " stwcx. %4,0,%3;" + " bne- 0b;" + "1: " + : "=&r"(oldvalue), "=y", "=x" + : "r"(address), "r"(1) + : "memory"); +@end example + @cindex macros containing @code{asm} Usually the most convenient way to use these @code{asm} instructions is to encapsulate them in macros that look like functions. For example,