⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reg_u_di.s

📁 汇编源码大全 有各种汇编源码 希望对你有所帮助
💻 S
字号:
	.file	"reg_u_div.S"/*---------------------------------------------------------------------------+ |  reg_u_div.S                                                              | |                                                                           | | Core division routines                                                    | |                                                                           | | Copyright (C) 1992,1993                                                   | |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      | |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    | |                                                                           | |                                                                           | +---------------------------------------------------------------------------*//*---------------------------------------------------------------------------+ |  Kernel for the division routines.                                        | |                                                                           | |  void reg_u_div(FPU_REG *a, FPU_REG *a,                                   | |                 FPU_REG *dest, unsigned int control_word)                 | |                                                                           | |  Does not compute the destination exponent, but does adjust it.           | +---------------------------------------------------------------------------*/#include "exception.h"#include "fpu_asm.h"#include "control_w.h"/* #define	dSIGL(x)	(x) *//* #define	dSIGH(x)	4(x) */#ifdef REENTRANT_FPU/*	Local storage on the stack:	Result:		FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0	Overflow flag:	ovfl_flag */#define FPU_accum_3	-4(%ebp)#define FPU_accum_2	-8(%ebp)#define FPU_accum_1	-12(%ebp)#define FPU_accum_0	-16(%ebp)#define FPU_result_1	-20(%ebp)#define FPU_result_2	-24(%ebp)#define FPU_ovfl_flag	-28(%ebp)#else.data/*	Local storage in a static area:	Result:		FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0	Overflow flag:	ovfl_flag */	.align 2,0FPU_accum_3:	.long	0FPU_accum_2:	.long	0FPU_accum_1:	.long	0FPU_accum_0:	.long	0FPU_result_1:	.long	0FPU_result_2:	.long	0FPU_ovfl_flag:	.byte	0#endif REENTRANT_FPU.text	.align 2,144.globl _reg_u_div.globl _divide_kernel_reg_u_div:	pushl	%ebp	movl	%esp,%ebp#ifdef REENTRANT_FPU	subl	$28,%esp#endif REENTRANT_FPU	pushl	%esi	pushl	%edi	pushl	%ebx	movl	PARAM1,%esi	/* pointer to num */	movl	PARAM2,%ebx	/* pointer to denom */	movl	PARAM3,%edi	/* pointer to answer */#ifdef DENORM_OPERAND	movl	EXP(%esi),%eax	cmpl	EXP_UNDER,%eax	jg	xOp1_not_denorm	call	_denormal_operand	orl	%eax,%eax	jnz	fpu_Arith_exitxOp1_not_denorm:	movl	EXP(%ebx),%eax	cmpl	EXP_UNDER,%eax	jg	xOp2_not_denorm	call	_denormal_operand	orl	%eax,%eax	jnz	fpu_Arith_exitxOp2_not_denorm:#endif DENORM_OPERAND_divide_kernel:#ifdef PARANOID/*	testl	$0x80000000, SIGH(%esi)	// Dividend *//*	je	L_bugged */	testl	$0x80000000, SIGH(%ebx)	/* Divisor */	je	L_bugged#endif PARANOID/* Check if the divisor can be treated as having just 32 bits */	cmpl	$0,SIGL(%ebx)	jnz	L_Full_Division	/* Can't do a quick divide *//* We should be able to zip through the division here */	movl	SIGH(%ebx),%ecx	/* The divisor */	movl	SIGH(%esi),%edx	/* Dividend */	movl	SIGL(%esi),%eax	/* Dividend */	cmpl	%ecx,%edx	setaeb	FPU_ovfl_flag	/* Keep a record */	jb	L_no_adjust	subl	%ecx,%edx	/* Prevent the overflow */L_no_adjust:	/* Divide the 64 bit number by the 32 bit denominator */	divl	%ecx	movl	%eax,FPU_result_2	/* Work on the remainder of the first division */	xorl	%eax,%eax	divl	%ecx	movl	%eax,FPU_result_1	/* Work on the remainder of the 64 bit division */	xorl	%eax,%eax	divl	%ecx	testb	$255,FPU_ovfl_flag	/* was the num > denom ? */	je	L_no_overflow	/* Do the shifting here */	/* increase the exponent */	incl	EXP(%edi)	/* shift the mantissa right one bit */	stc			/* To set the ms bit */	rcrl	FPU_result_2	rcrl	FPU_result_1	rcrl	%eaxL_no_overflow:	jmp	LRound_precision	/* Do the rounding as required *//*---------------------------------------------------------------------------+ |  Divide:   Return  arg1/arg2 to arg3.                                     | |                                                                           | |  This routine does not use the exponents of arg1 and arg2, but does       | |  adjust the exponent of arg3.                                             | |                                                                           | |  The maximum returned value is (ignoring exponents)                       | |               .ffffffff ffffffff                                          | |               ------------------  =  1.ffffffff fffffffe                  | |               .80000000 00000000                                          | | and the minimum is                                                        | |               .80000000 00000000                                          | |               ------------------  =  .80000000 00000001   (rounded)       | |               .ffffffff ffffffff                                          | |                                                                           | +---------------------------------------------------------------------------*/L_Full_Division:	/* Save extended dividend in local register */	movl	SIGL(%esi),%eax	movl	%eax,FPU_accum_2	movl	SIGH(%esi),%eax	movl	%eax,FPU_accum_3	xorl	%eax,%eax	movl	%eax,FPU_accum_1	/* zero the extension */	movl	%eax,FPU_accum_0	/* zero the extension */	movl	SIGL(%esi),%eax	/* Get the current num */	movl	SIGH(%esi),%edx/*----------------------------------------------------------------------*//* Initialization done.   Do the first 32 bits. */	movb	$0,FPU_ovfl_flag	cmpl	SIGH(%ebx),%edx	/* Test for imminent overflow */	jb	LLess_than_1	ja	LGreater_than_1	cmpl	SIGL(%ebx),%eax	jb	LLess_than_1LGreater_than_1:/* The dividend is greater or equal, would cause overflow */	setaeb	FPU_ovfl_flag		/* Keep a record */	subl	SIGL(%ebx),%eax	sbbl	SIGH(%ebx),%edx	/* Prevent the overflow */	movl	%eax,FPU_accum_2	movl	%edx,FPU_accum_3LLess_than_1:/* At this point, we have a dividend < divisor, with a record of   adjustment in FPU_ovfl_flag */	/* We will divide by a number which is too large */	movl	SIGH(%ebx),%ecx	addl	$1,%ecx	jnc	LFirst_div_not_1	/* here we need to divide by 100000000h,	   i.e., no division at all.. */	mov	%edx,%eax	jmp	LFirst_div_doneLFirst_div_not_1:	divl	%ecx		/* Divide the numerator by the augmented				   denom ms dw */LFirst_div_done:	movl	%eax,FPU_result_2	/* Put the result in the answer */	mull	SIGH(%ebx)	/* mul by the ms dw of the denom */	subl	%eax,FPU_accum_2	/* Subtract from the num local reg */	sbbl	%edx,FPU_accum_3	movl	FPU_result_2,%eax	/* Get the result back */	mull	SIGL(%ebx)	/* now mul the ls dw of the denom */	subl	%eax,FPU_accum_1	/* Subtract from the num local reg */	sbbl	%edx,FPU_accum_2	sbbl	$0,FPU_accum_3	je	LDo_2nd_32_bits		/* Must check for non-zero result here */#ifdef PARANOID	jb	L_bugged_1#endif PARANOID	/* need to subtract another once of the denom */	incl	FPU_result_2	/* Correct the answer */	movl	SIGL(%ebx),%eax	movl	SIGH(%ebx),%edx	subl	%eax,FPU_accum_1	/* Subtract from the num local reg */	sbbl	%edx,FPU_accum_2#ifdef PARANOID	sbbl	$0,FPU_accum_3	jne	L_bugged_1	/* Must check for non-zero result here */#endif PARANOID/*----------------------------------------------------------------------*//* Half of the main problem is done, there is just a reduced numerator   to handle now.   Work with the second 32 bits, FPU_accum_0 not used from now on */LDo_2nd_32_bits:	movl	FPU_accum_2,%edx	/* get the reduced num */	movl	FPU_accum_1,%eax	/* need to check for possible subsequent overflow */	cmpl	SIGH(%ebx),%edx	jb	LDo_2nd_div	ja	LPrevent_2nd_overflow	cmpl	SIGL(%ebx),%eax	jb	LDo_2nd_divLPrevent_2nd_overflow:/* The numerator is greater or equal, would cause overflow */	/* prevent overflow */	subl	SIGL(%ebx),%eax	sbbl	SIGH(%ebx),%edx	movl	%edx,FPU_accum_2	movl	%eax,FPU_accum_1	incl	FPU_result_2	/* Reflect the subtraction in the answer */#ifdef PARANOID	je	L_bugged_2	/* Can't bump the result to 1.0 */#endif PARANOIDLDo_2nd_div:	cmpl	$0,%ecx		/* augmented denom msw */	jnz	LSecond_div_not_1	/* %ecx == 0, we are dividing by 1.0 */	mov	%edx,%eax	jmp	LSecond_div_doneLSecond_div_not_1:	divl	%ecx		/* Divide the numerator by the denom ms dw */LSecond_div_done:	movl	%eax,FPU_result_1	/* Put the result in the answer */	mull	SIGH(%ebx)	/* mul by the ms dw of the denom */	subl	%eax,FPU_accum_1	/* Subtract from the num local reg */	sbbl	%edx,FPU_accum_2#ifdef PARANOID	jc	L_bugged_2#endif PARANOID	movl	FPU_result_1,%eax	/* Get the result back */	mull	SIGL(%ebx)	/* now mul the ls dw of the denom */	subl	%eax,FPU_accum_0	/* Subtract from the num local reg */	sbbl	%edx,FPU_accum_1	/* Subtract from the num local reg */	sbbl	$0,FPU_accum_2#ifdef PARANOID	jc	L_bugged_2#endif PARANOID	jz	LDo_3rd_32_bits#ifdef PARANOID	cmpl	$1,FPU_accum_2	jne	L_bugged_2#endif PARANOID	/* need to subtract another once of the denom */	movl	SIGL(%ebx),%eax	movl	SIGH(%ebx),%edx	subl	%eax,FPU_accum_0	/* Subtract from the num local reg */	sbbl	%edx,FPU_accum_1	sbbl	$0,FPU_accum_2#ifdef PARANOID	jc	L_bugged_2	jne	L_bugged_2#endif PARANOID	addl	$1,FPU_result_1	/* Correct the answer */	adcl	$0,FPU_result_2#ifdef PARANOID	jc	L_bugged_2	/* Must check for non-zero result here */#endif PARANOID/*----------------------------------------------------------------------*//* The division is essentially finished here, we just need to perform   tidying operations.   Deal with the 3rd 32 bits */LDo_3rd_32_bits:	movl	FPU_accum_1,%edx		/* get the reduced num */	movl	FPU_accum_0,%eax	/* need to check for possible subsequent overflow */	cmpl	SIGH(%ebx),%edx	/* denom */	jb	LRound_prep	ja	LPrevent_3rd_overflow	cmpl	SIGL(%ebx),%eax	/* denom */	jb	LRound_prepLPrevent_3rd_overflow:	/* prevent overflow */	subl	SIGL(%ebx),%eax	sbbl	SIGH(%ebx),%edx	movl	%edx,FPU_accum_1	movl	%eax,FPU_accum_0	addl	$1,FPU_result_1	/* Reflect the subtraction in the answer */	adcl	$0,FPU_result_2	jne	LRound_prep	jnc	LRound_prep	/* This is a tricky spot, there is an overflow of the answer */	movb	$255,FPU_ovfl_flag		/* Overflow -> 1.000 */LRound_prep:/* * Prepare for rounding. * To test for rounding, we just need to compare 2*accum with the * denom. */	movl	FPU_accum_0,%ecx	movl	FPU_accum_1,%edx	movl	%ecx,%eax	orl	%edx,%eax	jz	LRound_ovfl		/* The accumulator contains zero. */	/* Multiply by 2 */	clc	rcll	$1,%ecx	rcll	$1,%edx	jc	LRound_large		/* No need to compare, denom smaller */	subl	SIGL(%ebx),%ecx	sbbl	SIGH(%ebx),%edx	jnc	LRound_not_small	movl	$0x70000000,%eax	/* Denom was larger */	jmp	LRound_ovflLRound_not_small:	jnz	LRound_large	movl	$0x80000000,%eax	/* Remainder was exactly 1/2 denom */	jmp	LRound_ovflLRound_large:	movl	$0xff000000,%eax	/* Denom was smaller */LRound_ovfl:/* We are now ready to deal with rounding, but first we must get   the bits properly aligned */	testb	$255,FPU_ovfl_flag	/* was the num > denom ? */	je	LRound_precision	incl	EXP(%edi)	/* shift the mantissa right one bit */	stc			/* Will set the ms bit */	rcrl	FPU_result_2	rcrl	FPU_result_1	rcrl	%eax/* Round the result as required */LRound_precision:	decl	EXP(%edi)	/* binary point between 1st & 2nd bits */	movl	%eax,%edx	movl	FPU_result_1,%ebx	movl	FPU_result_2,%eax	jmp	fpu_reg_round#ifdef PARANOID/* The logic is wrong if we got here */L_bugged:	pushl	EX_INTERNAL|0x202	call	EXCEPTION	pop	%ebx	jmp	L_exitL_bugged_1:	pushl	EX_INTERNAL|0x203	call	EXCEPTION	pop	%ebx	jmp	L_exitL_bugged_2:	pushl	EX_INTERNAL|0x204	call	EXCEPTION	pop	%ebx	jmp	L_exitL_exit:	popl	%ebx	popl	%edi	popl	%esi	leave	ret#endif PARANOID

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -