Handle taking address of function when using -membedded-pic
From-SVN: r7105
This commit is contained in:
parent
c27c5281ce
commit
92544bdfd5
@ -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. */
|
||||
|
@ -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)); \
|
||||
\
|
||||
|
@ -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")])
|
||||
|
||||
|
||||
;;
|
||||
;; ....................
|
||||
|
Loading…
Reference in New Issue
Block a user