i386.c (struct ix86_address): Add seg.

* config/i386/i386.c (struct ix86_address): Add seg.
        (no_seg_address_operand): New.
        (ix86_decompose_address): Restructure PLUS loop.  Accept one
        UNSPEC_TP if TARGET_TLS_DIRECT_SEG_REFS.  Adjust ESP swap test
        to test for a regnum, not stack_pointer_rtx.
        (ix86_address_cost): Reduce cost if non-default segment.
        (legitimate_address_p): Remove UNSPEC_TP check.
        (get_thread_pointer): Add to_reg argument.  Don't represent
        the thread pointer as a memory load.
        (legitimize_tls_address): Split out of ...
        (legitimize_address): ... here.
        (print_operand_address): Handle parts.seg.
        (ix86_expand_move): Use legitimize_tls_address.
        (ix86_rtx_costs): Handle UNSPEC_TP.
        * config/i386/i386.h (MASK_TLS_DIRECT_SEG_REFS): New.
        (TARGET_TLS_DIRECT_SEG_REFS): New.
        (TARGET_SWITCHES): Add tls-direct-seg-refs.
        (TARGET_TLS_DIRECT_SEG_REFS_DEFAULT): Default.
        (PREDICATE_CODES): Add no_seg_address_operand.
        * config/i386/i386.md (lea_1): Use it.
        (lea_1_rex64, lea_1_zext, lea_2_rex64): Likewise.
        (load_tp_si, add_tp_si, load_tp_di, add_tp_di): New.
        * config/i386/linux.h (TARGET_TLS_DIRECT_SEG_REFS_DEFAULT): New.
        * config/i386/linux64.h (TARGET_TLS_DIRECT_SEG_REFS_DEFAULT): New.
        * doc/invoke.texi: Add -mtls-direct-seg-refs.

From-SVN: r67475
This commit is contained in:
Richard Henderson 2003-06-04 17:23:23 -07:00 committed by Richard Henderson
parent d7068b3d2a
commit 74dc3e94ed
7 changed files with 396 additions and 225 deletions

View File

@ -1,3 +1,31 @@
2003-06-04 Richard Henderson <rth@redhat.com>
* config/i386/i386.c (struct ix86_address): Add seg.
(no_seg_address_operand): New.
(ix86_decompose_address): Restructure PLUS loop. Accept one
UNSPEC_TP if TARGET_TLS_DIRECT_SEG_REFS. Adjust ESP swap test
to test for a regnum, not stack_pointer_rtx.
(ix86_address_cost): Reduce cost if non-default segment.
(legitimate_address_p): Remove UNSPEC_TP check.
(get_thread_pointer): Add to_reg argument. Don't represent
the thread pointer as a memory load.
(legitimize_tls_address): Split out of ...
(legitimize_address): ... here.
(print_operand_address): Handle parts.seg.
(ix86_expand_move): Use legitimize_tls_address.
(ix86_rtx_costs): Handle UNSPEC_TP.
* config/i386/i386.h (MASK_TLS_DIRECT_SEG_REFS): New.
(TARGET_TLS_DIRECT_SEG_REFS): New.
(TARGET_SWITCHES): Add tls-direct-seg-refs.
(TARGET_TLS_DIRECT_SEG_REFS_DEFAULT): Default.
(PREDICATE_CODES): Add no_seg_address_operand.
* config/i386/i386.md (lea_1): Use it.
(lea_1_rex64, lea_1_zext, lea_2_rex64): Likewise.
(load_tp_si, add_tp_si, load_tp_di, add_tp_di): New.
* config/i386/linux.h (TARGET_TLS_DIRECT_SEG_REFS_DEFAULT): New.
* config/i386/linux64.h (TARGET_TLS_DIRECT_SEG_REFS_DEFAULT): New.
* doc/invoke.texi: Add -mtls-direct-seg-refs.
2003-06-04 Mark Mitchell <mark@codesourcery.com>
* Makefile.in (QMTESTRUNFLAGS): Set for DejaGNU emulation.

View File

@ -793,7 +793,8 @@ static rtx maybe_get_pool_constant PARAMS ((rtx));
static rtx ix86_expand_int_compare PARAMS ((enum rtx_code, rtx, rtx));
static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code,
rtx *, rtx *));
static rtx get_thread_pointer PARAMS ((void));
static rtx get_thread_pointer PARAMS ((int));
static rtx legitimize_tls_address PARAMS ((rtx, enum tls_model, int));
static void get_pc_thunk_name PARAMS ((char [32], unsigned int));
static rtx gen_push PARAMS ((rtx));
static int memory_address_length PARAMS ((rtx addr));
@ -835,6 +836,7 @@ struct ix86_address
{
rtx base, index, disp;
HOST_WIDE_INT scale;
enum ix86_address_seg { SEG_DEFAULT, SEG_FS, SEG_GS } seg;
};
static int ix86_decompose_address PARAMS ((rtx, struct ix86_address *));
@ -3863,6 +3865,25 @@ vector_move_operand (op, mode)
return (op == CONST0_RTX (GET_MODE (op)));
}
/* Return true if op if a valid address, and does not contain
a segment override. */
int
no_seg_address_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
struct ix86_address parts;
if (! address_operand (op, mode))
return 0;
if (! ix86_decompose_address (op, &parts))
abort ();
return parts.seg == SEG_DEFAULT;
}
/* Return 1 if OP is a comparison that can be used in the CMPSS/CMPPS
insns. */
int
@ -5403,8 +5424,7 @@ ix86_output_function_epilogue (file, size)
/* Extract the parts of an RTL expression that is a valid memory address
for an instruction. Return 0 if the structure of the address is
grossly off. Return -1 if the address contains ASHIFT, so it is not
strictly valid, but still used for computing length of lea instruction.
*/
strictly valid, but still used for computing length of lea instruction. */
static int
ix86_decompose_address (addr, out)
@ -5417,47 +5437,72 @@ ix86_decompose_address (addr, out)
HOST_WIDE_INT scale = 1;
rtx scale_rtx = NULL_RTX;
int retval = 1;
enum ix86_address_seg seg = SEG_DEFAULT;
if (REG_P (addr) || GET_CODE (addr) == SUBREG)
base = addr;
else if (GET_CODE (addr) == PLUS)
{
rtx op0 = XEXP (addr, 0);
rtx op1 = XEXP (addr, 1);
enum rtx_code code0 = GET_CODE (op0);
enum rtx_code code1 = GET_CODE (op1);
rtx addends[4], op;
int n = 0, i;
if (code0 == REG || code0 == SUBREG)
op = addr;
do
{
if (code1 == REG || code1 == SUBREG)
index = op0, base = op1; /* index + base */
else
base = op0, disp = op1; /* base + displacement */
if (n >= 4)
return 0;
addends[n++] = XEXP (op, 1);
op = XEXP (op, 0);
}
else if (code0 == MULT)
{
index = XEXP (op0, 0);
scale_rtx = XEXP (op0, 1);
if (code1 == REG || code1 == SUBREG)
base = op1; /* index*scale + base */
else
disp = op1; /* index*scale + disp */
}
else if (code0 == PLUS && GET_CODE (XEXP (op0, 0)) == MULT)
{
index = XEXP (XEXP (op0, 0), 0); /* index*scale + base + disp */
scale_rtx = XEXP (XEXP (op0, 0), 1);
base = XEXP (op0, 1);
disp = op1;
}
else if (code0 == PLUS)
{
index = XEXP (op0, 0); /* index + base + disp */
base = XEXP (op0, 1);
disp = op1;
}
else
while (GET_CODE (op) == PLUS);
if (n >= 4)
return 0;
addends[n] = op;
for (i = n; i >= 0; --i)
{
op = addends[i];
switch (GET_CODE (op))
{
case MULT:
if (index)
return 0;
index = XEXP (op, 0);
scale_rtx = XEXP (op, 1);
break;
case UNSPEC:
if (XINT (op, 1) == UNSPEC_TP
&& TARGET_TLS_DIRECT_SEG_REFS
&& seg == SEG_DEFAULT)
seg = TARGET_64BIT ? SEG_FS : SEG_GS;
else
return 0;
break;
case REG:
case SUBREG:
if (!base)
base = op;
else if (!index)
index = op;
else
return 0;
break;
case CONST:
case CONST_INT:
case SYMBOL_REF:
case LABEL_REF:
if (disp)
return 0;
disp = op;
break;
default:
return 0;
}
}
}
else if (GET_CODE (addr) == MULT)
{
@ -5490,10 +5535,11 @@ ix86_decompose_address (addr, out)
scale = INTVAL (scale_rtx);
}
/* Allow arg pointer and stack pointer as index if there is not scaling */
/* Allow arg pointer and stack pointer as index if there is not scaling. */
if (base && index && scale == 1
&& (index == arg_pointer_rtx || index == frame_pointer_rtx
|| index == stack_pointer_rtx))
&& (index == arg_pointer_rtx
|| index == frame_pointer_rtx
|| (REG_P (index) && REGNO (index) == STACK_POINTER_REGNUM)))
{
rtx tmp = base;
base = index;
@ -5526,6 +5572,7 @@ ix86_decompose_address (addr, out)
out->index = index;
out->disp = disp;
out->scale = scale;
out->seg = seg;
return retval;
}
@ -5553,6 +5600,8 @@ ix86_address_cost (x)
/* More complex memory references are better. */
if (parts.disp && parts.disp != const0_rtx)
cost--;
if (parts.seg != SEG_DEFAULT)
cost--;
/* Attempt to minimize number of registers in the address. */
if ((parts.base
@ -5871,13 +5920,6 @@ legitimate_address_p (mode, addr, strict)
debug_rtx (addr);
}
if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_TP)
{
if (TARGET_DEBUG_ADDR)
fprintf (stderr, "Success.\n");
return TRUE;
}
if (ix86_decompose_address (addr, &parts) <= 0)
{
reason = "decomposition failed";
@ -6267,20 +6309,151 @@ legitimize_pic_address (orig, reg)
return new;
}
/* Load the thread pointer into a register. */
/* Load the thread pointer. If TO_REG is true, force it into a register. */
static rtx
get_thread_pointer ()
get_thread_pointer (to_reg)
int to_reg;
{
rtx tp;
rtx tp, reg, insn;
tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP);
tp = gen_rtx_MEM (Pmode, tp);
RTX_UNCHANGING_P (tp) = 1;
set_mem_alias_set (tp, ix86_GOT_alias_set ());
tp = force_reg (Pmode, tp);
if (!to_reg)
return tp;
return tp;
reg = gen_reg_rtx (Pmode);
insn = gen_rtx_SET (VOIDmode, reg, tp);
insn = emit_insn (insn);
return reg;
}
/* A subroutine of legitimize_address and ix86_expand_move. FOR_MOV is
false if we expect this to be used for a memory address and true if
we expect to load the address into a register. */
static rtx
legitimize_tls_address (x, model, for_mov)
rtx x;
enum tls_model model;
int for_mov;
{
rtx dest, base, off, pic;
int type;
switch (model)
{
case TLS_MODEL_GLOBAL_DYNAMIC:
dest = gen_reg_rtx (Pmode);
if (TARGET_64BIT)
{
rtx rax = gen_rtx_REG (Pmode, 0), insns;
start_sequence ();
emit_call_insn (gen_tls_global_dynamic_64 (rax, x));
insns = get_insns ();
end_sequence ();
emit_libcall_block (insns, dest, rax, x);
}
else
emit_insn (gen_tls_global_dynamic_32 (dest, x));
break;
case TLS_MODEL_LOCAL_DYNAMIC:
base = gen_reg_rtx (Pmode);
if (TARGET_64BIT)
{
rtx rax = gen_rtx_REG (Pmode, 0), insns, note;
start_sequence ();
emit_call_insn (gen_tls_local_dynamic_base_64 (rax));
insns = get_insns ();
end_sequence ();
note = gen_rtx_EXPR_LIST (VOIDmode, const0_rtx, NULL);
note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note);
emit_libcall_block (insns, base, rax, note);
}
else
emit_insn (gen_tls_local_dynamic_base_32 (base));
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
off = gen_rtx_CONST (Pmode, off);
return gen_rtx_PLUS (Pmode, base, off);
case TLS_MODEL_INITIAL_EXEC:
if (TARGET_64BIT)
{
pic = NULL;
type = UNSPEC_GOTNTPOFF;
}
else if (flag_pic)
{
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;
}
else if (!TARGET_GNU_TLS)
{
pic = gen_reg_rtx (Pmode);
emit_insn (gen_set_got (pic));
type = UNSPEC_GOTTPOFF;
}
else
{
pic = NULL;
type = UNSPEC_INDNTPOFF;
}
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), type);
off = gen_rtx_CONST (Pmode, off);
if (pic)
off = gen_rtx_PLUS (Pmode, pic, off);
off = gen_rtx_MEM (Pmode, off);
RTX_UNCHANGING_P (off) = 1;
set_mem_alias_set (off, ix86_GOT_alias_set ());
if (TARGET_64BIT || TARGET_GNU_TLS)
{
base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS);
off = force_reg (Pmode, off);
return gen_rtx_PLUS (Pmode, base, off);
}
else
{
base = get_thread_pointer (true);
dest = gen_reg_rtx (Pmode);
emit_insn (gen_subsi3 (dest, base, off));
}
break;
case TLS_MODEL_LOCAL_EXEC:
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
(TARGET_64BIT || TARGET_GNU_TLS)
? UNSPEC_NTPOFF : UNSPEC_TPOFF);
off = gen_rtx_CONST (Pmode, off);
if (TARGET_64BIT || TARGET_GNU_TLS)
{
base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS);
return gen_rtx_PLUS (Pmode, base, off);
}
else
{
base = get_thread_pointer (true);
dest = gen_reg_rtx (Pmode);
emit_insn (gen_subsi3 (dest, base, off));
}
break;
default:
abort ();
}
return dest;
}
/* Try machine-dependent ways of modifying an illegitimate address
@ -6322,120 +6495,7 @@ legitimize_address (x, oldx, mode)
log = tls_symbolic_operand (x, mode);
if (log)
{
rtx dest, base, off, pic;
int type;
switch (log)
{
case TLS_MODEL_GLOBAL_DYNAMIC:
dest = gen_reg_rtx (Pmode);
if (TARGET_64BIT)
{
rtx rax = gen_rtx_REG (Pmode, 0), insns;
start_sequence ();
emit_call_insn (gen_tls_global_dynamic_64 (rax, x));
insns = get_insns ();
end_sequence ();
emit_libcall_block (insns, dest, rax, x);
}
else
emit_insn (gen_tls_global_dynamic_32 (dest, x));
break;
case TLS_MODEL_LOCAL_DYNAMIC:
base = gen_reg_rtx (Pmode);
if (TARGET_64BIT)
{
rtx rax = gen_rtx_REG (Pmode, 0), insns, note;
start_sequence ();
emit_call_insn (gen_tls_local_dynamic_base_64 (rax));
insns = get_insns ();
end_sequence ();
note = gen_rtx_EXPR_LIST (VOIDmode, const0_rtx, NULL);
note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note);
emit_libcall_block (insns, base, rax, note);
}
else
emit_insn (gen_tls_local_dynamic_base_32 (base));
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
off = gen_rtx_CONST (Pmode, off);
return gen_rtx_PLUS (Pmode, base, off);
case TLS_MODEL_INITIAL_EXEC:
if (TARGET_64BIT)
{
pic = NULL;
type = UNSPEC_GOTNTPOFF;
}
else if (flag_pic)
{
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;
}
else if (!TARGET_GNU_TLS)
{
pic = gen_reg_rtx (Pmode);
emit_insn (gen_set_got (pic));
type = UNSPEC_GOTTPOFF;
}
else
{
pic = NULL;
type = UNSPEC_INDNTPOFF;
}
base = get_thread_pointer ();
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), type);
off = gen_rtx_CONST (Pmode, off);
if (pic)
off = gen_rtx_PLUS (Pmode, pic, off);
off = gen_rtx_MEM (Pmode, off);
RTX_UNCHANGING_P (off) = 1;
set_mem_alias_set (off, ix86_GOT_alias_set ());
dest = gen_reg_rtx (Pmode);
if (TARGET_64BIT || TARGET_GNU_TLS)
{
emit_move_insn (dest, off);
return gen_rtx_PLUS (Pmode, base, dest);
}
else
emit_insn (gen_subsi3 (dest, base, off));
break;
case TLS_MODEL_LOCAL_EXEC:
base = get_thread_pointer ();
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
(TARGET_64BIT || TARGET_GNU_TLS)
? UNSPEC_NTPOFF : UNSPEC_TPOFF);
off = gen_rtx_CONST (Pmode, off);
if (TARGET_64BIT || TARGET_GNU_TLS)
return gen_rtx_PLUS (Pmode, base, off);
else
{
dest = gen_reg_rtx (Pmode);
emit_insn (gen_subsi3 (dest, base, off));
}
break;
default:
abort ();
}
return dest;
}
return legitimize_tls_address (x, log, false);
if (flag_pic && SYMBOLIC_CONST (x))
return legitimize_pic_address (x, 0);
@ -7418,8 +7478,8 @@ print_operand (file, x, code)
fprintf (file, "0x%lx", l);
}
/* These float cases don't actually occur as immediate operands. */
else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
/* These float cases don't actually occur as immediate operands. */
else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
{
char dstr[30];
@ -7474,19 +7534,6 @@ print_operand_address (file, addr)
rtx base, index, disp;
int scale;
if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_TP)
{
if (ASSEMBLER_DIALECT == ASM_INTEL)
fputs ("DWORD PTR ", file);
if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
putc ('%', file);
if (TARGET_64BIT)
fputs ("fs:0", file);
else
fputs ("gs:0", file);
return;
}
if (! ix86_decompose_address (addr, &parts))
abort ();
@ -7495,35 +7542,49 @@ print_operand_address (file, addr)
disp = parts.disp;
scale = parts.scale;
switch (parts.seg)
{
case SEG_DEFAULT:
break;
case SEG_FS:
case SEG_GS:
if (USER_LABEL_PREFIX[0] == 0)
putc ('%', file);
fputs ((parts.seg == SEG_FS ? "fs:" : "gs:"), file);
break;
default:
abort ();
}
if (!base && !index)
{
/* Displacement only requires special attention. */
if (GET_CODE (disp) == CONST_INT)
{
if (ASSEMBLER_DIALECT == ASM_INTEL)
if (ASSEMBLER_DIALECT == ASM_INTEL && parts.seg == SEG_DEFAULT)
{
if (USER_LABEL_PREFIX[0] == 0)
putc ('%', file);
fputs ("ds:", file);
}
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (disp));
}
else if (flag_pic)
output_pic_addr_const (file, addr, 0);
output_pic_addr_const (file, disp, 0);
else
output_addr_const (file, addr);
output_addr_const (file, disp);
/* Use one byte shorter RIP relative addressing for 64bit mode. */
if (TARGET_64BIT
&& ((GET_CODE (addr) == SYMBOL_REF
&& ! tls_symbolic_operand (addr, GET_MODE (addr)))
|| GET_CODE (addr) == LABEL_REF
|| (GET_CODE (addr) == CONST
&& GET_CODE (XEXP (addr, 0)) == PLUS
&& (GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF
|| GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF)
&& GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)))
&& ((GET_CODE (disp) == SYMBOL_REF
&& ! tls_symbolic_operand (disp, GET_MODE (disp)))
|| GET_CODE (disp) == LABEL_REF
|| (GET_CODE (disp) == CONST
&& GET_CODE (XEXP (disp, 0)) == PLUS
&& (GET_CODE (XEXP (XEXP (disp, 0), 0)) == SYMBOL_REF
|| GET_CODE (XEXP (XEXP (disp, 0), 0)) == LABEL_REF)
&& GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)))
fputs ("(%rip)", file);
}
else
@ -8220,22 +8281,22 @@ ix86_expand_move (mode, operands)
rtx operands[];
{
int strict = (reload_in_progress || reload_completed);
rtx insn, op0, op1, tmp;
rtx op0, op1;
enum tls_model model;
op0 = operands[0];
op1 = operands[1];
if (tls_symbolic_operand (op1, Pmode))
model = tls_symbolic_operand (op1, Pmode);
if (model)
{
op1 = legitimize_address (op1, op1, VOIDmode);
if (GET_CODE (op0) == MEM)
{
tmp = gen_reg_rtx (mode);
emit_insn (gen_rtx_SET (VOIDmode, tmp, op1));
op1 = tmp;
}
op1 = legitimize_tls_address (op1, model, true);
op1 = force_operand (op1, op0);
if (op1 == op0)
return;
}
else if (flag_pic && mode == Pmode && symbolic_operand (op1, Pmode))
if (flag_pic && mode == Pmode && symbolic_operand (op1, Pmode))
{
#if TARGET_MACHO
if (MACHOPIC_PURE)
@ -8248,18 +8309,11 @@ ix86_expand_move (mode, operands)
op1 = machopic_legitimize_pic_address (op1, mode,
temp == op1 ? 0 : temp);
}
else
{
if (MACHOPIC_INDIRECT)
op1 = machopic_indirect_data_reference (op1, 0);
}
if (op0 != op1)
{
insn = gen_rtx_SET (VOIDmode, op0, op1);
emit_insn (insn);
}
return;
#endif /* TARGET_MACHO */
else if (MACHOPIC_INDIRECT)
op1 = machopic_indirect_data_reference (op1, 0);
if (op0 == op1)
return;
#else
if (GET_CODE (op0) == MEM)
op1 = force_reg (Pmode, op1);
else
@ -8272,6 +8326,7 @@ ix86_expand_move (mode, operands)
return;
op1 = temp;
}
#endif /* TARGET_MACHO */
}
else
{
@ -8316,9 +8371,7 @@ ix86_expand_move (mode, operands)
}
}
insn = gen_rtx_SET (VOIDmode, op0, op1);
emit_insn (insn);
emit_insn (gen_rtx_SET (VOIDmode, op0, op1));
}
void
@ -15094,6 +15147,11 @@ ix86_rtx_costs (x, code, outer_code, total)
*total = COSTS_N_INSNS (ix86_cost->fsqrt);
return false;
case UNSPEC:
if (XINT (x, 1) == UNSPEC_TP)
*total = 0;
return false;
default:
return false;
}

View File

@ -122,6 +122,7 @@ extern int target_flags;
#define MASK_128BIT_LONG_DOUBLE 0x00040000 /* long double size is 128bit */
#define MASK_64BIT 0x00080000 /* Produce 64bit code */
#define MASK_MS_BITFIELD_LAYOUT 0x00100000 /* Use native (MS) bitfield layout */
#define MASK_TLS_DIRECT_SEG_REFS 0x00200000 /* Avoid adding %gs:0 */
/* Unused: 0x03e0000 */
@ -201,6 +202,9 @@ extern int target_flags;
#endif
#endif
/* Avoid adding %gs:0 in TLS references; use %gs:address directly. */
#define TARGET_TLS_DIRECT_SEG_REFS (target_flags & MASK_TLS_DIRECT_SEG_REFS)
#define TARGET_386 (ix86_tune == PROCESSOR_I386)
#define TARGET_486 (ix86_tune == PROCESSOR_I486)
#define TARGET_PENTIUM (ix86_tune == PROCESSOR_PENTIUM)
@ -405,12 +409,21 @@ extern int x86_prefetch_sse;
N_("Use red-zone in the x86-64 code") }, \
{ "no-red-zone", MASK_NO_RED_ZONE, \
N_("Do not use red-zone in the x86-64 code") }, \
{ "tls-direct-seg-refs", MASK_TLS_DIRECT_SEG_REFS, \
N_("Use direct references against %gs when accessing tls data") }, \
{ "no-tls-direct-seg-refs", -MASK_TLS_DIRECT_SEG_REFS, \
N_("Do not use direct references against %gs when accessing tls data") }, \
SUBTARGET_SWITCHES \
{ "", TARGET_DEFAULT | TARGET_64BIT_DEFAULT | TARGET_SUBTARGET_DEFAULT, 0 }}
{ "", \
TARGET_DEFAULT | TARGET_64BIT_DEFAULT | TARGET_SUBTARGET_DEFAULT \
| TARGET_TLS_DIRECT_SEG_REFS_DEFAULT, 0 }}
#ifndef TARGET_64BIT_DEFAULT
#define TARGET_64BIT_DEFAULT 0
#endif
#ifndef TARGET_TLS_DIRECT_SEG_REFS_DEFAULT
#define TARGET_TLS_DIRECT_SEG_REFS_DEFAULT 0
#endif
/* Once GDB has been enhanced to deal with functions without frame
pointers, we can change this to allow for elimination of
@ -3034,6 +3047,8 @@ do { \
{"register_and_not_fp_reg_operand", {REG}}, \
{"zero_extended_scalar_load_operand", {MEM}}, \
{"vector_move_operand", {CONST_VECTOR, SUBREG, REG, MEM}}, \
{"no_seg_address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
LABEL_REF, SUBREG, REG, MEM, PLUS, MULT}},
/* A list of predicates that do special things with modes, and so
should not elicit warnings for VOIDmode match_operand. */

View File

@ -5312,7 +5312,7 @@
(define_insn "*lea_1"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operand:SI 1 "address_operand" "p"))]
(match_operand:SI 1 "no_seg_address_operand" "p"))]
"!TARGET_64BIT"
"lea{l}\t{%a1, %0|%0, %a1}"
[(set_attr "type" "lea")
@ -5320,7 +5320,7 @@
(define_insn "*lea_1_rex64"
[(set (match_operand:SI 0 "register_operand" "=r")
(subreg:SI (match_operand:DI 1 "address_operand" "p") 0))]
(subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))]
"TARGET_64BIT"
"lea{l}\t{%a1, %0|%0, %a1}"
[(set_attr "type" "lea")
@ -5328,7 +5328,8 @@
(define_insn "*lea_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (subreg:SI (match_operand:DI 1 "address_operand" "p") 0)))]
(zero_extend:DI
(subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0)))]
"TARGET_64BIT"
"lea{l}\t{%a1, %k0|%k0, %a1}"
[(set_attr "type" "lea")
@ -5336,7 +5337,7 @@
(define_insn "*lea_2_rex64"
[(set (match_operand:DI 0 "register_operand" "=r")
(match_operand:DI 1 "address_operand" "p"))]
(match_operand:DI 1 "no_seg_address_operand" "p"))]
"TARGET_64BIT"
"lea{q}\t{%a1, %0|%0, %a1}"
[(set_attr "type" "lea")
@ -14636,6 +14637,56 @@
(clobber (match_dup 5))
(clobber (reg:CC 17))])]
"")
;; Load and add the thread base pointer from %gs:0.
(define_insn "*load_tp_si"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI [(const_int 0)] UNSPEC_TP))]
"!TARGET_64BIT"
"mov{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
[(set_attr "type" "imov")
(set_attr "modrm" "0")
(set_attr "length" "7")
(set_attr "memory" "load")
(set_attr "imm_disp" "false")])
(define_insn "*add_tp_si"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP)
(match_operand:SI 1 "register_operand" "0")))
(clobber (reg:CC 17))]
"!TARGET_64BIT"
"add{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
[(set_attr "type" "alu")
(set_attr "modrm" "0")
(set_attr "length" "7")
(set_attr "memory" "load")
(set_attr "imm_disp" "false")])
(define_insn "*load_tp_di"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(const_int 0)] UNSPEC_TP))]
"TARGET_64BIT"
"mov{l}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
[(set_attr "type" "imov")
(set_attr "modrm" "0")
(set_attr "length" "7")
(set_attr "memory" "load")
(set_attr "imm_disp" "false")])
(define_insn "*add_tp_di"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (unspec:DI [(const_int 0)] UNSPEC_TP)
(match_operand:DI 1 "register_operand" "0")))
(clobber (reg:CC 17))]
"TARGET_64BIT"
"add{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
[(set_attr "type" "alu")
(set_attr "modrm" "0")
(set_attr "length" "7")
(set_attr "memory" "load")
(set_attr "imm_disp" "false")])
;; These patterns match the binary 387 instructions for addM3, subM3,
;; mulM3 and divM3. There are three patterns for each of DFmode and

View File

@ -40,6 +40,10 @@ Boston, MA 02111-1307, USA. */
#undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 1
/* We arrange for the whole %gs segment to map the tls area. */
#undef TARGET_TLS_DIRECT_SEG_REFS_DEFAULT
#define TARGET_TLS_DIRECT_SEG_REFS_DEFAULT MASK_TLS_DIRECT_SEG_REFS
#undef ASM_COMMENT_START
#define ASM_COMMENT_START "#"

View File

@ -47,6 +47,10 @@ Boston, MA 02111-1307, USA. */
#undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 1
/* We arrange for the whole %fs segment to map the tls area. */
#undef TARGET_TLS_DIRECT_SEG_REFS_DEFAULT
#define TARGET_TLS_DIRECT_SEG_REFS_DEFAULT MASK_TLS_DIRECT_SEG_REFS
/* Provide a LINK_SPEC. Here we provide support for the special GCC
options -static and -shared, which allow us to link things in one
of these three modes by applying the appropriate combinations of

View File

@ -490,7 +490,7 @@ in the following sections.
-mthreads -mno-align-stringops -minline-all-stringops @gol
-mpush-args -maccumulate-outgoing-args -m128bit-long-double @gol
-m96bit-long-double -mregparm=@var{num} -momit-leaf-frame-pointer @gol
-mno-red-zone @gol
-mno-red-zone -mno-tls-direct-seg-refs @gol
-mcmodel=@var{code-model} @gol
-m32 -m64}
@ -8401,6 +8401,17 @@ avoids the instructions to save, set up and restore frame pointers and
makes an extra register available in leaf functions. The option
@option{-fomit-frame-pointer} removes the frame pointer for all functions
which might make debugging harder.
@item -mtls-direct-seg-refs
@itemx -mno-tls-direct-seg-refs
@opindex mtls-direct-seg-refs
Controls whether TLS variables may be accessed with offsets from the
TLS segment register (@code{%gs} for 32-bit, @code{%fs} for 64-bit),
or whether the thread base pointer must be added. Whether or not this
is legal depends on the operating system, and whether it maps the
segment to cover the entire TLS area.
For systems that use GNU libc, the default is on.
@end table
These @samp{-m} switches are supported in addition to the above