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