| 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 x8, 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 x8, 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 x8, 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 x8, 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 x8, 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 x8, 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 x8, 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 x8, 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 x8, 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 x8, 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, x8 |
| 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, x8 |
| 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, x8 |
| 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, x8 |
| 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, x8 |
| 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, x8 |
| 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, x8 |
| 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, x8 |
| 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, x8 |
| 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, x8 |
| 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 | |