From: Ian Lance Taylor Date: Thu, 21 Apr 1994 18:28:09 +0000 (+0000) Subject: Handle taking address of function when using -membedded-pic X-Git-Tag: misc/cutover-egcs-0~6838 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=92544bdfd59b9deb0ae56887f89f6719321bc20e;p=thirdparty%2Fgcc.git Handle taking address of function when using -membedded-pic From-SVN: r7105 --- diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 562a1e98a6d2..66c31e15a243 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 * @@ -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. */ diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index dd4dc003649f..4f4b8f8ce1c9 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 be9e1512a06b..dfe0dad17885 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")]) + ;; ;; ....................