mesa/src/intel/compiler/brw_gram.y
Caio Oliveira 6cec413a78 brw: Add EU assembler support for bfloat16
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Rohan Garg <rohan.garg@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33664>
2025-03-25 05:23:37 +00:00

2244 lines
55 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

%{
/*
* Copyright © 2018 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "brw_asm_internal.h"
#undef yyerror
#ifdef YYBYACC
struct YYLTYPE;
void yyerror (struct YYLTYPE *, char *);
#else
void yyerror (char *);
#endif
#undef ALIGN16
#define YYLTYPE YYLTYPE
typedef struct YYLTYPE
{
int first_line;
int first_column;
int last_line;
int last_column;
} YYLTYPE;
enum message_level {
WARN,
ERROR,
};
int yydebug = 1;
static void
message(enum message_level level, YYLTYPE *location,
const char *fmt, ...)
{
static const char *level_str[] = { "warning", "error" };
va_list args;
if (location)
fprintf(stderr, "%s:%d:%d: %s: ", input_filename,
location->first_line,
location->first_column, level_str[level]);
else
fprintf(stderr, "%s:%s: ", input_filename, level_str[level]);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
#define warn(flag, l, fmt, ...) \
do { \
if (warning_flags & WARN_ ## flag) \
message(WARN, l, fmt, ## __VA_ARGS__); \
} while (0)
#define error(l, fmt, ...) \
do { \
message(ERROR, l, fmt, ## __VA_ARGS__); \
} while (0)
static bool
isPowerofTwo(unsigned int x)
{
return x && (!(x & (x - 1)));
}
static struct brw_reg
set_direct_src_operand(struct brw_reg *reg, int type)
{
return brw_make_reg(reg->file,
reg->nr,
reg->subnr,
0, // negate
0, // abs
type,
0, // vstride
0, // width
0, // hstride
BRW_SWIZZLE_NOOP,
WRITEMASK_XYZW);
}
static void
i965_asm_unary_instruction(int opcode, struct brw_codegen *p,
struct brw_reg dest, struct brw_reg src0)
{
switch (opcode) {
case BRW_OPCODE_BFREV:
brw_BFREV(p, dest, src0);
break;
case BRW_OPCODE_CBIT:
brw_CBIT(p, dest, src0);
break;
case BRW_OPCODE_MOV:
brw_MOV(p, dest, src0);
break;
case BRW_OPCODE_FBL:
brw_FBL(p, dest, src0);
break;
case BRW_OPCODE_FRC:
brw_FRC(p, dest, src0);
break;
case BRW_OPCODE_FBH:
brw_FBH(p, dest, src0);
break;
case BRW_OPCODE_NOT:
brw_NOT(p, dest, src0);
break;
case BRW_OPCODE_RNDE:
brw_RNDE(p, dest, src0);
break;
case BRW_OPCODE_RNDZ:
brw_RNDZ(p, dest, src0);
break;
case BRW_OPCODE_RNDD:
brw_RNDD(p, dest, src0);
break;
case BRW_OPCODE_LZD:
brw_LZD(p, dest, src0);
break;
case BRW_OPCODE_RNDU:
fprintf(stderr, "Opcode BRW_OPCODE_RNDU unhandled\n");
break;
default:
fprintf(stderr, "Unsupported unary opcode\n");
}
}
static void
i965_asm_binary_instruction(int opcode,
struct brw_codegen *p,
struct brw_reg dest,
struct brw_reg src0,
struct brw_reg src1)
{
switch (opcode) {
case BRW_OPCODE_ADDC:
brw_ADDC(p, dest, src0, src1);
break;
case BRW_OPCODE_BFI1:
brw_BFI1(p, dest, src0, src1);
break;
case BRW_OPCODE_DP2:
brw_DP2(p, dest, src0, src1);
break;
case BRW_OPCODE_DP3:
brw_DP3(p, dest, src0, src1);
break;
case BRW_OPCODE_DP4:
brw_DP4(p, dest, src0, src1);
break;
case BRW_OPCODE_DPH:
brw_DPH(p, dest, src0, src1);
break;
case BRW_OPCODE_LINE:
brw_LINE(p, dest, src0, src1);
break;
case BRW_OPCODE_MAC:
brw_MAC(p, dest, src0, src1);
break;
case BRW_OPCODE_MACH:
brw_MACH(p, dest, src0, src1);
break;
case BRW_OPCODE_PLN:
brw_PLN(p, dest, src0, src1);
break;
case BRW_OPCODE_ROL:
brw_ROL(p, dest, src0, src1);
break;
case BRW_OPCODE_ROR:
brw_ROR(p, dest, src0, src1);
break;
case BRW_OPCODE_SUBB:
brw_SUBB(p, dest, src0, src1);
break;
case BRW_OPCODE_ADD:
brw_ADD(p, dest, src0, src1);
break;
case BRW_OPCODE_CMP:
/* Third parameter is conditional modifier
* which gets updated later
*/
brw_CMP(p, dest, 0, src0, src1);
break;
case BRW_OPCODE_AND:
brw_AND(p, dest, src0, src1);
break;
case BRW_OPCODE_ASR:
brw_ASR(p, dest, src0, src1);
break;
case BRW_OPCODE_AVG:
brw_AVG(p, dest, src0, src1);
break;
case BRW_OPCODE_OR:
brw_OR(p, dest, src0, src1);
break;
case BRW_OPCODE_SEL:
brw_SEL(p, dest, src0, src1);
break;
case BRW_OPCODE_SHL:
brw_SHL(p, dest, src0, src1);
break;
case BRW_OPCODE_SHR:
brw_SHR(p, dest, src0, src1);
break;
case BRW_OPCODE_XOR:
brw_XOR(p, dest, src0, src1);
break;
case BRW_OPCODE_MUL:
brw_MUL(p, dest, src0, src1);
break;
default:
fprintf(stderr, "Unsupported binary opcode\n");
}
}
static void
i965_asm_ternary_instruction(int opcode,
struct brw_codegen *p,
struct brw_reg dest,
struct brw_reg src0,
struct brw_reg src1,
struct brw_reg src2)
{
switch (opcode) {
case BRW_OPCODE_MAD:
brw_MAD(p, dest, src0, src1, src2);
break;
case BRW_OPCODE_CSEL:
brw_CSEL(p, dest, src0, src1, src2);
break;
case BRW_OPCODE_LRP:
brw_LRP(p, dest, src0, src1, src2);
break;
case BRW_OPCODE_BFE:
brw_BFE(p, dest, src0, src1, src2);
break;
case BRW_OPCODE_BFI2:
brw_BFI2(p, dest, src0, src1, src2);
break;
case BRW_OPCODE_DP4A:
brw_DP4A(p, dest, src0, src1, src2);
break;
case BRW_OPCODE_ADD3:
brw_ADD3(p, dest, src0, src1, src2);
break;
default:
fprintf(stderr, "Unsupported ternary opcode\n");
}
}
static void
i965_asm_set_instruction_options(struct brw_codegen *p,
struct options options)
{
brw_eu_inst_set_access_mode(p->devinfo, brw_last_inst,
options.access_mode);
brw_eu_inst_set_mask_control(p->devinfo, brw_last_inst,
options.mask_control);
if (p->devinfo->ver < 12) {
brw_eu_inst_set_thread_control(p->devinfo, brw_last_inst,
options.thread_control);
brw_eu_inst_set_no_dd_check(p->devinfo, brw_last_inst,
options.no_dd_check);
brw_eu_inst_set_no_dd_clear(p->devinfo, brw_last_inst,
options.no_dd_clear);
} else {
enum opcode opcode = brw_eu_inst_opcode(p->isa, brw_last_inst);
brw_eu_inst_set_swsb(p->devinfo, brw_last_inst,
tgl_swsb_encode(p->devinfo, options.depinfo, opcode));
}
brw_eu_inst_set_debug_control(p->devinfo, brw_last_inst,
options.debug_control);
if (brw_has_branch_ctrl(p->devinfo, brw_eu_inst_opcode(p->isa, brw_last_inst))) {
if (options.acc_wr_control)
error(NULL, "Instruction does not support AccWrEnable\n");
brw_eu_inst_set_branch_control(p->devinfo, brw_last_inst,
options.branch_control);
} else if (options.branch_control) {
error(NULL, "Instruction does not support BranchCtrl\n");
} else if (p->devinfo->ver < 20) {
brw_eu_inst_set_acc_wr_control(p->devinfo, brw_last_inst,
options.acc_wr_control);
}
brw_eu_inst_set_cmpt_control(p->devinfo, brw_last_inst,
options.compaction);
}
%}
%locations
%start ROOT
%union {
char *string;
double number;
int integer;
unsigned long long int llint;
struct brw_reg reg;
enum brw_reg_type reg_type;
struct brw_codegen *program;
struct predicate predicate;
struct condition condition;
struct options options;
struct instoption instoption;
struct msgdesc msgdesc;
struct tgl_swsb depinfo;
struct { int sdepth; int rcount; } dpas_params;
brw_eu_inst *instruction;
}
%token ABS
%token COLON
%token COMMA
%token DOT
%token LANGLE RANGLE
%token LCURLY RCURLY
%token LPAREN RPAREN
%token LSQUARE RSQUARE
%token PLUS MINUS
%token SEMICOLON
%token ASSIGN
/* datatypes */
%token <integer> TYPE_B TYPE_UB
%token <integer> TYPE_W TYPE_UW
%token <integer> TYPE_D TYPE_UD
%token <integer> TYPE_Q TYPE_UQ
%token <integer> TYPE_V TYPE_UV
%token <integer> TYPE_F TYPE_HF
%token <integer> TYPE_BF
%token <integer> TYPE_DF
%token <integer> TYPE_VF
/* label */
%token <string> JUMP_LABEL
%token <string> JUMP_LABEL_TARGET
%token JIP UIP
/* opcodes */
%token <integer> ADD ADD3 ADDC AND ASR AVG
%token <integer> BFE BFI1 BFI2 BFB BFREV BRC BRD BREAK
%token <integer> CALL CALLA CASE CBIT CMP CMPN CONT CSEL
%token <integer> DIM DO DPAS DP2 DP3 DP4 DP4A DPH
%token <integer> ELSE ENDIF FBH FBL FORK FRC
%token <integer> GOTO
%token <integer> HALT
%token <integer> IF ILLEGAL
%token <integer> JMPI JOIN
%token <integer> LINE LRP LZD
%token <integer> MAC MACH MAD MADM MATH MOV MOVI MUL MREST MSAVE
%token <integer> NENOP NOP NOT
%token <integer> OR
%token <integer> PLN POP PUSH
%token <integer> RET RNDD RNDE RNDU RNDZ ROL ROR
%token <integer> SEL SENDS SENDSC SHL SHR SMOV SUBB SYNC
%token <integer> SEND_GFX4 SENDC_GFX4 SEND_GFX12 SENDC_GFX12
%token <integer> WAIT WHILE
%token <integer> XOR
/* extended math functions */
%token <integer> COS EXP FDIV INV INVM INTDIV INTDIVMOD INTMOD LOG POW RSQ
%token <integer> RSQRTM SIN SINCOS SQRT
/* sync instruction */
%token <integer> ALLRD ALLWR FENCE BAR HOST
%type <integer> sync_function
%type <reg> sync_arg
/* shared functions for send */
%token HDC0 HDC1 HDC2 HDC_RO GATEWAY PIXEL_INTERP RENDER SAMPLER
%token TS_BTD URB RT_ACCEL SLM TGM UGM
/* message details for send */
%token MSGDESC_BEGIN SRC1_LEN EX_BSO MSGDESC_END
%type <msgdesc> msgdesc msgdesc_parts;
/* Conditional modifiers */
%token <integer> EQUAL GREATER GREATER_EQUAL LESS LESS_EQUAL NOT_EQUAL
%token <integer> NOT_ZERO OVERFLOW UNORDERED ZERO
/* register Access Modes */
%token ALIGN1 ALIGN16
/* accumulator write control */
%token ACCWREN
/* compaction control */
%token CMPTCTRL
/* mask control (WeCtrl) */
%token WECTRL
/* debug control */
%token BREAKPOINT
/* dependency control */
%token NODDCLR NODDCHK
/* end of thread */
%token EOT
/* mask control */
%token MASK_DISABLE;
/* predicate control */
%token <integer> ANYV ALLV ANY2H ALL2H ANY4H ALL4H ANY8H ALL8H ANY16H ALL16H
%token <integer> ANY32H ALL32H
/* round instructions */
%token <integer> ROUND_INCREMENT
/* staturation */
%token SATURATE
/* thread control */
%token ATOMIC SWITCH
/* branch control */
%token BRANCH_CTRL
/* quater control */
%token QTR_2Q QTR_3Q QTR_4Q QTR_2H QTR_2N QTR_3N QTR_4N QTR_5N
%token QTR_6N QTR_7N QTR_8N
/* channels */
%token <integer> X Y Z W
/* reg files */
%token GENREGFILE
/* vertical stride in register region */
%token VxH
/* register type */
%token <integer> GENREG ADDRREG ACCREG FLAGREG NOTIFYREG STATEREG
%token <integer> CONTROLREG IPREG PERFORMANCEREG THREADREG CHANNELENABLEREG
%token <integer> MASKREG SCALARREG
%token <integer> INTEGER
%token <llint> LONG
%token NULL_TOKEN
%nonassoc SUBREGNUM
%left PLUS MINUS
%nonassoc DOT
%nonassoc EMPTYEXECSIZE
%nonassoc LPAREN
%type <integer> execsize exp
%type <llint> exp2
/* predicate control */
%type <integer> predctrl predstate
%type <predicate> predicate
/* conditional modifier */
%type <condition> cond_mod
%type <integer> condModifiers
/* instruction options */
%type <options> instoptions instoption_list
%type <instoption> instoption
/* writemask */
%type <integer> writemask_x writemask_y writemask_z writemask_w
%type <integer> writemask
/* dst operand */
%type <reg> dst dstoperand dstoperandex dstoperandex_typed dstreg
%type <integer> dstregion
%type <integer> saturate
%type <reg> relativelocation2
/* src operand */
%type <reg> directsrcoperand directsrcaccoperand indirectsrcoperand srcacc
%type <reg> srcarcoperandex srcaccimm srcarcoperandex_typed srcimm
%type <reg> indirectgenreg indirectregion
%type <reg> immreg src reg32 payload directgenreg_list addrparam region
%type <reg> region_wh directgenreg
%type <reg> desc ex_desc reg32a
%type <integer> swizzle
/* registers */
%type <reg> accreg addrreg channelenablereg controlreg flagreg ipreg scalarreg
%type <reg> notifyreg nullreg performancereg threadcontrolreg statereg maskreg
%type <integer> subregnum
/* register types */
%type <reg_type> reg_type imm_type
/* immediate values */
%type <llint> immval
/* instruction opcodes */
%type <integer> unaryopcodes binaryopcodes binaryaccopcodes ternaryopcodes
%type <integer> sendop sendsop
%type <instruction> sendopcode sendsopcode
%type <integer> negate abs chansel math_function sharedfunction
%type <string> jumplabeltarget
/* SWSB */
%token <integer> REG_DIST_CURRENT
%token <integer> REG_DIST_FLOAT
%token <integer> REG_DIST_INT
%token <integer> REG_DIST_LONG
%token <integer> REG_DIST_ALL
%token <integer> REG_DIST_MATH
%token <integer> REG_DIST_SCALAR
%token <integer> SBID_ALLOC
%token <integer> SBID_WAIT_SRC
%token <integer> SBID_WAIT_DST
%type <depinfo> depinfo
/* DPAS */
%token <dpas_params> DPAS_PARAMS
%code {
static void
add_instruction_option(struct options *options, struct instoption opt)
{
if (opt.type == INSTOPTION_DEP_INFO) {
if (opt.depinfo_value.regdist) {
options->depinfo.regdist = opt.depinfo_value.regdist;
options->depinfo.pipe = opt.depinfo_value.pipe;
} else {
options->depinfo.sbid = opt.depinfo_value.sbid;
options->depinfo.mode = opt.depinfo_value.mode;
}
return;
}
if (opt.type == INSTOPTION_CHAN_OFFSET) {
options->chan_offset = opt.uint_value;
return;
}
switch (opt.uint_value) {
case ALIGN1:
options->access_mode = BRW_ALIGN_1;
break;
case ALIGN16:
options->access_mode = BRW_ALIGN_16;
break;
case SWITCH:
options->thread_control |= BRW_THREAD_SWITCH;
break;
case ATOMIC:
options->thread_control |= BRW_THREAD_ATOMIC;
break;
case BRANCH_CTRL:
options->branch_control = true;
break;
case NODDCHK:
options->no_dd_check = true;
break;
case NODDCLR:
options->no_dd_clear = true;
break;
case MASK_DISABLE:
options->mask_control |= BRW_MASK_DISABLE;
break;
case BREAKPOINT:
options->debug_control = BRW_DEBUG_BREAKPOINT;
break;
case WECTRL:
options->mask_control |= BRW_WE_ALL;
break;
case CMPTCTRL:
/* Don't set the compaction flag to true, we're just reading
* text assembly, not instruction bits. The code that will
* assemble things later will set the flag if it decides to
* compact instructions.
*/
if (!compaction_warning_given) {
compaction_warning_given = true;
fprintf(stderr, "%s: ignoring 'compacted' "
"annotations for text assembly "
"instructions\n", input_filename);
}
break;
case ACCWREN:
options->acc_wr_control = true;
break;
case EOT:
options->end_of_thread = true;
break;
}
}
}
%%
ROOT:
instrseq
;
instrseq:
instrseq instruction SEMICOLON
| instrseq relocatableinstruction SEMICOLON
| instruction SEMICOLON
| relocatableinstruction SEMICOLON
| instrseq jumplabeltarget
| jumplabeltarget
;
/* Instruction Group */
instruction:
unaryinstruction
| binaryinstruction
| binaryaccinstruction
| mathinstruction
| nopinstruction
| waitinstruction
| ternaryinstruction
| sendinstruction
| illegalinstruction
| syncinstruction
;
relocatableinstruction:
jumpinstruction
| branchinstruction
| breakinstruction
| loopinstruction
| joininstruction
;
illegalinstruction:
ILLEGAL execsize instoptions
{
brw_next_insn(p, $1);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $2);
i965_asm_set_instruction_options(p, $3);
}
;
/* Unary instruction */
unaryinstruction:
predicate unaryopcodes saturate cond_mod execsize dst srcaccimm instoptions
{
brw_set_default_access_mode(p, $8.access_mode);
i965_asm_unary_instruction($2, p, $6, $7);
brw_pop_insn_state(p);
i965_asm_set_instruction_options(p, $8);
if ($4.cond_modifier) {
brw_eu_inst_set_cond_modifier(p->devinfo,
brw_last_inst,
$4.cond_modifier);
}
if (!brw_eu_inst_flag_reg_nr(p->devinfo, brw_last_inst)) {
brw_eu_inst_set_flag_reg_nr(p->devinfo,
brw_last_inst,
$4.flag_reg_nr);
brw_eu_inst_set_flag_subreg_nr(p->devinfo,
brw_last_inst,
$4.flag_subreg_nr);
}
if ($7.file != IMM) {
brw_eu_inst_set_src0_vstride(p->devinfo, brw_last_inst,
$7.vstride);
}
brw_eu_inst_set_saturate(p->devinfo, brw_last_inst, $3);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $5);
brw_eu_inst_set_group(p->devinfo, brw_last_inst, $8.chan_offset);
}
;
unaryopcodes:
BFREV
| CBIT
| DIM
| FBH
| FBL
| FRC
| LZD
| MOV
| NOT
| RNDD
| RNDE
| RNDU
| RNDZ
;
/* Binary instruction */
binaryinstruction:
predicate binaryopcodes saturate cond_mod execsize dst srcimm srcimm instoptions
{
brw_set_default_access_mode(p, $9.access_mode);
i965_asm_binary_instruction($2, p, $6, $7, $8);
i965_asm_set_instruction_options(p, $9);
if ($4.cond_modifier) {
brw_eu_inst_set_cond_modifier(p->devinfo,
brw_last_inst,
$4.cond_modifier);
}
if (!brw_eu_inst_flag_reg_nr(p->devinfo, brw_last_inst)) {
brw_eu_inst_set_flag_reg_nr(p->devinfo, brw_last_inst,
$4.flag_reg_nr);
brw_eu_inst_set_flag_subreg_nr(p->devinfo, brw_last_inst,
$4.flag_subreg_nr);
}
brw_eu_inst_set_saturate(p->devinfo, brw_last_inst, $3);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $5);
brw_eu_inst_set_group(p->devinfo, brw_last_inst, $9.chan_offset);
brw_pop_insn_state(p);
}
;
binaryopcodes:
ADDC
| BFI1
| DP2
| DP3
| DP4
| DPH
| LINE
| MAC
| MACH
| MUL
| PLN
| ROL
| ROR
| SUBB
;
/* Binary acc instruction */
binaryaccinstruction:
predicate binaryaccopcodes saturate cond_mod execsize dst srcacc srcimm instoptions
{
brw_set_default_access_mode(p, $9.access_mode);
i965_asm_binary_instruction($2, p, $6, $7, $8);
brw_pop_insn_state(p);
i965_asm_set_instruction_options(p, $9);
if ($4.cond_modifier) {
brw_eu_inst_set_cond_modifier(p->devinfo,
brw_last_inst,
$4.cond_modifier);
}
if (!brw_eu_inst_flag_reg_nr(p->devinfo, brw_last_inst)) {
brw_eu_inst_set_flag_reg_nr(p->devinfo,
brw_last_inst,
$4.flag_reg_nr);
brw_eu_inst_set_flag_subreg_nr(p->devinfo,
brw_last_inst,
$4.flag_subreg_nr);
}
brw_eu_inst_set_saturate(p->devinfo, brw_last_inst, $3);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $5);
brw_eu_inst_set_group(p->devinfo, brw_last_inst, $9.chan_offset);
}
;
binaryaccopcodes:
ADD
| AND
| ASR
| AVG
| CMP
| CMPN
| OR
| SEL
| SHL
| SHR
| XOR
;
/* Math instruction */
mathinstruction:
predicate MATH saturate math_function execsize dst src srcimm instoptions
{
brw_set_default_access_mode(p, $9.access_mode);
gfx6_math(p, $6, $4, $7, $8);
i965_asm_set_instruction_options(p, $9);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $5);
brw_eu_inst_set_saturate(p->devinfo, brw_last_inst, $3);
brw_eu_inst_set_group(p->devinfo, brw_last_inst, $9.chan_offset);
brw_pop_insn_state(p);
}
;
math_function:
COS
| EXP
| FDIV
| INV
| INVM
| INTDIV
| INTDIVMOD
| INTMOD
| LOG
| POW
| RSQ
| RSQRTM
| SIN
| SQRT
| SINCOS
;
/* NOP instruction */
nopinstruction:
NOP
{
brw_NOP(p);
}
;
/* Ternary operand instruction */
ternaryinstruction:
predicate ternaryopcodes saturate cond_mod execsize dst srcimm src srcimm instoptions
{
brw_set_default_access_mode(p, $10.access_mode);
i965_asm_ternary_instruction($2, p, $6, $7, $8, $9);
brw_pop_insn_state(p);
i965_asm_set_instruction_options(p, $10);
if ($4.cond_modifier) {
brw_eu_inst_set_cond_modifier(p->devinfo,
brw_last_inst,
$4.cond_modifier);
}
if (p->devinfo->ver < 12) {
brw_eu_inst_set_3src_a16_flag_reg_nr(p->devinfo, brw_last_inst,
$4.flag_reg_nr);
brw_eu_inst_set_3src_a16_flag_subreg_nr(p->devinfo, brw_last_inst,
$4.flag_subreg_nr);
}
brw_eu_inst_set_saturate(p->devinfo, brw_last_inst, $3);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $5);
brw_eu_inst_set_group(p->devinfo, brw_last_inst, $10.chan_offset);
}
|
predicate DPAS DPAS_PARAMS saturate cond_mod execsize dst src src src instoptions
{
assert(p->devinfo->verx10 >= 125);
brw_set_default_access_mode(p, $11.access_mode);
brw_DPAS(p, translate_systolic_depth($3.sdepth), $3.rcount, $7, $8, $9, $10);
brw_pop_insn_state(p);
i965_asm_set_instruction_options(p, $11);
if ($5.cond_modifier) {
brw_eu_inst_set_cond_modifier(p->devinfo,
brw_last_inst,
$5.cond_modifier);
}
brw_eu_inst_set_saturate(p->devinfo, brw_last_inst, $4);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $6);
brw_eu_inst_set_group(p->devinfo, brw_last_inst, $11.chan_offset);
}
;
ternaryopcodes:
CSEL
| BFE
| BFI2
| LRP
| MAD
| DP4A
| ADD3
;
/* Wait instruction */
waitinstruction:
WAIT execsize dst instoptions
{
brw_next_insn(p, $1);
i965_asm_set_instruction_options(p, $4);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $2);
brw_set_default_access_mode(p, $4.access_mode);
struct brw_reg dest = $3;
dest.swizzle = brw_swizzle_for_mask(dest.writemask);
if (dest.file != ARF || dest.nr != BRW_ARF_NOTIFICATION_COUNT)
error(&@1, "WAIT must use the notification register\n");
brw_set_dest(p, brw_last_inst, dest);
brw_set_src0(p, brw_last_inst, dest);
brw_set_src1(p, brw_last_inst, brw_null_reg());
brw_eu_inst_set_mask_control(p->devinfo, brw_last_inst, BRW_MASK_DISABLE);
}
;
/* Send instruction */
sendinstruction:
predicate sendopcode execsize dst payload exp2 sharedfunction msgdesc instoptions
{
i965_asm_set_instruction_options(p, $9);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_set_dest(p, brw_last_inst, $4);
brw_set_src0(p, brw_last_inst, $5);
brw_eu_inst_set_bits(brw_last_inst, 127, 96, $6);
brw_eu_inst_set_src1_file_type(p->devinfo, brw_last_inst,
IMM, BRW_TYPE_UD);
brw_eu_inst_set_sfid(p->devinfo, brw_last_inst, $7);
brw_eu_inst_set_eot(p->devinfo, brw_last_inst, $9.end_of_thread);
brw_eu_inst_set_group(p->devinfo, brw_last_inst, $9.chan_offset);
brw_pop_insn_state(p);
}
| predicate sendopcode execsize dst payload payload exp2 sharedfunction msgdesc instoptions
{
assert(p->devinfo->ver < 12);
i965_asm_set_instruction_options(p, $10);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_set_dest(p, brw_last_inst, $4);
brw_set_src0(p, brw_last_inst, $5);
brw_eu_inst_set_bits(brw_last_inst, 127, 96, $7);
brw_eu_inst_set_sfid(p->devinfo, brw_last_inst, $8);
brw_eu_inst_set_eot(p->devinfo, brw_last_inst, $10.end_of_thread);
brw_eu_inst_set_group(p->devinfo, brw_last_inst, $10.chan_offset);
brw_pop_insn_state(p);
}
| predicate sendsopcode execsize dst payload payload desc ex_desc sharedfunction msgdesc instoptions
{
i965_asm_set_instruction_options(p, $11);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_set_dest(p, brw_last_inst, $4);
brw_set_src0(p, brw_last_inst, $5);
brw_set_src1(p, brw_last_inst, $6);
if ($7.file == IMM) {
brw_eu_inst_set_send_sel_reg32_desc(p->devinfo, brw_last_inst, 0);
brw_eu_inst_set_send_desc(p->devinfo, brw_last_inst, $7.ud);
} else {
brw_eu_inst_set_send_sel_reg32_desc(p->devinfo, brw_last_inst, 1);
}
if ($8.file == IMM) {
brw_eu_inst_set_send_sel_reg32_ex_desc(p->devinfo, brw_last_inst, 0);
brw_eu_inst_set_sends_ex_desc(p->devinfo, brw_last_inst, $8.ud, false);
} else {
brw_eu_inst_set_send_sel_reg32_ex_desc(p->devinfo, brw_last_inst, 1);
brw_eu_inst_set_send_ex_desc_ia_subreg_nr(p->devinfo, brw_last_inst, $8.subnr >> 2);
}
brw_eu_inst_set_sfid(p->devinfo, brw_last_inst, $9);
brw_eu_inst_set_eot(p->devinfo, brw_last_inst, $11.end_of_thread);
brw_eu_inst_set_group(p->devinfo, brw_last_inst, $11.chan_offset);
if (p->devinfo->verx10 >= 125 && $10.ex_bso) {
brw_eu_inst_set_send_ex_bso(p->devinfo, brw_last_inst, 1);
brw_eu_inst_set_send_src1_len(p->devinfo, brw_last_inst, $10.src1_len);
}
brw_pop_insn_state(p);
}
| predicate sendsopcode execsize dst GENREGFILE LSQUARE scalarreg RSQUARE desc ex_desc sharedfunction msgdesc instoptions
{
assert(p->devinfo->ver >= 30);
i965_asm_set_instruction_options(p, $13);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_set_dest(p, brw_last_inst, $4);
brw_set_src0(p, brw_last_inst, $7);
brw_set_src1(p, brw_last_inst, brw_null_reg());
if ($9.file == IMM) {
brw_eu_inst_set_send_sel_reg32_desc(p->devinfo, brw_last_inst, 0);
brw_eu_inst_set_send_desc(p->devinfo, brw_last_inst, $9.ud);
} else {
brw_eu_inst_set_send_sel_reg32_desc(p->devinfo, brw_last_inst, 1);
}
if ($10.file == IMM) {
brw_eu_inst_set_send_sel_reg32_ex_desc(p->devinfo, brw_last_inst, 0);
brw_eu_inst_set_sends_ex_desc(p->devinfo, brw_last_inst, $10.ud, true);
} else {
brw_eu_inst_set_send_sel_reg32_ex_desc(p->devinfo, brw_last_inst, 1);
brw_eu_inst_set_send_ex_desc_ia_subreg_nr(p->devinfo, brw_last_inst, $10.subnr >> 2);
}
brw_eu_inst_set_sfid(p->devinfo, brw_last_inst, $11);
brw_eu_inst_set_eot(p->devinfo, brw_last_inst, $13.end_of_thread);
brw_eu_inst_set_group(p->devinfo, brw_last_inst, $13.chan_offset);
if ($12.ex_bso) {
brw_eu_inst_set_send_ex_bso(p->devinfo, brw_last_inst, 1);
/* Not settings src1 length, as its implied zero. */
}
brw_pop_insn_state(p);
}
;
sendop:
SEND_GFX4
| SENDC_GFX4
;
sendsop:
SEND_GFX12
| SENDC_GFX12
| SENDS
| SENDSC
;
sendopcode:
sendop { $$ = brw_next_insn(p, $1); }
;
sendsopcode:
sendsop { $$ = brw_next_insn(p, $1); }
;
sharedfunction:
NULL_TOKEN { $$ = BRW_SFID_NULL; }
| GATEWAY { $$ = BRW_SFID_MESSAGE_GATEWAY; }
| URB { $$ = BRW_SFID_URB; }
| TS_BTD { $$ = BRW_SFID_BINDLESS_THREAD_DISPATCH; }
| RENDER { $$ = BRW_SFID_RENDER_CACHE; }
| HDC_RO { $$ = BRW_SFID_HDC_READ_ONLY; }
| HDC0 { $$ = BRW_SFID_HDC0; }
| PIXEL_INTERP { $$ = BRW_SFID_PIXEL_INTERPOLATOR; }
| HDC1 { $$ = BRW_SFID_HDC1; }
| SAMPLER { $$ = BRW_SFID_SAMPLER; }
| HDC2 { $$ = BRW_SFID_HDC2; }
| RT_ACCEL { $$ = BRW_SFID_RAY_TRACE_ACCELERATOR; }
| SLM { $$ = BRW_SFID_SLM; }
| TGM { $$ = BRW_SFID_TGM; }
| UGM { $$ = BRW_SFID_UGM; }
;
exp2:
LONG { $$ = $1; }
| MINUS LONG { $$ = -$2; }
;
desc:
reg32a
| exp2
{
$$ = brw_imm_ud($1);
}
;
ex_desc:
reg32a
| exp2
{
$$ = brw_imm_ud($1);
}
;
reg32a:
addrreg region reg_type
{
$$ = set_direct_src_operand(&$1, $3);
$$ = stride($$, $2.vstride, $2.width, $2.hstride);
}
;
/* Jump instruction */
jumpinstruction:
predicate JMPI execsize relativelocation2 instoptions
{
brw_next_insn(p, $2);
i965_asm_set_instruction_options(p, $5);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_set_dest(p, brw_last_inst, brw_ip_reg());
brw_set_src0(p, brw_last_inst, brw_ip_reg());
brw_set_src1(p, brw_last_inst, $4);
brw_eu_inst_set_pred_control(p->devinfo, brw_last_inst,
brw_eu_inst_pred_control(p->devinfo, brw_last_inst));
brw_pop_insn_state(p);
}
;
/* branch instruction */
branchinstruction:
predicate ENDIF execsize JIP JUMP_LABEL instoptions
{
brw_next_insn(p, $2);
brw_asm_label_use_jip($5);
i965_asm_set_instruction_options(p, $6);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_set_src0(p, brw_last_inst, brw_imm_d(0x0));
brw_pop_insn_state(p);
}
| ELSE execsize JIP JUMP_LABEL UIP JUMP_LABEL instoptions
{
brw_next_insn(p, $1);
brw_asm_label_use_jip($4);
brw_asm_label_use_uip($6);
i965_asm_set_instruction_options(p, $7);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $2);
brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_TYPE_D));
if (p->devinfo->ver < 12)
brw_set_src0(p, brw_last_inst, brw_imm_d(0));
}
| predicate IF execsize JIP JUMP_LABEL UIP JUMP_LABEL instoptions
{
brw_next_insn(p, $2);
i965_asm_set_instruction_options(p, $8);
brw_asm_label_use_jip($5);
brw_asm_label_use_uip($7);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_set_dest(p, brw_last_inst, vec1(retype(brw_null_reg(), BRW_TYPE_D)));
if (p->devinfo->ver < 12)
brw_set_src0(p, brw_last_inst, brw_imm_d(0x0));
brw_pop_insn_state(p);
}
| predicate GOTO execsize JIP JUMP_LABEL UIP JUMP_LABEL instoptions
{
brw_next_insn(p, $2);
brw_asm_label_use_jip($5);
brw_asm_label_use_uip($7);
i965_asm_set_instruction_options(p, $8);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_pop_insn_state(p);
}
;
joininstruction:
predicate JOIN execsize JIP JUMP_LABEL instoptions
{
brw_next_insn(p, $2);
brw_asm_label_use_jip($5);
i965_asm_set_instruction_options(p, $6);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_pop_insn_state(p);
}
;
/* break instruction */
breakinstruction:
predicate BREAK execsize JIP JUMP_LABEL UIP JUMP_LABEL instoptions
{
brw_next_insn(p, $2);
brw_asm_label_use_jip($5);
brw_asm_label_use_uip($7);
i965_asm_set_instruction_options(p, $8);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_TYPE_D));
brw_set_src0(p, brw_last_inst, brw_imm_d(0x0));
brw_pop_insn_state(p);
}
| predicate HALT execsize JIP JUMP_LABEL UIP JUMP_LABEL instoptions
{
brw_next_insn(p, $2);
brw_asm_label_use_jip($5);
brw_asm_label_use_uip($7);
i965_asm_set_instruction_options(p, $8);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_TYPE_D));
if (p->devinfo->ver < 12) {
brw_set_src0(p, brw_last_inst, brw_imm_d(0x0));
}
brw_pop_insn_state(p);
}
| predicate CONT execsize JIP JUMP_LABEL UIP JUMP_LABEL instoptions
{
brw_next_insn(p, $2);
brw_asm_label_use_jip($5);
brw_asm_label_use_uip($7);
i965_asm_set_instruction_options(p, $8);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_set_dest(p, brw_last_inst, brw_ip_reg());
brw_set_src0(p, brw_last_inst, brw_imm_d(0x0));
brw_pop_insn_state(p);
}
;
/* loop instruction */
loopinstruction:
predicate WHILE execsize JIP JUMP_LABEL instoptions
{
brw_next_insn(p, $2);
brw_asm_label_use_jip($5);
i965_asm_set_instruction_options(p, $6);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $3);
brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_TYPE_D));
if (p->devinfo->ver < 12)
brw_set_src0(p, brw_last_inst, brw_imm_d(0x0));
brw_pop_insn_state(p);
}
| DO execsize instoptions
{
brw_next_insn(p, $1);
}
;
/* sync instruction */
syncinstruction:
predicate SYNC sync_function execsize sync_arg instoptions
{
if (p->devinfo->ver < 12) {
error(&@2, "sync instruction is supported only on gfx12+\n");
}
if ($5.file == IMM &&
$3 != TGL_SYNC_ALLRD &&
$3 != TGL_SYNC_ALLWR) {
error(&@2, "Only allrd and allwr support immediate argument\n");
}
brw_set_default_access_mode(p, $6.access_mode);
brw_SYNC(p, $3);
i965_asm_set_instruction_options(p, $6);
brw_eu_inst_set_exec_size(p->devinfo, brw_last_inst, $4);
brw_set_src0(p, brw_last_inst, $5);
brw_eu_inst_set_eot(p->devinfo, brw_last_inst, $6.end_of_thread);
brw_eu_inst_set_group(p->devinfo, brw_last_inst, $6.chan_offset);
brw_pop_insn_state(p);
}
;
sync_function:
NOP { $$ = TGL_SYNC_NOP; }
| ALLRD
| ALLWR
| FENCE
| BAR
| HOST
;
sync_arg:
nullreg region reg_type
{
$$ = $1;
$$.vstride = $2.vstride;
$$.width = $2.width;
$$.hstride = $2.hstride;
$$.type = $3;
}
| immreg
;
/* Relative location */
relativelocation2:
immreg
| reg32
;
jumplabeltarget:
JUMP_LABEL_TARGET
{
brw_asm_label_set($1);
}
;
/* Destination register */
dst:
dstoperand
| dstoperandex
;
dstoperand:
dstreg dstregion writemask reg_type
{
$$ = $1;
$$.vstride = BRW_VERTICAL_STRIDE_1;
$$.width = BRW_WIDTH_1;
$$.hstride = $2;
$$.type = $4;
$$.writemask = $3;
$$.swizzle = BRW_SWIZZLE_NOOP;
$$.subnr = $$.subnr * brw_type_size_bytes($4);
}
;
dstoperandex:
dstoperandex_typed dstregion writemask reg_type
{
$$ = $1;
$$.hstride = $2;
$$.type = $4;
$$.writemask = $3;
$$.subnr = $$.subnr * brw_type_size_bytes($4);
}
/* BSpec says "When the conditional modifier is present, updates
* to the selected flag register also occur. In this case, the
* register region fields of the null operand are valid."
*/
| nullreg dstregion writemask reg_type
{
$$ = $1;
$$.vstride = BRW_VERTICAL_STRIDE_1;
$$.width = BRW_WIDTH_1;
$$.hstride = $2;
$$.writemask = $3;
$$.type = $4;
}
| threadcontrolreg
{
$$ = $1;
$$.hstride = 1;
$$.type = BRW_TYPE_UW;
}
;
dstoperandex_typed:
accreg
| addrreg
| channelenablereg
| controlreg
| flagreg
| ipreg
| maskreg
| notifyreg
| performancereg
| statereg
| scalarreg
;
dstreg:
directgenreg
{
$$ = $1;
$$.address_mode = BRW_ADDRESS_DIRECT;
}
| indirectgenreg
{
$$ = $1;
$$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
}
;
/* Source register */
srcaccimm:
srcacc
| immreg
;
immreg:
immval imm_type
{
switch ($2) {
case BRW_TYPE_UD:
$$ = brw_imm_ud($1);
break;
case BRW_TYPE_D:
$$ = brw_imm_d($1);
break;
case BRW_TYPE_UW:
$$ = brw_imm_uw($1 | ($1 << 16));
break;
case BRW_TYPE_W:
$$ = brw_imm_w($1);
break;
case BRW_TYPE_F:
$$ = brw_imm_reg(BRW_TYPE_F);
/* Set u64 instead of ud since DIM uses a 64-bit F-typed imm */
$$.u64 = $1;
break;
case BRW_TYPE_V:
$$ = brw_imm_v($1);
break;
case BRW_TYPE_UV:
$$ = brw_imm_uv($1);
break;
case BRW_TYPE_VF:
$$ = brw_imm_vf($1);
break;
case BRW_TYPE_Q:
$$ = brw_imm_q($1);
break;
case BRW_TYPE_UQ:
$$ = brw_imm_uq($1);
break;
case BRW_TYPE_DF:
$$ = brw_imm_reg(BRW_TYPE_DF);
$$.d64 = $1;
break;
case BRW_TYPE_HF:
$$ = brw_imm_reg(BRW_TYPE_HF);
$$.ud = $1 | ($1 << 16);
break;
default:
error(&@2, "Unknown immediate type %s\n",
brw_reg_type_to_letters($2));
}
}
;
reg32:
directgenreg region reg_type
{
$$ = set_direct_src_operand(&$1, $3);
$$ = stride($$, $2.vstride, $2.width, $2.hstride);
}
;
payload:
directsrcoperand
;
src:
directsrcoperand
| indirectsrcoperand
;
srcacc:
directsrcaccoperand
| indirectsrcoperand
;
srcimm:
directsrcoperand
| indirectsrcoperand
| immreg
;
directsrcaccoperand:
directsrcoperand
| negate abs accreg region reg_type
{
$$ = set_direct_src_operand(&$3, $5);
$$.negate = $1;
$$.abs = $2;
$$.vstride = $4.vstride;
$$.width = $4.width;
$$.hstride = $4.hstride;
}
;
srcarcoperandex:
srcarcoperandex_typed region reg_type
{
$$ = brw_make_reg($1.file,
$1.nr,
$1.subnr,
0,
0,
$3,
$2.vstride,
$2.width,
$2.hstride,
BRW_SWIZZLE_NOOP,
WRITEMASK_XYZW);
}
| nullreg region reg_type
{
$$ = set_direct_src_operand(&$1, $3);
$$.vstride = $2.vstride;
$$.width = $2.width;
$$.hstride = $2.hstride;
}
| threadcontrolreg
{
$$ = set_direct_src_operand(&$1, BRW_TYPE_UW);
}
;
srcarcoperandex_typed:
channelenablereg
| controlreg
| flagreg
| ipreg
| maskreg
| statereg
| scalarreg
;
indirectsrcoperand:
negate abs indirectgenreg indirectregion swizzle reg_type
{
$$ = brw_make_reg($3.file,
0,
$3.subnr,
$1, // negate
$2, // abs
$6,
$4.vstride,
$4.width,
$4.hstride,
$5,
WRITEMASK_X);
$$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
// brw_reg set indirect_offset to 0 so set it to valid value
$$.indirect_offset = $3.indirect_offset;
}
;
directgenreg_list:
directgenreg
| notifyreg
| addrreg
| performancereg
;
directsrcoperand:
negate abs directgenreg_list region swizzle reg_type
{
$$ = brw_make_reg($3.file,
$3.nr,
$3.subnr,
$1,
$2,
$6,
$4.vstride,
$4.width,
$4.hstride,
$5,
WRITEMASK_X);
}
| srcarcoperandex
;
/* Address register */
addrparam:
addrreg exp
{
memset(&$$, '\0', sizeof($$));
$$.subnr = $1.subnr;
$$.indirect_offset = $2;
}
| addrreg
;
/* Register files and register numbers */
exp:
INTEGER { $$ = $1; }
| LONG { $$ = $1; }
;
subregnum:
DOT exp { $$ = $2; }
| /* empty */ %prec SUBREGNUM { $$ = 0; }
;
directgenreg:
GENREG subregnum
{
memset(&$$, '\0', sizeof($$));
$$.file = FIXED_GRF;
$$.nr = $1 * reg_unit(p->devinfo);
$$.subnr = $2;
}
;
indirectgenreg:
GENREGFILE LSQUARE addrparam RSQUARE
{
memset(&$$, '\0', sizeof($$));
$$.file = FIXED_GRF;
$$.subnr = $3.subnr;
$$.indirect_offset = $3.indirect_offset;
}
;
addrreg:
ADDRREG subregnum
{
int subnr = 16;
if ($2 > subnr)
error(&@2, "Address sub register number %d"
"out of range\n", $2);
$$.file = ARF;
$$.nr = BRW_ARF_ADDRESS;
$$.subnr = $2;
}
;
accreg:
ACCREG subregnum
{
int nr_reg = 10;
if ($1 > nr_reg)
error(&@1, "Accumulator register number %d"
" out of range\n", $1);
memset(&$$, '\0', sizeof($$));
$$.file = ARF;
$$.nr = BRW_ARF_ACCUMULATOR;
$$.subnr = $2;
}
;
flagreg:
FLAGREG subregnum
{
// 2 flag reg
int nr_reg = 2;
int subnr = nr_reg;
if ($1 > nr_reg)
error(&@1, "Flag register number %d"
" out of range \n", $1);
if ($2 > subnr)
error(&@2, "Flag subregister number %d"
" out of range\n", $2);
$$.file = ARF;
$$.nr = BRW_ARF_FLAG | $1;
$$.subnr = $2;
}
;
maskreg:
MASKREG subregnum
{
if ($1 > 0)
error(&@1, "Mask register number %d"
" out of range\n", $1);
$$.file = ARF;
$$.nr = BRW_ARF_MASK;
$$.subnr = $2;
}
;
notifyreg:
NOTIFYREG subregnum
{
int subnr = (p->devinfo->ver >= 11) ? 2 : 3;
if ($2 > subnr)
error(&@2, "Notification sub register number %d"
" out of range\n", $2);
$$.file = ARF;
$$.nr = BRW_ARF_NOTIFICATION_COUNT;
$$.subnr = $2;
}
;
scalarreg:
SCALARREG subregnum
{
if ($2 > 31)
error(&@2, "Scalar sub register number %d"
" out of range\n", $2);
$$.file = ARF;
$$.nr = BRW_ARF_SCALAR;
$$.subnr = $2;
}
statereg:
STATEREG subregnum
{
if ($1 > 2)
error(&@1, "State register number %d"
" out of range\n", $1);
if ($2 > 4)
error(&@2, "State sub register number %d"
" out of range\n", $2);
$$.file = ARF;
$$.nr = BRW_ARF_STATE;
$$.subnr = $2;
}
;
controlreg:
CONTROLREG subregnum
{
if ($2 > 3)
error(&@2, "control sub register number %d"
" out of range\n", $2);
$$.file = ARF;
$$.nr = BRW_ARF_CONTROL;
$$.subnr = $2;
}
;
ipreg:
IPREG { $$ = brw_ip_reg(); }
;
nullreg:
NULL_TOKEN { $$ = brw_null_reg(); }
;
threadcontrolreg:
THREADREG subregnum
{
if ($2 > 7)
error(&@2, "Thread control sub register number %d"
" out of range\n", $2);
$$.file = ARF;
$$.nr = BRW_ARF_TDR;
$$.subnr = $2;
}
;
performancereg:
PERFORMANCEREG subregnum
{
int subnr;
if (p->devinfo->ver >= 10)
subnr = 5;
else
subnr = 4;
if ($2 > subnr)
error(&@2, "Performance sub register number %d"
" out of range\n", $2);
$$.file = ARF;
$$.nr = BRW_ARF_TIMESTAMP;
$$.subnr = $2;
}
;
channelenablereg:
CHANNELENABLEREG subregnum
{
if ($1 > 0)
error(&@1, "Channel enable register number %d"
" out of range\n", $1);
$$.file = ARF;
$$.nr = BRW_ARF_MASK;
$$.subnr = $2;
}
;
/* Immediate values */
immval:
exp2
{
$$ = $1;
}
| LSQUARE exp2 COMMA exp2 COMMA exp2 COMMA exp2 RSQUARE
{
$$ = ($2 << 0) | ($4 << 8) | ($6 << 16) | ($8 << 24);
}
;
/* Regions */
dstregion:
/* empty */
{
$$ = BRW_HORIZONTAL_STRIDE_1;
}
| LANGLE exp RANGLE
{
if ($2 != 0 && ($2 > 4 || !isPowerofTwo($2)))
error(&@2, "Invalid Horizontal stride %d\n", $2);
$$ = ffs($2);
}
;
indirectregion:
region
| region_wh
;
region:
/* empty */
{
$$ = stride($$, 0, 1, 0);
}
| LANGLE exp RANGLE
{
if ($2 != 0 && ($2 > 32 || !isPowerofTwo($2)))
error(&@2, "Invalid VertStride %d\n", $2);
$$ = stride($$, $2, 1, 0);
}
| LANGLE exp COMMA exp COMMA exp RANGLE
{
if ($2 != 0 && ($2 > 32 || !isPowerofTwo($2)))
error(&@2, "Invalid VertStride %d\n", $2);
if ($4 > 16 || !isPowerofTwo($4))
error(&@4, "Invalid width %d\n", $4);
if ($6 != 0 && ($6 > 4 || !isPowerofTwo($6)))
error(&@6, "Invalid Horizontal stride in"
" region_wh %d\n", $6);
$$ = stride($$, $2, $4, $6);
}
| LANGLE exp SEMICOLON exp COMMA exp RANGLE
{
if ($2 != 0 && ($2 > 32 || !isPowerofTwo($2)))
error(&@2, "Invalid VertStride %d\n", $2);
if ($4 > 16 || !isPowerofTwo($4))
error(&@4, "Invalid width %d\n", $4);
if ($6 != 0 && ($6 > 4 || !isPowerofTwo($6)))
error(&@6, "Invalid Horizontal stride in"
" region_wh %d\n", $6);
$$ = stride($$, $2, $4, $6);
}
| LANGLE VxH COMMA exp COMMA exp RANGLE
{
if ($4 > 16 || !isPowerofTwo($4))
error(&@4, "Invalid width %d\n", $4);
if ($6 != 0 && ($6 > 4 || !isPowerofTwo($6)))
error(&@6, "Invalid Horizontal stride in"
" region_wh %d\n", $6);
$$ = brw_VxH_indirect(0, 0);
}
;
region_wh:
LANGLE exp COMMA exp RANGLE
{
if ($2 > 16 || !isPowerofTwo($2))
error(&@2, "Invalid width %d\n", $2);
if ($4 != 0 && ($4 > 4 || !isPowerofTwo($4)))
error(&@4, "Invalid Horizontal stride in"
" region_wh %d\n", $4);
$$ = stride($$, 0, $2, $4);
$$.vstride = BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL;
}
;
reg_type:
TYPE_F { $$ = BRW_TYPE_F; }
| TYPE_UD { $$ = BRW_TYPE_UD; }
| TYPE_D { $$ = BRW_TYPE_D; }
| TYPE_UW { $$ = BRW_TYPE_UW; }
| TYPE_W { $$ = BRW_TYPE_W; }
| TYPE_UB { $$ = BRW_TYPE_UB; }
| TYPE_B { $$ = BRW_TYPE_B; }
| TYPE_DF { $$ = BRW_TYPE_DF; }
| TYPE_UQ { $$ = BRW_TYPE_UQ; }
| TYPE_Q { $$ = BRW_TYPE_Q; }
| TYPE_HF { $$ = BRW_TYPE_HF; }
| TYPE_BF { $$ = BRW_TYPE_BF; }
;
imm_type:
reg_type { $$ = $1; }
| TYPE_V { $$ = BRW_TYPE_V; }
| TYPE_VF { $$ = BRW_TYPE_VF; }
| TYPE_UV { $$ = BRW_TYPE_UV; }
;
writemask:
/* empty */
{
$$ = WRITEMASK_XYZW;
}
| DOT writemask_x writemask_y writemask_z writemask_w
{
$$ = $2 | $3 | $4 | $5;
}
;
writemask_x:
/* empty */ { $$ = 0; }
| X { $$ = 1 << BRW_CHANNEL_X; }
;
writemask_y:
/* empty */ { $$ = 0; }
| Y { $$ = 1 << BRW_CHANNEL_Y; }
;
writemask_z:
/* empty */ { $$ = 0; }
| Z { $$ = 1 << BRW_CHANNEL_Z; }
;
writemask_w:
/* empty */ { $$ = 0; }
| W { $$ = 1 << BRW_CHANNEL_W; }
;
swizzle:
/* empty */
{
$$ = BRW_SWIZZLE_NOOP;
}
| DOT chansel
{
$$ = BRW_SWIZZLE4($2, $2, $2, $2);
}
| DOT chansel chansel chansel chansel
{
$$ = BRW_SWIZZLE4($2, $3, $4, $5);
}
;
chansel:
X
| Y
| Z
| W
;
/* Instruction prediction and modifiers */
predicate:
/* empty */
{
brw_push_insn_state(p);
brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
brw_set_default_flag_reg(p, 0, 0);
brw_set_default_predicate_inverse(p, false);
}
| LPAREN predstate flagreg predctrl RPAREN
{
brw_push_insn_state(p);
brw_set_default_predicate_inverse(p, $2);
brw_set_default_flag_reg(p, $3.nr, $3.subnr);
brw_set_default_predicate_control(p, $4);
}
;
predstate:
/* empty */ { $$ = 0; }
| PLUS { $$ = 0; }
| MINUS { $$ = 1; }
;
predctrl:
/* empty */ { $$ = BRW_PREDICATE_NORMAL; }
| DOT X { $$ = BRW_PREDICATE_ALIGN16_REPLICATE_X; }
| DOT Y { $$ = BRW_PREDICATE_ALIGN16_REPLICATE_Y; }
| DOT Z { $$ = BRW_PREDICATE_ALIGN16_REPLICATE_Z; }
| DOT W { $$ = BRW_PREDICATE_ALIGN16_REPLICATE_W; }
| ANYV
| ALLV
| ANY2H
| ALL2H
| ANY4H
| ALL4H
| ANY8H
| ALL8H
| ANY16H
| ALL16H
| ANY32H
| ALL32H
;
/* Source Modification */
negate:
/* empty */ { $$ = 0; }
| MINUS { $$ = 1; }
;
abs:
/* empty */ { $$ = 0; }
| ABS { $$ = 1; }
;
/* Flag (Conditional) Modifier */
cond_mod:
condModifiers
{
$$.cond_modifier = $1;
$$.flag_reg_nr = 0;
$$.flag_subreg_nr = 0;
}
| condModifiers DOT flagreg
{
$$.cond_modifier = $1;
$$.flag_reg_nr = $3.nr;
$$.flag_subreg_nr = $3.subnr;
}
;
condModifiers:
/* empty */ { $$ = BRW_CONDITIONAL_NONE; }
| ZERO
| EQUAL
| NOT_ZERO
| NOT_EQUAL
| GREATER
| GREATER_EQUAL
| LESS
| LESS_EQUAL
| OVERFLOW
| ROUND_INCREMENT
| UNORDERED
;
/* message details for send */
msgdesc:
MSGDESC_BEGIN msgdesc_parts MSGDESC_END { $$ = $2; }
;
msgdesc_parts:
SRC1_LEN ASSIGN INTEGER msgdesc_parts
{
$$ = $4;
$$.src1_len = $3;
}
| EX_BSO msgdesc_parts
{
$$ = $2;
$$.ex_bso = 1;
}
| INTEGER msgdesc_parts { $$ = $2; }
| ASSIGN msgdesc_parts { $$ = $2; }
| /* empty */
{
memset(&$$, 0, sizeof($$));
}
;
saturate:
/* empty */ { $$ = BRW_INSTRUCTION_NORMAL; }
| SATURATE { $$ = BRW_INSTRUCTION_SATURATE; }
;
/* Execution size */
execsize:
/* empty */ %prec EMPTYEXECSIZE
{
$$ = 0;
}
| LPAREN exp2 RPAREN
{
if ($2 > 32 || !isPowerofTwo($2))
error(&@2, "Invalid execution size %llu\n", $2);
$$ = cvt($2) - 1;
}
;
/* Instruction options */
instoptions:
/* empty */
{
memset(&$$, 0, sizeof($$));
}
| LCURLY instoption_list RCURLY
{
memset(&$$, 0, sizeof($$));
$$ = $2;
}
;
instoption_list:
instoption_list COMMA instoption
{
memset(&$$, 0, sizeof($$));
$$ = $1;
add_instruction_option(&$$, $3);
}
| instoption_list instoption
{
memset(&$$, 0, sizeof($$));
$$ = $1;
add_instruction_option(&$$, $2);
}
| /* empty */
{
memset(&$$, 0, sizeof($$));
}
;
depinfo:
REG_DIST_CURRENT
{
memset(&$$, 0, sizeof($$));
$$.regdist = $1;
$$.pipe = TGL_PIPE_NONE;
}
| REG_DIST_FLOAT
{
memset(&$$, 0, sizeof($$));
$$.regdist = $1;
$$.pipe = TGL_PIPE_FLOAT;
}
| REG_DIST_INT
{
memset(&$$, 0, sizeof($$));
$$.regdist = $1;
$$.pipe = TGL_PIPE_INT;
}
| REG_DIST_LONG
{
memset(&$$, 0, sizeof($$));
$$.regdist = $1;
$$.pipe = TGL_PIPE_LONG;
}
| REG_DIST_ALL
{
memset(&$$, 0, sizeof($$));
$$.regdist = $1;
$$.pipe = TGL_PIPE_ALL;
}
| REG_DIST_MATH
{
memset(&$$, 0, sizeof($$));
$$.regdist = $1;
$$.pipe = TGL_PIPE_MATH;
}
| REG_DIST_SCALAR
{
memset(&$$, 0, sizeof($$));
$$.regdist = $1;
$$.pipe = TGL_PIPE_SCALAR;
}
| SBID_ALLOC
{
memset(&$$, 0, sizeof($$));
$$.sbid = $1;
$$.mode = TGL_SBID_SET;
}
| SBID_WAIT_SRC
{
memset(&$$, 0, sizeof($$));
$$.sbid = $1;
$$.mode = TGL_SBID_SRC;
}
| SBID_WAIT_DST
{
memset(&$$, 0, sizeof($$));
$$.sbid = $1;
$$.mode = TGL_SBID_DST;
}
instoption:
ALIGN1 { $$.type = INSTOPTION_FLAG; $$.uint_value = ALIGN1;}
| ALIGN16 { $$.type = INSTOPTION_FLAG; $$.uint_value = ALIGN16; }
| ACCWREN
{
if (p->devinfo->ver >= 20)
error(&@1, "AccWrEnable not supported in Xe2+\n");
$$.type = INSTOPTION_FLAG;
$$.uint_value = ACCWREN;
}
| BREAKPOINT { $$.type = INSTOPTION_FLAG; $$.uint_value = BREAKPOINT; }
| NODDCLR { $$.type = INSTOPTION_FLAG; $$.uint_value = NODDCLR; }
| NODDCHK { $$.type = INSTOPTION_FLAG; $$.uint_value = NODDCHK; }
| MASK_DISABLE { $$.type = INSTOPTION_FLAG; $$.uint_value = MASK_DISABLE; }
| EOT { $$.type = INSTOPTION_FLAG; $$.uint_value = EOT; }
| SWITCH { $$.type = INSTOPTION_FLAG; $$.uint_value = SWITCH; }
| ATOMIC { $$.type = INSTOPTION_FLAG; $$.uint_value = ATOMIC; }
| BRANCH_CTRL { $$.type = INSTOPTION_FLAG; $$.uint_value = BRANCH_CTRL; }
| CMPTCTRL { $$.type = INSTOPTION_FLAG; $$.uint_value = CMPTCTRL; }
| WECTRL { $$.type = INSTOPTION_FLAG; $$.uint_value = WECTRL; }
| QTR_2Q { $$.type = INSTOPTION_CHAN_OFFSET; $$.uint_value = 8; }
| QTR_3Q { $$.type = INSTOPTION_CHAN_OFFSET; $$.uint_value = 16; }
| QTR_4Q { $$.type = INSTOPTION_CHAN_OFFSET; $$.uint_value = 24; }
| QTR_2H { $$.type = INSTOPTION_CHAN_OFFSET; $$.uint_value = 16; }
| QTR_2N
{
if (p->devinfo->ver >= 20)
error(&@1, "Channel offset must be multiple of 8 in Xe2+\n");
$$.type = INSTOPTION_CHAN_OFFSET;
$$.uint_value = 4;
}
| QTR_3N { $$.type = INSTOPTION_CHAN_OFFSET; $$.uint_value = 8; }
| QTR_4N
{
if (p->devinfo->ver >= 20)
error(&@1, "Channel offset must be multiple of 8 in Xe2+\n");
$$.type = INSTOPTION_CHAN_OFFSET; $$.uint_value = 12;
}
| QTR_5N { $$.type = INSTOPTION_CHAN_OFFSET; $$.uint_value = 16; }
| QTR_6N
{
if (p->devinfo->ver >= 20)
error(&@1, "Channel offset must be multiple of 8 in Xe2+\n");
$$.type = INSTOPTION_CHAN_OFFSET; $$.uint_value = 20;
}
| QTR_7N { $$.type = INSTOPTION_CHAN_OFFSET; $$.uint_value = 24; }
| QTR_8N
{
if (p->devinfo->ver >= 20)
error(&@1, "Channel offset must be multiple of 8 in Xe2+\n");
$$.type = INSTOPTION_CHAN_OFFSET; $$.uint_value = 28;
}
| depinfo { $$.type = INSTOPTION_DEP_INFO; $$.depinfo_value = $1; }
;
%%
extern int yylineno;
#ifdef YYBYACC
void
yyerror(YYLTYPE *ltype, char *msg)
#else
void
yyerror(char *msg)
#endif
{
fprintf(stderr, "%s: %d: %s at \"%s\"\n",
input_filename, yylineno, msg, lex_text());
++errors;
}