aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1995-06-27 07:27:14 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1995-06-27 07:27:14 -0400
commit65fed0cb234b7fb05da20b74be80460bffd96a06 (patch)
treea50614a77a7491dae026120f8d6792ad40ebf768
parent2ecc7cad44f6880075acfc4c12a99c6593f82d3a (diff)
downloadgcc-65fed0cb234b7fb05da20b74be80460bffd96a06.zip
gcc-65fed0cb234b7fb05da20b74be80460bffd96a06.tar.gz
gcc-65fed0cb234b7fb05da20b74be80460bffd96a06.tar.bz2
(expand_asm_operands): Handle input operands that may not be in a
register. From-SVN: r10060
-rw-r--r--gcc/stmt.c55
1 files changed, 49 insertions, 6 deletions
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 02ac0e6..02ef0db 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -1517,6 +1517,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
for (tail = inputs; tail; tail = TREE_CHAIN (tail))
{
int j;
+ int allows_reg = 0;
/* If there's an erroneous arg, emit no insn,
because the ASM_INPUT would get VOIDmode
@@ -1532,23 +1533,65 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
/* Make sure constraint has neither `=' nor `+'. */
- for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)); j++)
- if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '='
- || TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] == '+')
+ for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++)
+ switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j])
{
+ case '+': case '=':
error ("input operand constraint contains `%c'",
TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]);
return;
+
+ case '?': case '!': case '*': case '%': case '&':
+ case '0': case '1': case '2': case '3': case '4':
+ case 'V': case 'm': case 'o': case '<': case '>':
+ case 'E': case 'F': case 'G': case 'H': case 'X':
+ case 's': case 'i': case 'n':
+ case 'I': case 'J': case 'K': case 'L': case 'M':
+ case 'N': case 'O': case 'P': case ',':
+#ifdef EXTRA_CONSTRAINT
+ case 'Q': case 'R': case 'S': case 'T': case 'U':
+#endif
+ break;
+
+ case 'p': case 'g': case 'r':
+ default:
+ allows_reg = 1;
+ break;
}
+ if (! allows_reg)
+ mark_addressable (TREE_VALUE (tail));
+
XVECEXP (body, 3, i) /* argvec */
= expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
if (CONSTANT_P (XVECEXP (body, 3, i))
&& ! general_operand (XVECEXP (body, 3, i),
TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)))))
- XVECEXP (body, 3, i)
- = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
- XVECEXP (body, 3, i));
+ {
+ if (allows_reg)
+ XVECEXP (body, 3, i)
+ = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
+ XVECEXP (body, 3, i));
+ else
+ XVECEXP (body, 3, i)
+ = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
+ XVECEXP (body, 3, i));
+ }
+
+ if (! allows_reg
+ && (GET_CODE (XVECEXP (body, 3, i)) == REG
+ || GET_CODE (XVECEXP (body, 3, i)) == SUBREG
+ || GET_CODE (XVECEXP (body, 3, i)) == CONCAT))
+ {
+ tree type = TREE_TYPE (TREE_VALUE (tail));
+ rtx memloc = assign_stack_temp (TYPE_MODE (type),
+ int_size_in_bytes (type), 1);
+
+ MEM_IN_STRUCT_P (memloc) = AGGREGATE_TYPE_P (type);
+ emit_move_insn (memloc, XVECEXP (body, 3, i));
+ XVECEXP (body, 3, i) = memloc;
+ }
+
XVECEXP (body, 4, i) /* constraints */
= gen_rtx (ASM_INPUT, TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
TREE_STRING_POINTER (TREE_PURPOSE (tail)));