Linux Audio

Check our new training course

Loading...
v6.2
  1/* SPDX-License-Identifier: GPL-2.0 */
  2	.file	"reg_u_sub.S"
  3/*---------------------------------------------------------------------------+
  4 |  reg_u_sub.S                                                              |
  5 |                                                                           |
  6 | Core floating point subtraction 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 | Call from C as:                                                           |
 13 |    int FPU_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,             |
 14 |                                                int control_w)             |
 15 |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
 16 |    one was raised, or -1 on internal error.                               |
 17 |                                                                           |
 18 +---------------------------------------------------------------------------*/
 19
 20/*
 21 |    Kernel subtraction routine FPU_u_sub(reg *arg1, reg *arg2, reg *answ).
 22 |    Takes two valid reg f.p. numbers (TAG_Valid), which are
 23 |    treated as unsigned numbers,
 24 |    and returns their difference as a TAG_Valid or TAG_Zero f.p.
 25 |    number.
 26 |    The first number (arg1) must be the larger.
 27 |    The returned number is normalized.
 28 |    Basic checks are performed if PARANOID is defined.
 29 */
 30
 31#include "exception.h"
 32#include "fpu_emu.h"
 33#include "control_w.h"
 34
 35.text
 36SYM_FUNC_START(FPU_u_sub)
 37	pushl	%ebp
 38	movl	%esp,%ebp
 39	pushl	%esi
 40	pushl	%edi
 41	pushl	%ebx
 42
 43	movl	PARAM1,%esi	/* source 1 */
 44	movl	PARAM2,%edi	/* source 2 */
 45	
 46	movl	PARAM6,%ecx
 47	subl	PARAM7,%ecx	/* exp1 - exp2 */
 48
 49#ifdef PARANOID
 50	/* source 2 is always smaller than source 1 */
 51	js	L_bugged_1
 52
 53	testl	$0x80000000,SIGH(%edi)	/* The args are assumed to be be normalized */
 54	je	L_bugged_2
 55
 56	testl	$0x80000000,SIGH(%esi)
 57	je	L_bugged_2
 58#endif /* PARANOID */
 59
 60/*--------------------------------------+
 61 |	Form a register holding the     |
 62 |	smaller number                  |
 63 +--------------------------------------*/
 64	movl	SIGH(%edi),%eax	/* register ms word */
 65	movl	SIGL(%edi),%ebx	/* register ls word */
 66
 67	movl	PARAM3,%edi	/* destination */
 68	movl	PARAM6,%edx
 69	movw	%dx,EXP(%edi)	/* Copy exponent to destination */
 70
 71	xorl	%edx,%edx	/* register extension */
 72
 73/*--------------------------------------+
 74 |	Shift the temporary register	|
 75 |      right the required number of	|
 76 |	places.				|
 77 +--------------------------------------*/
 78
 79	cmpw	$32,%cx		/* shrd only works for 0..31 bits */
 80	jnc	L_more_than_31
 81
 82/* less than 32 bits */
 83	shrd	%cl,%ebx,%edx
 84	shrd	%cl,%eax,%ebx
 85	shr	%cl,%eax
 86	jmp	L_shift_done
 87
 88L_more_than_31:
 89	cmpw	$64,%cx
 90	jnc	L_more_than_63
 91
 92	subb	$32,%cl
 93	jz	L_exactly_32
 94
 95	shrd	%cl,%eax,%edx
 96	shr	%cl,%eax
 97	orl	%ebx,%ebx
 98	jz	L_more_31_no_low	/* none of the lowest bits is set */
 99
100	orl	$1,%edx			/* record the fact in the extension */
101
102L_more_31_no_low:
103	movl	%eax,%ebx
104	xorl	%eax,%eax
105	jmp	L_shift_done
106
107L_exactly_32:
108	movl	%ebx,%edx
109	movl	%eax,%ebx
110	xorl	%eax,%eax
111	jmp	L_shift_done
112
113L_more_than_63:
114	cmpw	$65,%cx
115	jnc	L_more_than_64
116
117	/* Shift right by 64 bits */
118	movl	%eax,%edx
119	orl	%ebx,%ebx
120	jz	L_more_63_no_low
121
122	orl	$1,%edx
123	jmp	L_more_63_no_low
124
125L_more_than_64:
126	jne	L_more_than_65
127
128	/* Shift right by 65 bits */
129	/* Carry is clear if we get here */
130	movl	%eax,%edx
131	rcrl	%edx
132	jnc	L_shift_65_nc
133
134	orl	$1,%edx
135	jmp	L_more_63_no_low
136
137L_shift_65_nc:
138	orl	%ebx,%ebx
139	jz	L_more_63_no_low
140
141	orl	$1,%edx
142	jmp	L_more_63_no_low
143
144L_more_than_65:
145	movl	$1,%edx		/* The shifted nr always at least one '1' */
146
147L_more_63_no_low:
148	xorl	%ebx,%ebx
149	xorl	%eax,%eax
150
151L_shift_done:
152L_subtr:
153/*------------------------------+
154 |	Do the subtraction	|
155 +------------------------------*/
156	xorl	%ecx,%ecx
157	subl	%edx,%ecx
158	movl	%ecx,%edx
159	movl	SIGL(%esi),%ecx
160	sbbl	%ebx,%ecx
161	movl	%ecx,%ebx
162	movl	SIGH(%esi),%ecx
163	sbbl	%eax,%ecx
164	movl	%ecx,%eax
165
166#ifdef PARANOID
167	/* We can never get a borrow */
168	jc	L_bugged
169#endif /* PARANOID */
170
171/*--------------------------------------+
172 |	Normalize the result		|
173 +--------------------------------------*/
174	testl	$0x80000000,%eax
175	jnz	L_round		/* no shifting needed */
176
177	orl	%eax,%eax
178	jnz	L_shift_1	/* shift left 1 - 31 bits */
179
180	orl	%ebx,%ebx
181	jnz	L_shift_32	/* shift left 32 - 63 bits */
182
183/*
184 *	 A rare case, the only one which is non-zero if we got here
185 *         is:           1000000 .... 0000
186 *                      -0111111 .... 1111 1
187 *                       -------------------- 
188 *                       0000000 .... 0000 1 
189 */
190
191	cmpl	$0x80000000,%edx
192	jnz	L_must_be_zero
193
194	/* Shift left 64 bits */
195	subw	$64,EXP(%edi)
196	xchg	%edx,%eax
197	jmp	fpu_reg_round
198
199L_must_be_zero:
200#ifdef PARANOID
201	orl	%edx,%edx
202	jnz	L_bugged_3
203#endif /* PARANOID */ 
204
205	/* The result is zero */
206	movw	$0,EXP(%edi)		/* exponent */
207	movl	$0,SIGL(%edi)
208	movl	$0,SIGH(%edi)
209	movl	TAG_Zero,%eax
210	jmp	L_exit
211
212L_shift_32:
213	movl	%ebx,%eax
214	movl	%edx,%ebx
215	movl	$0,%edx
216	subw	$32,EXP(%edi)	/* Can get underflow here */
217
218/* We need to shift left by 1 - 31 bits */
219L_shift_1:
220	bsrl	%eax,%ecx	/* get the required shift in %ecx */
221	subl	$31,%ecx
222	negl	%ecx
223	shld	%cl,%ebx,%eax
224	shld	%cl,%edx,%ebx
225	shl	%cl,%edx
226	subw	%cx,EXP(%edi)	/* Can get underflow here */
227
228L_round:
229	jmp	fpu_reg_round	/* Round the result */
230
231
232#ifdef PARANOID
233L_bugged_1:
234	pushl	EX_INTERNAL|0x206
235	call	EXCEPTION
236	pop	%ebx
237	jmp	L_error_exit
238
239L_bugged_2:
240	pushl	EX_INTERNAL|0x209
241	call	EXCEPTION
242	pop	%ebx
243	jmp	L_error_exit
244
245L_bugged_3:
246	pushl	EX_INTERNAL|0x210
247	call	EXCEPTION
248	pop	%ebx
249	jmp	L_error_exit
250
251L_bugged_4:
252	pushl	EX_INTERNAL|0x211
253	call	EXCEPTION
254	pop	%ebx
255	jmp	L_error_exit
256
257L_bugged:
258	pushl	EX_INTERNAL|0x212
259	call	EXCEPTION
260	pop	%ebx
261	jmp	L_error_exit
262
263L_error_exit:
264	movl	$-1,%eax
265
266#endif /* PARANOID */
267
268L_exit:
269	popl	%ebx
270	popl	%edi
271	popl	%esi
272	leave
273	RET
274SYM_FUNC_END(FPU_u_sub)
v6.13.7
  1/* SPDX-License-Identifier: GPL-2.0 */
  2	.file	"reg_u_sub.S"
  3/*---------------------------------------------------------------------------+
  4 |  reg_u_sub.S                                                              |
  5 |                                                                           |
  6 | Core floating point subtraction 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 | Call from C as:                                                           |
 13 |    int FPU_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,             |
 14 |                                                int control_w)             |
 15 |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
 16 |    one was raised, or -1 on internal error.                               |
 17 |                                                                           |
 18 +---------------------------------------------------------------------------*/
 19
 20/*
 21 |    Kernel subtraction routine FPU_u_sub(reg *arg1, reg *arg2, reg *answ).
 22 |    Takes two valid reg f.p. numbers (TAG_Valid), which are
 23 |    treated as unsigned numbers,
 24 |    and returns their difference as a TAG_Valid or TAG_Zero f.p.
 25 |    number.
 26 |    The first number (arg1) must be the larger.
 27 |    The returned number is normalized.
 28 |    Basic checks are performed if PARANOID is defined.
 29 */
 30
 31#include "exception.h"
 32#include "fpu_emu.h"
 33#include "control_w.h"
 34
 35.text
 36SYM_FUNC_START(FPU_u_sub)
 37	pushl	%ebp
 38	movl	%esp,%ebp
 39	pushl	%esi
 40	pushl	%edi
 41	pushl	%ebx
 42
 43	movl	PARAM1,%esi	/* source 1 */
 44	movl	PARAM2,%edi	/* source 2 */
 45	
 46	movl	PARAM6,%ecx
 47	subl	PARAM7,%ecx	/* exp1 - exp2 */
 48
 49#ifdef PARANOID
 50	/* source 2 is always smaller than source 1 */
 51	js	L_bugged_1
 52
 53	testl	$0x80000000,SIGH(%edi)	/* The args are assumed to be be normalized */
 54	je	L_bugged_2
 55
 56	testl	$0x80000000,SIGH(%esi)
 57	je	L_bugged_2
 58#endif /* PARANOID */
 59
 60/*--------------------------------------+
 61 |	Form a register holding the     |
 62 |	smaller number                  |
 63 +--------------------------------------*/
 64	movl	SIGH(%edi),%eax	/* register ms word */
 65	movl	SIGL(%edi),%ebx	/* register ls word */
 66
 67	movl	PARAM3,%edi	/* destination */
 68	movl	PARAM6,%edx
 69	movw	%dx,EXP(%edi)	/* Copy exponent to destination */
 70
 71	xorl	%edx,%edx	/* register extension */
 72
 73/*--------------------------------------+
 74 |	Shift the temporary register	|
 75 |      right the required number of	|
 76 |	places.				|
 77 +--------------------------------------*/
 78
 79	cmpw	$32,%cx		/* shrd only works for 0..31 bits */
 80	jnc	L_more_than_31
 81
 82/* less than 32 bits */
 83	shrd	%cl,%ebx,%edx
 84	shrd	%cl,%eax,%ebx
 85	shr	%cl,%eax
 86	jmp	L_shift_done
 87
 88L_more_than_31:
 89	cmpw	$64,%cx
 90	jnc	L_more_than_63
 91
 92	subb	$32,%cl
 93	jz	L_exactly_32
 94
 95	shrd	%cl,%eax,%edx
 96	shr	%cl,%eax
 97	orl	%ebx,%ebx
 98	jz	L_more_31_no_low	/* none of the lowest bits is set */
 99
100	orl	$1,%edx			/* record the fact in the extension */
101
102L_more_31_no_low:
103	movl	%eax,%ebx
104	xorl	%eax,%eax
105	jmp	L_shift_done
106
107L_exactly_32:
108	movl	%ebx,%edx
109	movl	%eax,%ebx
110	xorl	%eax,%eax
111	jmp	L_shift_done
112
113L_more_than_63:
114	cmpw	$65,%cx
115	jnc	L_more_than_64
116
117	/* Shift right by 64 bits */
118	movl	%eax,%edx
119	orl	%ebx,%ebx
120	jz	L_more_63_no_low
121
122	orl	$1,%edx
123	jmp	L_more_63_no_low
124
125L_more_than_64:
126	jne	L_more_than_65
127
128	/* Shift right by 65 bits */
129	/* Carry is clear if we get here */
130	movl	%eax,%edx
131	rcrl	%edx
132	jnc	L_shift_65_nc
133
134	orl	$1,%edx
135	jmp	L_more_63_no_low
136
137L_shift_65_nc:
138	orl	%ebx,%ebx
139	jz	L_more_63_no_low
140
141	orl	$1,%edx
142	jmp	L_more_63_no_low
143
144L_more_than_65:
145	movl	$1,%edx		/* The shifted nr always at least one '1' */
146
147L_more_63_no_low:
148	xorl	%ebx,%ebx
149	xorl	%eax,%eax
150
151L_shift_done:
152L_subtr:
153/*------------------------------+
154 |	Do the subtraction	|
155 +------------------------------*/
156	xorl	%ecx,%ecx
157	subl	%edx,%ecx
158	movl	%ecx,%edx
159	movl	SIGL(%esi),%ecx
160	sbbl	%ebx,%ecx
161	movl	%ecx,%ebx
162	movl	SIGH(%esi),%ecx
163	sbbl	%eax,%ecx
164	movl	%ecx,%eax
165
166#ifdef PARANOID
167	/* We can never get a borrow */
168	jc	L_bugged
169#endif /* PARANOID */
170
171/*--------------------------------------+
172 |	Normalize the result		|
173 +--------------------------------------*/
174	testl	$0x80000000,%eax
175	jnz	L_round		/* no shifting needed */
176
177	orl	%eax,%eax
178	jnz	L_shift_1	/* shift left 1 - 31 bits */
179
180	orl	%ebx,%ebx
181	jnz	L_shift_32	/* shift left 32 - 63 bits */
182
183/*
184 *	 A rare case, the only one which is non-zero if we got here
185 *         is:           1000000 .... 0000
186 *                      -0111111 .... 1111 1
187 *                       -------------------- 
188 *                       0000000 .... 0000 1 
189 */
190
191	cmpl	$0x80000000,%edx
192	jnz	L_must_be_zero
193
194	/* Shift left 64 bits */
195	subw	$64,EXP(%edi)
196	xchg	%edx,%eax
197	jmp	fpu_reg_round
198
199L_must_be_zero:
200#ifdef PARANOID
201	orl	%edx,%edx
202	jnz	L_bugged_3
203#endif /* PARANOID */ 
204
205	/* The result is zero */
206	movw	$0,EXP(%edi)		/* exponent */
207	movl	$0,SIGL(%edi)
208	movl	$0,SIGH(%edi)
209	movl	TAG_Zero,%eax
210	jmp	L_exit
211
212L_shift_32:
213	movl	%ebx,%eax
214	movl	%edx,%ebx
215	movl	$0,%edx
216	subw	$32,EXP(%edi)	/* Can get underflow here */
217
218/* We need to shift left by 1 - 31 bits */
219L_shift_1:
220	bsrl	%eax,%ecx	/* get the required shift in %ecx */
221	subl	$31,%ecx
222	negl	%ecx
223	shld	%cl,%ebx,%eax
224	shld	%cl,%edx,%ebx
225	shl	%cl,%edx
226	subw	%cx,EXP(%edi)	/* Can get underflow here */
227
228L_round:
229	jmp	fpu_reg_round	/* Round the result */
230
231
232#ifdef PARANOID
233L_bugged_1:
234	pushl	EX_INTERNAL|0x206
235	call	EXCEPTION
236	pop	%ebx
237	jmp	L_error_exit
238
239L_bugged_2:
240	pushl	EX_INTERNAL|0x209
241	call	EXCEPTION
242	pop	%ebx
243	jmp	L_error_exit
244
245L_bugged_3:
246	pushl	EX_INTERNAL|0x210
247	call	EXCEPTION
248	pop	%ebx
249	jmp	L_error_exit
250
251L_bugged_4:
252	pushl	EX_INTERNAL|0x211
253	call	EXCEPTION
254	pop	%ebx
255	jmp	L_error_exit
256
257L_bugged:
258	pushl	EX_INTERNAL|0x212
259	call	EXCEPTION
260	pop	%ebx
261	jmp	L_error_exit
262
263L_error_exit:
264	movl	$-1,%eax
265
266#endif /* PARANOID */
267
268L_exit:
269	popl	%ebx
270	popl	%edi
271	popl	%esi
272	leave
273	RET
274SYM_FUNC_END(FPU_u_sub)