1 /* SPDX-License-Identifier: GPL-2.0 */
2 	.file	"reg_u_mul.S"
3 /*---------------------------------------------------------------------------+
4  |  reg_u_mul.S                                                              |
5  |                                                                           |
6  | Core multiplication routine                                               |
7  |                                                                           |
8  | Copyright (C) 1992,1993,1995,1997                                         |
9  |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
10  |                  E-mail   billm@suburbia.net                              |
11  |                                                                           |
12  |                                                                           |
13  +---------------------------------------------------------------------------*/
14 
15 /*---------------------------------------------------------------------------+
16  |   Basic multiplication routine.                                           |
17  |   Does not check the resulting exponent for overflow/underflow            |
18  |                                                                           |
19  |   FPU_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw);         |
20  |                                                                           |
21  |   Internal working is at approx 128 bits.                                 |
22  |   Result is rounded to nearest 53 or 64 bits, using "nearest or even".    |
23  +---------------------------------------------------------------------------*/
24 
25 #include "exception.h"
26 #include "fpu_emu.h"
27 #include "control_w.h"
28 
29 
30 
31 #ifndef NON_REENTRANT_FPU
32 /*  Local storage on the stack: */
33 #define FPU_accum_0	-4(%ebp)	/* ms word */
34 #define FPU_accum_1	-8(%ebp)
35 
36 #else
37 /*  Local storage in a static area: */
38 .data
39 	.align 4,0
40 FPU_accum_0:
41 	.long	0
42 FPU_accum_1:
43 	.long	0
44 #endif /* NON_REENTRANT_FPU */
45 
46 
47 .text
48 SYM_FUNC_START(FPU_u_mul)
49 	pushl	%ebp
50 	movl	%esp,%ebp
51 #ifndef NON_REENTRANT_FPU
52 	subl	$8,%esp
53 #endif /* NON_REENTRANT_FPU */
54 
55 	pushl	%esi
56 	pushl	%edi
57 	pushl	%ebx
58 
59 	movl	PARAM1,%esi
60 	movl	PARAM2,%edi
61 
62 #ifdef PARANOID
63 	testl	$0x80000000,SIGH(%esi)
64 	jz	L_bugged
65 	testl	$0x80000000,SIGH(%edi)
66 	jz	L_bugged
67 #endif /* PARANOID */
68 
69 	xorl	%ecx,%ecx
70 	xorl	%ebx,%ebx
71 
72 	movl	SIGL(%esi),%eax
73 	mull	SIGL(%edi)
74 	movl	%eax,FPU_accum_0
75 	movl	%edx,FPU_accum_1
76 
77 	movl	SIGL(%esi),%eax
78 	mull	SIGH(%edi)
79 	addl	%eax,FPU_accum_1
80 	adcl	%edx,%ebx
81 /*	adcl	$0,%ecx		// overflow here is not possible */
82 
83 	movl	SIGH(%esi),%eax
84 	mull	SIGL(%edi)
85 	addl	%eax,FPU_accum_1
86 	adcl	%edx,%ebx
87 	adcl	$0,%ecx
88 
89 	movl	SIGH(%esi),%eax
90 	mull	SIGH(%edi)
91 	addl	%eax,%ebx
92 	adcl	%edx,%ecx
93 
94 	/* Get the sum of the exponents. */
95 	movl	PARAM6,%eax
96 	subl	EXP_BIAS-1,%eax
97 
98 	/* Two denormals can cause an exponent underflow */
99 	cmpl	EXP_WAY_UNDER,%eax
100 	jg	Exp_not_underflow
101 
102 	/* Set to a really low value allow correct handling */
103 	movl	EXP_WAY_UNDER,%eax
104 
105 Exp_not_underflow:
106 
107 /*  Have now finished with the sources */
108 	movl	PARAM3,%edi	/* Point to the destination */
109 	movw	%ax,EXP(%edi)
110 
111 /*  Now make sure that the result is normalized */
112 	testl	$0x80000000,%ecx
113 	jnz	LResult_Normalised
114 
115 	/* Normalize by shifting left one bit */
116 	shll	$1,FPU_accum_0
117 	rcll	$1,FPU_accum_1
118 	rcll	$1,%ebx
119 	rcll	$1,%ecx
120 	decw	EXP(%edi)
121 
122 LResult_Normalised:
123 	movl	FPU_accum_0,%eax
124 	movl	FPU_accum_1,%edx
125 	orl	%eax,%eax
126 	jz	L_extent_zero
127 
128 	orl	$1,%edx
129 
130 L_extent_zero:
131 	movl	%ecx,%eax
132 	jmp	fpu_reg_round
133 
134 
135 #ifdef PARANOID
136 L_bugged:
137 	pushl	EX_INTERNAL|0x205
138 	call	EXCEPTION
139 	pop	%ebx
140 	jmp	L_exit
141 
142 L_exit:
143 	popl	%ebx
144 	popl	%edi
145 	popl	%esi
146 	leave
147 	RET
148 #endif /* PARANOID */
149 
150 SYM_FUNC_END(FPU_u_mul)
151