@@ -100,3 +100,150 @@ impl BitMask for NeonBits {
100100 Self ( self . 0 & u64:: MAX >> ( n * 4 ) )
101101 }
102102}
103+
104+ #[ cfg( target_feature = "sve2" ) ]
105+ #[ derive( Debug , Clone , Copy ) ]
106+ pub struct SveBits ( usize ) ;
107+
108+ #[ cfg( target_feature = "sve2" ) ]
109+ impl SveBits {
110+ #[ inline( always) ]
111+ pub fn new ( u : usize ) -> Self {
112+ Self ( u)
113+ }
114+ }
115+
116+ #[ cfg( target_feature = "sve2" ) ]
117+ impl BitMask for SveBits {
118+ const LEN : usize = 16 ;
119+
120+ #[ inline( always) ]
121+ fn first_offset ( & self ) -> usize {
122+ self . 0
123+ }
124+
125+ #[ inline( always) ]
126+ fn before ( & self , rhs : & Self ) -> bool {
127+ self . 0 < rhs. 0
128+ }
129+
130+ #[ inline( always) ]
131+ fn all_zero ( & self ) -> bool {
132+ self . 0 == 16
133+ }
134+
135+ #[ inline( always) ]
136+ fn as_little_endian ( & self ) -> Self {
137+ * self
138+ }
139+
140+ #[ inline( always) ]
141+ fn clear_high_bits ( & self , n : usize ) -> Self {
142+ let nb = 16 - n;
143+
144+ if self . 0 >= nb {
145+ Self ( 16 )
146+ } else {
147+ * self
148+ }
149+ }
150+ }
151+
152+ #[ cfg( test) ]
153+ #[ cfg( target_feature = "sve2" ) ]
154+ #[ cfg( target_arch = "aarch64" ) ]
155+ mod tests {
156+ use super :: * ;
157+
158+ #[ derive( Debug ) ]
159+ struct SVEStringBlock {
160+ bs_bits : SveBits ,
161+ quote_bits : SveBits ,
162+ unescaped_bits : SveBits ,
163+ }
164+
165+ impl SVEStringBlock {
166+ #[ inline( always) ]
167+ pub fn new_sve ( ptr : * const u8 ) -> Self {
168+ let ( q, bs, un) : ( u64 , u64 , u64 ) ;
169+
170+ unsafe {
171+ core:: arch:: asm!(
172+ "ptrue p0.b, vl16" ,
173+ "ld1b {{z0.b}}, p0/z, [{ptr}]" ,
174+
175+ // "
176+ "mov z1.b, #34" ,
177+ "match p1.b, p0/z, z0.b, z1.b" ,
178+ "brkb p1.b, p0/z, p1.b" ,
179+ "cntp {q_idx}, p0, p1.b" ,
180+
181+ // /
182+ "mov z1.b, #92" ,
183+ "match p1.b, p0/z, z0.b, z1.b" ,
184+ "brkb p1.b, p0/z, p1.b" ,
185+ "cntp {bs_idx}, p0, p1.b" ,
186+
187+ // ascii control characters
188+ "mov z1.b, #31" ,
189+ "cmple p1.b, p0/z, z0.b, z1.b" ,
190+ "brkb p1.b, p0/z, p1.b" ,
191+ "cntp {un_idx}, p0, p1.b" ,
192+
193+ ptr = in( reg) ptr,
194+ q_idx = out( reg) q,
195+ bs_idx = out( reg) bs,
196+ un_idx = out( reg) un,
197+ out( "z0" ) _, out( "z1" ) _,
198+ out( "p0" ) _, out( "p1" ) _,
199+ ) ;
200+ }
201+
202+ Self {
203+ quote_bits : SveBits :: new ( q as usize ) ,
204+ bs_bits : SveBits :: new ( bs as usize ) ,
205+ unescaped_bits : SveBits :: new ( un as usize ) ,
206+ }
207+ }
208+ }
209+
210+ impl SVEStringBlock {
211+ #[ inline( always) ]
212+ pub fn has_unescaped ( & self ) -> bool {
213+ self . unescaped_bits . 0 < self . quote_bits . 0
214+ }
215+
216+ #[ inline( always) ]
217+ pub fn has_quote_first ( & self ) -> bool {
218+ self . quote_bits . 0 < self . bs_bits . 0 && !self . has_unescaped ( )
219+ }
220+
221+ #[ inline( always) ]
222+ pub fn has_backslash ( & self ) -> bool {
223+ self . bs_bits . 0 < self . quote_bits . 0
224+ }
225+
226+ #[ inline( always) ]
227+ pub fn quote_index ( & self ) -> usize {
228+ self . quote_bits . 0
229+ }
230+ }
231+
232+ #[ test]
233+ fn test_sve_bits ( ) {
234+ let s = b"\" \\ \t \n " ;
235+ let block = SVEStringBlock :: new_sve ( s. as_ptr ( ) ) ;
236+ assert_eq ! ( block. quote_bits. 0 , 0 ) ;
237+ assert_eq ! ( block. bs_bits. 0 , 1 ) ;
238+ assert_eq ! ( block. unescaped_bits. 0 , 2 ) ;
239+
240+ let block = SVEStringBlock :: new_sve ( unsafe {
241+ {
242+ s. as_ptr ( ) . add ( 2 )
243+ }
244+ } ) ;
245+ assert_eq ! ( block. quote_bits. 0 , 16 ) ;
246+ assert_eq ! ( block. bs_bits. 0 , 16 ) ;
247+ assert_eq ! ( block. unescaped_bits. 0 , 0 ) ;
248+ }
249+ }
0 commit comments