diff mbox

[7/9] i386: Add address space for tls

Message ID 1444280375-20866-8-git-send-email-rth@redhat.com
State New
Headers show

Commit Message

Richard Henderson Oct. 8, 2015, 4:59 a.m. UTC
* config/i386/i386-protos.h (ADDR_SPACE_SEG_TLS): New.
	* config/i386/i386-c.c (ix86_target_macros): Define __SEG_TLS.
	(ix86_register_pragmas): Register __seg_tls.
	* config/i386/i386.c (ix86_print_operand_address_as): Handle
	ADDR_SPACE_SEG_TLS.
	(ix86_addr_space_subset_p): New.
	(TARGET_ADDR_SPACE_SUBSET_P): New.
	(ix86_addr_space_convert): New.
	(TARGET_ADDR_SPACE_CONVERT): New.
---
 gcc/config/i386/i386-c.c      |  2 ++
 gcc/config/i386/i386-protos.h |  1 +
 gcc/config/i386/i386.c        | 39 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 41 insertions(+), 1 deletion(-)

Comments

Florian Weimer Oct. 8, 2015, 8:30 a.m. UTC | #1
On 10/08/2015 06:59 AM, Richard Henderson wrote:
>    cpp_define (parse_in, "__SEG_FS");
>    cpp_define (parse_in, "__SEG_GS");
> +  cpp_define (parse_in, "__SEG_TLS");

Is there a good place to document these #defines?  I looked at your
glibc patch and wonder where __SEG_TLS was coming from.

Florian
diff mbox

Patch

diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index e21b947..71c12de 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -595,6 +595,7 @@  ix86_target_macros (void)
 
   cpp_define (parse_in, "__SEG_FS");
   cpp_define (parse_in, "__SEG_GS");
+  cpp_define (parse_in, "__SEG_TLS");
 }
 
 
@@ -611,6 +612,7 @@  ix86_register_pragmas (void)
 
   c_register_addr_space ("__seg_fs", ADDR_SPACE_SEG_FS);
   c_register_addr_space ("__seg_gs", ADDR_SPACE_SEG_GS);
+  c_register_addr_space ("__seg_tls", ADDR_SPACE_SEG_TLS);
 
 #ifdef REGISTER_SUBTARGET_PRAGMAS
   REGISTER_SUBTARGET_PRAGMAS ();
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 4e6d9ad..026b778 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -328,3 +328,4 @@  struct ix86_first_cycle_multipass_data_
 
 const addr_space_t ADDR_SPACE_SEG_FS = 1;
 const addr_space_t ADDR_SPACE_SEG_GS = 2;
+const addr_space_t ADDR_SPACE_SEG_TLS = 3;
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f5a0b8f..f7abb00 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -17296,6 +17296,8 @@  ix86_print_operand_address_as (FILE *file, rtx addr, addr_space_t as)
     {
       const char *string;
 
+      if (as == ADDR_SPACE_SEG_TLS)
+	as = DEFAULT_TLS_SEG_REG;
       if (as == ADDR_SPACE_SEG_FS)
 	string = (ASSEMBLER_DIALECT == ASM_ATT ? "%fs:" : "fs:");
       else if (as == ADDR_SPACE_SEG_GS)
@@ -53629,8 +53631,43 @@  ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
         without resorting to a system call, we cannot convert a
         non-default address space to a default address space.
         Therefore we do not claim %fs or %gs are subsets of generic.
+    (e) However, __seg_tls uses UNSPEC_TP as the base (which itself is
+	stored at __seg_tls:0) so we can map between tls and generic.  */
 
-   Therefore, we need not override any of the address space hooks.  */
+static bool
+ix86_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
+{
+    return (subset == superset
+	    || (superset == ADDR_SPACE_GENERIC
+		&& subset == ADDR_SPACE_SEG_TLS));
+}
+#undef TARGET_ADDR_SPACE_SUBSET_P
+#define TARGET_ADDR_SPACE_SUBSET_P ix86_addr_space_subset_p
+
+static rtx
+ix86_addr_space_convert (rtx op, tree from_type, tree to_type)
+{
+  addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
+  addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
+
+  /* Conversion between SEG_TLS and GENERIC is handled by adding or
+     subtracting the thread pointer.  */
+  if ((from_as == ADDR_SPACE_GENERIC && to_as == ADDR_SPACE_SEG_TLS)
+      || (from_as == ADDR_SPACE_SEG_TLS && to_as == ADDR_SPACE_GENERIC))
+    {
+      machine_mode mode = GET_MODE (op);
+      if (mode == VOIDmode)
+	mode = ptr_mode;
+      rtx tp = get_thread_pointer (mode, optimize || mode != ptr_mode);
+      return expand_binop (mode, (to_as == ADDR_SPACE_GENERIC
+				  ? add_optab : sub_optab),
+			   op, tp, NULL, 1, OPTAB_WIDEN);
+    }
+
+  return op;
+}
+#undef TARGET_ADDR_SPACE_CONVERT
+#define TARGET_ADDR_SPACE_CONVERT ix86_addr_space_convert
 
 /* Initialize the GCC target structure.  */
 #undef TARGET_RETURN_IN_MEMORY