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 "BinaryEncoding.h"
10 #include "BuildIR.h"
11 
12 using namespace vISA;
13 
14 // Initlaize the platform dependent bit positions to some illegal value
15 // They will be set to the correct value by the Init() function
16 // Technically these should be TLS, but I'm counting on the fact that
17 // these values will be fixed for a given platform, and an application
18 // should never invoke the jitter twice with different platform strings.
19 // Initlaize the platform dependent bit positions to some illegal value
20 // They will be set to the correct value by the Init() function
21 // Technically these should be TLS, but I'm counting on the fact that
22 // these values will be fixed for a given platform, and an application
23 // should never invoke the jitter twice with different platform strings.
24 unsigned long bitsFlagSubRegNum[] = {128, 128};
25 unsigned long bitsNibCtrl[] = {128, 128};
26 unsigned long bits3SrcFlagSubRegNum[] = {128, 128};
27 unsigned long bits3SrcSrcType[] = {128, 128};
28 unsigned long bits3SrcDstType[] = {128, 128};
29 unsigned long bits3SrcNibCtrl[] = {128, 128};
30 unsigned long bits3SrcDstRegFile[] = {128, 128};
31 
32 unsigned long bitsDepCtrl[] = {128, 128};
33 unsigned long bitsWECtrl[] = {128, 128};
34 unsigned long bitsDstRegFile[] = {128, 128};
35 unsigned long bitsDstType[] = {128, 128};
36 unsigned long bitsDstIdxRegNum[] = {128, 128};
37 unsigned long bitsDstIdxImmOWord[] = {128, 128};
38 unsigned long bitsDstIdxImmByte[]   = {128, 128};
39 unsigned long bitsDstIdxImmMSB[] = {128, 128};
40 unsigned long bitsSrcType[] = {128, 128, 128, 128};
41 unsigned long bitsSrcIdxRegNum[] = {128, 128, 128, 128};
42 unsigned long bitsSrcIdxImmOWord[]  = {128, 128, 128, 128};
43 unsigned long bitsSrcIdxImmByte[] = {128, 128, 128, 128};
44 unsigned long bitsSrcIdxImmMSB[]    = {128, 128, 128, 128};
45 unsigned long bitsJIP[] = {128, 128};
46 unsigned long bitsUIP[] = {128, 128};
47 unsigned long bits3SrcSrcMod[]  = {128, 128, 128, 128, 128, 128};
48 
49 /************************************************************************/
50 /* Auxiliary                                                            */
51 /************************************************************************/
52 
SetOpCode(BinInst * mybin,uint32_t value)53 inline void SetOpCode(BinInst *mybin, uint32_t value)
54 {
55     mybin->SetBits(bitsOpCode_0, bitsOpCode_1, value);
56 }
57 
EncodeOpCode(G4_INST * inst)58 inline void BinaryEncoding::EncodeOpCode(G4_INST* inst)
59 {
60     BinInst *mybin = inst->getBinInst();
61     G4_opcode opcode = inst->opcode();
62     uint32_t euopc = getEUOpcode(opcode);
63     SetOpCode(mybin, euopc);
64 }
65 
EncodeExecSize(G4_INST * inst)66 inline void BinaryEncoding::EncodeExecSize(G4_INST* inst)
67 {
68     BinInst *mybin = inst->getBinInst();
69     mybin->SetBits(bitsExecSize_0, bitsExecSize_1, GetEncodeExecSize(inst));
70 }
71 
EncodeAccessMode(G4_INST * inst)72 inline void BinaryEncoding::EncodeAccessMode(G4_INST* inst)
73 {
74     BinInst *mybin = inst->getBinInst();
75 
76     if (inst->isAligned1Inst()) {
77         mybin->SetBits(bitsAccessMode_0, bitsAccessMode_1, ACCESS_MODE_ALIGN1);
78     }
79     else if (inst->isAligned16Inst()) {
80         mybin->SetBits(bitsAccessMode_0, bitsAccessMode_1, ACCESS_MODE_ALIGN16);
81     }
82     else
83     {
84     }
85 }
86 
87 static const unsigned PREDICATE_STATE[3] =
88 {
89     (unsigned)PREDICATE_STATE_NORMAL,   // plus and undef are normal
90     (unsigned)PREDICATE_STATE_INVERT << 4,    // minus is invert
91     (unsigned)PREDICATE_STATE_NORMAL    // plus and undef are normal
92 };
93 
EncodeFlagRegPredicate(G4_INST * inst)94 inline void BinaryEncoding::EncodeFlagRegPredicate(G4_INST* inst)
95 {
96     BinInst *mybin = inst->getBinInst();
97     G4_Predicate *pred = inst->getPredicate();
98     uint32_t flagState = 0, flagSwizzle;
99     if (pred)
100     {
101         unsigned pState = (unsigned)pred->getState();
102         MUST_BE_TRUE(pState <= (unsigned)PredState_undef,
103                      "BinaryEncoding: invalid prediate state");
104         flagState = PREDICATE_STATE[pState];
105 
106         flagSwizzle = inst->isAligned16Inst() ?
107             PREDICATE_ALIGN16_SEQUENTIAL : PREDICATE_ALIGN1_SEQUENTIAL;
108 
109         if (inst->isAligned16Inst())
110         {
111             flagSwizzle = pred->getAlign16PredicateControl();
112         }
113         else
114         {
115             auto predCtrl = pred->getControl();
116             if (predCtrl != PRED_DEFAULT)
117                 flagSwizzle = (uint32_t) GetAlign1PredCtrl(predCtrl);
118         }
119 
120         mybin->SetBits(bitsPredicate_0, bitsPredicate_1, flagState | flagSwizzle);
121     }
122 }
123 
SetFlagSubRegNum(BinInst * mybin,uint32_t value)124 inline void SetFlagSubRegNum(BinInst *mybin, uint32_t value)
125 {
126     if (mybin->GetIs3Src())
127         mybin->SetBits(bits3SrcFlagSubRegNum[0], bits3SrcFlagSubRegNum[1], value);
128     else
129         mybin->SetBits(bitsFlagSubRegNum[0], bitsFlagSubRegNum[1], value);
130 }
131 
132 
EncodeFlagReg(G4_INST * inst)133 inline void BinaryEncoding::EncodeFlagReg(G4_INST* inst)
134 {
135     bool flagRegNumValid = false;
136     unsigned FlagRegNumValue = 0;
137     unsigned FlagRegSubNumValue = 0;
138     BinInst *mybin = inst->getBinInst();
139 
140     G4_Predicate *pred = inst->getPredicate();
141     if (pred) {
142         FlagRegNumValue = pred->getBase()->ExRegNum(flagRegNumValid);
143         FlagRegSubNumValue = pred->getBase()->asRegVar()->getPhyRegOff();
144     }
145 
146     G4_CondMod *cModifier = inst->getCondMod();
147     if (cModifier)    { // cond modifier
148         G4_VarBase* flagReg = cModifier->getBase();
149         if (flagReg != NULL)
150         {
151             FlagRegNumValue = flagReg->ExRegNum(flagRegNumValid);
152             FlagRegSubNumValue = flagReg->asRegVar()->getPhyRegOff();
153         }
154         else
155         {
156             FlagRegNumValue = 0;
157             FlagRegSubNumValue = 0;
158         }
159     }
160 
161     if (pred || cModifier) {
162         if (flagRegNumValid) {
163             switch (FlagRegNumValue)    {
164                 case 0:
165                     // flag reg num is always zero prior to Gen7
166                     break;
167                 case 1:
168                     SetFlagRegNum(mybin, FlagRegNumValue);
169                     break;
170                 default:
171                     MUST_BE_TRUE(false, "Invalid flag register number");
172                     break;
173             }
174         }
175         if (FlagRegSubNumValue != UNDEFINED_SHORT) {
176             switch (FlagRegSubNumValue) {
177                 case 0:
178                 case 1:
179                     SetFlagSubRegNum(mybin, FlagRegSubNumValue);
180                     break;
181                 default:
182                     MUST_BE_TRUE(false, "invalid flag register sub-number");
183             }
184         }
185     }
186 }
187 
188 static const unsigned CONDITION_MODIFIER[11] =
189 {
190     (unsigned)COND_CODE_Z,
191     (unsigned)COND_CODE_Z,
192     (unsigned)COND_CODE_NZ,
193     (unsigned)COND_CODE_NZ,
194     (unsigned)COND_CODE_G,
195     (unsigned)COND_CODE_GE,
196     (unsigned)COND_CODE_L,
197     (unsigned)COND_CODE_LE,
198     (unsigned)COND_CODE_ANY,
199     (unsigned)COND_CODE_O,
200     (unsigned)COND_CODE_ALL
201 };
202 
EncodeCondModifier(G4_INST * inst)203 inline void BinaryEncoding::EncodeCondModifier(G4_INST* inst)
204 {
205     BinInst *mybin = inst->getBinInst();
206     G4_CondMod *cModifier = inst->getCondMod();
207     uint32_t value;
208     if (cModifier)    {
209         value = (unsigned)cModifier->getMod();
210         MUST_BE_TRUE(value < Mod_cond_undef,
211                      "[Verifying]:[ERR]: Invalid conditional modifier:\t");
212         mybin->SetBits(bitsCondModifier_0, bitsCondModifier_1, CONDITION_MODIFIER[value]);
213     }
214 }
215 
EncodeQtrControl(G4_INST * inst)216 inline void BinaryEncoding::EncodeQtrControl(G4_INST* inst)
217 {
218     BinInst *mybin = inst->getBinInst();
219 
220     unsigned int emaskOffset = inst->getMaskOffset();
221     mybin->SetBits(bitsQtrCtrl_0, bitsQtrCtrl_1, emaskOffset / 8);
222     mybin->SetBits(bitsNibCtrl[0], bitsNibCtrl[1], (emaskOffset % 8 != 0) ? 1 : 0);
223 }
224 
EncodeInstModifier(G4_INST * inst)225 inline void BinaryEncoding::EncodeInstModifier(G4_INST* inst)
226 {
227     BinInst *mybin = inst->getBinInst();
228     if (inst->getSaturate()) {
229         mybin->SetBits(bitsInstModifier_0, bitsInstModifier_1, INST_MOD_SAT);
230     }
231     else {
232         mybin->SetBits(bitsInstModifier_0, bitsInstModifier_1, INST_MOD_NONE);
233     }
234 }
235 
EncodeMathControl(G4_INST * inst)236 inline void BinaryEncoding::EncodeMathControl(G4_INST* inst)
237 {
238     MUST_BE_TRUE(inst->isMath(), "BinaryEncoding::EncodeMathControl called on non-math instruction.");
239     BinInst *mybin = inst->getBinInst();
240 
241     unsigned int MathControlValue = inst->asMathInst()->getMathCtrl();
242     unsigned MathFunction = MathControlValue & 0xf;
243     unsigned MathPartPrec = (MathControlValue >> 4) & 1;
244 
245     if (!mybin->GetIs3Src())     {
246         mybin->SetBits(bitsMathFunction_0, bitsMathFunction_1, MathFunction);
247         mybin->SetBits(bitsMathPartPrec_0, bitsMathPartPrec_1, MathPartPrec);
248     }
249 
250  }
251 
EncodeAccWrCtrlInst(G4_INST * inst)252 inline void EncodeAccWrCtrlInst(G4_INST *inst)
253 {
254     BinInst *mybin = inst->getBinInst();
255     //Jmpi does not support BranchControl
256     if (inst->isAccWrCtrlInst() || (inst->isFlowControl() && inst->asCFInst()->isBackward() && inst->opcode() != G4_jmpi))
257     {
258         mybin->SetBits(bitsAccWrCtrl_0, bitsAccWrCtrl_1, 1);
259         return;
260     }
261 }
262 
263 // set bit 29/30 (FP16 input/return) if message descriptor is indirect
264 // This is to work around a HW bug where only bit[0:28] of a0 is copied
EncodeSendMsgDesc29_30(G4_INST * inst)265 inline void BinaryEncoding::EncodeSendMsgDesc29_30(G4_INST* inst)
266 {
267     MUST_BE_TRUE(inst->isSend(), "must be a send inst");
268 
269     BinInst *mybin = inst->getBinInst();
270     G4_SendDescRaw* msgDesc = inst->getMsgDescRaw();
271     MUST_BE_TRUE(msgDesc, "expected raw descriptor");
272     G4_Operand* descOpnd = inst->isSplitSend() ? inst->getSrc(2) : inst->getSrc(1);
273     if (!descOpnd->isImm())
274     {
275         uint32_t bitValue = (msgDesc->is16BitReturn() << 1) + msgDesc->is16BitInput();
276         mybin->SetBits(bitsSendDesc_30, bitsSendDesc_29, bitValue);
277     }
278 }
279 
EncodeInstOptionsString(G4_INST * inst)280 inline void BinaryEncoding::EncodeInstOptionsString(G4_INST* inst)
281 {
282     BinInst *mybin = inst->getBinInst();
283 
284     EncodeAccessMode(inst);
285     EncodeQtrControl(inst);
286     EncodeAccWrCtrlInst(inst);
287 
288     mybin->SetBits(bitsCompactCtrl_0, bitsCompactCtrl_1,
289         inst->isCompactedInst());
290 
291     if (inst->opcode() == G4_if  ||
292          inst->opcode() == G4_else  ||
293          inst->opcode() == G4_endif)
294     {
295 
296     }
297     else
298     {
299         mybin->SetBits(bitsThreadCtrl_0, bitsThreadCtrl_1,
300             inst->isAtomicInst()? THREAD_CTRL_ATOMIC :
301             // CHAI: Add Switch InstOpt support
302             (inst->isYieldInst()? THREAD_CTRL_SWITCH : THREAD_CTRL_NORMAL));
303     }
304 
305 
306     if (inst->isNoDDChkInst())
307     {
308         if (inst->isNoDDClrInst())
309         {
310             mybin->SetBits(bitsDepCtrl[0], bitsDepCtrl[1],
311                 DEP_CTRL_DIS_CHECK_CLEAR_DEST);
312         }   else   {
313             mybin->SetBits(bitsDepCtrl[0], bitsDepCtrl[1],
314                 DEP_CTRL_DIS_CHECK);
315         }
316     }
317     else    {
318         if (inst->isNoDDClrInst())
319         {
320             mybin->SetBits(bitsDepCtrl[0], bitsDepCtrl[1],
321                 DEP_CTRL_DIS_CLEAR);
322     }   else        {
323             mybin->SetBits(bitsDepCtrl[0], bitsDepCtrl[1],
324                 DEP_CTRL_NORMAL);
325         }
326     }
327 
328     if (inst->isWriteEnableInst())
329         mybin->SetBits(bitsWECtrl[0], bitsWECtrl[1], 1);
330 
331     if (inst->opcode()==G4_jmpi)
332         mybin->SetBits(bitsWECtrl[0], bitsWECtrl[1], 1);
333 
334     if (inst->isBreakPointInst())
335         mybin->SetBits(bitsDebugCtrl_0, bitsDebugCtrl_1, 1);
336 
337     if (inst->isNoSrcDepSet())
338     {
339         mybin->SetBits(bitsNoSrcDepSet_0, bitsNoSrcDepSet_1, 1);
340     }
341 
342     if (!mybin->GetIs3Src())
343     {
344         if (inst->isEOT())
345             mybin->SetBits(bitsEndOfThread_0, bitsEndOfThread_1, 1);
346     }
347 
348 }
349 
350 ///////////////////////////////////////////////////////////////////////////////
351 //                       Generic Src Utilities
352 ///////////////////////////////////////////////////////////////////////////////
353 
GetOperandSrcType(G4_Operand * src)354 inline uint32_t GetOperandSrcType(G4_Operand *src)
355 {
356     uint32_t type;
357     G4_Type regType;
358 
359     if (src->isSrcRegRegion())
360     {
361         regType = src->asSrcRegRegion()->getType();
362     }
363     else
364     {
365         regType = src->getType();
366     }
367 
368     switch (regType) {
369         case Type_UD:
370         case Type_D:
371         case Type_UW:
372         case Type_W:
373         case Type_UB:
374         case Type_B:
375             type = regType;
376             break;
377         case Type_DF:
378             type = SRC_TYPE_DF;
379             break;
380         case Type_F:
381             type = SRC_TYPE_F;
382             break;
383         case Type_UQ:
384             type = SRC_TYPE_UQ;
385             break;
386         case Type_Q:
387             type = SRC_TYPE_Q;
388             break;
389         case Type_HF:
390             type = SRC_TYPE_HF;
391             break;
392         default:
393             type = SRC_TYPE_UNDEF;
394             MUST_BE_TRUE(false, "Binary code emission error: unknown type");
395     }
396     return type;
397 }
398 
GetOperandSrcImmType(G4_Operand * src)399 inline uint32_t GetOperandSrcImmType(G4_Operand *src)
400 {
401     uint32_t type;
402     switch (src->getType()) {
403         case Type_UD:
404         case Type_D:
405         case Type_UW:
406         case Type_W:
407             type = src->getType();
408             break;
409         case Type_UV:
410             type = SRC_IMM_TYPE_UV;
411             break;
412         case Type_VF:
413             type = SRC_IMM_TYPE_VF;
414             break;
415         case Type_V:
416             type = SRC_IMM_TYPE_V;
417             break;
418         case Type_F:
419             type = SRC_IMM_TYPE_F;
420             break;
421         case Type_UQ:
422             type = SRC_IMM_TYPE_UQ;
423             break;
424         case Type_Q:
425             type = SRC_IMM_TYPE_Q;
426             break;
427         case Type_DF:
428             type = SRC_IMM_TYPE_DF;
429             break;
430         case Type_HF:
431             type = SRC_IMM_TYPE_HF;
432             break;
433         default:
434             type = SRC_TYPE_UNDEF;
435             break;
436     }
437     return type;
438 }
439 
440 static const unsigned SOURCE_MODIFIER[5] =
441 {
442     (unsigned)SRC_MOD_NEGATE,
443     (unsigned)SRC_MOD_ABSOLUTE,
444     (unsigned)SRC_MOD_NEGATE_OF_ABSOLUTE,
445     (unsigned)SRC_MOD_NEGATE,
446     (unsigned)SRC_MOD_NONE
447 };
448 
GetSrcMod(G4_SrcRegRegion * srcRegion)449 inline uint32_t GetSrcMod(G4_SrcRegRegion *srcRegion)
450 {
451     unsigned mod = (unsigned)srcRegion->getModifier();
452     MUST_BE_TRUE(mod <= (unsigned)Mod_src_undef,
453                  "BinaryEncoding: Unexpected source modifier");
454     return SOURCE_MODIFIER[mod];
455 }
456 
457 
458 ///////////////////////////////////////////////////////////////////////////////
459 //                       Dst
460 ///////////////////////////////////////////////////////////////////////////////
461 
462 
463 
SetDstRegFile(BinInst * mybin,uint32_t value)464 inline void SetDstRegFile(BinInst *mybin, uint32_t value)
465 {
466     if (!mybin->GetIs3Src())
467     {
468         mybin->SetBits(bitsDstRegFile[0], bitsDstRegFile[1], value);
469     }
470 }
471 
SetDstType(BinInst * mybin,uint32_t value)472 inline void SetDstType(BinInst *mybin, uint32_t value)
473 {
474     if (mybin->GetIs3Src())
475         // handled by Set3SrcDstType
476         return;
477     else
478         mybin->SetBits(bitsDstType[0], bitsDstType[1], value);
479 }
480 
SetDstAddrMode(BinInst * mybin,uint32_t value)481 inline void SetDstAddrMode(BinInst *mybin, uint32_t value)
482 {
483     if (mybin->GetIs3Src())
484         return;
485     else
486         mybin->SetBits(bitsDstAddrMode_0, bitsDstAddrMode_1, value);
487 }
488 
SetDstRegNumOWord(BinInst * mybin,uint32_t value)489 inline void SetDstRegNumOWord(BinInst *mybin, uint32_t value)
490 {
491     if (mybin->GetIs3Src())
492         mybin->SetBits(bits3SrcDstRegNumOWord_0,
493         bits3SrcDstRegNumOWord_1, value);
494     else
495         mybin->SetBits(bitsDstRegNumOWord_0,
496         bitsDstRegNumOWord_1, value);
497 }
498 
SetDstRegNumByte(BinInst * mybin,uint32_t value)499 inline void SetDstRegNumByte(BinInst *mybin,  uint32_t value)
500 {
501     if (mybin->GetIs3Src())
502         mybin->SetBits(bits3SrcDstRegNumDWord_0, bits3SrcDstRegNumDWord_1, (value >> 2));
503     else
504         mybin->SetBits(bitsDstRegNumByte_0, bitsDstRegNumByte_1, value);
505 }
506 
SetDstChanEn(BinInst * mybin,uint32_t value)507 inline void SetDstChanEn(BinInst *mybin, uint32_t value)
508 {
509     if (mybin->GetIs3Src())
510         mybin->SetBits(bits3SrcDstChanEn_0,
511          bits3SrcDstChanEn_1, value);
512     else
513         mybin->SetBits(bitsDstChanEn_0,
514          bitsDstChanEn_1, value);
515 }
516 
517 /**
518  *  Below three functions set dst's indirect register number
519  */
SetDstIdxRegNum(BinInst * mybin,uint32_t value)520 inline void SetDstIdxRegNum(BinInst *mybin, uint32_t value)
521 {
522     if (mybin->GetIs3Src())
523         return;
524     else
525         mybin->SetBits(bitsDstIdxRegNum[0], bitsDstIdxRegNum[1], value);
526 }
527 
SetDstIdxImmOWord(BinInst * mybin,uint32_t value)528 inline void SetDstIdxImmOWord(BinInst *mybin, uint32_t value)
529 {
530     if (mybin->GetIs3Src())
531         return;
532 
533     mybin->SetBits(bitsDstIdxImmOWord[0], bitsDstIdxImmOWord[1], value);
534     mybin->SetBits(bitsDstIdxImmMSB[0], bitsDstIdxImmMSB[1], (value >> 5));
535 }
536 
SetDstIdxImmByte(BinInst * mybin,uint32_t value)537 inline void SetDstIdxImmByte(BinInst *mybin, uint32_t value)
538 {
539     if (mybin->GetIs3Src())
540         return;
541 
542     mybin->SetBits(bitsDstIdxImmByte[0], bitsDstIdxImmByte[1], value);
543     mybin->SetBits(bitsDstIdxImmMSB[0], bitsDstIdxImmMSB[1], (value >> 9));
544 }
545 
SetDstArchRegFile(BinInst * mybin,uint32_t value)546 inline void SetDstArchRegFile(BinInst *mybin, uint32_t value)
547 {
548     if (mybin->GetIs3Src())
549         return;
550     else
551         mybin->SetBits(bitsDstArchRegFile_0, bitsDstArchRegFile_1, value);
552 }
553 
SetDstArchRegNum(BinInst * mybin,uint32_t value)554 inline void SetDstArchRegNum(BinInst *mybin, uint32_t value)
555 {
556     if (mybin->GetIs3Src())
557         return;
558     else
559         mybin->SetBits(bitsDstArchRegNum_0, bitsDstArchRegNum_1, value);
560 }
561 
SetDstArchSubRegNumOWord(BinInst * mybin,uint32_t value)562 inline void SetDstArchSubRegNumOWord(BinInst *mybin,  uint32_t value)
563 {
564     if (mybin->GetIs3Src())
565         return;
566     else
567         mybin->SetBits(bitsDstArchSubRegNumOWord_0, bitsDstArchSubRegNumOWord_1, value);
568 }
569 
SetDstArchSubRegNumWord(BinInst * mybin,uint32_t value)570 inline void SetDstArchSubRegNumWord(BinInst *mybin, uint32_t value)
571 {
572     if (mybin->GetIs3Src())
573         return;
574     else
575         mybin->SetBits(bitsDstArchSubRegNumWord_0, bitsDstArchSubRegNumWord_1, value);
576 }
577 
SetDstArchSubRegNumByte(BinInst * mybin,uint32_t value)578 inline void SetDstArchSubRegNumByte(BinInst *mybin,  uint32_t value)
579 {
580     if (mybin->GetIs3Src())
581         return;
582     else
583         mybin->SetBits(bitsDstArchSubRegNumByte_0, bitsDstArchSubRegNumByte_1, value);
584 }
585 
SetOperandDstType(BinInst * mybin,G4_DstRegRegion * dst)586 inline void SetOperandDstType(BinInst *mybin, G4_DstRegRegion *dst)
587 {
588     G4_Type regType;
589 
590     regType = dst->getType();
591 
592     switch (regType)
593     {
594         case Type_UD:
595         case Type_D:
596         case Type_UW:
597         case Type_W:
598         case Type_UB:
599         case Type_B:
600             SetDstType(mybin, regType);
601             break;
602         case Type_DF:
603             SetDstType(mybin, DST_TYPE_DF);
604             break;
605         case Type_F:
606             SetDstType(mybin, DST_TYPE_F);
607             break;
608        case Type_UQ:
609             SetDstType(mybin, DST_TYPE_UQ);
610             break;
611         case Type_Q:
612             SetDstType(mybin, DST_TYPE_Q);
613             break;
614         case Type_HF:
615             SetDstType(mybin, DST_TYPE_HF);
616             break;
617         default:
618             MUST_BE_TRUE(false, "Encoding error: destination type unknown");
619             break;
620     }
621 }
622 
623 
EncodeDstRegFile(BinInst * mybin,G4_DstRegRegion * dst)624 inline void EncodeDstRegFile(BinInst *mybin, G4_DstRegRegion *dst)
625 {
626     SetDstRegFile(mybin, EncodingHelper::GetDstRegFile(dst));
627     if (EncodingHelper::GetDstRegFile(dst) == REG_FILE_A)
628     {
629         SetDstArchRegFile(mybin, EncodingHelper::GetDstArchRegType(dst));
630     }
631 }
632 
633 
EncodeDstAddrMode(BinInst * mybin,G4_DstRegRegion * dst)634 inline void EncodeDstAddrMode(BinInst *mybin, G4_DstRegRegion *dst)
635 {
636     SetDstAddrMode(mybin, EncodingHelper::GetDstAddrMode(dst));
637 }
638 
SetDstHorzStride(BinInst * mybin,uint32_t value)639 inline void SetDstHorzStride(BinInst *mybin, uint32_t value)
640 {
641     if (mybin->GetIs3Src())
642         return;
643     else
644         mybin->SetBits(bitsDstHorzStride_0, bitsDstHorzStride_1, value);
645 }
646 
EncodeDstHorzStride(G4_INST * inst,BinInst * mybin,G4_DstRegRegion * dst)647 inline void EncodeDstHorzStride(G4_INST *inst, BinInst *mybin, G4_DstRegRegion *dst)
648 {
649     switch (dst->getHorzStride())
650     {
651         case 1:
652             if (inst->isAligned16Inst())
653             {
654                 SetDstHorzStride(mybin, HORZ_STRIDE_0);
655             }
656             else
657             {
658                 SetDstHorzStride(mybin, HORZ_STRIDE_1);
659             }
660             break;
661         case 2: SetDstHorzStride(mybin, HORZ_STRIDE_2); break;
662         case 4: SetDstHorzStride(mybin, HORZ_STRIDE_4); break;
663         case UNDEFINED_SHORT: SetDstHorzStride(mybin, HORZ_STRIDE_1); break;
664         default:  MUST_BE_TRUE(false, "wrong dst horizontal stride " << dst->getHorzStride()); break;
665     }
666 }
667 
668 
EncodeDstChanEn(G4_INST * inst,BinInst * mybin,G4_DstRegRegion * dst)669 inline void EncodeDstChanEn(G4_INST* inst, BinInst *mybin, G4_DstRegRegion *dst)
670 {
671 
672     if (dst->isAccRegValid())
673     {
674         SetDstChanEn(mybin, dst->getAccRegSel());
675         return;
676     }
677 
678     SetDstChanEn(mybin, dst->getWriteMask());
679 
680 }
681 
EncodeDstRegNum(G4_INST * inst,BinInst * mybin,G4_DstRegRegion * dst)682 inline void BinaryEncoding::EncodeDstRegNum(G4_INST* inst, BinInst *mybin, G4_DstRegRegion *dst)
683 {
684     if (EncodingHelper::GetDstRegFile(dst) != REG_FILE_A &&
685          EncodingHelper::GetDstAddrMode(dst) == ADDR_MODE_IMMED)
686     {
687         uint32_t byteAddress = dst->getLinearizedStart();
688 
689         MUST_BE_TRUE(byteAddress < kernel.getNumRegTotal() * numEltPerGRF<Type_UB>(), "dst exceeds total GRF number");
690 
691         if (inst->isAligned1Inst())
692         {
693             SetDstRegNumByte(mybin, byteAddress);
694         } else {
695             SetDstRegNumOWord(mybin, byteAddress/BYTES_PER_OWORD);
696         }
697     }
698 }
699 
EncodeDstArchRegNum(G4_INST * inst,BinInst * mybin,G4_DstRegRegion * dst)700 inline void EncodeDstArchRegNum(G4_INST* inst, BinInst *mybin, G4_DstRegRegion *dst)
701 {
702     unsigned short RegNumValue = 0, RegSubNumValue = 0;
703     bool valid, subValid;
704     uint32_t regOffset;
705 
706     if (EncodingHelper::GetDstRegFile(dst) == REG_FILE_A  &&
707          EncodingHelper::GetDstAddrMode(dst) == ADDR_MODE_IMMED)
708     {
709         if (EncodingHelper::GetDstArchRegType(dst) != ARCH_REG_FILE_NULL)
710         {
711             RegNumValue = dst->ExRegNum(valid);
712             RegSubNumValue = dst->ExSubRegNum(subValid);
713 
714             SetDstArchRegNum(mybin, RegNumValue);
715 
716             unsigned short ElementSizeValue = EncodingHelper::GetElementSizeValue(dst);
717             regOffset = RegSubNumValue * ElementSizeValue;
718             if (inst->isAligned1Inst()) {
719                 SetDstArchSubRegNumByte(mybin, regOffset);
720             } else {
721                 SetDstArchSubRegNumOWord(mybin, regOffset/BYTES_PER_OWORD);
722             }
723         }
724     }
725 }
726 
EncodeDstIndirectRegNum(G4_INST * inst,BinInst * mybin,G4_DstRegRegion * dst)727 inline void EncodeDstIndirectRegNum(G4_INST* inst, BinInst *mybin, G4_DstRegRegion *dst)
728 {
729     bool subValid;
730     unsigned short IndAddrRegSubNumValue = 0;
731     short IndAddrImmedValue = 0;
732 
733     if (EncodingHelper::GetDstRegFile(dst)==REG_FILE_R ||
734          EncodingHelper::GetDstRegFile(dst)==REG_FILE_M)
735     {
736         if (EncodingHelper::GetDstAddrMode(dst) == ADDR_MODE_INDIR)
737         { // Indirect
738             IndAddrRegSubNumValue = dst->ExIndSubRegNum(subValid);
739             IndAddrImmedValue = dst->ExIndImmVal();
740 
741             SetDstIdxRegNum(mybin, IndAddrRegSubNumValue);
742             /* Set the indirect address immediate value. */
743             if (inst->isAligned1Inst())
744             {
745                 SetDstIdxImmByte(mybin, IndAddrImmedValue);
746             }  else  {
747                 SetDstIdxImmOWord(mybin, IndAddrImmedValue / BYTES_PER_OWORD);
748             }
749         }
750     }
751 }
752 
753 
754 ///////////////////////////////////////////////////////////////////////////////
755 //                       Src0
756 ///////////////////////////////////////////////////////////////////////////////
757 
758 
SetSrc0RegFile(BinInst * mybin,uint32_t value)759 inline void SetSrc0RegFile(BinInst *mybin, uint32_t value)
760 {
761     if (mybin->GetIs3Src())
762         return;
763     else
764         mybin->SetBits(bitsSrcRegFile[0],bitsSrcRegFile[1],value);
765 }
766 
SetSrc0Type(BinInst * mybin,uint32_t value)767 inline void SetSrc0Type(BinInst *mybin, uint32_t value)
768 {
769     if (mybin->GetIs3Src())
770         // handled by Set3SrcSrcType
771         return;
772     else
773         mybin->SetBits(bitsSrcType[0],bitsSrcType[1],value);
774 }
775 
SetSrc0AddrMode(BinInst * mybin,uint32_t value)776 inline void SetSrc0AddrMode(BinInst *mybin, uint32_t value)
777 {
778     if (mybin->GetIs3Src())
779         return;
780     else
781         mybin->SetBits(bitsSrcAddrMode_0,bitsSrcAddrMode_1,value);
782 }
783 
SetSrc0SrcMod(BinInst * mybin,uint32_t value)784 inline void SetSrc0SrcMod(BinInst *mybin, uint32_t value)
785 {
786     if (mybin->GetIs3Src())
787         mybin->SetBits(bits3SrcSrcMod[0], bits3SrcSrcMod[1], value);
788     else
789         mybin->SetBits(bitsSrcSrcMod_0, bitsSrcSrcMod_1,value);
790 }
791 
SetSrc0RepCtrl(BinInst * mybin,uint32_t value)792 inline void SetSrc0RepCtrl(BinInst *mybin, uint32_t value)
793 {
794     if (mybin->GetIs3Src())
795         mybin->SetBits(bits3SrcRepCtrl_0, bits3SrcRepCtrl_1, value);
796     else
797         return;
798 }
799 
SetSrc0Swizzle(BinInst * mybin,uint32_t value)800 inline void SetSrc0Swizzle(BinInst *mybin, uint32_t value)
801 {
802     if (mybin->GetIs3Src())
803         mybin->SetBits(bits3SrcSwizzle_0, bits3SrcSwizzle_1, value);
804     else
805         return;
806 }
807 
SetSrc0RegNumOWord(BinInst * mybin,uint32_t value)808 inline void SetSrc0RegNumOWord(BinInst *mybin, uint32_t value)
809 {
810     if (mybin->GetIs3Src())
811         mybin->SetBits(bits3SrcSrcRegNumOWord_0,
812             bits3SrcSrcRegNumOWord_1, value);
813     else
814         mybin->SetBits(bitsSrcRegNumOWord_0,
815             bitsSrcRegNumOWord_1, value);
816 }
817 
SetSrc0RegNumByte(BinInst * mybin,uint32_t value)818 inline void SetSrc0RegNumByte(BinInst *mybin, uint32_t value)
819 {
820     mybin->SetBits(bitsSrcRegNumByte_0,
821         bitsSrcRegNumByte_1, value);
822 }
823 
SetSrc0ChanSel_0(BinInst * mybin,uint32_t value)824 inline void SetSrc0ChanSel_0(BinInst *mybin, uint32_t value)
825 {
826     if (mybin->GetIs3Src())
827         mybin->SetBits(bits3SrcChanSel_0_0,
828             bits3SrcChanSel_0_1, value);
829     else
830         mybin->SetBits(bitsSrcChanSel_0_0,
831             bitsSrcChanSel_0_1,value);
832 }
833 
834 
SetSrc0ChanSel_1(BinInst * mybin,uint32_t value)835 inline void SetSrc0ChanSel_1(BinInst *mybin, uint32_t value)
836 {
837     if (mybin->GetIs3Src())
838         mybin->SetBits(bits3SrcChanSel_1_0,
839             bits3SrcChanSel_1_1, value);
840     else
841         mybin->SetBits(bitsSrcChanSel_1_0,
842          bitsSrcChanSel_1_1,value);
843 }
844 
SetSrc0ChanSel_2(BinInst * mybin,uint32_t value)845 inline void SetSrc0ChanSel_2(BinInst *mybin, uint32_t value)
846 {
847     if (mybin->GetIs3Src())
848         mybin->SetBits(bits3SrcChanSel_2_0,
849             bits3SrcChanSel_2_1, value);
850     else
851         mybin->SetBits(bitsSrcChanSel_2_0,
852             bitsSrcChanSel_2_1,value);
853 }
854 
SetSrc0ChanSel_3(BinInst * mybin,uint32_t value)855 inline void SetSrc0ChanSel_3(BinInst *mybin, uint32_t value)
856 {
857     if (mybin->GetIs3Src())
858         mybin->SetBits(bits3SrcChanSel_3_0,
859         bits3SrcChanSel_3_1, value);
860     else
861         mybin->SetBits(bitsSrcChanSel_3_0,
862             bitsSrcChanSel_3_1, value);
863 }
864 
SetSrc0VertStride(BinInst * mybin,uint32_t value)865 inline void SetSrc0VertStride(BinInst *mybin, uint32_t value)
866 {
867     if (mybin->GetIs3Src())
868         return;
869     else
870         mybin->SetBits(bitsSrcVertStride_0,bitsSrcVertStride_1,value);
871     }
872 
SetSrc0Width(BinInst * mybin,uint32_t value)873 inline void SetSrc0Width(BinInst *mybin, uint32_t value)
874 {
875     if (mybin->GetIs3Src())
876         return;
877     else
878         mybin->SetBits(bitsSrcWidth_0,bitsSrcWidth_1,value);
879 }
880 
SetSrc0HorzStride(BinInst * mybin,uint32_t value)881 inline void SetSrc0HorzStride(BinInst *mybin, uint32_t value)
882 {
883     if (mybin->GetIs3Src())
884         return;
885     else
886         mybin->SetBits(bitsSrcHorzStride_0,bitsSrcHorzStride_1,value);
887 }
888 
889 /**
890  *  Below three functions set src0's indirect register number
891  */
SetSrc0IdxRegNum(BinInst * mybin,uint32_t value)892 inline void SetSrc0IdxRegNum(BinInst *mybin, uint32_t value)
893 {
894     if (mybin->GetIs3Src())
895         return;
896     else
897         mybin->SetBits(bitsSrcIdxRegNum[0],bitsSrcIdxRegNum[1],value);
898 }
899 
SetSrc0IdxImmOWord(BinInst * mybin,uint32_t value)900 inline void SetSrc0IdxImmOWord(BinInst *mybin, uint32_t value)
901 {
902     if (mybin->GetIs3Src())
903         return;
904     mybin->SetBits(bitsSrcIdxImmOWord[0], bitsSrcIdxImmOWord[1], value);
905     mybin->SetBits(bitsSrcIdxImmMSB[0], bitsSrcIdxImmMSB[1], (value >> 5));
906 }
907 
SetSrc0IdxImmByte(BinInst * mybin,uint32_t value)908 inline void SetSrc0IdxImmByte(BinInst *mybin, uint32_t value)
909 {
910     if (mybin->GetIs3Src())
911         return;
912     mybin->SetBits(bitsSrcIdxImmByte[0], bitsSrcIdxImmByte[1], value);
913     mybin->SetBits(bitsSrcIdxImmMSB[0], bitsSrcIdxImmMSB[1], (value >> 9));
914 
915 }
916 
SetSrc0ArchRegFile(BinInst * mybin,uint32_t value)917 inline void SetSrc0ArchRegFile(BinInst *mybin, uint32_t value)
918 {
919     if (mybin->GetIs3Src())
920         return;
921     else
922         mybin->SetBits(bitsSrcArchRegFile_0,bitsSrcArchRegFile_1,value);
923 }
924 
SetSrc0ArchRegNum(BinInst * mybin,uint32_t value)925 inline void SetSrc0ArchRegNum(BinInst *mybin, uint32_t value)
926 {
927     if (mybin->GetIs3Src())
928         return;
929     else
930         mybin->SetBits(bitsSrcArchRegNum_0,bitsSrcArchRegNum_1,value);
931 }
932 
SetSrc0ArchSubRegNumOWord(BinInst * mybin,uint32_t value)933 inline void SetSrc0ArchSubRegNumOWord(BinInst *mybin, uint32_t value)
934 {
935     if (mybin->GetIs3Src())
936         return;
937     else
938         mybin->SetBits(bitsSrcArchSubRegNumOWord_0,bitsSrcArchSubRegNumOWord_1,value);
939 }
940 
SetSrc0ArchSubRegNumWord(BinInst * mybin,uint32_t value)941 inline void SetSrc0ArchSubRegNumWord(BinInst *mybin, uint32_t value)
942 {
943     if (mybin->GetIs3Src())
944         return;
945     else
946         mybin->SetBits(bitsSrcArchSubRegNumWord_0,bitsSrcArchSubRegNumWord_1,value);
947 }
948 
SetSrc0ArchSubRegNumByte(BinInst * mybin,uint32_t value)949 inline void SetSrc0ArchSubRegNumByte(BinInst *mybin, uint32_t value)
950 {
951     if (mybin->GetIs3Src())
952         return;
953     else
954         mybin->SetBits(bitsSrcArchSubRegNumByte_0,bitsSrcArchSubRegNumByte_1,value);
955 }
956 
SetSrc0Imm32(BinInst * mybin,uint32_t value,G4_Operand * src)957 inline void SetSrc0Imm32(BinInst *mybin, uint32_t value, G4_Operand* src)
958 {
959     if (mybin->GetIs3Src())
960         return;
961     else
962         mybin->SetBits(bitsSrcImm32_0,bitsSrcImm32_1,value);
963 }
964 
SetSrc0Imm64(BinInst * mybin,uint64_t value,G4_Operand * src)965 inline void SetSrc0Imm64(BinInst *mybin, uint64_t value, G4_Operand* src)
966 {
967     uint32_t low = value & 0xFFFFFFFF;
968     uint32_t high = value >> 32;
969     mybin->SetBits(bitsSrcImm64_2, bitsSrcImm64_3, low);
970     mybin->SetBits(bitsSrcImm64_0, bitsSrcImm64_1, high);
971 }
972 
EncodeSrc0RegFile(BinInst * mybin,G4_Operand * src0)973 inline void EncodeSrc0RegFile(BinInst *mybin, G4_Operand *src0)
974 {
975     RegFile refFile = EncodingHelper::GetSrcRegFile(src0);
976     SetSrc0RegFile(mybin, refFile);
977     if (refFile == REG_FILE_A) {
978         SetSrc0ArchRegFile(mybin, EncodingHelper::GetSrcArchRegType(src0));
979     }
980 }
981 
EncodeSrc0Type(G4_INST * inst,BinInst * mybin,G4_Operand * src0)982 inline void EncodeSrc0Type(G4_INST *inst, BinInst *mybin, G4_Operand *src0)
983 {
984     if (src0->isImm())
985     {
986         SetSrc0Type(mybin, GetOperandSrcImmType(src0));
987     } else {
988         //no need to force to F anymore.
989         //Also need actual type for IGA.
990         //So that through binary to binary path I can figure out
991         //whether I need to set bits 29/30 in msgDescriptor
992         //due to HW Bug on SKL.
993         if (inst->getPlatform() >= GENX_CHV)
994         {
995             SetSrc0Type(mybin, GetOperandSrcType(src0));
996         }
997         else
998         {
999             if (inst->isSend())
1000                 SetSrc0Type(mybin, SRC_TYPE_F);
1001             else
1002                 SetSrc0Type(mybin, GetOperandSrcType(src0));
1003         }
1004     }
1005 }
1006 
SetSrc1Imm32(BinInst * mybin,uint32_t value,G4_Operand * src)1007 inline void SetSrc1Imm32(BinInst *mybin, uint32_t value, G4_Operand* src)
1008 {
1009     if (mybin->GetIs3Src())
1010         return;
1011     else
1012         mybin->SetBits(bitsSrcImm32_2,bitsSrcImm32_3,value);
1013 }
1014 
EncodeSrcImmData(BinInst * mybin,G4_Operand * src)1015 inline void EncodeSrcImmData(BinInst *mybin, G4_Operand *src)
1016 {
1017     G4_Imm *isrc = (G4_Imm *)src->asImm();
1018     if (IS_WTYPE(src->getType()))
1019     {
1020         uint32_t val = (uint32_t) isrc->getInt();
1021         uint32_t data = (val << 16) | (val & 0xffff);
1022         SetSrc1Imm32(mybin, data, src);
1023     }
1024     else if (src->getType() == Type_F)
1025     {
1026         // Cannot use getFloat() as it will change sNAN to qNAN (bug1892)
1027         SetSrc1Imm32(mybin, (uint32_t)isrc->getImm(), src);
1028     }
1029     else if (src->getType() == Type_DF)
1030     {
1031         SetSrc0Imm64(mybin, (uint64_t)isrc->getImm(), src);
1032     }
1033     else if (src->getType() == Type_Q  || src->getType() == Type_UQ)
1034     {
1035         int64_t val = isrc->getInt();
1036         SetSrc0Imm64(mybin, *(uint64_t*)&(val), src);
1037     }
1038     else {
1039         SetSrc1Imm32(mybin, (uint32_t)isrc->getInt(), src);
1040     }
1041 }
1042 
EncodeSrc0AddrMode(BinInst * mybin,G4_Operand * src0)1043 inline void EncodeSrc0AddrMode(BinInst *mybin, G4_Operand *src0)
1044 {
1045     SetSrc0AddrMode(mybin, EncodingHelper::GetSrcAddrMode(src0));
1046 }
1047 
EncodeSrc0ChanSelect(G4_INST * inst,BinInst * mybin,G4_Operand * src0,G4_SrcRegRegion * srcRegion)1048 inline void EncodeSrc0ChanSelect(G4_INST *inst,
1049                                   BinInst *mybin,
1050                                   G4_Operand *src0,
1051                                   G4_SrcRegRegion *srcRegion)
1052 {
1053     // encode acc2~acc9 if it is valid
1054     if (src0->isAccRegValid())
1055     {
1056         if (inst->opcode() == G4_madm ||
1057             (inst->isMath() && inst->asMathInst()->getMathCtrl() == MATH_INVM) ||
1058             (inst->isMath() && inst->asMathInst()->getMathCtrl() == MATH_RSQRTM))
1059         {
1060             uint32_t value = src0->getAccRegSel();
1061             SetSrc0ChanSel_0(mybin, value & 0x3);
1062             SetSrc0ChanSel_1(mybin, value >> 2 & 0x3);
1063             SetSrc0ChanSel_2(mybin, 0);
1064             SetSrc0ChanSel_3(mybin, 0);
1065             return;
1066         }
1067         ASSERT_USER(false, "acc2~acc7 were set on wrong instruction");
1068     }
1069 
1070     const char *swizzle = srcRegion->getSwizzle();
1071     if (swizzle[0] != '\0' && swizzle[0] != 'r') {
1072         ChanSel ch0 = EncodingHelper::GetSrcChannelSelectValue(srcRegion, 0);
1073         ChanSel ch1 = EncodingHelper::GetSrcChannelSelectValue(srcRegion, 1);
1074         ChanSel ch2 = EncodingHelper::GetSrcChannelSelectValue(srcRegion, 2);
1075         ChanSel ch3 = EncodingHelper::GetSrcChannelSelectValue(srcRegion, 3);
1076         if (ch0 != CHAN_SEL_UNDEF)
1077             SetSrc0ChanSel_0(mybin, ch0);
1078         if (ch1 != CHAN_SEL_UNDEF)
1079             SetSrc0ChanSel_1(mybin, ch1);
1080         if (ch2 != CHAN_SEL_UNDEF)
1081             SetSrc0ChanSel_2(mybin, ch2);
1082         if (ch3 != CHAN_SEL_UNDEF)
1083             SetSrc0ChanSel_3(mybin, ch3);
1084     }
1085 
1086     if (swizzle[0] == '\0')
1087     {
1088         if (inst->isAligned16Inst())
1089         {
1090             SetSrc0ChanSel_0(mybin, CHAN_SEL_X);
1091             SetSrc0ChanSel_1(mybin, CHAN_SEL_Y);
1092             SetSrc0ChanSel_2(mybin, CHAN_SEL_Z);
1093             SetSrc0ChanSel_3(mybin, CHAN_SEL_W);
1094         }
1095     }
1096     else if (inst->getNumSrc() == 3 && !inst->isSend())
1097     {
1098         if (swizzle[0] == 'r')
1099         {
1100             if (inst->isAligned16Inst())
1101             {
1102                 SetSrc0ChanSel_0(mybin, CHAN_SEL_X);
1103                 SetSrc0ChanSel_1(mybin, CHAN_SEL_Y);
1104                 SetSrc0ChanSel_2(mybin, CHAN_SEL_Z);
1105                 SetSrc0ChanSel_3(mybin, CHAN_SEL_W);
1106             }
1107         }
1108     }
1109 }
1110 
EncodeSrc0RepCtrl(BinInst * mybin,G4_SrcRegRegion * srcRegion)1111 inline void EncodeSrc0RepCtrl(BinInst *mybin, G4_SrcRegRegion *srcRegion)
1112 {
1113     const char *swizzle = srcRegion->getSwizzle();
1114     if (swizzle[0] == 'r')
1115         SetSrc0RepCtrl(mybin, 0x1);
1116     else
1117         SetSrc0RepCtrl(mybin, 0x0);
1118 }
1119 
EncodeSrc0Modifier(BinInst * mybin,G4_Operand * src0,G4_SrcRegRegion * srcRegion)1120 inline void EncodeSrc0Modifier(BinInst *mybin, G4_Operand *src0, G4_SrcRegRegion *srcRegion)
1121 {
1122     if (EncodingHelper::GetSrcRegFile(src0) != REG_FILE_M)
1123     {
1124         SetSrc0SrcMod(mybin, GetSrcMod(srcRegion));
1125     }
1126 };
1127 
1128 static const uint32_t EXEC_CHANNELS[6] =
1129 {
1130      WIDTH_1,
1131      WIDTH_2,
1132      WIDTH_4,
1133      WIDTH_8,
1134      WIDTH_8,
1135      WIDTH_16
1136 };
1137 
EncodeSrc0Width(G4_INST * inst,BinInst * mybin,const RegionDesc * rd,G4_Operand * src0)1138 inline bool EncodeSrc0Width(
1139     G4_INST *inst, BinInst *mybin, const RegionDesc *rd, G4_Operand *src0)
1140 {
1141     bool WidthValid = false;
1142     if (inst->isAligned16Inst()) return false;
1143 
1144     if (rd)
1145     {
1146         if (rd->width != UNDEFINED_SHORT)
1147         {
1148             WidthValid = true;
1149         }
1150         switch (rd->width)
1151         {
1152             case 1:  SetSrc0Width(mybin, WIDTH_1); break;
1153             case 2:  SetSrc0Width(mybin, WIDTH_2); break;
1154             case 4:  SetSrc0Width(mybin, WIDTH_4); break;
1155             case 8:  SetSrc0Width(mybin, WIDTH_8); break;
1156             case 16: SetSrc0Width(mybin, WIDTH_16); break;
1157             case UNDEFINED_SHORT: break;
1158             default: MUST_BE_TRUE(false, "wrong width for src0!"); break;
1159         }
1160 
1161     }
1162 
1163     // apply default width
1164     if (!WidthValid)
1165     {
1166         if (EncodingHelper::isSrcSubRegNumValid(src0))
1167         {
1168             SetSrc0Width(mybin, WIDTH_1);
1169         }
1170         else
1171         {
1172             uint32_t execSize = GetEncodeExecSize(inst);
1173             MUST_BE_TRUE(execSize <= (uint32_t)ES_32_CHANNELS,
1174                          "BinaryEncoding: Invalid exeuction channels");
1175             SetSrc0Width(mybin, EXEC_CHANNELS[execSize]);
1176         }
1177     }
1178 
1179     return WidthValid;
1180  }
1181 
1182 static const unsigned HORIZONTAL_STRIDE[6] =
1183 {
1184     (unsigned)HORZ_STRIDE_0,
1185     (unsigned)HORZ_STRIDE_1,
1186     (unsigned)HORZ_STRIDE_1,
1187     (unsigned)HORZ_STRIDE_1,
1188     (unsigned)HORZ_STRIDE_1,
1189     (unsigned)HORZ_STRIDE_1,
1190 };
1191 
EncodeSrc0HorzStride(G4_INST * inst,BinInst * mybin,const RegionDesc * rd,G4_Operand * src0)1192 inline bool EncodeSrc0HorzStride(
1193     G4_INST *inst, BinInst *mybin, const RegionDesc *rd, G4_Operand *src0)
1194 {
1195     // For Align16 instruction (SIMD4), treat <HorzStride> as <VertStride>
1196     // For Align16 source operand disable HorzStride
1197     bool HorzStrideValid = false;  // undef
1198     if (inst->isAligned16Inst()) return false;
1199 
1200     if (rd)  {
1201         if (rd->horzStride != UNDEFINED_SHORT)
1202         {
1203             HorzStrideValid = true;
1204         }
1205         switch (rd->horzStride)
1206         {
1207             case 0: SetSrc0HorzStride(mybin, HORZ_STRIDE_0); break;
1208             case 1: SetSrc0HorzStride(mybin, HORZ_STRIDE_1); break;
1209             case 2: SetSrc0HorzStride(mybin, HORZ_STRIDE_2); break;
1210             case 4: SetSrc0HorzStride(mybin, HORZ_STRIDE_4); break;
1211             case UNDEFINED_SHORT: break;
1212             default: MUST_BE_TRUE(false, "wrong horizontal stride for src0!"); break;
1213         }
1214     }
1215     // apply default horizontal stride
1216     if (!HorzStrideValid)
1217     {
1218         if (EncodingHelper::isSrcSubRegNumValid(src0))
1219              SetSrc0HorzStride(mybin, HORZ_STRIDE_0);
1220         else
1221         {
1222             uint32_t execSize = GetEncodeExecSize(inst);
1223             if (execSize <= (uint32_t)ES_32_CHANNELS)
1224                 SetSrc0HorzStride(mybin, HORIZONTAL_STRIDE[execSize]);
1225         }
1226     } // end of valid horz stride
1227     return HorzStrideValid;
1228 }
1229 
1230 static const unsigned VERTICAL_STRIDE[6] =
1231 {
1232      (unsigned)VERT_STRIDE_0,
1233      (unsigned)VERT_STRIDE_2,
1234      (unsigned)VERT_STRIDE_4,
1235      (unsigned)VERT_STRIDE_8,
1236      (unsigned)VERT_STRIDE_8,
1237      (unsigned)VERT_STRIDE_16
1238 };
1239 
EncodeSrc0VertStride(G4_INST * inst,BinInst * mybin,const RegionDesc * rd,G4_Operand * src0,bool WidthValid,bool HorzStrideValid)1240 inline void EncodeSrc0VertStride(
1241     G4_INST *inst,
1242     BinInst *mybin,
1243     const RegionDesc *rd,
1244     G4_Operand *src0,
1245     bool WidthValid,
1246     bool HorzStrideValid)
1247 {
1248     bool VertStrideValid = false; // undef
1249     unsigned short VertStrideValue = UNDEFINED_SHORT, HorzStrideValue = 0;
1250 
1251     if (rd)
1252     {
1253         VertStrideValue = rd->vertStride;
1254         HorzStrideValue = rd->horzStride;
1255         if (VertStrideValue != UNDEFINED_SHORT)
1256         {
1257             VertStrideValid = true;
1258         }
1259         switch (VertStrideValue)
1260         {
1261             case 0:   SetSrc0VertStride(mybin, VERT_STRIDE_0); break;
1262             case 1:   SetSrc0VertStride(mybin, VERT_STRIDE_1); break;
1263             case 2:   SetSrc0VertStride(mybin, VERT_STRIDE_2); break;
1264             case 4:   SetSrc0VertStride(mybin, VERT_STRIDE_4); break;
1265             case 8:   SetSrc0VertStride(mybin, VERT_STRIDE_8); break;
1266             case 16:  SetSrc0VertStride(mybin, VERT_STRIDE_16); break;
1267             case 32:  SetSrc0VertStride(mybin, VERT_STRIDE_32); break;
1268             case UNDEFINED_SHORT: break;
1269             default: MUST_BE_TRUE(false, "wrong vertical stride for src0!"); break;
1270         }
1271     }
1272 
1273     //apply default vertical stride below
1274     if (!WidthValid             &&
1275         !HorzStrideValid        &&
1276         !VertStrideValid        &&
1277         src0)
1278     {
1279         VertStrideValid = true;
1280         if (EncodingHelper::isSrcSubRegNumValid(src0))
1281         {
1282             SetSrc0VertStride(mybin, VERT_STRIDE_0);
1283         }
1284         else
1285         {
1286             if (inst->isAligned1Inst())
1287             {
1288                 uint32_t value = GetEncodeExecSize(inst);
1289                 MUST_BE_TRUE(value <= (uint32_t)ES_32_CHANNELS,
1290                              "BinaryEncoding: Invalid execution size");
1291                 SetSrc0VertStride(mybin, VERTICAL_STRIDE[value]);
1292             }
1293             else
1294             {
1295                 SetSrc0VertStride(mybin, VERT_STRIDE_4);
1296             }
1297         }
1298     }
1299 
1300     if (VertStrideValid) { }
1301     else if (inst->isAligned16Inst())
1302     {
1303         if (HorzStrideValid  && HorzStrideValue == 0)
1304         {
1305             SetSrc0HorzStride(mybin, HORZ_STRIDE_1);
1306             SetSrc0VertStride(mybin, VERT_STRIDE_0);
1307         }
1308         else if (HorzStrideValid  && HorzStrideValue == 4)
1309         {
1310             SetSrc0HorzStride(mybin, HORZ_STRIDE_1);
1311             SetSrc0VertStride(mybin, VERT_STRIDE_4);
1312         }
1313     }
1314     else if (src0 != NULL && EncodingHelper::GetSrcAddrMode(src0) == ADDR_MODE_INDIR) { //indirect
1315         SetSrc0VertStride(mybin, VERT_STRIDE_ONE_DIMEN);
1316     }
1317 
1318 }
1319 
EncodeSrc0ArchRegNum(G4_INST * inst,BinInst * mybin,G4_SrcRegRegion * src0)1320 inline void EncodeSrc0ArchRegNum(G4_INST* inst, BinInst *mybin, G4_SrcRegRegion *src0)
1321 {
1322     unsigned short RegNumValue = 0, RegSubNumValue = 0;
1323     bool valid, subValid;
1324     uint32_t regOffset;
1325 
1326     if (EncodingHelper::GetSrcRegFile(src0)==REG_FILE_A &&
1327         EncodingHelper::GetSrcAddrMode(src0)==ADDR_MODE_IMMED)
1328     {
1329         if (EncodingHelper::GetSrcArchRegType(src0) != ARCH_REG_FILE_NULL)
1330         {
1331             RegNumValue = src0->ExRegNum(valid);
1332             RegSubNumValue = src0->ExSubRegNum(subValid);
1333 
1334             SetSrc0ArchRegNum(mybin, RegNumValue);
1335 
1336             unsigned short ElementSizeValue = EncodingHelper::GetElementSizeValue(src0);
1337             regOffset = RegSubNumValue * ElementSizeValue;
1338             if (inst->isAligned1Inst()) {
1339                 SetSrc0ArchSubRegNumByte(mybin, regOffset);
1340             } else {
1341                 SetSrc0ArchSubRegNumOWord(mybin, regOffset/BYTES_PER_OWORD);
1342             }
1343         }
1344     }
1345 
1346 }
1347 
1348 
EncodeSrc0RegNum(G4_INST * inst,BinInst * mybin,G4_Operand * src0)1349 inline void BinaryEncoding::EncodeSrc0RegNum(G4_INST* inst, BinInst *mybin, G4_Operand *src0)
1350 {
1351     if (EncodingHelper::GetSrcRegFile(src0) != REG_FILE_A &&
1352          EncodingHelper::GetSrcAddrMode(src0) == ADDR_MODE_IMMED)
1353     {
1354         bool repControl = EncodingHelper::GetRepControl(src0);
1355         uint32_t byteAddress = src0->getLinearizedStart();
1356         MUST_BE_TRUE(byteAddress < kernel.getNumRegTotal() * numEltPerGRF<Type_UB>(), "src0 exceeds total GRF number");
1357 
1358         if (mybin->GetIs3Src())
1359         {
1360             // encode dwords
1361             mybin->SetBits(bits3SrcSrc0RegDWord_H, bits3SrcSrc0RegDWord_L, byteAddress >> 2);
1362             // encode word (for word type)
1363             mybin->SetBits(bits3SrcSrc0SubRegNumW_H, bits3SrcSrc0SubRegNumW_L, (byteAddress >> 1) & 0x1);
1364 
1365         }
1366         else if (inst->isAligned1Inst() || repControl)
1367         {
1368             SetSrc0RegNumByte(mybin, byteAddress);
1369         }
1370         else
1371         {
1372             SetSrc0RegNumOWord(mybin, byteAddress/BYTES_PER_OWORD);
1373         }
1374     }
1375 }
1376 
EncodeSrc0IndirectRegNum(G4_INST * inst,BinInst * mybin,G4_SrcRegRegion * src0)1377 inline void EncodeSrc0IndirectRegNum(G4_INST* inst, BinInst *mybin, G4_SrcRegRegion *src0)
1378 {
1379     bool subValid;
1380     unsigned short IndAddrRegSubNumValue = 0;
1381     short IndAddrImmedValue = 0;
1382 
1383     if (EncodingHelper::GetSrcAddrMode(src0) == ADDR_MODE_INDIR)
1384     {
1385         if (!(EncodingHelper::GetSrcRegFile(src0)==REG_FILE_A &&
1386               EncodingHelper::GetSrcArchRegType(src0)==ARCH_REG_FILE_NULL))
1387         {
1388             IndAddrRegSubNumValue = src0->ExIndSubRegNum(subValid);
1389             IndAddrImmedValue = src0->ExIndImmVal();
1390 
1391             SetSrc0IdxRegNum(mybin, IndAddrRegSubNumValue);
1392             /* Set the indirect address immediate value. */
1393             if (inst->isAligned1Inst())
1394             {
1395                 SetSrc0IdxImmByte(mybin, IndAddrImmedValue);
1396             }  else  {
1397                 SetSrc0IdxImmOWord(mybin, IndAddrImmedValue / BYTES_PER_OWORD);
1398             }
1399         }
1400     }
1401 }
1402 
Set3SrcSrcType(BinInst * mybin,G4_INST * inst)1403 inline void Set3SrcSrcType(BinInst *mybin, G4_INST *inst)
1404 {
1405     if (inst->getSrc(0) == NULL) return;
1406     G4_Type type = inst->getSrc(0)->getType();
1407     ThreeSrcType sType = THREE_SRC_TYPE_F;
1408     switch (type)
1409     {
1410         case Type_F:
1411             sType = THREE_SRC_TYPE_F;
1412             break;
1413         case Type_D:
1414             sType = THREE_SRC_TYPE_D;
1415             break;
1416         case Type_UD:
1417             sType = THREE_SRC_TYPE_UD;
1418             break;
1419         case Type_DF:
1420             sType = THREE_SRC_TYPE_DF;
1421             break;
1422         case Type_HF:
1423             sType = THREE_SRC_TYPE_HF;
1424             break;
1425         default:
1426             break;
1427     }
1428      mybin->SetBits(bits3SrcSrcType[0], bits3SrcSrcType[1], (uint32_t)sType);
1429      if (inst->getPlatform() >= GENX_CHV)
1430      {
1431          if (inst->getSrc(1)->getType() == Type_HF)
1432          {
1433              mybin->SetBits(bits3SrcSrc1Type, bits3SrcSrc1Type, 1);
1434          }
1435          if (inst->getSrc(2)->getType() == Type_HF)
1436          {
1437              mybin->SetBits(bits3SrcSrc2Type, bits3SrcSrc2Type, 1);
1438          }
1439      }
1440 }
1441 
Set3SrcDstType(BinInst * mybin,G4_Type type)1442 inline void Set3SrcDstType(BinInst *mybin, G4_Type type)
1443 {
1444     ThreeSrcType dType = THREE_SRC_TYPE_F;
1445     switch (type)
1446     {
1447         case Type_F:
1448             dType = THREE_SRC_TYPE_F;
1449             break;
1450         case Type_D:
1451             dType = THREE_SRC_TYPE_D;
1452             break;
1453         case Type_UD:
1454             dType = THREE_SRC_TYPE_UD;
1455             break;
1456         case Type_DF:
1457             dType = THREE_SRC_TYPE_DF;
1458             break;
1459         case Type_HF:
1460             dType = THREE_SRC_TYPE_HF;
1461             break;
1462         default:
1463             break;
1464     }
1465      mybin->SetBits(bits3SrcDstType[0], bits3SrcDstType[1], (uint32_t)dType);
1466 }
1467 
EncodeOperandDst(G4_INST * inst)1468 BinaryEncoding::Status BinaryEncoding::EncodeOperandDst(G4_INST* inst)
1469 {
1470     Status myStatus = SUCCESS;
1471     BinInst *mybin = inst->getBinInst();
1472     G4_DstRegRegion *dst = inst->getDst();
1473 
1474     if (inst->isSplitSend())
1475     {
1476         return EncodeSplitSendDst(inst);
1477     }
1478 
1479     if (mybin->GetIs3Src())
1480     {
1481         MUST_BE_TRUE(EncodingHelper::GetDstRegFile(dst) == REG_FILE_R, "Dst for 3src instruction must be GRF");
1482         Set3SrcDstType(mybin, dst->getType());
1483         Set3SrcSrcType(mybin, inst);
1484     }
1485 
1486     if (inst->opcode() == G4_wait) return SUCCESS;
1487     if (inst->opcode() == G4_jmpi)
1488     {
1489         SetDstRegFile(mybin, REG_FILE_A);
1490         SetDstArchRegFile(mybin, ARCH_REG_FILE_IP);
1491         //SetDstRegNumByte(mybin, 0);
1492         SetDstArchSubRegNumByte(mybin, 0);
1493         SetDstAddrMode(mybin, ADDR_MODE_IMMED);
1494         SetDstType(mybin, DST_TYPE_UD);
1495         SetDstHorzStride(mybin, 1);
1496 
1497         if (inst->getSrc(0))
1498         {
1499             SetSrc0RegFile(mybin, REG_FILE_A);
1500             SetSrc0ArchRegFile(mybin, ARCH_REG_FILE_IP);
1501             SetSrc0Type(mybin, DST_TYPE_UD);
1502             SetSrc0AddrMode(mybin, ADDR_MODE_IMMED);
1503             //SetSrc0RegNumByte(mybin, 0);
1504             SetSrc0ArchSubRegNumByte(mybin, 0);
1505             if (!(inst->getSrc(0)->isLabel()))
1506             {
1507                 SetSrc0Width(mybin, WIDTH_1);
1508                 SetDstHorzStride(mybin, 1);
1509             }
1510             else
1511             {
1512                 SetSrc0Width(mybin, WIDTH_1);
1513                 SetSrc0VertStride(mybin, VERT_STRIDE_0);
1514                 SetSrc0HorzStride(mybin, HORZ_STRIDE_0);
1515                 SetSrc0SrcMod(mybin, SRC_MOD_NONE);
1516             }
1517         }
1518     }
1519 
1520     if (dst == NULL)
1521     {
1522         SetDstHorzStride(mybin, HORZ_STRIDE_1);
1523         return FAILURE;
1524     }
1525 
1526     SetOperandDstType(mybin, dst);
1527     EncodeDstRegFile(mybin, dst);
1528     EncodeDstAddrMode(mybin, dst);
1529     // Note: dst doesn't have the vertical stride and width
1530     EncodeDstHorzStride(inst, mybin, dst);
1531     EncodeDstChanEn(inst, mybin, dst);
1532     EncodeDstRegNum(inst, mybin, dst);
1533     EncodeDstIndirectRegNum(inst, mybin, dst);
1534     EncodeDstArchRegNum(inst, mybin, dst);
1535     return myStatus;
1536 }
1537 
1538 
EncodeOperandSrc0(G4_INST * inst)1539 inline BinaryEncoding::Status BinaryEncoding::EncodeOperandSrc0(G4_INST* inst)
1540 {
1541     Status myStatus = SUCCESS;
1542     if (inst->isLabel()  ||
1543          inst->isCall())
1544         return myStatus;
1545 
1546     if (inst->isSplitSend())
1547     {
1548         return EncodeSplitSendSrc0(inst);
1549     }
1550 
1551     BinInst *mybin = inst->getBinInst();
1552     G4_Operand *src0 = inst->getSrc(0);
1553 
1554     if (src0 == NULL ||src0->isLabel()) return FAILURE;
1555     if (inst->opcode() == G4_jmpi && src0->isSrcRegRegion())
1556     {
1557         // will treat this src0 as src1 in EncodeOperandSrc1
1558         return SUCCESS;
1559     }
1560 
1561     EncodeSrc0Type(inst, mybin, src0);
1562     EncodeSrc0RegFile(mybin, src0);
1563     if (src0->isImm())
1564     {
1565         if (inst->opcode() != G4_mov && src0->getTypeSize() == 8)
1566         {
1567             MUST_BE_TRUE(false, "only Mov is allowed for 64bit immediate");
1568         }
1569         EncodeSrcImmData(mybin, src0);
1570     }
1571     else
1572     {
1573         G4_SrcRegRegion* src0Region = src0->asSrcRegRegion();
1574         EncodeSrc0AddrMode(mybin, src0);
1575         EncodeSrc0ChanSelect(inst, mybin, src0, src0Region);
1576         EncodeSrc0RepCtrl(mybin, src0Region);
1577         EncodeSrc0Modifier(mybin, src0, src0Region);
1578 
1579         const RegionDesc *rd = src0Region->getRegion();
1580         bool WidthValid = EncodeSrc0Width(inst, mybin, rd, src0);
1581         bool HorzStrideValid = EncodeSrc0HorzStride(inst, mybin, rd, src0);
1582         EncodeSrc0VertStride(inst, mybin, rd, src0, WidthValid, HorzStrideValid);
1583 
1584         EncodeSrc0ArchRegNum(inst, mybin, src0Region);
1585         EncodeSrc0RegNum(inst, mybin, src0);
1586         EncodeSrc0IndirectRegNum(inst, mybin, src0Region);
1587     }
1588     return myStatus;
1589 }
1590 
1591 ///////////////////////////////////////////////////////////////////////////////
1592 //                       Src1
1593 ///////////////////////////////////////////////////////////////////////////////
1594 
SetSrc1RegFile(BinInst * mybin,uint32_t value)1595 inline void SetSrc1RegFile(BinInst *mybin, uint32_t value)
1596 {
1597     if (mybin->GetIs3Src())
1598         return;
1599     else
1600         mybin->SetBits(bitsSrcRegFile[2],bitsSrcRegFile[3],value);
1601 }
1602 
SetSrc1Type(BinInst * mybin,uint32_t value)1603 inline void SetSrc1Type(BinInst *mybin, uint32_t value)
1604 {
1605     if (mybin->GetIs3Src())
1606     // handled by Set3SrcSrcType
1607         return;
1608     else
1609      mybin->SetBits(bitsSrcType[2],bitsSrcType[3],value);
1610 }
1611 
SetSrc1AddrMode(BinInst * mybin,uint32_t value)1612 inline void SetSrc1AddrMode(BinInst *mybin, uint32_t value)
1613 {
1614     if (mybin->GetIs3Src())
1615         return;
1616     else
1617         mybin->SetBits(bitsSrcAddrMode_2,bitsSrcAddrMode_3,value);
1618 }
SetSrc1SrcMod(BinInst * mybin,uint32_t value)1619 inline void SetSrc1SrcMod(BinInst *mybin, uint32_t value)
1620 {
1621     if (mybin->GetIs3Src())
1622         mybin->SetBits(bits3SrcSrcMod[2],
1623             bits3SrcSrcMod[3],value);
1624     else
1625         mybin->SetBits(bitsSrcSrcMod_2,
1626             bitsSrcSrcMod_3,value);
1627 }
1628 
SetSrc1RepCtrl(BinInst * mybin,uint32_t value)1629 inline void SetSrc1RepCtrl(BinInst *mybin, uint32_t value)
1630 {
1631     if (mybin->GetIs3Src())
1632         mybin->SetBits(bits3SrcRepCtrl_2, bits3SrcRepCtrl_3, value);
1633     else
1634         return;
1635 }
1636 
SetSrc1Swizzle(BinInst * mybin,uint32_t value)1637 inline void SetSrc1Swizzle(BinInst *mybin, uint32_t value)
1638 {
1639     if (mybin->GetIs3Src())
1640         mybin->SetBits(bits3SrcSwizzle_2, bits3SrcSwizzle_3, value);
1641     else
1642         return;
1643 }
1644 
SetSrc1RegNumOWord(BinInst * mybin,uint32_t value)1645 inline void SetSrc1RegNumOWord(BinInst *mybin, uint32_t value)
1646 {
1647     if (mybin->GetIs3Src())
1648         mybin->SetBits(bits3SrcSrcRegNumOWord_2,
1649             bits3SrcSrcRegNumOWord_3, value);
1650     else
1651         mybin->SetBits(bitsSrcRegNumOWord_2,
1652             bitsSrcRegNumOWord_3, value);
1653 }
1654 
SetSrc1RegNumByte(BinInst * mybin,uint32_t value)1655 inline void SetSrc1RegNumByte(BinInst *mybin, uint32_t value)
1656 {
1657     mybin->SetBits(bitsSrcRegNumByte_2,bitsSrcRegNumByte_3,value);
1658 }
1659 
SetSrc1ChanSel_0(BinInst * mybin,uint32_t value)1660 inline void SetSrc1ChanSel_0(BinInst *mybin, uint32_t value)
1661 {
1662     if (mybin->GetIs3Src())
1663         mybin->SetBits(bits3SrcChanSel_0_2, bits3SrcChanSel_0_3, value);
1664     else
1665         mybin->SetBits(bitsSrcChanSel_0_2,bitsSrcChanSel_0_3,value);
1666 }
1667 
SetSrc1ChanSel_1(BinInst * mybin,uint32_t value)1668 void SetSrc1ChanSel_1(BinInst *mybin, uint32_t value)
1669 {
1670     if (mybin->GetIs3Src())
1671         mybin->SetBits(bits3SrcChanSel_1_2, bits3SrcChanSel_1_3, value);
1672     else
1673         mybin->SetBits(bitsSrcChanSel_1_2,bitsSrcChanSel_1_3,value);
1674 }
1675 
SetSrc1ChanSel_2(BinInst * mybin,uint32_t value)1676 inline void SetSrc1ChanSel_2(BinInst *mybin, uint32_t value)
1677 {
1678     if (mybin->GetIs3Src())
1679         mybin->SetBits(bits3SrcChanSel_2_2, bits3SrcChanSel_2_3, value);
1680     else
1681         mybin->SetBits(bitsSrcChanSel_2_2,bitsSrcChanSel_2_3,value);
1682 }
1683 
SetSrc1ChanSel_3(BinInst * mybin,uint32_t value)1684 inline void SetSrc1ChanSel_3(BinInst *mybin, uint32_t value)
1685 {
1686     if (mybin->GetIs3Src())
1687         mybin->SetBits(bits3SrcChanSel_3_2, bits3SrcChanSel_3_3, value);
1688     else
1689         mybin->SetBits(bitsSrcChanSel_3_2,bitsSrcChanSel_3_3,value);
1690 }
1691 
SetSrc1VertStride(BinInst * mybin,uint32_t value)1692 inline void SetSrc1VertStride(BinInst *mybin, uint32_t value)
1693 {
1694     if (mybin->GetIs3Src())
1695         return;
1696     else
1697         mybin->SetBits(bitsSrcVertStride_2,bitsSrcVertStride_3,value);
1698 }
1699 
SetSrc1Width(BinInst * mybin,uint32_t value)1700 inline void SetSrc1Width(BinInst *mybin, uint32_t value)
1701 {
1702     if (mybin->GetIs3Src())
1703         return;
1704     else
1705         mybin->SetBits(bitsSrcWidth_2,bitsSrcWidth_3,value);
1706 }
1707 
SetSrc1HorzStride(BinInst * mybin,uint32_t value)1708 inline void SetSrc1HorzStride(BinInst *mybin, uint32_t value)
1709 {
1710     if (mybin->GetIs3Src())
1711         return;
1712     else
1713         mybin->SetBits(bitsSrcHorzStride_2,bitsSrcHorzStride_3,value);
1714 }
1715 
1716 /**
1717  *  Below three functions set src1's indirect register number
1718  */
SetSrc1IdxRegNum(BinInst * mybin,uint32_t value)1719 inline void SetSrc1IdxRegNum(BinInst *mybin, uint32_t value)
1720 {
1721     if (mybin->GetIs3Src())
1722         return;
1723     else
1724         mybin->SetBits(bitsSrcIdxRegNum[2],bitsSrcIdxRegNum[3],value);
1725 }
1726 
SetSrc1IdxImmOWord(BinInst * mybin,uint32_t value)1727 inline void SetSrc1IdxImmOWord(BinInst *mybin, uint32_t value)
1728 {
1729     if (mybin->GetIs3Src())
1730         return;
1731     mybin->SetBits(bitsSrcIdxImmOWord[2], bitsSrcIdxImmOWord[3], value);
1732     mybin->SetBits(bitsSrcIdxImmMSB[2], bitsSrcIdxImmMSB[3], (value >> 5));
1733 }
1734 
SetSrc1IdxImmByte(BinInst * mybin,uint32_t value)1735 inline void SetSrc1IdxImmByte(BinInst *mybin, uint32_t value)
1736 {
1737     if (mybin->GetIs3Src())
1738         return;
1739     mybin->SetBits(bitsSrcIdxImmByte[2], bitsSrcIdxImmByte[3], value);
1740     mybin->SetBits(bitsSrcIdxImmMSB[2], bitsSrcIdxImmMSB[3], (value >> 9));
1741 }
1742 
SetSrc1ArchRegFile(BinInst * mybin,uint32_t value)1743 inline void SetSrc1ArchRegFile(BinInst *mybin, uint32_t value)
1744 {
1745     if (mybin->GetIs3Src())
1746         return;
1747     else
1748         mybin->SetBits(bitsSrcArchRegFile_2,bitsSrcArchRegFile_3,value);
1749 }
1750 
SetSrc1ArchRegNum(BinInst * mybin,uint32_t value)1751 inline void SetSrc1ArchRegNum(BinInst *mybin, uint32_t value)
1752 {
1753     if (mybin->GetIs3Src())
1754         return;
1755     else
1756         mybin->SetBits(bitsSrcArchRegNum_2,bitsSrcArchRegNum_3,value);
1757 }
1758 
SetSrc1ArchSubRegNumOWord(BinInst * mybin,uint32_t value)1759 inline void SetSrc1ArchSubRegNumOWord(BinInst *mybin, uint32_t value)
1760 {
1761     if (mybin->GetIs3Src())
1762         return;
1763     else
1764         mybin->SetBits(bitsSrcArchSubRegNumOWord_2,bitsSrcArchSubRegNumOWord_3,value);
1765 }
1766 
SetSrc1ArchSubRegNumWord(BinInst * mybin,uint32_t value)1767 inline void SetSrc1ArchSubRegNumWord(BinInst *mybin, uint32_t value)
1768 {
1769     if (mybin->GetIs3Src())
1770         return;
1771     else
1772         mybin->SetBits(bitsSrcArchSubRegNumWord_2,bitsSrcArchSubRegNumWord_3,value);
1773 }
1774 
SetSrc1ArchSubRegNumByte(BinInst * mybin,uint32_t value)1775 inline void SetSrc1ArchSubRegNumByte(BinInst *mybin, uint32_t value)
1776 {
1777     if (mybin->GetIs3Src())
1778         return;
1779     else
1780         mybin->SetBits(bitsSrcArchSubRegNumByte_2,bitsSrcArchSubRegNumByte_3,value);
1781 }
1782 
EncodeSrc1RegFile(BinInst * mybin,G4_Operand * src1)1783 inline void EncodeSrc1RegFile(BinInst *mybin, G4_Operand *src1)
1784 {
1785     RegFile regFile = EncodingHelper::GetSrcRegFile(src1);
1786     SetSrc1RegFile(mybin, regFile);
1787     if (regFile == REG_FILE_A)
1788     {
1789         SetSrc1ArchRegFile(mybin, EncodingHelper::GetSrcArchRegType(src1));
1790     }
1791 }
1792 
EncodeSrc1Type(BinInst * mybin,G4_Operand * src1)1793 inline void EncodeSrc1Type(BinInst *mybin, G4_Operand *src1)
1794 {
1795     if (src1->isImm())
1796     {
1797         SetSrc1Type(mybin, GetOperandSrcImmType(src1));
1798     } else {
1799         SetSrc1Type(mybin, GetOperandSrcType(src1));
1800     }
1801 }
1802 
EncodeSrc1AddrMode(BinInst * mybin,G4_Operand * src1)1803 inline void EncodeSrc1AddrMode(BinInst *mybin, G4_Operand *src1)
1804 {
1805     SetSrc1AddrMode(mybin, EncodingHelper::GetSrcAddrMode(src1));
1806 }
1807 
EncodeSrc1ChanSelect(G4_INST * inst,BinInst * mybin,G4_SrcRegRegion * srcRegion)1808 inline void EncodeSrc1ChanSelect(G4_INST *inst, BinInst *mybin, G4_SrcRegRegion *srcRegion)
1809 {
1810     // encode acc2~acc9 if it is valid
1811     if (srcRegion->isAccRegValid())
1812     {
1813         if (inst->opcode() == G4_madm ||
1814             (inst->isMath() && inst->asMathInst()->getMathCtrl() == MATH_INVM) ||
1815             (inst->isMath() && inst->asMathInst()->getMathCtrl() == MATH_RSQRTM))
1816         {
1817             uint32_t value = srcRegion->getAccRegSel();
1818             SetSrc1ChanSel_0(mybin, value & 0x3);
1819             SetSrc1ChanSel_1(mybin, value >> 2 & 0x3);
1820             SetSrc1ChanSel_2(mybin, 0);
1821             SetSrc1ChanSel_3(mybin, 0);
1822             return;
1823         }
1824         ASSERT_USER(false, "acc2~acc7 were set on wrong instruction");
1825     }
1826 
1827     const char *swizzle = srcRegion->getSwizzle();
1828     if (swizzle[0] != '\0' && swizzle[0] != 'r') {
1829         ChanSel ch0 = EncodingHelper::GetSrcChannelSelectValue(srcRegion, 0);
1830         ChanSel ch1 = EncodingHelper::GetSrcChannelSelectValue(srcRegion, 1);
1831         ChanSel ch2 = EncodingHelper::GetSrcChannelSelectValue(srcRegion, 2);
1832         ChanSel ch3 = EncodingHelper::GetSrcChannelSelectValue(srcRegion, 3);
1833         if (ch0 != CHAN_SEL_UNDEF)
1834             SetSrc1ChanSel_0(mybin, ch0);
1835         if (ch1 != CHAN_SEL_UNDEF)
1836             SetSrc1ChanSel_1(mybin, ch1);
1837         if (ch2 != CHAN_SEL_UNDEF)
1838             SetSrc1ChanSel_2(mybin, ch2);
1839         if (ch3 != CHAN_SEL_UNDEF)
1840             SetSrc1ChanSel_3(mybin, ch3);
1841     }
1842 
1843     if (swizzle[0] == '\0')
1844     {
1845         if (inst->isAligned16Inst())
1846         {
1847             SetSrc1ChanSel_0(mybin, CHAN_SEL_X);
1848             SetSrc1ChanSel_1(mybin, CHAN_SEL_Y);
1849             SetSrc1ChanSel_2(mybin, CHAN_SEL_Z);
1850             SetSrc1ChanSel_3(mybin, CHAN_SEL_W);
1851         }
1852     }
1853     else if (inst->getNumSrc() == 3 && !inst->isSend())
1854     {
1855         if (swizzle[0] == 'r')
1856         {
1857             if (inst->isAligned16Inst())
1858             {
1859                 SetSrc1ChanSel_0(mybin, CHAN_SEL_X);
1860                 SetSrc1ChanSel_1(mybin, CHAN_SEL_Y);
1861                 SetSrc1ChanSel_2(mybin, CHAN_SEL_Z);
1862                 SetSrc1ChanSel_3(mybin, CHAN_SEL_W);
1863             }
1864         }
1865     }
1866 }
1867 
EncodeSrc1RepCtrl(BinInst * mybin,G4_SrcRegRegion * srcRegion)1868 inline void EncodeSrc1RepCtrl(BinInst *mybin, G4_SrcRegRegion *srcRegion)
1869 {
1870     const char *swizzle = srcRegion->getSwizzle();
1871     if (swizzle[0] == 'r')
1872         SetSrc1RepCtrl(mybin, 0x1);
1873     else
1874         SetSrc1RepCtrl(mybin, 0x0);
1875 }
1876 
EncodeSrc1Modifier(BinInst * mybin,G4_SrcRegRegion * srcRegion)1877 inline void EncodeSrc1Modifier(BinInst *mybin, G4_SrcRegRegion *srcRegion)
1878 {
1879     SetSrc1SrcMod(mybin, GetSrcMod(srcRegion));
1880 }
1881 
EncodeSrc1Width(G4_INST * inst,BinInst * mybin,const RegionDesc * rd,G4_Operand * src1)1882 inline bool EncodeSrc1Width(
1883     G4_INST *inst, BinInst *mybin, const RegionDesc *rd, G4_Operand *src1)
1884 {
1885     bool WidthValid = false;
1886     if (inst->isAligned16Inst()) return false;
1887 
1888     if (rd)
1889     {
1890         if (rd->width != UNDEFINED_SHORT)
1891         {
1892             WidthValid = true;
1893         }
1894         switch (rd->width)
1895         {
1896             case 1:  SetSrc1Width(mybin, WIDTH_1); break;
1897             case 2:  SetSrc1Width(mybin, WIDTH_2); break;
1898             case 4:  SetSrc1Width(mybin, WIDTH_4); break;
1899             case 8:  SetSrc1Width(mybin, WIDTH_8); break;
1900             case 16: SetSrc1Width(mybin, WIDTH_16); break;
1901             case UNDEFINED_SHORT:break;
1902             default: MUST_BE_TRUE(false, "wrong width for src1!"); break;
1903         }
1904     }
1905 
1906     // apply default width
1907     if (!WidthValid)
1908     {
1909         if (EncodingHelper::isSrcSubRegNumValid(src1))
1910         {
1911             SetSrc1Width(mybin, WIDTH_1);
1912         }
1913         else
1914         {
1915             uint32_t width = GetEncodeExecSize(inst);
1916             if (width <= (uint32_t)ES_32_CHANNELS)
1917             {
1918                  SetSrc1Width(mybin, EXEC_CHANNELS[width]);
1919             }
1920         }
1921     }
1922 
1923     return WidthValid;
1924  }
1925 
EncodeSrc1HorzStride(G4_INST * inst,BinInst * mybin,const RegionDesc * rd,G4_Operand * src1)1926 inline bool EncodeSrc1HorzStride(
1927     G4_INST *inst, BinInst *mybin, const RegionDesc *rd, G4_Operand *src1)
1928 {
1929     // For Align16 instruction (SIMD4), treat <HorzStride> as <VertStride>
1930     // For Align16 source operand disable HorzStride
1931     bool HorzStrideValid = false;
1932     if (inst->isAligned16Inst()) return false;
1933 
1934     if (rd)
1935     {
1936         if (rd->horzStride != UNDEFINED_SHORT)
1937         {
1938             HorzStrideValid = true;
1939         }
1940         switch (rd->horzStride)
1941         {
1942             case 0: SetSrc1HorzStride(mybin, HORZ_STRIDE_0); break;
1943             case 1: SetSrc1HorzStride(mybin, HORZ_STRIDE_1); break;
1944             case 2: SetSrc1HorzStride(mybin, HORZ_STRIDE_2); break;
1945             case 4: SetSrc1HorzStride(mybin, HORZ_STRIDE_4); break;
1946             case UNDEFINED_SHORT: break;
1947             default: MUST_BE_TRUE(false, "wrong horizontal stride for src1!"); break;
1948         }
1949 
1950     }
1951     // apply default horizontal stride
1952     if (!HorzStrideValid)
1953     {
1954         if (EncodingHelper::isSrcSubRegNumValid(src1))
1955             SetSrc1HorzStride(mybin, HORZ_STRIDE_0);
1956         else
1957         {
1958             uint32_t exeSize = GetEncodeExecSize(inst);
1959             MUST_BE_TRUE(exeSize <= (uint32_t)ES_32_CHANNELS,
1960                          "Binary Encoding: Invalid execution size");
1961             {
1962                 SetSrc1HorzStride(mybin, HORIZONTAL_STRIDE[exeSize]);
1963             }
1964         }
1965     }
1966 
1967     return HorzStrideValid;
1968 }
1969 
EncodeSrc1VertStride(G4_INST * inst,BinInst * mybin,const RegionDesc * rd,G4_Operand * src1,bool WidthValid,bool HorzStrideValid)1970 inline void EncodeSrc1VertStride(G4_INST *inst,
1971                                  BinInst *mybin,
1972                                  const RegionDesc *rd,
1973                                  G4_Operand *src1,
1974                                  bool WidthValid,
1975                                  bool HorzStrideValid)
1976 {
1977     bool VertStrideValid = false;
1978     unsigned short VertStrideValue= UNDEFINED_SHORT;
1979     unsigned short HorzStrideValue= UNDEFINED_SHORT;
1980 
1981     if (rd)  {
1982         VertStrideValue = rd->vertStride;
1983         HorzStrideValue = rd->horzStride;
1984         if (VertStrideValue != UNDEFINED_SHORT)
1985         {
1986             VertStrideValid = true;
1987         }
1988         switch (VertStrideValue)
1989         {
1990             case 0:   SetSrc1VertStride(mybin, VERT_STRIDE_0); break;
1991             case 1:   SetSrc1VertStride(mybin, VERT_STRIDE_1); break;
1992             case 2:   SetSrc1VertStride(mybin, VERT_STRIDE_2); break;
1993             case 4:   SetSrc1VertStride(mybin, VERT_STRIDE_4); break;
1994             case 8:   SetSrc1VertStride(mybin, VERT_STRIDE_8); break;
1995             case 16:  SetSrc1VertStride(mybin, VERT_STRIDE_16); break;
1996             case 32:  SetSrc1VertStride(mybin, VERT_STRIDE_32); break;
1997             case UNDEFINED_SHORT: break;
1998             default: MUST_BE_TRUE(false, "wrong verical stride for src1!"); break;
1999         }
2000 
2001     }
2002 
2003         //apply default vertical stride below
2004     if (!WidthValid             &&
2005          !HorzStrideValid        &&
2006          !VertStrideValid        &&
2007          src1)
2008     {
2009         VertStrideValid = true;
2010         if (EncodingHelper::isSrcSubRegNumValid(src1))
2011         {
2012             SetSrc1VertStride(mybin, VERT_STRIDE_0);
2013         }
2014         else
2015         {
2016             if (inst->isAligned1Inst())
2017             {
2018                 uint32_t execSize = GetEncodeExecSize(inst);
2019                 MUST_BE_TRUE(execSize <= (uint32_t)ES_32_CHANNELS,
2020                              "BinaryEncoding: Invalid execution size");
2021                 SetSrc1VertStride(mybin, VERTICAL_STRIDE[execSize]);
2022             }
2023             else
2024             {
2025                 SetSrc1VertStride(mybin, VERT_STRIDE_4);
2026             }
2027         } // fi
2028     } // fi
2029 
2030     if (VertStrideValid) {}
2031     else if (inst->isAligned16Inst())
2032     {
2033         if (HorzStrideValid == 1   &&
2034              HorzStrideValue == 4)
2035         {
2036             SetSrc1HorzStride(mybin, HORZ_STRIDE_1);
2037             SetSrc1VertStride(mybin, VERT_STRIDE_4);
2038         }
2039     }
2040     else if (src1 != NULL && EncodingHelper::GetSrcAddrMode(src1) == ADDR_MODE_INDIR)
2041     { //indirect
2042         SetSrc1VertStride(mybin, VERT_STRIDE_ONE_DIMEN);
2043     }
2044 }
2045 
EncodeSrc1RegNum(G4_INST * inst,BinInst * mybin,G4_Operand * src1)2046 inline void BinaryEncoding::EncodeSrc1RegNum(G4_INST *inst, BinInst *mybin, G4_Operand *src1)
2047 {
2048     if (EncodingHelper::GetSrcRegFile(src1) != REG_FILE_A &&
2049         EncodingHelper::GetSrcAddrMode(src1)==ADDR_MODE_IMMED)
2050     {
2051         bool repControl = EncodingHelper::GetRepControl(src1);
2052         uint32_t byteAddress = src1->getLinearizedStart();
2053         MUST_BE_TRUE(byteAddress < kernel.getNumRegTotal() * numEltPerGRF<Type_UB>(), "src1 exceeds total GRF number");
2054 
2055         if (mybin->GetIs3Src())
2056         {
2057             // src1 subregnum crosses dword boundary, which SetBits can't handle, so we have to break it into two (sigh)
2058             mybin->SetBits(bits3SrcSrc1RegDWord1_H, bits3SrcSrc1RegDWord1_L, byteAddress >> 4);
2059             mybin->SetBits(bits3SrcSrc1RegDWord2_H, bits3SrcSrc1RegDWord2_L, (byteAddress >> 2) & 0x3);
2060             mybin->SetBits(bits3SrcSrc1SubRegNumW_H, bits3SrcSrc1SubRegNumW_L, (byteAddress >> 1) & 0x1);
2061         }
2062         else if (inst->isAligned1Inst() || repControl)
2063         {
2064             SetSrc1RegNumByte(mybin, byteAddress);
2065         }
2066         else
2067         {
2068             SetSrc1RegNumOWord(mybin, byteAddress/BYTES_PER_OWORD);
2069         }
2070     }
2071 }
2072 
EncodeSrc1ArchRegNum(G4_INST * inst,BinInst * mybin,G4_SrcRegRegion * src1)2073 inline void EncodeSrc1ArchRegNum(G4_INST *inst, BinInst *mybin, G4_SrcRegRegion *src1)
2074 {
2075     unsigned short RegNumValue = 0, RegSubNumValue = 0;
2076     bool valid, subValid;
2077     uint32_t regOffset;
2078 
2079     if (EncodingHelper::GetSrcRegFile(src1)==REG_FILE_A &&
2080         EncodingHelper::GetSrcAddrMode(src1) == ADDR_MODE_IMMED)
2081     {
2082         if (EncodingHelper::GetSrcArchRegType(src1) != ARCH_REG_FILE_NULL)
2083         {
2084             RegNumValue = src1->ExRegNum(valid);
2085             RegSubNumValue = src1->ExSubRegNum(subValid);
2086 
2087             SetSrc1ArchRegNum(mybin, RegNumValue);
2088 
2089             unsigned short ElementSizeValue = EncodingHelper::GetElementSizeValue(src1);
2090             regOffset = RegSubNumValue * ElementSizeValue;
2091             if (inst->isAligned1Inst())
2092             {
2093                 SetSrc1ArchSubRegNumByte(mybin, regOffset);
2094             } else {
2095                 SetSrc1ArchSubRegNumOWord(mybin, regOffset/BYTES_PER_OWORD);
2096             }
2097         }
2098     }
2099 }
2100 
EncodeSrc1IndirectRegNum(G4_INST * inst,BinInst * mybin,G4_SrcRegRegion * src1)2101 inline void EncodeSrc1IndirectRegNum(G4_INST* inst, BinInst *mybin, G4_SrcRegRegion *src1)
2102 {
2103     bool subValid;
2104     unsigned short IndAddrRegSubNumValue = 0;
2105     short IndAddrImmedValue = 0;
2106 
2107     if (EncodingHelper::GetSrcAddrMode(src1)==ADDR_MODE_INDIR)
2108     {
2109         if (! (EncodingHelper::GetSrcRegFile(src1)==REG_FILE_A &&
2110               EncodingHelper::GetSrcArchRegType(src1)==ARCH_REG_FILE_NULL))
2111         {
2112             IndAddrRegSubNumValue = src1->ExIndSubRegNum(subValid);
2113             IndAddrImmedValue = src1->ExIndImmVal();
2114 
2115             SetSrc1IdxRegNum(mybin, IndAddrRegSubNumValue);
2116             /* Set the indirect address immediate value. */
2117             if (inst->isAligned1Inst())  {
2118                 SetSrc1IdxImmByte(mybin, IndAddrImmedValue);
2119             }  else  {
2120                 SetSrc1IdxImmOWord(mybin, IndAddrImmedValue / BYTES_PER_OWORD);
2121             }
2122         }
2123     }
2124 }
2125 
EncodeSplitSendDst(G4_INST * inst)2126 BinaryEncoding::Status BinaryEncoding::EncodeSplitSendDst(G4_INST* inst)
2127 {
2128     BinInst *mybin = inst->getBinInst();
2129     if (inst->getDst() == NULL)
2130     {
2131         return FAILURE;
2132     }
2133     G4_DstRegRegion* dst = inst->getDst();
2134 
2135     EncodeDstRegFile(mybin, dst);
2136     SetOperandDstType(mybin, dst);
2137     if (EncodingHelper::GetDstAddrMode(dst)==ADDR_MODE_INDIR)
2138     {
2139         bool subValid;
2140         uint16_t IndAddrRegSubNumValue = dst->ExIndSubRegNum(subValid);
2141         int16_t IndAddrImmedValue = dst->ExIndImmVal();
2142 
2143         mybin->SetBits(bitsSendsDstAddrMode_0, bitsSendsDstAddrMode_1, ADDR_MODE_INDIR);
2144         mybin->SetBits(bitsSendsDstAddrSubRegNum_0, bitsSendsDstAddrSubRegNum_1, IndAddrRegSubNumValue);
2145         mybin->SetBits(bitsSendsDstAddrImm8_4_0, bitsSendsDstAddrImm8_4_1, (IndAddrImmedValue >> 4) & 0x1F);
2146         mybin->SetBits(bitsSendsDstAddrImmSign_0, bitsSendsDstAddrImmSign_1, (IndAddrImmedValue >> 9) & 0x1);
2147     }
2148     else
2149     {
2150         mybin->SetBits(bitsSendsDstAddrMode_0, bitsSendsDstAddrMode_1, ADDR_MODE_IMMED);
2151         if (EncodingHelper::GetDstRegFile(dst) == REG_FILE_A)
2152         {
2153             // must be NULL, do nothing
2154         }
2155         else
2156         {
2157             // must be GRF
2158             uint32_t byteAddress = dst->getLinearizedStart();
2159             MUST_BE_TRUE(byteAddress % 16 == 0, "dst for sends/sendsc must be oword-aligned");
2160             mybin->SetBits(bitsSendsDstRegNum_0, bitsSendsDstRegNum_1, byteAddress >> 5);
2161             mybin->SetBits(bitsSendsDstSubRegNum_0, bitsSendsDstSubRegNum_1, (byteAddress >> 4) & 0x1);
2162         }
2163     }
2164 
2165     return SUCCESS;
2166 }
2167 
2168 // src2 is the message descriptor (either a0.0 or imm)
EncodeSplitSendSrc2(G4_INST * inst)2169 BinaryEncoding::Status BinaryEncoding::EncodeSplitSendSrc2(G4_INST* inst)
2170 {
2171     BinInst *mybin = inst->getBinInst();
2172     if (inst->getSrc(2) == NULL)
2173     {
2174         return FAILURE;
2175     }
2176     G4_Operand* src2 = inst->getSrc(2);
2177 
2178     if (src2->isImm())
2179     {
2180         mybin->SetBits(bitsSendsSelReg32Desc_0, bitsSendsSelReg32Desc_0, 0);
2181         mybin->SetBits(bitsSrcImm32_2,bitsSrcImm32_3, (uint32_t) src2->asImm()->getInt());
2182     }
2183     else if (src2->isSrcRegRegion() && src2->asSrcRegRegion()->isA0())
2184     {
2185         mybin->SetBits(bitsSendsSelReg32Desc_0, bitsSendsSelReg32Desc_0, 1);
2186     }
2187 
2188     return SUCCESS;
2189 }
2190 
EncodeSplitSendSrc1(G4_INST * inst)2191 BinaryEncoding::Status BinaryEncoding::EncodeSplitSendSrc1(G4_INST* inst)
2192 {
2193     BinInst *mybin = inst->getBinInst();
2194     if (inst->getSrc(1) == NULL || !inst->getSrc(1)->isSrcRegRegion())
2195     {
2196         return FAILURE;
2197     }
2198     G4_SrcRegRegion* src1 = inst->getSrc(1)->asSrcRegRegion();
2199 
2200     if (src1->isNullReg())
2201     {
2202         mybin->SetBits(bitsSendsSrc1RegFile_0, bitsSendsSrc1RegFile_1, REG_FILE_A);
2203     }
2204     else
2205     {
2206         mybin->SetBits(bitsSendsSrc1RegFile_0, bitsSendsSrc1RegFile_1, REG_FILE_R);
2207         if (EncodingHelper::GetSrcAddrMode(src1) == ADDR_MODE_INDIR)
2208         {
2209             bool subValid;
2210             uint16_t IndAddrRegSubNumValue = src1->ExIndSubRegNum(subValid);
2211             int16_t IndAddrImmedValue = src1->ExIndImmVal();
2212 
2213             mybin->SetBits(bitsSendsSrc1AddrMode_0, bitsSendsSrc1AddrMode_1, ADDR_MODE_INDIR);
2214             mybin->SetBits(bitsSendsSrc1AddrSubRegNum_0, bitsSendsSrc1AddrSubRegNum_1, IndAddrRegSubNumValue);
2215             mybin->SetBits(bitsSendsSrc1AddrImm8_4_0, bitsSendsSrc1AddrImm8_4_1, (IndAddrImmedValue >> 4) & 0x1F);
2216             mybin->SetBits(bitsSendsSrc1AddrImmSign_0, bitsSendsSrc1AddrImmSign_1, (IndAddrImmedValue >> 9) & 0x1);
2217         }
2218         else
2219         {
2220             uint32_t byteAddress = src1->getLinearizedStart();
2221             MUST_BE_TRUE(byteAddress % 32 == 0, "src1 for sends/sendsc must be GRF-aligned");
2222             mybin->SetBits(bitsSendsSrc1RegNum_0, bitsSendsSrc1RegNum_1, byteAddress >> 5);
2223         }
2224     }
2225 
2226     return SUCCESS;
2227 }
2228 
EncodeSplitSendSrc0(G4_INST * inst)2229 BinaryEncoding::Status BinaryEncoding::EncodeSplitSendSrc0(G4_INST* inst)
2230 {
2231     BinInst *mybin = inst->getBinInst();
2232     if (inst->getSrc(0) == NULL || !inst->getSrc(0)->isSrcRegRegion())
2233     {
2234         return FAILURE;
2235     }
2236     G4_SrcRegRegion* src0 = inst->getSrc(0)->asSrcRegRegion();
2237 
2238     if (EncodingHelper::GetSrcAddrMode(src0)==ADDR_MODE_INDIR)
2239     {
2240         bool subValid;
2241         uint16_t IndAddrRegSubNumValue = src0->ExIndSubRegNum(subValid);
2242         int16_t IndAddrImmedValue = src0->ExIndImmVal();
2243 
2244         mybin->SetBits(bitsSendsSrc0AddrMode_0, bitsSendsSrc0AddrMode_1, ADDR_MODE_INDIR);
2245         mybin->SetBits(bitsSendsSrc0AddrSubRegNum_0, bitsSendsSrc0AddrSubRegNum_1, IndAddrRegSubNumValue);
2246         mybin->SetBits(bitsSendsSrc0AddrImm8_4_0, bitsSendsSrc0AddrImm8_4_1, (IndAddrImmedValue >> 4) & 0x1F);
2247         mybin->SetBits(bitsSendsSrc0AddrImmSign_0, bitsSendsSrc0AddrImmSign_1, (IndAddrImmedValue >> 9) & 0x1);
2248     }
2249     else
2250     {
2251         mybin->SetBits(bitsSendsSrc0AddrMode_0, bitsSendsSrc0AddrMode_1, ADDR_MODE_IMMED);
2252         uint32_t byteAddress = src0->getLinearizedStart();
2253         MUST_BE_TRUE(byteAddress % 32 == 0, "src1 for sends/sendsc must be GRF-aligned");
2254         mybin->SetBits(bitsSendsSrc0RegNum_0, bitsSendsSrc0RegNum_1, byteAddress >> 5);
2255     }
2256 
2257     return SUCCESS;
2258 }
2259 
2260 // Gen encodes target for call as src1, though internally we store it in src0
EncodeIndirectCallTarget(G4_INST * inst)2261 BinaryEncoding::Status BinaryEncoding::EncodeIndirectCallTarget(G4_INST* inst)
2262 {
2263     BinInst *mybin = inst->getBinInst();
2264     G4_Operand* funcAddr = inst->getSrc(0);
2265     EncodeSrc1RegFile(mybin, funcAddr);
2266     EncodeSrc1Type(mybin, funcAddr);
2267     if (funcAddr->isImm())
2268     {
2269         EncodeSrcImmData(mybin, funcAddr);
2270     }
2271     else
2272     {
2273         G4_SrcRegRegion *srcRegion = funcAddr->asSrcRegRegion();
2274         EncodeSrc1RegNum(inst, mybin, srcRegion);
2275         EncodeSrc1ArchRegNum(inst, mybin, srcRegion);
2276         EncodeSrc1IndirectRegNum(inst, mybin, srcRegion);
2277         EncodeSrc1AddrMode(mybin, srcRegion);
2278         EncodeSrc1RepCtrl(mybin, srcRegion);
2279         EncodeSrc1Modifier(mybin, srcRegion);
2280         EncodeSrc1ChanSelect(inst, mybin, srcRegion);
2281         const RegionDesc *rd = srcRegion->getRegion();
2282         bool WidthValid = EncodeSrc1Width(inst, mybin, rd, srcRegion);
2283         bool HorzStrideValid = EncodeSrc1HorzStride(inst, mybin, rd, srcRegion);
2284         EncodeSrc1VertStride(inst, mybin, rd, srcRegion, WidthValid, HorzStrideValid);
2285     }
2286 
2287     return SUCCESS;
2288 }
2289 
2290 
EncodeOperandSrc1(G4_INST * inst)2291 BinaryEncoding::Status BinaryEncoding::EncodeOperandSrc1(G4_INST* inst)
2292 {
2293     BinInst *mybin = inst->getBinInst();
2294     G4_Operand *src1 = NULL;
2295 
2296     if (inst->isSplitSend())
2297     {
2298         return EncodeSplitSendSrc1(inst);
2299     }
2300 
2301     G4_Operand *src0 = inst->getSrc(0);
2302     bool isSrc0Region = false;
2303     if (src0)
2304         isSrc0Region = src0->isSrcRegRegion();
2305 
2306     if (inst->opcode() == G4_jmpi &&
2307          isSrc0Region)
2308     {
2309         src1 = src0;
2310     }
2311     else
2312     {
2313         src1 = inst->getSrc(1);
2314     }
2315 
2316     if (inst->isLabel())  {
2317         if (isSrc0Region)
2318         {
2319             //Gen4_IR has src1 operand on src0's place
2320             src1 = src0;
2321         }
2322         else
2323             return SUCCESS;
2324     }
2325 
2326     if (src1==NULL ||src1->isLabel()) return FAILURE;
2327 
2328     EncodeSrc1RegFile(mybin, src1);
2329     EncodeSrc1Type(mybin, src1);
2330     if (src1->isImm())
2331     {
2332         MUST_BE_TRUE(src1->getTypeSize() != 8, "64-bit immediate must be src0");
2333         EncodeSrcImmData(mybin, src1);
2334     }
2335     else
2336     {
2337         G4_SrcRegRegion *srcRegion = src1->asSrcRegRegion();
2338         EncodeSrc1RegNum(inst, mybin, src1);
2339         EncodeSrc1ArchRegNum(inst, mybin, srcRegion);
2340         EncodeSrc1IndirectRegNum(inst, mybin, srcRegion);
2341         EncodeSrc1AddrMode(mybin, src1);
2342         EncodeSrc1RepCtrl(mybin, srcRegion);
2343         EncodeSrc1Modifier(mybin, srcRegion);
2344         EncodeSrc1ChanSelect(inst, mybin, srcRegion);
2345         const RegionDesc *rd = srcRegion->getRegion();
2346         bool WidthValid = EncodeSrc1Width(inst, mybin, rd, src1);
2347         bool HorzStrideValid = EncodeSrc1HorzStride(inst, mybin, rd, src1);
2348         EncodeSrc1VertStride(inst, mybin, rd, src1, WidthValid, HorzStrideValid);
2349     }
2350 
2351     return SUCCESS;
2352 }
2353 
2354 ///////////////////////////////////////////////////////////////////////////////
2355 //                       Src2
2356 ///////////////////////////////////////////////////////////////////////////////
2357 
SetSrc2SrcMod(BinInst * mybin,uint32_t value)2358 inline void SetSrc2SrcMod(BinInst *mybin, uint32_t value)
2359 {
2360     if (mybin->GetIs3Src())
2361         mybin->SetBits(bits3SrcSrcMod[4], bits3SrcSrcMod[5], value);
2362     else
2363         return;
2364 }
2365 
SetSrc2RepCtrl(BinInst * mybin,uint32_t value)2366 inline void SetSrc2RepCtrl(BinInst *mybin, uint32_t value)
2367 {
2368     if (mybin->GetIs3Src())
2369         mybin->SetBits(bits3SrcRepCtrl_4, bits3SrcRepCtrl_5, value);
2370     else
2371         return;
2372 
2373 }
2374 
SetSrc2Swizzle(BinInst * mybin,uint32_t value)2375 inline void SetSrc2Swizzle(BinInst *mybin, uint32_t value)
2376 {
2377     if (mybin->GetIs3Src())
2378         mybin->SetBits(bits3SrcSwizzle_4, bits3SrcSwizzle_5, value);
2379     else
2380         return;
2381 }
2382 
SetSrc2ChanSel_0(BinInst * mybin,uint32_t value)2383 inline void SetSrc2ChanSel_0(BinInst *mybin, uint32_t value)
2384 {
2385     if (mybin->GetIs3Src())
2386         mybin->SetBits(bits3SrcChanSel_0_4, bits3SrcChanSel_0_5, value);
2387     else
2388         return;
2389 }
2390 
SetSrc2ChanSel_1(BinInst * mybin,uint32_t value)2391 inline void SetSrc2ChanSel_1(BinInst *mybin, uint32_t value)
2392 {
2393     if (mybin->GetIs3Src())
2394         mybin->SetBits(bits3SrcChanSel_1_4, bits3SrcChanSel_1_5, value);
2395     else
2396         return;
2397 }
2398 
SetSrc2ChanSel_2(BinInst * mybin,uint32_t value)2399 inline void SetSrc2ChanSel_2(BinInst *mybin, uint32_t value)
2400 {
2401     if (mybin->GetIs3Src())
2402         mybin->SetBits(bits3SrcChanSel_2_4, bits3SrcChanSel_2_5, value);
2403     else
2404         return;
2405 }
2406 
SetSrc2ChanSel_3(BinInst * mybin,uint32_t value)2407 inline void SetSrc2ChanSel_3(BinInst *mybin, uint32_t value)
2408 {
2409     if (mybin->GetIs3Src())
2410         mybin->SetBits(bits3SrcChanSel_3_4, bits3SrcChanSel_3_5, value);
2411     else
2412         return;
2413 }
2414 
SetSrc2RegNumHWord(BinInst * mybin,uint32_t value)2415 inline void SetSrc2RegNumHWord(BinInst *mybin, uint32_t value)
2416 {
2417     if (mybin->GetIs3Src())
2418         mybin->SetBits(bits3SrcSrcRegNumHWord_4, bits3SrcSrcRegNumHWord_5, value);
2419     else
2420         return;
2421 }
2422 
SetSrc2RegNumOWord(BinInst * mybin,uint32_t value)2423 inline void SetSrc2RegNumOWord(BinInst *mybin, uint32_t value)
2424 {
2425     if (mybin->GetIs3Src())
2426         mybin->SetBits(bits3SrcSrcRegNumOWord_4, bits3SrcSrcRegNumOWord_5, value);
2427     else
2428         return;
2429 }
2430 
SetSrc2RegNumDWord(BinInst * mybin,uint32_t value)2431 inline void SetSrc2RegNumDWord(BinInst *mybin, uint32_t value)
2432 {
2433     if (mybin->GetIs3Src())
2434         mybin->SetBits(bits3SrcSrcRegNumDWord_4, bits3SrcSrcRegNumDWord_5, value);
2435     else
2436         return;
2437 }
2438 
EncodeSrc2ChanSelect(G4_INST * inst,BinInst * mybin,G4_SrcRegRegion * srcRegion,G4_Operand * src2)2439 inline void EncodeSrc2ChanSelect(G4_INST *inst,
2440                                   BinInst *mybin,
2441                                   G4_SrcRegRegion *srcRegion,
2442                                   G4_Operand *src2)
2443 {
2444     if (src2->isAccRegValid())
2445     {
2446         if (inst->opcode() == G4_madm)
2447         {
2448             uint32_t value = src2->getAccRegSel();
2449             SetSrc2ChanSel_0(mybin, value & 0x3);
2450             SetSrc2ChanSel_1(mybin, value >> 2 & 0x3);
2451             SetSrc2ChanSel_2(mybin, 0);
2452             SetSrc2ChanSel_3(mybin, 0);
2453             return;
2454         }
2455         ASSERT_USER(false, "acc2~acc7 were set on wrong instruction");
2456     }
2457 
2458     const char *swizzle = srcRegion->getSwizzle();
2459     {
2460         if (swizzle[0] != '\0' && swizzle[0] != 'r')
2461         {
2462             ChanSel ch0 = EncodingHelper::GetSrcChannelSelectValue(srcRegion, 0);
2463             ChanSel ch1 = EncodingHelper::GetSrcChannelSelectValue(srcRegion, 1);
2464             ChanSel ch2 = EncodingHelper::GetSrcChannelSelectValue(srcRegion, 2);
2465             ChanSel ch3 = EncodingHelper::GetSrcChannelSelectValue(srcRegion, 3);
2466             if (ch0 != CHAN_SEL_UNDEF)
2467                 SetSrc2ChanSel_0(mybin, ch0);
2468             if (ch1 != CHAN_SEL_UNDEF)
2469                 SetSrc2ChanSel_1(mybin, ch1);
2470             if (ch2 != CHAN_SEL_UNDEF)
2471                 SetSrc2ChanSel_2(mybin, ch2);
2472             if (ch3 != CHAN_SEL_UNDEF)
2473                 SetSrc2ChanSel_3(mybin, ch3);
2474         }
2475     }
2476 
2477     //Following ISAASM example which encodes it to xyzw and is able to compact as a result.
2478     if (swizzle[0] == '\0' || swizzle[0] == 'r')
2479     {
2480         if (inst->isAligned16Inst())
2481         {
2482             SetSrc2ChanSel_0(mybin, CHAN_SEL_X);
2483             SetSrc2ChanSel_1(mybin, CHAN_SEL_Y);
2484             SetSrc2ChanSel_2(mybin, CHAN_SEL_Z);
2485             SetSrc2ChanSel_3(mybin, CHAN_SEL_W);
2486         }
2487     }
2488 }
2489 
EncodeSrc2RepCtrl(BinInst * mybin,G4_SrcRegRegion * srcRegion)2490 inline void EncodeSrc2RepCtrl(BinInst *mybin, G4_SrcRegRegion *srcRegion)
2491 {
2492     const char *swizzle = srcRegion->getSwizzle();
2493     if (swizzle[0] == 'r')
2494         SetSrc2RepCtrl(mybin, 0x1);
2495     else
2496         SetSrc2RepCtrl(mybin, 0x0);
2497 }
2498 
EncodeSrc2Modifier(BinInst * mybin,G4_SrcRegRegion * srcRegion,G4_Operand * src2)2499 inline void EncodeSrc2Modifier(BinInst *mybin, G4_SrcRegRegion *srcRegion, G4_Operand *src2)
2500 {
2501     if (EncodingHelper::GetSrcRegFile(src2) != REG_FILE_M)
2502     {
2503         SetSrc2SrcMod(mybin, GetSrcMod(srcRegion));
2504     }
2505 }
2506 
EncodeSrc2RegNum(G4_INST * inst,BinInst * mybin,G4_Operand * src2)2507 inline void BinaryEncoding::EncodeSrc2RegNum(G4_INST* inst, BinInst *mybin, G4_Operand *src2)
2508 {
2509     if (EncodingHelper::GetSrcRegFile(src2) != REG_FILE_A &&
2510         EncodingHelper::GetSrcAddrMode(src2) == ADDR_MODE_IMMED)
2511     {
2512         uint32_t byteAddress = src2->getLinearizedStart();
2513         MUST_BE_TRUE(byteAddress < kernel.getNumRegTotal() * numEltPerGRF<Type_UB>(), "src2 exceeds total GRF number");
2514 
2515         // encode dwords
2516         mybin->SetBits(bits3SrcSrc2RegDWord_H, bits3SrcSrc2RegDWord_L, byteAddress >> 2);
2517         // encode word (for word type)
2518         mybin->SetBits(bits3SrcSrc2SubRegNumW_H, bits3SrcSrc2SubRegNumW_L, (byteAddress >> 1) & 0x1);
2519     }
2520 }
2521 
EncodeOperandSrc2(G4_INST * inst)2522 inline BinaryEncoding::Status BinaryEncoding::EncodeOperandSrc2(G4_INST* inst)
2523 {
2524     BinInst *mybin = inst->getBinInst();
2525     G4_Operand *src2 = inst->getSrc(2);
2526 
2527     if (src2==NULL || src2->isLabel())
2528     {
2529         return SUCCESS;
2530     }
2531 
2532     if (inst->isSplitSend())
2533     {
2534         return EncodeSplitSendSrc2(inst);
2535     }
2536 
2537     if (!src2->isImm())
2538     {
2539         G4_SrcRegRegion *srcRegion = src2->asSrcRegRegion();
2540         EncodeSrc2ChanSelect(inst, mybin, srcRegion, src2);
2541         EncodeSrc2RepCtrl(mybin, srcRegion);
2542         EncodeSrc2Modifier(mybin, srcRegion, src2);
2543         EncodeSrc2RegNum(inst, mybin, src2);
2544     }
2545 
2546     return SUCCESS;
2547 }
2548 
SetExtMsgDescr(G4_INST * inst,BinInst * mybin,uint32_t value)2549 void SetExtMsgDescr(G4_INST *inst, BinInst *mybin, uint32_t value)
2550 {
2551 
2552     EncExtMsgDescriptor emd;
2553     emd.ulData = value;
2554 
2555 
2556     if (inst->isSplitSend())
2557     {
2558         G4_Operand *src3 = inst->getSrc(3);
2559         // additional extended msg desc to be encoded
2560         if (src3 && src3->isSrcRegRegion() && src3->asSrcRegRegion()->isA0())
2561         {
2562             mybin->SetBits(bitsSendsSelReg32ExDesc_0, bitsSendsSelReg32ExDesc_1, 1);
2563             mybin->SetBits(bitsSendsExDescRegNum_0, bitsSendsExDescRegNum_1,
2564                 src3->asSrcRegRegion()->getBase()->asRegVar()->getPhyRegOff());
2565             return;
2566         }
2567     }
2568 
2569     // immediate extended message descriptor
2570     mybin->SetBits(bitsSharedFunctionID_0, bitsSharedFunctionID_1, emd.ExtMsgDescriptor.TargetUnitId);
2571     mybin->SetBits(bitsEndOfThread_0, bitsEndOfThread_1, emd.ExtMsgDescriptor.EndOfThread);
2572     mybin->SetBits(bitsExDescCPSLOD_0, bitsExDescCPSLOD_1, emd.ExtMsgDescriptor.CPSLODCompensation);
2573 
2574 
2575     if (inst->isSplitSend())
2576     {
2577         mybin->SetBits(bitsExMsgLength_0, bitsExMsgLength_1, emd.ExtMsgDescriptor.ExtMessageLength);
2578         mybin->SetBits(bitsSendsExDescFuncCtrl_0, bitsSendsExDescFuncCtrl_1, emd.ExtMsgDescriptor.ExtFunctionControl);
2579     }
2580     else if (inst->getPlatform() >= GENX_SKL)
2581     {
2582         // needs to encode extended message desc function control as well for SKL+
2583         uint32_t val = emd.ExtMsgDescriptor.ExtFunctionControl & 0xF;
2584         mybin->SetBits(bitsSendExDesc19, bitsSendExDesc16, val);
2585         val = (emd.ExtMsgDescriptor.ExtFunctionControl >> 4) & 0xF;
2586         mybin->SetBits(bitsSendExDesc23, bitsSendExDesc20, val);
2587         val = (emd.ExtMsgDescriptor.ExtFunctionControl >> 8) & 0xF;
2588         mybin->SetBits(bitsSendExDesc27, bitsSendExDesc24, val);
2589         val = (emd.ExtMsgDescriptor.ExtFunctionControl >> 12) & 0xF;
2590         mybin->SetBits(bitsSendExDesc31, bitsSendExDesc28, val);
2591     }
2592 }
2593 
2594 inline
EncodeExtMsgDescr(G4_INST * inst)2595 BinaryEncoding::Status BinaryEncoding::EncodeExtMsgDescr(G4_INST* inst)
2596 {
2597     BinInst *mybin = inst->getBinInst();
2598     MUST_BE_TRUE(inst->getMsgDescRaw(), "expected raw descriptor");
2599     uint32_t msgDesc = inst->getMsgDescRaw()->getExtendedDesc();
2600     SetExtMsgDescr(inst, mybin, msgDesc);
2601     return SUCCESS;
2602 }
2603 
EncodeOperands(G4_INST * inst)2604 BinaryEncoding::Status BinaryEncoding::EncodeOperands(G4_INST* inst)
2605 {
2606     Status myStatus = SUCCESS;
2607 
2608     //Don't need to encode src1 if math only has one src.
2609     int i = ((inst->isMath() && inst->asMathInst()->isOneSrcMath())?1:inst->getNumSrc());
2610     switch (i)
2611     {
2612         case 4: // split send's ext msg descriptor encoding is skipped here
2613         case 3:
2614             EncodeOperandSrc2(inst);
2615         case 2:
2616             EncodeOperandSrc1(inst);
2617         case 1:
2618             EncodeOperandSrc0(inst);
2619         default:
2620             break;
2621     }
2622 
2623     if (inst->opcode() == G4_jmpi      &&
2624          inst->getSrc(0)                &&
2625          inst->getSrc(0)->isSrcRegRegion())
2626     {
2627         EncodeOperandSrc1(inst);
2628     }
2629 
2630     if (inst->isSend())
2631         EncodeExtMsgDescr(inst); // all the ext msg descriptor is handled here
2632 
2633     return myStatus;
2634 }
2635 
insertWaitDst(G4_INST * inst)2636 void BinaryEncoding::insertWaitDst(G4_INST *inst)
2637 {
2638     BinInst *mybin = inst->getBinInst();
2639     if (inst->opcode()==G4_wait)
2640     {  // The wait instruction needs src0 inserted as dst operand
2641         G4_Operand *src0 = inst->getSrc(0);
2642 
2643         RegFile regFile = EncodingHelper::GetSrcRegFile(src0);
2644         SetDstRegFile(mybin, regFile);
2645         if (regFile == REG_FILE_A)
2646             SetDstArchRegFile(mybin, EncodingHelper::GetSrcArchRegType(src0));
2647 
2648         SetDstHorzStride(mybin, HORZ_STRIDE_1);
2649         SetDstAddrMode(mybin, EncodingHelper::GetSrcAddrMode(src0));
2650 
2651         // set dst's RegNum and RegSubNum according to its src0's.
2652         if (EncodingHelper::GetSrcRegFile(src0)!=REG_FILE_A &&
2653             EncodingHelper::GetSrcAddrMode(src0) == ADDR_MODE_IMMED)
2654         {
2655             bool repControl = EncodingHelper::GetRepControl(src0);
2656             uint32_t byteAddress = src0->getLinearizedStart();
2657 
2658             if (inst->isAligned1Inst() || repControl)
2659             {
2660                 SetDstRegNumByte(mybin, byteAddress);
2661             } else {
2662                 SetDstRegNumOWord(mybin, byteAddress/BYTES_PER_OWORD);
2663             }
2664         }
2665     }
2666 }
2667 
SetCompactCtrl(BinInst * mybin,uint32_t value)2668 void BinaryEncoding::SetCompactCtrl (BinInst *mybin, uint32_t value)
2669 {
2670     mybin->SetBits(bitsCompactCtrl_0, bitsCompactCtrl_1, value);
2671 }
2672 
GetCompactCtrl(BinInst * mybin)2673 uint32_t BinaryEncoding::GetCompactCtrl(BinInst *mybin)
2674 {
2675     return mybin->GetBits(bitsCompactCtrl_0, bitsCompactCtrl_1);
2676 }
2677 
GetComprCtrl(BinInst * mybin)2678 inline uint32_t GetComprCtrl(BinInst *mybin)
2679 {
2680     return mybin->GetBits(bitsComprCtrl_0,  bitsComprCtrl_1);
2681 }
2682 
isIndirectJmp(G4_INST * inst)2683 bool isIndirectJmp(G4_INST *inst)
2684 {
2685     return (inst                                &&
2686             inst->opcode() == G4_jmpi           &&
2687             inst->getSrc(0)->isSrcRegRegion()   &&
2688             ((G4_SrcRegRegion *)(inst->getSrc(0)))->getBase()->isRegVar());
2689 }
2690 
isIndirectJmpTarget(G4_INST * inst)2691 bool isIndirectJmpTarget(G4_INST *inst)
2692 {
2693     return (inst                                &&
2694             inst->opcode() == G4_jmpi           &&
2695             inst->getSrc(0)->isLabel());
2696 }
2697 
DoAllEncoding(G4_INST * inst)2698 BinaryEncoding::Status BinaryEncoding::DoAllEncoding(G4_INST* inst)
2699 {
2700     Status myStatus = SUCCESS;
2701     bool isFCCall = false, isFCRet = false;
2702 
2703     if (inst->opcode() == G4_label) return myStatus;
2704 
2705     if (inst->opcode() == G4_illegal)
2706          return FAILURE;
2707 
2708     EncodingHelper::mark3Src(inst);
2709 
2710     insertWaitDst(inst);
2711 
2712     if (inst->opcode() == G4_pseudo_fc_call)
2713     {
2714         inst->asCFInst()->pseudoCallToCall();
2715         isFCCall = true;
2716     }
2717 
2718     if (inst->opcode() == G4_pseudo_fc_ret)
2719     {
2720         inst->asCFInst()->pseudoRetToRet();
2721         isFCRet = true;
2722     }
2723 
2724     EncodeOpCode(inst);
2725 
2726     if (inst->opcode() == G4_nop)
2727     {
2728         return myStatus;
2729     }
2730 
2731     EncodeExecSize(inst);
2732     EncodeFlagReg(inst);
2733     EncodeFlagRegPredicate(inst);
2734     EncodeCondModifier(inst);
2735     EncodeInstModifier(inst);
2736     EncodeInstOptionsString(inst);
2737 
2738     if (inst->isSend())
2739     {
2740         EncodeSendMsgDesc29_30(inst);
2741     }
2742 
2743     if (inst->opcode() == G4_math)
2744     {
2745         EncodeMathControl(inst);
2746     }
2747 
2748     if (isFCCall == true) {
2749         BinInst *mybin = inst->getBinInst();
2750         SetSrc1RegFile(mybin, REG_FILE_I);
2751         SetSrc1Type(mybin, SRC_IMM_TYPE_D);
2752         inst->setOpcode(G4_pseudo_fc_call);
2753     }
2754 
2755     if (isFCRet == true) {
2756         inst->setOpcode(G4_pseudo_fc_ret);
2757     }
2758 
2759     return myStatus;
2760 }
2761 
2762 //inline void dumpOptReport(int totalInst,
2763 //                          int numCompactedInst,
2764 //                          int numCompacted3SrcInst,
2765 //                          G4_Kernel& kernel)
2766 //{
2767 //    if (kernel.getOption(vISA_OptReport))
2768 //    {
2769 //        std::ofstream optReport;
2770 //        getOptReportStream(optReport, kernel.fg.builder->getOptions());
2771 //        optReport << "             === Binary Compaction ===" <<endl;
2772 //        optReport<< fixed << endl;
2773 //        optReport<< kernel.getName() <<": "
2774 //            << numCompactedInst <<" out of " <<totalInst <<" instructions are compacted."<<endl;
2775 //        if (numCompacted3SrcInst>0)
2776 //        {
2777 //            optReport<< kernel.getName() <<": "
2778 //            << numCompacted3SrcInst <<" instructions of 3 src (mad/pln) are compacted."<<endl;
2779 //        }
2780 //        optReport<< setprecision(0)
2781 //            << (float)(numCompactedInst*100)/(float)(totalInst)
2782 //            << "% instructions of this kernel are compacted."
2783 //            <<endl;
2784 //        optReport<<endl;
2785 //        closeOptReportStream(optReport);
2786 //    }
2787 //}
2788 
ProduceBinaryInstructions()2789 inline BinaryEncoding::Status BinaryEncoding::ProduceBinaryInstructions()
2790 {
2791     Status myStatus = FAILURE;
2792     BB_LIST_ITER ib, bend(kernel.fg.end());
2793 
2794     int globalInstNum = 0;
2795     int globalHalfInstNum = 0;
2796     int numCompactedInst = 0;
2797     int numCompacted3SrcInst = 0;
2798     //define offsetVector to record forward jumps/calls
2799     std::vector<ForwardJmpOffset> offsetVector;
2800 
2801     if (doCompaction())
2802     {
2803         for (uint8_t i=0; i<(int)COMPACT_TABLE_SIZE; i++)
2804         {
2805             BDWCompactControlTable.AddIndex(IVBCompactControlTable[i], i);
2806             BDWCompactSourceTable.AddIndex(IVBCompactSourceTable[i], i);
2807             BDWCompactSubRegTable.AddIndex(IVBCompactSubRegTable[i], i);
2808             BDWCompactSubRegTable.AddIndex1(IVBCompactSubRegTable[i] & 0x1F, i);
2809             BDWCompactSubRegTable.AddIndex2(IVBCompactSubRegTable[i] & 0x3FF, i);
2810             BDWCompactDataTypeTableStr.AddIndex(BDWCompactDataTypeTable[i], i);
2811         }
2812     }
2813 
2814      /**
2815      * Traverse the flow graph basic block
2816      */
2817     for (ib = kernel.fg.begin(); ib != bend; ++ib)
2818     {
2819         G4_BB *bb = *ib;
2820         int localInstNum = 0;
2821         int localHalfInstNum = 0;
2822 
2823         /**
2824          * Traverse the instruction lists
2825          */
2826         INST_LIST_ITER ii, iend(bb->end());
2827         //indirectJump = false;
2828         for (ii = bb->begin(); ii != iend; ++ii)
2829         {
2830             /* do detailed encoding here */
2831             G4_INST *inst = *ii;
2832 
2833             if (inst->opcode() == G4_label)
2834             {
2835                 inst->setBinInst(NULL);
2836             }
2837             else
2838             {
2839                 BinInst *bin = new (mem) BinInst();
2840                 inst->setBinInst(bin);
2841 
2842                 myStatus = DoAllEncoding(inst);
2843 
2844 
2845                 if (inst->opcode() == G4_nop)
2846                 {
2847                     binInstList.push_back(inst->getBinInst());
2848                     BuildLabelMap(inst, localHalfInstNum, localInstNum,
2849                         globalHalfInstNum, globalInstNum);
2850                     continue;
2851                 }
2852 
2853 
2854                 EncodeOperandDst(inst);
2855 
2856                 if (!EncodingHelper::hasLabelString(inst))
2857                 {
2858                     EncodeOperands(inst);
2859                 }
2860 
2861                 if (inst->opcode() == G4_pseudo_fc_call ||
2862                     inst->opcode() == G4_pseudo_fc_ret)
2863                 {
2864                     inst->getBinInst()->SetDontCompactFlag(true);
2865                 }
2866 
2867                 if (doCompaction())
2868                 {
2869                     // do not compact the instruction that mark as NoCompact
2870                     inst->getBinInst()->SetMustCompactFlag(false);
2871                     inst->getBinInst()->SetDontCompactFlag(inst->isNoCompactedInst());
2872 
2873                     /**
2874                      * handling switch/case for gen6: jump table should not be compacted
2875                      */
2876                     bool compacted = false;
2877                     {
2878                         TIME_SCOPE(ENCODE_COMPACTION);
2879                         compacted = compactOneInstruction(inst);
2880                     }
2881                     if (compacted)
2882                     {
2883                         if (kernel.getOption(vISA_OptReport))
2884                         {
2885                             numCompactedInst++;
2886                             if (inst->getBinInst()->GetIs3Src())
2887                                 numCompacted3SrcInst++;
2888                         }
2889                         inst->setCompacted();
2890                     }
2891                 }
2892                 binInstList.push_back(inst->getBinInst());
2893 
2894                 if (inst->opcode() >= G4_jmpi && inst->opcode() <= G4_join)
2895                 {
2896                     if (!EncodeConditionalBranches(inst, globalHalfInstNum))
2897                     {
2898                         offsetVector.push_back(ForwardJmpOffset(inst, globalHalfInstNum));
2899                     }
2900                 }
2901             } // else if
2902 
2903             BuildLabelMap(inst, localHalfInstNum, localInstNum,
2904                 globalHalfInstNum, globalInstNum);
2905 
2906         } // for inst
2907     } // for bb
2908     kernel.setAsmCount(globalInstNum);
2909     SetInstCounts((uint32_t)globalHalfInstNum);
2910 
2911     EncodingHelper::dumpOptReport(globalInstNum, numCompactedInst, numCompacted3SrcInst, kernel);
2912     for (auto x = offsetVector.begin(), vEnd = offsetVector.end(); x != vEnd; x++)
2913     {
2914         // calculate offsets again since labels for forward jumps/calls
2915         // are available now
2916         if (!EncodeConditionalBranches(x->inst, x->offset))
2917         {
2918             MUST_BE_TRUE(false, "invalid label!");
2919         }
2920     }
2921 
2922     return myStatus;
2923 }
2924 
DoAll()2925 void BinaryEncoding::DoAll()
2926 {
2927     InitPlatform(getGenxPlatform());
2928     FixInst();
2929     ProduceBinaryInstructions();
2930 }
2931 
SetBranchJIP(BinInst * mybin,uint32_t JIP)2932 inline void SetBranchJIP(BinInst *mybin, uint32_t JIP)
2933 {
2934     if (mybin->GetIs3Src())
2935         return;
2936     else
2937     {
2938         mybin->SetBits(bitsJIP[0], bitsJIP[1], JIP);
2939     }
2940 }
2941 
2942 
SetBranchJIPUIP(BinInst * mybin,uint32_t JIP,uint32_t UIP)2943 inline void SetBranchJIPUIP(BinInst *mybin, uint32_t JIP, uint32_t UIP)
2944 {
2945     if (mybin->GetIs3Src())
2946         return;
2947     else
2948     {
2949         mybin->SetBits(bitsJIP[0], bitsJIP[1], JIP);
2950         mybin->SetBits(bitsUIP[0], bitsUIP[1], UIP);
2951     }
2952 }
2953 
SetBranchOffsets(G4_INST * inst,uint32_t JIP,uint32_t UIP)2954 void BinaryEncoding::SetBranchOffsets(G4_INST* inst,
2955                                       uint32_t JIP,
2956                                       uint32_t UIP)
2957 {
2958     BinInst *mybin = inst->getBinInst();
2959     G4_opcode opc = inst->opcode();
2960 
2961     {
2962         //JIP and UIP are at src1
2963         //No need to set type and srcReg for src1
2964         //Not needed for instructions with JIP only
2965         //and over written by UIP
2966 
2967         if (opc == G4_if            ||
2968             opc == G4_break         ||
2969             opc == G4_cont          ||
2970             opc == G4_halt          ||
2971             opc == G4_goto          ||
2972             opc == G4_else)
2973         {
2974             SetSrc0RegFile(mybin, REG_FILE_I);
2975             SetSrc0Type(mybin, SRC_IMM_TYPE_D);
2976             SetBranchJIPUIP(mybin, JIP, UIP);
2977         }
2978         else
2979         {
2980             //JIP is at location src1 and must be of type D (signed dword integer).
2981             if ((opc == G4_while ||
2982                 opc == G4_endif  ||
2983                 opc == G4_join))
2984             {
2985                 SetSrc1RegFile(mybin, REG_FILE_I);
2986                 SetSrc1Type(mybin, SRC_IMM_TYPE_D);
2987             }
2988             SetBranchJIP(mybin, JIP);
2989         }
2990     }
2991 }
2992 
isValidIPOffset(int32_t ipOffset)2993 inline bool isValidIPOffset(int32_t ipOffset)
2994 {
2995     return true;
2996 }
2997 
SetCmpSrc1Imm32(BinInst * mybin,uint32_t immediateData,G4_Operand * src)2998 void BinaryEncoding::SetCmpSrc1Imm32(BinInst *mybin, uint32_t immediateData, G4_Operand* src)
2999 {
3000     if (GetCompactCtrl(mybin))
3001     {
3002         SetCmpSrc1RegNum(mybin, immediateData & 0xff);          // 63:56
3003         SetCmpSrc1Index(mybin, (immediateData >> 8)& 0x1f);
3004     }
3005     else
3006     {
3007         SetSrc1Imm32(mybin, immediateData, src);
3008     }
3009 }
3010 
3011 /* EncodeConditionalBranches() returns true for backward jmp/call/jip/uip,
3012  * returns false for forward jmp/call/jip/uip.
3013  */
EncodeConditionalBranches(G4_INST * inst,uint32_t insOffset)3014 bool BinaryEncoding::EncodeConditionalBranches(G4_INST *inst,
3015                                    uint32_t insOffset)
3016 {
3017     std::string jipLabel;
3018     std::string uipLabel;
3019     int32_t jipOffset = 0;
3020     int32_t uipOffset = 0;
3021     G4_opcode op = inst->opcode();
3022 
3023     // while and case only have JIP for all platforms
3024     // break, cont and halt have both JIP and UIP for all platforms
3025     if (op == G4_if    ||
3026          op == G4_while ||
3027          op == G4_else  ||
3028          op == G4_break ||
3029          op == G4_cont  ||
3030          op == G4_halt ||
3031          op == G4_goto ||
3032          op == G4_endif ||
3033          op == G4_join)
3034     {
3035         G4_Label* jip = inst->asCFInst()->getJip();
3036         if (jip)
3037         {
3038             int32_t info = GetLabelInfo(jip);
3039             if (info == -1)
3040             {
3041                 return false;
3042             }
3043             jipOffset = info - insOffset;
3044             if (!isValidIPOffset(jipOffset))
3045             {
3046                 MUST_BE_TRUE(false, "invalid IP offset");
3047             }
3048             // BDW+: in unit of bytes
3049             jipOffset *= (int32_t)JUMP_INST_COUNT_SIZE;
3050         }
3051         //Setting RegFile and Type in case JIP is 0.
3052         else if (op == G4_while ||
3053             op == G4_endif ||
3054             op == G4_join)
3055         {
3056             BinInst * mybin = inst->getBinInst();
3057             SetSrc1RegFile(mybin, REG_FILE_I);
3058             SetSrc1Type(mybin, SRC_IMM_TYPE_D);
3059         }
3060     }
3061 
3062     // halt has both JIP and UIP on all platforms
3063     // else has JIP for all platforms; else has UIP for BDW only
3064     if (op == G4_break                 ||
3065          op == G4_cont                  ||
3066          op == G4_halt                  ||
3067          op == G4_if                    ||
3068          op == G4_else                  ||
3069          op == G4_goto)
3070     {
3071         G4_Label* uip = inst->asCFInst()->getUip();
3072         if (uip)
3073         {
3074             int32_t info = GetLabelInfo(uip);
3075             if (info == -1)
3076             {
3077                 return false;
3078             }
3079             uipOffset = info - insOffset;
3080             if (!isValidIPOffset(uipOffset))
3081             {
3082                 MUST_BE_TRUE(false, "invalid IP offset");
3083             }
3084             uipOffset *= (uint32_t)JUMP_INST_COUNT_SIZE;
3085         }
3086     }
3087 
3088     if (op == G4_endif && jipOffset == 0)
3089     {
3090         jipOffset = INST_SIZE; // Next instruction ...
3091     }
3092 
3093     if (jipOffset != 0 || uipOffset != 0)
3094     {
3095         SetBranchOffsets(inst, jipOffset, uipOffset);
3096     }
3097 
3098     if (op == G4_jmpi              &&
3099          inst->getSrc(0)            &&
3100          inst->getSrc(0)->isLabel())
3101     {
3102         // find the label's IP count
3103         G4_Label *opnd = inst->getSrc(0)->asLabel();
3104         BinInst * mybin = inst->getBinInst();
3105         // Calculate the address offset
3106         // Label has the same IP count as the following instruction,
3107         // "break 1" is to the fall through instruction
3108         int32_t info = GetLabelInfo(opnd);
3109         if (info == -1)
3110         {
3111             return false;
3112         }
3113         int32_t jmpOffset = info - insOffset;
3114         if (GetCompactCtrl(mybin))
3115             jmpOffset -= 1;
3116         else
3117             jmpOffset -= 2;
3118 
3119         jmpOffset *= (int32_t)JUMP_INST_COUNT_SIZE;
3120 
3121         if (!isValidIPOffset(jmpOffset))
3122         {
3123             // generate
3124             // add (1) ip ip jmpOffset+16
3125             // to work around the 16-bit jump offset limit
3126             // jmpOffset is incremented by 1 since jmpi implicitly performs it
3127             // (e.g., jmpi 0 jumps to the next instruction)
3128             // everything else about the instruction should stay the same
3129             // (dst and src0 are both ip for example)
3130             SetOpCode(mybin, G4_add);
3131             jmpOffset += 16;
3132         }
3133 
3134         if (GetCompactCtrl(mybin))
3135         {
3136             SetCmpSrc1RegNum(mybin, jmpOffset & 0xff);          // 63:56
3137             SetCmpSrc1Index(mybin, (jmpOffset >> 8)& 0x1f);
3138         }
3139         else
3140         {
3141             SetSrc1RegFile(mybin, REG_FILE_I);
3142             SetSrc1Type(mybin, SRC_IMM_TYPE_D);
3143             SetSrc1Imm32(mybin, (uint32_t)jmpOffset, opnd);
3144         }
3145     }
3146 
3147     if (op == G4_call && inst->getSrc(0))
3148     {
3149 
3150         if (inst->getSrc(0)->isLabel())
3151         {
3152             G4_Label *opnd = inst->getSrc(0)->asLabel();
3153             int32_t info = GetLabelInfo(opnd);
3154             if (info == -1)
3155             {
3156                 return false;
3157             }
3158             int32_t jmpOffset = info - insOffset;
3159             if (!isValidIPOffset(jmpOffset))
3160             {
3161                 MUST_BE_TRUE(false, "invalid IP offset for call");
3162             }
3163 
3164             jmpOffset *= (int32_t)JUMP_INST_COUNT_SIZE;
3165 
3166             BinInst *mybin = inst->getBinInst();
3167 
3168             SetSrc0VertStride(mybin, 2);
3169             SetSrc0Width(mybin, 2);
3170             SetSrc0HorzStride(mybin, 1);
3171 
3172 
3173             SetSrc1RegFile(mybin, REG_FILE_I);
3174             SetSrc1Type(mybin, SRC_IMM_TYPE_D);
3175 
3176             SetCmpSrc1Imm32(mybin, jmpOffset, opnd);
3177         }
3178         else
3179         {
3180             // indirect call
3181             BinInst *mybin = inst->getBinInst();
3182 
3183             SetSrc0VertStride(mybin, 2);
3184             SetSrc0Width(mybin, 2);
3185             SetSrc0HorzStride(mybin, 1);
3186             EncodeIndirectCallTarget(inst);
3187         }
3188     }
3189     return true;
3190 }
3191