From c4940b5111b201d58d39098d2ac8f6cef6e004ea Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Thu, 12 Dec 2002 05:13:04 +0000 Subject: * config/mips/mips.c (mips_output_conditional_branch): Support PIC-safe out-of-range branch and branch-likely. * config/mips/mips.md (attr length): PIC-safe out-of-range branches are longer. ("jump"): Support PIC-safe out-of-range-for-branch jumps. Remove unused code to support indirect jumps. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@60058 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 9 ++++++++ gcc/config/mips/mips.c | 60 ++++++++++++++++++++++++++++++++++++++++++------- gcc/config/mips/mips.md | 40 +++++++++++++++++++++++---------- 3 files changed, 89 insertions(+), 20 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 878a422fb84..a399390cd19 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2002-12-12 Alexandre Oliva + + * config/mips/mips.c (mips_output_conditional_branch): Support + PIC-safe out-of-range branch and branch-likely. + * config/mips/mips.md (attr length): PIC-safe out-of-range + branches are longer. + ("jump"): Support PIC-safe out-of-range-for-branch jumps. Remove + unused code to support indirect jumps. + 2002-12-11 John David Anglin * pa.h (BIGGEST_ALIGNMENT): Change 32-bit value to 64 bits. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index fa326abc928..2dcf69d3f43 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -10177,6 +10177,8 @@ mips_output_conditional_branch (insn, case 12: case 16: + case 24: + case 28: { /* Generate a reversed conditional branch around ` j' instruction: @@ -10184,18 +10186,41 @@ mips_output_conditional_branch (insn, .set noreorder .set nomacro bc l - nop + delay_slot or #nop j target + #nop + l: .set macro .set reorder + + If the original branch was a likely branch, the delay slot + must be executed only if the branch is taken, so generate: + + .set noreorder + .set nomacro + bc l + #nop + j target + delay slot or #nop l: + .set macro + .set reorder + + When generating non-embedded PIC, instead of: + + j target + + we emit: + .set noat + la $at, target + jr $at + .set at */ rtx orig_target; rtx target = gen_label_rtx (); - output_asm_insn ("%(%<", 0); orig_target = operands[1]; operands[1] = target; /* Generate the reversed comparison. This takes four @@ -10210,13 +10235,29 @@ mips_output_conditional_branch (insn, op1, op2); output_asm_insn (buffer, operands); - operands[1] = orig_target; - output_asm_insn ("nop\n\tj\t%1", operands); + if (length != 16 && length != 28 && ! mips_branch_likely) + { + /* Output delay slot instruction. */ + rtx insn = final_sequence; + final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, + optimize, 0, 1); + INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1; + } + else + output_asm_insn ("%#", 0); - if (length == 16) - output_asm_insn ("nop", 0); - else + if (length <= 16) + output_asm_insn ("j\t%0", &orig_target); + else + { + if (Pmode == DImode) + output_asm_insn ("%[dla\t%@,%0\n\tjr\t%@%]", &orig_target); + else + output_asm_insn ("%[la\t%@,%0\n\tjr\t%@%]", &orig_target); + } + + if (length != 16 && length != 28 && mips_branch_likely) { /* Output delay slot instruction. */ rtx insn = final_sequence; @@ -10224,9 +10265,12 @@ mips_output_conditional_branch (insn, optimize, 0, 1); INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1; } - output_asm_insn ("%>%)", 0); + else + output_asm_insn ("%#", 0); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (target)); + return ""; } diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 5d47e068b08..cc6cda53dba 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -105,9 +105,12 @@ (cond [(eq_attr "type" "branch") (cond [(lt (abs (minus (match_dup 1) (plus (pc) (const_int 4)))) (const_int 131072)) - (const_int 4)] - (const_int 12))] - (const_int 4))) + (const_int 4) + (ne (symbol_ref "flag_pic && ! TARGET_EMBEDDED_PIC") + (const_int 0)) + (const_int 24) + ] (const_int 12)) + ] (const_int 4))) ;; Attribute describing the processor. This attribute must match exactly ;; with the processor_type enumeration in mips.h. @@ -9592,18 +9595,31 @@ move\\t%0,%z4\\n\\ "!TARGET_MIPS16" "* { - if (GET_CODE (operands[0]) == REG) - return \"%*j\\t%0\"; - /* ??? I don't know why this is necessary. This works around an - assembler problem that appears when a label is defined, then referenced - in a switch table, then used in a `j' instruction. */ - else if (mips_abi != ABI_32 && mips_abi != ABI_O64) - return \"%*b\\t%l0\"; + if (flag_pic && ! TARGET_EMBEDDED_PIC) + { + if (get_attr_length (insn) <= 8) + return \"%*b\\t%l0\"; + else if (Pmode == DImode) + return \"%[dla\\t%@,%l0\;%*jr\\t%@%]\"; + else + return \"%[la\\t%@,%l0\;%*jr\\t%@%]\"; + } else return \"%*j\\t%l0\"; }" [(set_attr "type" "jump") - (set_attr "mode" "none")]) + (set_attr "mode" "none") + (set (attr "length") + ;; we can't use `j' when emitting non-embedded PIC, so we emit + ;; branch, if it's in range, or load the address of the branch + ;; target into $at in a PIC-compatible way and then jump to it. + (if_then_else + (ior (eq (symbol_ref "flag_pic && ! TARGET_EMBEDDED_PIC") + (const_int 0)) + (lt (abs (minus (match_dup 0) + (plus (pc) (const_int 4)))) + (const_int 131072))) + (const_int 4) (const_int 16)))]) ;; We need a different insn for the mips16, because a mips16 branch ;; does not have a delay slot. @@ -9611,7 +9627,7 @@ move\\t%0,%z4\\n\\ (define_insn "" [(set (pc) (label_ref (match_operand 0 "" "")))] - "TARGET_MIPS16 && GET_CODE (operands[0]) != REG" + "TARGET_MIPS16" "b\\t%l0" [(set_attr "type" "branch") (set_attr "mode" "none") -- cgit v1.2.3