📄 slang_execute_x86.c
字号:
/*
* Mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* \file slang_execute_x86.c
* x86 back end compiler
* \author Michal Krol, Keith Whitwell
*/
#include "imports.h"
#include "slang_execute.h"
#include "slang_library_noise.h"
#include "slang_library_texsample.h"
#if defined(USE_X86_ASM) || defined(SLANG_X86)
#include "x86/rtasm/x86sse.h"
typedef struct
{
GLuint index;
GLubyte *csr;
} fixup;
typedef struct
{
struct x86_function f;
struct x86_reg r_eax;
struct x86_reg r_ecx;
struct x86_reg r_edx;
struct x86_reg r_esp;
struct x86_reg r_ebp;
struct x86_reg r_st0;
struct x86_reg r_st1;
struct x86_reg r_st2;
struct x86_reg r_st3;
fixup *fixups;
GLuint fixup_count;
GLubyte **labels;
slang_machine *mach;
GLubyte *l_discard;
GLubyte *l_exit;
GLshort fpucntl;
} codegen_ctx;
static GLvoid add_fixup (codegen_ctx *G, GLuint index, GLubyte *csr)
{
G->fixups = (fixup *) slang_alloc_realloc (G->fixups, G->fixup_count * sizeof (fixup),
(G->fixup_count + 1) * sizeof (fixup));
G->fixups[G->fixup_count].index = index;
G->fixups[G->fixup_count].csr = csr;
G->fixup_count++;
}
#ifdef NO_FAST_MATH
#define RESTORE_FPU (DEFAULT_X86_FPU)
#define RND_NEG_FPU (DEFAULT_X86_FPU | 0x400)
#else
#define RESTORE_FPU (FAST_X86_FPU)
#define RND_NEG_FPU (FAST_X86_FPU | 0x400)
#endif
static void set_fpu_round_neg_inf (codegen_ctx *G)
{
if (G->fpucntl != RND_NEG_FPU)
{
G->fpucntl = RND_NEG_FPU;
x87_fnclex (&G->f);
x86_mov_reg_imm (&G->f, G->r_eax, (GLint) &G->mach->x86.fpucntl_rnd_neg);
x87_fldcw (&G->f, x86_deref (G->r_eax));
}
}
static void emit_x87_ex2 (codegen_ctx *G)
{
set_fpu_round_neg_inf (G);
x87_fld (&G->f, G->r_st0); /* a a */
x87_fprndint (&G->f); /* int(a) a */
x87_fld (&G->f, G->r_st0); /* int(a) int(a) a */
x87_fstp (&G->f, G->r_st3); /* int(a) a int(a)*/
x87_fsubp (&G->f, G->r_st1);/* frac(a) int(a) */
x87_f2xm1 (&G->f); /* (2^frac(a))-1 int(a)*/
x87_fld1 (&G->f); /* 1 (2^frac(a))-1 int(a)*/
x87_faddp (&G->f, G->r_st1);/* 2^frac(a) int(a) */
x87_fscale (&G->f); /* 2^a */
}
static GLfloat do_ceilf (GLfloat x)
{
return CEILF (x);
}
static GLfloat do_floorf (GLfloat x)
{
return FLOORF (x);
}
static GLvoid do_print_float (GLfloat x)
{
_mesa_printf ("slang print: %f\n", x);
}
static GLvoid do_print_int (GLfloat x)
{
_mesa_printf ("slang print: %d\n", (GLint) x);
}
static GLvoid do_print_bool (GLfloat x)
{
_mesa_printf ("slang print: %s\n", (GLint) x ? "true" : "false");
}
#define FLOAT_ONE 0x3f800000
#define FLOAT_ZERO 0
static GLvoid codegen_assem (codegen_ctx *G, slang_assembly *a)
{
GLint disp;
switch (a->type)
{
case slang_asm_none:
break;
case slang_asm_float_copy:
case slang_asm_int_copy:
case slang_asm_bool_copy:
x86_mov (&G->f, G->r_eax, x86_make_disp (G->r_esp, a->param[0]));
x86_pop (&G->f, G->r_ecx);
x86_mov (&G->f, x86_make_disp (G->r_eax, a->param[1]), G->r_ecx);
break;
case slang_asm_float_move:
case slang_asm_int_move:
case slang_asm_bool_move:
x86_lea (&G->f, G->r_eax, x86_make_disp (G->r_esp, a->param[1]));
x86_add (&G->f, G->r_eax, x86_deref (G->r_esp));
x86_mov (&G->f, G->r_eax, x86_deref (G->r_eax));
x86_mov (&G->f, x86_make_disp (G->r_esp, a->param[0]), G->r_eax);
break;
case slang_asm_float_push:
case slang_asm_int_push:
case slang_asm_bool_push:
/* TODO: use push imm32 */
x86_mov_reg_imm (&G->f, G->r_eax, *((GLint *) &a->literal));
x86_push (&G->f, G->r_eax);
break;
case slang_asm_float_deref:
case slang_asm_int_deref:
case slang_asm_bool_deref:
case slang_asm_addr_deref:
x86_mov (&G->f, G->r_eax, x86_deref (G->r_esp));
x86_mov (&G->f, G->r_eax, x86_deref (G->r_eax));
x86_mov (&G->f, x86_deref (G->r_esp), G->r_eax);
break;
case slang_asm_float_add:
x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
x87_fld (&G->f, x86_deref (G->r_esp));
x87_faddp (&G->f, G->r_st1);
x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
x87_fstp (&G->f, x86_deref (G->r_esp));
break;
case slang_asm_float_multiply:
x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
x87_fld (&G->f, x86_deref (G->r_esp));
x87_fmulp (&G->f, G->r_st1);
x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
x87_fstp (&G->f, x86_deref (G->r_esp));
break;
case slang_asm_float_divide:
x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
x87_fld (&G->f, x86_deref (G->r_esp));
x87_fdivp (&G->f, G->r_st1);
x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
x87_fstp (&G->f, x86_deref (G->r_esp));
break;
case slang_asm_float_negate:
x87_fld (&G->f, x86_deref (G->r_esp));
x87_fchs (&G->f);
x87_fstp (&G->f, x86_deref (G->r_esp));
break;
case slang_asm_float_less:
x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
x87_fcomp (&G->f, x86_deref (G->r_esp));
x87_fnstsw (&G->f, G->r_eax);
/* TODO: use test r8,imm8 */
x86_mov_reg_imm (&G->f, G->r_ecx, 0x100);
x86_test (&G->f, G->r_eax, G->r_ecx);
{
GLubyte *lab0, *lab1;
/* TODO: use jcc rel8 */
lab0 = x86_jcc_forward (&G->f, cc_E);
x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ONE);
/* TODO: use jmp rel8 */
lab1 = x86_jmp_forward (&G->f);
x86_fixup_fwd_jump (&G->f, lab0);
x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ZERO);
x86_fixup_fwd_jump (&G->f, lab1);
x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx);
}
break;
case slang_asm_float_equal_exp:
x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
x87_fcomp (&G->f, x86_deref (G->r_esp));
x87_fnstsw (&G->f, G->r_eax);
/* TODO: use test r8,imm8 */
x86_mov_reg_imm (&G->f, G->r_ecx, 0x4000);
x86_test (&G->f, G->r_eax, G->r_ecx);
{
GLubyte *lab0, *lab1;
/* TODO: use jcc rel8 */
lab0 = x86_jcc_forward (&G->f, cc_E);
x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ONE);
/* TODO: use jmp rel8 */
lab1 = x86_jmp_forward (&G->f);
x86_fixup_fwd_jump (&G->f, lab0);
x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ZERO);
x86_fixup_fwd_jump (&G->f, lab1);
x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx);
}
break;
case slang_asm_float_equal_int:
x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, -4));
x87_fld (&G->f, x86_make_disp (G->r_esp, a->param[0] + 4));
x87_fcomp (&G->f, x86_make_disp (G->r_esp, a->param[1] + 4));
x87_fnstsw (&G->f, G->r_eax);
/* TODO: use test r8,imm8 */
x86_mov_reg_imm (&G->f, G->r_ecx, 0x4000);
x86_test (&G->f, G->r_eax, G->r_ecx);
{
GLubyte *lab0, *lab1;
/* TODO: use jcc rel8 */
lab0 = x86_jcc_forward (&G->f, cc_E);
x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ONE);
/* TODO: use jmp rel8 */
lab1 = x86_jmp_forward (&G->f);
x86_fixup_fwd_jump (&G->f, lab0);
x86_mov_reg_imm (&G->f, G->r_ecx, FLOAT_ZERO);
x86_fixup_fwd_jump (&G->f, lab1);
x86_mov (&G->f, x86_deref (G->r_esp), G->r_ecx);
}
break;
case slang_asm_float_to_int:
x87_fld (&G->f, x86_deref (G->r_esp));
x87_fistp (&G->f, x86_deref (G->r_esp));
break;
case slang_asm_float_sine:
/* TODO: use fsin */
x86_call (&G->f, (GLubyte *) _mesa_sinf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -