OSDN Git Service

Optimize __memset_chk, __memcpy_chk.
[android-x86/bionic.git] / libc / arch-arm / krait / bionic / memcpy.S
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 /* Assumes neon instructions and a cache line size of 32 bytes. */
30
31 #include <machine/cpu-features.h>
32 #include <machine/asm.h>
33 #include "libc_events.h"
34
35 /*
36  * This code assumes it is running on a processor that supports all arm v7
37  * instructions, that supports neon instructions, and that has a 32 byte
38  * cache line.
39  */
40
41 #define CACHE_LINE_SIZE     32
42
43         .text
44         .fpu    neon
45
46 ENTRY(__memcpy_chk)
47         cmp         r2, r3
48         bgt         fortify_check_failed
49
50         // Fall through to memcpy...
51 END(__memcpy_chk)
52
53 ENTRY(memcpy)
54         .save       {r0, lr}
55         /* start preloading as early as possible */
56         pld         [r1, #(CACHE_LINE_SIZE*4)]
57         stmfd       sp!, {r0, lr}
58
59         /* do we have at least 16-bytes to copy (needed for alignment below) */
60         cmp         r2, #16
61         blo         5f
62
63         /* align destination to cache-line for the write-buffer */
64         rsb         r3, r0, #0
65         ands        r3, r3, #0xF
66         beq         2f
67
68         /* copy up to 15-bytes (count in r3) */
69         sub         r2, r2, r3
70         movs        ip, r3, lsl #31
71         ldrmib      lr, [r1], #1
72         strmib      lr, [r0], #1
73         ldrcsb      ip, [r1], #1
74         ldrcsb      lr, [r1], #1
75         strcsb      ip, [r0], #1
76         strcsb      lr, [r0], #1
77         movs        ip, r3, lsl #29
78         bge         1f
79         // copies 4 bytes, destination 32-bits aligned
80         vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]!
81         vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
82 1:      bcc         2f
83         // copies 8 bytes, destination 64-bits aligned
84         vld1.8      {d0}, [r1]!
85         vst1.8      {d0}, [r0, :64]!
86
87 2:      /* make sure we have at least 64 bytes to copy */
88         subs        r2, r2, #64
89         blo         2f
90
91 1:      /* The main loop copies 64 bytes at a time */
92         vld1.8      {d0  - d3},   [r1]!
93         vld1.8      {d4  - d7},   [r1]!
94         pld         [r1, #(CACHE_LINE_SIZE*2)]
95         subs        r2, r2, #64
96         vst1.8      {d0  - d3},   [r0, :128]!
97         vst1.8      {d4  - d7},   [r0, :128]!
98         bhs         1b
99
100 2:      /* fix-up the remaining count and make sure we have >= 32 bytes left */
101         adds        r2, r2, #32
102         blo         4f
103
104         /* Copy 32 bytes. These cache lines were already preloaded */
105         vld1.8      {d0 - d3},  [r1]!
106         sub         r2, r2, #32
107         vst1.8      {d0 - d3},  [r0, :128]!
108
109 4:      /* less than 32 left */
110         add         r2, r2, #32
111         tst         r2, #0x10
112         beq         5f
113         // copies 16 bytes, 128-bits aligned
114         vld1.8      {d0, d1}, [r1]!
115         vst1.8      {d0, d1}, [r0, :128]!
116
117 5:      /* copy up to 15-bytes (count in r2) */
118         movs        ip, r2, lsl #29
119         bcc         1f
120         vld1.8      {d0}, [r1]!
121         vst1.8      {d0}, [r0]!
122 1:      bge         2f
123         vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]!
124         vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0]!
125 2:      movs        ip, r2, lsl #31
126         ldrmib      r3, [r1], #1
127         ldrcsb      ip, [r1], #1
128         ldrcsb      lr, [r1], #1
129         strmib      r3, [r0], #1
130         strcsb      ip, [r0], #1
131         strcsb      lr, [r0], #1
132
133         ldmfd       sp!, {r0, lr}
134         bx          lr
135
136         // Only reached when the __memcpy_chk check fails.
137 fortify_check_failed:
138         ldr     r0, error_message
139         ldr     r1, error_code
140 1:
141         add     r0, pc
142         bl      __fortify_chk_fail
143 error_code:
144         .word   BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
145 error_message:
146         .word   error_string-(1b+8)
147 END(memcpy)
148
149         .data
150 error_string:
151         .string     "memcpy buffer overflow"