1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2017-2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 #include "BinaryEncodingCNL.h"
10 #include "BuildIR.h"
11 using namespace vISA;
12
13 ////////////////////////////// DST ////////////////////////////////////////
14
15
16 ////////////////////////////////////////////////////////////////////////////////////////////////////
17 ////////////////////////////////////////////////////////////////////////////////////////////////////
18 ////////////////////////////// SRC ///////////////
19 ////////////////////////////// SRC ///////////////
20
getEUOpcode(G4_opcode g4opc)21 uint32_t BinaryEncodingBase::getEUOpcode(G4_opcode g4opc)
22 {
23 G9HDL::EU_OPCODE euopcode = G9HDL::EU_OPCODE_ILLEGAL;
24 switch (g4opc)
25 {
26 //3src - complete
27 case G4_bfe: euopcode = G9HDL::EU_OPCODE_BFE; break;
28 case G4_bfi2: euopcode = G9HDL::EU_OPCODE_BFI2; break;
29 case G4_csel: euopcode = G9HDL::EU_OPCODE_CSEL; break;
30 case G4_lrp: euopcode = G9HDL::EU_OPCODE_LRP; break;
31 case G4_mad: euopcode = G9HDL::EU_OPCODE_MAD; break;
32 case G4_madm: euopcode = G9HDL::EU_OPCODE_MADM; break;
33
34 //1src - complete
35 case G4_bfrev: euopcode = G9HDL::EU_OPCODE_BFREV; break;
36 case G4_cbit: euopcode = G9HDL::EU_OPCODE_CBIT; break;
37 case G4_fbh: euopcode = G9HDL::EU_OPCODE_FBH; break;
38 case G4_fbl: euopcode = G9HDL::EU_OPCODE_FBL; break;
39 case G4_lzd: euopcode = G9HDL::EU_OPCODE_LZD; break;
40 case G4_mov: euopcode = G9HDL::EU_OPCODE_MOV; break;
41 case G4_movi: euopcode = G9HDL::EU_OPCODE_MOVI; break;
42 case G4_not: euopcode = G9HDL::EU_OPCODE_NOT; break;
43 case G4_rndd: euopcode = G9HDL::EU_OPCODE_RNDD; break;
44 case G4_rnde: euopcode = G9HDL::EU_OPCODE_RNDE; break;
45 case G4_rndu: euopcode = G9HDL::EU_OPCODE_RNDU; break;
46 case G4_rndz: euopcode = G9HDL::EU_OPCODE_RNDZ; break;
47 case G4_frc: euopcode = G9HDL::EU_OPCODE_FRC; break;
48
49 //2src - complete
50 case G4_add: euopcode = G9HDL::EU_OPCODE_ADD; break;
51 case G4_addc: euopcode = G9HDL::EU_OPCODE_ADDC; break;
52 case G4_and: euopcode = G9HDL::EU_OPCODE_AND; break;
53 case G4_asr: euopcode = G9HDL::EU_OPCODE_ASR; break;
54 case G4_avg: euopcode = G9HDL::EU_OPCODE_AVG; break;
55 case G4_bfi1: euopcode = G9HDL::EU_OPCODE_BFI1; break;
56 case G4_cmp: euopcode = G9HDL::EU_OPCODE_CMP; break;
57 case G4_cmpn: euopcode = G9HDL::EU_OPCODE_CMPN; break;
58 case G4_dp2: euopcode = G9HDL::EU_OPCODE_DP2; break;
59 case G4_dp3: euopcode = G9HDL::EU_OPCODE_DP3; break;
60 case G4_dp4: euopcode = G9HDL::EU_OPCODE_DP4; break;
61 case G4_dph: euopcode = G9HDL::EU_OPCODE_DPH; break;
62 case G4_line: euopcode = G9HDL::EU_OPCODE_LINE; break;
63 case G4_mac: euopcode = G9HDL::EU_OPCODE_MAC; break;
64 case G4_mach: euopcode = G9HDL::EU_OPCODE_MACH; break;
65 case G4_mul: euopcode = G9HDL::EU_OPCODE_MUL; break;
66 case G4_or: euopcode = G9HDL::EU_OPCODE_OR; break;
67 case G4_pln: euopcode = G9HDL::EU_OPCODE_PLN; break;
68 case G4_sad2: euopcode = G9HDL::EU_OPCODE_SAD2; break;
69 case G4_sada2: euopcode = G9HDL::EU_OPCODE_SADA2; break;
70 case G4_sel: euopcode = G9HDL::EU_OPCODE_SEL; break;
71 case G4_shl: euopcode = G9HDL::EU_OPCODE_SHL; break;
72 case G4_shr: euopcode = G9HDL::EU_OPCODE_SHR; break;
73 case G4_xor: euopcode = G9HDL::EU_OPCODE_XOR; break;
74 case G4_subb: euopcode = G9HDL::EU_OPCODE_SUBB; break;
75
76 //send type
77 case G4_send: euopcode = G9HDL::EU_OPCODE_SEND; break;
78 case G4_sendc: euopcode = G9HDL::EU_OPCODE_SENDC; break;
79 case G4_sends: euopcode = G9HDL::EU_OPCODE_SENDS; break;
80 case G4_sendsc: euopcode = G9HDL::EU_OPCODE_SENDSC; break;
81
82 //math type
83 case G4_math: euopcode = G9HDL::EU_OPCODE_MATH; break;
84
85 //control flow
86 case G4_brc: euopcode = G9HDL::EU_OPCODE_BRC; break;
87 case G4_brd: euopcode = G9HDL::EU_OPCODE_BRD; break;
88 case G4_break: euopcode = G9HDL::EU_OPCODE_BREAK; break;
89 case G4_call: euopcode = G9HDL::EU_OPCODE_CALL; break;
90 //case G4_calla: euopcode = G9HDL::EU_OPCODE_CALLA; break;
91 case G4_cont: euopcode = G9HDL::EU_OPCODE_CONT; break;
92 case G4_else: euopcode = G9HDL::EU_OPCODE_ELSE; break;
93 case G4_endif: euopcode = G9HDL::EU_OPCODE_ENDIF; break;
94 case G4_goto: euopcode = G9HDL::EU_OPCODE_GOTO; break;
95 case G4_halt: euopcode = G9HDL::EU_OPCODE_HALT; break;
96 case G4_if: euopcode = G9HDL::EU_OPCODE_IF; break;
97 case G4_jmpi: euopcode = G9HDL::EU_OPCODE_JMPI; break;
98 case G4_join: euopcode = G9HDL::EU_OPCODE_JOIN; break;
99 case G4_return: euopcode = G9HDL::EU_OPCODE_RET; break;
100 case G4_wait: euopcode = G9HDL::EU_OPCODE_WAIT; break;
101 case G4_while: euopcode = G9HDL::EU_OPCODE_WHILE; break;
102
103 //misc:
104 case G4_nop: euopcode = G9HDL::EU_OPCODE_NOP; break;
105 case G4_illegal: euopcode = G9HDL::EU_OPCODE_ILLEGAL; break;
106 case G4_smov: euopcode = G9HDL::EU_OPCODE_SMOV; break;
107
108 default: assert(false && "Invalid G4 opcode!"); break;
109 }
110 return (uint32_t)euopcode;
111 }
112
113 /// \brief Returns the HDL immediate type for a given source operand
114 ///
GetOperandSrcHDLImmType(G4_Type srcType)115 static inline int GetOperandSrcHDLImmType(G4_Type srcType)
116 {
117 int type = G11HDL::SRCIMMTYPE_UD;
118
119 switch (srcType) {
120 case Type_UD: type = G11HDL::SRCIMMTYPE_UD; break;
121 case Type_D: type = G11HDL::SRCIMMTYPE_D; break;
122 case Type_UW: type = G11HDL::SRCIMMTYPE_UW; break;
123 case Type_W: type = G11HDL::SRCIMMTYPE_W; break;
124 case Type_UV: type = G11HDL::SRCIMMTYPE_UV; break;
125 case Type_VF: type = G11HDL::SRCIMMTYPE_VF; break;
126 case Type_V: type = G11HDL::SRCIMMTYPE_V; break;
127 case Type_F: type = G11HDL::SRCIMMTYPE_F; break;
128 case Type_UQ: type = G11HDL::SRCIMMTYPE_UQ; break;
129 case Type_Q: type = G11HDL::SRCIMMTYPE_Q; break;
130 case Type_DF: type = G11HDL::SRCIMMTYPE_DF; break;
131 case Type_HF: type = G11HDL::SRCIMMTYPE_HF; break;
132 default: MUST_BE_TRUE(false, "invalid type"); break;
133 }
134 return type;
135 }
136
137 /// \brief Returns the HDL source type for a given source operand
138 ///
GetOperandSrcHDLType(G4_Type regType)139 static inline int GetOperandSrcHDLType(G4_Type regType)
140 {
141 int type = G11HDL::SRCTYPE_UD;
142
143 switch (regType)
144 {
145 case Type_UD: type = G11HDL::SRCTYPE_UD; break;
146 case Type_D: type = G11HDL::SRCTYPE_D; break;
147 case Type_UW: type = G11HDL::SRCTYPE_UW; break;
148 case Type_W: type = G11HDL::SRCTYPE_W; break;
149 case Type_UB: type = G11HDL::SRCTYPE_UB; break;
150 case Type_B: type = G11HDL::SRCTYPE_B; break;
151 case Type_DF: type = G11HDL::SRCTYPE_DF; break;
152 case Type_F: type = G11HDL::SRCTYPE_F; break;
153 case Type_UQ: type = G11HDL::SRCTYPE_UQ; break;
154 case Type_Q: type = G11HDL::SRCTYPE_Q; break;
155 case Type_HF: type = G11HDL::SRCTYPE_HF; break;
156 default: MUST_BE_TRUE(false, "invalid type"); break;
157 }
158
159 return type;
160 }
161
162 ////////////////////////////////////////////////////////////////////////////////////////////////////
163 ////////////////////////////// ENCODERS ///////////////
164
165
166 ////////////////////////////// HEADER ///////////////
167
168 /// \brief (Header) Field encoder for instruction opcode
169 ///
EncodeOpCode(G4_INST * inst,G9HDL::EU_INSTRUCTION_HEADER & header)170 void BinaryEncodingCNL::EncodeOpCode(G4_INST* inst,
171 G9HDL::EU_INSTRUCTION_HEADER& header)
172 {
173 G4_opcode opcode = inst->opcode();
174 G9HDL::EU_OPCODE euopcode = getEUOpcode(opcode);
175 header.SetOpcode(euopcode);
176 }
177
getEUOpcode(G4_opcode g4opc)178 G9HDL::EU_OPCODE BinaryEncodingCNL::getEUOpcode(G4_opcode g4opc)
179 {
180
181 switch (g4opc)
182 {
183 // GEN11 specific
184 case G4_ror: return G9HDL::EU_OPCODE_ROR;
185 case G4_rol: return G9HDL::EU_OPCODE_ROL;
186 case G4_dp4a: return G9HDL::EU_OPCODE_DP4A;
187 default: break;
188 }
189
190 return (G9HDL::EU_OPCODE)BinaryEncodingBase::getEUOpcode(g4opc);
191 }
192
193 ////////////////////////////// HEADER.CONTROLS ///////////////
194
195 /// \brief (Helper) Converts v-isa execution size to HDL exec size enumeration
196 ///
GetHDLExecSizeFromVISAExecSize(uint32_t execSize)197 static inline G9HDL::EXECSIZE GetHDLExecSizeFromVISAExecSize(uint32_t execSize)
198 {
199 switch (execSize)
200 {
201 case ES_1_CHANNEL:
202 return G9HDL::EXECSIZE_1_CHANNEL_SCALAR_OPERATION;
203 case ES_2_CHANNELS:
204 return G9HDL::EXECSIZE_2_CHANNELS;
205 case ES_4_CHANNELS:
206 return G9HDL::EXECSIZE_4_CHANNELS;
207 case ES_8_CHANNELS:
208 return G9HDL::EXECSIZE_8_CHANNELS;
209 case ES_16_CHANNELS:
210 return G9HDL::EXECSIZE_16_CHANNELS;
211 case ES_32_CHANNELS:
212 return G9HDL::EXECSIZE_32_CHANNELS;
213 }
214 //Default:
215 return G9HDL::EXECSIZE_1_CHANNEL_SCALAR_OPERATION;
216 }
217
218 //////////////////////////////////////////////////////////////////////////
219 /// \brief (Header) Field encoder for execution size
220 ///
EncodeExecSize(G4_INST * inst,G9HDL::EU_INSTRUCTION_CONTROLS_A & controls)221 void BinaryEncodingCNL::EncodeExecSize(G4_INST* inst,
222 G9HDL::EU_INSTRUCTION_CONTROLS_A& controls)
223 {
224 G9HDL::EXECSIZE exSz;
225 exSz = GetHDLExecSizeFromVISAExecSize(GetEncodeExecSize(inst));
226 controls.SetExecsize(exSz);
227 }
228
229 //////////////////////////////////////////////////////////////////////////
230 /// \brief (Header) Field encoder for access mode bit
231 ///
EncodeAccessMode(G4_INST * inst,G9HDL::EU_INSTRUCTION_CONTROLS_A & controls)232 void BinaryEncodingCNL::EncodeAccessMode(G4_INST* inst,
233 G9HDL::EU_INSTRUCTION_CONTROLS_A& controls)
234 {
235 if (inst->isAligned1Inst()) {
236 controls.SetAccessmode(G9HDL::ACCESSMODE_ALIGN1);
237 }
238 else if (inst->isAligned16Inst()) {
239 controls.SetAccessmode(G9HDL::ACCESSMODE_ALIGN16);
240 }
241 }
242
243 //////////////////////////////////////////////////////////////////////////
244 /// \brief (Header) Field encoder for QTR control fields
245 ///
EncodeQtrControl(G4_INST * inst,G9HDL::EU_INSTRUCTION_CONTROLS_A & controls)246 void BinaryEncodingCNL::EncodeQtrControl(G4_INST* inst,
247 G9HDL::EU_INSTRUCTION_CONTROLS_A& controls)
248 {
249 G9HDL::QTRCTRL qtrCtrl = G9HDL::QTRCTRL_1Q;
250 G9HDL::NIBCTRL nibCtrl = G9HDL::NIBCTRL::NIBCTRL_EVEN;
251
252 switch (inst->getMaskOffset())
253 {
254 case 0:
255 qtrCtrl = G9HDL::QTRCTRL_1Q;
256 nibCtrl = G9HDL::NIBCTRL_ODD;
257 break;
258 case 4:
259 qtrCtrl = G9HDL::QTRCTRL_1Q;
260 nibCtrl = G9HDL::NIBCTRL_EVEN;
261 break;
262 case 8:
263 qtrCtrl = G9HDL::QTRCTRL_2Q;
264 nibCtrl = G9HDL::NIBCTRL_ODD;
265 break;
266 case 12:
267 qtrCtrl = G9HDL::QTRCTRL_2Q;
268 nibCtrl = G9HDL::NIBCTRL_EVEN;
269 break;
270 case 16:
271 qtrCtrl = G9HDL::QTRCTRL_3Q;
272 nibCtrl = G9HDL::NIBCTRL_ODD;
273 break;
274 case 20:
275 qtrCtrl = G9HDL::QTRCTRL_3Q;
276 nibCtrl = G9HDL::NIBCTRL_EVEN;
277 break;
278 case 24:
279 qtrCtrl = G9HDL::QTRCTRL_4Q;
280 nibCtrl = G9HDL::NIBCTRL_ODD;
281 break;
282 case 28:
283 qtrCtrl = G9HDL::QTRCTRL_4Q;
284 nibCtrl = G9HDL::NIBCTRL_EVEN;
285 break;
286 }
287
288 controls.SetQtrctrl(qtrCtrl);
289 controls.SetNibctrl(nibCtrl);
290 }
291
292 /// \brief Field encoder for dependency control check fields
EncodeDepControl(G4_INST * inst,G9HDL::EU_INSTRUCTION_CONTROLS_A & controlsA)293 inline void BinaryEncodingCNL::EncodeDepControl(G4_INST* inst,
294 G9HDL::EU_INSTRUCTION_CONTROLS_A& controlsA)
295 {
296 if (inst->isNoDDChkInst())
297 {
298 if (inst->isNoDDClrInst())
299 {
300 controlsA.SetDepctrl(G9HDL::DEPCTRL_NODDCLR_NODDCHK);
301 } else {
302 controlsA.SetDepctrl(G9HDL::DEPCTRL_NODDCHK);
303 }
304 }
305 else {
306 if (inst->isNoDDClrInst())
307 {
308 controlsA.SetDepctrl(G9HDL::DEPCTRL_NODDCLR);
309 } else {
310 controlsA.SetDepctrl(G9HDL::DEPCTRL_NONE);
311 }
312 }
313 }
314
315 /// \brief Field encoder for thread control field. Includes some logic that is
316 // dependant on the platform.
EncodeThreadControl(G4_INST * inst,G9HDL::EU_INSTRUCTION_CONTROLS_A & controlsA)317 inline void BinaryEncodingCNL::EncodeThreadControl(G4_INST* inst,
318 G9HDL::EU_INSTRUCTION_CONTROLS_A& controlsA)
319 {
320 if (inst->opcode() == G4_if ||
321 inst->opcode() == G4_else ||
322 inst->opcode() == G4_endif)
323 {
324
325 }
326
327 else
328 {
329 controlsA.SetThreadControl(
330 inst->isAtomicInst()? G9HDL::THREADCTRL_ATOMIC :
331 // CHAI: Add Switch InstOpt support
332 (inst->isYieldInst() ? G9HDL::THREADCTRL_SWITCH :
333 (inst->isNoPreemptInst() ? G9HDL::THREADCTRL_NOPREEMPT :
334 G9HDL::THREADCTRL_NORMAL)));
335 }
336 }
337
338 /// \brief Field encoder for ACC write control field
EncodeAccWrCtrl(G4_INST * inst,G9HDL::EU_INSTRUCTION_CONTROLS & instructionControls)339 void BinaryEncodingCNL::EncodeAccWrCtrl(G4_INST* inst,
340 G9HDL::EU_INSTRUCTION_CONTROLS& instructionControls)
341 {
342 if (inst->isAccWrCtrlInst() || (inst->isFlowControl() && inst->opcode() != G4_jmpi && inst->asCFInst()->isBackward()))
343 {
344 instructionControls.SetControlsB_Accwrctrl(G9HDL::ACCWRCTRL_UPDATE_ACC);
345 }
346 }
347
348 //////////////////////////////////////////////////////////////////////////
349 //// Field encoder
EncodeInstModifier(G4_INST * inst,G9HDL::EU_INSTRUCTION_CONTROLS & instructionControls)350 void BinaryEncodingCNL::EncodeInstModifier(G4_INST* inst,
351 G9HDL::EU_INSTRUCTION_CONTROLS& instructionControls)
352 {
353 if (inst->getSaturate()) {
354 instructionControls.SetControlsB_Saturate(G9HDL::SATURATE_SAT);
355 } else {
356 instructionControls.SetControlsB_Saturate(G9HDL::SATURATE_NO_DESTINATION_MODIFICATION);
357 }
358 }
359
360 //////////////////////////////////////////////////////////////////////////
361 //// Field encoder
EncodeFlagRegPredicate(G4_INST * inst,G9HDL::EU_INSTRUCTION_CONTROLS_A & instructionControlsA)362 void BinaryEncodingCNL::EncodeFlagRegPredicate(
363 G4_INST* inst,
364 G9HDL::EU_INSTRUCTION_CONTROLS_A& instructionControlsA)
365 {
366 G4_Predicate *pred = inst->getPredicate();
367 if (pred)
368 {
369 switch (pred->getState())
370 {
371 // plus and undef are normal
372 case PredState_Plus:
373 case PredState_undef:
374 instructionControlsA.SetPredinv(G9HDL::PREDINV_POSITIVE);
375 //instructionHeader.SetControl_Predinv(G9HDL::PREDINV_POSITIVE);
376 //flagState = PREDICATE_STATE_NORMAL;
377 break;
378 // minus is invert
379 case PredState_Minus:
380 instructionControlsA.SetPredinv(G9HDL::PREDINV_NEGATIVE);
381 //instructionHeader.SetControl_Predinv(G9HDL::PREDINV_NEGATIVE);
382 //flagState = PREDICATE_STATE_INVERT<<4;
383 break;
384 }
385
386 G9HDL::PREDCTRL predCtrl = G9HDL::PREDCTRL_SEQUENTIAL_FLAG_CHANNEL_MAPPING;
387
388 if (inst->isAligned16Inst())
389 {
390 switch (pred->getAlign16PredicateControl())
391 {
392 case PRED_ALIGN16_DEFAULT:
393 predCtrl = G9HDL::PREDCTRL_SEQUENTIAL_FLAG_CHANNEL_MAPPING;
394 break;
395 case PRED_ALIGN16_X:
396 predCtrl = G9HDL::PREDCTRL_REPLICATION_SWIZZLE_X;
397 break;
398 case PRED_ALIGN16_Y:
399 predCtrl = G9HDL::PREDCTRL_REPLICATION_SWIZZLE_Y;
400 break;
401 case PRED_ALIGN16_Z:
402 predCtrl = G9HDL::PREDCTRL_REPLICATION_SWIZZLE_Z;
403 break;
404 case PRED_ALIGN16_W:
405 predCtrl = G9HDL::PREDCTRL_REPLICATION_SWIZZLE_W;
406 break;
407 case PRED_ALIGN16_ANY4H:
408 predCtrl = G9HDL::PREDCTRL_ANY4H;
409 break;
410 case PRED_ALIGN16_ALL4H:
411 predCtrl = G9HDL::PREDCTRL_ALL4H;
412 break;
413 default:
414 MUST_BE_TRUE(false, "invalid align16 predicate control");
415 }
416 instructionControlsA.SetPredctrl(predCtrl);
417 //instructionHeader.SetControl_Predctrl(predCtrl);
418 }
419 else
420 {
421 auto pc = pred->getControl();
422 if (pc != PRED_DEFAULT)
423 predCtrl = (G9HDL::PREDCTRL)GetAlign1PredCtrl(pc);
424 instructionControlsA.SetPredctrl(predCtrl);
425 }
426 }
427 }
428
429 static const unsigned CONDITION_MODIIFER[11] =
430 {
431 (unsigned)G9HDL::CONDMODIFIER_Z,
432 (unsigned)G9HDL::CONDMODIFIER_E,
433 (unsigned)G9HDL::CONDMODIFIER_NZ,
434 (unsigned)G9HDL::CONDMODIFIER_NE,
435 (unsigned)G9HDL::CONDMODIFIER_G,
436 (unsigned)G9HDL::CONDMODIFIER_GE,
437 (unsigned)G9HDL::CONDMODIFIER_L,
438 (unsigned)G9HDL::CONDMODIFIER_LE,
439 (unsigned)G9HDL::CONDMODIFIER_O, // Mod_o
440 (unsigned)G9HDL::CONDMODIFIER_O, // Mod_r
441 (unsigned)G9HDL::CONDMODIFIER_U // Mod_u
442 };
443 /// \brief Field encoder
444 ///
EncodeCondModifier(G4_INST * inst,G9HDL::EU_INSTRUCTION_CONTROLS & instructionControls)445 void BinaryEncodingCNL::EncodeCondModifier(G4_INST* inst, G9HDL::EU_INSTRUCTION_CONTROLS& instructionControls)
446 {
447 G4_CondMod *cModifier = inst->getCondMod();
448 if (cModifier) {
449 G9HDL::CONDMODIFIER value;
450
451 unsigned mod = (unsigned)cModifier->getMod();
452 MUST_BE_TRUE(mod != (unsigned)Mod_r && mod < (unsigned)Mod_cond_undef,
453 //case Mod_r:
454 // value = G9HDL::CONDMODIFIER_O; //7
455 // break;
456 "[Verifying]:[ERR]: Invalid conditional modifier:\t");
457 value = (G9HDL::CONDMODIFIER)CONDITION_MODIIFER[mod];
458 instructionControls.SetCondmodifier(value);
459 }
460 }
461
462
463 /// \brief Encodes instruction header DWORD, common for all types of instructions
EncodeInstHeader(G4_INST * inst,G9HDL::EU_INSTRUCTION_HEADER & header)464 inline void BinaryEncodingCNL::EncodeInstHeader(G4_INST *inst,
465 G9HDL::EU_INSTRUCTION_HEADER& header)
466 {
467 G9HDL::EU_INSTRUCTION_CONTROLS& controls = header.GetControl();
468 G9HDL::EU_INSTRUCTION_CONTROLS_A& controlsA = controls.GetControlsA();
469
470 header.Init();
471 EncodeOpCode(inst, header);
472 EncodeExecSize(inst, controlsA);
473 EncodeAccessMode(inst, controlsA);
474 EncodeQtrControl(inst, controlsA);
475 EncodeThreadControl(inst, controlsA);
476 EncodeDepControl(inst, controlsA);
477 EncodeFlagRegPredicate(inst, controlsA);
478 EncodeAccWrCtrl(inst,controls);
479 EncodeInstModifier(inst,controls);
480 EncodeCondModifier(inst,controls);
481
482 controls.SetControlsB_Cmptctrl(
483 inst->isCompactedInst() ?
484 G9HDL::CMPTCTRL_COMPACTED :G9HDL::CMPTCTRL_NOCOMPACTION);
485
486 if (inst->isBreakPointInst())
487 controls.SetControlsB_Debugctrl(G9HDL::DEBUGCTRL_BREAKPOINT);
488
489 }
490
491 ////////////////////////////// DST.OPERAND_CONTROLS ///////////////
492 ////////////////////////////// DST.OPERAND_CONTROLS ///////////////
493 ////////////////////////////// DST.OPERAND_CONTROLS ///////////////
494 ////////////////////////////// DST.OPERAND_CONTROLS ///////////////
495 ////////////////////////////// DST.OPERAND_CONTROLS ///////////////
496 ////////////////////////////// DST.OPERAND_CONTROLS ///////////////
497 ////////////////////////////// DST.OPERAND_CONTROLS ///////////////
498 ////////////////////////////// DST.OPERAND_CONTROLS ///////////////
499
500
501 //////////////////////////////////////////////////////////////////////////
502 //// Field encoder
EncodeDstHorzStride(G4_INST * inst,G4_DstRegRegion * dst,G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS & opnds)503 inline void BinaryEncodingCNL::EncodeDstHorzStride(G4_INST *inst, G4_DstRegRegion *dst,
504 G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS& opnds)
505 {
506 switch (dst->getHorzStride())
507 {
508 case 1:
509 //NOTE: not sure if this is correct?
510 if (inst->isAligned16Inst())
511 {
512 //NOTE: use align1 union, even if setting align16 field. Masks are equal.
513 //note: Although Dst.HorzStride is a don't care for Align16, HW needs this to be programmed as '01'.
514 opnds.GetDestinationRegisterRegion_Align1().SetDestinationHorizontalStride(G9HDL::HORZSTRIDE_4_ELEMENTS);
515 } else {
516 opnds.GetDestinationRegisterRegion_Align1().SetDestinationHorizontalStride(G9HDL::HORZSTRIDE_1_ELEMENTS);
517 }
518 break;
519 case 2:
520 opnds.GetDestinationRegisterRegion_Align1().SetDestinationHorizontalStride(G9HDL::HORZSTRIDE_2_ELEMENTS);
521 break;
522 case 4:
523 opnds.GetDestinationRegisterRegion_Align1().SetDestinationHorizontalStride(G9HDL::HORZSTRIDE_4_ELEMENTS);
524 break;
525 case UNDEFINED_SHORT:
526 opnds.GetDestinationRegisterRegion_Align1().SetDestinationHorizontalStride(G9HDL::HORZSTRIDE_1_ELEMENTS);
527 break;
528 default: MUST_BE_TRUE(false, "wrong dst horizontal stride"); break;
529 }
530 }
531
532 //////////////////////////////////////////////////////////////////////////
533 //// Field encoder
534 //NOTE: could change interface, so that 'dst' is passed directly
EncodeDstChanEn(G4_INST * inst,G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS & opnds)535 void BinaryEncodingCNL::EncodeDstChanEn(G4_INST* inst,
536 G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS& opnds)
537 {
538 G4_DstRegRegion* dst = inst->getDst();
539
540 if (dst->isAccRegValid())
541 {
542 //NOTE: this one is special case for instructions that use special accumulators
543 opnds.GetDestinationRegisterRegion_Align16().SetDestinationChannelEnable(dst->getAccRegSel());
544 } else {
545 G4_DstRegRegion *dstRegion = static_cast<G4_DstRegRegion*>(dst);
546
547 opnds.GetDestinationRegisterRegion_Align16().
548 SetDestinationChannelEnable(dstRegion->getWriteMask());
549 }
550 }
551
552 //////////////////////////////////////////////////////////////////////////
553 //// Field encoder
554 //NOTE: could change interface, so that 'dst' is passed directly
555 //NOTE2: Encoding for ARF register type is moved into setting reg destination logic.
EncodeDstRegFile(G4_INST * inst,G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS & opnds)556 void BinaryEncodingCNL::EncodeDstRegFile(G4_INST* inst,
557 G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS& opnds)
558 {
559 G4_DstRegRegion* dst = inst->getDst();
560 switch (EncodingHelper::GetDstRegFile(dst))
561 { //Bug Line 846, bitrange: 3-4, should be: 35-36
562 case REG_FILE_A:
563 opnds.SetDestinationRegisterFile(G9HDL::REGFILE_ARF); break;
564 case REG_FILE_R:
565 opnds.SetDestinationRegisterFile(G9HDL::REGFILE_GRF); break;
566 case REG_FILE_M:
567 MUST_BE_TRUE(0 ," Memory is invalid register file on CNL");
568 //opnds.SetDestinationRegisterFile(G9HDL::REGFILE_IMM); break;
569 default:
570 break;
571 }
572 }
573
574 //////////////////////////////////////////////////////////////////////////
575 //// Field encoder
576 //NOTE: could change interface, so that 'dst' is passed directly
EncodeDstRegNum(G4_INST * inst,G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS & opnds)577 void BinaryEncodingCNL::EncodeDstRegNum(G4_INST* inst,
578 G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS& opnds)
579 {
580 G4_DstRegRegion* dst = inst->getDst();
581
582 if (EncodingHelper::GetDstRegFile(dst) != REG_FILE_A &&
583 EncodingHelper::GetDstAddrMode(dst) == ADDR_MODE_IMMED)
584 {
585 uint32_t byteAddress = dst->getLinearizedStart();
586
587 if (inst->isAligned1Inst())
588 {
589 //register number: 256 bit (32 byte) aligned part of an address
590 //sub-register number: 32 byte address (5 bits encoding) within a GRF
591 // 98765 43210
592 // regn |subre
593
594 opnds.GetDestinationRegisterRegion_Align1().
595 SetDestinationRegisterNumber_DestinationRegisterNumber(byteAddress >> 5);
596 if (dst->isAccRegValid() && kernel.fg.builder->encodeAccRegSelAsAlign1())
597 {
598 MUST_BE_TRUE((byteAddress & 0x1F) == 0, "subreg must be 0 for dst with special accumulator");
599 opnds.GetDestinationRegisterRegion_Align1().
600 SetDestinationSpecialAcc(dst->getAccRegSel());
601 }
602 else
603 {
604 opnds.GetDestinationRegisterRegion_Align1().
605 SetDestinationSubregisterNumber_DestinationSubRegisterNumber(byteAddress & 0x1F);
606 }
607 } else { //align 16
608 //register number: 256 bit (32 byte) aligned part of an address
609 //sub-register number: first/second 16 byte part of 32 byte address. Encoded with 1 bit.
610 // 98765 43210
611 // regn |x0000
612
613 //opnds.GetDestinationRegisterRegion_Align1().
614 // SetDestinationRegisterNumber_DestinationRegisterNumber(byteAddress >> 5);
615 opnds.GetDestinationRegisterRegion_Align16().
616 SetDestinationRegisterNumber_DestinationRegisterNumber(byteAddress >> 5);
617
618 //opnds.GetDestinationRegisterRegion_Align1().
619 // SetDestinationSubregisterNumber_DestinationSubRegisterNumber((byteAddress >> 4) & 0x1);
620 opnds.GetDestinationRegisterRegion_Align16().
621 SetDestinationSubregisterNumber((WORD)byteAddress);
622 }
623 }
624 }
625
626 //////////////////////////////////////////////////////////////////////////
627 //// Field encoder
628 //NOTE: could change interface, so that 'dst' is passed directly
629 //
630 // SetDstArchRegNum (53:56) + SetDstArchRegFile (57:60)
631 // SetDstArchSubRegNumByte (48:52)
632 // essentially, this encoding is split in three parts:
633 // setting reg num : arch reg file + arch reg number
634 // setting sub-reg-num
635 // Here, we fuse two original methods into one: EncodeDstArchRegNum and EncodeDstRegFile for ARF
EncodeDstArchRegNum(G4_INST * inst,G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS & opnds)636 void BinaryEncodingCNL::EncodeDstArchRegNum(G4_INST* inst,
637 G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS& opnds)
638 {
639 G4_DstRegRegion* dst = inst->getDst();
640
641 if (EncodingHelper::GetDstRegFile(dst) == REG_FILE_A &&
642 EncodingHelper::GetDstAddrMode(dst) == ADDR_MODE_IMMED)
643 {
644 if (EncodingHelper::GetDstArchRegType(dst) != ARCH_REG_FILE_NULL)
645 {
646 bool valid;
647
648 unsigned short RegFile = (unsigned short) EncodingHelper::GetDstArchRegType(dst); //4 bits
649 unsigned short RegNumValue = dst->ExRegNum(valid);
650
651 // 7654|3210
652 // RegF|RegNumVal
653 unsigned short EncodedRegNum = RegFile << 4;
654 EncodedRegNum = EncodedRegNum | (RegNumValue & 0xF);
655
656 //the same as for align16
657 opnds.GetDestinationRegisterRegion_Align1().SetDestinationRegisterNumber_DestinationRegisterNumber(EncodedRegNum);
658 {
659 bool subValid;
660 unsigned short RegSubNumValue = dst->ExSubRegNum(subValid);
661 unsigned short ElementSizeValue = EncodingHelper::GetElementSizeValue(dst);
662 uint32_t regOffset = RegSubNumValue * ElementSizeValue;
663
664 if (inst->isAligned1Inst())
665 {
666 //sub-register number: 32 byte address (5 bits encoding) within a GRF
667 opnds.GetDestinationRegisterRegion_Align1().
668 SetDestinationSubregisterNumber_DestinationSubRegisterNumber((WORD)regOffset);
669 } else { //align 16
670 //sub-register number: first/second 16 byte part of 32 byte address. Encoded with 1 bit.
671 // 9876543210
672 // regn|x0000
673 //opnds.GetDestinationRegisterRegion_Align16().SetDestinationSubregisterNumber((regOffset >> 4) & 0x1);
674 opnds.GetDestinationRegisterRegion_Align16().SetDestinationSubregisterNumber((WORD)regOffset);
675 }
676 }
677 }
678 }
679 }
680
681 //////////////////////////////////////////////////////////////////////////
682 //// Field encoder
683 //NOTE: could change interface, so that 'dst' is passed directly
EncodeDstIndirectRegNum(G4_INST * inst,G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS & opnds)684 void BinaryEncodingCNL::EncodeDstIndirectRegNum(G4_INST* inst,
685 G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS& opnds)
686 {
687 G4_DstRegRegion* dst = inst->getDst();
688
689 if (EncodingHelper::GetDstRegFile(dst)==REG_FILE_R ||
690 EncodingHelper::GetDstRegFile(dst)==REG_FILE_M)
691 {
692 if (EncodingHelper::GetDstAddrMode(dst) == ADDR_MODE_INDIR)
693 { // Indirect
694 bool subValid;
695 unsigned short IndAddrRegSubNumValue = 0;
696 short IndAddrImmedValue = 0;
697
698 IndAddrRegSubNumValue = dst->ExIndSubRegNum(subValid);
699 IndAddrImmedValue = dst->ExIndImmVal();
700
701 //the same is for align16
702 opnds.GetDestinationRegisterRegion_Align1().
703 SetDestinationAddressSubregisterNumber_AddressSubregisterNumber(IndAddrRegSubNumValue);
704
705 /* Set the indirect address immediate value. */
706 if (inst->isAligned1Inst())
707 {
708 //bits [0-8]
709 opnds.GetDestinationRegisterRegion_Align1().SetDestinationAddressImmediate(IndAddrImmedValue);
710 //bit[9:9]
711 opnds.SetDestinationAddressImmediate99(IndAddrImmedValue >> 9);
712 } else { //here we are setting align16
713 //bits [4-8]
714 opnds.GetDestinationRegisterRegion_Align16().
715 SetDestinationAddressImmediate84((IndAddrImmedValue >> 4) & 0x1F);
716 //bit[9:9], originally: (IndAddrImmedValue / BYTES_PER_OWORD) >> 5
717 opnds.SetDestinationAddressImmediate99(IndAddrImmedValue >> 9);
718 }
719 }
720 }
721 }
722
723 /// \brief Encodes instruction operand (1st DWORD) of instruction
724 ///
725 /// src0 reg file and type are not encoded here, even though they belong to dword 1
EncodeOperandDst(G4_INST * inst,G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS & opnds)726 inline void BinaryEncodingCNL::EncodeOperandDst(G4_INST* inst,
727 G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS& opnds)
728 {
729 G4_DstRegRegion* dst = inst->getDst();
730
731 DstBuilder<G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS>::EncodeFlagReg(inst, opnds);
732 DstBuilder<G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS>::EncodeMaskCtrl(inst, opnds);
733
734 if (dst == NULL)
735 {
736 return;
737 }
738
739 EncodeDstRegFile(inst,opnds);
740 DstBuilder<G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS>::EncodeOperandDstType(inst, opnds);
741
742 if (inst->isAligned16Inst())
743 {
744 EncodeDstChanEn(inst,opnds);
745 }
746 // Note: dst doesn't have the vertical stride and width
747 EncodeDstRegNum(inst, opnds);
748 EncodeDstArchRegNum(inst, opnds);
749 EncodeDstIndirectRegNum(inst, opnds);
750
751 EncodeDstHorzStride(inst, dst, opnds);
752 DstBuilder<G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS>::EncodeDstAddrMode(inst, opnds);
753 }
754
755
756
757 //EU_INSTRUCTION_BASIC_ONE_SRC
758 // (EU_INSTRUCTION_SOURCES_REG
759 // EU_INSTRUCTION_OPERAND_SRC_REG_ALIGN1
760 // or
761 // EU_INSTRUCTION_OPERAND_SRC_REG_ALIGN16)
762 // or
763 // (EU_INSTRUCTION_SOURCES_IMM32
764
765
766
EncodeOneSrcInst(G4_INST * inst,G9HDL::EU_INSTRUCTION_BASIC_ONE_SRC & oneSrc)767 inline void BinaryEncodingCNL::EncodeOneSrcInst(G4_INST* inst, G9HDL::EU_INSTRUCTION_BASIC_ONE_SRC& oneSrc)
768 {
769 EncodeInstHeader(inst, oneSrc.Common.Header);
770 EncodeOperandDst(inst, oneSrc.Common.OperandControls);
771 G4_Operand *src0 = inst->getSrc(0);
772
773 //EncodeSrc0RegFile
774 oneSrc.GetOperandControls().SetSrc0Regfile(TranslateVisaToHDLRegFile(EncodingHelper::GetSrcRegFile(src0)));
775
776 //EncodeSrc0Type
777 if (src0->isImm())
778 {
779 oneSrc.GetOperandControls().SetSrc0Srctype_Imm(GetOperandSrcHDLImmType(src0->getType()));
780 }
781 else
782 {
783 oneSrc.GetOperandControls().SetSrc0Srctype(GetOperandSrcHDLType(src0->getType()));
784 }
785
786 if (src0->isImm())
787 {
788 // this should be compiled as dead code in non-debug mode
789 MUST_BE_TRUE(inst->opcode() == G4_mov || src0->getTypeSize() != 8,
790 "only Mov is allowed for 64-bit immediate");
791 if (src0->getTypeSize() == 8) {
792 G9HDL::EU_INSTRUCTION_IMM64_SRC* ptr = (G9HDL::EU_INSTRUCTION_IMM64_SRC*) &oneSrc;
793 EncodeSrcImm64Data(*ptr, src0);
794 }
795 else
796 {
797 //EncodeSrcImmData(oneSrc.GetImmsource(), src0);
798 SrcBuilder<G9HDL::EU_INSTRUCTION_SOURCES_IMM32,0>::EncodeSrcImmData(
799 oneSrc.GetImmsource(), src0);
800 }
801 }
802 else
803 {
804 SrcBuilder<G9HDL::EU_INSTRUCTION_SOURCES_REG,0>::EncodeEuInstructionSourcesReg(
805 inst, src0, oneSrc. GetRegsource()); // by reference
806 }
807
808 }
809
EncodeTwoSrcInst(G4_INST * inst,G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC & twoSrc)810 inline void BinaryEncodingCNL::EncodeTwoSrcInst(G4_INST* inst, G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC& twoSrc)
811 {
812
813 EncodeInstHeader(inst, twoSrc.Common.Header);
814 EncodeOperandDst(inst, twoSrc.Common.OperandControls);
815 G4_Operand *src0 = inst->getSrc(0);
816 G4_Operand *src1 = inst->getSrc(1);
817
818 //EncodeSrc0RegFile
819 twoSrc.GetOperandControls().SetSrc0Regfile(TranslateVisaToHDLRegFile(EncodingHelper::GetSrcRegFile(src0)));
820
821 bool src0ImmOk = inst->isMath() && inst->asMathInst()->isOneSrcMath();
822 MUST_BE_TRUE(src0ImmOk || !src0->isImm(), "src0 is immediate in two src instruction!");
823 //EncodeSrc0Type
824 if (src0->isImm())
825 {
826 twoSrc.GetOperandControls().SetSrc0Srctype_Imm(GetOperandSrcHDLImmType(src0->getType()));
827 }
828 else
829 {
830 if (inst->isSend())
831 {
832 twoSrc.GetOperandControls().SetSrc0Srctype(GetOperandSrcHDLType(Type_F));
833 }
834 else
835 {
836 twoSrc.GetOperandControls().SetSrc0Srctype(GetOperandSrcHDLType(src0->getType()));
837 }
838 }
839
840 if (src0->isImm())
841 {
842 MUST_BE_TRUE(src0->getTypeSize() < 8, "only Mov is allowed for 64bit immediate");
843 // FIXME: feels like this should be 0 here, but it gives a type mismatch as the headers assume src0
844 // must be REG
845 SrcBuilder<G9HDL::EU_INSTRUCTION_SOURCES_REG_IMM, 1>::EncodeSrcImmData(
846 twoSrc.GetImmsource(), src0);
847 }
848 else
849 {
850 SrcBuilder<G9HDL::EU_INSTRUCTION_SOURCES_REG_REG, 0>::EncodeEuInstructionSourcesReg(
851 inst, src0, twoSrc.GetRegsource()); // by reference
852 }
853
854 //no need to encode one src math instruction
855 if (inst->isMath() && src1->isNullReg() && !src0->isImm())
856 {
857 SrcBuilder<G9HDL::EU_INSTRUCTION_SOURCES_REG_REG, 1>::EncodeEuInstructionNullSourcesReg(inst, src1, twoSrc.GetRegsource());
858 return;
859 }
860
861 twoSrc.GetRegsource().SetSrc1Regfile(TranslateVisaToHDLRegFile(EncodingHelper::GetSrcRegFile(src1)));
862 if (src1->isImm())
863 {
864 twoSrc.GetImmsource().SetSrc1Srctype(GetOperandSrcHDLImmType(src1->getType()));
865 }
866 // adding to fix above no need to encode type if src0 is immediate and src1 is null reg
867 else if (!(inst->isMath() && src1->isNullReg() && src0->isImm()))
868 {
869 twoSrc.GetRegsource().SetSrc1Srctype(GetOperandSrcHDLType(src1->getType()));
870 }
871
872 if (src1->isImm())
873 {
874 MUST_BE_TRUE(inst->opcode() == G4_mov || src1->getTypeSize() != 8,
875 "only Mov is allowed for 64bit immediate");
876
877 SrcBuilder<G9HDL::EU_INSTRUCTION_SOURCES_REG_IMM,1>::EncodeSrcImmData(
878 twoSrc.GetImmsource(), src1);
879 }
880 else
881 {
882 if (src0->isImm())
883 {
884 // src1 must be null, and don't encode anything so it won't overwrite src0's imm value
885 MUST_BE_TRUE(src1->isNullReg(), "src1 must be null ARF if src0 is immediate");
886 }
887 else
888 {
889 SrcBuilder<G9HDL::EU_INSTRUCTION_SOURCES_REG_REG, 1>::EncodeEuInstructionSourcesReg(
890 inst, src1, twoSrc.GetRegsource()); //by reference
891 }
892 }
893
894 }
895
896 /// \brief Given a two-src mask, apply a patch for send instruction
897 ///
PatchSend(G4_INST * inst,G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC * twoSrc)898 void PatchSend(G4_INST* inst, G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC* twoSrc)
899 {
900 MUST_BE_TRUE(inst->getMsgDescRaw(), "expected raw descriptor");
901 uint32_t msgDesc = inst->getMsgDescRaw()->getExtendedDesc();
902 EncExtMsgDescriptor emd;
903 emd.ulData = msgDesc;
904
905 G9HDL::EU_INSTRUCTION_SEND* sendInstruction = (G9HDL::EU_INSTRUCTION_SEND*) twoSrc;
906 G9HDL::SFID sfid = (G9HDL::SFID) emd.ExtMsgDescriptor.TargetUnitId;
907
908 sendInstruction->SetSharedFunctionIdSfid(sfid);
909 sendInstruction->SetExdesc1111(msgDesc);
910
911 //this is a hack, but:
912 //fixme: this is missing in auto-header, currently need to override the acc write field
913 if (inst->isNoSrcDepSet())
914 {
915 //equivalent to: mybin->SetBits(bitsNoSrcDepSet_0, bitsNoSrcDepSet_1, 1);
916 sendInstruction->SetControlsB_Accwrctrl(G9HDL::ACCWRCTRL_UPDATE_ACC); //0x1
917 }
918
919 G9HDL::EOT eot = (G9HDL::EOT) emd.ExtMsgDescriptor.EndOfThread;
920 sendInstruction->GetMessage().SetEot(eot);
921 }
922
923 /// \brief EncodeMathControl
924 ///
PatchMath(G4_INST * inst,G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC * twoSrc)925 void PatchMath(G4_INST* inst, G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC* twoSrc)
926 {
927 MUST_BE_TRUE(inst->isMath(), "PatchMath must be called on math instruction.");
928
929 unsigned int MathControlValue = inst->asMathInst()->getMathCtrl();
930 unsigned MathFunction = MathControlValue & 0xf;
931
932 G9HDL::EU_INSTRUCTION_MATH* mathInstruction = (G9HDL::EU_INSTRUCTION_MATH*) twoSrc;
933 G9HDL::FC mathFunctionControl = (G9HDL::FC) MathFunction;
934 mathInstruction->SetFunctionControlFc(mathFunctionControl);
935
936 //fixme: what about partial precision bit?
937 //if (!mybin->GetIs3Src()) {
938 // mybin->SetBits(bitsMathFunction_0, bitsMathFunction_1, MathFunction);
939 // mybin->SetBits(bitsMathPartPrec_0, bitsMathPartPrec_1, MathPartPrec);
940 //}
941 }
942
943
Get3SrcLimitedType(G4_Type type)944 inline G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::DESTINATION_DATA_TYPE Get3SrcLimitedType(G4_Type type)
945 {
946 switch (type)
947 {
948 case Type_F:
949 return G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::DESTINATION_DATA_TYPE_F;
950 case Type_D:
951 return G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::DESTINATION_DATA_TYPE_D;
952 case Type_UD:
953 return G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::DESTINATION_DATA_TYPE_UD;
954 case Type_DF:
955 return G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::DESTINATION_DATA_TYPE_DF;
956 case Type_HF:
957 return G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::DESTINATION_DATA_TYPE_HF;
958 default:
959 break;
960 }
961 //default
962 return G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::DESTINATION_DATA_TYPE_F;
963 }
964
Get3SrcLimitedSrcType(G4_Type type)965 inline static G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::SOURCE_DATA_TYPE Get3SrcLimitedSrcType(G4_Type type)
966 {
967 switch (type)
968 {
969 case Type_F:
970 return G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::SOURCE_DATA_TYPE_F;
971 case Type_D:
972 return G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::SOURCE_DATA_TYPE_D;
973 case Type_UD:
974 return G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::SOURCE_DATA_TYPE_UD;
975 case Type_DF:
976 return G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::SOURCE_DATA_TYPE_DF;
977 case Type_HF:
978 return G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::SOURCE_DATA_TYPE_HF;
979 default:
980 break;
981 }
982 //default
983 return G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC::SOURCE_DATA_TYPE_F;
984 }
985
986 /// Gets align1 ternary instruction limited type, given execution type (integer/float)
Get3SrcAlign1LimitedSrcType(G4_Type type,G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::EXECUTION_DATATYPE isFloatExecutionType)987 inline static G9HDL::TERNARYALIGN1DATATYPE Get3SrcAlign1LimitedSrcType(
988 G4_Type type,
989 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::EXECUTION_DATATYPE isFloatExecutionType)
990 {
991 if (isFloatExecutionType == G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::EXECUTION_DATATYPE_FLOAT)
992 {
993 switch (type)
994 {
995 case Type_F:
996 return G9HDL::TERNARYALIGN1DATATYPE::TERNARYALIGN1DATATYPE_F;
997 case Type_DF:
998 return G9HDL::TERNARYALIGN1DATATYPE::TERNARYALIGN1DATATYPE_DF;
999 case Type_HF:
1000 return G9HDL::TERNARYALIGN1DATATYPE::TERNARYALIGN1DATATYPE_HF;
1001 case Type_NF:
1002 return G9HDL::TERNARYALIGN1DATATYPE::TERNARYALIGN1DATATYPE_NF;
1003 default:
1004 MUST_BE_TRUE(0, "wrong type for align1 ternary instruction with float execution type.");
1005 break;
1006 }
1007
1008 //Some reasonable default:
1009 return G9HDL::TERNARYALIGN1DATATYPE::TERNARYALIGN1DATATYPE_F;
1010 }
1011 else
1012 {
1013 switch (type)
1014 {
1015 case Type_UD:
1016 return G9HDL::TERNARYALIGN1DATATYPE::TERNARYALIGN1DATATYPE_UD;
1017 case Type_D:
1018 return G9HDL::TERNARYALIGN1DATATYPE::TERNARYALIGN1DATATYPE_D;
1019 case Type_UW:
1020 return G9HDL::TERNARYALIGN1DATATYPE::TERNARYALIGN1DATATYPE_UW;
1021 case Type_W:
1022 return G9HDL::TERNARYALIGN1DATATYPE::TERNARYALIGN1DATATYPE_W;
1023 case Type_UB:
1024 return G9HDL::TERNARYALIGN1DATATYPE::TERNARYALIGN1DATATYPE_UB;
1025 case Type_B:
1026 return G9HDL::TERNARYALIGN1DATATYPE::TERNARYALIGN1DATATYPE_B;
1027 default:
1028 MUST_BE_TRUE(0, "wrong type for align1 ternary instruction with integer execution type.");
1029 break;
1030 }
1031 //Some reasonable default:
1032 return G9HDL::TERNARYALIGN1DATATYPE::TERNARYALIGN1DATATYPE_UD;
1033 }
1034
1035 }
1036
1037
EncodeThreeSrcInst(G4_INST * inst,G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC & threeSrc)1038 inline void BinaryEncodingCNL::EncodeThreeSrcInst(G4_INST* inst, G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC& threeSrc)
1039 {
1040 G4_Operand *src0 = inst->getSrc(0);
1041 G4_Operand *src1 = inst->getSrc(1);
1042 G4_Operand *src2 = inst->getSrc(2);
1043 G4_Operand *dst = inst->getDst();
1044
1045 EncodeInstHeader(inst, threeSrc.Common.Header);
1046
1047 //threeSrc doesn't have OperandControls field, need to implement its dst encoding separately
1048
1049 DstBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC>::EncodeFlagReg(inst, threeSrc);
1050 DstBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC>::EncodeMaskCtrl(inst, threeSrc);
1051 {
1052 threeSrc.SetDestinationDataType(Get3SrcLimitedType(dst->getType()));
1053 threeSrc.SetSourceDataType(Get3SrcLimitedSrcType(src0->getType()));
1054 if (src1->getType() == Type_HF)
1055 {
1056 threeSrc.SetSource1Type(1);
1057 }
1058 if (src2->getType() == Type_HF)
1059 {
1060 threeSrc.SetSource2Type(1);
1061 }
1062
1063 G4_DstRegRegion* dst = inst->getDst();
1064
1065 //this is for 'special accumulators', encoded with channel enable..
1066 if (dst->isAccRegValid())
1067 {
1068 threeSrc.SetDestinationChannelEnable(dst->getAccRegSel());
1069 //NOTE: this one is special case for instructions that use special accumulators
1070 }
1071 else
1072 {
1073 G4_DstRegRegion *dstRegion = static_cast<G4_DstRegRegion*>(dst);
1074 threeSrc.SetDestinationChannelEnable(dstRegion->getWriteMask());
1075 }
1076
1077 if (EncodingHelper::GetDstRegFile(dst) != REG_FILE_A &&
1078 EncodingHelper::GetDstAddrMode(dst) == ADDR_MODE_IMMED)
1079 {
1080 uint32_t byteAddress = dst->getLinearizedStart();
1081
1082 threeSrc.SetDestinationRegisterNumber_DestinationRegisterNumber(byteAddress >> 5);
1083 //must be DWORD aligned
1084 //3 bits for subregnum
1085 threeSrc.SetDestinationSubregisterNumber((byteAddress >> 2) & 0x7);
1086 MUST_BE_TRUE(inst->isAligned16Inst(), "3src only support align16 mode");
1087 }
1088
1089 //src0
1090 {
1091 //EncodeSrc0RepCtrl
1092 G4_SrcRegRegion* src0Region = src0->asSrcRegRegion();
1093 G4_SrcRegRegion* src1Region = src1->asSrcRegRegion();
1094 G4_SrcRegRegion* src2Region = src2->asSrcRegRegion();
1095
1096 //char *swizzle = src0Region->getSwizzle();
1097 //if (swizzle[0] == 'r')
1098 // threeSrc.SetSource0_SourceReplicateControl(G9HDL::REPCTRL_REPLICATE_ACROSS_ALL_CHANNELS);
1099 //else
1100 // threeSrc.SetSource0_SourceReplicateControl(G9HDL::REPCTRL_NO_REPLICATION);
1101
1102 //source modifiers:
1103 SrcBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC, 0>::EncodeSrcModifier(inst, src0, threeSrc);
1104 SrcBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC, 1>::EncodeSrcModifier(inst, src1, threeSrc);
1105 SrcBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC, 2>::EncodeSrcModifier(inst, src2, threeSrc);
1106
1107 //rep control:
1108 SrcBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC, 0>::Encode3SrcReplicateControl(&threeSrc, src0Region);
1109 SrcBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC, 1>::Encode3SrcReplicateControl(&threeSrc, src1Region);
1110 SrcBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC, 2>::Encode3SrcReplicateControl(&threeSrc, src2Region);
1111
1112 //chan select:
1113 SrcBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC, 0>::EncodeSrcChanSelect(&threeSrc, inst, src0, src0Region);
1114 SrcBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC, 1>::EncodeSrcChanSelect(&threeSrc, inst, src1, src1Region);
1115 SrcBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC, 2>::EncodeSrcChanSelect(&threeSrc, inst, src2, src2Region);
1116
1117 SrcBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC, 0>::EncodeSrcRegNum3Src(inst, src0, threeSrc);
1118 SrcBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC, 1>::EncodeSrcRegNum3Src(inst, src1, threeSrc);
1119 SrcBuilder<G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC, 2>::EncodeSrcRegNum3Src(inst, src2, threeSrc);
1120 //register
1121 //sub-register
1122 }
1123 }
1124 }
1125
EncodeThreeSrcInstAlign1(G4_INST * inst,G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC & threeSrc)1126 inline void BinaryEncodingCNL::EncodeThreeSrcInstAlign1(G4_INST* inst, G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC& threeSrc)
1127 {
1128 G4_Operand* src0 = inst->getSrc(0);
1129 G4_Operand* src1 = inst->getSrc(1);
1130 G4_Operand* src2 = inst->getSrc(2);
1131 G4_DstRegRegion* dst = inst->getDst();
1132
1133 //Common instruction fields:
1134 EncodeInstHeader(inst, threeSrc.TheStructure.Common.Header);
1135 DstBuilder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC>::EncodeFlagReg(inst, threeSrc);
1136 DstBuilder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC>::EncodeMaskCtrl(inst, threeSrc);
1137
1138 MUST_BE_TRUE((IS_TYPE_FLOAT_ALL(src0->getType()) &&
1139 IS_TYPE_FLOAT_ALL(src1->getType()) &&
1140 IS_TYPE_FLOAT_ALL(src2->getType()) &&
1141 IS_TYPE_FLOAT_ALL(dst->getType()))
1142 ||
1143 (IS_TYPE_INT(src0->getType()) &&
1144 IS_TYPE_INT(src1->getType()) &&
1145 IS_TYPE_INT(src2->getType()) &&
1146 IS_TYPE_INT(dst->getType())), "No mixed mode in align1 ternary encoding.");
1147
1148 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::EXECUTION_DATATYPE execType =
1149 IS_TYPE_FLOAT_ALL(dst->getType()) ?
1150 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::EXECUTION_DATATYPE_FLOAT :
1151 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::EXECUTION_DATATYPE_INTEGER;
1152
1153 threeSrc.SetExecutionDatatype(execType);
1154
1155 //DST REGFILE
1156 switch (EncodingHelper::GetDstRegFile(dst))
1157 {
1158 case REG_FILE_R:
1159 threeSrc.SetDestinationRegisterFile(
1160 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::DESTINATION_REGISTER_FILE_GRF);
1161 break;
1162 case REG_FILE_A:
1163 threeSrc.SetDestinationRegisterFile(
1164 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::DESTINATION_REGISTER_FILE_ARF);
1165 break;
1166 default:
1167 MUST_BE_TRUE(0, "Invalid dst register file for for align1 ternary instruction (expected grf or arf).");
1168 break;
1169 }
1170
1171 //SRC modifiers:
1172 if (src0->isSrcRegRegion())
1173 {
1174 threeSrc.SetSource0Modifier(BinaryEncodingCNL::GetSrcHLDMod(src0->asSrcRegRegion()));
1175 }
1176 else
1177 {
1178 threeSrc.SetSource0Modifier(G9HDL::SRCMOD_NO_MODIFICATION);
1179 }
1180
1181 if (src1->isSrcRegRegion())
1182 {
1183 threeSrc.SetSource1Modifier(BinaryEncodingCNL::GetSrcHLDMod(src1->asSrcRegRegion()));
1184 }
1185 else
1186 {
1187 threeSrc.SetSource1Modifier(G9HDL::SRCMOD_NO_MODIFICATION);
1188 }
1189 if (src2->isSrcRegRegion())
1190 {
1191 threeSrc.SetSource2Modifier(BinaryEncodingCNL::GetSrcHLDMod(src2->asSrcRegRegion()));
1192 }
1193 else
1194 {
1195 threeSrc.SetSource2Modifier(G9HDL::SRCMOD_NO_MODIFICATION);
1196 }
1197
1198 //SRC0 regfile
1199 switch (EncodingHelper::GetSrcRegFile(src0))
1200 {
1201 case REG_FILE_R:
1202 threeSrc.SetSource0RegisterFile(
1203 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::SOURCE_0_REGISTER_FILE_GRF);
1204 break;
1205 case REG_FILE_I:
1206 threeSrc.SetSource0RegisterFile(
1207 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::SOURCE_0_REGISTER_FILE_IMM);
1208 break;
1209 case REG_FILE_A:
1210 MUST_BE_TRUE(src0->getType() == Type_NF, "Invalid register file for src0 in align1 ternary instruction (expected grf or imm).");
1211 threeSrc.SetSource0RegisterFile(
1212 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::SOURCE_0_REGISTER_FILE_ARF);
1213 break;
1214 default:
1215 break;
1216 }
1217
1218 //SRC1 regfile
1219 switch (EncodingHelper::GetSrcRegFile(src1))
1220 {
1221 case REG_FILE_R:
1222 threeSrc.SetSource1RegisterFile(
1223 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::SOURCE_1_REGISTER_FILE_GRF);
1224 break;
1225 case REG_FILE_A:
1226 threeSrc.SetSource1RegisterFile(
1227 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::SOURCE_1_REGISTER_FILE_ARF);
1228 break;
1229 default:
1230 MUST_BE_TRUE(0, "Invalid register file for src1 in align1 ternary instruction(expected grf or arf).");
1231 break;
1232 }
1233
1234 //SRC2 regfile
1235 switch (EncodingHelper::GetSrcRegFile(src2))
1236 {
1237 case REG_FILE_R:
1238 threeSrc.SetSource2RegisterFile(
1239 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::SOURCE_2_REGISTER_FILE_GRF);
1240 break;
1241 case REG_FILE_I:
1242 threeSrc.SetSource2RegisterFile(
1243 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::SOURCE_2_REGISTER_FILE_IMM);
1244 break;
1245 default:
1246 MUST_BE_TRUE(0, "Invalid register file for src2 in align1 ternary instruction(expected grf or imm).");
1247 break;
1248 }
1249
1250 threeSrc.SetDestinationDatatype(Get3SrcAlign1LimitedSrcType(dst->getType(), execType));
1251
1252 // Dst reg/subreg
1253 switch (EncodingHelper::GetDstRegFile(dst))
1254 {
1255 case REG_FILE_R:
1256 {
1257 uint32_t byteAddress = dst->getLinearizedStart();
1258 if (kernel.fg.builder->encodeAccRegSelAsAlign1() && dst->isAccRegValid())
1259 {
1260 // special accumulator region (acc2-acc9) is encoded as part of subreg
1261 MUST_BE_TRUE((byteAddress & 0x1F) == 0, "subreg must be 0 for dst with special accumulator");
1262 threeSrc.SetDestinationSpecialAcc(dst->getAccRegSel());
1263 }
1264 else
1265 {
1266 threeSrc.SetDestinationSubregisterNumber(byteAddress & 0x1f);
1267 }
1268 threeSrc.SetDestinationRegisterNumber(byteAddress >> 5);
1269 break;
1270 }
1271 case REG_FILE_A:
1272 {
1273 bool valid;
1274 unsigned short RegFile = (unsigned short)EncodingHelper::GetDstArchRegType(dst); //4 bits
1275 unsigned short RegNumValue = dst->ExRegNum(valid);
1276
1277 // 7654|3210
1278 // RegF|RegNumVal
1279 unsigned short EncodedRegNum = RegFile << 4;
1280 EncodedRegNum = EncodedRegNum | (RegNumValue & 0xF);
1281 threeSrc.SetDestinationRegisterNumber(EncodedRegNum);
1282 break;
1283 }
1284 default:
1285 MUST_BE_TRUE(0, "Invalid register file for dst in align1 ternary instruction(expected grf or acc).");
1286 break;
1287 }
1288
1289
1290 switch (dst->getHorzStride())
1291 {
1292 case 1:
1293 threeSrc.SetDestinationHorizontalStride(G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::DESTINATION_HORIZONTAL_STRIDE_1_ELEMENT);
1294 break;
1295 case 2:
1296 threeSrc.SetDestinationHorizontalStride(G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::DESTINATION_HORIZONTAL_STRIDE_2_ELEMENT);
1297 break;
1298 case UNDEFINED_SHORT:
1299 MUST_BE_TRUE(false, "Dst horizontal stride for align1 ternary instruction is undefined.");
1300 threeSrc.SetDestinationHorizontalStride(G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC::DESTINATION_HORIZONTAL_STRIDE_1_ELEMENT);
1301 break;
1302 default:
1303 MUST_BE_TRUE(false, "Wrong dst horizontal stride for align1 ternary instruction (is neither 1 nor 2).");
1304 break;
1305 }
1306
1307
1308 //SRC0 fields
1309 //////////////////////////////////////////////////////////////////////////
1310 //////////////////////////////////////////////////////////////////////////
1311 threeSrc.SetSource0Datatype(Get3SrcAlign1LimitedSrcType(src0->getType(), execType));
1312
1313 if (src0->isSrcRegRegion())
1314 {
1315 const RegionDesc *regdesc0 = src0->asSrcRegRegion()->getRegion();
1316 MUST_BE_TRUE(regdesc0, "Align1 ternary encoder: src0 region desc for ternary instruction is null!");
1317
1318 //look for <N;N,1> contiguous region
1319 if (regdesc0->vertStride > 8)
1320 {
1321 //TODO: should we care about this case?
1322 MUST_BE_TRUE(0, "Align1 3 src instruction with vertStride>8 not supported yet.");
1323 }
1324 else
1325 {
1326 //src0: vstride
1327 switch (regdesc0->vertStride)
1328 {
1329 case 0:
1330 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 0>::
1331 SetSourceVerticalStride(&threeSrc, G9HDL::TERNARYALIGN1VERTSTRIDE_0_ELEMENTS);
1332 break;
1333 case 2:
1334 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 0>::
1335 SetSourceVerticalStride(&threeSrc, G9HDL::TERNARYALIGN1VERTSTRIDE_2_ELEMENTS);
1336 break;
1337 case 4:
1338 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 0>::
1339 SetSourceVerticalStride(&threeSrc, G9HDL::TERNARYALIGN1VERTSTRIDE_4_ELEMENTS);
1340 break;
1341 case 8:
1342 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 0>::
1343 SetSourceVerticalStride(&threeSrc, G9HDL::TERNARYALIGN1VERTSTRIDE_8_ELEMENTS);
1344 break;
1345 default:
1346 MUST_BE_TRUE(false, "wrong vertical stride for ternary align1 instruction at src0!");
1347 break;
1348 }
1349
1350 //src0: hstride
1351 SrcBuilder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 0>::EncodeSrcHorzStride(
1352 inst,
1353 &threeSrc,
1354 regdesc0,
1355 src0);
1356 }
1357
1358 MUST_BE_TRUE(EncodingHelper::GetSrcRegFile(src0) != REG_FILE_I, "Align1 ternary: src0 register file must not be immediate if src region is present. ");
1359 if (EncodingHelper::GetSrcRegFile(src0) != REG_FILE_A)
1360 {
1361 uint32_t byteAddress = src0->getLinearizedStart();
1362 threeSrc.SetSource0RegisterNumber_SourceRegisterNumber(byteAddress >> 5);
1363 if (kernel.fg.builder->encodeAccRegSelAsAlign1() && src0->isAccRegValid())
1364 {
1365 MUST_BE_TRUE((byteAddress & 0x1F) == 0, "subreg must be 0 for source with special accumualators");
1366 threeSrc.SetSource0SpecialAcc(src0->getAccRegSel());
1367 }
1368 else
1369 {
1370 threeSrc.SetSource0SubregisterNumber_SourceSubRegisterNumber(byteAddress & 0x1f);
1371 }
1372 }
1373 else
1374 {
1375 MUST_BE_TRUE(src0->getType() == Type_NF, "only NF type src0 can be accumulator");
1376 //encode acc
1377 bool valid;
1378 unsigned short RegFile = (unsigned short)EncodingHelper::GetSrcArchRegType(src0); //4 bits
1379 unsigned short RegNumValue = src0->asSrcRegRegion()->ExRegNum(valid);
1380
1381 // 7654|3210
1382 // RegF|RegNumVal
1383 unsigned short EncodedRegNum = RegFile << 4;
1384 EncodedRegNum = EncodedRegNum | (RegNumValue & 0xF);
1385 threeSrc.SetSource0RegisterNumber_SourceRegisterNumber(EncodedRegNum);
1386 }
1387 }
1388 else
1389 {
1390 MUST_BE_TRUE(EncodingHelper::GetSrcRegFile(src0) == REG_FILE_I,
1391 "Align1 ternary: src0 reg file must be immediate if operand is immediate.");
1392
1393 G4_Imm *isrc = (G4_Imm *)src0->asImm();
1394 threeSrc.SetSource0ImmediateValue((uint32_t)isrc->getImm());
1395 }
1396
1397 //SRC1 fields
1398 //////////////////////////////////////////////////////////////////////////
1399 //////////////////////////////////////////////////////////////////////////
1400 threeSrc.SetSource1Datatype(Get3SrcAlign1LimitedSrcType(src1->getType(), execType));
1401
1402 MUST_BE_TRUE(EncodingHelper::GetSrcRegFile(src1) != REG_FILE_I,
1403 "Align1 ternary:src1 immediate register file not supported by definition.");
1404 if (EncodingHelper::GetSrcRegFile(src1) != REG_FILE_A)
1405 {
1406 uint32_t byteAddress = src1->getLinearizedStart();
1407 threeSrc.SetSource1RegisterNumber_SourceRegisterNumber(byteAddress >> 5);
1408 if (kernel.fg.builder->encodeAccRegSelAsAlign1() && src1->isAccRegValid())
1409 {
1410 MUST_BE_TRUE((byteAddress & 0x1F) == 0, "subreg must be 0 for source with special accumualators");
1411 threeSrc.SetSource1SpecialAcc(src1->getAccRegSel());
1412 }
1413 else
1414 {
1415 threeSrc.SetSource1SubregisterNumber_SourceSubRegisterNumber(byteAddress & 0x1f);
1416 }
1417 }
1418 else
1419 {
1420 //encode acc
1421 bool valid;
1422 unsigned short RegFile = (unsigned short)EncodingHelper::GetSrcArchRegType(src1); //4 bits
1423 unsigned short RegNumValue = src1->asSrcRegRegion()->ExRegNum(valid);
1424
1425 // 7654|3210
1426 // RegF|RegNumVal
1427 unsigned short EncodedRegNum = RegFile << 4;
1428 EncodedRegNum = EncodedRegNum | (RegNumValue & 0xF);
1429 threeSrc.SetSource1RegisterNumber_SourceRegisterNumber(EncodedRegNum);
1430 }
1431
1432 const RegionDesc *regdesc1 = src1->asSrcRegRegion()->getRegion();
1433 MUST_BE_TRUE(regdesc1,
1434 "Align1 ternary encoder: src1 region desc for ternary instruction is null!");
1435
1436 //look for <N;N,1> contiguous region
1437 if (regdesc1->vertStride > 8)
1438 {
1439 //TODO: should we care about this case?
1440 MUST_BE_TRUE(0, "align1 3 src instruction with vertStride>8 not supported yet.");
1441 }
1442 else
1443 {
1444 SrcBuilder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 1>::EncodeSrcHorzStride(
1445 inst,
1446 &threeSrc,
1447 regdesc1,
1448 src1);
1449
1450 //src1: vstride
1451 switch (regdesc1->vertStride)
1452 {
1453 case 0:
1454 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 1>::
1455 SetSourceVerticalStride(&threeSrc, G9HDL::TERNARYALIGN1VERTSTRIDE_0_ELEMENTS);
1456 break;
1457 case 2:
1458 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 1>::
1459 SetSourceVerticalStride(&threeSrc, G9HDL::TERNARYALIGN1VERTSTRIDE_2_ELEMENTS);
1460 break;
1461 case 4:
1462 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 1>::
1463 SetSourceVerticalStride(&threeSrc, G9HDL::TERNARYALIGN1VERTSTRIDE_4_ELEMENTS);
1464 break;
1465 case 8:
1466 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 1>::
1467 SetSourceVerticalStride(&threeSrc, G9HDL::TERNARYALIGN1VERTSTRIDE_8_ELEMENTS);
1468 break;
1469 default:
1470 MUST_BE_TRUE(false, "wrong vertical stride for ternary align1 instruction at src0!");
1471 break;
1472 }
1473 }
1474
1475 //SRC2 fields
1476 //////////////////////////////////////////////////////////////////////////
1477 //////////////////////////////////////////////////////////////////////////
1478 threeSrc.SetSource2Datatype(Get3SrcAlign1LimitedSrcType(src2->getType(), execType));
1479
1480 if (src2->isSrcRegRegion())
1481 {
1482 const RegionDesc *regdesc2 = src2->asSrcRegRegion()->getRegion();
1483 MUST_BE_TRUE(regdesc2,
1484 "Align1 ternary instruction: src2 region desc for instruction is null!");
1485 MUST_BE_TRUE(EncodingHelper::GetSrcRegFile(src2) != REG_FILE_I,
1486 "Align1 ternary encoder: src2 reg file is immediate even if src region present.");
1487
1488 //src2 reg/subreg
1489
1490 if (EncodingHelper::GetSrcRegFile(src2) != REG_FILE_A)
1491 {
1492 uint32_t byteAddress = src2->getLinearizedStart();
1493 threeSrc.SetSource2RegisterNumber_SourceRegisterNumber(byteAddress >> 5);
1494 if (kernel.fg.builder->encodeAccRegSelAsAlign1() && src2->isAccRegValid())
1495 {
1496 MUST_BE_TRUE((byteAddress & 0x1F) == 0, "subreg must be 0 for source with special accumualators");
1497 threeSrc.SetSource2SpecialAcc(src2->getAccRegSel());
1498 }
1499 else
1500 {
1501 threeSrc.SetSource2SubregisterNumber_SourceSubRegisterNumber(byteAddress & 0x1f);
1502 }
1503 }
1504
1505 switch (regdesc2->horzStride)
1506 {
1507 case 0:
1508 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 2>::
1509 SetSourceHorizontalStride(&threeSrc, G9HDL::HORZSTRIDE_0_ELEMENTS);
1510 break;
1511 case 1:
1512 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 2>::
1513 SetSourceHorizontalStride(&threeSrc, G9HDL::HORZSTRIDE_1_ELEMENTS);
1514 break;
1515 case 2:
1516 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 2>::
1517 SetSourceHorizontalStride(&threeSrc, G9HDL::HORZSTRIDE_2_ELEMENTS);
1518 break;
1519 case 4:
1520 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC, 2>::
1521 SetSourceHorizontalStride(&threeSrc, G9HDL::HORZSTRIDE_4_ELEMENTS);
1522 break;
1523 default:
1524 MUST_BE_TRUE(false, "Align1 ternary: src2 has non-encodable horizontal stride (accepted: 0,1,2,4).");
1525 break;
1526 }
1527 }
1528 else
1529 {
1530 MUST_BE_TRUE(EncodingHelper::GetSrcRegFile(src2) == REG_FILE_I,
1531 "Align1 ternary: src2 reg file must be immediate if operand is immediate.");
1532
1533 G4_Imm *isrc = (G4_Imm *)src2->asImm();
1534 threeSrc.SetSource2ImmediateValue((uint32_t)isrc->getImm());
1535 }
1536 }
1537
1538 /// \brief Get compaction control bit from already encoded binary instruction
1539 ///
GetCompactCtrl(BinInst * mybin)1540 uint32_t BinaryEncodingCNL::GetCompactCtrl(BinInst *mybin)
1541 {
1542 G9HDL::EU_INSTRUCTION_HEADER* ptr = (G9HDL::EU_INSTRUCTION_HEADER*) &(mybin->DWords);
1543 return (uint32_t) ptr->GetControl().GetControlsB_Cmptctrl();
1544 }
1545
1546 /// \brief Set compaction control bit. TODO: how to write to mybin->DWords. below doesn't work
1547 ///
SetCompactCtrl(BinInst * mybin,uint32_t value)1548 void BinaryEncodingCNL::SetCompactCtrl (BinInst *mybin, uint32_t value)
1549 {
1550 G9HDL::EU_INSTRUCTION_HEADER* ptr = (G9HDL::EU_INSTRUCTION_HEADER*) &(mybin->DWords);
1551 ptr->GetControl().SetControlsB_Cmptctrl(G9HDL::CMPTCTRL_COMPACTED);
1552 }
1553
1554 /// \brief Encode JIP and(or) UIP at their respective places
1555 ///
1556 ///Comments are left from original binary encoder
1557 ///TODO: move as a class method
SetBranchOffsets(G4_INST * inst,uint32_t JIP,uint32_t UIP)1558 void BinaryEncodingCNL::SetBranchOffsets(G4_INST* inst,
1559 uint32_t JIP,
1560 uint32_t UIP)
1561 {
1562 BinInst *mybin = inst->getBinInst();
1563 G4_opcode opc = inst->opcode();
1564
1565 {
1566 if (opc == G4_if ||
1567 opc == G4_break ||
1568 opc == G4_cont ||
1569 opc == G4_halt ||
1570 opc == G4_goto ||
1571 opc == G4_else)
1572 {
1573 //cast binary as branch two src
1574 //note: if an instruction has both JIP and UIP, then
1575 //only src0 type and regfile are being set (higher dword is occupied)
1576
1577 G9HDL::EU_INSTRUCTION_BRANCH_TWO_SRC* twoSrc =
1578 (G9HDL::EU_INSTRUCTION_BRANCH_TWO_SRC*) mybin->DWords;
1579
1580 twoSrc->GetOperandControl().SetSrc0Regfile(G9HDL::REGFILE_IMM);
1581 twoSrc->GetOperandControl().SetSrc0Srctype_Imm(GetOperandSrcHDLImmType(Type_D));
1582 twoSrc->SetJip(JIP);
1583 twoSrc->SetUip(UIP);
1584 //SetBranchJIPUIP(mybin, JIP, UIP);
1585 }
1586 else
1587 {
1588 G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC* oneSrc =
1589 (G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC*) mybin->DWords;
1590
1591 oneSrc->SetSrc1Regfile(G9HDL::REGFILE_IMM);
1592 oneSrc->SetSrc1Srctype(GetOperandSrcHDLImmType(Type_D));
1593 oneSrc->SetJip(JIP);
1594 //SetBranchJIP(mybin, JIP);
1595 }
1596 }
1597 }
1598
1599 /// \brief encodes JIP and(or) UIP offsets
1600 ///
1601 /// This is done in this separate method, and not during the main
1602 /// encoding phase, since the real jump offsets are visible only
1603 /// now.
EncodeConditionalBranches(G4_INST * inst,uint32_t insOffset)1604 bool BinaryEncodingCNL::EncodeConditionalBranches(G4_INST *inst,
1605 uint32_t insOffset)
1606 {
1607 std::string jipLabel;
1608 std::string uipLabel;
1609 int32_t jipOffset = 0;
1610 int32_t uipOffset = 0;
1611 G4_opcode op = inst->opcode();
1612
1613 // while and case only have JIP for all platforms
1614 // break, cont and halt have both JIP and UIP for all platforms
1615 if (op == G4_if ||
1616 op == G4_else ||
1617 op == G4_endif ||
1618 op == G4_while ||
1619 op == G4_break ||
1620 op == G4_cont ||
1621 op == G4_halt ||
1622 op == G4_goto ||
1623 op == G4_join)
1624 {
1625 G4_Label *jip = inst->asCFInst()->getJip();
1626 if (jip)
1627 {
1628 int32_t info = GetLabelInfo(jip);
1629 if (info == -1)
1630 {
1631 return false;
1632 }
1633 jipOffset = info - insOffset;
1634 jipOffset *= (int32_t)JUMP_INST_COUNT_SIZE;
1635 }
1636 else if (op == G4_while ||
1637 op == G4_endif ||
1638 op == G4_join)
1639 {
1640 {
1641 BinInst *mybin = inst->getBinInst();
1642 G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC* oneSrc =
1643 (G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC*) mybin->DWords;
1644
1645 oneSrc->SetSrc1Regfile(G9HDL::REGFILE_IMM);
1646 oneSrc->SetSrc1Srctype(GetOperandSrcHDLImmType(Type_D));
1647 }
1648 }
1649 }
1650
1651 // halt has both JIP and UIP on all platforms
1652 // else has JIP for all platforms; else has UIP for BDW only
1653 if (op == G4_break ||
1654 op == G4_cont ||
1655 op == G4_halt ||
1656 op == G4_if ||
1657 op == G4_else ||
1658 op == G4_goto)
1659 {
1660 G4_Label* uip = inst->asCFInst()->getUip();
1661 if (uip)
1662 {
1663 int32_t info = GetLabelInfo(uip);
1664 if (info == -1)
1665 {
1666 return false;
1667 }
1668 uipOffset = info - insOffset;
1669 uipOffset *= (uint32_t)JUMP_INST_COUNT_SIZE;
1670 }
1671 }
1672
1673 if (op == G4_endif && jipOffset == 0)
1674 {
1675 jipOffset = INST_SIZE;
1676 }
1677
1678 if (jipOffset != 0 || uipOffset != 0)
1679 {
1680 SetBranchOffsets(inst, jipOffset, uipOffset);
1681 }
1682
1683 if (op == G4_jmpi &&
1684 inst->getSrc(0) &&
1685 inst->getSrc(0)->isLabel())
1686 {
1687 // find the label's IP count
1688 G4_Operand *opnd = inst->getSrc(0);
1689 BinInst * mybin = inst->getBinInst();
1690 // Calculate the address offset
1691 // Label has the same IP count as the following instruction,
1692 // "break 1" is to the fall through instruction
1693 int32_t info = GetLabelInfo(opnd->asLabel());
1694 if (info == -1)
1695 {
1696 return false;
1697 }
1698 int32_t jmpOffset = info - insOffset;
1699 if (GetCompactCtrl(mybin))
1700 jmpOffset -= 1;
1701 else
1702 jmpOffset -= 2;
1703
1704 jmpOffset *= (int32_t)JUMP_INST_COUNT_SIZE;
1705
1706 //FIXME: add compaction support
1707 //if (GetCompactCtrl(mybin))
1708 //{
1709 // SetCmpSrc1RegNum(mybin, jmpOffset & 0xff); // 63:56
1710 // SetCmpSrc1Index(mybin, (jmpOffset >> 8)& 0x1f);
1711 //}
1712 //else
1713 {
1714 BinInst *mybin = inst->getBinInst();
1715 G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC* oneSrc =
1716 (G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC*) mybin->DWords;
1717
1718 oneSrc->SetSrc1Regfile(G9HDL::REGFILE_IMM);
1719 oneSrc->SetSrc1Srctype(GetOperandSrcHDLImmType(Type_D));
1720 oneSrc->SetJip((uint32_t)jmpOffset);
1721 }
1722 }
1723
1724 if (op == G4_call &&
1725 inst->getSrc(0) &&
1726 inst->getSrc(0)->isLabel())
1727 {
1728 G4_Operand *opnd = inst->getSrc(0);
1729 int32_t info = GetLabelInfo(opnd->asLabel());
1730 if (info == -1)
1731 {
1732 return false;
1733 }
1734
1735 int32_t jmpOffset = info - insOffset;
1736
1737 {
1738 jmpOffset *= (int32_t)JUMP_INST_COUNT_SIZE;
1739 }
1740
1741 BinInst *mybin = inst->getBinInst();
1742 G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC* oneSrc =
1743 (G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC*) mybin->DWords;
1744
1745 oneSrc->SetSource0_SourceVerticalStride(G9HDL::VERTSTRIDE_2_ELEMENTS);
1746 oneSrc->SetSource0_SourceWidth(G9HDL::WIDTH_4_ELEMENTS);
1747 oneSrc->SetSource0_SourceHorizontalStride(G9HDL::HORZSTRIDE_1_ELEMENTS);
1748
1749 oneSrc->SetSrc1Regfile(G9HDL::REGFILE_IMM);
1750 oneSrc->SetSrc1Srctype(GetOperandSrcHDLImmType(Type_D));
1751 oneSrc->SetJip((uint32_t)jmpOffset);
1752
1753 //TODO: do not forget about compacted variant
1754 }
1755 return true;
1756 }
1757
1758 /// \brief initializes auto-header generated structure for split send instruction
1759 ///
EncodeSplitSend(G4_INST * inst,G9HDL::EU_INSTRUCTION_SENDS & sends)1760 BinaryEncodingCNL::Status BinaryEncodingCNL::EncodeSplitSend(G4_INST* inst, G9HDL::EU_INSTRUCTION_SENDS& sends)
1761 {
1762 Status myStatus = SUCCESS;
1763
1764 G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC* twoSrcMirror
1765 = (G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC*) &sends;
1766
1767 EncodeInstHeader(inst, twoSrcMirror->Common.Header);
1768
1769 //encode dst part
1770 //trimmed down EncodeOperandDst
1771 {
1772 DstBuilder<G9HDL::EU_INSTRUCTION_SENDS>::EncodeFlagReg(inst, sends);
1773 DstBuilder<G9HDL::EU_INSTRUCTION_SENDS>::EncodeMaskCtrl(inst, sends);
1774 DstBuilder<G9HDL::EU_INSTRUCTION_SENDS>::EncodeOperandDstType(inst, sends);
1775 DstBuilder<G9HDL::EU_INSTRUCTION_SENDS>::EncodeDstAddrMode(inst, sends);
1776
1777 G4_DstRegRegion* dst = inst->getDst();
1778
1779 //encode dst reg file
1780 //note: for sends, we have only one bit available for dst reg file
1781 {
1782 switch (EncodingHelper::GetDstRegFile(dst))
1783 {
1784 case REG_FILE_R:
1785 sends.SetDestinationRegisterFile(G9HDL::REGFILE_GRF); break;
1786 case REG_FILE_A:
1787 sends.SetDestinationRegisterFile(G9HDL::REGFILE_ARF); break;
1788 default:
1789 MUST_BE_TRUE(0 ," Invalid register file for split-send.");
1790 break;
1791 }
1792 }
1793
1794 if (EncodingHelper::GetDstAddrMode(dst)==ADDR_MODE_INDIR)
1795 {
1796 // addr subregister
1797 // addr immediate
1798 bool subValid;
1799 uint16_t IndAddrRegSubNumValue = dst->ExIndSubRegNum(subValid);
1800 int16_t IndAddrImmedValue = dst->ExIndImmVal();
1801
1802 sends.SetDestinationAddressSubregisterNumber(IndAddrRegSubNumValue);
1803 sends.SetDestinationAddressImmediate84((IndAddrImmedValue >> 4) & 0x1F);
1804 sends.SetDestinationAddressImmediateSign9((IndAddrImmedValue >> 9) & 0x1);
1805 }
1806 else
1807 {
1808 if (EncodingHelper::GetDstRegFile(dst) != REG_FILE_A)
1809 {
1810 uint32_t byteAddress = dst->getLinearizedStart();
1811 MUST_BE_TRUE(byteAddress % 16 == 0, "dst for sends/sendsc must be oword-aligned");
1812
1813 sends.SetDestinationRegisterNumber(byteAddress >> 5);
1814 sends.SetDestinationSubregisterNumber4((byteAddress >> 4) & 0x1);
1815 }
1816 }
1817
1818 }
1819
1820 //encode src1
1821 {
1822 G4_Operand *src1 = inst->getSrc(1);
1823
1824 //src1 reg file - 1 bit
1825 switch (EncodingHelper::GetSrcRegFile(src1))
1826 {
1827 case REG_FILE_R:
1828 sends.SetSrc1Regfile(G9HDL::REGFILE_GRF); break;
1829 case REG_FILE_A:
1830 sends.SetSrc1Regfile(G9HDL::REGFILE_ARF); break;
1831 default:
1832 MUST_BE_TRUE(0 ," Invalid register file for split-send.");
1833 break;
1834 }
1835
1836 G4_SrcRegRegion* src1Region = src1->asSrcRegRegion();
1837
1838 SrcBuilder<G9HDL::EU_INSTRUCTION_SENDS, 1>::EncodeSrcAddrMode(&sends, inst, src1);
1839 if (EncodingHelper::GetSrcAddrMode(src1)==ADDR_MODE_INDIR)
1840 {
1841 bool subValid;
1842 uint16_t IndAddrRegSubNumValue = src1Region->ExIndSubRegNum(subValid);
1843 int16_t IndAddrImmedValue = src1Region->ExIndImmVal();
1844
1845 sends.SetSource1_SourceAddressImmediate84((IndAddrImmedValue >> 4) & 0x1F);
1846 sends.SetSource1_SourceAddressImmediateSign9((IndAddrImmedValue >> 9) & 0x1);
1847 sends.SetSource1_SourceAddressSubregisterNumber_0(IndAddrRegSubNumValue);
1848 }
1849 else
1850 {
1851 uint32_t byteAddress = src1->getLinearizedStart();
1852 MUST_BE_TRUE(byteAddress % 32 == 0, "src1 for sends/sendsc must be GRF-aligned");
1853 sends.SetSource1_SourceRegisterNumber(byteAddress >> 5);
1854 //mybin->SetBits(bitsSendsSrc1RegNum_0, bitsSendsSrc1RegNum_1, byteAddress >> 5);
1855
1856 }
1857 }
1858
1859 //encode src0
1860 {
1861 G4_SrcRegRegion *src0 = inst->getSrc(0)->asSrcRegRegion();
1862 //note: no regfile for src0
1863
1864 SrcBuilder<G9HDL::EU_INSTRUCTION_SENDS, 0>::EncodeSrcAddrMode(&sends, inst, src0);
1865
1866 if (EncodingHelper::GetSrcAddrMode(src0)==ADDR_MODE_INDIR)
1867 {
1868 bool subValid;
1869 uint16_t IndAddrRegSubNumValue = src0->ExIndSubRegNum(subValid);
1870 int16_t IndAddrImmedValue = src0->ExIndImmVal();
1871
1872 sends.SetSource0_SourceAddressImmediate84((IndAddrImmedValue >> 4) & 0x1F);
1873 sends.SetSource0_SourceAddressImmediateSign9((IndAddrImmedValue >> 9) & 0x1);
1874 sends.SetSource0_SourceAddressSubregisterNumber(IndAddrRegSubNumValue);
1875 }
1876 else
1877 {
1878 uint32_t byteAddress = src0->getLinearizedStart();
1879 MUST_BE_TRUE(byteAddress % 32 == 0, "src1 for sends/sendsc must be GRF-aligned");
1880 sends.SetSource0_SourceRegisterNumber(byteAddress >> 5);
1881 //mybin->SetBits(bitsSendsSrc1RegNum_0, bitsSendsSrc1RegNum_1, byteAddress >> 5);
1882
1883 }
1884 }
1885
1886 //encode src2
1887 {
1888 G4_Operand *src2 = inst->getSrc(2);
1889 if (src2 == NULL)
1890 {
1891 return FAILURE;
1892 }
1893
1894 if (src2->isImm())
1895 {
1896 sends.SetSelreg32desc(0);
1897 sends.GetMessage().GetDWORD(0) = (uint32_t) src2->asImm()->getInt();
1898 }
1899 else if (src2->isSrcRegRegion() && src2->asSrcRegRegion()->isA0())
1900 {
1901 sends.SetSelreg32desc(1);
1902 }
1903 }
1904
1905 //Patch SFID and EOT
1906 {
1907 MUST_BE_TRUE(inst->getMsgDescRaw(), "expected raw descriptor");
1908 uint32_t msgDesc = inst->getMsgDescRaw()->getExtendedDesc();
1909 EncExtMsgDescriptor emd;
1910 emd.ulData = msgDesc;
1911
1912 G9HDL::SFID sfid = (G9HDL::SFID) emd.ExtMsgDescriptor.TargetUnitId;
1913 sends.SetSharedFunctionIdSfid(sfid);
1914
1915 G9HDL::EOT eot = (G9HDL::EOT) emd.ExtMsgDescriptor.EndOfThread;
1916 sends.GetMessage().SetEot(eot);
1917
1918 // additional extended msg desc to be encoded
1919 sends.SetExdesc96(msgDesc);
1920 sends.SetExdesc3116(msgDesc);
1921 sends.SetExdesc1111(msgDesc);
1922
1923 // encoding for src3 A0 is done in DoAllEncodingSplitSEND later on
1924 }
1925
1926 //this is a hack, but:
1927 //fixme: this is missing in auto-header, currently need to override the acc write field
1928 if (inst->isNoSrcDepSet())
1929 {
1930 //equivalent to: mybin->SetBits(bitsNoSrcDepSet_0, bitsNoSrcDepSet_1, 1);
1931 sends.SetControlsB_Accwrctrl(G9HDL::ACCWRCTRL_UPDATE_ACC); //0x1
1932 }
1933
1934 return myStatus;
1935 }
1936
1937 /// \brief Do customized encoding of WAIT instruction
1938 ///
DoAllEncodingWAIT(G4_INST * inst)1939 BinaryEncodingCNL::Status BinaryEncodingCNL::DoAllEncodingWAIT(G4_INST* inst)
1940 {
1941 Status myStatus = SUCCESS;
1942
1943 G9HDL::EU_INSTRUCTION_BASIC_ONE_SRC oneSrc;
1944
1945 oneSrc.Init();
1946
1947 EncodeInstHeader(inst, oneSrc.Common.Header);
1948 EncodeOperandDst(inst, oneSrc.Common.OperandControls);
1949 G4_Operand *src0 = inst->getSrc(0);
1950
1951 //EncodeSrc0RegFile
1952 oneSrc.GetOperandControls().SetSrc0Regfile(TranslateVisaToHDLRegFile(EncodingHelper::GetSrcRegFile(src0)));
1953
1954 //EncodeSrc0Type
1955 MUST_BE_TRUE(!src0->isImm(), "src0 must not be immediate in WAIT instruction!");
1956 {
1957 oneSrc.GetOperandControls().SetSrc0Srctype(GetOperandSrcHDLType(src0->getType()));
1958 }
1959
1960 SrcBuilder<G9HDL::EU_INSTRUCTION_SOURCES_REG,0>::EncodeEuInstructionSourcesReg(
1961 inst, src0, oneSrc. GetRegsource()); // by reference
1962
1963 //Dst patching:
1964
1965 RegFile regFile = EncodingHelper::GetSrcRegFile(src0);
1966 MUST_BE_TRUE(regFile == REG_FILE_A, "WAIT instruction source has reg file different than ARF!");
1967 oneSrc.Common.OperandControls.SetDestinationRegisterFile(
1968 TranslateVisaToHDLRegFile(regFile));
1969
1970 if (regFile == REG_FILE_A)
1971 {
1972 bool valid;
1973 G4_SrcRegRegion* src0Region = src0->asSrcRegRegion();
1974 unsigned short RegFile = (unsigned short)EncodingHelper::GetSrcArchRegType(src0); //4 bits
1975 unsigned short RegNumValue = src0Region->ExRegNum(valid);
1976 unsigned short EncodedRegNum = PackArchRegTypeAndArchRegFile(RegFile, RegNumValue);
1977
1978 oneSrc.Common.OperandControls.GetDestinationRegisterRegion_Align1().
1979 SetDestinationRegisterNumber_DestinationRegisterNumber(EncodedRegNum);
1980
1981 {
1982 bool subValid;
1983 unsigned short RegSubNumValue = src0Region->ExSubRegNum(subValid);
1984 unsigned short ElementSizeValue = EncodingHelper::GetElementSizeValue(src0);
1985 uint32_t regOffset = RegSubNumValue * ElementSizeValue;
1986
1987 if (inst->isAligned1Inst())
1988 {
1989 //sub-register number: 32 byte address (5 bits encoding) within a GRF
1990 oneSrc.Common.OperandControls.GetDestinationRegisterRegion_Align1().
1991 SetDestinationSubregisterNumber_DestinationSubRegisterNumber((WORD)regOffset);
1992 } else { //align 16
1993 //sub-register number: first/second 16 byte part of 32 byte address. Encoded with 1 bit.
1994 // 9876543210
1995 // regn|x0000
1996 //opnds.GetDestinationRegisterRegion_Align16().SetDestinationSubregisterNumber((regOffset >> 4) & 0x1);
1997 oneSrc.Common.OperandControls.GetDestinationRegisterRegion_Align16().
1998 SetDestinationSubregisterNumber((WORD)regOffset);
1999 }
2000 }
2001
2002 }
2003
2004
2005 oneSrc.Common.OperandControls.
2006 GetDestinationRegisterRegion_Align1().
2007 SetDestinationHorizontalStride(G9HDL::HORZSTRIDE_1_ELEMENTS);
2008
2009 oneSrc.Common.OperandControls.SetDestinationAddressingMode(
2010 TranslateVisaToHDLAddrMode(EncodingHelper::GetSrcAddrMode(src0)));
2011
2012 //if (EncodingHelper::GetSrcRegFile(src0)!=REG_FILE_A &&
2013 // EncodingHelper::GetSrcAddrMode(src0) == ADDR_MODE_IMMED)
2014 //{
2015 // bool repControl = EncodingHelper::GetRepControl(src0);
2016 // uint32_t byteAddress = src0->getLinearizedStart();
2017
2018 // if (inst->isAligned1Inst() || repControl)
2019 // {
2020 // SetDstRegNumByte(mybin, byteAddress);
2021 // } else {
2022 // SetDstRegNumOWord(mybin, byteAddress/BYTES_PER_OWORD);
2023 // }
2024
2025 //}
2026
2027 BinInst *bin = inst->getBinInst();
2028 bin->DWords[0] = oneSrc.GetDWord(0);
2029 bin->DWords[1] = oneSrc.GetDWord(1);
2030 bin->DWords[2] = oneSrc.GetDWord(2);
2031 bin->DWords[3] = oneSrc.GetDWord(3);
2032
2033 return myStatus;
2034 }
2035
2036
2037 /// \brief Do encoding of JMPI instruction
2038 ///
DoAllEncodingJMPI(G4_INST * inst)2039 BinaryEncodingCNL::Status BinaryEncodingCNL::DoAllEncodingJMPI(G4_INST* inst)
2040 {
2041 Status myStatus = SUCCESS;
2042
2043 G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC brOneSrc;
2044
2045 brOneSrc.Init();
2046 EncodeInstHeader(inst, brOneSrc.GetHeader());
2047
2048 //BEGIN: OPND CONTROL WORD:
2049 DstBuilder<G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS>::EncodeFlagReg(inst, brOneSrc.GetOperandControl());
2050 DstBuilder<G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS>::EncodeMaskCtrl(inst, brOneSrc.GetOperandControl());
2051
2052 //hardcode:
2053 brOneSrc.GetOperandControl().SetDestinationRegisterFile(G9HDL::REGFILE_ARF);
2054 brOneSrc.GetOperandControl().SetDestinationDataType(G11HDL::DSTTYPE_UD);
2055 brOneSrc.GetOperandControl().SetDestinationAddressingMode(G9HDL::ADDRMODE_DIRECT);
2056
2057 //FIXME: bxml does not have arch reg file enumerations
2058 unsigned short RegFile = ARCH_REG_FILE_IP; //4 bits
2059 unsigned short RegNumValue = 0;
2060 // 7654|3210
2061 // RegF|RegNumVal
2062 unsigned short EncodedRegNum = RegFile << 4;
2063 EncodedRegNum = EncodedRegNum | (RegNumValue & 0xF);
2064
2065 //the same as for align16
2066 brOneSrc.GetOperandControl().
2067 GetDestinationRegisterRegion_Align1().
2068 SetDestinationRegisterNumber_DestinationRegisterNumber(EncodedRegNum);
2069 brOneSrc.GetOperandControl().
2070 GetDestinationRegisterRegion_Align1().
2071 SetDestinationSubregisterNumber_DestinationSubRegisterNumber(0);
2072
2073 brOneSrc.GetOperandControl().
2074 GetDestinationRegisterRegion_Align1().
2075 SetDestinationHorizontalStride(G9HDL::HORZSTRIDE_1_ELEMENTS);
2076
2077 //src0, but belongs to opndCtl dword
2078 brOneSrc.GetOperandControl().SetSrc0Regfile(G9HDL::REGFILE_ARF);
2079 brOneSrc.GetOperandControl().SetSrc0Srctype(GetOperandSrcHDLType(Type_UD));
2080
2081 //END: OPND CONTROL WORD
2082
2083 //BEGIN: src0
2084 if (inst->getSrc(0))
2085 {
2086 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC,0>::
2087 SetSourceAddressingMode(&brOneSrc,G9HDL::ADDRMODE_DIRECT);
2088 //FIXME: bxml does not have arch reg file enumerations
2089 unsigned short RegFile = ARCH_REG_FILE_IP; //4 bits
2090 unsigned short RegNumValue = 0;
2091 // 7654|3210
2092 // RegF|RegNumVal
2093 unsigned short EncodedRegNum = RegFile << 4;
2094 EncodedRegNum = EncodedRegNum | (RegNumValue & 0xF);
2095 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC,0>::
2096 SetSourceRegisterNumber(&brOneSrc,EncodedRegNum);
2097 SrcOperandEncoder<G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC,0>::
2098 SetSourceSubRegisterNumber(&brOneSrc,0);
2099
2100 brOneSrc.SetSource0_SourceWidth(G9HDL::WIDTH_1_ELEMENTS);
2101 if (inst->getSrc(0)->isLabel())
2102 {
2103 brOneSrc.SetSource0_SourceVerticalStride(G9HDL::VERTSTRIDE_0_ELEMENTS);
2104 brOneSrc.SetSource0_SourceHorizontalStride(G9HDL::HORZSTRIDE_0_ELEMENTS);
2105 brOneSrc.SetSource0_SourceModifier(G9HDL::SRCMOD_NO_MODIFICATION);
2106 }
2107 }
2108
2109 if (inst->getSrc(0) &&
2110 inst->getSrc(0)->isSrcRegRegion())
2111 {
2112
2113 G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC* ptr = (G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC*)&brOneSrc;
2114
2115 SrcBuilder<G9HDL::EU_INSTRUCTION_SOURCES_REG_REG,1>::EncodeEuInstructionSourcesReg(
2116 inst, inst->getSrc(0), ptr->GetRegsource()); // by reference
2117
2118 ptr->GetRegsource().SetSrc1Regfile(TranslateVisaToHDLRegFile(EncodingHelper::GetSrcRegFile(inst->getSrc(0))));
2119
2120 if (!inst->getSrc(0)->isImm())
2121 {
2122 ptr->GetRegsource().SetSrc1Srctype(GetOperandSrcHDLType(inst->getSrc(0)->getType()));
2123 }
2124 }
2125
2126 //END: src0
2127
2128 //BEGIN: src1
2129 // The rest is encoded in EncodeConditionalBranches
2130 //END: src1
2131 BinInst *bin = inst->getBinInst();
2132 bin->DWords[0] = brOneSrc.GetDWORD(0);
2133 bin->DWords[1] = brOneSrc.GetDWORD(1);
2134 bin->DWords[2] = brOneSrc.GetDWORD(2);
2135 bin->DWords[3] = brOneSrc.GetDWORD(3);
2136
2137 return myStatus;
2138 }
2139
DoAllEncodingCALL(G4_INST * inst)2140 BinaryEncodingCNL::Status BinaryEncodingCNL::DoAllEncodingCALL(G4_INST* inst)
2141 {
2142 Status myStatus = SUCCESS;
2143
2144 BinInst *bin = inst->getBinInst();
2145 G9HDL::EU_INSTRUCTION_BRANCH_ONE_SRC oneSrc;
2146 oneSrc.Init();
2147
2148 EncodeInstHeader(inst, oneSrc.GetHeader());
2149 EncodeOperandDst(inst, oneSrc.GetOperandControl());
2150
2151 if (inst->getSrc(0) && !inst->getSrc(0)->isLabel())
2152 {
2153 // indirect call
2154 G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC* ptr = (G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC*)&oneSrc;
2155
2156 SrcBuilder<G9HDL::EU_INSTRUCTION_SOURCES_REG_REG, 1>::EncodeEuInstructionSourcesReg(
2157 inst, inst->getSrc(0), ptr->GetRegsource()); // by reference
2158
2159 ptr->GetRegsource().SetSrc1Regfile(TranslateVisaToHDLRegFile(EncodingHelper::GetSrcRegFile(inst->getSrc(0))));
2160
2161 if (!inst->getSrc(0)->isImm())
2162 {
2163 ptr->GetRegsource().SetSrc1Srctype(GetOperandSrcHDLType(inst->getSrc(0)->getType()));
2164 }
2165 }
2166 else
2167 {
2168 //Needed for correctness
2169 oneSrc.SetSrc1Regfile(G9HDL::REGFILE_IMM);
2170 oneSrc.SetSrc1Srctype(GetOperandSrcHDLImmType(Type_D));
2171 }
2172
2173
2174
2175
2176 bin->DWords[0] = oneSrc.GetDWORD(0);
2177 bin->DWords[1] = oneSrc.GetDWORD(1);
2178 bin->DWords[2] = oneSrc.GetDWORD(2);
2179 bin->DWords[3] = oneSrc.GetDWORD(3);
2180
2181 return myStatus;
2182 }
2183
2184 /// \brief Do encoding of control flow type instructions
2185 ///
DoAllEncodingCF(G4_INST * inst)2186 BinaryEncodingCNL::Status BinaryEncodingCNL::DoAllEncodingCF(G4_INST* inst)
2187 {
2188 Status myStatus = SUCCESS;
2189 BinInst *bin = inst->getBinInst();
2190
2191 G9HDL::EU_INSTRUCTION_BRANCH_TWO_SRC brTwoSrc;
2192 brTwoSrc.Init();
2193 //brTwoSrc.Common.OperandControls
2194 EncodeInstHeader(inst, brTwoSrc.GetHeader());
2195 //fixme: not sure why we are setting only this field for dst, but keep the binary encoding the same as original one...
2196 brTwoSrc.GetOperandControl().GetDestinationRegisterRegion_Align1().SetDestinationHorizontalStride(G9HDL::HORZSTRIDE_1_ELEMENTS);
2197 DstBuilder<G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS>::EncodeFlagReg(inst, brTwoSrc.GetOperandControl());
2198 DstBuilder<G9HDL::EU_INSTRUCTION_OPERAND_CONTROLS>::EncodeMaskCtrl(inst, brTwoSrc.GetOperandControl());
2199 bin->DWords[0] = brTwoSrc.GetDWord(0);
2200 bin->DWords[1] = brTwoSrc.GetDWord(1);
2201 bin->DWords[2] = brTwoSrc.GetDWord(2);
2202 bin->DWords[3] = brTwoSrc.GetDWord(3);
2203 return myStatus;
2204 }
2205
2206 /// \brief Do encoding of split send instruction
2207 ///
DoAllEncodingSplitSEND(G4_INST * inst)2208 BinaryEncodingCNL::Status BinaryEncodingCNL::DoAllEncodingSplitSEND(G4_INST* inst)
2209 {
2210 Status myStatus = SUCCESS;
2211 BinInst *bin = inst->getBinInst();
2212
2213 G9HDL::EU_INSTRUCTION_SENDS sends;
2214 sends.Init();
2215
2216 EncodeSplitSend(inst, sends);
2217
2218 bin->DWords[0] = sends.GetDWORD(0);
2219 bin->DWords[1] = sends.GetDWORD(1);
2220 bin->DWords[2] = sends.GetDWORD(2);
2221 bin->DWords[3] = sends.GetDWORD(3);
2222
2223 //This is a workaround for BXML defect
2224 G4_Operand *src3 = inst->getSrc(3);
2225 // additional extended msg desc to be encoded
2226 // FIXME: does it apply to regular SKL+ sends too?
2227 if (src3 && src3->isSrcRegRegion() && src3->asSrcRegRegion()->isA0())
2228 {
2229 bin->SetBits(bitsSendsSelReg32ExDesc_0, bitsSendsSelReg32ExDesc_1, 1);
2230 bin->SetBits(bitsSendsExDescRegNum_0, bitsSendsExDescRegNum_1,
2231 src3->asSrcRegRegion()->getBase()->asRegVar()->getPhyRegOff());
2232 }
2233
2234 return myStatus;
2235 }
2236
2237 /// \brief Do encoding of all 'regular' one, two or three-src instructions
2238 /// Treats send and math instructions as two-src and patches them accordingly.
DoAllEncodingRegular(G4_INST * inst)2239 BinaryEncodingCNL::Status BinaryEncodingCNL::DoAllEncodingRegular(G4_INST* inst)
2240 {
2241 Status myStatus = SUCCESS;
2242
2243 MUST_BE_TRUE(!inst->isSplitSend(), "Improper instruction type called with DoAllEncodingRegular: sends or sendsc");
2244
2245 BinInst *bin = inst->getBinInst();
2246 int i=inst->getNumSrc();
2247 switch (i)
2248 {
2249 case 0:
2250 {
2251 // for nop, we have to encode the opcode, borrow the oneSrc format
2252 G9HDL::EU_INSTRUCTION_BASIC_ONE_SRC oneSrc;
2253 oneSrc.Init();
2254 EncodeOpCode(inst, oneSrc.Common.Header);
2255 bin->DWords[0] = oneSrc.GetDWord(0);
2256 bin->DWords[1] = oneSrc.GetDWord(1);
2257 bin->DWords[2] = oneSrc.GetDWord(2);
2258 bin->DWords[3] = oneSrc.GetDWord(3);
2259 break;
2260 }
2261 case 1:
2262 G9HDL::EU_INSTRUCTION_BASIC_ONE_SRC oneSrc;
2263 oneSrc.Init();
2264 EncodeOneSrcInst(inst, oneSrc);
2265 bin->DWords[0] = oneSrc.GetDWord(0);
2266 bin->DWords[1] = oneSrc.GetDWord(1);
2267 bin->DWords[2] = oneSrc.GetDWord(2);
2268 bin->DWords[3] = oneSrc.GetDWord(3);
2269 break;
2270 case 2:
2271 G9HDL::EU_INSTRUCTION_BASIC_TWO_SRC twoSrc;
2272 twoSrc.Init();
2273 EncodeTwoSrcInst(inst, twoSrc);
2274 if (inst->isSend())
2275 {
2276 PatchSend(inst, &twoSrc);
2277 }
2278 else if (inst->isMath())
2279 {
2280 //fixme: math is only for two-src encoding?
2281 PatchMath(inst, &twoSrc);
2282 }
2283
2284 bin->DWords[0] = twoSrc.GetDWord(0);
2285 bin->DWords[1] = twoSrc.GetDWord(1);
2286 bin->DWords[2] = twoSrc.GetDWord(2);
2287 bin->DWords[3] = twoSrc.GetDWord(3);
2288 break;
2289 case 3:
2290 {
2291 if (inst->isAligned1Inst())
2292 {
2293 G9HDL::EU_INSTRUCTION_ALIGN1_THREE_SRC threeSrcAlign1;
2294 threeSrcAlign1.Init();
2295 EncodeThreeSrcInstAlign1(inst, threeSrcAlign1);
2296 bin->DWords[0] = threeSrcAlign1.GetRawData(0);
2297 bin->DWords[1] = threeSrcAlign1.GetRawData(1);
2298 bin->DWords[2] = threeSrcAlign1.GetRawData(2);
2299 bin->DWords[3] = threeSrcAlign1.GetRawData(3);
2300
2301 }
2302 else
2303 {
2304 G9HDL::EU_INSTRUCTION_BASIC_THREE_SRC threeSrc;
2305 threeSrc.Init();
2306 EncodeThreeSrcInst(inst, threeSrc);
2307 bin->DWords[0] = threeSrc.GetDWORD(0);
2308 bin->DWords[1] = threeSrc.GetDWORD(1);
2309 bin->DWords[2] = threeSrc.GetDWORD(2);
2310 bin->DWords[3] = threeSrc.GetDWORD(3);
2311 }
2312
2313 }
2314 break;
2315 default:
2316 break;
2317 }
2318
2319 return myStatus;
2320 }
2321
2322 /// \brief Do all encoding for an instruction.
DoAllEncoding(G4_INST * inst)2323 BinaryEncodingCNL::Status BinaryEncodingCNL::DoAllEncoding(G4_INST* inst)
2324 {
2325 Status myStatus = SUCCESS;
2326 bool isFCCall = false, isFCRet = false;
2327
2328 if (inst->opcode() == G4_label) return myStatus;
2329
2330 if (inst->opcode() == G4_illegal)
2331 return FAILURE;
2332
2333 EncodingHelper::mark3Src(inst);
2334
2335 {
2336
2337 //Prolog:
2338 if (inst->opcode() == G4_pseudo_fc_call)
2339 {
2340 inst->asCFInst()->pseudoCallToCall();
2341 isFCCall = true;
2342 }
2343
2344 if (inst->opcode() == G4_pseudo_fc_ret)
2345 {
2346 inst->asCFInst()->pseudoRetToRet();
2347 isFCRet = true;
2348 }
2349
2350 if (inst->opcode() == G4_jmpi)
2351 {
2352 DoAllEncodingJMPI(inst);
2353 }
2354 else if (inst->opcode() == G4_wait)
2355 {
2356 DoAllEncodingWAIT(inst);
2357 }
2358 else if (inst->opcode() == G4_if ||
2359 inst->opcode() == G4_endif ||
2360 inst->opcode() == G4_else ||
2361 inst->opcode() == G4_while ||
2362 inst->opcode() == G4_break ||
2363 inst->opcode() == G4_cont ||
2364 inst->opcode() == G4_halt ||
2365 inst->opcode() == G4_goto ||
2366 inst->opcode() == G4_join)
2367 {
2368 DoAllEncodingCF(inst);
2369 }
2370 else if (inst->opcode() == G4_call)
2371 {
2372 DoAllEncodingCALL(inst);
2373 }
2374 else if (inst->isSplitSend()) {
2375 DoAllEncodingSplitSEND(inst);
2376 }
2377 else if (!EncodingHelper::hasLabelString(inst)) {
2378 DoAllEncodingRegular(inst);
2379 }
2380
2381 //Epilog:
2382 if (isFCCall == true)
2383 {
2384 inst->setOpcode(G4_pseudo_fc_call);
2385 }
2386
2387 if (isFCRet == true)
2388 {
2389 inst->setOpcode(G4_pseudo_fc_ret);
2390 }
2391 }
2392
2393 return myStatus;
2394 }
2395
2396 /// \brief Entry point.
2397 ///
2398 /// This is counterpart of ProduceBinaryInstructions from 'old' encoder
DoAll()2399 void BinaryEncodingCNL::DoAll()
2400 {
2401 std::vector<ForwardJmpOffset> offsetVector;
2402 FixInst();
2403 BinaryEncodingBase::InitPlatform();
2404 // BDW/CHV/SKL/BXT/CNL use the same compaction tables except from 3src.
2405 for (uint8_t i=0; i<(int)COMPACT_TABLE_SIZE; i++)
2406 {
2407 BDWCompactControlTable.AddIndex(IVBCompactControlTable[i], i);
2408 BDWCompactSourceTable.AddIndex(IVBCompactSourceTable[i], i);
2409 BDWCompactSubRegTable.AddIndex(IVBCompactSubRegTable[i], i);
2410 BDWCompactSubRegTable.AddIndex1(IVBCompactSubRegTable[i] & 0x1F, i);
2411 BDWCompactSubRegTable.AddIndex2(IVBCompactSubRegTable[i] & 0x3FF, i);
2412 if (getGenxPlatform() >= GENX_ICLLP)
2413 {
2414 BDWCompactDataTypeTableStr.AddIndex(ICLCompactDataTypeTable[i], i);
2415 }
2416 else
2417 {
2418 BDWCompactDataTypeTableStr.AddIndex(BDWCompactDataTypeTable[i], i);
2419 }
2420 }
2421
2422 int globalInstNum = 0;
2423 int globalHalfInstNum = 0;
2424 int numCompactedInst = 0;
2425 int numCompacted3SrcInst = 0;
2426
2427 BB_LIST_ITER ib, bend(kernel.fg.end());
2428 for (ib = kernel.fg.begin(); ib != bend; ++ib)
2429 {
2430 G4_BB *bb = *ib;
2431 int localInstNum = 0;
2432 int localHalfInstNum = 0;
2433
2434 /**
2435 * Traverse the instruction lists
2436 */
2437 INST_LIST_ITER ii, iend(bb->end());
2438 for (ii = bb->begin(); ii != iend; ++ii)
2439 {
2440 /* do detailed encoding here */
2441 G4_INST *inst = *ii;
2442 G4_opcode opcode = inst->opcode();
2443
2444 if (opcode == G4_label)
2445 {
2446 inst->setBinInst(NULL);
2447 } else {
2448 // reuse "BinInst" from BinaryEncoding.h which can be simplified
2449 BinInst *bin = new (mem) BinInst();
2450 inst->setBinInst(bin);
2451
2452 bin->DWords[0] = 0;
2453 bin->DWords[1] = 0;
2454 bin->DWords[2] = 0;
2455 bin->DWords[3] = 0;
2456
2457 DoAllEncoding(inst);
2458
2459 if (inst->opcode() == G4_pseudo_fc_call ||
2460 inst->opcode() == G4_pseudo_fc_ret)
2461 {
2462 inst->getBinInst()->SetDontCompactFlag(true);
2463 }
2464
2465 if (doCompaction())
2466 {
2467 inst->getBinInst()->SetMustCompactFlag(false);
2468 inst->getBinInst()->SetDontCompactFlag(inst->isNoCompactedInst());
2469
2470 /**
2471 * handling switch/case for gen6: jump table should not be compacted
2472 */
2473 bool compacted;
2474 {
2475 TIME_SCOPE(ENCODE_COMPACTION);
2476 compacted = BinaryEncodingBase::compactOneInstruction(inst);
2477 }
2478
2479 if (compacted)
2480 {
2481 if (kernel.getOption(vISA_OptReport))
2482 {
2483 numCompactedInst++;
2484 if (inst->getBinInst()->GetIs3Src())
2485 numCompacted3SrcInst++;
2486 }
2487 inst->setCompacted();
2488 }
2489 }
2490 binInstList.push_back(inst->getBinInst());
2491
2492 if (inst->opcode() >= G4_jmpi && inst->opcode() <= G4_join)
2493 {
2494 if (!EncodeConditionalBranches(inst, globalHalfInstNum))
2495 {
2496 offsetVector.push_back(ForwardJmpOffset(inst, globalHalfInstNum));
2497 }
2498 }
2499 } //else
2500
2501 BuildLabelMap(inst, localHalfInstNum, localInstNum,
2502 globalHalfInstNum, globalInstNum);
2503 } // for inst
2504 } // for bb
2505
2506 kernel.setAsmCount(globalInstNum);
2507 SetInstCounts((uint32_t)globalHalfInstNum);
2508
2509 EncodingHelper::dumpOptReport(globalInstNum, numCompactedInst, numCompacted3SrcInst, kernel);
2510 for (auto x = offsetVector.begin(), vEnd = offsetVector.end(); x != vEnd; x++)
2511 {
2512 if (!EncodeConditionalBranches(x->inst, x->offset))
2513 {
2514 MUST_BE_TRUE(false, "invalid label!");
2515 }
2516 }
2517 }
2518
2519