| 	.file	"reg_u_mul.S" | 
 | /*---------------------------------------------------------------------------+ | 
 |  |  reg_u_mul.S                                                              | | 
 |  |                                                                           | | 
 |  | Core multiplication routine                                               | | 
 |  |                                                                           | | 
 |  | Copyright (C) 1992,1993,1995,1997                                         | | 
 |  |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia | | 
 |  |                  E-mail   billm@suburbia.net                              | | 
 |  |                                                                           | | 
 |  |                                                                           | | 
 |  +---------------------------------------------------------------------------*/ | 
 |  | 
 | /*---------------------------------------------------------------------------+ | 
 |  |   Basic multiplication routine.                                           | | 
 |  |   Does not check the resulting exponent for overflow/underflow            | | 
 |  |                                                                           | | 
 |  |   FPU_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw);         | | 
 |  |                                                                           | | 
 |  |   Internal working is at approx 128 bits.                                 | | 
 |  |   Result is rounded to nearest 53 or 64 bits, using "nearest or even".    | | 
 |  +---------------------------------------------------------------------------*/ | 
 |  | 
 | #include "exception.h" | 
 | #include "fpu_emu.h" | 
 | #include "control_w.h" | 
 |  | 
 |  | 
 |  | 
 | #ifndef NON_REENTRANT_FPU | 
 | /*  Local storage on the stack: */ | 
 | #define FPU_accum_0	-4(%ebp)	/* ms word */ | 
 | #define FPU_accum_1	-8(%ebp) | 
 |  | 
 | #else | 
 | /*  Local storage in a static area: */ | 
 | .data | 
 | 	.align 4,0 | 
 | FPU_accum_0: | 
 | 	.long	0 | 
 | FPU_accum_1: | 
 | 	.long	0 | 
 | #endif /* NON_REENTRANT_FPU */ | 
 |  | 
 |  | 
 | .text | 
 | ENTRY(FPU_u_mul) | 
 | 	pushl	%ebp | 
 | 	movl	%esp,%ebp | 
 | #ifndef NON_REENTRANT_FPU | 
 | 	subl	$8,%esp | 
 | #endif /* NON_REENTRANT_FPU */  | 
 |  | 
 | 	pushl	%esi | 
 | 	pushl	%edi | 
 | 	pushl	%ebx | 
 |  | 
 | 	movl	PARAM1,%esi | 
 | 	movl	PARAM2,%edi | 
 |  | 
 | #ifdef PARANOID | 
 | 	testl	$0x80000000,SIGH(%esi) | 
 | 	jz	L_bugged | 
 | 	testl	$0x80000000,SIGH(%edi) | 
 | 	jz	L_bugged | 
 | #endif /* PARANOID */ | 
 |  | 
 | 	xorl	%ecx,%ecx | 
 | 	xorl	%ebx,%ebx | 
 |  | 
 | 	movl	SIGL(%esi),%eax | 
 | 	mull	SIGL(%edi) | 
 | 	movl	%eax,FPU_accum_0 | 
 | 	movl	%edx,FPU_accum_1 | 
 |  | 
 | 	movl	SIGL(%esi),%eax | 
 | 	mull	SIGH(%edi) | 
 | 	addl	%eax,FPU_accum_1 | 
 | 	adcl	%edx,%ebx | 
 | /*	adcl	$0,%ecx		// overflow here is not possible */ | 
 |  | 
 | 	movl	SIGH(%esi),%eax | 
 | 	mull	SIGL(%edi) | 
 | 	addl	%eax,FPU_accum_1 | 
 | 	adcl	%edx,%ebx | 
 | 	adcl	$0,%ecx | 
 |  | 
 | 	movl	SIGH(%esi),%eax | 
 | 	mull	SIGH(%edi) | 
 | 	addl	%eax,%ebx | 
 | 	adcl	%edx,%ecx | 
 |  | 
 | 	/* Get the sum of the exponents. */ | 
 | 	movl	PARAM6,%eax | 
 | 	subl	EXP_BIAS-1,%eax | 
 |  | 
 | 	/* Two denormals can cause an exponent underflow */ | 
 | 	cmpl	EXP_WAY_UNDER,%eax | 
 | 	jg	Exp_not_underflow | 
 |  | 
 | 	/* Set to a really low value allow correct handling */ | 
 | 	movl	EXP_WAY_UNDER,%eax | 
 |  | 
 | Exp_not_underflow: | 
 |  | 
 | /*  Have now finished with the sources */ | 
 | 	movl	PARAM3,%edi	/* Point to the destination */ | 
 | 	movw	%ax,EXP(%edi) | 
 |  | 
 | /*  Now make sure that the result is normalized */ | 
 | 	testl	$0x80000000,%ecx | 
 | 	jnz	LResult_Normalised | 
 |  | 
 | 	/* Normalize by shifting left one bit */ | 
 | 	shll	$1,FPU_accum_0 | 
 | 	rcll	$1,FPU_accum_1 | 
 | 	rcll	$1,%ebx | 
 | 	rcll	$1,%ecx | 
 | 	decw	EXP(%edi) | 
 |  | 
 | LResult_Normalised: | 
 | 	movl	FPU_accum_0,%eax | 
 | 	movl	FPU_accum_1,%edx | 
 | 	orl	%eax,%eax | 
 | 	jz	L_extent_zero | 
 |  | 
 | 	orl	$1,%edx | 
 |  | 
 | L_extent_zero: | 
 | 	movl	%ecx,%eax | 
 | 	jmp	fpu_reg_round | 
 |  | 
 |  | 
 | #ifdef PARANOID | 
 | L_bugged: | 
 | 	pushl	EX_INTERNAL|0x205 | 
 | 	call	EXCEPTION | 
 | 	pop	%ebx | 
 | 	jmp	L_exit | 
 |  | 
 | L_exit: | 
 | 	popl	%ebx | 
 | 	popl	%edi | 
 | 	popl	%esi | 
 | 	leave | 
 | 	ret | 
 | #endif /* PARANOID */  | 
 |  |