Home | History | Annotate | Download | only in amd64
      1 /* https://bugs.kde.org/show_bug.cgi?id=309921 */
      2 
      3 #define _XOPEN_SOURCE 600 /* for posix_memalign() */
      4 
      5 #include "../../memcheck.h"
      6 
      7 #include <stdio.h>
      8 #include <assert.h>
      9 #include <string.h>
     10 #include <stdlib.h>
     11 
     12 /* Exercise pcmpistri instruction in a realistic way. */
     13 int aligned_strlen(const char *const s)
     14 {
     15    assert(((unsigned long)s & 0x0F) == 0);
     16 
     17    const char *p = s;
     18 
     19    /* volatile asm and "memory" clobber are needed here, since we
     20       access memory in ways we cannot describe to GCC. */
     21    __asm__ __volatile__ ("\n1:\n"
     22                          "\tmovdqa (%0),%%xmm6\n"
     23                          "\tpcmpistri $0x3a,%%xmm6,%%xmm6\n"
     24                          "\tjc 2f\n"
     25                          "\tadd $0x10,%0\n"
     26                          "\tjmp 1b\n"
     27                          "2:\n"
     28                          "\tadd %%rcx,%0\n"
     29                          : "=p" (p) : "0" (p) : "xmm6", "rcx", "cc", "memory");
     30 
     31    return p-s;
     32 }
     33 
     34 /* Compute strlen(s).  Arrange for result to be valid or invalid
     35    according to second argument. */
     36 int test_strlen(const char *const s, int valid)
     37 {
     38    /* len = length of string including trailing null */
     39    const size_t len = strlen(s) + 1;
     40    const size_t roundup = ((len+15)/16)*16;
     41    int result = -1;
     42 
     43    void *space;
     44    posix_memalign(&space, 16, roundup);
     45    memset(space, 'x', roundup);
     46    memcpy(space, s, len);
     47 
     48    const char *const s_copy = space;
     49    const unsigned char ff = 0xFF;
     50    if (valid) {
     51       /* Mark all bytes beyond the null as invalid. */
     52       size_t i;
     53       for (i=len ; i < roundup ; ++i)
     54          (void)VALGRIND_SET_VBITS(&s_copy[i], &ff, 1);
     55    }
     56    else {
     57       /* Mark the null byte itself as invalid. */
     58       assert(len > 0);
     59       (void)VALGRIND_SET_VBITS(&s_copy[len-1], &ff, 1);
     60    }
     61 
     62    result = aligned_strlen(s_copy);
     63 
     64    free(space);
     65 
     66    return result;
     67 }
     68 
     69 void doit(const char *const s)
     70 {
     71    printf("strlen(\"%s\")=%d\n", s, test_strlen(s, 1));
     72 
     73    fprintf(stderr, "strlen(\"%s\")=%s\n", s,
     74            test_strlen(s, 0) ? "true" : "false");
     75 }
     76 
     77 int main(int argc, char *argv[])
     78 {
     79    doit("");
     80    doit("a");
     81    doit("ab");
     82    doit("abc");
     83    doit("abcd");
     84    doit("abcde");
     85    doit("abcdef");
     86    doit("abcdefg");
     87    /* 8 */
     88    doit("abcdefgh");
     89    doit("abcdefghi");
     90    doit("abcdefghij");
     91    doit("abcdefghijk");
     92    doit("abcdefghijkl");
     93    doit("abcdefghijklm");
     94    doit("abcdefghijklmn");
     95    doit("abcdefghijklmno");
     96    /* 16 */
     97    doit("abcdefghijklmnop");
     98    doit("abcdefghijklmnopq");
     99    doit("abcdefghijklmnopqr");
    100    doit("abcdefghijklmnopqrs");
    101    doit("abcdefghijklmnopqrst");
    102    doit("abcdefghijklmnopqrstu");
    103    doit("abcdefghijklmnopqrstuv");
    104    doit("abcdefghijklmnopqrstuvw");
    105    doit("abcdefghijklmnopqrstuwvx");
    106    doit("abcdefghijklmnopqrstuwvxy");
    107    doit("abcdefghijklmnopqrstuwvxyz");
    108    /* 255 */
    109    doit("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    110         "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    111         "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    112         "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    113    /* 256 */
    114    doit("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    115         "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    116         "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    117         "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    118    return 0;
    119 }
    120