1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* https://bugs.kde.org/show_bug.cgi?id=309921 */ 2436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define _XOPEN_SOURCE 600 /* for posix_memalign() */ 4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 5436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "../../memcheck.h" 6436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 7436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <stdio.h> 8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <assert.h> 9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <string.h> 10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <stdlib.h> 11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Exercise pcmpistri instruction in a realistic way. */ 13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovint aligned_strlen(const char *const s) 14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 15436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assert(((unsigned long)s & 0x0F) == 0); 16436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 17436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const char *p = s; 18436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 19436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* volatile asm and "memory" clobber are needed here, since we 20436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov access memory in ways we cannot describe to GCC. */ 21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov __asm__ __volatile__ ("\n1:\n" 22436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "\tmovdqa (%0),%%xmm6\n" 23436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "\tpcmpistri $0x3a,%%xmm6,%%xmm6\n" 24436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "\tjc 2f\n" 25436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "\tadd $0x10,%0\n" 26436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "\tjmp 1b\n" 27436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "2:\n" 28436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "\tadd %%rcx,%0\n" 29436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov : "=p" (p) : "0" (p) : "xmm6", "rcx", "cc", "memory"); 30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 31436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return p-s; 32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 33436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 34436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Compute strlen(s). Arrange for result to be valid or invalid 35436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov according to second argument. */ 36436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovint test_strlen(const char *const s, int valid) 37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* len = length of string including trailing null */ 39436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const size_t len = strlen(s) + 1; 40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const size_t roundup = ((len+15)/16)*16; 41436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov int result = -1; 42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov void *space; 44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov posix_memalign(&space, 16, roundup); 45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov memset(space, 'x', roundup); 46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov memcpy(space, s, len); 47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const char *const s_copy = space; 49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const unsigned char ff = 0xFF; 50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (valid) { 51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Mark all bytes beyond the null as invalid. */ 52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov size_t i; 53436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i=len ; i < roundup ; ++i) 54436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (void)VALGRIND_SET_VBITS(&s_copy[i], &ff, 1); 55436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else { 57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Mark the null byte itself as invalid. */ 58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assert(len > 0); 59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (void)VALGRIND_SET_VBITS(&s_copy[len-1], &ff, 1); 60436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 62436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov result = aligned_strlen(s_copy); 63436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov free(space); 65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 66436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return result; 67436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 68436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid doit(const char *const s) 70436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 71436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov printf("strlen(\"%s\")=%d\n", s, test_strlen(s, 1)); 72436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 73436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fprintf(stderr, "strlen(\"%s\")=%s\n", s, 74436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov test_strlen(s, 0) ? "true" : "false"); 75436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 76436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 77436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovint main(int argc, char *argv[]) 78436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 79436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit(""); 80436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("a"); 81436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("ab"); 82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abc"); 83436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcd"); 84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcde"); 85436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdef"); 86436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefg"); 87436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* 8 */ 88436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefgh"); 89436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghi"); 90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghij"); 91436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijk"); 92436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijkl"); 93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklm"); 94436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmn"); 95436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmno"); 96436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* 16 */ 97436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmnop"); 98436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmnopq"); 99436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmnopqr"); 100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmnopqrs"); 101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmnopqrst"); 102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmnopqrstu"); 103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmnopqrstuv"); 104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmnopqrstuvw"); 105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmnopqrstuwvx"); 106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmnopqrstuwvxy"); 107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("abcdefghijklmnopqrstuwvxyz"); 108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* 255 */ 109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); 113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* 256 */ 114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doit("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); 118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return 0; 119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 120