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 <machine/cpu-features.h> 30#include <private/bionic_asm.h> 31#include <private/libc_events.h> 32 33 /* 34 * Optimized memset() for ARM. 35 * 36 * memset() returns its first argument. 37 */ 38 39 .fpu neon 40 .syntax unified 41 42ENTRY(__memset_chk) 43 cmp r2, r3 44 bls .L_done 45 46 // Preserve lr for backtrace. 47 push {lr} 48 .cfi_def_cfa_offset 4 49 .cfi_rel_offset lr, 0 50 51 ldr r0, error_message 52 ldr r1, error_code 531: 54 add r0, pc 55 bl __fortify_chk_fail 56error_code: 57 .word BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW 58error_message: 59 .word error_string-(1b+8) 60END(__memset_chk) 61 62ENTRY(bzero) 63 mov r2, r1 64 mov r1, #0 65.L_done: 66 // Fall through to memset... 67END(bzero) 68 69ENTRY(memset) 70 mov r3, r0 71 // At this point only d0, d1 are going to be used below. 72 vdup.8 q0, r1 73 cmp r2, #16 74 blo .L_set_less_than_16_unknown_align 75 76.L_check_alignment: 77 // Align destination to a double word to avoid the store crossing 78 // a cache line boundary. 79 ands ip, r3, #7 80 bne .L_do_double_word_align 81 82.L_double_word_aligned: 83 // Duplicate since the less than 64 can use d2, d3. 84 vmov q1, q0 85 subs r2, #64 86 blo .L_set_less_than_64 87 88 // Duplicate the copy value so that we can store 64 bytes at a time. 89 vmov q2, q0 90 vmov q3, q0 91 921: // Main loop stores 64 bytes at a time. 93 subs r2, #64 94 vstmia r3!, {d0 - d7} 95 bge 1b 96 97.L_set_less_than_64: 98 // Restore r2 to the count of bytes left to set. 99 add r2, #64 100 lsls ip, r2, #27 101 bcc .L_set_less_than_32 102 // Set 32 bytes. 103 vstmia r3!, {d0 - d3} 104 105.L_set_less_than_32: 106 bpl .L_set_less_than_16 107 // Set 16 bytes. 108 vstmia r3!, {d0, d1} 109 110.L_set_less_than_16: 111 // Less than 16 bytes to set. 112 lsls ip, r2, #29 113 bcc .L_set_less_than_8 114 115 // Set 8 bytes. 116 vstmia r3!, {d0} 117 118.L_set_less_than_8: 119 bpl .L_set_less_than_4 120 // Set 4 bytes 121 vst1.32 {d0[0]}, [r3]! 122 123.L_set_less_than_4: 124 lsls ip, r2, #31 125 it ne 126 strbne r1, [r3], #1 127 itt cs 128 strbcs r1, [r3], #1 129 strbcs r1, [r3] 130 bx lr 131 132.L_do_double_word_align: 133 rsb ip, ip, #8 134 sub r2, r2, ip 135 136 // Do this comparison now, otherwise we'll need to save a 137 // register to the stack since we've used all available 138 // registers. 139 cmp ip, #4 140 blo 1f 141 142 // Need to do a four byte copy. 143 movs ip, ip, lsl #31 144 it mi 145 strbmi r1, [r3], #1 146 itt cs 147 strbcs r1, [r3], #1 148 strbcs r1, [r3], #1 149 vst1.32 {d0[0]}, [r3]! 150 b .L_double_word_aligned 151 1521: 153 // No four byte copy. 154 movs ip, ip, lsl #31 155 it mi 156 strbmi r1, [r3], #1 157 itt cs 158 strbcs r1, [r3], #1 159 strbcs r1, [r3], #1 160 b .L_double_word_aligned 161 162.L_set_less_than_16_unknown_align: 163 // Set up to 15 bytes. 164 movs ip, r2, lsl #29 165 bcc 1f 166 vst1.8 {d0}, [r3]! 1671: bge 2f 168 vst1.32 {d0[0]}, [r3]! 1692: movs ip, r2, lsl #31 170 it mi 171 strbmi r1, [r3], #1 172 itt cs 173 strbcs r1, [r3], #1 174 strbcs r1, [r3], #1 175 bx lr 176END(memset) 177 178 .data 179error_string: 180 .string "memset: prevented write past end of buffer" 181