55//! It dispatches to the appropriate architecture-specific implementation
66//! based on the target architecture.
77
8+ #[ cfg( target_arch = "aarch64" ) ]
9+ use std:: arch:: is_aarch64_feature_detected;
10+
811#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" , target_arch = "aarch64" ) ) ]
912use crate :: algorithm;
1013
@@ -14,13 +17,14 @@ use crate::structs::CrcParams;
1417use crate :: structs:: { Width32 , Width64 } ;
1518
1619#[ cfg( target_arch = "aarch64" ) ]
17- use crate :: arch :: aarch64:: AArch64Ops ;
20+ use aarch64:: AArch64Ops ;
1821
1922#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
20- use crate :: arch :: x86:: X86Ops ;
23+ use x86:: X86Ops ;
2124
22- #[ cfg( all( target_arch = "x86_64" , feature = "vpclmulqdq" ) ) ]
23- use crate :: arch:: vpclmulqdq:: Vpclmulqdq512Ops ;
25+ #[ cfg( target_arch = "x86_64" ) ]
26+ #[ rustversion:: since( 1.89 ) ]
27+ use vpclmulqdq:: Vpclmulqdq512Ops ;
2428
2529mod aarch64;
2630mod software;
@@ -33,84 +37,118 @@ mod x86;
3337/// # Safety
3438/// May use native CPU features
3539#[ inline]
36- #[ cfg_attr(
37- any( target_arch = "x86" , target_arch = "x86_64" ) ,
38- target_feature( enable = "sse2,sse4.1,pclmulqdq" )
39- ) ]
40- #[ cfg_attr(
41- all( target_arch = "x86_64" , feature = "vpclmulqdq" ) ,
42- target_feature( enable = "avx2,vpclmulqdq,avx512f,avx512vl" )
43- ) ]
44- #[ cfg_attr( target_arch = "aarch64" , target_feature( enable = "neon,aes" ) ) ]
40+ #[ cfg( target_arch = "aarch64" ) ]
41+ #[ target_feature( enable = "neon,aes" ) ]
4542pub ( crate ) unsafe fn update ( state : u64 , bytes : & [ u8 ] , params : CrcParams ) -> u64 {
46- #[ cfg( target_arch = "aarch64" ) ]
47- {
48- let ops = AArch64Ops ;
43+ let ops = AArch64Ops ;
4944
50- match params. width {
51- 64 => algorithm:: update :: < AArch64Ops , Width64 > ( state, bytes, params, & ops) ,
52- 32 => {
53- algorithm:: update :: < AArch64Ops , Width32 > ( state as u32 , bytes, params, & ops) as u64
54- }
55- _ => panic ! ( "Unsupported CRC width: {}" , params. width) ,
56- }
45+ match params. width {
46+ 64 => algorithm:: update :: < AArch64Ops , Width64 > ( state, bytes, params, & ops) ,
47+ 32 => algorithm:: update :: < AArch64Ops , Width32 > ( state as u32 , bytes, params, & ops) as u64 ,
48+ _ => panic ! ( "Unsupported CRC width: {}" , params. width) ,
5749 }
50+ }
5851
59- #[ cfg( all( target_arch = "x86_64" , feature = "vpclmulqdq" ) ) ]
60- {
61- use std:: arch:: is_x86_feature_detected;
62-
63- if bytes. len ( ) >= 256 && is_x86_feature_detected ! ( "vpclmulqdq" ) {
64- let ops = Vpclmulqdq512Ops :: new ( ) ;
65-
66- return match params. width {
67- 64 => algorithm:: update :: < Vpclmulqdq512Ops , Width64 > ( state, bytes, params, & ops) ,
68- 32 => algorithm:: update :: < Vpclmulqdq512Ops , Width32 > (
69- state as u32 ,
70- bytes,
71- params,
72- & ops,
73- ) as u64 ,
74- _ => panic ! ( "Unsupported CRC width: {}" , params. width) ,
75- } ;
76- }
52+ #[ rustversion:: before( 1.89 ) ]
53+ #[ inline]
54+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
55+ #[ target_feature( enable = "sse2,sse4.1,pclmulqdq" ) ]
56+ pub ( crate ) unsafe fn update ( state : u64 , bytes : & [ u8 ] , params : CrcParams ) -> u64 {
57+ let ops = X86Ops ;
58+
59+ match params. width {
60+ 64 => algorithm:: update :: < X86Ops , Width64 > ( state, bytes, params, & ops) ,
61+ 32 => algorithm:: update :: < X86Ops , Width32 > ( state as u32 , bytes, params, & ops) as u64 ,
62+ _ => panic ! ( "Unsupported CRC width: {}" , params. width) ,
7763 }
64+ }
7865
79- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
80- {
81- let ops = X86Ops ;
66+ #[ rustversion:: since( 1.89 ) ]
67+ #[ inline]
68+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
69+ #[ target_feature( enable = "sse2,sse4.1,pclmulqdq" ) ]
70+ pub ( crate ) unsafe fn update ( state : u64 , bytes : & [ u8 ] , params : CrcParams ) -> u64 {
71+ use std:: arch:: is_x86_feature_detected;
72+
73+ if bytes. len ( ) >= 256 && is_x86_feature_detected ! ( "vpclmulqdq" ) {
74+ let ops = Vpclmulqdq512Ops :: new ( ) ;
8275
83- match params. width {
84- 64 => algorithm:: update :: < X86Ops , Width64 > ( state, bytes, params, & ops) ,
85- 32 => algorithm:: update :: < X86Ops , Width32 > ( state as u32 , bytes, params, & ops) as u64 ,
76+ return match params. width {
77+ 64 => algorithm:: update :: < Vpclmulqdq512Ops , Width64 > ( state, bytes, params, & ops) ,
78+ 32 => algorithm:: update :: < Vpclmulqdq512Ops , Width32 > ( state as u32 , bytes, params, & ops)
79+ as u64 ,
8680 _ => panic ! ( "Unsupported CRC width: {}" , params. width) ,
81+ } ;
82+ }
83+
84+ // fallback to the standard x86 SSE implementation
85+
86+ let ops = X86Ops ;
87+
88+ match params. width {
89+ 64 => algorithm:: update :: < X86Ops , Width64 > ( state, bytes, params, & ops) ,
90+ 32 => algorithm:: update :: < X86Ops , Width32 > ( state as u32 , bytes, params, & ops) as u64 ,
91+ _ => panic ! ( "Unsupported CRC width: {}" , params. width) ,
92+ }
93+ }
94+
95+ #[ inline]
96+ #[ cfg( all(
97+ not( target_arch = "x86" ) ,
98+ not( target_arch = "x86_64" ) ,
99+ not( target_arch = "aarch64" )
100+ ) ) ]
101+ pub ( crate ) unsafe fn update ( state : u64 , bytes : & [ u8 ] , params : CrcParams ) -> u64 {
102+ software:: update ( state, bytes, params)
103+ }
104+
105+ #[ rustversion:: before( 1.89 ) ]
106+ pub fn get_target ( ) -> String {
107+ #[ cfg( target_arch = "aarch64" ) ]
108+ {
109+ if is_aarch64_feature_detected ! ( "sha3" ) {
110+ return "aarch64-neon-eor3-pclmulqdq" . to_string ( ) ;
87111 }
112+
113+ "aarch64-neon-pclmulqdq" . to_string ( )
88114 }
89115
90- #[ cfg( not( any( target_arch = "x86" , target_arch = "x86_64" , target_arch = "aarch64" ) ) ) ]
91- return software:: update ( state, bytes, params) ;
116+ #[ allow( unreachable_code) ]
117+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
118+ return "x86-sse-pclmulqdq" . to_string ( ) ;
119+
120+ #[ cfg( not( any( target_arch = "aarch64" , target_arch = "x86" , target_arch = "x86_64" ) ) ) ]
121+ return "software-fallback-tables" . to_string ( ) ;
92122}
93123
124+ #[ rustversion:: since( 1.89 ) ]
94125pub fn get_target ( ) -> String {
95- #[ cfg( all( target_arch = "aarch64" , target_feature = "sha3" ) ) ]
96- return "internal-aarch64-neon-eor3" . to_string ( ) ;
126+ #[ cfg( target_arch = "aarch64" ) ]
127+ {
128+ if is_aarch64_feature_detected ! ( "sha3" ) {
129+ return "aarch64-neon-eor3-pclmulqdq" . to_string ( ) ;
130+ }
97131
98- # [ cfg ( all ( target_arch = "aarch64" , not ( target_feature = "sha3" ) ) ) ]
99- return "internal-aarch64-neon" . to_string ( ) ;
132+ "aarch64-neon-pclmulqdq" . to_string ( )
133+ }
100134
101- #[ cfg( all ( target_arch = "x86_64" , feature = "vpclmulqdq" ) ) ]
135+ #[ cfg( target_arch = "x86_64" ) ]
102136 {
103137 if is_x86_feature_detected ! ( "vpclmulqdq" ) {
104- return "internal-x86_64-avx512-vpclmulqdq" . to_string ( ) ;
138+ return "x86_64-avx512-vpclmulqdq" . to_string ( ) ;
139+ }
140+
141+ if is_x86_feature_detected ! ( "avx2" ) {
142+ return "x86_64-avx2-pclmulqdq" . to_string ( ) ;
105143 }
106144 }
107145
108146 #[ allow( unreachable_code) ]
109147 #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
110- return "internal- x86-sse-pclmulqdq" . to_string ( ) ;
148+ return "x86-sse-pclmulqdq" . to_string ( ) ;
111149
112150 #[ cfg( not( any( target_arch = "aarch64" , target_arch = "x86" , target_arch = "x86_64" ) ) ) ]
113- return "software-fallback" . to_string ( ) ;
151+ return "software-fallback-tables " . to_string ( ) ;
114152}
115153
116154#[ cfg( test) ]
0 commit comments