diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2005-01-26 00:07:08 +0000 |
---|---|---|
committer | Aldy Hernandez <aldyh@gcc.gnu.org> | 2005-01-26 00:07:08 +0000 |
commit | bef8809ed27296fa51b8f03467e2ae2a947ffc14 (patch) | |
tree | ebb18462d718659ec4d73acecc8727e06a61549d /gcc | |
parent | a7f7b3348c3abeddc55d218e7b555751b26f7957 (diff) | |
download | gcc-bef8809ed27296fa51b8f03467e2ae2a947ffc14.zip gcc-bef8809ed27296fa51b8f03467e2ae2a947ffc14.tar.gz gcc-bef8809ed27296fa51b8f03467e2ae2a947ffc14.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 54 | ||||
-rw-r--r-- | gcc/config/frv/frv-protos.h | 5 | ||||
-rw-r--r-- | gcc/config/frv/frv.c | 258 | ||||
-rw-r--r-- | gcc/config/frv/frv.h | 38 | ||||
-rw-r--r-- | gcc/config/frv/frv.md | 134 |
5 files changed, 481 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0596f11..3519940 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,57 @@ +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 diff --git a/gcc/config/frv/frv-protos.h b/gcc/config/frv/frv-protos.h index 63b43b9..534188e 100644 --- a/gcc/config/frv/frv-protos.h +++ b/gcc/config/frv/frv-protos.h @@ -1,5 +1,6 @@ /* 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. @@ -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 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); @@ -221,5 +223,6 @@ extern int accg_operand (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 diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index cdf9744..5dd280b 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -1,4 +1,4 @@ -/* 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. @@ -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 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); @@ -414,6 +415,9 @@ static int frv_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, #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 @@ -431,6 +435,10 @@ static int frv_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, #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) + /* Any function call that satisfies the machine-independent requirements is eligible on FR-V. */ @@ -640,7 +648,20 @@ frv_override_options (void) 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) @@ -3304,6 +3325,9 @@ frv_legitimate_address_p (enum machine_mode mode, HOST_WIDE_INT value; unsigned regno0; + if (FRV_SYMBOL_REF_TLS_P (x)) + return 0; + switch (GET_CODE (x)) { default: @@ -3421,11 +3445,178 @@ frv_legitimate_address_p (enum machine_mode mode, 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; } @@ -3501,6 +3692,15 @@ unspec_got_name (int i) 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 (); } } @@ -4617,6 +4817,7 @@ got12_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) case R_FRV_FUNCDESC_GOT12: case R_FRV_FUNCDESC_GOTOFF12: case R_FRV_GPREL12: + case R_FRV_TLSMOFF12: return true; } return false; @@ -4790,6 +4991,24 @@ sibcall_operand (rtx op, enum machine_mode 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. */ int @@ -5181,6 +5400,13 @@ direct_return_p (void) 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: @@ -5314,6 +5540,15 @@ frv_emit_movsi (rtx dest, rtx src) 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)) @@ -10327,4 +10562,21 @@ frv_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, 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" diff --git a/gcc/config/frv/frv.h b/gcc/config/frv/frv.h index ed62183..0636fff 100644 --- a/gcc/config/frv/frv.h +++ b/gcc/config/frv/frv.h @@ -1,5 +1,5 @@ /* 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. @@ -309,6 +309,7 @@ extern int target_flags; #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 */ @@ -353,6 +354,7 @@ extern int target_flags; #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) @@ -414,6 +416,10 @@ extern int target_flags; (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. @@ -494,6 +500,8 @@ extern int target_flags; { "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" }, \ @@ -1267,6 +1275,9 @@ enum reg_class CR_REGS, LCR_REG, LR_REG, + GR8_REGS, + GR9_REGS, + GR89_REGS, FDPIC_REGS, FDPIC_FPTR_REGS, FDPIC_CALL_REGS, @@ -1304,6 +1315,9 @@ enum reg_class "CR_REGS", \ "LCR_REG", \ "LR_REG", \ + "GR8_REGS", \ + "GR9_REGS", \ + "GR89_REGS", \ "FDPIC_REGS", \ "FDPIC_FPTR_REGS", \ "FDPIC_CALL_REGS", \ @@ -1342,6 +1356,9 @@ enum reg_class { 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 */\ @@ -1581,6 +1598,17 @@ extern enum reg_class reg_class_from_letter[]; : (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))) + /* Basic Stack Layout. */ @@ -2578,6 +2606,13 @@ do { \ 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) @@ -3025,6 +3060,7 @@ do { \ 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, \ diff --git a/gcc/config/frv/frv.md b/gcc/config/frv/frv.md index 269de03..bab7755 100644 --- a/gcc/config/frv/frv.md +++ b/gcc/config/frv/frv.md @@ -1,5 +1,6 @@ ;; 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. @@ -41,6 +42,15 @@ (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) @@ -58,7 +68,21 @@ (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) ]) @@ -330,7 +354,7 @@ ;; 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" @@ -529,6 +553,11 @@ (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 @@ -8134,3 +8163,102 @@ "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")]) |