OSDN Git Service

* config/frv/frv.c (frv_legitimize_tls_address): New.
authoraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 26 Jan 2005 00:07:08 +0000 (00:07 +0000)
committeraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 26 Jan 2005 00:07:08 +0000 (00:07 +0000)
(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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94237 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/frv/frv-protos.h
gcc/config/frv/frv.c
gcc/config/frv/frv.h
gcc/config/frv/frv.md

index 0596f11..3519940 100644 (file)
@@ -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
index 63b43b9..534188e 100644 (file)
@@ -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
 
index cdf9744..5dd280b 100644 (file)
@@ -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)
+
 \f
 /* 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;
 }
 \f
@@ -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"
index ed62183..0636fff 100644 (file)
@@ -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)))
+
 \f
 /* 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)
 \f
@@ -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,       \
index 269de03..bab7755 100644 (file)
@@ -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.
    (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")])