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