/* memcpy.S: optimised assembly memcpy1*2* Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.3* Written by David Howells ([email protected])4*5* This program is free software; you can redistribute it and/or6* modify it under the terms of the GNU General Public License7* as published by the Free Software Foundation; either version8* 2 of the License, or (at your option) any later version.9*/101112.text13.p2align 41415###############################################################################16#17# void *memcpy(void *to, const char *from, size_t count)18#19# - NOTE: must not use any stack. exception detection performs function return20# to caller's fixup routine, aborting the remainder of the copy21#22###############################################################################23.globl memcpy,__memcpy_end24.type memcpy,@function25memcpy:26or.p gr8,gr9,gr427orcc gr10,gr0,gr0,icc328or.p gr10,gr4,gr429beqlr icc3,#03031# optimise based on best common alignment for to, from & count32andicc.p gr4,#0x0f,gr0,icc033setlos #8,gr1134andicc.p gr4,#0x07,gr0,icc135beq icc0,#0,memcpy_1636andicc.p gr4,#0x03,gr0,icc037beq icc1,#0,memcpy_838andicc.p gr4,#0x01,gr0,icc139beq icc0,#0,memcpy_440setlos.p #1,gr1141beq icc1,#0,memcpy_24243# do byte by byte copy44sub.p gr8,gr11,gr345sub gr9,gr11,gr9460: ldubu.p @(gr9,gr11),gr447subicc gr10,#1,gr10,icc048stbu.p gr4,@(gr3,gr11)49bne icc0,#2,0b50bralr5152# do halfword by halfword copy53memcpy_2:54setlos #2,gr1155sub.p gr8,gr11,gr356sub gr9,gr11,gr9570: lduhu.p @(gr9,gr11),gr458subicc gr10,#2,gr10,icc059sthu.p gr4,@(gr3,gr11)60bne icc0,#2,0b61bralr6263# do word by word copy64memcpy_4:65setlos #4,gr1166sub.p gr8,gr11,gr367sub gr9,gr11,gr9680: ldu.p @(gr9,gr11),gr469subicc gr10,#4,gr10,icc070stu.p gr4,@(gr3,gr11)71bne icc0,#2,0b72bralr7374# do double-word by double-word copy75memcpy_8:76sub.p gr8,gr11,gr377sub gr9,gr11,gr9780: lddu.p @(gr9,gr11),gr479subicc gr10,#8,gr10,icc080stdu.p gr4,@(gr3,gr11)81bne icc0,#2,0b82bralr8384# do quad-word by quad-word copy85memcpy_16:86sub.p gr8,gr11,gr387sub gr9,gr11,gr9880: lddu @(gr9,gr11),gr489lddu.p @(gr9,gr11),gr690subicc gr10,#16,gr10,icc091stdu gr4,@(gr3,gr11)92stdu.p gr6,@(gr3,gr11)93bne icc0,#2,0b94bralr95__memcpy_end:9697.size memcpy, __memcpy_end-memcpy9899###############################################################################100#101# copy to/from userspace102# - return the number of bytes that could not be copied (0 on complete success)103#104# long __memcpy_user(void *dst, const void *src, size_t count)105#106###############################################################################107.globl __memcpy_user, __memcpy_user_error_lr, __memcpy_user_error_handler108.type __memcpy_user,@function109__memcpy_user:110movsg lr,gr7111subi.p sp,#8,sp112add gr8,gr10,gr6 ; calculate expected end address113stdi gr6,@(sp,#0)114115# abuse memcpy to do the dirty work116call memcpy117__memcpy_user_error_lr:118ldi.p @(sp,#4),gr7119setlos #0,gr8120jmpl.p @(gr7,gr0)121addi sp,#8,sp122123# deal any exception generated by memcpy124# GR8 - memcpy's current dest address125# GR11 - memset's step value (index register for store insns)126__memcpy_user_error_handler:127lddi.p @(sp,#0),gr4 ; load GR4 with dst+count, GR5 with ret addr128add gr11,gr3,gr7129sub.p gr4,gr7,gr8130131addi sp,#8,sp132jmpl @(gr5,gr0)133134.size __memcpy_user, .-__memcpy_user135136137