1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * linux/arch/m32r/strlen.S -- strlen code. 4 * 5 * Copyright (C) 2001 Hirokazu Takata 6 * 7 * size_t strlen(const char *s); 8 * 9 */ 10 11#include <linux/linkage.h> 12#include <asm/assembler.h> 13 14#ifdef CONFIG_ISA_DUAL_ISSUE 15 16 .text 17ENTRY(strlen) 18 mv r6, r0 || ldi r2, #0 19 and3 r0, r0, #3 20 bnez r0, strlen_byte 21; 22strlen_word: 23 ld r0, @r6+ 24; 25 seth r5, #high(0x01010101) 26 or3 r5, r5, #low(0x01010101) 27 sll3 r7, r5, #7 28strlen_word_loop: 29 ld r1, @r6+ || not r4, r0 30 sub r0, r5 || and r4, r7 31 and r4, r0 32 bnez r4, strlen_last_bytes 33 ld r0, @r6+ || not r4, r1 34 sub r1, r5 || and r4, r7 35 and r4, r1 || addi r2, #4 36 bnez r4, strlen_last_bytes 37 addi r2, #4 || bra.s strlen_word_loop 38 39 ; NOTE: If a null char. exists, return 0. 40 ; if ((x - 0x01010101) & ~x & 0x80808080) 41 ; return 0; 42; 43strlen_byte: 44 ldb r1, @r6 || addi r6, #1 45 beqz r1, strlen_exit 46 addi r2, #1 || bra.s strlen_byte 47; 48strlen_last_bytes: 49 ldi r0, #4 || addi r6, #-8 50; 51strlen_byte_loop: 52 ldb r1, @r6 || addi r6, #1 53 addi r0, #-1 || cmpz r1 54 bc.s strlen_exit || cmpz r0 55 addi r2, #1 || bnc.s strlen_byte_loop 56; 57strlen_exit: 58 mv r0, r2 || jmp r14 59 60#else /* not CONFIG_ISA_DUAL_ISSUE */ 61 62 .text 63ENTRY(strlen) 64 mv r6, r0 65 ldi r2, #0 66 and3 r0, r0, #3 67 bnez r0, strlen_byte 68; 69strlen_word: 70 ld r0, @r6+ 71; 72 seth r5, #high(0x01010101) 73 or3 r5, r5, #low(0x01010101) 74 sll3 r7, r5, #7 75strlen_word_loop: 76 ld r1, @r6+ 77 not r4, r0 ; NOTE: If a null char. exists, return 0. 78 sub r0, r5 ; if ((x - 0x01010101) & ~x & 0x80808080) 79 and r4, r7 ; return 0; 80 and r4, r0 81 bnez r4, strlen_last_bytes 82 addi r2, #4 83; 84 ld r0, @r6+ 85 not r4, r1 ; NOTE: If a null char. exists, return 0. 86 sub r1, r5 ; if ((x - 0x01010101) & ~x & 0x80808080) 87 and r4, r7 ; return 0; 88 and r4, r1 89 bnez r4, strlen_last_bytes 90 addi r2, #4 91 bra strlen_word_loop 92; 93strlen_byte: 94 ldb r1, @r6 95 addi r6, #1 96 beqz r1, strlen_exit 97 addi r2, #1 98 bra strlen_byte 99; 100strlen_last_bytes: 101 ldi r0, #4 102 addi r6, #-8 103; 104strlen_byte_loop: 105 ldb r1, @r6 106 addi r6, #1 107 addi r0, #-1 108 beqz r1, strlen_exit 109 addi r2, #1 110 bnez r0, strlen_byte_loop 111; 112strlen_exit: 113 mv r0, r2 114 jmp r14 115 116#endif /* not CONFIG_ISA_DUAL_ISSUE */ 117 118 .end 119