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
#[cfg(test)]
use stdarch_test::assert_instr;

extern "unadjusted" {
    #[link_name = "llvm.prefetch"]
    fn prefetch(p: *const i8, rw: i32, loc: i32, ty: i32);
}

/// 请参见 [`prefetch`](fn._prefetch.html)。
pub const _PREFETCH_READ: i32 = 0;

/// 请参见 [`prefetch`](fn._prefetch.html)。
pub const _PREFETCH_WRITE: i32 = 1;

/// 请参见 [`prefetch`](fn._prefetch.html)。
pub const _PREFETCH_LOCALITY0: i32 = 0;

/// 请参见 [`prefetch`](fn._prefetch.html)。
pub const _PREFETCH_LOCALITY1: i32 = 1;

/// 请参见 [`prefetch`](fn._prefetch.html)。
pub const _PREFETCH_LOCALITY2: i32 = 2;

/// 请参见 [`prefetch`](fn._prefetch.html)。
pub const _PREFETCH_LOCALITY3: i32 = 3;

/// 使用给定的 `RW` 和 `LOCALITY` 获取包含地址 `p` 的缓存行。
///
/// `RW` 必须是以下之一:
///
/// * [`_PREFETCH_READ`](constant._PREFETCH_READ.html): 预获取正在准备读取。
///
/// * [`_PREFETCH_WRITE`](constant._PREFETCH_WRITE.html): 预获取正在准备写入。
///
/// `LOCALITY` 必须是以下之一:
///
/// * [`_PREFETCH_LOCALITY0`](constant._PREFETCH_LOCALITY0.html): 流式或非临时预取,用于仅使用一次的数据。
///
/// * [`_PREFETCH_LOCALITY1`](constant._PREFETCH_LOCALITY1.html): 获取到 3 级缓存。
///
/// * [`_PREFETCH_LOCALITY2`](constant._PREFETCH_LOCALITY2.html): 获取到 2 级缓存。
///
/// * [`_PREFETCH_LOCALITY3`](constant._PREFETCH_LOCALITY3.html): 获取到 1 级缓存。
///
/// 预取存储器指令向存储器系统发送信号,表明从指定地址进行的存储器访问可能发生在 future 附近。
/// 内存系统可以通过采取某些措施来做出响应,这些措施可以在确实发生时加快内存访问的速度,例如将指定地址预加载到一个或多个高速缓存中。
///
/// 因为这些信号只是提示,所以对于特定的 CPU,将任何或所有预取指令视为 NOP 是有效的。
///
/// [Arm's documentation](https://developer.arm.com/documentation/den0024/a/the-a64-instruction-set/memory-access-instructions/prefetching-memory?lang=en)
///
///
///
///
///
///
#[inline(always)]
#[cfg_attr(test, assert_instr("prfm pldl1strm", RW = _PREFETCH_READ, LOCALITY = _PREFETCH_LOCALITY0))]
#[cfg_attr(test, assert_instr("prfm pldl3keep", RW = _PREFETCH_READ, LOCALITY = _PREFETCH_LOCALITY1))]
#[cfg_attr(test, assert_instr("prfm pldl2keep", RW = _PREFETCH_READ, LOCALITY = _PREFETCH_LOCALITY2))]
#[cfg_attr(test, assert_instr("prfm pldl1keep", RW = _PREFETCH_READ, LOCALITY = _PREFETCH_LOCALITY3))]
#[cfg_attr(test, assert_instr("prfm pstl1strm", RW = _PREFETCH_WRITE, LOCALITY = _PREFETCH_LOCALITY0))]
#[cfg_attr(test, assert_instr("prfm pstl3keep", RW = _PREFETCH_WRITE, LOCALITY = _PREFETCH_LOCALITY1))]
#[cfg_attr(test, assert_instr("prfm pstl2keep", RW = _PREFETCH_WRITE, LOCALITY = _PREFETCH_LOCALITY2))]
#[cfg_attr(test, assert_instr("prfm pstl1keep", RW = _PREFETCH_WRITE, LOCALITY = _PREFETCH_LOCALITY3))]
#[rustc_legacy_const_generics(1, 2)]
// FIXME: 将其替换为标准的 ACLE __pld/__pldx/__pli/__plix 内部函数
pub unsafe fn _prefetch<const RW: i32, const LOCALITY: i32>(p: *const i8) {
    // 我们使用 `cache type` =1 (数据缓存) 的 `llvm.prefetch` 内部函数。
    static_assert_uimm_bits!(RW, 1);
    static_assert_uimm_bits!(LOCALITY, 2);
    prefetch(p, RW, LOCALITY, 1);
}