summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Krol <michal@vmware.com>2010-01-11 20:06:41 +0100
committerMichal Krol <michal@vmware.com>2010-01-11 20:06:41 +0100
commitb1351782f90e82465188cd117440628bbad9ddf4 (patch)
treee7db14321aab6e8da38f2014555d01d2f0059974
parente5ce45b62ca5c6837f3b0e7673b6d3e9be8c64e7 (diff)
tgsi: Implement F2D, D2F, DMOV, DADD in interpreter.
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 2bcb33392a..b9ea76131c 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -69,6 +69,16 @@
#define TILE_BOTTOM_LEFT 2
#define TILE_BOTTOM_RIGHT 3
+union tgsi_double_channel {
+ double d[QUAD_SIZE];
+ unsigned u[QUAD_SIZE][2];
+};
+
+struct tgsi_double_vector {
+ union tgsi_double_channel xy;
+ union tgsi_double_channel zw;
+};
+
static void
micro_abs(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
@@ -120,6 +130,26 @@ micro_cos(union tgsi_exec_channel *dst,
}
static void
+micro_d2f(union tgsi_exec_channel *dst,
+ const union tgsi_double_channel *src)
+{
+ dst->f[0] = (float)src->d[0];
+ dst->f[1] = (float)src->d[1];
+ dst->f[2] = (float)src->d[2];
+ dst->f[3] = (float)src->d[3];
+}
+
+static void
+micro_dadd(union tgsi_double_channel *dst,
+ const union tgsi_double_channel *src)
+{
+ dst->d[0] = src[0].d[0] + src[1].d[0];
+ dst->d[1] = src[0].d[1] + src[1].d[1];
+ dst->d[2] = src[0].d[2] + src[1].d[2];
+ dst->d[3] = src[0].d[3] + src[1].d[3];
+}
+
+static void
micro_ddx(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
@@ -140,6 +170,16 @@ micro_ddy(union tgsi_exec_channel *dst,
}
static void
+micro_dmov(union tgsi_double_channel *dst,
+ const union tgsi_double_channel *src)
+{
+ dst->d[0] = src->d[0];
+ dst->d[1] = src->d[1];
+ dst->d[2] = src->d[2];
+ dst->d[3] = src->d[3];
+}
+
+static void
micro_exp2(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
@@ -174,6 +214,16 @@ micro_exp2(union tgsi_exec_channel *dst,
}
static void
+micro_f2d(union tgsi_double_channel *dst,
+ const union tgsi_exec_channel *src)
+{
+ dst->d[0] = (double)src->f[0];
+ dst->d[1] = (double)src->f[1];
+ dst->d[2] = (double)src->f[2];
+ dst->d[3] = (double)src->f[3];
+}
+
+static void
micro_flr(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
@@ -2122,6 +2172,132 @@ exec_endswitch(struct tgsi_exec_machine *mach)
UPDATE_EXEC_MASK(mach);
}
+typedef void (* micro_dop)(union tgsi_double_channel *dst,
+ const union tgsi_double_channel *src);
+
+static void
+fetch_double_channel(struct tgsi_exec_machine *mach,
+ union tgsi_double_channel *chan,
+ const struct tgsi_full_src_register *reg,
+ uint chan_0,
+ uint chan_1)
+{
+ union tgsi_exec_channel src[2];
+ uint i;
+
+ /* XXX: That won't work for operand modifiers.
+ */
+ fetch_source(mach, &src[0], reg, chan_0, TGSI_EXEC_DATA_UINT);
+ fetch_source(mach, &src[1], reg, chan_1, TGSI_EXEC_DATA_UINT);
+
+ for (i = 0; i < QUAD_SIZE; i++) {
+ chan->u[i][0] = src[0].u[i];
+ chan->u[i][1] = src[1].u[i];
+ }
+}
+
+static void
+store_double_channel(struct tgsi_exec_machine *mach,
+ const union tgsi_double_channel *chan,
+ const struct tgsi_full_dst_register *reg,
+ const struct tgsi_full_instruction *inst,
+ uint chan_0,
+ uint chan_1)
+{
+ union tgsi_exec_channel dst[2];
+ uint i;
+
+ for (i = 0; i < QUAD_SIZE; i++) {
+ dst[0].u[i] = chan->u[i][0];
+ dst[1].u[i] = chan->u[i][1];
+ }
+
+ /* XXX: That won't work for saturate modifiers.
+ */
+ store_dest(mach, &dst[0], reg, inst, chan_0, TGSI_EXEC_DATA_UINT);
+ store_dest(mach, &dst[1], reg, inst, chan_1, TGSI_EXEC_DATA_UINT);
+}
+
+static void
+exec_double_unary(struct tgsi_exec_machine *mach,
+ const struct tgsi_full_instruction *inst,
+ micro_dop op)
+{
+ union tgsi_double_channel src;
+ union tgsi_double_channel dst;
+
+ if ((inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XY) == TGSI_WRITEMASK_XY) {
+ fetch_double_channel(mach, &src, &inst->Src[0], CHAN_X, CHAN_Y);
+ op(&dst, &src);
+ store_double_channel(mach, &dst, &inst->Dst[0], inst, CHAN_X, CHAN_Y);
+ }
+ if ((inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_ZW) == TGSI_WRITEMASK_ZW) {
+ fetch_double_channel(mach, &src, &inst->Src[0], CHAN_Z, CHAN_W);
+ op(&dst, &src);
+ store_double_channel(mach, &dst, &inst->Dst[0], inst, CHAN_Z, CHAN_W);
+ }
+}
+
+static void
+exec_double_binary(struct tgsi_exec_machine *mach,
+ const struct tgsi_full_instruction *inst,
+ micro_dop op)
+{
+ union tgsi_double_channel src[2];
+ union tgsi_double_channel dst;
+
+ if ((inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XY) == TGSI_WRITEMASK_XY) {
+ fetch_double_channel(mach, &src[0], &inst->Src[0], CHAN_X, CHAN_Y);
+ fetch_double_channel(mach, &src[1], &inst->Src[1], CHAN_X, CHAN_Y);
+ op(&dst, src);
+ store_double_channel(mach, &dst, &inst->Dst[0], inst, CHAN_X, CHAN_Y);
+ }
+ if ((inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_ZW) == TGSI_WRITEMASK_ZW) {
+ fetch_double_channel(mach, &src[0], &inst->Src[0], CHAN_Z, CHAN_W);
+ fetch_double_channel(mach, &src[1], &inst->Src[1], CHAN_Z, CHAN_W);
+ op(&dst, src);
+ store_double_channel(mach, &dst, &inst->Dst[0], inst, CHAN_Z, CHAN_W);
+ }
+}
+
+static void
+exec_f2d(struct tgsi_exec_machine *mach,
+ const struct tgsi_full_instruction *inst)
+{
+ union tgsi_exec_channel src;
+ union tgsi_double_channel dst;
+
+ if ((inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XY) == TGSI_WRITEMASK_XY) {
+ fetch_source(mach, &src, &inst->Src[0], CHAN_X, TGSI_EXEC_DATA_FLOAT);
+ micro_f2d(&dst, &src);
+ store_double_channel(mach, &dst, &inst->Dst[0], inst, CHAN_X, CHAN_Y);
+ }
+ if ((inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_ZW) == TGSI_WRITEMASK_ZW) {
+ fetch_source(mach, &src, &inst->Src[0], CHAN_Y, TGSI_EXEC_DATA_FLOAT);
+ micro_f2d(&dst, &src);
+ store_double_channel(mach, &dst, &inst->Dst[0], inst, CHAN_Z, CHAN_W);
+ }
+}
+
+static void
+exec_d2f(struct tgsi_exec_machine *mach,
+ const struct tgsi_full_instruction *inst)
+{
+ union tgsi_double_channel src;
+ union tgsi_exec_channel dst;
+
+ if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
+ fetch_double_channel(mach, &src, &inst->Src[0], CHAN_X, CHAN_Y);
+ micro_d2f(&dst, &src);
+ store_dest(mach, &dst, &inst->Dst[0], inst, CHAN_X, TGSI_EXEC_DATA_FLOAT);
+ }
+ if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
+ fetch_double_channel(mach, &src, &inst->Src[0], CHAN_Z, CHAN_W);
+ micro_d2f(&dst, &src);
+ store_dest(mach, &dst, &inst->Dst[0], inst, CHAN_Y, TGSI_EXEC_DATA_FLOAT);
+ }
+}
+
static void
micro_i2f(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
@@ -3537,6 +3713,22 @@ exec_instruction(
exec_endswitch(mach);
break;
+ case TGSI_OPCODE_F2D:
+ exec_f2d(mach, inst);
+ break;
+
+ case TGSI_OPCODE_D2F:
+ exec_d2f(mach, inst);
+ break;
+
+ case TGSI_OPCODE_DMOV:
+ exec_double_unary(mach, inst, micro_dmov);
+ break;
+
+ case TGSI_OPCODE_DADD:
+ exec_double_binary(mach, inst, micro_dadd);
+ break;
+
default:
assert( 0 );
}