From: ian Date: Mon, 8 Nov 2010 04:34:32 +0000 (+0000) Subject: gcc/: X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=457123d6b452607d10df2f2355f8bc1478d426da gcc/: PR target/46089 * config/i386/i386.c (split_stack_fn_large): New static variable. (ix86_expand_split_stack_prologue): Handle large model. libgcc/: * config/i386/morestack.S (__morestack_large_model): New function. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166427 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ce49a50cd77..4088046710f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2010-11-07 Ian Lance Taylor + + PR target/46089 + * config/i386/i386.c (split_stack_fn_large): New static variable. + (ix86_expand_split_stack_prologue): Handle large model. + 2010-11-07 Andreas Schwab * config/m68k/m68k.c (m68k_delegitimize_address): Update to handle diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 6e086bc5f72..b4ba2c16627 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -11050,6 +11050,11 @@ split_stack_prologue_scratch_regno (void) static GTY(()) rtx split_stack_fn; +/* A SYMBOL_REF for the more stack function when using the large + model. */ + +static GTY(()) rtx split_stack_fn_large; + /* Handle -fsplit-stack. These are the first instructions in the function, even before the regular prologue. */ @@ -11062,6 +11067,7 @@ ix86_expand_split_stack_prologue (void) rtx label, limit, current, jump_insn, allocate_rtx, call_insn, call_fusage; rtx scratch_reg = NULL_RTX; rtx varargs_label = NULL_RTX; + rtx fn; gcc_assert (flag_split_stack && reload_completed); @@ -11125,6 +11131,10 @@ ix86_expand_split_stack_prologue (void) add_reg_note (jump_insn, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100)); + if (split_stack_fn == NULL_RTX) + split_stack_fn = gen_rtx_SYMBOL_REF (Pmode, "__morestack"); + fn = split_stack_fn; + /* Get more stack space. We pass in the desired stack space and the size of the arguments to copy to the new stack. In 32-bit mode we push the parameters; __morestack will return on a new stack @@ -11135,9 +11145,10 @@ ix86_expand_split_stack_prologue (void) call_fusage = NULL_RTX; if (TARGET_64BIT) { - rtx reg; + rtx reg10, reg11; - reg = gen_rtx_REG (Pmode, R10_REG); + reg10 = gen_rtx_REG (Pmode, R10_REG); + reg11 = gen_rtx_REG (Pmode, R11_REG); /* If this function uses a static chain, it will be in %r10. Preserve it across the call to __morestack. */ @@ -11146,24 +11157,69 @@ ix86_expand_split_stack_prologue (void) rtx rax; rax = gen_rtx_REG (Pmode, AX_REG); - emit_move_insn (rax, reg); + emit_move_insn (rax, reg10); use_reg (&call_fusage, rax); } - emit_move_insn (reg, allocate_rtx); - use_reg (&call_fusage, reg); - reg = gen_rtx_REG (Pmode, R11_REG); - emit_move_insn (reg, GEN_INT (args_size)); - use_reg (&call_fusage, reg); + if (ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC) + { + HOST_WIDE_INT argval; + + /* When using the large model we need to load the address + into a register, and we've run out of registers. So we + switch to a different calling convention, and we call a + different function: __morestack_large. We pass the + argument size in the upper 32 bits of r10 and pass the + frame size in the lower 32 bits. */ + gcc_assert ((allocate & 0xffffffff) == allocate); + gcc_assert (((HOST_WIDE_INT) args_size & 0xffffffff) + == (HOST_WIDE_INT) args_size); + + if (split_stack_fn_large == NULL_RTX) + split_stack_fn_large = + gen_rtx_SYMBOL_REF (Pmode, "__morestack_large_model"); + + if (ix86_cmodel == CM_LARGE_PIC) + { + rtx label, x; + + label = gen_label_rtx (); + emit_label (label); + LABEL_PRESERVE_P (label) = 1; + emit_insn (gen_set_rip_rex64 (reg10, label)); + emit_insn (gen_set_got_offset_rex64 (reg11, label)); + emit_insn (gen_adddi3 (reg10, reg10, reg11)); + x = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, split_stack_fn_large), + UNSPEC_GOT); + x = gen_rtx_CONST (Pmode, x); + emit_move_insn (reg11, x); + x = gen_rtx_PLUS (Pmode, reg10, reg11); + x = gen_const_mem (Pmode, x); + emit_move_insn (reg11, x); + } + else + emit_move_insn (reg11, split_stack_fn_large); + + fn = reg11; + + argval = ((HOST_WIDE_INT) args_size << 32) + allocate; + emit_move_insn (reg10, GEN_INT (argval)); + } + else + { + emit_move_insn (reg10, allocate_rtx); + emit_move_insn (reg11, GEN_INT (args_size)); + use_reg (&call_fusage, reg11); + } + + use_reg (&call_fusage, reg10); } else { emit_insn (gen_push (GEN_INT (args_size))); emit_insn (gen_push (allocate_rtx)); } - if (split_stack_fn == NULL_RTX) - split_stack_fn = gen_rtx_SYMBOL_REF (Pmode, "__morestack"); - call_insn = ix86_expand_call (NULL_RTX, gen_rtx_MEM (QImode, split_stack_fn), + call_insn = ix86_expand_call (NULL_RTX, gen_rtx_MEM (QImode, fn), GEN_INT (UNITS_PER_WORD), constm1_rtx, NULL_RTX, 0); add_function_usage_to (call_insn, call_fusage); diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index ea864d33dcb..21099ab697d 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,9 @@ +2010-11-07 Ian Lance Taylor + + PR target/46089 + * config/i386/morestack.S (__morestack_large_model): New + function. + 2010-10-23 Nathan Froyd * config/libbid/bid_gcc_intrinsics.h (LIBGCC2_WORDS_BIG_ENDIAN): diff --git a/libgcc/config/i386/morestack.S b/libgcc/config/i386/morestack.S index 79abba3ead1..10fa1fdf73a 100644 --- a/libgcc/config/i386/morestack.S +++ b/libgcc/config/i386/morestack.S @@ -488,6 +488,40 @@ DW.ref.__gcc_personality_v0: #endif #endif +#ifdef __x86_64__ + +# This entry point is used for the large model. With this entry point +# the upper 32 bits of %r10 hold the argument size and the lower 32 +# bits hold the new stack frame size. There doesn't seem to be a way +# to know in the assembler code that we are assembling for the large +# model, and there doesn't seem to be a large model multilib anyhow. +# If one is developed, then the non-PIC code is probably OK since we +# will probably be close to the morestack code, but the PIC code +# almost certainly needs to be changed. FIXME. + + .text + .global __morestack_large_model + .hidden __morestack_large_model + +#ifdef __ELF__ + .type __morestack_large_model,@function +#endif + +__morestack_large_model: + + .cfi_startproc + + movq %r10, %r11 + andl $0xffffffff, %r10d + sarq $32, %r11 + jmp __morestack + + .cfi_endproc +#ifdef __ELF__ + .size __morestack_large_model, . - __morestack_large_model +#endif + +#endif /* __x86_64__ */ # Initialize the stack test value when the program starts or when a # new thread starts. We don't know how large the main stack is, so we