aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>1994-04-21 18:28:09 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>1994-04-21 18:28:09 +0000
commit92544bdfd59b9deb0ae56887f89f6719321bc20e (patch)
treee5c25c39c55ce660a022d9bd7f000574ef5da2bb /gcc
parentc27c5281ceb7ece21291237c93135a7432d51c99 (diff)
downloadgcc-92544bdfd59b9deb0ae56887f89f6719321bc20e.zip
gcc-92544bdfd59b9deb0ae56887f89f6719321bc20e.tar.gz
gcc-92544bdfd59b9deb0ae56887f89f6719321bc20e.tar.bz2
Handle taking address of function when using -membedded-pic
From-SVN: r7105
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/mips/mips.c58
-rw-r--r--gcc/config/mips/mips.h27
-rw-r--r--gcc/config/mips/mips.md31
3 files changed, 113 insertions, 3 deletions
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 562a1e9..66c31e1 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -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)
}
+/* 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 *
@@ -4200,6 +4219,33 @@ epilogue_reg_mentioned_p (insn)
}
+/* 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;
+}
+
+
/* 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. */
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index dd4dc00..4f4b8f8 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -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 ()
/* 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)); \
\
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index be9e151..dfe0dad 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -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")])
+
;;
;; ....................