Commit 0c433c31 by Richard Sandiford Committed by Richard Sandiford

mips-protos.h (mips_cfun_has_cprestore_slot_p): Declare.

gcc/
	* config/mips/mips-protos.h (mips_cfun_has_cprestore_slot_p): Declare.
	(mips_cprestore_address_p): Likewise.
	(mips_save_gp_to_cprestore_slot): Likewise.
	(mips_restore_gp): Rename to...
	(mips_restore_gp_from_cprestore_slot): ...this.
	(mips_must_initialize_gp_p): Declare.
	(mips_emit_save_slot_move): Likewise.
	(mips_output_load_label): Return nothing.
	(mips_eh_uses): Declare.
	* config/mips/mips.h (TARGET_SPLIT_CALLS): Require epilogue_completed.
	(TARGET_CPRESTORE_DIRECTIVE): New macro.
	(TARGET_ABSOLUTE_JUMPS): Likewise.
	(EH_USES): Likewise.
	(FIRST_PSEUDO_REGISTER): Update comment.
	(MIPS_ABSOLUTE_JUMP): New macro, extracted from...
	(MIPS_CALL): ...here.
	(REGISTER_NAMES): Add $cprestore.
	* config/mips/mips.c (machine_function): Remove has_gp_insn_p.
	Add load_label_length, has_inflexible_gp_insn_p,
	has_flexible_gp_insn_p, must_initialize_gp_p and
	must_restore_gp_when_clobbered_p.
	(mips_expand_call): Don't generate split instructions here.
	(mips_split_call): Update the call to mips_restore_gp after
	the above name change.
	(mips16_cfun_returns_in_fpr_p): Move earlier in file.
	(mips_find_gp_ref): New function.
	(mips_insn_has_inflexible_gp_ref_p): Likewise.
	(mips_cfun_has_inflexible_gp_ref_p): Likewise.
	(mips_insn_has_flexible_gp_ref_p): Likewise.
	(mips_cfun_has_flexible_gp_ref_p): Likewise.
	(mips_function_has_gp_insn): Delete.
	(mips_global_pointer): Drop the df_regs_ever_live_p check.
	Use the new functions above.  Only return INVALID_REGNUM
	for TARGET_ABSOLUTE_JUMPS.
	(mips_must_initialize_gp_p): New function.
	(mips_get_cprestore_base_and_offset): New function, extracted from...
	(mips_cprestore_slot): ...here.  Take a bool parameter.
	(mips_cfun_has_cprestore_slot_p): New function.
	(mips_cprestore_address_p): Likewise.
	(mips_save_gp_to_cprestore_slot): Likewise.
	(mips_restore_gp): Rename to...
	(mips_restore_gp_from_cprestore_slot): ...this.  Assert
	epilogue_completed.  Update the call to mips_cprestore_slot.
	Test cfun->machine->must_restore_gp_when_clobbered_p.
	(mips_direct_save_slot_move_p): New function.
	(mips_emit_save_slot_move): Likewise.
	(mips_output_cplocal): Test mips_must_initialize_gp_p () instead
	of cfun->machine->global_pointer.
	(mips_output_function_prologue): Check mips_must_initialize_gp_p ().
	(mips_save_reg): Use mips_emit_save_slot_move.
	(mips_expand_prologue): Set must_initialize_gp_p.
	Use mips_cfun_has_cprestore_slot_p.  Use gen_potential_cprestore
	for all cprestore saves.  Emit a use_cprestore instruction after
	setting up the cprestore slot.
	(mips_restore_reg): Use mips_emit_save_slot_move.
	(mips_process_load_label): New function.
	(mips_load_label_length): Likewise.
	(mips_output_load_label): Don't return asm: output it here instead.
	Use mips_process_load_label.
	(mips_adjust_insn_length): Adjust the length of branch instructions
	that have length MAX_PIC_BRANCH_LENGTH.
	(mips_output_conditional_branch): Update the call to
	mips_output_load_label.  Assume the branch target is OPERANDS[0]
	rather than OPERANDS[1].  Use MIPS_ABSOLUTE_JUMP for absolute jumps.
	(mips_output_order_conditional_branch): Swap the meaning of
	OPERANDS[0] and OPERANDS[1].
	(mips_variable_issue): Don't count ghost instructions.
	(mips_expand_ghost_gp_insns): New function.
	(mips_reorg): Rerun mips_reorg_process_insns if it returns true.
	(mips_output_mi_thunk): Set must_initialize_gp_p.
	(mips_eh_uses): New function.
	* config/mips/predicates.md (cprestore_save_slot_operand)
	(cprestore_load_slot_operand): New predicates.
	* config/mips/mips.md (UNSPEC_POTENTIAL_CPRESTORE): New unspec.
	(UNSPEC_MOVE_GP): Likewise.
	(UNSPEC_CPRESTORE, UNSPEC_RESTORE_GP, UNSPEC_EH_RETURN)
	(UNSPEC_CONSTTABLE_INT, UNSPEC_CONSTTABLE_FLOAT): Bump to make room.
	(CPRESTORE_SLOT_REGNUM): New register.
	(MAX_PIC_BRANCH_LENGTH): New constant.
	(jal_macro): Use MIPS_ABSOLUTE_JUMPS.
	(length): Use MAX_PIC_BRANCH_LENGTH as a placeholder for PIC long
	branches.  Fix commentary.
	(loadgp_newabi_<mode>): Change from unspec_volatile to unspec.
	Only split if mips_must_initialize_gp_p; expand to nothing otherwise.
	Change type to "ghost".
	(loadgp_absolute_<mode>): Likewise.
	(loadgp_rtp_<mode>): Likewise.
	(copygp_mips16): Likewise.
	(loadgp_blockage): Remove redundant mode attribute.
	(potential_cprestore): New instruction.
	(cprestore): Turn into an unspec set.
	(use_cprestore): New instruction.
	(*branch_fp): Swap operands 0 and 1.  Remove redundant mode attribute.
	(*branch_fp_inverted): Likewise.
	(*branch_order<mode>): Likewise.
	(*branch_order<mode>_inverted): Likewise.
	(*branch_equality<mode>): Likewise.
	(*branch_equality<mode>_inverted): Likewise.
	(*branch_bit<bbv><mode>): Likewise.
	(*branch_bit<bbv><mode>_inverted): Likewise.
	(*branch_equality<mode>_mips16): Remove redundant mode.
	(jump): Turn into a define_expand.
	(*jump_absolute): New instruction.
	(*jump_pic): Likewise.
	(*jump_mips16): Rename previously-unnamed pattern.  Remove
	redundant mode attribute.
	(restore_gp): Split on epilogue_completed rather than
	reload_completed.  Change type to "ghost".
	(move_gp<mode>): New instruction.
	* config/mips/mips-dsp.md (mips_bposge): Swap operands 0 and 1.
	Remove redundant mode attribute.
	* config/mips/mips-ps-3d.md (bc1any4t): Likewise.
	(bc1any4f, bc1any2t, bc1any2f): Likewise.
	(*branch_upper_lower, *branch_upper_lower_inverted): Likewise.

gcc/testsuite/
	* gcc.target/mips/branch-helper.h: New file.
	* gcc.target/mips/branch-2.c,
	* gcc.target/mips/branch-3.c,
	* gcc.target/mips/branch-4.c,
	* gcc.target/mips/branch-5.c,
	* gcc.target/mips/branch-6.c,
	* gcc.target/mips/branch-7.c,
	* gcc.target/mips/branch-8.c,
	* gcc.target/mips/branch-9.c,
	* gcc.target/mips/branch-10.c,
	* gcc.target/mips/branch-11.c,
	* gcc.target/mips/branch-12.c,
	* gcc.target/mips/branch-13.c,
	* gcc.target/mips/branch-14.c,
	* gcc.target/mips/branch-15.c: New tests.

From-SVN: r151695
parent af0b8d73
2009-09-14 Richard Sandiford <rdsandiford@googlemail.com>
* config/mips/mips-protos.h (mips_cfun_has_cprestore_slot_p): Declare.
(mips_cprestore_address_p): Likewise.
(mips_save_gp_to_cprestore_slot): Likewise.
(mips_restore_gp): Rename to...
(mips_restore_gp_from_cprestore_slot): ...this.
(mips_must_initialize_gp_p): Declare.
(mips_emit_save_slot_move): Likewise.
(mips_output_load_label): Return nothing.
(mips_eh_uses): Declare.
* config/mips/mips.h (TARGET_SPLIT_CALLS): Require epilogue_completed.
(TARGET_CPRESTORE_DIRECTIVE): New macro.
(TARGET_ABSOLUTE_JUMPS): Likewise.
(EH_USES): Likewise.
(FIRST_PSEUDO_REGISTER): Update comment.
(MIPS_ABSOLUTE_JUMP): New macro, extracted from...
(MIPS_CALL): ...here.
(REGISTER_NAMES): Add $cprestore.
* config/mips/mips.c (machine_function): Remove has_gp_insn_p.
Add load_label_length, has_inflexible_gp_insn_p,
has_flexible_gp_insn_p, must_initialize_gp_p and
must_restore_gp_when_clobbered_p.
(mips_expand_call): Don't generate split instructions here.
(mips_split_call): Update the call to mips_restore_gp after
the above name change.
(mips16_cfun_returns_in_fpr_p): Move earlier in file.
(mips_find_gp_ref): New function.
(mips_insn_has_inflexible_gp_ref_p): Likewise.
(mips_cfun_has_inflexible_gp_ref_p): Likewise.
(mips_insn_has_flexible_gp_ref_p): Likewise.
(mips_cfun_has_flexible_gp_ref_p): Likewise.
(mips_function_has_gp_insn): Delete.
(mips_global_pointer): Drop the df_regs_ever_live_p check.
Use the new functions above. Only return INVALID_REGNUM
for TARGET_ABSOLUTE_JUMPS.
(mips_must_initialize_gp_p): New function.
(mips_get_cprestore_base_and_offset): New function, extracted from...
(mips_cprestore_slot): ...here. Take a bool parameter.
(mips_cfun_has_cprestore_slot_p): New function.
(mips_cprestore_address_p): Likewise.
(mips_save_gp_to_cprestore_slot): Likewise.
(mips_restore_gp): Rename to...
(mips_restore_gp_from_cprestore_slot): ...this. Assert
epilogue_completed. Update the call to mips_cprestore_slot.
Test cfun->machine->must_restore_gp_when_clobbered_p.
(mips_direct_save_slot_move_p): New function.
(mips_emit_save_slot_move): Likewise.
(mips_output_cplocal): Test mips_must_initialize_gp_p () instead
of cfun->machine->global_pointer.
(mips_output_function_prologue): Check mips_must_initialize_gp_p ().
(mips_save_reg): Use mips_emit_save_slot_move.
(mips_expand_prologue): Set must_initialize_gp_p.
Use mips_cfun_has_cprestore_slot_p. Use gen_potential_cprestore
for all cprestore saves. Emit a use_cprestore instruction after
setting up the cprestore slot.
(mips_restore_reg): Use mips_emit_save_slot_move.
(mips_process_load_label): New function.
(mips_load_label_length): Likewise.
(mips_output_load_label): Don't return asm: output it here instead.
Use mips_process_load_label.
(mips_adjust_insn_length): Adjust the length of branch instructions
that have length MAX_PIC_BRANCH_LENGTH.
(mips_output_conditional_branch): Update the call to
mips_output_load_label. Assume the branch target is OPERANDS[0]
rather than OPERANDS[1]. Use MIPS_ABSOLUTE_JUMP for absolute jumps.
(mips_output_order_conditional_branch): Swap the meaning of
OPERANDS[0] and OPERANDS[1].
(mips_variable_issue): Don't count ghost instructions.
(mips_expand_ghost_gp_insns): New function.
(mips_reorg): Rerun mips_reorg_process_insns if it returns true.
(mips_output_mi_thunk): Set must_initialize_gp_p.
(mips_eh_uses): New function.
* config/mips/predicates.md (cprestore_save_slot_operand)
(cprestore_load_slot_operand): New predicates.
* config/mips/mips.md (UNSPEC_POTENTIAL_CPRESTORE): New unspec.
(UNSPEC_MOVE_GP): Likewise.
(UNSPEC_CPRESTORE, UNSPEC_RESTORE_GP, UNSPEC_EH_RETURN)
(UNSPEC_CONSTTABLE_INT, UNSPEC_CONSTTABLE_FLOAT): Bump to make room.
(CPRESTORE_SLOT_REGNUM): New register.
(MAX_PIC_BRANCH_LENGTH): New constant.
(jal_macro): Use MIPS_ABSOLUTE_JUMPS.
(length): Use MAX_PIC_BRANCH_LENGTH as a placeholder for PIC long
branches. Fix commentary.
(loadgp_newabi_<mode>): Change from unspec_volatile to unspec.
Only split if mips_must_initialize_gp_p; expand to nothing otherwise.
Change type to "ghost".
(loadgp_absolute_<mode>): Likewise.
(loadgp_rtp_<mode>): Likewise.
(copygp_mips16): Likewise.
(loadgp_blockage): Remove redundant mode attribute.
(potential_cprestore): New instruction.
(cprestore): Turn into an unspec set.
(use_cprestore): New instruction.
(*branch_fp): Swap operands 0 and 1. Remove redundant mode attribute.
(*branch_fp_inverted): Likewise.
(*branch_order<mode>): Likewise.
(*branch_order<mode>_inverted): Likewise.
(*branch_equality<mode>): Likewise.
(*branch_equality<mode>_inverted): Likewise.
(*branch_bit<bbv><mode>): Likewise.
(*branch_bit<bbv><mode>_inverted): Likewise.
(*branch_equality<mode>_mips16): Remove redundant mode.
(jump): Turn into a define_expand.
(*jump_absolute): New instruction.
(*jump_pic): Likewise.
(*jump_mips16): Rename previously-unnamed pattern. Remove
redundant mode attribute.
(restore_gp): Split on epilogue_completed rather than
reload_completed. Change type to "ghost".
(move_gp<mode>): New instruction.
* config/mips/mips-dsp.md (mips_bposge): Swap operands 0 and 1.
Remove redundant mode attribute.
* config/mips/mips-ps-3d.md (bc1any4t): Likewise.
(bc1any4f, bc1any2t, bc1any2f): Likewise.
(*branch_upper_lower, *branch_upper_lower_inverted): Likewise.
2009-09-14 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/41210
......
......@@ -1102,11 +1102,10 @@
(define_insn "mips_bposge"
[(set (pc)
(if_then_else (ge (reg:CCDSP CCDSP_PO_REGNUM)
(match_operand:SI 0 "immediate_operand" "I"))
(label_ref (match_operand 1 "" ""))
(match_operand:SI 1 "immediate_operand" "I"))
(label_ref (match_operand 0 "" ""))
(pc)))]
"ISA_HAS_DSP"
"%*bposge%0\t%1%/"
[(set_attr "type" "branch")
(set_attr "mode" "none")])
"%*bposge%1\t%0%/"
[(set_attr "type" "branch")])
......@@ -219,7 +219,10 @@ extern rtx mips_subword (rtx, bool);
extern bool mips_split_64bit_move_p (rtx, rtx);
extern void mips_split_doubleword_move (rtx, rtx);
extern const char *mips_output_move (rtx, rtx);
extern void mips_restore_gp (rtx);
extern bool mips_cfun_has_cprestore_slot_p (void);
extern bool mips_cprestore_address_p (rtx, bool);
extern void mips_save_gp_to_cprestore_slot (rtx, rtx, rtx, rtx);
extern void mips_restore_gp_from_cprestore_slot (rtx);
#ifdef RTX_CODE
extern void mips_expand_scc (rtx *);
extern void mips_expand_conditional_branch (rtx *);
......@@ -276,7 +279,9 @@ extern bool mips_small_data_pattern_p (rtx);
extern rtx mips_rewrite_small_data (rtx);
extern HOST_WIDE_INT mips_initial_elimination_offset (int, int);
extern rtx mips_return_addr (int, rtx);
extern bool mips_must_initialize_gp_p (void);
extern enum mips_loadgp_style mips_current_loadgp_style (void);
extern void mips_emit_save_slot_move (rtx, rtx, rtx);
extern void mips_expand_prologue (void);
extern void mips_expand_before_return (void);
extern void mips_expand_epilogue (bool);
......@@ -296,7 +301,7 @@ extern int mips_register_move_cost (enum machine_mode, enum reg_class,
enum reg_class);
extern int mips_adjust_insn_length (rtx, int);
extern const char *mips_output_load_label (void);
extern void mips_output_load_label (rtx);
extern const char *mips_output_conditional_branch (rtx, rtx *, const char *,
const char *);
extern const char *mips_output_order_conditional_branch (rtx, rtx *, bool);
......@@ -334,6 +339,7 @@ extern void mips_expand_atomic_qihi (union mips_gen_fn_ptrs,
extern void mips_expand_vector_init (rtx, rtx);
extern bool mips_eh_uses (unsigned int);
extern bool mips_epilogue_uses (unsigned int);
extern void mips_final_prescan_insn (rtx, rtx *, int);
......
......@@ -439,50 +439,46 @@
; Branch on Any of Four Floating Point Condition Codes True
(define_insn "bc1any4t"
[(set (pc)
(if_then_else (ne (match_operand:CCV4 0 "register_operand" "z")
(if_then_else (ne (match_operand:CCV4 1 "register_operand" "z")
(const_int 0))
(label_ref (match_operand 1 "" ""))
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
"%*bc1any4t\t%0,%1%/"
[(set_attr "type" "branch")
(set_attr "mode" "none")])
"%*bc1any4t\t%1,%0%/"
[(set_attr "type" "branch")])
; Branch on Any of Four Floating Point Condition Codes False
(define_insn "bc1any4f"
[(set (pc)
(if_then_else (ne (match_operand:CCV4 0 "register_operand" "z")
(if_then_else (ne (match_operand:CCV4 1 "register_operand" "z")
(const_int -1))
(label_ref (match_operand 1 "" ""))
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
"%*bc1any4f\t%0,%1%/"
[(set_attr "type" "branch")
(set_attr "mode" "none")])
"%*bc1any4f\t%1,%0%/"
[(set_attr "type" "branch")])
; Branch on Any of Two Floating Point Condition Codes True
(define_insn "bc1any2t"
[(set (pc)
(if_then_else (ne (match_operand:CCV2 0 "register_operand" "z")
(if_then_else (ne (match_operand:CCV2 1 "register_operand" "z")
(const_int 0))
(label_ref (match_operand 1 "" ""))
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
"%*bc1any2t\t%0,%1%/"
[(set_attr "type" "branch")
(set_attr "mode" "none")])
"%*bc1any2t\t%1,%0%/"
[(set_attr "type" "branch")])
; Branch on Any of Two Floating Point Condition Codes False
(define_insn "bc1any2f"
[(set (pc)
(if_then_else (ne (match_operand:CCV2 0 "register_operand" "z")
(if_then_else (ne (match_operand:CCV2 1 "register_operand" "z")
(const_int -1))
(label_ref (match_operand 1 "" ""))
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT"
"%*bc1any2f\t%0,%1%/"
[(set_attr "type" "branch")
(set_attr "mode" "none")])
"%*bc1any2f\t%1,%0%/"
[(set_attr "type" "branch")])
; Used to access one register in a CCV2 pair. Operand 0 is the register
; pair and operand 1 is the index of the register we want (a CONST_INT).
......@@ -497,45 +493,43 @@
(define_insn "*branch_upper_lower"
[(set (pc)
(if_then_else
(match_operator 0 "equality_operator"
(match_operator 1 "equality_operator"
[(unspec:CC [(match_operand:CCV2 2 "register_operand" "z")
(match_operand 3 "const_int_operand")]
UNSPEC_SINGLE_CC)
(const_int 0)])
(label_ref (match_operand 1 "" ""))
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_HARD_FLOAT"
{
operands[2]
= gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3]));
return mips_output_conditional_branch (insn, operands,
MIPS_BRANCH ("b%F0", "%2,%1"),
MIPS_BRANCH ("b%W0", "%2,%1"));
MIPS_BRANCH ("b%F1", "%2,%0"),
MIPS_BRANCH ("b%W1", "%2,%0"));
}
[(set_attr "type" "branch")
(set_attr "mode" "none")])
[(set_attr "type" "branch")])
; As above, but with the sense of the condition reversed.
(define_insn "*branch_upper_lower_inverted"
[(set (pc)
(if_then_else
(match_operator 0 "equality_operator"
(match_operator 1 "equality_operator"
[(unspec:CC [(match_operand:CCV2 2 "register_operand" "z")
(match_operand 3 "const_int_operand")]
UNSPEC_SINGLE_CC)
(const_int 0)])
(pc)
(label_ref (match_operand 1 "" ""))))]
(label_ref (match_operand 0 "" ""))))]
"TARGET_HARD_FLOAT"
{
operands[2]
= gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3]));
return mips_output_conditional_branch (insn, operands,
MIPS_BRANCH ("b%W0", "%2,%1"),
MIPS_BRANCH ("b%F0", "%2,%1"));
MIPS_BRANCH ("b%W1", "%2,%0"),
MIPS_BRANCH ("b%F1", "%2,%0"));
}
[(set_attr "type" "branch")
(set_attr "mode" "none")])
[(set_attr "type" "branch")])
;----------------------------------------------------------------------------
; Floating Point Reduced Precision Reciprocal Square Root Instructions.
......
......@@ -161,10 +161,13 @@ enum mips_code_readable_setting {
/* True if the call patterns should be split into a jalr followed by
an instruction to restore $gp. It is only safe to split the load
from the call when every use of $gp is explicit. */
from the call when every use of $gp is explicit.
See mips_must_initialize_gp_p for details about how we manage the
global pointer. */
#define TARGET_SPLIT_CALLS \
(TARGET_EXPLICIT_RELOCS && TARGET_CALL_CLOBBERED_GP)
(TARGET_EXPLICIT_RELOCS && TARGET_CALL_CLOBBERED_GP && epilogue_completed)
/* True if we're generating a form of -mabicalls in which we can use
operators like %hi and %lo to refer to locally-binding symbols.
......@@ -202,6 +205,17 @@ enum mips_code_readable_setting {
/* True if TARGET_USE_GOT and if $gp is a call-saved register. */
#define TARGET_CALL_SAVED_GP (TARGET_USE_GOT && !TARGET_CALL_CLOBBERED_GP)
/* True if we should use .cprestore to store to the cprestore slot.
We continue to use .cprestore for explicit-reloc code so that JALs
inside inline asms will work correctly. */
#define TARGET_CPRESTORE_DIRECTIVE \
(TARGET_ABICALLS_PIC2 && !TARGET_MIPS16)
/* True if we can use the J and JAL instructions. */
#define TARGET_ABSOLUTE_JUMPS \
(!flag_pic || TARGET_ABSOLUTE_ABICALLS)
/* True if indirect calls must use register class PIC_FN_ADDR_REG.
This is true for both the PIC and non-PIC VxWorks RTP modes. */
#define TARGET_USE_PIC_FN_ADDR_REG (TARGET_ABICALLS || TARGET_VXWORKS_RTP)
......@@ -1300,6 +1314,8 @@ enum mips_code_readable_setting {
#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_REG_FIRST + 3)
#define EH_USES(N) mips_eh_uses (N)
/* Offsets recorded in opcodes are a multiple of this alignment factor.
The default for this in 64-bit mode is 8, which causes problems with
SFmode register saves. */
......@@ -1543,11 +1559,12 @@ enum mips_code_readable_setting {
- 8 condition code registers
- 2 accumulator registers (hi and lo)
- 32 registers each for coprocessors 0, 2 and 3
- 3 fake registers:
- 4 fake registers:
- ARG_POINTER_REGNUM
- FRAME_POINTER_REGNUM
- GOT_VERSION_REGNUM (see the comment above load_call<mode> for details)
- 3 dummy entries that were used at various times in the past.
- CPRESTORE_SLOT_REGNUM
- 2 dummy entries that were used at various times in the past.
- 6 DSP accumulator registers (3 hi-lo pairs) for MIPS DSP ASE
- 6 DSP control registers */
......@@ -2661,6 +2678,13 @@ typedef struct mips_args {
#define MIPS_BRANCH(OPCODE, OPERANDS) \
"%*" OPCODE "%?\t" OPERANDS "%/"
/* Return an asm string that forces INSN to be treated as an absolute
J or JAL instruction instead of an assembler macro. */
#define MIPS_ABSOLUTE_JUMP(INSN) \
(TARGET_ABICALLS_PIC2 \
? ".option\tpic0\n\t" INSN "\n\t.option\tpic2" \
: INSN)
/* Return the asm template for a call. INSN is the instruction's mnemonic
("j" or "jal"), OPERANDS are its operands, and OPNO is the operand number
of the target.
......@@ -2675,11 +2699,7 @@ typedef struct mips_args {
? "%*" INSN "\t%" #OPNO "%/" \
: REG_P (OPERANDS[OPNO]) \
? "%*" INSN "r\t%" #OPNO "%/" \
: TARGET_ABICALLS_PIC2 \
? (".option\tpic0\n\t" \
"%*" INSN "\t%" #OPNO "%/\n\t" \
".option\tpic2") \
: "%*" INSN "\t%" #OPNO "%/")
: MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #OPNO "%/"))
/* Control the assembler format that we output. */
......@@ -2707,7 +2727,7 @@ typedef struct mips_args {
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", \
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", \
"hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", \
"$fcc5","$fcc6","$fcc7","", "", "$arg", "$frame", "$fakec", \
"$fcc5","$fcc6","$fcc7","", "$cprestore", "$arg", "$frame", "$fakec", \
"$c0r0", "$c0r1", "$c0r2", "$c0r3", "$c0r4", "$c0r5", "$c0r6", "$c0r7", \
"$c0r8", "$c0r9", "$c0r10","$c0r11","$c0r12","$c0r13","$c0r14","$c0r15", \
"$c0r16","$c0r17","$c0r18","$c0r19","$c0r20","$c0r21","$c0r22","$c0r23", \
......
......@@ -244,6 +244,14 @@
}
})
(define_predicate "cprestore_save_slot_operand"
(and (match_code "mem")
(match_test "mips_cprestore_address_p (XEXP (op, 0), false)")))
(define_predicate "cprestore_load_slot_operand"
(and (match_code "mem")
(match_test "mips_cprestore_address_p (XEXP (op, 0), true)")))
(define_predicate "consttable_operand"
(match_test "CONSTANT_P (op)"))
......
2009-09-14 Richard Sandiford <rdsandiford@googlemail.com>
* gcc.target/mips/branch-helper.h: New file.
* gcc.target/mips/branch-2.c,
* gcc.target/mips/branch-3.c,
* gcc.target/mips/branch-4.c,
* gcc.target/mips/branch-5.c,
* gcc.target/mips/branch-6.c,
* gcc.target/mips/branch-7.c,
* gcc.target/mips/branch-8.c,
* gcc.target/mips/branch-9.c,
* gcc.target/mips/branch-10.c,
* gcc.target/mips/branch-11.c,
* gcc.target/mips/branch-12.c,
* gcc.target/mips/branch-13.c,
* gcc.target/mips/branch-14.c,
* gcc.target/mips/branch-15.c: New tests.
2009-09-14 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/41331
......
/* { dg-options "-mabicalls -mshared -mabi=n32" } */
/* { dg-final { scan-assembler-not "(\\\$28|%gp_rel|%got)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (void (*bar) (void), volatile int *x)
{
bar ();
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
/* { dg-options "-mabicalls -mshared -mabi=n32" } */
/* { dg-final { scan-assembler "\tsd\t\\\$28," } } */
/* { dg-final { scan-assembler "\tld\t\\\$28," } } */
/* { dg-final { scan-assembler "\taddiu\t\\\$28,\\\$28,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */
/* { dg-final { scan-assembler "\tlw\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$28\\)\n" } } */
/* { dg-final { scan-assembler "\taddiu\t\\\$1,\\\$1,%got_ofst\\(\[^)\]*\\)\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (void (*bar) (void), volatile int *x)
{
bar ();
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
/* { dg-options "-mabicalls -mshared -mabi=64" } */
/* { dg-final { scan-assembler-not "(\\\$28|%gp_rel|%got)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (void (*bar) (void), volatile int *x)
{
bar ();
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
/* { dg-options "-mabicalls -mshared -mabi=64" } */
/* { dg-final { scan-assembler "\tsd\t\\\$28," } } */
/* { dg-final { scan-assembler "\tld\t\\\$28," } } */
/* { dg-final { scan-assembler "\tdaddiu\t\\\$28,\\\$28,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */
/* { dg-final { scan-assembler "\tld\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$28\\)\n" } } */
/* { dg-final { scan-assembler "\tdaddiu\t\\\$1,\\\$1,%got_ofst\\(\[^)\]*\\)\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (void (*bar) (void), volatile int *x)
{
bar ();
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
/* An executable version of branch-2.c. */
/* { dg-do run } */
#include "branch-helper.h"
void __attribute__((noinline))
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
int
main (void)
{
int x = 0;
int y = 1;
foo (&x);
foo (&y);
return 0;
}
/* An executable version of branch-3.c. */
/* { dg-do run } */
#include "branch-helper.h"
void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
int
main (void)
{
int x = 0;
int y = 1;
foo (&x);
foo (&y);
return 0;
}
/* { dg-options "-mabicalls -mshared -mabi=32" } */
/* { dg-final { scan-assembler-not "(\\\$25|\\\$28|cpload)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "cprestore" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
/* { dg-options "-mabicalls -mshared -mabi=32" } */
/* { dg-final { scan-assembler "\t\\.cpload\t\\\$25\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "cprestore" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
/* { dg-options "-mabicalls -mshared -mabi=n32" } */
/* { dg-final { scan-assembler-not "(\\\$25|\\\$28|%gp_rel|%got)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
/* { dg-options "-mabicalls -mshared -mabi=n32" } */
/* { dg-final { scan-assembler "\taddiu\t\\\$3,\\\$3,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */
/* { dg-final { scan-assembler "\tlw\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$3\\)\\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\\\$28" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
/* { dg-options "-mabicalls -mshared -mabi=64" } */
/* { dg-final { scan-assembler-not "(\\\$25|\\\$28|%gp_rel|%got)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
/* { dg-options "-mabicalls -mshared -mabi=64" } */
/* { dg-final { scan-assembler "\tdaddiu\t\\\$3,\\\$3,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */
/* { dg-final { scan-assembler "\tld\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$3\\)\\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\\\$28" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (volatile int *x)
{
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
/* { dg-options "-mabicalls -mshared -mabi=32" } */
/* { dg-final { scan-assembler-not "(\\\$28|cpload|cprestore)" } } */
/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (void (*bar) (void), volatile int *x)
{
bar ();
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fff8;
}
/* { dg-options "-mabicalls -mshared -mabi=32" } */
/* { dg-final { scan-assembler "\t\\.cpload\t\\\$25\n" } } */
/* { dg-final { scan-assembler "\t\\.cprestore\t16\n" } } */
/* { dg-final { scan-assembler "\tlw\t\\\$1,16\\(\\\$fp\\)\n" } } */
/* { dg-final { scan-assembler "\tlw\t\\\$1,%got\\(\[^)\]*\\)\\(\\\$1\\)\n" } } */
/* { dg-final { scan-assembler "\taddiu\t\\\$1,\\\$1,%lo\\(\[^)\]*\\)\n" } } */
/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */
/* { dg-final { scan-assembler-not "\tlw\t\\\$28,16\\(\\\$sp\\)\n" } } */
#include "branch-helper.h"
NOMIPS16 void
foo (void (*bar) (void), volatile int *x)
{
bar ();
if (__builtin_expect (*x == 0, 1))
OCCUPY_0x1fffc;
}
/* DN(X) generates 2**N copies of asm instruction X. */
#define D0(X) X
#define D1(X) X "\n\t" X
#define D2(X) D1 (D1 (X))
#define D3(X) D2 (D1 (X))
#define D4(X) D2 (D2 (X))
#define D5(X) D4 (D1 (X))
#define D6(X) D4 (D2 (X))
#define D7(X) D4 (D2 (D1 (X)))
#define D8(X) D4 (D4 (X))
#define D9(X) D8 (D1 (X))
#define D10(X) D8 (D2 (X))
#define D11(X) D8 (D2 (D1 (X)))
#define D12(X) D8 (D4 (X))
#define D13(X) D8 (D4 (D1 (X)))
#define D14(X) D8 (D4 (D2 (X)))
/* Emit something that is 0x1fff8 bytes long, which is the largest
permissible range for non-MIPS16 forward branches. */
#define OCCUPY_0x1fff8 \
asm (D14 ("nop") "\n\t" \
D13 ("nop") "\n\t" \
D12 ("nop") "\n\t" \
D11 ("nop") "\n\t" \
D10 ("nop") "\n\t" \
D9 ("nop") "\n\t" \
D8 ("nop") "\n\t" \
D7 ("nop") "\n\t" \
D6 ("nop") "\n\t" \
D5 ("nop") "\n\t" \
D4 ("nop") "\n\t" \
D3 ("nop") "\n\t" \
D2 ("nop") "\n\t" \
D1 ("nop"))
/* Likewise emit something that is 0x1fffc bytes long. */
#define OCCUPY_0x1fffc do { asm ("nop"); OCCUPY_0x1fff8; } while (0)
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