| /* | |
| * linux/arch/m32r/strlen.S -- strlen code. | |
| * | |
| * Copyright (C) 2001 Hirokazu Takata | |
| * | |
| * size_t strlen(const char *s); | |
| * | |
| */ | |
| #include <linux/linkage.h> | |
| #include <asm/assembler.h> | |
| #ifdef CONFIG_ISA_DUAL_ISSUE | |
| .text | |
| ENTRY(strlen) | |
| mv r6, r0 || ldi r2, #0 | |
| and3 r0, r0, #3 | |
| bnez r0, strlen_byte | |
| ; | |
| strlen_word: | |
| ld r0, @r6+ | |
| ; | |
| seth r5, #high(0x01010101) | |
| or3 r5, r5, #low(0x01010101) | |
| sll3 r7, r5, #7 | |
| strlen_word_loop: | |
| ld r1, @r6+ || not r4, r0 | |
| sub r0, r5 || and r4, r7 | |
| and r4, r0 | |
| bnez r4, strlen_last_bytes | |
| ld r0, @r6+ || not r4, r1 | |
| sub r1, r5 || and r4, r7 | |
| and r4, r1 || addi r2, #4 | |
| bnez r4, strlen_last_bytes | |
| addi r2, #4 || bra.s strlen_word_loop | |
| ; NOTE: If a null char. exists, return 0. | |
| ; if ((x - 0x01010101) & ~x & 0x80808080) | |
| ; return 0; | |
| ; | |
| strlen_byte: | |
| ldb r1, @r6 || addi r6, #1 | |
| beqz r1, strlen_exit | |
| addi r2, #1 || bra.s strlen_byte | |
| ; | |
| strlen_last_bytes: | |
| ldi r0, #4 || addi r6, #-8 | |
| ; | |
| strlen_byte_loop: | |
| ldb r1, @r6 || addi r6, #1 | |
| addi r0, #-1 || cmpz r1 | |
| bc.s strlen_exit || cmpz r0 | |
| addi r2, #1 || bnc.s strlen_byte_loop | |
| ; | |
| strlen_exit: | |
| mv r0, r2 || jmp r14 | |
| #else /* not CONFIG_ISA_DUAL_ISSUE */ | |
| .text | |
| ENTRY(strlen) | |
| mv r6, r0 | |
| ldi r2, #0 | |
| and3 r0, r0, #3 | |
| bnez r0, strlen_byte | |
| ; | |
| strlen_word: | |
| ld r0, @r6+ | |
| ; | |
| seth r5, #high(0x01010101) | |
| or3 r5, r5, #low(0x01010101) | |
| sll3 r7, r5, #7 | |
| strlen_word_loop: | |
| ld r1, @r6+ | |
| not r4, r0 ; NOTE: If a null char. exists, return 0. | |
| sub r0, r5 ; if ((x - 0x01010101) & ~x & 0x80808080) | |
| and r4, r7 ; return 0; | |
| and r4, r0 | |
| bnez r4, strlen_last_bytes | |
| addi r2, #4 | |
| ; | |
| ld r0, @r6+ | |
| not r4, r1 ; NOTE: If a null char. exists, return 0. | |
| sub r1, r5 ; if ((x - 0x01010101) & ~x & 0x80808080) | |
| and r4, r7 ; return 0; | |
| and r4, r1 | |
| bnez r4, strlen_last_bytes | |
| addi r2, #4 | |
| bra strlen_word_loop | |
| ; | |
| strlen_byte: | |
| ldb r1, @r6 | |
| addi r6, #1 | |
| beqz r1, strlen_exit | |
| addi r2, #1 | |
| bra strlen_byte | |
| ; | |
| strlen_last_bytes: | |
| ldi r0, #4 | |
| addi r6, #-8 | |
| ; | |
| strlen_byte_loop: | |
| ldb r1, @r6 | |
| addi r6, #1 | |
| addi r0, #-1 | |
| beqz r1, strlen_exit | |
| addi r2, #1 | |
| bnez r0, strlen_byte_loop | |
| ; | |
| strlen_exit: | |
| mv r0, r2 | |
| jmp r14 | |
| #endif /* not CONFIG_ISA_DUAL_ISSUE */ | |
| .end |