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:
parent
b453c877d9
commit
422aceb407
3 changed files with 57 additions and 18 deletions
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue