162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) Paul Mackerras 1997.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * NOTE: this code runs in 32 bit mode and is packaged as ELF32.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "ppc_asm.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci	.text
1162306a36Sopenharmony_ci	.globl	strcpy
1262306a36Sopenharmony_cistrcpy:
1362306a36Sopenharmony_ci	addi	r5,r3,-1
1462306a36Sopenharmony_ci	addi	r4,r4,-1
1562306a36Sopenharmony_ci1:	lbzu	r0,1(r4)
1662306a36Sopenharmony_ci	cmpwi	0,r0,0
1762306a36Sopenharmony_ci	stbu	r0,1(r5)
1862306a36Sopenharmony_ci	bne	1b
1962306a36Sopenharmony_ci	blr
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	.globl	strncpy
2262306a36Sopenharmony_cistrncpy:
2362306a36Sopenharmony_ci	cmpwi	0,r5,0
2462306a36Sopenharmony_ci	beqlr
2562306a36Sopenharmony_ci	mtctr	r5
2662306a36Sopenharmony_ci	addi	r6,r3,-1
2762306a36Sopenharmony_ci	addi	r4,r4,-1
2862306a36Sopenharmony_ci1:	lbzu	r0,1(r4)
2962306a36Sopenharmony_ci	cmpwi	0,r0,0
3062306a36Sopenharmony_ci	stbu	r0,1(r6)
3162306a36Sopenharmony_ci	bdnzf	2,1b		/* dec ctr, branch if ctr != 0 && !cr0.eq */
3262306a36Sopenharmony_ci	blr
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	.globl	strcat
3562306a36Sopenharmony_cistrcat:
3662306a36Sopenharmony_ci	addi	r5,r3,-1
3762306a36Sopenharmony_ci	addi	r4,r4,-1
3862306a36Sopenharmony_ci1:	lbzu	r0,1(r5)
3962306a36Sopenharmony_ci	cmpwi	0,r0,0
4062306a36Sopenharmony_ci	bne	1b
4162306a36Sopenharmony_ci	addi	r5,r5,-1
4262306a36Sopenharmony_ci1:	lbzu	r0,1(r4)
4362306a36Sopenharmony_ci	cmpwi	0,r0,0
4462306a36Sopenharmony_ci	stbu	r0,1(r5)
4562306a36Sopenharmony_ci	bne	1b
4662306a36Sopenharmony_ci	blr
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	.globl	strchr
4962306a36Sopenharmony_cistrchr:
5062306a36Sopenharmony_ci	addi	r3,r3,-1
5162306a36Sopenharmony_ci1:	lbzu	r0,1(r3)
5262306a36Sopenharmony_ci	cmpw	0,r0,r4
5362306a36Sopenharmony_ci	beqlr
5462306a36Sopenharmony_ci	cmpwi	0,r0,0
5562306a36Sopenharmony_ci	bne	1b
5662306a36Sopenharmony_ci	li	r3,0
5762306a36Sopenharmony_ci	blr
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	.globl	strcmp
6062306a36Sopenharmony_cistrcmp:
6162306a36Sopenharmony_ci	addi	r5,r3,-1
6262306a36Sopenharmony_ci	addi	r4,r4,-1
6362306a36Sopenharmony_ci1:	lbzu	r3,1(r5)
6462306a36Sopenharmony_ci	cmpwi	1,r3,0
6562306a36Sopenharmony_ci	lbzu	r0,1(r4)
6662306a36Sopenharmony_ci	subf.	r3,r0,r3
6762306a36Sopenharmony_ci	beqlr	1
6862306a36Sopenharmony_ci	beq	1b
6962306a36Sopenharmony_ci	blr
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	.globl	strncmp
7262306a36Sopenharmony_cistrncmp:
7362306a36Sopenharmony_ci	mtctr	r5
7462306a36Sopenharmony_ci	addi	r5,r3,-1
7562306a36Sopenharmony_ci	addi	r4,r4,-1
7662306a36Sopenharmony_ci1:	lbzu	r3,1(r5)
7762306a36Sopenharmony_ci	cmpwi	1,r3,0
7862306a36Sopenharmony_ci	lbzu	r0,1(r4)
7962306a36Sopenharmony_ci	subf.	r3,r0,r3
8062306a36Sopenharmony_ci	beqlr	1
8162306a36Sopenharmony_ci	bdnzt	eq,1b
8262306a36Sopenharmony_ci	blr
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	.globl	strlen
8562306a36Sopenharmony_cistrlen:
8662306a36Sopenharmony_ci	addi	r4,r3,-1
8762306a36Sopenharmony_ci1:	lbzu	r0,1(r4)
8862306a36Sopenharmony_ci	cmpwi	0,r0,0
8962306a36Sopenharmony_ci	bne	1b
9062306a36Sopenharmony_ci	subf	r3,r3,r4
9162306a36Sopenharmony_ci	blr
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	.globl	memset
9462306a36Sopenharmony_cimemset:
9562306a36Sopenharmony_ci	rlwimi	r4,r4,8,16,23
9662306a36Sopenharmony_ci	rlwimi	r4,r4,16,0,15
9762306a36Sopenharmony_ci	addi	r6,r3,-4
9862306a36Sopenharmony_ci	cmplwi	0,r5,4
9962306a36Sopenharmony_ci	blt	7f
10062306a36Sopenharmony_ci	stwu	r4,4(r6)
10162306a36Sopenharmony_ci	beqlr
10262306a36Sopenharmony_ci	andi.	r0,r6,3
10362306a36Sopenharmony_ci	add	r5,r0,r5
10462306a36Sopenharmony_ci	subf	r6,r0,r6
10562306a36Sopenharmony_ci	rlwinm	r0,r5,32-2,2,31
10662306a36Sopenharmony_ci	mtctr	r0
10762306a36Sopenharmony_ci	bdz	6f
10862306a36Sopenharmony_ci1:	stwu	r4,4(r6)
10962306a36Sopenharmony_ci	bdnz	1b
11062306a36Sopenharmony_ci6:	andi.	r5,r5,3
11162306a36Sopenharmony_ci7:	cmpwi	0,r5,0
11262306a36Sopenharmony_ci	beqlr
11362306a36Sopenharmony_ci	mtctr	r5
11462306a36Sopenharmony_ci	addi	r6,r6,3
11562306a36Sopenharmony_ci8:	stbu	r4,1(r6)
11662306a36Sopenharmony_ci	bdnz	8b
11762306a36Sopenharmony_ci	blr
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	.globl	memmove
12062306a36Sopenharmony_cimemmove:
12162306a36Sopenharmony_ci	cmplw	0,r3,r4
12262306a36Sopenharmony_ci	bgt	backwards_memcpy
12362306a36Sopenharmony_ci	/* fall through */
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	.globl	memcpy
12662306a36Sopenharmony_cimemcpy:
12762306a36Sopenharmony_ci	rlwinm.	r7,r5,32-3,3,31		/* r7 = r5 >> 3 */
12862306a36Sopenharmony_ci	addi	r6,r3,-4
12962306a36Sopenharmony_ci	addi	r4,r4,-4
13062306a36Sopenharmony_ci	beq	3f			/* if less than 8 bytes to do */
13162306a36Sopenharmony_ci	andi.	r0,r6,3			/* get dest word aligned */
13262306a36Sopenharmony_ci	mtctr	r7
13362306a36Sopenharmony_ci	bne	5f
13462306a36Sopenharmony_ci	andi.	r0,r4,3			/* check src word aligned too */
13562306a36Sopenharmony_ci	bne	3f
13662306a36Sopenharmony_ci1:	lwz	r7,4(r4)
13762306a36Sopenharmony_ci	lwzu	r8,8(r4)
13862306a36Sopenharmony_ci	stw	r7,4(r6)
13962306a36Sopenharmony_ci	stwu	r8,8(r6)
14062306a36Sopenharmony_ci	bdnz	1b
14162306a36Sopenharmony_ci	andi.	r5,r5,7
14262306a36Sopenharmony_ci2:	cmplwi	0,r5,4
14362306a36Sopenharmony_ci	blt	3f
14462306a36Sopenharmony_ci	lwzu	r0,4(r4)
14562306a36Sopenharmony_ci	addi	r5,r5,-4
14662306a36Sopenharmony_ci	stwu	r0,4(r6)
14762306a36Sopenharmony_ci3:	cmpwi	0,r5,0
14862306a36Sopenharmony_ci	beqlr
14962306a36Sopenharmony_ci	mtctr	r5
15062306a36Sopenharmony_ci	addi	r4,r4,3
15162306a36Sopenharmony_ci	addi	r6,r6,3
15262306a36Sopenharmony_ci4:	lbzu	r0,1(r4)
15362306a36Sopenharmony_ci	stbu	r0,1(r6)
15462306a36Sopenharmony_ci	bdnz	4b
15562306a36Sopenharmony_ci	blr
15662306a36Sopenharmony_ci5:	subfic	r0,r0,4
15762306a36Sopenharmony_ci	cmpw	cr1,r0,r5
15862306a36Sopenharmony_ci	add	r7,r0,r4
15962306a36Sopenharmony_ci	andi.	r7,r7,3			/* will source be word-aligned too? */
16062306a36Sopenharmony_ci	ble	cr1,3b
16162306a36Sopenharmony_ci	bne	3b			/* do byte-by-byte if not */
16262306a36Sopenharmony_ci	mtctr	r0
16362306a36Sopenharmony_ci6:	lbz	r7,4(r4)
16462306a36Sopenharmony_ci	addi	r4,r4,1
16562306a36Sopenharmony_ci	stb	r7,4(r6)
16662306a36Sopenharmony_ci	addi	r6,r6,1
16762306a36Sopenharmony_ci	bdnz	6b
16862306a36Sopenharmony_ci	subf	r5,r0,r5
16962306a36Sopenharmony_ci	rlwinm.	r7,r5,32-3,3,31
17062306a36Sopenharmony_ci	beq	2b
17162306a36Sopenharmony_ci	mtctr	r7
17262306a36Sopenharmony_ci	b	1b
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	.globl	backwards_memcpy
17562306a36Sopenharmony_cibackwards_memcpy:
17662306a36Sopenharmony_ci	rlwinm.	r7,r5,32-3,3,31		/* r7 = r5 >> 3 */
17762306a36Sopenharmony_ci	add	r6,r3,r5
17862306a36Sopenharmony_ci	add	r4,r4,r5
17962306a36Sopenharmony_ci	beq	3f
18062306a36Sopenharmony_ci	andi.	r0,r6,3
18162306a36Sopenharmony_ci	mtctr	r7
18262306a36Sopenharmony_ci	bne	5f
18362306a36Sopenharmony_ci	andi.	r0,r4,3
18462306a36Sopenharmony_ci	bne	3f
18562306a36Sopenharmony_ci1:	lwz	r7,-4(r4)
18662306a36Sopenharmony_ci	lwzu	r8,-8(r4)
18762306a36Sopenharmony_ci	stw	r7,-4(r6)
18862306a36Sopenharmony_ci	stwu	r8,-8(r6)
18962306a36Sopenharmony_ci	bdnz	1b
19062306a36Sopenharmony_ci	andi.	r5,r5,7
19162306a36Sopenharmony_ci2:	cmplwi	0,r5,4
19262306a36Sopenharmony_ci	blt	3f
19362306a36Sopenharmony_ci	lwzu	r0,-4(r4)
19462306a36Sopenharmony_ci	subi	r5,r5,4
19562306a36Sopenharmony_ci	stwu	r0,-4(r6)
19662306a36Sopenharmony_ci3:	cmpwi	0,r5,0
19762306a36Sopenharmony_ci	beqlr
19862306a36Sopenharmony_ci	mtctr	r5
19962306a36Sopenharmony_ci4:	lbzu	r0,-1(r4)
20062306a36Sopenharmony_ci	stbu	r0,-1(r6)
20162306a36Sopenharmony_ci	bdnz	4b
20262306a36Sopenharmony_ci	blr
20362306a36Sopenharmony_ci5:	cmpw	cr1,r0,r5
20462306a36Sopenharmony_ci	subf	r7,r0,r4
20562306a36Sopenharmony_ci	andi.	r7,r7,3
20662306a36Sopenharmony_ci	ble	cr1,3b
20762306a36Sopenharmony_ci	bne	3b
20862306a36Sopenharmony_ci	mtctr	r0
20962306a36Sopenharmony_ci6:	lbzu	r7,-1(r4)
21062306a36Sopenharmony_ci	stbu	r7,-1(r6)
21162306a36Sopenharmony_ci	bdnz	6b
21262306a36Sopenharmony_ci	subf	r5,r0,r5
21362306a36Sopenharmony_ci	rlwinm.	r7,r5,32-3,3,31
21462306a36Sopenharmony_ci	beq	2b
21562306a36Sopenharmony_ci	mtctr	r7
21662306a36Sopenharmony_ci	b	1b
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	.globl	memchr
21962306a36Sopenharmony_cimemchr:
22062306a36Sopenharmony_ci	cmpwi	0,r5,0
22162306a36Sopenharmony_ci	blelr
22262306a36Sopenharmony_ci	mtctr	r5
22362306a36Sopenharmony_ci	addi	r3,r3,-1
22462306a36Sopenharmony_ci1:	lbzu	r0,1(r3)
22562306a36Sopenharmony_ci	cmpw	r0,r4
22662306a36Sopenharmony_ci	beqlr
22762306a36Sopenharmony_ci	bdnz	1b
22862306a36Sopenharmony_ci	li	r3,0
22962306a36Sopenharmony_ci	blr
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	.globl	memcmp
23262306a36Sopenharmony_cimemcmp:
23362306a36Sopenharmony_ci	cmpwi	0,r5,0
23462306a36Sopenharmony_ci	ble	2f
23562306a36Sopenharmony_ci	mtctr	r5
23662306a36Sopenharmony_ci	addi	r6,r3,-1
23762306a36Sopenharmony_ci	addi	r4,r4,-1
23862306a36Sopenharmony_ci1:	lbzu	r3,1(r6)
23962306a36Sopenharmony_ci	lbzu	r0,1(r4)
24062306a36Sopenharmony_ci	subf.	r3,r0,r3
24162306a36Sopenharmony_ci	bdnzt	2,1b
24262306a36Sopenharmony_ci	blr
24362306a36Sopenharmony_ci2:	li	r3,0
24462306a36Sopenharmony_ci	blr
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci/*
24862306a36Sopenharmony_ci * Flush the dcache and invalidate the icache for a range of addresses.
24962306a36Sopenharmony_ci *
25062306a36Sopenharmony_ci * flush_cache(addr, len)
25162306a36Sopenharmony_ci */
25262306a36Sopenharmony_ci	.global	flush_cache
25362306a36Sopenharmony_ciflush_cache:
25462306a36Sopenharmony_ci	addi	4,4,0x1f	/* len = (len + 0x1f) / 0x20 */
25562306a36Sopenharmony_ci	rlwinm.	4,4,27,5,31
25662306a36Sopenharmony_ci	mtctr	4
25762306a36Sopenharmony_ci	beqlr
25862306a36Sopenharmony_ci1:	dcbf	0,3
25962306a36Sopenharmony_ci	icbi	0,3
26062306a36Sopenharmony_ci	addi	3,3,0x20
26162306a36Sopenharmony_ci	bdnz	1b
26262306a36Sopenharmony_ci	sync
26362306a36Sopenharmony_ci	isync
26462306a36Sopenharmony_ci	blr
26562306a36Sopenharmony_ci
266