+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>
PR rtl-optimization/19579
/* 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.
This file is part of GCC.
extern int small_data_symbolic_operand (rtx, enum machine_mode);
extern int upper_int16_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 signed_relational_operator (rtx, enum machine_mode);
extern int unsigned_relational_operator (rtx, enum machine_mode);
extern rtx frv_matching_accg_for_acc (rtx);
extern void frv_expand_fdpic_call (rtx *, bool, bool);
extern rtx frv_gen_GPsym2reg (rtx, rtx);
+extern void frv_output_dwarf_dtprel (FILE *, int, rtx);
#endif
-/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004
+/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
static int frv_check_constant_argument (enum insn_code, int, rtx);
static rtx frv_legitimize_target (enum insn_code, 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_unop_builtin (enum insn_code, tree, rtx);
static rtx frv_expand_binop_builtin (enum insn_code, tree, rtx);
#undef TARGET_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
#define TARGET_STRUCT_VALUE_RTX frv_struct_value_rtx
#undef TARGET_MUST_PASS_IN_STACK
#define TARGET_MACHINE_DEPENDENT_REORG frv_reorg
struct gcc_target targetm = TARGET_INITIALIZER;
+
+#define FRV_SYMBOL_REF_TLS_P(RTX) \
+ (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
+
\f
/* Any function call that satisfies the machine-independent
requirements is eligible on FR-V. */
if (GPR_P (regno))
{
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;
else if ((gpr_reg & 1) == 0)
HOST_WIDE_INT value;
unsigned regno0;
+ if (FRV_SYMBOL_REF_TLS_P (x))
+ return 0;
+
switch (GET_CODE (x))
{
default:
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
-frv_legitimize_address (rtx x ATTRIBUTE_UNUSED,
+frv_legitimize_address (rtx x,
rtx oldx 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;
}
\f
case R_FRV_GPREL12: return "gprel12";
case R_FRV_GPRELHI: return "gprelhi";
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 ();
}
}
case R_FRV_FUNCDESC_GOT12:
case R_FRV_FUNCDESC_GOTOFF12:
case R_FRV_GPREL12:
+ case R_FRV_TLSMOFF12:
return true;
}
return false;
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. */
int
void
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)
{
case SImode:
handle_sym:
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 (frv_local_funcdesc_p (sym))
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"
/* 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.
Contributed by Red Hat Inc.
#define MASK_LONG_CALLS 0x00000800 /* Use indirect calls */
#define MASK_ALIGN_LABELS 0x00001000 /* Optimize label alignments */
#define MASK_LINKED_FP 0x00002000 /* Follow ABI linkage requirements. */
+#define MASK_BIG_TLS 0x00008000 /* Assume a big TLS segment */
/* put debug masks up high */
#define MASK_DEBUG_ARG 0x40000000 /* debug argument handling */
#define TARGET_NO_NESTED_CE ((target_flags & MASK_NO_NESTED_CE) != 0)
#define TARGET_FDPIC ((target_flags & MASK_FDPIC) != 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_PACK ((target_flags & MASK_PACK) != 0)
#define TARGET_LONG_CALLS ((target_flags & MASK_LONG_CALLS) != 0)
(frv_cpu_type == FRV_CPU_FR405 \
|| 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
`target_flags'. Its definition is an initializer with a subgrouping for
each command option.
{ "no-fdpic", -MASK_FDPIC, "Disable file descriptor PIC mode" }, \
{ "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" }, \
+ { "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" }, \
{ "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" }, \
CR_REGS,
LCR_REG,
LR_REG,
+ GR8_REGS,
+ GR9_REGS,
+ GR89_REGS,
FDPIC_REGS,
FDPIC_FPTR_REGS,
FDPIC_CALL_REGS,
"CR_REGS", \
"LCR_REG", \
"LR_REG", \
+ "GR8_REGS", \
+ "GR9_REGS", \
+ "GR89_REGS", \
"FDPIC_REGS", \
"FDPIC_FPTR_REGS", \
"FDPIC_CALL_REGS", \
{ 0x00000000,0x00000000,0x00000000,0x00000000,0x0000ff00,0x0}, /* CR_REGS */\
{ 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x400}, /* LCR_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 */\
{ 0x00004000,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* FDPIC_FPTR_REGS */\
{ 0x0000c000,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* FDPIC_CALL_REGS */\
: (C) == 'U' ? EXTRA_CONSTRAINT_FOR_U (VALUE) \
: 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)))
+
\f
/* Basic Stack Layout. */
assemble_name (STREAM, LABEL); \
} 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. */
#define DWARF2_ASM_LINE_DEBUG_INFO (TARGET_DEBUG_LOC)
\f
CONST }}, \
{ "upper_int16_operand", { CONST_INT }}, \
{ "uint16_operand", { CONST_INT }}, \
+ { "symbolic_operand", { SYMBOL_REF, CONST_INT }}, \
{ "relational_operator", { EQ, NE, LE, LT, GE, GT, \
LEU, LTU, GEU, GTU }}, \
{ "integer_relational_operator", { EQ, NE, LE, LT, GE, GT, \
;; 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.
;; This file is part of GCC.
(UNSPEC_GOT 7)
(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_GOTHI 12)
(R_FRV_GOTLO 13)
(R_FRV_GPREL12 25)
(R_FRV_GPRELHI 26)
(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)
])
;; Instruction type
;; "unknown" must come last.
(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"))
(define_attr "acc_group" "none,even,odd"
(eq_attr "type" "trap,spr,unknown,multi")
"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
"TARGET_FR500_FR550_BUILTINS"
"nop.p\\n\\tnldub @(%0, gr0), gr0"
[(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")])