@@ -4703,34 +4703,57 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
4703
4703
#ifdef IMPL_EXECUTE_LOOP
4704
4704
VERIFY_IS_MATCH_STATE (src , "bs_match_string" );
4705
4705
4706
- if (bits % 8 != 0 ) {
4707
- TRACE ("bs_match_string: Unsupported bits size (must be evenly divisible by 8). bits=%u\n" , (unsigned ) bits );
4708
- RAISE_ERROR (UNSUPPORTED_ATOM );
4709
- }
4710
- avm_int_t bytes = bits / 8 ;
4711
4706
avm_int_t bs_offset = term_get_match_state_offset (src );
4712
4707
term bs_bin = term_get_match_state_binary (src );
4713
4708
4714
- if (bs_offset % 8 != 0 ) {
4715
- TRACE ("bs_match_string: Unsupported offset (must be evenly divisible by 8). bs_offset=%li\n" , bs_offset );
4716
- RAISE_ERROR (UNSUPPORTED_ATOM );
4717
- }
4718
- avm_int_t byte_offset = bs_offset / 8 ;
4719
-
4720
- TRACE ("bs_match_string/4, fail=%u src=%p bits=%u offset=%u\n" , (unsigned ) fail , (void * ) src , (unsigned ) bits , (unsigned ) offset );
4721
-
4722
4709
size_t remaining = 0 ;
4723
4710
const uint8_t * str = module_get_str (mod , offset , & remaining );
4724
4711
if (IS_NULL_PTR (str )) {
4725
4712
TRACE ("bs_match_string: Bad offset in strings table.\n" );
4726
4713
RAISE_ERROR (BADARG_ATOM );
4727
4714
}
4728
- if (memcmp (term_binary_data (bs_bin ) + byte_offset , str , MIN (remaining , (unsigned int ) bytes )) != 0 ) {
4729
- TRACE ("bs_match_string: failed to match\n" );
4730
- JUMP_TO_ADDRESS (mod -> labels [fail ]);
4715
+
4716
+ TRACE ("bs_match_string/4, fail=%u src=%p bits=%u offset=%u\n" , (unsigned ) fail , (void * ) src , (unsigned ) bits , (unsigned ) offset );
4717
+
4718
+ if (bits % 8 == 0 && bs_offset % 8 == 0 ) {
4719
+ avm_int_t bytes = bits / 8 ;
4720
+ avm_int_t byte_offset = bs_offset / 8 ;
4721
+
4722
+ if (memcmp (term_binary_data (bs_bin ) + byte_offset , str , MIN (remaining , (unsigned int ) bytes )) != 0 ) {
4723
+ TRACE ("bs_match_string: failed to match\n" );
4724
+ JUMP_TO_ADDRESS (mod -> labels [fail ]);
4725
+ }
4731
4726
} else {
4732
- term_set_match_state_offset (src , bs_offset + bits );
4727
+ // Compare unaligned bits
4728
+ const uint8_t * bs_str = (const uint8_t * ) term_binary_data (bs_bin ) + (bs_offset / 8 );
4729
+ uint8_t bin_bit_offset = 7 - (bs_offset - (8 * (bs_offset / 8 )));
4730
+ uint8_t str_bit_offset = 7 ;
4731
+ size_t remaining_bits = bits ;
4732
+ while (remaining_bits > 0 ) {
4733
+ uint8_t str_ch = * str ;
4734
+ uint8_t bin_ch = * bs_str ;
4735
+ uint8_t str_ch_bit = (str_ch >> str_bit_offset ) & 1 ;
4736
+ uint8_t bin_ch_bit = (bin_ch >> bin_bit_offset ) & 1 ;
4737
+ if (str_ch_bit ^ bin_ch_bit ) {
4738
+ TRACE ("bs_match_string: failed to match\n" );
4739
+ JUMP_TO_ADDRESS (mod -> labels [fail ]);
4740
+ }
4741
+ if (str_bit_offset ) {
4742
+ str_bit_offset -- ;
4743
+ } else {
4744
+ str_bit_offset = 7 ;
4745
+ str ++ ;
4746
+ }
4747
+ if (bin_bit_offset ) {
4748
+ bin_bit_offset -- ;
4749
+ } else {
4750
+ bin_bit_offset = 7 ;
4751
+ bs_str ++ ;
4752
+ }
4753
+ remaining_bits -- ;
4754
+ }
4733
4755
}
4756
+ term_set_match_state_offset (src , bs_offset + bits );
4734
4757
#endif
4735
4758
break ;
4736
4759
}
0 commit comments