1 // REQUIRES: aarch64-registered-target
2 
3 // RUN: %clang_cc1 -triple arm64-windows -fms-compatibility -emit-llvm -S \
4 // RUN: -o - %s | FileCheck %s -check-prefix CHECK-ASM
5 
6 // RUN: %clang_cc1 -triple arm64-windows -fms-compatibility -emit-llvm \
7 // RUN: -o - %s | FileCheck %s -check-prefix CHECK-IR
8 
9 // From winnt.h
10 #define ARM64_SYSREG(op0, op1, crn, crm, op2) \
11         ( ((op0 & 1) << 14) | \
12           ((op1 & 7) << 11) | \
13           ((crn & 15) << 7) | \
14           ((crm & 15) << 3) | \
15           ((op2 & 7) << 0) )
16 
17 #define ARM64_CNTVCT            ARM64_SYSREG(3,3,14, 0,2)  // Generic Timer counter register
18 #define ARM64_PMCCNTR_EL0       ARM64_SYSREG(3,3, 9,13,0)  // Cycle Count Register [CP15_PMCCNTR]
19 #define ARM64_PMSELR_EL0        ARM64_SYSREG(3,3, 9,12,5)  // Event Counter Selection Register [CP15_PMSELR]
20 #define ARM64_PMXEVCNTR_EL0     ARM64_SYSREG(3,3, 9,13,2)  // Event Count Register [CP15_PMXEVCNTR]
21 #define ARM64_PMXEVCNTRn_EL0(n) ARM64_SYSREG(3,3,14, 8+((n)/8), (n)%8)    // Direct Event Count Register [n/a]
22 #define ARM64_TPIDR_EL0         ARM64_SYSREG(3,3,13, 0,2)  // Thread ID Register, User Read/Write [CP15_TPIDRURW]
23 #define ARM64_TPIDRRO_EL0       ARM64_SYSREG(3,3,13, 0,3)  // Thread ID Register, User Read Only [CP15_TPIDRURO]
24 #define ARM64_TPIDR_EL1         ARM64_SYSREG(3,0,13, 0,4)  // Thread ID Register, Privileged Only [CP15_TPIDRPRW]
25 
26 // From intrin.h
27 __int64 _ReadStatusReg(int);
28 void _WriteStatusReg(int, __int64);
29 
30 void check_ReadWriteStatusReg(__int64 v) {
31   __int64 ret;
32   ret = _ReadStatusReg(ARM64_CNTVCT);
33 // CHECK-ASM: mrs     x0, CNTVCT_EL0
34 // CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2:.*]])
35 // CHECK-IR-NEXT: store i64 %[[VAR]]
36 
37   ret = _ReadStatusReg(ARM64_PMCCNTR_EL0);
38 // CHECK-ASM: mrs     x0, PMCCNTR_EL0
39 // CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD3:.*]])
40 // CHECK-IR-NEXT: store i64 %[[VAR]]
41 
42   ret = _ReadStatusReg(ARM64_PMSELR_EL0);
43 // CHECK-ASM: mrs     x0, PMSELR_EL0
44 // CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD4:.*]])
45 // CHECK-IR-NEXT: store i64 %[[VAR]]
46 
47   ret = _ReadStatusReg(ARM64_PMXEVCNTR_EL0);
48 // CHECK-ASM: mrs     x0, PMXEVCNTR_EL0
49 // CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD5:.*]])
50 // CHECK-IR-NEXT: store i64 %[[VAR]]
51 
52   ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(0));
53 // CHECK-ASM: mrs     x0, PMEVCNTR0_EL0
54 // CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD6:.*]])
55 // CHECK-IR-NEXT: store i64 %[[VAR]]
56 
57   ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(1));
58 // CHECK-ASM: mrs     x0, PMEVCNTR1_EL0
59 // CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD7:.*]])
60 // CHECK-IR-NEXT: store i64 %[[VAR]]
61 
62   ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(30));
63 // CHECK-ASM: mrs     x0, PMEVCNTR30_EL0
64 // CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD8:.*]])
65 // CHECK-IR-NEXT: store i64 %[[VAR]]
66 
67   ret = _ReadStatusReg(ARM64_TPIDR_EL0);
68 // CHECK-ASM: mrs     x0, TPIDR_EL0
69 // CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD9:.*]])
70 // CHECK-IR-NEXT: store i64 %[[VAR]]
71 
72   ret = _ReadStatusReg(ARM64_TPIDRRO_EL0);
73 // CHECK-ASM: mrs     x0, TPIDRRO_EL0
74 // CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD10:.*]])
75 // CHECK-IR-NEXT: store i64 %[[VAR]]
76 
77   ret = _ReadStatusReg(ARM64_TPIDR_EL1);
78 // CHECK-ASM: mrs     x0, TPIDR_EL1
79 // CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD11:.*]])
80 // CHECK-IR-NEXT: store i64 %[[VAR]]
81 
82 
83   _WriteStatusReg(ARM64_CNTVCT, v);
84 // CHECK-ASM: msr     S3_3_C14_C0_2, x0
85 // CHECK-IR: %[[VAR:.*]] = load i64,
86 // CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD2:.*]], i64 %[[VAR]])
87 
88   _WriteStatusReg(ARM64_PMCCNTR_EL0, v);
89 // CHECK-ASM: msr     PMCCNTR_EL0, x0
90 // CHECK-IR: %[[VAR:.*]] = load i64,
91 // CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD3:.*]], i64 %[[VAR]])
92 
93   _WriteStatusReg(ARM64_PMSELR_EL0, v);
94 // CHECK-ASM: msr     PMSELR_EL0, x0
95 // CHECK-IR: %[[VAR:.*]] = load i64,
96 // CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD4:.*]], i64 %[[VAR]])
97 
98   _WriteStatusReg(ARM64_PMXEVCNTR_EL0, v);
99 // CHECK-ASM: msr     PMXEVCNTR_EL0, x0
100 // CHECK-IR: %[[VAR:.*]] = load i64,
101 // CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD5:.*]], i64 %[[VAR]])
102 
103   _WriteStatusReg(ARM64_PMXEVCNTRn_EL0(0), v);
104 // CHECK-ASM: msr     PMEVCNTR0_EL0, x0
105 // CHECK-IR: %[[VAR:.*]] = load i64,
106 // CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD6:.*]], i64 %[[VAR]])
107 
108   _WriteStatusReg(ARM64_PMXEVCNTRn_EL0(1), v);
109 // CHECK-ASM: msr     PMEVCNTR1_EL0, x0
110 // CHECK-IR: %[[VAR:.*]] = load i64,
111 // CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD7:.*]], i64 %[[VAR]])
112 
113   _WriteStatusReg(ARM64_PMXEVCNTRn_EL0(30), v);
114 // CHECK-ASM: msr     PMEVCNTR30_EL0, x0
115 // CHECK-IR: %[[VAR:.*]] = load i64,
116 // CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD8:.*]], i64 %[[VAR]])
117 
118   _WriteStatusReg(ARM64_TPIDR_EL0, v);
119 // CHECK-ASM: msr     TPIDR_EL0, x0
120 // CHECK-IR: %[[VAR:.*]] = load i64,
121 // CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD9:.*]], i64 %[[VAR]])
122 
123   _WriteStatusReg(ARM64_TPIDRRO_EL0, v);
124 // CHECK-ASM: msr     TPIDRRO_EL0, x0
125 // CHECK-IR: %[[VAR:.*]] = load i64,
126 // CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD10:.*]], i64 %[[VAR]])
127 
128   _WriteStatusReg(ARM64_TPIDR_EL1, v);
129 // CHECK-ASM: msr     TPIDR_EL1, x0
130 // CHECK-IR: %[[VAR:.*]] = load i64,
131 // CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD11:.*]], i64 %[[VAR]])
132 }
133 
134 // CHECK-IR: ![[MD2]] = !{!"3:3:14:0:2"}
135 // CHECK-IR: ![[MD3]] = !{!"3:3:9:13:0"}
136 // CHECK-IR: ![[MD4]] = !{!"3:3:9:12:5"}
137 // CHECK-IR: ![[MD5]] = !{!"3:3:9:13:2"}
138 // CHECK-IR: ![[MD6]] = !{!"3:3:14:8:0"}
139 // CHECK-IR: ![[MD7]] = !{!"3:3:14:8:1"}
140 // CHECK-IR: ![[MD8]] = !{!"3:3:14:11:6"}
141 // CHECK-IR: ![[MD9]] = !{!"3:3:13:0:2"}
142 // CHECK-IR: ![[MD10]] = !{!"3:3:13:0:3"}
143 // CHECK-IR: ![[MD11]] = !{!"3:0:13:0:4"}
144