panfrost/midgard: Document sign-extension/zero-extension bits (vector)

For floating point ops, these bits determine the "negate?" and "abs?"
modifiers. For integer ops, it turns out they control how sign/zero
extension work, useful for mixing types.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
Alyssa Rosenzweig 2019-04-22 03:08:25 +00:00
parent b453c877d9
commit 422aceb407
3 changed files with 57 additions and 18 deletions

View file

@ -32,6 +32,7 @@
#include "midgard.h"
#include "midgard-parse.h"
#include "disassemble.h"
#include "helpers.h"
#include "util/half_float.h"
#define DEFINE_CASE(define, str) case define: { printf(str); break; }
@ -110,15 +111,37 @@ print_quad_word(uint32_t *words, unsigned tabs)
static void
print_vector_src(unsigned src_binary, bool out_high,
bool out_half, unsigned reg)
bool out_half, unsigned reg,
bool is_int)
{
midgard_vector_alu_src *src = (midgard_vector_alu_src *)&src_binary;
if (src->negate)
printf("-");
/* Modifiers change meaning depending on the op's context */
if (src->abs)
printf("abs(");
midgard_int_mod int_mod = src->mod;
if (is_int) {
switch (int_mod) {
case midgard_int_sign_extend:
printf("sext(");
break;
case midgard_int_zero_extend:
printf("zext(");
break;
case midgard_int_reserved:
printf("unk(");
break;
case midgard_int_normal:
/* Implicit */
break;
}
} else {
if (src->mod & MIDGARD_FLOAT_MOD_NEG)
printf("-");
if (src->mod & MIDGARD_FLOAT_MOD_ABS)
printf("abs(");
}
//register
@ -173,7 +196,10 @@ print_vector_src(unsigned src_binary, bool out_high,
printf("%c", c[(src->swizzle >> (i * 2)) & 3]);
}
if (src->abs)
/* Since we wrapped with a function-looking thing */
if ((is_int && (int_mod != midgard_int_normal))
|| (!is_int && src->mod & MIDGARD_FLOAT_MOD_ABS))
printf(")");
}
@ -277,7 +303,8 @@ print_vector_field(const char *name, uint16_t *words, uint16_t reg_word,
printf(", ");
print_vector_src(alu_field->src1, out_high, half, reg_info->src1_reg);
bool is_int = midgard_is_integer_op(alu_field->op);
print_vector_src(alu_field->src1, out_high, half, reg_info->src1_reg, is_int);
printf(", ");
@ -286,7 +313,7 @@ print_vector_field(const char *name, uint16_t *words, uint16_t reg_word,
print_immediate(imm);
} else {
print_vector_src(alu_field->src2, out_high, half,
reg_info->src2_reg);
reg_info->src2_reg, is_int);
}
printf("\n");

View file

@ -161,11 +161,22 @@ typedef enum {
midgard_dest_override_none = 2
} midgard_dest_override;
typedef enum {
midgard_int_sign_extend = 0,
midgard_int_zero_extend = 1,
midgard_int_normal = 2,
midgard_int_reserved = 3
} midgard_int_mod;
#define MIDGARD_FLOAT_MOD_ABS (1 << 0)
#define MIDGARD_FLOAT_MOD_NEG (1 << 1)
typedef struct
__attribute__((__packed__))
{
bool abs : 1;
bool negate : 1;
/* Either midgard_int_mod or from midgard_float_mod_*, depending on the
* type of op */
unsigned mod : 2;
/* replicate lower half if dest = half, or low/high half selection if
* dest = full

View file

@ -254,8 +254,7 @@ vector_alu_modifiers(nir_alu_src *src)
if (!src) return blank_alu_src;
midgard_vector_alu_src alu_src = {
.abs = src->abs,
.negate = src->negate,
.mod = (src->abs << 0) | (src->negate << 1),
.rep_low = 0,
.rep_high = 0,
.half = 0, /* TODO */
@ -1474,10 +1473,10 @@ emit_intrinsic(compiler_context *ctx, nir_intrinsic_instr *instr)
emit_mir_instruction(ctx, ins);
}
/* vadd.u2f hr2, abs(hr2), #0 */
/* vadd.u2f hr2, zext(hr2), #0 */
midgard_vector_alu_src alu_src = blank_alu_src;
alu_src.abs = true;
alu_src.mod = midgard_int_zero_extend;
alu_src.half = true;
midgard_instruction u2f = {
@ -1502,7 +1501,7 @@ emit_intrinsic(compiler_context *ctx, nir_intrinsic_instr *instr)
/* vmul.fmul.sat r1, hr2, #0.00392151 */
alu_src.abs = false;
alu_src.mod = 0;
midgard_instruction fmul = {
.type = TAG_ALU_4,
@ -2183,9 +2182,11 @@ vector_to_scalar_source(unsigned u)
midgard_vector_alu_src v;
memcpy(&v, &u, sizeof(v));
/* TODO: Integers */
midgard_scalar_alu_src s = {
.abs = v.abs,
.negate = v.negate,
.abs = v.mod & MIDGARD_FLOAT_MOD_ABS,
.negate = v.mod & MIDGARD_FLOAT_MOD_NEG,
.full = !v.half,
.component = (v.swizzle & 3) << 1
};
@ -2975,7 +2976,7 @@ embedded_to_inline_constant(compiler_context *ctx)
/* We don't know how to handle these with a constant */
if (src->abs || src->negate || src->half || src->rep_low || src->rep_high) {
if (src->mod || src->half || src->rep_low || src->rep_high) {
DBG("Bailing inline constant...\n");
continue;
}