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];
}
\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 *
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.
{
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. */
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. */
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 ();
#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.
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; \
} \
} \
#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)); \
\
""
"
{
+ /* 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]))
;; }
;; }")
+;; 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
;;
;; ....................