panfrost/midgard: Add shifting int modifiers

As a source modifier, shift allows shifting a value left by the bit
size, useful in conjunction with a greater register mode, for instance
to implement `upsample`. As a concrete example, the following OpenCL:

   ushort hr0 = /* ... */, uint r1 = /* ... */;
   uint r2 = (convert_uint(hr0) << 16) ^ b;

compiles to the following Midgard assembly:

   ixor r, (hr0) << 16, b

In reverse, the ".hi" output modifier shifts the value right by the bit
size, leaving just the carry/overflow at the bottom. To implement *_hi
functions in OpenCL (for <64-bit), we do arithmetic in the 2x higher
mode with the .hi modifier. (For 64-bit, things are hairier, since there
is not an 128-bit int mode).

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
This commit is contained in:
Alyssa Rosenzweig 2019-06-05 15:20:26 -07:00
parent 6780481a3f
commit 2d0bda0885
2 changed files with 14 additions and 18 deletions

View file

@ -143,7 +143,14 @@ static char *outmod_names_int[4] = {
".isat",
".usat",
"",
".unk3"
".hi"
};
static char *srcmod_names_int[4] = {
"sext(",
"zext(",
"",
"("
};
static void
@ -176,20 +183,7 @@ print_vector_src(unsigned src_binary, bool out_high,
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;
}
printf("%s", srcmod_names_int[int_mod]);
} else {
if (src->mod & MIDGARD_FLOAT_MOD_NEG)
printf("-");
@ -284,7 +278,9 @@ print_vector_src(unsigned src_binary, bool out_high,
/* Since we wrapped with a function-looking thing */
if ((is_int && (int_mod != midgard_int_normal))
if (is_int && int_mod == midgard_int_shift)
printf(") << %d", bits);
else if ((is_int && (int_mod != midgard_int_normal))
|| (!is_int && src->mod & MIDGARD_FLOAT_MOD_ABS))
printf(")");
}

View file

@ -180,7 +180,7 @@ typedef enum {
midgard_outmod_int_saturate = 0,
midgard_outmod_uint_saturate = 1,
midgard_outmod_int_wrap = 2,
/* 0x3 unknown */
midgard_outmod_int_high = 3, /* Overflowed portion */
} midgard_outmod_int;
typedef enum {
@ -200,7 +200,7 @@ typedef enum {
midgard_int_sign_extend = 0,
midgard_int_zero_extend = 1,
midgard_int_normal = 2,
midgard_int_reserved = 3
midgard_int_shift = 3
} midgard_int_mod;
#define MIDGARD_FLOAT_MOD_ABS (1 << 0)