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::F16TO32(GenRegister dest, GenRegister src0) {
100 MOV(GenRegister::retype(dest, GEN_TYPE_F), GenRegister::retype(src0, GEN_TYPE_HF));
103 void Gen8Encoder::F32TO16(GenRegister dest, GenRegister src0) {
104 MOV(GenRegister::retype(dest, GEN_TYPE_HF), GenRegister::retype(src0, GEN_TYPE_F));
107 void Gen8Encoder::ATOMIC(GenRegister dst, uint32_t function, GenRegister src, uint32_t bti, uint32_t srcNum) {
108 GenNativeInstruction *insn = this->next(GEN_OPCODE_SEND);
109 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
110 uint32_t msg_length = 0;
111 uint32_t response_length = 0;
113 if (this->curr.execWidth == 8) {
116 } else if (this->curr.execWidth == 16) {
117 msg_length = 2 * srcNum;
122 this->setHeader(insn);
123 this->setDst(insn, GenRegister::uw16grf(dst.nr, 0));
124 this->setSrc0(insn, GenRegister::ud8grf(src.nr, 0));
125 this->setSrc1(insn, GenRegister::immud(0));
127 const GenMessageTarget sfid = GEN_SFID_DATAPORT1_DATA;
128 setMessageDescriptor(insn, sfid, msg_length, response_length);
129 gen8_insn->bits3.gen7_atomic_op.msg_type = GEN75_P1_UNTYPED_ATOMIC_OP;
130 gen8_insn->bits3.gen7_atomic_op.bti = bti;
131 gen8_insn->bits3.gen7_atomic_op.return_data = 1;
132 gen8_insn->bits3.gen7_atomic_op.aop_type = function;
134 if (this->curr.execWidth == 8)
135 gen8_insn->bits3.gen7_atomic_op.simd_mode = GEN_ATOMIC_SIMD8;
136 else if (this->curr.execWidth == 16)
137 gen8_insn->bits3.gen7_atomic_op.simd_mode = GEN_ATOMIC_SIMD16;
142 void Gen8Encoder::UNTYPED_READ(GenRegister dst, GenRegister src, uint32_t bti, uint32_t elemNum) {
143 GenNativeInstruction *insn = this->next(GEN_OPCODE_SEND);
144 assert(elemNum >= 1 || elemNum <= 4);
145 uint32_t msg_length = 0;
146 uint32_t response_length = 0;
147 if (this->curr.execWidth == 8) {
149 response_length = elemNum;
150 } else if (this->curr.execWidth == 16) {
152 response_length = 2 * elemNum;
156 this->setHeader(insn);
157 this->setDst(insn, GenRegister::uw16grf(dst.nr, 0));
158 this->setSrc0(insn, GenRegister::ud8grf(src.nr, 0));
159 this->setSrc1(insn, GenRegister::immud(0));
162 untypedRWMask[elemNum],
163 GEN75_P1_UNTYPED_READ,
168 void Gen8Encoder::UNTYPED_WRITE(GenRegister msg, uint32_t bti, uint32_t elemNum) {
169 GenNativeInstruction *insn = this->next(GEN_OPCODE_SEND);
170 assert(elemNum >= 1 || elemNum <= 4);
171 uint32_t msg_length = 0;
172 uint32_t response_length = 0;
173 this->setHeader(insn);
174 if (this->curr.execWidth == 8) {
175 this->setDst(insn, GenRegister::retype(GenRegister::null(), GEN_TYPE_UD));
176 msg_length = 1 + elemNum;
177 } else if (this->curr.execWidth == 16) {
178 this->setDst(insn, GenRegister::retype(GenRegister::null(), GEN_TYPE_UW));
179 msg_length = 2 * (1 + elemNum);
183 this->setSrc0(insn, GenRegister::ud8grf(msg.nr, 0));
184 this->setSrc1(insn, GenRegister::immud(0));
187 untypedRWMask[elemNum],
188 GEN75_P1_UNTYPED_SURFACE_WRITE,
193 void Gen8Encoder::LOAD_DF_IMM(GenRegister dest, GenRegister tmp, double value) {
194 union { double d; unsigned u[2]; } u;
196 GenRegister r = GenRegister::retype(tmp, GEN_TYPE_UD);
198 curr.predicate = GEN_PREDICATE_NONE;
201 MOV(r, GenRegister::immud(u.u[0]));
202 MOV(GenRegister::suboffset(r, 1), GenRegister::immud(u.u[1]));
204 r.type = GEN_TYPE_DF;
205 r.vstride = GEN_VERTICAL_STRIDE_0;
206 r.width = GEN_WIDTH_1;
207 r.hstride = GEN_HORIZONTAL_STRIDE_0;
209 uint32_t width = curr.execWidth;
211 curr.predicate = GEN_PREDICATE_NONE;
213 curr.quarterControl = GEN_COMPRESSION_Q1;
216 curr.quarterControl = GEN_COMPRESSION_Q2;
217 MOV(GenRegister::offset(dest, 2), r);
222 void Gen8Encoder::MOV_DF(GenRegister dest, GenRegister src0, GenRegister r) {
223 GBE_ASSERT((src0.type == GEN_TYPE_F && dest.isdf()) || (src0.isdf() && dest.type == GEN_TYPE_F));
224 int w = curr.execWidth;
226 r0 = GenRegister::h2(r);
229 curr.predicate = GEN_PREDICATE_NONE;
232 MOV(GenRegister::suboffset(r0, 4), GenRegister::suboffset(src0, 4));
234 curr.quarterControl = 0;
238 MOV(GenRegister::suboffset(dest, 4), GenRegister::suboffset(r0, 4));
243 curr.predicate = GEN_PREDICATE_NONE;
245 MOV(r0, GenRegister::suboffset(src0, 8));
246 MOV(GenRegister::suboffset(r0, 4), GenRegister::suboffset(src0, 12));
248 curr.quarterControl = 1;
250 MOV(GenRegister::suboffset(dest, 8), r0);
252 MOV(GenRegister::suboffset(dest, 12), GenRegister::suboffset(r0, 4));
257 void Gen8Encoder::JMPI(GenRegister src, bool longjmp) {
258 alu2(this, GEN_OPCODE_JMPI, GenRegister::ip(), GenRegister::ip(), src);
261 void Gen8Encoder::patchJMPI(uint32_t insnID, int32_t jip, int32_t uip) {
262 GenNativeInstruction &insn = *(GenNativeInstruction *)&this->store[insnID];
263 GBE_ASSERT(insnID < this->store.size());
264 GBE_ASSERT(insn.header.opcode == GEN_OPCODE_JMPI ||
265 insn.header.opcode == GEN_OPCODE_BRD ||
266 insn.header.opcode == GEN_OPCODE_ENDIF ||
267 insn.header.opcode == GEN_OPCODE_IF ||
268 insn.header.opcode == GEN_OPCODE_BRC ||
269 insn.header.opcode == GEN_OPCODE_WHILE ||
270 insn.header.opcode == GEN_OPCODE_ELSE);
272 if( insn.header.opcode == GEN_OPCODE_WHILE ) {
273 // if this WHILE instruction jump back to an ELSE instruction,
274 // need add distance to go to the next instruction.
275 GenNativeInstruction & insn_else = *(GenNativeInstruction *)&this->store[insnID+jip];
276 if(insn_else.header.opcode == GEN_OPCODE_ELSE) {
281 if(insn.header.opcode == GEN_OPCODE_ELSE)
284 if (insn.header.opcode == GEN_OPCODE_IF ||
285 insn.header.opcode == GEN_OPCODE_ELSE) {
286 Gen8NativeInstruction *gen8_insn = &insn.gen8_insn;
287 this->setSrc0(&insn, GenRegister::immud(0));
288 gen8_insn->bits2.gen8_branch.uip = uip*8;
289 gen8_insn->bits3.gen8_branch.jip = jip*8;
292 else if (insn.header.opcode == GEN_OPCODE_JMPI) {
293 //jumpDistance'unit is Qword, and the HSW's offset of jmpi is in byte, so multi 8
297 this->setSrc1(&insn, GenRegister::immd(jip*8));
300 void Gen8Encoder::setDst(GenNativeInstruction *insn, GenRegister dest) {
301 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
302 if (dest.file != GEN_ARCHITECTURE_REGISTER_FILE)
303 assert(dest.nr < 128);
305 gen8_insn->bits1.da1.dest_reg_file = dest.file;
306 gen8_insn->bits1.da1.dest_reg_type = dest.type;
307 gen8_insn->bits1.da1.dest_address_mode = dest.address_mode;
308 gen8_insn->bits1.da1.dest_reg_nr = dest.nr;
309 gen8_insn->bits1.da1.dest_subreg_nr = dest.subnr;
310 if (dest.hstride == GEN_HORIZONTAL_STRIDE_0) {
311 if (dest.type == GEN_TYPE_UB || dest.type == GEN_TYPE_B)
312 dest.hstride = GEN_HORIZONTAL_STRIDE_4;
313 else if (dest.type == GEN_TYPE_UW || dest.type == GEN_TYPE_W)
314 dest.hstride = GEN_HORIZONTAL_STRIDE_2;
316 dest.hstride = GEN_HORIZONTAL_STRIDE_1;
318 gen8_insn->bits1.da1.dest_horiz_stride = dest.hstride;
321 void Gen8Encoder::setSrc0(GenNativeInstruction *insn, GenRegister reg) {
322 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
323 if (reg.file != GEN_ARCHITECTURE_REGISTER_FILE)
324 assert(reg.nr < 128);
326 if (reg.address_mode == GEN_ADDRESS_DIRECT) {
327 gen8_insn->bits1.da1.src0_reg_file = reg.file;
328 gen8_insn->bits1.da1.src0_reg_type = reg.type;
329 gen8_insn->bits2.da1.src0_abs = reg.absolute;
330 gen8_insn->bits2.da1.src0_negate = reg.negation;
331 gen8_insn->bits2.da1.src0_address_mode = reg.address_mode;
332 if (reg.file == GEN_IMMEDIATE_VALUE) {
333 gen8_insn->bits3.ud = reg.value.ud;
335 /* Required to set some fields in src1 as well: */
336 gen8_insn->bits2.da1.src1_reg_file = 0; /* arf */
337 gen8_insn->bits2.da1.src1_reg_type = reg.type;
340 if (gen8_insn->header.access_mode == GEN_ALIGN_1) {
341 gen8_insn->bits2.da1.src0_subreg_nr = reg.subnr;
342 gen8_insn->bits2.da1.src0_reg_nr = reg.nr;
344 gen8_insn->bits2.da16.src0_subreg_nr = reg.subnr / 16;
345 gen8_insn->bits2.da16.src0_reg_nr = reg.nr;
348 if (reg.width == GEN_WIDTH_1 &&
349 gen8_insn->header.execution_size == GEN_WIDTH_1) {
350 gen8_insn->bits2.da1.src0_horiz_stride = GEN_HORIZONTAL_STRIDE_0;
351 gen8_insn->bits2.da1.src0_width = GEN_WIDTH_1;
352 gen8_insn->bits2.da1.src0_vert_stride = GEN_VERTICAL_STRIDE_0;
355 gen8_insn->bits2.da1.src0_horiz_stride = reg.hstride;
356 gen8_insn->bits2.da1.src0_width = reg.width;
357 gen8_insn->bits2.da1.src0_vert_stride = reg.vstride;
361 gen8_insn->bits1.ia1.src0_reg_file = GEN_GENERAL_REGISTER_FILE;
362 gen8_insn->bits1.ia1.src0_reg_type = reg.type;
363 gen8_insn->bits2.ia1.src0_subreg_nr = 0;
364 gen8_insn->bits2.ia1.src0_indirect_offset = 0;
365 gen8_insn->bits2.ia1.src0_abs = 0;
366 gen8_insn->bits2.ia1.src0_negate = 0;
367 gen8_insn->bits2.ia1.src0_address_mode = reg.address_mode;
368 gen8_insn->bits2.ia1.src0_horiz_stride = GEN_HORIZONTAL_STRIDE_0;
369 gen8_insn->bits2.ia1.src0_width = GEN_WIDTH_1;
370 gen8_insn->bits2.ia1.src0_vert_stride = GEN_VERTICAL_STRIDE_ONE_DIMENSIONAL;
374 void Gen8Encoder::setSrc1(GenNativeInstruction *insn, GenRegister reg) {
375 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
376 assert(reg.nr < 128);
377 assert(reg.file != GEN_ARCHITECTURE_REGISTER_FILE || reg.nr == 0);
379 gen8_insn->bits2.da1.src1_reg_file = reg.file;
380 gen8_insn->bits2.da1.src1_reg_type = reg.type;
381 gen8_insn->bits3.da1.src1_abs = reg.absolute;
382 gen8_insn->bits3.da1.src1_negate = reg.negation;
384 assert(gen8_insn->bits1.da1.src0_reg_file != GEN_IMMEDIATE_VALUE);
386 if (reg.file == GEN_IMMEDIATE_VALUE)
387 gen8_insn->bits3.ud = reg.value.ud;
389 assert (reg.address_mode == GEN_ADDRESS_DIRECT);
390 if (gen8_insn->header.access_mode == GEN_ALIGN_1) {
391 gen8_insn->bits3.da1.src1_subreg_nr = reg.subnr;
392 gen8_insn->bits3.da1.src1_reg_nr = reg.nr;
394 gen8_insn->bits3.da16.src1_subreg_nr = reg.subnr / 16;
395 gen8_insn->bits3.da16.src1_reg_nr = reg.nr;
398 if (reg.width == GEN_WIDTH_1 &&
399 gen8_insn->header.execution_size == GEN_WIDTH_1) {
400 gen8_insn->bits3.da1.src1_horiz_stride = GEN_HORIZONTAL_STRIDE_0;
401 gen8_insn->bits3.da1.src1_width = GEN_WIDTH_1;
402 gen8_insn->bits3.da1.src1_vert_stride = GEN_VERTICAL_STRIDE_0;
404 gen8_insn->bits3.da1.src1_horiz_stride = reg.hstride;
405 gen8_insn->bits3.da1.src1_width = reg.width;
406 gen8_insn->bits3.da1.src1_vert_stride = reg.vstride;
411 #define NO_SWIZZLE ((0<<0) | (1<<2) | (2<<4) | (3<<6))
413 void Gen8Encoder::alu3(uint32_t opcode,
419 GenNativeInstruction *insn = this->next(opcode);
420 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
422 assert(dest.file == GEN_GENERAL_REGISTER_FILE);
423 assert(dest.nr < 128);
424 assert(dest.address_mode == GEN_ADDRESS_DIRECT);
425 assert(dest.type = GEN_TYPE_F);
426 //gen8_insn->bits1.da3src.dest_reg_file = 0;
427 gen8_insn->bits1.da3src.dest_reg_nr = dest.nr;
428 gen8_insn->bits1.da3src.dest_subreg_nr = dest.subnr / 16;
429 gen8_insn->bits1.da3src.dest_writemask = 0xf;
430 this->setHeader(insn);
431 gen8_insn->header.access_mode = GEN_ALIGN_16;
432 gen8_insn->header.execution_size = GEN_WIDTH_8;
434 assert(src0.file == GEN_GENERAL_REGISTER_FILE);
435 assert(src0.address_mode == GEN_ADDRESS_DIRECT);
436 assert(src0.nr < 128);
437 assert(src0.type == GEN_TYPE_F);
438 gen8_insn->bits2.da3src.src0_swizzle = NO_SWIZZLE;
439 gen8_insn->bits2.da3src.src0_subreg_nr = src0.subnr / 4 ;
440 gen8_insn->bits2.da3src.src0_reg_nr = src0.nr;
441 gen8_insn->bits1.da3src.src0_abs = src0.absolute;
442 gen8_insn->bits1.da3src.src0_negate = src0.negation;
443 gen8_insn->bits2.da3src.src0_rep_ctrl = src0.vstride == GEN_VERTICAL_STRIDE_0;
445 assert(src1.file == GEN_GENERAL_REGISTER_FILE);
446 assert(src1.address_mode == GEN_ADDRESS_DIRECT);
447 assert(src1.nr < 128);
448 assert(src1.type == GEN_TYPE_F);
449 gen8_insn->bits2.da3src.src1_swizzle = NO_SWIZZLE;
450 gen8_insn->bits2.da3src.src1_subreg_nr_low = (src1.subnr / 4) & 0x3;
451 gen8_insn->bits3.da3src.src1_subreg_nr_high = (src1.subnr / 4) >> 2;
452 gen8_insn->bits2.da3src.src1_rep_ctrl = src1.vstride == GEN_VERTICAL_STRIDE_0;
453 gen8_insn->bits3.da3src.src1_reg_nr = src1.nr;
454 gen8_insn->bits1.da3src.src1_abs = src1.absolute;
455 gen8_insn->bits1.da3src.src1_negate = src1.negation;
457 assert(src2.file == GEN_GENERAL_REGISTER_FILE);
458 assert(src2.address_mode == GEN_ADDRESS_DIRECT);
459 assert(src2.nr < 128);
460 assert(src2.type == GEN_TYPE_F);
461 gen8_insn->bits3.da3src.src2_swizzle = NO_SWIZZLE;
462 gen8_insn->bits3.da3src.src2_subreg_nr = src2.subnr / 4;
463 gen8_insn->bits3.da3src.src2_rep_ctrl = src2.vstride == GEN_VERTICAL_STRIDE_0;
464 gen8_insn->bits3.da3src.src2_reg_nr = src2.nr;
465 gen8_insn->bits1.da3src.src2_abs = src2.absolute;
466 gen8_insn->bits1.da3src.src2_negate = src2.negation;
468 // Emit second half of the instruction
469 if (this->curr.execWidth == 16) {
470 GenNativeInstruction q1Insn = *insn;
471 insn = this->next(opcode);
473 gen8_insn = &insn->gen8_insn;
474 gen8_insn->header.quarter_control = GEN_COMPRESSION_Q2;
475 gen8_insn->bits1.da3src.dest_reg_nr++;
476 if (gen8_insn->bits2.da3src.src0_rep_ctrl == 0)
477 gen8_insn->bits2.da3src.src0_reg_nr++;
478 if (gen8_insn->bits2.da3src.src1_rep_ctrl == 0)
479 gen8_insn->bits3.da3src.src1_reg_nr++;
480 if (gen8_insn->bits3.da3src.src2_rep_ctrl == 0)
481 gen8_insn->bits3.da3src.src2_reg_nr++;
484 } /* End of the name space. */