1 /* SPDX-License-Identifier: GPL-2.0 */ 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* $Id: memmove.S,v 1.2 2001/07/27 11:51:09 gn !! 2 /* 3 * !! 3 * arch/alpha/lib/memmove.S 4 * "memmove" implementation of SuperH << 5 * 4 * 6 * Copyright (C) 1999 Niibe Yutaka !! 5 * Barely optimized memmove routine for Alpha EV5. 7 * 6 * >> 7 * This is hand-massaged output from the original memcpy.c. We defer to >> 8 * memcpy whenever possible; the backwards copy loops are not unrolled. 8 */ 9 */ >> 10 #include <linux/export.h> >> 11 .set noat >> 12 .set noreorder >> 13 .text >> 14 >> 15 .align 4 >> 16 .globl memmove >> 17 .ent memmove >> 18 memmove: >> 19 ldgp $29, 0($27) >> 20 unop >> 21 nop >> 22 .prologue 1 >> 23 >> 24 addq $16,$18,$4 >> 25 addq $17,$18,$5 >> 26 cmpule $4,$17,$1 /* dest + n <= src */ >> 27 cmpule $5,$16,$2 /* dest >= src + n */ >> 28 >> 29 bis $1,$2,$1 >> 30 mov $16,$0 >> 31 xor $16,$17,$2 >> 32 bne $1,memcpy !samegp >> 33 >> 34 and $2,7,$2 /* Test for src/dest co-alignment. */ >> 35 and $16,7,$1 >> 36 cmpule $16,$17,$3 >> 37 bne $3,$memmove_up /* dest < src */ >> 38 >> 39 and $4,7,$1 >> 40 bne $2,$misaligned_dn >> 41 unop >> 42 beq $1,$skip_aligned_byte_loop_head_dn >> 43 >> 44 $aligned_byte_loop_head_dn: >> 45 lda $4,-1($4) >> 46 lda $5,-1($5) >> 47 unop >> 48 ble $18,$egress >> 49 >> 50 ldq_u $3,0($5) >> 51 ldq_u $2,0($4) >> 52 lda $18,-1($18) >> 53 extbl $3,$5,$1 >> 54 >> 55 insbl $1,$4,$1 >> 56 mskbl $2,$4,$2 >> 57 bis $1,$2,$1 >> 58 and $4,7,$6 >> 59 >> 60 stq_u $1,0($4) >> 61 bne $6,$aligned_byte_loop_head_dn >> 62 >> 63 $skip_aligned_byte_loop_head_dn: >> 64 lda $18,-8($18) >> 65 blt $18,$skip_aligned_word_loop_dn >> 66 >> 67 $aligned_word_loop_dn: >> 68 ldq $1,-8($5) >> 69 nop >> 70 lda $5,-8($5) >> 71 lda $18,-8($18) >> 72 >> 73 stq $1,-8($4) >> 74 nop >> 75 lda $4,-8($4) >> 76 bge $18,$aligned_word_loop_dn >> 77 >> 78 $skip_aligned_word_loop_dn: >> 79 lda $18,8($18) >> 80 bgt $18,$byte_loop_tail_dn >> 81 unop >> 82 ret $31,($26),1 >> 83 >> 84 .align 4 >> 85 $misaligned_dn: >> 86 nop >> 87 fnop >> 88 unop >> 89 beq $18,$egress >> 90 >> 91 $byte_loop_tail_dn: >> 92 ldq_u $3,-1($5) >> 93 ldq_u $2,-1($4) >> 94 lda $5,-1($5) >> 95 lda $4,-1($4) >> 96 >> 97 lda $18,-1($18) >> 98 extbl $3,$5,$1 >> 99 insbl $1,$4,$1 >> 100 mskbl $2,$4,$2 >> 101 >> 102 bis $1,$2,$1 >> 103 stq_u $1,0($4) >> 104 bgt $18,$byte_loop_tail_dn >> 105 br $egress >> 106 >> 107 $memmove_up: >> 108 mov $16,$4 >> 109 mov $17,$5 >> 110 bne $2,$misaligned_up >> 111 beq $1,$skip_aligned_byte_loop_head_up >> 112 >> 113 $aligned_byte_loop_head_up: >> 114 unop >> 115 ble $18,$egress >> 116 ldq_u $3,0($5) >> 117 ldq_u $2,0($4) >> 118 >> 119 lda $18,-1($18) >> 120 extbl $3,$5,$1 >> 121 insbl $1,$4,$1 >> 122 mskbl $2,$4,$2 >> 123 >> 124 bis $1,$2,$1 >> 125 lda $5,1($5) >> 126 stq_u $1,0($4) >> 127 lda $4,1($4) >> 128 >> 129 and $4,7,$6 >> 130 bne $6,$aligned_byte_loop_head_up >> 131 >> 132 $skip_aligned_byte_loop_head_up: >> 133 lda $18,-8($18) >> 134 blt $18,$skip_aligned_word_loop_up >> 135 >> 136 $aligned_word_loop_up: >> 137 ldq $1,0($5) >> 138 nop >> 139 lda $5,8($5) >> 140 lda $18,-8($18) >> 141 >> 142 stq $1,0($4) >> 143 nop >> 144 lda $4,8($4) >> 145 bge $18,$aligned_word_loop_up >> 146 >> 147 $skip_aligned_word_loop_up: >> 148 lda $18,8($18) >> 149 bgt $18,$byte_loop_tail_up >> 150 unop >> 151 ret $31,($26),1 >> 152 >> 153 .align 4 >> 154 $misaligned_up: >> 155 nop >> 156 fnop >> 157 unop >> 158 beq $18,$egress >> 159 >> 160 $byte_loop_tail_up: >> 161 ldq_u $3,0($5) >> 162 ldq_u $2,0($4) >> 163 lda $18,-1($18) >> 164 extbl $3,$5,$1 >> 165 >> 166 insbl $1,$4,$1 >> 167 mskbl $2,$4,$2 >> 168 bis $1,$2,$1 >> 169 stq_u $1,0($4) >> 170 >> 171 lda $5,1($5) >> 172 lda $4,1($4) >> 173 nop >> 174 bgt $18,$byte_loop_tail_up >> 175 >> 176 $egress: >> 177 ret $31,($26),1 >> 178 nop >> 179 nop >> 180 nop 9 181 10 /* !! 182 .end memmove 11 * void *memmove(void *dst, const void *src, s !! 183 EXPORT_SYMBOL(memmove) 12 * The memory areas may overlap. << 13 */ << 14 << 15 #include <linux/linkage.h> << 16 ENTRY(memmove) << 17 ! if dest > src, call memcpy (it copie << 18 cmp/hi r5,r4 << 19 bf 1f << 20 mov.l 2f,r0 << 21 jmp @r0 << 22 nop << 23 .balign 4 << 24 2: .long memcpy << 25 1: << 26 sub r5,r4 ! From here, r << 27 tst r6,r6 << 28 bt/s 9f ! if n=0, do n << 29 mov r5,r0 << 30 add r6,r5 << 31 mov #12,r1 << 32 cmp/gt r6,r1 << 33 bt/s 8f ! if it's too << 34 add #-1,r4 << 35 add #1,r4 << 36 ! << 37 ! [ ... ] DST << 38 ! [ ... ] << 39 ! : << 40 ! r0+r4--> [ ... ] r0 << 41 ! : << 42 ! [ ... ] << 43 ! r5 << 44 ! << 45 mov r4,r1 << 46 mov #3,r2 << 47 and r2,r1 << 48 shll2 r1 << 49 mov r0,r3 ! Save the val << 50 mova jmptable,r0 << 51 add r1,r0 << 52 mov.l @r0,r1 << 53 jmp @r1 << 54 mov r3,r0 ! and back to << 55 .balign 4 << 56 jmptable: << 57 .long case0 << 58 .long case1 << 59 .long case2 << 60 .long case3 << 61 << 62 ! copy a byte at once << 63 8: mov.b @r0+,r1 << 64 cmp/hs r5,r0 << 65 bf/s 8b ! whil << 66 mov.b r1,@(r0,r4) << 67 add #1,r4 << 68 9: << 69 add r4,r0 << 70 rts << 71 sub r6,r0 << 72 << 73 case_none: << 74 bra 8b << 75 add #-1,r4 << 76 << 77 case0: << 78 ! << 79 ! GHIJ KLMN OPQR --> GHIJ KLMN << 80 ! << 81 ! First, align to long word boundary << 82 mov r0,r3 << 83 and r2,r3 << 84 tst r3,r3 << 85 bt/s 2f << 86 add #-1,r4 << 87 mov #4,r2 << 88 sub r3,r2 << 89 1: dt r2 << 90 mov.b @r0+,r1 << 91 bf/s 1b << 92 mov.b r1,@(r0,r4) << 93 ! << 94 2: ! Second, copy a long word at once << 95 add #-3,r4 << 96 add #-3,r5 << 97 3: mov.l @r0+,r1 << 98 cmp/hs r5,r0 << 99 bf/s 3b << 100 mov.l r1,@(r0,r4) << 101 add #3,r5 << 102 ! << 103 ! Third, copy a byte at once, if neces << 104 cmp/eq r5,r0 << 105 bt/s 9b << 106 add #4,r4 << 107 bra 8b << 108 add #-1,r4 << 109 << 110 case3: << 111 ! << 112 ! GHIJ KLMN OPQR --> ...G HIJK << 113 ! << 114 ! First, align to long word boundary << 115 mov r0,r3 << 116 and r2,r3 << 117 tst r3,r3 << 118 bt/s 2f << 119 add #-1,r4 << 120 mov #4,r2 << 121 sub r3,r2 << 122 1: dt r2 << 123 mov.b @r0+,r1 << 124 bf/s 1b << 125 mov.b r1,@(r0,r4) << 126 ! << 127 2: ! Second, read a long word and write a << 128 add #-2,r4 << 129 mov.l @(r0,r4),r1 << 130 add #-7,r5 << 131 add #-4,r4 << 132 ! << 133 #ifdef __LITTLE_ENDIAN__ << 134 shll8 r1 << 135 3: mov r1,r3 ! JIHG << 136 shlr8 r3 ! xJIH << 137 mov.l @r0+,r1 ! NMLK << 138 mov r1,r2 << 139 shll16 r2 << 140 shll8 r2 ! Kxxx << 141 or r2,r3 ! KJIH << 142 cmp/hs r5,r0 << 143 bf/s 3b << 144 mov.l r3,@(r0,r4) << 145 #else << 146 shlr8 r1 << 147 3: mov r1,r3 ! GHIJ << 148 shll8 r3 ! HIJx << 149 mov.l @r0+,r1 ! KLMN << 150 mov r1,r2 << 151 shlr16 r2 << 152 shlr8 r2 ! xxxK << 153 or r2,r3 ! HIJK << 154 cmp/hs r5,r0 << 155 bf/s 3b << 156 mov.l r3,@(r0,r4) << 157 #endif << 158 add #7,r5 << 159 ! << 160 ! Third, copy a byte at once, if neces << 161 cmp/eq r5,r0 << 162 bt/s 9b << 163 add #7,r4 << 164 add #-3,r0 << 165 bra 8b << 166 add #-1,r4 << 167 << 168 case2: << 169 ! << 170 ! GHIJ KLMN OPQR --> ..GH IJKL << 171 ! << 172 ! First, align to word boundary << 173 tst #1,r0 << 174 bt/s 2f << 175 add #-1,r4 << 176 mov.b @r0+,r1 << 177 mov.b r1,@(r0,r4) << 178 ! << 179 2: ! Second, read a word and write a word << 180 add #-1,r4 << 181 add #-1,r5 << 182 ! << 183 3: mov.w @r0+,r1 << 184 cmp/hs r5,r0 << 185 bf/s 3b << 186 mov.w r1,@(r0,r4) << 187 add #1,r5 << 188 ! << 189 ! Third, copy a byte at once, if neces << 190 cmp/eq r5,r0 << 191 bt/s 9b << 192 add #2,r4 << 193 mov.b @r0,r1 << 194 mov.b r1,@(r0,r4) << 195 bra 9b << 196 add #1,r0 << 197 << 198 case1: << 199 ! << 200 ! GHIJ KLMN OPQR --> .GHI JKLM << 201 ! << 202 ! First, align to long word boundary << 203 mov r0,r3 << 204 and r2,r3 << 205 tst r3,r3 << 206 bt/s 2f << 207 add #-1,r4 << 208 mov #4,r2 << 209 sub r3,r2 << 210 1: dt r2 << 211 mov.b @r0+,r1 << 212 bf/s 1b << 213 mov.b r1,@(r0,r4) << 214 ! << 215 2: ! Second, read a long word and write a << 216 mov.l @(r0,r4),r1 << 217 add #-7,r5 << 218 add #-4,r4 << 219 ! << 220 #ifdef __LITTLE_ENDIAN__ << 221 shll16 r1 << 222 shll8 r1 << 223 3: mov r1,r3 ! JIHG << 224 shlr16 r3 << 225 shlr8 r3 ! xxxJ << 226 mov.l @r0+,r1 ! NMLK << 227 mov r1,r2 << 228 shll8 r2 ! MLKx << 229 or r2,r3 ! MLKJ << 230 cmp/hs r5,r0 << 231 bf/s 3b << 232 mov.l r3,@(r0,r4) << 233 #else << 234 shlr16 r1 << 235 shlr8 r1 << 236 3: mov r1,r3 ! GHIJ << 237 shll16 r3 << 238 shll8 r3 ! Jxxx << 239 mov.l @r0+,r1 ! KLMN << 240 mov r1,r2 << 241 shlr8 r2 ! xKLM << 242 or r2,r3 ! JKLM << 243 cmp/hs r5,r0 << 244 bf/s 3b ! while(r0<r5) << 245 mov.l r3,@(r0,r4) << 246 #endif << 247 add #7,r5 << 248 ! << 249 ! Third, copy a byte at once, if neces << 250 cmp/eq r5,r0 << 251 bt/s 9b << 252 add #5,r4 << 253 add #-3,r0 << 254 bra 8b << 255 add #-1,r4 <<
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.