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