@@ -617,9 +617,9 @@ let Predicates = [BPFNoALU32] in {
617
617
def : Pat<(i64 (extloadi32 ADDRri:$src)), (i64 (LDW ADDRri:$src))>;
618
618
}
619
619
620
- // Atomics
620
+ // Atomic XADD for BPFNoALU32
621
621
class XADD<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
622
- : TYPE_LD_ST<BPF_XADD .Value, SizeOp.Value,
622
+ : TYPE_LD_ST<BPF_ATOMIC .Value, SizeOp.Value,
623
623
(outs GPR:$dst),
624
624
(ins MEMri:$addr, GPR:$val),
625
625
"lock *("#OpcodeStr#" *)($addr) += $val",
@@ -630,34 +630,206 @@ class XADD<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
630
630
let Inst{51-48} = addr{19-16}; // base reg
631
631
let Inst{55-52} = dst;
632
632
let Inst{47-32} = addr{15-0}; // offset
633
+ let Inst{7-4} = BPF_ADD.Value;
633
634
let BPFClass = BPF_STX;
634
635
}
635
636
636
- class XADD32<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
637
- : TYPE_LD_ST<BPF_XADD.Value, SizeOp.Value,
637
+ let Constraints = "$dst = $val" in {
638
+ let Predicates = [BPFNoALU32] in {
639
+ def XADDW : XADD<BPF_W, "u32", atomic_load_add_32>;
640
+ }
641
+ }
642
+
643
+ // Atomic add, and, or, xor
644
+ class ATOMIC_NOFETCH<BPFArithOp Opc, string Opstr>
645
+ : TYPE_LD_ST<BPF_ATOMIC.Value, BPF_DW.Value,
646
+ (outs GPR:$dst),
647
+ (ins MEMri:$addr, GPR:$val),
648
+ "lock *(u64 *)($addr) " #Opstr# "= $val",
649
+ []> {
650
+ bits<4> dst;
651
+ bits<20> addr;
652
+
653
+ let Inst{51-48} = addr{19-16}; // base reg
654
+ let Inst{55-52} = dst;
655
+ let Inst{47-32} = addr{15-0}; // offset
656
+ let Inst{7-4} = Opc.Value;
657
+ let BPFClass = BPF_STX;
658
+ }
659
+
660
+ class ATOMIC32_NOFETCH<BPFArithOp Opc, string Opstr>
661
+ : TYPE_LD_ST<BPF_ATOMIC.Value, BPF_W.Value,
638
662
(outs GPR32:$dst),
639
663
(ins MEMri:$addr, GPR32:$val),
640
- "lock *("#OpcodeStr#" *)($addr) += $val",
664
+ "lock *(u32 *)($addr) " #Opstr# "= $val",
665
+ []> {
666
+ bits<4> dst;
667
+ bits<20> addr;
668
+
669
+ let Inst{51-48} = addr{19-16}; // base reg
670
+ let Inst{55-52} = dst;
671
+ let Inst{47-32} = addr{15-0}; // offset
672
+ let Inst{7-4} = Opc.Value;
673
+ let BPFClass = BPF_STX;
674
+ }
675
+
676
+ let Constraints = "$dst = $val" in {
677
+ let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
678
+ def XADDW32 : ATOMIC32_NOFETCH<BPF_ADD, "+">;
679
+ def XANDW32 : ATOMIC32_NOFETCH<BPF_AND, "&">;
680
+ def XORW32 : ATOMIC32_NOFETCH<BPF_OR, "|">;
681
+ def XXORW32 : ATOMIC32_NOFETCH<BPF_XOR, "^">;
682
+ }
683
+
684
+ def XADDD : ATOMIC_NOFETCH<BPF_ADD, "+">;
685
+ def XANDD : ATOMIC_NOFETCH<BPF_AND, "&">;
686
+ def XORD : ATOMIC_NOFETCH<BPF_OR, "|">;
687
+ def XXORD : ATOMIC_NOFETCH<BPF_XOR, "^">;
688
+ }
689
+
690
+ // Atomic Fetch-and-<add, and, or, xor> operations
691
+ class XFALU64<BPFWidthModifer SizeOp, BPFArithOp Opc, string OpcodeStr,
692
+ string OpcStr, PatFrag OpNode>
693
+ : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
694
+ (outs GPR:$dst),
695
+ (ins MEMri:$addr, GPR:$val),
696
+ "$dst = atomic_fetch_"#OpcStr#"(("#OpcodeStr#" *)($addr), $val)",
697
+ [(set GPR:$dst, (OpNode ADDRri:$addr, GPR:$val))]> {
698
+ bits<4> dst;
699
+ bits<20> addr;
700
+
701
+ let Inst{51-48} = addr{19-16}; // base reg
702
+ let Inst{55-52} = dst;
703
+ let Inst{47-32} = addr{15-0}; // offset
704
+ let Inst{7-4} = Opc.Value;
705
+ let Inst{3-0} = BPF_FETCH.Value;
706
+ let BPFClass = BPF_STX;
707
+ }
708
+
709
+ class XFALU32<BPFWidthModifer SizeOp, BPFArithOp Opc, string OpcodeStr,
710
+ string OpcStr, PatFrag OpNode>
711
+ : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
712
+ (outs GPR32:$dst),
713
+ (ins MEMri:$addr, GPR32:$val),
714
+ "$dst = atomic_fetch_"#OpcStr#"(("#OpcodeStr#" *)($addr), $val)",
641
715
[(set GPR32:$dst, (OpNode ADDRri:$addr, GPR32:$val))]> {
642
716
bits<4> dst;
643
717
bits<20> addr;
644
718
645
719
let Inst{51-48} = addr{19-16}; // base reg
646
720
let Inst{55-52} = dst;
647
721
let Inst{47-32} = addr{15-0}; // offset
722
+ let Inst{7-4} = Opc.Value;
723
+ let Inst{3-0} = BPF_FETCH.Value;
648
724
let BPFClass = BPF_STX;
649
725
}
650
726
651
727
let Constraints = "$dst = $val" in {
652
- let Predicates = [BPFNoALU32] in {
653
- def XADDW : XADD<BPF_W, "u32", atomic_load_add_32>;
728
+ let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
729
+ def XFADDW32 : XFALU32<BPF_W, BPF_ADD, "u32", "add", atomic_load_add_32>;
730
+ def XFANDW32 : XFALU32<BPF_W, BPF_AND, "u32", "and", atomic_load_and_32>;
731
+ def XFORW32 : XFALU32<BPF_W, BPF_OR, "u32", "or", atomic_load_or_32>;
732
+ def XFXORW32 : XFALU32<BPF_W, BPF_XOR, "u32", "xor", atomic_load_xor_32>;
654
733
}
655
734
735
+ def XFADDD : XFALU64<BPF_DW, BPF_ADD, "u64", "add", atomic_load_add_64>;
736
+ def XFANDD : XFALU64<BPF_DW, BPF_AND, "u64", "and", atomic_load_and_64>;
737
+ def XFORD : XFALU64<BPF_DW, BPF_OR, "u64", "or", atomic_load_or_64>;
738
+ def XFXORD : XFALU64<BPF_DW, BPF_XOR, "u64", "xor", atomic_load_xor_64>;
739
+ }
740
+
741
+ // atomic_load_sub can be represented as a neg followed
742
+ // by an atomic_load_add.
743
+ def : Pat<(atomic_load_sub_32 ADDRri:$addr, GPR32:$val),
744
+ (XFADDW32 ADDRri:$addr, (NEG_32 GPR32:$val))>;
745
+ def : Pat<(atomic_load_sub_64 ADDRri:$addr, GPR:$val),
746
+ (XFADDD ADDRri:$addr, (NEG_64 GPR:$val))>;
747
+
748
+ // Atomic Exchange
749
+ class XCHG<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
750
+ : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
751
+ (outs GPR:$dst),
752
+ (ins MEMri:$addr, GPR:$val),
753
+ "$dst = xchg_"#OpcodeStr#"($addr, $val)",
754
+ [(set GPR:$dst, (OpNode ADDRri:$addr,GPR:$val))]> {
755
+ bits<4> dst;
756
+ bits<20> addr;
757
+
758
+ let Inst{51-48} = addr{19-16}; // base reg
759
+ let Inst{55-52} = dst;
760
+ let Inst{47-32} = addr{15-0}; // offset
761
+ let Inst{7-4} = BPF_XCHG.Value;
762
+ let Inst{3-0} = BPF_FETCH.Value;
763
+ let BPFClass = BPF_STX;
764
+ }
765
+
766
+ class XCHG32<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
767
+ : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
768
+ (outs GPR32:$dst),
769
+ (ins MEMri:$addr, GPR32:$val),
770
+ "$dst = xchg32_"#OpcodeStr#"($addr, $val)",
771
+ [(set GPR32:$dst, (OpNode ADDRri:$addr,GPR32:$val))]> {
772
+ bits<4> dst;
773
+ bits<20> addr;
774
+
775
+ let Inst{51-48} = addr{19-16}; // base reg
776
+ let Inst{55-52} = dst;
777
+ let Inst{47-32} = addr{15-0}; // offset
778
+ let Inst{7-4} = BPF_XCHG.Value;
779
+ let Inst{3-0} = BPF_FETCH.Value;
780
+ let BPFClass = BPF_STX;
781
+ }
782
+
783
+ let Constraints = "$dst = $val" in {
656
784
let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
657
- def XADDW32 : XADD32 <BPF_W, "u32 ", atomic_load_add_32 >;
785
+ def XCHGW32 : XCHG32 <BPF_W, "32 ", atomic_swap_32 >;
658
786
}
659
787
660
- def XADDD : XADD<BPF_DW, "u64", atomic_load_add_64>;
788
+ def XCHGD : XCHG<BPF_DW, "64", atomic_swap_64>;
789
+ }
790
+
791
+ // Compare-And-Exchange
792
+ class CMPXCHG<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
793
+ : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
794
+ (outs),
795
+ (ins MEMri:$addr, GPR:$new),
796
+ "r0 = cmpxchg_"#OpcodeStr#"($addr, r0, $new)",
797
+ [(set R0, (OpNode ADDRri:$addr, R0, GPR:$new))]> {
798
+ bits<4> new;
799
+ bits<20> addr;
800
+
801
+ let Inst{51-48} = addr{19-16}; // base reg
802
+ let Inst{55-52} = new;
803
+ let Inst{47-32} = addr{15-0}; // offset
804
+ let Inst{7-4} = BPF_CMPXCHG.Value;
805
+ let Inst{3-0} = BPF_FETCH.Value;
806
+ let BPFClass = BPF_STX;
807
+ }
808
+
809
+ class CMPXCHG32<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
810
+ : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
811
+ (outs),
812
+ (ins MEMri:$addr, GPR32:$new),
813
+ "w0 = cmpxchg32_"#OpcodeStr#"($addr, w0, $new)",
814
+ [(set W0, (OpNode ADDRri:$addr, W0, GPR32:$new))]> {
815
+ bits<4> new;
816
+ bits<20> addr;
817
+
818
+ let Inst{51-48} = addr{19-16}; // base reg
819
+ let Inst{55-52} = new;
820
+ let Inst{47-32} = addr{15-0}; // offset
821
+ let Inst{7-4} = BPF_CMPXCHG.Value;
822
+ let Inst{3-0} = BPF_FETCH.Value;
823
+ let BPFClass = BPF_STX;
824
+ }
825
+
826
+ let Predicates = [BPFHasALU32], Defs = [W0], Uses = [W0],
827
+ DecoderNamespace = "BPFALU32" in {
828
+ def CMPXCHGW32 : CMPXCHG32<BPF_W, "32", atomic_cmp_swap_32>;
829
+ }
830
+
831
+ let Defs = [R0], Uses = [R0] in {
832
+ def CMPXCHGD : CMPXCHG<BPF_DW, "64", atomic_cmp_swap_64>;
661
833
}
662
834
663
835
// bswap16, bswap32, bswap64
0 commit comments