]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Handle taking address of function when using -membedded-pic
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 21 Apr 1994 18:28:09 +0000 (18:28 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 21 Apr 1994 18:28:09 +0000 (18:28 +0000)
From-SVN: r7105

gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md

index 562a1e98a6d27007586612e4efe672bf8e136621..66c31e15a24345bc3955571474f4e680b4d0cb9b 100644 (file)
@@ -218,6 +218,11 @@ struct mips_frame_info zero_frame_info;
    for -mgpopt.  */
 static char *temp_filename;
 
+/* Pseudo-reg holding the address of the current function when
+   generating embedded PIC code.  Created by LEGITIMIZE_ADDRESS, used
+   by mips_finalize_pic if it was created.  */
+rtx embedded_pic_fnaddr_rtx;
+
 /* List of all MIPS punctuation characters used by print_operand.  */
 char mips_print_operand_punct[256];
 
@@ -853,6 +858,20 @@ mips_count_memory_refs (op, num)
 }
 
 \f
+/* Return RTL for the offset from the current function to the
+   argument.  */
+
+rtx
+embedded_pic_offset (x)
+     rtx x;
+{
+  if (embedded_pic_fnaddr_rtx == NULL)
+    embedded_pic_fnaddr_rtx = gen_reg_rtx (Pmode);
+  return gen_rtx (CONST, Pmode,
+                 gen_rtx (MINUS, Pmode, x,
+                          XEXP (DECL_RTL (current_function_decl), 0)));
+}
+
 /* Return the appropriate instructions to move one operand to another.  */
 
 char *
@@ -4199,6 +4218,33 @@ epilogue_reg_mentioned_p (insn)
   return 0;
 }
 
+\f
+/* When generating embedded PIC code we may need to get the address of
+   the current function.  We will need it if we take the address of
+   any symbol in the .text section.  */
+
+void
+mips_finalize_pic ()
+{
+  rtx seq;
+
+  if (! TARGET_EMBEDDED_PIC)
+    return;
+  if (embedded_pic_fnaddr_rtx == NULL)
+    return;
+
+  start_sequence ();
+
+  emit_insn (gen_get_fnaddr (embedded_pic_fnaddr_rtx,
+                            XEXP (DECL_RTL (current_function_decl), 0)));
+
+  seq = gen_sequence ();
+  end_sequence ();
+  emit_insn_after (seq, get_insns ());
+
+  embedded_pic_fnaddr_rtx = NULL;
+}
+
 \f
 /* Return the bytes needed to compute the frame pointer from the current
    stack pointer.
@@ -5221,7 +5267,17 @@ mips_select_section (decl, reloc)
 {
   int size = int_size_in_bytes (TREE_TYPE (decl));
 
-  if (TARGET_EMBEDDED_DATA)
+  if (TARGET_EMBEDDED_PIC
+      && TREE_CODE (decl) == STRING_CST
+      && !flag_writable_strings)
+    {
+      /* For embedded position independent code, put constant strings
+        in the text section, because the data section is limited to
+        64K in size.  */
+
+      text_section ();
+    }
+  else if (TARGET_EMBEDDED_DATA)
     {
       /* For embedded applications, always put an object in read-only data
         if possible, in order to reduce RAM usage.  */
index dd4dc003649f32d129f80efb1e8815f9801215e9..4f4b8f8ce1c92f2d58430bc4f2cd8be26a001302 100644 (file)
@@ -132,6 +132,7 @@ extern struct rtx_def *mips_load_reg;       /* register to check for load delay */
 extern struct rtx_def *mips_load_reg2; /* 2nd reg to check for load delay */
 extern struct rtx_def *mips_load_reg3; /* 3rd reg to check for load delay */
 extern struct rtx_def *mips_load_reg4; /* 4th reg to check for load delay */
+extern struct rtx_def *embedded_pic_fnaddr_rtx;        /* function address */
 
 /* Functions within mips.c that we reference.  */
 
@@ -183,6 +184,8 @@ extern int          simple_memory_operand ();
 extern int             small_int ();
 extern void            trace();
 extern int             uns_arith_operand ();
+extern struct rtx_def *        embedded_pic_offset ();
+extern void            mips_finalize_pic ();
 
 /* Recognition functions that return if a condition is true.  */
 extern int             address_operand ();
@@ -1292,6 +1295,7 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
 
 #define PIC_FUNCTION_ADDR_REGNUM (GP_REG_FIRST + 25)
 
+#define FINALIZE_PIC mips_finalize_pic ()
 \f
 /* Define the classes of registers for register constraints in the
    machine description.  Also define ranges of constants.
@@ -2246,8 +2250,14 @@ typedef struct mips_args {
             appropriate relocation.  */                                \
                                                                        \
          /* Also accept CONST_INT addresses here, so no else.  */      \
+         /* Reject combining an embedded PIC text segment reference    \
+            with a register.  That requires an additional              \
+            instruction.  */                                           \
          if (!TARGET_DEBUG_A_MODE                                      \
-             && CONSTANT_ADDRESS_P (xplus1))                           \
+             && CONSTANT_ADDRESS_P (xplus1)                            \
+             && (!TARGET_EMBEDDED_PIC                                  \
+                 || code1 != CONST                                     \
+                 || GET_CODE (XEXP (xplus1, 0)) != MINUS))             \
            goto ADDR;                                                  \
        }                                                               \
     }                                                                  \
@@ -2430,7 +2440,20 @@ typedef struct mips_args {
 #define ENCODE_SECTION_INFO(DECL)                                      \
 do                                                                     \
   {                                                                    \
-    if (TARGET_GP_OPT && TREE_CODE (DECL) == VAR_DECL)                 \
+    if (TARGET_EMBEDDED_PIC)                                           \
+      {                                                                        \
+        if (TREE_CODE (DECL) == VAR_DECL)                              \
+         SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;              \
+        else if (TREE_CODE (DECL) == FUNCTION_DECL)                    \
+         SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 0;              \
+       else if (TREE_CODE (DECL) == STRING_CST                         \
+                && ! flag_writable_strings)                            \
+         SYMBOL_REF_FLAG (XEXP (TREE_CST_RTL (DECL), 0)) = 0;          \
+        else                                                           \
+         SYMBOL_REF_FLAG (XEXP (TREE_CST_RTL (DECL), 0)) = 1;          \
+      }                                                                        \
+                                                                       \
+    else if (TARGET_GP_OPT && TREE_CODE (DECL) == VAR_DECL)            \
       {                                                                        \
        int size = int_size_in_bytes (TREE_TYPE (DECL));                \
                                                                        \
index be9e1512a06b6d7f2b078d68748dfd35908a7e42..dfe0dad17885ffba855eeefc8410535df5b30753 100644 (file)
@@ -2759,6 +2759,23 @@ move\\t%0,%z4\\n\\
   ""
   "
 {
+  /* If we are generating embedded PIC code, and we are referring to a
+     symbol in the .text section, we must use an offset from the start
+     of the function.  */
+  if (TARGET_EMBEDDED_PIC
+      && (GET_CODE (operands[1]) == LABEL_REF
+         || (GET_CODE (operands[1]) == SYMBOL_REF
+             && ! SYMBOL_REF_FLAG (operands[1]))))
+    {
+      rtx temp;
+
+      temp = embedded_pic_offset (operands[1]);
+      temp = gen_rtx (PLUS, Pmode, embedded_pic_fnaddr_rtx,
+                     force_reg (SImode, temp));
+      emit_move_insn (operands[0], force_reg (SImode, temp));
+      DONE;
+    }
+
   /* If operands[1] is a constant address illegal for pic, then we need to
      handle it just like LEGITIMIZE_ADDRESS does.  */
   if (flag_pic && pic_address_needs_scratch (operands[1]))
@@ -5542,6 +5559,20 @@ move\\t%0,%z4\\n\\
 ;;     }
 ;; }")
 
+;; When generating embedded PIC code we need to get the address of the
+;; current function.  This specialized instruction does just that.
+
+(define_insn "get_fnaddr"
+  [(set (match_operand 0 "register_operand" "d")
+       (unspec [(match_operand 1 "" "")] 1))
+   (clobber (reg:SI 31))]
+  "TARGET_EMBEDDED_PIC
+   && GET_CODE (operands[1]) == SYMBOL_REF"
+  "%($LF%= = . + 8\;bal\\t$LF%=\;la\\t%0,%1-$LF%=%)\;addu\\t%0,%0,$31"
+  [(set_attr "type"    "call")
+   (set_attr "mode"    "none")
+   (set_attr "length"  "4")])
+
 \f
 ;;
 ;;  ....................