Rev 286 | Blame | Last modification | View Log | RSS feed
/**************************************************************************** __________ __ ___.* Open \______ \ ____ ____ | | _\_ |__ _______ ___* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \* \/ \/ \/ \/ \/* $Id$** Copyright (C) 2006 Free Software Foundation, Inc.* This file was originally part of the GNU C Library* Contributed to glibc by MontaVista Software, Inc. (written by Nicolas Pitre)* Adapted for Rockbox by Daniel Ankers** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation; either version 2* of the License, or (at your option) any later version.** This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY* KIND, either express or implied.*****************************************************************************/#define ASM_FILE#include "global.h"/* ARMv4T doesn't switch the T bit when popping pc directly, we must use BX */.macro ldmpc cond="", order="ia", regs#if ARM_ARCH == 4 && defined(USE_THUMB)ldm\cond\order sp!, { \regs, lr }bx\cond lr#elseldm\cond\order sp!, { \regs, pc }#endif.endm.macro ldrpc cond=""#if ARM_ARCH == 4 && defined(USE_THUMB)ldr\cond lr, [sp], #4bx\cond lr#elseldr\cond pc, [sp], #4#endif.endm/** Endian independent macros for shifting bytes within registers.*/#ifndef __ARMEB__#define pull lsr#define push lsl#else#define pull lsl#define push lsr#endif/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */.section .icode,"ax",%progbits.align 2.global memcpy.type memcpy,%functionmemcpy:stmfd sp!, {r0, r4, lr}subs r2, r2, #4blt 8fands ip, r0, #3bne 9fands ip, r1, #3bne 10f1: subs r2, r2, #(28)stmfd sp!, {r5 - r8}blt 5f2:3:4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr}subs r2, r2, #32stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr}bge 3b5: ands ip, r2, #28rsb ip, ip, #32addne pc, pc, ip @ C is always clear hereb 7f6: nopldr r3, [r1], #4ldr r4, [r1], #4ldr r5, [r1], #4ldr r6, [r1], #4ldr r7, [r1], #4ldr r8, [r1], #4ldr lr, [r1], #4add pc, pc, ipnopnopstr r3, [r0], #4str r4, [r0], #4str r5, [r0], #4str r6, [r0], #4str r7, [r0], #4str r8, [r0], #4str lr, [r0], #47: ldmfd sp!, {r5 - r8}8: movs r2, r2, lsl #31ldrneb r3, [r1], #1ldrcsb r4, [r1], #1ldrcsb ip, [r1]strneb r3, [r0], #1strcsb r4, [r0], #1strcsb ip, [r0]ldmpc regs="r0, r4"9: rsb ip, ip, #4cmp ip, #2ldrgtb r3, [r1], #1ldrgeb r4, [r1], #1ldrb lr, [r1], #1strgtb r3, [r0], #1strgeb r4, [r0], #1subs r2, r2, ipstrb lr, [r0], #1blt 8bands ip, r1, #3beq 1b10: bic r1, r1, #3cmp ip, #2ldr lr, [r1], #4beq 17fbgt 18f.macro forward_copy_shift pull pushsubs r2, r2, #28blt 14f11: stmfd sp!, {r5 - r9}12:13: ldmia r1!, {r4, r5, r6, r7}mov r3, lr, pull #\pullsubs r2, r2, #32ldmia r1!, {r8, r9, ip, lr}orr r3, r3, r4, push #\pushmov r4, r4, pull #\pullorr r4, r4, r5, push #\pushmov r5, r5, pull #\pullorr r5, r5, r6, push #\pushmov r6, r6, pull #\pullorr r6, r6, r7, push #\pushmov r7, r7, pull #\pullorr r7, r7, r8, push #\pushmov r8, r8, pull #\pullorr r8, r8, r9, push #\pushmov r9, r9, pull #\pullorr r9, r9, ip, push #\pushmov ip, ip, pull #\pullorr ip, ip, lr, push #\pushstmia r0!, {r3, r4, r5, r6, r7, r8, r9, ip}bge 12bldmfd sp!, {r5 - r9}14: ands ip, r2, #28beq 16f15: mov r3, lr, pull #\pullldr lr, [r1], #4subs ip, ip, #4orr r3, r3, lr, push #\pushstr r3, [r0], #4bgt 15b16: sub r1, r1, #(\push / 8)b 8b.endmforward_copy_shift pull=8 push=2417: forward_copy_shift pull=16 push=1618: forward_copy_shift pull=24 push=8