Generates working SSE code for gears under the swrast driver.

This commit is contained in:
Keith Whitwell
2005-05-18 12:26:21 +00:00
parent b745bf08cd
commit dd4c1dd038
+137 -68
View File
@@ -42,6 +42,8 @@
#define Z 2
#define W 3
#define DISASSEM 1
struct x86_reg {
GLuint file:3;
GLuint idx:3;
@@ -144,6 +146,17 @@ static struct x86_reg make_disp( struct x86_reg reg,
return reg;
}
static struct x86_reg deref( struct x86_reg reg )
{
return make_disp(reg, 0);
}
static struct x86_reg get_base_reg( struct x86_reg reg )
{
return make_reg( reg.file, reg.idx );
}
/* Retreive a reference to one of the function arguments, taking into
* account any push/pop activity:
*/
@@ -179,30 +192,48 @@ static void emit_1b( struct x86_program *p, GLbyte b0 )
*(GLbyte *)(p->csr++) = b0;
}
static void emit_1ub( struct x86_program *p, GLubyte b0 )
{
*(p->csr++) = b0;
}
static void emit_2ub( struct x86_program *p, GLubyte b0, GLubyte b1 )
{
*(p->csr++) = b0;
*(p->csr++) = b1;
}
static void emit_3ub( struct x86_program *p, GLubyte b0, GLubyte b1, GLubyte b2 )
{
*(p->csr++) = b0;
*(p->csr++) = b1;
*(p->csr++) = b2;
}
static void emit_1i( struct x86_program *p, GLint i0 )
{
*(GLint *)(p->csr) = i0;
p->csr += 4;
}
static void disassem( struct x86_program *p, const char *fn )
{
#if DISASSEM
static const char *last_fn;
if (fn && fn != last_fn) {
_mesa_printf("0x%x: %s\n", p->csr, fn);
last_fn = fn;
}
#endif
}
static void emit_1ub_fn( struct x86_program *p, GLubyte b0, const char *fn )
{
disassem(p, fn);
*(p->csr++) = b0;
}
static void emit_2ub_fn( struct x86_program *p, GLubyte b0, GLubyte b1, const char *fn )
{
disassem(p, fn);
*(p->csr++) = b0;
*(p->csr++) = b1;
}
static void emit_3ub_fn( struct x86_program *p, GLubyte b0, GLubyte b1, GLubyte b2, const char *fn )
{
disassem(p, fn);
*(p->csr++) = b0;
*(p->csr++) = b1;
*(p->csr++) = b2;
}
#define emit_1ub(p, b0) emit_1ub_fn(p, b0, __FUNCTION__)
#define emit_2ub(p, b0, b1) emit_2ub_fn(p, b0, b1, __FUNCTION__)
#define emit_3ub(p, b0, b1, b2) emit_3ub_fn(p, b0, b1, b2, __FUNCTION__)
/* Labels, jumps and fixup:
*/
@@ -216,7 +247,7 @@ static void emit_jcc( struct x86_program *p,
GLubyte *label )
{
GLint offset = label - (get_label(p) + 2);
if (offset <= 127 && offset >= -128) {
emit_1ub(p, 0x70 + cc);
emit_1b(p, (GLbyte) offset);
@@ -273,7 +304,7 @@ static void emit_dec( struct x86_program *p,
struct x86_reg reg )
{
assert(reg.mod == mod_REG);
emit_1ub(p, 0x40 + reg.idx);
emit_1ub(p, 0x48 + reg.idx);
}
static void emit_ret( struct x86_program *p )
@@ -299,7 +330,13 @@ static void emit_modrm( struct x86_program *p,
val |= reg.idx << 3; /* reg field */
val |= regmem.idx; /* r/m field */
emit_1ub(p, val);
emit_1ub_fn(p, val, 0);
/* Oh-oh we've stumbled into the SIB thing.
*/
if (regmem.idx == reg_SP) {
emit_1ub_fn(p, 0x24, 0); /* simplistic! */
}
switch (regmem.mod) {
case mod_REG:
@@ -307,8 +344,10 @@ static void emit_modrm( struct x86_program *p,
break;
case mod_DISP8:
emit_1b(p, regmem.disp);
break;
case mod_DISP32:
emit_1i(p, regmem.disp);
break;
}
}
@@ -325,14 +364,14 @@ static void emit_op_modrm( struct x86_program *p,
{
switch (dst.mod) {
case mod_REG:
emit_1ub(p, op_dst_is_reg);
emit_1ub_fn(p, op_dst_is_reg, 0);
emit_modrm(p, dst, src);
break;
case mod_INDIRECT:
case mod_DISP32:
case mod_DISP8:
assert(src.mod == mod_REG);
emit_1ub(p, op_dst_is_mem);
emit_1ub_fn(p, op_dst_is_mem, 0);
emit_modrm(p, src, dst);
break;
}
@@ -352,6 +391,13 @@ static void emit_xor( struct x86_program *p,
emit_op_modrm( p, 0x33, 0x31, dst, src );
}
static void emit_cmp( struct x86_program *p,
struct x86_reg dst,
struct x86_reg src )
{
emit_op_modrm( p, 0x3b, 0x39, dst, src );
}
static void emit_movlps( struct x86_program *p,
struct x86_reg dst,
struct x86_reg src )
@@ -443,6 +489,14 @@ static void emit_packsswb( struct x86_program *p,
emit_modrm( p, dst, src );
}
static void emit_packuswb( struct x86_program *p,
struct x86_reg dst,
struct x86_reg src )
{
emit_3ub(p, 0x66, X86_TWOB, 0x67);
emit_modrm( p, dst, src );
}
/* Load effective address:
*/
static void emit_lea( struct x86_program *p,
@@ -461,6 +515,14 @@ static void emit_add_imm( struct x86_program *p,
emit_lea(p, dst, make_disp(src, value));
}
static void emit_test( struct x86_program *p,
struct x86_reg dst,
struct x86_reg src )
{
emit_1ub(p, 0x85);
emit_modrm( p, dst, src );
}
@@ -487,7 +549,7 @@ static void emit_pk4ub( struct x86_program *p,
{
emit_cvtps2dq(p, dest, arg0);
emit_packssdw(p, dest, dest);
emit_packsswb(p, dest, dest);
emit_packuswb(p, dest, dest);
}
static void emit_load4f_4( struct x86_program *p,
@@ -620,12 +682,12 @@ static void (*load[4][4])( struct x86_program *p,
};
static void emit_load( struct x86_program *p,
struct x86_reg temp,
struct x86_reg dest,
GLuint sz,
struct x86_reg src,
GLuint src_sz)
{
load[sz-1][src_sz-1](p, temp, src);
load[sz-1][src_sz-1](p, dest, src);
}
@@ -721,6 +783,7 @@ static GLboolean build_vertex_emit( struct x86_program *p )
struct x86_reg tmp = make_reg(file_XMM, 0);
struct x86_reg vp0 = make_reg(file_XMM, 1);
struct x86_reg vp1 = make_reg(file_XMM, 2);
struct x86_reg chan0 = make_reg(file_XMM, 3);
GLubyte *fixup, *label;
p->csr = p->store;
@@ -731,6 +794,15 @@ static GLboolean build_vertex_emit( struct x86_program *p )
emit_push(p, countEBP);
emit_push(p, vtxESI);
/* Get vertex count, compare to zero
*/
emit_xor(p, srcEDI, srcEDI);
emit_mov(p, countEBP, make_fn_arg(p, 2));
emit_cmp(p, countEBP, srcEDI);
fixup = emit_jcc_forward(p, cc_E);
/* Initialize destination register.
*/
emit_mov(p, vertexEAX, make_fn_arg(p, 3));
@@ -741,10 +813,6 @@ static GLboolean build_vertex_emit( struct x86_program *p )
emit_mov(p, vtxESI, make_disp(vtxESI, get_offset(ctx, &ctx->swtnl_context)));
vtxESI = make_disp(vtxESI, get_offset(tnl, &tnl->clipspace));
/* Get vertex count, compare to zero
*/
emit_mov(p, countEBP, make_fn_arg(p, 2));
fixup = emit_jcc_forward(p, cc_NZ);
/* Possibly load vp0, vp1 for viewport calcs:
*/
@@ -753,6 +821,10 @@ static GLboolean build_vertex_emit( struct x86_program *p )
emit_movups(p, vp1, make_disp(vtxESI, get_offset(vtx, &vtx->vp_xlate[0])));
}
/* always load, needed or not:
*/
emit_movups(p, chan0, make_disp(vtxESI, get_offset(vtx, &vtx->chan_scale[0])));
/* Note address for loop jump */
label = get_label(p);
@@ -775,40 +847,40 @@ static GLboolean build_vertex_emit( struct x86_program *p )
*/
switch (a[j].format) {
case EMIT_1F:
emit_load(p, tmp, 1, srcEDI, vtx->attr[j].inputsize);
emit_load(p, tmp, 1, deref(srcEDI), vtx->attr[j].inputsize);
emit_store(p, dest, 1, tmp);
case EMIT_2F:
emit_load(p, tmp, 2, srcEDI, vtx->attr[j].inputsize);
emit_load(p, tmp, 2, deref(srcEDI), vtx->attr[j].inputsize);
emit_store(p, dest, 2, tmp);
case EMIT_3F:
/* Potentially the worst case - hardcode 2+1 copying:
*/
emit_load(p, tmp, 3, srcEDI, vtx->attr[j].inputsize);
emit_load(p, tmp, 3, deref(srcEDI), vtx->attr[j].inputsize);
emit_store(p, dest, 3, tmp);
case EMIT_4F:
emit_load(p, tmp, 4, srcEDI, vtx->attr[j].inputsize);
emit_load(p, tmp, 4, deref(srcEDI), vtx->attr[j].inputsize);
emit_store(p, dest, 4, tmp);
break;
case EMIT_2F_VIEWPORT:
emit_load(p, tmp, 2, srcEDI, vtx->attr[j].inputsize);
emit_mulps(p, dest, vp0);
emit_addps(p, dest, vp1);
emit_load(p, tmp, 2, deref(srcEDI), vtx->attr[j].inputsize);
emit_mulps(p, tmp, vp0);
emit_addps(p, tmp, vp1);
emit_store(p, dest, 2, tmp);
break;
case EMIT_3F_VIEWPORT:
emit_load(p, tmp, 3, srcEDI, vtx->attr[j].inputsize);
emit_mulps(p, dest, vp0);
emit_addps(p, dest, vp1);
emit_load(p, tmp, 3, deref(srcEDI), vtx->attr[j].inputsize);
emit_mulps(p, tmp, vp0);
emit_addps(p, tmp, vp1);
emit_store(p, dest, 3, tmp);
break;
case EMIT_4F_VIEWPORT:
emit_load(p, tmp, 4, srcEDI, vtx->attr[j].inputsize);
emit_mulps(p, dest, vp0);
emit_addps(p, dest, vp1);
emit_load(p, tmp, 4, deref(srcEDI), vtx->attr[j].inputsize);
emit_mulps(p, tmp, vp0);
emit_addps(p, tmp, vp1);
emit_store(p, dest, 4, tmp);
break;
case EMIT_3F_XYW:
emit_load(p, tmp, 4, srcEDI, vtx->attr[j].inputsize);
emit_load(p, tmp, 4, deref(srcEDI), vtx->attr[j].inputsize);
emit_pshufd(p, tmp, tmp, X, Y, W, Z);
emit_store(p, dest, 3, tmp);
break;
@@ -818,48 +890,56 @@ static GLboolean build_vertex_emit( struct x86_program *p )
case EMIT_1UB_1F:
case EMIT_3UB_3F_RGB:
case EMIT_3UB_3F_BGR:
_mesa_printf("non-implemneted format %d\n", a[j].format);
return GL_FALSE; /* add this later */
case EMIT_4UB_4F_RGBA:
emit_load(p, tmp, 4, srcEDI, vtx->attr[j].inputsize);
emit_load(p, tmp, 4, deref(srcEDI), vtx->attr[j].inputsize);
emit_mulps(p, tmp, chan0);
emit_pk4ub(p, tmp, tmp);
emit_store(p, dest, 1, tmp);
break;
case EMIT_4UB_4F_BGRA:
emit_load(p, tmp, 4, srcEDI, vtx->attr[j].inputsize);
emit_load(p, tmp, 4, deref(srcEDI), vtx->attr[j].inputsize);
emit_pshufd(p, tmp, tmp, Z, Y, X, W);
emit_mulps(p, tmp, chan0);
emit_pk4ub(p, tmp, tmp);
emit_store(p, dest, 1, tmp);
break;
case EMIT_4UB_4F_ARGB:
emit_load(p, tmp, 4, srcEDI, vtx->attr[j].inputsize);
emit_load(p, tmp, 4, deref(srcEDI), vtx->attr[j].inputsize);
emit_pshufd(p, tmp, tmp, W, X, Y, Z);
emit_mulps(p, tmp, chan0);
emit_pk4ub(p, tmp, tmp);
emit_store(p, dest, 1, tmp);
break;
case EMIT_4UB_4F_ABGR:
emit_load(p, tmp, 4, srcEDI, vtx->attr[j].inputsize);
emit_load(p, tmp, 4, deref(srcEDI), vtx->attr[j].inputsize);
emit_pshufd(p, tmp, tmp, W, Z, Y, X);
emit_mulps(p, tmp, chan0);
emit_pk4ub(p, tmp, tmp);
emit_store(p, dest, 1, tmp);
break;
case EMIT_4CHAN_4F_RGBA:
switch (CHAN_TYPE) {
case GL_UNSIGNED_BYTE:
emit_load(p, tmp, 4, srcEDI, vtx->attr[j].inputsize);
emit_load(p, tmp, 4, deref(srcEDI), vtx->attr[j].inputsize);
emit_mulps(p, tmp, chan0);
emit_pk4ub(p, tmp, tmp);
emit_store(p, dest, 1, tmp);
break;
case GL_UNSIGNED_SHORT:
return GL_FALSE;
case GL_FLOAT:
emit_load(p, tmp, 4, srcEDI, vtx->attr[j].inputsize);
emit_load(p, tmp, 4, deref(srcEDI), vtx->attr[j].inputsize);
emit_store(p, dest, 4, tmp);
break;
case GL_UNSIGNED_SHORT:
default:
break;
_mesa_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[j].format);
return GL_FALSE; /* catch any new opcodes */
}
@@ -881,6 +961,7 @@ static GLboolean build_vertex_emit( struct x86_program *p )
/* decr count, loop if not zero
*/
emit_dec(p, countEBP);
emit_test(p, countEBP, countEBP);
emit_jcc(p, cc_NZ, label);
/* Land forward jump here:
@@ -889,7 +970,7 @@ static GLboolean build_vertex_emit( struct x86_program *p )
/* Pop regs and return
*/
emit_pop(p, vtxESI);
emit_pop(p, get_base_reg(vtxESI));
emit_pop(p, countEBP);
emit_pop(p, srcEDI);
emit_ret(p);
@@ -912,20 +993,8 @@ void _tnl_generate_sse_emit( GLcontext *ctx )
if (build_vertex_emit(&p)) {
_tnl_register_fastpath( vtx, GL_TRUE );
{
static int i = 0;
char filename[100];
int fd;
sprintf(filename, "fastpath%d.o", i);
fd = creat(filename, 0600);
if (fd != -1) {
write(fd, p.store, p.csr - p.store);
close(fd);
_mesa_printf("wrote %s\n", filename);
}
}
if (DISASSEM)
_mesa_printf("disassemble 0x%x 0x%x\n", p.store, p.csr);
}
else {
FREE(p.store);