| /* SPDX-License-Identifier: GPL-2.0-or-later */ | |
| /* | |
| * Copyright (C) Paul Mackerras 1997. | |
| * | |
| * NOTE: this code runs in 32 bit mode and is packaged as ELF32. | |
| */ | |
| #include "ppc_asm.h" | |
| .text | |
| .globl strcpy | |
| strcpy: | |
| addi r5,r3,-1 | |
| addi r4,r4,-1 | |
| 1: lbzu r0,1(r4) | |
| cmpwi 0,r0,0 | |
| stbu r0,1(r5) | |
| bne 1b | |
| blr | |
| .globl strncpy | |
| strncpy: | |
| cmpwi 0,r5,0 | |
| beqlr | |
| mtctr r5 | |
| addi r6,r3,-1 | |
| addi r4,r4,-1 | |
| 1: lbzu r0,1(r4) | |
| cmpwi 0,r0,0 | |
| stbu r0,1(r6) | |
| bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */ | |
| blr | |
| .globl strcat | |
| strcat: | |
| addi r5,r3,-1 | |
| addi r4,r4,-1 | |
| 1: lbzu r0,1(r5) | |
| cmpwi 0,r0,0 | |
| bne 1b | |
| addi r5,r5,-1 | |
| 1: lbzu r0,1(r4) | |
| cmpwi 0,r0,0 | |
| stbu r0,1(r5) | |
| bne 1b | |
| blr | |
| .globl strchr | |
| strchr: | |
| addi r3,r3,-1 | |
| 1: lbzu r0,1(r3) | |
| cmpw 0,r0,r4 | |
| beqlr | |
| cmpwi 0,r0,0 | |
| bne 1b | |
| li r3,0 | |
| blr | |
| .globl strcmp | |
| strcmp: | |
| addi r5,r3,-1 | |
| addi r4,r4,-1 | |
| 1: lbzu r3,1(r5) | |
| cmpwi 1,r3,0 | |
| lbzu r0,1(r4) | |
| subf. r3,r0,r3 | |
| beqlr 1 | |
| beq 1b | |
| blr | |
| .globl strncmp | |
| strncmp: | |
| mtctr r5 | |
| addi r5,r3,-1 | |
| addi r4,r4,-1 | |
| 1: lbzu r3,1(r5) | |
| cmpwi 1,r3,0 | |
| lbzu r0,1(r4) | |
| subf. r3,r0,r3 | |
| beqlr 1 | |
| bdnzt eq,1b | |
| blr | |
| .globl strlen | |
| strlen: | |
| addi r4,r3,-1 | |
| 1: lbzu r0,1(r4) | |
| cmpwi 0,r0,0 | |
| bne 1b | |
| subf r3,r3,r4 | |
| blr | |
| .globl memset | |
| memset: | |
| rlwimi r4,r4,8,16,23 | |
| rlwimi r4,r4,16,0,15 | |
| addi r6,r3,-4 | |
| cmplwi 0,r5,4 | |
| blt 7f | |
| stwu r4,4(r6) | |
| beqlr | |
| andi. r0,r6,3 | |
| add r5,r0,r5 | |
| subf r6,r0,r6 | |
| rlwinm r0,r5,32-2,2,31 | |
| mtctr r0 | |
| bdz 6f | |
| 1: stwu r4,4(r6) | |
| bdnz 1b | |
| 6: andi. r5,r5,3 | |
| 7: cmpwi 0,r5,0 | |
| beqlr | |
| mtctr r5 | |
| addi r6,r6,3 | |
| 8: stbu r4,1(r6) | |
| bdnz 8b | |
| blr | |
| .globl memmove | |
| memmove: | |
| cmplw 0,r3,r4 | |
| bgt backwards_memcpy | |
| /* fall through */ | |
| .globl memcpy | |
| memcpy: | |
| rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */ | |
| addi r6,r3,-4 | |
| addi r4,r4,-4 | |
| beq 3f /* if less than 8 bytes to do */ | |
| andi. r0,r6,3 /* get dest word aligned */ | |
| mtctr r7 | |
| bne 5f | |
| andi. r0,r4,3 /* check src word aligned too */ | |
| bne 3f | |
| 1: lwz r7,4(r4) | |
| lwzu r8,8(r4) | |
| stw r7,4(r6) | |
| stwu r8,8(r6) | |
| bdnz 1b | |
| andi. r5,r5,7 | |
| 2: cmplwi 0,r5,4 | |
| blt 3f | |
| lwzu r0,4(r4) | |
| addi r5,r5,-4 | |
| stwu r0,4(r6) | |
| 3: cmpwi 0,r5,0 | |
| beqlr | |
| mtctr r5 | |
| addi r4,r4,3 | |
| addi r6,r6,3 | |
| 4: lbzu r0,1(r4) | |
| stbu r0,1(r6) | |
| bdnz 4b | |
| blr | |
| 5: subfic r0,r0,4 | |
| cmpw cr1,r0,r5 | |
| add r7,r0,r4 | |
| andi. r7,r7,3 /* will source be word-aligned too? */ | |
| ble cr1,3b | |
| bne 3b /* do byte-by-byte if not */ | |
| mtctr r0 | |
| 6: lbz r7,4(r4) | |
| addi r4,r4,1 | |
| stb r7,4(r6) | |
| addi r6,r6,1 | |
| bdnz 6b | |
| subf r5,r0,r5 | |
| rlwinm. r7,r5,32-3,3,31 | |
| beq 2b | |
| mtctr r7 | |
| b 1b | |
| .globl backwards_memcpy | |
| backwards_memcpy: | |
| rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */ | |
| add r6,r3,r5 | |
| add r4,r4,r5 | |
| beq 3f | |
| andi. r0,r6,3 | |
| mtctr r7 | |
| bne 5f | |
| andi. r0,r4,3 | |
| bne 3f | |
| 1: lwz r7,-4(r4) | |
| lwzu r8,-8(r4) | |
| stw r7,-4(r6) | |
| stwu r8,-8(r6) | |
| bdnz 1b | |
| andi. r5,r5,7 | |
| 2: cmplwi 0,r5,4 | |
| blt 3f | |
| lwzu r0,-4(r4) | |
| subi r5,r5,4 | |
| stwu r0,-4(r6) | |
| 3: cmpwi 0,r5,0 | |
| beqlr | |
| mtctr r5 | |
| 4: lbzu r0,-1(r4) | |
| stbu r0,-1(r6) | |
| bdnz 4b | |
| blr | |
| 5: cmpw cr1,r0,r5 | |
| subf r7,r0,r4 | |
| andi. r7,r7,3 | |
| ble cr1,3b | |
| bne 3b | |
| mtctr r0 | |
| 6: lbzu r7,-1(r4) | |
| stbu r7,-1(r6) | |
| bdnz 6b | |
| subf r5,r0,r5 | |
| rlwinm. r7,r5,32-3,3,31 | |
| beq 2b | |
| mtctr r7 | |
| b 1b | |
| .globl memchr | |
| memchr: | |
| cmpwi 0,r5,0 | |
| blelr | |
| mtctr r5 | |
| addi r3,r3,-1 | |
| 1: lbzu r0,1(r3) | |
| cmpw r0,r4 | |
| beqlr | |
| bdnz 1b | |
| li r3,0 | |
| blr | |
| .globl memcmp | |
| memcmp: | |
| cmpwi 0,r5,0 | |
| ble 2f | |
| mtctr r5 | |
| addi r6,r3,-1 | |
| addi r4,r4,-1 | |
| 1: lbzu r3,1(r6) | |
| lbzu r0,1(r4) | |
| subf. r3,r0,r3 | |
| bdnzt 2,1b | |
| blr | |
| 2: li r3,0 | |
| blr | |
| /* | |
| * Flush the dcache and invalidate the icache for a range of addresses. | |
| * | |
| * flush_cache(addr, len) | |
| */ | |
| .global flush_cache | |
| flush_cache: | |
| addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */ | |
| rlwinm. 4,4,27,5,31 | |
| mtctr 4 | |
| beqlr | |
| 1: dcbf 0,3 | |
| icbi 0,3 | |
| addi 3,3,0x20 | |
| bdnz 1b | |
| sync | |
| isync | |
| blr | |