* Keith Whitwell <keithw@tungstengraphics.com>
*/
-#include "glheader.h"
-#include "context.h"
-#include "colormac.h"
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/simple_list.h"
+#include "main/enums.h"
#include "t_context.h"
#include "t_vertex.h"
-#include "simple_list.h"
-#include "enums.h"
#if defined(USE_SSE_ASM)
#include "x86/common_x86_asm.h"
+/**
+ * Number of bytes to allocate for generated SSE functions
+ */
+#define MAX_SSE_CODE_SIZE 1024
+
+
#define X 0
#define Y 1
#define Z 2
struct x86_program {
struct x86_function func;
- GLcontext *ctx;
+ struct gl_context *ctx;
GLboolean inputs_safe;
GLboolean outputs_safe;
GLboolean have_sse2;
* a b c 1
*/
sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
- sse_shufps(&p->func, dest, get_identity(p), X,Y,Z,W );
- sse_shufps(&p->func, dest, dest, Y,Z,X,W );
+ sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
+ sse_shufps(&p->func, dest, dest, SHUF(Y,Z,X,W) );
sse_movlps(&p->func, dest, arg0);
}
{
/* Pull in low word, then swizzle in identity */
sse_movss(&p->func, dest, arg0);
- sse_shufps(&p->func, dest, get_identity(p), X,Y,Z,W );
+ sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
}
* a b c c
*/
sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
- sse_shufps(&p->func, dest, dest, X,X,X,X);
+ sse_shufps(&p->func, dest, dest, SHUF(X,X,X,X));
sse_movlps(&p->func, dest, arg0);
}
}
struct x86_reg dest,
struct x86_reg arg0 )
{
- emit_load4f_1(p, dest, arg0);
+ /* Loading from memory erases the upper bits. */
+ sse_movss(&p->func, dest, arg0);
}
static void emit_load2f_2( struct x86_program *p,
struct x86_reg dest,
struct x86_reg arg0 )
{
- emit_load4f_1(p, dest, arg0);
+ /* Loading from memory erases the upper bits. */
+ sse_movss(&p->func, dest, arg0);
}
static void emit_load1f_1( struct x86_program *p,
/* Alternate strategy - emit two, shuffle, emit one.
*/
sse_movlps(&p->func, dest, arg0);
- sse_shufps(&p->func, arg0, arg0, Z, Z, Z, Z ); /* NOTE! destructive */
+ sse_shufps(&p->func, arg0, arg0, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */
sse_movss(&p->func, x86_make_disp(dest,8), arg0);
}
}
*/
static GLboolean build_vertex_emit( struct x86_program *p )
{
- GLcontext *ctx = p->ctx;
+ struct gl_context *ctx = p->ctx;
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
GLuint j = 0;
struct x86_reg temp = x86_make_reg(file_XMM, 0);
struct x86_reg vp0 = x86_make_reg(file_XMM, 1);
struct x86_reg vp1 = x86_make_reg(file_XMM, 2);
+ struct x86_reg temp2 = x86_make_reg(file_XMM, 3);
GLubyte *fixup, *label;
- x86_init_func(&p->func);
-
/* Push a few regs?
*/
x86_push(&p->func, countEBP);
case EMIT_3F_XYW:
get_src_ptr(p, srcECX, vtxESI, a);
emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
- sse_shufps(&p->func, temp, temp, X, Y, W, Z);
+ sse_shufps(&p->func, temp, temp, SHUF(X,Y,W,Z));
emit_store(p, dest, 3, temp);
update_src_ptr(p, srcECX, vtxESI, a);
break;
{
get_src_ptr(p, srcECX, vtxESI, a);
emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize);
- sse_shufps(&p->func, temp, temp, X, X, X, X);
+ sse_shufps(&p->func, temp, temp, SHUF(X,X,X,X));
emit_pack_store_4ub(p, x86_make_disp(dest, -3), temp); /* overkill! */
update_src_ptr(p, srcECX, vtxESI, a);
}
else {
- _mesa_printf("Can't emit 1ub %x %x %d\n", a->vertoffset, a[-1].vertoffset, a[-1].vertattrsize );
+ printf("Can't emit 1ub %x %x %d\n", a->vertoffset, a[-1].vertoffset, a[-1].vertattrsize );
return GL_FALSE;
}
break;
get_src_ptr(p, srcECX, vtxESI, a);
emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
if (a->format == EMIT_3UB_3F_BGR)
- sse_shufps(&p->func, temp, temp, Z, Y, X, W);
+ sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
emit_pack_store_4ub(p, dest, temp);
update_src_ptr(p, srcECX, vtxESI, a);
}
/* Make room for incoming value:
*/
- sse_shufps(&p->func, temp, temp, W, X, Y, Z);
+ sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
get_src_ptr(p, srcECX, vtxESI, &a[1]);
- emit_load(p, temp, 1, x86_deref(srcECX), a[1].inputsize);
+ emit_load(p, temp2, 1, x86_deref(srcECX), a[1].inputsize);
+ sse_movss(&p->func, temp, temp2);
update_src_ptr(p, srcECX, vtxESI, &a[1]);
/* Rearrange and possibly do BGR conversion:
*/
if (a->format == EMIT_3UB_3F_BGR)
- sse_shufps(&p->func, temp, temp, W, Z, Y, X);
+ sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
else
- sse_shufps(&p->func, temp, temp, Y, Z, W, X);
+ sse_shufps(&p->func, temp, temp, SHUF(Y,Z,W,X));
emit_pack_store_4ub(p, dest, temp);
j++; /* NOTE: two attrs consumed */
}
else {
- _mesa_printf("Can't emit 3ub\n");
+ printf("Can't emit 3ub\n");
+ return GL_FALSE; /* add this later */
}
- return GL_FALSE; /* add this later */
break;
case EMIT_4UB_4F_RGBA:
case EMIT_4UB_4F_BGRA:
get_src_ptr(p, srcECX, vtxESI, a);
emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
- sse_shufps(&p->func, temp, temp, Z, Y, X, W);
+ sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
emit_pack_store_4ub(p, dest, temp);
update_src_ptr(p, srcECX, vtxESI, a);
break;
case EMIT_4UB_4F_ARGB:
get_src_ptr(p, srcECX, vtxESI, a);
emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
- sse_shufps(&p->func, temp, temp, W, X, Y, Z);
+ sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
emit_pack_store_4ub(p, dest, temp);
update_src_ptr(p, srcECX, vtxESI, a);
break;
case EMIT_4UB_4F_ABGR:
get_src_ptr(p, srcECX, vtxESI, a);
emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
- sse_shufps(&p->func, temp, temp, W, Z, Y, X);
+ sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
emit_pack_store_4ub(p, dest, temp);
update_src_ptr(p, srcECX, vtxESI, a);
break;
break;
case GL_UNSIGNED_SHORT:
default:
- _mesa_printf("unknown CHAN_TYPE %s\n", _mesa_lookup_enum_by_nr(CHAN_TYPE));
+ printf("unknown CHAN_TYPE %s\n", _mesa_lookup_enum_by_nr(CHAN_TYPE));
return GL_FALSE;
}
break;
default:
- _mesa_printf("unknown a[%d].format %d\n", j, a->format);
+ printf("unknown a[%d].format %d\n", j, a->format);
return GL_FALSE; /* catch any new opcodes */
}
x86_pop(&p->func, countEBP);
x86_ret(&p->func);
+ assert(!vtx->emit);
vtx->emit = (tnl_emit_func)x86_get_func(&p->func);
+
+ assert( (char *) p->func.csr - (char *) p->func.store <= MAX_SSE_CODE_SIZE );
return GL_TRUE;
}
-void _tnl_generate_sse_emit( GLcontext *ctx )
+void _tnl_generate_sse_emit( struct gl_context *ctx )
{
struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
struct x86_program p;
p.ctx = ctx;
p.inputs_safe = 0; /* for now */
- p.outputs_safe = 1; /* for now */
+ p.outputs_safe = 0; /* for now */
p.have_sse2 = cpu_has_xmm2;
p.identity = x86_make_reg(file_XMM, 6);
p.chan0 = x86_make_reg(file_XMM, 7);
- x86_init_func(&p.func);
+ if (!x86_init_func_size(&p.func, MAX_SSE_CODE_SIZE)) {
+ vtx->emit = NULL;
+ return;
+ }
if (build_vertex_emit(&p)) {
_tnl_register_fastpath( vtx, GL_TRUE );
#else
-void _tnl_generate_sse_emit( GLcontext *ctx )
+void _tnl_generate_sse_emit( struct gl_context *ctx )
{
/* Dummy version for when USE_SSE_ASM not defined */
}