/* https://bugs.kde.org/show_bug.cgi?id=309921 */
#define _XOPEN_SOURCE 600 /* for posix_memalign() */
#include "../../memcheck.h"
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
/* Exercise pcmpistri instruction in a realistic way. */
int aligned_strlen(const char *const s)
{
assert(((unsigned long)s & 0x0F) == 0);
const char *p = s;
/* volatile asm and "memory" clobber are needed here, since we
access memory in ways we cannot describe to GCC. */
__asm__ __volatile__ ("\n1:\n"
"\tmovdqa (%0),%%xmm6\n"
"\tpcmpistri $0x3a,%%xmm6,%%xmm6\n"
"\tjc 2f\n"
"\tadd $0x10,%0\n"
"\tjmp 1b\n"
"2:\n"
"\tadd %%rcx,%0\n"
: "=p" (p) : "0" (p) : "xmm6", "rcx", "cc", "memory");
return p-s;
}
/* Compute strlen(s). Arrange for result to be valid or invalid
according to second argument. */
int test_strlen(const char *const s, int valid)
{
/* len = length of string including trailing null */
const size_t len = strlen(s) + 1;
const size_t roundup = ((len+15)/16)*16;
int result = -1;
void *space;
posix_memalign(&space, 16, roundup);
memset(space, 'x', roundup);
memcpy(space, s, len);
const char *const s_copy = space;
const unsigned char ff = 0xFF;
if (valid) {
/* Mark all bytes beyond the null as invalid. */
size_t i;
for (i=len ; i < roundup ; ++i)
(void)VALGRIND_SET_VBITS(&s_copy[i], &ff, 1);
}
else {
/* Mark the null byte itself as invalid. */
assert(len > 0);
(void)VALGRIND_SET_VBITS(&s_copy[len-1], &ff, 1);
}
result = aligned_strlen(s_copy);
free(space);
return result;
}
void doit(const char *const s)
{
printf("strlen(\"%s\")=%d\n", s, test_strlen(s, 1));
fprintf(stderr, "strlen(\"%s\")=%s\n", s,
test_strlen(s, 0) ? "true" : "false");
}
int main(int argc, char *argv[])
{
doit("");
doit("a");
doit("ab");
doit("abc");
doit("abcd");
doit("abcde");
doit("abcdef");
doit("abcdefg");
/* 8 */
doit("abcdefgh");
doit("abcdefghi");
doit("abcdefghij");
doit("abcdefghijk");
doit("abcdefghijkl");
doit("abcdefghijklm");
doit("abcdefghijklmn");
doit("abcdefghijklmno");
/* 16 */
doit("abcdefghijklmnop");
doit("abcdefghijklmnopq");
doit("abcdefghijklmnopqr");
doit("abcdefghijklmnopqrs");
doit("abcdefghijklmnopqrst");
doit("abcdefghijklmnopqrstu");
doit("abcdefghijklmnopqrstuv");
doit("abcdefghijklmnopqrstuvw");
doit("abcdefghijklmnopqrstuwvx");
doit("abcdefghijklmnopqrstuwvxy");
doit("abcdefghijklmnopqrstuwvxyz");
/* 255 */
doit("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
/* 256 */
doit("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
return 0;
}