freedreno/a6xx: Add register offset for STG/LDG
These instructions take a 64 bit iova as two conescutive registers and a immediate offset. This patch adds support for the offset to be a single register, which is added to the 64 bit iova. Signed-off-by: Kristian H. Kristensen <hoegsberg@google.com> Acked-by: Eric Anholt <eric@anholt.net> Reviewed-by: Rob Clark <robdclark@gmail.com>
This commit is contained in:
@@ -721,6 +721,26 @@ static void print_instr_cat6_a3xx(struct disasm_ctx *ctx, instr_t *instr)
|
|||||||
if (debug & PRINT_VERBOSE)
|
if (debug & PRINT_VERBOSE)
|
||||||
fprintf(ctx->out, " (pad0=%x, pad3=%x, mustbe0=%x)", cat6->ldgb.pad0, cat6->ldgb.pad3, cat6->ldgb.mustbe0);
|
fprintf(ctx->out, " (pad0=%x, pad3=%x, mustbe0=%x)", cat6->ldgb.pad0, cat6->ldgb.pad3, cat6->ldgb.mustbe0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else if (_OPC(6, cat6->opc) == OPC_LDG && cat6->a.src1_im && cat6->a.src2_im) {
|
||||||
|
struct reginfo src3;
|
||||||
|
|
||||||
|
memset(&src3, 0, sizeof(src3));
|
||||||
|
src1.reg = (reg_t)(cat6->a.src1);
|
||||||
|
src2.reg = (reg_t)(cat6->a.src2);
|
||||||
|
src2.im = cat6->a.src2_im;
|
||||||
|
src3.reg = (reg_t)(cat6->a.off);
|
||||||
|
src3.full = true;
|
||||||
|
dst.reg = (reg_t)(cat6->d.dst);
|
||||||
|
|
||||||
|
print_src(ctx, &dst);
|
||||||
|
fprintf(ctx->out, ", g[");
|
||||||
|
print_src(ctx, &src1);
|
||||||
|
fprintf(ctx->out, "+");
|
||||||
|
print_src(ctx, &src3);
|
||||||
|
fprintf(ctx->out, "], ");
|
||||||
|
print_src(ctx, &src2);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cat6->dst_off) {
|
if (cat6->dst_off) {
|
||||||
@@ -748,8 +768,15 @@ static void print_instr_cat6_a3xx(struct disasm_ctx *ctx, instr_t *instr)
|
|||||||
fprintf(ctx->out, "%c[", sd);
|
fprintf(ctx->out, "%c[", sd);
|
||||||
/* note: dst might actually be a src (ie. address to store to) */
|
/* note: dst might actually be a src (ie. address to store to) */
|
||||||
print_src(ctx, &dst);
|
print_src(ctx, &dst);
|
||||||
if (dstoff)
|
if (cat6->dst_off && cat6->g) {
|
||||||
|
struct reginfo dstoff_reg = {};
|
||||||
|
dstoff_reg.reg = (reg_t) cat6->c.off;
|
||||||
|
dstoff_reg.full = true;
|
||||||
|
fprintf(ctx->out, "+");
|
||||||
|
print_src(ctx, &dstoff_reg);
|
||||||
|
} else if (dstoff) {
|
||||||
fprintf(ctx->out, "%+d", dstoff);
|
fprintf(ctx->out, "%+d", dstoff);
|
||||||
|
}
|
||||||
if (sd)
|
if (sd)
|
||||||
fprintf(ctx->out, "]");
|
fprintf(ctx->out, "]");
|
||||||
fprintf(ctx->out, ", ");
|
fprintf(ctx->out, ", ");
|
||||||
@@ -765,7 +792,9 @@ static void print_instr_cat6_a3xx(struct disasm_ctx *ctx, instr_t *instr)
|
|||||||
print_src(ctx, &src1);
|
print_src(ctx, &src1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src1off)
|
if (cat6->src_off && cat6->g)
|
||||||
|
print_src(ctx, &src2);
|
||||||
|
else if (src1off)
|
||||||
fprintf(ctx->out, "%+d", src1off);
|
fprintf(ctx->out, "%+d", src1off);
|
||||||
if (ss)
|
if (ss)
|
||||||
fprintf(ctx->out, "]");
|
fprintf(ctx->out, "]");
|
||||||
|
|||||||
@@ -284,6 +284,8 @@ typedef union PACKED {
|
|||||||
uint32_t dummy12 : 12;
|
uint32_t dummy12 : 12;
|
||||||
uint32_t dummy13 : 13;
|
uint32_t dummy13 : 13;
|
||||||
uint32_t dummy8 : 8;
|
uint32_t dummy8 : 8;
|
||||||
|
int32_t idummy13 : 13;
|
||||||
|
int32_t idummy8 : 8;
|
||||||
} reg_t;
|
} reg_t;
|
||||||
|
|
||||||
/* special registers: */
|
/* special registers: */
|
||||||
|
|||||||
+26
-7
@@ -801,16 +801,24 @@ static int emit_cat6(struct ir3_instruction *instr, void *ptr,
|
|||||||
|
|
||||||
cat6->src_off = true;
|
cat6->src_off = true;
|
||||||
|
|
||||||
cat6a->src1 = reg(src1, info, instr->repeat, IR3_REG_IMMED);
|
if (instr->opc == OPC_LDG) {
|
||||||
cat6a->src1_im = !!(src1->flags & IR3_REG_IMMED);
|
/* For LDG src1 can not be immediate, so src1_imm is redundant and
|
||||||
|
* instead used to signal whether (when true) 'off' is a 32 bit
|
||||||
|
* register or an immediate offset.
|
||||||
|
*/
|
||||||
|
cat6a->src1 = reg(src1, info, instr->repeat, 0);
|
||||||
|
cat6a->src1_im = !(src3->flags & IR3_REG_IMMED);
|
||||||
|
cat6a->off = reg(src3, info, instr->repeat, IR3_REG_IMMED);
|
||||||
|
} else {
|
||||||
|
cat6a->src1 = reg(src1, info, instr->repeat, IR3_REG_IMMED);
|
||||||
|
cat6a->src1_im = !!(src1->flags & IR3_REG_IMMED);
|
||||||
|
cat6a->off = reg(src3, info, instr->repeat, IR3_REG_IMMED);
|
||||||
|
iassert(src3->flags & IR3_REG_IMMED);
|
||||||
|
}
|
||||||
|
|
||||||
/* Num components */
|
/* Num components */
|
||||||
cat6a->src2 = reg(src2, info, instr->repeat, IR3_REG_IMMED);
|
cat6a->src2 = reg(src2, info, instr->repeat, IR3_REG_IMMED);
|
||||||
cat6a->src2_im = true;
|
cat6a->src2_im = true;
|
||||||
|
|
||||||
/* Offset */
|
|
||||||
iassert(src3->flags & IR3_REG_IMMED);
|
|
||||||
cat6a->off = reg(src3, info, instr->repeat, IR3_REG_IMMED);
|
|
||||||
} else {
|
} else {
|
||||||
instr_cat6b_t *cat6b = ptr;
|
instr_cat6b_t *cat6b = ptr;
|
||||||
|
|
||||||
@@ -827,9 +835,20 @@ 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->opc == OPC_STLW)) {
|
(instr->opc == OPC_STL) || (instr->opc == OPC_STLW)) {
|
||||||
instr_cat6c_t *cat6c = ptr;
|
instr_cat6c_t *cat6c = ptr;
|
||||||
|
struct ir3_register *src3 = instr->regs[4];
|
||||||
cat6->dst_off = true;
|
cat6->dst_off = true;
|
||||||
cat6c->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
|
cat6c->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
|
||||||
cat6c->off = instr->cat6.dst_offset;
|
|
||||||
|
if (instr->flags & IR3_INSTR_G) {
|
||||||
|
cat6c->off = reg(src3, info, instr->repeat, IR3_REG_R | IR3_REG_HALF);
|
||||||
|
if (src3->flags & IR3_REG_IMMED) {
|
||||||
|
/* Immediate offsets are in bytes... */
|
||||||
|
cat6->g = false;
|
||||||
|
cat6c->off *= 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cat6c->off = instr->cat6.dst_offset;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
instr_cat6d_t *cat6d = ptr;
|
instr_cat6d_t *cat6d = ptr;
|
||||||
cat6->dst_off = false;
|
cat6->dst_off = false;
|
||||||
|
|||||||
@@ -1471,6 +1471,8 @@ INSTR4F(G, ATOMIC_OR)
|
|||||||
INSTR4F(G, ATOMIC_XOR)
|
INSTR4F(G, ATOMIC_XOR)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
INSTR4F(G, STG)
|
||||||
|
|
||||||
/* cat7 instructions: */
|
/* cat7 instructions: */
|
||||||
INSTR0(BAR)
|
INSTR0(BAR)
|
||||||
INSTR0(FENCE)
|
INSTR0(FENCE)
|
||||||
|
|||||||
@@ -238,6 +238,9 @@ static bool valid_flags(struct ir3_instruction *instr, unsigned n,
|
|||||||
if (is_atomic(instr->opc) && !(instr->flags & IR3_INSTR_G))
|
if (is_atomic(instr->opc) && !(instr->flags & IR3_INSTR_G))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (instr->opc == OPC_STG && (instr->flags & IR3_INSTR_G) && (n != 2))
|
||||||
|
return false;
|
||||||
|
|
||||||
/* as with atomics, ldib on a6xx can only have immediate for
|
/* as with atomics, ldib on a6xx can only have immediate for
|
||||||
* SSBO slot argument
|
* SSBO slot argument
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user