1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */ 2304987e3SHeiko Carstens/* 3304987e3SHeiko Carstens * String handling functions. 4304987e3SHeiko Carstens * 5304987e3SHeiko Carstens * Copyright IBM Corp. 2012 6304987e3SHeiko Carstens */ 7304987e3SHeiko Carstens 8*b8c723f1SMasahiro Yamada#include <linux/export.h> 9304987e3SHeiko Carstens#include <linux/linkage.h> 1097489e06SMartin Schwidefsky#include <asm/nospec-insn.h> 1197489e06SMartin Schwidefsky 1297489e06SMartin Schwidefsky GEN_BR_THUNK %r14 13304987e3SHeiko Carstens 14304987e3SHeiko Carstens/* 15b4623d4eSHeiko Carstens * void *memmove(void *dest, const void *src, size_t n) 16b4623d4eSHeiko Carstens */ 17e48b6853SHeiko CarstensSYM_FUNC_START(__memmove) 18b4623d4eSHeiko Carstens ltgr %r4,%r4 19b4623d4eSHeiko Carstens lgr %r1,%r2 205eda25b1SMartin Schwidefsky jz .Lmemmove_exit 21551f4134SHeiko Carstens aghi %r4,-1 22b4623d4eSHeiko Carstens clgr %r2,%r3 23b4623d4eSHeiko Carstens jnh .Lmemmove_forward 24551f4134SHeiko Carstens la %r5,1(%r4,%r3) 25b4623d4eSHeiko Carstens clgr %r2,%r5 26b4623d4eSHeiko Carstens jl .Lmemmove_reverse 27b4623d4eSHeiko Carstens.Lmemmove_forward: 28b4623d4eSHeiko Carstens srlg %r0,%r4,8 29b4623d4eSHeiko Carstens ltgr %r0,%r0 30551f4134SHeiko Carstens jz .Lmemmove_forward_remainder 31551f4134SHeiko Carstens.Lmemmove_forward_loop: 32b4623d4eSHeiko Carstens mvc 0(256,%r1),0(%r3) 33b4623d4eSHeiko Carstens la %r1,256(%r1) 34b4623d4eSHeiko Carstens la %r3,256(%r3) 35551f4134SHeiko Carstens brctg %r0,.Lmemmove_forward_loop 36551f4134SHeiko Carstens.Lmemmove_forward_remainder: 37b4623d4eSHeiko Carstens larl %r5,.Lmemmove_mvc 38b4623d4eSHeiko Carstens ex %r4,0(%r5) 395eda25b1SMartin Schwidefsky.Lmemmove_exit: 4097489e06SMartin Schwidefsky BR_EX %r14 41b4623d4eSHeiko Carstens.Lmemmove_reverse: 42b4623d4eSHeiko Carstens ic %r0,0(%r4,%r3) 43b4623d4eSHeiko Carstens stc %r0,0(%r4,%r1) 44551f4134SHeiko Carstens brctg %r4,.Lmemmove_reverse 45b4623d4eSHeiko Carstens ic %r0,0(%r4,%r3) 46b4623d4eSHeiko Carstens stc %r0,0(%r4,%r1) 4797489e06SMartin Schwidefsky BR_EX %r14 48b4623d4eSHeiko Carstens.Lmemmove_mvc: 49b4623d4eSHeiko Carstens mvc 0(1,%r1),0(%r3) 50e48b6853SHeiko CarstensSYM_FUNC_END(__memmove) 51e48b6853SHeiko CarstensEXPORT_SYMBOL(__memmove) 52e48b6853SHeiko Carstens 53e48b6853SHeiko CarstensSYM_FUNC_ALIAS(memmove, __memmove) 54b4623d4eSHeiko CarstensEXPORT_SYMBOL(memmove) 55b4623d4eSHeiko Carstens 56b4623d4eSHeiko Carstens/* 57304987e3SHeiko Carstens * memset implementation 58304987e3SHeiko Carstens * 59304987e3SHeiko Carstens * This code corresponds to the C construct below. We do distinguish 60304987e3SHeiko Carstens * between clearing (c == 0) and setting a memory array (c != 0) simply 61304987e3SHeiko Carstens * because nearly all memset invocations in the kernel clear memory and 62304987e3SHeiko Carstens * the xc instruction is preferred in such cases. 63304987e3SHeiko Carstens * 64304987e3SHeiko Carstens * void *memset(void *s, int c, size_t n) 65304987e3SHeiko Carstens * { 66304987e3SHeiko Carstens * if (likely(c == 0)) 67304987e3SHeiko Carstens * return __builtin_memset(s, 0, n); 68304987e3SHeiko Carstens * return __builtin_memset(s, c, n); 69304987e3SHeiko Carstens * } 70304987e3SHeiko Carstens */ 71e48b6853SHeiko CarstensSYM_FUNC_START(__memset) 72304987e3SHeiko Carstens ltgr %r4,%r4 735eda25b1SMartin Schwidefsky jz .Lmemset_exit 74304987e3SHeiko Carstens ltgr %r3,%r3 75304987e3SHeiko Carstens jnz .Lmemset_fill 76304987e3SHeiko Carstens aghi %r4,-1 77304987e3SHeiko Carstens srlg %r3,%r4,8 78304987e3SHeiko Carstens ltgr %r3,%r3 79304987e3SHeiko Carstens lgr %r1,%r2 80551f4134SHeiko Carstens jz .Lmemset_clear_remainder 81304987e3SHeiko Carstens.Lmemset_clear_loop: 82304987e3SHeiko Carstens xc 0(256,%r1),0(%r1) 83304987e3SHeiko Carstens la %r1,256(%r1) 84304987e3SHeiko Carstens brctg %r3,.Lmemset_clear_loop 85551f4134SHeiko Carstens.Lmemset_clear_remainder: 86304987e3SHeiko Carstens larl %r3,.Lmemset_xc 87304987e3SHeiko Carstens ex %r4,0(%r3) 885eda25b1SMartin Schwidefsky.Lmemset_exit: 8997489e06SMartin Schwidefsky BR_EX %r14 90304987e3SHeiko Carstens.Lmemset_fill: 91304987e3SHeiko Carstens cghi %r4,1 92304987e3SHeiko Carstens lgr %r1,%r2 93993fef95SHeiko Carstens je .Lmemset_fill_exit 94304987e3SHeiko Carstens aghi %r4,-2 95993fef95SHeiko Carstens srlg %r5,%r4,8 96993fef95SHeiko Carstens ltgr %r5,%r5 97551f4134SHeiko Carstens jz .Lmemset_fill_remainder 98304987e3SHeiko Carstens.Lmemset_fill_loop: 99993fef95SHeiko Carstens stc %r3,0(%r1) 100993fef95SHeiko Carstens mvc 1(255,%r1),0(%r1) 101304987e3SHeiko Carstens la %r1,256(%r1) 102993fef95SHeiko Carstens brctg %r5,.Lmemset_fill_loop 103551f4134SHeiko Carstens.Lmemset_fill_remainder: 104993fef95SHeiko Carstens stc %r3,0(%r1) 105993fef95SHeiko Carstens larl %r5,.Lmemset_mvc 106993fef95SHeiko Carstens ex %r4,0(%r5) 10797489e06SMartin Schwidefsky BR_EX %r14 108993fef95SHeiko Carstens.Lmemset_fill_exit: 109993fef95SHeiko Carstens stc %r3,0(%r1) 11097489e06SMartin Schwidefsky BR_EX %r14 111304987e3SHeiko Carstens.Lmemset_xc: 112304987e3SHeiko Carstens xc 0(1,%r1),0(%r1) 113304987e3SHeiko Carstens.Lmemset_mvc: 114304987e3SHeiko Carstens mvc 1(1,%r1),0(%r1) 115e48b6853SHeiko CarstensSYM_FUNC_END(__memset) 116e48b6853SHeiko CarstensEXPORT_SYMBOL(__memset) 117e48b6853SHeiko Carstens 118e48b6853SHeiko CarstensSYM_FUNC_ALIAS(memset, __memset) 119711f5df7SAl ViroEXPORT_SYMBOL(memset) 120304987e3SHeiko Carstens 121304987e3SHeiko Carstens/* 122304987e3SHeiko Carstens * memcpy implementation 123304987e3SHeiko Carstens * 124304987e3SHeiko Carstens * void *memcpy(void *dest, const void *src, size_t n) 125304987e3SHeiko Carstens */ 126e48b6853SHeiko CarstensSYM_FUNC_START(__memcpy) 127304987e3SHeiko Carstens ltgr %r4,%r4 1285eda25b1SMartin Schwidefsky jz .Lmemcpy_exit 129304987e3SHeiko Carstens aghi %r4,-1 130304987e3SHeiko Carstens srlg %r5,%r4,8 131304987e3SHeiko Carstens ltgr %r5,%r5 132304987e3SHeiko Carstens lgr %r1,%r2 133304987e3SHeiko Carstens jnz .Lmemcpy_loop 134551f4134SHeiko Carstens.Lmemcpy_remainder: 135304987e3SHeiko Carstens larl %r5,.Lmemcpy_mvc 136304987e3SHeiko Carstens ex %r4,0(%r5) 1375eda25b1SMartin Schwidefsky.Lmemcpy_exit: 13897489e06SMartin Schwidefsky BR_EX %r14 139304987e3SHeiko Carstens.Lmemcpy_loop: 140304987e3SHeiko Carstens mvc 0(256,%r1),0(%r3) 141304987e3SHeiko Carstens la %r1,256(%r1) 142304987e3SHeiko Carstens la %r3,256(%r3) 143304987e3SHeiko Carstens brctg %r5,.Lmemcpy_loop 144551f4134SHeiko Carstens j .Lmemcpy_remainder 145304987e3SHeiko Carstens.Lmemcpy_mvc: 146304987e3SHeiko Carstens mvc 0(1,%r1),0(%r3) 147e48b6853SHeiko CarstensSYM_FUNC_END(__memcpy) 148e48b6853SHeiko CarstensEXPORT_SYMBOL(__memcpy) 149e48b6853SHeiko Carstens 150e48b6853SHeiko CarstensSYM_FUNC_ALIAS(memcpy, __memcpy) 151711f5df7SAl ViroEXPORT_SYMBOL(memcpy) 1520b77d670SHeiko Carstens 1530b77d670SHeiko Carstens/* 1540b77d670SHeiko Carstens * __memset16/32/64 1550b77d670SHeiko Carstens * 1560b77d670SHeiko Carstens * void *__memset16(uint16_t *s, uint16_t v, size_t count) 1570b77d670SHeiko Carstens * void *__memset32(uint32_t *s, uint32_t v, size_t count) 1580b77d670SHeiko Carstens * void *__memset64(uint64_t *s, uint64_t v, size_t count) 1590b77d670SHeiko Carstens */ 1600b77d670SHeiko Carstens.macro __MEMSET bits,bytes,insn 16145769052SHeiko CarstensSYM_FUNC_START(__memset\bits) 1620b77d670SHeiko Carstens ltgr %r4,%r4 1635eda25b1SMartin Schwidefsky jz .L__memset_exit\bits 1640b77d670SHeiko Carstens cghi %r4,\bytes 1655eda25b1SMartin Schwidefsky je .L__memset_store\bits 1660b77d670SHeiko Carstens aghi %r4,-(\bytes+1) 1670b77d670SHeiko Carstens srlg %r5,%r4,8 1680b77d670SHeiko Carstens ltgr %r5,%r5 1690b77d670SHeiko Carstens lgr %r1,%r2 1700b77d670SHeiko Carstens jz .L__memset_remainder\bits 1710b77d670SHeiko Carstens.L__memset_loop\bits: 1720b77d670SHeiko Carstens \insn %r3,0(%r1) 1730b77d670SHeiko Carstens mvc \bytes(256-\bytes,%r1),0(%r1) 1740b77d670SHeiko Carstens la %r1,256(%r1) 1750b77d670SHeiko Carstens brctg %r5,.L__memset_loop\bits 1760b77d670SHeiko Carstens.L__memset_remainder\bits: 1770b77d670SHeiko Carstens \insn %r3,0(%r1) 1780b77d670SHeiko Carstens larl %r5,.L__memset_mvc\bits 1790b77d670SHeiko Carstens ex %r4,0(%r5) 18097489e06SMartin Schwidefsky BR_EX %r14 1815eda25b1SMartin Schwidefsky.L__memset_store\bits: 1820b77d670SHeiko Carstens \insn %r3,0(%r2) 1835eda25b1SMartin Schwidefsky.L__memset_exit\bits: 18497489e06SMartin Schwidefsky BR_EX %r14 1850b77d670SHeiko Carstens.L__memset_mvc\bits: 1860b77d670SHeiko Carstens mvc \bytes(1,%r1),0(%r1) 18745769052SHeiko CarstensSYM_FUNC_END(__memset\bits) 1880b77d670SHeiko Carstens.endm 1890b77d670SHeiko Carstens 1900b77d670SHeiko Carstens__MEMSET 16,2,sth 1910b77d670SHeiko CarstensEXPORT_SYMBOL(__memset16) 1920b77d670SHeiko Carstens 1930b77d670SHeiko Carstens__MEMSET 32,4,st 1940b77d670SHeiko CarstensEXPORT_SYMBOL(__memset32) 1950b77d670SHeiko Carstens 1960b77d670SHeiko Carstens__MEMSET 64,8,stg 1970b77d670SHeiko CarstensEXPORT_SYMBOL(__memset64) 198