aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2002-12-12 05:13:04 +0000
committerAlexandre Oliva <aoliva@redhat.com>2002-12-12 05:13:04 +0000
commitc4940b5111b201d58d39098d2ac8f6cef6e004ea (patch)
tree8535bfc0d0721f4de4c8fecd3380a56bd5cb907a
parent15c43792e61d300ba3ceb3eab9feb091e750c436 (diff)
* 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
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/mips/mips.c60
-rw-r--r--gcc/config/mips/mips.md40
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 <aoliva@redhat.com>
+
+ * 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 <dave@hiauly1.hia.nrc.ca>
* 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")