summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>2010-01-07 17:59:58 +0100
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>2010-01-07 21:19:58 +0100
commitd550de2342bd2672a74707554171f9f9f1947baa (patch)
tree65943e257234508132266b74f1747cb20176d38e
parent607b9c2e09def36aca0b77e26826cd22e2573e66 (diff)
nv50: handle TGSI_OPCODE_IMAX,IMIN,UMAX,UMIN
-rw-r--r--src/gallium/drivers/nv50/nv50_program.c59
1 files changed, 49 insertions, 10 deletions
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index d61229b65e..c71592347d 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -971,6 +971,13 @@ emit_arl(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src,
emit(pc, e);
}
+#define NV50_MAX_F32 0x880
+#define NV50_MAX_S32 0x08c
+#define NV50_MAX_U32 0x084
+#define NV50_MIN_F32 0x8a0
+#define NV50_MIN_S32 0x0ac
+#define NV50_MIN_U32 0x0a4
+
static void
emit_minmax(struct nv50_pc *pc, unsigned sub, struct nv50_reg *dst,
struct nv50_reg *src0, struct nv50_reg *src1)
@@ -978,8 +985,8 @@ emit_minmax(struct nv50_pc *pc, unsigned sub, struct nv50_reg *dst,
struct nv50_program_exec *e = exec(pc);
set_long(pc, e);
- e->inst[0] |= 0xb0000000;
- e->inst[1] |= (sub << 29);
+ e->inst[0] |= 0x30000000 | ((sub & 0x800) << 20);
+ e->inst[1] |= (sub << 24);
check_swap_src_0_1(pc, &src0, &src1);
set_dst(pc, dst, e);
@@ -1341,18 +1348,18 @@ emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask,
if (mask & (3 << 1)) {
tmp[0] = alloc_temp(pc, NULL);
- emit_minmax(pc, 4, tmp[0], src[0], zero);
+ emit_minmax(pc, NV50_MAX_F32, tmp[0], src[0], zero);
}
if (mask & (1 << 2)) {
set_pred_wr(pc, 1, 0, pc->p->exec_tail);
tmp[1] = temp_temp(pc);
- emit_minmax(pc, 4, tmp[1], src[1], zero);
+ emit_minmax(pc, NV50_MAX_F32, tmp[1], src[1], zero);
tmp[3] = temp_temp(pc);
- emit_minmax(pc, 4, tmp[3], src[3], neg128);
- emit_minmax(pc, 5, tmp[3], tmp[3], pos128);
+ emit_minmax(pc, NV50_MAX_F32, tmp[3], src[3], neg128);
+ emit_minmax(pc, NV50_MIN_F32, tmp[3], tmp[3], pos128);
emit_pow(pc, dst[2], tmp[1], tmp[3]);
emit_mov(pc, dst[2], zero);
@@ -1496,8 +1503,8 @@ load_cube_tex_coords(struct nv50_pc *pc, struct nv50_reg *t[4],
src[1]->mod |= NV50_MOD_ABS;
src[2]->mod |= NV50_MOD_ABS;
- emit_minmax(pc, 4, t[2], src[0], src[1]);
- emit_minmax(pc, 4, t[2], src[2], t[2]);
+ emit_minmax(pc, NV50_MAX_F32, t[2], src[0], src[1]);
+ emit_minmax(pc, NV50_MAX_F32, t[2], src[2], t[2]);
src[0]->mod = mod[0];
src[1]->mod = mod[1];
@@ -1872,7 +1879,11 @@ get_supported_mods(const struct tgsi_full_instruction *insn, int i)
case TGSI_OPCODE_U2F:
return NV50_MOD_NEG | NV50_MOD_ABS | NV50_MOD_I32;
case TGSI_OPCODE_SHL:
+ case TGSI_OPCODE_IMAX:
+ case TGSI_OPCODE_IMIN:
case TGSI_OPCODE_ISHR:
+ case TGSI_OPCODE_UMAX:
+ case TGSI_OPCODE_UMIN:
case TGSI_OPCODE_USHR:
return NV50_MOD_I32;
default:
@@ -2504,6 +2515,20 @@ nv50_program_tx_insn(struct nv50_pc *pc,
pc->if_insn[pc->if_lvl++] = emit_branch(pc, 0, 2);;
terminate_mbb(pc);
break;
+ case TGSI_OPCODE_IMAX:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_minmax(pc, 0x08c, dst[c], src[0][c], src[1][c]);
+ }
+ break;
+ case TGSI_OPCODE_IMIN:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_minmax(pc, 0x0ac, dst[c], src[0][c], src[1][c]);
+ }
+ break;
case TGSI_OPCODE_INEG:
for (c = 0; c < 4; c++) {
if (!(mask & (1 << c)))
@@ -2576,14 +2601,14 @@ nv50_program_tx_insn(struct nv50_pc *pc,
for (c = 0; c < 4; c++) {
if (!(mask & (1 << c)))
continue;
- emit_minmax(pc, 4, dst[c], src[0][c], src[1][c]);
+ emit_minmax(pc, 0x880, dst[c], src[0][c], src[1][c]);
}
break;
case TGSI_OPCODE_MIN:
for (c = 0; c < 4; c++) {
if (!(mask & (1 << c)))
continue;
- emit_minmax(pc, 5, dst[c], src[0][c], src[1][c]);
+ emit_minmax(pc, 0x8a0, dst[c], src[0][c], src[1][c]);
}
break;
case TGSI_OPCODE_MOV:
@@ -2712,6 +2737,20 @@ nv50_program_tx_insn(struct nv50_pc *pc,
emit_cvt(pc, dst[c], src[0][c], -1, CVT_F32_U32);
}
break;
+ case TGSI_OPCODE_UMAX:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_minmax(pc, 0x084, dst[c], src[0][c], src[1][c]);
+ }
+ break;
+ case TGSI_OPCODE_UMIN:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_minmax(pc, 0x0a4, dst[c], src[0][c], src[1][c]);
+ }
+ break;
case TGSI_OPCODE_XPD:
temp = temp_temp(pc);
if (mask & (1 << 0)) {