@@ -353,6 +353,18 @@ const TernaryLogicInfo& TernaryLogicInfo::lookup(uint8_t control)
353353 return ternaryLogicFlags[control];
354354}
355355
356+ // ------------------------------------------------------------------------
357+ // GetTernaryControlByte: Get the control byte for a TernaryLogic operation
358+ // given the oper and two existing control bytes
359+ //
360+ // Arguments:
361+ // oper -- the operation being performed
362+ // op1 -- the control byte for op1
363+ // op2 -- the control byte for op2
364+ //
365+ // Return Value:
366+ // The new control byte evaluated from performing oper on op1 and op2
367+ //
356368uint8_t TernaryLogicInfo::GetTernaryControlByte (genTreeOps oper, uint8_t op1, uint8_t op2)
357369{
358370 switch (oper)
@@ -369,12 +381,12 @@ uint8_t TernaryLogicInfo::GetTernaryControlByte(genTreeOps oper, uint8_t op1, ui
369381
370382 case GT_OR:
371383 {
372- return static_cast <uint8_t >(op1 & op2);
384+ return static_cast <uint8_t >(op1 | op2);
373385 }
374386
375387 case GT_XOR:
376388 {
377- return static_cast <uint8_t >(op1 & op2);
389+ return static_cast <uint8_t >(op1 ^ op2);
378390 }
379391
380392 default :
@@ -383,6 +395,322 @@ uint8_t TernaryLogicInfo::GetTernaryControlByte(genTreeOps oper, uint8_t op1, ui
383395 }
384396 }
385397}
398+
399+ // ------------------------------------------------------------------------
400+ // GetTernaryControlByte: Get the control byte for a TernaryLogic operation
401+ // given a ternary logic oper and two inputs
402+ //
403+ // Arguments:
404+ // oper -- the operation being performed
405+ // op1 -- the control byte for op1, this is ignored for unary oper
406+ // op2 -- the control byte for op2
407+ //
408+ // Return Value:
409+ // The new control byte evaluated from performing oper on op1 and op2
410+ //
411+ uint8_t TernaryLogicInfo::GetTernaryControlByte (TernaryLogicOperKind oper, uint8_t op1, uint8_t op2)
412+ {
413+ switch (oper)
414+ {
415+ case TernaryLogicOperKind::Select:
416+ {
417+ return op2;
418+ }
419+
420+ case TernaryLogicOperKind::Not:
421+ {
422+ return ~op2;
423+ }
424+
425+ case TernaryLogicOperKind::And:
426+ {
427+ return op1 & op2;
428+ }
429+
430+ case TernaryLogicOperKind::Nand:
431+ {
432+ return ~(op1 & op2);
433+ }
434+
435+ case TernaryLogicOperKind::Or:
436+ {
437+ return op1 | op2;
438+ }
439+
440+ case TernaryLogicOperKind::Nor:
441+ {
442+ return ~(op1 | op2);
443+ }
444+
445+ case TernaryLogicOperKind::Xor:
446+ {
447+ return op1 ^ op2;
448+ }
449+
450+ case TernaryLogicOperKind::Xnor:
451+ {
452+ return ~(op1 ^ op2);
453+ }
454+
455+ default :
456+ {
457+ unreached ();
458+ }
459+ }
460+ }
461+
462+ // ------------------------------------------------------------------------
463+ // GetTernaryControlByte: Get the control byte for a TernaryLogic operation
464+ // given an existing info and three control bytes
465+ //
466+ // Arguments:
467+ // info -- the info describing the operation being performed
468+ // op1 -- the control byte for op1
469+ // op2 -- the control byte for op2
470+ // op3 -- the control byte for op3
471+ //
472+ // Return Value:
473+ // The new control byte evaluated from performing info on op1, op2, and op3
474+ //
475+ uint8_t TernaryLogicInfo::GetTernaryControlByte (const TernaryLogicInfo& info, uint8_t op1, uint8_t op2, uint8_t op3)
476+ {
477+ uint8_t oper1Result;
478+
479+ switch (info.oper1Use )
480+ {
481+ case TernaryLogicUseFlags::None:
482+ {
483+ assert (info.oper2 == TernaryLogicOperKind::None);
484+ assert (info.oper2Use == TernaryLogicUseFlags::None);
485+
486+ assert (info.oper3 == TernaryLogicOperKind::None);
487+ assert (info.oper3Use == TernaryLogicUseFlags::None);
488+
489+ switch (info.oper1 )
490+ {
491+ case TernaryLogicOperKind::False:
492+ {
493+ oper1Result = 0x00 ;
494+ break ;
495+ }
496+
497+ case TernaryLogicOperKind::True:
498+ {
499+ oper1Result = 0xFF ;
500+ break ;
501+ }
502+
503+ default :
504+ {
505+ unreached ();
506+ }
507+ }
508+ break ;
509+ }
510+
511+ case TernaryLogicUseFlags::A:
512+ {
513+ oper1Result = GetTernaryControlByte (info.oper1 , 0x00 , op1);
514+ break ;
515+ }
516+
517+ case TernaryLogicUseFlags::B:
518+ {
519+ oper1Result = GetTernaryControlByte (info.oper1 , 0x00 , op2);
520+ break ;
521+ }
522+
523+ case TernaryLogicUseFlags::C:
524+ {
525+ oper1Result = GetTernaryControlByte (info.oper1 , 0x00 , op3);
526+ break ;
527+ }
528+
529+ case TernaryLogicUseFlags::AB:
530+ {
531+ oper1Result = GetTernaryControlByte (info.oper1 , op1, op2);
532+ break ;
533+ }
534+
535+ case TernaryLogicUseFlags::AC:
536+ {
537+ oper1Result = GetTernaryControlByte (info.oper1 , op1, op3);
538+ break ;
539+ }
540+
541+ case TernaryLogicUseFlags::BC:
542+ {
543+ oper1Result = GetTernaryControlByte (info.oper1 , op2, op3);
544+ break ;
545+ }
546+
547+ case TernaryLogicUseFlags::ABC:
548+ {
549+ assert (info.oper2 == TernaryLogicOperKind::None);
550+ assert (info.oper2Use == TernaryLogicUseFlags::None);
551+
552+ assert (info.oper3 == TernaryLogicOperKind::None);
553+ assert (info.oper3Use == TernaryLogicUseFlags::None);
554+
555+ switch (info.oper1 )
556+ {
557+ case TernaryLogicOperKind::Nor:
558+ {
559+ oper1Result = ~(op1 | op2 | op3);
560+ break ;
561+ }
562+
563+ case TernaryLogicOperKind::Minor:
564+ {
565+ oper1Result = 0x17 ;
566+ break ;
567+ }
568+
569+ case TernaryLogicOperKind::Xnor:
570+ {
571+ oper1Result = ~(op1 ^ op2 ^ op3);
572+ break ;
573+ }
574+
575+ case TernaryLogicOperKind::Nand:
576+ {
577+ oper1Result = ~(op1 & op2 & op3);
578+ break ;
579+ }
580+
581+ case TernaryLogicOperKind::And:
582+ {
583+ oper1Result = op1 & op2 & op3;
584+ break ;
585+ }
586+
587+ case TernaryLogicOperKind::Xor:
588+ {
589+ oper1Result = op1 ^ op2 ^ op3;
590+ break ;
591+ }
592+
593+ case TernaryLogicOperKind::Major:
594+ {
595+ oper1Result = 0xE8 ;
596+ break ;
597+ }
598+
599+ case TernaryLogicOperKind::Or:
600+ {
601+ oper1Result = op1 | op2 | op3;
602+ break ;
603+ }
604+
605+ default :
606+ {
607+ unreached ();
608+ }
609+ }
610+ break ;
611+ }
612+
613+ default :
614+ {
615+ unreached ();
616+ }
617+ }
618+
619+ uint8_t oper2Result;
620+
621+ switch (info.oper2Use )
622+ {
623+ case TernaryLogicUseFlags::None:
624+ {
625+ assert (info.oper3 == TernaryLogicOperKind::None);
626+ assert (info.oper3Use == TernaryLogicUseFlags::None);
627+
628+ oper2Result = oper1Result;
629+ break ;
630+ }
631+
632+ case TernaryLogicUseFlags::A:
633+ {
634+ oper2Result = GetTernaryControlByte (info.oper2 , oper1Result, op1);
635+ break ;
636+ }
637+
638+ case TernaryLogicUseFlags::B:
639+ {
640+ oper2Result = GetTernaryControlByte (info.oper2 , oper1Result, op2);
641+ break ;
642+ }
643+
644+ case TernaryLogicUseFlags::C:
645+ {
646+ oper2Result = GetTernaryControlByte (info.oper2 , oper1Result, op3);
647+ break ;
648+ }
649+
650+ case TernaryLogicUseFlags::AB:
651+ {
652+ oper2Result = GetTernaryControlByte (info.oper1 , op1, op2);
653+ break ;
654+ }
655+
656+ case TernaryLogicUseFlags::AC:
657+ {
658+ oper2Result = GetTernaryControlByte (info.oper1 , op1, op3);
659+ break ;
660+ }
661+
662+ case TernaryLogicUseFlags::BC:
663+ {
664+ oper2Result = GetTernaryControlByte (info.oper1 , op2, op3);
665+ break ;
666+ }
667+
668+ default :
669+ {
670+ unreached ();
671+ }
672+ }
673+
674+ uint8_t oper3Result;
675+
676+ switch (info.oper3Use )
677+ {
678+ case TernaryLogicUseFlags::None:
679+ {
680+ assert (info.oper3 == TernaryLogicOperKind::None);
681+ oper3Result = oper2Result;
682+ break ;
683+ }
684+
685+ case TernaryLogicUseFlags::A:
686+ {
687+ assert (info.oper3 == TernaryLogicOperKind::Cond);
688+ oper3Result = (oper1Result & op1) | (oper2Result & ~op1);
689+ break ;
690+ }
691+
692+ case TernaryLogicUseFlags::B:
693+ {
694+ assert (info.oper3 == TernaryLogicOperKind::Cond);
695+ oper3Result = (oper1Result & op2) | (oper2Result & ~op2);
696+ break ;
697+ }
698+
699+ case TernaryLogicUseFlags::C:
700+ {
701+ assert (info.oper3 == TernaryLogicOperKind::Cond);
702+ oper3Result = (oper1Result & op3) | (oper2Result & ~op3);
703+ break ;
704+ }
705+
706+ default :
707+ {
708+ unreached ();
709+ }
710+ }
711+
712+ return oper3Result;
713+ }
386714#endif // TARGET_XARCH
387715
388716// ------------------------------------------------------------------------
0 commit comments