2005-04-16 15:20:36 -07:00
.file " div_ X s i g . S "
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| div_ X s i g . S |
| |
| Division s u b r o u t i n e f o r 9 6 b i t q u a n t i t i e s |
| |
| Copyright ( C ) 1 9 9 4 ,1 9 9 5 |
| W. M e t z e n t h e n , 2 2 P a r k e r S t , O r m o n d , V i c 3 1 6 3 , |
| Australia. E - m a i l b i l l m @jacobi.maths.monash.edu.au |
| |
| |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * /
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Divide t h e 9 6 b i t q u a n t i t y p o i n t e d t o b y a , b y t h a t p o i n t e d t o b y b , a n d |
| put t h e 9 6 b i t r e s u l t a t t h e l o c a t i o n d . |
| |
| The r e s u l t m a y n o t b e a c c u r a t e t o 9 6 b i t s . I t i s i n t e n d e d f o r u s e w h e r e |
| a r e s u l t b e t t e r t h a n 6 4 b i t s i s r e q u i r e d . T h e r e s u l t s h o u l d u s u a l l y b e |
| good t o a t l e a s t 9 4 b i t s . |
| The r e t u r n e d r e s u l t i s a c t u a l l y d i v i d e d b y o n e h a l f . T h i s i s d o n e t o |
| prevent o v e r f l o w . |
| |
| .aaaaaaaaaaaaaa / .bbbbbbbbbbbbb - > .dddddddddddd |
| |
| void d i v _ X s i g ( X s i g * a , X s i g * b , X s i g * d e s t ) |
| |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * /
# include " e x c e p t i o n . h "
# include " f p u _ e m u . h "
# define X s i g L L ( x ) ( x )
# define X s i g L ( x ) 4 ( x )
# define X s i g H ( x ) 8 ( x )
# ifndef N O N _ R E E N T R A N T _ F P U
/ *
Local s t o r a g e o n t h e s t a c k :
Accumulator : FPU_accum_3 : FPU_accum_2 : FPU_accum_1 : FPU_ a c c u m _ 0
* /
# define F P U _ a c c u m _ 3 - 4 ( % e b p )
# define F P U _ a c c u m _ 2 - 8 ( % e b p )
# define F P U _ a c c u m _ 1 - 1 2 ( % e b p )
# define F P U _ a c c u m _ 0 - 1 6 ( % e b p )
# define F P U _ r e s u l t _ 3 - 2 0 ( % e b p )
# define F P U _ r e s u l t _ 2 - 2 4 ( % e b p )
# define F P U _ r e s u l t _ 1 - 2 8 ( % e b p )
# else
.data
/ *
Local s t o r a g e i n a s t a t i c a r e a :
Accumulator : FPU_accum_3 : FPU_accum_2 : FPU_accum_1 : FPU_ a c c u m _ 0
* /
.align 4 , 0
FPU_accum_3 :
.long 0
FPU_accum_2 :
.long 0
FPU_accum_1 :
.long 0
FPU_accum_0 :
.long 0
FPU_result_3 :
.long 0
FPU_result_2 :
.long 0
FPU_result_1 :
.long 0
# endif / * N O N _ R E E N T R A N T _ F P U * /
.text
ENTRY( d i v _ X s i g )
pushl % e b p
movl % e s p ,% e b p
# ifndef N O N _ R E E N T R A N T _ F P U
subl $ 2 8 ,% e s p
# endif / * N O N _ R E E N T R A N T _ F P U * /
pushl % e s i
pushl % e d i
pushl % e b x
movl P A R A M 1 ,% e s i / * p o i n t e r t o n u m * /
movl P A R A M 2 ,% e b x / * p o i n t e r t o d e n o m * /
# ifdef P A R A N O I D
testl $ 0 x80 0 0 0 0 0 0 , X s i g H ( % e b x ) / * D i v i s o r * /
je L _ b u g g e d
# endif / * P A R A N O I D * /
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Divide : Return a r g 1 / a r g 2 t o a r g 3 . |
| |
| The m a x i m u m r e t u r n e d v a l u e i s ( i g n o r i n g e x p o n e n t s ) |
| .ffffffff ffffffff |
| - - - - - - - - - - - - - - - - - - = 1 .ffffffff fffffffe |
| .80000000 00000000 |
| and t h e m i n i m u m i s |
| .80000000 00000000 |
| - - - - - - - - - - - - - - - - - - = .80000000 00000001 ( rounded) |
| .ffffffff ffffffff |
| |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * /
/* Save extended dividend in local register */
/* Divide by 2 to prevent overflow */
clc
movl X s i g H ( % e s i ) ,% e a x
rcrl % e a x
movl % e a x ,F P U _ a c c u m _ 3
movl X s i g L ( % e s i ) ,% e a x
rcrl % e a x
movl % e a x ,F P U _ a c c u m _ 2
movl X s i g L L ( % e s i ) ,% e a x
rcrl % e a x
movl % e a x ,F P U _ a c c u m _ 1
movl $ 0 ,% e a x
rcrl % e a x
movl % e a x ,F P U _ a c c u m _ 0
movl F P U _ a c c u m _ 2 ,% e a x / * G e t t h e c u r r e n t n u m * /
movl F P U _ a c c u m _ 3 ,% e d x
/*----------------------------------------------------------------------*/
/ * Initialization d o n e .
Do t h e f i r s t 3 2 b i t s . * /
/* We will divide by a number which is too large */
movl X s i g H ( % e b x ) ,% e c x
addl $ 1 ,% e c x
jnc L F i r s t _ d i v _ n o t _ 1
/ * here w e n e e d t o d i v i d e b y 1 0 0 0 0 0 0 0 0 h ,
i. e . , n o d i v i s i o n a t a l l . . * /
mov % e d x ,% e a x
jmp L F i r s t _ d i v _ d o n e
LFirst_div_not_1 :
divl % e c x / * D i v i d e t h e n u m e r a t o r b y t h e a u g m e n t e d
denom m s d w * /
LFirst_div_done :
movl % e a x ,F P U _ r e s u l t _ 3 / * P u t t h e r e s u l t i n t h e a n s w e r * /
mull X s i g H ( % e b x ) / * m u l b y t h e m s d w o f t h e d e n o m * /
subl % e a x ,F P U _ a c c u m _ 2 / * S u b t r a c t f r o m t h e n u m l o c a l r e g * /
sbbl % e d x ,F P U _ a c c u m _ 3
movl F P U _ r e s u l t _ 3 ,% e a x / * G e t t h e r e s u l t b a c k * /
mull X s i g L ( % e b x ) / * n o w m u l t h e l s d w o f t h e d e n o m * /
subl % e a x ,F P U _ a c c u m _ 1 / * S u b t r a c t f r o m t h e n u m l o c a l r e g * /
sbbl % e d x ,F P U _ a c c u m _ 2
sbbl $ 0 ,F P U _ a c c u m _ 3
je L D o _ 2 n d _ 3 2 _ b i t s / * M u s t c h e c k f o r n o n - z e r o r e s u l t h e r e * /
# ifdef P A R A N O I D
jb L _ b u g g e d _ 1
# endif / * P A R A N O I D * /
/* need to subtract another once of the denom */
incl F P U _ r e s u l t _ 3 / * C o r r e c t t h e a n s w e r * /
movl X s i g L ( % e b x ) ,% e a x
movl X s i g H ( % e b x ) ,% e d x
subl % e a x ,F P U _ a c c u m _ 1 / * S u b t r a c t f r o m t h e n u m l o c a l r e g * /
sbbl % e d x ,F P U _ a c c u m _ 2
# ifdef P A R A N O I D
sbbl $ 0 ,F P U _ a c c u m _ 3
jne L _ b u g g e d _ 1 / * M u s t c h e c k f o r n o n - z e r o r e s u l t h e r e * /
# endif / * P A R A N O I D * /
/*----------------------------------------------------------------------*/
/ * Half o f t h e m a i n p r o b l e m i s d o n e , t h e r e i s j u s t a r e d u c e d n u m e r a t o r
to h a n d l e n o w .
Work w i t h t h e s e c o n d 3 2 b i t s , F P U _ a c c u m _ 0 n o t u s e d f r o m n o w o n * /
LDo_2nd_32_bits :
movl F P U _ a c c u m _ 2 ,% e d x / * g e t t h e r e d u c e d n u m * /
movl F P U _ a c c u m _ 1 ,% e a x
/* need to check for possible subsequent overflow */
cmpl X s i g H ( % e b x ) ,% e d x
jb L D o _ 2 n d _ d i v
ja L P r e v e n t _ 2 n d _ o v e r f l o w
cmpl X s i g L ( % e b x ) ,% e a x
jb L D o _ 2 n d _ d i v
LPrevent_2nd_overflow :
/* The numerator is greater or equal, would cause overflow */
/* prevent overflow */
subl X s i g L ( % e b x ) ,% e a x
sbbl X s i g H ( % e b x ) ,% e d x
movl % e d x ,F P U _ a c c u m _ 2
movl % e a x ,F P U _ a c c u m _ 1
incl F P U _ r e s u l t _ 3 / * R e f l e c t t h e s u b t r a c t i o n i n t h e a n s w e r * /
# ifdef P A R A N O I D
je L _ b u g g e d _ 2 / * C a n ' t b u m p t h e r e s u l t t o 1 . 0 * /
# endif / * P A R A N O I D * /
LDo_2nd_div :
cmpl $ 0 ,% e c x / * a u g m e n t e d d e n o m m s w * /
jnz L S e c o n d _ d i v _ n o t _ 1
/* %ecx == 0, we are dividing by 1.0 */
mov % e d x ,% e a x
jmp L S e c o n d _ d i v _ d o n e
LSecond_div_not_1 :
divl % e c x / * D i v i d e t h e n u m e r a t o r b y t h e d e n o m m s d w * /
LSecond_div_done :
movl % e a x ,F P U _ r e s u l t _ 2 / * P u t t h e r e s u l t i n t h e a n s w e r * /
mull X s i g H ( % e b x ) / * m u l b y t h e m s d w o f t h e d e n o m * /
subl % e a x ,F P U _ a c c u m _ 1 / * S u b t r a c t f r o m t h e n u m l o c a l r e g * /
sbbl % e d x ,F P U _ a c c u m _ 2
# ifdef P A R A N O I D
jc L _ b u g g e d _ 2
# endif / * P A R A N O I D * /
movl F P U _ r e s u l t _ 2 ,% e a x / * G e t t h e r e s u l t b a c k * /
mull X s i g L ( % e b x ) / * n o w m u l t h e l s d w o f t h e d e n o m * /
subl % e a x ,F P U _ a c c u m _ 0 / * S u b t r a c t f r o m t h e n u m l o c a l r e g * /
sbbl % e d x ,F P U _ a c c u m _ 1 / * S u b t r a c t f r o m t h e n u m l o c a l r e g * /
sbbl $ 0 ,F P U _ a c c u m _ 2
# ifdef P A R A N O I D
jc L _ b u g g e d _ 2
# endif / * P A R A N O I D * /
jz L D o _ 3 r d _ 3 2 _ b i t s
# ifdef P A R A N O I D
cmpl $ 1 ,F P U _ a c c u m _ 2
jne L _ b u g g e d _ 2
# endif / * P A R A N O I D * /
/* need to subtract another once of the denom */
movl X s i g L ( % e b x ) ,% e a x
movl X s i g H ( % e b x ) ,% e d x
subl % e a x ,F P U _ a c c u m _ 0 / * S u b t r a c t f r o m t h e n u m l o c a l r e g * /
sbbl % e d x ,F P U _ a c c u m _ 1
sbbl $ 0 ,F P U _ a c c u m _ 2
# ifdef P A R A N O I D
jc L _ b u g g e d _ 2
jne L _ b u g g e d _ 2
# endif / * P A R A N O I D * /
addl $ 1 ,F P U _ r e s u l t _ 2 / * C o r r e c t t h e a n s w e r * /
adcl $ 0 ,F P U _ r e s u l t _ 3
# ifdef P A R A N O I D
jc L _ b u g g e d _ 2 / * M u s t c h e c k f o r n o n - z e r o r e s u l t h e r e * /
# endif / * P A R A N O I D * /
/*----------------------------------------------------------------------*/
/ * The d i v i s i o n i s e s s e n t i a l l y f i n i s h e d h e r e , w e j u s t n e e d t o p e r f o r m
tidying o p e r a t i o n s .
Deal w i t h t h e 3 r d 3 2 b i t s * /
LDo_3rd_32_bits :
/ * We u s e a n a p p r o x i m a t i o n f o r t h e t h i r d 3 2 b i t s .
To t a k e a c c o u n t o f t h e 3 r d 3 2 b i t s o f t h e d i v i s o r
( call t h e m d e l ) , w e s u b t r a c t d e l * ( a / b ) * /
movl F P U _ r e s u l t _ 3 ,% e a x / * a / b * /
mull X s i g L L ( % e b x ) / * d e l * /
subl % e d x ,F P U _ a c c u m _ 1
/* A borrow indicates that the result is negative */
jnb L T e s t _ o v e r
movl X s i g H ( % e b x ) ,% e d x
addl % e d x ,F P U _ a c c u m _ 1
subl $ 1 ,F P U _ r e s u l t _ 2 / * A d j u s t t h e a n s w e r * /
sbbl $ 0 ,F P U _ r e s u l t _ 3
/* The above addition might not have been enough, check again. */
movl F P U _ a c c u m _ 1 ,% e d x / * g e t t h e r e d u c e d n u m * /
cmpl X s i g H ( % e b x ) ,% e d x / * d e n o m * /
jb L D o _ 3 r d _ d i v
movl X s i g H ( % e b x ) ,% e d x
addl % e d x ,F P U _ a c c u m _ 1
subl $ 1 ,F P U _ r e s u l t _ 2 / * A d j u s t t h e a n s w e r * /
sbbl $ 0 ,F P U _ r e s u l t _ 3
jmp L D o _ 3 r d _ d i v
LTest_over :
movl F P U _ a c c u m _ 1 ,% e d x / * g e t t h e r e d u c e d n u m * /
/* need to check for possible subsequent overflow */
cmpl X s i g H ( % e b x ) ,% e d x / * d e n o m * /
jb L D o _ 3 r d _ d i v
/* prevent overflow */
subl X s i g H ( % e b x ) ,% e d x
movl % e d x ,F P U _ a c c u m _ 1
addl $ 1 ,F P U _ r e s u l t _ 2 / * R e f l e c t t h e s u b t r a c t i o n i n t h e a n s w e r * /
adcl $ 0 ,F P U _ r e s u l t _ 3
LDo_3rd_div :
movl F P U _ a c c u m _ 0 ,% e a x
movl F P U _ a c c u m _ 1 ,% e d x
divl X s i g H ( % e b x )
movl % e a x ,F P U _ r e s u l t _ 1 / * R o u g h e s t i m a t e o f t h i r d w o r d * /
movl P A R A M 3 ,% e s i / * p o i n t e r t o a n s w e r * /
movl F P U _ r e s u l t _ 1 ,% e a x
movl % e a x ,X s i g L L ( % e s i )
movl F P U _ r e s u l t _ 2 ,% e a x
movl % e a x ,X s i g L ( % e s i )
movl F P U _ r e s u l t _ 3 ,% e a x
movl % e a x ,X s i g H ( % e s i )
L_exit :
popl % e b x
popl % e d i
popl % e s i
leave
ret
# ifdef P A R A N O I D
/* The logic is wrong if we got here */
L_bugged :
pushl E X _ I N T E R N A L | 0 x24 0
call E X C E P T I O N
pop % e b x
jmp L _ e x i t
L_bugged_1 :
pushl E X _ I N T E R N A L | 0 x24 1
call E X C E P T I O N
pop % e b x
jmp L _ e x i t
L_bugged_2 :
pushl E X _ I N T E R N A L | 0 x24 2
call E X C E P T I O N
pop % e b x
jmp L _ e x i t
# endif / * P A R A N O I D * /
2017-08-24 10:06:23 +02:00
ENDPROC( d i v _ X s i g )