diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-05-23 07:43:13 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-05-23 07:43:13 +0000 |
commit | 2b8ca2992c00cbb7c5ff5a1527f8b671ce8b2752 (patch) | |
tree | f1439a904007439715062fb9bf92dd5024deb42f /gcc/config/i386 | |
parent | f993b2302ece6964f4e3e95dfc41d202e1d466eb (diff) | |
download | gcc-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.h | 2 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 65 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 68 |
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; }) |