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>
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.h (MASK_CHECK_RANGE_DIV): Remove.
......
......@@ -1945,14 +1945,20 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
kept in a register. */
#define NO_RECURSIVE_FUNCTION_CSE 1
/* The register number of the register used to address a table of
static data addresses in memory. In some cases this register is
defined by a processor's "application binary interface" (ABI).
When this macro is defined, RTL is generated for this register
once, as with the stack pointer and frame pointer registers. If
this macro is not defined, it is up to the machine-dependent
files to allocate such a register (if necessary). */
#define PIC_OFFSET_TABLE_REGNUM (GP_REG_FIRST + 28)
/* The ABI-defined global pointer. Sometimes we use a different
register in leaf functions: see PIC_OFFSET_TABLE_REGNUM. */
#define GLOBAL_POINTER_REGNUM (GP_REG_FIRST + 28)
/* We normally use $28 as the global pointer. However, when generating
n32/64 PIC, it is better for leaf functions to use a call-clobbered
register instead. They can then avoid saving and restoring $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)
......@@ -2353,23 +2359,14 @@ extern enum reg_class mips_char_to_class[256];
/* 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 this if the nominal address of the stack frame
is at the high-address end of the local variables;
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. */
/* The offset of the first local variable from the beginning of the frame.
See compute_frame_size for details about the frame layout. */
#define STARTING_FRAME_OFFSET \
(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
allocated on the stack, e.g., by `alloca'.
......@@ -2837,13 +2834,6 @@ typedef struct mips_args {
(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
in the case of sibcalls, the values "used by the epilogue" are
considered live at the start of the called function. */
......
......@@ -32,9 +32,7 @@
(UNSPEC_STORE_DF_HIGH 2)
(UNSPEC_GET_FNADDR 4)
(UNSPEC_BLOCKAGE 6)
(UNSPEC_LOADGP 7)
(UNSPEC_SETJMP 8)
(UNSPEC_LONGJMP 9)
(UNSPEC_CPRESTORE 8)
(UNSPEC_EH_RECEIVER 10)
(UNSPEC_EH_RETURN 11)
(UNSPEC_CONSTTABLE_QI 12)
......@@ -67,7 +65,9 @@
(RELOC_GOT_DISP 104)
(RELOC_CALL16 105)
(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\\
(set_attr "mode" "SF")
(set_attr "length" "4")])
;; Instructions to load the global pointer register.
;; This is volatile to make sure that the scheduler won't move any symbol_ref
;; uses in front of it. All symbol_refs implicitly use the gp reg.
;; The use of gp is hidden when not using explicit relocations.
;; This blockage instruction prevents the gp load from being
;; 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"
[(set (reg:DI 28)
(unspec_volatile:DI [(match_operand 0 "immediate_operand" "")
(match_operand:DI 1 "register_operand" "")]
UNSPEC_LOADGP))
(clobber (reg:DI 1))]
;; Emit a .cprestore directive, which expands to a single store instruction.
;; Note that we continue to use .cprestore for explicit reloc code so that
;; jals inside inlines asms will work correctly.
(define_insn "cprestore"
[(unspec_volatile [(match_operand 0 "const_int_operand" "")]
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%]"
[(set_attr "type" "move")
(set_attr "mode" "DI")
(set_attr "length" "12")])
".cprestore\t%0"
[(set_attr "type" "store")
(set_attr "length" "4")])
;; Block moves, see mips.c for more details.
;; 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"
(set_attr "mode" "none")
(set_attr "length" "24")])
;; For o32/n32/n64, we save the gp in the jmp_buf as well. While it is
;; possible to either pull it off the stack (in the o32 case) or recalculate
;; it given t9 and our target label, it takes 3 or 4 insns to do so, and
;; this is easy.
;; For TARGET_ABICALLS, we save the gp in the jmp_buf as well.
;; While it is possible to either pull it off the stack (in the
;; o32 case) or recalculate it given t9 and our target label,
;; it takes 3 or 4 insns to do so.
(define_expand "builtin_setjmp_setup"
[(unspec [(match_operand 0 "register_operand" "r")] UNSPEC_SETJMP)]
[(use (match_operand 0 "register_operand" ""))]
"TARGET_ABICALLS"
"
{
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)"
"")
{
rtx addr;
(define_expand "builtin_setjmp_setup_64"
[(set (mem:DI (plus:DI (match_operand:DI 0 "register_operand" "r")
(const_int 24)))
(reg:DI 28))]
"TARGET_ABICALLS && Pmode == DImode"
"")
addr = plus_constant (operands[0], GET_MODE_SIZE (Pmode) * 3);
emit_move_insn (gen_rtx_MEM (Pmode, addr), pic_offset_table_rtx);
DONE;
})
;; For o32/n32/n64, we need to arrange for longjmp to put the
;; target address in t9 so that we can use it for loading $gp.
;; Restore the gp that we saved above. Despite the comment, it seems that
;; 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"
[(unspec_volatile [(match_operand 0 "register_operand" "r")] UNSPEC_LONGJMP)]
[(use (match_operand 0 "register_operand" "r"))]
"TARGET_ABICALLS"
"
{
/* 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 lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*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 pv = gen_rtx_REG (Pmode, 25);
rtx gp = gen_rtx_REG (Pmode, 28);
/* This bit is the same as expand_builtin_longjmp. */
rtx pv = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
/* Use gen_raw_REG to avoid being given pic_offset_table_rtx.
The target is bound to be using $28 as the global pointer
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 (pv, lab);
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