#include "midgard_quirks.h"
#include "disassemble.h"
#include "helpers.h"
+#include "util/bitscan.h"
#include "util/half_float.h"
#include "util/u_math.h"
}
static void
+print_scalar_constant(FILE *fp, unsigned src_binary,
+ const midgard_constants *consts,
+ midgard_scalar_alu *alu)
+{
+ midgard_scalar_alu_src *src = (midgard_scalar_alu_src *)&src_binary;
+ unsigned mod = 0;
+
+ if (!midgard_is_integer_op(alu->op)) {
+ if (src->abs)
+ mod |= MIDGARD_FLOAT_MOD_ABS;
+ if (src->negate)
+ mod |= MIDGARD_FLOAT_MOD_NEG;
+ } else {
+ mod = midgard_int_normal;
+ }
+
+ fprintf(fp, "#");
+ mir_print_constant_component(fp, consts, src->component,
+ src->full ?
+ midgard_reg_mode_32 : midgard_reg_mode_16,
+ false, mod, alu->op);
+}
+
+static void
+print_vector_constants(FILE *fp, unsigned src_binary,
+ const midgard_constants *consts,
+ midgard_vector_alu *alu)
+{
+ midgard_vector_alu_src *src = (midgard_vector_alu_src *)&src_binary;
+ unsigned bits = bits_for_mode_halved(alu->reg_mode, src->half);
+ unsigned max_comp = MIN2((sizeof(*consts) * 8) / bits, 8);
+ unsigned comp_mask, num_comp = 0;
+
+ assert(consts);
+
+ comp_mask = effective_writemask(alu, condense_writemask(alu->mask, bits));
+ num_comp = util_bitcount(comp_mask);
+
+ fprintf(fp, "#");
+ if (num_comp > 1)
+ fprintf(fp, "vec%d(", num_comp);
+
+ bool first = true;
+
+ for (unsigned i = 0; i < max_comp; ++i) {
+ if (!(comp_mask & (1 << i))) continue;
+
+ unsigned c = (src->swizzle >> (i * 2)) & 3;
+
+ if (first)
+ first = false;
+ else
+ fprintf(fp, ", ");
+
+ mir_print_constant_component(fp, consts, c, alu->reg_mode,
+ src->half, src->mod, alu->op);
+ }
+
+ if (num_comp > 1)
+ fprintf(fp, ")");
+}
+
+static void
print_vector_src(FILE *fp, unsigned src_binary,
midgard_reg_mode mode, unsigned reg,
midgard_dest_override override, bool is_int)
static void
print_vector_field(FILE *fp, const char *name, uint16_t *words, uint16_t reg_word,
- unsigned tabs)
+ const midgard_constants *consts, unsigned tabs)
{
midgard_reg_info *reg_info = (midgard_reg_info *)®_word;
midgard_vector_alu *alu_field = (midgard_vector_alu *) words;
fprintf(fp, ", ");
bool is_int = midgard_is_integer_op(alu_field->op);
- print_vector_src(fp, alu_field->src1, mode, reg_info->src1_reg, override, is_int);
+
+ if (reg_info->src1_reg == 26)
+ print_vector_constants(fp, alu_field->src1, consts, alu_field);
+ else
+ print_vector_src(fp, alu_field->src1, mode, reg_info->src1_reg, override, is_int);
fprintf(fp, ", ");
if (reg_info->src2_imm) {
uint16_t imm = decode_vector_imm(reg_info->src2_reg, alu_field->src2 >> 2);
print_immediate(fp, imm);
+ } else if (reg_info->src2_reg == 26) {
+ print_vector_constants(fp, alu_field->src2, consts, alu_field);
} else {
print_vector_src(fp, alu_field->src2, mode,
reg_info->src2_reg, override, is_int);
static void
print_scalar_field(FILE *fp, const char *name, uint16_t *words, uint16_t reg_word,
- unsigned tabs)
+ const midgard_constants *consts, unsigned tabs)
{
midgard_reg_info *reg_info = (midgard_reg_info *)®_word;
midgard_scalar_alu *alu_field = (midgard_scalar_alu *) words;
fprintf(fp, ".%c, ", components[c]);
- print_scalar_src(fp, alu_field->src1, reg_info->src1_reg);
+ if (reg_info->src1_reg == 26)
+ print_scalar_constant(fp, alu_field->src1, consts, alu_field);
+ else
+ print_scalar_src(fp, alu_field->src1, reg_info->src1_reg);
fprintf(fp, ", ");
uint16_t imm = decode_scalar_imm(reg_info->src2_reg,
alu_field->src2);
print_immediate(fp, imm);
+ } else if (reg_info->src2_reg == 26) {
+ print_scalar_constant(fp, alu_field->src2, consts, alu_field);
} else
print_scalar_src(fp, alu_field->src2, reg_info->src2_reg);
unsigned num_fields = num_alu_fields_enabled(control_word);
uint16_t *word_ptr = beginning_ptr + num_fields;
unsigned num_words = 2 + num_fields;
+ const midgard_constants *consts = NULL;
bool branch_forward = false;
+ if ((control_word >> 17) & 1)
+ num_words += 3;
+
+ if ((control_word >> 19) & 1)
+ num_words += 2;
+
+ if ((control_word >> 21) & 1)
+ num_words += 3;
+
+ if ((control_word >> 23) & 1)
+ num_words += 2;
+
+ if ((control_word >> 25) & 1)
+ num_words += 3;
+
+ if ((control_word >> 26) & 1)
+ num_words += 1;
+
+ if ((control_word >> 27) & 1)
+ num_words += 3;
+
+ if (num_quad_words > (num_words + 7) / 8) {
+ assert(num_quad_words == (num_words + 15) / 8);
+ //Assume that the extra quadword is constants
+ consts = (midgard_constants *)(words + (4 * num_quad_words - 4));
+ }
+
if ((control_word >> 16) & 1)
fprintf(fp, "unknown bit 16 enabled\n");
if ((control_word >> 17) & 1) {
- print_vector_field(fp, "vmul", word_ptr, *beginning_ptr, tabs);
+ print_vector_field(fp, "vmul", word_ptr, *beginning_ptr, consts, tabs);
beginning_ptr += 1;
word_ptr += 3;
- num_words += 3;
}
if ((control_word >> 18) & 1)
fprintf(fp, "unknown bit 18 enabled\n");
if ((control_word >> 19) & 1) {
- print_scalar_field(fp, "sadd", word_ptr, *beginning_ptr, tabs);
+ print_scalar_field(fp, "sadd", word_ptr, *beginning_ptr, consts, tabs);
beginning_ptr += 1;
word_ptr += 2;
- num_words += 2;
}
if ((control_word >> 20) & 1)
fprintf(fp, "unknown bit 20 enabled\n");
if ((control_word >> 21) & 1) {
- print_vector_field(fp, "vadd", word_ptr, *beginning_ptr, tabs);
+ print_vector_field(fp, "vadd", word_ptr, *beginning_ptr, consts, tabs);
beginning_ptr += 1;
word_ptr += 3;
- num_words += 3;
}
if ((control_word >> 22) & 1)
fprintf(fp, "unknown bit 22 enabled\n");
if ((control_word >> 23) & 1) {
- print_scalar_field(fp, "smul", word_ptr, *beginning_ptr, tabs);
+ print_scalar_field(fp, "smul", word_ptr, *beginning_ptr, consts, tabs);
beginning_ptr += 1;
word_ptr += 2;
- num_words += 2;
}
if ((control_word >> 24) & 1)
fprintf(fp, "unknown bit 24 enabled\n");
if ((control_word >> 25) & 1) {
- print_vector_field(fp, "lut", word_ptr, *beginning_ptr, tabs);
+ print_vector_field(fp, "lut", word_ptr, *beginning_ptr, consts, tabs);
word_ptr += 3;
- num_words += 3;
}
if ((control_word >> 26) & 1) {
branch_forward |= print_compact_branch_writeout_field(fp, *word_ptr);
word_ptr += 1;
- num_words += 1;
}
if ((control_word >> 27) & 1) {
branch_forward |= print_extended_branch_writeout_field(fp, (uint8_t *) word_ptr, next);
word_ptr += 3;
- num_words += 3;
}
- if (num_quad_words > (num_words + 7) / 8) {
- assert(num_quad_words == (num_words + 15) / 8);
- //Assume that the extra quadword is constants
- void *consts = words + (4 * num_quad_words - 4);
-
- if (is_embedded_constant_int) {
- if (is_embedded_constant_half) {
- int16_t *sconsts = (int16_t *) consts;
- fprintf(fp, "sconstants %d, %d, %d, %d\n",
- sconsts[0],
- sconsts[1],
- sconsts[2],
- sconsts[3]);
- } else {
- uint32_t *iconsts = (uint32_t *) consts;
- fprintf(fp, "iconstants 0x%X, 0x%X, 0x%X, 0x%X\n",
- iconsts[0],
- iconsts[1],
- iconsts[2],
- iconsts[3]);
- }
- } else {
- if (is_embedded_constant_half) {
- uint16_t *hconsts = (uint16_t *) consts;
- fprintf(fp, "hconstants %g, %g, %g, %g\n",
- _mesa_half_to_float(hconsts[0]),
- _mesa_half_to_float(hconsts[1]),
- _mesa_half_to_float(hconsts[2]),
- _mesa_half_to_float(hconsts[3]));
- } else {
- uint32_t *fconsts = (uint32_t *) consts;
- fprintf(fp, "fconstants %g, %g, %g, %g\n",
- float_bitcast(fconsts[0]),
- float_bitcast(fconsts[1]),
- float_bitcast(fconsts[2]),
- float_bitcast(fconsts[3]));
- }
-
- }
- }
+ if (consts)
+ fprintf(fp, "uconstants 0x%X, 0x%X, 0x%X, 0x%X\n",
+ consts->u32[0], consts->u32[1],
+ consts->u32[2], consts->u32[3]);
return branch_forward;
}
* SOFTWARE.
*/
+#include <math.h>
+
+#include "util/bitscan.h"
+#include "util/half_float.h"
#include "compiler.h"
#include "helpers.h"
#include "midgard_ops.h"
}
void
+mir_print_constant_component(FILE *fp, const midgard_constants *consts, unsigned c,
+ midgard_reg_mode reg_mode, bool half,
+ unsigned mod, midgard_alu_op op)
+{
+ bool is_sint = false, is_uint = false, is_hex = false;
+ const char *opname = alu_opcode_props[op].name;
+
+ if (opname[0] == 'u') {
+ /* If the opcode starts with a 'u' we are sure we deal with an
+ * unsigned int operation
+ */
+ is_uint = true;
+ } else if (opname[0] == 'i') {
+ /* Bit ops are easier to follow when the constant is printed in
+ * hexadecimal. Other operations starting with a 'i' are
+ * considered to operate on signed integers. That might not
+ * be true for all of them, but it's good enough for traces.
+ */
+ if (op >= midgard_alu_op_iand &&
+ op <= midgard_alu_op_ibitcount8)
+ is_hex = true;
+ else
+ is_sint = true;
+ }
+
+ if (half)
+ reg_mode--;
+
+ switch (reg_mode) {
+ case midgard_reg_mode_64:
+ if (is_sint) {
+ printf("%"PRIi64, consts->i64[c]);
+ } else if (is_uint) {
+ printf("%"PRIu64, consts->u64[c]);
+ } else if (is_hex) {
+ printf("0x%"PRIX64, consts->u64[c]);
+ } else {
+ double v = consts->f64[c];
+
+ if (mod & MIDGARD_FLOAT_MOD_ABS) v = fabs(v);
+ if (mod & MIDGARD_FLOAT_MOD_NEG) v = -v;
+
+ printf("%g", v);
+ }
+ break;
+
+ case midgard_reg_mode_32:
+ if (is_sint) {
+ int64_t v;
+
+ if (half && mod == midgard_int_zero_extend)
+ v = consts->u32[c];
+ else if (half && mod == midgard_int_shift)
+ v = (uint64_t)consts->u32[c] << 32;
+ else
+ v = consts->i32[c];
+
+ printf("%"PRIi64, v);
+ } else if (is_uint || is_hex) {
+ uint64_t v;
+
+ if (half && mod == midgard_int_shift)
+ v = (uint64_t)consts->u32[c] << 32;
+ else
+ v = consts->u32[c];
+
+ printf(is_uint ? "%"PRIu64 : "0x%"PRIX64, v);
+ } else {
+ float v = consts->f32[c];
+
+ if (mod & MIDGARD_FLOAT_MOD_ABS) v = fabsf(v);
+ if (mod & MIDGARD_FLOAT_MOD_NEG) v = -v;
+
+ printf("%g", v);
+ }
+ break;
+
+ case midgard_reg_mode_16:
+ if (is_sint) {
+ int32_t v;
+
+ if (half && mod == midgard_int_zero_extend)
+ v = consts->u16[c];
+ else if (half && mod == midgard_int_shift)
+ v = (uint32_t)consts->u16[c] << 16;
+ else
+ v = consts->i16[c];
+
+ printf("%d", v);
+ } else if (is_uint || is_hex) {
+ uint32_t v;
+
+ if (half && mod == midgard_int_shift)
+ v = (uint32_t)consts->u16[c] << 16;
+ else
+ v = consts->u16[c];
+
+ printf(is_uint ? "%u" : "0x%X", v);
+ } else {
+ float v = _mesa_half_to_float(consts->f16[c]);
+
+ if (mod & MIDGARD_FLOAT_MOD_ABS) v = fabsf(v);
+ if (mod & MIDGARD_FLOAT_MOD_NEG) v = -v;
+
+ printf("%g", v);
+ }
+ break;
+
+ case midgard_reg_mode_8:
+ unreachable("XXX TODO: sort out how 8-bit constant encoding works");
+ break;
+ }
+}
+
+static void
+mir_print_embedded_constant(midgard_instruction *ins, unsigned src_idx)
+{
+ unsigned type_size = mir_bytes_for_mode(ins->alu.reg_mode);
+ midgard_vector_alu_src src;
+
+ assert(src_idx <= 1);
+ if (src_idx == 0)
+ src = vector_alu_from_unsigned(ins->alu.src1);
+ else
+ src = vector_alu_from_unsigned(ins->alu.src2);
+
+ unsigned *swizzle = ins->swizzle[src_idx];
+ unsigned comp_mask = effective_writemask(&ins->alu, ins->mask);
+ unsigned num_comp = util_bitcount(comp_mask);
+ unsigned max_comp = 16 / type_size;
+ bool first = true;
+
+ printf("#");
+
+ if (num_comp > 1)
+ printf("vec%d(", num_comp);
+
+ for (unsigned comp = 0; comp < max_comp; comp++) {
+ if (!(comp_mask & (1 << comp)))
+ continue;
+
+ if (first)
+ first = false;
+ else
+ printf(", ");
+
+ mir_print_constant_component(stdout, &ins->constants,
+ swizzle[comp], ins->alu.reg_mode,
+ src.half, src.mod, ins->alu.op);
+ }
+
+ if (num_comp > 1)
+ printf(")");
+}
+
+void
mir_print_instruction(midgard_instruction *ins)
{
printf("\t");
printf(", ");
- mir_print_index(ins->src[0]);
- mir_print_swizzle(ins->swizzle[0]);
+ unsigned r_constant = SSA_FIXED_REGISTER(REGISTER_CONSTANT);
+
+ if (ins->src[0] == r_constant)
+ mir_print_embedded_constant(ins, 0);
+ else {
+ mir_print_index(ins->src[0]);
+ mir_print_swizzle(ins->swizzle[0]);
+ }
printf(", ");
if (ins->has_inline_constant)
printf("#%d", ins->inline_constant);
+ else if (ins->src[1] == r_constant)
+ mir_print_embedded_constant(ins, 1);
else {
mir_print_index(ins->src[1]);
mir_print_swizzle(ins->swizzle[1]);
mir_print_index(ins->src[3]);
mir_print_swizzle(ins->swizzle[3]);
- if (ins->has_constants) {
- uint32_t *uc = ins->constants.u32;
- float *fc = ins->constants.f32;
-
- if (midgard_is_integer_op(ins->alu.op))
- printf(" <0x%X, 0x%X, 0x%X, 0x%x>", uc[0], uc[1], uc[2], uc[3]);
- else
- printf(" <%f, %f, %f, %f>", fc[0], fc[1], fc[2], fc[3]);
- }
-
if (ins->no_spill)
printf(" /* no spill */");