gram.y 103 KB
Newer Older
Eric Anholt's avatar
Eric Anholt committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
%{
/*
 * 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>
Eric Anholt's avatar
Eric Anholt committed
30
#include <string.h>
31
#include <stdlib.h>
32
#include <stdbool.h>
33
#include <stdarg.h>
34
#include <assert.h>
Eric Anholt's avatar
Eric Anholt committed
35
#include "gen4asm.h"
36
#include "brw_eu.h"
37
#include "gen8_instruction.h"
Eric Anholt's avatar
Eric Anholt committed
38

39 40 41
#define DEFAULT_EXECSIZE (ffs(program_defaults.execute_size) - 1)
#define DEFAULT_DSTREGION -1

42 43
#define SWIZZLE(reg) (reg.dw1.bits.swizzle)

44
#define GEN(i)	(&(i)->insn.gen)
45
#define GEN8(i)	(&(i)->insn.gen8)
46

47 48 49 50 51 52 53 54 55
#define YYLTYPE YYLTYPE
typedef struct YYLTYPE
{
 int first_line;
 int first_column;
 int last_line;
 int last_column;
} YYLTYPE;

56
extern int need_export;
57 58
static struct src_operand src_null_reg =
{
59 60 61
    .reg.file = BRW_ARCHITECTURE_REGISTER_FILE,
    .reg.nr = BRW_ARF_NULL,
    .reg.type = BRW_REGISTER_TYPE_UD,
62
};
63
static struct brw_reg dst_null_reg =
64
{
65 66
    .file = BRW_ARCHITECTURE_REGISTER_FILE,
    .nr = BRW_ARF_NULL,
67
};
68
static struct brw_reg ip_dst =
69
{
70 71 72
    .file = BRW_ARCHITECTURE_REGISTER_FILE,
    .nr = BRW_ARF_IP,
    .type = BRW_REGISTER_TYPE_UD,
73
    .address_mode = BRW_ADDRESS_DIRECT,
74 75
    .hstride = 1,
    .dw1.bits.writemask = BRW_WRITEMASK_XYZW,
76 77 78
};
static struct src_operand ip_src =
{
79 80 81 82 83
    .reg.file = BRW_ARCHITECTURE_REGISTER_FILE,
    .reg.nr = BRW_ARF_IP,
    .reg.type = BRW_REGISTER_TYPE_UD,
    .reg.address_mode = BRW_ADDRESS_DIRECT,
    .reg.dw1.bits.swizzle = BRW_SWIZZLE_NOOP,
84
};
Haihao Xiang's avatar
Haihao Xiang committed
85

86
static int get_type_size(unsigned type);
87 88
static void set_instruction_opcode(struct brw_program_instruction *instr,
				   unsigned opcode);
89
static int set_instruction_dest(struct brw_program_instruction *instr,
90
				struct brw_reg *dest);
91
static int set_instruction_src0(struct brw_program_instruction *instr,
92 93
				struct src_operand *src,
				YYLTYPE *location);
94
static int set_instruction_src1(struct brw_program_instruction *instr,
95 96
				struct src_operand *src,
				YYLTYPE *location);
97
static int set_instruction_dest_three_src(struct brw_program_instruction *instr,
98
					  struct brw_reg *dest);
99
static int set_instruction_src0_three_src(struct brw_program_instruction *instr,
100
					  struct src_operand *src);
101
static int set_instruction_src1_three_src(struct brw_program_instruction *instr,
102
					  struct src_operand *src);
103
static int set_instruction_src2_three_src(struct brw_program_instruction *instr,
104
					  struct src_operand *src);
105 106
static void set_instruction_saturate(struct brw_program_instruction *instr,
				     int saturate);
107
static void set_instruction_options(struct brw_program_instruction *instr,
108
				    struct options options);
109
static void set_instruction_predicate(struct brw_program_instruction *instr,
110
				      struct predicate *p);
111 112 113 114
static void set_instruction_pred_cond(struct brw_program_instruction *instr,
				      struct predicate *p,
				      struct condition *c,
				      YYLTYPE *location);
115 116 117 118
static void set_direct_dst_operand(struct brw_reg *dst, struct brw_reg *reg,
				   int type);
static void set_direct_src_operand(struct src_operand *src, struct brw_reg *reg,
				   int type);
119

120 121 122
void set_branch_two_offsets(struct brw_program_instruction *insn, int jip_offset, int uip_offset);
void set_branch_one_offset(struct brw_program_instruction *insn, int jip_offset);

123 124 125 126 127 128 129 130 131 132 133 134
enum message_level {
    WARN,
    ERROR,
};

static void message(enum message_level level, YYLTYPE *location,
		    const char *fmt, ...)
{
    static const char *level_str[] = { "warning", "error" };
    va_list args;

    if (location)
135
	fprintf(stderr, "%s:%d:%d: %s: ", input_filename, location->first_line,
136 137
		location->first_column, level_str[level]);
    else
138
	fprintf(stderr, "%s:%s: ", input_filename, level_str[level]);
139 140 141 142 143 144

    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
}

145 146 147
#define warn(flag, l, fmt, ...)					\
    do {							\
	if (warning_flags & WARN_ ## flag)			\
148
	    message(WARN, l, fmt, ## __VA_ARGS__);	\
149 150
    } while(0)

151 152 153 154
#define error(l, fmt, ...)			\
    do {					\
	message(ERROR, l, fmt, ## __VA_ARGS__);	\
    } while(0)
155

156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
/* like strcmp, but handles NULL pointers */
static bool strcmp0(const char *s1, const char* s2)
{
    if (!s1)
	return -(s1 != s2);
    if (!s2)
	return s1 != s2;
    return strcmp (s1, s2);
}

static bool region_equal(struct region *r1, struct region *r2)
{
    return memcmp(r1, r2, sizeof(struct region)) == 0;
}

static bool reg_equal(struct brw_reg *r1, struct brw_reg *r2)
{
    return memcmp(r1, r2, sizeof(struct brw_reg)) == 0;
}

static bool declared_register_equal(struct declared_register *r1,
				     struct declared_register *r2)
{
    if (strcmp0(r1->name, r2->name) != 0)
	return false;

    if (!reg_equal(&r1->reg, &r2->reg))
	return false;

    if (!region_equal(&r1->src_region, &r2->src_region))
	return false;

    if (r1->element_size != r2->element_size ||
189
        r1->dst_region != r2->dst_region)
190 191 192 193 194
	return false;

    return true;
}

195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
static void brw_program_init(struct brw_program *p)
{
   memset(p, 0, sizeof(struct brw_program));
}

static void brw_program_append_entry(struct brw_program *p,
				     struct brw_program_instruction *entry)
{
    entry->next = NULL;
    if (p->last)
	p->last->next = entry;
    else
	p->first = entry;
    p->last = entry;
}

211 212 213
static void
brw_program_add_instruction(struct brw_program *p,
			    struct brw_program_instruction *instruction)
214 215 216 217
{
    struct brw_program_instruction *list_entry;

    list_entry = calloc(sizeof(struct brw_program_instruction), 1);
218
    list_entry->type = GEN4ASM_INSTRUCTION_GEN;
219
    list_entry->insn.gen = instruction->insn.gen;
220 221 222
    brw_program_append_entry(p, list_entry);
}

223 224 225
static void
brw_program_add_relocatable(struct brw_program *p,
			    struct brw_program_instruction *instruction)
226 227 228 229 230
{
    struct brw_program_instruction *list_entry;

    list_entry = calloc(sizeof(struct brw_program_instruction), 1);
    list_entry->type = GEN4ASM_INSTRUCTION_GEN_RELOCATABLE;
231 232
    list_entry->insn.gen = instruction->insn.gen;
    list_entry->reloc = instruction->reloc;
233 234 235
    brw_program_append_entry(p, list_entry);
}

236 237 238 239 240
static void brw_program_add_label(struct brw_program *p, const char *label)
{
    struct brw_program_instruction *list_entry;

    list_entry = calloc(sizeof(struct brw_program_instruction), 1);
241
    list_entry->type = GEN4ASM_INSTRUCTION_LABEL;
242
    list_entry->insn.label.name = strdup(label);
243 244 245
    brw_program_append_entry(p, list_entry);
}

246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
static int resolve_dst_region(struct declared_register *reference, int region)
{
    int resolved = region;

    if (resolved == DEFAULT_DSTREGION) {
	if (reference)
	    resolved = reference->dst_region;
        else
            resolved = 1;
    }

    assert(resolved == 1 || resolved == 2 || resolved == 3);
    return resolved;
}

261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
static inline int access_mode(struct brw_program_instruction *insn)
{
    if (IS_GENp(8))
	return gen8_access_mode(GEN8(insn));
    else
	return GEN(insn)->header.access_mode;
}

static inline int exec_size(struct brw_program_instruction *insn)
{
    if (IS_GENp(8))
	return gen8_exec_size(GEN8(insn));
    else
	return GEN(insn)->header.execution_size;
}

277 278 279 280 281 282 283 284
static void set_execsize(struct brw_program_instruction *insn, int execsize)
{
    if (IS_GENp(8))
	gen8_set_exec_size(GEN8(insn), execsize);
    else
	GEN(insn)->header.execution_size = execsize;
}

285
static bool validate_dst_reg(struct brw_program_instruction *insn, struct brw_reg *reg)
286 287 288
{

    if (reg->address_mode == BRW_ADDRESS_DIRECT &&
289
	access_mode(insn) == BRW_ALIGN_1 &&
290 291 292 293 294 295 296
	reg->dw1.bits.writemask != 0 &&
	reg->dw1.bits.writemask != BRW_WRITEMASK_XYZW)
    {
	fprintf(stderr, "error: write mask set in align1 instruction\n");
	return false;
    }

297 298 299 300 301 302
    if (reg->address_mode == BRW_ADDRESS_REGISTER_INDIRECT_REGISTER &&
	access_mode(insn) == BRW_ALIGN_16) {
	fprintf(stderr, "error: indirect Dst addr mode in align16 instruction\n");
	return false;
    }

303 304 305
    return true;
}

306
static bool validate_src_reg(struct brw_program_instruction *insn,
307 308
			     struct brw_reg reg,
			     YYLTYPE *location)
309
{
310
    int hstride_for_reg[] = {0, 1, 2, 4};
311
    int vstride_for_reg[] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 256};
312
    int width_for_reg[] = {1, 2, 4, 8, 16};
313 314
    int execsize_for_reg[] = {1, 2, 4, 8, 16, 32};
    int width, hstride, vstride, execsize;
315

316 317 318
    if (reg.file == BRW_IMMEDIATE_VALUE)
	return true;

319
    if (access_mode(insn) == BRW_ALIGN_1 &&
320 321
	SWIZZLE(reg) && SWIZZLE(reg) != BRW_SWIZZLE_NOOP)
    {
322
	error(location, "swizzle bits set in align1 instruction\n");
323 324 325
	return false;
    }

326 327 328 329 330 331
    if (reg.address_mode == BRW_ADDRESS_REGISTER_INDIRECT_REGISTER &&
	access_mode(insn) == BRW_ALIGN_16) {
	fprintf(stderr, "error: indirect Source addr mode in align16 instruction\n");
	return false;
    }

332 333 334
    assert(reg.hstride >= 0 && reg.hstride < ARRAY_SIZE(hstride_for_reg));
    hstride = hstride_for_reg[reg.hstride];

335 336 337 338 339 340 341
    if (reg.vstride == 0xf) {
	vstride = -1;
    } else {
	assert(reg.vstride >= 0 && reg.vstride < ARRAY_SIZE(vstride_for_reg));
	vstride = vstride_for_reg[reg.vstride];
    }

342 343 344
    assert(reg.width >= 0 && reg.width < ARRAY_SIZE(width_for_reg));
    width = width_for_reg[reg.width];

345 346 347
    assert(exec_size(insn) >= 0 &&
	   exec_size(insn) < ARRAY_SIZE(execsize_for_reg));
    execsize = execsize_for_reg[exec_size(insn)];
348

349 350
    /* Register Region Restrictions */

351 352 353
    /* B. If ExecSize = Width and HorzStride ≠ 0, VertStride must be set to
     * Width * HorzStride. */
    if (execsize == width && hstride != 0) {
354
	if (vstride != -1 && vstride != width * hstride)
355 356 357 358
	    warn(ALL, location, "execution size == width and hstride != 0 but "
		 "vstride is not width * hstride\n");
    }

359 360 361 362 363 364 365 366 367 368
    /* D. If Width = 1, HorzStride must be 0 regardless of the values of
     * ExecSize and VertStride.
     *
     * FIXME: In "advanced mode" hstride is set to 1, this is probably a bug
     * to fix, but it changes the generated opcodes and thus needs validation.
     */
    if (width == 1 && hstride != 0)
	warn(ALL, location, "region width is 1 but horizontal stride is %d "
	     " (should be 0)\n", hstride);

369 370 371 372 373 374 375 376 377 378 379
    /* E. If ExecSize = Width = 1, both VertStride and HorzStride must be 0.
     * This defines a scalar. */
    if (execsize == 1 && width == 1) {
        if (hstride != 0)
	    warn(ALL, location, "execution size and region width are 1 but "
		 "horizontal stride is %d (should be 0)\n", hstride);
        if (vstride != 0)
	    warn(ALL, location, "execution size and region width are 1 but "
		 "vertical stride is %d (should be 0)\n", vstride);
    }

380 381 382
    return true;
}

383
static int get_subreg_address(unsigned regfile, unsigned type, unsigned subreg, unsigned address_mode)
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
{
    int unit_size = 1;

    assert(address_mode == BRW_ADDRESS_DIRECT);
    assert(regfile != BRW_IMMEDIATE_VALUE);

    if (advanced_flag)
	unit_size = get_type_size(type);

    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
 */
414
static int get_indirect_subreg_address(unsigned subreg)
415 416 417 418 419 420
{
    return advanced_flag == 0 ? subreg / 2 : subreg;
}

static void resolve_subnr(struct brw_reg *reg)
{
421 422 423
   if (reg->file == BRW_IMMEDIATE_VALUE)
	return;

424 425 426 427 428 429 430 431
   if (reg->address_mode == BRW_ADDRESS_DIRECT)
	reg->subnr = get_subreg_address(reg->file, reg->type, reg->subnr,
					reg->address_mode);
   else
        reg->subnr = get_indirect_subreg_address(reg->subnr);
}


Eric Anholt's avatar
Eric Anholt committed
432
%}
433
%locations
Eric Anholt's avatar
Eric Anholt committed
434 435 436 437

%start ROOT

%union {
438
	char *string;
Eric Anholt's avatar
Eric Anholt committed
439 440
	int integer;
	double number;
441
	struct brw_program_instruction instruction;
Eric Anholt's avatar
Eric Anholt committed
442
	struct brw_program program;
443 444
	struct region region;
	struct regtype regtype;
445
	struct brw_reg reg;
446
	struct condition condition;
447
	struct predicate predicate;
448
	struct options options;
449
	struct declared_register symbol_reg;
450
	imm32_t imm32;
451 452

	struct src_operand src_operand;
Eric Anholt's avatar
Eric Anholt committed
453 454
}

455
%token COLON
Eric Anholt's avatar
Eric Anholt committed
456 457 458 459
%token SEMICOLON
%token LPAREN RPAREN
%token LANGLE RANGLE
%token LCURLY RCURLY
460
%token LSQUARE RSQUARE
461 462 463
%token COMMA EQ
%token ABS DOT 
%token PLUS MINUS MULTIPLY DIVIDE
Eric Anholt's avatar
Eric Anholt committed
464

465 466
%token <integer> TYPE_UD TYPE_D TYPE_UW TYPE_W TYPE_UB TYPE_B
%token <integer> TYPE_VF TYPE_HF TYPE_V TYPE_F
Eric Anholt's avatar
Eric Anholt committed
467

468
%token ALIGN1 ALIGN16 SECHALF COMPR SWITCH ATOMIC NODDCHK NODDCLR
469
%token MASK_DISABLE BREAKPOINT ACCWRCTRL EOT
Eric Anholt's avatar
Eric Anholt committed
470

471 472 473
%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
474 475 476 477
%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
478
%token GENREGFILE MSGREGFILE
Eric Anholt's avatar
Eric Anholt committed
479

Eric Anholt's avatar
Eric Anholt committed
480 481
%token <integer> MOV FRC RNDU RNDD RNDE RNDZ NOT LZD
%token <integer> MUL MAC MACH LINE SAD2 SADA2 DP4 DPH DP3 DP2
482
%token <integer> AVG ADD SEL AND OR XOR SHR SHL ASR CMP CMPN PLN
483
%token <integer> ADDC BFI1 BFREV CBIT F16TO32 F32TO16 FBH FBL
484
%token <integer> SEND SENDC NOP JMPI IF IFF WHILE ELSE BREAK CONT HALT MSAVE
Eric Anholt's avatar
Eric Anholt committed
485
%token <integer> PUSH MREST POP WAIT DO ENDIF ILLEGAL
486
%token <integer> MATH_INST
487
%token <integer> MAD LRP BFE BFI2 SUBB
488
%token <integer> CALL RET
489
%token <integer> BRD BRC
Eric Anholt's avatar
Eric Anholt committed
490

491
%token NULL_TOKEN MATH SAMPLER GATEWAY READ WRITE URB THREAD_SPAWNER VME DATA_PORT CRE
Eric Anholt's avatar
Eric Anholt committed
492 493

%token MSGLEN RETURNLEN
494
%token <integer> ALLOCATE USED COMPLETE TRANSPOSE INTERLEAVE
495
%token SATURATE
Eric Anholt's avatar
Eric Anholt committed
496 497

%token <integer> INTEGER
498
%token <string> STRING
Eric Anholt's avatar
Eric Anholt committed
499 500
%token <number> NUMBER

501 502 503 504
%token <integer> INV LOG EXP SQRT RSQ POW SIN COS SINCOS INTDIV INTMOD
%token <integer> INTDIVMOD
%token SIGNED SCALAR

505 506
%token <integer> X Y Z W

507 508 509 510 511
%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
512 513
%precedence SUBREGNUM
%precedence SNDOPR
514 515
%left  PLUS MINUS
%left  MULTIPLY DIVIDE
516 517 518 519 520
%precedence UMINUS
%precedence DOT
%precedence STR_SYMBOL_REG
%precedence EMPTEXECSIZE
%precedence LPAREN
521 522

%type <integer> exp sndopr
523
%type <integer> simple_int
Eric Anholt's avatar
Eric Anholt committed
524
%type <instruction> instruction unaryinstruction binaryinstruction
525
%type <instruction> binaryaccinstruction trinaryinstruction sendinstruction
526
%type <instruction> syncinstruction
527
%type <instruction> msgtarget
528
%type <instruction> mathinstruction
529
%type <instruction> nopinstruction
530 531 532
%type <instruction> relocatableinstruction breakinstruction
%type <instruction> ifelseinstruction loopinstruction haltinstruction
%type <instruction> multibranchinstruction subroutineinstruction jumpinstruction
533
%type <string> label
Eric Anholt's avatar
Eric Anholt committed
534
%type <program> instrseq
535
%type <integer> instoption
536
%type <integer> unaryop binaryop binaryaccop breakop
537
%type <integer> trinaryop
538
%type <integer> sendop
539
%type <condition> conditionalmodifier 
540
%type <predicate> predicate
541
%type <options> instoptions instoption_list
542
%type <integer> condition saturate negate abs chansel
543
%type <integer> writemask_x writemask_y writemask_z writemask_w
544
%type <integer> srcimmtype execsize dstregion immaddroffset
545
%type <integer> subregnum sampler_datatype
546
%type <integer> urb_swizzle urb_allocate urb_used urb_complete
547
%type <integer> math_function math_signed math_scalar
548
%type <integer> predctrl predstate
549 550
%type <region> region region_wh indirectregion declare_srcregion;
%type <regtype> regtype
551 552 553 554 555 556 557
%type <reg> directgenreg directmsgreg addrreg accreg flagreg maskreg
%type <reg> maskstackreg notifyreg
/* %type <reg>  maskstackdepthreg */
%type <reg> statereg controlreg ipreg nullreg
%type <reg> dstoperandex_typed srcarchoperandex_typed
%type <reg> sendleadreg
%type <reg> indirectgenreg indirectmsgreg addrparam
558
%type <integer> mask_subreg maskstack_subreg 
559
%type <integer> declare_elementsize declare_dstregion declare_type
560
/* %type <intger> maskstackdepth_subreg */
561
%type <symbol_reg> symbol_reg symbol_reg_p;
Eric Anholt's avatar
Eric Anholt committed
562
%type <imm32> imm32
563 564
%type <reg> dst dstoperand dstoperandex dstreg post_dst writemask
%type <reg> declare_base
565
%type <src_operand> directsrcoperand srcarchoperandex directsrcaccoperand
566
%type <src_operand> indirectsrcoperand
567
%type <src_operand> src srcimm imm32reg payload srcacc srcaccimm swizzle
568
%type <src_operand> relativelocation relativelocation2
569 570 571 572 573 574 575 576 577 578

%code {

#undef error
#define error(l, fmt, ...)			\
    do {					\
	message(ERROR, l, fmt, ## __VA_ARGS__);	\
	YYERROR;				\
    } while(0)

579
static void add_option(struct options *options, int option)
580 581 582
{
    switch (option) {
    case ALIGN1:
583
	options->access_mode = BRW_ALIGN_1;
584 585
	break;
    case ALIGN16:
586
	options->access_mode = BRW_ALIGN_16;
587 588
	break;
    case SECHALF:
589
	options->compression_control |= BRW_COMPRESSION_2NDHALF;
590 591 592
	break;
    case COMPR:
	if (!IS_GENp(6))
593
	    options->compression_control |= BRW_COMPRESSION_COMPRESSED;
594 595
	break;
    case SWITCH:
596
	options->thread_control |= BRW_THREAD_SWITCH;
597 598
	break;
    case ATOMIC:
599
	options->thread_control |= BRW_THREAD_ATOMIC;
600 601
	break;
    case NODDCHK:
602
	options->dependency_control |= BRW_DEPENDENCY_NOTCHECKED;
603 604
	break;
    case NODDCLR:
605
	options->dependency_control |= BRW_DEPENDENCY_NOTCLEARED;
606 607
	break;
    case MASK_DISABLE:
608
	options->mask_control = BRW_MASK_DISABLE;
609 610
	break;
    case BREAKPOINT:
611
	options->debug_control = BRW_DEBUG_BREAKPOINT;
612 613
	break;
    case ACCWRCTRL:
614
	options->acc_wr_control = BRW_ACCUMULATOR_WRITE_ENABLE;
615 616
	break;
    case EOT:
617
	options->end_of_thread = 1;
618 619 620 621
	break;
    }
}

622 623
}

Eric Anholt's avatar
Eric Anholt committed
624
%%
625 626 627 628
simple_int:     INTEGER { $$ = $1; }
		| MINUS INTEGER { $$ = -$2;}
;

629 630 631
exp:		INTEGER { $$ = $1; }
		| exp PLUS exp { $$ = $1 + $3; }
		| exp MINUS exp { $$ = $1 - $3; }
632 633 634
		| exp MULTIPLY exp { $$ = $1 * $3; } 
		| exp DIVIDE exp { if ($3) $$ = $1 / $3; else YYERROR;}
		| MINUS exp %prec UMINUS { $$ = -$2;}
635
		| LPAREN exp RPAREN { $$ = $2; }
636
		;
Eric Anholt's avatar
Eric Anholt committed
637 638 639 640 641 642 643

ROOT:		instrseq
		{
		  compiled_program = $1;
		}
;

644 645 646 647

label:          STRING COLON
;

648 649 650 651 652 653 654 655 656 657
declare_base:  	BASE EQ dstreg 
	       	{
		   $$ = $3;
	       	}
;
declare_elementsize:  ELEMENTSIZE EQ exp
		{
		   $$ = $3;
		}
;
658
declare_srcregion: %empty /* empty */
659 660 661 662
		{
		  /* XXX is this default correct?*/
		  memset (&$$, '\0', sizeof ($$));
		  $$.vert_stride = ffs(0);
663
		  $$.width = BRW_WIDTH_1;
664 665 666 667 668 669 670
		  $$.horiz_stride = ffs(0);
		}
		| SRCREGION EQ region
		{
		    $$ = $3;
		}
;
671
declare_dstregion: %empty /* empty */
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
		{
		    $$ = 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
		{
687 688 689 690 691 692 693
		    struct declared_register reg, *found, *new_reg;

		    reg.name = $2;
		    reg.reg = $3;
		    reg.element_size = $4;
		    reg.src_region = $5;
		    reg.dst_region = $6;
694
		    reg.reg.type = $7;
695 696 697

		    found = find_register($2);
		    if (found) {
698 699 700
		        if (!declared_register_equal(&reg, found))
			    error(&@1, "%s already defined and definitions "
				  "don't agree\n", $2);
701
			free($2); // $2 has been malloc'ed by strdup
702
		    } else {
703 704 705
			new_reg = malloc(sizeof(struct declared_register));
			*new_reg = reg;
			insert_register(new_reg);
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736
		    }
		}
;

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
Eric Anholt's avatar
Eric Anholt committed
737
		{
738
		  brw_program_add_instruction(&$1, &$2);
739
		  $$ = $1;
Eric Anholt's avatar
Eric Anholt committed
740 741 742
		}
		| instruction SEMICOLON
		{
743 744
		  brw_program_init(&$$);
		  brw_program_add_instruction(&$$, &$1);
Eric Anholt's avatar
Eric Anholt committed
745
		}
746 747 748 749 750 751 752 753 754 755
		| instrseq relocatableinstruction SEMICOLON
		{
		  brw_program_add_relocatable(&$1, &$2);
		  $$ = $1;
		}
		| relocatableinstruction SEMICOLON
		{
		  brw_program_init(&$$);
		  brw_program_add_relocatable(&$$, &$1);
		}
756
		| instrseq SEMICOLON
757 758 759
		{
		    $$ = $1;
		}
760
		| instrseq label
761
        	{
762
		  brw_program_add_label(&$1, $2);
763
		  $$ = $1;
764
                }
765 766
		| label
		{
767 768
		  brw_program_init(&$$);
		  brw_program_add_label(&$$, $1);
769
		}
770 771 772 773 774
		| pragma
		{
		  $$.first = NULL;
		  $$.last = NULL;
		}
Chen, Yangyang's avatar
Chen, Yangyang committed
775 776
		| instrseq error SEMICOLON {
		  $$ = $1;
Eric Anholt's avatar
Eric Anholt committed
777 778 779 780
		}
;

/* 1.4.1: Instruction groups */
781 782
// binaryinstruction:    Source operands cannot be accumulators
// binaryaccinstruction: Source operands can be accumulators
Eric Anholt's avatar
Eric Anholt committed
783 784 785
instruction:	unaryinstruction
		| binaryinstruction
		| binaryaccinstruction
786 787
		| trinaryinstruction
		| sendinstruction
788
		| syncinstruction
789
		| mathinstruction
790
		| nopinstruction
791 792 793 794 795 796 797 798 799 800
;

/* relocatableinstruction are instructions that needs a relocation pass */
relocatableinstruction:	ifelseinstruction
			| loopinstruction
			| haltinstruction
			| multibranchinstruction
			| subroutineinstruction
			| jumpinstruction
			| breakinstruction
801 802
;

803
ifelseinstruction: ENDIF
804
		{
805
		  // for Gen4 
806 807
		  if(IS_GENp(6)) // For gen6+.
		    error(&@1, "should be 'ENDIF execsize relativelocation'\n");
808
		  memset(&$$, 0, sizeof($$));
809
		  set_instruction_opcode(&$$, $1);
810 811 812 813
		  GEN(&$$)->header.thread_control |= BRW_THREAD_SWITCH;
		  GEN(&$$)->bits1.da1.dest_horiz_stride = 1;
		  GEN(&$$)->bits1.da1.src1_reg_file = BRW_ARCHITECTURE_REGISTER_FILE;
		  GEN(&$$)->bits1.da1.src1_reg_type = BRW_REGISTER_TYPE_UD;
814 815 816
		}
		| ENDIF execsize relativelocation instoptions
		{
Homer Hsing's avatar
Homer Hsing committed
817 818
		  // for Gen6+
		  /* Gen6, Gen7 bspec: predication is prohibited */
819 820
		  if(!IS_GENp(6)) // for gen6-
		    error(&@1, "ENDIF Syntax error: should be 'ENDIF'\n");
821
		  memset(&$$, 0, sizeof($$));
822
		  set_instruction_opcode(&$$, $1);
823
		  set_execsize(&$$, $2);
824 825
		  $$.reloc.first_reloc_target = $3.reloc_target;
		  $$.reloc.first_reloc_offset = $3.imm32;
826 827 828
		}
		| ELSE execsize relativelocation instoptions
		{
829 830
		  if(!IS_GENp(6)) {
		    // for Gen4, Gen5. gen_level < 60
831 832 833 834
		    /* Set the istack pop count, which must always be 1. */
		    $3.imm32 |= (1 << 16);

		    memset(&$$, 0, sizeof($$));
835
		    set_instruction_opcode(&$$, $1);
836
		    GEN(&$$)->header.thread_control |= BRW_THREAD_SWITCH;
837
		    ip_dst.width = $2;
838 839 840
		    set_instruction_dest(&$$, &ip_dst);
		    set_instruction_src0(&$$, &ip_src, NULL);
		    set_instruction_src1(&$$, &$3, NULL);
841 842
		    $$.reloc.first_reloc_target = $3.reloc_target;
		    $$.reloc.first_reloc_offset = $3.imm32;
843
		  } else if(IS_GENp(6)) {
844
		    memset(&$$, 0, sizeof($$));
845
		    set_instruction_opcode(&$$, $1);
846
		    set_execsize(&$$, $2);
847 848
		    $$.reloc.first_reloc_target = $3.reloc_target;
		    $$.reloc.first_reloc_offset = $3.imm32;
849
		  } else {
850
		    error(&@1, "'ELSE' instruction is not implemented.\n");
851 852 853 854 855 856 857 858 859
		  }
		}
		| predicate IF execsize relativelocation
		{
		  /* 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.
		   */
860 861 862
		  if(IS_GENp(7)) /* Error in Gen7+. */
		    error(&@2, "IF should be 'IF execsize JIP UIP'\n");

863
		  memset(&$$, 0, sizeof($$));
864
		  set_instruction_predicate(&$$, &$1);
865
		  set_instruction_opcode(&$$, $2);
866
		  if(!IS_GENp(6)) {
867
		    GEN(&$$)->header.thread_control |= BRW_THREAD_SWITCH;
868
		    ip_dst.width = $3;
869 870 871
		    set_instruction_dest(&$$, &ip_dst);
		    set_instruction_src0(&$$, &ip_src, NULL);
		    set_instruction_src1(&$$, &$4, NULL);
Homer Hsing's avatar
Homer Hsing committed
872
		  }
873 874
		  $$.reloc.first_reloc_target = $4.reloc_target;
		  $$.reloc.first_reloc_offset = $4.imm32;
875
		}
876
		| predicate IF execsize relativelocation relativelocation
877
		{
878
		  /* for Gen7+ */
879 880 881
		  if(!IS_GENp(7))
		    error(&@2, "IF should be 'IF execsize relativelocation'\n");

882
		  memset(&$$, 0, sizeof($$));
883
		  set_instruction_predicate(&$$, &$1);
884
		  set_instruction_opcode(&$$, $2);
885
		  set_execsize(&$$, $3);
886 887 888 889
		  $$.reloc.first_reloc_target = $4.reloc_target;
		  $$.reloc.first_reloc_offset = $4.imm32;
		  $$.reloc.second_reloc_target = $5.reloc_target;
		  $$.reloc.second_reloc_offset = $5.imm32;
890
		}
891 892 893 894
;

loopinstruction: predicate WHILE execsize relativelocation instoptions
		{
895
		  if(!IS_GENp(6)) {
896 897 898 899 900
		    /* 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.
		     */
901
		    ip_dst.width = $3;
902
		    set_instruction_dest(&$$, &ip_dst);
903
		    memset(&$$, 0, sizeof($$));
904
		    set_instruction_predicate(&$$, &$1);
905
		    set_instruction_opcode(&$$, $2);
906 907 908
		    GEN(&$$)->header.thread_control |= BRW_THREAD_SWITCH;
		    set_instruction_src0(&$$, &ip_src, NULL);
		    set_instruction_src1(&$$, &$4, NULL);
909 910
		    $$.reloc.first_reloc_target = $4.reloc_target;
		    $$.reloc.first_reloc_offset = $4.imm32;
911
		  } else if (IS_GENp(6)) {
912 913 914
		    /* Gen6 spec:
		         dest must have the same element size as src0.
		         dest horizontal stride must be 1. */
915
		    memset(&$$, 0, sizeof($$));
916
		    set_instruction_predicate(&$$, &$1);
917
		    set_instruction_opcode(&$$, $2);
918
		    set_execsize(&$$, $3);
919 920
		    $$.reloc.first_reloc_target = $4.reloc_target;
		    $$.reloc.first_reloc_offset = $4.imm32;
921
		  } else {
922
		    error(&@2, "'WHILE' instruction is not implemented!\n");
923 924 925
		  }
		}
		| DO
926
		{
927 928
		  // deprecated
		  memset(&$$, 0, sizeof($$));
929
		  set_instruction_opcode(&$$, $1);
930 931 932 933
		};

haltinstruction: predicate HALT execsize relativelocation relativelocation instoptions
		{
934 935
		  // for Gen6, Gen7
		  /* Gen6, Gen7 bspec: dst and src0 must be the null reg. */
936
		  memset(&$$, 0, sizeof($$));
937
		  set_instruction_predicate(&$$, &$1);
938
		  set_instruction_opcode(&$$, $2);
939 940 941 942
		  $$.reloc.first_reloc_target = $4.reloc_target;
		  $$.reloc.first_reloc_offset = $4.imm32;
		  $$.reloc.second_reloc_target = $5.reloc_target;
		  $$.reloc.second_reloc_offset = $5.imm32;
943
		  dst_null_reg.width = $3;
944 945
		  set_instruction_dest(&$$, &dst_null_reg);
		  set_instruction_src0(&$$, &src_null_reg, NULL);
946 947 948 949 950 951 952
		};

multibranchinstruction:
		predicate BRD execsize relativelocation instoptions
		{
		  /* Gen7 bspec: dest must be null. use Switch option */
		  memset(&$$, 0, sizeof($$));
953
		  set_instruction_predicate(&$$, &$1);
954
		  set_instruction_opcode(&$$, $2);
955 956 957 958
		  if (IS_GENp(8))
                      gen8_set_thread_control(GEN8(&$$), gen8_thread_control(GEN8(&$$)) | BRW_THREAD_SWITCH);
		  else
                      GEN(&$$)->header.thread_control |= BRW_THREAD_SWITCH;
959 960
		  $$.reloc.first_reloc_target = $4.reloc_target;
		  $$.reloc.first_reloc_offset = $4.imm32;
961
		  dst_null_reg.width = $3;
962
		  set_instruction_dest(&$$, &dst_null_reg);
963
		}
964
		| predicate BRC execsize relativelocation relativelocation instoptions
965
		{
966
		  /* Gen7 bspec: dest must be null. src0 must be null. use Switch option */
967
		  memset(&$$, 0, sizeof($$));
968
		  set_instruction_predicate(&$$, &$1);
969
		  set_instruction_opcode(&$$, $2);
970 971 972 973
		  if (IS_GENp(8))
                      gen8_set_thread_control(GEN8(&$$), gen8_thread_control(GEN8(&$$)) | BRW_THREAD_SWITCH);
		  else
                      GEN(&$$)->header.thread_control |= BRW_THREAD_SWITCH;
974 975 976 977
		  $$.reloc.first_reloc_target = $4.reloc_target;
		  $$.reloc.first_reloc_offset = $4.imm32;
		  $$.reloc.second_reloc_target = $5.reloc_target;
		  $$.reloc.second_reloc_offset = $5.imm32;
978
		  dst_null_reg.width = $3;
979 980
		  set_instruction_dest(&$$, &dst_null_reg);
		  set_instruction_src0(&$$, &src_null_reg, NULL);
981
		}
982 983 984 985 986
;

subroutineinstruction:
		predicate CALL execsize dst relativelocation instoptions
		{
987 988 989 990 991 992 993 994 995 996 997 998 999 1000
		  /*
		    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.
		   */
1001
		  memset(&$$, 0, sizeof($$));
1002
		  set_instruction_predicate(&$$, &$1);
1003
		  set_instruction_opcode(&$$, $2);
1004

1005
		  $4.type = BRW_REGISTER_TYPE_D; /* dest type should be DWORD */
1006
		  $4.width = BRW_WIDTH_2; /* execution size must be 2. */
1007
		  set_instruction_dest(&$$, &$4);
1008 1009 1010

		  struct src_operand src0;
		  memset(&src0, 0, sizeof(src0));
1011
		  src0.reg.type = BRW_REGISTER_TYPE_D; /* source type should be DWORD */
1012
		  /* source0 region control must be <2,2,1>. */
1013
		  src0.reg.hstride = 1; /*encoded 1*/
1014
		  src0.reg.width = BRW_WIDTH_2;
1015
		  src0.reg.vstride = 2; /*encoded 2*/
1016
		  set_instruction_src0(&$$, &src0, NULL);
1017

1018 1019
		  $$.reloc.first_reloc_target = $5.reloc_target;
		  $$.reloc.first_reloc_offset = $5.imm32;
1020 1021 1022
		}
		| predicate RET execsize dstoperandex src instoptions
		{
1023 1024 1025 1026 1027 1028
		  /*
		     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)
		   */
1029
		  memset(&$$, 0, sizeof($$));
1030
		  set_instruction_predicate(&$$, &$1);
1031
		  set_instruction_opcode(&$$, $2);
1032
		  dst_null_reg.width = BRW_WIDTH_2; /* execution size of RET should be 2 */
1033
		  set_instruction_dest(&$$, &dst_null_reg);
1034 1035
		  $5.reg.type = BRW_REGISTER_TYPE_D;
		  $5.reg.hstride = 1; /*encoded 1*/
1036
		  $5.reg.width = BRW_WIDTH_2;
1037
		  $5.reg.vstride = 2; /*encoded 2*/
1038
		  set_instruction_src0(&$$, &$5, NULL);
1039
		}
Eric Anholt's avatar
Eric Anholt committed
1040 1041
;

1042 1043 1044
unaryinstruction:
		predicate unaryop conditionalmodifier saturate execsize
		dst srcaccimm instoptions
Eric Anholt's avatar
Eric Anholt committed
1045
		{
Homer Hsing's avatar
Homer Hsing committed
1046
		  memset(&$$, 0, sizeof($$));
1047
		  set_instruction_opcode(&$$, $2);
1048
		  set_instruction_saturate(&$$, $4);
1049
		  $6.width = $5;
1050
		  set_instruction_options(&$$, $8);
1051
		  set_instruction_pred_cond(&$$, &$1, &$3, &@3);
1052 1053
		  if (set_instruction_dest(&$$, &$6) != 0)
		    YYERROR;
1054
		  if (set_instruction_src0(&$$, &$7, &@7) != 0)
1055
		    YYERROR;
1056

1057
		  if (!IS_GENp(6) && 
1058 1059
				get_type_size(GEN(&$$)->bits1.da1.dest_reg_type) * (1 << $6.width) == 64)
		    GEN(&$$)->header.compression_control = BRW_COMPRESSION_COMPRESSED;
Eric Anholt's avatar
Eric Anholt committed
1060 1061 1062
		}
;

1063
unaryop:	MOV | FRC | RNDU | RNDD | RNDE | RNDZ | NOT | LZD | BFREV | CBIT
1064
          | F16TO32 | F32TO16 | FBH | FBL
Eric Anholt's avatar
Eric Anholt committed
1065 1066
;

1067
// Source operands cannot be accumulators
Eric Anholt's avatar
Eric Anholt committed
1068
binaryinstruction:
1069 1070
		predicate binaryop conditionalmodifier saturate execsize
		dst src srcimm instoptions
Eric Anholt's avatar
Eric Anholt committed
1071
		{
Homer Hsing's avatar
Homer Hsing committed
1072
		  memset(&$$, 0, sizeof($$));
1073
		  set_instruction_opcode(&$$, $2);
1074
		  set_instruction_saturate(&$$, $4);
1075
		  set_instruction_options(&$$, $9);
1076
		  set_instruction_pred_cond(&$$, &$1, &$3, &@3);
1077
		  $6.width = $5;
1078 1079
		  if (set_instruction_dest(&$$, &$6) != 0)
		    YYERROR;
1080
		  if (set_instruction_src0(&$$, &$7, &@7) != 0)
1081
		    YYERROR;
1082
		  if (set_instruction_src1(&$$, &$8, &@8) != 0)
1083
		    YYERROR;
1084

1085
		  if (!IS_GENp(6) && 
1086 1087
				get_type_size(GEN(&$$)->bits1.da1.dest_reg_type) * (1 << $6.width) == 64)
		    GEN(&$$)->header.compression_control = BRW_COMPRESSION_COMPRESSED;
Eric Anholt's avatar
Eric Anholt committed
1088 1089 1090
		}
;

1091 1092
/* bspec: BFI1 should not access accumulator. */
binaryop:	MUL | MAC | MACH | LINE | SAD2 | SADA2 | DP4 | DPH | DP3 | DP2 | PLN | BFI1
1093
;
Eric Anholt's avatar
Eric Anholt committed
1094

1095
// Source operands can be accumulators
Eric Anholt's avatar
Eric Anholt committed
1096
binaryaccinstruction:
1097 1098
		predicate binaryaccop conditionalmodifier saturate execsize
		dst srcacc srcimm instoptions
Eric Anholt's avatar
Eric Anholt committed
1099
		{
Homer Hsing's avatar
Homer Hsing committed
1100
		  memset(&$$, 0, sizeof($$));
1101
		  set_instruction_opcode(&$$, $2);
1102
		  set_instruction_saturate(&$$, $4);
1103
		  $6.width = $5;
1104
		  set_instruction_options(&$$, $9);
1105
		  set_instruction_pred_cond(&$$, &$1, &$3, &@3);
1106 1107
		  if (set_instruction_dest(&$$, &$6) != 0)
		    YYERROR;
1108
		  if (set_instruction_src0(&$$, &$7, &@7) != 0)
1109
		    YYERROR;
1110
		  if (set_instruction_src1(&$$, &$8, &@8) != 0)
1111
		    YYERROR;
1112

1113
		  if (!IS_GENp(6) && 
1114 1115
				get_type_size(GEN(&$$)->bits1.da1.dest_reg_type) * (1 << $6.width) == 64)
		    GEN(&$$)->header.compression_control = BRW_COMPRESSION_COMPRESSED;
Eric Anholt's avatar
Eric Anholt committed
1116 1117 1118
		}
;

1119 1120
/* 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
Eric Anholt's avatar
Eric Anholt committed
1121 1122
;

1123
trinaryop:	MAD | LRP | BFE | BFI2
1124 1125 1126 1127 1128 1129 1130 1131
;

trinaryinstruction:
		predicate trinaryop conditionalmodifier saturate execsize
		dst src src src instoptions
{
		  memset(&$$, 0, sizeof($$));

1132
		  set_instruction_pred_cond(&$$, &$1, &$3, &@3);
1133

1134
		  set_instruction_opcode(&$$, $2);
1135
		  set_instruction_saturate(&$$, $4);
1136
		  set_instruction_options(&$$, $10);
1137

1138
		  $6.width = $5;
1139 1140 1141 1142 1143 1144 1145 1146 1147
		  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;
}
1148
;
Eric Anholt's avatar
Eric Anholt committed
1149

1150 1151 1152 1153
sendop:		SEND | SENDC
;

sendinstruction: predicate sendop execsize exp post_dst payload msgtarget
1154
		MSGLEN exp RETURNLEN exp instoptions
Eric Anholt's avatar
Eric Anholt committed
1155
		{
1156 1157 1158 1159 1160 1161 1162 1163 1164
		  /* 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.
		   */
Homer Hsing's avatar
Homer Hsing committed
1165
		  memset(&$$, 0, sizeof($$));
1166
		  set_instruction_opcode(&$$, $2);
1167
		  $5.width = $3;
1168
		  GEN(&$$)->header.destreg__conditionalmod = $4; /* msg reg index */
1169
		  set_instruction_predicate(&$$, &$1);
1170 1171
		  if (set_instruction_dest(&$$, &$5) != 0)
		    YYERROR;
1172

1173
		  if (IS_GENp(6)) {
1174 1175 1176
                      struct src_operand src0;

                      memset(&src0, 0, sizeof(src0));
1177
                      src0.reg.address_mode = BRW_ADDRESS_DIRECT;
1178

1179
                      if (IS_GENp(7))
1180
                          src0.reg.file = BRW_GENERAL_REGISTER_FILE;
1181
                      else
1182
                          src0.reg.file = BRW_MESSAGE_REGISTER_FILE;
1183

1184 1185 1186
                      src0.reg.type = BRW_REGISTER_TYPE_D;
                      src0.reg.nr = $4;
                      src0.reg.subnr = 0;
1187
                      set_instruction_src0(&$$, &src0, NULL);
1188
		  } else {
1189
                      if (set_instruction_src0(&$$, &$6, &@6) != 0)
1190 1191 1192
                          YYERROR;
		  }

1193 1194 1195 1196 1197
		  if (IS_GENp(9)) {
		      gen8_set_src1_reg_file(GEN8(&$$), BRW_IMMEDIATE_VALUE);
		      gen8_set_src1_reg_type(GEN8(&$$), BRW_REGISTER_TYPE_D);
		      gen9_set_send_extdesc(GEN8(&$$), 0);
		  } else if (IS_GENp(8)) {
1198 1199 1200 1201 1202 1203
		      gen8_set_src1_reg_file(GEN8(&$$), BRW_IMMEDIATE_VALUE);
		      gen8_set_src1_reg_type(GEN8(&$$), BRW_REGISTER_TYPE_D);
		  } else {
		      GEN(&$$)->bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE;
		      GEN(&$$)->bits1.da1.src1_reg_type = BRW_REGISTER_TYPE_D;
		  }
Haihao Xiang's avatar
Haihao Xiang committed
1204

1205 1206 1207 1208 1209 1210 1211
		  if (IS_GENp(8)) {
		      GEN8(&$$)->data[3] = GEN8(&$7)->data[3];
		      gen8_set_sfid(GEN8(&$$), gen8_sfid(GEN8(&$7)));
		      gen8_set_mlen(GEN8(&$$), $9);
		      gen8_set_rlen(GEN8(&$$), $11);
		      gen8_set_eot(GEN8(&$$), $12.end_of_thread);
		  } else if (IS_GENp(5)) {
1212
                      if (IS_GENp(6)) {
1213
                          GEN(&$$)->header.destreg__conditionalmod = GEN(&$7)->bits2.send_gen5.sfid;
1214
                      } else {
1215 1216
                          GEN(&$$)->header.destreg__conditionalmod = $4; /* msg reg index */
                          GEN(&$$)->bits2.send_gen5.sfid = GEN(&$7)->bits2.send_gen5.sfid;
1217
                          GEN(&$$)->bits2.send_gen5.end_of_thread = $12.end_of_thread;
1218 1219
                      }

1220 1221 1222
                      GEN(&$$)->bits3.generic_gen5 = GEN(&$7)->bits3.generic_gen5;
                      GEN(&$$)->bits3.generic_gen5.msg_length = $9;
                      GEN(&$$)->bits3.generic_gen5.response_length = $11;
1223
                      GEN(&$$)->bits3.generic_gen5.end_of_thread = $12.end_of_thread;
Haihao Xiang's avatar
Haihao Xiang committed
1224
		  } else {
1225 1226 1227 1228
                      GEN(&$$)->header.destreg__conditionalmod = $4; /* msg reg index */
                      GEN(&$$)->bits3.generic = GEN(&$7)->bits3.generic;
                      GEN(&$$)->bits3.generic.msg_length = $9;
                      GEN(&$$)->bits3.generic.response_length = $11;
1229
                      GEN(&$$)->bits3.generic.end_of_thread = $12.end_of_thread;
Haihao Xiang's avatar
Haihao Xiang committed
1230
		  }
Eric Anholt's avatar
Eric Anholt committed
1231
		}
1232
		| predicate sendop execsize dst sendleadreg payload directsrcoperand instoptions
1233
		{
1234
		  if (IS_GENp(6))
1235
                      error(&@2, "invalid syntax for send on gen6+\n");
1236

Homer Hsing's avatar
Homer Hsing committed
1237
		  memset(&$$, 0, sizeof($$));
1238
		  set_instruction_opcode(&$$, $2);
1239
		  GEN(&$$)->header.destreg__conditionalmod = $5.nr; /* msg reg index */
1240 1241 1242

		  set_instruction_predicate(&$$, &$1);

1243
		  $4.width = $3;
1244 1245
		  if (set_instruction_dest(&$$, &$4) != 0)
		    YYERROR;
1246
		  if (set_instruction_src0(&$$, &$6, &@6) != 0)
1247 1248
		    YYERROR;
		  /* XXX is this correct? */
1249
		  if (set_instruction_src1(&$$, &$7, &@7) != 0)
1250
		    YYERROR;
1251

1252
		  }
1253
		| predicate sendop execsize dst sendleadreg payload imm32reg instoptions
1254
                {
1255
		  if (IS_GENp(6))
1256
                      error(&@2, "invalid syntax for send on gen6+\n");
1257

1258 1259 1260
		  if ($7.reg.type != BRW_REGISTER_TYPE_UD &&
		      $7.reg.type != BRW_REGISTER_TYPE_D &&
		      $7.reg.type != BRW_REGISTER_TYPE_V) {
1261 1262
		    error (&@7, "non-int D/UD/V representation: %d,"
			   "type=%d\n", $7.reg.dw1.ud, $7.reg.type);
1263
		  }
Homer Hsing's avatar
Homer Hsing committed
1264
		  memset(&$$, 0, sizeof($$));
1265
		  set_instruction_opcode(&$$, $2);
1266
		  GEN(&$$)->header.destreg__conditionalmod = $5.nr; /* msg reg index */
1267 1268

		  set_instruction_predicate(&$$, &$1);
1269
		  $4.width = $3;
1270 1271
		  if (set_instruction_dest(&$$, &$4) != 0)
		    YYERROR;
1272
		  if (set_instruction_src0(&$$, &$6, &@6) != 0)
1273
		    YYERROR;
1274 1275
		  if (set_instruction_src1(&$$, &$7, &@7) != 0)
		    YYERROR;
1276
                }
1277
		| predicate sendop execsize dst sendleadreg sndopr imm32reg instoptions
Haihao Xiang's avatar
Haihao Xiang committed
1278 1279 1280
		{
		  struct src_operand src0;

1281
		  if (!IS_GENp(6))
1282
                      error(&@2, "invalid syntax for send on gen6+\n");
Haihao Xiang's avatar
Haihao Xiang committed
1283

1284 1285 1286
		  if ($7.reg.type != BRW_REGISTER_TYPE_UD &&
                      $7.reg.type != BRW_REGISTER_TYPE_D &&
                      $7.reg.type != BRW_REGISTER_TYPE_V) {
1287 1288
                      error(&@7,"non-int D/UD/V representation: %d,"
			    "type=%d\n", $7.reg.dw1.ud, $7.reg.type);
Haihao Xiang's avatar
Haihao Xiang committed
1289 1290
		  }

Homer Hsing's avatar
Homer Hsing committed
1291
		  memset(&$$, 0, sizeof($$));
1292
		  set_instruction_opcode(&$$, $2);
Haihao Xiang's avatar
Haihao Xiang committed
1293 1294
		  set_instruction_predicate(&$$, &$1);

1295
		  $4.width = $3;
Haihao Xiang's avatar
Haihao Xiang committed
1296 1297
		  if (set_instruction_dest(&$$, &$4) != 0)
                      YYERROR;
1298

Haihao Xiang's avatar
Haihao Xiang committed
1299
                  memset(&src0, 0, sizeof(src0));
1300
                  src0.reg.address_mode = BRW_ADDRESS_DIRECT;
1301

1302
                  if (IS_GENp(7)) {
1303 1304
                      src0.reg.file = BRW_GENERAL_REGISTER_FILE;
                      src0.reg.type = BRW_REGISTER_TYPE_UB;
1305
                  } else {
1306 1307
                      src0.reg.file = BRW_MESSAGE_REGISTER_FILE;
                      src0.reg.type = BRW_REGISTER_TYPE_D;
1308
                  }
1309

1310 1311
                  src0.reg.nr = $5.nr;
                  src0.reg.subnr = 0;
1312
                  set_instruction_src0(&$$, &src0, NULL);
1313
		  set_instruction_src1(&$$, &$7, NULL);
Haihao Xiang's avatar
Haihao Xiang committed
1314

1315 1316 1317 1318 1319
                  if (IS_GENp(9)) {
                      gen8_set_sfid(GEN8(&$$), $6 & EX_DESC_SFID_MASK);
                      gen8_set_eot(GEN8(&$$), !!($6 & EX_DESC_EOT_MASK));
                      gen9_set_send_extdesc(GEN8(&$$), $6 & EX_DESC_FUNC_MASK);
                  } else if (IS_GENp(8)) {
1320 1321 1322 1323 1324 1325
                      gen8_set_sfid(GEN8(&$$), $6 & EX_DESC_SFID_MASK);
                      gen8_set_eot(GEN8(&$$), !!($6 & EX_DESC_EOT_MASK));
		  } else {
                      GEN(&$$)->header.destreg__conditionalmod = ($6 & EX_DESC_SFID_MASK); /* SFID */
                      GEN(&$$)->bits3.generic_gen5.end_of_thread = !!($6 & EX_DESC_EOT_MASK);
                  }
Haihao Xiang's avatar
Haihao Xiang committed
1326
		}