blob: 70caeb4132a6f6a08cacee215d922bea6ac1fb34 [file] [log] [blame]
%{
/*
* Copyright © 2006 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.
*
* Authors:
* Eric Anholt <eric@anholt.net>
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "gen4asm.h"
#include "brw_defines.h"
#define DEFAULT_EXECSIZE (ffs(program_defaults.execute_size) - 1)
#define DEFAULT_DSTREGION -1
extern long int gen_level;
extern int advanced_flag;
extern int yylineno;
extern int need_export;
static struct src_operand src_null_reg =
{
.reg_file = BRW_ARCHITECTURE_REGISTER_FILE,
.reg_nr = BRW_ARF_NULL,
.reg_type = BRW_REGISTER_TYPE_UD,
};
static struct dst_operand dst_null_reg =
{
.reg_file = BRW_ARCHITECTURE_REGISTER_FILE,
.reg_nr = BRW_ARF_NULL,
};
static struct dst_operand ip_dst =
{
.reg_file = BRW_ARCHITECTURE_REGISTER_FILE,
.reg_nr = BRW_ARF_IP,
.reg_type = BRW_REGISTER_TYPE_UD,
.address_mode = BRW_ADDRESS_DIRECT,
.horiz_stride = 1,
.writemask = 0xF,
};
static struct src_operand ip_src =
{
.reg_file = BRW_ARCHITECTURE_REGISTER_FILE,
.reg_nr = BRW_ARF_IP,
.reg_type = BRW_REGISTER_TYPE_UD,
.address_mode = BRW_ADDRESS_DIRECT,
.swizzle_x = BRW_CHANNEL_X,
.swizzle_y = BRW_CHANNEL_Y,
.swizzle_z = BRW_CHANNEL_Z,
.swizzle_w = BRW_CHANNEL_W,
};
static int get_type_size(GLuint type);
int set_instruction_dest(struct brw_instruction *instr,
struct dst_operand *dest);
int set_instruction_src0(struct brw_instruction *instr,
struct src_operand *src);
int set_instruction_src1(struct brw_instruction *instr,
struct src_operand *src);
int set_instruction_dest_three_src(struct brw_instruction *instr,
struct dst_operand *dest);
int set_instruction_src0_three_src(struct brw_instruction *instr,
struct src_operand *src);
int set_instruction_src1_three_src(struct brw_instruction *instr,
struct src_operand *src);
int set_instruction_src2_three_src(struct brw_instruction *instr,
struct src_operand *src);
void set_instruction_options(struct brw_instruction *instr,
struct brw_instruction *options);
void set_instruction_predicate(struct brw_instruction *instr,
struct brw_instruction *predicate);
void set_direct_dst_operand(struct dst_operand *dst, struct direct_reg *reg,
int type);
void set_direct_src_operand(struct src_operand *src, struct direct_reg *reg,
int type);
%}
%start ROOT
%union {
char *string;
int integer;
double number;
struct brw_instruction instruction;
struct brw_program program;
struct region region;
struct regtype regtype;
struct direct_reg direct_reg;
struct indirect_reg indirect_reg;
struct condition condition;
struct declared_register symbol_reg;
imm32_t imm32;
struct dst_operand dst_operand;
struct src_operand src_operand;
}
%token COLON
%token SEMICOLON
%token LPAREN RPAREN
%token LANGLE RANGLE
%token LCURLY RCURLY
%token LSQUARE RSQUARE
%token COMMA EQ
%token ABS DOT
%token PLUS MINUS MULTIPLY DIVIDE
%token <integer> TYPE_UD TYPE_D TYPE_UW TYPE_W TYPE_UB TYPE_B
%token <integer> TYPE_VF TYPE_HF TYPE_V TYPE_F
%token ALIGN1 ALIGN16 SECHALF COMPR SWITCH ATOMIC NODDCHK NODDCLR
%token MASK_DISABLE BREAKPOINT ACCWRCTRL EOT
%token SEQ ANY2H ALL2H ANY4H ALL4H ANY8H ALL8H ANY16H ALL16H ANYV ALLV
%token <integer> ZERO EQUAL NOT_ZERO NOT_EQUAL GREATER GREATER_EQUAL LESS LESS_EQUAL
%token <integer> ROUND_INCREMENT OVERFLOW UNORDERED
%token <integer> GENREG MSGREG ADDRESSREG ACCREG FLAGREG
%token <integer> MASKREG AMASK IMASK LMASK CMASK
%token <integer> MASKSTACKREG LMS IMS MASKSTACKDEPTHREG IMSD LMSD
%token <integer> NOTIFYREG STATEREG CONTROLREG IPREG
%token GENREGFILE MSGREGFILE
%token <integer> MOV FRC RNDU RNDD RNDE RNDZ NOT LZD
%token <integer> MUL MAC MACH LINE SAD2 SADA2 DP4 DPH DP3 DP2
%token <integer> AVG ADD SEL AND OR XOR SHR SHL ASR CMP CMPN PLN
%token <integer> ADDC BFI1 BFREV CBIT F16TO32 F32TO16 FBH FBL
%token <integer> SEND NOP JMPI IF IFF WHILE ELSE BREAK CONT HALT MSAVE
%token <integer> PUSH MREST POP WAIT DO ENDIF ILLEGAL
%token <integer> MATH_INST
%token <integer> MAD LRP BFE BFI2 SUBB
%token <integer> CALL RET
%token <integer> BRD BRC
%token NULL_TOKEN MATH SAMPLER GATEWAY READ WRITE URB THREAD_SPAWNER VME DATA_PORT CRE
%token MSGLEN RETURNLEN
%token <integer> ALLOCATE USED COMPLETE TRANSPOSE INTERLEAVE
%token SATURATE
%token <integer> INTEGER
%token <string> STRING
%token <number> NUMBER
%token <integer> INV LOG EXP SQRT RSQ POW SIN COS SINCOS INTDIV INTMOD
%token <integer> INTDIVMOD
%token SIGNED SCALAR
%token <integer> X Y Z W
%token <integer> KERNEL_PRAGMA END_KERNEL_PRAGMA CODE_PRAGMA END_CODE_PRAGMA
%token <integer> REG_COUNT_PAYLOAD_PRAGMA REG_COUNT_TOTAL_PRAGMA DECLARE_PRAGMA
%token <integer> BASE ELEMENTSIZE SRCREGION DSTREGION TYPE
%token <integer> DEFAULT_EXEC_SIZE_PRAGMA DEFAULT_REG_TYPE_PRAGMA
%nonassoc SUBREGNUM
%nonassoc SNDOPR
%left PLUS MINUS
%left MULTIPLY DIVIDE
%right UMINUS
%nonassoc DOT
%nonassoc STR_SYMBOL_REG
%nonassoc EMPTEXECSIZE
%nonassoc LPAREN
%type <integer> exp sndopr
%type <integer> simple_int
%type <instruction> instruction unaryinstruction binaryinstruction
%type <instruction> binaryaccinstruction trinaryinstruction sendinstruction
%type <instruction> jumpinstruction
%type <instruction> breakinstruction syncinstruction
%type <instruction> msgtarget
%type <instruction> instoptions instoption_list predicate
%type <instruction> mathinstruction
%type <instruction> subroutineinstruction
%type <instruction> multibranchinstruction
%type <instruction> nopinstruction loopinstruction ifelseinstruction haltinstruction
%type <string> label
%type <program> instrseq
%type <integer> instoption
%type <integer> unaryop binaryop binaryaccop breakop
%type <integer> trinaryop
%type <condition> conditionalmodifier
%type <integer> condition saturate negate abs chansel
%type <integer> writemask_x writemask_y writemask_z writemask_w
%type <integer> srcimmtype execsize dstregion immaddroffset
%type <integer> subregnum sampler_datatype
%type <integer> urb_swizzle urb_allocate urb_used urb_complete
%type <integer> math_function math_signed math_scalar
%type <integer> predctrl predstate
%type <region> region region_wh indirectregion declare_srcregion;
%type <regtype> regtype
%type <direct_reg> directgenreg directmsgreg addrreg accreg flagreg maskreg
%type <direct_reg> maskstackreg notifyreg
/* %type <direct_reg> maskstackdepthreg */
%type <direct_reg> statereg controlreg ipreg nullreg
%type <direct_reg> dstoperandex_typed srcarchoperandex_typed
%type <direct_reg> sendleadreg
%type <indirect_reg> indirectgenreg indirectmsgreg addrparam
%type <integer> mask_subreg maskstack_subreg
%type <integer> declare_elementsize declare_dstregion declare_type
/* %type <intger> maskstackdepth_subreg */
%type <symbol_reg> symbol_reg symbol_reg_p;
%type <imm32> imm32
%type <dst_operand> dst dstoperand dstoperandex dstreg post_dst writemask
%type <dst_operand> declare_base
%type <src_operand> directsrcoperand srcarchoperandex directsrcaccoperand
%type <src_operand> indirectsrcoperand
%type <src_operand> src srcimm imm32reg payload srcacc srcaccimm swizzle
%type <src_operand> relativelocation relativelocation2
%%
simple_int: INTEGER { $$ = $1; }
| MINUS INTEGER { $$ = -$2;}
;
exp: INTEGER { $$ = $1; }
| exp PLUS exp { $$ = $1 + $3; }
| exp MINUS exp { $$ = $1 - $3; }
| exp MULTIPLY exp { $$ = $1 * $3; }
| exp DIVIDE exp { if ($3) $$ = $1 / $3; else YYERROR;}
| MINUS exp %prec UMINUS { $$ = -$2;}
| LPAREN exp RPAREN { $$ = $2; }
;
ROOT: instrseq
{
compiled_program = $1;
}
;
label: STRING COLON
;
declare_base: BASE EQ dstreg
{
$$ = $3;
}
;
declare_elementsize: ELEMENTSIZE EQ exp
{
$$ = $3;
}
;
declare_srcregion: /* empty */
{
/* XXX is this default correct?*/
memset (&$$, '\0', sizeof ($$));
$$.vert_stride = ffs(0);
$$.width = ffs(1) - 1;
$$.horiz_stride = ffs(0);
}
| SRCREGION EQ region
{
$$ = $3;
}
;
declare_dstregion: /* empty */
{
$$ = 1;
}
| DSTREGION EQ dstregion
{
$$ = $3;
}
;
declare_type: TYPE EQ regtype
{
$$ = $3.type;
}
;
declare_pragma: DECLARE_PRAGMA STRING declare_base declare_elementsize declare_srcregion declare_dstregion declare_type
{
struct declared_register *reg;
int defined;
defined = (reg = find_register($2)) != NULL;
if (defined) {
fprintf(stderr, "WARNING: %s already defined\n", $2);
free($2); // $2 has been malloc'ed by strdup
} else {
reg = calloc(sizeof(struct declared_register), 1);
reg->name = $2;
}
reg->base.reg_file = $3.reg_file;
reg->base.reg_nr = $3.reg_nr;
reg->base.subreg_nr = $3.subreg_nr;
reg->element_size = $4;
reg->src_region = $5;
reg->dst_region = $6;
reg->type = $7;
if (!defined) {
insert_register(reg);
}
}
;
reg_count_total_pragma: REG_COUNT_TOTAL_PRAGMA exp
;
reg_count_payload_pragma: REG_COUNT_PAYLOAD_PRAGMA exp
;
default_exec_size_pragma: DEFAULT_EXEC_SIZE_PRAGMA exp
{
program_defaults.execute_size = $2;
}
;
default_reg_type_pragma: DEFAULT_REG_TYPE_PRAGMA regtype
{
program_defaults.register_type = $2.type;
}
;
pragma: reg_count_total_pragma
|reg_count_payload_pragma
|default_exec_size_pragma
|default_reg_type_pragma
|declare_pragma
;
instrseq: instrseq pragma
{
$$ = $1;
}
| instrseq instruction SEMICOLON
{
struct brw_program_instruction *list_entry =
calloc(sizeof(struct brw_program_instruction), 1);
list_entry->instruction = $2;
list_entry->next = NULL;
if ($1.last) {
$1.last->next = list_entry;
} else {
$1.first = list_entry;
}
$1.last = list_entry;
$$ = $1;
}
| instruction SEMICOLON
{
struct brw_program_instruction *list_entry =
calloc(sizeof(struct brw_program_instruction), 1);
list_entry->instruction = $1;
list_entry->next = NULL;
$$.first = list_entry;
$$.last = list_entry;
}
| instrseq SEMICOLON
{
$$ = $1;
}
| instrseq label
{
struct brw_program_instruction *list_entry =
calloc(sizeof(struct brw_program_instruction), 1);
list_entry->string = strdup($2);
list_entry->islabel = 1;
list_entry->next = NULL;
if ($1.last) {
$1.last->next = list_entry;
} else {
$1.first = list_entry;
}
$1.last = list_entry;
$$ = $1;
}
| label
{
struct brw_program_instruction *list_entry =
calloc(sizeof(struct brw_program_instruction), 1);
list_entry->string = strdup($1);
list_entry->islabel = 1;
list_entry->next = NULL;
$$.first = list_entry;
$$.last = list_entry;
}
| pragma
{
$$.first = NULL;
$$.last = NULL;
}
| instrseq error SEMICOLON {
$$ = $1;
}
;
/* 1.4.1: Instruction groups */
// binaryinstruction: Source operands cannot be accumulators
// binaryaccinstruction: Source operands can be accumulators
instruction: unaryinstruction
| binaryinstruction
| binaryaccinstruction
| trinaryinstruction
| sendinstruction
| jumpinstruction
| ifelseinstruction
| breakinstruction
| syncinstruction
| mathinstruction
| subroutineinstruction
| multibranchinstruction
| nopinstruction
| haltinstruction
| loopinstruction
;
ifelseinstruction: ENDIF
{
// for Gen4
if(IS_GENp(6)) { // For gen6+.
fprintf(stderr, "ENDIF Syntax error: should be 'ENDIF execsize relativelocation'\n");
YYERROR;
}
memset(&$$, 0, sizeof($$));
$$.header.opcode = $1;
$$.header.thread_control |= BRW_THREAD_SWITCH;
$$.bits1.da1.dest_horiz_stride = 1;
$$.bits1.da1.src1_reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.bits1.da1.src1_reg_type = BRW_REGISTER_TYPE_UD;
}
| ENDIF execsize relativelocation instoptions
{
// for Gen6+
/* Gen6, Gen7 bspec: predication is prohibited */
if(!IS_GENp(6)) { // for gen6-
fprintf(stderr, "ENDIF Syntax error: should be 'ENDIF'\n");
YYERROR;
}
memset(&$$, 0, sizeof($$));
$$.header.opcode = $1;
$$.header.execution_size = $2;
$$.first_reloc_target = $3.reloc_target;
$$.first_reloc_offset = $3.imm32;
}
| ELSE execsize relativelocation instoptions
{
if(!IS_GENp(6)) {
// for Gen4, Gen5. gen_level < 60
/* Set the istack pop count, which must always be 1. */
$3.imm32 |= (1 << 16);
memset(&$$, 0, sizeof($$));
$$.header.opcode = $1;
$$.header.execution_size = $2;
$$.header.thread_control |= BRW_THREAD_SWITCH;
set_instruction_dest(&$$, &ip_dst);
set_instruction_src0(&$$, &ip_src);
set_instruction_src1(&$$, &$3);
$$.first_reloc_target = $3.reloc_target;
$$.first_reloc_offset = $3.imm32;
} else if(IS_GENp(6)) {
memset(&$$, 0, sizeof($$));
$$.header.opcode = $1;
$$.header.execution_size = $2;
$$.first_reloc_target = $3.reloc_target;
$$.first_reloc_offset = $3.imm32;
} else {
fprintf(stderr, "'ELSE' instruction is not implemented.\n");
YYERROR;
}
}
| predicate IF execsize relativelocation
{
/* for Gen4, Gen5 */
/* The branch instructions require that the IP register
* be the destination and first source operand, while the
* offset is the second source operand. The offset is added
* to the pre-incremented IP.
*/
/* for Gen6 */
if(IS_GENp(7)) {
/* Error in Gen7+. */
fprintf(stderr, "Syntax error: IF should be 'IF execsize JIP UIP'\n");
YYERROR;
}
memset(&$$, 0, sizeof($$));
set_instruction_predicate(&$$, &$1);
$$.header.opcode = $2;
$$.header.execution_size = $3;
if(!IS_GENp(6)) {
$$.header.thread_control |= BRW_THREAD_SWITCH;
set_instruction_dest(&$$, &ip_dst);
set_instruction_src0(&$$, &ip_src);
set_instruction_src1(&$$, &$4);
}
$$.first_reloc_target = $4.reloc_target;
$$.first_reloc_offset = $4.imm32;
}
| predicate IF execsize relativelocation relativelocation
{
/* for Gen7+ */
if(!IS_GENp(7)) {
fprintf(stderr, "Syntax error: IF should be 'IF execsize relativelocation'\n");
YYERROR;
}
memset(&$$, 0, sizeof($$));
set_instruction_predicate(&$$, &$1);
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.first_reloc_target = $4.reloc_target;
$$.first_reloc_offset = $4.imm32;
$$.second_reloc_target = $5.reloc_target;
$$.second_reloc_offset = $5.imm32;
}
;
loopinstruction: predicate WHILE execsize relativelocation instoptions
{
if(!IS_GENp(6)) {
/* The branch instructions require that the IP register
* be the destination and first source operand, while the
* offset is the second source operand. The offset is added
* to the pre-incremented IP.
*/
set_instruction_dest(&$$, &ip_dst);
memset(&$$, 0, sizeof($$));
set_instruction_predicate(&$$, &$1);
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.header.thread_control |= BRW_THREAD_SWITCH;
set_instruction_src0(&$$, &ip_src);
set_instruction_src1(&$$, &$4);
$$.first_reloc_target = $4.reloc_target;
$$.first_reloc_offset = $4.imm32;
} else if (IS_GENp(6)) {
/* Gen6 spec:
dest must have the same element size as src0.
dest horizontal stride must be 1. */
memset(&$$, 0, sizeof($$));
set_instruction_predicate(&$$, &$1);
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.first_reloc_target = $4.reloc_target;
$$.first_reloc_offset = $4.imm32;
} else {
fprintf(stderr, "'WHILE' instruction is not implemented!\n");
YYERROR;
}
}
| DO
{
// deprecated
memset(&$$, 0, sizeof($$));
$$.header.opcode = $1;
};
haltinstruction: predicate HALT execsize relativelocation relativelocation instoptions
{
// for Gen6, Gen7
/* Gen6, Gen7 bspec: dst and src0 must be the null reg. */
memset(&$$, 0, sizeof($$));
set_instruction_predicate(&$$, &$1);
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.first_reloc_target = $4.reloc_target;
$$.first_reloc_offset = $4.imm32;
$$.second_reloc_target = $5.reloc_target;
$$.second_reloc_offset = $5.imm32;
set_instruction_dest(&$$, &dst_null_reg);
set_instruction_src0(&$$, &src_null_reg);
};
multibranchinstruction:
predicate BRD execsize relativelocation instoptions
{
/* Gen7 bspec: dest must be null. use Switch option */
memset(&$$, 0, sizeof($$));
set_instruction_predicate(&$$, &$1);
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.header.thread_control |= BRW_THREAD_SWITCH;
$$.first_reloc_target = $4.reloc_target;
$$.first_reloc_offset = $4.imm32;
set_instruction_dest(&$$, &dst_null_reg);
}
| predicate BRC execsize relativelocation relativelocation instoptions
{
/* Gen7 bspec: dest must be null. src0 must be null. use Switch option */
memset(&$$, 0, sizeof($$));
set_instruction_predicate(&$$, &$1);
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.header.thread_control |= BRW_THREAD_SWITCH;
$$.first_reloc_target = $4.reloc_target;
$$.first_reloc_offset = $4.imm32;
$$.second_reloc_target = $5.reloc_target;
$$.second_reloc_offset = $5.imm32;
set_instruction_dest(&$$, &dst_null_reg);
set_instruction_src0(&$$, &src_null_reg);
}
;
subroutineinstruction:
predicate CALL execsize dst relativelocation instoptions
{
/*
Gen6 bspec:
source, dest type should be DWORD.
dest must be QWord aligned.
source0 region control must be <2,2,1>.
execution size must be 2.
QtrCtrl is prohibited.
JIP is an immediate operand, must be of type W.
Gen7 bspec:
source, dest type should be DWORD.
dest must be QWord aligned.
source0 region control must be <2,2,1>.
execution size must be 2.
*/
memset(&$$, 0, sizeof($$));
set_instruction_predicate(&$$, &$1);
$$.header.opcode = $2;
$$.header.execution_size = 1; /* execution size must be 2. Here 1 is encoded 2. */
$4.reg_type = BRW_REGISTER_TYPE_D; /* dest type should be DWORD */
set_instruction_dest(&$$, &$4);
struct src_operand src0;
memset(&src0, 0, sizeof(src0));
src0.reg_type = BRW_REGISTER_TYPE_D; /* source type should be DWORD */
/* source0 region control must be <2,2,1>. */
src0.horiz_stride = 1; /*encoded 1*/
src0.width = 1; /*encoded 2*/
src0.vert_stride = 2; /*encoded 2*/
set_instruction_src0(&$$, &src0);
$$.first_reloc_target = $5.reloc_target;
$$.first_reloc_offset = $5.imm32;
}
| predicate RET execsize dstoperandex src instoptions
{
/*
Gen6, 7:
source cannot be accumulator.
dest must be null.
src0 region control must be <2,2,1> (not specified clearly. should be same as CALL)
*/
memset(&$$, 0, sizeof($$));
set_instruction_predicate(&$$, &$1);
$$.header.opcode = $2;
$$.header.execution_size = 1; /* execution size of RET should be 2 */
set_instruction_dest(&$$, &dst_null_reg);
$5.reg_type = BRW_REGISTER_TYPE_D;
$5.horiz_stride = 1; /*encoded 1*/
$5.width = 1; /*encoded 2*/
$5.vert_stride = 2; /*encoded 2*/
set_instruction_src0(&$$, &$5);
}
;
unaryinstruction:
predicate unaryop conditionalmodifier saturate execsize
dst srcaccimm instoptions
{
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.destreg__conditionalmod = $3.cond;
$$.header.saturate = $4;
$$.header.execution_size = $5;
set_instruction_options(&$$, &$8);
set_instruction_predicate(&$$, &$1);
if (set_instruction_dest(&$$, &$6) != 0)
YYERROR;
if (set_instruction_src0(&$$, &$7) != 0)
YYERROR;
if ($3.flag_subreg_nr != -1) {
if ($$.header.predicate_control != BRW_PREDICATE_NONE &&
($1.bits2.da1.flag_reg_nr != $3.flag_reg_nr ||
$1.bits2.da1.flag_subreg_nr != $3.flag_subreg_nr))
fprintf(stderr, "WARNING: must use the same flag register if both prediction and conditional modifier are enabled\n");
$$.bits2.da1.flag_reg_nr = $3.flag_reg_nr;
$$.bits2.da1.flag_subreg_nr = $3.flag_subreg_nr;
}
if (!IS_GENp(6) &&
get_type_size($$.bits1.da1.dest_reg_type) * (1 << $$.header.execution_size) == 64)
$$.header.compression_control = BRW_COMPRESSION_COMPRESSED;
}
;
unaryop: MOV | FRC | RNDU | RNDD | RNDE | RNDZ | NOT | LZD | BFREV | CBIT
| F16TO32 | F32TO16 | FBH | FBL
;
// Source operands cannot be accumulators
binaryinstruction:
predicate binaryop conditionalmodifier saturate execsize
dst src srcimm instoptions
{
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.destreg__conditionalmod = $3.cond;
$$.header.saturate = $4;
$$.header.execution_size = $5;
set_instruction_options(&$$, &$9);
set_instruction_predicate(&$$, &$1);
if (set_instruction_dest(&$$, &$6) != 0)
YYERROR;
if (set_instruction_src0(&$$, &$7) != 0)
YYERROR;
if (set_instruction_src1(&$$, &$8) != 0)
YYERROR;
if ($3.flag_subreg_nr != -1) {
if ($$.header.predicate_control != BRW_PREDICATE_NONE &&
($1.bits2.da1.flag_reg_nr != $3.flag_reg_nr ||
$1.bits2.da1.flag_subreg_nr != $3.flag_subreg_nr))
fprintf(stderr, "WARNING: must use the same flag register if both prediction and conditional modifier are enabled\n");
$$.bits2.da1.flag_reg_nr = $3.flag_reg_nr;
$$.bits2.da1.flag_subreg_nr = $3.flag_subreg_nr;
}
if (!IS_GENp(6) &&
get_type_size($$.bits1.da1.dest_reg_type) * (1 << $$.header.execution_size) == 64)
$$.header.compression_control = BRW_COMPRESSION_COMPRESSED;
}
;
/* bspec: BFI1 should not access accumulator. */
binaryop: MUL | MAC | MACH | LINE | SAD2 | SADA2 | DP4 | DPH | DP3 | DP2 | PLN | BFI1
;
// Source operands can be accumulators
binaryaccinstruction:
predicate binaryaccop conditionalmodifier saturate execsize
dst srcacc srcimm instoptions
{
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.destreg__conditionalmod = $3.cond;
$$.header.saturate = $4;
$$.header.execution_size = $5;
set_instruction_options(&$$, &$9);
set_instruction_predicate(&$$, &$1);
if (set_instruction_dest(&$$, &$6) != 0)
YYERROR;
if (set_instruction_src0(&$$, &$7) != 0)
YYERROR;
if (set_instruction_src1(&$$, &$8) != 0)
YYERROR;
if ($3.flag_subreg_nr != -1) {
if ($$.header.predicate_control != BRW_PREDICATE_NONE &&
($1.bits2.da1.flag_reg_nr != $3.flag_reg_nr ||
$1.bits2.da1.flag_subreg_nr != $3.flag_subreg_nr))
fprintf(stderr, "WARNING: must use the same flag register if both prediction and conditional modifier are enabled\n");
$$.bits2.da1.flag_reg_nr = $3.flag_reg_nr;
$$.bits2.da1.flag_subreg_nr = $3.flag_subreg_nr;
}
if (!IS_GENp(6) &&
get_type_size($$.bits1.da1.dest_reg_type) * (1 << $$.header.execution_size) == 64)
$$.header.compression_control = BRW_COMPRESSION_COMPRESSED;
}
;
/* TODO: bspec says ADDC/SUBB/CMP/CMPN/SHL/BFI1 cannot use accumulator as dest. */
binaryaccop: AVG | ADD | SEL | AND | OR | XOR | SHR | SHL | ASR | CMP | CMPN | ADDC | SUBB
;
trinaryop: MAD | LRP | BFE | BFI2
;
trinaryinstruction:
predicate trinaryop conditionalmodifier saturate execsize
dst src src src instoptions
{
memset(&$$, 0, sizeof($$));
$$.header.predicate_control = $1.header.predicate_control;
$$.header.predicate_inverse = $1.header.predicate_inverse;
$$.bits1.da3src.flag_reg_nr = $1.bits2.da1.flag_reg_nr;
$$.bits1.da3src.flag_subreg_nr = $1.bits2.da1.flag_subreg_nr;
$$.header.opcode = $2;
$$.header.destreg__conditionalmod = $3.cond;
$$.header.saturate = $4;
$$.header.execution_size = $5;
if (set_instruction_dest_three_src(&$$, &$6))
YYERROR;
if (set_instruction_src0_three_src(&$$, &$7))
YYERROR;
if (set_instruction_src1_three_src(&$$, &$8))
YYERROR;
if (set_instruction_src2_three_src(&$$, &$9))
YYERROR;
set_instruction_options(&$$, &$10);
if ($3.flag_subreg_nr != -1) {
if ($$.header.predicate_control != BRW_PREDICATE_NONE &&
($1.bits2.da1.flag_reg_nr != $3.flag_reg_nr ||
$1.bits2.da1.flag_subreg_nr != $3.flag_subreg_nr))
fprintf(stderr, "WARNING: must use the same flag register if both prediction and conditional modifier are enabled\n");
}
}
;
sendinstruction: predicate SEND execsize exp post_dst payload msgtarget
MSGLEN exp RETURNLEN exp instoptions
{
/* Send instructions are messy. The first argument is the
* post destination -- the grf register that the response
* starts from. The second argument is the current
* destination, which is the start of the message arguments
* to the shared function, and where src0 payload is loaded
* to if not null. The payload is typically based on the
* grf 0 thread payload of your current thread, and is
* implicitly loaded if non-null.
*/
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.header.destreg__conditionalmod = $4; /* msg reg index */
set_instruction_predicate(&$$, &$1);
if (set_instruction_dest(&$$, &$5) != 0)
YYERROR;
if (IS_GENp(6)) {
struct src_operand src0;
memset(&src0, 0, sizeof(src0));
src0.address_mode = BRW_ADDRESS_DIRECT;
if (IS_GENp(7))
src0.reg_file = BRW_GENERAL_REGISTER_FILE;
else
src0.reg_file = BRW_MESSAGE_REGISTER_FILE;
src0.reg_type = BRW_REGISTER_TYPE_D;
src0.reg_nr = $4;
src0.subreg_nr = 0;
set_instruction_src0(&$$, &src0);
} else {
if (set_instruction_src0(&$$, &$6) != 0)
YYERROR;
}
$$.bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE;
$$.bits1.da1.src1_reg_type = BRW_REGISTER_TYPE_D;
if (IS_GENp(5)) {
if (IS_GENp(6)) {
$$.header.destreg__conditionalmod = $7.bits2.send_gen5.sfid;
} else {
$$.header.destreg__conditionalmod = $4; /* msg reg index */
$$.bits2.send_gen5.sfid = $7.bits2.send_gen5.sfid;
$$.bits2.send_gen5.end_of_thread = $12.bits3.generic_gen5.end_of_thread;
}
$$.bits3.generic_gen5 = $7.bits3.generic_gen5;
$$.bits3.generic_gen5.msg_length = $9;
$$.bits3.generic_gen5.response_length = $11;
$$.bits3.generic_gen5.end_of_thread =
$12.bits3.generic_gen5.end_of_thread;
} else {
$$.header.destreg__conditionalmod = $4; /* msg reg index */
$$.bits3.generic = $7.bits3.generic;
$$.bits3.generic.msg_length = $9;
$$.bits3.generic.response_length = $11;
$$.bits3.generic.end_of_thread =
$12.bits3.generic.end_of_thread;
}
}
| predicate SEND execsize dst sendleadreg payload directsrcoperand instoptions
{
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.header.destreg__conditionalmod = $5.reg_nr; /* msg reg index */
set_instruction_predicate(&$$, &$1);
if (set_instruction_dest(&$$, &$4) != 0)
YYERROR;
if (set_instruction_src0(&$$, &$6) != 0)
YYERROR;
/* XXX is this correct? */
if (set_instruction_src1(&$$, &$7) != 0)
YYERROR;
}
| predicate SEND execsize dst sendleadreg payload imm32reg instoptions
{
if ($7.reg_type != BRW_REGISTER_TYPE_UD &&
$7.reg_type != BRW_REGISTER_TYPE_D &&
$7.reg_type != BRW_REGISTER_TYPE_V) {
fprintf (stderr, "%d: non-int D/UD/V representation: %d,type=%d\n", yylineno, $7.imm32, $7.reg_type);
YYERROR;
}
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.header.destreg__conditionalmod = $5.reg_nr; /* msg reg index */
set_instruction_predicate(&$$, &$1);
if (set_instruction_dest(&$$, &$4) != 0)
YYERROR;
if (set_instruction_src0(&$$, &$6) != 0)
YYERROR;
$$.bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE;
$$.bits1.da1.src1_reg_type = $7.reg_type;
$$.bits3.ud = $7.imm32;
}
| predicate SEND execsize dst sendleadreg sndopr imm32reg instoptions
{
struct src_operand src0;
if (!IS_GENp(6)) {
fprintf(stderr, "error: the syntax of send instruction\n");
YYERROR;
}
if ($7.reg_type != BRW_REGISTER_TYPE_UD &&
$7.reg_type != BRW_REGISTER_TYPE_D &&
$7.reg_type != BRW_REGISTER_TYPE_V) {
fprintf (stderr, "%d: non-int D/UD/V representation: %d,type=%d\n", yylineno, $7.imm32, $7.reg_type);
YYERROR;
}
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.header.destreg__conditionalmod = ($6 & EX_DESC_SFID_MASK); /* SFID */
set_instruction_predicate(&$$, &$1);
if (set_instruction_dest(&$$, &$4) != 0)
YYERROR;
memset(&src0, 0, sizeof(src0));
src0.address_mode = BRW_ADDRESS_DIRECT;
if (IS_GENp(7)) {
src0.reg_file = BRW_GENERAL_REGISTER_FILE;
src0.reg_type = BRW_REGISTER_TYPE_UB;
} else {
src0.reg_file = BRW_MESSAGE_REGISTER_FILE;
src0.reg_type = BRW_REGISTER_TYPE_D;
}
src0.reg_nr = $5.reg_nr;
src0.subreg_nr = 0;
set_instruction_src0(&$$, &src0);
$$.bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE;
$$.bits1.da1.src1_reg_type = $7.reg_type;
$$.bits3.ud = $7.imm32;
$$.bits3.generic_gen5.end_of_thread = !!($6 & EX_DESC_EOT_MASK);
}
| predicate SEND execsize dst sendleadreg sndopr directsrcoperand instoptions
{
struct src_operand src0;
if (!IS_GENp(6)) {
fprintf(stderr, "error: the syntax of send instruction\n");
YYERROR;
}
if ($7.reg_file != BRW_ARCHITECTURE_REGISTER_FILE ||
($7.reg_nr & 0xF0) != BRW_ARF_ADDRESS ||
($7.reg_nr & 0x0F) != 0 ||
$7.subreg_nr != 0) {
fprintf (stderr, "%d: scalar register must be a0.0<0;1,0>:ud\n", yylineno);
YYERROR;
}
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.header.destreg__conditionalmod = ($6 & EX_DESC_SFID_MASK); /* SFID */
set_instruction_predicate(&$$, &$1);
if (set_instruction_dest(&$$, &$4) != 0)
YYERROR;
memset(&src0, 0, sizeof(src0));
src0.address_mode = BRW_ADDRESS_DIRECT;
if (IS_GENp(7)) {
src0.reg_file = BRW_GENERAL_REGISTER_FILE;
src0.reg_type = BRW_REGISTER_TYPE_UB;
} else {
src0.reg_file = BRW_MESSAGE_REGISTER_FILE;
src0.reg_type = BRW_REGISTER_TYPE_D;
}
src0.reg_nr = $5.reg_nr;
src0.subreg_nr = 0;
set_instruction_src0(&$$, &src0);
set_instruction_src1(&$$, &$7);
$$.bits3.generic_gen5.end_of_thread = !!($6 & EX_DESC_EOT_MASK);
}
| predicate SEND execsize dst sendleadreg payload sndopr imm32reg instoptions
{
if ($8.reg_type != BRW_REGISTER_TYPE_UD &&
$8.reg_type != BRW_REGISTER_TYPE_D &&
$8.reg_type != BRW_REGISTER_TYPE_V) {
fprintf (stderr, "%d: non-int D/UD/V representation: %d,type=%d\n", yylineno, $8.imm32, $8.reg_type);
YYERROR;
}
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.header.destreg__conditionalmod = $5.reg_nr; /* msg reg index */
set_instruction_predicate(&$$, &$1);
if (set_instruction_dest(&$$, &$4) != 0)
YYERROR;
if (set_instruction_src0(&$$, &$6) != 0)
YYERROR;
$$.bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE;
$$.bits1.da1.src1_reg_type = $8.reg_type;
if (IS_GENx(5)) {
$$.bits2.send_gen5.sfid = ($7 & EX_DESC_SFID_MASK);
$$.bits3.ud = $8.imm32;
$$.bits3.generic_gen5.end_of_thread = !!($7 & EX_DESC_EOT_MASK);
}
else
$$.bits3.ud = $8.imm32;
}
| predicate SEND execsize dst sendleadreg payload exp directsrcoperand instoptions
{
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.header.destreg__conditionalmod = $5.reg_nr; /* msg reg index */
set_instruction_predicate(&$$, &$1);
if (set_instruction_dest(&$$, &$4) != 0)
YYERROR;
if (set_instruction_src0(&$$, &$6) != 0)
YYERROR;
/* XXX is this correct? */
if (set_instruction_src1(&$$, &$8) != 0)
YYERROR;
if (IS_GENx(5)) {
$$.bits2.send_gen5.sfid = $7;
}
}
;
sndopr: exp %prec SNDOPR
{
$$ = $1;
}
;
jumpinstruction: predicate JMPI execsize relativelocation2
{
/* The jump instruction requires that the IP register
* be the destination and first source operand, while the
* offset is the second source operand. The next instruction
* is the post-incremented IP plus the offset.
*/
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.execution_size = ffs(1) - 1;
if(advanced_flag)
$$.header.mask_control = BRW_MASK_DISABLE;
set_instruction_predicate(&$$, &$1);
set_instruction_dest(&$$, &ip_dst);
set_instruction_src0(&$$, &ip_src);
set_instruction_src1(&$$, &$4);
$$.first_reloc_target = $4.reloc_target;
$$.first_reloc_offset = $4.imm32;
}
;
mathinstruction: predicate MATH_INST execsize dst src srcimm math_function instoptions
{
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.destreg__conditionalmod = $7;
$$.header.execution_size = $3;
set_instruction_options(&$$, &$8);
set_instruction_predicate(&$$, &$1);
if (set_instruction_dest(&$$, &$4) != 0)
YYERROR;
if (set_instruction_src0(&$$, &$5) != 0)
YYERROR;
if (set_instruction_src1(&$$, &$6) != 0)
YYERROR;
}
;
breakinstruction: predicate breakop execsize relativelocation relativelocation instoptions
{
// for Gen6, Gen7
memset(&$$, 0, sizeof($$));
set_instruction_predicate(&$$, &$1);
$$.header.opcode = $2;
$$.header.execution_size = $3;
$$.first_reloc_target = $4.reloc_target;
$$.first_reloc_offset = $4.imm32;
$$.second_reloc_target = $5.reloc_target;
$$.second_reloc_offset = $5.imm32;
}
;
breakop: BREAK | CONT
;
/*
maskpushop: MSAVE | PUSH
;
*/
syncinstruction: predicate WAIT notifyreg
{
struct dst_operand notify_dst;
struct src_operand notify_src;
memset(&$$, 0, sizeof($$));
$$.header.opcode = $2;
$$.header.execution_size = ffs(1) - 1;
set_direct_dst_operand(&notify_dst, &$3, BRW_REGISTER_TYPE_D);
set_instruction_dest(&$$, &notify_dst);
set_direct_src_operand(&notify_src, &$3, BRW_REGISTER_TYPE_D);
set_instruction_src0(&$$, &notify_src);
set_instruction_src1(&$$, &src_null_reg);
}
;
nopinstruction: NOP
{
memset(&$$, 0, sizeof($$));
$$.header.opcode = $1;
};
/* XXX! */
payload: directsrcoperand
;
post_dst: dst
;
msgtarget: NULL_TOKEN
{
if (IS_GENp(5)) {
$$.bits2.send_gen5.sfid= BRW_MESSAGE_TARGET_NULL;
$$.bits3.generic_gen5.header_present = 0; /* ??? */
} else {
$$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_NULL;
}
}
| SAMPLER LPAREN INTEGER COMMA INTEGER COMMA
sampler_datatype RPAREN
{
if (IS_GENp(7)) {
$$.bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_SAMPLER;
$$.bits3.generic_gen5.header_present = 1; /* ??? */
$$.bits3.sampler_gen7.binding_table_index = $3;
$$.bits3.sampler_gen7.sampler = $5;
$$.bits3.sampler_gen7.simd_mode = 2; /* SIMD16, maybe we should add a new parameter */
} else if (IS_GENp(5)) {
$$.bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_SAMPLER;
$$.bits3.generic_gen5.header_present = 1; /* ??? */
$$.bits3.sampler_gen5.binding_table_index = $3;
$$.bits3.sampler_gen5.sampler = $5;
$$.bits3.sampler_gen5.simd_mode = 2; /* SIMD16, maybe we should add a new parameter */
} else {
$$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_SAMPLER;
$$.bits3.sampler.binding_table_index = $3;
$$.bits3.sampler.sampler = $5;
switch ($7) {
case TYPE_F:
$$.bits3.sampler.return_format =
BRW_SAMPLER_RETURN_FORMAT_FLOAT32;
break;
case TYPE_UD:
$$.bits3.sampler.return_format =
BRW_SAMPLER_RETURN_FORMAT_UINT32;
break;
case TYPE_D:
$$.bits3.sampler.return_format =
BRW_SAMPLER_RETURN_FORMAT_SINT32;
break;
}
}
}
| MATH math_function saturate math_signed math_scalar
{
if (IS_GENp(6)) {
fprintf (stderr, "Gen6+ doesn't have math function\n");
YYERROR;
} else if (IS_GENx(5)) {
$$.bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_MATH;
$$.bits3.generic_gen5.header_present = 0;
$$.bits3.math_gen5.function = $2;
if ($3 == BRW_INSTRUCTION_SATURATE)
$$.bits3.math_gen5.saturate = 1;
else
$$.bits3.math_gen5.saturate = 0;
$$.bits3.math_gen5.int_type = $4;
$$.bits3.math_gen5.precision = BRW_MATH_PRECISION_FULL;
$$.bits3.math_gen5.data_type = $5;
} else {
$$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_MATH;
$$.bits3.math.function = $2;
if ($3 == BRW_INSTRUCTION_SATURATE)
$$.bits3.math.saturate = 1;
else
$$.bits3.math.saturate = 0;
$$.bits3.math.int_type = $4;
$$.bits3.math.precision = BRW_MATH_PRECISION_FULL;
$$.bits3.math.data_type = $5;
}
}
| GATEWAY
{
if (IS_GENp(5)) {
$$.bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_GATEWAY;
$$.bits3.generic_gen5.header_present = 0; /* ??? */
} else {
$$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_GATEWAY;
}
}
| READ LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA
INTEGER RPAREN
{
if (IS_GENx(7)) {
$$.bits2.send_gen5.sfid =
BRW_MESSAGE_TARGET_DP_SC;
$$.bits3.generic_gen5.header_present = 1;
$$.bits3.dp_gen7.binding_table_index = $3;
$$.bits3.dp_gen7.msg_control = $7;
$$.bits3.dp_gen7.msg_type = $9;
} else if (IS_GENx(6)) {
$$.bits2.send_gen5.sfid =
BRW_MESSAGE_TARGET_DP_SC;
$$.bits3.generic_gen5.header_present = 1;
$$.bits3.gen6_dp_sampler_const_cache.binding_table_index = $3;
$$.bits3.gen6_dp_sampler_const_cache.msg_control = $7;
$$.bits3.gen6_dp_sampler_const_cache.msg_type = $9;
} else if (IS_GENx(5)) {
$$.bits2.send_gen5.sfid =
BRW_MESSAGE_TARGET_DATAPORT_READ;
$$.bits3.generic_gen5.header_present = 1;
$$.bits3.dp_read_gen5.binding_table_index = $3;
$$.bits3.dp_read_gen5.target_cache = $5;
$$.bits3.dp_read_gen5.msg_control = $7;
$$.bits3.dp_read_gen5.msg_type = $9;
} else {
$$.bits3.generic.msg_target =
BRW_MESSAGE_TARGET_DATAPORT_READ;
$$.bits3.dp_read.binding_table_index = $3;
$$.bits3.dp_read.target_cache = $5;
$$.bits3.dp_read.msg_control = $7;
$$.bits3.dp_read.msg_type = $9;
}
}
| WRITE LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA
INTEGER RPAREN
{
if (IS_GENx(7)) {
$$.bits2.send_gen5.sfid =
BRW_MESSAGE_TARGET_DP_RC;
$$.bits3.generic_gen5.header_present = 1;
$$.bits3.dp_gen7.binding_table_index = $3;
$$.bits3.dp_gen7.msg_control = $5;
$$.bits3.dp_gen7.msg_type = $7;
} else if (IS_GENx(6)) {
$$.bits2.send_gen5.sfid =
BRW_MESSAGE_TARGET_DP_RC;
/* Sandybridge supports headerlesss message for render target write.
* Currently the GFX assembler doesn't support it. so the program must provide
* message header
*/
$$.bits3.generic_gen5.header_present = 1;
$$.bits3.dp_write_gen6.binding_table_index = $3;
$$.bits3.dp_write_gen6.msg_control = $5;
$$.bits3.dp_write_gen6.msg_type = $7;
$$.bits3.dp_write_gen6.send_commit_msg = $9;
} else if (IS_GENx(5)) {
$$.bits2.send_gen5.sfid =
BRW_MESSAGE_TARGET_DATAPORT_WRITE;
$$.bits3.generic_gen5.header_present = 1;
$$.bits3.dp_write_gen5.binding_table_index = $3;
$$.bits3.dp_write_gen5.pixel_scoreboard_clear = ($5 & 0x8) >> 3;
$$.bits3.dp_write_gen5.msg_control = $5 & 0x7;
$$.bits3.dp_write_gen5.msg_type = $7;
$$.bits3.dp_write_gen5.send_commit_msg = $9;
} else {
$$.bits3.generic.msg_target =
BRW_MESSAGE_TARGET_DATAPORT_WRITE;
$$.bits3.dp_write.binding_table_index = $3;
/* The msg control field of brw_struct.h is split into
* msg control and pixel_scoreboard_clear, even though
* pixel_scoreboard_clear isn't common to all write messages.
*/
$$.bits3.dp_write.pixel_scoreboard_clear = ($5 & 0x8) >> 3;
$$.bits3.dp_write.msg_control = $5 & 0x7;
$$.bits3.dp_write.msg_type = $7;
$$.bits3.dp_write.send_commit_msg = $9;
}
}
| WRITE LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA
INTEGER COMMA INTEGER RPAREN
{
if (IS_GENx(7)) {
$$.bits2.send_gen5.sfid =
BRW_MESSAGE_TARGET_DP_RC;
$$.bits3.generic_gen5.header_present = ($11 != 0);
$$.bits3.dp_gen7.binding_table_index = $3;
$$.bits3.dp_gen7.msg_control = $5;
$$.bits3.dp_gen7.msg_type = $7;
} else if (IS_GENx(6)) {
$$.bits2.send_gen5.sfid =
BRW_MESSAGE_TARGET_DP_RC;
$$.bits3.generic_gen5.header_present = ($11 != 0);
$$.bits3.dp_write_gen6.binding_table_index = $3;
$$.bits3.dp_write_gen6.msg_control = $5;
$$.bits3.dp_write_gen6.msg_type = $7;
$$.bits3.dp_write_gen6.send_commit_msg = $9;
} else if (IS_GENx(5)) {
$$.bits2.send_gen5.sfid =
BRW_MESSAGE_TARGET_DATAPORT_WRITE;
$$.bits3.generic_gen5.header_present = ($11 != 0);
$$.bits3.dp_write_gen5.binding_table_index = $3;
$$.bits3.dp_write_gen5.pixel_scoreboard_clear = ($5 & 0x8) >> 3;
$$.bits3.dp_write_gen5.msg_control = $5 & 0x7;
$$.bits3.dp_write_gen5.msg_type = $7;
$$.bits3.dp_write_gen5.send_commit_msg = $9;
} else {
$$.bits3.generic.msg_target =
BRW_MESSAGE_TARGET_DATAPORT_WRITE;
$$.bits3.dp_write.binding_table_index = $3;
/* The msg control field of brw_struct.h is split into
* msg control and pixel_scoreboard_clear, even though
* pixel_scoreboard_clear isn't common to all write messages.
*/
$$.bits3.dp_write.pixel_scoreboard_clear = ($5 & 0x8) >> 3;
$$.bits3.dp_write.msg_control = $5 & 0x7;
$$.bits3.dp_write.msg_type = $7;
$$.bits3.dp_write.send_commit_msg = $9;
}
}
| URB INTEGER urb_swizzle urb_allocate urb_used urb_complete
{
$$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_URB;
if (IS_GENp(5)) {
$$.bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_URB;
$$.bits3.generic_gen5.header_present = 1;
$$.bits3.urb_gen5.opcode = BRW_URB_OPCODE_WRITE;
$$.bits3.urb_gen5.offset = $2;
$$.bits3.urb_gen5.swizzle_control = $3;
$$.bits3.urb_gen5.pad = 0;
$$.bits3.urb_gen5.allocate = $4;
$$.bits3.urb_gen5.used = $5;
$$.bits3.urb_gen5.complete = $6;
} else {
$$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_URB;
$$.bits3.urb.opcode = BRW_URB_OPCODE_WRITE;
$$.bits3.urb.offset = $2;
$$.bits3.urb.swizzle_control = $3;
$$.bits3.urb.pad = 0;
$$.bits3.urb.allocate = $4;
$$.bits3.urb.used = $5;
$$.bits3.urb.complete = $6;
}
}
| THREAD_SPAWNER LPAREN INTEGER COMMA INTEGER COMMA
INTEGER RPAREN
{
$$.bits3.generic.msg_target =
BRW_MESSAGE_TARGET_THREAD_SPAWNER;
if (IS_GENp(5)) {
$$.bits2.send_gen5.sfid =
BRW_MESSAGE_TARGET_THREAD_SPAWNER;
$$.bits3.generic_gen5.header_present = 0;
$$.bits3.thread_spawner_gen5.opcode = $3;
$$.bits3.thread_spawner_gen5.requester_type = $5;
$$.bits3.thread_spawner_gen5.resource_select = $7;
} else {
$$.bits3.generic.msg_target =
BRW_MESSAGE_TARGET_THREAD_SPAWNER;
$$.bits3.thread_spawner.opcode = $3;
$$.bits3.thread_spawner.requester_type = $5;
$$.bits3.thread_spawner.resource_select = $7;
}
}
| VME LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA INTEGER RPAREN
{
$$.bits3.generic.msg_target =
BRW_MESSAGE_TARGET_VME;
if (IS_GENp(6)) {
$$.bits2.send_gen5.sfid =
BRW_MESSAGE_TARGET_VME;
$$.bits3.vme_gen6.binding_table_index = $3;
$$.bits3.vme_gen6.search_path_index = $5;
$$.bits3.vme_gen6.lut_subindex = $7;
$$.bits3.vme_gen6.message_type = $9;
$$.bits3.generic_gen5.header_present = 1;
} else {
fprintf (stderr, "Gen6- doesn't have vme function\n");
YYERROR;
}
}
| CRE LPAREN INTEGER COMMA INTEGER RPAREN
{
if (gen_level < 75) {
fprintf (stderr, "Below Gen7.5 doesn't have CRE function\n");
YYERROR;
}
$$.bits3.generic.msg_target =
BRW_MESSAGE_TARGET_CRE;
$$.bits2.send_gen5.sfid =
BRW_MESSAGE_TARGET_CRE;
$$.bits3.cre_gen75.binding_table_index = $3;
$$.bits3.cre_gen75.message_type = $5;
$$.bits3.generic_gen5.header_present = 1;
}
| DATA_PORT LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA
INTEGER COMMA INTEGER COMMA INTEGER RPAREN
{
$$.bits2.send_gen5.sfid = $3;
$$.bits3.generic_gen5.header_present = ($13 != 0);
if (IS_GENp(7)) {
if ($3 != BRW_MESSAGE_TARGET_DP_SC &&
$3 != BRW_MESSAGE_TARGET_DP_RC &&
$3 != BRW_MESSAGE_TARGET_DP_CC &&
$3 != BRW_MESSAGE_TARGET_DP_DC) {
fprintf (stderr, "error: wrong cache type\n");
YYERROR;
}
$$.bits3.dp_gen7.category = $11;
$$.bits3.dp_gen7.binding_table_index = $9;
$$.bits3.dp_gen7.msg_control = $7;
$$.bits3.dp_gen7.msg_type = $5;
} else if (IS_GENx(6)) {
if ($3 != BRW_MESSAGE_TARGET_DP_SC &&
$3 != BRW_MESSAGE_TARGET_DP_RC &&
$3 != BRW_MESSAGE_TARGET_DP_CC) {
fprintf (stderr, "error: wrong cache type\n");
YYERROR;
}
$$.bits3.dp_gen6.send_commit_msg = $11;
$$.bits3.dp_gen6.binding_table_index = $9;
$$.bits3.dp_gen6.msg_control = $7;
$$.bits3.dp_gen6.msg_type = $5;
} else if (!IS_GENp(5)) {
fprintf (stderr, "Gen6- doesn't support data port for sampler/render/constant/data cache\n");
YYERROR;
}
}
;
urb_allocate: ALLOCATE { $$ = 1; }
| /* empty */ { $$ = 0; }
;
urb_used: USED { $$ = 1; }
| /* empty */ { $$ = 0; }
;
urb_complete: COMPLETE { $$ = 1; }
| /* empty */ { $$ = 0; }
;
urb_swizzle: TRANSPOSE { $$ = BRW_URB_SWIZZLE_TRANSPOSE; }
| INTERLEAVE { $$ = BRW_URB_SWIZZLE_INTERLEAVE; }
| /* empty */ { $$ = BRW_URB_SWIZZLE_NONE; }
;
sampler_datatype:
TYPE_F
| TYPE_UD
| TYPE_D
;
math_function: INV | LOG | EXP | SQRT | POW | SIN | COS | SINCOS | INTDIV
| INTMOD | INTDIVMOD
;
math_signed: /* empty */ { $$ = 0; }
| SIGNED { $$ = 1; }
;
math_scalar: /* empty */ { $$ = 0; }
| SCALAR { $$ = 1; }
;
/* 1.4.2: Destination register */
dst: dstoperand | dstoperandex
;
dstoperand: symbol_reg dstregion
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = $1.base.reg_file;
$$.reg_nr = $1.base.reg_nr;
$$.subreg_nr = $1.base.subreg_nr;
if ($2 == DEFAULT_DSTREGION) {
$$.horiz_stride = $1.dst_region;
} else {
$$.horiz_stride = $2;
}
$$.reg_type = $1.type;
}
| dstreg dstregion writemask regtype
{
/* Returns an instruction with just the destination register
* filled in.
*/
memset (&$$, '\0', sizeof ($$));
$$.reg_file = $1.reg_file;
$$.reg_nr = $1.reg_nr;
$$.subreg_nr = $1.subreg_nr;
$$.address_mode = $1.address_mode;
$$.address_subreg_nr = $1.address_subreg_nr;
$$.indirect_offset = $1.indirect_offset;
$$.horiz_stride = $2;
$$.writemask_set = $3.writemask_set;
$$.writemask = $3.writemask;
$$.reg_type = $4.type;
}
;
/* The dstoperandex returns an instruction with just the destination register
* filled in.
*/
dstoperandex: dstoperandex_typed dstregion regtype
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = $1.reg_file;
$$.reg_nr = $1.reg_nr;
$$.subreg_nr = $1.subreg_nr;
$$.horiz_stride = $2;
$$.reg_type = $3.type;
}
| maskstackreg
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = $1.reg_file;
$$.reg_nr = $1.reg_nr;
$$.subreg_nr = $1.subreg_nr;
$$.horiz_stride = 1;
$$.reg_type = BRW_REGISTER_TYPE_UW;
}
| controlreg
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = $1.reg_file;
$$.reg_nr = $1.reg_nr;
$$.subreg_nr = $1.subreg_nr;
$$.horiz_stride = 1;
$$.reg_type = BRW_REGISTER_TYPE_UD;
}
| ipreg
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = $1.reg_file;
$$.reg_nr = $1.reg_nr;
$$.subreg_nr = $1.subreg_nr;
$$.horiz_stride = 1;
$$.reg_type = BRW_REGISTER_TYPE_UD;
}
| nullreg dstregion regtype
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = $1.reg_file;
$$.reg_nr = $1.reg_nr;
$$.subreg_nr = $1.subreg_nr;
$$.horiz_stride = $2;
$$.reg_type = $3.type;
}
;
dstoperandex_typed: accreg | flagreg | addrreg | maskreg
;
symbol_reg: STRING %prec STR_SYMBOL_REG
{
struct declared_register *dcl_reg = find_register($1);
if (dcl_reg == NULL) {
fprintf(stderr, "can't find register %s\n", $1);
YYERROR;
}
memcpy(&$$, dcl_reg, sizeof(*dcl_reg));
free($1); // $1 has been malloc'ed by strdup
}
| symbol_reg_p
{
$$=$1;
}
;
symbol_reg_p: STRING LPAREN exp RPAREN
{
struct declared_register *dcl_reg = find_register($1);
if (dcl_reg == NULL) {
fprintf(stderr, "can't find register %s\n", $1);
YYERROR;
}
memcpy(&$$, dcl_reg, sizeof(*dcl_reg));
$$.base.reg_nr += $3;
free($1);
}
| STRING LPAREN exp COMMA exp RPAREN
{
struct declared_register *dcl_reg = find_register($1);
if (dcl_reg == NULL) {
fprintf(stderr, "can't find register %s\n", $1);
YYERROR;
}
memcpy(&$$, dcl_reg, sizeof(*dcl_reg));
$$.base.reg_nr += $3;
$$.base.subreg_nr += $5;
if(advanced_flag) {
$$.base.reg_nr += $$.base.subreg_nr / (32 / get_type_size(dcl_reg->type));
$$.base.subreg_nr = $$.base.subreg_nr % (32 / get_type_size(dcl_reg->type));
} else {
$$.base.reg_nr += $$.base.subreg_nr / 32;
$$.base.subreg_nr = $$.base.subreg_nr % 32;
}
free($1);
}
;
/* Returns a partially complete destination register consisting of the
* direct or indirect register addressing fields, but not stride or writemask.
*/
dstreg: directgenreg
{
memset (&$$, '\0', sizeof ($$));
$$.address_mode = BRW_ADDRESS_DIRECT;
$$.reg_file = $1.reg_file;
$$.reg_nr = $1.reg_nr;
$$.subreg_nr = $1.subreg_nr;
}
| directmsgreg
{
memset (&$$, '\0', sizeof ($$));
$$.address_mode = BRW_ADDRESS_DIRECT;
$$.reg_file = $1.reg_file;
$$.reg_nr = $1.reg_nr;
$$.subreg_nr = $1.subreg_nr;
}
| indirectgenreg
{
memset (&$$, '\0', sizeof ($$));
$$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
$$.reg_file = $1.reg_file;
$$.address_subreg_nr = $1.address_subreg_nr;
$$.indirect_offset = $1.indirect_offset;
}
| indirectmsgreg
{
memset (&$$, '\0', sizeof ($$));
$$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
$$.reg_file = $1.reg_file;
$$.address_subreg_nr = $1.address_subreg_nr;
$$.indirect_offset = $1.indirect_offset;
}
;
/* 1.4.3: Source register */
srcaccimm: srcacc | imm32reg
;
srcacc: directsrcaccoperand | indirectsrcoperand
;
srcimm: directsrcoperand | indirectsrcoperand| imm32reg
;
imm32reg: imm32 srcimmtype
{
union {
int i;
float f;
} intfloat;
uint32_t d;
switch ($2) {
case BRW_REGISTER_TYPE_UD:
case BRW_REGISTER_TYPE_D:
case BRW_REGISTER_TYPE_V:
case BRW_REGISTER_TYPE_VF:
switch ($1.r) {
case imm32_d:
d = $1.u.d;
break;
default:
fprintf (stderr, "%d: non-int D/UD/V/VF representation: %d,type=%d\n", yylineno, $1.r, $2);
YYERROR;
}
break;
case BRW_REGISTER_TYPE_UW:
case BRW_REGISTER_TYPE_W:
switch ($1.r) {
case imm32_d:
d = $1.u.d;
break;
default:
fprintf (stderr, "non-int W/UW representation\n");
YYERROR;
}
d &= 0xffff;
d |= d << 16;
break;
case BRW_REGISTER_TYPE_F:
switch ($1.r) {
case imm32_f:
intfloat.f = $1.u.f;
break;
case imm32_d:
intfloat.f = (float) $1.u.d;
break;
default:
fprintf (stderr, "non-float F representation\n");
YYERROR;
}
d = intfloat.i;
break;
#if 0
case BRW_REGISTER_TYPE_VF:
fprintf (stderr, "Immediate type VF not supported yet\n");
YYERROR;
#endif
default:
fprintf(stderr, "unknown immediate type %d\n", $2);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_IMMEDIATE_VALUE;
$$.reg_type = $2;
$$.imm32 = d;
}
;
directsrcaccoperand: directsrcoperand
| accreg region regtype
{
set_direct_src_operand(&$$, &$1, $3.type);
$$.vert_stride = $2.vert_stride;
$$.width = $2.width;
$$.horiz_stride = $2.horiz_stride;
$$.default_region = $2.is_default;
}
;
/* Returns a source operand in the src0 fields of an instruction. */
srcarchoperandex: srcarchoperandex_typed region regtype
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = $1.reg_file;
$$.reg_type = $3.type;
$$.subreg_nr = $1.subreg_nr;
$$.reg_nr = $1.reg_nr;
$$.vert_stride = $2.vert_stride;
$$.width = $2.width;
$$.horiz_stride = $2.horiz_stride;
$$.default_region = $2.is_default;
$$.negate = 0;
$$.abs = 0;
}
| maskstackreg
{
set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UB);
}
| controlreg
{
set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD);
}
/* | statereg
{
set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD);
}*/
| notifyreg
{
set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD);
}
| ipreg
{
set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD);
}
| nullreg region regtype
{
if ($3.is_default) {
set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD);
} else {
set_direct_src_operand(&$$, &$1, $3.type);
}
$$.default_region = 1;
}
;
srcarchoperandex_typed: flagreg | addrreg | maskreg
;
sendleadreg: symbol_reg
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = $1.base.reg_file;
$$.reg_nr = $1.base.reg_nr;
$$.subreg_nr = $1.base.subreg_nr;
}
| directgenreg | directmsgreg
;
src: directsrcoperand | indirectsrcoperand
;
directsrcoperand: negate abs symbol_reg region regtype
{
memset (&$$, '\0', sizeof ($$));
$$.address_mode = BRW_ADDRESS_DIRECT;
$$.reg_file = $3.base.reg_file;
$$.reg_nr = $3.base.reg_nr;
$$.subreg_nr = $3.base.subreg_nr;
if ($5.is_default) {
$$.reg_type = $3.type;
} else {
$$.reg_type = $5.type;
}
if ($4.is_default) {
$$.vert_stride = $3.src_region.vert_stride;
$$.width = $3.src_region.width;
$$.horiz_stride = $3.src_region.horiz_stride;
} else {
$$.vert_stride = $4.vert_stride;
$$.width = $4.width;
$$.horiz_stride = $4.horiz_stride;
}
$$.negate = $1;
$$.abs = $2;
}
| statereg region regtype
{
if($2.is_default ==1 && $3.is_default == 1)
{
set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD);
}
else{
memset (&$$, '\0', sizeof ($$));
$$.address_mode = BRW_ADDRESS_DIRECT;
$$.reg_file = $1.reg_file;
$$.reg_nr = $1.reg_nr;
$$.subreg_nr = $1.subreg_nr;
$$.vert_stride = $2.vert_stride;
$$.width = $2.width;
$$.horiz_stride = $2.horiz_stride;
$$.reg_type = $3.type;
}
}
| negate abs directgenreg region regtype swizzle
{
memset (&$$, '\0', sizeof ($$));
$$.address_mode = BRW_ADDRESS_DIRECT;
$$.reg_file = $3.reg_file;
$$.reg_nr = $3.reg_nr;
$$.subreg_nr = $3.subreg_nr;
$$.reg_type = $5.type;
$$.vert_stride = $4.vert_stride;
$$.width = $4.width;
$$.horiz_stride = $4.horiz_stride;
$$.default_region = $4.is_default;
$$.negate = $1;
$$.abs = $2;
$$.swizzle_set = $6.swizzle_set;
$$.swizzle_x = $6.swizzle_x;
$$.swizzle_y = $6.swizzle_y;
$$.swizzle_z = $6.swizzle_z;
$$.swizzle_w = $6.swizzle_w;
}
| srcarchoperandex
;
indirectsrcoperand:
negate abs indirectgenreg indirectregion regtype swizzle
{
memset (&$$, '\0', sizeof ($$));
$$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
$$.reg_file = $3.reg_file;
$$.address_subreg_nr = $3.address_subreg_nr;
$$.indirect_offset = $3.indirect_offset;
$$.reg_type = $5.type;
$$.vert_stride = $4.vert_stride;
$$.width = $4.width;
$$.horiz_stride = $4.horiz_stride;
$$.negate = $1;
$$.abs = $2;
$$.swizzle_set = $6.swizzle_set;
$$.swizzle_x = $6.swizzle_x;
$$.swizzle_y = $6.swizzle_y;
$$.swizzle_z = $6.swizzle_z;
$$.swizzle_w = $6.swizzle_w;
}
;
/* 1.4.4: Address Registers */
/* Returns a partially-completed indirect_reg consisting of the address
* register fields for register-indirect access.
*/
addrparam: addrreg COMMA immaddroffset
{
if ($3 < -512 || $3 > 511) {
fprintf(stderr, "Address immediate offset %d out of"
"range %d\n", $3, yylineno);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.address_subreg_nr = $1.subreg_nr;
$$.indirect_offset = $3;
}
| addrreg
{
memset (&$$, '\0', sizeof ($$));
$$.address_subreg_nr = $1.subreg_nr;
$$.indirect_offset = 0;
}
;
/* The immaddroffset provides an immediate offset value added to the addresses
* from the address register in register-indirect register access.
*/
immaddroffset: /* empty */ { $$ = 0; }
| exp
;
/* 1.4.5: Register files and register numbers */
subregnum: DOT exp
{
$$ = $2;
}
| %prec SUBREGNUM
{
/* Default to subreg 0 if unspecified. */
$$ = 0;
}
;
directgenreg: GENREG subregnum
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_GENERAL_REGISTER_FILE;
$$.reg_nr = $1;
$$.subreg_nr = $2;
}
;
indirectgenreg: GENREGFILE LSQUARE addrparam RSQUARE
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_GENERAL_REGISTER_FILE;
$$.address_subreg_nr = $3.address_subreg_nr;
$$.indirect_offset = $3.indirect_offset;
}
;
directmsgreg: MSGREG subregnum
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_MESSAGE_REGISTER_FILE;
$$.reg_nr = $1;
$$.subreg_nr = $2;
}
;
indirectmsgreg: MSGREGFILE LSQUARE addrparam RSQUARE
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_MESSAGE_REGISTER_FILE;
$$.address_subreg_nr = $3.address_subreg_nr;
$$.indirect_offset = $3.indirect_offset;
}
;
addrreg: ADDRESSREG subregnum
{
if ($1 != 0) {
fprintf(stderr,
"address register number %d out of range", $1);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_ADDRESS | $1;
$$.subreg_nr = $2;
}
;
accreg: ACCREG subregnum
{
if ($1 > 1) {
fprintf(stderr,
"accumulator register number %d out of range", $1);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_ACCUMULATOR | $1;
$$.subreg_nr = $2;
}
;
flagreg: FLAGREG subregnum
{
if ((!IS_GENp(7) && $1) > 0 ||
(IS_GENp(7) && $1 > 1)) {
fprintf(stderr,
"flag register number %d out of range\n", $1);
YYERROR;
}
if ($2 > 1) {
fprintf(stderr,
"flag subregister number %d out of range\n", $1);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_FLAG | $1;
$$.subreg_nr = $2;
}
;
maskreg: MASKREG subregnum
{
if ($1 > 0) {
fprintf(stderr,
"mask register number %d out of range", $1);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_MASK;
$$.subreg_nr = $2;
}
| mask_subreg
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_MASK;
$$.subreg_nr = $1;
}
;
mask_subreg: AMASK | IMASK | LMASK | CMASK
;
maskstackreg: MASKSTACKREG subregnum
{
if ($1 > 0) {
fprintf(stderr,
"mask stack register number %d out of range", $1);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_MASK_STACK;
$$.subreg_nr = $2;
}
| maskstack_subreg
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_MASK_STACK;
$$.subreg_nr = $1;
}
;
maskstack_subreg: IMS | LMS
;
/*
maskstackdepthreg: MASKSTACKDEPTHREG subregnum
{
if ($1 > 0) {
fprintf(stderr,
"mask stack register number %d out of range", $1);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_MASK_STACK_DEPTH;
$$.subreg_nr = $2;
}
| maskstackdepth_subreg
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_MASK_STACK_DEPTH;
$$.subreg_nr = $1;
}
;
maskstackdepth_subreg: IMSD | LMSD
;
*/
notifyreg: NOTIFYREG regtype
{
int num_notifyreg = (IS_GENp(6)) ? 3 : 2;
if ($1 > num_notifyreg) {
fprintf(stderr,
"notification register number %d out of range",
$1);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
if (IS_GENp(6)) {
$$.reg_nr = BRW_ARF_NOTIFICATION_COUNT;
$$.subreg_nr = $1;
} else {
$$.reg_nr = BRW_ARF_NOTIFICATION_COUNT | $1;
$$.subreg_nr = 0;
}
}
/*
| NOTIFYREG regtype
{
if ($1 > 1) {
fprintf(stderr,
"notification register number %d out of range",
$1);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_NOTIFICATION_COUNT;
$$.subreg_nr = 0;
}
*/
;
statereg: STATEREG subregnum
{
if ($1 > 0) {
fprintf(stderr,
"state register number %d out of range", $1);
YYERROR;
}
if ($2 > 1) {
fprintf(stderr,
"state subregister number %d out of range", $1);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_STATE | $1;
$$.subreg_nr = $2;
}
;
controlreg: CONTROLREG subregnum
{
if ($1 > 0) {
fprintf(stderr,
"control register number %d out of range", $1);
YYERROR;
}
if ($2 > 2) {
fprintf(stderr,
"control subregister number %d out of range", $1);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_CONTROL | $1;
$$.subreg_nr = $2;
}
;
ipreg: IPREG regtype
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_IP;
$$.subreg_nr = 0;
}
;
nullreg: NULL_TOKEN
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
$$.reg_nr = BRW_ARF_NULL;
$$.subreg_nr = 0;
}
;
/* 1.4.6: Relative locations */
relativelocation:
simple_int
{
if (($1 > 32767) || ($1 < -32768)) {
fprintf(stderr,
"error: relative offset %d out of range \n",
$1);
YYERROR;
}
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_IMMEDIATE_VALUE;
$$.reg_type = BRW_REGISTER_TYPE_D;
$$.imm32 = $1 & 0x0000ffff;
}
| STRING
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_IMMEDIATE_VALUE;
$$.reg_type = BRW_REGISTER_TYPE_D;
$$.reloc_target = $1;
}
;
relativelocation2:
STRING
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_IMMEDIATE_VALUE;
$$.reg_type = BRW_REGISTER_TYPE_D;
$$.reloc_target = $1;
}
| exp
{
memset (&$$, '\0', sizeof ($$));
$$.reg_file = BRW_IMMEDIATE_VALUE;
$$.reg_type = BRW_REGISTER_TYPE_D;
$$.imm32 = $1;
}
| directgenreg region regtype
{
set_direct_src_operand(&$$, &$1, $3.type);
$$.vert_stride = $2.vert_stride;
$$.width = $2.width;
$$.horiz_stride = $2.horiz_stride;
$$.default_region = $2.is_default;
}
| symbol_reg_p
{
memset (&$$, '\0', sizeof ($$));
$$.address_mode = BRW_ADDRESS_DIRECT;
$$.reg_file = $1.base.reg_file;
$$.reg_nr = $1.base.reg_nr;
$$.subreg_nr = $1.base.subreg_nr;
$$.reg_type = $1.type;
$$.vert_stride = $1.src_region.vert_stride;
$$.width = $1.src_region.width;
$$.horiz_stride = $1.src_region.horiz_stride;
}
| indirectgenreg indirectregion regtype
{
memset (&$$, '\0', sizeof ($$));
$$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
$$.reg_file = $1.reg_file;
$$.address_subreg_nr = $1.address_subreg_nr;
$$.indirect_offset = $1.indirect_offset;
$$.reg_type = $3.type;
$$.vert_stride = $2.vert_stride;
$$.width = $2.width;
$$.horiz_stride = $2.horiz_stride;
}
;
/* 1.4.7: Regions */
dstregion: /* empty */
{
$$ = DEFAULT_DSTREGION;
}
|LANGLE exp RANGLE
{
/* Returns a value for a horiz_stride field of an
* instruction.
*/
if ($2 != 1 && $2 != 2 && $2 != 4) {
fprintf(stderr, "Invalid horiz size %d\n", $2);
}
$$ = ffs($2);
}
;
region: /* empty */
{
/* XXX is this default value correct?*/
memset (&$$, '\0', sizeof ($$));
$$.vert_stride = ffs(0);
$$.width = ffs(1) - 1;
$$.horiz_stride = ffs(0);
$$.is_default = 1;
}
|LANGLE exp RANGLE
{
/* XXX is this default value correct for accreg?*/
memset (&$$, '\0', sizeof ($$));
$$.vert_stride = ffs($2);
$$.width = ffs(1) - 1;
$$.horiz_stride = ffs(0);
}
|LANGLE exp COMMA exp COMMA exp RANGLE
{
memset (&$$, '\0', sizeof ($$));
$$.vert_stride = ffs($2);
$$.width = ffs($4) - 1;
$$.horiz_stride = ffs($6);
}
| LANGLE exp SEMICOLON exp COMMA exp RANGLE
{
memset (&$$, '\0', sizeof ($$));
$$.vert_stride = ffs($2);
$$.width = ffs($4) - 1;
$$.horiz_stride = ffs($6);
}
;
/* region_wh is used in specifying indirect operands where rather than having
* a vertical stride, you use subsequent address registers to get a new base
* offset for the next row.
*/
region_wh: LANGLE exp COMMA exp RANGLE
{
memset (&$$, '\0', sizeof ($$));
$$.vert_stride = BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL;
$$.width = ffs($2) - 1;
$$.horiz_stride = ffs($4);
}
;
indirectregion: region | region_wh
;
/* 1.4.8: Types */
/* regtype returns an integer register type suitable for inserting into an
* instruction.
*/
regtype: /* empty */
{ $$.type = program_defaults.register_type;$$.is_default = 1;}
| TYPE_F { $$.type = BRW_REGISTER_TYPE_F;$$.is_default = 0; }
| TYPE_UD { $$.type = BRW_REGISTER_TYPE_UD;$$.is_default = 0; }
| TYPE_D { $$.type = BRW_REGISTER_TYPE_D;$$.is_default = 0; }
| TYPE_UW { $$.type = BRW_REGISTER_TYPE_UW;$$.is_default = 0; }
| TYPE_W { $$.type = BRW_REGISTER_TYPE_W;$$.is_default = 0; }
| TYPE_UB { $$.type = BRW_REGISTER_TYPE_UB;$$.is_default = 0; }
| TYPE_B { $$.type = BRW_REGISTER_TYPE_B;$$.is_default = 0; }
;
srcimmtype: /* empty */
{
/* XXX change to default when pragma parse is done */
$$ = BRW_REGISTER_TYPE_D;
}
|TYPE_F { $$ = BRW_REGISTER_TYPE_F; }
| TYPE_UD { $$ = BRW_REGISTER_TYPE_UD; }
| TYPE_D { $$ = BRW_REGISTER_TYPE_D; }
| TYPE_UW { $$ = BRW_REGISTER_TYPE_UW; }
| TYPE_W { $$ = BRW_REGISTER_TYPE_W; }
| TYPE_V { $$ = BRW_REGISTER_TYPE_V; }
| TYPE_VF { $$ = BRW_REGISTER_TYPE_VF; }
;
/* 1.4.10: Swizzle control */
/* Returns the swizzle control for an align16 instruction's source operand
* in the src0 fields.
*/
swizzle: /* empty */
{
$$.swizzle_set = 0;
$$.swizzle_x = BRW_CHANNEL_X;
$$.swizzle_y = BRW_CHANNEL_Y;
$$.swizzle_z = BRW_CHANNEL_Z;
$$.swizzle_w = BRW_CHANNEL_W;
}
| DOT chansel
{
$$.swizzle_set = 1;
$$.swizzle_x = $2;
$$.swizzle_y = $2;
$$.swizzle_z = $2;
$$.swizzle_w = $2;
}
| DOT chansel chansel chansel chansel
{
$$.swizzle_set = 1;
$$.swizzle_x = $2;
$$.swizzle_y = $3;
$$.swizzle_z = $4;
$$.swizzle_w = $5;
}
;
chansel: X | Y | Z | W
;
/* 1.4.9: Write mask */
/* Returns a partially completed dst_operand, with just the writemask bits
* filled out.
*/
writemask: /* empty */
{
$$.writemask_set = 0;
$$.writemask = 0xf;
}
| DOT writemask_x writemask_y writemask_z writemask_w
{
$$.writemask_set = 1;
$$.writemask = $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; }
;
/* 1.4.11: Immediate values */
imm32: exp { $$.r = imm32_d; $$.u.d = $1; }
| NUMBER { $$.r = imm32_f; $$.u.f = $1; }
;
/* 1.4.12: Predication and modifiers */
predicate: /* empty */
{
$$.header.predicate_control = BRW_PREDICATE_NONE;
$$.bits2.da1.flag_reg_nr = 0;
$$.bits2.da1.flag_subreg_nr = 0;
$$.header.predicate_inverse = 0;
}
| LPAREN predstate flagreg predctrl RPAREN
{
$$.header.predicate_control = $4;
/* XXX: Should deal with erroring when the user tries to
* set a predicate for one flag register and conditional
* modification on the other flag register.
*/
$$.bits2.da1.flag_reg_nr = ($3.reg_nr & 0xF);
$$.bits2.da1.flag_subreg_nr = $3.subreg_nr;
$$.header.predicate_inverse = $2;
}
;
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 { $$ = BRW_PREDICATE_ALIGN1_ANYV; }
| ALLV { $$ = BRW_PREDICATE_ALIGN1_ALLV; }
| ANY2H { $$ = BRW_PREDICATE_ALIGN1_ANY2H; }
| ALL2H { $$ = BRW_PREDICATE_ALIGN1_ALL2H; }
| ANY4H { $$ = BRW_PREDICATE_ALIGN1_ANY4H; }
| ALL4H { $$ = BRW_PREDICATE_ALIGN1_ALL4H; }
| ANY8H { $$ = BRW_PREDICATE_ALIGN1_ANY8H; }
| ALL8H { $$ = BRW_PREDICATE_ALIGN1_ALL8H; }
| ANY16H { $$ = BRW_PREDICATE_ALIGN1_ANY16H; }
| ALL16H { $$ = BRW_PREDICATE_ALIGN1_ALL16H; }
;
negate: /* empty */ { $$ = 0; }
| MINUS { $$ = 1; }
;
abs: /* empty */ { $$ = 0; }
| ABS { $$ = 1; }
;
execsize: /* empty */ %prec EMPTEXECSIZE
{
$$ = ffs(program_defaults.execute_size) - 1;
}
|LPAREN exp RPAREN
{
/* Returns a value for the execution_size field of an
* instruction.
*/
if ($2 != 1 && $2 != 2 && $2 != 4 && $2 != 8 && $2 != 16 &&
$2 != 32) {
fprintf(stderr, "Invalid execution size %d\n", $2);
YYERROR;
}
$$ = ffs($2) - 1;
}
;
saturate: /* empty */ { $$ = BRW_INSTRUCTION_NORMAL; }
| SATURATE { $$ = BRW_INSTRUCTION_SATURATE; }
;
conditionalmodifier: condition
{
$$.cond = $1;
$$.flag_reg_nr = 0;
$$.flag_subreg_nr = -1;
}
| condition DOT flagreg
{
$$.cond = $1;
$$.flag_reg_nr = ($3.reg_nr & 0xF);
$$.flag_subreg_nr = $3.subreg_nr;
}
condition: /* empty */ { $$ = BRW_CONDITIONAL_NONE; }
| ZERO
| EQUAL
| NOT_ZERO
| NOT_EQUAL
| GREATER
| GREATER_EQUAL
| LESS
| LESS_EQUAL
| ROUND_INCREMENT
| OVERFLOW
| UNORDERED
;
/* 1.4.13: Instruction options */
instoptions: /* empty */
{ memset(&$$, 0, sizeof($$)); }
| LCURLY instoption_list RCURLY
{ $$ = $2; }
;
instoption_list:instoption_list COMMA instoption
{
$$ = $1;
switch ($3) {
case ALIGN1:
$$.header.access_mode = BRW_ALIGN_1;
break;
case ALIGN16:
$$.header.access_mode = BRW_ALIGN_16;
break;
case SECHALF:
$$.header.compression_control |= BRW_COMPRESSION_2NDHALF;
break;
case COMPR:
if (!IS_GENp(6)) {
$$.header.compression_control |=
BRW_COMPRESSION_COMPRESSED;
}
break;
case SWITCH:
$$.header.thread_control |= BRW_THREAD_SWITCH;
break;
case ATOMIC:
$$.header.thread_control |= BRW_THREAD_ATOMIC;
break;
case NODDCHK:
$$.header.dependency_control |= BRW_DEPENDENCY_NOTCHECKED;
break;
case NODDCLR:
$$.header.dependency_control |= BRW_DEPENDENCY_NOTCLEARED;
break;
case MASK_DISABLE:
$$.header.mask_control = BRW_MASK_DISABLE;
break;
case BREAKPOINT:
$$.header.debug_control = BRW_DEBUG_BREAKPOINT;
break;
case ACCWRCTRL:
$$.header.acc_wr_control = BRW_ACCWRCTRL_ACCWRCTRL;
}
}
| instoption_list instoption
{
$$ = $1;
switch ($2) {
case ALIGN1:
$$.header.access_mode = BRW_ALIGN_1;
break;
case ALIGN16:
$$.header.access_mode = BRW_ALIGN_16;
break;
case SECHALF:
$$.header.compression_control |= BRW_COMPRESSION_2NDHALF;
break;
case COMPR:
if (!IS_GENp(6)) {
$$.header.compression_control |=
BRW_COMPRESSION_COMPRESSED;
}
break;
case SWITCH:
$$.header.thread_control |= BRW_THREAD_SWITCH;
break;
case ATOMIC:
$$.header.thread_control |= BRW_THREAD_ATOMIC;
break;
case NODDCHK:
$$.header.dependency_control |= BRW_DEPENDENCY_NOTCHECKED;
break;
case NODDCLR:
$$.header.dependency_control |= BRW_DEPENDENCY_NOTCLEARED;
break;
case MASK_DISABLE:
$$.header.mask_control = BRW_MASK_DISABLE;
break;
case BREAKPOINT:
$$.header.debug_control = BRW_DEBUG_BREAKPOINT;
break;
case EOT:
/* XXX: EOT shouldn't be an instoption, I don't think */
$$.bits3.generic.end_of_thread = 1;
break;
}
}
| /* empty, header defaults to zeroes. */
{
memset(&$$, 0, sizeof($$));
}
;
instoption: ALIGN1 { $$ = ALIGN1; }
| ALIGN16 { $$ = ALIGN16; }
| SECHALF { $$ = SECHALF; }
| COMPR { $$ = COMPR; }
| SWITCH { $$ = SWITCH; }
| ATOMIC { $$ = ATOMIC; }
| NODDCHK { $$ = NODDCHK; }
| NODDCLR { $$ = NODDCLR; }
| MASK_DISABLE { $$ = MASK_DISABLE; }
| BREAKPOINT { $$ = BREAKPOINT; }
| ACCWRCTRL { $$ = ACCWRCTRL; }
| EOT { $$ = EOT; }
;
%%
extern int yylineno;
extern char *input_filename;
int errors;
void yyerror (char *msg)
{
fprintf(stderr, "%s: %d: %s at \"%s\"\n",
input_filename, yylineno, msg, lex_text());
++errors;
}
static int get_type_size(GLuint type)
{
int size = 1;
switch (type) {
case BRW_REGISTER_TYPE_F:
case BRW_REGISTER_TYPE_UD:
case BRW_REGISTER_TYPE_D:
size = 4;
break;
case BRW_REGISTER_TYPE_UW:
case BRW_REGISTER_TYPE_W:
size = 2;
break;
case BRW_REGISTER_TYPE_UB:
case BRW_REGISTER_TYPE_B:
size = 1;
break;
default:
assert(0);
size = 1;
break;
}
return size;
}
static int get_subreg_address(GLuint regfile, GLuint type, GLuint subreg, GLuint address_mode)
{
int unit_size = 1;
if (address_mode == BRW_ADDRESS_DIRECT) {
if (advanced_flag == 1) {
if ((regfile == BRW_GENERAL_REGISTER_FILE ||
regfile == BRW_MESSAGE_REGISTER_FILE ||
regfile == BRW_ARCHITECTURE_REGISTER_FILE)) {
unit_size = get_type_size(type);
}
}
} else {
unit_size = 1;
}
return subreg * unit_size;
}
/* only used in indirect address mode.
* input: sub-register number of an address register
* output: the value of AddrSubRegNum in the instruction binary code
*
* input output(advanced_flag==0) output(advanced_flag==1)
* a0.0 0 0
* a0.1 invalid input 1
* a0.2 1 2
* a0.3 invalid input 3
* a0.4 2 4
* a0.5 invalid input 5
* a0.6 3 6
* a0.7 invalid input 7
* a0.8 4 invalid input
* a0.10 5 invalid input
* a0.12 6 invalid input
* a0.14 7 invalid input
*/
static int get_indirect_subreg_address(GLuint subreg)
{
return advanced_flag == 0 ? subreg / 2 : subreg;
}
static void reset_instruction_src_region(struct brw_instruction *instr,
struct src_operand *src)
{
if (!src->default_region)
return;
if (src->reg_file == BRW_ARCHITECTURE_REGISTER_FILE &&
((src->reg_nr & 0xF0) == BRW_ARF_ADDRESS)) {
src->vert_stride = ffs(0);
src->width = ffs(1) - 1;
src->horiz_stride = ffs(0);
} else if (src->reg_file == BRW_ARCHITECTURE_REGISTER_FILE &&
((src->reg_nr & 0xF0) == BRW_ARF_ACCUMULATOR)) {
int horiz_stride = 1, width, vert_stride;
if (instr->header.compression_control == BRW_COMPRESSION_COMPRESSED) {
width = 16;
} else {
width = 8;
}
if (width > (1 << instr->header.execution_size))
width = (1 << instr->header.execution_size);
vert_stride = horiz_stride * width;
src->vert_stride = ffs(vert_stride);
src->width = ffs(width) - 1;
src->horiz_stride = ffs(horiz_stride);
} else if ((src->reg_file == BRW_ARCHITECTURE_REGISTER_FILE) &&
(src->reg_nr == BRW_ARF_NULL) &&
(instr->header.opcode == BRW_OPCODE_SEND)) {
src->vert_stride = ffs(8);
src->width = ffs(8) - 1;
src->horiz_stride = ffs(1);
} else {
int horiz_stride = 1, width, vert_stride;
if (instr->header.execution_size == 0) { /* scalar */
horiz_stride = 0;
width = 1;
vert_stride = 0;
} else {
if ((instr->header.opcode == BRW_OPCODE_MUL) ||
(instr->header.opcode == BRW_OPCODE_MAC) ||
(instr->header.opcode == BRW_OPCODE_CMP) ||
(instr->header.opcode == BRW_OPCODE_ASR) ||
(instr->header.opcode == BRW_OPCODE_ADD) ||
(instr->header.opcode == BRW_OPCODE_SHL)) {
horiz_stride = 0;
width = 1;
vert_stride = 0;
} else {
width = (1 << instr->header.execution_size) / horiz_stride;
vert_stride = horiz_stride * width;
if (get_type_size(src->reg_type) * (width + src->subreg_nr) > 32) {
horiz_stride = 0;
width = 1;
vert_stride = 0;
}
}
}
src->vert_stride = ffs(vert_stride);
src->width = ffs(width) - 1;
src->horiz_stride = ffs(horiz_stride);
}
}
/**
* Fills in the destination register information in instr from the bits in dst.
*/
int set_instruction_dest(struct brw_instruction *instr,
struct dst_operand *dest)
{
if (dest->horiz_stride == DEFAULT_DSTREGION)
dest->horiz_stride = ffs(1);
if (dest->address_mode == BRW_ADDRESS_DIRECT &&
instr->header.access_mode == BRW_ALIGN_1) {
instr->bits1.da1.dest_reg_file = dest->reg_file;
instr->bits1.da1.dest_reg_type = dest->reg_type;
instr->bits1.da1.dest_subreg_nr = get_subreg_address(dest->reg_file, dest->reg_type, dest->subreg_nr, dest->address_mode);
instr->bits1.da1.dest_reg_nr = dest->reg_nr;
instr->bits1.da1.dest_horiz_stride = dest->horiz_stride;
instr->bits1.da1.dest_address_mode = dest->address_mode;
if (dest->writemask_set) {
fprintf(stderr, "error: write mask set in align1 "
"instruction\n");
return 1;
}
} else if (dest->address_mode == BRW_ADDRESS_DIRECT) {
instr->bits1.da16.dest_reg_file = dest->reg_file;
instr->bits1.da16.dest_reg_type = dest->reg_type;
instr->bits1.da16.dest_subreg_nr = get_subreg_address(dest->reg_file, dest->reg_type, dest->subreg_nr, dest->address_mode);
instr->bits1.da16.dest_reg_nr = dest->reg_nr;
instr->bits1.da16.dest_address_mode = dest->address_mode;
instr->bits1.da16.dest_horiz_stride = ffs(1);
instr->bits1.da16.dest_writemask = dest->writemask;
} else if (instr->header.access_mode == BRW_ALIGN_1) {
instr->bits1.ia1.dest_reg_file = dest->reg_file;
instr->bits1.ia1.dest_reg_type = dest->reg_type;
instr->bits1.ia1.dest_subreg_nr = get_indirect_subreg_address(dest->address_subreg_nr);
instr->bits1.ia1.dest_horiz_stride = dest->horiz_stride;
instr->bits1.ia1.dest_indirect_offset = dest->indirect_offset;
instr->bits1.ia1.dest_address_mode = dest->address_mode;
if (dest->writemask_set) {
fprintf(stderr, "error: write mask set in align1 "
"instruction\n");
return 1;
}
} else {
instr->bits1.ia16.dest_reg_file = dest->reg_file;
instr->bits1.ia16.dest_reg_type = dest->reg_type;
instr->bits1.ia16.dest_subreg_nr = get_indirect_subreg_address(dest->address_subreg_nr);
instr->bits1.ia16.dest_writemask = dest->writemask;
instr->bits1.ia16.dest_horiz_stride = ffs(1);
instr->bits1.ia16.dest_indirect_offset = (dest->indirect_offset >> 4); /* half register aligned */
instr->bits1.ia16.dest_address_mode = dest->address_mode;
}
return 0;
}
/* Sets the first source operand for the instruction. Returns 0 on success. */
int set_instruction_src0(struct brw_instruction *instr,
struct src_operand *src)
{
if (advanced_flag) {
reset_instruction_src_region(instr, src);
}
instr->bits1.da1.src0_reg_file = src->reg_file;
instr->bits1.da1.src0_reg_type = src->reg_type;
if (src->reg_file == BRW_IMMEDIATE_VALUE) {
instr->bits3.ud = src->imm32;
} else if (src->address_mode == BRW_ADDRESS_DIRECT) {
if (instr->header.access_mode == BRW_ALIGN_1) {
instr->bits2.da1.src0_subreg_nr = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode);
instr->bits2.da1.src0_reg_nr = src->reg_nr;
instr->bits2.da1.src0_vert_stride = src->vert_stride;
instr->bits2.da1.src0_width = src->width;
instr->bits2.da1.src0_horiz_stride = src->horiz_stride;
instr->bits2.da1.src0_negate = src->negate;
instr->bits2.da1.src0_abs = src->abs;
instr->bits2.da1.src0_address_mode = src->address_mode;
if (src->swizzle_set) {
fprintf(stderr, "error: swizzle bits set in align1 "
"instruction\n");
return 1;
}
} else {
instr->bits2.da16.src0_subreg_nr = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode);
instr->bits2.da16.src0_reg_nr = src->reg_nr;
instr->bits2.da16.src0_vert_stride = src->vert_stride;
instr->bits2.da16.src0_negate = src->negate;
instr->bits2.da16.src0_abs = src->abs;
instr->bits2.da16.src0_swz_x = src->swizzle_x;
instr->bits2.da16.src0_swz_y = src->swizzle_y;
instr->bits2.da16.src0_swz_z = src->swizzle_z;
instr->bits2.da16.src0_swz_w = src->swizzle_w;
instr->bits2.da16.src0_address_mode = src->address_mode;
}
} else {
if (instr->header.access_mode == BRW_ALIGN_1) {
instr->bits2.ia1.src0_indirect_offset = src->indirect_offset;
instr->bits2.ia1.src0_subreg_nr = get_indirect_subreg_address(src->address_subreg_nr);
instr->bits2.ia1.src0_abs = src->abs;
instr->bits2.ia1.src0_negate = src->negate;
instr->bits2.ia1.src0_address_mode = src->address_mode;
instr->bits2.ia1.src0_horiz_stride = src->horiz_stride;
instr->bits2.ia1.src0_width = src->width;
instr->bits2.ia1.src0_vert_stride = src->vert_stride;
if (src->swizzle_set) {
fprintf(stderr, "error: swizzle bits set in align1 "
"instruction\n");
return 1;
}
} else {
instr->bits2.ia16.src0_swz_x = src->swizzle_x;
instr->bits2.ia16.src0_swz_y = src->swizzle_y;
instr->bits2.ia16.src0_indirect_offset = (src->indirect_offset >> 4); /* half register aligned */
instr->bits2.ia16.src0_subreg_nr = get_indirect_subreg_address(src->address_subreg_nr);
instr->bits2.ia16.src0_abs = src->abs;
instr->bits2.ia16.src0_negate = src->negate;
instr->bits2.ia16.src0_address_mode = src->address_mode;
instr->bits2.ia16.src0_swz_z = src->swizzle_z;
instr->bits2.ia16.src0_swz_w = src->swizzle_w;
instr->bits2.ia16.src0_vert_stride = src->vert_stride;
}
}
return 0;
}
/* Sets the second source operand for the instruction. Returns 0 on success.
*/
int set_instruction_src1(struct brw_instruction *instr,
struct src_operand *src)
{
if (advanced_flag) {
reset_instruction_src_region(instr, src);
}
instr->bits1.da1.src1_reg_file = src->reg_file;
instr->bits1.da1.src1_reg_type = src->reg_type;
if (src->reg_file == BRW_IMMEDIATE_VALUE) {
instr->bits3.ud = src->imm32;
} else if (src->address_mode == BRW_ADDRESS_DIRECT) {
if (instr->header.access_mode == BRW_ALIGN_1) {
instr->bits3.da1.src1_subreg_nr = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode);
instr->bits3.da1.src1_reg_nr = src->reg_nr;
instr->bits3.da1.src1_vert_stride = src->vert_stride;
instr->bits3.da1.src1_width = src->width;
instr->bits3.da1.src1_horiz_stride = src->horiz_stride;
instr->bits3.da1.src1_negate = src->negate;
instr->bits3.da1.src1_abs = src->abs;
instr->bits3.da1.src1_address_mode = src->address_mode;
/* XXX why?
if (src->address_mode != BRW_ADDRESS_DIRECT) {
fprintf(stderr, "error: swizzle bits set in align1 "
"instruction\n");
return 1;
}
*/
if (src->swizzle_set) {
fprintf(stderr, "error: swizzle bits set in align1 "
"instruction\n");
return 1;
}
} else {
instr->bits3.da16.src1_subreg_nr = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode);
instr->bits3.da16.src1_reg_nr = src->reg_nr;
instr->bits3.da16.src1_vert_stride = src->vert_stride;
instr->bits3.da16.src1_negate = src->negate;
instr->bits3.da16.src1_abs = src->abs;
instr->bits3.da16.src1_swz_x = src->swizzle_x;
instr->bits3.da16.src1_swz_y = src->swizzle_y;
instr->bits3.da16.src1_swz_z = src->swizzle_z;
instr->bits3.da16.src1_swz_w = src->swizzle_w;
instr->bits3.da16.src1_address_mode = src->address_mode;
if (src->address_mode != BRW_ADDRESS_DIRECT) {
fprintf(stderr, "error: swizzle bits set in align1 "
"instruction\n");
return 1;
}
}
} else {
if (instr->header.access_mode == BRW_ALIGN_1) {
instr->bits3.ia1.src1_indirect_offset = src->indirect_offset;
instr->bits3.ia1.src1_subreg_nr = get_indirect_subreg_address(src->address_subreg_nr);
instr->bits3.ia1.src1_abs = src->abs;
instr->bits3.ia1.src1_negate = src->negate;
instr->bits3.ia1.src1_address_mode = src->address_mode;
instr->bits3.ia1.src1_horiz_stride = src->horiz_stride;
instr->bits3.ia1.src1_width = src->width;
instr->bits3.ia1.src1_vert_stride = src->vert_stride;
if (src->swizzle_set) {
fprintf(stderr, "error: swizzle bits set in align1 "
"instruction\n");
return 1;
}
} else {
instr->bits3.ia16.src1_swz_x = src->swizzle_x;
instr->bits3.ia16.src1_swz_y = src->swizzle_y;
instr->bits3.ia16.src1_indirect_offset = (src->indirect_offset >> 4); /* half register aligned */
instr->bits3.ia16.src1_subreg_nr = get_indirect_subreg_address(src->address_subreg_nr);
instr->bits3.ia16.src1_abs = src->abs;
instr->bits3.ia16.src1_negate = src->negate;
instr->bits3.ia16.src1_address_mode = src->address_mode;
instr->bits3.ia16.src1_swz_z = src->swizzle_z;
instr->bits3.ia16.src1_swz_w = src->swizzle_w;
instr->bits3.ia16.src1_vert_stride = src->vert_stride;
}
}
return 0;
}
/* convert 2-src reg type to 3-src reg type
*
* 2-src reg type:
* 000=UD 001=D 010=UW 011=W 100=UB 101=B 110=DF 111=F
*
* 3-src reg type:
* 00=F 01=D 10=UD 11=DF
*/
static int reg_type_2_to_3(int reg_type)
{
int r = 0;
switch(reg_type) {
case 7: r = 0; break;
case 1: r = 1; break;
case 0: r = 2; break;
// TODO: supporting DF
}
return r;
}
int set_instruction_dest_three_src(struct brw_instruction *instr,
struct dst_operand *dest)
{
instr->bits1.da3src.dest_reg_file = dest->reg_file;
instr->bits1.da3src.dest_reg_nr = dest->reg_nr;
instr->bits1.da3src.dest_subreg_nr = get_subreg_address(dest->reg_file, dest->reg_type, dest->subreg_nr, dest->address_mode) / 4; // in DWORD
instr->bits1.da3src.dest_writemask = dest->writemask;
instr->bits1.da3src.dest_reg_type = reg_type_2_to_3(dest->reg_type);
return 0;
}
int set_instruction_src0_three_src(struct brw_instruction *instr,
struct src_operand *src)
{
if (advanced_flag) {
reset_instruction_src_region(instr, src);
}
// TODO: supporting src0 swizzle, src0 modifier, src0 rep_ctrl
instr->bits1.da3src.src_reg_type = reg_type_2_to_3(src->reg_type);
instr->bits2.da3src.src0_subreg_nr = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode) / 4; // in DWORD
instr->bits2.da3src.src0_reg_nr = src->reg_nr;
return 0;
}
int set_instruction_src1_three_src(struct brw_instruction *instr,
struct src_operand *src)
{
if (advanced_flag) {
reset_instruction_src_region(instr, src);
}
// TODO: supporting src1 swizzle, src1 modifier, src1 rep_ctrl
int v = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode) / 4; // in DWORD
instr->bits2.da3src.src1_subreg_nr_low = v % 4; // lower 2 bits
instr->bits3.da3src.src1_subreg_nr_high = v / 4; // highest bit
instr->bits3.da3src.src1_reg_nr = src->reg_nr;
return 0;
}
int set_instruction_src2_three_src(struct brw_instruction *instr,
struct src_operand *src)
{
if (advanced_flag) {
reset_instruction_src_region(instr, src);
}
// TODO: supporting src2 swizzle, src2 modifier, src2 rep_ctrl
instr->bits3.da3src.src2_subreg_nr = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode) / 4; // in DWORD
instr->bits3.da3src.src2_reg_nr = src->reg_nr;
return 0;
}
void set_instruction_options(struct brw_instruction *instr,
struct brw_instruction *options)
{
/* XXX: more instr options */
instr->header.access_mode = options->header.access_mode;
instr->header.mask_control = options->header.mask_control;
instr->header.dependency_control = options->header.dependency_control;
instr->header.compression_control =
options->header.compression_control;
}
void set_instruction_predicate(struct brw_instruction *instr,
struct brw_instruction *predicate)
{
instr->header.predicate_control = predicate->header.predicate_control;
instr->header.predicate_inverse = predicate->header.predicate_inverse;
instr->bits2.da1.flag_reg_nr = predicate->bits2.da1.flag_reg_nr;
instr->bits2.da1.flag_subreg_nr = predicate->bits2.da1.flag_subreg_nr;
}
void set_direct_dst_operand(struct dst_operand *dst, struct direct_reg *reg,
int type)
{
memset(dst, 0, sizeof(*dst));
dst->address_mode = BRW_ADDRESS_DIRECT;
dst->reg_file = reg->reg_file;
dst->reg_nr = reg->reg_nr;
dst->subreg_nr = reg->subreg_nr;
dst->reg_type = type;
dst->horiz_stride = 1;
dst->writemask_set = 0;
dst->writemask = 0xf;
}
void set_direct_src_operand(struct src_operand *src, struct direct_reg *reg,
int type)
{
memset(src, 0, sizeof(*src));
src->address_mode = BRW_ADDRESS_DIRECT;
src->reg_file = reg->reg_file;
src->reg_type = type;
src->subreg_nr = reg->subreg_nr;
src->reg_nr = reg->reg_nr;
src->vert_stride = 0;
src->width = 0;
src->horiz_stride = 0;
src->negate = 0;
src->abs = 0;
src->swizzle_set = 0;
src->swizzle_x = BRW_CHANNEL_X;
src->swizzle_y = BRW_CHANNEL_Y;
src->swizzle_z = BRW_CHANNEL_Z;
src->swizzle_w = BRW_CHANNEL_W;
}