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:
parent
d7068b3d2a
commit
74dc3e94ed
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 "#"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue