1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 2010 LunarG Inc.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22848b8605Smrg * DEALINGS IN THE SOFTWARE.
23848b8605Smrg *
24848b8605Smrg * Authors:
25848b8605Smrg *    Chia-I Wu <olv@lunarg.com>
26848b8605Smrg */
27848b8605Smrg
28848b8605Smrg#include <string.h>
29b8e80941Smrg
30b8e80941Smrg#ifdef HAVE_FUNC_ATTRIBUTE_VISIBILITY
31b8e80941Smrg#define HIDDEN __attribute__((visibility("hidden")))
32b8e80941Smrg#else
33b8e80941Smrg#define HIDDEN
34b8e80941Smrg#endif
35848b8605Smrg
36848b8605Smrg__asm__(".text");
37848b8605Smrg
38848b8605Smrg__asm__("x86_current_tls:\n\t"
39848b8605Smrg	"call 1f\n"
40848b8605Smrg        "1:\n\t"
41848b8605Smrg        "popl %eax\n\t"
42848b8605Smrg	"addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %eax\n\t"
43848b8605Smrg	"movl " ENTRY_CURRENT_TABLE "@GOTNTPOFF(%eax), %eax\n\t"
44848b8605Smrg	"ret");
45848b8605Smrg
46b8e80941Smrg#if defined(__NetBSD__)
47b8e80941Smrg__asm__("x86_current_table_helper:\n\t"
48b8e80941Smrg	"movl %gs:(%eax), %eax\n\t"   \
49b8e80941Smrg	"testl %eax, %eax\n\t"        \
50b8e80941Smrg	"je 1f\n\t"                   \
51b8e80941Smrg	"ret\n\t"                     \
52b8e80941Smrg	"1:\n\t"                      \
53b8e80941Smrg	"call 2f\n\t"                 \
54b8e80941Smrg	"2:\n\t"                      \
55b8e80941Smrg	"popl %eax\n\t"               \
56b8e80941Smrg	"addl $_GLOBAL_OFFSET_TABLE_+[.-2b], %eax\n\t" \
57b8e80941Smrg	"jmp *" ENTRY_CURRENT_TABLE_GET "@GOT(%eax)");
58b8e80941Smrg#endif
59b8e80941Smrg
60848b8605Smrg#ifndef GLX_X86_READONLY_TEXT
61848b8605Smrg__asm__(".section wtext, \"awx\", @progbits");
62848b8605Smrg#endif /* GLX_X86_READONLY_TEXT */
63848b8605Smrg
64848b8605Smrg__asm__(".balign 16\n"
65848b8605Smrg        "x86_entry_start:");
66848b8605Smrg
67848b8605Smrg#define STUB_ASM_ENTRY(func)     \
68848b8605Smrg   ".globl " func "\n"           \
69848b8605Smrg   ".type " func ", @function\n" \
70848b8605Smrg   ".balign 16\n"                \
71848b8605Smrg   func ":"
72848b8605Smrg
73b8e80941Smrg#if defined(__NetBSD__)
74848b8605Smrg#define STUB_ASM_CODE(slot)      \
75b8e80941Smrg   "call x86_current_tls\n\t"    \
76b8e80941Smrg   "call x86_current_table_helper\n\t"    \
77848b8605Smrg   "jmp *(4 * " slot ")(%eax)"
78848b8605Smrg#else
79848b8605Smrg#define STUB_ASM_CODE(slot)      \
80848b8605Smrg   "call x86_current_tls\n\t"    \
81848b8605Smrg   "movl %gs:(%eax), %eax\n\t"   \
82848b8605Smrg   "jmp *(4 * " slot ")(%eax)"
83848b8605Smrg#endif
84848b8605Smrg
85848b8605Smrg#define MAPI_TMP_STUB_ASM_GCC
86848b8605Smrg#include "mapi_tmp.h"
87848b8605Smrg
88848b8605Smrg#ifndef GLX_X86_READONLY_TEXT
89848b8605Smrg__asm__(".balign 16\n"
90848b8605Smrg        "x86_entry_end:");
91848b8605Smrg__asm__(".text");
92848b8605Smrg#endif /* GLX_X86_READONLY_TEXT */
93848b8605Smrg
94848b8605Smrg#ifndef MAPI_MODE_BRIDGE
95848b8605Smrg
96848b8605Smrg#include "u_execmem.h"
97848b8605Smrg
98848b8605Smrgextern unsigned long
99848b8605Smrgx86_current_tls();
100848b8605Smrg
101b8e80941Smrgextern char x86_entry_start[] HIDDEN;
102b8e80941Smrgextern char x86_entry_end[] HIDDEN;
103848b8605Smrg
104848b8605Smrgvoid
105848b8605Smrgentry_patch_public(void)
106848b8605Smrg{
107848b8605Smrg#ifndef GLX_X86_READONLY_TEXT
108848b8605Smrg   char patch[8] = {
109848b8605Smrg      0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, /* movl %gs:0x0, %eax */
110848b8605Smrg      0x90, 0x90                          /* nop's */
111848b8605Smrg   };
112848b8605Smrg   char *entry;
113848b8605Smrg
114848b8605Smrg   *((unsigned long *) (patch + 2)) = x86_current_tls();
115848b8605Smrg
116848b8605Smrg   for (entry = x86_entry_start; entry < x86_entry_end; entry += 16)
117848b8605Smrg      memcpy(entry, patch, sizeof(patch));
118848b8605Smrg#endif
119848b8605Smrg}
120848b8605Smrg
121848b8605Smrgmapi_func
122848b8605Smrgentry_get_public(int slot)
123848b8605Smrg{
124848b8605Smrg   return (mapi_func) (x86_entry_start + slot * 16);
125848b8605Smrg}
126848b8605Smrg
127848b8605Smrgvoid
128848b8605Smrgentry_patch(mapi_func entry, int slot)
129848b8605Smrg{
130848b8605Smrg   char *code = (char *) entry;
131848b8605Smrg   *((unsigned long *) (code + 8)) = slot * sizeof(mapi_func);
132848b8605Smrg}
133848b8605Smrg
134848b8605Smrgmapi_func
135848b8605Smrgentry_generate(int slot)
136848b8605Smrg{
137848b8605Smrg   const char code_templ[16] = {
138848b8605Smrg      0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, /* movl %gs:0x0, %eax */
139848b8605Smrg      0xff, 0xa0, 0x34, 0x12, 0x00, 0x00, /* jmp *0x1234(%eax) */
140848b8605Smrg      0x90, 0x90, 0x90, 0x90              /* nop's */
141848b8605Smrg   };
142b8e80941Smrg   char *code;
143848b8605Smrg   mapi_func entry;
144848b8605Smrg
145848b8605Smrg   code = u_execmem_alloc(sizeof(code_templ));
146848b8605Smrg   if (!code)
147848b8605Smrg      return NULL;
148848b8605Smrg
149848b8605Smrg   memcpy(code, code_templ, sizeof(code_templ));
150848b8605Smrg
151848b8605Smrg   *((unsigned long *) (code + 2)) = x86_current_tls();
152848b8605Smrg   entry = (mapi_func) code;
153848b8605Smrg   entry_patch(entry, slot);
154848b8605Smrg
155848b8605Smrg   return entry;
156848b8605Smrg}
157848b8605Smrg
158848b8605Smrg#endif /* MAPI_MODE_BRIDGE */
159