mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-25 07:25:32 +08:00
Introduce TLS descriptors for i386 and x86_64.
* config/i386/i386.h (TARGET_GNU2_TLS): New macro. (TARGET_ANY_GNU_TLS): New macro. (enum tls_dialect): Added TLS_DIALECT_GNU2. (struct machine_function): Add tls_descriptor_call_expanded_p. (ix86_tls_descriptor_calls_expande_in_cfun): New macro. (ix86_current_function_calls_tls_descriptor): Likewise. * config/i386/i386.c (ix86_tls_dialect): Fix typo in comment. (override_options): Introduce gnu2 tls dialect. (ix86_frame_pointer_required): Functions containing TLSCALLs are not leaves. (ix86_select_alt_pic_regnum, ix86_compute_frame_layout): Likewise. (legitimize_tls_address): Adjust logic for GNU2 TLS. (ix86_init_machine_status): Initialize new field. (ix86_tls_get_addr): Use TARGET_ANY_GNU_TLS. (ix86_tls_module_base): New. * config/i386/i386-protos.h (ix86_tls_module_base): Declare it. * config/i386/i386.md (UNSPEC_TLSDESC): New constant. (tls_global_dynamic_32, tls_global_dynamic_64): Handle GNU2 TLS. (tls_local_dynamic_base_32, tls_local_dynamic_base_64): Likewise. (tls_dynamic_gnu2_32, *tls_dynamic_lea_32): New patterns. (*tls_dynamic_call_32, *tls_dynamic_gnu2_combine_32): Likewise. (tls_dynamic_gnu2_64, *tls_dynamic_lea_64): Likewise. (*tls_dynamic_call_64, *tls_dynamic_gnu2_combine_64): Likewise. * config/i386/predicates.md (tls_modbase_operand): New. (tp_or_register_operand): New. From-SVN: r109934
This commit is contained in:
parent
7dbca013b2
commit
5bf5a10b1c
@ -1,3 +1,33 @@
|
||||
2006-01-18 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
Introduce TLS descriptors for i386 and x86_64.
|
||||
* config/i386/i386.h (TARGET_GNU2_TLS): New macro.
|
||||
(TARGET_ANY_GNU_TLS): New macro.
|
||||
(enum tls_dialect): Added TLS_DIALECT_GNU2.
|
||||
(struct machine_function): Add tls_descriptor_call_expanded_p.
|
||||
(ix86_tls_descriptor_calls_expande_in_cfun): New macro.
|
||||
(ix86_current_function_calls_tls_descriptor): Likewise.
|
||||
* config/i386/i386.c (ix86_tls_dialect): Fix typo in comment.
|
||||
(override_options): Introduce gnu2 tls dialect.
|
||||
(ix86_frame_pointer_required): Functions containing TLSCALLs are
|
||||
not leaves.
|
||||
(ix86_select_alt_pic_regnum, ix86_compute_frame_layout):
|
||||
Likewise.
|
||||
(legitimize_tls_address): Adjust logic for GNU2 TLS.
|
||||
(ix86_init_machine_status): Initialize new field.
|
||||
(ix86_tls_get_addr): Use TARGET_ANY_GNU_TLS.
|
||||
(ix86_tls_module_base): New.
|
||||
* config/i386/i386-protos.h (ix86_tls_module_base): Declare it.
|
||||
* config/i386/i386.md (UNSPEC_TLSDESC): New constant.
|
||||
(tls_global_dynamic_32, tls_global_dynamic_64): Handle GNU2 TLS.
|
||||
(tls_local_dynamic_base_32, tls_local_dynamic_base_64): Likewise.
|
||||
(tls_dynamic_gnu2_32, *tls_dynamic_lea_32): New patterns.
|
||||
(*tls_dynamic_call_32, *tls_dynamic_gnu2_combine_32): Likewise.
|
||||
(tls_dynamic_gnu2_64, *tls_dynamic_lea_64): Likewise.
|
||||
(*tls_dynamic_call_64, *tls_dynamic_gnu2_combine_64): Likewise.
|
||||
* config/i386/predicates.md (tls_modbase_operand): New.
|
||||
(tp_or_register_operand): New.
|
||||
|
||||
2006-01-18 Daniel Berlin <dberlin@dberlin.org>
|
||||
|
||||
* ipa-reference.c (check_operand): Allow FUNCTION_DECL.
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* Definitions of target machine for GCC for IA-32.
|
||||
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1996, 1997, 1998, 1999,
|
||||
2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -179,6 +180,7 @@ extern int x86_field_alignment (tree, int);
|
||||
#endif
|
||||
|
||||
extern rtx ix86_tls_get_addr (void);
|
||||
extern rtx ix86_tls_module_base (void);
|
||||
|
||||
extern void ix86_expand_vector_init (bool, rtx, rtx);
|
||||
extern void ix86_expand_vector_set (bool, rtx, rtx, int);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Subroutines used for code generation on IA-32.
|
||||
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -876,7 +876,7 @@ struct ix86_frame
|
||||
enum cmodel ix86_cmodel;
|
||||
/* Asm dialect. */
|
||||
enum asm_dialect ix86_asm_dialect = ASM_ATT;
|
||||
/* TLS dialext. */
|
||||
/* TLS dialects. */
|
||||
enum tls_dialect ix86_tls_dialect = TLS_DIALECT_GNU;
|
||||
|
||||
/* Which unit we are generating floating point math for. */
|
||||
@ -1626,6 +1626,8 @@ override_options (void)
|
||||
{
|
||||
if (strcmp (ix86_tls_dialect_string, "gnu") == 0)
|
||||
ix86_tls_dialect = TLS_DIALECT_GNU;
|
||||
else if (strcmp (ix86_tls_dialect_string, "gnu2") == 0)
|
||||
ix86_tls_dialect = TLS_DIALECT_GNU2;
|
||||
else if (strcmp (ix86_tls_dialect_string, "sun") == 0)
|
||||
ix86_tls_dialect = TLS_DIALECT_SUN;
|
||||
else
|
||||
@ -4415,7 +4417,8 @@ ix86_frame_pointer_required (void)
|
||||
the frame pointer by default. Turn it back on now if we've not
|
||||
got a leaf function. */
|
||||
if (TARGET_OMIT_LEAF_FRAME_POINTER
|
||||
&& (!current_function_is_leaf))
|
||||
&& (!current_function_is_leaf
|
||||
|| ix86_current_function_calls_tls_descriptor))
|
||||
return 1;
|
||||
|
||||
if (current_function_profile)
|
||||
@ -4597,7 +4600,8 @@ gen_push (rtx arg)
|
||||
static unsigned int
|
||||
ix86_select_alt_pic_regnum (void)
|
||||
{
|
||||
if (current_function_is_leaf && !current_function_profile)
|
||||
if (current_function_is_leaf && !current_function_profile
|
||||
&& !ix86_current_function_calls_tls_descriptor)
|
||||
{
|
||||
int i;
|
||||
for (i = 2; i >= 0; --i)
|
||||
@ -4788,7 +4792,8 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
|
||||
expander assumes that last current_function_outgoing_args_size
|
||||
of stack frame are unused. */
|
||||
if (ACCUMULATE_OUTGOING_ARGS
|
||||
&& (!current_function_is_leaf || current_function_calls_alloca))
|
||||
&& (!current_function_is_leaf || current_function_calls_alloca
|
||||
|| ix86_current_function_calls_tls_descriptor))
|
||||
{
|
||||
offset += current_function_outgoing_args_size;
|
||||
frame->outgoing_arguments_size = current_function_outgoing_args_size;
|
||||
@ -4798,7 +4803,8 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
|
||||
|
||||
/* Align stack boundary. Only needed if we're calling another function
|
||||
or using alloca. */
|
||||
if (!current_function_is_leaf || current_function_calls_alloca)
|
||||
if (!current_function_is_leaf || current_function_calls_alloca
|
||||
|| ix86_current_function_calls_tls_descriptor)
|
||||
frame->padding2 = ((offset + preferred_alignment - 1)
|
||||
& -preferred_alignment) - offset;
|
||||
else
|
||||
@ -4819,7 +4825,8 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
|
||||
frame->save_regs_using_mov = false;
|
||||
|
||||
if (TARGET_RED_ZONE && current_function_sp_is_unchanging
|
||||
&& current_function_is_leaf)
|
||||
&& current_function_is_leaf
|
||||
&& !ix86_current_function_calls_tls_descriptor)
|
||||
{
|
||||
frame->red_zone_size = frame->to_allocate;
|
||||
if (frame->save_regs_using_mov)
|
||||
@ -6351,14 +6358,16 @@ get_thread_pointer (int to_reg)
|
||||
static rtx
|
||||
legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
|
||||
{
|
||||
rtx dest, base, off, pic;
|
||||
rtx dest, base, off, pic, tp;
|
||||
int type;
|
||||
|
||||
switch (model)
|
||||
{
|
||||
case TLS_MODEL_GLOBAL_DYNAMIC:
|
||||
dest = gen_reg_rtx (Pmode);
|
||||
if (TARGET_64BIT)
|
||||
tp = TARGET_GNU2_TLS ? get_thread_pointer (1) : 0;
|
||||
|
||||
if (TARGET_64BIT && ! TARGET_GNU2_TLS)
|
||||
{
|
||||
rtx rax = gen_rtx_REG (Pmode, 0), insns;
|
||||
|
||||
@ -6369,13 +6378,24 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
|
||||
|
||||
emit_libcall_block (insns, dest, rax, x);
|
||||
}
|
||||
else if (TARGET_64BIT && TARGET_GNU2_TLS)
|
||||
emit_insn (gen_tls_global_dynamic_64 (dest, x));
|
||||
else
|
||||
emit_insn (gen_tls_global_dynamic_32 (dest, x));
|
||||
|
||||
if (TARGET_GNU2_TLS)
|
||||
{
|
||||
dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, tp, dest));
|
||||
|
||||
set_unique_reg_note (get_last_insn (), REG_EQUIV, x);
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_MODEL_LOCAL_DYNAMIC:
|
||||
base = gen_reg_rtx (Pmode);
|
||||
if (TARGET_64BIT)
|
||||
tp = TARGET_GNU2_TLS ? get_thread_pointer (1) : 0;
|
||||
|
||||
if (TARGET_64BIT && ! TARGET_GNU2_TLS)
|
||||
{
|
||||
rtx rax = gen_rtx_REG (Pmode, 0), insns, note;
|
||||
|
||||
@ -6388,13 +6408,25 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
|
||||
note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note);
|
||||
emit_libcall_block (insns, base, rax, note);
|
||||
}
|
||||
else if (TARGET_64BIT && TARGET_GNU2_TLS)
|
||||
emit_insn (gen_tls_local_dynamic_base_64 (base));
|
||||
else
|
||||
emit_insn (gen_tls_local_dynamic_base_32 (base));
|
||||
|
||||
if (TARGET_GNU2_TLS)
|
||||
{
|
||||
rtx x = ix86_tls_module_base ();
|
||||
|
||||
base = force_reg (Pmode, gen_rtx_PLUS (Pmode, tp, base));
|
||||
|
||||
set_unique_reg_note (get_last_insn (), REG_EQUIV, x);
|
||||
}
|
||||
|
||||
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
|
||||
off = gen_rtx_CONST (Pmode, off);
|
||||
|
||||
return gen_rtx_PLUS (Pmode, base, off);
|
||||
dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, off));
|
||||
break;
|
||||
|
||||
case TLS_MODEL_INITIAL_EXEC:
|
||||
if (TARGET_64BIT)
|
||||
@ -6407,9 +6439,9 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
|
||||
if (reload_in_progress)
|
||||
regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
|
||||
pic = pic_offset_table_rtx;
|
||||
type = TARGET_GNU_TLS ? UNSPEC_GOTNTPOFF : UNSPEC_GOTTPOFF;
|
||||
type = TARGET_ANY_GNU_TLS ? UNSPEC_GOTNTPOFF : UNSPEC_GOTTPOFF;
|
||||
}
|
||||
else if (!TARGET_GNU_TLS)
|
||||
else if (!TARGET_ANY_GNU_TLS)
|
||||
{
|
||||
pic = gen_reg_rtx (Pmode);
|
||||
emit_insn (gen_set_got (pic));
|
||||
@ -6428,7 +6460,7 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
|
||||
off = gen_const_mem (Pmode, off);
|
||||
set_mem_alias_set (off, ix86_GOT_alias_set ());
|
||||
|
||||
if (TARGET_64BIT || TARGET_GNU_TLS)
|
||||
if (TARGET_64BIT || TARGET_ANY_GNU_TLS)
|
||||
{
|
||||
base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS);
|
||||
off = force_reg (Pmode, off);
|
||||
@ -6444,11 +6476,11 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
|
||||
|
||||
case TLS_MODEL_LOCAL_EXEC:
|
||||
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
|
||||
(TARGET_64BIT || TARGET_GNU_TLS)
|
||||
(TARGET_64BIT || TARGET_ANY_GNU_TLS)
|
||||
? UNSPEC_NTPOFF : UNSPEC_TPOFF);
|
||||
off = gen_rtx_CONST (Pmode, off);
|
||||
|
||||
if (TARGET_64BIT || TARGET_GNU_TLS)
|
||||
if (TARGET_64BIT || TARGET_ANY_GNU_TLS)
|
||||
{
|
||||
base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS);
|
||||
return gen_rtx_PLUS (Pmode, base, off);
|
||||
@ -12900,6 +12932,7 @@ ix86_init_machine_status (void)
|
||||
|
||||
f = ggc_alloc_cleared (sizeof (struct machine_function));
|
||||
f->use_fast_prologue_epilogue_nregs = -1;
|
||||
f->tls_descriptor_call_expanded_p = 0;
|
||||
|
||||
return f;
|
||||
}
|
||||
@ -12942,13 +12975,32 @@ ix86_tls_get_addr (void)
|
||||
if (!ix86_tls_symbol)
|
||||
{
|
||||
ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode,
|
||||
(TARGET_GNU_TLS && !TARGET_64BIT)
|
||||
(TARGET_ANY_GNU_TLS
|
||||
&& !TARGET_64BIT)
|
||||
? "___tls_get_addr"
|
||||
: "__tls_get_addr");
|
||||
}
|
||||
|
||||
return ix86_tls_symbol;
|
||||
}
|
||||
|
||||
/* Construct the SYMBOL_REF for the _TLS_MODULE_BASE_ symbol. */
|
||||
|
||||
static GTY(()) rtx ix86_tls_module_base_symbol;
|
||||
rtx
|
||||
ix86_tls_module_base (void)
|
||||
{
|
||||
|
||||
if (!ix86_tls_module_base_symbol)
|
||||
{
|
||||
ix86_tls_module_base_symbol = gen_rtx_SYMBOL_REF (Pmode,
|
||||
"_TLS_MODULE_BASE_");
|
||||
SYMBOL_REF_FLAGS (ix86_tls_module_base_symbol)
|
||||
|= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT;
|
||||
}
|
||||
|
||||
return ix86_tls_module_base_symbol;
|
||||
}
|
||||
|
||||
/* Calculate the length of the memory address in the instruction
|
||||
encoding. Does not include the one-byte modrm, opcode, or prefix. */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Definitions of target machine for GCC for IA-32.
|
||||
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -225,6 +225,8 @@ extern int x86_prefetch_sse;
|
||||
&& (ix86_fpmath & FPMATH_387))
|
||||
|
||||
#define TARGET_GNU_TLS (ix86_tls_dialect == TLS_DIALECT_GNU)
|
||||
#define TARGET_GNU2_TLS (ix86_tls_dialect == TLS_DIALECT_GNU2)
|
||||
#define TARGET_ANY_GNU_TLS (TARGET_GNU_TLS || TARGET_GNU2_TLS)
|
||||
#define TARGET_SUN_TLS (ix86_tls_dialect == TLS_DIALECT_SUN)
|
||||
|
||||
#define TARGET_CMPXCHG (x86_cmpxchg & (1 << ix86_arch))
|
||||
@ -2134,6 +2136,7 @@ extern enum fpmath_unit ix86_fpmath;
|
||||
enum tls_dialect
|
||||
{
|
||||
TLS_DIALECT_GNU,
|
||||
TLS_DIALECT_GNU2,
|
||||
TLS_DIALECT_SUN
|
||||
};
|
||||
|
||||
@ -2275,11 +2278,30 @@ struct machine_function GTY(())
|
||||
/* Number of saved registers USE_FAST_PROLOGUE_EPILOGUE has been computed
|
||||
for. */
|
||||
int use_fast_prologue_epilogue_nregs;
|
||||
/* If true, the current function needs the default PIC register, not
|
||||
an alternate register (on x86) and must not use the red zone (on
|
||||
x86_64), even if it's a leaf function. We don't want the
|
||||
function to be regarded as non-leaf because TLS calls need not
|
||||
affect register allocation. This flag is set when a TLS call
|
||||
instruction is expanded within a function, and never reset, even
|
||||
if all such instructions are optimized away. Use the
|
||||
ix86_current_function_calls_tls_descriptor macro for a better
|
||||
approximation. */
|
||||
int tls_descriptor_call_expanded_p;
|
||||
};
|
||||
|
||||
#define ix86_stack_locals (cfun->machine->stack_locals)
|
||||
#define ix86_save_varrargs_registers (cfun->machine->save_varrargs_registers)
|
||||
#define ix86_optimize_mode_switching (cfun->machine->optimize_mode_switching)
|
||||
#define ix86_tls_descriptor_calls_expanded_in_cfun \
|
||||
(cfun->machine->tls_descriptor_call_expanded_p)
|
||||
/* Since tls_descriptor_call_expanded is not cleared, even if all TLS
|
||||
calls are optimized away, we try to detect cases in which it was
|
||||
optimized away. Since such instructions (use (reg REG_SP)), we can
|
||||
verify whether there's any such instruction live by testing that
|
||||
REG_SP is live. */
|
||||
#define ix86_current_function_calls_tls_descriptor \
|
||||
(ix86_tls_descriptor_calls_expanded_in_cfun && regs_ever_live[SP_REG])
|
||||
|
||||
/* Control behavior of x86_file_start. */
|
||||
#define X86_FILE_START_VERSION_DIRECTIVE false
|
||||
|
@ -1,6 +1,6 @@
|
||||
;; GCC machine description for IA-32 and x86-64.
|
||||
;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
;; 2001, 2002, 2003, 2004, 2005
|
||||
;; 2001, 2002, 2003, 2004, 2005, 2006
|
||||
;; Free Software Foundation, Inc.
|
||||
;; Mostly by William Schelter.
|
||||
;; x86_64 support added by Jan Hubicka
|
||||
@ -73,6 +73,7 @@
|
||||
(UNSPEC_TP 16)
|
||||
(UNSPEC_TLS_GD 17)
|
||||
(UNSPEC_TLS_LD_BASE 18)
|
||||
(UNSPEC_TLSDESC 19)
|
||||
|
||||
; Other random patterns
|
||||
(UNSPEC_SCAS 20)
|
||||
@ -14161,6 +14162,12 @@
|
||||
operands[2] = gen_reg_rtx (Pmode);
|
||||
emit_insn (gen_set_got (operands[2]));
|
||||
}
|
||||
if (TARGET_GNU2_TLS)
|
||||
{
|
||||
emit_insn (gen_tls_dynamic_gnu2_32
|
||||
(operands[0], operands[1], operands[2]));
|
||||
DONE;
|
||||
}
|
||||
operands[3] = ix86_tls_get_addr ();
|
||||
})
|
||||
|
||||
@ -14182,6 +14189,12 @@
|
||||
UNSPEC_TLS_GD)])]
|
||||
""
|
||||
{
|
||||
if (TARGET_GNU2_TLS)
|
||||
{
|
||||
emit_insn (gen_tls_dynamic_gnu2_64
|
||||
(operands[0], operands[1]));
|
||||
DONE;
|
||||
}
|
||||
operands[2] = ix86_tls_get_addr ();
|
||||
})
|
||||
|
||||
@ -14228,6 +14241,12 @@
|
||||
operands[1] = gen_reg_rtx (Pmode);
|
||||
emit_insn (gen_set_got (operands[1]));
|
||||
}
|
||||
if (TARGET_GNU2_TLS)
|
||||
{
|
||||
emit_insn (gen_tls_dynamic_gnu2_32
|
||||
(operands[0], ix86_tls_module_base (), operands[1]));
|
||||
DONE;
|
||||
}
|
||||
operands[2] = ix86_tls_get_addr ();
|
||||
})
|
||||
|
||||
@ -14247,6 +14266,12 @@
|
||||
(unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
|
||||
""
|
||||
{
|
||||
if (TARGET_GNU2_TLS)
|
||||
{
|
||||
emit_insn (gen_tls_dynamic_gnu2_64
|
||||
(operands[0], ix86_tls_module_base ()));
|
||||
DONE;
|
||||
}
|
||||
operands[1] = ix86_tls_get_addr ();
|
||||
})
|
||||
|
||||
@ -14324,6 +14349,146 @@
|
||||
(set_attr "length" "7")
|
||||
(set_attr "memory" "load")
|
||||
(set_attr "imm_disp" "false")])
|
||||
|
||||
;; GNU2 TLS patterns can be split.
|
||||
|
||||
(define_expand "tls_dynamic_gnu2_32"
|
||||
[(set (match_dup 3)
|
||||
(plus:SI (match_operand:SI 2 "register_operand" "")
|
||||
(const:SI
|
||||
(unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")]
|
||||
UNSPEC_TLSDESC))))
|
||||
(parallel
|
||||
[(set (match_operand:SI 0 "register_operand" "")
|
||||
(unspec:SI [(match_dup 1) (match_dup 3)
|
||||
(match_dup 2) (reg:SI SP_REG)]
|
||||
UNSPEC_TLSDESC))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
"!TARGET_64BIT && TARGET_GNU2_TLS"
|
||||
{
|
||||
operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
|
||||
ix86_tls_descriptor_calls_expanded_in_cfun = true;
|
||||
})
|
||||
|
||||
(define_insn "*tls_dynamic_lea_32"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(plus:SI (match_operand:SI 1 "register_operand" "b")
|
||||
(const:SI
|
||||
(unspec:SI [(match_operand:SI 2 "tls_symbolic_operand" "")]
|
||||
UNSPEC_TLSDESC))))]
|
||||
"!TARGET_64BIT && TARGET_GNU2_TLS"
|
||||
"lea{l}\t{%a2@TLSDESC(%1), %0|%0, %a2@TLSDESC[%1]}"
|
||||
[(set_attr "type" "lea")
|
||||
(set_attr "mode" "SI")
|
||||
(set_attr "length" "6")
|
||||
(set_attr "length_address" "4")])
|
||||
|
||||
(define_insn "*tls_dynamic_call_32"
|
||||
[(set (match_operand:SI 0 "register_operand" "=a")
|
||||
(unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")
|
||||
(match_operand:SI 2 "register_operand" "0")
|
||||
;; we have to make sure %ebx still points to the GOT
|
||||
(match_operand:SI 3 "register_operand" "b")
|
||||
(reg:SI SP_REG)]
|
||||
UNSPEC_TLSDESC))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
"!TARGET_64BIT && TARGET_GNU2_TLS"
|
||||
"call\t{*%a1@TLSCALL(%2)|[DWORD PTR [%2+%a1@TLSCALL]]}"
|
||||
[(set_attr "type" "call")
|
||||
(set_attr "length" "2")
|
||||
(set_attr "length_address" "0")])
|
||||
|
||||
(define_insn_and_split "*tls_dynamic_gnu2_combine_32"
|
||||
[(set (match_operand:SI 0 "register_operand" "=&a")
|
||||
(plus:SI
|
||||
(plus:SI (match_operand:SI 3 "tp_or_register_operand" "ir")
|
||||
(unspec:SI [(match_operand:SI 4 "tls_modbase_operand" "")
|
||||
(match_operand:SI 5 "" "")
|
||||
(match_operand:SI 2 "register_operand" "b")
|
||||
(reg:SI SP_REG)]
|
||||
UNSPEC_TLSDESC))
|
||||
(const:SI (unspec:SI
|
||||
[(match_operand:SI 1 "tls_symbolic_operand" "")]
|
||||
UNSPEC_DTPOFF))))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
"!TARGET_64BIT && TARGET_GNU2_TLS"
|
||||
"#"
|
||||
""
|
||||
[(parallel
|
||||
[(set (match_dup 0)
|
||||
(plus:SI (match_dup 3)
|
||||
(match_dup 5)))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
{
|
||||
operands[5] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
|
||||
emit_insn (gen_tls_dynamic_gnu2_32 (operands[5], operands[1], operands[2]));
|
||||
})
|
||||
|
||||
(define_expand "tls_dynamic_gnu2_64"
|
||||
[(set (match_dup 2)
|
||||
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
|
||||
UNSPEC_TLSDESC))
|
||||
(parallel
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(unspec:DI [(match_dup 1) (match_dup 2) (reg:DI SP_REG)]
|
||||
UNSPEC_TLSDESC))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
"TARGET_64BIT && TARGET_GNU2_TLS"
|
||||
{
|
||||
operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
|
||||
ix86_tls_descriptor_calls_expanded_in_cfun = true;
|
||||
})
|
||||
|
||||
(define_insn "*tls_dynamic_lea_64"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
|
||||
UNSPEC_TLSDESC))]
|
||||
"TARGET_64BIT && TARGET_GNU2_TLS"
|
||||
"lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[%%rip]}"
|
||||
[(set_attr "type" "lea")
|
||||
(set_attr "mode" "DI")
|
||||
(set_attr "length" "7")
|
||||
(set_attr "length_address" "4")])
|
||||
|
||||
(define_insn "*tls_dynamic_call_64"
|
||||
[(set (match_operand:DI 0 "register_operand" "=a")
|
||||
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")
|
||||
(match_operand:DI 2 "register_operand" "0")
|
||||
(reg:DI SP_REG)]
|
||||
UNSPEC_TLSDESC))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
"TARGET_64BIT && TARGET_GNU2_TLS"
|
||||
"call\t{*%a1@TLSCALL(%2)|[QWORD PTR [%2+%a1@TLSCALL]]}"
|
||||
[(set_attr "type" "call")
|
||||
(set_attr "length" "2")
|
||||
(set_attr "length_address" "0")])
|
||||
|
||||
(define_insn_and_split "*tls_dynamic_gnu2_combine_64"
|
||||
[(set (match_operand:DI 0 "register_operand" "=&a")
|
||||
(plus:DI
|
||||
(plus:DI (match_operand:DI 2 "tp_or_register_operand" "ir")
|
||||
(unspec:DI [(match_operand:DI 3 "tls_modbase_operand" "")
|
||||
(match_operand:DI 4 "" "")
|
||||
(reg:DI SP_REG)]
|
||||
UNSPEC_TLSDESC))
|
||||
(const:DI (unspec:DI
|
||||
[(match_operand:DI 1 "tls_symbolic_operand" "")]
|
||||
UNSPEC_DTPOFF))))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
"TARGET_64BIT && TARGET_GNU2_TLS"
|
||||
"#"
|
||||
""
|
||||
[(parallel
|
||||
[(set (match_dup 0)
|
||||
(plus:DI (match_dup 2)
|
||||
(match_dup 4)))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
{
|
||||
operands[4] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
|
||||
emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1]));
|
||||
})
|
||||
|
||||
;;
|
||||
|
||||
;; These patterns match the binary 387 instructions for addM3, subM3,
|
||||
;; mulM3 and divM3. There are three patterns for each of DFmode and
|
||||
|
@ -1,5 +1,5 @@
|
||||
;; Predicate definitions for IA-32 and x86-64.
|
||||
;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
;;
|
||||
;; This file is part of GCC.
|
||||
;;
|
||||
@ -467,6 +467,15 @@
|
||||
(and (match_code "symbol_ref")
|
||||
(match_test "SYMBOL_REF_TLS_MODEL (op) != 0")))
|
||||
|
||||
(define_predicate "tls_modbase_operand"
|
||||
(and (match_code "symbol_ref")
|
||||
(match_test "op == ix86_tls_module_base ()")))
|
||||
|
||||
(define_predicate "tp_or_register_operand"
|
||||
(ior (match_operand 0 "register_operand")
|
||||
(and (match_code "unspec")
|
||||
(match_test "XINT (op, 1) == UNSPEC_TP"))))
|
||||
|
||||
;; Test for a pc-relative call operand
|
||||
(define_predicate "constant_call_address_operand"
|
||||
(ior (match_code "symbol_ref")
|
||||
|
Loading…
Reference in New Issue
Block a user