/* 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 */