Commit f833ffd4 by Richard Sandiford Committed by Richard Sandiford

mips.h (GLOBAL_POINTER_REGNUM): New macro.

	* config/mips/mips.h (GLOBAL_POINTER_REGNUM): New macro.
	(PIC_OFFSET_TABLE_REGNUM): Look at pic_offset_table_rtx after reload.
	(STARTING_FRAME_OFFSET): Don't allocate a cprestore slot for
	n32/64 PIC.
	(MUST_SAVE_REGISTERS): Delete.
	* config/mips/mips.c (mips_frame_info): Remove extra_size field.
	(machine_function): Add global_pointer field.
	(mips_classify_constant): Check for (const $gp) using pointer equality
	with pic_offset_table_rtx.
	(mips_classify_constant): Handle RELOC_LOADGP_HI and RELOC_LOADGP_LO.
	(mips_restore_gp): Use current_function_outgoing_args_size.
	(print_operand): Use PIC_OFFSET_TABLE_REGNUM instead of
	GP_REG_FIRST + 28.  Handle relocation strings that have
	more than one '('.
	(mips_reloc_string): Handle RELOC_LOADGP_HI and RELOC_LOADGP_LO.
	(mips_global_pointer): New function.
	(mips_save_reg_p): New function, mostly split out from...
	(compute_frame_size): ...here.  Remove handling of extra_size.
	Reclaim args_size if no variables depend on it.  Don't treat gp
	as a special case: handle it in the main GPR loop.
	(mips_initial_elimination_offset): Fix comment.
	(save_restore_insns): Save every register in the GPR mask,
	removing distinction between mask and real_mask.
	(mips_output_function_prologue): Update .frame psuedo-op after
	the removal of extra_size.  Move the SVR4 PIC stack allocation
	and cprestore instructions to mips_expand_prologue.
	(mips_gp_insn): New function.
	(mips_expand_prologue): Set REGNO (pic_offset_table_rtx) to
	the chosen global pointer.  Handle SVR4 PIC stack allocation
	in the same way as other ABIs.  Adjust varargs code accordingly.
	Emit a cprestore insn after allocating the stack.  Use mips_gp_insn
	to emit the loadgp sequence.  Follow it with a loadgp_blockage
	if not using explicit relocs.
	(mips_output_function_epilogue): Reinstate the default gp register.
	(mips16_gp_pseudo_reg): Use pic_offset_table_rtx.
	(mips16_optimize_gp): Likewise.
	* config/mips/mips.md (UNSPEC_LOADGP): Remove.
	(UNSPEC_SETJMP, UNSPEC_LONGJMP): Remove.
	(UNSPEC_CPRESTORE, RELOC_LOADGP_HI, RELOC_LOADGP_LO): New.
	(loadgp): Remove.
	(loadgp_blockage, cprestore): New instructions.
	(builtin_setjmp_setup): Implement using emit_move_insn.  Use
	pic_offset_table_rtx.
	(builtin_setjmp_setup_32, builtin_setjmp_setup_64): Remove.
	(builtin_longjmp): Use gen_raw_REG to force use of $28.

Co-Authored-By: Alexandre Oliva <aoliva@redhat.com>

From-SVN: r67656
parent 32ad6a47
2003-06-09 Richard Sandiford <rsandifo@redhat.com> 2003-06-09 Richard Sandiford <rsandifo@redhat.com>
Alexandre Oliva <aoliva@redhat.com>
* config/mips/mips.h (GLOBAL_POINTER_REGNUM): New macro.
(PIC_OFFSET_TABLE_REGNUM): Look at pic_offset_table_rtx after reload.
(STARTING_FRAME_OFFSET): Don't allocate a cprestore slot for
n32/64 PIC.
(MUST_SAVE_REGISTERS): Delete.
* config/mips/mips.c (mips_frame_info): Remove extra_size field.
(machine_function): Add global_pointer field.
(mips_classify_constant): Check for (const $gp) using pointer equality
with pic_offset_table_rtx.
(mips_classify_constant): Handle RELOC_LOADGP_HI and RELOC_LOADGP_LO.
(mips_restore_gp): Use current_function_outgoing_args_size.
(print_operand): Use PIC_OFFSET_TABLE_REGNUM instead of
GP_REG_FIRST + 28. Handle relocation strings that have
more than one '('.
(mips_reloc_string): Handle RELOC_LOADGP_HI and RELOC_LOADGP_LO.
(mips_global_pointer): New function.
(mips_save_reg_p): New function, mostly split out from...
(compute_frame_size): ...here. Remove handling of extra_size.
Reclaim args_size if no variables depend on it. Don't treat gp
as a special case: handle it in the main GPR loop.
(mips_initial_elimination_offset): Fix comment.
(save_restore_insns): Save every register in the GPR mask,
removing distinction between mask and real_mask.
(mips_output_function_prologue): Update .frame psuedo-op after
the removal of extra_size. Move the SVR4 PIC stack allocation
and cprestore instructions to mips_expand_prologue.
(mips_gp_insn): New function.
(mips_expand_prologue): Set REGNO (pic_offset_table_rtx) to
the chosen global pointer. Handle SVR4 PIC stack allocation
in the same way as other ABIs. Adjust varargs code accordingly.
Emit a cprestore insn after allocating the stack. Use mips_gp_insn
to emit the loadgp sequence. Follow it with a loadgp_blockage
if not using explicit relocs.
(mips_output_function_epilogue): Reinstate the default gp register.
(mips16_gp_pseudo_reg): Use pic_offset_table_rtx.
(mips16_optimize_gp): Likewise.
* config/mips/mips.md (UNSPEC_LOADGP): Remove.
(UNSPEC_SETJMP, UNSPEC_LONGJMP): Remove.
(UNSPEC_CPRESTORE, RELOC_LOADGP_HI, RELOC_LOADGP_LO): New.
(loadgp): Remove.
(loadgp_blockage, cprestore): New instructions.
(builtin_setjmp_setup): Implement using emit_move_insn. Use
pic_offset_table_rtx.
(builtin_setjmp_setup_32, builtin_setjmp_setup_64): Remove.
(builtin_longjmp): Use gen_raw_REG to force use of $28.
2003-06-09 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips-protos.h (mips_output_division): Declare. * config/mips/mips-protos.h (mips_output_division): Declare.
* config/mips/mips.h (MASK_CHECK_RANGE_DIV): Remove. * config/mips/mips.h (MASK_CHECK_RANGE_DIV): Remove.
......
...@@ -1945,14 +1945,20 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; ...@@ -1945,14 +1945,20 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
kept in a register. */ kept in a register. */
#define NO_RECURSIVE_FUNCTION_CSE 1 #define NO_RECURSIVE_FUNCTION_CSE 1
/* The register number of the register used to address a table of /* The ABI-defined global pointer. Sometimes we use a different
static data addresses in memory. In some cases this register is register in leaf functions: see PIC_OFFSET_TABLE_REGNUM. */
defined by a processor's "application binary interface" (ABI). #define GLOBAL_POINTER_REGNUM (GP_REG_FIRST + 28)
When this macro is defined, RTL is generated for this register
once, as with the stack pointer and frame pointer registers. If /* We normally use $28 as the global pointer. However, when generating
this macro is not defined, it is up to the machine-dependent n32/64 PIC, it is better for leaf functions to use a call-clobbered
files to allocate such a register (if necessary). */ register instead. They can then avoid saving and restoring $28
#define PIC_OFFSET_TABLE_REGNUM (GP_REG_FIRST + 28) and perhaps avoid using a frame at all.
When a leaf function uses something other than $28, mips_expand_prologue
will modify pic_offset_table_rtx in place. Take the register number
from there after reload. */
#define PIC_OFFSET_TABLE_REGNUM \
(reload_completed ? REGNO (pic_offset_table_rtx) : GLOBAL_POINTER_REGNUM)
#define PIC_FUNCTION_ADDR_REGNUM (GP_REG_FIRST + 25) #define PIC_FUNCTION_ADDR_REGNUM (GP_REG_FIRST + 25)
...@@ -2353,23 +2359,14 @@ extern enum reg_class mips_char_to_class[256]; ...@@ -2353,23 +2359,14 @@ extern enum reg_class mips_char_to_class[256];
/* Stack layout; function entry, exit and calling. */ /* Stack layout; function entry, exit and calling. */
/* Define this if pushing a word on the stack
makes the stack pointer a smaller address. */
#define STACK_GROWS_DOWNWARD #define STACK_GROWS_DOWNWARD
/* Define this if the nominal address of the stack frame /* The offset of the first local variable from the beginning of the frame.
is at the high-address end of the local variables; See compute_frame_size for details about the frame layout. */
that is, each additional local variable allocated
goes at a more negative offset in the frame. */
/* #define FRAME_GROWS_DOWNWARD */
/* Offset within stack frame to start allocating local variables at.
If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
first local allocated. Otherwise, it is the offset to the BEGINNING
of the first local allocated. */
#define STARTING_FRAME_OFFSET \ #define STARTING_FRAME_OFFSET \
(current_function_outgoing_args_size \ (current_function_outgoing_args_size \
+ (TARGET_ABICALLS ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0)) + (TARGET_ABICALLS && !TARGET_NEWABI \
? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0))
/* Offset from the stack pointer register to an item dynamically /* Offset from the stack pointer register to an item dynamically
allocated on the stack, e.g., by `alloca'. allocated on the stack, e.g., by `alloca'.
...@@ -2837,13 +2834,6 @@ typedef struct mips_args { ...@@ -2837,13 +2834,6 @@ typedef struct mips_args {
(mips_abi == ABI_EABI && UNITS_PER_FPVALUE >= UNITS_PER_DOUBLE) (mips_abi == ABI_EABI && UNITS_PER_FPVALUE >= UNITS_PER_DOUBLE)
/* Tell prologue and epilogue if register REGNO should be saved / restored. */
#define MUST_SAVE_REGISTER(regno) \
((regs_ever_live[regno] && !call_used_regs[regno]) \
|| (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) \
|| (regno == (GP_REG_FIRST + 31) && regs_ever_live[GP_REG_FIRST + 31]))
/* Say that the epilogue uses the return address register. Note that /* Say that the epilogue uses the return address register. Note that
in the case of sibcalls, the values "used by the epilogue" are in the case of sibcalls, the values "used by the epilogue" are
considered live at the start of the called function. */ considered live at the start of the called function. */
......
...@@ -32,9 +32,7 @@ ...@@ -32,9 +32,7 @@
(UNSPEC_STORE_DF_HIGH 2) (UNSPEC_STORE_DF_HIGH 2)
(UNSPEC_GET_FNADDR 4) (UNSPEC_GET_FNADDR 4)
(UNSPEC_BLOCKAGE 6) (UNSPEC_BLOCKAGE 6)
(UNSPEC_LOADGP 7) (UNSPEC_CPRESTORE 8)
(UNSPEC_SETJMP 8)
(UNSPEC_LONGJMP 9)
(UNSPEC_EH_RECEIVER 10) (UNSPEC_EH_RECEIVER 10)
(UNSPEC_EH_RETURN 11) (UNSPEC_EH_RETURN 11)
(UNSPEC_CONSTTABLE_QI 12) (UNSPEC_CONSTTABLE_QI 12)
...@@ -67,7 +65,9 @@ ...@@ -67,7 +65,9 @@
(RELOC_GOT_DISP 104) (RELOC_GOT_DISP 104)
(RELOC_CALL16 105) (RELOC_CALL16 105)
(RELOC_CALL_HI 106) (RELOC_CALL_HI 106)
(RELOC_CALL_LO 107)]) (RELOC_CALL_LO 107)
(RELOC_LOADGP_HI 108)
(RELOC_LOADGP_LO 109)])
;; .................... ;; ....................
...@@ -5428,21 +5428,28 @@ move\\t%0,%z4\\n\\ ...@@ -5428,21 +5428,28 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "SF") (set_attr "mode" "SF")
(set_attr "length" "4")]) (set_attr "length" "4")])
;; Instructions to load the global pointer register. ;; The use of gp is hidden when not using explicit relocations.
;; This is volatile to make sure that the scheduler won't move any symbol_ref ;; This blockage instruction prevents the gp load from being
;; uses in front of it. All symbol_refs implicitly use the gp reg. ;; scheduled after an implicit use of gp. It also prevents
;; the load from being deleted as dead.
(define_insn "loadgp_blockage"
[(unspec_volatile [(reg:DI 28)] UNSPEC_BLOCKAGE)]
""
""
[(set_attr "type" "unknown")
(set_attr "mode" "none")
(set_attr "length" "0")])
(define_insn "loadgp" ;; Emit a .cprestore directive, which expands to a single store instruction.
[(set (reg:DI 28) ;; Note that we continue to use .cprestore for explicit reloc code so that
(unspec_volatile:DI [(match_operand 0 "immediate_operand" "") ;; jals inside inlines asms will work correctly.
(match_operand:DI 1 "register_operand" "")] (define_insn "cprestore"
UNSPEC_LOADGP)) [(unspec_volatile [(match_operand 0 "const_int_operand" "")]
(clobber (reg:DI 1))] UNSPEC_CPRESTORE)]
"" ""
"%[lui\\t$1,%%hi(%%neg(%%gp_rel(%0)))\\n\\taddiu\\t$1,$1,%%lo(%%neg(%%gp_rel(%0)))\\n\\tdaddu\\t$gp,$1,%1%]" ".cprestore\t%0"
[(set_attr "type" "move") [(set_attr "type" "store")
(set_attr "mode" "DI") (set_attr "length" "4")])
(set_attr "length" "12")])
;; Block moves, see mips.c for more details. ;; Block moves, see mips.c for more details.
;; Argument 0 is the destination ;; Argument 0 is the destination
...@@ -8776,55 +8783,45 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2" ...@@ -8776,55 +8783,45 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2"
(set_attr "mode" "none") (set_attr "mode" "none")
(set_attr "length" "24")]) (set_attr "length" "24")])
;; For o32/n32/n64, we save the gp in the jmp_buf as well. While it is ;; For TARGET_ABICALLS, we save the gp in the jmp_buf as well.
;; possible to either pull it off the stack (in the o32 case) or recalculate ;; While it is possible to either pull it off the stack (in the
;; it given t9 and our target label, it takes 3 or 4 insns to do so, and ;; o32 case) or recalculate it given t9 and our target label,
;; this is easy. ;; it takes 3 or 4 insns to do so.
(define_expand "builtin_setjmp_setup" (define_expand "builtin_setjmp_setup"
[(unspec [(match_operand 0 "register_operand" "r")] UNSPEC_SETJMP)] [(use (match_operand 0 "register_operand" ""))]
"TARGET_ABICALLS" "TARGET_ABICALLS"
" {
{ rtx addr;
if (Pmode == DImode)
emit_insn (gen_builtin_setjmp_setup_64 (operands[0]));
else
emit_insn (gen_builtin_setjmp_setup_32 (operands[0]));
DONE;
}")
(define_expand "builtin_setjmp_setup_32"
[(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
(const_int 12)))
(reg:SI 28))]
"TARGET_ABICALLS && ! (Pmode == DImode)"
"")
(define_expand "builtin_setjmp_setup_64" addr = plus_constant (operands[0], GET_MODE_SIZE (Pmode) * 3);
[(set (mem:DI (plus:DI (match_operand:DI 0 "register_operand" "r") emit_move_insn (gen_rtx_MEM (Pmode, addr), pic_offset_table_rtx);
(const_int 24))) DONE;
(reg:DI 28))] })
"TARGET_ABICALLS && Pmode == DImode"
"")
;; For o32/n32/n64, we need to arrange for longjmp to put the ;; Restore the gp that we saved above. Despite the comment, it seems that
;; target address in t9 so that we can use it for loading $gp. ;; older code did recalculate the gp from $25. Continue to jump through
;; $25 for compatibility (we lose nothing by doing so).
(define_expand "builtin_longjmp" (define_expand "builtin_longjmp"
[(unspec_volatile [(match_operand 0 "register_operand" "r")] UNSPEC_LONGJMP)] [(use (match_operand 0 "register_operand" "r"))]
"TARGET_ABICALLS" "TARGET_ABICALLS"
" "
{ {
/* The elements of the buffer are, in order: */ /* The elements of the buffer are, in order: */
int W = (Pmode == DImode ? 8 : 4); int W = GET_MODE_SIZE (Pmode);
rtx fp = gen_rtx_MEM (Pmode, operands[0]); rtx fp = gen_rtx_MEM (Pmode, operands[0]);
rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W)); rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W));
rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W)); rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W));
rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W)); rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W));
rtx pv = gen_rtx_REG (Pmode, 25); rtx pv = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
rtx gp = gen_rtx_REG (Pmode, 28); /* Use gen_raw_REG to avoid being given pic_offset_table_rtx.
The target is bound to be using $28 as the global pointer
/* This bit is the same as expand_builtin_longjmp. */ but the current function might not be. */
rtx gp = gen_raw_REG (Pmode, GLOBAL_POINTER_REGNUM);
/* This bit is similar to expand_builtin_longjmp except that it
restores $gp as well. */
emit_move_insn (hard_frame_pointer_rtx, fp); emit_move_insn (hard_frame_pointer_rtx, fp);
emit_move_insn (pv, lab); emit_move_insn (pv, lab);
emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment