~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/lib/memmove_32.S

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 
  3 #include <linux/export.h>
  4 #include <linux/linkage.h>
  5 
  6 SYM_FUNC_START(memmove)
  7 /*
  8  * void *memmove(void *dest_in, const void *src_in, size_t n)
  9  * -mregparm=3 passes these in registers:
 10  * dest_in: %eax
 11  * src_in: %edx
 12  * n: %ecx
 13  * See also: arch/x86/entry/calling.h for description of the calling convention.
 14  *
 15  * n can remain in %ecx, but for `rep movsl`, we'll need dest in %edi and src
 16  * in %esi.
 17  */
 18 .set dest_in, %eax
 19 .set dest, %edi
 20 .set src_in, %edx
 21 .set src, %esi
 22 .set n, %ecx
 23 .set tmp0, %edx
 24 .set tmp0w, %dx
 25 .set tmp1, %ebx
 26 .set tmp1w, %bx
 27 .set tmp2, %eax
 28 .set tmp3b, %cl
 29 
 30 /*
 31  * Save all callee-saved registers, because this function is going to clobber
 32  * all of them:
 33  */
 34         pushl   %ebp
 35         movl    %esp, %ebp      // set standard frame pointer
 36 
 37         pushl   %ebx
 38         pushl   %edi
 39         pushl   %esi
 40         pushl   %eax            // save 'dest_in' parameter [eax] as the return value
 41 
 42         movl src_in, src
 43         movl dest_in, dest
 44 
 45         /* Handle more 16 bytes in loop */
 46         cmpl    $0x10, n
 47         jb      .Lmove_16B
 48 
 49         /* Decide forward/backward copy mode */
 50         cmpl    dest, src
 51         jb      .Lbackwards_header
 52 
 53         /*
 54          * movs instruction have many startup latency
 55          * so we handle small size by general register.
 56          */
 57         cmpl    $680, n
 58         jb      .Ltoo_small_forwards
 59         /* movs instruction is only good for aligned case. */
 60         movl    src, tmp0
 61         xorl    dest, tmp0
 62         andl    $0xff, tmp0
 63         jz      .Lforward_movs
 64 .Ltoo_small_forwards:
 65         subl    $0x10, n
 66 
 67         /* We gobble 16 bytes forward in each loop. */
 68 .Lmove_16B_forwards_loop:
 69         subl    $0x10, n
 70         movl    0*4(src), tmp0
 71         movl    1*4(src), tmp1
 72         movl    tmp0, 0*4(dest)
 73         movl    tmp1, 1*4(dest)
 74         movl    2*4(src), tmp0
 75         movl    3*4(src), tmp1
 76         movl    tmp0, 2*4(dest)
 77         movl    tmp1, 3*4(dest)
 78         leal    0x10(src), src
 79         leal    0x10(dest), dest
 80         jae     .Lmove_16B_forwards_loop
 81         addl    $0x10, n
 82         jmp     .Lmove_16B
 83 
 84         /* Handle data forward by movs. */
 85 .p2align 4
 86 .Lforward_movs:
 87         movl    -4(src, n), tmp0
 88         leal    -4(dest, n), tmp1
 89         shrl    $2, n
 90         rep     movsl
 91         movl    tmp0, (tmp1)
 92         jmp     .Ldone
 93 
 94         /* Handle data backward by movs. */
 95 .p2align 4
 96 .Lbackwards_movs:
 97         movl    (src), tmp0
 98         movl    dest, tmp1
 99         leal    -4(src, n), src
100         leal    -4(dest, n), dest
101         shrl    $2, n
102         std
103         rep     movsl
104         movl    tmp0,(tmp1)
105         cld
106         jmp     .Ldone
107 
108         /* Start to prepare for backward copy. */
109 .p2align 4
110 .Lbackwards_header:
111         cmpl    $680, n
112         jb      .Ltoo_small_backwards
113         movl    src, tmp0
114         xorl    dest, tmp0
115         andl    $0xff, tmp0
116         jz      .Lbackwards_movs
117 
118         /* Calculate copy position to tail. */
119 .Ltoo_small_backwards:
120         addl    n, src
121         addl    n, dest
122         subl    $0x10, n
123 
124         /* We gobble 16 bytes backward in each loop. */
125 .Lmove_16B_backwards_loop:
126         subl    $0x10, n
127 
128         movl    -1*4(src), tmp0
129         movl    -2*4(src), tmp1
130         movl    tmp0, -1*4(dest)
131         movl    tmp1, -2*4(dest)
132         movl    -3*4(src), tmp0
133         movl    -4*4(src), tmp1
134         movl    tmp0, -3*4(dest)
135         movl    tmp1, -4*4(dest)
136         leal    -0x10(src), src
137         leal    -0x10(dest), dest
138         jae     .Lmove_16B_backwards_loop
139         /* Calculate copy position to head. */
140         addl    $0x10, n
141         subl    n, src
142         subl    n, dest
143 
144         /* Move data from 8 bytes to 15 bytes. */
145 .p2align 4
146 .Lmove_16B:
147         cmpl    $8, n
148         jb      .Lmove_8B
149         movl    0*4(src), tmp0
150         movl    1*4(src), tmp1
151         movl    -2*4(src, n), tmp2
152         movl    -1*4(src, n), src
153 
154         movl    tmp0, 0*4(dest)
155         movl    tmp1, 1*4(dest)
156         movl    tmp2, -2*4(dest, n)
157         movl    src, -1*4(dest, n)
158         jmp     .Ldone
159 
160         /* Move data from 4 bytes to 7 bytes. */
161 .p2align 4
162 .Lmove_8B:
163         cmpl    $4, n
164         jb      .Lmove_4B
165         movl    0*4(src), tmp0
166         movl    -1*4(src, n), tmp1
167         movl    tmp0, 0*4(dest)
168         movl    tmp1, -1*4(dest, n)
169         jmp     .Ldone
170 
171         /* Move data from 2 bytes to 3 bytes. */
172 .p2align 4
173 .Lmove_4B:
174         cmpl    $2, n
175         jb      .Lmove_1B
176         movw    0*2(src), tmp0w
177         movw    -1*2(src, n), tmp1w
178         movw    tmp0w, 0*2(dest)
179         movw    tmp1w, -1*2(dest, n)
180         jmp     .Ldone
181 
182         /* Move data for 1 byte. */
183 .p2align 4
184 .Lmove_1B:
185         cmpl    $1, n
186         jb      .Ldone
187         movb    (src), tmp3b
188         movb    tmp3b, (dest)
189 .p2align 4
190 .Ldone:
191         popl    dest_in // restore 'dest_in' [eax] as the return value
192         /* Restore all callee-saved registers: */
193         popl    %esi
194         popl    %edi
195         popl    %ebx
196         popl    %ebp
197 
198         RET
199 SYM_FUNC_END(memmove)
200 EXPORT_SYMBOL(memmove)

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php