xref: /kernel/linux/linux-6.6/arch/sh/lib/memmove.S (revision 62306a36)
162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/* $Id: memmove.S,v 1.2 2001/07/27 11:51:09 gniibe Exp $
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * "memmove" implementation of SuperH
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 1999  Niibe Yutaka
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/*
1162306a36Sopenharmony_ci * void *memmove(void *dst, const void *src, size_t n);
1262306a36Sopenharmony_ci * The memory areas may overlap.
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/linkage.h>
1662306a36Sopenharmony_ciENTRY(memmove)
1762306a36Sopenharmony_ci	! if dest > src, call memcpy (it copies in decreasing order)
1862306a36Sopenharmony_ci	cmp/hi	r5,r4
1962306a36Sopenharmony_ci	bf	1f
2062306a36Sopenharmony_ci	mov.l	2f,r0
2162306a36Sopenharmony_ci	jmp	@r0
2262306a36Sopenharmony_ci	 nop
2362306a36Sopenharmony_ci	.balign 4
2462306a36Sopenharmony_ci2:	.long	memcpy
2562306a36Sopenharmony_ci1:
2662306a36Sopenharmony_ci	sub	r5,r4		! From here, r4 has the distance to r0
2762306a36Sopenharmony_ci	tst	r6,r6
2862306a36Sopenharmony_ci	bt/s	9f		! if n=0, do nothing
2962306a36Sopenharmony_ci	 mov	r5,r0
3062306a36Sopenharmony_ci	add	r6,r5
3162306a36Sopenharmony_ci	mov	#12,r1
3262306a36Sopenharmony_ci	cmp/gt	r6,r1
3362306a36Sopenharmony_ci	bt/s	8f		! if it's too small, copy a byte at once
3462306a36Sopenharmony_ci	 add	#-1,r4
3562306a36Sopenharmony_ci	add	#1,r4
3662306a36Sopenharmony_ci	!
3762306a36Sopenharmony_ci	!                [ ...  ] DST             [ ...  ] SRC
3862306a36Sopenharmony_ci	!	         [ ...  ]                 [ ...  ]
3962306a36Sopenharmony_ci	!	           :                        :
4062306a36Sopenharmony_ci	!      r0+r4-->  [ ...  ]       r0    --> [ ...  ]
4162306a36Sopenharmony_ci	!	           :                        :
4262306a36Sopenharmony_ci	!	         [ ...  ]                 [ ...  ]
4362306a36Sopenharmony_ci	!			        r5    -->
4462306a36Sopenharmony_ci	!
4562306a36Sopenharmony_ci	mov	r4,r1
4662306a36Sopenharmony_ci	mov	#3,r2
4762306a36Sopenharmony_ci	and	r2,r1
4862306a36Sopenharmony_ci	shll2	r1
4962306a36Sopenharmony_ci	mov	r0,r3		! Save the value on R0 to R3
5062306a36Sopenharmony_ci	mova	jmptable,r0
5162306a36Sopenharmony_ci	add	r1,r0
5262306a36Sopenharmony_ci	mov.l	@r0,r1
5362306a36Sopenharmony_ci	jmp	@r1
5462306a36Sopenharmony_ci	 mov	r3,r0		! and back to R0
5562306a36Sopenharmony_ci	.balign	4
5662306a36Sopenharmony_cijmptable:
5762306a36Sopenharmony_ci	.long	case0
5862306a36Sopenharmony_ci	.long	case1
5962306a36Sopenharmony_ci	.long	case2
6062306a36Sopenharmony_ci	.long	case3
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	! copy a byte at once
6362306a36Sopenharmony_ci8:	mov.b	@r0+,r1
6462306a36Sopenharmony_ci	cmp/hs	r5,r0
6562306a36Sopenharmony_ci	bf/s	8b			! while (r0<r5)
6662306a36Sopenharmony_ci	 mov.b	r1,@(r0,r4)
6762306a36Sopenharmony_ci	add	#1,r4
6862306a36Sopenharmony_ci9:
6962306a36Sopenharmony_ci	add	r4,r0
7062306a36Sopenharmony_ci	rts
7162306a36Sopenharmony_ci	 sub	r6,r0
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cicase_none:
7462306a36Sopenharmony_ci	bra	8b
7562306a36Sopenharmony_ci	 add	#-1,r4
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cicase0:
7862306a36Sopenharmony_ci	!
7962306a36Sopenharmony_ci	!	GHIJ KLMN OPQR -->  GHIJ KLMN OPQR
8062306a36Sopenharmony_ci	!
8162306a36Sopenharmony_ci	! First, align to long word boundary
8262306a36Sopenharmony_ci	mov	r0,r3
8362306a36Sopenharmony_ci	and	r2,r3
8462306a36Sopenharmony_ci	tst	r3,r3
8562306a36Sopenharmony_ci	bt/s	2f
8662306a36Sopenharmony_ci	 add	#-1,r4
8762306a36Sopenharmony_ci	mov	#4,r2
8862306a36Sopenharmony_ci	sub	r3,r2
8962306a36Sopenharmony_ci1:	dt	r2
9062306a36Sopenharmony_ci	mov.b	@r0+,r1
9162306a36Sopenharmony_ci	bf/s	1b
9262306a36Sopenharmony_ci	 mov.b	r1,@(r0,r4)
9362306a36Sopenharmony_ci	!
9462306a36Sopenharmony_ci2:	! Second, copy a long word at once
9562306a36Sopenharmony_ci	add	#-3,r4
9662306a36Sopenharmony_ci	add	#-3,r5
9762306a36Sopenharmony_ci3:	mov.l	@r0+,r1
9862306a36Sopenharmony_ci	cmp/hs	r5,r0
9962306a36Sopenharmony_ci	bf/s	3b
10062306a36Sopenharmony_ci	 mov.l	r1,@(r0,r4)
10162306a36Sopenharmony_ci	add	#3,r5
10262306a36Sopenharmony_ci	!
10362306a36Sopenharmony_ci	! Third, copy a byte at once, if necessary
10462306a36Sopenharmony_ci	cmp/eq	r5,r0
10562306a36Sopenharmony_ci	bt/s	9b
10662306a36Sopenharmony_ci	 add	#4,r4
10762306a36Sopenharmony_ci	bra	8b
10862306a36Sopenharmony_ci	 add	#-1,r4
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cicase3:
11162306a36Sopenharmony_ci	!
11262306a36Sopenharmony_ci	!	GHIJ KLMN OPQR -->  ...G HIJK LMNO PQR.
11362306a36Sopenharmony_ci	!
11462306a36Sopenharmony_ci	! First, align to long word boundary
11562306a36Sopenharmony_ci	mov	r0,r3
11662306a36Sopenharmony_ci	and	r2,r3
11762306a36Sopenharmony_ci	tst	r3,r3
11862306a36Sopenharmony_ci	bt/s	2f
11962306a36Sopenharmony_ci	 add	#-1,r4
12062306a36Sopenharmony_ci	mov	#4,r2
12162306a36Sopenharmony_ci	sub	r3,r2
12262306a36Sopenharmony_ci1:	dt	r2
12362306a36Sopenharmony_ci	mov.b	@r0+,r1
12462306a36Sopenharmony_ci	bf/s	1b
12562306a36Sopenharmony_ci	 mov.b	r1,@(r0,r4)
12662306a36Sopenharmony_ci	!
12762306a36Sopenharmony_ci2:	! Second, read a long word and write a long word at once
12862306a36Sopenharmony_ci	add	#-2,r4
12962306a36Sopenharmony_ci	mov.l	@(r0,r4),r1
13062306a36Sopenharmony_ci	add	#-7,r5
13162306a36Sopenharmony_ci	add	#-4,r4
13262306a36Sopenharmony_ci	!
13362306a36Sopenharmony_ci#ifdef __LITTLE_ENDIAN__
13462306a36Sopenharmony_ci	shll8	r1
13562306a36Sopenharmony_ci3:	mov	r1,r3		! JIHG
13662306a36Sopenharmony_ci	shlr8	r3		! xJIH
13762306a36Sopenharmony_ci	mov.l	@r0+,r1		! NMLK
13862306a36Sopenharmony_ci	mov	r1,r2
13962306a36Sopenharmony_ci	shll16	r2
14062306a36Sopenharmony_ci	shll8	r2		! Kxxx
14162306a36Sopenharmony_ci	or	r2,r3		! KJIH
14262306a36Sopenharmony_ci	cmp/hs	r5,r0
14362306a36Sopenharmony_ci	bf/s	3b
14462306a36Sopenharmony_ci	 mov.l	r3,@(r0,r4)
14562306a36Sopenharmony_ci#else
14662306a36Sopenharmony_ci	shlr8	r1
14762306a36Sopenharmony_ci3:	mov	r1,r3		! GHIJ
14862306a36Sopenharmony_ci	shll8	r3		! HIJx
14962306a36Sopenharmony_ci	mov.l	@r0+,r1		! KLMN
15062306a36Sopenharmony_ci	mov	r1,r2
15162306a36Sopenharmony_ci	shlr16	r2
15262306a36Sopenharmony_ci	shlr8	r2		! xxxK
15362306a36Sopenharmony_ci	or	r2,r3		! HIJK
15462306a36Sopenharmony_ci	cmp/hs	r5,r0
15562306a36Sopenharmony_ci	bf/s	3b
15662306a36Sopenharmony_ci	 mov.l	r3,@(r0,r4)
15762306a36Sopenharmony_ci#endif
15862306a36Sopenharmony_ci	add	#7,r5
15962306a36Sopenharmony_ci	!
16062306a36Sopenharmony_ci	! Third, copy a byte at once, if necessary
16162306a36Sopenharmony_ci	cmp/eq	r5,r0
16262306a36Sopenharmony_ci	bt/s	9b
16362306a36Sopenharmony_ci	 add	#7,r4
16462306a36Sopenharmony_ci	add	#-3,r0
16562306a36Sopenharmony_ci	bra	8b
16662306a36Sopenharmony_ci	 add	#-1,r4
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cicase2:
16962306a36Sopenharmony_ci	!
17062306a36Sopenharmony_ci	!	GHIJ KLMN OPQR -->  ..GH IJKL MNOP QR..
17162306a36Sopenharmony_ci	!
17262306a36Sopenharmony_ci	! First, align to word boundary
17362306a36Sopenharmony_ci	tst	#1,r0
17462306a36Sopenharmony_ci	bt/s	2f
17562306a36Sopenharmony_ci	 add	#-1,r4
17662306a36Sopenharmony_ci	mov.b	@r0+,r1
17762306a36Sopenharmony_ci	mov.b	r1,@(r0,r4)
17862306a36Sopenharmony_ci	!
17962306a36Sopenharmony_ci2:	! Second, read a word and write a word at once
18062306a36Sopenharmony_ci	add	#-1,r4
18162306a36Sopenharmony_ci	add	#-1,r5
18262306a36Sopenharmony_ci	!
18362306a36Sopenharmony_ci3:	mov.w	@r0+,r1
18462306a36Sopenharmony_ci	cmp/hs	r5,r0
18562306a36Sopenharmony_ci	bf/s	3b
18662306a36Sopenharmony_ci	 mov.w	r1,@(r0,r4)
18762306a36Sopenharmony_ci	add	#1,r5
18862306a36Sopenharmony_ci	!
18962306a36Sopenharmony_ci	! Third, copy a byte at once, if necessary
19062306a36Sopenharmony_ci	cmp/eq	r5,r0
19162306a36Sopenharmony_ci	bt/s	9b
19262306a36Sopenharmony_ci	 add	#2,r4
19362306a36Sopenharmony_ci	mov.b	@r0,r1
19462306a36Sopenharmony_ci	mov.b	r1,@(r0,r4)
19562306a36Sopenharmony_ci	bra	9b
19662306a36Sopenharmony_ci	 add	#1,r0
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cicase1:
19962306a36Sopenharmony_ci	!
20062306a36Sopenharmony_ci	!	GHIJ KLMN OPQR -->  .GHI JKLM NOPQ R...
20162306a36Sopenharmony_ci	!
20262306a36Sopenharmony_ci	! First, align to long word boundary
20362306a36Sopenharmony_ci	mov	r0,r3
20462306a36Sopenharmony_ci	and	r2,r3
20562306a36Sopenharmony_ci	tst	r3,r3
20662306a36Sopenharmony_ci	bt/s	2f
20762306a36Sopenharmony_ci	 add	#-1,r4
20862306a36Sopenharmony_ci	mov	#4,r2
20962306a36Sopenharmony_ci	sub	r3,r2
21062306a36Sopenharmony_ci1:	dt	r2
21162306a36Sopenharmony_ci	mov.b	@r0+,r1
21262306a36Sopenharmony_ci	bf/s	1b
21362306a36Sopenharmony_ci	 mov.b	r1,@(r0,r4)
21462306a36Sopenharmony_ci	!
21562306a36Sopenharmony_ci2:	! Second, read a long word and write a long word at once
21662306a36Sopenharmony_ci	mov.l	@(r0,r4),r1
21762306a36Sopenharmony_ci	add	#-7,r5
21862306a36Sopenharmony_ci	add	#-4,r4
21962306a36Sopenharmony_ci	!
22062306a36Sopenharmony_ci#ifdef __LITTLE_ENDIAN__
22162306a36Sopenharmony_ci	shll16	r1
22262306a36Sopenharmony_ci	shll8	r1
22362306a36Sopenharmony_ci3:	mov	r1,r3		! JIHG
22462306a36Sopenharmony_ci	shlr16	r3
22562306a36Sopenharmony_ci	shlr8	r3		! xxxJ
22662306a36Sopenharmony_ci	mov.l	@r0+,r1		! NMLK
22762306a36Sopenharmony_ci	mov	r1,r2
22862306a36Sopenharmony_ci	shll8	r2		! MLKx
22962306a36Sopenharmony_ci	or	r2,r3		! MLKJ
23062306a36Sopenharmony_ci	cmp/hs	r5,r0
23162306a36Sopenharmony_ci	bf/s	3b
23262306a36Sopenharmony_ci	 mov.l	r3,@(r0,r4)
23362306a36Sopenharmony_ci#else
23462306a36Sopenharmony_ci	shlr16	r1
23562306a36Sopenharmony_ci	shlr8	r1
23662306a36Sopenharmony_ci3:	mov	r1,r3		! GHIJ
23762306a36Sopenharmony_ci	shll16	r3
23862306a36Sopenharmony_ci	shll8	r3		! Jxxx
23962306a36Sopenharmony_ci	mov.l	@r0+,r1		! KLMN
24062306a36Sopenharmony_ci	mov	r1,r2
24162306a36Sopenharmony_ci	shlr8	r2		! xKLM
24262306a36Sopenharmony_ci	or	r2,r3		! JKLM
24362306a36Sopenharmony_ci	cmp/hs	r5,r0
24462306a36Sopenharmony_ci	bf/s	3b		! while(r0<r5)
24562306a36Sopenharmony_ci	 mov.l	r3,@(r0,r4)
24662306a36Sopenharmony_ci#endif
24762306a36Sopenharmony_ci	add	#7,r5
24862306a36Sopenharmony_ci	!
24962306a36Sopenharmony_ci	! Third, copy a byte at once, if necessary
25062306a36Sopenharmony_ci	cmp/eq	r5,r0
25162306a36Sopenharmony_ci	bt/s	9b
25262306a36Sopenharmony_ci	 add	#5,r4
25362306a36Sopenharmony_ci	add	#-3,r0
25462306a36Sopenharmony_ci	bra	8b
25562306a36Sopenharmony_ci	 add	#-1,r4
256