2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial
16 portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **********************************************************************/
28 #include "backend/gen8_encoder.hpp"
30 static const uint32_t untypedRWMask[] = {
31 GEN_UNTYPED_ALPHA|GEN_UNTYPED_BLUE|GEN_UNTYPED_GREEN|GEN_UNTYPED_RED,
32 GEN_UNTYPED_ALPHA|GEN_UNTYPED_BLUE|GEN_UNTYPED_GREEN,
33 GEN_UNTYPED_ALPHA|GEN_UNTYPED_BLUE,
40 void Gen8Encoder::setHeader(GenNativeInstruction *insn) {
41 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
42 if (this->curr.execWidth == 8)
43 gen8_insn->header.execution_size = GEN_WIDTH_8;
44 else if (this->curr.execWidth == 16)
45 gen8_insn->header.execution_size = GEN_WIDTH_16;
46 else if (this->curr.execWidth == 1)
47 gen8_insn->header.execution_size = GEN_WIDTH_1;
48 else if (this->curr.execWidth == 4)
49 gen8_insn->header.execution_size = GEN_WIDTH_4;
52 gen8_insn->header.acc_wr_control = this->curr.accWrEnable;
53 gen8_insn->header.quarter_control = this->curr.quarterControl;
54 gen8_insn->header.nib_ctrl = this->curr.nibControl;
55 gen8_insn->bits1.ia1.mask_control = this->curr.noMask;
56 gen8_insn->bits1.ia1.flag_reg_nr = this->curr.flag;
57 gen8_insn->bits1.ia1.flag_sub_reg_nr = this->curr.subFlag;
58 if (this->curr.predicate != GEN_PREDICATE_NONE) {
59 gen8_insn->header.predicate_control = this->curr.predicate;
60 gen8_insn->header.predicate_inverse = this->curr.inversePredicate;
62 gen8_insn->header.saturate = this->curr.saturate;
65 void Gen8Encoder::setDPUntypedRW(GenNativeInstruction *insn,
70 uint32_t response_length)
72 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
73 const GenMessageTarget sfid = GEN_SFID_DATAPORT1_DATA;
74 setMessageDescriptor(insn, sfid, msg_length, response_length);
75 gen8_insn->bits3.gen7_untyped_rw.msg_type = msg_type;
76 gen8_insn->bits3.gen7_untyped_rw.bti = bti;
77 gen8_insn->bits3.gen7_untyped_rw.rgba = rgba;
78 if (curr.execWidth == 8)
79 gen8_insn->bits3.gen7_untyped_rw.simd_mode = GEN_UNTYPED_SIMD8;
80 else if (curr.execWidth == 16)
81 gen8_insn->bits3.gen7_untyped_rw.simd_mode = GEN_UNTYPED_SIMD16;
86 void Gen8Encoder::setTypedWriteMessage(GenNativeInstruction *insn, unsigned char bti,
87 unsigned char msg_type, uint32_t msg_length, bool header_present)
89 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
90 const GenMessageTarget sfid = GEN_SFID_DATAPORT1_DATA;
91 setMessageDescriptor(insn, sfid, msg_length, 0, header_present);
92 gen8_insn->bits3.gen7_typed_rw.bti = bti;
93 gen8_insn->bits3.gen7_typed_rw.msg_type = msg_type;
95 /* Always using the low 8 slots here. */
96 gen8_insn->bits3.gen7_typed_rw.slot = 1;
99 void Gen8Encoder::ATOMIC(GenRegister dst, uint32_t function, GenRegister src, uint32_t bti, uint32_t srcNum) {
100 GenNativeInstruction *insn = this->next(GEN_OPCODE_SEND);
101 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
102 uint32_t msg_length = 0;
103 uint32_t response_length = 0;
105 if (this->curr.execWidth == 8) {
108 } else if (this->curr.execWidth == 16) {
109 msg_length = 2 * srcNum;
114 this->setHeader(insn);
115 this->setDst(insn, GenRegister::uw16grf(dst.nr, 0));
116 this->setSrc0(insn, GenRegister::ud8grf(src.nr, 0));
117 this->setSrc1(insn, GenRegister::immud(0));
119 const GenMessageTarget sfid = GEN_SFID_DATAPORT1_DATA;
120 setMessageDescriptor(insn, sfid, msg_length, response_length);
121 gen8_insn->bits3.gen7_atomic_op.msg_type = GEN75_P1_UNTYPED_ATOMIC_OP;
122 gen8_insn->bits3.gen7_atomic_op.bti = bti;
123 gen8_insn->bits3.gen7_atomic_op.return_data = 1;
124 gen8_insn->bits3.gen7_atomic_op.aop_type = function;
126 if (this->curr.execWidth == 8)
127 gen8_insn->bits3.gen7_atomic_op.simd_mode = GEN_ATOMIC_SIMD8;
128 else if (this->curr.execWidth == 16)
129 gen8_insn->bits3.gen7_atomic_op.simd_mode = GEN_ATOMIC_SIMD16;
134 void Gen8Encoder::UNTYPED_READ(GenRegister dst, GenRegister src, uint32_t bti, uint32_t elemNum) {
135 GenNativeInstruction *insn = this->next(GEN_OPCODE_SEND);
136 assert(elemNum >= 1 || elemNum <= 4);
137 uint32_t msg_length = 0;
138 uint32_t response_length = 0;
139 if (this->curr.execWidth == 8) {
141 response_length = elemNum;
142 } else if (this->curr.execWidth == 16) {
144 response_length = 2 * elemNum;
148 this->setHeader(insn);
149 this->setDst(insn, GenRegister::uw16grf(dst.nr, 0));
150 this->setSrc0(insn, GenRegister::ud8grf(src.nr, 0));
151 this->setSrc1(insn, GenRegister::immud(0));
154 untypedRWMask[elemNum],
155 GEN75_P1_UNTYPED_READ,
160 void Gen8Encoder::UNTYPED_WRITE(GenRegister msg, uint32_t bti, uint32_t elemNum) {
161 GenNativeInstruction *insn = this->next(GEN_OPCODE_SEND);
162 assert(elemNum >= 1 || elemNum <= 4);
163 uint32_t msg_length = 0;
164 uint32_t response_length = 0;
165 this->setHeader(insn);
166 if (this->curr.execWidth == 8) {
167 this->setDst(insn, GenRegister::retype(GenRegister::null(), GEN_TYPE_UD));
168 msg_length = 1 + elemNum;
169 } else if (this->curr.execWidth == 16) {
170 this->setDst(insn, GenRegister::retype(GenRegister::null(), GEN_TYPE_UW));
171 msg_length = 2 * (1 + elemNum);
175 this->setSrc0(insn, GenRegister::ud8grf(msg.nr, 0));
176 this->setSrc1(insn, GenRegister::immud(0));
179 untypedRWMask[elemNum],
180 GEN75_P1_UNTYPED_SURFACE_WRITE,
185 void Gen8Encoder::LOAD_DF_IMM(GenRegister dest, GenRegister tmp, double value) {
186 union { double d; unsigned u[2]; } u;
188 GenRegister r = GenRegister::retype(tmp, GEN_TYPE_UD);
190 curr.predicate = GEN_PREDICATE_NONE;
193 MOV(r, GenRegister::immud(u.u[0]));
194 MOV(GenRegister::suboffset(r, 1), GenRegister::immud(u.u[1]));
196 r.type = GEN_TYPE_DF;
197 r.vstride = GEN_VERTICAL_STRIDE_0;
198 r.width = GEN_WIDTH_1;
199 r.hstride = GEN_HORIZONTAL_STRIDE_0;
201 uint32_t width = curr.execWidth;
203 curr.predicate = GEN_PREDICATE_NONE;
205 curr.quarterControl = GEN_COMPRESSION_Q1;
208 curr.quarterControl = GEN_COMPRESSION_Q2;
209 MOV(GenRegister::offset(dest, 2), r);
214 void Gen8Encoder::MOV_DF(GenRegister dest, GenRegister src0, GenRegister r) {
215 GBE_ASSERT((src0.type == GEN_TYPE_F && dest.isdf()) || (src0.isdf() && dest.type == GEN_TYPE_F));
216 int w = curr.execWidth;
218 r0 = GenRegister::h2(r);
221 curr.predicate = GEN_PREDICATE_NONE;
224 MOV(GenRegister::suboffset(r0, 4), GenRegister::suboffset(src0, 4));
226 curr.quarterControl = 0;
230 MOV(GenRegister::suboffset(dest, 4), GenRegister::suboffset(r0, 4));
235 curr.predicate = GEN_PREDICATE_NONE;
237 MOV(r0, GenRegister::suboffset(src0, 8));
238 MOV(GenRegister::suboffset(r0, 4), GenRegister::suboffset(src0, 12));
240 curr.quarterControl = 1;
242 MOV(GenRegister::suboffset(dest, 8), r0);
244 MOV(GenRegister::suboffset(dest, 12), GenRegister::suboffset(r0, 4));
249 void Gen8Encoder::JMPI(GenRegister src, bool longjmp) {
250 alu2(this, GEN_OPCODE_JMPI, GenRegister::ip(), GenRegister::ip(), src);
253 void Gen8Encoder::patchJMPI(uint32_t insnID, int32_t jip, int32_t uip) {
254 GenNativeInstruction &insn = *(GenNativeInstruction *)&this->store[insnID];
255 GBE_ASSERT(insnID < this->store.size());
256 GBE_ASSERT(insn.header.opcode == GEN_OPCODE_JMPI ||
257 insn.header.opcode == GEN_OPCODE_BRD ||
258 insn.header.opcode == GEN_OPCODE_ENDIF ||
259 insn.header.opcode == GEN_OPCODE_IF ||
260 insn.header.opcode == GEN_OPCODE_BRC ||
261 insn.header.opcode == GEN_OPCODE_WHILE ||
262 insn.header.opcode == GEN_OPCODE_ELSE);
264 if( insn.header.opcode == GEN_OPCODE_WHILE ) {
265 // if this WHILE instruction jump back to an ELSE instruction,
266 // need add distance to go to the next instruction.
267 GenNativeInstruction & insn_else = *(GenNativeInstruction *)&this->store[insnID+jip];
268 if(insn_else.header.opcode == GEN_OPCODE_ELSE) {
273 if(insn.header.opcode == GEN_OPCODE_ELSE)
276 if (insn.header.opcode == GEN_OPCODE_IF ||
277 insn.header.opcode == GEN_OPCODE_ELSE) {
278 Gen8NativeInstruction *gen8_insn = &insn.gen8_insn;
279 this->setSrc0(&insn, GenRegister::immud(0));
280 gen8_insn->bits2.gen8_branch.uip = uip*8;
281 gen8_insn->bits3.gen8_branch.jip = jip*8;
284 else if (insn.header.opcode == GEN_OPCODE_JMPI) {
285 //jumpDistance'unit is Qword, and the HSW's offset of jmpi is in byte, so multi 8
289 this->setSrc1(&insn, GenRegister::immd(jip*8));
292 void Gen8Encoder::setDst(GenNativeInstruction *insn, GenRegister dest) {
293 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
294 if (dest.file != GEN_ARCHITECTURE_REGISTER_FILE)
295 assert(dest.nr < 128);
297 gen8_insn->bits1.da1.dest_reg_file = dest.file;
298 gen8_insn->bits1.da1.dest_reg_type = dest.type;
299 gen8_insn->bits1.da1.dest_address_mode = dest.address_mode;
300 gen8_insn->bits1.da1.dest_reg_nr = dest.nr;
301 gen8_insn->bits1.da1.dest_subreg_nr = dest.subnr;
302 if (dest.hstride == GEN_HORIZONTAL_STRIDE_0) {
303 if (dest.type == GEN_TYPE_UB || dest.type == GEN_TYPE_B)
304 dest.hstride = GEN_HORIZONTAL_STRIDE_4;
305 else if (dest.type == GEN_TYPE_UW || dest.type == GEN_TYPE_W)
306 dest.hstride = GEN_HORIZONTAL_STRIDE_2;
308 dest.hstride = GEN_HORIZONTAL_STRIDE_1;
310 gen8_insn->bits1.da1.dest_horiz_stride = dest.hstride;
313 void Gen8Encoder::setSrc0(GenNativeInstruction *insn, GenRegister reg) {
314 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
315 if (reg.file != GEN_ARCHITECTURE_REGISTER_FILE)
316 assert(reg.nr < 128);
318 if (reg.address_mode == GEN_ADDRESS_DIRECT) {
319 gen8_insn->bits1.da1.src0_reg_file = reg.file;
320 gen8_insn->bits1.da1.src0_reg_type = reg.type;
321 gen8_insn->bits2.da1.src0_abs = reg.absolute;
322 gen8_insn->bits2.da1.src0_negate = reg.negation;
323 gen8_insn->bits2.da1.src0_address_mode = reg.address_mode;
324 if (reg.file == GEN_IMMEDIATE_VALUE) {
325 gen8_insn->bits3.ud = reg.value.ud;
327 /* Required to set some fields in src1 as well: */
328 gen8_insn->bits2.da1.src1_reg_file = 0; /* arf */
329 gen8_insn->bits2.da1.src1_reg_type = reg.type;
332 if (gen8_insn->header.access_mode == GEN_ALIGN_1) {
333 gen8_insn->bits2.da1.src0_subreg_nr = reg.subnr;
334 gen8_insn->bits2.da1.src0_reg_nr = reg.nr;
336 gen8_insn->bits2.da16.src0_subreg_nr = reg.subnr / 16;
337 gen8_insn->bits2.da16.src0_reg_nr = reg.nr;
340 if (reg.width == GEN_WIDTH_1 &&
341 gen8_insn->header.execution_size == GEN_WIDTH_1) {
342 gen8_insn->bits2.da1.src0_horiz_stride = GEN_HORIZONTAL_STRIDE_0;
343 gen8_insn->bits2.da1.src0_width = GEN_WIDTH_1;
344 gen8_insn->bits2.da1.src0_vert_stride = GEN_VERTICAL_STRIDE_0;
347 gen8_insn->bits2.da1.src0_horiz_stride = reg.hstride;
348 gen8_insn->bits2.da1.src0_width = reg.width;
349 gen8_insn->bits2.da1.src0_vert_stride = reg.vstride;
353 gen8_insn->bits1.ia1.src0_reg_file = GEN_GENERAL_REGISTER_FILE;
354 gen8_insn->bits1.ia1.src0_reg_type = reg.type;
355 gen8_insn->bits2.ia1.src0_subreg_nr = 0;
356 gen8_insn->bits2.ia1.src0_indirect_offset = 0;
357 gen8_insn->bits2.ia1.src0_abs = 0;
358 gen8_insn->bits2.ia1.src0_negate = 0;
359 gen8_insn->bits2.ia1.src0_address_mode = reg.address_mode;
360 gen8_insn->bits2.ia1.src0_horiz_stride = GEN_HORIZONTAL_STRIDE_0;
361 gen8_insn->bits2.ia1.src0_width = GEN_WIDTH_1;
362 gen8_insn->bits2.ia1.src0_vert_stride = GEN_VERTICAL_STRIDE_ONE_DIMENSIONAL;
366 void Gen8Encoder::setSrc1(GenNativeInstruction *insn, GenRegister reg) {
367 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
368 assert(reg.nr < 128);
369 assert(reg.file != GEN_ARCHITECTURE_REGISTER_FILE || reg.nr == 0);
371 gen8_insn->bits2.da1.src1_reg_file = reg.file;
372 gen8_insn->bits2.da1.src1_reg_type = reg.type;
373 gen8_insn->bits3.da1.src1_abs = reg.absolute;
374 gen8_insn->bits3.da1.src1_negate = reg.negation;
376 assert(gen8_insn->bits1.da1.src0_reg_file != GEN_IMMEDIATE_VALUE);
378 if (reg.file == GEN_IMMEDIATE_VALUE)
379 gen8_insn->bits3.ud = reg.value.ud;
381 assert (reg.address_mode == GEN_ADDRESS_DIRECT);
382 if (gen8_insn->header.access_mode == GEN_ALIGN_1) {
383 gen8_insn->bits3.da1.src1_subreg_nr = reg.subnr;
384 gen8_insn->bits3.da1.src1_reg_nr = reg.nr;
386 gen8_insn->bits3.da16.src1_subreg_nr = reg.subnr / 16;
387 gen8_insn->bits3.da16.src1_reg_nr = reg.nr;
390 if (reg.width == GEN_WIDTH_1 &&
391 gen8_insn->header.execution_size == GEN_WIDTH_1) {
392 gen8_insn->bits3.da1.src1_horiz_stride = GEN_HORIZONTAL_STRIDE_0;
393 gen8_insn->bits3.da1.src1_width = GEN_WIDTH_1;
394 gen8_insn->bits3.da1.src1_vert_stride = GEN_VERTICAL_STRIDE_0;
396 gen8_insn->bits3.da1.src1_horiz_stride = reg.hstride;
397 gen8_insn->bits3.da1.src1_width = reg.width;
398 gen8_insn->bits3.da1.src1_vert_stride = reg.vstride;
403 #define NO_SWIZZLE ((0<<0) | (1<<2) | (2<<4) | (3<<6))
405 void Gen8Encoder::alu3(uint32_t opcode,
411 GenNativeInstruction *insn = this->next(opcode);
412 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
414 assert(dest.file == GEN_GENERAL_REGISTER_FILE);
415 assert(dest.nr < 128);
416 assert(dest.address_mode == GEN_ADDRESS_DIRECT);
417 assert(dest.type = GEN_TYPE_F);
418 //gen8_insn->bits1.da3src.dest_reg_file = 0;
419 gen8_insn->bits1.da3src.dest_reg_nr = dest.nr;
420 gen8_insn->bits1.da3src.dest_subreg_nr = dest.subnr / 16;
421 gen8_insn->bits1.da3src.dest_writemask = 0xf;
422 this->setHeader(insn);
423 gen8_insn->header.access_mode = GEN_ALIGN_16;
424 gen8_insn->header.execution_size = GEN_WIDTH_8;
426 assert(src0.file == GEN_GENERAL_REGISTER_FILE);
427 assert(src0.address_mode == GEN_ADDRESS_DIRECT);
428 assert(src0.nr < 128);
429 assert(src0.type == GEN_TYPE_F);
430 gen8_insn->bits2.da3src.src0_swizzle = NO_SWIZZLE;
431 gen8_insn->bits2.da3src.src0_subreg_nr = src0.subnr / 4 ;
432 gen8_insn->bits2.da3src.src0_reg_nr = src0.nr;
433 gen8_insn->bits1.da3src.src0_abs = src0.absolute;
434 gen8_insn->bits1.da3src.src0_negate = src0.negation;
435 gen8_insn->bits2.da3src.src0_rep_ctrl = src0.vstride == GEN_VERTICAL_STRIDE_0;
437 assert(src1.file == GEN_GENERAL_REGISTER_FILE);
438 assert(src1.address_mode == GEN_ADDRESS_DIRECT);
439 assert(src1.nr < 128);
440 assert(src1.type == GEN_TYPE_F);
441 gen8_insn->bits2.da3src.src1_swizzle = NO_SWIZZLE;
442 gen8_insn->bits2.da3src.src1_subreg_nr_low = (src1.subnr / 4) & 0x3;
443 gen8_insn->bits3.da3src.src1_subreg_nr_high = (src1.subnr / 4) >> 2;
444 gen8_insn->bits2.da3src.src1_rep_ctrl = src1.vstride == GEN_VERTICAL_STRIDE_0;
445 gen8_insn->bits3.da3src.src1_reg_nr = src1.nr;
446 gen8_insn->bits1.da3src.src1_abs = src1.absolute;
447 gen8_insn->bits1.da3src.src1_negate = src1.negation;
449 assert(src2.file == GEN_GENERAL_REGISTER_FILE);
450 assert(src2.address_mode == GEN_ADDRESS_DIRECT);
451 assert(src2.nr < 128);
452 assert(src2.type == GEN_TYPE_F);
453 gen8_insn->bits3.da3src.src2_swizzle = NO_SWIZZLE;
454 gen8_insn->bits3.da3src.src2_subreg_nr = src2.subnr / 4;
455 gen8_insn->bits3.da3src.src2_rep_ctrl = src2.vstride == GEN_VERTICAL_STRIDE_0;
456 gen8_insn->bits3.da3src.src2_reg_nr = src2.nr;
457 gen8_insn->bits1.da3src.src2_abs = src2.absolute;
458 gen8_insn->bits1.da3src.src2_negate = src2.negation;
460 // Emit second half of the instruction
461 if (this->curr.execWidth == 16) {
462 GenNativeInstruction q1Insn = *insn;
463 insn = this->next(opcode);
465 gen8_insn = &insn->gen8_insn;
466 gen8_insn->header.quarter_control = GEN_COMPRESSION_Q2;
467 gen8_insn->bits1.da3src.dest_reg_nr++;
468 if (gen8_insn->bits2.da3src.src0_rep_ctrl == 0)
469 gen8_insn->bits2.da3src.src0_reg_nr++;
470 if (gen8_insn->bits2.da3src.src1_rep_ctrl == 0)
471 gen8_insn->bits3.da3src.src1_reg_nr++;
472 if (gen8_insn->bits3.da3src.src2_rep_ctrl == 0)
473 gen8_insn->bits3.da3src.src2_reg_nr++;
476 } /* End of the name space. */