142542f5fSchristos/*
242542f5fSchristos * Copyright © 2013 Intel Corporation
342542f5fSchristos *
442542f5fSchristos * Permission is hereby granted, free of charge, to any person obtaining a
542542f5fSchristos * copy of this software and associated documentation files (the "Software"),
642542f5fSchristos * to deal in the Software without restriction, including without limitation
742542f5fSchristos * the rights to use, copy, modify, merge, publish, distribute, sublicense,
842542f5fSchristos * and/or sell copies of the Software, and to permit persons to whom the
942542f5fSchristos * Software is furnished to do so, subject to the following conditions:
1042542f5fSchristos *
1142542f5fSchristos * The above copyright notice and this permission notice (including the next
1242542f5fSchristos * paragraph) shall be included in all copies or substantial portions of the
1342542f5fSchristos * Software.
1442542f5fSchristos *
1542542f5fSchristos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1642542f5fSchristos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1742542f5fSchristos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1842542f5fSchristos * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1942542f5fSchristos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2042542f5fSchristos * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2142542f5fSchristos * IN THE SOFTWARE.
2242542f5fSchristos */
2342542f5fSchristos
2442542f5fSchristos#ifdef HAVE_CONFIG_H
2542542f5fSchristos#include "config.h"
2642542f5fSchristos#endif
2742542f5fSchristos
2842542f5fSchristos#include <string.h>
2942542f5fSchristos
3042542f5fSchristos#include "compiler.h"
3142542f5fSchristos#include "brw/brw.h"
3242542f5fSchristos#include "gen8_eu.h"
3342542f5fSchristos
3442542f5fSchristos#ifndef ARRAY_SIZE
3542542f5fSchristos#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
3642542f5fSchristos#endif
3742542f5fSchristos
3842542f5fSchristos/* EU ISA */
3942542f5fSchristos
4042542f5fSchristos#define MRF_HACK_START 111
4142542f5fSchristos
4242542f5fSchristosstruct gen8_instruction {
4342542f5fSchristos	uint32_t data[4];
4442542f5fSchristos};
4542542f5fSchristos
4642542f5fSchristosstatic inline unsigned
4742542f5fSchristos__gen8_mask(unsigned high, unsigned low)
4842542f5fSchristos{
4942542f5fSchristos	assert(high >= low);
5042542f5fSchristos	return (1 << (high - low + 1)) - 1;
5142542f5fSchristos}
5242542f5fSchristos
5342542f5fSchristos/**
5442542f5fSchristos * Fetch a set of contiguous bits from the instruction.
5542542f5fSchristos *
5642542f5fSchristos * Bits indexes range from 0..127; fields may not cross 32-bit boundaries.
5742542f5fSchristos */
5842542f5fSchristosstatic inline unsigned
5942542f5fSchristos__gen8_bits(struct gen8_instruction *insn, unsigned high, unsigned low)
6042542f5fSchristos{
6142542f5fSchristos	/* We assume the field doesn't cross 32-bit boundaries. */
6242542f5fSchristos	const unsigned word = high / 32;
6342542f5fSchristos
6442542f5fSchristos	assert(word == low / 32);
6542542f5fSchristos
6642542f5fSchristos	high %= 32;
6742542f5fSchristos	low %= 32;
6842542f5fSchristos
6942542f5fSchristos	return (insn->data[word] >> low) & __gen8_mask(high, low);
7042542f5fSchristos}
7142542f5fSchristos
7242542f5fSchristos/**
7342542f5fSchristos * Set bits in the instruction, with proper shifting and masking.
7442542f5fSchristos *
7542542f5fSchristos * Bits indexes range from 0..127; fields may not cross 32-bit boundaries.
7642542f5fSchristos */
7742542f5fSchristosstatic inline void
7842542f5fSchristos__gen8_set_bits(struct gen8_instruction *insn,
7942542f5fSchristos		unsigned high,
8042542f5fSchristos		unsigned low,
8142542f5fSchristos		unsigned value)
8242542f5fSchristos{
8342542f5fSchristos	const unsigned word = high / 32;
8442542f5fSchristos	unsigned mask;
8542542f5fSchristos
8642542f5fSchristos	assert(word == low / 32);
8742542f5fSchristos
8842542f5fSchristos	high %= 32;
8942542f5fSchristos	low %= 32;
9042542f5fSchristos	assert(value < __gen8_mask(high, low) + 1);
9142542f5fSchristos
9242542f5fSchristos	mask = __gen8_mask(high, low) << low;
9342542f5fSchristos	insn->data[word] &= ~mask;
9442542f5fSchristos	insn->data[word] |= (value << low) & mask;
9542542f5fSchristos
9642542f5fSchristos	assert(__gen8_bits(insn, 32*word+high, 32*word+low) == value);
9742542f5fSchristos}
9842542f5fSchristos
9942542f5fSchristos#define F(name, high, low) \
10042542f5fSchristosstatic inline void __gen8_set_##name(struct gen8_instruction *insn, unsigned v) \
10142542f5fSchristos{ \
10242542f5fSchristos	__gen8_set_bits(insn, high, low, v); \
10342542f5fSchristos} \
10442542f5fSchristosstatic inline unsigned __gen8_##name(struct gen8_instruction *insn) \
10542542f5fSchristos{ \
10642542f5fSchristos	return __gen8_bits(insn, high, low); \
10742542f5fSchristos}
10842542f5fSchristos
10942542f5fSchristos/**
11042542f5fSchristos* Direct addressing only:
11142542f5fSchristos*  @{
11242542f5fSchristos*/
11342542f5fSchristosF(src1_da_reg_nr,      108, 101);
11442542f5fSchristosF(src0_da_reg_nr,       76,  69);
11542542f5fSchristosF(dst_da1_hstride,      62,  61);
11642542f5fSchristosF(dst_da_reg_nr,        60,  53);
11742542f5fSchristosF(dst_da16_subreg_nr,   52,  52);
11842542f5fSchristosF(dst_da1_subreg_nr,    52,  48);
11942542f5fSchristosF(da16_writemask,       51,  48); /* Dst.ChanEn */
12042542f5fSchristos/** @} */
12142542f5fSchristos
12242542f5fSchristosF(src1_vert_stride,    120, 117)
12342542f5fSchristosF(src1_da1_width,      116, 114)
12442542f5fSchristosF(src1_da16_swiz_w,    115, 114)
12542542f5fSchristosF(src1_da16_swiz_z,    113, 112)
12642542f5fSchristosF(src1_da1_hstride,    113, 112)
12742542f5fSchristosF(src1_address_mode,   111, 111)
12842542f5fSchristos/** Src1.SrcMod @{ */
12942542f5fSchristosF(src1_negate,         110, 110)
13042542f5fSchristosF(src1_abs,            109, 109)
13142542f5fSchristos/** @} */
13242542f5fSchristosF(src1_da16_subreg_nr, 100, 100)
13342542f5fSchristosF(src1_da1_subreg_nr,  100,  96)
13442542f5fSchristosF(src1_da16_swiz_y,     99,  98)
13542542f5fSchristosF(src1_da16_swiz_x,     97,  96)
13642542f5fSchristosF(src1_reg_type,        94,  91)
13742542f5fSchristosF(src1_reg_file,        90,  89)
13842542f5fSchristosF(src0_vert_stride,     88,  85)
13942542f5fSchristosF(src0_da1_width,       84,  82)
14042542f5fSchristosF(src0_da16_swiz_w,     83,  82)
14142542f5fSchristosF(src0_da16_swiz_z,     81,  80)
14242542f5fSchristosF(src0_da1_hstride,     81,  80)
14342542f5fSchristosF(src0_address_mode,    79,  79)
14442542f5fSchristos/** Src0.SrcMod @{ */
14542542f5fSchristosF(src0_negate,          78,  78)
14642542f5fSchristosF(src0_abs,             77,  77)
14742542f5fSchristos/** @} */
14842542f5fSchristosF(src0_da16_subreg_nr,  68,  68)
14942542f5fSchristosF(src0_da1_subreg_nr,   68,  64)
15042542f5fSchristosF(src0_da16_swiz_y,     67,  66)
15142542f5fSchristosF(src0_da16_swiz_x,     65,  64)
15242542f5fSchristosF(dst_address_mode,     63,  63)
15342542f5fSchristosF(src0_reg_type,        46,  43)
15442542f5fSchristosF(src0_reg_file,        42,  41)
15542542f5fSchristosF(dst_reg_type,         40,  37)
15642542f5fSchristosF(dst_reg_file,         36,  35)
15742542f5fSchristosF(mask_control,         34,  34)
15842542f5fSchristosF(flag_reg_nr,          33,  33)
15942542f5fSchristosF(flag_subreg_nr,       32,  32)
16042542f5fSchristosF(saturate,             31,  31)
16142542f5fSchristosF(branch_control,       30,  30)
16242542f5fSchristosF(debug_control,        30,  30)
16342542f5fSchristosF(cmpt_control,         29,  29)
16442542f5fSchristosF(acc_wr_control,       28,  28)
16542542f5fSchristosF(cond_modifier,        27,  24)
16642542f5fSchristosF(exec_size,            23,  21)
16742542f5fSchristosF(pred_inv,             20,  20)
16842542f5fSchristosF(pred_control,         19,  16)
16942542f5fSchristosF(thread_control,       15,  14)
17042542f5fSchristosF(qtr_control,          13,  12)
17142542f5fSchristosF(nib_control,          11,  11)
17242542f5fSchristosF(dep_control,          10,   9)
17342542f5fSchristosF(access_mode,           8,   8)
17442542f5fSchristos/* Bit 7 is Reserved (for future Opcode expansion) */
17542542f5fSchristosF(opcode,                6,   0)
17642542f5fSchristos
17742542f5fSchristos/**
17842542f5fSchristos* Three-source instructions:
17942542f5fSchristos*  @{
18042542f5fSchristos*/
18142542f5fSchristosF(src2_3src_reg_nr,    125, 118)
18242542f5fSchristosF(src2_3src_subreg_nr, 117, 115)
18342542f5fSchristosF(src2_3src_swizzle,   114, 107)
18442542f5fSchristosF(src2_3src_rep_ctrl,  106, 106)
18542542f5fSchristosF(src1_3src_reg_nr,    104,  97)
18642542f5fSchristosF(src1_3src_subreg_hi,  96,  96)
18742542f5fSchristosF(src1_3src_subreg_lo,  95,  94)
18842542f5fSchristosF(src1_3src_swizzle,    93,  86)
18942542f5fSchristosF(src1_3src_rep_ctrl,   85,  85)
19042542f5fSchristosF(src0_3src_reg_nr,     83,  76)
19142542f5fSchristosF(src0_3src_subreg_nr,  75,  73)
19242542f5fSchristosF(src0_3src_swizzle,    72,  65)
19342542f5fSchristosF(src0_3src_rep_ctrl,   64,  64)
19442542f5fSchristosF(dst_3src_reg_nr,      63,  56)
19542542f5fSchristosF(dst_3src_subreg_nr,   55,  53)
19642542f5fSchristosF(dst_3src_writemask,   52,  49)
19742542f5fSchristosF(dst_3src_type,        48,  46)
19842542f5fSchristosF(src_3src_type,        45,  43)
19942542f5fSchristosF(src2_3src_negate,     42,  42)
20042542f5fSchristosF(src2_3src_abs,        41,  41)
20142542f5fSchristosF(src1_3src_negate,     40,  40)
20242542f5fSchristosF(src1_3src_abs,        39,  39)
20342542f5fSchristosF(src0_3src_negate,     38,  38)
20442542f5fSchristosF(src0_3src_abs,        37,  37)
20542542f5fSchristos/** @} */
20642542f5fSchristos
20742542f5fSchristos/**
20842542f5fSchristos* Fields for SEND messages:
20942542f5fSchristos*  @{
21042542f5fSchristos*/
21142542f5fSchristosF(eot,                 127, 127)
21242542f5fSchristosF(mlen,                124, 121)
21342542f5fSchristosF(rlen,                120, 116)
21442542f5fSchristosF(header_present,      115, 115)
21542542f5fSchristosF(function_control,    114,  96)
21642542f5fSchristosF(sfid,                 27,  24)
21742542f5fSchristosF(math_function,        27,  24)
21842542f5fSchristos/** @} */
21942542f5fSchristos
22042542f5fSchristos/**
22142542f5fSchristos* URB message function control bits:
22242542f5fSchristos*  @{
22342542f5fSchristos*/
22442542f5fSchristosF(urb_per_slot_offset, 113, 113)
22542542f5fSchristosF(urb_interleave,      111, 111)
22642542f5fSchristosF(urb_global_offset,   110, 100)
22742542f5fSchristosF(urb_opcode,           99,  96)
22842542f5fSchristos/** @} */
22942542f5fSchristos
23042542f5fSchristos/**
23142542f5fSchristos* Sampler message function control bits:
23242542f5fSchristos*  @{
23342542f5fSchristos*/
23442542f5fSchristosF(sampler_simd_mode,   114, 113)
23542542f5fSchristosF(sampler_msg_type,    112, 108)
23642542f5fSchristosF(sampler,             107, 104)
23742542f5fSchristosF(binding_table_index, 103,  96)
23842542f5fSchristos/** @} */
23942542f5fSchristos
24042542f5fSchristos/**
24142542f5fSchristos * Data port message function control bits:
24242542f5fSchristos *  @ {
24342542f5fSchristos */
24442542f5fSchristosF(dp_category,            114, 114)
24542542f5fSchristosF(dp_message_type,        113, 110)
24642542f5fSchristosF(dp_message_control,     109, 104)
24742542f5fSchristosF(dp_binding_table_index, 103,  96)
24842542f5fSchristos/** @} */
24942542f5fSchristos
25042542f5fSchristos/**
25142542f5fSchristos * Thread Spawn message function control bits:
25242542f5fSchristos *  @ {
25342542f5fSchristos */
25442542f5fSchristosF(ts_resource_select,     100, 100)
25542542f5fSchristosF(ts_request_type,         97,  97)
25642542f5fSchristosF(ts_opcode,               96,  96)
25742542f5fSchristos/** @} */
25842542f5fSchristos
25942542f5fSchristos/**
26042542f5fSchristos * Video Motion Estimation message function control bits:
26142542f5fSchristos *  @ {
26242542f5fSchristos */
26342542f5fSchristosF(vme_message_type,        110, 109)
26442542f5fSchristosF(vme_binding_table_index, 103,  96)
26542542f5fSchristos/** @} */
26642542f5fSchristos
26742542f5fSchristos/**
26842542f5fSchristos * Check & Refinement Engine message function control bits:
26942542f5fSchristos *  @ {
27042542f5fSchristos */
27142542f5fSchristosF(cre_message_type,        110, 109)
27242542f5fSchristosF(cre_binding_table_index, 103,  96)
27342542f5fSchristos/** @} */
27442542f5fSchristos
27542542f5fSchristos#undef F
27642542f5fSchristos
27742542f5fSchristos/**
27842542f5fSchristos* Flow control instruction bits:
27942542f5fSchristos*  @{
28042542f5fSchristos*/
28142542f5fSchristosstatic inline unsigned __gen8_uip(struct gen8_instruction *insn)
28242542f5fSchristos{
28342542f5fSchristos	return insn->data[2];
28442542f5fSchristos}
28542542f5fSchristos
28642542f5fSchristosstatic inline void __gen8_set_uip(struct gen8_instruction *insn, unsigned uip)
28742542f5fSchristos{
28842542f5fSchristos	insn->data[2] = uip;
28942542f5fSchristos}
29042542f5fSchristos
29142542f5fSchristosstatic inline unsigned __gen8_jip(struct gen8_instruction *insn)
29242542f5fSchristos{
29342542f5fSchristos	return insn->data[3];
29442542f5fSchristos}
29542542f5fSchristos
29642542f5fSchristosstatic inline void __gen8_set_jip(struct gen8_instruction *insn, unsigned jip)
29742542f5fSchristos{
29842542f5fSchristos	insn->data[3] = jip;
29942542f5fSchristos}
30042542f5fSchristos/** @} */
30142542f5fSchristos
30242542f5fSchristosstatic inline int __gen8_src1_imm_d(struct gen8_instruction *insn)
30342542f5fSchristos{
30442542f5fSchristos	return insn->data[3];
30542542f5fSchristos}
30642542f5fSchristos
30742542f5fSchristosstatic inline unsigned __gen8_src1_imm_ud(struct gen8_instruction *insn)
30842542f5fSchristos{
30942542f5fSchristos	return insn->data[3];
31042542f5fSchristos}
31142542f5fSchristos
31242542f5fSchristosstatic inline float __gen8_src1_imm_f(struct gen8_instruction *insn)
31342542f5fSchristos{
31442542f5fSchristos	union {
31542542f5fSchristos		uint32_t u;
31642542f5fSchristos		float f;
31742542f5fSchristos	} ft = { insn->data[3] };
31842542f5fSchristos	return ft.f;
31942542f5fSchristos}
32042542f5fSchristos
32142542f5fSchristosstatic void
32242542f5fSchristos__gen8_set_dst(struct brw_compile *p,
32342542f5fSchristos	       struct gen8_instruction *inst,
32442542f5fSchristos	       struct brw_reg reg)
32542542f5fSchristos{
32642542f5fSchristos	/* MRFs haven't existed since Gen7, so we better not be using them. */
32742542f5fSchristos	if (reg.file == BRW_MESSAGE_REGISTER_FILE) {
32842542f5fSchristos		reg.file = BRW_GENERAL_REGISTER_FILE;
32942542f5fSchristos		reg.nr += MRF_HACK_START;
33042542f5fSchristos	}
33142542f5fSchristos
33242542f5fSchristos	assert(reg.file != BRW_MESSAGE_REGISTER_FILE);
33342542f5fSchristos
33442542f5fSchristos	if (reg.file == BRW_GENERAL_REGISTER_FILE)
33542542f5fSchristos		assert(reg.nr < BRW_MAX_GRF);
33642542f5fSchristos
33742542f5fSchristos	__gen8_set_dst_reg_file(inst, reg.file);
33842542f5fSchristos	__gen8_set_dst_reg_type(inst, reg.type);
33942542f5fSchristos
34042542f5fSchristos	assert(reg.address_mode == BRW_ADDRESS_DIRECT);
34142542f5fSchristos
34242542f5fSchristos	__gen8_set_dst_da_reg_nr(inst, reg.nr);
34342542f5fSchristos
34442542f5fSchristos	if (__gen8_access_mode(inst) == BRW_ALIGN_1) {
34542542f5fSchristos		/* Set Dst.SubRegNum[4:0] */
34642542f5fSchristos		__gen8_set_dst_da1_subreg_nr(inst, reg.subnr);
34742542f5fSchristos
34842542f5fSchristos		/* Set Dst.HorzStride */
34942542f5fSchristos		if (reg.hstride == BRW_HORIZONTAL_STRIDE_0)
35042542f5fSchristos			reg.hstride = BRW_HORIZONTAL_STRIDE_1;
35142542f5fSchristos		__gen8_set_dst_da1_hstride(inst, reg.hstride);
35242542f5fSchristos	} else {
35342542f5fSchristos		/* Align16 SubRegNum only has a single bit (bit 4; bits 3:0 MBZ). */
35442542f5fSchristos		assert(reg.subnr == 0 || reg.subnr == 16);
35542542f5fSchristos		__gen8_set_dst_da16_subreg_nr(inst, reg.subnr >> 4);
35642542f5fSchristos		__gen8_set_da16_writemask(inst, reg.dw1.bits.writemask);
35742542f5fSchristos	}
35842542f5fSchristos
35942542f5fSchristos#if 1
36042542f5fSchristos	if (reg.width == BRW_WIDTH_8 && p->compressed)
36142542f5fSchristos		__gen8_set_exec_size(inst, BRW_EXECUTE_16);
36242542f5fSchristos	else
36342542f5fSchristos		__gen8_set_exec_size(inst, reg.width);
36442542f5fSchristos#else
36542542f5fSchristos	if (reg.width < BRW_EXECUTE_8)
36642542f5fSchristos		__gen8_set_exec_size(inst, reg.width);
36742542f5fSchristos#endif
36842542f5fSchristos}
36942542f5fSchristos
37042542f5fSchristosstatic void
37142542f5fSchristos__gen8_validate_reg(struct gen8_instruction *inst, struct brw_reg reg)
37242542f5fSchristos{
37342542f5fSchristos	int hstride_for_reg[] = {0, 1, 2, 4};
37442542f5fSchristos	int vstride_for_reg[] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 256};
37542542f5fSchristos	int width_for_reg[] = {1, 2, 4, 8, 16};
37642542f5fSchristos	int execsize_for_reg[] = {1, 2, 4, 8, 16};
37742542f5fSchristos	int width, hstride, vstride, execsize;
37842542f5fSchristos
37942542f5fSchristos	if (reg.file == BRW_IMMEDIATE_VALUE) {
38042542f5fSchristos		/* TODO: check immediate vectors */
38142542f5fSchristos		return;
38242542f5fSchristos	}
38342542f5fSchristos
38442542f5fSchristos	if (reg.file == BRW_ARCHITECTURE_REGISTER_FILE)
38542542f5fSchristos		return;
38642542f5fSchristos
38742542f5fSchristos	assert(reg.hstride >= 0 && reg.hstride < ARRAY_SIZE(hstride_for_reg));
38842542f5fSchristos	hstride = hstride_for_reg[reg.hstride];
38942542f5fSchristos
39042542f5fSchristos	if (reg.vstride == 0xf) {
39142542f5fSchristos		vstride = -1;
39242542f5fSchristos	} else {
39342542f5fSchristos		assert(reg.vstride >= 0 && reg.vstride < ARRAY_SIZE(vstride_for_reg));
39442542f5fSchristos		vstride = vstride_for_reg[reg.vstride];
39542542f5fSchristos	}
39642542f5fSchristos
39742542f5fSchristos	assert(reg.width >= 0 && reg.width < ARRAY_SIZE(width_for_reg));
39842542f5fSchristos	width = width_for_reg[reg.width];
39942542f5fSchristos
40042542f5fSchristos	assert(__gen8_exec_size(inst) >= 0 &&
40142542f5fSchristos	       __gen8_exec_size(inst) < ARRAY_SIZE(execsize_for_reg));
40242542f5fSchristos	execsize = execsize_for_reg[__gen8_exec_size(inst)];
40342542f5fSchristos
40442542f5fSchristos	/* Restrictions from 3.3.10: Register Region Restrictions. */
40542542f5fSchristos	/* 3. */
40642542f5fSchristos	assert(execsize >= width);
40742542f5fSchristos
40842542f5fSchristos	/* 4. */
40942542f5fSchristos	if (execsize == width && hstride != 0) {
41042542f5fSchristos		assert(vstride == -1 || vstride == width * hstride);
41142542f5fSchristos	}
41242542f5fSchristos
41342542f5fSchristos	/* 5. */
41442542f5fSchristos	if (execsize == width && hstride == 0) {
41542542f5fSchristos		/* no restriction on vstride. */
41642542f5fSchristos	}
41742542f5fSchristos
41842542f5fSchristos	/* 6. */
41942542f5fSchristos	if (width == 1) {
42042542f5fSchristos		assert(hstride == 0);
42142542f5fSchristos	}
42242542f5fSchristos
42342542f5fSchristos	/* 7. */
42442542f5fSchristos	if (execsize == 1 && width == 1) {
42542542f5fSchristos		assert(hstride == 0);
42642542f5fSchristos		assert(vstride == 0);
42742542f5fSchristos	}
42842542f5fSchristos
42942542f5fSchristos	/* 8. */
43042542f5fSchristos	if (vstride == 0 && hstride == 0) {
43142542f5fSchristos		assert(width == 1);
43242542f5fSchristos	}
43342542f5fSchristos
43442542f5fSchristos	/* 10. Check destination issues. */
43542542f5fSchristos}
43642542f5fSchristos
43742542f5fSchristosstatic void
43842542f5fSchristos__gen8_set_src0(struct gen8_instruction *inst, struct brw_reg reg)
43942542f5fSchristos{
44042542f5fSchristos	/* MRFs haven't existed since Gen7, so we better not be using them. */
44142542f5fSchristos	if (reg.file == BRW_MESSAGE_REGISTER_FILE) {
44242542f5fSchristos		reg.file = BRW_GENERAL_REGISTER_FILE;
44342542f5fSchristos		reg.nr += MRF_HACK_START;
44442542f5fSchristos	}
44542542f5fSchristos
44642542f5fSchristos	if (reg.file == BRW_GENERAL_REGISTER_FILE)
44742542f5fSchristos		assert(reg.nr < BRW_MAX_GRF);
44842542f5fSchristos
44942542f5fSchristos	__gen8_validate_reg(inst, reg);
45042542f5fSchristos
45142542f5fSchristos	__gen8_set_src0_reg_file(inst, reg.file);
45242542f5fSchristos	__gen8_set_src0_reg_type(inst, reg.type);
45342542f5fSchristos	__gen8_set_src0_abs(inst, reg.abs);
45442542f5fSchristos	__gen8_set_src0_negate(inst, reg.negate);
45542542f5fSchristos
45642542f5fSchristos	assert(reg.address_mode == BRW_ADDRESS_DIRECT);
45742542f5fSchristos
45842542f5fSchristos	if (reg.file == BRW_IMMEDIATE_VALUE) {
45942542f5fSchristos		inst->data[3] = reg.dw1.ud;
46042542f5fSchristos
46142542f5fSchristos		/* Required to set some fields in src1 as well: */
46242542f5fSchristos		__gen8_set_src1_reg_file(inst, 0); /* arf */
46342542f5fSchristos		__gen8_set_src1_reg_type(inst, reg.type);
46442542f5fSchristos	} else {
46542542f5fSchristos		__gen8_set_src0_da_reg_nr(inst, reg.nr);
46642542f5fSchristos
46742542f5fSchristos		if (__gen8_access_mode(inst) == BRW_ALIGN_1) {
46842542f5fSchristos			/* Set Src0.SubRegNum[4:0] */
46942542f5fSchristos			__gen8_set_src0_da1_subreg_nr(inst, reg.subnr);
47042542f5fSchristos
47142542f5fSchristos			if (reg.width == BRW_WIDTH_1 &&
47242542f5fSchristos			    __gen8_exec_size(inst) == BRW_EXECUTE_1) {
47342542f5fSchristos				__gen8_set_src0_da1_hstride(inst, BRW_HORIZONTAL_STRIDE_0);
47442542f5fSchristos				__gen8_set_src0_vert_stride(inst, BRW_VERTICAL_STRIDE_0);
47542542f5fSchristos			} else {
47642542f5fSchristos				__gen8_set_src0_da1_hstride(inst, reg.hstride);
47742542f5fSchristos				__gen8_set_src0_vert_stride(inst, reg.vstride);
47842542f5fSchristos			}
47942542f5fSchristos			__gen8_set_src0_da1_width(inst, reg.width);
48042542f5fSchristos		} else {
48142542f5fSchristos			/* Align16 SubRegNum only has a single bit (bit 4; bits 3:0 MBZ). */
48242542f5fSchristos			assert(reg.subnr == 0 || reg.subnr == 16);
48342542f5fSchristos			__gen8_set_src0_da16_subreg_nr(inst, reg.subnr >> 4);
48442542f5fSchristos
48542542f5fSchristos			__gen8_set_src0_da16_swiz_x(inst,
48642542f5fSchristos						  BRW_GET_SWZ(reg.dw1.bits.swizzle,
48742542f5fSchristos							      BRW_CHANNEL_X));
48842542f5fSchristos			__gen8_set_src0_da16_swiz_y(inst,
48942542f5fSchristos						  BRW_GET_SWZ(reg.dw1.bits.swizzle,
49042542f5fSchristos							      BRW_CHANNEL_Y));
49142542f5fSchristos			__gen8_set_src0_da16_swiz_z(inst,
49242542f5fSchristos						  BRW_GET_SWZ(reg.dw1.bits.swizzle,
49342542f5fSchristos							      BRW_CHANNEL_Z));
49442542f5fSchristos			__gen8_set_src0_da16_swiz_w(inst,
49542542f5fSchristos						  BRW_GET_SWZ(reg.dw1.bits.swizzle,
49642542f5fSchristos							      BRW_CHANNEL_W));
49742542f5fSchristos
49842542f5fSchristos			/* This is an oddity of the fact that we're using the same
49942542f5fSchristos			 * descriptions for registers in both Align16 and Align1 modes.
50042542f5fSchristos			 */
50142542f5fSchristos			if (reg.vstride == BRW_VERTICAL_STRIDE_8)
50242542f5fSchristos				__gen8_set_src0_vert_stride(inst, BRW_VERTICAL_STRIDE_4);
50342542f5fSchristos			else
50442542f5fSchristos				__gen8_set_src0_vert_stride(inst, reg.vstride);
50542542f5fSchristos		}
50642542f5fSchristos	}
50742542f5fSchristos}
50842542f5fSchristos
50942542f5fSchristosstatic void
51042542f5fSchristos__gen8_set_src1(struct gen8_instruction *inst, struct brw_reg reg)
51142542f5fSchristos{
51242542f5fSchristos	/* MRFs haven't existed since Gen7, so we better not be using them. */
51342542f5fSchristos	if (reg.file == BRW_MESSAGE_REGISTER_FILE) {
51442542f5fSchristos		reg.file = BRW_GENERAL_REGISTER_FILE;
51542542f5fSchristos		reg.nr += MRF_HACK_START;
51642542f5fSchristos	}
51742542f5fSchristos
51842542f5fSchristos	if (reg.file == BRW_GENERAL_REGISTER_FILE)
51942542f5fSchristos		assert(reg.nr < BRW_MAX_GRF);
52042542f5fSchristos
52142542f5fSchristos	__gen8_validate_reg(inst, reg);
52242542f5fSchristos
52342542f5fSchristos	__gen8_set_src1_reg_file(inst, reg.file);
52442542f5fSchristos	__gen8_set_src1_reg_type(inst, reg.type);
52542542f5fSchristos	__gen8_set_src1_abs(inst, reg.abs);
52642542f5fSchristos	__gen8_set_src1_negate(inst, reg.negate);
52742542f5fSchristos
52842542f5fSchristos	/* Only src1 can be an immediate in two-argument instructions. */
52942542f5fSchristos	assert(__gen8_src0_reg_file(inst) != BRW_IMMEDIATE_VALUE);
53042542f5fSchristos
53142542f5fSchristos	assert(reg.address_mode == BRW_ADDRESS_DIRECT);
53242542f5fSchristos
53342542f5fSchristos	if (reg.file == BRW_IMMEDIATE_VALUE) {
53442542f5fSchristos		inst->data[3] = reg.dw1.ud;
53542542f5fSchristos	} else {
53642542f5fSchristos		__gen8_set_src1_da_reg_nr(inst, reg.nr);
53742542f5fSchristos
53842542f5fSchristos		if (__gen8_access_mode(inst) == BRW_ALIGN_1) {
53942542f5fSchristos			/* Set Src0.SubRegNum[4:0] */
54042542f5fSchristos			__gen8_set_src1_da1_subreg_nr(inst, reg.subnr);
54142542f5fSchristos
54242542f5fSchristos			if (reg.width == BRW_WIDTH_1 &&
54342542f5fSchristos			    __gen8_exec_size(inst) == BRW_EXECUTE_1) {
54442542f5fSchristos				__gen8_set_src1_da1_hstride(inst, BRW_HORIZONTAL_STRIDE_0);
54542542f5fSchristos				__gen8_set_src1_vert_stride(inst, BRW_VERTICAL_STRIDE_0);
54642542f5fSchristos			} else {
54742542f5fSchristos				__gen8_set_src1_da1_hstride(inst, reg.hstride);
54842542f5fSchristos				__gen8_set_src1_vert_stride(inst, reg.vstride);
54942542f5fSchristos			}
55042542f5fSchristos			__gen8_set_src1_da1_width(inst, reg.width);
55142542f5fSchristos		} else {
55242542f5fSchristos			/* Align16 SubRegNum only has a single bit (bit 4; bits 3:0 MBZ). */
55342542f5fSchristos			assert(reg.subnr == 0 || reg.subnr == 16);
55442542f5fSchristos			__gen8_set_src1_da16_subreg_nr(inst, reg.subnr >> 4);
55542542f5fSchristos
55642542f5fSchristos			__gen8_set_src1_da16_swiz_x(inst,
55742542f5fSchristos						  BRW_GET_SWZ(reg.dw1.bits.swizzle,
55842542f5fSchristos							      BRW_CHANNEL_X));
55942542f5fSchristos			__gen8_set_src1_da16_swiz_y(inst,
56042542f5fSchristos						  BRW_GET_SWZ(reg.dw1.bits.swizzle,
56142542f5fSchristos							      BRW_CHANNEL_Y));
56242542f5fSchristos			__gen8_set_src1_da16_swiz_z(inst,
56342542f5fSchristos						  BRW_GET_SWZ(reg.dw1.bits.swizzle,
56442542f5fSchristos							      BRW_CHANNEL_Z));
56542542f5fSchristos			__gen8_set_src1_da16_swiz_w(inst,
56642542f5fSchristos						  BRW_GET_SWZ(reg.dw1.bits.swizzle,
56742542f5fSchristos							      BRW_CHANNEL_W));
56842542f5fSchristos
56942542f5fSchristos			/* This is an oddity of the fact that we're using the same
57042542f5fSchristos			 * descriptions for registers in both Align16 and Align1 modes.
57142542f5fSchristos			 */
57242542f5fSchristos			if (reg.vstride == BRW_VERTICAL_STRIDE_8)
57342542f5fSchristos				__gen8_set_src1_vert_stride(inst, BRW_VERTICAL_STRIDE_4);
57442542f5fSchristos			else
57542542f5fSchristos				__gen8_set_src1_vert_stride(inst, reg.vstride);
57642542f5fSchristos		}
57742542f5fSchristos	}
57842542f5fSchristos}
57942542f5fSchristos
58042542f5fSchristos/**
58142542f5fSchristos * Set the Message Descriptor and Extended Message Descriptor fields
58242542f5fSchristos * for SEND messages.
58342542f5fSchristos *
58442542f5fSchristos * \note This zeroes out the Function Control bits, so it must be called
58542542f5fSchristos *       \b before filling out any message-specific data.  Callers can
58642542f5fSchristos *       choose not to fill in irrelevant bits; they will be zero.
58742542f5fSchristos */
58842542f5fSchristosstatic void
58942542f5fSchristos__gen8_set_message_descriptor(struct gen8_instruction *inst,
59042542f5fSchristos			      enum brw_message_target sfid,
59142542f5fSchristos			      unsigned msg_length,
59242542f5fSchristos			      unsigned response_length,
59342542f5fSchristos			      bool header_present,
59442542f5fSchristos			      bool end_of_thread)
59542542f5fSchristos{
59642542f5fSchristos	__gen8_set_src1(inst, brw_imm_d(0));
59742542f5fSchristos
59842542f5fSchristos	__gen8_set_sfid(inst, sfid);
59942542f5fSchristos	__gen8_set_mlen(inst, msg_length);
60042542f5fSchristos	__gen8_set_rlen(inst, response_length);
60142542f5fSchristos	__gen8_set_header_present(inst, header_present);
60242542f5fSchristos	__gen8_set_eot(inst, end_of_thread);
60342542f5fSchristos}
60442542f5fSchristos
60542542f5fSchristos#if 0
60642542f5fSchristosstatic void
60742542f5fSchristos__gen8_set_urb_message(struct gen8_instruction *inst,
60842542f5fSchristos		       unsigned opcode,
60942542f5fSchristos		       unsigned msg_length,
61042542f5fSchristos		       unsigned response_length,
61142542f5fSchristos		       bool end_of_thread,
61242542f5fSchristos		       unsigned offset,
61342542f5fSchristos		       bool interleave)
61442542f5fSchristos{
61542542f5fSchristos	__gen8_set_message_descriptor(inst, BRW_SFID_URB, msg_length, response_length,
61642542f5fSchristos				      true, end_of_thread);
61742542f5fSchristos	__gen8_set_src0(inst, brw_vec8_grf(MRF_HACK_START + 1, 0));
61842542f5fSchristos	__gen8_set_urb_opcode(inst, 0); /* URB_WRITE_HWORD */
61942542f5fSchristos	__gen8_set_urb_global_offset(inst, offset);
62042542f5fSchristos	__gen8_set_urb_interleave(inst, interleave);
62142542f5fSchristos	/* per_slot_offset = 0 makes it ignore offsets in message header */
62242542f5fSchristos	__gen8_set_urb_per_slot_offset(inst, 0);
62342542f5fSchristos}
62442542f5fSchristos#endif
62542542f5fSchristos
62642542f5fSchristosstatic void
62742542f5fSchristos__gen8_set_sampler_message(struct gen8_instruction *inst,
62842542f5fSchristos			   unsigned binding_table_index,
62942542f5fSchristos			   unsigned sampler,
63042542f5fSchristos			   unsigned msg_type,
63142542f5fSchristos			   unsigned response_length,
63242542f5fSchristos			   unsigned msg_length,
63342542f5fSchristos			   bool header_present,
63442542f5fSchristos			   unsigned simd_mode)
63542542f5fSchristos{
63642542f5fSchristos	__gen8_set_message_descriptor(inst, BRW_SFID_SAMPLER, msg_length,
63742542f5fSchristos				      response_length, header_present, false);
63842542f5fSchristos
63942542f5fSchristos	__gen8_set_binding_table_index(inst, binding_table_index);
64042542f5fSchristos	__gen8_set_sampler(inst, sampler);
64142542f5fSchristos	__gen8_set_sampler_msg_type(inst, msg_type);
64242542f5fSchristos	__gen8_set_sampler_simd_mode(inst, simd_mode);
64342542f5fSchristos}
64442542f5fSchristos
64542542f5fSchristosstatic void
64642542f5fSchristos__gen8_set_dp_message(struct gen8_instruction *inst,
64742542f5fSchristos		      enum brw_message_target sfid,
64842542f5fSchristos		      unsigned binding_table_index,
64942542f5fSchristos		      unsigned msg_type,
65042542f5fSchristos		      unsigned msg_control,
65142542f5fSchristos		      unsigned mlen,
65242542f5fSchristos		      unsigned rlen,
65342542f5fSchristos		      bool header_present,
65442542f5fSchristos		      bool end_of_thread)
65542542f5fSchristos{
65642542f5fSchristos	/* Binding table index is from 0..255 */
65742542f5fSchristos	assert((binding_table_index & 0xff) == binding_table_index);
65842542f5fSchristos
65942542f5fSchristos	/* Message Type is only 5 bits */
66042542f5fSchristos	assert((msg_type & 0x1f) == msg_type);
66142542f5fSchristos
66242542f5fSchristos	/* Message Control is only 6 bits */
66342542f5fSchristos	assert((msg_control & 0x3f) == msg_control);
66442542f5fSchristos
66542542f5fSchristos	__gen8_set_message_descriptor(inst, sfid, mlen, rlen, header_present,
66642542f5fSchristos				      end_of_thread);
66742542f5fSchristos	__gen8_set_function_control(inst,
66842542f5fSchristos				    binding_table_index | msg_type << 14 | msg_control << 8);
66942542f5fSchristos}
67042542f5fSchristos
67142542f5fSchristosstatic inline struct gen8_instruction *
67242542f5fSchristosgen8_next_insn(struct brw_compile *p, int opcode)
67342542f5fSchristos{
67442542f5fSchristos	struct gen8_instruction *insn;
67542542f5fSchristos
67642542f5fSchristos	assert(p->nr_insn + 1 < BRW_EU_MAX_INSN);
67742542f5fSchristos
67842542f5fSchristos	insn = memcpy(&p->store[p->nr_insn++], p->current, sizeof(*insn));
67942542f5fSchristos	__gen8_set_opcode(insn, opcode);
68042542f5fSchristos
68142542f5fSchristos	return insn;
68242542f5fSchristos}
68342542f5fSchristos
68442542f5fSchristosstatic void gen8_math(struct brw_compile *p,
68542542f5fSchristos		      struct brw_reg dst,
68642542f5fSchristos		      unsigned function,
68742542f5fSchristos		      unsigned saturate,
68842542f5fSchristos		      unsigned msg_reg_nr,
68942542f5fSchristos		      struct brw_reg src,
69042542f5fSchristos		      unsigned data_type,
69142542f5fSchristos		      unsigned precision)
69242542f5fSchristos{
69342542f5fSchristos	struct gen8_instruction *insn = gen8_next_insn(p, BRW_OPCODE_MATH);
69442542f5fSchristos
69542542f5fSchristos	assert(dst.file == BRW_GENERAL_REGISTER_FILE);
69642542f5fSchristos	assert(src.file == BRW_GENERAL_REGISTER_FILE);
69742542f5fSchristos
69842542f5fSchristos	assert(dst.hstride == BRW_HORIZONTAL_STRIDE_1);
69942542f5fSchristos	assert(src.hstride == BRW_HORIZONTAL_STRIDE_1);
70042542f5fSchristos
70142542f5fSchristos	/* Source modifiers are ignored for extended math instructions. */
70242542f5fSchristos	assert(!src.negate);
70342542f5fSchristos	assert(!src.abs);
70442542f5fSchristos
70542542f5fSchristos	if (function != BRW_MATH_FUNCTION_INT_DIV_QUOTIENT &&
70642542f5fSchristos	    function != BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER) {
70742542f5fSchristos		assert(src.type == BRW_REGISTER_TYPE_F);
70842542f5fSchristos	}
70942542f5fSchristos
71042542f5fSchristos	/* Math is the same ISA format as other opcodes, except that CondModifier
71142542f5fSchristos	 * becomes FC[3:0] and ThreadCtrl becomes FC[5:4].
71242542f5fSchristos	 */
71342542f5fSchristos	__gen8_set_cond_modifier(insn, function);
71442542f5fSchristos	__gen8_set_saturate(insn, saturate);
71542542f5fSchristos
71642542f5fSchristos	__gen8_set_dst(p, insn, dst);
71742542f5fSchristos	__gen8_set_src0(insn, src);
71842542f5fSchristos	__gen8_set_src1(insn, brw_null_reg());
71942542f5fSchristos}
72042542f5fSchristos
72142542f5fSchristosstatic inline void gen8_math_invert(struct brw_compile *p,
72242542f5fSchristos				    struct brw_reg dst,
72342542f5fSchristos				    struct brw_reg src)
72442542f5fSchristos{
72542542f5fSchristos	gen8_math(p,
72642542f5fSchristos		  dst,
72742542f5fSchristos		  BRW_MATH_FUNCTION_INV,
72842542f5fSchristos		  BRW_MATH_SATURATE_NONE,
72942542f5fSchristos		  0,
73042542f5fSchristos		  src,
73142542f5fSchristos		  BRW_MATH_PRECISION_FULL,
73242542f5fSchristos		  BRW_MATH_DATA_VECTOR);
73342542f5fSchristos
73442542f5fSchristos}
73542542f5fSchristos
73642542f5fSchristos/* Helpers for regular instructions: */
73742542f5fSchristosstatic inline struct gen8_instruction *gen8_alu1(struct brw_compile *p,
73842542f5fSchristos						 unsigned opcode,
73942542f5fSchristos						 struct brw_reg dst,
74042542f5fSchristos						 struct brw_reg src)
74142542f5fSchristos{
74242542f5fSchristos	struct gen8_instruction *insn = gen8_next_insn(p, opcode);
74342542f5fSchristos	__gen8_set_dst(p, insn, dst);
74442542f5fSchristos	__gen8_set_src0(insn, src);
74542542f5fSchristos	return insn;
74642542f5fSchristos}
74742542f5fSchristos
74842542f5fSchristosstatic inline struct gen8_instruction *gen8_alu2(struct brw_compile *p,
74942542f5fSchristos						 unsigned opcode,
75042542f5fSchristos						 struct brw_reg dst,
75142542f5fSchristos						 struct brw_reg src0,
75242542f5fSchristos						 struct brw_reg src1)
75342542f5fSchristos{
75442542f5fSchristos	struct gen8_instruction *insn = gen8_next_insn(p, opcode);
75542542f5fSchristos	__gen8_set_dst(p, insn, dst);
75642542f5fSchristos	__gen8_set_src0(insn, src0);
75742542f5fSchristos	__gen8_set_src1(insn, src1);
75842542f5fSchristos	return insn;
75942542f5fSchristos}
76042542f5fSchristos
76142542f5fSchristos#define ALU1(OP)							\
76242542f5fSchristosstatic inline struct gen8_instruction *gen8_##OP(struct brw_compile *p,	\
76342542f5fSchristos						 struct brw_reg dst,	\
76442542f5fSchristos						 struct brw_reg src0)	\
76542542f5fSchristos{									\
76642542f5fSchristos   return gen8_alu1(p, BRW_OPCODE_##OP, dst, src0);			\
76742542f5fSchristos}
76842542f5fSchristos
76942542f5fSchristos#define ALU2(OP)							\
77042542f5fSchristosstatic inline struct gen8_instruction *gen8_##OP(struct brw_compile *p,	\
77142542f5fSchristos						 struct brw_reg dst,	\
77242542f5fSchristos						 struct brw_reg src0,	\
77342542f5fSchristos						 struct brw_reg src1)	\
77442542f5fSchristos{									\
77542542f5fSchristos   return gen8_alu2(p, BRW_OPCODE_##OP, dst, src0, src1);		\
77642542f5fSchristos}
77742542f5fSchristos
77842542f5fSchristosstatic inline struct gen8_instruction *gen8_ADD(struct brw_compile *p,
77942542f5fSchristos						struct brw_reg dst,
78042542f5fSchristos						struct brw_reg src0,
78142542f5fSchristos						struct brw_reg src1)
78242542f5fSchristos{
78342542f5fSchristos	/* 6.2.2: add */
78442542f5fSchristos	if (src0.type == BRW_REGISTER_TYPE_F ||
78542542f5fSchristos	    (src0.file == BRW_IMMEDIATE_VALUE &&
78642542f5fSchristos	     src0.type == BRW_REGISTER_TYPE_VF)) {
78742542f5fSchristos		assert(src1.type != BRW_REGISTER_TYPE_UD);
78842542f5fSchristos		assert(src1.type != BRW_REGISTER_TYPE_D);
78942542f5fSchristos	}
79042542f5fSchristos
79142542f5fSchristos	if (src1.type == BRW_REGISTER_TYPE_F ||
79242542f5fSchristos	    (src1.file == BRW_IMMEDIATE_VALUE &&
79342542f5fSchristos	     src1.type == BRW_REGISTER_TYPE_VF)) {
79442542f5fSchristos		assert(src0.type != BRW_REGISTER_TYPE_UD);
79542542f5fSchristos		assert(src0.type != BRW_REGISTER_TYPE_D);
79642542f5fSchristos	}
79742542f5fSchristos
79842542f5fSchristos	return gen8_alu2(p, BRW_OPCODE_ADD, dst, src0, src1);
79942542f5fSchristos}
80042542f5fSchristos
80142542f5fSchristosstatic inline struct gen8_instruction *gen8_MUL(struct brw_compile *p,
80242542f5fSchristos						struct brw_reg dst,
80342542f5fSchristos						struct brw_reg src0,
80442542f5fSchristos						struct brw_reg src1)
80542542f5fSchristos{
80642542f5fSchristos	/* 6.32.38: mul */
80742542f5fSchristos	if (src0.type == BRW_REGISTER_TYPE_D ||
80842542f5fSchristos	    src0.type == BRW_REGISTER_TYPE_UD ||
80942542f5fSchristos	    src1.type == BRW_REGISTER_TYPE_D ||
81042542f5fSchristos	    src1.type == BRW_REGISTER_TYPE_UD) {
81142542f5fSchristos		assert(dst.type != BRW_REGISTER_TYPE_F);
81242542f5fSchristos	}
81342542f5fSchristos
81442542f5fSchristos	if (src0.type == BRW_REGISTER_TYPE_F ||
81542542f5fSchristos	    (src0.file == BRW_IMMEDIATE_VALUE &&
81642542f5fSchristos	     src0.type == BRW_REGISTER_TYPE_VF)) {
81742542f5fSchristos		assert(src1.type != BRW_REGISTER_TYPE_UD);
81842542f5fSchristos		assert(src1.type != BRW_REGISTER_TYPE_D);
81942542f5fSchristos	}
82042542f5fSchristos
82142542f5fSchristos	if (src1.type == BRW_REGISTER_TYPE_F ||
82242542f5fSchristos	    (src1.file == BRW_IMMEDIATE_VALUE &&
82342542f5fSchristos	     src1.type == BRW_REGISTER_TYPE_VF)) {
82442542f5fSchristos		assert(src0.type != BRW_REGISTER_TYPE_UD);
82542542f5fSchristos		assert(src0.type != BRW_REGISTER_TYPE_D);
82642542f5fSchristos	}
82742542f5fSchristos
82842542f5fSchristos	assert(src0.file != BRW_ARCHITECTURE_REGISTER_FILE ||
82942542f5fSchristos	       src0.nr != BRW_ARF_ACCUMULATOR);
83042542f5fSchristos	assert(src1.file != BRW_ARCHITECTURE_REGISTER_FILE ||
83142542f5fSchristos	       src1.nr != BRW_ARF_ACCUMULATOR);
83242542f5fSchristos
83342542f5fSchristos	return gen8_alu2(p, BRW_OPCODE_MUL, dst, src0, src1);
83442542f5fSchristos}
83542542f5fSchristos
83642542f5fSchristosALU1(MOV);
83742542f5fSchristosALU2(SEL);
83842542f5fSchristosALU1(NOT);
83942542f5fSchristosALU2(AND);
84042542f5fSchristosALU2(OR);
84142542f5fSchristosALU2(XOR);
84242542f5fSchristosALU2(SHR);
84342542f5fSchristosALU2(SHL);
84442542f5fSchristosALU2(RSR);
84542542f5fSchristosALU2(RSL);
84642542f5fSchristosALU2(ASR);
84742542f5fSchristosALU1(FRC);
84842542f5fSchristosALU1(RNDD);
84942542f5fSchristosALU2(MAC);
85042542f5fSchristosALU2(MACH);
85142542f5fSchristosALU1(LZD);
85242542f5fSchristosALU2(DP4);
85342542f5fSchristosALU2(DPH);
85442542f5fSchristosALU2(DP3);
85542542f5fSchristosALU2(DP2);
85642542f5fSchristosALU2(LINE);
85742542f5fSchristosALU2(PLN);
85842542f5fSchristos
85942542f5fSchristosALU1(RNDZ);
86042542f5fSchristosALU1(RNDE);
86142542f5fSchristos
86242542f5fSchristos#undef ALU1
86342542f5fSchristos#undef ALU2
86442542f5fSchristos
86542542f5fSchristosstatic void gen8_set_compression_control(struct brw_compile *p,
86642542f5fSchristos					 enum brw_compression compression_control)
86742542f5fSchristos{
86842542f5fSchristos	unsigned v;
86942542f5fSchristos
87042542f5fSchristos	p->compressed = compression_control == BRW_COMPRESSION_COMPRESSED;
87142542f5fSchristos
87242542f5fSchristos	switch (compression_control) {
87342542f5fSchristos	default: assert(0);
87442542f5fSchristos	case BRW_COMPRESSION_NONE:       v = GEN6_COMPRESSION_1Q; break;
87542542f5fSchristos	case BRW_COMPRESSION_2NDHALF:    v = GEN6_COMPRESSION_2Q; break;
87642542f5fSchristos	case BRW_COMPRESSION_COMPRESSED: v = GEN6_COMPRESSION_1H; break;
87742542f5fSchristos	}
87842542f5fSchristos	__gen8_set_cmpt_control((struct gen8_instruction *)p->current, v);
87942542f5fSchristos}
88042542f5fSchristos
88142542f5fSchristosstatic inline void gen8_set_mask_control(struct brw_compile *p, unsigned value)
88242542f5fSchristos{
88342542f5fSchristos	__gen8_set_mask_control((struct gen8_instruction *)p->current, value);
88442542f5fSchristos}
88542542f5fSchristos
88642542f5fSchristosstatic inline void gen8_set_saturate(struct brw_compile *p, unsigned value)
88742542f5fSchristos{
88842542f5fSchristos	__gen8_set_saturate((struct gen8_instruction *)p->current, value);
88942542f5fSchristos}
89042542f5fSchristos
89142542f5fSchristosstatic inline void gen8_set_acc_write_control(struct brw_compile *p, unsigned value)
89242542f5fSchristos{
89342542f5fSchristos	__gen8_set_acc_wr_control((struct gen8_instruction *)p->current, value);
89442542f5fSchristos}
89542542f5fSchristos
89642542f5fSchristosstatic void gen8_SAMPLE(struct brw_compile *p,
89742542f5fSchristos			struct brw_reg dst,
89842542f5fSchristos			unsigned msg_reg_nr,
89942542f5fSchristos			unsigned binding_table_index,
90042542f5fSchristos			unsigned sampler,
90142542f5fSchristos			unsigned writemask,
90242542f5fSchristos			unsigned msg_type,
90342542f5fSchristos			unsigned response_length,
90442542f5fSchristos			unsigned msg_length,
90542542f5fSchristos			bool header_present,
90642542f5fSchristos			unsigned simd_mode)
90742542f5fSchristos{
90842542f5fSchristos	struct brw_reg src0 = brw_message_reg(msg_reg_nr);
90942542f5fSchristos
91042542f5fSchristos	assert(writemask);
91142542f5fSchristos
91242542f5fSchristos	if (writemask != WRITEMASK_XYZW) {
91342542f5fSchristos		writemask = ~writemask & WRITEMASK_XYZW;
91442542f5fSchristos
91542542f5fSchristos		brw_push_insn_state(p);
91642542f5fSchristos
91742542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_NONE);
91842542f5fSchristos		gen8_set_mask_control(p, BRW_MASK_DISABLE);
91942542f5fSchristos
92042542f5fSchristos		gen8_MOV(p, __retype_ud(src0), __retype_ud(brw_vec8_grf(0,0)));
92142542f5fSchristos		gen8_MOV(p, get_element_ud(src0, 2), brw_imm_ud(writemask << 12));
92242542f5fSchristos
92342542f5fSchristos		brw_pop_insn_state(p);
92442542f5fSchristos	}
92542542f5fSchristos
92642542f5fSchristos	{
92742542f5fSchristos		struct gen8_instruction *insn;
92842542f5fSchristos
92942542f5fSchristos		insn = gen8_next_insn(p, BRW_OPCODE_SEND);
93042542f5fSchristos		__gen8_set_pred_control(insn, 0); /* XXX */
93142542f5fSchristos		__gen8_set_cmpt_control(insn, GEN6_COMPRESSION_1Q);
93242542f5fSchristos
93342542f5fSchristos		__gen8_set_dst(p, insn, dst);
93442542f5fSchristos		__gen8_set_src0(insn, src0);
93542542f5fSchristos		__gen8_set_sampler_message(insn,
93642542f5fSchristos					   binding_table_index,
93742542f5fSchristos					   sampler,
93842542f5fSchristos					   msg_type,
93942542f5fSchristos					   response_length,
94042542f5fSchristos					   msg_length,
94142542f5fSchristos					   header_present,
94242542f5fSchristos					   simd_mode);
94342542f5fSchristos	}
94442542f5fSchristos}
94542542f5fSchristos
94642542f5fSchristos/* shader logic */
94742542f5fSchristos
94842542f5fSchristosstatic void wm_affine_st(struct brw_compile *p, int dw, int channel, int msg)
94942542f5fSchristos{
95042542f5fSchristos	int uv;
95142542f5fSchristos
95242542f5fSchristos	if (dw == 16) {
95342542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_COMPRESSED);
95442542f5fSchristos		uv = 6;
95542542f5fSchristos	} else {
95642542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_NONE);
95742542f5fSchristos		uv = 4;
95842542f5fSchristos	}
95942542f5fSchristos	uv += 2*channel;
96042542f5fSchristos
96142542f5fSchristos	msg++;
96242542f5fSchristos	gen8_PLN(p,
96342542f5fSchristos		 brw_message_reg(msg),
96442542f5fSchristos		 brw_vec1_grf(uv, 0),
96542542f5fSchristos		 brw_vec8_grf(2, 0));
96642542f5fSchristos	msg += dw/8;
96742542f5fSchristos
96842542f5fSchristos	gen8_PLN(p,
96942542f5fSchristos		 brw_message_reg(msg),
97042542f5fSchristos		 brw_vec1_grf(uv, 4),
97142542f5fSchristos		 brw_vec8_grf(2, 0));
97242542f5fSchristos}
97342542f5fSchristos
97442542f5fSchristosstatic inline unsigned simd(int dw)
97542542f5fSchristos{
97642542f5fSchristos	return dw == 16 ? BRW_SAMPLER_SIMD_MODE_SIMD16 : BRW_SAMPLER_SIMD_MODE_SIMD8;
97742542f5fSchristos}
97842542f5fSchristos
97942542f5fSchristosstatic inline struct brw_reg sample_result(int dw, int result)
98042542f5fSchristos{
98142542f5fSchristos	return brw_reg(BRW_GENERAL_REGISTER_FILE, result, 0,
98242542f5fSchristos		       BRW_REGISTER_TYPE_UW,
98342542f5fSchristos		       dw == 16 ? BRW_VERTICAL_STRIDE_16 : BRW_VERTICAL_STRIDE_8,
98442542f5fSchristos		       dw == 16 ? BRW_WIDTH_16 : BRW_WIDTH_8,
98542542f5fSchristos		       BRW_HORIZONTAL_STRIDE_1,
98642542f5fSchristos		       BRW_SWIZZLE_XYZW,
98742542f5fSchristos		       WRITEMASK_XYZW);
98842542f5fSchristos}
98942542f5fSchristos
99042542f5fSchristosstatic int wm_sample(struct brw_compile *p, int dw,
99142542f5fSchristos		     int channel, int msg, int result)
99242542f5fSchristos{
99342542f5fSchristos	int len = dw == 16 ? 4 : 2;
99442542f5fSchristos	gen8_SAMPLE(p, sample_result(dw, result), ++msg,
99542542f5fSchristos		    channel+1, channel, WRITEMASK_XYZW, 0,
99642542f5fSchristos		    2*len, len, false, simd(dw));
99742542f5fSchristos	return result;
99842542f5fSchristos}
99942542f5fSchristos
100042542f5fSchristosstatic int wm_sample__alpha(struct brw_compile *p, int dw,
100142542f5fSchristos			    int channel, int msg, int result)
100242542f5fSchristos{
100342542f5fSchristos	int mlen, rlen;
100442542f5fSchristos
100542542f5fSchristos	if (dw == 8) {
100642542f5fSchristos		mlen = 3;
100742542f5fSchristos		rlen = 1;
100842542f5fSchristos	} else {
100942542f5fSchristos		mlen = 5;
101042542f5fSchristos		rlen = 2;
101142542f5fSchristos	}
101242542f5fSchristos
101342542f5fSchristos	gen8_SAMPLE(p, sample_result(dw, result), msg,
101442542f5fSchristos		    channel+1, channel, WRITEMASK_W, 0,
101542542f5fSchristos		    rlen, mlen, true, simd(dw));
101642542f5fSchristos
101742542f5fSchristos	return result;
101842542f5fSchristos}
101942542f5fSchristos
102042542f5fSchristosstatic int wm_affine(struct brw_compile *p, int dw,
102142542f5fSchristos		     int channel, int msg, int result)
102242542f5fSchristos{
102342542f5fSchristos	wm_affine_st(p, dw, channel, msg);
102442542f5fSchristos	return wm_sample(p, dw, channel, msg, result);
102542542f5fSchristos}
102642542f5fSchristos
102742542f5fSchristosstatic int wm_affine__alpha(struct brw_compile *p, int dw,
102842542f5fSchristos			    int channel, int msg, int result)
102942542f5fSchristos{
103042542f5fSchristos	wm_affine_st(p, dw, channel, msg);
103142542f5fSchristos	return wm_sample__alpha(p, dw, channel, msg, result);
103242542f5fSchristos}
103342542f5fSchristos
103442542f5fSchristosstatic inline struct brw_reg null_result(int dw)
103542542f5fSchristos{
103642542f5fSchristos	return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0,
103742542f5fSchristos		       BRW_REGISTER_TYPE_UW,
103842542f5fSchristos		       dw == 16 ? BRW_VERTICAL_STRIDE_16 : BRW_VERTICAL_STRIDE_8,
103942542f5fSchristos		       dw == 16 ? BRW_WIDTH_16 : BRW_WIDTH_8,
104042542f5fSchristos		       BRW_HORIZONTAL_STRIDE_1,
104142542f5fSchristos		       BRW_SWIZZLE_XYZW,
104242542f5fSchristos		       WRITEMASK_XYZW);
104342542f5fSchristos}
104442542f5fSchristos
104542542f5fSchristosstatic void fb_write(struct brw_compile *p, int dw)
104642542f5fSchristos{
104742542f5fSchristos	struct gen8_instruction *insn;
104842542f5fSchristos	unsigned msg_control, msg_len;
104942542f5fSchristos	struct brw_reg src0;
105042542f5fSchristos
105142542f5fSchristos	if (dw == 16) {
105242542f5fSchristos		msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE;
105342542f5fSchristos		msg_len = 8;
105442542f5fSchristos	} else {
105542542f5fSchristos		msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01;
105642542f5fSchristos		msg_len = 4;
105742542f5fSchristos	}
105842542f5fSchristos	msg_control |= 1 << 4; /* Last Render Target */
105942542f5fSchristos
106042542f5fSchristos	/* The execution mask is ignored for render target writes. */
106142542f5fSchristos	insn = gen8_next_insn(p, BRW_OPCODE_SEND);
106242542f5fSchristos	__gen8_set_pred_control(insn, 0);
106342542f5fSchristos	__gen8_set_cmpt_control(insn, GEN6_COMPRESSION_1Q);
106442542f5fSchristos
106542542f5fSchristos	src0 = brw_message_reg(2);
106642542f5fSchristos
106742542f5fSchristos	__gen8_set_dst(p, insn, null_result(dw));
106842542f5fSchristos	__gen8_set_src0(insn, src0);
106942542f5fSchristos	__gen8_set_dp_message(insn,
107042542f5fSchristos			      GEN6_SFID_DATAPORT_RENDER_CACHE,
107142542f5fSchristos			      0,
107242542f5fSchristos			      GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE,
107342542f5fSchristos			      msg_control,
107442542f5fSchristos			      msg_len, 0,
107542542f5fSchristos			      false, true);
107642542f5fSchristos}
107742542f5fSchristos
107842542f5fSchristosstatic void wm_write__mask(struct brw_compile *p, int dw,
107942542f5fSchristos			   int src, int mask)
108042542f5fSchristos{
108142542f5fSchristos	int n;
108242542f5fSchristos
108342542f5fSchristos	if (dw == 8) {
108442542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_NONE);
108542542f5fSchristos		for (n = 0; n < 4; n++)
108642542f5fSchristos			gen8_MUL(p,
108742542f5fSchristos				 brw_message_reg(2 + n),
108842542f5fSchristos				 brw_vec8_grf(src + n, 0),
108942542f5fSchristos				 brw_vec8_grf(mask, 0));
109042542f5fSchristos	} else {
109142542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_COMPRESSED);
109242542f5fSchristos		for (n = 0; n < 4; n++)
109342542f5fSchristos			gen8_MUL(p,
109442542f5fSchristos				 brw_message_reg(2 + 2*n),
109542542f5fSchristos				 brw_vec8_grf(src + 2*n, 0),
109642542f5fSchristos				 brw_vec8_grf(mask, 0));
109742542f5fSchristos	}
109842542f5fSchristos
109942542f5fSchristos	fb_write(p, dw);
110042542f5fSchristos}
110142542f5fSchristos
110242542f5fSchristosstatic void wm_write__opacity(struct brw_compile *p, int dw, int src, int mask)
110342542f5fSchristos{
110442542f5fSchristos	int n;
110542542f5fSchristos
110642542f5fSchristos	if (dw == 8) {
110742542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_NONE);
110842542f5fSchristos		for (n = 0; n < 4; n++)
110942542f5fSchristos			gen8_MUL(p,
111042542f5fSchristos				 brw_message_reg(2 + n),
111142542f5fSchristos				 brw_vec8_grf(src + n, 0),
111242542f5fSchristos				 brw_vec1_grf(mask, 3));
111342542f5fSchristos	} else {
111442542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_COMPRESSED);
111542542f5fSchristos		for (n = 0; n < 4; n++)
111642542f5fSchristos			gen8_MUL(p,
111742542f5fSchristos				 brw_message_reg(2 + 2*n),
111842542f5fSchristos				 brw_vec8_grf(src + 2*n, 0),
111942542f5fSchristos				 brw_vec1_grf(mask, 3));
112042542f5fSchristos	}
112142542f5fSchristos
112242542f5fSchristos	fb_write(p, dw);
112342542f5fSchristos}
112442542f5fSchristos
112542542f5fSchristosstatic void wm_write__mask_ca(struct brw_compile *p, int dw,
112642542f5fSchristos			      int src, int mask)
112742542f5fSchristos{
112842542f5fSchristos	int n;
112942542f5fSchristos
113042542f5fSchristos	if (dw == 8) {
113142542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_NONE);
113242542f5fSchristos		for (n = 0; n < 4; n++)
113342542f5fSchristos			gen8_MUL(p,
113442542f5fSchristos				 brw_message_reg(2 + n),
113542542f5fSchristos				 brw_vec8_grf(src + n, 0),
113642542f5fSchristos				 brw_vec8_grf(mask + n, 0));
113742542f5fSchristos	} else {
113842542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_COMPRESSED);
113942542f5fSchristos		for (n = 0; n < 4; n++)
114042542f5fSchristos			gen8_MUL(p,
114142542f5fSchristos				 brw_message_reg(2 + 2*n),
114242542f5fSchristos				 brw_vec8_grf(src + 2*n, 0),
114342542f5fSchristos				 brw_vec8_grf(mask + 2*n, 0));
114442542f5fSchristos	}
114542542f5fSchristos
114642542f5fSchristos	fb_write(p, dw);
114742542f5fSchristos}
114842542f5fSchristos
114942542f5fSchristosstatic void gen8_compile_init(struct brw_compile *p)
115042542f5fSchristos{
115142542f5fSchristos	struct gen8_instruction *insn = memset(p->current, 0, sizeof(*insn));
115242542f5fSchristos	COMPILE_TIME_ASSERT(sizeof(*insn) == sizeof(*p->current));
115342542f5fSchristos	__gen8_set_mask_control(insn, BRW_MASK_ENABLE);
115442542f5fSchristos	__gen8_set_saturate(insn, 0);
115542542f5fSchristos	__gen8_set_cmpt_control(insn, GEN6_COMPRESSION_1Q);
115642542f5fSchristos	//__gen8_set_pred_control(insn, 0xf);
115742542f5fSchristos}
115842542f5fSchristos
115942542f5fSchristosbool
116042542f5fSchristosgen8_wm_kernel__affine(struct brw_compile *p, int dispatch)
116142542f5fSchristos{
116242542f5fSchristos	gen8_compile_init(p);
116342542f5fSchristos
116413496ba1Ssnj	wm_affine(p, dispatch, 0, 10, MRF_HACK_START+2);
116513496ba1Ssnj	fb_write(p, dispatch);
116642542f5fSchristos	return true;
116742542f5fSchristos}
116842542f5fSchristos
116942542f5fSchristosbool
117042542f5fSchristosgen8_wm_kernel__affine_mask(struct brw_compile *p, int dispatch)
117142542f5fSchristos{
117242542f5fSchristos	int src, mask;
117342542f5fSchristos
117442542f5fSchristos	gen8_compile_init(p);
117542542f5fSchristos
117642542f5fSchristos	src = wm_affine(p, dispatch, 0, 1, 12);
117742542f5fSchristos	mask = wm_affine__alpha(p, dispatch, 1, 6, 20);
117842542f5fSchristos	wm_write__mask(p, dispatch, src, mask);
117942542f5fSchristos
118042542f5fSchristos	return true;
118142542f5fSchristos}
118242542f5fSchristos
118342542f5fSchristosbool
118442542f5fSchristosgen8_wm_kernel__affine_mask_ca(struct brw_compile *p, int dispatch)
118542542f5fSchristos{
118642542f5fSchristos	int src, mask;
118742542f5fSchristos
118842542f5fSchristos	gen8_compile_init(p);
118942542f5fSchristos
119042542f5fSchristos	src = wm_affine(p, dispatch, 0, 1, 12);
119142542f5fSchristos	mask = wm_affine(p, dispatch, 1, 6, 20);
119242542f5fSchristos	wm_write__mask_ca(p, dispatch, src, mask);
119342542f5fSchristos
119442542f5fSchristos	return true;
119542542f5fSchristos}
119642542f5fSchristos
119742542f5fSchristosbool
119842542f5fSchristosgen8_wm_kernel__affine_mask_sa(struct brw_compile *p, int dispatch)
119942542f5fSchristos{
120042542f5fSchristos	int src, mask;
120142542f5fSchristos
120242542f5fSchristos	gen8_compile_init(p);
120342542f5fSchristos
120442542f5fSchristos	src = wm_affine__alpha(p, dispatch, 0, 1, 12);
120542542f5fSchristos	mask = wm_affine(p, dispatch, 1, 6, 16);
120642542f5fSchristos	wm_write__mask(p, dispatch, mask, src);
120742542f5fSchristos
120842542f5fSchristos	return true;
120942542f5fSchristos}
121042542f5fSchristos
121142542f5fSchristos/* Projective variants */
121242542f5fSchristos
121342542f5fSchristosstatic void wm_projective_st(struct brw_compile *p, int dw,
121442542f5fSchristos			     int channel, int msg)
121542542f5fSchristos{
121642542f5fSchristos	int uv;
121742542f5fSchristos
121842542f5fSchristos	gen8_compile_init(p);
121942542f5fSchristos
122042542f5fSchristos	if (dw == 16) {
122142542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_COMPRESSED);
122242542f5fSchristos		uv = 6;
122342542f5fSchristos	} else {
122442542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_NONE);
122542542f5fSchristos		uv = 4;
122642542f5fSchristos	}
122742542f5fSchristos	uv += 2*channel;
122842542f5fSchristos
122942542f5fSchristos	msg++;
123042542f5fSchristos	/* First compute 1/z */
123142542f5fSchristos	gen8_PLN(p,
123242542f5fSchristos		 brw_vec8_grf(30, 0),
123342542f5fSchristos		 brw_vec1_grf(uv+1, 0),
123442542f5fSchristos		 brw_vec8_grf(2, 0));
123542542f5fSchristos
123642542f5fSchristos	if (dw == 16) {
123742542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_NONE);
123842542f5fSchristos		gen8_math_invert(p, brw_vec8_grf(30, 0), brw_vec8_grf(30, 0));
123942542f5fSchristos		gen8_math_invert(p, brw_vec8_grf(31, 0), brw_vec8_grf(31, 0));
124042542f5fSchristos		gen8_set_compression_control(p, BRW_COMPRESSION_COMPRESSED);
124142542f5fSchristos	} else
124242542f5fSchristos		gen8_math_invert(p, brw_vec8_grf(30, 0), brw_vec8_grf(30, 0));
124342542f5fSchristos
124442542f5fSchristos	gen8_PLN(p,
124542542f5fSchristos		 brw_vec8_grf(26, 0),
124642542f5fSchristos		 brw_vec1_grf(uv, 0),
124742542f5fSchristos		 brw_vec8_grf(2, 0));
124842542f5fSchristos	gen8_PLN(p,
124942542f5fSchristos		 brw_vec8_grf(28, 0),
125013496ba1Ssnj		 brw_vec1_grf(uv, 4),
125113496ba1Ssnj		 brw_vec8_grf(2, 0));
125242542f5fSchristos
125342542f5fSchristos	gen8_MUL(p,
125442542f5fSchristos		 brw_message_reg(msg),
125542542f5fSchristos		 brw_vec8_grf(26, 0),
125642542f5fSchristos		 brw_vec8_grf(30, 0));
125742542f5fSchristos	gen8_MUL(p,
125842542f5fSchristos		 brw_message_reg(msg + dw/8),
125942542f5fSchristos		 brw_vec8_grf(28, 0),
126042542f5fSchristos		 brw_vec8_grf(30, 0));
126142542f5fSchristos}
126242542f5fSchristos
126342542f5fSchristosstatic int wm_projective(struct brw_compile *p, int dw,
126442542f5fSchristos			 int channel, int msg, int result)
126542542f5fSchristos{
126642542f5fSchristos	gen8_compile_init(p);
126742542f5fSchristos
126842542f5fSchristos	wm_projective_st(p, dw, channel, msg);
126942542f5fSchristos	return wm_sample(p, dw, channel, msg, result);
127042542f5fSchristos}
127142542f5fSchristos
127242542f5fSchristosstatic int wm_projective__alpha(struct brw_compile *p, int dw,
127342542f5fSchristos				int channel, int msg, int result)
127442542f5fSchristos{
127542542f5fSchristos	gen8_compile_init(p);
127642542f5fSchristos
127742542f5fSchristos	wm_projective_st(p, dw, channel, msg);
127842542f5fSchristos	return wm_sample__alpha(p, dw, channel, msg, result);
127942542f5fSchristos}
128042542f5fSchristos
128142542f5fSchristosbool
128242542f5fSchristosgen8_wm_kernel__projective(struct brw_compile *p, int dispatch)
128342542f5fSchristos{
128442542f5fSchristos	gen8_compile_init(p);
128542542f5fSchristos
128613496ba1Ssnj	wm_projective(p, dispatch, 0, 10, MRF_HACK_START+2);
128713496ba1Ssnj	fb_write(p, dispatch);
128842542f5fSchristos	return true;
128942542f5fSchristos}
129042542f5fSchristos
129142542f5fSchristosbool
129242542f5fSchristosgen8_wm_kernel__projective_mask(struct brw_compile *p, int dispatch)
129342542f5fSchristos{
129442542f5fSchristos	int src, mask;
129542542f5fSchristos
129642542f5fSchristos	gen8_compile_init(p);
129742542f5fSchristos
129842542f5fSchristos	src = wm_projective(p, dispatch, 0, 1, 12);
129942542f5fSchristos	mask = wm_projective__alpha(p, dispatch, 1, 6, 20);
130042542f5fSchristos	wm_write__mask(p, dispatch, src, mask);
130142542f5fSchristos
130242542f5fSchristos	return true;
130342542f5fSchristos}
130442542f5fSchristos
130542542f5fSchristosbool
130642542f5fSchristosgen8_wm_kernel__projective_mask_ca(struct brw_compile *p, int dispatch)
130742542f5fSchristos{
130842542f5fSchristos	int src, mask;
130942542f5fSchristos
131042542f5fSchristos	gen8_compile_init(p);
131142542f5fSchristos
131242542f5fSchristos	src = wm_projective(p, dispatch, 0, 1, 12);
131342542f5fSchristos	mask = wm_projective(p, dispatch, 1, 6, 20);
131442542f5fSchristos	wm_write__mask_ca(p, dispatch, src, mask);
131542542f5fSchristos
131642542f5fSchristos	return true;
131742542f5fSchristos}
131842542f5fSchristos
131942542f5fSchristosbool
132042542f5fSchristosgen8_wm_kernel__projective_mask_sa(struct brw_compile *p, int dispatch)
132142542f5fSchristos{
132242542f5fSchristos	int src, mask;
132342542f5fSchristos
132442542f5fSchristos	gen8_compile_init(p);
132542542f5fSchristos
132642542f5fSchristos	src = wm_projective__alpha(p, dispatch, 0, 1, 12);
132742542f5fSchristos	mask = wm_projective(p, dispatch, 1, 6, 16);
132842542f5fSchristos	wm_write__mask(p, dispatch, mask, src);
132942542f5fSchristos
133042542f5fSchristos	return true;
133142542f5fSchristos}
133242542f5fSchristos
133342542f5fSchristosbool
133442542f5fSchristosgen8_wm_kernel__affine_opacity(struct brw_compile *p, int dispatch)
133542542f5fSchristos{
133642542f5fSchristos	int src, mask;
133742542f5fSchristos
133842542f5fSchristos	gen8_compile_init(p);
133942542f5fSchristos
134042542f5fSchristos	src = wm_affine(p, dispatch, 0, 1, 12);
134142542f5fSchristos	mask = dispatch == 16 ? 8 : 6;
134242542f5fSchristos	wm_write__opacity(p, dispatch, src, mask);
134342542f5fSchristos
134442542f5fSchristos	return true;
134542542f5fSchristos}
134642542f5fSchristos
134742542f5fSchristosbool
134842542f5fSchristosgen8_wm_kernel__projective_opacity(struct brw_compile *p, int dispatch)
134942542f5fSchristos{
135042542f5fSchristos	int src, mask;
135142542f5fSchristos
135242542f5fSchristos	gen8_compile_init(p);
135342542f5fSchristos
135442542f5fSchristos	mask = dispatch == 16 ? 8 : 6;
135542542f5fSchristos	src = wm_projective(p, dispatch, 0, 1, 12);
135642542f5fSchristos	wm_write__opacity(p, dispatch, src, mask);
135742542f5fSchristos
135842542f5fSchristos	return true;
135942542f5fSchristos}
1360