@@ -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)
@@ -369,12 +381,12 @@ uint8_t TernaryLogicInfo::GetTernaryControlByte(genTreeOps oper, uint8_t op1, ui
369
381
370
382
case GT_OR:
371
383
{
372
- return static_cast <uint8_t >(op1 & op2);
384
+ return static_cast <uint8_t >(op1 | op2);
373
385
}
374
386
375
387
case GT_XOR:
376
388
{
377
- return static_cast <uint8_t >(op1 & op2);
389
+ return static_cast <uint8_t >(op1 ^ op2);
378
390
}
379
391
380
392
default :
@@ -383,6 +395,322 @@ 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 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
+ }
386
714
#endif // TARGET_XARCH
387
715
388
716
// ------------------------------------------------------------------------
0 commit comments