diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-11-16 06:40:52 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-11-16 06:40:52 +0000 |
commit | fcf58632e1d3c4f06052ca818ad1c0485e763f39 (patch) | |
tree | 32a3bd41ae4fe487c060eb303b0bd60332762f27 /gcc/config | |
parent | 547ca3bd8e3409e0a796c9daace21b8fb981e866 (diff) | |
download | gcc-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.md | 58 | ||||
-rw-r--r-- | gcc/config/avr/avr-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/avr/avr.c | 39 | ||||
-rw-r--r-- | gcc/config/avr/avr.h | 6 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 5 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 2 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 78 | ||||
-rw-r--r-- | gcc/config/i386/predicates.md | 20 | ||||
-rw-r--r-- | gcc/config/iq2000/iq2000-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/iq2000/iq2000.c | 39 | ||||
-rw-r--r-- | gcc/config/iq2000/iq2000.h | 13 |
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. */ |