2005-04-16 15:20:36 -07:00
/ *
* INET A n i m p l e m e n t a t i o n o f t h e T C P / I P p r o t o c o l s u i t e f o r t h e L I N U X
* operating s y s t e m . I N E T i s i m p l e m e n t e d u s i n g t h e B S D S o c k e t
* interface a s t h e m e a n s o f c o m m u n i c a t i o n w i t h t h e u s e r l e v e l .
*
* IP/ T C P / U D P c h e c k s u m m i n g r o u t i n e s
*
* Authors : Jorge C w i k , < j o r g e @laser.satlink.net>
* Arnt G u l b r a n d s e n , < a g u l b r a @nvg.unit.no>
* Tom M a y , < f t o m @netcom.com>
* Pentium P r o / I I r o u t i n e s :
* Alexander K j e l d a a s < a s t o r @guardian.no>
* Finn A r n e G a n g s t a d < f i n n a g @guardian.no>
* Lots o f c o d e m o v e d f r o m t c p . c a n d i p . c ; see those files
* for m o r e n a m e s .
*
* Changes : Ingo M o l n a r , c o n v e r t e d c s u m _ p a r t i a l _ c o p y ( ) t o 2 . 1 e x c e p t i o n
* handling.
* Andi K l e e n , a d d z e r o i n g o n e r r o r
* converted t o p u r e a s s e m b l e r
* Hirokazu T a k a t a ,H i r o y u k i K o n d o r e w r i t e f o r t h e m 3 2 r a r c h i t e c t u r e .
*
* 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 i t 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
* as p u b l i s h e d 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 ; either version
* 2 of t h e L i c e n s e , o r ( a t y o u r o p t i o n ) a n y l a t e r v e r s i o n .
* /
# include < l i n u x / l i n k a g e . h >
# include < a s m / a s s e m b l e r . h >
# include < a s m / e r r n o . h >
/ *
* computes a p a r t i a l c h e c k s u m , e . g . f o r T C P / U D P f r a g m e n t s
* /
/ *
unsigned i n t c s u m _ p a r t i a l ( c o n s t u n s i g n e d c h a r * b u f f , i n t l e n , u n s i g n e d i n t s u m )
* /
# ifdef C O N F I G _ I S A _ D U A L _ I S S U E
/ *
* Experiments w i t h E t h e r n e t a n d S L I P c o n n e c t i o n s s h o w t h a t b u f f
* is a l i g n e d o n e i t h e r a 2 - b y t e o r 4 - b y t e b o u n d a r y . W e g e t a t
* least a t w o f o l d s p e e d u p o n 4 8 6 a n d P e n t i u m i f i t i s 4 - b y t e a l i g n e d .
* Fortunately, i t i s e a s y t o c o n v e r t 2 - b y t e a l i g n m e n t t o 4 - b y t e
* alignment f o r t h e u n r o l l e d l o o p .
* /
.text
ENTRY( c s u m _ p a r t i a l )
; Function args
; r0: unsigned char *buff
; r1: int len
; r2: unsigned int sum
push r2 | | l d i r2 , #0
and3 r7 , r0 , #1 ; Check alignment.
beqz r7 , 1 f ; Jump if alignment is ok.
; 1-byte mis aligned
ldub r4 , @r0 || addi r0, #1
; clear c-bit || Alignment uses up bytes.
cmp r0 , r0 | | a d d i r1 , #- 1
ldi r3 , #0 | | a d d x r2 , r4
addx r2 , r3
.fillinsn
1 :
and3 r4 , r0 , #2 ; Check alignment.
beqz r4 , 2 f ; Jump if alignment is ok.
; clear c-bit || Alignment uses up two bytes.
cmp r0 , r0 | | a d d i r1 , #- 2
bgtz r1 , 1 f ; Jump if we had at least two bytes.
bra 4 f | | a d d i r1 , #2
.fillinsn ; len(r1) was < 2. Deal with it.
1 :
; 2-byte aligned
lduh r4 , @r0 || ldi r3, #0
addx r2 , r4 | | a d d i r0 , #2
addx r2 , r3
.fillinsn
2 :
; 4-byte aligned
cmp r0 , r0 ; clear c-bit
srl3 r6 , r1 , #5
beqz r6 , 2 f
.fillinsn
1 : ld r3 , @r0+
ld r4 , @r0+ ; +4
ld r5 , @r0+ ; +8
ld r3 , @r0+ || addx r2, r3 ; +12
ld r4 , @r0+ || addx r2, r4 ; +16
ld r5 , @r0+ || addx r2, r5 ; +20
ld r3 , @r0+ || addx r2, r3 ; +24
ld r4 , @r0+ || addx r2, r4 ; +28
addx r2 , r5 | | a d d i r6 , #- 1
addx r2 , r3
addx r2 , r4
bnez r6 , 1 b
addx r2 , r6 ; r6=0
cmp r0 , r0 ; This clears c-bit
.fillinsn
2 : and3 r6 , r1 , #0x1c ; withdraw len
beqz r6 , 4 f
srli r6 , #2
.fillinsn
3 : ld r4 , @r0+ || addi r6, #-1
addx r2 , r4
bnez r6 , 3 b
addx r2 , r6 ; r6=0
cmp r0 , r0 ; This clears c-bit
.fillinsn
4 : and3 r1 , r1 , #3
beqz r1 , 7 f ; if len == 0 goto end
and3 r6 , r1 , #2
beqz r6 , 5 f ; if len < 2 goto 5f(1byte)
lduh r4 , @r0 || addi r0, #2
addi r1 , #- 2 | | s l l i r4 , #16
addx r2 , r4
beqz r1 , 6 f
.fillinsn
5 : ldub r4 , @r0 || ldi r1, #0
# ifndef _ _ L I T T L E _ E N D I A N _ _
slli r4 , #8
# endif
addx r2 , r4
.fillinsn
6 : addx r2 , r1
.fillinsn
7 :
and3 r0 , r2 , #0xffff
srli r2 , #16
add r0 , r2
srl3 r2 , r0 , #16
beqz r2 , 1 f
addi r0 , #1
and3 r0 , r0 , #0xffff
.fillinsn
1 :
beqz r7 , 1 f ; swap the upper byte for the lower
and3 r2 , r0 , #0xff
srl3 r0 , r0 , #8
slli r2 , #8
or r0 , r2
.fillinsn
1 :
pop r2 | | c m p r0 , r0
addx r0 , r2 | | l d i r2 , #0
addx r0 , r2
jmp r14
# else / * n o t C O N F I G _ I S A _ D U A L _ I S S U E * /
/ *
* Experiments w i t h E t h e r n e t a n d S L I P c o n n e c t i o n s s h o w t h a t b u f f
* is a l i g n e d o n e i t h e r a 2 - b y t e o r 4 - b y t e b o u n d a r y . W e g e t a t
* least a t w o f o l d s p e e d u p o n 4 8 6 a n d P e n t i u m i f i t i s 4 - b y t e a l i g n e d .
* Fortunately, i t i s e a s y t o c o n v e r t 2 - b y t e a l i g n m e n t t o 4 - b y t e
* alignment f o r t h e u n r o l l e d l o o p .
* /
.text
ENTRY( c s u m _ p a r t i a l )
; Function args
; r0: unsigned char *buff
; r1: int len
; r2: unsigned int sum
push r2
ldi r2 , #0
and3 r7 , r0 , #1 ; Check alignment.
beqz r7 , 1 f ; Jump if alignment is ok.
; 1-byte mis aligned
ldub r4 , @r0
addi r0 , #1
addi r1 , #- 1 ; Alignment uses up bytes.
cmp r0 , r0 ; clear c-bit
ldi r3 , #0
addx r2 , r4
addx r2 , r3
.fillinsn
1 :
and3 r4 , r0 , #2 ; Check alignment.
beqz r4 , 2 f ; Jump if alignment is ok.
addi r1 , #- 2 ; Alignment uses up two bytes.
cmp r0 , r0 ; clear c-bit
bgtz r1 , 1 f ; Jump if we had at least two bytes.
addi r1 , #2 ; len(r1) was < 2. Deal with it.
bra 4 f
.fillinsn
1 :
; 2-byte aligned
lduh r4 , @r0
addi r0 , #2
ldi r3 , #0
addx r2 , r4
addx r2 , r3
.fillinsn
2 :
; 4-byte aligned
cmp r0 , r0 ; clear c-bit
srl3 r6 , r1 , #5
beqz r6 , 2 f
.fillinsn
1 : ld r3 , @r0+
ld r4 , @r0+ ; +4
ld r5 , @r0+ ; +8
addx r2 , r3
addx r2 , r4
addx r2 , r5
ld r3 , @r0+ ; +12
ld r4 , @r0+ ; +16
ld r5 , @r0+ ; +20
addx r2 , r3
addx r2 , r4
addx r2 , r5
ld r3 , @r0+ ; +24
ld r4 , @r0+ ; +28
addi r6 , #- 1
addx r2 , r3
addx r2 , r4
bnez r6 , 1 b
addx r2 , r6 ; r6=0
cmp r0 , r0 ; This clears c-bit
.fillinsn
2 : and3 r6 , r1 , #0x1c ; withdraw len
beqz r6 , 4 f
srli r6 , #2
.fillinsn
3 : ld r4 , @r0+
addi r6 , #- 1
addx r2 , r4
bnez r6 , 3 b
addx r2 , r6 ; r6=0
cmp r0 , r0 ; This clears c-bit
.fillinsn
4 : and3 r1 , r1 , #3
beqz r1 , 7 f ; if len == 0 goto end
and3 r6 , r1 , #2
beqz r6 , 5 f ; if len < 2 goto 5f(1byte)
lduh r4 , @r0
addi r0 , #2
addi r1 , #- 2
slli r4 , #16
addx r2 , r4
beqz r1 , 6 f
.fillinsn
5 : ldub r4 , @r0
# ifndef _ _ L I T T L E _ E N D I A N _ _
slli r4 , #8
# endif
addx r2 , r4
.fillinsn
6 : ldi r5 , #0
addx r2 , r5
.fillinsn
7 :
and3 r0 , r2 , #0xffff
srli r2 , #16
add r0 , r2
srl3 r2 , r0 , #16
beqz r2 , 1 f
addi r0 , #1
and3 r0 , r0 , #0xffff
.fillinsn
1 :
beqz r7 , 1 f
mv r2 , r0
srl3 r0 , r2 , #8
and3 r2 , r2 , #0xff
slli r2 , #8
or r0 , r2
.fillinsn
1 :
pop r2
cmp r0 , r0
addx r0 , r2
ldi r2 , #0
addx r0 , r2
jmp r14
# endif / * n o t C O N F I G _ I S A _ D U A L _ I S S U E * /
/ *
unsigned i n t c s u m _ p a r t i a l _ c o p y _ g e n e r i c ( c o n s t c h a r * s r c , c h a r * d s t ,
int l e n , i n t s u m , i n t * s r c _ e r r _ p t r , i n t * d s t _ e r r _ p t r )
* /
/ *
* Copy f r o m d s w h i l e c h e c k s u m m i n g , o t h e r w i s e l i k e c s u m _ p a r t i a l
*
* The m a c r o s S R C a n d D S T s p e c i f y t h e t y p e o f a c c e s s f o r t h e i n s t r u c t i o n .
* thus w e c a n c a l l a c u s t o m e x c e p t i o n h a n d l e r f o r a l l a c c e s s t y p e s .
*
* FIXME : could s o m e o n e d o u b l e - c h e c k w h e t h e r I h a v e n ' t m i x e d u p s o m e S R C a n d
* DST d e f i n i t i o n s ? I t ' s d a m n h a r d t o t r i g g e r a l l c a s e s . I h o p e I g o t
* them a l l b u t t h e r e ' s n o g u a r a n t e e .
* /
ENTRY( c s u m _ p a r t i a l _ c o p y _ g e n e r i c )
nop
nop
nop
nop
jmp r14
nop
nop
nop
2007-02-10 01:43:40 -08:00
.end