summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/freedreno/ir3/ir3.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/freedreno/ir3/ir3.c')
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3.c80
1 files changed, 62 insertions, 18 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3.c b/src/gallium/drivers/freedreno/ir3/ir3.c
index 61bc3b5ad47..6db0a2a20cd 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3.c
@@ -501,21 +501,58 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr,
src2 = (instr->regs_count >= 3) ? instr->regs[2] : NULL;
}
-
/* TODO we need a more comprehensive list about which instructions
* can be encoded which way. Or possibly use IR3_INSTR_0 flag to
* indicate to use the src_off encoding even if offset is zero
* (but then what to do about dst_off?)
*/
- if ((instr->opc == OPC_LDGB) || is_atomic(instr->opc)) {
+ if (is_atomic(instr->opc)) {
+ instr_cat6ldgb_t *ldgb = ptr;
+
+ /* maybe these two bits both determine the instruction encoding? */
+ cat6->src_off = false;
+
+ ldgb->d = instr->cat6.d - 1;
+ ldgb->typed = instr->cat6.typed;
+ ldgb->type_size = instr->cat6.iim_val - 1;
+
+ ldgb->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
+
+ if (ldgb->g) {
+ struct ir3_register *src3 = instr->regs[3];
+ struct ir3_register *src4 = instr->regs[4];
+
+ /* first src is src_ssbo: */
+ iassert(src1->flags & IR3_REG_IMMED);
+ ldgb->src_ssbo = src1->uim_val;
+
+ ldgb->src1 = reg(src2, info, instr->repeat, IR3_REG_IMMED);
+ ldgb->src1_im = !!(src2->flags & IR3_REG_IMMED);
+ ldgb->src2 = reg(src3, info, instr->repeat, IR3_REG_IMMED);
+ ldgb->src2_im = !!(src3->flags & IR3_REG_IMMED);
+
+ ldgb->src3 = reg(src4, info, instr->repeat, 0);
+ ldgb->pad0 = 0x1;
+ ldgb->pad3 = 0x1;
+ } else {
+ ldgb->src1 = reg(src1, info, instr->repeat, IR3_REG_IMMED);
+ ldgb->src1_im = !!(src1->flags & IR3_REG_IMMED);
+ ldgb->src2 = reg(src2, info, instr->repeat, IR3_REG_IMMED);
+ ldgb->src2_im = !!(src2->flags & IR3_REG_IMMED);
+ ldgb->pad0 = 0x1;
+ ldgb->pad3 = 0x0;
+ }
+
+ return 0;
+ } else if (instr->opc == OPC_LDGB) {
struct ir3_register *src3 = instr->regs[3];
instr_cat6ldgb_t *ldgb = ptr;
/* maybe these two bits both determine the instruction encoding? */
cat6->src_off = false;
- ldgb->d = 4 - 1; /* always .4d ? */
- ldgb->typed = false; /* TODO true for images */
+ ldgb->d = instr->cat6.d - 1;
+ ldgb->typed = instr->cat6.typed;
ldgb->type_size = instr->cat6.iim_val - 1;
ldgb->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
@@ -530,18 +567,23 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr,
ldgb->src2 = reg(src3, info, instr->repeat, IR3_REG_IMMED);
ldgb->src2_im = !!(src3->flags & IR3_REG_IMMED);
- if (is_atomic(instr->opc)) {
- struct ir3_register *src4 = instr->regs[4];
- ldgb->src3 = reg(src4, info, instr->repeat, 0);
- ldgb->pad0 = 0x1;
- ldgb->pad3 = 0x3;
- } else {
- ldgb->pad0 = 0x0;
- ldgb->pad3 = 0x2;
- }
+ ldgb->pad0 = 0x0;
+ ldgb->pad3 = 0x1;
+
+ return 0;
+ } else if (instr->opc == OPC_RESINFO) {
+ instr_cat6ldgb_t *ldgb = ptr;
+
+ ldgb->d = instr->cat6.d - 1;
+
+ ldgb->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
+
+ /* first src is src_ssbo: */
+ iassert(src1->flags & IR3_REG_IMMED);
+ ldgb->src_ssbo = src1->uim_val;
return 0;
- } else if (instr->opc == OPC_STGB) {
+ } else if ((instr->opc == OPC_STGB) || (instr->opc == OPC_STIB)) {
struct ir3_register *src3 = instr->regs[4];
instr_cat6stgb_t *stgb = ptr;
@@ -549,8 +591,8 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr,
cat6->src_off = true;
stgb->pad3 = 0x2;
- stgb->d = 4 - 1; /* always .4d ? */
- stgb->typed = false;
+ stgb->d = instr->cat6.d - 1;
+ stgb->typed = instr->cat6.typed;
stgb->type_size = instr->cat6.iim_val - 1;
/* first src is dst_ssbo: */
@@ -565,7 +607,8 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr,
stgb->src3_im = !!(src3->flags & IR3_REG_IMMED);
return 0;
- } else if (instr->cat6.src_offset || (instr->opc == OPC_LDG)) {
+ } else if (instr->cat6.src_offset || (instr->opc == OPC_LDG) ||
+ (instr->opc == OPC_LDL)) {
instr_cat6a_t *cat6a = ptr;
cat6->src_off = true;
@@ -590,7 +633,8 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr,
}
}
- if (instr->cat6.dst_offset || (instr->opc == OPC_STG)) {
+ if (instr->cat6.dst_offset || (instr->opc == OPC_STG) ||
+ (instr->opc == OPC_STL)) {
instr_cat6c_t *cat6c = ptr;
cat6->dst_off = true;
cat6c->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);