freedreno/ir3: Add support for disasm of cat2 float32 immediates.
authorEric Anholt <eric@anholt.net>
Fri, 24 Apr 2020 18:45:31 +0000 (11:45 -0700)
committerMarge Bot <eric+marge@anholt.net>
Mon, 27 Apr 2020 19:35:00 +0000 (19:35 +0000)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4736>

src/freedreno/ir3/disasm-a3xx.c
src/freedreno/ir3/instr-a3xx.h
src/freedreno/ir3/ir3.h
src/freedreno/ir3/ir3_cp.c
src/freedreno/ir3/tests/disasm.c

index 8d4604fa7143cc89b7f4b133c1b239a806824a32..54ed027f55c36f2b0e6822a4c53243d8565ac0dc 100644 (file)
@@ -88,7 +88,23 @@ struct disasm_ctx {
        unsigned instructions;
 };
 
-static void print_reg(struct disasm_ctx *ctx, reg_t reg, bool full, bool r,
+static const char *float_imms[] = {
+       "0.0",
+       "0.5",
+       "1.0",
+       "2.0",
+       "e",
+       "pi",
+       "1/pi",
+       "1/log2(e)",
+       "log2(e)",
+       "1/log2(10)",
+       "log2(10)",
+       "4.0",
+};
+
+static void print_reg(struct disasm_ctx *ctx, reg_t reg, bool full,
+               bool is_float, bool r,
                bool c, bool im, bool neg, bool abs, bool addr_rel)
 {
        const char type = c ? 'c' : 'r';
@@ -107,7 +123,11 @@ static void print_reg(struct disasm_ctx *ctx, reg_t reg, bool full, bool r,
                fprintf(ctx->out, "(r)");
 
        if (im) {
-               fprintf(ctx->out, "%d", reg.iim_val);
+               if (is_float && full && reg.iim_val < ARRAY_SIZE(float_imms)) {
+                       fprintf(ctx->out, "(%s)", float_imms[reg.iim_val]);
+               } else {
+                       fprintf(ctx->out, "%d", reg.iim_val);
+               }
        } else if (addr_rel) {
                /* I would just use %+d but trying to make it diff'able with
                 * libllvm-a3xx...
@@ -146,7 +166,7 @@ static reg_t idxreg(unsigned idx)
 static void print_reg_dst(struct disasm_ctx *ctx, reg_t reg, bool full, bool addr_rel)
 {
        reg = idxreg(regidx(reg) + ctx->repeatidx);
-       print_reg(ctx, reg, full, false, false, false, false, false, addr_rel);
+       print_reg(ctx, reg, full, false, false, false, false, false, false, addr_rel);
 }
 
 /* TODO switch to using reginfo struct everywhere, since more readable
@@ -158,6 +178,7 @@ struct reginfo {
        bool full;
        bool r;
        bool c;
+       bool f; /* src reg is interpreted as float, used for printing immediates */
        bool im;
        bool neg;
        bool abs;
@@ -171,7 +192,7 @@ static void print_src(struct disasm_ctx *ctx, struct reginfo *info)
        if (info->r)
                reg = idxreg(regidx(info->reg) + ctx->repeatidx);
 
-       print_reg(ctx, reg, info->full, info->r, info->c, info->im,
+       print_reg(ctx, reg, info->full, info->f, info->r, info->c, info->im,
                        info->neg, info->abs, info->addr_rel);
 }
 
@@ -273,6 +294,7 @@ static void print_instr_cat1(struct disasm_ctx *ctx, instr_t *instr)
 static void print_instr_cat2(struct disasm_ctx *ctx, instr_t *instr)
 {
        instr_cat2_t *cat2 = &instr->cat2;
+       int opc = _OPC(2, cat2->opc);
        static const char *cond[] = {
                        "lt",
                        "le",
@@ -283,7 +305,7 @@ static void print_instr_cat2(struct disasm_ctx *ctx, instr_t *instr)
                        "?6?",
        };
 
-       switch (_OPC(2, cat2->opc)) {
+       switch (opc) {
        case OPC_CMPS_F:
        case OPC_CMPS_U:
        case OPC_CMPS_S:
@@ -303,6 +325,7 @@ static void print_instr_cat2(struct disasm_ctx *ctx, instr_t *instr)
        struct reginfo src1 = {
                .full = cat2->full,
                .r = cat2->repeat ? cat2->src1_r : 0,
+               .f = is_cat2_float(opc),
                .im = cat2->src1_im,
                .abs = cat2->src1_abs,
                .neg = cat2->src1_neg,
@@ -323,11 +346,12 @@ static void print_instr_cat2(struct disasm_ctx *ctx, instr_t *instr)
        struct reginfo src2 = {
                .r = cat2->repeat ? cat2->src2_r : 0,
                .full = cat2->full,
+               .f = is_cat2_float(opc),
                .abs = cat2->src2_abs,
                .neg = cat2->src2_neg,
                .im = cat2->src2_im,
        };
-       switch (_OPC(2, cat2->opc)) {
+       switch (opc) {
        case OPC_ABSNEG_F:
        case OPC_ABSNEG_S:
        case OPC_CLZ_B:
index f36c73b88e243bf806613c7a4f445338a3538abb..565b296739f8adb2300dd5ea1aaf3cb8c6211c13 100644 (file)
@@ -1050,6 +1050,43 @@ static inline bool is_isam(opc_t opc)
        }
 }
 
+
+static inline bool is_cat2_float(opc_t opc)
+{
+       switch (opc) {
+       case OPC_ADD_F:
+       case OPC_MIN_F:
+       case OPC_MAX_F:
+       case OPC_MUL_F:
+       case OPC_SIGN_F:
+       case OPC_CMPS_F:
+       case OPC_ABSNEG_F:
+       case OPC_CMPV_F:
+       case OPC_FLOOR_F:
+       case OPC_CEIL_F:
+       case OPC_RNDNE_F:
+       case OPC_RNDAZ_F:
+       case OPC_TRUNC_F:
+               return true;
+
+       default:
+               return false;
+       }
+}
+
+static inline bool is_cat3_float(opc_t opc)
+{
+       switch (opc) {
+       case OPC_MAD_F16:
+       case OPC_MAD_F32:
+       case OPC_SEL_F16:
+       case OPC_SEL_F32:
+               return true;
+       default:
+               return false;
+       }
+}
+
 int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out, unsigned gpu_id);
 
 #endif /* INSTR_A3XX_H_ */
index 441758882008e45b4045af0f23842d7816d9b74a..0f3bb54f31652fa9fef8ea5ba885a56f9a01eb54 100644 (file)
@@ -957,42 +957,6 @@ static inline bool ir3_cat2_int(opc_t opc)
        }
 }
 
-static inline bool ir3_cat2_float(opc_t opc)
-{
-       switch (opc) {
-       case OPC_ADD_F:
-       case OPC_MIN_F:
-       case OPC_MAX_F:
-       case OPC_MUL_F:
-       case OPC_SIGN_F:
-       case OPC_CMPS_F:
-       case OPC_ABSNEG_F:
-       case OPC_CMPV_F:
-       case OPC_FLOOR_F:
-       case OPC_CEIL_F:
-       case OPC_RNDNE_F:
-       case OPC_RNDAZ_F:
-       case OPC_TRUNC_F:
-               return true;
-
-       default:
-               return false;
-       }
-}
-
-static inline bool ir3_cat3_float(opc_t opc)
-{
-       switch (opc) {
-       case OPC_MAD_F16:
-       case OPC_MAD_F32:
-       case OPC_SEL_F16:
-       case OPC_SEL_F32:
-               return true;
-       default:
-               return false;
-       }
-}
-
 /* map cat2 instruction to valid abs/neg flags: */
 static inline unsigned ir3_cat2_absneg(opc_t opc)
 {
index 782be12c1928ee1a32797338c00b0a9dcfa5dfa9..22023b0ac674b92fdc9ae6530cd8a934921880e9 100644 (file)
@@ -478,8 +478,8 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr,
                if (!valid_flags(instr, n, new_flags)) {
                        /* See if lowering an immediate to const would help. */
                        if (valid_flags(instr, n, (new_flags & ~IR3_REG_IMMED) | IR3_REG_CONST)) {
-                               bool f_opcode = (ir3_cat2_float(instr->opc) ||
-                                               ir3_cat3_float(instr->opc)) ? true : false;
+                               bool f_opcode = (is_cat2_float(instr->opc) ||
+                                               is_cat3_float(instr->opc)) ? true : false;
 
                                debug_assert(new_flags & IR3_REG_IMMED);
 
@@ -533,7 +533,7 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr,
                        if (src->cat1.dst_type == TYPE_F16) {
                                if (instr->opc == OPC_MOV && !type_float(instr->cat1.src_type))
                                        return false;
-                               if (!ir3_cat2_float(instr->opc) && !ir3_cat3_float(instr->opc))
+                               if (!is_cat2_float(instr->opc) && !is_cat3_float(instr->opc))
                                        return false;
                        }
 
@@ -594,8 +594,8 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr,
 
                                return true;
                        } else if (valid_flags(instr, n, (new_flags & ~IR3_REG_IMMED) | IR3_REG_CONST)) {
-                               bool f_opcode = (ir3_cat2_float(instr->opc) ||
-                                               ir3_cat3_float(instr->opc)) ? true : false;
+                               bool f_opcode = (is_cat2_float(instr->opc) ||
+                                               is_cat3_float(instr->opc)) ? true : false;
 
                                /* See if lowering an immediate to const would help. */
                                instr->regs[n+1] = lower_immed(ctx, src_reg, new_flags, f_opcode);
index b6aa5ed39d5f755b1c5db86e039a60be78af811a..ee94578391ecaedfca6b5486b128a568eedeefa0 100644 (file)
@@ -77,6 +77,20 @@ static const struct test {
        /* discard stuff */
        INSTR_6XX(42b400f8_20010004, "cmps.s.eq p0.x, r1.x, 1"),
        INSTR_6XX(02800000_00000000, "kill p0.x"),
+
+       /* Immediates */
+       INSTR_6XX(40100007_68000008, "add.f r1.w, r2.x, (neg)(0.0)"),
+       INSTR_6XX(40100007_68010008, "add.f r1.w, r2.x, (neg)(0.5)"),
+       INSTR_6XX(40100007_68020008, "add.f r1.w, r2.x, (neg)(1.0)"),
+       INSTR_6XX(40100007_68030008, "add.f r1.w, r2.x, (neg)(2.0)"),
+       INSTR_6XX(40100007_68040008, "add.f r1.w, r2.x, (neg)(e)"),
+       INSTR_6XX(40100007_68050008, "add.f r1.w, r2.x, (neg)(pi)"),
+       INSTR_6XX(40100007_68060008, "add.f r1.w, r2.x, (neg)(1/pi)"),
+       INSTR_6XX(40100007_68070008, "add.f r1.w, r2.x, (neg)(1/log2(e))"),
+       INSTR_6XX(40100007_68080008, "add.f r1.w, r2.x, (neg)(log2(e))"),
+       INSTR_6XX(40100007_68090008, "add.f r1.w, r2.x, (neg)(1/log2(10))"),
+       INSTR_6XX(40100007_680a0008, "add.f r1.w, r2.x, (neg)(log2(10))"),
+       INSTR_6XX(40100007_680b0008, "add.f r1.w, r2.x, (neg)(4.0)"),
 };
 
 static void