1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
//! 分支的事务性内存扩展 (TME)。
//!
//! 此 CPU 特性在 Aarch64 上可用 - 架构概要。
//! 此特性在非 neon 的特性集中。可以在 [TME Intrinsics 介绍][tme_intrinsics_intro] 上找到 TME 特定的供应商文档。
//!
//! 引用的是 [ACLE Q4 2019][acle_q4_2019_ref]。
//!
//! ACLE 有一个用于 TME 扩展的部分,以及用于中止和故障代码的状态掩码的部分。
//! [ARM A64 架构登记数据表][a_profile_future] 还描述了可能的故障代码场景。
//!
//! [acle_q4_2019_ref]: https://static.docs.arm.com/101028/0010/ACLE_2019Q4_release-0010.pdf
//! [tme_intrinsics_intro]: https://developer.arm.com/docs/101028/0010/transactional-memory-extension-tme-intrinsics
//! [llvm_aarch64_int]: https://github.com/llvm/llvm-project/commit/a36d31478c182903523e04eb271bbf102bfab2cc#diff-ff24e1c35f4d54f1110ce5d90c709319R626-R646
//! [a_profile_future]: https://static.docs.arm.com/ddi0601/a/SysReg_xml_futureA-2019-04.pdf?_ga=2.116560387.441514988.1590524918-1110153136.1588469296
//!
#[cfg(test)]
use stdarch_test::assert_instr;
extern "unadjusted" {
#[link_name = "llvm.aarch64.tstart"]
fn aarch64_tstart() -> u64;
#[link_name = "llvm.aarch64.tcommit"]
fn aarch64_tcommit() -> ();
#[link_name = "llvm.aarch64.tcancel"]
fn aarch64_tcancel(imm0: u64) -> ();
#[link_name = "llvm.aarch64.ttest"]
fn aarch64_ttest() -> u64;
}
/// 事务成功开始。
pub const _TMSTART_SUCCESS: u64 = 0x00_u64;
/// 故障原因的提取码
pub const _TMFAILURE_REASON: u64 = 0x00007FFF_u64;
/// 事务重试是可能的。
pub const _TMFAILURE_RTRY: u64 = 1 << 15;
/// 事务执行了 TCANCEL 指令
pub const _TMFAILURE_CNCL: u64 = 1 << 16;
/// 事务因发生冲突而中止
pub const _TMFAILURE_MEM: u64 = 1 << 17;
/// 后备错误类型 (由于任何其他原因)
pub const _TMFAILURE_IMP: u64 = 1 << 18;
/// 事务中止,因为尝试了不允许的操作
pub const _TMFAILURE_ERR: u64 = 1 << 19;
/// 事务由于超出读或写集限制而中止
pub const _TMFAILURE_SIZE: u64 = 1 << 20;
/// 由于超出了事务嵌套级别,事务中止了
pub const _TMFAILURE_NEST: u64 = 1 << 21;
/// 事务由于调试陷阱而中止。
pub const _TMFAILURE_DBG: u64 = 1 << 22;
/// 事务因中断而失败
pub const _TMFAILURE_INT: u64 = 1 << 23;
/// 表示 TM 的试用版可用
pub const _TMFAILURE_TRIVIAL: u64 = 1 << 24;
/// 开始新的事务。当交易开始成功时,返回值是 0.
/// 如果事务失败,则将丢弃所有状态修改,并将失败原因编码在返回值中。
///
/// [ARM TME Intrinsics](https://developer.arm.com/docs/101028/0010/transactional-memory-extension-tme-intrinsics).
///
#[inline]
#[target_feature(enable = "tme")]
#[cfg_attr(test, assert_instr(tstart))]
pub unsafe fn __tstart() -> u64 {
aarch64_tstart()
}
/// 提交当前事务。
/// 对于嵌套事务,唯一的效果是减少了事务嵌套深度。
/// 对于外部事务,将事务执行的状态修改提交给体系结构状态。
///
/// [ARM TME Intrinsics](https://developer.arm.com/docs/101028/0010/transactional-memory-extension-tme-intrinsics).
#[inline]
#[target_feature(enable = "tme")]
#[cfg_attr(test, assert_instr(tcommit))]
pub unsafe fn __tcommit() {
aarch64_tcommit()
}
/// 取消当前事务,并放弃所有通过事务执行的状态修改。
/// [ARM TME Intrinsics](https://developer.arm.com/docs/101028/0010/transactional-memory-extension-tme-intrinsics).
///
#[inline]
#[target_feature(enable = "tme")]
#[cfg_attr(test, assert_instr(tcancel, IMM16 = 0x0))]
#[rustc_legacy_const_generics(0)]
pub unsafe fn __tcancel<const IMM16: u64>() {
static_assert!(IMM16 <= 65535);
aarch64_tcancel(IMM16);
}
/// 测试是否在事务内执行。
/// 如果当前没有事务正在执行,则返回值为 0.
/// 否则,此内部函数将返回事务的深度。
/// [ARM TME Intrinsics](https://developer.arm.com/docs/101028/0010/transactional-memory-extension-tme-intrinsics).
#[inline]
#[target_feature(enable = "tme")]
#[cfg_attr(test, assert_instr(ttest))]
pub unsafe fn __ttest() -> u64 {
aarch64_ttest()
}
#[cfg(test)]
mod tests {
use stdarch_test::simd_test;
use crate::core_arch::aarch64::*;
const CANCEL_CODE: u64 = (0 | (0x123 & _TMFAILURE_REASON) as u64) as u64;
#[simd_test(enable = "tme")]
unsafe fn test_tstart() {
let mut x = 0;
for i in 0..10 {
let code = tme::__tstart();
if code == _TMSTART_SUCCESS {
x += 1;
assert_eq!(x, i + 1);
break;
}
assert_eq!(x, 0);
}
}
#[simd_test(enable = "tme")]
unsafe fn test_tcommit() {
let mut x = 0;
for i in 0..10 {
let code = tme::__tstart();
if code == _TMSTART_SUCCESS {
x += 1;
assert_eq!(x, i + 1);
tme::__tcommit();
}
assert_eq!(x, i + 1);
}
}
#[simd_test(enable = "tme")]
unsafe fn test_tcancel() {
let mut x = 0;
for i in 0..10 {
let code = tme::__tstart();
if code == _TMSTART_SUCCESS {
x += 1;
assert_eq!(x, i + 1);
tme::__tcancel::<CANCEL_CODE>();
break;
}
}
assert_eq!(x, 0);
}
#[simd_test(enable = "tme")]
unsafe fn test_ttest() {
for _ in 0..10 {
let code = tme::__tstart();
if code == _TMSTART_SUCCESS {
if tme::__ttest() == 2 {
tme::__tcancel::<CANCEL_CODE>();
break;
}
}
}
}
}