aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meissner <meissner@gcc.gnu.org>1996-04-08 19:48:29 +0000
committerMichael Meissner <meissner@gcc.gnu.org>1996-04-08 19:48:29 +0000
commit766a866c11644e16aadc27aa954332d4b0c464ac (patch)
treea72000c5003c2623a66a656aa3890c50072b574e
parent2038dc12982de24c46a65f5339c105ad81c4a5f9 (diff)
downloadgcc-766a866c11644e16aadc27aa954332d4b0c464ac.zip
gcc-766a866c11644e16aadc27aa954332d4b0c464ac.tar.gz
gcc-766a866c11644e16aadc27aa954332d4b0c464ac.tar.bz2
Add -fpic/-fPIC support
From-SVN: r11676
-rw-r--r--gcc/config/rs6000/rs6000.c16
-rw-r--r--gcc/config/rs6000/rs6000.h53
-rw-r--r--gcc/config/rs6000/rs6000.md82
3 files changed, 148 insertions, 3 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 9a35b2f..cd3f675 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -93,6 +93,9 @@ enum rs6000_abi rs6000_current_abi;
/* Temporary memory used to convert integer -> float */
static rtx stack_temps[NUM_MACHINE_MODES];
+/* Current PIC register used by the V4 code */
+struct rtx_def *rs6000_pic_register = (struct rtx_def *)0;
+
/* Print the options used in the assembly file. */
@@ -524,6 +527,18 @@ reg_or_cint_operand (op, mode)
return GET_CODE (op) == CONST_INT || gpc_reg_operand (op, mode);
}
+/* Return 1 if the operand is an operand that can be loaded via the GOT */
+
+int
+got_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == SYMBOL_REF
+ || GET_CODE (op) == CONST
+ || GET_CODE (op) == LABEL_REF);
+}
+
/* Return the number of instructions it takes to form a constant in an
integer register. */
@@ -3663,6 +3678,7 @@ output_epilog (file, size)
/* Reset varargs and save TOC indicator */
rs6000_sysv_varargs_p = 0;
rs6000_save_toc_p = 0;
+ rs6000_pic_register = (rtx)0;
if (DEFAULT_ABI == ABI_NT)
{
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 669dacb..1620ad4 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1842,6 +1842,54 @@ typedef struct rs6000_args
goto LABEL; \
}
+/* The register number of the register used to address a table of
+ static data addresses in memory. In some cases this register is
+ defined by a processor's "application binary interface" (ABI).
+ When this macro is defined, RTL is generated for this register
+ once, as with the stack pointer and frame pointer registers. If
+ this macro is not defined, it is up to the machine-dependent files
+ to allocate such a register (if necessary). */
+
+/* #define PIC_OFFSET_TABLE_REGNUM */
+
+/* Define this macro if the register defined by
+ `PIC_OFFSET_TABLE_REGNUM' is clobbered by calls. Do not define
+ this macro if `PPIC_OFFSET_TABLE_REGNUM' is not defined. */
+
+/* #define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED */
+
+/* By generating position-independent code, when two different
+ programs (A and B) share a common library (libC.a), the text of
+ the library can be shared whether or not the library is linked at
+ the same address for both programs. In some of these
+ environments, position-independent code requires not only the use
+ of different addressing modes, but also special code to enable the
+ use of these addressing modes.
+
+ The `FINALIZE_PIC' macro serves as a hook to emit these special
+ codes once the function is being compiled into assembly code, but
+ not before. (It is not done before, because in the case of
+ compiling an inline function, it would lead to multiple PIC
+ prologues being included in functions which used inline functions
+ and were compiled to assembly language.) */
+
+/* #define FINALIZE_PIC */
+
+/* Current PIC register used by the V4 code */
+extern struct rtx_def *rs6000_pic_register;
+
+
+/* A C expression that is nonzero if X is a legitimate immediate
+ operand on the target machine when generating position independent
+ code. You can assume that X satisfies `CONSTANT_P', so you need
+ not check this. You can also assume FLAG_PIC is true, so you need
+ not check it either. You need not define this macro if all
+ constants (including `SYMBOL_REF') can be immediate operands when
+ generating position independent code. */
+
+/* #define LEGITIMATE_PIC_OPERAND_P (X) */
+
+
/* Define this if some processing needs to be done immediately before
emitting code for an insn. */
@@ -2769,6 +2817,7 @@ do { \
{"reg_or_neg_short_operand", {SUBREG, REG, CONST_INT}}, \
{"reg_or_u_short_operand", {SUBREG, REG, CONST_INT}}, \
{"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \
+ {"got_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
{"easy_fp_constant", {CONST_DOUBLE}}, \
{"reg_or_mem_operand", {SUBREG, MEM, REG}}, \
{"lwa_operand", {SUBREG, MEM, REG}}, \
@@ -2804,7 +2853,8 @@ do { \
(no need to use the default) */
#define MACHINE_issue_rate
-/* General optimization flags. */
+/* General flags. */
+extern int flag_pic;
extern int optimize;
extern int flag_expensive_optimizations;
@@ -2824,6 +2874,7 @@ extern int reg_or_short_operand ();
extern int reg_or_neg_short_operand ();
extern int reg_or_u_short_operand ();
extern int reg_or_cint_operand ();
+extern int got_operand ();
extern int num_insns_constant ();
extern int easy_fp_constant ();
extern int volatile_mem_operand ();
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 58258b3..5aa1813 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -4815,6 +4815,68 @@
"TARGET_ELF && !TARGET_64BIT"
"{cal %0,%a2@l(%1)|addi %0,%1,%2@l}")
+;; Set up a register with a value from the GOT table
+
+(define_expand "movsi_got"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unspec [(match_operand:SI 1 "got_operand" "")
+ (match_dup 2)] 8))]
+ "DEFAULT_ABI == ABI_V4 && flag_pic"
+ "
+{
+ if (!rs6000_pic_register)
+ {
+ rs6000_pic_register = gen_reg_rtx (SImode);
+ emit_insn (gen_init_v4_pic (rs6000_pic_register));
+ }
+
+ operands[2] = rs6000_pic_register;
+ if (flag_pic > 1)
+ {
+ emit_insn (gen_movsi_got_large (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+}")
+
+(define_insn "*movsi_got_internal1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec [(match_operand:SI 1 "got_operand" "")
+ (match_operand:SI 2 "register_operand" "b")] 8))]
+ "DEFAULT_ABI == ABI_V4 && flag_pic == 1"
+ "{l|lwz} %0,%a1@got(%2)"
+ [(set_attr "type" "load")])
+
+(define_expand "movsi_got_large"
+ [(set (match_dup 3)
+ (unspec [(match_operand:SI 1 "got_operand" "")] 9))
+ (set (match_dup 3)
+ (unspec [(match_dup 1)
+ (match_dup 3)] 10))
+ (set (match_operand:SI 0 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 3)
+ (match_operand:SI 2 "register_operand" ""))))]
+ "DEFAULT_ABI == ABI_V4 && flag_pic > 1"
+ "
+{
+ if (reload_completed || reload_in_progress)
+ abort ();
+
+ operands[3] = gen_reg_rtx (SImode);
+}")
+
+(define_insn "*movsi_got_internal2_high"
+ [(set (match_operand:SI 0 "register_operand" "=b")
+ (unspec [(match_operand:SI 1 "got_operand" "")] 9))]
+ "DEFAULT_ABI == ABI_V4 && flag_pic > 1"
+ "{cau|addis} %0,0,%1@got@ha")
+
+(define_insn "*movsi_got_internal2_losum"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec [(match_operand:SI 1 "got_operand" "")
+ (match_operand:SI 2 "register_operand" "b")] 10))]
+ "DEFAULT_ABI == ABI_V4 && flag_pic > 1"
+ "{cal %0,%a1@got@l(%2)|addi %0,%2,%a1@got@l}")
+
;; For SI, we special-case integers that can't be loaded in one insn. We
;; do the load 16-bits at a time. We could do this by loading from memory,
;; and this is even supposed to be faster, but it is simpler not to get
@@ -4842,6 +4904,12 @@
DONE;
}
+ if (DEFAULT_ABI == ABI_V4 && flag_pic && got_operand (operands[1], SImode))
+ {
+ emit_insn (gen_movsi_got (operands[0], operands[1]));
+ DONE;
+ }
+
if (TARGET_ELF && TARGET_NO_TOC && !TARGET_64BIT
&& CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != HIGH
@@ -6985,7 +7053,7 @@
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
- return \"bl %z0\";
+ return (flag_pic) ? \"bl %z0@plt\" : \"bl %z0\";
}"
[(set_attr "type" "branch")
(set_attr "length" "4,8")])
@@ -7055,7 +7123,7 @@
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
- return \"bl %z1\";
+ return (flag_pic) ? \"bl %z1@plt\" : \"bl %z1\";
}"
[(set_attr "type" "branch")
(set_attr "length" "4,8")])
@@ -7123,6 +7191,16 @@
""
"{ics|isync}")
+
+;; V.4 specific code to initialize the PIC register
+
+(define_insn "init_v4_pic"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (unspec [(const_int 0)] 7))]
+ "DEFAULT_ABI == ABI_V4"
+ "bl _GLOBAL_OFFSET_TABLE_-4"
+ [(set_attr "type" "branch")])
+
;; Compare insns are next. Note that the RS/6000 has two types of compares,
;; signed & unsigned, and one type of branch.