cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

string_32.c (4748B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Most of the string-functions are rather heavily hand-optimized,
      4 * see especially strsep,strstr,str[c]spn. They should work, but are not
      5 * very easy to understand. Everything is done entirely within the register
      6 * set, making the functions fast and clean. String instructions have been
      7 * used through-out, making for "slightly" unclear code :-)
      8 *
      9 * AK: On P4 and K7 using non string instruction implementations might be faster
     10 * for large memory blocks. But most of them are unlikely to be used on large
     11 * strings.
     12 */
     13
     14#define __NO_FORTIFY
     15#include <linux/string.h>
     16#include <linux/export.h>
     17
     18#ifdef __HAVE_ARCH_STRCPY
     19char *strcpy(char *dest, const char *src)
     20{
     21	int d0, d1, d2;
     22	asm volatile("1:\tlodsb\n\t"
     23		"stosb\n\t"
     24		"testb %%al,%%al\n\t"
     25		"jne 1b"
     26		: "=&S" (d0), "=&D" (d1), "=&a" (d2)
     27		: "0" (src), "1" (dest) : "memory");
     28	return dest;
     29}
     30EXPORT_SYMBOL(strcpy);
     31#endif
     32
     33#ifdef __HAVE_ARCH_STRNCPY
     34char *strncpy(char *dest, const char *src, size_t count)
     35{
     36	int d0, d1, d2, d3;
     37	asm volatile("1:\tdecl %2\n\t"
     38		"js 2f\n\t"
     39		"lodsb\n\t"
     40		"stosb\n\t"
     41		"testb %%al,%%al\n\t"
     42		"jne 1b\n\t"
     43		"rep\n\t"
     44		"stosb\n"
     45		"2:"
     46		: "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
     47		: "0" (src), "1" (dest), "2" (count) : "memory");
     48	return dest;
     49}
     50EXPORT_SYMBOL(strncpy);
     51#endif
     52
     53#ifdef __HAVE_ARCH_STRCAT
     54char *strcat(char *dest, const char *src)
     55{
     56	int d0, d1, d2, d3;
     57	asm volatile("repne\n\t"
     58		"scasb\n\t"
     59		"decl %1\n"
     60		"1:\tlodsb\n\t"
     61		"stosb\n\t"
     62		"testb %%al,%%al\n\t"
     63		"jne 1b"
     64		: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
     65		: "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu) : "memory");
     66	return dest;
     67}
     68EXPORT_SYMBOL(strcat);
     69#endif
     70
     71#ifdef __HAVE_ARCH_STRNCAT
     72char *strncat(char *dest, const char *src, size_t count)
     73{
     74	int d0, d1, d2, d3;
     75	asm volatile("repne\n\t"
     76		"scasb\n\t"
     77		"decl %1\n\t"
     78		"movl %8,%3\n"
     79		"1:\tdecl %3\n\t"
     80		"js 2f\n\t"
     81		"lodsb\n\t"
     82		"stosb\n\t"
     83		"testb %%al,%%al\n\t"
     84		"jne 1b\n"
     85		"2:\txorl %2,%2\n\t"
     86		"stosb"
     87		: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
     88		: "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu), "g" (count)
     89		: "memory");
     90	return dest;
     91}
     92EXPORT_SYMBOL(strncat);
     93#endif
     94
     95#ifdef __HAVE_ARCH_STRCMP
     96int strcmp(const char *cs, const char *ct)
     97{
     98	int d0, d1;
     99	int res;
    100	asm volatile("1:\tlodsb\n\t"
    101		"scasb\n\t"
    102		"jne 2f\n\t"
    103		"testb %%al,%%al\n\t"
    104		"jne 1b\n\t"
    105		"xorl %%eax,%%eax\n\t"
    106		"jmp 3f\n"
    107		"2:\tsbbl %%eax,%%eax\n\t"
    108		"orb $1,%%al\n"
    109		"3:"
    110		: "=a" (res), "=&S" (d0), "=&D" (d1)
    111		: "1" (cs), "2" (ct)
    112		: "memory");
    113	return res;
    114}
    115EXPORT_SYMBOL(strcmp);
    116#endif
    117
    118#ifdef __HAVE_ARCH_STRNCMP
    119int strncmp(const char *cs, const char *ct, size_t count)
    120{
    121	int res;
    122	int d0, d1, d2;
    123	asm volatile("1:\tdecl %3\n\t"
    124		"js 2f\n\t"
    125		"lodsb\n\t"
    126		"scasb\n\t"
    127		"jne 3f\n\t"
    128		"testb %%al,%%al\n\t"
    129		"jne 1b\n"
    130		"2:\txorl %%eax,%%eax\n\t"
    131		"jmp 4f\n"
    132		"3:\tsbbl %%eax,%%eax\n\t"
    133		"orb $1,%%al\n"
    134		"4:"
    135		: "=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
    136		: "1" (cs), "2" (ct), "3" (count)
    137		: "memory");
    138	return res;
    139}
    140EXPORT_SYMBOL(strncmp);
    141#endif
    142
    143#ifdef __HAVE_ARCH_STRCHR
    144char *strchr(const char *s, int c)
    145{
    146	int d0;
    147	char *res;
    148	asm volatile("movb %%al,%%ah\n"
    149		"1:\tlodsb\n\t"
    150		"cmpb %%ah,%%al\n\t"
    151		"je 2f\n\t"
    152		"testb %%al,%%al\n\t"
    153		"jne 1b\n\t"
    154		"movl $1,%1\n"
    155		"2:\tmovl %1,%0\n\t"
    156		"decl %0"
    157		: "=a" (res), "=&S" (d0)
    158		: "1" (s), "0" (c)
    159		: "memory");
    160	return res;
    161}
    162EXPORT_SYMBOL(strchr);
    163#endif
    164
    165#ifdef __HAVE_ARCH_STRLEN
    166size_t strlen(const char *s)
    167{
    168	int d0;
    169	size_t res;
    170	asm volatile("repne\n\t"
    171		"scasb"
    172		: "=c" (res), "=&D" (d0)
    173		: "1" (s), "a" (0), "0" (0xffffffffu)
    174		: "memory");
    175	return ~res - 1;
    176}
    177EXPORT_SYMBOL(strlen);
    178#endif
    179
    180#ifdef __HAVE_ARCH_MEMCHR
    181void *memchr(const void *cs, int c, size_t count)
    182{
    183	int d0;
    184	void *res;
    185	if (!count)
    186		return NULL;
    187	asm volatile("repne\n\t"
    188		"scasb\n\t"
    189		"je 1f\n\t"
    190		"movl $1,%0\n"
    191		"1:\tdecl %0"
    192		: "=D" (res), "=&c" (d0)
    193		: "a" (c), "0" (cs), "1" (count)
    194		: "memory");
    195	return res;
    196}
    197EXPORT_SYMBOL(memchr);
    198#endif
    199
    200#ifdef __HAVE_ARCH_MEMSCAN
    201void *memscan(void *addr, int c, size_t size)
    202{
    203	if (!size)
    204		return addr;
    205	asm volatile("repnz; scasb\n\t"
    206	    "jnz 1f\n\t"
    207	    "dec %%edi\n"
    208	    "1:"
    209	    : "=D" (addr), "=c" (size)
    210	    : "0" (addr), "1" (size), "a" (c)
    211	    : "memory");
    212	return addr;
    213}
    214EXPORT_SYMBOL(memscan);
    215#endif
    216
    217#ifdef __HAVE_ARCH_STRNLEN
    218size_t strnlen(const char *s, size_t count)
    219{
    220	int d0;
    221	int res;
    222	asm volatile("movl %2,%0\n\t"
    223		"jmp 2f\n"
    224		"1:\tcmpb $0,(%0)\n\t"
    225		"je 3f\n\t"
    226		"incl %0\n"
    227		"2:\tdecl %1\n\t"
    228		"cmpl $-1,%1\n\t"
    229		"jne 1b\n"
    230		"3:\tsubl %2,%0"
    231		: "=a" (res), "=&d" (d0)
    232		: "c" (s), "1" (count)
    233		: "memory");
    234	return res;
    235}
    236EXPORT_SYMBOL(strnlen);
    237#endif