Handle taking address of function when using -membedded-pic

From-SVN: r7105
This commit is contained in:
Ian Lance Taylor 1994-04-21 18:28:09 +00:00
parent c27c5281ce
commit 92544bdfd5
3 changed files with 113 additions and 3 deletions

View 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)
}
/* 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;
}
/* 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. */

View 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 ()
/* 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)); \
\

View 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")])
;;
;; ....................