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 GLvoid
do_print_float (GLfloat x
)
117 _mesa_printf ("slang print: %f\n", x
);
120 static GLvoid
do_print_int (GLfloat x
)
122 _mesa_printf ("slang print: %d\n", (GLint
) x
);
125 static GLvoid
do_print_bool (GLfloat x
)
127 _mesa_printf ("slang print: %s\n", (GLint
) x
? "true" : "false");
130 static GLvoid
codegen_assem (codegen_ctx
*G
, slang_assembly
*a
)
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
);
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
);
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
);
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
);
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
));
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
));
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
));
189 case slang_asm_float_negate
:
190 x87_fld (&G
->f
, x86_deref (G
->r_esp
));
192 x87_fstp (&G
->f
, x86_deref (G
->r_esp
));
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
);
202 GLfloat one
= 1.0f
, zero
= 0.0f
;
203 GLubyte
*lab0
, *lab1
;
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
);
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
);
225 GLfloat one
= 1.0f
, zero
= 0.0f
;
226 GLubyte
*lab0
, *lab1
;
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
);
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
);
249 GLfloat one
= 1.0f
, zero
= 0.0f
;
250 GLubyte
*lab0
, *lab1
;
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
);
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
));
267 case slang_asm_float_sine
:
269 x86_call (&G
->f
, (GLubyte
*) _mesa_sinf
);
270 x87_fstp (&G
->f
, x86_deref (G
->r_esp
));
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
));
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
));
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));
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
));
290 case slang_asm_float_log2
:
292 x87_fld (&G
->f
, x86_deref (G
->r_esp
));
294 x87_fstp (&G
->f
, x86_deref (G
->r_esp
));
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
));
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
));
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
));
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
));
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
));
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
));
326 case slang_asm_int_to_float
:
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
));
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
);
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
);
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
);
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
);
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));
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));
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));
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));
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));
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));
377 add_fixup (G
, a
->param
[0], x86_jmp_forward (&G
->f
));
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));
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
);
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]));
398 case slang_asm_leave
:
399 x86_pop (&G
->f
, G
->r_ebp
);
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]));
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]));
411 case slang_asm_local_addr
:
412 disp
= -(GLint
) (a
->param
[0] + a
->param
[1]) + 4;
415 x86_lea (&G
->f
, G
->r_eax
, x86_make_disp (G
->r_ebp
, disp
));
416 x86_push (&G
->f
, G
->r_eax
);
419 x86_push (&G
->f
, G
->r_ebp
);
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
);
427 add_fixup (G
, a
->param
[0], x86_call_forward (&G
->f
));
429 case slang_asm_return
:
432 case slang_asm_discard
:
433 x86_jmp (&G
->f
, G
->l_discard
);
436 x86_jmp (&G
->f
, G
->l_exit
);
438 /* mesa-specific extensions */
439 case slang_asm_float_print
:
440 x86_call (&G
->f
, (GLubyte
*) do_print_float
);
442 case slang_asm_int_print
:
443 x86_call (&G
->f
, (GLubyte
*) do_print_int
);
445 case slang_asm_bool_print
:
446 x86_call (&G
->f
, (GLubyte
*) do_print_bool
);
453 GLboolean
_slang_x86_codegen (slang_machine
*mach
, slang_assembly_file
*file
, GLuint start
)
456 GLubyte
*j_body
, *j_exit
;
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.
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);
477 G
.labels
= (GLubyte
**) slang_alloc_malloc (file
->count
* sizeof (GLubyte
*));
479 G
.fpucntl
= RESTORE_FPU
;
481 mach
->x86
.fpucntl_rnd_neg
= RND_NEG_FPU
;
482 mach
->x86
.fpucntl_restore
= RESTORE_FPU
;
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
);
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
);
500 for (i
= 0; i
< file
->count
; i
++)
502 G
.labels
[i
] = x86_get_label (&G
.f
);
504 x86_fixup_fwd_jump (&G
.f
, j_body
);
505 codegen_assem (&G
, &file
->code
[i
]);
509 * Restore stack and return.
510 * This must be handled this way, because "discard" can be invoked from any
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
)
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
));
525 /* fixup forward labels */
526 for (i
= 0; i
< G
.fixup_count
; i
++)
528 G
.f
.csr
= G
.labels
[G
.fixups
[i
].index
];
529 x86_fixup_fwd_jump (&G
.f
, G
.fixups
[i
].csr
);
532 slang_alloc_free (G
.fixups
);
533 slang_alloc_free (G
.labels
);
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
);