149 lines
		
	
	
	
		
			3.6 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
		
		
			
		
	
	
			149 lines
		
	
	
	
		
			3.6 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| 
								 | 
							
									.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 */ 
							 | 
						||
| 
								 | 
							
								
							 |