| /*---------------------------------------------------------------------------+ | 
 |  |  reg_norm.S                                                               | | 
 |  |                                                                           | | 
 |  | Copyright (C) 1992,1993,1994,1995,1997                                    | | 
 |  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      | | 
 |  |                       Australia.  E-mail billm@suburbia.net               | | 
 |  |                                                                           | | 
 |  | Normalize the value in a FPU_REG.                                         | | 
 |  |                                                                           | | 
 |  | Call from C as:                                                           | | 
 |  |    int FPU_normalize(FPU_REG *n)                                          | | 
 |  |                                                                           | | 
 |  |    int FPU_normalize_nuo(FPU_REG *n)                                      | | 
 |  |                                                                           | | 
 |  |    Return value is the tag of the answer, or-ed with FPU_Exception if     | | 
 |  |    one was raised, or -1 on internal error.                               | | 
 |  |                                                                           | | 
 |  +---------------------------------------------------------------------------*/ | 
 |  | 
 | #include "fpu_emu.h" | 
 |  | 
 |  | 
 | .text | 
 | ENTRY(FPU_normalize) | 
 | 	pushl	%ebp | 
 | 	movl	%esp,%ebp | 
 | 	pushl	%ebx | 
 |  | 
 | 	movl	PARAM1,%ebx | 
 |  | 
 | 	movl	SIGH(%ebx),%edx | 
 | 	movl	SIGL(%ebx),%eax | 
 |  | 
 | 	orl	%edx,%edx	/* ms bits */ | 
 | 	js	L_done		/* Already normalized */ | 
 | 	jnz	L_shift_1	/* Shift left 1 - 31 bits */ | 
 |  | 
 | 	orl	%eax,%eax | 
 | 	jz	L_zero		/* The contents are zero */ | 
 |  | 
 | 	movl	%eax,%edx | 
 | 	xorl	%eax,%eax | 
 | 	subw	$32,EXP(%ebx)	/* This can cause an underflow */ | 
 |  | 
 | /* We need to shift left by 1 - 31 bits */ | 
 | L_shift_1: | 
 | 	bsrl	%edx,%ecx	/* get the required shift in %ecx */ | 
 | 	subl	$31,%ecx | 
 | 	negl	%ecx | 
 | 	shld	%cl,%eax,%edx | 
 | 	shl	%cl,%eax | 
 | 	subw	%cx,EXP(%ebx)	/* This can cause an underflow */ | 
 |  | 
 | 	movl	%edx,SIGH(%ebx) | 
 | 	movl	%eax,SIGL(%ebx) | 
 |  | 
 | L_done: | 
 | 	cmpw	EXP_OVER,EXP(%ebx) | 
 | 	jge	L_overflow | 
 |  | 
 | 	cmpw	EXP_UNDER,EXP(%ebx) | 
 | 	jle	L_underflow | 
 |  | 
 | L_exit_valid: | 
 | 	movl	TAG_Valid,%eax | 
 |  | 
 | 	/* Convert the exponent to 80x87 form. */ | 
 | 	addw	EXTENDED_Ebias,EXP(%ebx) | 
 | 	andw	$0x7fff,EXP(%ebx) | 
 |  | 
 | L_exit: | 
 | 	popl	%ebx | 
 | 	leave | 
 | 	ret | 
 |  | 
 |  | 
 | L_zero: | 
 | 	movw	$0,EXP(%ebx) | 
 | 	movl	TAG_Zero,%eax | 
 | 	jmp	L_exit | 
 |  | 
 | L_underflow: | 
 | 	/* Convert the exponent to 80x87 form. */ | 
 | 	addw	EXTENDED_Ebias,EXP(%ebx) | 
 | 	push	%ebx | 
 | 	call	arith_underflow | 
 | 	pop	%ebx | 
 | 	jmp	L_exit | 
 |  | 
 | L_overflow: | 
 | 	/* Convert the exponent to 80x87 form. */ | 
 | 	addw	EXTENDED_Ebias,EXP(%ebx) | 
 | 	push	%ebx | 
 | 	call	arith_overflow | 
 | 	pop	%ebx | 
 | 	jmp	L_exit | 
 |  | 
 |  | 
 |  | 
 | /* Normalise without reporting underflow or overflow */ | 
 | ENTRY(FPU_normalize_nuo) | 
 | 	pushl	%ebp | 
 | 	movl	%esp,%ebp | 
 | 	pushl	%ebx | 
 |  | 
 | 	movl	PARAM1,%ebx | 
 |  | 
 | 	movl	SIGH(%ebx),%edx | 
 | 	movl	SIGL(%ebx),%eax | 
 |  | 
 | 	orl	%edx,%edx	/* ms bits */ | 
 | 	js	L_exit_nuo_valid	/* Already normalized */ | 
 | 	jnz	L_nuo_shift_1	/* Shift left 1 - 31 bits */ | 
 |  | 
 | 	orl	%eax,%eax | 
 | 	jz	L_exit_nuo_zero		/* The contents are zero */ | 
 |  | 
 | 	movl	%eax,%edx | 
 | 	xorl	%eax,%eax | 
 | 	subw	$32,EXP(%ebx)	/* This can cause an underflow */ | 
 |  | 
 | /* We need to shift left by 1 - 31 bits */ | 
 | L_nuo_shift_1: | 
 | 	bsrl	%edx,%ecx	/* get the required shift in %ecx */ | 
 | 	subl	$31,%ecx | 
 | 	negl	%ecx | 
 | 	shld	%cl,%eax,%edx | 
 | 	shl	%cl,%eax | 
 | 	subw	%cx,EXP(%ebx)	/* This can cause an underflow */ | 
 |  | 
 | 	movl	%edx,SIGH(%ebx) | 
 | 	movl	%eax,SIGL(%ebx) | 
 |  | 
 | L_exit_nuo_valid: | 
 | 	movl	TAG_Valid,%eax | 
 |  | 
 | 	popl	%ebx | 
 | 	leave | 
 | 	ret | 
 |  | 
 | L_exit_nuo_zero: | 
 | 	movl	TAG_Zero,%eax | 
 | 	movw	EXP_UNDER,EXP(%ebx) | 
 |  | 
 | 	popl	%ebx | 
 | 	leave | 
 | 	ret |