2005-04-17 02:20:36 +04:00
.file " reg_ u _ s u b . S "
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| reg_ u _ s u b . S |
| |
| Core f l o a t i n g p o i n t s u b t r a c t i o n r o u t i n e . |
| |
| 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 _ s u b ( F P U _ R E G * a r g 1 , F P U _ R E G * a r g 2 , F P U _ R E G * a n s w , |
| int c o n t r o l _ w ) |
| 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 . |
| |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * /
/ *
| Kernel s u b t r a c t i o n r o u t i n e F P U _ u _ s u b ( r e g * a r g 1 , r e g * a r g 2 , r e g * a n s w ) .
| Takes t w o v a l i d r e g f . p . n u m b e r s ( T A G _ V a l i d ) , w h i c h a r e
| treated a s u n s i g n e d n u m b e r s ,
| and r e t u r n s t h e i r d i f f e r e n c e a s a T A G _ V a l i d o r T A G _ Z e r o f . p .
| number.
| The f i r s t n u m b e r ( a r g 1 ) m u s t b e t h e l a r g e r .
| The r e t u r n e d n u m b e r i s n o r m a l i z e d .
| Basic c h e c k s a r e p e r f o r m e d i f P A R A N O I D i s d e f i n e d .
* /
# 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 "
.text
ENTRY( F P U _ u _ s u b )
pushl % e b p
movl % e s p ,% e b p
pushl % e s i
pushl % e d i
pushl % e b x
movl P A R A M 1 ,% e s i / * s o u r c e 1 * /
movl P A R A M 2 ,% e d i / * s o u r c e 2 * /
movl P A R A M 6 ,% e c x
subl P A R A M 7 ,% e c x / * e x p1 - e x p2 * /
# ifdef P A R A N O I D
/* source 2 is always smaller than source 1 */
js L _ b u g g e d _ 1
testl $ 0 x80 0 0 0 0 0 0 ,S I G H ( % e d i ) / * T h e a r g s a r e a s s u m e d t o b e b e n o r m a l i z e d * /
je L _ b u g g e d _ 2
testl $ 0 x80 0 0 0 0 0 0 ,S I G H ( % e s i )
je L _ b u g g e d _ 2
# endif / * P A R A N O I D * /
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Form a r e g i s t e r h o l d i n g t h e |
| smaller n u m b e r |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * /
movl S I G H ( % e d i ) ,% e a x / * r e g i s t e r m s w o r d * /
movl S I G L ( % e d i ) ,% e b x / * r e g i s t e r l s w o r d * /
movl P A R A M 3 ,% e d i / * d e s t i n a t i o n * /
movl P A R A M 6 ,% e d x
movw % d x ,E X P ( % e d i ) / * C o p y e x p o n e n t t o d e s t i n a t i o n * /
xorl % e d x ,% e d x / * r e g i s t e r e x t e n s i o n * /
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Shift t h e t e m p o r a r y r e g i s t e r |
| right t h e r e q u i r e d n u m b e r o f |
| places. |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * /
cmpw $ 3 2 ,% c x / * s h r d o n l y w o r k s f o r 0 . . 3 1 b i t s * /
jnc L _ m o r e _ t h a n _ 3 1
/* less than 32 bits */
shrd % c l ,% e b x ,% e d x
shrd % c l ,% e a x ,% e b x
shr % c l ,% e a x
jmp L _ s h i f t _ d o n e
L_more_than_31 :
cmpw $ 6 4 ,% c x
jnc L _ m o r e _ t h a n _ 6 3
subb $ 3 2 ,% c l
jz L _ e x a c t l y _ 3 2
shrd % c l ,% e a x ,% e d x
shr % c l ,% e a x
orl % e b x ,% e b x
jz L _ m o r e _ 3 1 _ n o _ l o w / * n o n e o f t h e l o w e s t b i t s i s s e t * /
orl $ 1 ,% e d x / * r e c o r d t h e f a c t i n t h e e x t e n s i o n * /
L_more_31_no_low :
movl % e a x ,% e b x
xorl % e a x ,% e a x
jmp L _ s h i f t _ d o n e
L_exactly_32 :
movl % e b x ,% e d x
movl % e a x ,% e b x
xorl % e a x ,% e a x
jmp L _ s h i f t _ d o n e
L_more_than_63 :
cmpw $ 6 5 ,% c x
jnc L _ m o r e _ t h a n _ 6 4
/* Shift right by 64 bits */
movl % e a x ,% e d x
orl % e b x ,% e b x
jz L _ m o r e _ 6 3 _ n o _ l o w
orl $ 1 ,% e d x
jmp L _ m o r e _ 6 3 _ n o _ l o w
L_more_than_64 :
jne L _ m o r e _ t h a n _ 6 5
/* Shift right by 65 bits */
/* Carry is clear if we get here */
movl % e a x ,% e d x
rcrl % e d x
jnc L _ s h i f t _ 6 5 _ n c
orl $ 1 ,% e d x
jmp L _ m o r e _ 6 3 _ n o _ l o w
L_shift_65_nc :
orl % e b x ,% e b x
jz L _ m o r e _ 6 3 _ n o _ l o w
orl $ 1 ,% e d x
jmp L _ m o r e _ 6 3 _ n o _ l o w
L_more_than_65 :
movl $ 1 ,% e d x / * T h e s h i f t e d n r a l w a y s a t l e a s t o n e ' 1 ' * /
L_more_63_no_low :
xorl % e b x ,% e b x
xorl % e a x ,% e a x
L_shift_done :
L_subtr :
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Do t h e s u b t r a c t i o n |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * /
xorl % e c x ,% e c x
subl % e d x ,% e c x
movl % e c x ,% e d x
movl S I G L ( % e s i ) ,% e c x
sbbl % e b x ,% e c x
movl % e c x ,% e b x
movl S I G H ( % e s i ) ,% e c x
sbbl % e a x ,% e c x
movl % e c x ,% e a x
# ifdef P A R A N O I D
/* We can never get a borrow */
jc L _ b u g g e d
# endif / * P A R A N O I D * /
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Normalize t h e r e s u l t |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * /
testl $ 0 x80 0 0 0 0 0 0 ,% e a x
jnz L _ r o u n d / * n o s h i f t i n g n e e d e d * /
orl % e a x ,% e a x
jnz L _ s h i f t _ 1 / * s h i f t l e f t 1 - 3 1 b i t s * /
orl % e b x ,% e b x
jnz L _ s h i f t _ 3 2 / * s h i f t l e f t 3 2 - 6 3 b i t s * /
/ *
* A r a r e c a s e , t h e o n l y o n e w h i c h i s n o n - z e r o i f w e g o t h e r e
* is : 1 0 0 0 0 0 0 . . . . 0 0 0 0
* - 0 1 1 1 1 1 1 . . . . 1 1 1 1 1
* - - - - - - - - - - - - - - - - - - - -
* 0 0 0 0 0 0 0 . . . . 0 0 0 0 1
* /
cmpl $ 0 x80 0 0 0 0 0 0 ,% e d x
jnz L _ m u s t _ b e _ z e r o
/* Shift left 64 bits */
subw $ 6 4 ,E X P ( % e d i )
xchg % e d x ,% e a x
jmp f p u _ r e g _ r o u n d
L_must_be_zero :
# ifdef P A R A N O I D
orl % e d x ,% e d x
jnz L _ b u g g e d _ 3
# endif / * P A R A N O I D * /
/* The result is zero */
movw $ 0 ,E X P ( % e d i ) / * e x p o n e n t * /
movl $ 0 ,S I G L ( % e d i )
movl $ 0 ,S I G H ( % e d i )
movl T A G _ Z e r o ,% e a x
jmp L _ e x i t
L_shift_32 :
movl % e b x ,% e a x
movl % e d x ,% e b x
movl $ 0 ,% e d x
subw $ 3 2 ,E X P ( % e d i ) / * C a n g e t u n d e r f l o w h e r e * /
/* We need to shift left by 1 - 31 bits */
L_shift_1 :
bsrl % e a x ,% e c x / * g e t t h e r e q u i r e d s h i f t i n % e c x * /
subl $ 3 1 ,% e c x
negl % e c x
shld % c l ,% e b x ,% e a x
shld % c l ,% e d x ,% e b x
shl % c l ,% e d x
subw % c x ,E X P ( % e d i ) / * C a n g e t u n d e r f l o w h e r e * /
L_round :
jmp f p u _ r e g _ r o u n d / * R o u n d t h e r e s u l t * /
# ifdef P A R A N O I D
L_bugged_1 :
pushl E X _ I N T E R N A L | 0 x20 6
call E X C E P T I O N
pop % e b x
jmp L _ e r r o r _ e x i t
L_bugged_2 :
pushl E X _ I N T E R N A L | 0 x20 9
call E X C E P T I O N
pop % e b x
jmp L _ e r r o r _ e x i t
L_bugged_3 :
pushl E X _ I N T E R N A L | 0 x21 0
call E X C E P T I O N
pop % e b x
jmp L _ e r r o r _ e x i t
L_bugged_4 :
pushl E X _ I N T E R N A L | 0 x21 1
call E X C E P T I O N
pop % e b x
jmp L _ e r r o r _ e x i t
L_bugged :
pushl E X _ I N T E R N A L | 0 x21 2
call E X C E P T I O N
pop % e b x
jmp L _ e r r o r _ e x i t
L_error_exit :
movl $ - 1 ,% e a x
# endif / * P A R A N O I D * /
L_exit :
popl % e b x
popl % e d i
popl % e s i
leave
ret
2017-08-24 11:06:23 +03:00
ENDPROC( F P U _ u _ s u b )