1 /*-
2  * Copyright (C) 2004 NVIDIA Corporation.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <stdio.h>
28 
29 #define __G_TLS_OFFSETS_SIZE    8
30 unsigned long int __gl_tls_offsets[__G_TLS_OFFSETS_SIZE];
31 
32 void __gl_tls_init_offsets();
33 
34 #ifdef __GL_TLS_SINGLE_INSTRUCTION
35 #define THREAD_GETMEM(num)                  \
36 ({                                          \
37     void *__value;                          \
38     __asm__ __volatile__ (                  \
39         "movl %%gs:(%1),%0"                 \
40         : "=r" (__value)                    \
41         : "r" (__gl_tls_offsets[num])       \
42     );                                      \
43     __value;                                \
44 })
45 
46 #define THREAD_SETMEM(num, value)           \
47 do {                                        \
48     void *__value = (value);                \
49     __asm__ __volatile__ (                  \
50         "movl %0,%%gs:(%1)"                 \
51         :                                   \
52         : "r" (__value),                    \
53           "r" (__gl_tls_offsets[num])       \
54     );                                      \
55 } while (0)
56 #else
57 #define __GL_TLS_GET(num)                   \
58 ({                                          \
59     void *__dummy, *__value;                \
60     __asm__ __volatile__ (                  \
61         "movl %%gs:0,%2     \n\t"           \
62         "movl (%2,%1),%0    \n\t"           \
63         : "=r" (__value)                    \
64         : "r" (__gl_tls_offsets[num]),      \
65           "r" (__dummy)                     \
66     );                                      \
67     __value;                                \
68 })
69 
70 #define __GL_TLS_SET(num, value)            \
71 do {                                        \
72     void *__dummy, *__value = (value);      \
73     __asm__ __volatile__ (                  \
74         "movl %%gs:0,%2     \n\t"           \
75         "movl %0,(%2,%1)    \n\t"           \
76         :                                   \
77         : "r" (__value),                    \
78           "r" (__gl_tls_offsets[num]),      \
79           "r" (__dummy)                     \
80     );                                      \
81 } while (0)
82 #endif
83 
84 void _init(void)
85 {
86     __gl_tls_init_offsets();
87 
88     __GL_TLS_SET(0, (void *) 0xff000000);
89     __GL_TLS_SET(1, (void *) 0xff000001);
90     __GL_TLS_SET(2, (void *) 0xff000002);
91     __GL_TLS_SET(3, (void *) 0xff000003);
92     __GL_TLS_SET(4, (void *) 0xff000004);
93     __GL_TLS_SET(5, (void *) 0xff000005);
94     __GL_TLS_SET(6, (void *) 0xff000006);
95     __GL_TLS_SET(7, (void *) 0xff000007);
96 }
97 
98 void __gl_tls_test(void)
99 {
100     printf("__GL_TLS_GET(0) = %p\n", __GL_TLS_GET(0));
101     printf("__GL_TLS_GET(1) = %p\n", __GL_TLS_GET(1));
102     printf("__GL_TLS_GET(2) = %p\n", __GL_TLS_GET(2));
103     printf("__GL_TLS_GET(3) = %p\n", __GL_TLS_GET(3));
104     printf("__GL_TLS_GET(4) = %p\n", __GL_TLS_GET(4));
105     printf("__GL_TLS_GET(5) = %p\n", __GL_TLS_GET(5));
106     printf("__GL_TLS_GET(6) = %p\n", __GL_TLS_GET(6));
107     printf("__GL_TLS_GET(7) = %p\n", __GL_TLS_GET(7));
108 }
109