#define Z 2
#define W 3
+#define DISASSEM 1
+
struct x86_reg {
GLuint file:3;
GLuint idx:3;
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:
*/
*(GLbyte *)(p->csr++) = b0;
}
-static void emit_1ub( struct x86_program *p, GLubyte b0 )
+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( struct x86_program *p, GLubyte b0, GLubyte b1 )
+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( struct x86_program *p, GLubyte b0, GLubyte b1, GLubyte b2 )
+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;
}
-static void emit_1i( struct x86_program *p, GLint i0 )
-{
- *(GLint *)(p->csr) = i0;
- p->csr += 4;
-}
+#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:
GLubyte *label )
{
GLint offset = label - (get_label(p) + 2);
-
+
if (offset <= 127 && offset >= -128) {
emit_1ub(p, 0x70 + cc);
emit_1b(p, (GLbyte) offset);
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 )
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:
break;
case mod_DISP8:
emit_1b(p, regmem.disp);
+ break;
case mod_DISP32:
emit_1i(p, regmem.disp);
+ break;
}
}
{
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;
}
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 )
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,
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 );
+}
+
{
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,
};
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);
}
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;
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));
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:
*/
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);
*/
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;
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 */
}
/* 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:
/* 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);
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);