Skip to content

Commit 586801d

Browse files
authored
Add HWCAP2 support for AArch64 Linux. (rust-lang#1335)
1 parent b9cf2d7 commit 586801d

File tree

8 files changed

+211
-101
lines changed

8 files changed

+211
-101
lines changed

crates/core_arch/src/arm_shared/neon/mod.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12461,30 +12461,30 @@ mod tests {
1246112461
}
1246212462
#[simd_test(enable = "neon,i8mm")]
1246312463
unsafe fn test_vmmlaq_s32() {
12464-
let a: i32x4 = i32x4::new(1, 3, 4, 9);
12465-
let b: i8x16 = i8x16::new(1, 21, 31, 14, 5, 6, 17, 8, 9, 13, 15, 12, 13, 19, 20, 16);
12466-
let c: i8x16 = i8x16::new(12, 22, 3, 4, 5, 56, 7, 8, 91, 10, 11, 15, 13, 14, 17, 16);
12467-
let e: i32x4 = i32x4::new(1, 2, 3, 4);
12464+
let a = i32x4::new(1, 3, 4, -0x10000);
12465+
let b = i8x16::new(1, 21, 31, 14, 5, 6, -128, 8, 9, 13, 15, 12, 13, -1, 20, 16);
12466+
let c = i8x16::new(12, 22, 3, 4, -1, 56, 7, 8, 91, 10, -128, 15, 13, 14, 17, 16);
12467+
let e = i32x4::new(123, -5353, 690, -65576);
1246812468
let r: i32x4 = transmute(vmmlaq_s32(transmute(a), transmute(b), transmute(c)));
1246912469
assert_eq!(r, e);
1247012470
}
1247112471

1247212472
#[simd_test(enable = "neon,i8mm")]
1247312473
unsafe fn test_vmmlaq_u32() {
12474-
let a: u32x4 = u32x4::new(1, 3, 4, 9);
12475-
let b: i8x16 = i8x16::new(1, 21, 31, 14, 5, 6, 17, 8, 9, 13, 15, 12, 13, 19, 20, 16);
12476-
let c: i8x16 = i8x16::new(12, 22, 3, 4, 5, 56, 7, 8, 91, 10, 11, 15, 13, 14, 17, 16);
12477-
let e: u32x4 = u32x4::new(1, 2, 3, 4);
12474+
let a = u32x4::new(1, 3, 4, 0xffff0000);
12475+
let b = u8x16::new(1, 21, 31, 14, 5, 6, 128, 8, 9, 13, 15, 12, 13, 255, 20, 16);
12476+
let c = u8x16::new(12, 22, 3, 4, 255, 56, 7, 8, 91, 10, 128, 15, 13, 14, 17, 16);
12477+
let e = u32x4::new(3195, 6935, 18354, 4294909144);
1247812478
let r: u32x4 = transmute(vmmlaq_u32(transmute(a), transmute(b), transmute(c)));
1247912479
assert_eq!(r, e);
1248012480
}
1248112481

1248212482
#[simd_test(enable = "neon,i8mm")]
1248312483
unsafe fn test_vusmmlaq_s32() {
12484-
let a: i32x4 = i32x4::new(1, 3, 4, 9);
12485-
let b: i8x16 = i8x16::new(1, 21, 31, 14, 5, 6, 17, 8, 9, 13, 15, 12, 13, 19, 20, 16);
12486-
let c: i8x16 = i8x16::new(12, 22, 3, 4, 5, 56, 7, 8, 91, 10, 11, 15, 13, 14, 17, 16);
12487-
let e: i32x4 = i32x4::new(1, 2, 3, 4);
12484+
let a = i32x4::new(1, 3, 4, -0x10000);
12485+
let b = u8x16::new(1, 21, 31, 14, 5, 6, 128, 8, 9, 13, 15, 12, 13, 255, 20, 16);
12486+
let c = i8x16::new(12, 22, 3, 4, -1, 56, 7, 8, 91, 10, -128, 15, 13, 14, 17, 16);
12487+
let e = i32x4::new(1915, -1001, 15026, -61992);
1248812488
let r: i32x4 = transmute(vusmmlaq_s32(transmute(a), transmute(b), transmute(c)));
1248912489
assert_eq!(r, e);
1249012490
}

crates/std_detect/src/detect/os/linux/aarch64.rs

Lines changed: 157 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -23,58 +23,62 @@ pub(crate) fn detect_features() -> cache::Initializer {
2323
/// The names match those used for cpuinfo.
2424
///
2525
/// [hwcap]: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
26+
#[derive(Debug, Default, PartialEq)]
2627
struct AtHwcap {
27-
fp: bool, // 0
28-
asimd: bool, // 1
29-
// evtstrm: bool, // 2 No LLVM support
30-
aes: bool, // 3
31-
pmull: bool, // 4
32-
sha1: bool, // 5
33-
sha2: bool, // 6
34-
crc32: bool, // 7
35-
atomics: bool, // 8
36-
fphp: bool, // 9
37-
asimdhp: bool, // 10
38-
// cpuid: bool, // 11 No LLVM support
39-
asimdrdm: bool, // 12
40-
jscvt: bool, // 13
41-
fcma: bool, // 14
42-
lrcpc: bool, // 15
43-
dcpop: bool, // 16
44-
sha3: bool, // 17
45-
sm3: bool, // 18
46-
sm4: bool, // 19
47-
asimddp: bool, // 20
48-
sha512: bool, // 21
49-
sve: bool, // 22
50-
fhm: bool, // 23
51-
dit: bool, // 24
52-
uscat: bool, // 25
53-
ilrcpc: bool, // 26
54-
flagm: bool, // 27
55-
ssbs: bool, // 28
56-
sb: bool, // 29
57-
paca: bool, // 30
58-
pacg: bool, // 31
59-
dcpodp: bool, // 32
60-
sve2: bool, // 33
61-
sveaes: bool, // 34
62-
// svepmull: bool, // 35 No LLVM support
63-
svebitperm: bool, // 36
64-
svesha3: bool, // 37
65-
svesm4: bool, // 38
66-
// flagm2: bool, // 39 No LLVM support
67-
frint: bool, // 40
68-
// svei8mm: bool, // 41 See i8mm feature
69-
svef32mm: bool, // 42
70-
svef64mm: bool, // 43
71-
// svebf16: bool, // 44 See bf16 feature
72-
i8mm: bool, // 45
73-
bf16: bool, // 46
74-
// dgh: bool, // 47 No LLVM support
75-
rng: bool, // 48
76-
bti: bool, // 49
77-
mte: bool, // 50
28+
// AT_HWCAP
29+
fp: bool,
30+
asimd: bool,
31+
// evtstrm: No LLVM support.
32+
aes: bool,
33+
pmull: bool,
34+
sha1: bool,
35+
sha2: bool,
36+
crc32: bool,
37+
atomics: bool,
38+
fphp: bool,
39+
asimdhp: bool,
40+
// cpuid: No LLVM support.
41+
asimdrdm: bool,
42+
jscvt: bool,
43+
fcma: bool,
44+
lrcpc: bool,
45+
dcpop: bool,
46+
sha3: bool,
47+
sm3: bool,
48+
sm4: bool,
49+
asimddp: bool,
50+
sha512: bool,
51+
sve: bool,
52+
fhm: bool,
53+
dit: bool,
54+
uscat: bool,
55+
ilrcpc: bool,
56+
flagm: bool,
57+
ssbs: bool,
58+
sb: bool,
59+
paca: bool,
60+
pacg: bool,
61+
62+
// AT_HWCAP2
63+
dcpodp: bool,
64+
sve2: bool,
65+
sveaes: bool,
66+
// svepmull: No LLVM support.
67+
svebitperm: bool,
68+
svesha3: bool,
69+
svesm4: bool,
70+
// flagm2: No LLVM support.
71+
frint: bool,
72+
// svei8mm: See i8mm feature.
73+
svef32mm: bool,
74+
svef64mm: bool,
75+
// svebf16: See bf16 feature.
76+
i8mm: bool,
77+
bf16: bool,
78+
// dgh: No LLVM support.
79+
rng: bool,
80+
bti: bool,
81+
mte: bool,
7882
}
7983

8084
impl From<auxvec::AuxVec> for AtHwcap {
@@ -113,25 +117,25 @@ impl From<auxvec::AuxVec> for AtHwcap {
113117
sb: bit::test(auxv.hwcap, 29),
114118
paca: bit::test(auxv.hwcap, 30),
115119
pacg: bit::test(auxv.hwcap, 31),
116-
dcpodp: bit::test(auxv.hwcap, 32),
117-
sve2: bit::test(auxv.hwcap, 33),
118-
sveaes: bit::test(auxv.hwcap, 34),
119-
// svepmull: bit::test(auxv.hwcap, 35),
120-
svebitperm: bit::test(auxv.hwcap, 36),
121-
svesha3: bit::test(auxv.hwcap, 37),
122-
svesm4: bit::test(auxv.hwcap, 38),
123-
// flagm2: bit::test(auxv.hwcap, 39),
124-
frint: bit::test(auxv.hwcap, 40),
125-
// svei8mm: bit::test(auxv.hwcap, 41),
126-
svef32mm: bit::test(auxv.hwcap, 42),
127-
svef64mm: bit::test(auxv.hwcap, 43),
128-
// svebf16: bit::test(auxv.hwcap, 44),
129-
i8mm: bit::test(auxv.hwcap, 45),
130-
bf16: bit::test(auxv.hwcap, 46),
131-
// dgh: bit::test(auxv.hwcap, 47),
132-
rng: bit::test(auxv.hwcap, 48),
133-
bti: bit::test(auxv.hwcap, 49),
134-
mte: bit::test(auxv.hwcap, 50),
120+
dcpodp: bit::test(auxv.hwcap2, 0),
121+
sve2: bit::test(auxv.hwcap2, 1),
122+
sveaes: bit::test(auxv.hwcap2, 2),
123+
// svepmull: bit::test(auxv.hwcap2, 3),
124+
svebitperm: bit::test(auxv.hwcap2, 4),
125+
svesha3: bit::test(auxv.hwcap2, 5),
126+
svesm4: bit::test(auxv.hwcap2, 6),
127+
// flagm2: bit::test(auxv.hwcap2, 7),
128+
frint: bit::test(auxv.hwcap2, 8),
129+
// svei8mm: bit::test(auxv.hwcap2, 9),
130+
svef32mm: bit::test(auxv.hwcap2, 10),
131+
svef64mm: bit::test(auxv.hwcap2, 11),
132+
// svebf16: bit::test(auxv.hwcap2, 12),
133+
i8mm: bit::test(auxv.hwcap2, 13),
134+
bf16: bit::test(auxv.hwcap2, 14),
135+
// dgh: bit::test(auxv.hwcap2, 15),
136+
rng: bit::test(auxv.hwcap2, 16),
137+
bti: bit::test(auxv.hwcap2, 17),
138+
mte: bit::test(auxv.hwcap2, 18),
135139
}
136140
}
137141
}
@@ -288,3 +292,86 @@ impl AtHwcap {
288292
value
289293
}
290294
}
295+
296+
#[cfg(test)]
297+
mod tests {
298+
use super::*;
299+
300+
#[cfg(feature = "std_detect_file_io")]
301+
mod auxv_from_file {
302+
use super::auxvec::auxv_from_file;
303+
use super::*;
304+
// The baseline hwcaps used in the (artificial) auxv test files.
305+
fn baseline_hwcaps() -> AtHwcap {
306+
AtHwcap {
307+
fp: true,
308+
asimd: true,
309+
aes: true,
310+
pmull: true,
311+
sha1: true,
312+
sha2: true,
313+
crc32: true,
314+
atomics: true,
315+
fphp: true,
316+
asimdhp: true,
317+
asimdrdm: true,
318+
lrcpc: true,
319+
dcpop: true,
320+
asimddp: true,
321+
ssbs: true,
322+
..AtHwcap::default()
323+
}
324+
}
325+
326+
#[test]
327+
fn linux_empty_hwcap2_aarch64() {
328+
let file = concat!(
329+
env!("CARGO_MANIFEST_DIR"),
330+
"/src/detect/test_data/linux-empty-hwcap2-aarch64.auxv"
331+
);
332+
println!("file: {}", file);
333+
let v = auxv_from_file(file).unwrap();
334+
println!("HWCAP : 0x{:0x}", v.hwcap);
335+
println!("HWCAP2: 0x{:0x}", v.hwcap2);
336+
assert_eq!(AtHwcap::from(v), baseline_hwcaps());
337+
}
338+
#[test]
339+
fn linux_no_hwcap2_aarch64() {
340+
let file = concat!(
341+
env!("CARGO_MANIFEST_DIR"),
342+
"/src/detect/test_data/linux-no-hwcap2-aarch64.auxv"
343+
);
344+
println!("file: {}", file);
345+
let v = auxv_from_file(file).unwrap();
346+
println!("HWCAP : 0x{:0x}", v.hwcap);
347+
println!("HWCAP2: 0x{:0x}", v.hwcap2);
348+
assert_eq!(AtHwcap::from(v), baseline_hwcaps());
349+
}
350+
#[test]
351+
fn linux_hwcap2_aarch64() {
352+
let file = concat!(
353+
env!("CARGO_MANIFEST_DIR"),
354+
"/src/detect/test_data/linux-hwcap2-aarch64.auxv"
355+
);
356+
println!("file: {}", file);
357+
let v = auxv_from_file(file).unwrap();
358+
println!("HWCAP : 0x{:0x}", v.hwcap);
359+
println!("HWCAP2: 0x{:0x}", v.hwcap2);
360+
assert_eq!(
361+
AtHwcap::from(v),
362+
AtHwcap {
363+
// Some other HWCAP bits.
364+
paca: true,
365+
pacg: true,
366+
// HWCAP2-only bits.
367+
dcpodp: true,
368+
frint: true,
369+
rng: true,
370+
bti: true,
371+
mte: true,
372+
..baseline_hwcaps()
373+
}
374+
);
375+
}
376+
}
377+
}

0 commit comments

Comments
 (0)