| /* |
| * Copyright 2010 The Android Open Source Project |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| /* Changes: |
| * 2010-08-11 Steve McIntyre <steve.mcintyre@arm.com> |
| * Added small changes to the two functions to make them work on the |
| * specified number of 16- or 32-bit values rather than the original |
| * code which was specified as a count of bytes. More verbose comments |
| * to aid future maintenance. |
| */ |
| |
| .text |
| .align |
| |
| .global arm_memset32 |
| .type arm_memset32, %function |
| .global arm_memset16 |
| .type arm_memset16, %function |
| |
| /* |
| * Optimized memset functions for ARM. |
| * |
| * void arm_memset16(uint16_t* dst, uint16_t value, int count); |
| * void arm_memset32(uint32_t* dst, uint32_t value, int count); |
| * |
| */ |
| arm_memset16: |
| .fnstart |
| push {lr} |
| |
| /* if count is equal to zero then abort */ |
| teq r2, #0 |
| ble .Lfinish |
| |
| /* Multiply count by 2 - go from the number of 16-bit shorts |
| * to the number of bytes desired. */ |
| mov r2, r2, lsl #1 |
| |
| /* expand the data to 32 bits */ |
| orr r1, r1, lsl #16 |
| |
| /* align to 32 bits */ |
| tst r0, #2 |
| strneh r1, [r0], #2 |
| subne r2, r2, #2 |
| |
| /* Now jump into the main loop below. */ |
| b .Lwork_32 |
| .fnend |
| |
| arm_memset32: |
| .fnstart |
| push {lr} |
| |
| /* if count is equal to zero then abort */ |
| teq r2, #0 |
| ble .Lfinish |
| |
| /* Multiply count by 4 - go from the number of 32-bit words to |
| * the number of bytes desired. */ |
| mov r2, r2, lsl #2 |
| |
| .Lwork_32: |
| /* Set up registers ready for writing them out. */ |
| mov ip, r1 |
| mov lr, r1 |
| |
| /* Try to align the destination to a cache line. Assume 32 |
| * byte (8 word) cache lines, it's the common case. */ |
| rsb r3, r0, #0 |
| ands r3, r3, #0x1C |
| beq .Laligned32 |
| cmp r3, r2 |
| andhi r3, r2, #0x1C |
| sub r2, r2, r3 |
| |
| /* (Optionally) write any unaligned leading bytes. |
| * (0-28 bytes, length in r3) */ |
| movs r3, r3, lsl #28 |
| stmcsia r0!, {r1, lr} |
| stmcsia r0!, {r1, lr} |
| stmmiia r0!, {r1, lr} |
| movs r3, r3, lsl #2 |
| strcs r1, [r0], #4 |
| |
| /* Now quickly loop through the cache-aligned data. */ |
| .Laligned32: |
| mov r3, r1 |
| 1: subs r2, r2, #32 |
| stmhsia r0!, {r1,r3,ip,lr} |
| stmhsia r0!, {r1,r3,ip,lr} |
| bhs 1b |
| add r2, r2, #32 |
| |
| /* (Optionally) store any remaining trailing bytes. |
| * (0-30 bytes, length in r2) */ |
| movs r2, r2, lsl #28 |
| stmcsia r0!, {r1,r3,ip,lr} |
| stmmiia r0!, {r1,lr} |
| movs r2, r2, lsl #2 |
| strcs r1, [r0], #4 |
| strmih lr, [r0], #2 |
| |
| .Lfinish: |
| pop {pc} |
| .fnend |