More GLSL code:
[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 GLvoid do_print_float (GLfloat x)
116 {
117 _mesa_printf ("slang print: %f\n", x);
118 }
119
120 static GLvoid do_print_int (GLfloat x)
121 {
122 _mesa_printf ("slang print: %d\n", (GLint) x);
123 }
124
125 static GLvoid do_print_bool (GLfloat x)
126 {
127 _mesa_printf ("slang print: %s\n", (GLint) x ? "true" : "false");
128 }
129
130 static GLvoid codegen_assem (codegen_ctx *G, slang_assembly *a)
131 {
132 GLint disp;
133
134 switch (a->type)
135 {
136 case slang_asm_none:
137 break;
138 case slang_asm_float_copy:
139 case slang_asm_int_copy:
140 case slang_asm_bool_copy:
141 x86_mov (&G->f, G->r_eax, x86_make_disp (G->r_esp, a->param[0]));
142 x86_pop (&G->f, G->r_ecx);
143 x86_mov (&G->f, x86_make_disp (G->r_eax, a->param[1]), G->r_ecx);
144 break;
145 case slang_asm_float_move:
146 case slang_asm_int_move:
147 case slang_asm_bool_move:
148 x86_lea (&G->f, G->r_eax, x86_make_disp (G->r_esp, a->param[1]));
149 x86_add (&G->f, G->r_eax, x86_deref (G->r_esp));
150 x86_mov (&G->f, G->r_eax, x86_deref (G->r_eax));
151 x86_mov (&G->f, x86_make_disp (G->r_esp, a->param[0]), G->r_eax);
152 break;
153 case slang_asm_float_push:
154 case slang_asm_int_push:
155 case slang_asm_bool_push:
156 /* TODO: use push imm32 */
157 x86_mov_reg_imm (&G->f, G->r_eax, *((GLint *) &a->literal));
158 x86_push (&G->f, G->r_eax);
159 break;
160 case slang_asm_float_deref:
161 case slang_asm_int_deref:
162 case slang_asm_bool_deref:
163 case slang_asm_addr_deref:
164 x86_mov (&G->f, G->r_eax, x86_deref (G->r_esp));
165 x86_mov (&G->f, G->r_eax, x86_deref (G->r_eax));
166 x86_mov (&G->f, x86_deref (G->r_esp), G->r_eax);
167 break;
168 case slang_asm_float_add:
169 x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
170 x87_fld (&G->f, x86_deref (G->r_esp));
171 x87_faddp (&G->f, G->r_st1);
172 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
173 x87_fstp (&G->f, x86_deref (G->r_esp));
174 break;
175 case slang_asm_float_multiply:
176 x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
177 x87_fld (&G->f, x86_deref (G->r_esp));
178 x87_fmulp (&G->f, G->r_st1);
179 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
180 x87_fstp (&G->f, x86_deref (G->r_esp));
181 break;
182 case slang_asm_float_divide:
183 x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
184 x87_fld (&G->f, x86_deref (G->r_esp));
185 x87_fdivp (&G->f, G->r_st1);
186 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
187 x87_fstp (&G->f, x86_deref (G->r_esp));
188 break;
189 case slang_asm_float_negate:
190 x87_fld (&G->f, x86_deref (G->r_esp));
191 x87_fchs (&G->f);
192 x87_fstp (&G->f, x86_deref (G->r_esp));
193 break;
194 case slang_asm_float_less:
195 x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
196 x87_fcomp (&G->f, x86_deref (G->r_esp));
197 x87_fnstsw (&G->f, G->r_eax);
198 /* TODO: use test r8,imm8 */
199 x86_mov_reg_imm (&G->f, G->r_ecx, 0x100);
200 x86_test (&G->f, G->r_eax, G->r_ecx);
201 {
202 GLfloat one = 1.0f, zero = 0.0f;
203 GLubyte *lab0, *lab1;
204
205 /* TODO: use jcc rel8 */
206 lab0 = x86_jcc_forward (&G->f, cc_E);
207 x86_mov_reg_imm (&G->f, G->r_ecx, *((GLint *) &one));
208 /* TODO: use jmp rel8 */
209 lab1 = x86_jmp_forward (&G->f);
210 x86_fixup_fwd_jump (&G->f, lab0);
211 x86_mov_reg_imm (&G->f, G->r_ecx, *((GLint *) &zero));
212 x86_fixup_fwd_jump (&G->f, lab1);
213 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
214 x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx);
215 }
216 break;
217 case slang_asm_float_equal_exp:
218 x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
219 x87_fcomp (&G->f, x86_deref (G->r_esp));
220 x87_fnstsw (&G->f, G->r_eax);
221 /* TODO: use test r8,imm8 */
222 x86_mov_reg_imm (&G->f, G->r_ecx, 0x4000);
223 x86_test (&G->f, G->r_eax, G->r_ecx);
224 {
225 GLfloat one = 1.0f, zero = 0.0f;
226 GLubyte *lab0, *lab1;
227
228 /* TODO: use jcc rel8 */
229 lab0 = x86_jcc_forward (&G->f, cc_E);
230 x86_mov_reg_imm (&G->f, G->r_ecx, *((GLint *) &one));
231 /* TODO: use jmp rel8 */
232 lab1 = x86_jmp_forward (&G->f);
233 x86_fixup_fwd_jump (&G->f, lab0);
234 x86_mov_reg_imm (&G->f, G->r_ecx, *((GLint *) &zero));
235 x86_fixup_fwd_jump (&G->f, lab1);
236 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
237 x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx);
238 }
239 break;
240 case slang_asm_float_equal_int:
241 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, -4));
242 x87_fld (&G->f, x86_make_disp (G->r_esp, a->param[0] + 4));
243 x87_fcomp (&G->f, x86_make_disp (G->r_esp, a->param[1] + 4));
244 x87_fnstsw (&G->f, G->r_eax);
245 /* TODO: use test r8,imm8 */
246 x86_mov_reg_imm (&G->f, G->r_ecx, 0x4000);
247 x86_test (&G->f, G->r_eax, G->r_ecx);
248 {
249 GLfloat one = 1.0f, zero = 0.0f;
250 GLubyte *lab0, *lab1;
251
252 /* TODO: use jcc rel8 */
253 lab0 = x86_jcc_forward (&G->f, cc_E);
254 x86_mov_reg_imm (&G->f, G->r_ecx, *((GLint *) &one));
255 /* TODO: use jmp rel8 */
256 lab1 = x86_jmp_forward (&G->f);
257 x86_fixup_fwd_jump (&G->f, lab0);
258 x86_mov_reg_imm (&G->f, G->r_ecx, *((GLint *) &zero));
259 x86_fixup_fwd_jump (&G->f, lab1);
260 x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx);
261 }
262 break;
263 case slang_asm_float_to_int:
264 x87_fld (&G->f, x86_deref (G->r_esp));
265 x87_fistp (&G->f, x86_deref (G->r_esp));
266 break;
267 case slang_asm_float_sine:
268 /* TODO: use fsin */
269 x86_call (&G->f, (GLubyte *) _mesa_sinf);
270 x87_fstp (&G->f, x86_deref (G->r_esp));
271 break;
272 case slang_asm_float_arcsine:
273 /* TODO: use fpatan (?) */
274 x86_call (&G->f, (GLubyte *) _mesa_asinf);
275 x87_fstp (&G->f, x86_deref (G->r_esp));
276 break;
277 case slang_asm_float_arctan:
278 /* TODO: use fpatan */
279 x86_call (&G->f, (GLubyte *) _mesa_atanf);
280 x87_fstp (&G->f, x86_deref (G->r_esp));
281 break;
282 case slang_asm_float_power:
283 x87_fld (&G->f, x86_deref (G->r_esp));
284 x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
285 x87_fyl2x (&G->f);
286 emit_x87_ex2 (G);
287 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
288 x87_fstp (&G->f, x86_deref (G->r_esp));
289 break;
290 case slang_asm_float_log2:
291 x87_fld1 (&G->f);
292 x87_fld (&G->f, x86_deref (G->r_esp));
293 x87_fyl2x (&G->f);
294 x87_fstp (&G->f, x86_deref (G->r_esp));
295 break;
296 case slang_asm_float_floor:
297 set_fpu_round_neg_inf (G);
298 x87_fld (&G->f, x86_deref (G->r_esp));
299 x87_fprndint (&G->f);
300 x87_fstp (&G->f, x86_deref (G->r_esp));
301 break;
302 case slang_asm_float_ceil:
303 /* TODO: use frndint */
304 x86_call (&G->f, (GLubyte *) do_ceilf);
305 x87_fstp (&G->f, x86_deref (G->r_esp));
306 break;
307 case slang_asm_float_noise1:
308 x86_call (&G->f, (GLubyte *) _slang_library_noise1);
309 x87_fstp (&G->f, x86_deref (G->r_esp));
310 break;
311 case slang_asm_float_noise2:
312 x86_call (&G->f, (GLubyte *) _slang_library_noise2);
313 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
314 x87_fstp (&G->f, x86_deref (G->r_esp));
315 break;
316 case slang_asm_float_noise3:
317 x86_call (&G->f, (GLubyte *) _slang_library_noise4);
318 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 8));
319 x87_fstp (&G->f, x86_deref (G->r_esp));
320 break;
321 case slang_asm_float_noise4:
322 x86_call (&G->f, (GLubyte *) _slang_library_noise4);
323 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 12));
324 x87_fstp (&G->f, x86_deref (G->r_esp));
325 break;
326 case slang_asm_int_to_float:
327 break;
328 case slang_asm_int_to_addr:
329 x87_fld (&G->f, x86_deref (G->r_esp));
330 x87_fistp (&G->f, x86_deref (G->r_esp));
331 break;
332 case slang_asm_addr_copy:
333 x86_pop (&G->f, G->r_eax);
334 x86_mov (&G->f, G->r_ecx, x86_deref (G->r_esp));
335 x86_mov (&G->f, x86_deref (G->r_ecx), G->r_eax);
336 break;
337 case slang_asm_addr_push:
338 /* TODO: use push imm32 */
339 x86_mov_reg_imm (&G->f, G->r_eax, (GLint) a->param[0]);
340 x86_push (&G->f, G->r_eax);
341 break;
342 case slang_asm_addr_add:
343 x86_pop (&G->f, G->r_eax);
344 x86_add (&G->f, x86_deref (G->r_esp), G->r_eax);
345 break;
346 case slang_asm_addr_multiply:
347 x86_pop (&G->f, G->r_ecx);
348 x86_mov (&G->f, G->r_eax, x86_deref (G->r_esp));
349 x86_mul (&G->f, G->r_ecx);
350 x86_mov (&G->f, x86_deref (G->r_esp), G->r_eax);
351 break;
352 case slang_asm_vec4_tex1d:
353 x86_call (&G->f, (GLubyte *) _slang_library_tex1d);
354 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 12));
355 break;
356 case slang_asm_vec4_tex2d:
357 x86_call (&G->f, (GLubyte *) _slang_library_tex2d);
358 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 16));
359 break;
360 case slang_asm_vec4_tex3d:
361 x86_call (&G->f, (GLubyte *) _slang_library_tex3d);
362 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 20));
363 break;
364 case slang_asm_vec4_texcube:
365 x86_call (&G->f, (GLubyte *) _slang_library_texcube);
366 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 20));
367 break;
368 case slang_asm_vec4_shad1d:
369 x86_call (&G->f, (GLubyte *) _slang_library_shad1d);
370 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 20));
371 break;
372 case slang_asm_vec4_shad2d:
373 x86_call (&G->f, (GLubyte *) _slang_library_shad2d);
374 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 20));
375 break;
376 case slang_asm_jump:
377 add_fixup (G, a->param[0], x86_jmp_forward (&G->f));
378 break;
379 case slang_asm_jump_if_zero:
380 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
381 x86_xor (&G->f, G->r_eax, G->r_eax);
382 x86_cmp (&G->f, G->r_eax, x86_make_disp (G->r_esp, -4));
383 {
384 GLubyte *lab0;
385
386 /* TODO: use jcc rel8 */
387 lab0 = x86_jcc_forward (&G->f, cc_NE);
388 add_fixup (G, a->param[0], x86_jmp_forward (&G->f));
389 x86_fixup_fwd_jump (&G->f, lab0);
390 }
391 break;
392 case slang_asm_enter:
393 /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */
394 assert (a->param[0] != 0);
395 x86_push (&G->f, G->r_ebp);
396 x86_lea (&G->f, G->r_ebp, x86_make_disp (G->r_esp, (GLint) a->param[0]));
397 break;
398 case slang_asm_leave:
399 x86_pop (&G->f, G->r_ebp);
400 break;
401 case slang_asm_local_alloc:
402 /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */
403 assert (a->param[0] != 0);
404 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, -(GLint) a->param[0]));
405 break;
406 case slang_asm_local_free:
407 /* FIXME: x86_make_disp(esp, 0) + x86_lea() generates bogus code */
408 assert (a->param[0] != 0);
409 x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, (GLint) a->param[0]));
410 break;
411 case slang_asm_local_addr:
412 disp = -(GLint) (a->param[0] + a->param[1]) + 4;
413 if (disp != 0)
414 {
415 x86_lea (&G->f, G->r_eax, x86_make_disp (G->r_ebp, disp));
416 x86_push (&G->f, G->r_eax);
417 }
418 else
419 x86_push (&G->f, G->r_ebp);
420 break;
421 case slang_asm_global_addr:
422 /* TODO: use push imm32 */
423 x86_mov_reg_imm (&G->f, G->r_eax, (GLint) &G->mach->mem + a->param[0]);
424 x86_push (&G->f, G->r_eax);
425 break;
426 case slang_asm_call:
427 add_fixup (G, a->param[0], x86_call_forward (&G->f));
428 break;
429 case slang_asm_return:
430 x86_ret (&G->f);
431 break;
432 case slang_asm_discard:
433 x86_jmp (&G->f, G->l_discard);
434 break;
435 case slang_asm_exit:
436 x86_jmp (&G->f, G->l_exit);
437 break;
438 /* mesa-specific extensions */
439 case slang_asm_float_print:
440 x86_call (&G->f, (GLubyte *) do_print_float);
441 break;
442 case slang_asm_int_print:
443 x86_call (&G->f, (GLubyte *) do_print_int);
444 break;
445 case slang_asm_bool_print:
446 x86_call (&G->f, (GLubyte *) do_print_bool);
447 break;
448 default:
449 assert (0);
450 }
451 }
452
453 GLboolean _slang_x86_codegen (slang_machine *mach, slang_assembly_file *file, GLuint start)
454 {
455 codegen_ctx G;
456 GLubyte *j_body, *j_exit;
457 GLuint i;
458
459 /*
460 * We need as much as 1M because *all* assembly, including built-in library, is
461 * being translated to x86.
462 * The built-in library occupies 450K, so we can be safe for now.
463 * It is going to change in the future, when we get assembly analysis running.
464 */
465 x86_init_func_size (&G.f, 1048576);
466 G.r_eax = x86_make_reg (file_REG32, reg_AX);
467 G.r_ecx = x86_make_reg (file_REG32, reg_CX);
468 G.r_edx = x86_make_reg (file_REG32, reg_DX);
469 G.r_esp = x86_make_reg (file_REG32, reg_SP);
470 G.r_ebp = x86_make_reg (file_REG32, reg_BP);
471 G.r_st0 = x86_make_reg (file_x87, 0);
472 G.r_st1 = x86_make_reg (file_x87, 1);
473 G.r_st2 = x86_make_reg (file_x87, 2);
474 G.r_st3 = x86_make_reg (file_x87, 3);
475 G.fixups = NULL;
476 G.fixup_count = 0;
477 G.labels = (GLubyte **) slang_alloc_malloc (file->count * sizeof (GLubyte *));
478 G.mach = mach;
479 G.fpucntl = RESTORE_FPU;
480
481 mach->x86.fpucntl_rnd_neg = RND_NEG_FPU;
482 mach->x86.fpucntl_restore = RESTORE_FPU;
483
484 /* prepare stack and jump to start */
485 x86_push (&G.f, G.r_ebp);
486 x86_mov_reg_imm (&G.f, G.r_eax, (GLint) &mach->x86.esp_restore);
487 x86_push (&G.f, G.r_esp);
488 x86_pop (&G.f, G.r_ecx);
489 x86_mov (&G.f, x86_deref (G.r_eax), G.r_ecx);
490 j_body = x86_jmp_forward (&G.f);
491
492 /* "discard" instructions jump to this label */
493 G.l_discard = x86_get_label (&G.f);
494 x86_mov_reg_imm (&G.f, G.r_eax, (GLint) &G.mach->kill);
495 x86_mov_reg_imm (&G.f, G.r_ecx, 1);
496 x86_mov (&G.f, x86_deref (G.r_eax), G.r_ecx);
497 G.l_exit = x86_get_label (&G.f);
498 j_exit = x86_jmp_forward (&G.f);
499
500 for (i = 0; i < file->count; i++)
501 {
502 G.labels[i] = x86_get_label (&G.f);
503 if (i == start)
504 x86_fixup_fwd_jump (&G.f, j_body);
505 codegen_assem (&G, &file->code[i]);
506 }
507
508 /*
509 * Restore stack and return.
510 * This must be handled this way, because "discard" can be invoked from any
511 * place in the code.
512 */
513 x86_fixup_fwd_jump (&G.f, j_exit);
514 x86_mov_reg_imm (&G.f, G.r_eax, (GLint) &mach->x86.esp_restore);
515 x86_mov (&G.f, G.r_esp, x86_deref (G.r_eax));
516 x86_pop (&G.f, G.r_ebp);
517 if (G.fpucntl != RESTORE_FPU)
518 {
519 x87_fnclex (&G.f);
520 x86_mov_reg_imm (&G.f, G.r_eax, (GLint) &G.mach->x86.fpucntl_restore);
521 x87_fldcw (&G.f, x86_deref (G.r_eax));
522 }
523 x86_ret (&G.f);
524
525 /* fixup forward labels */
526 for (i = 0; i < G.fixup_count; i++)
527 {
528 G.f.csr = G.labels[G.fixups[i].index];
529 x86_fixup_fwd_jump (&G.f, G.fixups[i].csr);
530 }
531
532 slang_alloc_free (G.fixups);
533 slang_alloc_free (G.labels);
534
535 /* install new code */
536 if (mach->x86.compiled_func != NULL)
537 _mesa_exec_free (mach->x86.compiled_func);
538 mach->x86.compiled_func = (GLvoid (*) (slang_machine *)) x86_get_func (&G.f);
539
540 return GL_TRUE;
541 }
542
543 #endif
544