summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2009-11-16 06:40:52 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2009-11-16 06:40:52 +0000
commitfcf58632e1d3c4f06052ca818ad1c0485e763f39 (patch)
tree32a3bd41ae4fe487c060eb303b0bd60332762f27 /gcc/config
parent547ca3bd8e3409e0a796c9daace21b8fb981e866 (diff)
downloadgcc-fcf58632e1d3c4f06052ca818ad1c0485e763f39.tar.gz
2009-11-16 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 154195 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@154196 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/arm/arm.md58
-rw-r--r--gcc/config/avr/avr-protos.h1
-rw-r--r--gcc/config/avr/avr.c39
-rw-r--r--gcc/config/avr/avr.h6
-rw-r--r--gcc/config/i386/i386.c5
-rw-r--r--gcc/config/i386/i386.h2
-rw-r--r--gcc/config/i386/i386.md78
-rw-r--r--gcc/config/i386/predicates.md20
-rw-r--r--gcc/config/iq2000/iq2000-protos.h2
-rw-r--r--gcc/config/iq2000/iq2000.c39
-rw-r--r--gcc/config/iq2000/iq2000.h13
11 files changed, 146 insertions, 117 deletions
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 691bd5568d7..8527208d6f3 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -523,7 +523,7 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(plus:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "r,0")))
+ (match_operand:DI 1 "s_register_operand" "0,r")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
"#"
@@ -552,7 +552,7 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(plus:DI (zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "r,0")))
+ (match_operand:DI 1 "s_register_operand" "0,r")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
"#"
@@ -1015,7 +1015,7 @@
(define_insn "*subdi_di_zesidi"
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
+ (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
(zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))))
(clobber (reg:CC CC_REGNUM))]
@@ -1027,7 +1027,7 @@
(define_insn "*subdi_di_sesidi"
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
+ (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
(sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))))
(clobber (reg:CC CC_REGNUM))]
@@ -1041,7 +1041,7 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(minus:DI (zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))
+ (match_operand:DI 1 "s_register_operand" "0,r")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
@@ -1053,7 +1053,7 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(minus:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))
+ (match_operand:DI 1 "s_register_operand" "0,r")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
@@ -1222,7 +1222,7 @@
(define_insn "*arm_mulsi3"
[(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
(mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 1 "s_register_operand" "%?r,0")))]
+ (match_operand:SI 1 "s_register_operand" "%0,r")))]
"TARGET_32BIT && !arm_arch6"
"mul%?\\t%0, %2, %1"
[(set_attr "insn" "mul")
@@ -1276,7 +1276,7 @@
[(set (reg:CC_NOOV CC_REGNUM)
(compare:CC_NOOV (mult:SI
(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 1 "s_register_operand" "%?r,0"))
+ (match_operand:SI 1 "s_register_operand" "%0,r"))
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
(mult:SI (match_dup 2) (match_dup 1)))]
@@ -1304,7 +1304,7 @@
[(set (reg:CC_NOOV CC_REGNUM)
(compare:CC_NOOV (mult:SI
(match_operand:SI 2 "s_register_operand" "r,r")
- (match_operand:SI 1 "s_register_operand" "%?r,0"))
+ (match_operand:SI 1 "s_register_operand" "%0,r"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=&r,&r"))]
"TARGET_ARM && !arm_arch6"
@@ -1332,8 +1332,8 @@
[(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
(plus:SI
(mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
- (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
- (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
+ (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
+ (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
"TARGET_32BIT && !arm_arch6"
"mla%?\\t%0, %2, %1, %3"
[(set_attr "insn" "mla")
@@ -1357,8 +1357,8 @@
(compare:CC_NOOV
(plus:SI (mult:SI
(match_operand:SI 2 "s_register_operand" "r,r,r,r")
- (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
- (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
+ (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
+ (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
(plus:SI (mult:SI (match_dup 2) (match_dup 1))
@@ -1391,7 +1391,7 @@
(compare:CC_NOOV
(plus:SI (mult:SI
(match_operand:SI 2 "s_register_operand" "r,r,r,r")
- (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
+ (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
(match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
@@ -1571,7 +1571,7 @@
(truncate:SI
(lshiftrt:DI
(mult:DI
- (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
+ (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
(sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
(const_int 32))))
(clobber (match_scratch:SI 3 "=&r,&r"))]
@@ -1615,7 +1615,7 @@
(truncate:SI
(lshiftrt:DI
(mult:DI
- (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
+ (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
(zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
(const_int 32))))
(clobber (match_scratch:SI 3 "=&r,&r"))]
@@ -1870,7 +1870,7 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(and:DI (zero_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
+ (match_operand:DI 1 "s_register_operand" "0,r")))]
"TARGET_32BIT"
"#"
"TARGET_32BIT && reload_completed"
@@ -1891,7 +1891,7 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(and:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
+ (match_operand:DI 1 "s_register_operand" "0,r")))]
"TARGET_32BIT"
"#"
[(set_attr "length" "8")]
@@ -2457,8 +2457,8 @@
; constants for op 2 will never be given to these patterns.
(define_insn_and_split "*anddi_notdi_di"
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
- (match_operand:DI 2 "s_register_operand" "0,r")))]
+ (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
+ (match_operand:DI 2 "s_register_operand" "r,0")))]
"TARGET_32BIT"
"#"
"TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
@@ -2612,7 +2612,7 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(ior:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
+ (match_operand:DI 1 "s_register_operand" "0,r")))]
"TARGET_32BIT"
"#"
[(set_attr "length" "8")
@@ -2742,7 +2742,7 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(xor:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r"))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
+ (match_operand:DI 1 "s_register_operand" "0,r")))]
"TARGET_32BIT"
"#"
[(set_attr "length" "8")
@@ -2836,7 +2836,7 @@
(define_insn "*andsi_iorsi3_notsi"
[(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
- (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
+ (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
(match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
(not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
"TARGET_32BIT"
@@ -3190,7 +3190,7 @@
(define_insn "arm_ashldi3_1bit"
[(set (match_operand:DI 0 "s_register_operand" "=&r,r")
- (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
+ (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
(const_int 1)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT"
@@ -3249,7 +3249,7 @@
(define_insn "arm_ashrdi3_1bit"
[(set (match_operand:DI 0 "s_register_operand" "=&r,r")
- (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
+ (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
(const_int 1)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT"
@@ -3305,7 +3305,7 @@
(define_insn "arm_lshrdi3_1bit"
[(set (match_operand:DI 0 "s_register_operand" "=&r,r")
- (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
+ (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
(const_int 1)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT"
@@ -3552,10 +3552,10 @@
)
;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
-;; The second alternative is to allow the common case of a *full* overlap.
+;; The first alternative allows the common case of a *full* overlap.
(define_insn "*arm_negdi2"
[(set (match_operand:DI 0 "s_register_operand" "=&r,r")
- (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
+ (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
@@ -3708,7 +3708,7 @@
(define_insn_and_split "one_cmpldi2"
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
- (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
+ (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
"TARGET_32BIT"
"#"
"TARGET_32BIT && reload_completed"
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index c39b97be177..e014085ac34 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -39,6 +39,7 @@ extern int avr_simple_epilogue (void);
extern void gas_output_limited_string (FILE *file, const char *str);
extern void gas_output_ascii (FILE *file, const char *str, size_t length);
extern int avr_hard_regno_rename_ok (unsigned int, unsigned int);
+extern rtx avr_return_addr_rtx (int count, const_rtx tem);
#ifdef TREE_CODE
extern void asm_output_external (FILE *file, tree decl, char *name);
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index cb2d709c89a..b1713a89c20 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -461,6 +461,31 @@ rtx avr_builtin_setjmp_frame_value (void)
gen_int_mode (STARTING_FRAME_OFFSET, Pmode));
}
+/* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3 byte PC).
+ This is return address of function. */
+rtx
+avr_return_addr_rtx (int count, const_rtx tem)
+{
+ rtx r;
+
+ /* Can only return this functions return address. Others not supported. */
+ if (count)
+ return NULL;
+
+ if (AVR_3_BYTE_PC)
+ {
+ r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
+ warning (0, "'builtin_return_address' contains only 2 bytes of address");
+ }
+ else
+ r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
+
+ r = gen_rtx_PLUS (Pmode, tem, r);
+ r = gen_frame_mem (Pmode, memory_address (Pmode, r));
+ r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
+ return r;
+}
+
/* Return 1 if the function epilogue is just a single "ret". */
int
@@ -560,6 +585,7 @@ expand_prologue (void)
cfun->machine->is_signal = signal_function_p (current_function_decl);
cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl);
cfun->machine->is_OS_main = avr_OS_main_function_p (current_function_decl);
+ cfun->machine->stack_usage = 0;
/* Prologue: naked. */
if (cfun->machine->is_naked)
@@ -588,10 +614,12 @@ expand_prologue (void)
/* Push zero reg. */
insn = emit_move_insn (pushbyte, zero_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage++;
/* Push tmp reg. */
insn = emit_move_insn (pushbyte, tmp_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage++;
/* Push SREG. */
insn = emit_move_insn (tmp_reg_rtx,
@@ -599,6 +627,7 @@ expand_prologue (void)
RTX_FRAME_RELATED_P (insn) = 1;
insn = emit_move_insn (pushbyte, tmp_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage++;
/* Push RAMPZ. */
if(AVR_HAVE_RAMPZ
@@ -609,6 +638,7 @@ expand_prologue (void)
RTX_FRAME_RELATED_P (insn) = 1;
insn = emit_move_insn (pushbyte, tmp_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage++;
}
/* Clear zero reg. */
@@ -630,6 +660,7 @@ expand_prologue (void)
emit_insn (gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
gen_int_mode (size + live_seq, HImode)));
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage += size + live_seq;
}
else
{
@@ -641,6 +672,7 @@ expand_prologue (void)
/* Emit push of register to save. */
insn=emit_move_insn (pushbyte, gen_rtx_REG (QImode, reg));
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage++;
}
}
if (frame_pointer_needed)
@@ -650,6 +682,7 @@ expand_prologue (void)
/* Push frame pointer. */
insn = emit_move_insn (pushword, frame_pointer_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
+ cfun->machine->stack_usage += 2;
}
if (!size)
@@ -756,6 +789,7 @@ expand_prologue (void)
emit_insn (sp_plus_insns);
else
emit_insn (fp_plus_insns);
+ cfun->machine->stack_usage += size;
}
}
}
@@ -785,6 +819,11 @@ avr_asm_function_end_prologue (FILE *file)
}
fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
get_frame_size());
+ fprintf (file, "/* stack size = %d */\n",
+ cfun->machine->stack_usage);
+ /* Create symbol stack offset here so all functions have it. Add 1 to stack
+ usage for offset so that SP + .L__stack_offset = return address. */
+ fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
}
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 782ad11627b..4e07a2ecded 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -367,8 +367,7 @@ enum reg_class {
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
OFFSET = avr_initial_elimination_offset (FROM, TO)
-#define RETURN_ADDR_RTX(count, x) \
- gen_rtx_MEM (Pmode, memory_address (Pmode, plus_constant (tem, 1)))
+#define RETURN_ADDR_RTX(count, tem) avr_return_addr_rtx (count, tem)
/* Don't use Push rounding. expr.c: emit_single_push_insn is broken
for POST_DEC targets (PR27386). */
@@ -857,4 +856,7 @@ struct GTY(()) machine_function
/* 'true' - if current function is a 'main' function
as specified by the "OS_main" attribute. */
int is_OS_main;
+
+ /* Current function stack size. */
+ int stack_usage;
};
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 8630640ef52..69e4e61b1b9 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1553,11 +1553,6 @@ static unsigned int initial_ix86_arch_features[X86_ARCH_LAST] = {
/* X86_ARCH_BSWAP: Byteswap was added for 80486. */
~m_386,
-
- /* X86_ARCH_CALL_ESP: P6 processors will jump to the address after
- the decrement (so they will execute return address as code). See
- Pentium Pro errata 70, Pentium 2 errata A33, Pentium 3 errata E17. */
- ~(m_386 | m_486 | m_PENT | m_PPRO),
};
static const unsigned int x86_accumulate_outgoing_args
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 4bc8ef18500..eb1c86fa2a8 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -402,7 +402,6 @@ enum ix86_arch_indices {
X86_ARCH_CMPXCHG8B,
X86_ARCH_XADD,
X86_ARCH_BSWAP,
- X86_ARCH_CALL_ESP,
X86_ARCH_LAST
};
@@ -414,7 +413,6 @@ extern unsigned char ix86_arch_features[X86_ARCH_LAST];
#define TARGET_CMPXCHG8B ix86_arch_features[X86_ARCH_CMPXCHG8B]
#define TARGET_XADD ix86_arch_features[X86_ARCH_XADD]
#define TARGET_BSWAP ix86_arch_features[X86_ARCH_BSWAP]
-#define TARGET_CALL_ESP ix86_arch_features[X86_ARCH_CALL_ESP]
#define TARGET_FISTTP (TARGET_SSE3 && TARGET_80387)
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 2a313665c15..d896205530f 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -14562,6 +14562,10 @@
;; checked for calls. This is a bug in the generic code, but it isn't that
;; easy to fix. Ignore it for now and be prepared to fix things up.
+;; P6 processors will jump to the address after the decrement when %esp
+;; is used as a call operand, so they will execute return address as a code.
+;; See Pentium Pro errata 70, Pentium 2 errata A33 and Pentium 3 errata E17.
+
;; Call subroutine returning no value.
(define_expand "call_pop"
@@ -14592,27 +14596,13 @@
}
[(set_attr "type" "call")])
-(define_insn "*call_pop_1_esp"
- [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
- (match_operand:SI 1 "" ""))
- (set (reg:SI SP_REG)
- (plus:SI (reg:SI SP_REG)
- (match_operand:SI 2 "immediate_operand" "i")))]
- "!TARGET_64BIT && TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
-{
- if (constant_call_address_operand (operands[0], Pmode))
- return "call\t%P0";
- return "call\t%A0";
-}
- [(set_attr "type" "call")])
-
(define_insn "*call_pop_1"
[(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm"))
(match_operand:SI 1 "" ""))
(set (reg:SI SP_REG)
(plus:SI (reg:SI SP_REG)
(match_operand:SI 2 "immediate_operand" "i")))]
- "!TARGET_64BIT && !TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
+ "!TARGET_64BIT && !SIBLING_CALL_P (insn)"
{
if (constant_call_address_operand (operands[0], Pmode))
return "call\t%P0";
@@ -14664,21 +14654,10 @@
}
[(set_attr "type" "call")])
-(define_insn "*call_1_esp"
- [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm"))
- (match_operand 1 "" ""))]
- "!TARGET_64BIT && TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
-{
- if (constant_call_address_operand (operands[0], Pmode))
- return "call\t%P0";
- return "call\t%A0";
-}
- [(set_attr "type" "call")])
-
(define_insn "*call_1"
[(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lsm"))
(match_operand 1 "" ""))]
- "!TARGET_64BIT && !TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
+ "!TARGET_64BIT && !SIBLING_CALL_P (insn)"
{
if (constant_call_address_operand (operands[0], Pmode))
return "call\t%P0";
@@ -21158,8 +21137,9 @@
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand:SI 1 "constant_call_address_operand" ""))
(match_operand:SI 2 "" "")))
- (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
- (match_operand:SI 3 "immediate_operand" "")))]
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 3 "immediate_operand" "")))]
"!TARGET_64BIT"
{
if (SIBLING_CALL_P (insn))
@@ -21169,27 +21149,14 @@
}
[(set_attr "type" "callv")])
-(define_insn "*call_value_pop_1_esp"
- [(set (match_operand 0 "" "")
- (call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
- (match_operand:SI 2 "" "")))
- (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
- (match_operand:SI 3 "immediate_operand" "i")))]
- "!TARGET_64BIT && TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
-{
- if (constant_call_address_operand (operands[1], Pmode))
- return "call\t%P1";
- return "call\t%A1";
-}
- [(set_attr "type" "callv")])
-
(define_insn "*call_value_pop_1"
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm"))
(match_operand:SI 2 "" "")))
- (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
- (match_operand:SI 3 "immediate_operand" "i")))]
- "!TARGET_64BIT && !TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 3 "immediate_operand" "i")))]
+ "!TARGET_64BIT && !SIBLING_CALL_P (insn)"
{
if (constant_call_address_operand (operands[1], Pmode))
return "call\t%P1";
@@ -21201,8 +21168,9 @@
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,U"))
(match_operand:SI 2 "" "")))
- (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
- (match_operand:SI 3 "immediate_operand" "i,i")))]
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand:SI 3 "immediate_operand" "i,i")))]
"!TARGET_64BIT && SIBLING_CALL_P (insn)"
"@
jmp\t%P1
@@ -21261,23 +21229,11 @@
}
[(set_attr "type" "callv")])
-(define_insn "*call_value_1_esp"
- [(set (match_operand 0 "" "")
- (call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
- (match_operand:SI 2 "" "")))]
- "!TARGET_64BIT && TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
-{
- if (constant_call_address_operand (operands[1], Pmode))
- return "call\t%P1";
- return "call\t%A1";
-}
- [(set_attr "type" "callv")])
-
(define_insn "*call_value_1"
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand:SI 1 "call_insn_operand" "lsm"))
(match_operand:SI 2 "" "")))]
- "!TARGET_64BIT && !TARGET_CALL_ESP && !SIBLING_CALL_P (insn)"
+ "!TARGET_64BIT && !SIBLING_CALL_P (insn)"
{
if (constant_call_address_operand (operands[1], Pmode))
return "call\t%P1";
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index dee6df9fa01..3ade8f5a33d 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -533,6 +533,22 @@
FIRST_PSEUDO_REGISTER, LAST_VIRTUAL_REGISTER));
})
+;; P6 processors will jump to the address after the decrement when %esp
+;; is used as a call operand, so they will execute return address as a code.
+;; See Pentium Pro errata 70, Pentium 2 errata A33 and Pentium 3 errata E17.
+
+(define_predicate "call_register_no_elim_operand"
+ (match_operand 0 "register_operand")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ if (!TARGET_64BIT && op == stack_pointer_rtx)
+ return 0;
+
+ return register_no_elim_operand (op, mode);
+})
+
;; Similarly, but include the stack pointer. This is used to prevent esp
;; from being used as an index reg.
(define_predicate "index_register_operand"
@@ -561,9 +577,7 @@
;; Test for a valid operand for a call instruction.
(define_predicate "call_insn_operand"
(ior (match_operand 0 "constant_call_address_operand")
- (ior (and (match_operand 0 "register_no_elim_operand")
- (ior (match_test "TARGET_CALL_ESP")
- (match_operand 0 "index_register_operand")))
+ (ior (match_operand 0 "call_register_no_elim_operand")
(match_operand 0 "memory_operand"))))
;; Similarly, but for tail calls, in which we cannot allow memory references.
diff --git a/gcc/config/iq2000/iq2000-protos.h b/gcc/config/iq2000/iq2000-protos.h
index 0e4dba77eb4..c01b6eee3b9 100644
--- a/gcc/config/iq2000/iq2000-protos.h
+++ b/gcc/config/iq2000/iq2000-protos.h
@@ -47,7 +47,7 @@ extern void gen_conditional_branch (rtx *, enum machine_mode);
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
extern struct rtx_def * function_arg (CUMULATIVE_ARGS *, enum machine_mode, const_tree, int);
-extern rtx iq2000_function_value (const_tree, const_tree);
+extern bool iq2000_function_value_regno_p (const unsigned int);
#endif
#endif /* ! GCC_IQ2000_PROTOS_H */
diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c
index 2e2f29aaeb7..4359f5edfb9 100644
--- a/gcc/config/iq2000/iq2000.c
+++ b/gcc/config/iq2000/iq2000.c
@@ -168,6 +168,8 @@ static bool iq2000_legitimate_address_p (enum machine_mode, rtx, bool);
static bool iq2000_can_eliminate (const int, const int);
static void iq2000_asm_trampoline_template (FILE *);
static void iq2000_trampoline_init (rtx, tree, rtx);
+static rtx iq2000_function_value (const_tree, const_tree, bool);
+static rtx iq2000_libcall_value (enum machine_mode, const_rtx);
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS iq2000_init_builtins
@@ -197,6 +199,10 @@ static void iq2000_trampoline_init (rtx, tree, rtx);
#undef TARGET_PROMOTE_PROTOTYPES
#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE iq2000_function_value
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE iq2000_libcall_value
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY iq2000_return_in_memory
#undef TARGET_PASS_BY_REFERENCE
@@ -2210,18 +2216,47 @@ iq2000_select_section (tree decl, int reloc ATTRIBUTE_UNUSED,
/* Return register to use for a function return value with VALTYPE for function
FUNC. */
-rtx
-iq2000_function_value (const_tree valtype, const_tree func)
+static rtx
+iq2000_function_value (const_tree valtype,
+ const_tree fn_decl_or_type,
+ bool outgoing ATTRIBUTE_UNUSED)
{
int reg = GP_RETURN;
enum machine_mode mode = TYPE_MODE (valtype);
int unsignedp = TYPE_UNSIGNED (valtype);
+ tree func = fn_decl_or_type;
+
+ if (fn_decl_or_type
+ && !DECL_P (fn_decl_or_type))
+ fn_decl_or_type = NULL;
/* Since we promote return types, we must promote the mode here too. */
mode = promote_function_mode (valtype, mode, &unsignedp, func, 1);
return gen_rtx_REG (mode, reg);
}
+
+/* Worker function for TARGET_LIBCALL_VALUE. */
+
+static rtx
+iq2000_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
+{
+ return gen_rtx_REG (((GET_MODE_CLASS (mode) != MODE_INT
+ || GET_MODE_SIZE (mode) >= 4)
+ ? mode : SImode),
+ GP_RETURN);
+}
+
+/* Worker function for FUNCTION_VALUE_REGNO_P.
+
+ On the IQ2000, R2 and R3 are the only register thus used. */
+
+bool
+iq2000_function_value_regno_p (const unsigned int regno)
+{
+ return (regno == GP_RETURN);
+}
+
/* Return true when an argument must be passed by reference. */
diff --git a/gcc/config/iq2000/iq2000.h b/gcc/config/iq2000/iq2000.h
index 4dadbdb5472..0b207b5e8d4 100644
--- a/gcc/config/iq2000/iq2000.h
+++ b/gcc/config/iq2000/iq2000.h
@@ -422,20 +422,9 @@ typedef struct iq2000_args
(((N) >= GP_ARG_FIRST && (N) <= GP_ARG_LAST))
-/* How Scalar Function Values are Returned. */
-
-#define FUNCTION_VALUE(VALTYPE, FUNC) iq2000_function_value (VALTYPE, FUNC)
-
-#define LIBCALL_VALUE(MODE) \
- gen_rtx_REG (((GET_MODE_CLASS (MODE) != MODE_INT \
- || GET_MODE_SIZE (MODE) >= 4) \
- ? (MODE) \
- : SImode), \
- GP_RETURN)
-
/* On the IQ2000, R2 and R3 are the only register thus used. */
-#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN)
+#define FUNCTION_VALUE_REGNO_P(N) iq2000_function_value_regno_p (N)
/* How Large Values are Returned. */