memset.S revision 59a13c122ebc4191583b67c846a95d690dcda5cf
17c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris/*
27c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * Copyright (C) 2008 The Android Open Source Project
37c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * All rights reserved.
47c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris *
57c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * Redistribution and use in source and binary forms, with or without
67c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * modification, are permitted provided that the following conditions
77c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * are met:
87c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris *  * Redistributions of source code must retain the above copyright
97c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris *    notice, this list of conditions and the following disclaimer.
107c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris *  * Redistributions in binary form must reproduce the above copyright
117c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris *    notice, this list of conditions and the following disclaimer in
127c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris *    the documentation and/or other materials provided with the
137c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris *    distribution.
147c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris *
157c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
167c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
177c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
187c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
197c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
207c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
217c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
227c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
237c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
247c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
257c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
267c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * SUCH DAMAGE.
277c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris */
287c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
297c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris#include <machine/cpu-features.h>
307c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris#include <machine/asm.h>
3159a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris#include "libc_events.h"
327c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
337c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris/*
347c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * This code assumes it is running on a processor that supports all arm v7
357c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris * instructions and that supports neon instructions.
367c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris */
377c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
387c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris    .fpu    neon
397c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
4059a13c122ebc4191583b67c846a95d690dcda5cfChristopher FerrisENTRY(__memset_chk)
4159a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris        cmp         r2, r3
4259a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris        bls         done
4359a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris
4459a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris        ldr         r0, error_message
4559a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris        ldr         r1, error_code
4659a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris1:
4759a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris        add         r0, pc
4859a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris        bl          __fortify_chk_fail
4959a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferriserror_code:
5059a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris        .word       BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
5159a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferriserror_message:
5259a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris        .word       error_string-(1b+8)
5359a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris
5459a13c122ebc4191583b67c846a95d690dcda5cfChristopher FerrisEND(__memset_chk)
5559a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris
567c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher FerrisENTRY(bzero)
577c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        mov     r2, r1
587c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        mov     r1, #0
5959a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris
6059a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferrisdone:
6159a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris        // Fall through to memset...
627c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher FerrisEND(bzero)
637c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
647c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris/* memset() returns its first argument.  */
657c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher FerrisENTRY(memset)
667c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        # The neon memset only wins for less than 132.
677c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        cmp         r2, #132
687c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        bhi         11f
697c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
707c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        .save       {r0}
717c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        stmfd       sp!, {r0}
727c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
737c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        vdup.8      q0, r1
747c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
757c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        /* make sure we have at least 32 bytes to write */
767c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        subs        r2, r2, #32
777c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        blo         2f
787c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        vmov        q1, q0
797c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
807c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris1:      /* The main loop writes 32 bytes at a time */
817c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        subs        r2, r2, #32
827c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        vst1.8      {d0 - d3}, [r0]!
837c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        bhs         1b
847c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
857c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris2:      /* less than 32 left */
867c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        add         r2, r2, #32
877c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        tst         r2, #0x10
887c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        beq         3f
897c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
907c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        // writes 16 bytes, 128-bits aligned
917c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        vst1.8      {d0, d1}, [r0]!
927c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris3:      /* write up to 15-bytes (count in r2) */
937c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        movs        ip, r2, lsl #29
947c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        bcc         1f
957c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        vst1.8      {d0}, [r0]!
967c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris1:      bge         2f
977c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        vst1.32     {d0[0]}, [r0]!
987c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris2:      movs        ip, r2, lsl #31
997c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        strmib      r1, [r0], #1
1007c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        strcsb      r1, [r0], #1
1017c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        strcsb      r1, [r0], #1
1027c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        ldmfd       sp!, {r0}
1037c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        bx          lr
1047c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris11:
1057c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        /* compute the offset to align the destination
1067c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris         * offset = (4-(src&3))&3 = -src & 3
1077c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris         */
1087c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
1097c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        .save       {r0, r4-r7, lr}
1107c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        stmfd       sp!, {r0, r4-r7, lr}
1117c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        rsb         r3, r0, #0
1127c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        ands        r3, r3, #3
1137c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        cmp         r3, r2
1147c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        movhi       r3, r2
1157c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
1167c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        /* splat r1 */
1177c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        mov         r1, r1, lsl #24
1187c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        orr         r1, r1, r1, lsr #8
1197c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        orr         r1, r1, r1, lsr #16
1207c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
1217c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        movs        r12, r3, lsl #31
1227c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        strcsb      r1, [r0], #1    /* can't use strh (alignment unknown) */
1237c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        strcsb      r1, [r0], #1
1247c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        strmib      r1, [r0], #1
1257c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        subs        r2, r2, r3
1267c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        ldmlsfd     sp!, {r0, r4-r7, lr}   /* return */
1277c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        bxls        lr
1287c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
1297c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        /* align the destination to a cache-line */
1307c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        mov         r12, r1
1317c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        mov         lr, r1
1327c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        mov         r4, r1
1337c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        mov         r5, r1
1347c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        mov         r6, r1
1357c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        mov         r7, r1
1367c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
1377c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        rsb         r3, r0, #0
1387c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        ands        r3, r3, #0x1C
1397c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        beq         3f
1407c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        cmp         r3, r2
1417c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        andhi       r3, r2, #0x1C
1427c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        sub         r2, r2, r3
1437c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
1447c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        /* conditionally writes 0 to 7 words (length in r3) */
1457c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        movs        r3, r3, lsl #28
1467c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        stmcsia     r0!, {r1, lr}
1477c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        stmcsia     r0!, {r1, lr}
1487c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        stmmiia     r0!, {r1, lr}
1497c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        movs        r3, r3, lsl #2
1507c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        strcs       r1, [r0], #4
1517c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
1527c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris3:
1537c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        subs        r2, r2, #32
1547c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        mov         r3, r1
1557c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        bmi         2f
1567c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris1:      subs        r2, r2, #32
1577c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        stmia       r0!, {r1,r3,r4,r5,r6,r7,r12,lr}
1587c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        bhs         1b
1597c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris2:      add         r2, r2, #32
1607c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris
1617c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        /* conditionally stores 0 to 31 bytes */
1627c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        movs        r2, r2, lsl #28
1637c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        stmcsia     r0!, {r1,r3,r12,lr}
1647c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        stmmiia     r0!, {r1, lr}
1657c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        movs        r2, r2, lsl #2
1667c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        strcs       r1, [r0], #4
1677c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        strmih      r1, [r0], #2
1687c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        movs        r2, r2, lsl #2
1697c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        strcsb      r1, [r0]
1707c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        ldmfd       sp!, {r0, r4-r7, lr}
1717c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher Ferris        bx          lr
1727c83a1ed81a15f3e75836c1ac7d500a952f02e10Christopher FerrisEND(memset)
17359a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris
17459a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris        .data
17559a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferriserror_string:
17659a13c122ebc4191583b67c846a95d690dcda5cfChristopher Ferris        .string     "memset buffer overflow"
177