Commit bef8809e by Aldy Hernandez Committed by Aldy Hernandez

frv.c (frv_legitimize_tls_address): New.

	* config/frv/frv.c (frv_legitimize_tls_address): New.
	(TARGET_HAVE_TLS): Define.
	(FRV_SYMBOL_REF_TLS_P): Define.
	(frv_override_options): Handle new register classes.
	(frv_legitimate_address_p): Reject tls addresses.
	(frv_legitimize_address): Handle TLS addresses.
	(gen_inlined_tls_plt): New.
	(gen_tlsmoff): New.
	(frv_legitimize_tls_address): New.
	(unspec_got_name): Add TLS entries.
	(got12_operand): Add R_FRV_TLSMOFF12 case.
	(frv_emit_move): Fixup TLS addresses.
	(frv_emit_movsi): Legitimize TLS addresses.

	* config/frv/frv.h (MASK_BIG_TLS): New.
	(TARGET_BIG_TLS): New.
	(HAVE_AS_TLS): Define.
	(TARGET_SWITCHES): Add -mTLS and -mtls options.
	(enum reg_class): Add GR8_REGS, GR9_REGS, GR89_REGS.
	(REG_CLASS_NAMES): Same.
	(REG_CLASS_CONTENTS): Same.
	(CONSTRAINT_LEN): New.
	(REG_CLASS_FROM_CONSTRAINT): New.
	(PREDICATE_CODES): Add symbolic_operand.

	* config/frv/frv.md (define_constants): Add UNSPEC_GETTLSOFF,
	UNSPEC_TLS_LOAD_GOTTLSOFF12, UNSPEC_TLS_INDIRECT_CALL,
	UNSPEC_TLS_TLSDESC_LDD, UNSPEC_TLS_TLSDESC_LDD_AUX,
	UNSPEC_TLS_TLSOFF_LD, UNSPEC_TLS_LDDI, UNSPEC_TLSOFF_HILO,
	R_FRV_GOTTLSOFF_HI, R_FRV_GOTTLSOFF_LO, R_FRV_TLSMOFFHI,
	R_FRV_TLSMOFFLO, R_FRV_TLSMOFF12, R_FRV_TLSDESCHI,
	R_FRV_TLSDESCLO, R_FRV_GOTTLSDESCHI, R_FRV_GOTTLSDESCLO, GR8_REG,
	GR9_REG, GR14_REG, LRREG.
	(type): Add load_or_call attribute.
	("load_or_call"): New reservation.
	("call_gettlsoff"): New.
	("tls_indirect_call"): New.
	("tls_load_gottlsoff12"): New.
	("tlsoff_hilo"): New.
	("tls_tlsdesc_ldd"): New.
	("tls_tlsoff_ld"): New.
	("tls_lddi"): New.

	* config/frv/frv-protos.h (symbolic_operand): Protoize.

        * config/frv/frv.h (ASM_OUTPUT_DWARF_DTPREL): Define.
        * config/frv/frv-protos.h (frv_output_dwarf_dtprel): Declare.
        * config/frv/frv.c (TLS_BIAS): Define.
        (frv_output_dwarf_dtprel): New.

From-SVN: r94237
parent a7f7b334
2005-01-25 Aldy Hernandez <aldyh@redhat.com>
* config/frv/frv.c (frv_legitimize_tls_address): New.
(TARGET_HAVE_TLS): Define.
(FRV_SYMBOL_REF_TLS_P): Define.
(frv_override_options): Handle new register classes.
(frv_legitimate_address_p): Reject tls addresses.
(frv_legitimize_address): Handle TLS addresses.
(gen_inlined_tls_plt): New.
(gen_tlsmoff): New.
(frv_legitimize_tls_address): New.
(unspec_got_name): Add TLS entries.
(got12_operand): Add R_FRV_TLSMOFF12 case.
(frv_emit_move): Fixup TLS addresses.
(frv_emit_movsi): Legitimize TLS addresses.
* config/frv/frv.h (MASK_BIG_TLS): New.
(TARGET_BIG_TLS): New.
(HAVE_AS_TLS): Define.
(TARGET_SWITCHES): Add -mTLS and -mtls options.
(enum reg_class): Add GR8_REGS, GR9_REGS, GR89_REGS.
(REG_CLASS_NAMES): Same.
(REG_CLASS_CONTENTS): Same.
(CONSTRAINT_LEN): New.
(REG_CLASS_FROM_CONSTRAINT): New.
(PREDICATE_CODES): Add symbolic_operand.
* config/frv/frv.md (define_constants): Add UNSPEC_GETTLSOFF,
UNSPEC_TLS_LOAD_GOTTLSOFF12, UNSPEC_TLS_INDIRECT_CALL,
UNSPEC_TLS_TLSDESC_LDD, UNSPEC_TLS_TLSDESC_LDD_AUX,
UNSPEC_TLS_TLSOFF_LD, UNSPEC_TLS_LDDI, UNSPEC_TLSOFF_HILO,
R_FRV_GOTTLSOFF_HI, R_FRV_GOTTLSOFF_LO, R_FRV_TLSMOFFHI,
R_FRV_TLSMOFFLO, R_FRV_TLSMOFF12, R_FRV_TLSDESCHI,
R_FRV_TLSDESCLO, R_FRV_GOTTLSDESCHI, R_FRV_GOTTLSDESCLO, GR8_REG,
GR9_REG, GR14_REG, LRREG.
(type): Add load_or_call attribute.
("load_or_call"): New reservation.
("call_gettlsoff"): New.
("tls_indirect_call"): New.
("tls_load_gottlsoff12"): New.
("tlsoff_hilo"): New.
("tls_tlsdesc_ldd"): New.
("tls_tlsoff_ld"): New.
("tls_lddi"): New.
* config/frv/frv-protos.h (symbolic_operand): Protoize.
2005-01-25 Alexandre Oliva <aoliva@redhat.com>
* config/frv/frv.h (ASM_OUTPUT_DWARF_DTPREL): Define.
* config/frv/frv-protos.h (frv_output_dwarf_dtprel): Declare.
* config/frv/frv.c (TLS_BIAS): Define.
(frv_output_dwarf_dtprel): New.
2005-01-26 Jakub Jelinek <jakub@redhat.com> 2005-01-26 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/19579 PR rtl-optimization/19579
......
/* Frv prototypes. /* Frv prototypes.
Copyright (C) 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc. Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005 Free Software Foundation,
Inc.
Contributed by Red Hat, Inc. Contributed by Red Hat, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -200,6 +201,7 @@ extern int small_data_register_operand (rtx, enum machine_mode); ...@@ -200,6 +201,7 @@ extern int small_data_register_operand (rtx, enum machine_mode);
extern int small_data_symbolic_operand (rtx, enum machine_mode); extern int small_data_symbolic_operand (rtx, enum machine_mode);
extern int upper_int16_operand (rtx, enum machine_mode); extern int upper_int16_operand (rtx, enum machine_mode);
extern int uint16_operand (rtx, enum machine_mode); extern int uint16_operand (rtx, enum machine_mode);
extern int symbolic_operand (rtx, enum machine_mode);
extern int relational_operator (rtx, enum machine_mode); extern int relational_operator (rtx, enum machine_mode);
extern int signed_relational_operator (rtx, enum machine_mode); extern int signed_relational_operator (rtx, enum machine_mode);
extern int unsigned_relational_operator (rtx, enum machine_mode); extern int unsigned_relational_operator (rtx, enum machine_mode);
...@@ -221,5 +223,6 @@ extern int accg_operand (rtx, enum machine_mode); ...@@ -221,5 +223,6 @@ extern int accg_operand (rtx, enum machine_mode);
extern rtx frv_matching_accg_for_acc (rtx); extern rtx frv_matching_accg_for_acc (rtx);
extern void frv_expand_fdpic_call (rtx *, bool, bool); extern void frv_expand_fdpic_call (rtx *, bool, bool);
extern rtx frv_gen_GPsym2reg (rtx, rtx); extern rtx frv_gen_GPsym2reg (rtx, rtx);
extern void frv_output_dwarf_dtprel (FILE *, int, rtx);
#endif #endif
/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004 /* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
Free Software Foundation, Inc. Free Software Foundation, Inc.
Contributed by Red Hat, Inc. Contributed by Red Hat, Inc.
...@@ -303,6 +303,7 @@ static rtx frv_read_iacc_argument (enum machine_mode, tree *); ...@@ -303,6 +303,7 @@ static rtx frv_read_iacc_argument (enum machine_mode, tree *);
static int frv_check_constant_argument (enum insn_code, int, rtx); static int frv_check_constant_argument (enum insn_code, int, rtx);
static rtx frv_legitimize_target (enum insn_code, rtx); static rtx frv_legitimize_target (enum insn_code, rtx);
static rtx frv_legitimize_argument (enum insn_code, int, rtx); static rtx frv_legitimize_argument (enum insn_code, int, rtx);
static rtx frv_legitimize_tls_address (rtx, enum tls_model);
static rtx frv_expand_set_builtin (enum insn_code, tree, rtx); static rtx frv_expand_set_builtin (enum insn_code, tree, rtx);
static rtx frv_expand_unop_builtin (enum insn_code, tree, rtx); static rtx frv_expand_unop_builtin (enum insn_code, tree, rtx);
static rtx frv_expand_binop_builtin (enum insn_code, tree, rtx); static rtx frv_expand_binop_builtin (enum insn_code, tree, rtx);
...@@ -414,6 +415,9 @@ static int frv_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, ...@@ -414,6 +415,9 @@ static int frv_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
#undef TARGET_CANNOT_FORCE_CONST_MEM #undef TARGET_CANNOT_FORCE_CONST_MEM
#define TARGET_CANNOT_FORCE_CONST_MEM frv_cannot_force_const_mem #define TARGET_CANNOT_FORCE_CONST_MEM frv_cannot_force_const_mem
#undef TARGET_HAVE_TLS
#define TARGET_HAVE_TLS HAVE_AS_TLS
#undef TARGET_STRUCT_VALUE_RTX #undef TARGET_STRUCT_VALUE_RTX
#define TARGET_STRUCT_VALUE_RTX frv_struct_value_rtx #define TARGET_STRUCT_VALUE_RTX frv_struct_value_rtx
#undef TARGET_MUST_PASS_IN_STACK #undef TARGET_MUST_PASS_IN_STACK
...@@ -431,6 +435,10 @@ static int frv_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, ...@@ -431,6 +435,10 @@ static int frv_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
#define TARGET_MACHINE_DEPENDENT_REORG frv_reorg #define TARGET_MACHINE_DEPENDENT_REORG frv_reorg
struct gcc_target targetm = TARGET_INITIALIZER; struct gcc_target targetm = TARGET_INITIALIZER;
#define FRV_SYMBOL_REF_TLS_P(RTX) \
(GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
/* Any function call that satisfies the machine-independent /* Any function call that satisfies the machine-independent
requirements is eligible on FR-V. */ requirements is eligible on FR-V. */
...@@ -640,7 +648,20 @@ frv_override_options (void) ...@@ -640,7 +648,20 @@ frv_override_options (void)
if (GPR_P (regno)) if (GPR_P (regno))
{ {
int gpr_reg = regno - GPR_FIRST; int gpr_reg = regno - GPR_FIRST;
if ((gpr_reg & 3) == 0)
if (gpr_reg == GR8_REG)
class = GR8_REGS;
else if (gpr_reg == GR9_REG)
class = GR9_REGS;
else if (gpr_reg == GR14_REG)
class = FDPIC_FPTR_REGS;
else if (gpr_reg == FDPIC_REGNO)
class = FDPIC_REGS;
else if ((gpr_reg & 3) == 0)
class = QUAD_REGS; class = QUAD_REGS;
else if ((gpr_reg & 1) == 0) else if ((gpr_reg & 1) == 0)
...@@ -3304,6 +3325,9 @@ frv_legitimate_address_p (enum machine_mode mode, ...@@ -3304,6 +3325,9 @@ frv_legitimate_address_p (enum machine_mode mode,
HOST_WIDE_INT value; HOST_WIDE_INT value;
unsigned regno0; unsigned regno0;
if (FRV_SYMBOL_REF_TLS_P (x))
return 0;
switch (GET_CODE (x)) switch (GET_CODE (x))
{ {
default: default:
...@@ -3421,11 +3445,178 @@ frv_legitimate_address_p (enum machine_mode mode, ...@@ -3421,11 +3445,178 @@ frv_legitimate_address_p (enum machine_mode mode,
return ret; return ret;
} }
/* Given an ADDR, generate code to inline the PLT. */
static rtx
gen_inlined_tls_plt (rtx addr)
{
rtx mem, retval, dest;
rtx picreg = get_hard_reg_initial_val (Pmode, FDPIC_REG);
dest = gen_reg_rtx (DImode);
if (flag_pic == 1)
{
/*
-fpic version:
lddi.p @(gr15, #gottlsdesc12(ADDR)), gr8
calll #gettlsoff(ADDR)@(gr8, gr0)
*/
emit_insn (gen_tls_lddi (dest, addr, picreg));
}
else
{
/*
-fPIC version:
sethi.p #gottlsdeschi(ADDR), gr8
setlo #gottlsdesclo(ADDR), gr8
ldd #tlsdesc(ADDR)@(gr15, gr8), gr8
calll #gettlsoff(ADDR)@(gr8, gr0)
*/
rtx reguse = gen_reg_rtx (Pmode);
emit_insn (gen_tlsoff_hilo (reguse, addr, GEN_INT (R_FRV_GOTTLSDESCHI)));
emit_insn (gen_tls_tlsdesc_ldd (dest, picreg, reguse, addr));
}
retval = gen_reg_rtx (Pmode);
emit_insn (gen_tls_indirect_call (retval, addr, dest, gen_reg_rtx (Pmode),
picreg));
return retval;
}
/* Emit a TLSMOFF or TLSMOFF12 offset, depending on -mTLS. Returns
the destination address. */
static rtx
gen_tlsmoff (rtx addr, rtx reg)
{
rtx dest = gen_reg_rtx (Pmode);
if (TARGET_BIG_TLS)
{
/* sethi.p #tlsmoffhi(x), grA
setlo #tlsmofflo(x), grA
*/
dest = gen_reg_rtx (Pmode);
emit_insn (gen_tlsoff_hilo (dest, addr,
GEN_INT (R_FRV_TLSMOFFHI)));
dest = gen_rtx_PLUS (Pmode, dest, reg);
}
else
{
/* addi grB, #tlsmoff12(x), grC
-or-
ld/st @(grB, #tlsmoff12(x)), grC
*/
dest = gen_reg_rtx (Pmode);
emit_insn (gen_symGOTOFF2reg_i (dest, addr, reg,
GEN_INT (R_FRV_TLSMOFF12)));
}
return dest;
}
/* Generate code for a TLS address. */
static rtx
frv_legitimize_tls_address (rtx addr, enum tls_model model)
{
rtx dest, tp = gen_rtx_REG (Pmode, 29);
rtx picreg = get_hard_reg_initial_val (Pmode, 15);
switch (model)
{
case TLS_MODEL_INITIAL_EXEC:
if (flag_pic == 1)
{
/* -fpic version.
ldi @(gr15, #gottlsoff12(x)), gr5
*/
dest = gen_reg_rtx (Pmode);
emit_insn (gen_tls_load_gottlsoff12 (dest, addr, picreg));
dest = gen_rtx_PLUS (Pmode, tp, dest);
}
else
{
/* -fPIC or anything else.
sethi.p #gottlsoffhi(x), gr14
setlo #gottlsofflo(x), gr14
ld #tlsoff(x)@(gr15, gr14), gr9
*/
rtx tmp = gen_reg_rtx (Pmode);
dest = gen_reg_rtx (Pmode);
emit_insn (gen_tlsoff_hilo (tmp, addr,
GEN_INT (R_FRV_GOTTLSOFF_HI)));
emit_insn (gen_tls_tlsoff_ld (dest, picreg, tmp, addr));
dest = gen_rtx_PLUS (Pmode, tp, dest);
}
break;
case TLS_MODEL_LOCAL_DYNAMIC:
{
rtx reg, retval;
if (TARGET_INLINE_PLT)
retval = gen_inlined_tls_plt (GEN_INT (0));
else
{
/* call #gettlsoff(0) */
retval = gen_reg_rtx (Pmode);
emit_insn (gen_call_gettlsoff (retval, GEN_INT (0), picreg));
}
reg = gen_reg_rtx (Pmode);
emit_insn (gen_rtx_SET (VOIDmode, reg,
gen_rtx_PLUS (Pmode,
retval, tp)));
dest = gen_tlsmoff (addr, reg);
/*
dest = gen_reg_rtx (Pmode);
emit_insn (gen_tlsoff_hilo (dest, addr,
GEN_INT (R_FRV_TLSMOFFHI)));
dest = gen_rtx_PLUS (Pmode, dest, reg);
*/
break;
}
case TLS_MODEL_LOCAL_EXEC:
dest = gen_tlsmoff (addr, gen_rtx_REG (Pmode, 29));
break;
case TLS_MODEL_GLOBAL_DYNAMIC:
{
rtx retval;
if (TARGET_INLINE_PLT)
retval = gen_inlined_tls_plt (addr);
else
{
/* call #gettlsoff(x) */
retval = gen_reg_rtx (Pmode);
emit_insn (gen_call_gettlsoff (retval, addr, picreg));
}
dest = gen_rtx_PLUS (Pmode, retval, tp);
break;
}
default:
abort ();
}
return dest;
}
rtx rtx
frv_legitimize_address (rtx x ATTRIBUTE_UNUSED, frv_legitimize_address (rtx x,
rtx oldx ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
enum machine_mode mode ATTRIBUTE_UNUSED) enum machine_mode mode ATTRIBUTE_UNUSED)
{ {
if (GET_CODE (x) == SYMBOL_REF)
{
enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
if (model != 0)
return frv_legitimize_tls_address (x, model);
}
return NULL_RTX; return NULL_RTX;
} }
...@@ -3501,6 +3692,15 @@ unspec_got_name (int i) ...@@ -3501,6 +3692,15 @@ unspec_got_name (int i)
case R_FRV_GPREL12: return "gprel12"; case R_FRV_GPREL12: return "gprel12";
case R_FRV_GPRELHI: return "gprelhi"; case R_FRV_GPRELHI: return "gprelhi";
case R_FRV_GPRELLO: return "gprello"; case R_FRV_GPRELLO: return "gprello";
case R_FRV_GOTTLSOFF_HI: return "gottlsoffhi";
case R_FRV_GOTTLSOFF_LO: return "gottlsofflo";
case R_FRV_TLSMOFFHI: return "tlsmoffhi";
case R_FRV_TLSMOFFLO: return "tlsmofflo";
case R_FRV_TLSMOFF12: return "tlsmoff12";
case R_FRV_TLSDESCHI: return "tlsdeschi";
case R_FRV_TLSDESCLO: return "tlsdesclo";
case R_FRV_GOTTLSDESCHI: return "gottlsdeschi";
case R_FRV_GOTTLSDESCLO: return "gottlsdesclo";
default: abort (); default: abort ();
} }
} }
...@@ -4617,6 +4817,7 @@ got12_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) ...@@ -4617,6 +4817,7 @@ got12_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
case R_FRV_FUNCDESC_GOT12: case R_FRV_FUNCDESC_GOT12:
case R_FRV_FUNCDESC_GOTOFF12: case R_FRV_FUNCDESC_GOTOFF12:
case R_FRV_GPREL12: case R_FRV_GPREL12:
case R_FRV_TLSMOFF12:
return true; return true;
} }
return false; return false;
...@@ -4790,6 +4991,24 @@ sibcall_operand (rtx op, enum machine_mode mode) ...@@ -4790,6 +4991,24 @@ sibcall_operand (rtx op, enum machine_mode mode)
return gpr_or_int12_operand (op, mode); return gpr_or_int12_operand (op, mode);
} }
/* Returns 1 if OP is either a SYMBOL_REF or a constant. */
int
symbolic_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
enum rtx_code c = GET_CODE (op);
if (c == CONST)
{
/* Allow (const:SI (plus:SI (symbol_ref) (const_int))). */
return GET_MODE (op) == SImode
&& GET_CODE (XEXP (op, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
&& GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT;
}
return c == SYMBOL_REF || c == CONST_INT;
}
/* Return true if operator is a kind of relational operator. */ /* Return true if operator is a kind of relational operator. */
int int
...@@ -5181,6 +5400,13 @@ direct_return_p (void) ...@@ -5181,6 +5400,13 @@ direct_return_p (void)
void void
frv_emit_move (enum machine_mode mode, rtx dest, rtx src) frv_emit_move (enum machine_mode mode, rtx dest, rtx src)
{ {
if (GET_CODE (src) == SYMBOL_REF)
{
enum tls_model model = SYMBOL_REF_TLS_MODEL (src);
if (model != 0)
src = frv_legitimize_tls_address (src, model);
}
switch (mode) switch (mode)
{ {
case SImode: case SImode:
...@@ -5314,6 +5540,15 @@ frv_emit_movsi (rtx dest, rtx src) ...@@ -5314,6 +5540,15 @@ frv_emit_movsi (rtx dest, rtx src)
handle_sym: handle_sym:
if (TARGET_FDPIC) if (TARGET_FDPIC)
{ {
enum tls_model model = SYMBOL_REF_TLS_MODEL (sym);
if (model != 0)
{
src = frv_legitimize_tls_address (src, model);
emit_move_insn (dest, src);
return TRUE;
}
if (SYMBOL_REF_FUNCTION_P (sym)) if (SYMBOL_REF_FUNCTION_P (sym))
{ {
if (frv_local_funcdesc_p (sym)) if (frv_local_funcdesc_p (sym))
...@@ -10327,4 +10562,21 @@ frv_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, ...@@ -10327,4 +10562,21 @@ frv_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
return gen_rtx_REG (Pmode, FRV_STRUCT_VALUE_REGNUM); return gen_rtx_REG (Pmode, FRV_STRUCT_VALUE_REGNUM);
} }
#define TLS_BIAS (2048 - 16)
/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
We need to emit DTP-relative relocations. */
void
frv_output_dwarf_dtprel (FILE *file, int size, rtx x)
{
if (size != 4)
abort ();
fputs ("\t.picptr\ttlsmoff(", file);
/* We want the unbiased TLS offset, so add the bias to the
expression, such that the implicit biasing cancels out. */
output_addr_const (file, plus_constant (x, TLS_BIAS));
fputs (")", file);
}
#include "gt-frv.h" #include "gt-frv.h"
/* Target macros for the FRV port of GCC. /* Target macros for the FRV port of GCC.
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc. Free Software Foundation, Inc.
Contributed by Red Hat Inc. Contributed by Red Hat Inc.
...@@ -309,6 +309,7 @@ extern int target_flags; ...@@ -309,6 +309,7 @@ extern int target_flags;
#define MASK_LONG_CALLS 0x00000800 /* Use indirect calls */ #define MASK_LONG_CALLS 0x00000800 /* Use indirect calls */
#define MASK_ALIGN_LABELS 0x00001000 /* Optimize label alignments */ #define MASK_ALIGN_LABELS 0x00001000 /* Optimize label alignments */
#define MASK_LINKED_FP 0x00002000 /* Follow ABI linkage requirements. */ #define MASK_LINKED_FP 0x00002000 /* Follow ABI linkage requirements. */
#define MASK_BIG_TLS 0x00008000 /* Assume a big TLS segment */
/* put debug masks up high */ /* put debug masks up high */
#define MASK_DEBUG_ARG 0x40000000 /* debug argument handling */ #define MASK_DEBUG_ARG 0x40000000 /* debug argument handling */
...@@ -353,6 +354,7 @@ extern int target_flags; ...@@ -353,6 +354,7 @@ extern int target_flags;
#define TARGET_NO_NESTED_CE ((target_flags & MASK_NO_NESTED_CE) != 0) #define TARGET_NO_NESTED_CE ((target_flags & MASK_NO_NESTED_CE) != 0)
#define TARGET_FDPIC ((target_flags & MASK_FDPIC) != 0) #define TARGET_FDPIC ((target_flags & MASK_FDPIC) != 0)
#define TARGET_INLINE_PLT ((target_flags & MASK_INLINE_PLT) != 0) #define TARGET_INLINE_PLT ((target_flags & MASK_INLINE_PLT) != 0)
#define TARGET_BIG_TLS ((target_flags & MASK_BIG_TLS) != 0)
#define TARGET_GPREL_RO ((target_flags & MASK_GPREL_RO) != 0) #define TARGET_GPREL_RO ((target_flags & MASK_GPREL_RO) != 0)
#define TARGET_PACK ((target_flags & MASK_PACK) != 0) #define TARGET_PACK ((target_flags & MASK_PACK) != 0)
#define TARGET_LONG_CALLS ((target_flags & MASK_LONG_CALLS) != 0) #define TARGET_LONG_CALLS ((target_flags & MASK_LONG_CALLS) != 0)
...@@ -414,6 +416,10 @@ extern int target_flags; ...@@ -414,6 +416,10 @@ extern int target_flags;
(frv_cpu_type == FRV_CPU_FR405 \ (frv_cpu_type == FRV_CPU_FR405 \
|| frv_cpu_type == FRV_CPU_FR450) || frv_cpu_type == FRV_CPU_FR450)
#ifndef HAVE_AS_TLS
#define HAVE_AS_TLS 0
#endif
/* This macro defines names of command options to set and clear bits in /* This macro defines names of command options to set and clear bits in
`target_flags'. Its definition is an initializer with a subgrouping for `target_flags'. Its definition is an initializer with a subgrouping for
each command option. each command option.
...@@ -494,6 +500,8 @@ extern int target_flags; ...@@ -494,6 +500,8 @@ extern int target_flags;
{ "no-fdpic", -MASK_FDPIC, "Disable file descriptor PIC mode" }, \ { "no-fdpic", -MASK_FDPIC, "Disable file descriptor PIC mode" }, \
{ "inline-plt", MASK_INLINE_PLT, "Enable inlining of PLT in function calls" }, \ { "inline-plt", MASK_INLINE_PLT, "Enable inlining of PLT in function calls" }, \
{ "no-inline-plt", -MASK_INLINE_PLT, "Disable inlining of PLT in function calls" }, \ { "no-inline-plt", -MASK_INLINE_PLT, "Disable inlining of PLT in function calls" }, \
{ "TLS", MASK_BIG_TLS, "Assume a large TLS segment" }, \
{ "tls", -MASK_BIG_TLS, "Do not assume a large TLS segment" }, \
{ "gprel-ro", MASK_GPREL_RO, "Enable use of GPREL for read-only data in FDPIC" }, \ { "gprel-ro", MASK_GPREL_RO, "Enable use of GPREL for read-only data in FDPIC" }, \
{ "no-gprel-ro", -MASK_GPREL_RO, "Disable use of GPREL for read-only data in FDPIC" }, \ { "no-gprel-ro", -MASK_GPREL_RO, "Disable use of GPREL for read-only data in FDPIC" }, \
{ "tomcat-stats", 0, "Cause gas to print tomcat statistics" }, \ { "tomcat-stats", 0, "Cause gas to print tomcat statistics" }, \
...@@ -1267,6 +1275,9 @@ enum reg_class ...@@ -1267,6 +1275,9 @@ enum reg_class
CR_REGS, CR_REGS,
LCR_REG, LCR_REG,
LR_REG, LR_REG,
GR8_REGS,
GR9_REGS,
GR89_REGS,
FDPIC_REGS, FDPIC_REGS,
FDPIC_FPTR_REGS, FDPIC_FPTR_REGS,
FDPIC_CALL_REGS, FDPIC_CALL_REGS,
...@@ -1304,6 +1315,9 @@ enum reg_class ...@@ -1304,6 +1315,9 @@ enum reg_class
"CR_REGS", \ "CR_REGS", \
"LCR_REG", \ "LCR_REG", \
"LR_REG", \ "LR_REG", \
"GR8_REGS", \
"GR9_REGS", \
"GR89_REGS", \
"FDPIC_REGS", \ "FDPIC_REGS", \
"FDPIC_FPTR_REGS", \ "FDPIC_FPTR_REGS", \
"FDPIC_CALL_REGS", \ "FDPIC_CALL_REGS", \
...@@ -1342,6 +1356,9 @@ enum reg_class ...@@ -1342,6 +1356,9 @@ enum reg_class
{ 0x00000000,0x00000000,0x00000000,0x00000000,0x0000ff00,0x0}, /* CR_REGS */\ { 0x00000000,0x00000000,0x00000000,0x00000000,0x0000ff00,0x0}, /* CR_REGS */\
{ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x400}, /* LCR_REGS */\ { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x400}, /* LCR_REGS */\
{ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x200}, /* LR_REGS */\ { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x200}, /* LR_REGS */\
{ 0x00000100,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* GR8_REGS */\
{ 0x00000200,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* GR9_REGS */\
{ 0x00000300,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* GR89_REGS */\
{ 0x00008000,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* FDPIC_REGS */\ { 0x00008000,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* FDPIC_REGS */\
{ 0x00004000,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* FDPIC_FPTR_REGS */\ { 0x00004000,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* FDPIC_FPTR_REGS */\
{ 0x0000c000,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* FDPIC_CALL_REGS */\ { 0x0000c000,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* FDPIC_CALL_REGS */\
...@@ -1581,6 +1598,17 @@ extern enum reg_class reg_class_from_letter[]; ...@@ -1581,6 +1598,17 @@ extern enum reg_class reg_class_from_letter[];
: (C) == 'U' ? EXTRA_CONSTRAINT_FOR_U (VALUE) \ : (C) == 'U' ? EXTRA_CONSTRAINT_FOR_U (VALUE) \
: 0) : 0)
#define CONSTRAINT_LEN(C, STR) \
((C) == 'D' ? 3 : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
#define REG_CLASS_FROM_CONSTRAINT(C, STR) \
(((C) == 'D' && (STR)[1] == '8' && (STR)[2] == '9') ? GR89_REGS : \
((C) == 'D' && (STR)[1] == '0' && (STR)[2] == '9') ? GR9_REGS : \
((C) == 'D' && (STR)[1] == '0' && (STR)[2] == '8') ? GR8_REGS : \
((C) == 'D' && (STR)[1] == '1' && (STR)[2] == '4') ? FDPIC_FPTR_REGS : \
((C) == 'D' && (STR)[1] == '1' && (STR)[2] == '5') ? FDPIC_REGS : \
REG_CLASS_FROM_LETTER ((C)))
/* Basic Stack Layout. */ /* Basic Stack Layout. */
...@@ -2578,6 +2606,13 @@ do { \ ...@@ -2578,6 +2606,13 @@ do { \
assemble_name (STREAM, LABEL); \ assemble_name (STREAM, LABEL); \
} while (0) } while (0)
#if HAVE_AS_TLS
/* Emit a dtp-relative reference to a TLS variable. */
#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \
frv_output_dwarf_dtprel ((FILE), (SIZE), (X))
#endif
/* Whether to emit the gas specific dwarf2 line number support. */ /* Whether to emit the gas specific dwarf2 line number support. */
#define DWARF2_ASM_LINE_DEBUG_INFO (TARGET_DEBUG_LOC) #define DWARF2_ASM_LINE_DEBUG_INFO (TARGET_DEBUG_LOC)
...@@ -3025,6 +3060,7 @@ do { \ ...@@ -3025,6 +3060,7 @@ do { \
CONST }}, \ CONST }}, \
{ "upper_int16_operand", { CONST_INT }}, \ { "upper_int16_operand", { CONST_INT }}, \
{ "uint16_operand", { CONST_INT }}, \ { "uint16_operand", { CONST_INT }}, \
{ "symbolic_operand", { SYMBOL_REF, CONST_INT }}, \
{ "relational_operator", { EQ, NE, LE, LT, GE, GT, \ { "relational_operator", { EQ, NE, LE, LT, GE, GT, \
LEU, LTU, GEU, GTU }}, \ LEU, LTU, GEU, GTU }}, \
{ "integer_relational_operator", { EQ, NE, LE, LT, GE, GT, \ { "integer_relational_operator", { EQ, NE, LE, LT, GE, GT, \
......
;; Frv Machine Description ;; Frv Machine Description
;; Copyright (C) 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc. ;; Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005 Free Software Foundation,
;; Inc.
;; Contributed by Red Hat, Inc. ;; Contributed by Red Hat, Inc.
;; This file is part of GCC. ;; This file is part of GCC.
...@@ -41,6 +42,15 @@ ...@@ -41,6 +42,15 @@
(UNSPEC_GOT 7) (UNSPEC_GOT 7)
(UNSPEC_LDD 8) (UNSPEC_LDD 8)
(UNSPEC_GETTLSOFF 200)
(UNSPEC_TLS_LOAD_GOTTLSOFF12 201)
(UNSPEC_TLS_INDIRECT_CALL 202)
(UNSPEC_TLS_TLSDESC_LDD 203)
(UNSPEC_TLS_TLSDESC_LDD_AUX 204)
(UNSPEC_TLS_TLSOFF_LD 205)
(UNSPEC_TLS_LDDI 206)
(UNSPEC_TLSOFF_HILO 207)
(R_FRV_GOT12 11) (R_FRV_GOT12 11)
(R_FRV_GOTHI 12) (R_FRV_GOTHI 12)
(R_FRV_GOTLO 13) (R_FRV_GOTLO 13)
...@@ -58,7 +68,21 @@ ...@@ -58,7 +68,21 @@
(R_FRV_GPREL12 25) (R_FRV_GPREL12 25)
(R_FRV_GPRELHI 26) (R_FRV_GPRELHI 26)
(R_FRV_GPRELLO 27) (R_FRV_GPRELLO 27)
(R_FRV_GOTTLSOFF_HI 28)
(R_FRV_GOTTLSOFF_LO 29)
(R_FRV_TLSMOFFHI 30)
(R_FRV_TLSMOFFLO 31)
(R_FRV_TLSMOFF12 32)
(R_FRV_TLSDESCHI 33)
(R_FRV_TLSDESCLO 34)
(R_FRV_GOTTLSDESCHI 35)
(R_FRV_GOTTLSDESCLO 36)
(GR8_REG 8)
(GR9_REG 9)
(GR14_REG 14)
;; LR_REG conflicts with definition in frv.h
(LRREG 169)
(FDPIC_REG 15) (FDPIC_REG 15)
]) ])
...@@ -330,7 +354,7 @@ ...@@ -330,7 +354,7 @@
;; Instruction type ;; Instruction type
;; "unknown" must come last. ;; "unknown" must come last.
(define_attr "type" (define_attr "type"
"int,sethi,setlo,mul,div,gload,gstore,fload,fstore,movfg,movgf,macc,scan,cut,branch,jump,jumpl,call,spr,trap,fnop,fsconv,fsadd,fscmp,fsmul,fsmadd,fsdiv,sqrt_single,fdconv,fdadd,fdcmp,fdmul,fdmadd,fddiv,sqrt_double,mnop,mlogic,maveh,msath,maddh,mqaddh,mpackh,munpackh,mdpackh,mbhconv,mrot,mshift,mexpdhw,mexpdhd,mwcut,mmulh,mmulxh,mmach,mmrdh,mqmulh,mqmulxh,mqmach,mcpx,mqcpx,mcut,mclracc,mclracca,mdunpackh,mbhconve,mrdacc,mwtacc,maddacc,mdaddacc,mabsh,mdrot,mcpl,mdcut,mqsath,mqlimh,mqshift,mset,ccr,multi,unknown" "int,sethi,setlo,mul,div,gload,gstore,fload,fstore,movfg,movgf,macc,scan,cut,branch,jump,jumpl,call,spr,trap,fnop,fsconv,fsadd,fscmp,fsmul,fsmadd,fsdiv,sqrt_single,fdconv,fdadd,fdcmp,fdmul,fdmadd,fddiv,sqrt_double,mnop,mlogic,maveh,msath,maddh,mqaddh,mpackh,munpackh,mdpackh,mbhconv,mrot,mshift,mexpdhw,mexpdhd,mwcut,mmulh,mmulxh,mmach,mmrdh,mqmulh,mqmulxh,mqmach,mcpx,mqcpx,mcut,mclracc,mclracca,mdunpackh,mbhconve,mrdacc,mwtacc,maddacc,mdaddacc,mabsh,mdrot,mcpl,mdcut,mqsath,mqlimh,mqshift,mset,ccr,multi,load_or_call,unknown"
(const_string "unknown")) (const_string "unknown"))
(define_attr "acc_group" "none,even,odd" (define_attr "acc_group" "none,even,odd"
...@@ -529,6 +553,11 @@ ...@@ -529,6 +553,11 @@
(eq_attr "type" "trap,spr,unknown,multi") (eq_attr "type" "trap,spr,unknown,multi")
"c + control") "c + control")
;; Reservation for relaxable calls to gettlsoff.
(define_insn_reservation "load_or_call" 3
(eq_attr "type" "load_or_call")
"c + control")
;; :::::::::::::::::::: ;; ::::::::::::::::::::
;; :: ;; ::
;; :: Generic/FR500 scheduler description ;; :: Generic/FR500 scheduler description
...@@ -8134,3 +8163,102 @@ ...@@ -8134,3 +8163,102 @@
"TARGET_FR500_FR550_BUILTINS" "TARGET_FR500_FR550_BUILTINS"
"nop.p\\n\\tnldub @(%0, gr0), gr0" "nop.p\\n\\tnldub @(%0, gr0), gr0"
[(set_attr "length" "8")]) [(set_attr "length" "8")])
;; TLS patterns
(define_insn "call_gettlsoff"
[(set (match_operand:SI 0 "register_operand" "=D09")
(unspec:SI
[(match_operand:SI 1 "symbolic_operand" "")]
UNSPEC_GETTLSOFF))
(clobber (reg:SI GR8_REG))
(clobber (reg:SI LRREG))
(use (match_operand:SI 2 "register_operand" "D15"))]
"HAVE_AS_TLS"
"call #gettlsoff(%a1)"
[(set_attr "length" "4")
(set_attr "type" "load_or_call")])
;; Reads GR8 and GR9.
;; Clobbers GR8.
;; Modifies GR9.
(define_insn "tls_indirect_call"
[(set (match_operand:SI 0 "register_operand" "=D09")
(unspec:SI
[(match_operand:SI 1 "symbolic_operand" "")
(match_operand:DI 2 "register_operand" "D89")]
UNSPEC_TLS_INDIRECT_CALL))
(clobber (match_operand:SI 3 "register_operand" "=D08"))
(clobber (reg:SI LRREG))
;; If there was a way to represent the fact that we don't need GR9
;; or GR15 to be set before this instruction (it could be in
;; parallel), we could use it here. This change wouldn't apply to
;; call_gettlsoff, thought, since the linker may turn the latter
;; into ldi @(gr15,offset),gr9.
(use (match_operand:SI 4 "register_operand" "D15"))]
"HAVE_AS_TLS"
"calll #gettlsoff(%a1)@(%2,gr0)"
[(set_attr "length" "4")
(set_attr "type" "jumpl")])
(define_insn "tls_load_gottlsoff12"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI
[(match_operand:SI 1 "symbolic_operand" "")
(match_operand:SI 2 "register_operand" "r")]
UNSPEC_TLS_LOAD_GOTTLSOFF12))]
"HAVE_AS_TLS"
"ldi @(%2, #gottlsoff12(%1)), %0"
[(set_attr "length" "4")])
(define_expand "tlsoff_hilo"
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (const:SI (unspec:SI
[(match_operand:SI 1 "symbolic_operand" "")
(match_operand:SI 2 "immediate_operand" "n")]
UNSPEC_GOT))))
(set (match_dup 0)
(lo_sum:SI (match_dup 0)
(const:SI (unspec:SI [(match_dup 1)
(match_dup 3)] UNSPEC_GOT))))]
""
"
{
operands[3] = GEN_INT (INTVAL (operands[2]) + 1);
}")
;; Just like movdi_ldd, but with relaxation annotations.
(define_insn "tls_tlsdesc_ldd"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(mem:DI (unspec:SI
[(match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "register_operand" "r")
(match_operand:SI 3 "symbolic_operand" "")]
UNSPEC_TLS_TLSDESC_LDD_AUX))]
UNSPEC_TLS_TLSDESC_LDD))]
""
"ldd #tlsdesc(%a3)@(%1,%2), %0"
[(set_attr "length" "4")
(set_attr "type" "gload")])
(define_insn "tls_tlsoff_ld"
[(set (match_operand:SI 0 "register_operand" "=r")
(mem:SI (unspec:SI
[(match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "register_operand" "r")
(match_operand:SI 3 "symbolic_operand" "")]
UNSPEC_TLS_TLSOFF_LD)))]
""
"ld #tlsoff(%a3)@(%1,%2), %0"
[(set_attr "length" "4")
(set_attr "type" "gload")])
(define_insn "tls_lddi"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:SI 1 "symbolic_operand" "")
(match_operand:SI 2 "register_operand" "d")]
UNSPEC_TLS_LDDI))]
""
"lddi @(%2, #gottlsdesc12(%a1)), %0"
[(set_attr "length" "4")
(set_attr "type" "gload")])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment