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 tmp) {
223 GBE_ASSERT((src0.type == GEN_TYPE_F && dest.isdf()) || (src0.isdf() && dest.type == GEN_TYPE_F));
224 GenRegister r = GenRegister::retype(tmp, GEN_TYPE_F);
225 int w = curr.execWidth;
227 r0 = GenRegister::h2(r);
230 curr.predicate = GEN_PREDICATE_NONE;
233 MOV(GenRegister::suboffset(r0, 4), GenRegister::suboffset(src0, 4));
235 curr.quarterControl = 0;
239 MOV(GenRegister::suboffset(dest, 4), GenRegister::suboffset(r0, 4));
244 curr.predicate = GEN_PREDICATE_NONE;
246 MOV(r0, GenRegister::suboffset(src0, 8));
247 MOV(GenRegister::suboffset(r0, 4), GenRegister::suboffset(src0, 12));
249 curr.quarterControl = 1;
251 MOV(GenRegister::suboffset(dest, 8), r0);
253 MOV(GenRegister::suboffset(dest, 12), GenRegister::suboffset(r0, 4));
258 void Gen8Encoder::JMPI(GenRegister src, bool longjmp) {
259 alu2(this, GEN_OPCODE_JMPI, GenRegister::ip(), GenRegister::ip(), src);
262 void Gen8Encoder::patchJMPI(uint32_t insnID, int32_t jip, int32_t uip) {
263 GenNativeInstruction &insn = *(GenNativeInstruction *)&this->store[insnID];
264 GBE_ASSERT(insnID < this->store.size());
265 GBE_ASSERT(insn.header.opcode == GEN_OPCODE_JMPI ||
266 insn.header.opcode == GEN_OPCODE_BRD ||
267 insn.header.opcode == GEN_OPCODE_ENDIF ||
268 insn.header.opcode == GEN_OPCODE_IF ||
269 insn.header.opcode == GEN_OPCODE_BRC ||
270 insn.header.opcode == GEN_OPCODE_WHILE ||
271 insn.header.opcode == GEN_OPCODE_ELSE);
273 if( insn.header.opcode == GEN_OPCODE_WHILE ) {
274 // if this WHILE instruction jump back to an ELSE instruction,
275 // need add distance to go to the next instruction.
276 GenNativeInstruction & insn_else = *(GenNativeInstruction *)&this->store[insnID+jip];
277 if(insn_else.header.opcode == GEN_OPCODE_ELSE) {
282 if(insn.header.opcode == GEN_OPCODE_ELSE)
285 if (insn.header.opcode == GEN_OPCODE_IF ||
286 insn.header.opcode == GEN_OPCODE_ELSE) {
287 Gen8NativeInstruction *gen8_insn = &insn.gen8_insn;
288 this->setSrc0(&insn, GenRegister::immud(0));
289 gen8_insn->bits2.gen8_branch.uip = uip*8;
290 gen8_insn->bits3.gen8_branch.jip = jip*8;
293 else if (insn.header.opcode == GEN_OPCODE_JMPI) {
294 //jumpDistance'unit is Qword, and the HSW's offset of jmpi is in byte, so multi 8
298 this->setSrc1(&insn, GenRegister::immd(jip*8));
301 void Gen8Encoder::setDst(GenNativeInstruction *insn, GenRegister dest) {
302 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
303 if (dest.file != GEN_ARCHITECTURE_REGISTER_FILE)
304 assert(dest.nr < 128);
306 gen8_insn->bits1.da1.dest_reg_file = dest.file;
307 gen8_insn->bits1.da1.dest_reg_type = dest.type;
308 gen8_insn->bits1.da1.dest_address_mode = dest.address_mode;
309 gen8_insn->bits1.da1.dest_reg_nr = dest.nr;
310 gen8_insn->bits1.da1.dest_subreg_nr = dest.subnr;
311 if (dest.hstride == GEN_HORIZONTAL_STRIDE_0) {
312 if (dest.type == GEN_TYPE_UB || dest.type == GEN_TYPE_B)
313 dest.hstride = GEN_HORIZONTAL_STRIDE_4;
314 else if (dest.type == GEN_TYPE_UW || dest.type == GEN_TYPE_W)
315 dest.hstride = GEN_HORIZONTAL_STRIDE_2;
317 dest.hstride = GEN_HORIZONTAL_STRIDE_1;
319 gen8_insn->bits1.da1.dest_horiz_stride = dest.hstride;
322 void Gen8Encoder::setSrc0(GenNativeInstruction *insn, GenRegister reg) {
323 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
324 if (reg.file != GEN_ARCHITECTURE_REGISTER_FILE)
325 assert(reg.nr < 128);
327 if (reg.address_mode == GEN_ADDRESS_DIRECT) {
328 gen8_insn->bits1.da1.src0_reg_file = reg.file;
329 gen8_insn->bits1.da1.src0_reg_type = reg.type;
330 gen8_insn->bits2.da1.src0_abs = reg.absolute;
331 gen8_insn->bits2.da1.src0_negate = reg.negation;
332 gen8_insn->bits2.da1.src0_address_mode = reg.address_mode;
333 if (reg.file == GEN_IMMEDIATE_VALUE) {
334 gen8_insn->bits3.ud = reg.value.ud;
336 /* Required to set some fields in src1 as well: */
337 gen8_insn->bits2.da1.src1_reg_file = 0; /* arf */
338 gen8_insn->bits2.da1.src1_reg_type = reg.type;
341 if (gen8_insn->header.access_mode == GEN_ALIGN_1) {
342 gen8_insn->bits2.da1.src0_subreg_nr = reg.subnr;
343 gen8_insn->bits2.da1.src0_reg_nr = reg.nr;
345 gen8_insn->bits2.da16.src0_subreg_nr = reg.subnr / 16;
346 gen8_insn->bits2.da16.src0_reg_nr = reg.nr;
349 if (reg.width == GEN_WIDTH_1 &&
350 gen8_insn->header.execution_size == GEN_WIDTH_1) {
351 gen8_insn->bits2.da1.src0_horiz_stride = GEN_HORIZONTAL_STRIDE_0;
352 gen8_insn->bits2.da1.src0_width = GEN_WIDTH_1;
353 gen8_insn->bits2.da1.src0_vert_stride = GEN_VERTICAL_STRIDE_0;
356 gen8_insn->bits2.da1.src0_horiz_stride = reg.hstride;
357 gen8_insn->bits2.da1.src0_width = reg.width;
358 gen8_insn->bits2.da1.src0_vert_stride = reg.vstride;
362 gen8_insn->bits1.ia1.src0_reg_file = GEN_GENERAL_REGISTER_FILE;
363 gen8_insn->bits1.ia1.src0_reg_type = reg.type;
364 gen8_insn->bits2.ia1.src0_subreg_nr = 0;
365 gen8_insn->bits2.ia1.src0_indirect_offset = 0;
366 gen8_insn->bits2.ia1.src0_abs = 0;
367 gen8_insn->bits2.ia1.src0_negate = 0;
368 gen8_insn->bits2.ia1.src0_address_mode = reg.address_mode;
369 gen8_insn->bits2.ia1.src0_horiz_stride = GEN_HORIZONTAL_STRIDE_0;
370 gen8_insn->bits2.ia1.src0_width = GEN_WIDTH_1;
371 gen8_insn->bits2.ia1.src0_vert_stride = GEN_VERTICAL_STRIDE_ONE_DIMENSIONAL;
375 void Gen8Encoder::setSrc1(GenNativeInstruction *insn, GenRegister reg) {
376 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
377 assert(reg.nr < 128);
378 assert(reg.file != GEN_ARCHITECTURE_REGISTER_FILE || reg.nr == 0);
380 gen8_insn->bits2.da1.src1_reg_file = reg.file;
381 gen8_insn->bits2.da1.src1_reg_type = reg.type;
382 gen8_insn->bits3.da1.src1_abs = reg.absolute;
383 gen8_insn->bits3.da1.src1_negate = reg.negation;
385 assert(gen8_insn->bits1.da1.src0_reg_file != GEN_IMMEDIATE_VALUE);
387 if (reg.file == GEN_IMMEDIATE_VALUE)
388 gen8_insn->bits3.ud = reg.value.ud;
390 assert (reg.address_mode == GEN_ADDRESS_DIRECT);
391 if (gen8_insn->header.access_mode == GEN_ALIGN_1) {
392 gen8_insn->bits3.da1.src1_subreg_nr = reg.subnr;
393 gen8_insn->bits3.da1.src1_reg_nr = reg.nr;
395 gen8_insn->bits3.da16.src1_subreg_nr = reg.subnr / 16;
396 gen8_insn->bits3.da16.src1_reg_nr = reg.nr;
399 if (reg.width == GEN_WIDTH_1 &&
400 gen8_insn->header.execution_size == GEN_WIDTH_1) {
401 gen8_insn->bits3.da1.src1_horiz_stride = GEN_HORIZONTAL_STRIDE_0;
402 gen8_insn->bits3.da1.src1_width = GEN_WIDTH_1;
403 gen8_insn->bits3.da1.src1_vert_stride = GEN_VERTICAL_STRIDE_0;
405 gen8_insn->bits3.da1.src1_horiz_stride = reg.hstride;
406 gen8_insn->bits3.da1.src1_width = reg.width;
407 gen8_insn->bits3.da1.src1_vert_stride = reg.vstride;
412 #define NO_SWIZZLE ((0<<0) | (1<<2) | (2<<4) | (3<<6))
414 void Gen8Encoder::alu3(uint32_t opcode,
420 GenNativeInstruction *insn = this->next(opcode);
421 Gen8NativeInstruction *gen8_insn = &insn->gen8_insn;
423 assert(dest.file == GEN_GENERAL_REGISTER_FILE);
424 assert(dest.nr < 128);
425 assert(dest.address_mode == GEN_ADDRESS_DIRECT);
426 assert(dest.type = GEN_TYPE_F);
427 //gen8_insn->bits1.da3src.dest_reg_file = 0;
428 gen8_insn->bits1.da3src.dest_reg_nr = dest.nr;
429 gen8_insn->bits1.da3src.dest_subreg_nr = dest.subnr / 16;
430 gen8_insn->bits1.da3src.dest_writemask = 0xf;
431 this->setHeader(insn);
432 gen8_insn->header.access_mode = GEN_ALIGN_16;
433 gen8_insn->header.execution_size = GEN_WIDTH_8;
435 assert(src0.file == GEN_GENERAL_REGISTER_FILE);
436 assert(src0.address_mode == GEN_ADDRESS_DIRECT);
437 assert(src0.nr < 128);
438 assert(src0.type == GEN_TYPE_F);
439 gen8_insn->bits2.da3src.src0_swizzle = NO_SWIZZLE;
440 gen8_insn->bits2.da3src.src0_subreg_nr = src0.subnr / 4 ;
441 gen8_insn->bits2.da3src.src0_reg_nr = src0.nr;
442 gen8_insn->bits1.da3src.src0_abs = src0.absolute;
443 gen8_insn->bits1.da3src.src0_negate = src0.negation;
444 gen8_insn->bits2.da3src.src0_rep_ctrl = src0.vstride == GEN_VERTICAL_STRIDE_0;
446 assert(src1.file == GEN_GENERAL_REGISTER_FILE);
447 assert(src1.address_mode == GEN_ADDRESS_DIRECT);
448 assert(src1.nr < 128);
449 assert(src1.type == GEN_TYPE_F);
450 gen8_insn->bits2.da3src.src1_swizzle = NO_SWIZZLE;
451 gen8_insn->bits2.da3src.src1_subreg_nr_low = (src1.subnr / 4) & 0x3;
452 gen8_insn->bits3.da3src.src1_subreg_nr_high = (src1.subnr / 4) >> 2;
453 gen8_insn->bits2.da3src.src1_rep_ctrl = src1.vstride == GEN_VERTICAL_STRIDE_0;
454 gen8_insn->bits3.da3src.src1_reg_nr = src1.nr;
455 gen8_insn->bits1.da3src.src1_abs = src1.absolute;
456 gen8_insn->bits1.da3src.src1_negate = src1.negation;
458 assert(src2.file == GEN_GENERAL_REGISTER_FILE);
459 assert(src2.address_mode == GEN_ADDRESS_DIRECT);
460 assert(src2.nr < 128);
461 assert(src2.type == GEN_TYPE_F);
462 gen8_insn->bits3.da3src.src2_swizzle = NO_SWIZZLE;
463 gen8_insn->bits3.da3src.src2_subreg_nr = src2.subnr / 4;
464 gen8_insn->bits3.da3src.src2_rep_ctrl = src2.vstride == GEN_VERTICAL_STRIDE_0;
465 gen8_insn->bits3.da3src.src2_reg_nr = src2.nr;
466 gen8_insn->bits1.da3src.src2_abs = src2.absolute;
467 gen8_insn->bits1.da3src.src2_negate = src2.negation;
469 // Emit second half of the instruction
470 if (this->curr.execWidth == 16) {
471 GenNativeInstruction q1Insn = *insn;
472 insn = this->next(opcode);
474 gen8_insn = &insn->gen8_insn;
475 gen8_insn->header.quarter_control = GEN_COMPRESSION_Q2;
476 gen8_insn->bits1.da3src.dest_reg_nr++;
477 if (gen8_insn->bits2.da3src.src0_rep_ctrl == 0)
478 gen8_insn->bits2.da3src.src0_reg_nr++;
479 if (gen8_insn->bits2.da3src.src1_rep_ctrl == 0)
480 gen8_insn->bits3.da3src.src1_reg_nr++;
481 if (gen8_insn->bits3.da3src.src2_rep_ctrl == 0)
482 gen8_insn->bits3.da3src.src2_reg_nr++;
485 } /* End of the name space. */