Module: Mesa
Branch: master
Commit: e7471ce77612b746b01a4926a7d04b0921044ae0
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=e7471ce77612b746b01a4926a7d04b0921044ae0

Author: Connor Abbott <[email protected]>
Date:   Fri Oct 23 14:07:04 2020 +0200

ir3: Support assembling & disassembling getspid/getwid

These aren't useful yet in the driver, but were useful for
reverse-engineering how private memory works.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7386>

---

 src/freedreno/ir3/disasm-a3xx.c  | 42 +++++++++++++---------
 src/freedreno/ir3/ir3.c          | 78 ++++++++++++++++++++++------------------
 src/freedreno/ir3/ir3_lexer.l    |  2 ++
 src/freedreno/ir3/ir3_parser.y   |  9 +++++
 src/freedreno/ir3/tests/disasm.c |  4 +++
 5 files changed, 84 insertions(+), 51 deletions(-)

diff --git a/src/freedreno/ir3/disasm-a3xx.c b/src/freedreno/ir3/disasm-a3xx.c
index 420d27442a8..66699e66880 100644
--- a/src/freedreno/ir3/disasm-a3xx.c
+++ b/src/freedreno/ir3/disasm-a3xx.c
@@ -1185,6 +1185,7 @@ static void print_instr_cat6_a6xx(struct disasm_ctx *ctx, 
instr_t *instr)
        instr_cat6_a6xx_t *cat6 = &instr->cat6_a6xx;
        struct reginfo src1, src2, ssbo;
        uint32_t opc = _OPC(6, cat6->opc);
+       bool is_id = opc == OPC_GETSPID || opc == OPC_GETWID;
        bool uses_type = opc != OPC_LDC;
 
        static const struct {
@@ -1229,35 +1230,44 @@ static void print_instr_cat6_a6xx(struct disasm_ctx 
*ctx, instr_t *instr)
        memset(&ssbo, 0, sizeof(ssbo));
 
        if (uses_type) {
-               fprintf(ctx->out, ".%s", cat6->typed ? "typed" : "untyped");
-               fprintf(ctx->out, ".%dd", cat6->d + 1);
+               if (!is_id) {
+                       fprintf(ctx->out, ".%s", cat6->typed ? "typed" : 
"untyped");
+                       fprintf(ctx->out, ".%dd", cat6->d + 1);
+               }
                fprintf(ctx->out, ".%s", type[cat6->type]);
        } else {
                fprintf(ctx->out, ".offset%d", cat6->d);
        }
-       fprintf(ctx->out, ".%u", cat6->type_size + 1);
 
-       fprintf(ctx->out, ".%s", desc_features[cat6->desc_mode].name);
-       if (bindless)
-               fprintf(ctx->out, ".base%d", cat6->base);
+       if (!is_id) {
+               fprintf(ctx->out, ".%u", cat6->type_size + 1);
+               fprintf(ctx->out, ".%s", desc_features[cat6->desc_mode].name);
+
+               if (bindless)
+                       fprintf(ctx->out, ".base%d", cat6->base);
+       }
+
        fprintf(ctx->out, " ");
 
        src2.reg = (reg_t)(cat6->src2);
        src2.full = type_full;
        print_src(ctx, &src2);
-       fprintf(ctx->out, ", ");
 
-       if (opc != OPC_RESINFO) {
-               src1.reg = (reg_t)(cat6->src1);
-               src1.full = true; // XXX
-               print_src(ctx, &src1);
+       if (!is_id) {
                fprintf(ctx->out, ", ");
-       }
 
-       ssbo.reg = (reg_t)(cat6->ssbo);
-       ssbo.im = !indirect_ssbo;
-       ssbo.full = true;
-       print_src(ctx, &ssbo);
+               if (opc != OPC_RESINFO) {
+                       src1.reg = (reg_t)(cat6->src1);
+                       src1.full = true; // XXX
+                       print_src(ctx, &src1);
+                       fprintf(ctx->out, ", ");
+               }
+
+               ssbo.reg = (reg_t)(cat6->ssbo);
+               ssbo.im = !indirect_ssbo;
+               ssbo.full = true;
+               print_src(ctx, &ssbo);
+       }
 
        if (debug & PRINT_VERBOSE) {
                fprintf(ctx->out, " (pad1=%x, pad2=%x, pad3=%x, pad4=%x, 
pad5=%x)",
diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c
index 8966e7afecc..05720b44dc2 100644
--- a/src/freedreno/ir3/ir3.c
+++ b/src/freedreno/ir3/ir3.c
@@ -537,53 +537,57 @@ static int emit_cat5(struct ir3_instruction *instr, void 
*ptr,
 static int emit_cat6_a6xx(struct ir3_instruction *instr, void *ptr,
                struct ir3_info *info)
 {
-       struct ir3_register *ssbo;
        instr_cat6_a6xx_t *cat6 = ptr;
 
-       ssbo = instr->regs[1];
-
        cat6->type      = instr->cat6.type;
-       cat6->d         = instr->cat6.d - (instr->opc == OPC_LDC ? 0 : 1);
-       cat6->typed     = instr->cat6.typed;
-       cat6->type_size = instr->cat6.iim_val - 1;
        cat6->opc       = instr->opc;
        cat6->jmp_tgt   = !!(instr->flags & IR3_INSTR_JP);
        cat6->sync      = !!(instr->flags & IR3_INSTR_SY);
        cat6->opc_cat   = 6;
 
-       cat6->ssbo = reg(ssbo, info, instr->repeat, IR3_REG_IMMED);
-
-       /* For unused sources in an opcode, initialize contents with the ir3 
dest
-        * reg
-        */
-       switch (instr->opc) {
-       case OPC_RESINFO:
-               cat6->src1 = reg(instr->regs[0], info, instr->repeat, 0);
+       if (instr->opc == OPC_GETWID || instr->opc == OPC_GETSPID) {
                cat6->src2 = reg(instr->regs[0], info, instr->repeat, 0);
-               break;
-       case OPC_LDC:
-       case OPC_LDIB:
-               cat6->src1 = reg(instr->regs[2], info, instr->repeat, 0);
-               cat6->src2 = reg(instr->regs[0], info, instr->repeat, 0);
-               break;
-       default:
-               cat6->src1 = reg(instr->regs[2], info, instr->repeat, 0);
-               cat6->src2 = reg(instr->regs[3], info, instr->repeat, 0);
-               break;
-       }
+               cat6->src1 = cat6->ssbo = 0;
+               cat6->d = cat6->typed = cat6->type_size = 0;
+       } else {
+               struct ir3_register *ssbo = instr->regs[1];
+               cat6->d         = instr->cat6.d - (instr->opc == OPC_LDC ? 0 : 
1);
+               cat6->typed     = instr->cat6.typed;
+               cat6->type_size = instr->cat6.iim_val - 1;
+               cat6->ssbo = reg(ssbo, info, instr->repeat, IR3_REG_IMMED);
+
+               /* For unused sources in an opcode, initialize contents with 
the ir3
+                * dest reg
+                */
+               switch (instr->opc) {
+               case OPC_RESINFO:
+                       cat6->src1 = reg(instr->regs[0], info, instr->repeat, 
0);
+                       cat6->src2 = reg(instr->regs[0], info, instr->repeat, 
0);
+                       break;
+               case OPC_LDC:
+               case OPC_LDIB:
+                       cat6->src1 = reg(instr->regs[2], info, instr->repeat, 
0);
+                       cat6->src2 = reg(instr->regs[0], info, instr->repeat, 
0);
+                       break;
+               default:
+                       cat6->src1 = reg(instr->regs[2], info, instr->repeat, 
0);
+                       cat6->src2 = reg(instr->regs[3], info, instr->repeat, 
0);
+                       break;
+               }
 
-       if (instr->flags & IR3_INSTR_B) {
-               if (ssbo->flags & IR3_REG_IMMED) {
-                       cat6->desc_mode = CAT6_BINDLESS_IMM;
+               if (instr->flags & IR3_INSTR_B) {
+                       if (ssbo->flags & IR3_REG_IMMED) {
+                               cat6->desc_mode = CAT6_BINDLESS_IMM;
+                       } else {
+                               cat6->desc_mode = CAT6_BINDLESS_UNIFORM;
+                       }
+                       cat6->base = instr->cat6.base;
                } else {
-                       cat6->desc_mode = CAT6_BINDLESS_UNIFORM;
+                       if (ssbo->flags & IR3_REG_IMMED)
+                               cat6->desc_mode = CAT6_IMM;
+                       else
+                               cat6->desc_mode = CAT6_UNIFORM;
                }
-               cat6->base = instr->cat6.base;
-       } else {
-               if (ssbo->flags & IR3_REG_IMMED)
-                       cat6->desc_mode = CAT6_IMM;
-               else
-                       cat6->desc_mode = CAT6_UNIFORM;
        }
 
        switch (instr->opc) {
@@ -614,6 +618,8 @@ static int emit_cat6_a6xx(struct ir3_instruction *instr, 
void *ptr,
                cat6->pad5 = 0x2;
                break;
        case OPC_LDC:
+       case OPC_GETWID:
+       case OPC_GETSPID:
                cat6->pad1 = 0x0;
                cat6->pad3 = 0x4;
                cat6->pad5 = 0x2;
@@ -658,6 +664,8 @@ static int emit_cat6(struct ir3_instruction *instr, void 
*ptr,
                case OPC_LDIB:
                case OPC_LDC:
                case OPC_RESINFO:
+               case OPC_GETSPID:
+               case OPC_GETWID:
                        return emit_cat6_a6xx(instr, ptr, info);
                default:
                        break;
diff --git a/src/freedreno/ir3/ir3_lexer.l b/src/freedreno/ir3/ir3_lexer.l
index f93d25b5328..b0ba0032c4a 100644
--- a/src/freedreno/ir3/ir3_lexer.l
+++ b/src/freedreno/ir3/ir3_lexer.l
@@ -264,6 +264,8 @@ static int parse_reg(const char *str)
 "stib"                            return TOKEN(T_OP_STIB);
 "ldc"                             return TOKEN(T_OP_LDC);
 "ldlv"                            return TOKEN(T_OP_LDLV);
+"getspid"                         return TOKEN(T_OP_GETSPID);
+"getwid"                          return TOKEN(T_OP_GETWID);
 
 "f16"                             return TOKEN(T_TYPE_F16);
 "f32"                             return TOKEN(T_TYPE_F32);
diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y
index 945a3e0d1ce..fbb0c3f6fae 100644
--- a/src/freedreno/ir3/ir3_parser.y
+++ b/src/freedreno/ir3/ir3_parser.y
@@ -439,6 +439,8 @@ static void print_token(FILE *file, int type, YYSTYPE value)
 %token <tok> T_OP_STIB
 %token <tok> T_OP_LDC
 %token <tok> T_OP_LDLV
+%token <tok> T_OP_GETSPID
+%token <tok> T_OP_GETWID
 
 /* type qualifiers: */
 %token <tok> T_TYPE_F16
@@ -811,6 +813,12 @@ cat6_atomic:       T_OP_ATOMIC_ADD     { 
new_instr(OPC_ATOMIC_ADD); }    cat6_at
 |                  T_OP_ATOMIC_OR      { new_instr(OPC_ATOMIC_OR); }     
cat6_atomic_l_g cat6_type dst_reg ',' 'l' '[' reg cat6_offset ']' ',' cat6_immed
 |                  T_OP_ATOMIC_XOR     { new_instr(OPC_ATOMIC_XOR); }    
cat6_atomic_l_g cat6_type dst_reg ',' 'l' '[' reg cat6_offset ']' ',' cat6_immed
 
+cat6_id_opc:
+                   T_OP_GETSPID { new_instr(OPC_GETSPID); }
+|                  T_OP_GETWID  { new_instr(OPC_GETWID); }
+
+cat6_id:           cat6_id_opc cat6_type dst_reg
+
 cat6_todo:         T_OP_G2L                 { new_instr(OPC_G2L); }
 |                  T_OP_L2G                 { new_instr(OPC_L2G); }
 |                  T_OP_RESFMT              { new_instr(OPC_RESFMT); }
@@ -824,6 +832,7 @@ cat6_instr:        cat6_load
 |                  cat6_storeib
 |                  cat6_prefetch
 |                  cat6_atomic
+|                  cat6_id
 |                  cat6_todo
 
 reg:               T_REGISTER     { $$ = new_reg($1, 0); }
diff --git a/src/freedreno/ir3/tests/disasm.c b/src/freedreno/ir3/tests/disasm.c
index 1b16fad6957..1747f05393b 100644
--- a/src/freedreno/ir3/tests/disasm.c
+++ b/src/freedreno/ir3/tests/disasm.c
@@ -192,6 +192,10 @@ static const struct test {
        INSTR_6XX(a0c81f07_0100000b, "sam.s2en (f32)(xyzw)r1.w, r1.y, hr2.x"), 
/* sam.s2en.mode0 (f32)(xyzw)r1.w, r1.y, hr2.x */
        /* 
dEQP-GLES31.functional.shaders.opaque_type_indexing.sampler.dynamically_uniform.fragment.sampler2d
 */
        INSTR_6XX(a0c81f07_8100000b, "sam.s2en.uniform (f32)(xyzw)r1.w, r1.y, 
hr2.x"), /* sam.s2en.mode4 (f32)(xyzw)r1.w, r1.y, hr2.x */
+
+       /* Custom test since we've never seen the blob emit these. */
+       INSTR_6XX(c0260004_00490000, "getspid.u32 r1.x"),
+       INSTR_6XX(c0260005_00494000, "getwid.u32 r1.y"),
 };
 
 static void

_______________________________________________
mesa-commit mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to