/* Mask off bits. LoongArch version. Copyright (C) 2022 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see . */ #ifndef _STRING_MASKOFF_H #define _STRING_MASKOFF_H 1 #include #include #include #include /* Provide a mask based on the pointer alignment that sets up non-zero bytes before the beginning of the word. It is used to mask off undesirable bits from an aligned read from an unaligned pointer. For instance, on a 64 bits machine with a pointer alignment of 3 the function returns 0x0000000000ffffff for LE and 0xffffff0000000000 (meaning to mask off the initial 3 bytes). */ static inline op_t create_mask (uintptr_t i) { i = i % sizeof (op_t); return ~(((op_t)-1) << (i * CHAR_BIT)); } /* Setup an word with each byte being c_in. For instance, on a 64 bits machine with input as 0xce the functions returns 0xcececececececece. */ static inline op_t repeat_bytes (unsigned char c_in) { op_t r = c_in * 0x01010101; _Static_assert (sizeof (op_t) == 4 || sizeof (op_t) == 8, "unsupported op_t size"); if (sizeof (op_t) == 8) asm ("bstrins.d\t%0, %0, 63, 32" : "+r" (r)); return r; } /* Based on mask created by 'create_mask', mask off the high bit of each byte in the mask. It is used to mask off undesirable bits from an aligned read from an unaligned pointer, and also taking care to avoid match possible bytes meant to be matched. For instance, on a 64 bits machine with a mask created from a pointer with an alignment of 3 (0x0000000000ffffff) the function returns 0x7f7f7f0000000000 for BE and 0x00000000007f7f7f for LE. */ static inline op_t highbit_mask (op_t m) { return m & repeat_bytes (0x7f); } /* Return the address of the op_t word containing the address P. For instance on address 0x0011223344556677 and op_t with size of 8, it returns 0x0011223344556670. */ static inline op_t * word_containing (char const *p) { _Static_assert (sizeof (op_t) == 4 || sizeof (op_t) == 8, "unsupported op_t size"); if (sizeof (op_t) == 8) asm ("bstrins.d\t%0, $zero, 2, 0" : "+r" (p)); else asm ("bstrins.d\t%0, $zero, 1, 0" : "+r" (p)); return (op_t *) p; } #endif /* _STRING_MASKOFF_H */