2 * Mesa 3-D graphics library
5 * Copyright (C) 2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 * \file slang_execute_x86.c
27 * x86 back end compiler
28 * \author Michal Krol, Keith Whitwell
32 #include "slang_execute.h"
33 #include "slang_library_noise.h"
34 #include "slang_library_texsample.h"
36 #if defined(USE_X86_ASM) || defined(SLANG_X86)
38 #include "x86/rtasm/x86sse.h"
48 struct x86_function f
;
67 static GLvoid
add_fixup (codegen_ctx
*G
, GLuint index
, GLubyte
*csr
)
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
;
77 #define RESTORE_FPU (DEFAULT_X86_FPU)
78 #define RND_NEG_FPU (DEFAULT_X86_FPU | 0x400)
80 #define RESTORE_FPU (FAST_X86_FPU)
81 #define RND_NEG_FPU (FAST_X86_FPU | 0x400)
84 static void set_fpu_round_neg_inf (codegen_ctx
*G
)
86 if (G
->fpucntl
!= RND_NEG_FPU
)
88 G
->fpucntl
= RND_NEG_FPU
;
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
));
95 static void emit_x87_ex2 (codegen_ctx
*G
)
97 set_fpu_round_neg_inf (G
);
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 */
110 static GLfloat
do_ceilf (GLfloat x
)
115 static GLfloat
do_floorf (GLfloat x
)
120 static GLvoid
do_print_float (GLfloat x
)
122 _mesa_printf ("slang print: %f\n", x
);
125 static GLvoid
do_print_int (GLfloat x
)
127 _mesa_printf ("slang print: %d\n", (GLint
) x
);
130 static GLvoid
do_print_bool (GLfloat x
)
132 _mesa_printf ("slang print: %s\n", (GLint
) x
? "true" : "false");
135 static GLvoid
codegen_assem (codegen_ctx
*G
, slang_assembly
*a
)
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
);
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
);
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
);
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
);
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
));
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
));
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
));
194 case slang_asm_float_negate
:
195 x87_fld (&G
->f
, x86_deref (G
->r_esp
));
197 x87_fstp (&G
->f
, x86_deref (G
->r_esp
));
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
);
207 GLfloat one
= 1.0f
, zero
= 0.0f
;
208 GLubyte
*lab0
, *lab1
;
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
);
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
);
230 GLfloat one
= 1.0f
, zero
= 0.0f
;
231 GLubyte
*lab0
, *lab1
;
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
);
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
);
254 GLfloat one
= 1.0f
, zero
= 0.0f
;
255 GLubyte
*lab0
, *lab1
;
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
);
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
));
272 case slang_asm_float_sine
:
274 x86_call (&G
->f
, (GLubyte
*) _mesa_sinf
);
275 x87_fstp (&G
->f
, x86_deref (G
->r_esp
));
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
));
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
));
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));
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
));
295 case slang_asm_float_log2
:
297 x87_fld (&G
->f
, x86_deref (G
->r_esp
));
299 x87_fstp (&G
->f
, x86_deref (G
->r_esp
));
301 case slang_asm_float_floor
:
302 x86_call (&G
->f
, (GLubyte
*) do_floorf
);
303 x87_fstp (&G
->f
, x86_deref (G
->r_esp
));
305 case slang_asm_float_ceil
:
306 x86_call (&G
->f
, (GLubyte
*) do_ceilf
);
307 x87_fstp (&G
->f
, x86_deref (G
->r_esp
));
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
));
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
));
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
));
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
));
328 case slang_asm_int_to_float
:
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
));
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
);
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
);
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
);
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
);
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));
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));
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));
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));
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));
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));
379 add_fixup (G
, a
->param
[0], x86_jmp_forward (&G
->f
));
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));
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
);
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]));
400 case slang_asm_leave
:
401 x86_pop (&G
->f
, G
->r_ebp
);
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]));
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]));
413 case slang_asm_local_addr
:
414 disp
= -(GLint
) (a
->param
[0] + a
->param
[1]) + 4;
417 x86_lea (&G
->f
, G
->r_eax
, x86_make_disp (G
->r_ebp
, disp
));
418 x86_push (&G
->f
, G
->r_eax
);
421 x86_push (&G
->f
, G
->r_ebp
);
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
);
429 add_fixup (G
, a
->param
[0], x86_call_forward (&G
->f
));
431 case slang_asm_return
:
434 case slang_asm_discard
:
435 x86_jmp (&G
->f
, G
->l_discard
);
438 x86_jmp (&G
->f
, G
->l_exit
);
440 /* mesa-specific extensions */
441 case slang_asm_float_print
:
442 x86_call (&G
->f
, (GLubyte
*) do_print_float
);
444 case slang_asm_int_print
:
445 x86_call (&G
->f
, (GLubyte
*) do_print_int
);
447 case slang_asm_bool_print
:
448 x86_call (&G
->f
, (GLubyte
*) do_print_bool
);
455 GLboolean
_slang_x86_codegen (slang_machine
*mach
, slang_assembly_file
*file
, GLuint start
)
458 GLubyte
*j_body
, *j_exit
;
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.
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);
479 G
.labels
= (GLubyte
**) slang_alloc_malloc (file
->count
* sizeof (GLubyte
*));
481 G
.fpucntl
= RESTORE_FPU
;
483 mach
->x86
.fpucntl_rnd_neg
= RND_NEG_FPU
;
484 mach
->x86
.fpucntl_restore
= RESTORE_FPU
;
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
);
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
);
502 for (i
= 0; i
< file
->count
; i
++)
504 G
.labels
[i
] = x86_get_label (&G
.f
);
506 x86_fixup_fwd_jump (&G
.f
, j_body
);
507 codegen_assem (&G
, &file
->code
[i
]);
511 * Restore stack and return.
512 * This must be handled this way, because "discard" can be invoked from any
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
)
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
));
527 /* fixup forward labels */
528 for (i
= 0; i
< G
.fixup_count
; i
++)
530 G
.f
.csr
= G
.labels
[G
.fixups
[i
].index
];
531 x86_fixup_fwd_jump (&G
.f
, G
.fixups
[i
].csr
);
534 slang_alloc_free (G
.fixups
);
535 slang_alloc_free (G
.labels
);
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
);