18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * String handling functions. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2012 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/linkage.h> 98c2ecf20Sopenharmony_ci#include <asm/export.h> 108c2ecf20Sopenharmony_ci#include <asm/nospec-insn.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci GEN_BR_THUNK %r14 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* 158c2ecf20Sopenharmony_ci * void *memmove(void *dest, const void *src, size_t n) 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_ciWEAK(memmove) 188c2ecf20Sopenharmony_ciENTRY(__memmove) 198c2ecf20Sopenharmony_ci ltgr %r4,%r4 208c2ecf20Sopenharmony_ci lgr %r1,%r2 218c2ecf20Sopenharmony_ci jz .Lmemmove_exit 228c2ecf20Sopenharmony_ci aghi %r4,-1 238c2ecf20Sopenharmony_ci clgr %r2,%r3 248c2ecf20Sopenharmony_ci jnh .Lmemmove_forward 258c2ecf20Sopenharmony_ci la %r5,1(%r4,%r3) 268c2ecf20Sopenharmony_ci clgr %r2,%r5 278c2ecf20Sopenharmony_ci jl .Lmemmove_reverse 288c2ecf20Sopenharmony_ci.Lmemmove_forward: 298c2ecf20Sopenharmony_ci srlg %r0,%r4,8 308c2ecf20Sopenharmony_ci ltgr %r0,%r0 318c2ecf20Sopenharmony_ci jz .Lmemmove_forward_remainder 328c2ecf20Sopenharmony_ci.Lmemmove_forward_loop: 338c2ecf20Sopenharmony_ci mvc 0(256,%r1),0(%r3) 348c2ecf20Sopenharmony_ci la %r1,256(%r1) 358c2ecf20Sopenharmony_ci la %r3,256(%r3) 368c2ecf20Sopenharmony_ci brctg %r0,.Lmemmove_forward_loop 378c2ecf20Sopenharmony_ci.Lmemmove_forward_remainder: 388c2ecf20Sopenharmony_ci larl %r5,.Lmemmove_mvc 398c2ecf20Sopenharmony_ci ex %r4,0(%r5) 408c2ecf20Sopenharmony_ci.Lmemmove_exit: 418c2ecf20Sopenharmony_ci BR_EX %r14 428c2ecf20Sopenharmony_ci.Lmemmove_reverse: 438c2ecf20Sopenharmony_ci ic %r0,0(%r4,%r3) 448c2ecf20Sopenharmony_ci stc %r0,0(%r4,%r1) 458c2ecf20Sopenharmony_ci brctg %r4,.Lmemmove_reverse 468c2ecf20Sopenharmony_ci ic %r0,0(%r4,%r3) 478c2ecf20Sopenharmony_ci stc %r0,0(%r4,%r1) 488c2ecf20Sopenharmony_ci BR_EX %r14 498c2ecf20Sopenharmony_ci.Lmemmove_mvc: 508c2ecf20Sopenharmony_ci mvc 0(1,%r1),0(%r3) 518c2ecf20Sopenharmony_ciENDPROC(__memmove) 528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(memmove) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/* 558c2ecf20Sopenharmony_ci * memset implementation 568c2ecf20Sopenharmony_ci * 578c2ecf20Sopenharmony_ci * This code corresponds to the C construct below. We do distinguish 588c2ecf20Sopenharmony_ci * between clearing (c == 0) and setting a memory array (c != 0) simply 598c2ecf20Sopenharmony_ci * because nearly all memset invocations in the kernel clear memory and 608c2ecf20Sopenharmony_ci * the xc instruction is preferred in such cases. 618c2ecf20Sopenharmony_ci * 628c2ecf20Sopenharmony_ci * void *memset(void *s, int c, size_t n) 638c2ecf20Sopenharmony_ci * { 648c2ecf20Sopenharmony_ci * if (likely(c == 0)) 658c2ecf20Sopenharmony_ci * return __builtin_memset(s, 0, n); 668c2ecf20Sopenharmony_ci * return __builtin_memset(s, c, n); 678c2ecf20Sopenharmony_ci * } 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_ciWEAK(memset) 708c2ecf20Sopenharmony_ciENTRY(__memset) 718c2ecf20Sopenharmony_ci ltgr %r4,%r4 728c2ecf20Sopenharmony_ci jz .Lmemset_exit 738c2ecf20Sopenharmony_ci ltgr %r3,%r3 748c2ecf20Sopenharmony_ci jnz .Lmemset_fill 758c2ecf20Sopenharmony_ci aghi %r4,-1 768c2ecf20Sopenharmony_ci srlg %r3,%r4,8 778c2ecf20Sopenharmony_ci ltgr %r3,%r3 788c2ecf20Sopenharmony_ci lgr %r1,%r2 798c2ecf20Sopenharmony_ci jz .Lmemset_clear_remainder 808c2ecf20Sopenharmony_ci.Lmemset_clear_loop: 818c2ecf20Sopenharmony_ci xc 0(256,%r1),0(%r1) 828c2ecf20Sopenharmony_ci la %r1,256(%r1) 838c2ecf20Sopenharmony_ci brctg %r3,.Lmemset_clear_loop 848c2ecf20Sopenharmony_ci.Lmemset_clear_remainder: 858c2ecf20Sopenharmony_ci larl %r3,.Lmemset_xc 868c2ecf20Sopenharmony_ci ex %r4,0(%r3) 878c2ecf20Sopenharmony_ci.Lmemset_exit: 888c2ecf20Sopenharmony_ci BR_EX %r14 898c2ecf20Sopenharmony_ci.Lmemset_fill: 908c2ecf20Sopenharmony_ci cghi %r4,1 918c2ecf20Sopenharmony_ci lgr %r1,%r2 928c2ecf20Sopenharmony_ci je .Lmemset_fill_exit 938c2ecf20Sopenharmony_ci aghi %r4,-2 948c2ecf20Sopenharmony_ci srlg %r5,%r4,8 958c2ecf20Sopenharmony_ci ltgr %r5,%r5 968c2ecf20Sopenharmony_ci jz .Lmemset_fill_remainder 978c2ecf20Sopenharmony_ci.Lmemset_fill_loop: 988c2ecf20Sopenharmony_ci stc %r3,0(%r1) 998c2ecf20Sopenharmony_ci mvc 1(255,%r1),0(%r1) 1008c2ecf20Sopenharmony_ci la %r1,256(%r1) 1018c2ecf20Sopenharmony_ci brctg %r5,.Lmemset_fill_loop 1028c2ecf20Sopenharmony_ci.Lmemset_fill_remainder: 1038c2ecf20Sopenharmony_ci stc %r3,0(%r1) 1048c2ecf20Sopenharmony_ci larl %r5,.Lmemset_mvc 1058c2ecf20Sopenharmony_ci ex %r4,0(%r5) 1068c2ecf20Sopenharmony_ci BR_EX %r14 1078c2ecf20Sopenharmony_ci.Lmemset_fill_exit: 1088c2ecf20Sopenharmony_ci stc %r3,0(%r1) 1098c2ecf20Sopenharmony_ci BR_EX %r14 1108c2ecf20Sopenharmony_ci.Lmemset_xc: 1118c2ecf20Sopenharmony_ci xc 0(1,%r1),0(%r1) 1128c2ecf20Sopenharmony_ci.Lmemset_mvc: 1138c2ecf20Sopenharmony_ci mvc 1(1,%r1),0(%r1) 1148c2ecf20Sopenharmony_ciENDPROC(__memset) 1158c2ecf20Sopenharmony_ciEXPORT_SYMBOL(memset) 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci/* 1188c2ecf20Sopenharmony_ci * memcpy implementation 1198c2ecf20Sopenharmony_ci * 1208c2ecf20Sopenharmony_ci * void *memcpy(void *dest, const void *src, size_t n) 1218c2ecf20Sopenharmony_ci */ 1228c2ecf20Sopenharmony_ciWEAK(memcpy) 1238c2ecf20Sopenharmony_ciENTRY(__memcpy) 1248c2ecf20Sopenharmony_ci ltgr %r4,%r4 1258c2ecf20Sopenharmony_ci jz .Lmemcpy_exit 1268c2ecf20Sopenharmony_ci aghi %r4,-1 1278c2ecf20Sopenharmony_ci srlg %r5,%r4,8 1288c2ecf20Sopenharmony_ci ltgr %r5,%r5 1298c2ecf20Sopenharmony_ci lgr %r1,%r2 1308c2ecf20Sopenharmony_ci jnz .Lmemcpy_loop 1318c2ecf20Sopenharmony_ci.Lmemcpy_remainder: 1328c2ecf20Sopenharmony_ci larl %r5,.Lmemcpy_mvc 1338c2ecf20Sopenharmony_ci ex %r4,0(%r5) 1348c2ecf20Sopenharmony_ci.Lmemcpy_exit: 1358c2ecf20Sopenharmony_ci BR_EX %r14 1368c2ecf20Sopenharmony_ci.Lmemcpy_loop: 1378c2ecf20Sopenharmony_ci mvc 0(256,%r1),0(%r3) 1388c2ecf20Sopenharmony_ci la %r1,256(%r1) 1398c2ecf20Sopenharmony_ci la %r3,256(%r3) 1408c2ecf20Sopenharmony_ci brctg %r5,.Lmemcpy_loop 1418c2ecf20Sopenharmony_ci j .Lmemcpy_remainder 1428c2ecf20Sopenharmony_ci.Lmemcpy_mvc: 1438c2ecf20Sopenharmony_ci mvc 0(1,%r1),0(%r3) 1448c2ecf20Sopenharmony_ciENDPROC(__memcpy) 1458c2ecf20Sopenharmony_ciEXPORT_SYMBOL(memcpy) 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci/* 1488c2ecf20Sopenharmony_ci * __memset16/32/64 1498c2ecf20Sopenharmony_ci * 1508c2ecf20Sopenharmony_ci * void *__memset16(uint16_t *s, uint16_t v, size_t count) 1518c2ecf20Sopenharmony_ci * void *__memset32(uint32_t *s, uint32_t v, size_t count) 1528c2ecf20Sopenharmony_ci * void *__memset64(uint64_t *s, uint64_t v, size_t count) 1538c2ecf20Sopenharmony_ci */ 1548c2ecf20Sopenharmony_ci.macro __MEMSET bits,bytes,insn 1558c2ecf20Sopenharmony_ciENTRY(__memset\bits) 1568c2ecf20Sopenharmony_ci ltgr %r4,%r4 1578c2ecf20Sopenharmony_ci jz .L__memset_exit\bits 1588c2ecf20Sopenharmony_ci cghi %r4,\bytes 1598c2ecf20Sopenharmony_ci je .L__memset_store\bits 1608c2ecf20Sopenharmony_ci aghi %r4,-(\bytes+1) 1618c2ecf20Sopenharmony_ci srlg %r5,%r4,8 1628c2ecf20Sopenharmony_ci ltgr %r5,%r5 1638c2ecf20Sopenharmony_ci lgr %r1,%r2 1648c2ecf20Sopenharmony_ci jz .L__memset_remainder\bits 1658c2ecf20Sopenharmony_ci.L__memset_loop\bits: 1668c2ecf20Sopenharmony_ci \insn %r3,0(%r1) 1678c2ecf20Sopenharmony_ci mvc \bytes(256-\bytes,%r1),0(%r1) 1688c2ecf20Sopenharmony_ci la %r1,256(%r1) 1698c2ecf20Sopenharmony_ci brctg %r5,.L__memset_loop\bits 1708c2ecf20Sopenharmony_ci.L__memset_remainder\bits: 1718c2ecf20Sopenharmony_ci \insn %r3,0(%r1) 1728c2ecf20Sopenharmony_ci larl %r5,.L__memset_mvc\bits 1738c2ecf20Sopenharmony_ci ex %r4,0(%r5) 1748c2ecf20Sopenharmony_ci BR_EX %r14 1758c2ecf20Sopenharmony_ci.L__memset_store\bits: 1768c2ecf20Sopenharmony_ci \insn %r3,0(%r2) 1778c2ecf20Sopenharmony_ci.L__memset_exit\bits: 1788c2ecf20Sopenharmony_ci BR_EX %r14 1798c2ecf20Sopenharmony_ci.L__memset_mvc\bits: 1808c2ecf20Sopenharmony_ci mvc \bytes(1,%r1),0(%r1) 1818c2ecf20Sopenharmony_ciENDPROC(__memset\bits) 1828c2ecf20Sopenharmony_ci.endm 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci__MEMSET 16,2,sth 1858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__memset16) 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci__MEMSET 32,4,st 1888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__memset32) 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci__MEMSET 64,8,stg 1918c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__memset64) 192