2005-04-16 15:20:36 -07:00
.file " reg_ u _ d i v . S "
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| reg_ u _ d i v . S |
| |
| Divide o n e F P U _ R E G b y a n o t h e r a n d p u t t h e r e s u l t i n a d e s t i n a t i o n F P U _ R E G . |
| |
| Copyright ( C ) 1 9 9 2 ,1 9 9 3 ,1 9 9 5 ,1 9 9 7 |
| 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 , A u s t r a l i a |
| E- m a i l b i l l m @suburbia.net |
| |
| |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * /
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Call f r o m C a s : |
| int F P U _ u _ d i v ( F P U _ R E G * a , F P U _ R E G * b , F P U _ R E G * d e s t , |
| unsigned i n t c o n t r o l _ w o r d , c h a r * s i g n ) |
| |
| Does n o t c o m p u t e t h e d e s t i n a t i o n e x p o n e n t , b u t d o e s a d j u s t i t . |
| |
| Return v a l u e i s t h e t a g o f t h e a n s w e r , o r - e d w i t h F P U _ E x c e p t i o n i f |
| one w a s r a i s e d , o r - 1 o n i n t e r n a l e r r o r . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * /
# include " e x c e p t i o n . h "
# include " f p u _ e m u . h "
# include " c o n t r o l _ w . h "
/* #define dSIGL(x) (x) */
/* #define dSIGH(x) 4(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 :
Result : FPU_accum_3 : FPU_accum_2 : FPU_accum_1 : FPU_ a c c u m _ 0
Overflow f l a g : o v f l _ f l a g
* /
# 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 _ 1 - 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 _ o v f l _ f l a g - 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 :
Result : FPU_accum_3 : FPU_accum_2 : FPU_accum_1 : FPU_ a c c u m _ 0
Overflow f l a g : o v f l _ f l a g
* /
.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_1 :
.long 0
FPU_result_2 :
.long 0
FPU_ovfl_flag :
.byte 0
# endif / * N O N _ R E E N T R A N T _ F P U * /
# define R E G A P A R A M 1
# define R E G B P A R A M 2
# define D E S T P A R A M 3
.text
ENTRY( F P U _ u _ d i v )
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 R E G A ,% e s i
movl R E G B ,% e b x
movl D E S T ,% e d i
movswl E X P ( % e s i ) ,% e d x
movswl E X P ( % e b x ) ,% e a x
subl % e a x ,% e d x
addl E X P _ B I A S ,% e d x
/* A denormal and a large number can cause an exponent underflow */
cmpl E X P _ W A Y _ U N D E R ,% e d x
jg x E x p _ n o t _ u n d e r f l o w
/* Set to a really low value allow correct handling */
movl E X P _ W A Y _ U N D E R ,% e d x
xExp_not_underflow :
movw % d x ,E X P ( % e d i )
# ifdef P A R A N O I D
/* testl $0x80000000, SIGH(%esi) // Dividend */
/* je L_bugged */
testl $ 0 x80 0 0 0 0 0 0 , 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 * /
/* Check if the divisor can be treated as having just 32 bits */
cmpl $ 0 ,S I G L ( % e b x )
jnz L _ F u l l _ D i v i s i o n / * C a n ' t d o a q u i c k d i v i d e * /
/* We should be able to zip through the division here */
movl S I G H ( % e b x ) ,% e c x / * T h e d i v i s o r * /
movl S I G H ( % e s i ) ,% e d x / * D i v i d e n d * /
movl S I G L ( % e s i ) ,% e a x / * D i v i d e n d * /
cmpl % e c x ,% e d x
setaeb F P U _ o v f l _ f l a g / * K e e p a r e c o r d * /
jb L _ n o _ a d j u s t
subl % e c x ,% e d x / * P r e v e n t t h e o v e r f l o w * /
L_no_adjust :
/* Divide the 64 bit number by the 32 bit denominator */
divl % e c x
movl % e a x ,F P U _ r e s u l t _ 2
/* Work on the remainder of the first division */
xorl % e a x ,% e a x
divl % e c x
movl % e a x ,F P U _ r e s u l t _ 1
/* Work on the remainder of the 64 bit division */
xorl % e a x ,% e a x
divl % e c x
testb $ 2 5 5 ,F P U _ o v f l _ f l a g / * w a s t h e n u m > d e n o m ? * /
je L _ n o _ o v e r f l o w
/* Do the shifting here */
/* increase the exponent */
incw E X P ( % e d i )
/* shift the mantissa right one bit */
stc / * T o s e t t h e m s b i t * /
rcrl F P U _ r e s u l t _ 2
rcrl F P U _ r e s u l t _ 1
rcrl % e a x
L_no_overflow :
jmp L R o u n d _ p r e c i s i o n / * D o t h e r o u n d i n g a s r e q u i r e d * /
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Divide : Return a r g 1 / a r g 2 t o a r g 3 . |
| |
| This r o u t i n e d o e s n o t u s e t h e e x p o n e n t s o f a r g 1 a n d a r g 2 , b u t d o e s |
| adjust t h e e x p o n e n t o f 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 |
| |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * /
L_Full_Division :
/* Save extended dividend in local register */
movl S I G L ( % e s i ) ,% e a x
movl % e a x ,F P U _ a c c u m _ 2
movl S I G H ( % e s i ) ,% e a x
movl % e a x ,F P U _ a c c u m _ 3
xorl % e a x ,% e a x
movl % e a x ,F P U _ a c c u m _ 1 / * z e r o t h e e x t e n s i o n * /
movl % e a x ,F P U _ a c c u m _ 0 / * z e r o t h e e x t e n s i o n * /
movl S I G L ( % e s i ) ,% e a x / * G e t t h e c u r r e n t n u m * /
movl S I G H ( % e s i ) ,% e d x
/*----------------------------------------------------------------------*/
/ * Initialization d o n e .
Do t h e f i r s t 3 2 b i t s . * /
movb $ 0 ,F P U _ o v f l _ f l a g
cmpl S I G H ( % e b x ) ,% e d x / * T e s t f o r i m m i n e n t o v e r f l o w * /
jb L L e s s _ t h a n _ 1
ja L G r e a t e r _ t h a n _ 1
cmpl S I G L ( % e b x ) ,% e a x
jb L L e s s _ t h a n _ 1
LGreater_than_1 :
/* The dividend is greater or equal, would cause overflow */
setaeb F P U _ o v f l _ f l a g / * K e e p a r e c o r d * /
subl S I G L ( % e b x ) ,% e a x
sbbl S I G H ( % e b x ) ,% e d x / * P r e v e n t t h e o v e r f l o w * /
movl % e a x ,F P U _ a c c u m _ 2
movl % e d x ,F P U _ a c c u m _ 3
LLess_than_1 :
/ * At t h i s p o i n t , w e h a v e a d i v i d e n d < d i v i s o r , w i t h a r e c o r d o f
adjustment i n F P U _ o v f l _ f l a g * /
/* We will divide by a number which is too large */
movl 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 _ 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 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 _ 2 ,% e a x / * G e t t h e r e s u l t b a c k * /
mull 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 _ 2 / * C o r r e c t t h e a n s w e r * /
movl S I G L ( % e b x ) ,% e a x
movl 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 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 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 S I G L ( % e b x ) ,% e a x
sbbl 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 _ 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 * /
# 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 _ 1 / * P u t t h e r e s u l t i n t h e a n s w e r * /
mull 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 _ 1 ,% e a x / * G e t t h e r e s u l t b a c k * /
mull 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 S I G L ( % e b x ) ,% e a x
movl 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 _ 1 / * 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 _ 2
# 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 :
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 * /
movl F P U _ a c c u m _ 0 ,% e a x
/* need to check for possible subsequent overflow */
cmpl S I G H ( % e b x ) ,% e d x / * d e n o m * /
jb L R o u n d _ p r e p
ja L P r e v e n t _ 3 r d _ o v e r f l o w
cmpl S I G L ( % e b x ) ,% e a x / * d e n o m * /
jb L R o u n d _ p r e p
LPrevent_3rd_overflow :
/* prevent overflow */
subl S I G L ( % e b x ) ,% e a x
sbbl S I G H ( % e b x ) ,% e d x
movl % e d x ,F P U _ a c c u m _ 1
movl % e a x ,F P U _ a c c u m _ 0
addl $ 1 ,F P U _ r e s u l t _ 1 / * 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 _ 2
jne L R o u n d _ p r e p
jnc L R o u n d _ p r e p
/* This is a tricky spot, there is an overflow of the answer */
movb $ 2 5 5 ,F P U _ o v f l _ f l a g / * O v e r f l o w - > 1 . 0 0 0 * /
LRound_prep :
/ *
* Prepare f o r r o u n d i n g .
* To t e s t f o r r o u n d i n g , w e j u s t n e e d t o c o m p a r e 2 * a c c u m w i t h t h e
* denom.
* /
movl F P U _ a c c u m _ 0 ,% e c x
movl F P U _ a c c u m _ 1 ,% e d x
movl % e c x ,% e a x
orl % e d x ,% e a x
jz L R o u n d _ o v f l / * T h e a c c u m u l a t o r c o n t a i n s z e r o . * /
/* Multiply by 2 */
clc
rcll $ 1 ,% e c x
rcll $ 1 ,% e d x
jc L R o u n d _ l a r g e / * N o n e e d t o c o m p a r e , d e n o m s m a l l e r * /
subl S I G L ( % e b x ) ,% e c x
sbbl S I G H ( % e b x ) ,% e d x
jnc L R o u n d _ n o t _ s m a l l
movl $ 0 x70 0 0 0 0 0 0 ,% e a x / * D e n o m w a s l a r g e r * /
jmp L R o u n d _ o v f l
LRound_not_small :
jnz L R o u n d _ l a r g e
movl $ 0 x80 0 0 0 0 0 0 ,% e a x / * R e m a i n d e r w a s e x a c t l y 1 / 2 d e n o m * /
jmp L R o u n d _ o v f l
LRound_large :
movl $ 0 x f f00 0 0 0 0 ,% e a x / * D e n o m w a s s m a l l e r * /
LRound_ovfl :
/ * We a r e n o w r e a d y t o d e a l w i t h r o u n d i n g , b u t f i r s t w e m u s t g e t
the b i t s p r o p e r l y a l i g n e d * /
testb $ 2 5 5 ,F P U _ o v f l _ f l a g / * w a s t h e n u m > d e n o m ? * /
je L R o u n d _ p r e c i s i o n
incw E X P ( % e d i )
/* shift the mantissa right one bit */
stc / * W i l l s e t t h e m s b i t * /
rcrl F P U _ r e s u l t _ 2
rcrl F P U _ r e s u l t _ 1
rcrl % e a x
/* Round the result as required */
LRound_precision :
decw E X P ( % e d i ) / * b i n a r y p o i n t b e t w e e n 1 s t & 2 n d b i t s * /
movl % e a x ,% e d x
movl F P U _ r e s u l t _ 1 ,% e b x
movl F P U _ r e s u l t _ 2 ,% e a x
jmp f p u _ r e g _ r o u n d
# 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 x20 2
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 x20 3
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 x20 4
call E X C E P T I O N
pop % e b x
jmp L _ e x i t
L_exit :
movl $ - 1 ,% e a x
popl % e b x
popl % e d i
popl % e s i
leave
ret
# endif / * P A R A N O I D * /
2017-08-24 10:06:23 +02:00
ENDPROC( F P U _ u _ d i v )