| @@ -0,0 +1,91 @@ | |||
| /* | |||
| * Copyright (c) 2014 Travis Geiselbrecht | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining | |||
| * a copy of this software and associated documentation files | |||
| * (the "Software"), to deal in the Software without restriction, | |||
| * including without limitation the rights to use, copy, modify, merge, | |||
| * publish, distribute, sublicense, and/or sell copies of the Software, | |||
| * and to permit persons to whom the Software is furnished to do so, | |||
| * subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be | |||
| * included in all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |||
| * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |||
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |||
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| //#include <asm.h> | |||
| //#include <arch/arm/cores.h> | |||
| #if defined (__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) | |||
| .global memset | |||
| .text | |||
| .syntax unified | |||
| .thumb | |||
| .align 2 | |||
| /* void *memset(void *s, int c, size_t n); */ | |||
| .type memset, %function | |||
| .thumb_func | |||
| memset: | |||
| //FUNCTION(memset) | |||
| // save the original pointer | |||
| push { r0, lr } | |||
| // check for zero length | |||
| cbz r2, .L_done | |||
| // short memsets aren't worth optimizing and make sure we have | |||
| // enough headroom to try to do dwordwise move optimization | |||
| cmp r2, #16 | |||
| blt .L_bytewise | |||
| // see how many bytes we need to move to align to dword boundaries | |||
| and r3, r0, #7 | |||
| cbz r3, .L_prepare_dwordwise | |||
| rsb r3, #8 | |||
| subs r2, r3 | |||
| .L_bytewise_align: | |||
| // bytewise to align memset | |||
| subs r3, r3, #1 | |||
| strb r1, [r0], #1 | |||
| bgt .L_bytewise_align | |||
| .L_prepare_dwordwise: | |||
| // fill a pair of 32 bit registers with the 8 bit value | |||
| uxtb r1, r1 | |||
| orr r1, r1, r1, lsl #8 | |||
| orr r1, r1, r1, lsl #16 | |||
| mov r12, r1 | |||
| // load the number of dwords left | |||
| lsrs r3, r2, #3 | |||
| .L_dwordwise: | |||
| // dwordwise memset | |||
| subs r3, r3, #1 | |||
| strd r1, r12, [r0], #8 | |||
| bgt .L_dwordwise | |||
| // remaining bytes | |||
| ands r2, #7 | |||
| beq .L_done | |||
| .L_bytewise: | |||
| // bytewise memset | |||
| subs r2, r2, #1 | |||
| strb r1, [r0], #1 | |||
| bgt .L_bytewise | |||
| .L_done: | |||
| // restore the base pointer as return value | |||
| pop { r0, pc } | |||
| #endif | |||