This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

patch: TLS for FR-V (FDPIC ABI)


Hi folks.

The patch below adds support for thread-local storage to the FR-V backend
(on the FDPIC abi).  There is also an additional patch by Alex Oliva,
related to TLS.

(Alex, do we have a copy of the TLS FDPIC ABI on-line, to point folks to?).

This has been tested on frv-elf under the simulator.  It has also been
tested, on a Red Hat local tree on actual hardware, and used to build
glibc, the Linux kernel, and a few other things ;-).

I'm committing to mainline.

Cheers.

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.

Index: config/frv/frv.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/frv/frv.c,v
retrieving revision 1.78
diff -c -p -r1.78 frv.c
*** config/frv/frv.c	30 Dec 2004 03:07:46 -0000	1.78
--- config/frv/frv.c	25 Jan 2005 23:18:50 -0000
***************
*** 1,4 ****
! /* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004
     Free Software Foundation, Inc.
     Contributed by Red Hat, Inc.
  
--- 1,4 ----
! /* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
     Free Software Foundation, Inc.
     Contributed by Red Hat, Inc.
  
*************** static rtx frv_read_iacc_argument		(enum
*** 303,308 ****
--- 303,309 ----
  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);
*************** static int frv_arg_partial_bytes (CUMULA
*** 414,419 ****
--- 415,423 ----
  #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
*************** static int frv_arg_partial_bytes (CUMULA
*** 431,436 ****
--- 435,444 ----
  #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.  */
*************** frv_override_options (void)
*** 640,646 ****
        if (GPR_P (regno))
  	{
  	  int gpr_reg = regno - GPR_FIRST;
! 	  if ((gpr_reg & 3) == 0)
  	    class = QUAD_REGS;
  
  	  else if ((gpr_reg & 1) == 0)
--- 648,667 ----
        if (GPR_P (regno))
  	{
  	  int gpr_reg = regno - GPR_FIRST;
! 
! 	  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)
*************** frv_legitimate_address_p (enum machine_m
*** 3304,3309 ****
--- 3325,3333 ----
    HOST_WIDE_INT value;
    unsigned regno0;
  
+   if (FRV_SYMBOL_REF_TLS_P (x))
+     return 0;
+ 
    switch (GET_CODE (x))
      {
      default:
*************** frv_legitimate_address_p (enum machine_m
*** 3421,3431 ****
    return ret;
  }
  
  rtx
! frv_legitimize_address (rtx x ATTRIBUTE_UNUSED,
  			rtx oldx ATTRIBUTE_UNUSED,
  			enum machine_mode mode ATTRIBUTE_UNUSED)
  {
    return NULL_RTX;
  }
  
--- 3445,3622 ----
    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,
  			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;
  }
  
*************** unspec_got_name (int i)
*** 3501,3506 ****
--- 3692,3706 ----
      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 ();
      }
  }
*************** got12_operand (rtx op, enum machine_mode
*** 4617,4622 ****
--- 4817,4823 ----
        case R_FRV_FUNCDESC_GOT12:
        case R_FRV_FUNCDESC_GOTOFF12:
        case R_FRV_GPREL12:
+       case R_FRV_TLSMOFF12:
  	return true;
        }
    return false;
*************** sibcall_operand (rtx op, enum machine_mo
*** 4790,4795 ****
--- 4991,5014 ----
    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
*************** direct_return_p (void)
*** 5181,5186 ****
--- 5400,5412 ----
  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:
*************** frv_emit_movsi (rtx dest, rtx src)
*** 5314,5319 ****
--- 5540,5554 ----
      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))
*************** frv_struct_value_rtx (tree fntype ATTRIB
*** 10327,10330 ****
--- 10562,10582 ----
    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: config/frv/frv.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/frv/frv.h,v
retrieving revision 1.57
diff -c -p -r1.57 frv.h
*** config/frv/frv.h	30 Dec 2004 03:07:47 -0000	1.57
--- config/frv/frv.h	25 Jan 2005 23:18:53 -0000
***************
*** 1,5 ****
  /* Target macros for the FRV port of GCC.
!    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
     Free Software Foundation, Inc.
     Contributed by Red Hat Inc.
  
--- 1,5 ----
  /* Target macros for the FRV port of GCC.
!    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
     Free Software Foundation, Inc.
     Contributed by Red Hat Inc.
  
*************** extern int target_flags;
*** 309,314 ****
--- 309,315 ----
  #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 */
*************** extern int target_flags;
*** 353,358 ****
--- 354,360 ----
  #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)
*************** extern int target_flags;
*** 414,419 ****
--- 416,425 ----
    (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.
*************** extern int target_flags;
*** 494,499 ****
--- 500,507 ----
   { "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" }, \
*************** enum reg_class
*** 1267,1272 ****
--- 1275,1283 ----
    CR_REGS,
    LCR_REG,
    LR_REG,
+   GR8_REGS,
+   GR9_REGS,
+   GR89_REGS,
    FDPIC_REGS,
    FDPIC_FPTR_REGS,
    FDPIC_CALL_REGS,
*************** enum reg_class
*** 1304,1309 ****
--- 1315,1323 ----
     "CR_REGS",								\
     "LCR_REG",								\
     "LR_REG",								\
+    "GR8_REGS",                                                          \
+    "GR9_REGS",                                                          \
+    "GR89_REGS",                                                         \
     "FDPIC_REGS",							\
     "FDPIC_FPTR_REGS",							\
     "FDPIC_CALL_REGS",							\
*************** enum reg_class
*** 1342,1347 ****
--- 1356,1364 ----
    { 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 */\
*************** extern enum reg_class reg_class_from_let
*** 1581,1586 ****
--- 1598,1614 ----
     : (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.  */
  
*************** do {									\
*** 2578,2583 ****
--- 2606,2618 ----
    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)
  
*************** do {                                    
*** 3025,3030 ****
--- 3060,3066 ----
  					  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: config/frv/frv.md
===================================================================
RCS file: /cvs/uberbaum/gcc/config/frv/frv.md,v
retrieving revision 1.27
diff -c -p -r1.27 frv.md
*** config/frv/frv.md	10 Dec 2004 16:33:25 -0000	1.27
--- config/frv/frv.md	25 Jan 2005 23:18:56 -0000
***************
*** 1,5 ****
  ;; Frv Machine Description
! ;; Copyright (C) 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
  ;; Contributed by Red Hat, Inc.
  
  ;; This file is part of GCC.
--- 1,6 ----
  ;; Frv Machine Description
! ;; Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005 Free Software Foundation,
! ;; Inc.
  ;; Contributed by Red Hat, Inc.
  
  ;; This file is part of GCC.
***************
*** 41,46 ****
--- 42,56 ----
     (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,64 ****
     (R_FRV_GPREL12		25)
     (R_FRV_GPRELHI		26)
     (R_FRV_GPRELLO		27)
! 
     (FDPIC_REG			15)
     ])
  
--- 68,88 ----
     (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,336 ****
  ;; 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"
    (const_string "unknown"))
  
  (define_attr "acc_group" "none,even,odd"
--- 354,360 ----
  ;; 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,load_or_call,unknown"
    (const_string "unknown"))
  
  (define_attr "acc_group" "none,even,odd"
***************
*** 529,534 ****
--- 553,563 ----
    (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,8136 ****
--- 8163,8264 ----
    "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")])
Index: config/frv/frv-protos.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/frv/frv-protos.h,v
retrieving revision 1.23
diff -c -p -r1.23 frv-protos.h
*** config/frv/frv-protos.h	30 Dec 2004 03:07:46 -0000	1.23
--- config/frv/frv-protos.h	25 Jan 2005 23:18:56 -0000
***************
*** 1,5 ****
  /* Frv prototypes.
!    Copyright (C) 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
     Contributed by Red Hat, Inc.
  
  This file is part of GCC.
--- 1,6 ----
  /* Frv prototypes.
!    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_register_operand	(
*** 200,205 ****
--- 201,207 ----
  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 int accg_operand			(rtx, enum mac
*** 221,225 ****
--- 223,228 ----
  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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]