1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * String handling functions. 4 * 5 * Copyright IBM Corp. 2012 6 */ 7 8#include <linux/linkage.h> 9#include <asm/export.h> 10 11/* 12 * void *memmove(void *dest, const void *src, size_t n) 13 */ 14ENTRY(memmove) 15 ltgr %r4,%r4 16 lgr %r1,%r2 17 bzr %r14 18 aghi %r4,-1 19 clgr %r2,%r3 20 jnh .Lmemmove_forward 21 la %r5,1(%r4,%r3) 22 clgr %r2,%r5 23 jl .Lmemmove_reverse 24.Lmemmove_forward: 25 srlg %r0,%r4,8 26 ltgr %r0,%r0 27 jz .Lmemmove_forward_remainder 28.Lmemmove_forward_loop: 29 mvc 0(256,%r1),0(%r3) 30 la %r1,256(%r1) 31 la %r3,256(%r3) 32 brctg %r0,.Lmemmove_forward_loop 33.Lmemmove_forward_remainder: 34 larl %r5,.Lmemmove_mvc 35 ex %r4,0(%r5) 36 br %r14 37.Lmemmove_reverse: 38 ic %r0,0(%r4,%r3) 39 stc %r0,0(%r4,%r1) 40 brctg %r4,.Lmemmove_reverse 41 ic %r0,0(%r4,%r3) 42 stc %r0,0(%r4,%r1) 43 br %r14 44.Lmemmove_mvc: 45 mvc 0(1,%r1),0(%r3) 46EXPORT_SYMBOL(memmove) 47 48/* 49 * memset implementation 50 * 51 * This code corresponds to the C construct below. We do distinguish 52 * between clearing (c == 0) and setting a memory array (c != 0) simply 53 * because nearly all memset invocations in the kernel clear memory and 54 * the xc instruction is preferred in such cases. 55 * 56 * void *memset(void *s, int c, size_t n) 57 * { 58 * if (likely(c == 0)) 59 * return __builtin_memset(s, 0, n); 60 * return __builtin_memset(s, c, n); 61 * } 62 */ 63ENTRY(memset) 64 ltgr %r4,%r4 65 bzr %r14 66 ltgr %r3,%r3 67 jnz .Lmemset_fill 68 aghi %r4,-1 69 srlg %r3,%r4,8 70 ltgr %r3,%r3 71 lgr %r1,%r2 72 jz .Lmemset_clear_remainder 73.Lmemset_clear_loop: 74 xc 0(256,%r1),0(%r1) 75 la %r1,256(%r1) 76 brctg %r3,.Lmemset_clear_loop 77.Lmemset_clear_remainder: 78 larl %r3,.Lmemset_xc 79 ex %r4,0(%r3) 80 br %r14 81.Lmemset_fill: 82 cghi %r4,1 83 lgr %r1,%r2 84 je .Lmemset_fill_exit 85 aghi %r4,-2 86 srlg %r5,%r4,8 87 ltgr %r5,%r5 88 jz .Lmemset_fill_remainder 89.Lmemset_fill_loop: 90 stc %r3,0(%r1) 91 mvc 1(255,%r1),0(%r1) 92 la %r1,256(%r1) 93 brctg %r5,.Lmemset_fill_loop 94.Lmemset_fill_remainder: 95 stc %r3,0(%r1) 96 larl %r5,.Lmemset_mvc 97 ex %r4,0(%r5) 98 br %r14 99.Lmemset_fill_exit: 100 stc %r3,0(%r1) 101 br %r14 102.Lmemset_xc: 103 xc 0(1,%r1),0(%r1) 104.Lmemset_mvc: 105 mvc 1(1,%r1),0(%r1) 106EXPORT_SYMBOL(memset) 107 108/* 109 * memcpy implementation 110 * 111 * void *memcpy(void *dest, const void *src, size_t n) 112 */ 113ENTRY(memcpy) 114 ltgr %r4,%r4 115 bzr %r14 116 aghi %r4,-1 117 srlg %r5,%r4,8 118 ltgr %r5,%r5 119 lgr %r1,%r2 120 jnz .Lmemcpy_loop 121.Lmemcpy_remainder: 122 larl %r5,.Lmemcpy_mvc 123 ex %r4,0(%r5) 124 br %r14 125.Lmemcpy_loop: 126 mvc 0(256,%r1),0(%r3) 127 la %r1,256(%r1) 128 la %r3,256(%r3) 129 brctg %r5,.Lmemcpy_loop 130 j .Lmemcpy_remainder 131.Lmemcpy_mvc: 132 mvc 0(1,%r1),0(%r3) 133EXPORT_SYMBOL(memcpy) 134 135/* 136 * __memset16/32/64 137 * 138 * void *__memset16(uint16_t *s, uint16_t v, size_t count) 139 * void *__memset32(uint32_t *s, uint32_t v, size_t count) 140 * void *__memset64(uint64_t *s, uint64_t v, size_t count) 141 */ 142.macro __MEMSET bits,bytes,insn 143ENTRY(__memset\bits) 144 ltgr %r4,%r4 145 bzr %r14 146 cghi %r4,\bytes 147 je .L__memset_exit\bits 148 aghi %r4,-(\bytes+1) 149 srlg %r5,%r4,8 150 ltgr %r5,%r5 151 lgr %r1,%r2 152 jz .L__memset_remainder\bits 153.L__memset_loop\bits: 154 \insn %r3,0(%r1) 155 mvc \bytes(256-\bytes,%r1),0(%r1) 156 la %r1,256(%r1) 157 brctg %r5,.L__memset_loop\bits 158.L__memset_remainder\bits: 159 \insn %r3,0(%r1) 160 larl %r5,.L__memset_mvc\bits 161 ex %r4,0(%r5) 162 br %r14 163.L__memset_exit\bits: 164 \insn %r3,0(%r2) 165 br %r14 166.L__memset_mvc\bits: 167 mvc \bytes(1,%r1),0(%r1) 168.endm 169 170__MEMSET 16,2,sth 171EXPORT_SYMBOL(__memset16) 172 173__MEMSET 32,4,st 174EXPORT_SYMBOL(__memset32) 175 176__MEMSET 64,8,stg 177EXPORT_SYMBOL(__memset64) 178