GLSL fixes:
[mesa.git] / src / mesa / shader / slang / slang_execute_x86.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 2006 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file slang_execute_x86.c
27 * x86 back end compiler
28 * \author Michal Krol, Keith Whitwell
29 */
30
31 #include "imports.h"
32 #include "slang_execute.h"
33 #include "slang_library_noise.h"
34 #include "slang_library_texsample.h"
35
36 #if defined(USE_X86_ASM) || defined(SLANG_X86)
37
38 #include "x86/rtasm/x86sse.h"
39
40 typedef struct
41 {
42 GLuint index;
43 GLubyte *csr;
44 } fixup;
45
46 typedef struct
47 {
48 struct x86_function f;
49 struct x86_reg r_eax;
50 struct x86_reg r_ecx;
51 struct x86_reg r_edx;
52 struct x86_reg r_esp;
53 struct x86_reg r_ebp;
54 struct x86_reg r_st0;
55 struct x86_reg r_st1;
56 struct x86_reg r_st2;
57 struct x86_reg r_st3;
58 fixup *fixups;
59 GLuint fixup_count;
60 GLubyte **labels;
61 slang_machine *mach;
62 GLubyte *l_discard;
63 GLubyte *l_exit;
64 GLshort fpucntl;
65 } codegen_ctx;
66
67 static GLvoid add_fixup (codegen_ctx *G, GLuint index, GLubyte *csr)
68 {
69 G->fixups = (fixup *) slang_alloc_realloc (G->fixups, G->fixup_count * sizeof (fixup),
70 (G->fixup_count + 1) * sizeof (fixup));
71 G->fixups[G->fixup_count].index = index;
72 G->fixups[G->fixup_count].csr = csr;
73 G->fixup_count++;
74 }
75
76 #ifdef NO_FAST_MATH
77 #define RESTORE_FPU (DEFAULT_X86_FPU)
78 #define RND_NEG_FPU (DEFAULT_X86_FPU | 0x400)
79 #else
80 #define RESTORE_FPU (FAST_X86_FPU)
81 #define RND_NEG_FPU (FAST_X86_FPU | 0x400)
82 #endif
83
84 static void set_fpu_round_neg_inf (codegen_ctx *G)
85 {
86 if (G->fpucntl != RND_NEG_FPU)
87 {
88 G->fpucntl = RND_NEG_FPU;
89 x87_fnclex (&G->f);
90 x86_mov_reg_imm (&G->f, G->r_eax, (GLint) &G->mach->x86.fpucntl_rnd_neg);
91 x87_fldcw (&G->f, x86_deref (G->r_eax));
92 }
93 }
94
95 static void emit_x87_ex2 (codegen_ctx *G)
96 {
97 set_fpu_round_neg_inf (G);
98
99 x87_fld (&G->f, G->r_st0); /* a a */
100 x87_fprndint (&G->f); /* int(a) a */
101 x87_fld (&G->f, G->r_st0); /* int(a) int(a) a */
102 x87_fstp (&G->f, G->r_st3); /* int(a) a int(a)*/
103 x87_fsubp (&G->f, G->r_st1);/* frac(a) int(a) */
104 x87_f2xm1 (&G->f); /* (2^frac(a))-1 int(a)*/
105 x87_fld1 (&G->f); /* 1 (2^frac(a))-1 int(a)*/
106 x87_faddp (&G->f, G->r_st1);/* 2^frac(a) int(a) */
107 x87_fscale (&G->f); /* 2^a */
108 }
109
110 static GLfloat do_ceilf (GLfloat x)
111 {
112 return CEILF (x);
113 }
114
115 static GLfloat do_floorf (GLfloat x)
116 {
117 return FLOORF (x);
118 }
119
120 static GLvoid do_print_float (GLfloat x)
121 {
122 _mesa_printf ("slang print: %f\n", x);
123 }
124
125 static GLvoid do_print_int (GLfloat x)
126 {
127 _mesa_printf ("slang print: %d\n", (GLint) x);
128 }
129
130 static GLvoid do_print_bool (GLfloat x)
131 {
132 _mesa_printf ("slang print: %s\n", (GLint) x ? "true" : "false");
133 }
134
135 static GLvoid codegen_assem (codegen_ctx *G, slang_assembly *a)
136 {
137 GLint disp;
138
139 switch (a->type)
140 {
141 case slang_asm_none:
142 break;
143 case slang_asm_float_copy:
144 case slang_asm_int_copy:
145 case slang_asm_bool_copy:
146 x86_mov (&G->f, G->r_eax, x86_make_disp (G->r_esp, a->param[0]));
147 x86_pop (&G->f, G->r_ecx);
148 x86_mov (&G->f, x86_make_disp (G->r_eax, a->param[1]), G->r_ecx);
149 break;
150 case slang_asm_float_move:
151 case slang_asm_int_move:
152 case slang_asm_bool_move:
153 x86_lea (&G->f, G->r_eax, x86_make_disp (G->r_esp, a->param[1]));
154 x86_add (&G->f, G->r_eax, x86_deref (G->r_esp));
155 x86_mov (&G->f, G->r_eax, x86_deref (G->r_eax));
156 x86_mov (&G->f, x86_make_disp (G->r_esp, a->param[0]), G->r_eax);
157 break;
158 case slang_asm_float_push:
159 case slang_asm_int_push:
160 case slang_asm_bool_push:
161 /* TODO: use push imm32 */
162 x86_mov_reg_imm (&G->f, G->r_eax, *((GLint *) &a->literal));
163 x86_push (&G->f, G->r_eax);
164 break;
165 case slang_asm_float_deref:
166 case slang_asm_int_deref:
167 case slang_asm_bool_deref:
168 case slang_asm_addr_deref:
169 x86_mov (&G->f, G->r_eax, x86_deref (G->r_esp));
170 x86_mov (&G->f, G->r_eax, x86_deref (G->r_eax));
171 x86_mov (&G->f, x86_deref (G->r_esp), G->r_eax);
172 break;
173 case slang_asm_float_add:
174 x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
175 x87_fld (&G->f, x86_deref (G->r_esp));
176 x87_faddp (&G->f, G->r_st1);
177 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
178 x87_fstp (&G->f, x86_deref (G->r_esp));
179 break;
180 case slang_asm_float_multiply:
181 x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
182 x87_fld (&G->f, x86_deref (G->r_esp));
183 x87_fmulp (&G->f, G->r_st1);
184 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
185 x87_fstp (&G->f, x86_deref (G->r_esp));
186 break;
187 case slang_asm_float_divide:
188 x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
189 x87_fld (&G->f, x86_deref (G->r_esp));
190 x87_fdivp (&G->f, G->r_st1);
191 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
192 x87_fstp (&G->f, x86_deref (G->r_esp));
193 break;
194 case slang_asm_float_negate:
195 x87_fld (&G->f, x86_deref (G->r_esp));
196 x87_fchs (&G->f);
197 x87_fstp (&G->f, x86_deref (G->r_esp));
198 break;
199 case slang_asm_float_less:
200 x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
201 x87_fcomp (&G->f, x86_deref (G->r_esp));
202 x87_fnstsw (&G->f, G->r_eax);
203 /* TODO: use test r8,imm8 */
204 x86_mov_reg_imm (&G->f, G->r_ecx, 0x100);
205 x86_test (&G->f, G->r_eax, G->r_ecx);
206 {
207 GLfloat one = 1.0f, zero = 0.0f;
208 GLubyte *lab0, *lab1;
209
210 /* TODO: use jcc rel8 */
211 lab0 = x86_jcc_forward (&G->f, cc_E);
212 x86_mov_reg_imm (&G->f, G->r_ecx, *((GLint *) &one));
213 /* TODO: use jmp rel8 */
214 lab1 = x86_jmp_forward (&G->f);
215 x86_fixup_fwd_jump (&G->f, lab0);
216 x86_mov_reg_imm (&G->f, G->r_ecx, *((GLint *) &zero));
217 x86_fixup_fwd_jump (&G->f, lab1);
218 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
219 x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx);
220 }
221 break;
222 case slang_asm_float_equal_exp:
223 x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
224 x87_fcomp (&G->f, x86_deref (G->r_esp));
225 x87_fnstsw (&G->f, G->r_eax);
226 /* TODO: use test r8,imm8 */
227 x86_mov_reg_imm (&G->f, G->r_ecx, 0x4000);
228 x86_test (&G->f, G->r_eax, G->r_ecx);
229 {
230 GLfloat one = 1.0f, zero = 0.0f;
231 GLubyte *lab0, *lab1;
232
233 /* TODO: use jcc rel8 */
234 lab0 = x86_jcc_forward (&G->f, cc_E);
235 x86_mov_reg_imm (&G->f, G->r_ecx, *((GLint *) &one));
236 /* TODO: use jmp rel8 */
237 lab1 = x86_jmp_forward (&G->f);
238 x86_fixup_fwd_jump (&G->f, lab0);
239 x86_mov_reg_imm (&G->f, G->r_ecx, *((GLint *) &zero));
240 x86_fixup_fwd_jump (&G->f, lab1);
241 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
242 x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx);
243 }
244 break;
245 case slang_asm_float_equal_int:
246 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, -4));
247 x87_fld (&G->f, x86_make_disp (G->r_esp, a->param[0] + 4));
248 x87_fcomp (&G->f, x86_make_disp (G->r_esp, a->param[1] + 4));
249 x87_fnstsw (&G->f, G->r_eax);
250 /* TODO: use test r8,imm8 */
251 x86_mov_reg_imm (&G->f, G->r_ecx, 0x4000);
252 x86_test (&G->f, G->r_eax, G->r_ecx);
253 {
254 GLfloat one = 1.0f, zero = 0.0f;
255 GLubyte *lab0, *lab1;
256
257 /* TODO: use jcc rel8 */
258 lab0 = x86_jcc_forward (&G->f, cc_E);
259 x86_mov_reg_imm (&G->f, G->r_ecx, *((GLint *) &one));
260 /* TODO: use jmp rel8 */
261 lab1 = x86_jmp_forward (&G->f);
262 x86_fixup_fwd_jump (&G->f, lab0);
263 x86_mov_reg_imm (&G->f, G->r_ecx, *((GLint *) &zero));
264 x86_fixup_fwd_jump (&G->f, lab1);
265 x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx);
266 }
267 break;
268 case slang_asm_float_to_int:
269 x87_fld (&G->f, x86_deref (G->r_esp));
270 x87_fistp (&G->f, x86_deref (G->r_esp));
271 break;
272 case slang_asm_float_sine:
273 /* TODO: use fsin */
274 x86_call (&G->f, (GLubyte *) _mesa_sinf);
275 x87_fstp (&G->f, x86_deref (G->r_esp));
276 break;
277 case slang_asm_float_arcsine:
278 /* TODO: use fpatan (?) */
279 x86_call (&G->f, (GLubyte *) _mesa_asinf);
280 x87_fstp (&G->f, x86_deref (G->r_esp));
281 break;
282 case slang_asm_float_arctan:
283 /* TODO: use fpatan */
284 x86_call (&G->f, (GLubyte *) _mesa_atanf);
285 x87_fstp (&G->f, x86_deref (G->r_esp));
286 break;
287 case slang_asm_float_power:
288 x87_fld (&G->f, x86_deref (G->r_esp));
289 x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
290 x87_fyl2x (&G->f);
291 emit_x87_ex2 (G);
292 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
293 x87_fstp (&G->f, x86_deref (G->r_esp));
294 break;
295 case slang_asm_float_log2:
296 x87_fld1 (&G->f);
297 x87_fld (&G->f, x86_deref (G->r_esp));
298 x87_fyl2x (&G->f);
299 x87_fstp (&G->f, x86_deref (G->r_esp));
300 break;
301 case slang_asm_float_floor:
302 x86_call (&G->f, (GLubyte *) do_floorf);
303 x87_fstp (&G->f, x86_deref (G->r_esp));
304 break;
305 case slang_asm_float_ceil:
306 x86_call (&G->f, (GLubyte *) do_ceilf);
307 x87_fstp (&G->f, x86_deref (G->r_esp));
308 break;
309 case slang_asm_float_noise1:
310 x86_call (&G->f, (GLubyte *) _slang_library_noise1);
311 x87_fstp (&G->f, x86_deref (G->r_esp));
312 break;
313 case slang_asm_float_noise2:
314 x86_call (&G->f, (GLubyte *) _slang_library_noise2);
315 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
316 x87_fstp (&G->f, x86_deref (G->r_esp));
317 break;
318 case slang_asm_float_noise3:
319 x86_call (&G->f, (GLubyte *) _slang_library_noise4);
320 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 8));
321 x87_fstp (&G->f, x86_deref (G->r_esp));
322 break;
323 case slang_asm_float_noise4:
324 x86_call (&G->f, (GLubyte *) _slang_library_noise4);
325 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 12));
326 x87_fstp (&G->f, x86_deref (G->r_esp));
327 break;
328 case slang_asm_int_to_float:
329 break;
330 case slang_asm_int_to_addr:
331 x87_fld (&G->f, x86_deref (G->r_esp));
332 x87_fistp (&G->f, x86_deref (G->r_esp));
333 break;
334 case slang_asm_addr_copy:
335 x86_pop (&G->f, G->r_eax);
336 x86_mov (&G->f, G->r_ecx, x86_deref (G->r_esp));
337 x86_mov (&G->f, x86_deref (G->r_ecx), G->r_eax);
338 break;
339 case slang_asm_addr_push:
340 /* TODO: use push imm32 */
341 x86_mov_reg_imm (&G->f, G->r_eax, (GLint) a->param[0]);
342 x86_push (&G->f, G->r_eax);
343 break;
344 case slang_asm_addr_add:
345 x86_pop (&G->f, G->r_eax);
346 x86_add (&G->f, x86_deref (G->r_esp), G->r_eax);
347 break;
348 case slang_asm_addr_multiply:
349 x86_pop (&G->f, G->r_ecx);
350 x86_mov (&G->f, G->r_eax, x86_deref (G->r_esp));
351 x86_mul (&G->f, G->r_ecx);
352 x86_mov (&G->f, x86_deref (G->r_esp), G->r_eax);
353 break;
354 case slang_asm_vec4_tex1d:
355 x86_call (&G->f, (GLubyte *) _slang_library_tex1d);
356 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 12));
357 break;
358 case slang_asm_vec4_tex2d:
359 x86_call (&G->f, (GLubyte *) _slang_library_tex2d);
360 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 16));
361 break;
362 case slang_asm_vec4_tex3d:
363 x86_call (&G->f, (GLubyte *) _slang_library_tex3d);
364 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 20));
365 break;
366 case slang_asm_vec4_texcube:
367 x86_call (&G->f, (GLubyte *) _slang_library_texcube);
368 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 20));
369 break;
370 case slang_asm_vec4_shad1d:
371 x86_call (&G->f, (GLubyte *) _slang_library_shad1d);
372 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 20));
373 break;
374 case slang_asm_vec4_shad2d:
375 x86_call (&G->f, (GLubyte *) _slang_library_shad2d);
376 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 20));
377 break;
378 case slang_asm_jump:
379 add_fixup (G, a->param[0], x86_jmp_forward (&G->f));
380 break;
381 case slang_asm_jump_if_zero:
382 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
383 x86_xor (&G->f, G->r_eax, G->r_eax);
384 x86_cmp (&G->f, G->r_eax, x86_make_disp (G->r_esp, -4));
385 {
386 GLubyte *lab0;
387
388 /* TODO: use jcc rel8 */
389 lab0 = x86_jcc_forward (&G->f, cc_NE);
390 add_fixup (G, a->param[0], x86_jmp_forward (&G->f));
391 x86_fixup_fwd_jump (&G->f, lab0);
392 }
393 break;
394 case slang_asm_enter:
395 /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */
396 assert (a->param[0] != 0);
397 x86_push (&G->f, G->r_ebp);
398 x86_lea (&G->f, G->r_ebp, x86_make_disp (G->r_esp, (GLint) a->param[0]));
399 break;
400 case slang_asm_leave:
401 x86_pop (&G->f, G->r_ebp);
402 break;
403 case slang_asm_local_alloc:
404 /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */
405 assert (a->param[0] != 0);
406 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, -(GLint) a->param[0]));
407 break;
408 case slang_asm_local_free:
409 /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */
410 assert (a->param[0] != 0);
411 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, (GLint) a->param[0]));
412 break;
413 case slang_asm_local_addr:
414 disp = -(GLint) (a->param[0] + a->param[1]) + 4;
415 if (disp != 0)
416 {
417 x86_lea (&G->f, G->r_eax, x86_make_disp (G->r_ebp, disp));
418 x86_push (&G->f, G->r_eax);
419 }
420 else
421 x86_push (&G->f, G->r_ebp);
422 break;
423 case slang_asm_global_addr:
424 /* TODO: use push imm32 */
425 x86_mov_reg_imm (&G->f, G->r_eax, (GLint) &G->mach->mem + a->param[0]);
426 x86_push (&G->f, G->r_eax);
427 break;
428 case slang_asm_call:
429 add_fixup (G, a->param[0], x86_call_forward (&G->f));
430 break;
431 case slang_asm_return:
432 x86_ret (&G->f);
433 break;
434 case slang_asm_discard:
435 x86_jmp (&G->f, G->l_discard);
436 break;
437 case slang_asm_exit:
438 x86_jmp (&G->f, G->l_exit);
439 break;
440 /* mesa-specific extensions */
441 case slang_asm_float_print:
442 x86_call (&G->f, (GLubyte *) do_print_float);
443 break;
444 case slang_asm_int_print:
445 x86_call (&G->f, (GLubyte *) do_print_int);
446 break;
447 case slang_asm_bool_print:
448 x86_call (&G->f, (GLubyte *) do_print_bool);
449 break;
450 default:
451 assert (0);
452 }
453 }
454
455 GLboolean _slang_x86_codegen (slang_machine *mach, slang_assembly_file *file, GLuint start)
456 {
457 codegen_ctx G;
458 GLubyte *j_body, *j_exit;
459 GLuint i;
460
461 /*
462 * We need as much as 1M because *all* assembly, including built-in library, is
463 * being translated to x86.
464 * The built-in library occupies 450K, so we can be safe for now.
465 * It is going to change in the future, when we get assembly analysis running.
466 */
467 x86_init_func_size (&G.f, 1048576);
468 G.r_eax = x86_make_reg (file_REG32, reg_AX);
469 G.r_ecx = x86_make_reg (file_REG32, reg_CX);
470 G.r_edx = x86_make_reg (file_REG32, reg_DX);
471 G.r_esp = x86_make_reg (file_REG32, reg_SP);
472 G.r_ebp = x86_make_reg (file_REG32, reg_BP);
473 G.r_st0 = x86_make_reg (file_x87, 0);
474 G.r_st1 = x86_make_reg (file_x87, 1);
475 G.r_st2 = x86_make_reg (file_x87, 2);
476 G.r_st3 = x86_make_reg (file_x87, 3);
477 G.fixups = NULL;
478 G.fixup_count = 0;
479 G.labels = (GLubyte **) slang_alloc_malloc (file->count * sizeof (GLubyte *));
480 G.mach = mach;
481 G.fpucntl = RESTORE_FPU;
482
483 mach->x86.fpucntl_rnd_neg = RND_NEG_FPU;
484 mach->x86.fpucntl_restore = RESTORE_FPU;
485
486 /* prepare stack and jump to start */
487 x86_push (&G.f, G.r_ebp);
488 x86_mov_reg_imm (&G.f, G.r_eax, (GLint) &mach->x86.esp_restore);
489 x86_push (&G.f, G.r_esp);
490 x86_pop (&G.f, G.r_ecx);
491 x86_mov (&G.f, x86_deref (G.r_eax), G.r_ecx);
492 j_body = x86_jmp_forward (&G.f);
493
494 /* "discard" instructions jump to this label */
495 G.l_discard = x86_get_label (&G.f);
496 x86_mov_reg_imm (&G.f, G.r_eax, (GLint) &G.mach->kill);
497 x86_mov_reg_imm (&G.f, G.r_ecx, 1);
498 x86_mov (&G.f, x86_deref (G.r_eax), G.r_ecx);
499 G.l_exit = x86_get_label (&G.f);
500 j_exit = x86_jmp_forward (&G.f);
501
502 for (i = 0; i < file->count; i++)
503 {
504 G.labels[i] = x86_get_label (&G.f);
505 if (i == start)
506 x86_fixup_fwd_jump (&G.f, j_body);
507 codegen_assem (&G, &file->code[i]);
508 }
509
510 /*
511 * Restore stack and return.
512 * This must be handled this way, because "discard" can be invoked from any
513 * place in the code.
514 */
515 x86_fixup_fwd_jump (&G.f, j_exit);
516 x86_mov_reg_imm (&G.f, G.r_eax, (GLint) &mach->x86.esp_restore);
517 x86_mov (&G.f, G.r_esp, x86_deref (G.r_eax));
518 x86_pop (&G.f, G.r_ebp);
519 if (G.fpucntl != RESTORE_FPU)
520 {
521 x87_fnclex (&G.f);
522 x86_mov_reg_imm (&G.f, G.r_eax, (GLint) &G.mach->x86.fpucntl_restore);
523 x87_fldcw (&G.f, x86_deref (G.r_eax));
524 }
525 x86_ret (&G.f);
526
527 /* fixup forward labels */
528 for (i = 0; i < G.fixup_count; i++)
529 {
530 G.f.csr = G.labels[G.fixups[i].index];
531 x86_fixup_fwd_jump (&G.f, G.fixups[i].csr);
532 }
533
534 slang_alloc_free (G.fixups);
535 slang_alloc_free (G.labels);
536
537 /* install new code */
538 if (mach->x86.compiled_func != NULL)
539 _mesa_exec_free (mach->x86.compiled_func);
540 mach->x86.compiled_func = (GLvoid (*) (slang_machine *)) x86_get_func (&G.f);
541
542 return GL_TRUE;
543 }
544
545 #endif
546