1133066Sdfr/*-
2133066Sdfr * Copyright (C) 2004 NVIDIA Corporation.
3133066Sdfr * All rights reserved.
4133066Sdfr *
5133066Sdfr * Redistribution and use in source and binary forms, with or without
6133066Sdfr * modification, are permitted provided that the following conditions
7133066Sdfr * are met:
8133066Sdfr * 1. Redistributions of source code must retain the above copyright
9133066Sdfr *    notice, this list of conditions and the following disclaimer.
10133066Sdfr * 2. Redistributions in binary form must reproduce the above copyright
11133066Sdfr *    notice, this list of conditions and the following disclaimer in the
12133066Sdfr *    documentation and/or other materials provided with the distribution.
13133066Sdfr *
14133066Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15133066Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16133066Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17133066Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18133066Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19133066Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20133066Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21133066Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22133066Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23133066Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24133066Sdfr * SUCH DAMAGE.
25133066Sdfr *
26133066Sdfr *	$FreeBSD$
27133066Sdfr */
28133066Sdfr
29133066Sdfr#include <stdio.h>
30133066Sdfr
31133066Sdfr#define __G_TLS_OFFSETS_SIZE    8
32133066Sdfrunsigned long int __gl_tls_offsets[__G_TLS_OFFSETS_SIZE];
33133066Sdfr
34133066Sdfrvoid __gl_tls_init_offsets();
35133066Sdfr
36133066Sdfr#ifdef __GL_TLS_SINGLE_INSTRUCTION
37133066Sdfr#define THREAD_GETMEM(num)                  \
38133066Sdfr({                                          \
39133066Sdfr    void *__value;                          \
40133066Sdfr    __asm__ __volatile__ (                  \
41133066Sdfr        "movl %%gs:(%1),%0"                 \
42133066Sdfr        : "=r" (__value)                    \
43133066Sdfr        : "r" (__gl_tls_offsets[num])       \
44133066Sdfr    );                                      \
45133066Sdfr    __value;                                \
46133066Sdfr})
47133066Sdfr
48133066Sdfr#define THREAD_SETMEM(num, value)           \
49133066Sdfrdo {                                        \
50133066Sdfr    void *__value = (value);                \
51133066Sdfr    __asm__ __volatile__ (                  \
52133066Sdfr        "movl %0,%%gs:(%1)"                 \
53133066Sdfr        :                                   \
54133066Sdfr        : "r" (__value),                    \
55133066Sdfr          "r" (__gl_tls_offsets[num])       \
56133066Sdfr    );                                      \
57133066Sdfr} while (0)
58133066Sdfr#else
59133066Sdfr#define __GL_TLS_GET(num)                   \
60133066Sdfr({                                          \
61133066Sdfr    void *__dummy, *__value;                \
62133066Sdfr    __asm__ __volatile__ (                  \
63133066Sdfr        "movl %%gs:0,%2     \n\t"           \
64133066Sdfr        "movl (%2,%1),%0    \n\t"           \
65133066Sdfr        : "=r" (__value)                    \
66133066Sdfr        : "r" (__gl_tls_offsets[num]),      \
67133066Sdfr          "r" (__dummy)                     \
68133066Sdfr    );                                      \
69133066Sdfr    __value;                                \
70133066Sdfr})
71133066Sdfr
72133066Sdfr#define __GL_TLS_SET(num, value)            \
73133066Sdfrdo {                                        \
74133066Sdfr    void *__dummy, *__value = (value);      \
75133066Sdfr    __asm__ __volatile__ (                  \
76133066Sdfr        "movl %%gs:0,%2     \n\t"           \
77133066Sdfr        "movl %0,(%2,%1)    \n\t"           \
78133066Sdfr        :                                   \
79133066Sdfr        : "r" (__value),                    \
80133066Sdfr          "r" (__gl_tls_offsets[num]),      \
81133066Sdfr          "r" (__dummy)                     \
82133066Sdfr    );                                      \
83133066Sdfr} while (0)
84133066Sdfr#endif
85133066Sdfr
86133066Sdfrvoid _init(void)
87133066Sdfr{
88133066Sdfr    __gl_tls_init_offsets();
89133066Sdfr
90133066Sdfr    __GL_TLS_SET(0, (void *) 0xff000000);
91133066Sdfr    __GL_TLS_SET(1, (void *) 0xff000001);
92133066Sdfr    __GL_TLS_SET(2, (void *) 0xff000002);
93133066Sdfr    __GL_TLS_SET(3, (void *) 0xff000003);
94133066Sdfr    __GL_TLS_SET(4, (void *) 0xff000004);
95133066Sdfr    __GL_TLS_SET(5, (void *) 0xff000005);
96133066Sdfr    __GL_TLS_SET(6, (void *) 0xff000006);
97133066Sdfr    __GL_TLS_SET(7, (void *) 0xff000007);
98133066Sdfr}
99133066Sdfr
100133066Sdfrvoid __gl_tls_test(void)
101133066Sdfr{
102133066Sdfr    printf("__GL_TLS_GET(0) = %p\n", __GL_TLS_GET(0));
103133066Sdfr    printf("__GL_TLS_GET(1) = %p\n", __GL_TLS_GET(1));
104133066Sdfr    printf("__GL_TLS_GET(2) = %p\n", __GL_TLS_GET(2));
105133066Sdfr    printf("__GL_TLS_GET(3) = %p\n", __GL_TLS_GET(3));
106133066Sdfr    printf("__GL_TLS_GET(4) = %p\n", __GL_TLS_GET(4));
107133066Sdfr    printf("__GL_TLS_GET(5) = %p\n", __GL_TLS_GET(5));
108133066Sdfr    printf("__GL_TLS_GET(6) = %p\n", __GL_TLS_GET(6));
109133066Sdfr    printf("__GL_TLS_GET(7) = %p\n", __GL_TLS_GET(7));
110133066Sdfr}
111