Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <private/bionic_asm.h>
     30 
     31     .syntax unified
     32 
     33     .thumb
     34     .thumb_func
     35 
     36     // To avoid warning about deprecated instructions, add an explicit
     37     // arch. The code generated is exactly the same.
     38     .arch armv7-a
     39 
     40 // Get the length of src string, then get the source of the dst string.
     41 // Check that the two lengths together don't exceed the threshold, then
     42 // do a memcpy of the data.
     43 ENTRY(__strcat_chk)
     44     pld     [r0, #0]
     45     push    {r0, lr}
     46     .cfi_def_cfa_offset 8
     47     .cfi_rel_offset r0, 0
     48     .cfi_rel_offset lr, 4
     49     push    {r4, r5}
     50     .cfi_adjust_cfa_offset 8
     51     .cfi_rel_offset r4, 0
     52     .cfi_rel_offset r5, 4
     53 
     54     mov     lr, r2
     55 
     56     // Save the dst register to r5
     57     mov     r5, r0
     58 
     59     // Zero out r4
     60     eor     r4, r4, r4
     61 
     62     // r1 contains the address of the string to count.
     63 .L_strlen_start:
     64     mov     r0, r1
     65     ands    r3, r1, #7
     66     beq     .L_mainloop
     67 
     68     // Align to a double word (64 bits).
     69     rsb     r3, r3, #8
     70     lsls    ip, r3, #31
     71     beq     .L_align_to_32
     72 
     73     ldrb    r2, [r1], #1
     74     cbz     r2, .L_update_count_and_finish
     75 
     76 .L_align_to_32:
     77     bcc     .L_align_to_64
     78     ands    ip, r3, #2
     79     beq     .L_align_to_64
     80 
     81     ldrb    r2, [r1], #1
     82     cbz     r2, .L_update_count_and_finish
     83     ldrb    r2, [r1], #1
     84     cbz     r2, .L_update_count_and_finish
     85 
     86 .L_align_to_64:
     87     tst     r3, #4
     88     beq     .L_mainloop
     89     ldr     r3, [r1], #4
     90 
     91     sub     ip, r3, #0x01010101
     92     bic     ip, ip, r3
     93     ands    ip, ip, #0x80808080
     94     bne     .L_zero_in_second_register
     95 
     96     .p2align 2
     97 .L_mainloop:
     98     ldrd    r2, r3, [r1], #8
     99 
    100     pld     [r1, #64]
    101 
    102     sub     ip, r2, #0x01010101
    103     bic     ip, ip, r2
    104     ands    ip, ip, #0x80808080
    105     bne     .L_zero_in_first_register
    106 
    107     sub     ip, r3, #0x01010101
    108     bic     ip, ip, r3
    109     ands    ip, ip, #0x80808080
    110     bne     .L_zero_in_second_register
    111     b       .L_mainloop
    112 
    113 .L_update_count_and_finish:
    114     sub     r3, r1, r0
    115     sub     r3, r3, #1
    116     b       .L_finish
    117 
    118 .L_zero_in_first_register:
    119     sub     r3, r1, r0
    120     lsls    r2, ip, #17
    121     bne     .L_sub8_and_finish
    122     bcs     .L_sub7_and_finish
    123     lsls    ip, ip, #1
    124     bne     .L_sub6_and_finish
    125 
    126     sub     r3, r3, #5
    127     b       .L_finish
    128 
    129 .L_sub8_and_finish:
    130     sub     r3, r3, #8
    131     b       .L_finish
    132 
    133 .L_sub7_and_finish:
    134     sub     r3, r3, #7
    135     b       .L_finish
    136 
    137 .L_sub6_and_finish:
    138     sub     r3, r3, #6
    139     b       .L_finish
    140 
    141 .L_zero_in_second_register:
    142     sub     r3, r1, r0
    143     lsls    r2, ip, #17
    144     bne     .L_sub4_and_finish
    145     bcs     .L_sub3_and_finish
    146     lsls    ip, ip, #1
    147     bne     .L_sub2_and_finish
    148 
    149     sub     r3, r3, #1
    150     b       .L_finish
    151 
    152 .L_sub4_and_finish:
    153     sub     r3, r3, #4
    154     b       .L_finish
    155 
    156 .L_sub3_and_finish:
    157     sub     r3, r3, #3
    158     b       .L_finish
    159 
    160 .L_sub2_and_finish:
    161     sub     r3, r3, #2
    162 
    163 .L_finish:
    164     cmp     r4, #0
    165     bne     .L_strlen_done
    166 
    167     // Time to get the dst string length.
    168     mov     r1, r5
    169 
    170     // Save the original source address to r5.
    171     mov     r5, r0
    172 
    173     // Save the current length (adding 1 for the terminator).
    174     add     r4, r3, #1
    175     b       .L_strlen_start
    176 
    177     // r0 holds the pointer to the dst string.
    178     // r3 holds the dst string length.
    179     // r4 holds the src string length + 1.
    180 .L_strlen_done:
    181     add     r2, r3, r4
    182     cmp     r2, lr
    183     itt     hi
    184     movhi   r0, lr
    185     bhi     __strcat_chk_fail
    186 
    187     // Set up the registers for the memcpy code.
    188     mov     r1, r5
    189     pld     [r1, #64]
    190     mov     r2, r4
    191     add     r0, r0, r3
    192     pop     {r4, r5}
    193     .cfi_adjust_cfa_offset -8
    194     .cfi_restore r4
    195     .cfi_restore r5
    196 
    197 #include "memcpy_base.S"
    198 
    199     // Undo the above cfi directives
    200     .cfi_adjust_cfa_offset 8
    201     .cfi_rel_offset r4, 0
    202     .cfi_rel_offset r5, 4
    203 END(__strcat_chk)
    204