⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slang_execute_x86.c

📁 mesa-6.5-minigui源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -