summaryrefslogtreecommitdiff
path: root/gcc/config/i386
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2002-05-23 07:43:13 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2002-05-23 07:43:13 +0000
commit2b8ca2992c00cbb7c5ff5a1527f8b671ce8b2752 (patch)
treef1439a904007439715062fb9bf92dd5024deb42f /gcc/config/i386
parentf993b2302ece6964f4e3e95dfc41d202e1d466eb (diff)
downloadgcc-2b8ca2992c00cbb7c5ff5a1527f8b671ce8b2752.tar.gz
* config/i386/i386.c (get_pic_label_name): New.
(load_pic_register): Remove. (output_set_got): New. (ix86_expand_prologue): Use gen_set_got; mark insn REG_MAYBE_DEAD. * config/i386/i386.md (UNSPEC_SET_GOT): New. (UNSPECV_PROLOGUE_SET_GOT, UNSPECV_PROLOGUE_GET_PC): Remove. (prologue_set_got, prologue_get_pc): Remove. (set_got, set_got_nopic, set_got_deep, set_got_nodeep): New. (builtin_setjmp_receiver): Use gen_set_got. * config/i386/i386-protos.h: Update. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@53773 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/i386')
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c65
-rw-r--r--gcc/config/i386/i386.md68
3 files changed, 78 insertions, 57 deletions
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index c02e2e3ffc7..21babe91c2d 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -28,7 +28,6 @@ extern int ix86_frame_pointer_required PARAMS ((void));
extern void ix86_setup_frame_addresses PARAMS ((void));
extern void ix86_asm_file_end PARAMS ((FILE *));
-extern void load_pic_register PARAMS ((void));
extern HOST_WIDE_INT ix86_initial_elimination_offset PARAMS((int, int));
extern void ix86_expand_prologue PARAMS ((void));
extern void ix86_expand_epilogue PARAMS ((int));
@@ -96,6 +95,7 @@ extern void print_operand_address PARAMS ((FILE*, rtx));
extern void split_di PARAMS ((rtx[], int, rtx[], rtx[]));
extern void split_ti PARAMS ((rtx[], int, rtx[], rtx[]));
+extern const char *output_set_got PARAMS ((rtx));
extern const char *output_387_binary_op PARAMS ((rtx, rtx*));
extern const char *output_fix_trunc PARAMS ((rtx, rtx*));
extern const char *output_fp_compare PARAMS ((rtx, rtx*, int, int));
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 65051319169..96d0916d86a 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -647,6 +647,7 @@ static char internal_label_prefix[16];
static int internal_label_prefix_len;
static int local_symbolic_operand PARAMS ((rtx, enum machine_mode));
+static const char *get_pic_label_name PARAMS ((void));
static void output_pic_addr_const PARAMS ((FILE *, rtx, int));
static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode,
int, int, FILE *));
@@ -3795,6 +3796,14 @@ ix86_setup_frame_addresses ()
static char pic_label_name[32];
+static const char *
+get_pic_label_name ()
+{
+ if (! pic_label_name[0])
+ ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
+ return pic_label_name;
+}
+
/* This function generates code for -fpic that loads %ebx with
the return address of the caller and then returns. */
@@ -3847,33 +3856,45 @@ ix86_asm_file_end (file)
output_asm_insn ("ret", xops);
}
-void
-load_pic_register ()
-{
- rtx gotsym, pclab;
+/* Emit code for the SET_GOT patterns. */
- if (TARGET_64BIT)
- abort ();
+const char *
+output_set_got (dest)
+ rtx dest;
+{
+ rtx xops[3];
- gotsym = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+ xops[0] = dest;
+ xops[1] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
- if (TARGET_DEEP_BRANCH_PREDICTION)
+ if (! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic)
{
- if (! pic_label_name[0])
- ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
- pclab = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, pic_label_name));
+ xops[2] = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
+
+ if (!flag_pic)
+ output_asm_insn ("mov{l}\t{%2, %0|%0, %2}", xops);
+ else
+ output_asm_insn ("call\t%a2", xops);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
+
+ if (flag_pic)
+ output_asm_insn ("pop{l}\t%0", xops);
}
else
{
- pclab = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ xops[2] = gen_rtx_SYMBOL_REF (Pmode, get_pic_label_name ());
+ xops[2] = gen_rtx_MEM (QImode, xops[2]);
+ output_asm_insn ("call\t%X2", xops);
}
- emit_insn (gen_prologue_get_pc (pic_offset_table_rtx, pclab));
-
- if (! TARGET_DEEP_BRANCH_PREDICTION)
- emit_insn (gen_popsi1 (pic_offset_table_rtx));
+ if (!flag_pic || TARGET_DEEP_BRANCH_PREDICTION)
+ output_asm_insn ("add{l}\t{%1, %0|%0, %1}", xops);
+ else
+ output_asm_insn ("add{l}\t{%1+[.-%X2], %0|%0, %a1+(.-%X2)}", xops);
- emit_insn (gen_prologue_set_got (pic_offset_table_rtx, gotsym, pclab));
+ return "";
}
/* Generate an "push" pattern for input ARG. */
@@ -4197,7 +4218,15 @@ ix86_expand_prologue ()
#endif
if (pic_reg_used)
- load_pic_register ();
+ {
+ insn = emit_insn (gen_set_got (pic_offset_table_rtx));
+
+ /* ??? The current_function_uses_pic_offset_table flag is woefully
+ inaccurate, as it isn't updated as code gets deleted. Allow the
+ thing to be removed. A better solution would be to actually get
+ proper liveness for ebx, as then we won't save/restore it too. */
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
+ }
/* If we are profiling, make sure no instructions are scheduled before
the call to mcount. However, if -fpic, the above call will have
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index cdd99fc22d5..a385ead7ad5 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -69,6 +69,7 @@
(UNSPEC_SSE_PROLOGUE_SAVE 13)
(UNSPEC_FLDCW 14)
(UNSPEC_GOTPCREL 15)
+ (UNSPEC_SET_GOT 16)
; For SSE/MMX support:
(UNSPEC_FIX 30)
@@ -97,8 +98,6 @@
(define_constants
[(UNSPECV_BLOCKAGE 0)
- (UNSPECV_PROLOGUE_SET_GOT 1)
- (UNSPECV_PROLOGUE_GET_PC 2)
(UNSPECV_EH_RETURN 13)
(UNSPECV_EMMS 31)
(UNSPECV_LDMXCSR 37)
@@ -13120,46 +13119,39 @@
""
"ix86_expand_prologue (); DONE;")
-(define_insn "prologue_set_got"
+(define_expand "set_got"
+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
+ (clobber (reg:CC 17))])]
+ "!TARGET_64BIT"
+ "")
+
+(define_insn "*set_got_nopic"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec_volatile:SI
- [(plus:SI (match_dup 0)
- (plus:SI (match_operand:SI 1 "symbolic_operand" "")
- (minus:SI (pc) (match_operand 2 "" ""))))]
- UNSPECV_PROLOGUE_SET_GOT))
+ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
(clobber (reg:CC 17))]
- "!TARGET_64BIT"
-{
- if (GET_CODE (operands[2]) == LABEL_REF)
- operands[2] = XEXP (operands[2], 0);
- if (TARGET_DEEP_BRANCH_PREDICTION)
- return "add{l}\t{%1, %0|%0, %1}";
- else
- return "add{l}\t{%1+[.-%X2], %0|%0, %a1+(.-%X2)}";
-}
- [(set_attr "type" "alu")
- ; Since this insn may have two constant operands, we must set the
- ; length manually.
- (set_attr "length_immediate" "4")
- (set_attr "mode" "SI")])
+ "!TARGET_64BIT && !flag_pic"
+ { return output_set_got (operands[0]); }
+ [(set_attr "type" "multi")
+ (set_attr "length" "11")])
-(define_insn "prologue_get_pc"
+(define_insn "*set_got_deep"
+ [(set (match_operand:SI 0 "register_operand" "=b")
+ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
+ (clobber (reg:CC 17))]
+ "!TARGET_64BIT && TARGET_DEEP_BRANCH_PREDICTION"
+ { return output_set_got (operands[0]); }
+ [(set_attr "type" "multi")
+ (set_attr "length" "11")])
+
+(define_insn "*set_got_nodeep"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec_volatile:SI [(plus:SI (pc) (match_operand 1 "" ""))]
- UNSPECV_PROLOGUE_GET_PC))]
+ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
+ (clobber (reg:CC 17))]
"!TARGET_64BIT"
-{
- if (GET_CODE (operands[1]) == LABEL_REF)
- operands[1] = XEXP (operands[1], 0);
- output_asm_insn ("call\t%X1", operands);
- if (! TARGET_DEEP_BRANCH_PREDICTION)
- {
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
- CODE_LABEL_NUMBER (operands[1]));
- }
- RET;
-}
- [(set_attr "type" "multi")])
+ { return output_set_got (operands[0]); }
+ [(set_attr "type" "multi")
+ (set_attr "length" "12")])
(define_expand "epilogue"
[(const_int 1)]
@@ -16212,7 +16204,7 @@
[(label_ref (match_operand 0 "" ""))]
"!TARGET_64BIT && flag_pic"
{
- load_pic_register ();
+ emit_insn (gen_set_got (pic_offset_table_rtx));
DONE;
})