OSDN Git Service

* config/mips/mips.c (mips_output_conditional_branch): Support
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 12 Dec 2002 05:13:04 +0000 (05:13 +0000)
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 12 Dec 2002 05:13:04 +0000 (05:13 +0000)
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: svn+ssh://gcc.gnu.org/svn/gcc/trunk@60058 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/config/mips/mips.md

index 878a422..a399390 100644 (file)
@@ -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.
index fa326ab..2dcf69d 100644 (file)
@@ -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 "";
       }
 
index 5d47e06..cc6cda5 100644 (file)
    (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")