12 #ifdef OT_PLATFORM_RV32
13 #define OT_PREFIX_IF_NOT_RV32(name) name
15 #define OT_PREFIX_IF_NOT_RV32(name) ot_##name
18 static size_t compute_num_leading_bytes(
const void *left,
const void *right,
20 if (len <
alignof(uint32_t)) {
25 if (right == NULL || left_ahead == right_ahead) {
26 return (4 - left_ahead) & 0x3;
46 static void compute_alignment(
const void *left,
const void *right,
size_t len,
47 size_t *out_body_offset,
48 size_t *out_tail_offset) {
49 const size_t num_leading_bytes = compute_num_leading_bytes(left, right, len);
50 *out_body_offset = num_leading_bytes;
52 const size_t num_words = (len - num_leading_bytes) /
sizeof(uint32_t);
53 *out_tail_offset = num_leading_bytes + num_words *
sizeof(uint32_t);
56 static uint32_t repeat_byte_to_u32(uint8_t
byte) {
57 const uint32_t word = byte;
58 return word << 24 | word << 16 | word << 8 | word;
61 void *OT_PREFIX_IF_NOT_RV32(
memcpy)(
void *restrict dest,
62 const void *restrict src,
size_t len) {
63 if (dest == NULL || src == NULL) {
66 unsigned char *dest8 = (
unsigned char *)dest;
67 const unsigned char *src8 = (
const unsigned char *)src;
68 size_t body_offset, tail_offset;
69 compute_alignment(dest, src, len, &body_offset, &tail_offset);
71 for (; i < body_offset; ++i) {
74 for (; i < tail_offset; i +=
sizeof(uint32_t)) {
75 uint32_t word =
read_32(&src8[i]);
78 for (; i < len; ++i) {
84 void *OT_PREFIX_IF_NOT_RV32(
memset)(
void *dest,
int value,
size_t len) {
85 unsigned char *dest8 = (
unsigned char *)dest;
86 const uint8_t value8 = (uint8_t)value;
88 size_t body_offset, tail_offset;
89 compute_alignment(dest, NULL, len, &body_offset, &tail_offset);
91 for (; i < body_offset; ++i) {
94 const uint32_t value32 = repeat_byte_to_u32(value8);
95 for (; i < tail_offset; i +=
sizeof(uint32_t)) {
98 for (; i < len; ++i) {
110 int OT_PREFIX_IF_NOT_RV32(
memcmp)(
const void *lhs,
const void *rhs,
112 const unsigned char *lhs8 = (
const unsigned char *)lhs;
113 const unsigned char *rhs8 = (
const unsigned char *)rhs;
114 size_t body_offset, tail_offset;
115 compute_alignment(lhs, rhs, len, &body_offset, &tail_offset);
117 for (; i < body_offset; ++i) {
118 if (lhs8[i] < rhs8[i]) {
120 }
else if (lhs8[i] > rhs8[i]) {
124 for (; i < tail_offset; i +=
sizeof(uint32_t)) {
125 #if OT_BUILD_FOR_STATIC_ANALYZER
126 assert(&lhs8[i] != NULL);
127 assert(&rhs8[i] != NULL);
129 uint32_t word_left = __builtin_bswap32(
read_32(&lhs8[i]));
130 uint32_t word_right = __builtin_bswap32(
read_32(&rhs8[i]));
131 static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__,
132 "memcmp assumes that the system is little endian.");
133 if (word_left < word_right) {
135 }
else if (word_left > word_right) {
139 for (; i < len; ++i) {
140 if (lhs8[i] < rhs8[i]) {
142 }
else if (lhs8[i] > rhs8[i]) {
149 int memrcmp(
const void *lhs,
const void *rhs,
size_t len) {
150 const unsigned char *lhs8 = (
const unsigned char *)lhs;
151 const unsigned char *rhs8 = (
const unsigned char *)rhs;
152 size_t body_offset, tail_offset;
153 compute_alignment(lhs, rhs, len, &body_offset, &tail_offset);
155 for (; end > tail_offset; --end) {
156 const size_t i = end - 1;
157 if (lhs8[i] < rhs8[i]) {
159 }
else if (lhs8[i] > rhs8[i]) {
163 for (; end > body_offset; end -=
sizeof(uint32_t)) {
164 const size_t i = end -
sizeof(uint32_t);
165 #if OT_BUILD_FOR_STATIC_ANALYZER
166 assert(&lhs8[i] != NULL);
167 assert(&rhs8[i] != NULL);
169 uint32_t word_left =
read_32(&lhs8[i]);
170 uint32_t word_right =
read_32(&rhs8[i]);
171 static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__,
172 "memrcmp assumes that the system is little endian.");
173 if (word_left < word_right) {
175 }
else if (word_left > word_right) {
179 for (; end > 0; --end) {
180 const size_t i = end - 1;
181 if (lhs8[i] < rhs8[i]) {
183 }
else if (lhs8[i] > rhs8[i]) {
190 void *OT_PREFIX_IF_NOT_RV32(
memchr)(
const void *ptr,
int value,
size_t len) {
191 const unsigned char *ptr8 = (
const unsigned char *)ptr;
192 const uint8_t value8 = (uint8_t)value;
194 size_t body_offset, tail_offset;
195 compute_alignment(ptr, NULL, len, &body_offset, &tail_offset);
197 for (; i < body_offset; ++i) {
198 if (ptr8[i] == value8) {
199 return (
void *)&ptr8[i];
202 const uint32_t value32 = repeat_byte_to_u32(value8);
203 for (; i < tail_offset; i +=
sizeof(uint32_t)) {
204 uint32_t word =
read_32(&ptr8[i]);
205 uint32_t bits_eq = ~(word ^ value32);
206 static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__,
207 "memchr assumes that the system is little endian.");
208 if ((bits_eq & UINT8_MAX) == UINT8_MAX) {
209 return (
void *)&ptr8[i];
211 if (((bits_eq >> 8) & UINT8_MAX) == UINT8_MAX) {
212 return (
void *)&ptr8[i + 1];
214 if (((bits_eq >> 16) & UINT8_MAX) == UINT8_MAX) {
215 return (
void *)&ptr8[i + 2];
217 if (((bits_eq >> 24) & UINT8_MAX) == UINT8_MAX) {
218 return (
void *)&ptr8[i + 3];
221 for (; i < len; ++i) {
222 if (ptr8[i] == value8) {
223 return (
void *)&ptr8[i];
229 void *OT_PREFIX_IF_NOT_RV32(
memrchr)(
const void *ptr,
int value,
size_t len) {
230 const unsigned char *ptr8 = (
const unsigned char *)ptr;
231 const uint8_t value8 = (uint8_t)value;
233 size_t body_offset, tail_offset;
234 compute_alignment(ptr, NULL, len, &body_offset, &tail_offset);
237 for (; end > tail_offset; --end) {
238 const size_t i = end - 1;
239 if (ptr8[i] == value8) {
240 return (
void *)&ptr8[i];
243 const uint32_t value32 = repeat_byte_to_u32(value8);
244 for (; end > body_offset; end -=
sizeof(uint32_t)) {
245 const size_t i = end -
sizeof(uint32_t);
246 uint32_t word =
read_32(&ptr8[i]);
247 uint32_t bits_eq = ~(word ^ value32);
248 static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__,
249 "memrchr assumes that the system is little endian.");
250 if (((bits_eq >> 24) & UINT8_MAX) == UINT8_MAX) {
251 return (
void *)&ptr8[i + 3];
253 if (((bits_eq >> 16) & UINT8_MAX) == UINT8_MAX) {
254 return (
void *)&ptr8[i + 2];
256 if (((bits_eq >> 8) & UINT8_MAX) == UINT8_MAX) {
257 return (
void *)&ptr8[i + 1];
259 if ((bits_eq & UINT8_MAX) == UINT8_MAX) {
260 return (
void *)&ptr8[i];
263 for (; end > 0; --end) {
264 const size_t i = end - 1;
265 if (ptr8[i] == value8) {
266 return (
void *)&ptr8[i];
276 extern uint32_t
read_32(
const void *);
277 extern void write_32(uint32_t,
void *);
278 extern uint64_t
read_64(
const void *);
279 extern void write_64(uint64_t,
void *);
281 #undef OT_PREFIX_IF_NOT_RV32