summaryrefslogtreecommitdiff
path: root/src/broadcom/qpu/qpu_instr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/broadcom/qpu/qpu_instr.c')
-rw-r--r--src/broadcom/qpu/qpu_instr.c197
1 files changed, 174 insertions, 23 deletions
diff --git a/src/broadcom/qpu/qpu_instr.c b/src/broadcom/qpu/qpu_instr.c
index 569c5fc4074..9a6434d94dd 100644
--- a/src/broadcom/qpu/qpu_instr.c
+++ b/src/broadcom/qpu/qpu_instr.c
@@ -35,6 +35,14 @@ v3d_qpu_magic_waddr_name(const struct v3d_device_info *devinfo,
if (devinfo->ver < 40 && waddr == V3D_QPU_WADDR_TMU)
return "tmu";
+ /* V3D 7.x QUAD and REP aliases R5 and R5REPT in the table below
+ */
+ if (devinfo->ver >= 71 && waddr == V3D_QPU_WADDR_QUAD)
+ return "quad";
+
+ if (devinfo->ver >= 71 && waddr == V3D_QPU_WADDR_REP)
+ return "rep";
+
static const char *waddr_magic[] = {
[V3D_QPU_WADDR_R0] = "r0",
[V3D_QPU_WADDR_R1] = "r1",
@@ -169,6 +177,19 @@ v3d_qpu_add_op_name(enum v3d_qpu_add_op op)
[V3D_QPU_A_ITOF] = "itof",
[V3D_QPU_A_CLZ] = "clz",
[V3D_QPU_A_UTOF] = "utof",
+ [V3D_QPU_A_MOV] = "mov",
+ [V3D_QPU_A_FMOV] = "fmov",
+ [V3D_QPU_A_VPACK] = "vpack",
+ [V3D_QPU_A_V8PACK] = "v8pack",
+ [V3D_QPU_A_V10PACK] = "v10pack",
+ [V3D_QPU_A_V11FPACK] = "v11fpack",
+ [V3D_QPU_A_BALLOT] = "ballot",
+ [V3D_QPU_A_BCASTF] = "bcastf",
+ [V3D_QPU_A_ALLEQ] = "alleq",
+ [V3D_QPU_A_ALLFEQ] = "allfeq",
+ [V3D_QPU_A_ROTQ] = "rotq",
+ [V3D_QPU_A_ROT] = "rot",
+ [V3D_QPU_A_SHUFFLE] = "shuffle",
};
if (op >= ARRAY_SIZE(op_names))
@@ -191,6 +212,12 @@ v3d_qpu_mul_op_name(enum v3d_qpu_mul_op op)
[V3D_QPU_M_MOV] = "mov",
[V3D_QPU_M_NOP] = "nop",
[V3D_QPU_M_FMUL] = "fmul",
+ [V3D_QPU_M_FTOUNORM16] = "ftounorm16",
+ [V3D_QPU_M_FTOSNORM16] = "ftosnorm16",
+ [V3D_QPU_M_VFTOUNORM8] = "vftounorm8",
+ [V3D_QPU_M_VFTOSNORM8] = "vftosnorm8",
+ [V3D_QPU_M_VFTOUNORM10LO] = "vftounorm10lo",
+ [V3D_QPU_M_VFTOUNORM10HI] = "vftounorm10hi",
};
if (op >= ARRAY_SIZE(op_names))
@@ -450,6 +477,21 @@ static const uint8_t add_op_args[] = {
[V3D_QPU_A_ITOF] = D | A,
[V3D_QPU_A_CLZ] = D | A,
[V3D_QPU_A_UTOF] = D | A,
+
+ [V3D_QPU_A_MOV] = D | A,
+ [V3D_QPU_A_FMOV] = D | A,
+ [V3D_QPU_A_VPACK] = D | A | B,
+ [V3D_QPU_A_V8PACK] = D | A | B,
+ [V3D_QPU_A_V10PACK] = D | A | B,
+ [V3D_QPU_A_V11FPACK] = D | A | B,
+
+ [V3D_QPU_A_BALLOT] = D | A,
+ [V3D_QPU_A_BCASTF] = D | A,
+ [V3D_QPU_A_ALLEQ] = D | A,
+ [V3D_QPU_A_ALLFEQ] = D | A,
+ [V3D_QPU_A_ROTQ] = D | A | B,
+ [V3D_QPU_A_ROT] = D | A | B,
+ [V3D_QPU_A_SHUFFLE] = D | A | B,
};
static const uint8_t mul_op_args[] = {
@@ -463,6 +505,12 @@ static const uint8_t mul_op_args[] = {
[V3D_QPU_M_NOP] = 0,
[V3D_QPU_M_MOV] = D | A,
[V3D_QPU_M_FMUL] = D | A | B,
+ [V3D_QPU_M_FTOUNORM16] = D | A,
+ [V3D_QPU_M_FTOSNORM16] = D | A,
+ [V3D_QPU_M_VFTOUNORM8] = D | A,
+ [V3D_QPU_M_VFTOSNORM8] = D | A,
+ [V3D_QPU_M_VFTOUNORM10LO] = D | A,
+ [V3D_QPU_M_VFTOUNORM10HI] = D | A,
};
bool
@@ -636,19 +684,23 @@ v3d_qpu_add_op_writes_vpm(enum v3d_qpu_add_op op)
}
bool
-v3d_qpu_uses_tlb(const struct v3d_qpu_instr *inst)
+v3d_qpu_reads_tlb(const struct v3d_qpu_instr *inst)
{
- if (inst->sig.ldtlb ||
- inst->sig.ldtlbu)
- return true;
+ return inst->sig.ldtlb || inst->sig.ldtlbu;
+}
+bool
+v3d_qpu_writes_tlb(const struct v3d_qpu_instr *inst)
+{
if (inst->type == V3D_QPU_INSTR_TYPE_ALU) {
- if (inst->alu.add.magic_write &&
+ if (inst->alu.add.op != V3D_QPU_A_NOP &&
+ inst->alu.add.magic_write &&
v3d_qpu_magic_waddr_is_tlb(inst->alu.add.waddr)) {
return true;
}
- if (inst->alu.mul.magic_write &&
+ if (inst->alu.mul.op != V3D_QPU_M_NOP &&
+ inst->alu.mul.magic_write &&
v3d_qpu_magic_waddr_is_tlb(inst->alu.mul.waddr)) {
return true;
}
@@ -658,18 +710,32 @@ v3d_qpu_uses_tlb(const struct v3d_qpu_instr *inst)
}
bool
+v3d_qpu_uses_tlb(const struct v3d_qpu_instr *inst)
+{
+ return v3d_qpu_writes_tlb(inst) || v3d_qpu_reads_tlb(inst);
+}
+
+bool
v3d_qpu_uses_sfu(const struct v3d_qpu_instr *inst)
{
- if (v3d_qpu_instr_is_sfu(inst))
- return true;
+ return v3d_qpu_instr_is_sfu(inst) || v3d_qpu_instr_is_legacy_sfu(inst);
+}
+/* Checks whether the instruction implements a SFU operation by the writing
+ * to specific magic register addresses instead of using SFU ALU opcodes.
+ */
+bool
+v3d_qpu_instr_is_legacy_sfu(const struct v3d_qpu_instr *inst)
+{
if (inst->type == V3D_QPU_INSTR_TYPE_ALU) {
- if (inst->alu.add.magic_write &&
+ if (inst->alu.add.op != V3D_QPU_A_NOP &&
+ inst->alu.add.magic_write &&
v3d_qpu_magic_waddr_is_sfu(inst->alu.add.waddr)) {
return true;
}
- if (inst->alu.mul.magic_write &&
+ if (inst->alu.mul.op != V3D_QPU_M_NOP &&
+ inst->alu.mul.magic_write &&
v3d_qpu_magic_waddr_is_sfu(inst->alu.mul.waddr)) {
return true;
}
@@ -689,6 +755,13 @@ v3d_qpu_instr_is_sfu(const struct v3d_qpu_instr *inst)
case V3D_QPU_A_LOG:
case V3D_QPU_A_SIN:
case V3D_QPU_A_RSQRT2:
+ case V3D_QPU_A_BALLOT:
+ case V3D_QPU_A_BCASTF:
+ case V3D_QPU_A_ALLEQ:
+ case V3D_QPU_A_ALLFEQ:
+ case V3D_QPU_A_ROTQ:
+ case V3D_QPU_A_ROT:
+ case V3D_QPU_A_SHUFFLE:
return true;
default:
return false;
@@ -702,9 +775,11 @@ v3d_qpu_writes_tmu(const struct v3d_device_info *devinfo,
const struct v3d_qpu_instr *inst)
{
return (inst->type == V3D_QPU_INSTR_TYPE_ALU &&
- ((inst->alu.add.magic_write &&
+ ((inst->alu.add.op != V3D_QPU_A_NOP &&
+ inst->alu.add.magic_write &&
v3d_qpu_magic_waddr_is_tmu(devinfo, inst->alu.add.waddr)) ||
- (inst->alu.mul.magic_write &&
+ (inst->alu.mul.op != V3D_QPU_M_NOP &&
+ inst->alu.mul.magic_write &&
v3d_qpu_magic_waddr_is_tmu(devinfo, inst->alu.mul.waddr))));
}
@@ -740,12 +815,14 @@ v3d_qpu_writes_vpm(const struct v3d_qpu_instr *inst)
if (v3d_qpu_add_op_writes_vpm(inst->alu.add.op))
return true;
- if (inst->alu.add.magic_write &&
+ if (inst->alu.add.op != V3D_QPU_A_NOP &&
+ inst->alu.add.magic_write &&
v3d_qpu_magic_waddr_is_vpm(inst->alu.add.waddr)) {
return true;
}
- if (inst->alu.mul.magic_write &&
+ if (inst->alu.mul.op != V3D_QPU_M_NOP &&
+ inst->alu.mul.magic_write &&
v3d_qpu_magic_waddr_is_vpm(inst->alu.mul.waddr)) {
return true;
}
@@ -773,12 +850,18 @@ v3d_qpu_writes_unifa(const struct v3d_device_info *devinfo,
inst->alu.mul.waddr == V3D_QPU_WADDR_UNIFA) {
return true;
}
+
+ if (v3d_qpu_sig_writes_address(devinfo, &inst->sig) &&
+ inst->sig_magic &&
+ inst->sig_addr == V3D_QPU_WADDR_UNIFA) {
+ return true;
+ }
}
return false;
}
-static bool
+bool
v3d_qpu_waits_vpm(const struct v3d_qpu_instr *inst)
{
return inst->type == V3D_QPU_INSTR_TYPE_ALU &&
@@ -805,10 +888,12 @@ qpu_writes_magic_waddr_explicitly(const struct v3d_device_info *devinfo,
uint32_t waddr)
{
if (inst->type == V3D_QPU_INSTR_TYPE_ALU) {
- if (inst->alu.add.magic_write && inst->alu.add.waddr == waddr)
+ if (inst->alu.add.op != V3D_QPU_A_NOP &&
+ inst->alu.add.magic_write && inst->alu.add.waddr == waddr)
return true;
- if (inst->alu.mul.magic_write && inst->alu.mul.waddr == waddr)
+ if (inst->alu.mul.op != V3D_QPU_M_NOP &&
+ inst->alu.mul.magic_write && inst->alu.mul.waddr == waddr)
return true;
}
@@ -824,6 +909,9 @@ bool
v3d_qpu_writes_r3(const struct v3d_device_info *devinfo,
const struct v3d_qpu_instr *inst)
{
+ if(!devinfo->has_accumulators)
+ return false;
+
if (qpu_writes_magic_waddr_explicitly(devinfo, inst, V3D_QPU_WADDR_R3))
return true;
@@ -834,14 +922,19 @@ bool
v3d_qpu_writes_r4(const struct v3d_device_info *devinfo,
const struct v3d_qpu_instr *inst)
{
+ if (!devinfo->has_accumulators)
+ return false;
+
if (inst->type == V3D_QPU_INSTR_TYPE_ALU) {
- if (inst->alu.add.magic_write &&
+ if (inst->alu.add.op != V3D_QPU_A_NOP &&
+ inst->alu.add.magic_write &&
(inst->alu.add.waddr == V3D_QPU_WADDR_R4 ||
v3d_qpu_magic_waddr_is_sfu(inst->alu.add.waddr))) {
return true;
}
- if (inst->alu.mul.magic_write &&
+ if (inst->alu.mul.op != V3D_QPU_M_NOP &&
+ inst->alu.mul.magic_write &&
(inst->alu.mul.waddr == V3D_QPU_WADDR_R4 ||
v3d_qpu_magic_waddr_is_sfu(inst->alu.mul.waddr))) {
return true;
@@ -862,6 +955,9 @@ bool
v3d_qpu_writes_r5(const struct v3d_device_info *devinfo,
const struct v3d_qpu_instr *inst)
{
+ if (!devinfo->has_accumulators)
+ return false;
+
if (qpu_writes_magic_waddr_explicitly(devinfo, inst, V3D_QPU_WADDR_R5))
return true;
@@ -872,6 +968,9 @@ bool
v3d_qpu_writes_accum(const struct v3d_device_info *devinfo,
const struct v3d_qpu_instr *inst)
{
+ if (!devinfo->has_accumulators)
+ return false;
+
if (v3d_qpu_writes_r5(devinfo, inst))
return true;
if (v3d_qpu_writes_r4(devinfo, inst))
@@ -889,15 +988,67 @@ v3d_qpu_writes_accum(const struct v3d_device_info *devinfo,
}
bool
+v3d_qpu_writes_rf0_implicitly(const struct v3d_device_info *devinfo,
+ const struct v3d_qpu_instr *inst)
+{
+ if (devinfo->ver >= 71 &&
+ (inst->sig.ldvary || inst->sig.ldunif || inst->sig.ldunifa)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool
v3d_qpu_uses_mux(const struct v3d_qpu_instr *inst, enum v3d_qpu_mux mux)
{
int add_nsrc = v3d_qpu_add_op_num_src(inst->alu.add.op);
int mul_nsrc = v3d_qpu_mul_op_num_src(inst->alu.mul.op);
- return ((add_nsrc > 0 && inst->alu.add.a == mux) ||
- (add_nsrc > 1 && inst->alu.add.b == mux) ||
- (mul_nsrc > 0 && inst->alu.mul.a == mux) ||
- (mul_nsrc > 1 && inst->alu.mul.b == mux));
+ return ((add_nsrc > 0 && inst->alu.add.a.mux == mux) ||
+ (add_nsrc > 1 && inst->alu.add.b.mux == mux) ||
+ (mul_nsrc > 0 && inst->alu.mul.a.mux == mux) ||
+ (mul_nsrc > 1 && inst->alu.mul.b.mux == mux));
+}
+
+bool
+v3d71_qpu_reads_raddr(const struct v3d_qpu_instr *inst, uint8_t raddr)
+{
+ int add_nsrc = v3d_qpu_add_op_num_src(inst->alu.add.op);
+ int mul_nsrc = v3d_qpu_mul_op_num_src(inst->alu.mul.op);
+
+ return (add_nsrc > 0 && !inst->sig.small_imm_a && inst->alu.add.a.raddr == raddr) ||
+ (add_nsrc > 1 && !inst->sig.small_imm_b && inst->alu.add.b.raddr == raddr) ||
+ (mul_nsrc > 0 && !inst->sig.small_imm_c && inst->alu.mul.a.raddr == raddr) ||
+ (mul_nsrc > 1 && !inst->sig.small_imm_d && inst->alu.mul.b.raddr == raddr);
+}
+
+bool
+v3d71_qpu_writes_waddr_explicitly(const struct v3d_device_info *devinfo,
+ const struct v3d_qpu_instr *inst,
+ uint8_t waddr)
+{
+ if (inst->type != V3D_QPU_INSTR_TYPE_ALU)
+ return false;
+
+ if (v3d_qpu_add_op_has_dst(inst->alu.add.op) &&
+ !inst->alu.add.magic_write &&
+ inst->alu.add.waddr == waddr) {
+ return true;
+ }
+
+ if (v3d_qpu_mul_op_has_dst(inst->alu.mul.op) &&
+ !inst->alu.mul.magic_write &&
+ inst->alu.mul.waddr == waddr) {
+ return true;
+ }
+
+ if (v3d_qpu_sig_writes_address(devinfo, &inst->sig) &&
+ !inst->sig_magic && inst->sig_addr == waddr) {
+ return true;
+ }
+
+ return false;
}
bool