From d968f46997a6c02dff738d6e1e5c69b3b5e9a31f Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 19 Dec 2020 15:36:24 -0800 Subject: [PATCH] freedreno/ir3/parser: Handle half-immed Signed-off-by: Rob Clark Part-of: --- src/freedreno/ir3/ir3.c | 17 +++++++++++ src/freedreno/ir3/ir3_lexer.l | 13 ++++++++ src/freedreno/ir3/ir3_parser.y | 56 +++++++++++++++++++++++++++++++--- 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c index 85c905b9999..879ffa4950e 100644 --- a/src/freedreno/ir3/ir3.c +++ b/src/freedreno/ir3/ir3.c @@ -302,6 +302,23 @@ static int emit_cat2(struct ir3_instruction *instr, void *ptr, cat2->src2_abs = !!(src2->flags & (IR3_REG_FABS | IR3_REG_SABS)); } + if (!ir3_cat2_int(instr->opc)) { + /* For floating point ALU with immediate arg, it will be a + * FLUT index + */ + if (src1->flags & IR3_REG_IMMED) { + cat2->must_be_zero1 = 1; + if (src1->flags & IR3_REG_HALF) + cat2->src1 |= 0x400; + } + + if (src2 && (src2->flags & IR3_REG_IMMED)) { + cat2->must_be_zero2 = 1; + if (src2->flags & IR3_REG_HALF) + cat2->src2 |= 0x400; + } + } + cat2->dst = reg(dst, info, instr->repeat, IR3_REG_R | IR3_REG_EI | IR3_REG_HALF | IR3_REG_SHARED); cat2->repeat = instr->repeat; diff --git a/src/freedreno/ir3/ir3_lexer.l b/src/freedreno/ir3/ir3_lexer.l index 2924d788abf..d5994e0c6fd 100644 --- a/src/freedreno/ir3/ir3_lexer.l +++ b/src/freedreno/ir3/ir3_lexer.l @@ -89,6 +89,18 @@ static int parse_w(const char *str) "\n" yylineno++; [ \t] ; /* ignore whitespace */ ";"[^\n]*"\n" yylineno++; /* ignore comments */ +"0.0" ir3_yylval.num = 0; return T_FLUT_0_0; +"0.5" ir3_yylval.num = 1; return T_FLUT_0_5; +"1.0" ir3_yylval.num = 2; return T_FLUT_1_0; +"2.0" ir3_yylval.num = 3; return T_FLUT_2_0; +"e" ir3_yylval.num = 4; return T_FLUT_E; +"pi" ir3_yylval.num = 5; return T_FLUT_PI; +"1/pi" ir3_yylval.num = 6; return T_FLUT_INV_PI; +"1/log2(e)" ir3_yylval.num = 7; return T_FLUT_INV_LOG2_E; +"log2(e)" ir3_yylval.num = 8; return T_FLUT_LOG2_E; +"1/log2(10)" ir3_yylval.num = 9; return T_FLUT_INV_LOG2_10; +"log2(10)" ir3_yylval.num = 10; return T_FLUT_LOG2_10; +"4.0" ir3_yylval.num = 11; return T_FLUT_4_0; [0-9]+"."[0-9]+ ir3_yylval.flt = strtod(yytext, NULL); return T_FLOAT; [0-9]* ir3_yylval.num = strtoul(yytext, NULL, 0); return T_INT; "0x"[0-9a-fA-F]* ir3_yylval.num = strtoul(yytext, NULL, 0); return T_HEX; @@ -339,6 +351,7 @@ static int parse_w(const char *str) "s" return 's'; "base"[0-9]+ ir3_yylval.num = strtol(yytext+4, NULL, 10); return T_BASE; +"h(" return TOKEN(T_HP); "=" return '='; "(" return '('; ")" return ')'; diff --git a/src/freedreno/ir3/ir3_parser.y b/src/freedreno/ir3/ir3_parser.y index 582b593a575..f262563b0f8 100644 --- a/src/freedreno/ir3/ir3_parser.y +++ b/src/freedreno/ir3/ir3_parser.y @@ -36,6 +36,7 @@ struct ir3 * ir3_parse(struct ir3_shader_variant *v, #include #include +#include "util/half_float.h" #include "util/u_math.h" #include "ir3/ir3.h" @@ -266,6 +267,7 @@ static void print_token(FILE *file, int type, YYSTYPE value) %token T_HR %token T_HC +%token T_HP /* dst register flags */ %token T_EVEN @@ -273,6 +275,20 @@ static void print_token(FILE *file, int type, YYSTYPE value) %token T_EI %token T_WRMASK +/* Float LUT values accepted as immed: */ +%token T_FLUT_0_0 +%token T_FLUT_0_5 +%token T_FLUT_1_0 +%token T_FLUT_2_0 +%token T_FLUT_E +%token T_FLUT_PI +%token T_FLUT_INV_PI +%token T_FLUT_INV_LOG2_E +%token T_FLUT_LOG2_E +%token T_FLUT_INV_LOG2_10 +%token T_FLUT_LOG2_10 +%token T_FLUT_4_0 + /* instruction flags */ %token T_SY %token T_SS @@ -502,6 +518,7 @@ static void print_token(FILE *file, int type, YYSTYPE value) %token T_CAT1_TYPE_TYPE %type integer offset +%type flut_immed %type float %type reg const %type cat1_opc @@ -654,6 +671,9 @@ cat1_opc: T_OP_MOV '.' T_CAT1_TYPE_TYPE { parse_type_type(new_instr(OPC_MOV), $3); } +cat1_src: src_reg_or_const_or_rel +| immediate_cat1 + cat1_movmsk: T_OP_MOVMSK '.' T_W { new_instr(OPC_MOVMSK); instr->cat1.src_type = TYPE_U32; @@ -667,21 +687,21 @@ cat1_mova1: T_OP_MOVA1 T_A1 ',' { instr->cat1.src_type = TYPE_U16; instr->cat1.dst_type = TYPE_U16; new_reg((61 << 3) + 2, IR3_REG_HALF); - } src_reg_or_const_or_rel_or_imm + } cat1_src cat1_mova: T_OP_MOVA T_A0 ',' { new_instr(OPC_MOV); instr->cat1.src_type = TYPE_S16; instr->cat1.dst_type = TYPE_S16; new_reg((61 << 3), IR3_REG_HALF); - } src_reg_or_const_or_rel_or_imm + } cat1_src /* NOTE: cat1 can also *write* to relative gpr */ cat1_instr: cat1_movmsk | cat1_mova1 | cat1_mova -| cat1_opc dst_reg ',' src_reg_or_const_or_rel_or_imm -| cat1_opc relative_gpr ',' src_reg_or_const_or_rel_or_imm +| cat1_opc dst_reg ',' cat1_src +| cat1_opc relative_gpr ',' cat1_src cat2_opc_1src: T_OP_ABSNEG_F { new_instr(OPC_ABSNEG_F); } | T_OP_ABSNEG_S { new_instr(OPC_ABSNEG_S); } @@ -956,12 +976,38 @@ relative_const: 'c' '<' T_A0 offset '>' { new_reg(0, IR3_REG_RELATIV | IR3_R relative: relative_gpr | relative_const -immediate: integer { new_reg(0, IR3_REG_IMMED)->iim_val = $1; } +/* cat1 immediates differ slighly in the floating point case from the cat2 + * case which can only encode certain predefined values (ie. and index into + * the FLUT table) + */ +immediate_cat1: integer { new_reg(0, IR3_REG_IMMED)->iim_val = type_size(instr->cat1.src_type) < 32 ? $1 & 0xffff : $1; } | '(' integer ')' { new_reg(0, IR3_REG_IMMED)->fim_val = $2; } | '(' float ')' { new_reg(0, IR3_REG_IMMED)->fim_val = $2; } +| T_HP integer ')' { new_reg(0, IR3_REG_IMMED | IR3_REG_HALF)->iim_val = $2 & 0xffff; } +| T_HP float ')' { new_reg(0, IR3_REG_IMMED | IR3_REG_HALF)->uim_val = _mesa_float_to_half($2); } | '(' T_NAN ')' { new_reg(0, IR3_REG_IMMED)->fim_val = NAN; } | '(' T_INF ')' { new_reg(0, IR3_REG_IMMED)->fim_val = INFINITY; } +immediate: integer { new_reg(0, IR3_REG_IMMED)->iim_val = $1; } +| '(' integer ')' { new_reg(0, IR3_REG_IMMED)->fim_val = $2; } +| '(' flut_immed ')' { new_reg(0, IR3_REG_IMMED)->uim_val = $2; } +| T_HP integer ')' { new_reg(0, IR3_REG_IMMED | IR3_REG_HALF)->iim_val = $2; } +| T_HP flut_immed ')' { new_reg(0, IR3_REG_IMMED | IR3_REG_HALF)->uim_val = $2; } + +/* Float LUT values accepted as immed: */ +flut_immed: T_FLUT_0_0 +| T_FLUT_0_5 +| T_FLUT_1_0 +| T_FLUT_2_0 +| T_FLUT_E +| T_FLUT_PI +| T_FLUT_INV_PI +| T_FLUT_INV_LOG2_E +| T_FLUT_LOG2_E +| T_FLUT_INV_LOG2_10 +| T_FLUT_LOG2_10 +| T_FLUT_4_0 + integer: T_INT { $$ = $1; } | '-' T_INT { $$ = -$2; } | T_HEX { $$ = $1; }