2005-11-01 22:52:23 +03:00
/ *
* linux/ a r c h / a r m / l i b / c o p y _ t e m p l a t e . s
*
* Code t e m p l a t e f o r o p t i m i z e d m e m o r y c o p y f u n c t i o n s
*
* Author : Nicolas P i t r e
* Created : Sep 2 8 , 2 0 0 5
* Copyright : MontaVista S o f t w a r e , I n c .
*
* This p r o g r a m i s f r e e s o f t w a r e ; you can redistribute it and/or modify
* it u n d e r t h e t e r m s o f t h e G N U G e n e r a l P u b l i c L i c e n s e v e r s i o n 2 a s
* published b y t h e F r e e S o f t w a r e F o u n d a t i o n .
* /
/ *
* Theory o f o p e r a t i o n
* - - - - - - - - - - - - - - - - - - -
*
* This f i l e p r o v i d e s t h e c o r e c o d e f o r a f o r w a r d m e m o r y c o p y u s e d i n
* the i m p l e m e n t a t i o n o f m e m c o p y ( ) , c o p y _ t o _ u s e r ( ) a n d c o p y _ f r o m _ u s e r ( ) .
*
* The i n c l u d i n g f i l e m u s t d e f i n e t h e f o l l o w i n g a c c e s s o r m a c r o s
* according t o t h e n e e d o f t h e g i v e n f u n c t i o n :
*
* ldr1 w p t r r e g a b o r t
*
* This l o a d s o n e w o r d f r o m ' p t r ' , s t o r e s i t i n ' r e g ' a n d i n c r e m e n t s
* ' ptr' t o t h e n e x t w o r d . T h e ' a b o r t ' a r g u m e n t i s u s e d f o r f i x u p t a b l e s .
*
* ldr4 w p t r r e g 1 r e g 2 r e g 3 r e g 4 a b o r t
* ldr8 w p t r , r e g 1 r e g 2 r e g 3 r e g 4 r e g 5 r e g 6 r e g 7 r e g 8 a b o r t
*
* This l o a d s f o u r o r e i g h t w o r d s s t a r t i n g f r o m ' p t r ' , s t o r e s t h e m
* in p r o v i d e d r e g i s t e r s a n d i n c r e m e n t s ' p t r ' p a s t t h o s e w o r d s .
* The' a b o r t ' a r g u m e n t i s u s e d f o r f i x u p t a b l e s .
*
* ldr1 b p t r r e g c o n d a b o r t
*
* Similar t o l d r1 w , b u t i t l o a d s a b y t e a n d i n c r e m e n t s ' p t r ' o n e b y t e .
* It a l s o m u s t a p p l y t h e c o n d i t i o n c o d e i f p r o v i d e d , o t h e r w i s e t h e
* " al" c o n d i t i o n i s a s s u m e d b y d e f a u l t .
*
* str1 w p t r r e g a b o r t
* str8 w p t r r e g 1 r e g 2 r e g 3 r e g 4 r e g 5 r e g 6 r e g 7 r e g 8 a b o r t
* str1 b p t r r e g c o n d a b o r t
*
* Same a s t h e i r l d r * c o u n t e r p a r t s , b u t d a t a i s s t o r e d t o ' p t r ' l o c a t i o n
* rather t h a n b e i n g l o a d e d .
*
* enter r e g 1 r e g 2
*
* Preserve t h e p r o v i d e d r e g i s t e r s o n t h e s t a c k p l u s a n y a d d i t i o n a l
* data a s n e e d e d b y t h e i m p l e m e n t a t i o n i n c l u d i n g t h i s c o d e . C a l l e d
* upon c o d e e n t r y .
*
2014-11-26 16:38:33 +03:00
* usave r e g 1 r e g 2
*
* Unwind a n n o t a t i o n m a c r o i s c o r r e s p o n d i n g f o r ' e n t e r ' m a c r o .
* It t e l l u n w i n d e r t h a t p r e s e r v e d s o m e p r o v i d e d r e g i s t e r s o n t h e s t a c k
* and a d d i t i o n a l d a t a b y a p r i o r ' e n t e r ' m a c r o .
*
2005-11-01 22:52:23 +03:00
* exit r e g 1 r e g 2
*
* Restore r e g i s t e r s w i t h t h e v a l u e s p r e v i o u s l y s a v e d w i t h t h e
* ' preserv' m a c r o . C a l l e d u p o n c o d e t e r m i n a t i o n .
2009-07-24 15:32:57 +04:00
*
* LDR1 W _ S H I F T
* STR1 W _ S H I F T
*
* Correction t o b e a p p l i e d t o t h e " i p " r e g i s t e r w h e n b r a n c h i n g i n t o
* the l d r1 w o r s t r1 w i n s t r u c t i o n s ( s o m e o f t h e s e m a c r o s m a y e x p a n d t o
* than o n e 3 2 b i t i n s t r u c t i o n i n T h u m b - 2 )
2005-11-01 22:52:23 +03:00
* /
2014-11-26 16:38:33 +03:00
UNWIND( . f n s t a r t )
2005-11-01 22:52:23 +03:00
enter r4 , l r
2014-11-26 16:38:33 +03:00
UNWIND( . f n e n d )
UNWIND( . f n s t a r t )
usave r4 , l r @ in first stmdb block
2005-11-01 22:52:23 +03:00
subs r2 , r2 , #4
blt 8 f
ands i p , r0 , #3
PLD( p l d [ r1 , #0 ] )
bne 9 f
ands i p , r1 , #3
bne 1 0 f
1 : subs r2 , r2 , #( 28 )
stmfd s p ! , { r5 - r8 }
2014-11-26 16:38:33 +03:00
UNWIND( . f n e n d )
UNWIND( . f n s t a r t )
usave r4 , l r
UNWIND( . s a v e { r5 - r8 } ) @ in second stmfd block
2005-11-01 22:52:23 +03:00
blt 5 f
2008-03-31 20:38:31 +04:00
CALGN( a n d s i p , r0 , #31 )
2005-11-01 22:52:23 +03:00
CALGN( r s b r3 , i p , #32 )
CALGN( s b c n e s r4 , r3 , r2 ) @ C is always set here
CALGN( b c s 2 f )
CALGN( a d r r4 , 6 f )
CALGN( s u b s r2 , r2 , r3 ) @ C gets set
CALGN( a d d p c , r4 , i p )
PLD( p l d [ r1 , #0 ] )
2 : PLD( s u b s r2 , r2 , #96 )
PLD( p l d [ r1 , #28 ] )
PLD( b l t 4 f )
PLD( p l d [ r1 , #60 ] )
PLD( p l d [ r1 , #92 ] )
3 : PLD( p l d [ r1 , #124 ] )
4 : ldr8 w r1 , r3 , r4 , r5 , r6 , r7 , r8 , i p , l r , a b o r t =20f
subs r2 , r2 , #32
str8 w r0 , r3 , r4 , r5 , r6 , r7 , r8 , i p , l r , a b o r t =20f
bge 3 b
PLD( c m n r2 , #96 )
PLD( b g e 4 b )
5 : ands i p , r2 , #28
rsb i p , i p , #32
2009-07-24 15:32:57 +04:00
# if L D R 1 W _ S H I F T > 0
lsl i p , i p , #L D R 1 W _ S H I F T
# endif
2005-11-01 22:52:23 +03:00
addne p c , p c , i p @ C is always clear here
b 7 f
2009-07-24 15:32:57 +04:00
6 :
.rept ( 1 < < LDR1 W _ S H I F T )
W( n o p )
.endr
2005-11-01 22:52:23 +03:00
ldr1 w r1 , r3 , a b o r t =20f
ldr1 w r1 , r4 , a b o r t =20f
ldr1 w r1 , r5 , a b o r t =20f
ldr1 w r1 , r6 , a b o r t =20f
ldr1 w r1 , r7 , a b o r t =20f
ldr1 w r1 , r8 , a b o r t =20f
ldr1 w r1 , l r , a b o r t =20f
2009-07-24 15:32:57 +04:00
# if L D R 1 W _ S H I F T < S T R 1 W _ S H I F T
lsl i p , i p , #S T R 1 W _ S H I F T - L D R 1 W _ S H I F T
# elif L D R 1 W _ S H I F T > S T R 1 W _ S H I F T
lsr i p , i p , #L D R 1 W _ S H I F T - S T R 1 W _ S H I F T
# endif
2005-11-01 22:52:23 +03:00
add p c , p c , i p
nop
2009-07-24 15:32:57 +04:00
.rept ( 1 < < STR1 W _ S H I F T )
W( n o p )
.endr
2005-11-01 22:52:23 +03:00
str1 w r0 , r3 , a b o r t =20f
str1 w r0 , r4 , a b o r t =20f
str1 w r0 , r5 , a b o r t =20f
str1 w r0 , r6 , a b o r t =20f
str1 w r0 , r7 , a b o r t =20f
str1 w r0 , r8 , a b o r t =20f
str1 w r0 , l r , a b o r t =20f
CALGN( b c s 2 b )
7 : ldmfd s p ! , { r5 - r8 }
2014-11-26 16:38:33 +03:00
UNWIND( . f n e n d ) @ end of second stmfd block
2005-11-01 22:52:23 +03:00
2014-11-26 16:38:33 +03:00
UNWIND( . f n s t a r t )
usave r4 , l r @ still in first stmdb block
2005-11-01 22:52:23 +03:00
8 : movs r2 , r2 , l s l #31
ldr1 b r1 , r3 , n e , a b o r t =21f
ldr1 b r1 , r4 , c s , a b o r t =21f
ldr1 b r1 , i p , c s , a b o r t =21f
str1 b r0 , r3 , n e , a b o r t =21f
str1 b r0 , r4 , c s , a b o r t =21f
str1 b r0 , i p , c s , a b o r t =21f
exit r4 , p c
9 : rsb i p , i p , #4
cmp i p , #2
ldr1 b r1 , r3 , g t , a b o r t =21f
ldr1 b r1 , r4 , g e , a b o r t =21f
ldr1 b r1 , l r , a b o r t =21f
str1 b r0 , r3 , g t , a b o r t =21f
str1 b r0 , r4 , g e , a b o r t =21f
subs r2 , r2 , i p
str1 b r0 , l r , a b o r t =21f
blt 8 b
ands i p , r1 , #3
beq 1 b
10 : bic r1 , r1 , #3
cmp i p , #2
ldr1 w r1 , l r , a b o r t =21f
beq 1 7 f
bgt 1 8 f
2014-11-26 16:38:33 +03:00
UNWIND( . f n e n d )
2005-11-01 22:52:23 +03:00
.macro forward_copy_shift pull p u s h
2014-11-26 16:38:33 +03:00
UNWIND( . f n s t a r t )
usave r4 , l r @ still in first stmdb block
2005-11-01 22:52:23 +03:00
subs r2 , r2 , #28
blt 1 4 f
2008-03-31 20:38:31 +04:00
CALGN( a n d s i p , r0 , #31 )
2005-11-01 22:52:23 +03:00
CALGN( r s b i p , i p , #32 )
CALGN( s b c n e s r4 , i p , r2 ) @ C is always set here
CALGN( s u b c c r2 , r2 , i p )
CALGN( b c c 1 5 f )
11 : stmfd s p ! , { r5 - r9 }
2014-11-26 16:38:33 +03:00
UNWIND( . f n e n d )
2005-11-01 22:52:23 +03:00
2014-11-26 16:38:33 +03:00
UNWIND( . f n s t a r t )
usave r4 , l r
UNWIND( . s a v e { r5 - r9 } ) @ in new second stmfd block
2005-11-01 22:52:23 +03:00
PLD( p l d [ r1 , #0 ] )
PLD( s u b s r2 , r2 , #96 )
PLD( p l d [ r1 , #28 ] )
PLD( b l t 1 3 f )
PLD( p l d [ r1 , #60 ] )
PLD( p l d [ r1 , #92 ] )
12 : PLD( p l d [ r1 , #124 ] )
13 : ldr4 w r1 , r4 , r5 , r6 , r7 , a b o r t =19f
2014-02-25 11:41:09 +04:00
mov r3 , l r , l s p u l l #\ p u l l
2005-11-01 22:52:23 +03:00
subs r2 , r2 , #32
ldr4 w r1 , r8 , r9 , i p , l r , a b o r t =19f
2014-02-25 11:41:09 +04:00
orr r3 , r3 , r4 , l s p u s h #\ p u s h
mov r4 , r4 , l s p u l l #\ p u l l
orr r4 , r4 , r5 , l s p u s h #\ p u s h
mov r5 , r5 , l s p u l l #\ p u l l
orr r5 , r5 , r6 , l s p u s h #\ p u s h
mov r6 , r6 , l s p u l l #\ p u l l
orr r6 , r6 , r7 , l s p u s h #\ p u s h
mov r7 , r7 , l s p u l l #\ p u l l
orr r7 , r7 , r8 , l s p u s h #\ p u s h
mov r8 , r8 , l s p u l l #\ p u l l
orr r8 , r8 , r9 , l s p u s h #\ p u s h
mov r9 , r9 , l s p u l l #\ p u l l
orr r9 , r9 , i p , l s p u s h #\ p u s h
mov i p , i p , l s p u l l #\ p u l l
orr i p , i p , l r , l s p u s h #\ p u s h
2005-11-01 22:52:23 +03:00
str8 w r0 , r3 , r4 , r5 , r6 , r7 , r8 , r9 , i p , , a b o r t =19f
bge 1 2 b
PLD( c m n r2 , #96 )
PLD( b g e 1 3 b )
ldmfd s p ! , { r5 - r9 }
2014-11-26 16:38:33 +03:00
UNWIND( . f n e n d ) @ end of the second stmfd block
2005-11-01 22:52:23 +03:00
2014-11-26 16:38:33 +03:00
UNWIND( . f n s t a r t )
usave r4 , l r @ still in first stmdb block
2005-11-01 22:52:23 +03:00
14 : ands i p , r2 , #28
beq 1 6 f
2014-02-25 11:41:09 +04:00
15 : mov r3 , l r , l s p u l l #\ p u l l
2005-11-01 22:52:23 +03:00
ldr1 w r1 , l r , a b o r t =21f
subs i p , i p , #4
2014-02-25 11:41:09 +04:00
orr r3 , r3 , l r , l s p u s h #\ p u s h
2005-11-01 22:52:23 +03:00
str1 w r0 , r3 , a b o r t =21f
bgt 1 5 b
CALGN( c m p r2 , #0 )
CALGN( b g e 1 1 b )
16 : sub r1 , r1 , #( \ p u s h / 8 )
b 8 b
2014-11-26 16:38:33 +03:00
UNWIND( . f n e n d )
2005-11-01 22:52:23 +03:00
.endm
forward_ c o p y _ s h i f t p u l l =8 p u s h =24
17 : forward_ c o p y _ s h i f t p u l l =16 p u s h =16
18 : forward_ c o p y _ s h i f t p u l l =24 p u s h =8
/ *
2006-03-28 13:56:53 +04:00
* Abort p r e a m b l e a n d c o m p l e t i o n m a c r o s .
2005-11-01 22:52:23 +03:00
* If a f i x u p h a n d l e r i s r e q u i r e d t h e n t h o s e m a c r o s m u s t s u r r o u n d i t .
* It i s a s s u m e d t h a t t h e f i x u p c o d e w i l l h a n d l e t h e p r i v a t e p a r t o f
* the e x i t m a c r o .
* /
.macro copy_abort_preamble
19 : ldmfd s p ! , { r5 - r9 }
b 2 1 f
20 : ldmfd s p ! , { r5 - r8 }
21 :
.endm
.macro copy_abort_end
ldmfd s p ! , { r4 , p c }
.endm