xref: /reactos/win32ss/gdi/eng/i386/floatobj.S (revision 12dfa8ce)
1c2c66affSColin Finck/*
2c2c66affSColin Finck * COPYRIGHT:         LGPL, see LGPL.txt in the top level directory
3c2c66affSColin Finck * PROJECT:           ReactOS Win32 subsystem
4c2c66affSColin Finck * PURPOSE:           FLOATOBJ floating point emulation functions for x86
5c2c66affSColin Finck * FILE:              win32ss/gdi/eng/i386/floatobj.S
6c2c66affSColin Finck * PROGRAMMER:        Timo Kreuzer
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck#include <asm.inc>
10c2c66affSColin Finck
11c2c66affSColin Finck.code
12c2c66affSColin Finck/*******************************************************************************
13c2c66affSColin Finck * IEEE 754-1985 single precision floating point
14c2c66affSColin Finck *
15c2c66affSColin Finck *    | 31 | 30...23  | 22...0   |
16c2c66affSColin Finck *    |sign| exponent | fraction |
17c2c66affSColin Finck *
18c2c66affSColin Finck *  mantissa = 1 + (fraction / 2^23)
19c2c66affSColin Finck *  f = (-1)^sign * mantissa * 2 ^ (exponent - bias)
20c2c66affSColin Finck *  bias = 127
21c2c66affSColin Finck *
22c2c66affSColin Finck *******************************************************************************
23c2c66affSColin Finck * win32k x86 floating point emulation
24c2c66affSColin Finck *
25c2c66affSColin Finck * struct _EFLOAT
26c2c66affSColin Finck = {
27c2c66affSColin Finck *    LONG lMant;
28c2c66affSColin Finck *    LONG lExp;
29c2c66affSColin Finck * };
30c2c66affSColin Finck *
31c2c66affSColin Finck * f = (lMant / 0x40000000) * 2 ^ (lExp - 2)
32c2c66affSColin Finck *   = lMant * 2 ^ (lExp - 32)
33c2c66affSColin Finck *
34c2c66affSColin Finck *******************************************************************************
35c2c66affSColin Finck * Optimization notes:
36c2c66affSColin Finck *
37c2c66affSColin Finck * - shld is slow (4 cycles) and not pairable, mov + shl is faster
38c2c66affSColin Finck * - esp is used, because it's available earlier
39c2c66affSColin Finck * - bsr is very slow on old cpus (up to 72 cycles on a p1) while being much
40c2c66affSColin Finck *   faster on modern cpus (2-11 cycles). Workarounds using branch trees or
41c2c66affSColin Finck *   table lookups are of no use nowadays.
42c2c66affSColin Finck *******************************************************************************
43c2c66affSColin Finck * Compatibility notes:
44c2c66affSColin Finck * - There are issues with very large size values near integer overflow.
45c2c66affSColin Finck *   Floating point values are behaving different there. This behavior isn't
46c2c66affSColin Finck *   simulated yet. Difference is < 10^-5 %
47c2c66affSColin Finck * - The result of a multiplication can differ from Windows result in the
48c2c66affSColin Finck *   least significant bit, that is a difference of 1 / 2^30 or ~10^-9
49c2c66affSColin Finck *******************************************************************************
50c2c66affSColin Finck * Implementation status:
51c2c66affSColin Finck *
52c2c66affSColin Finck * FLOATOBJ_SetFloat - implemented, tested
53c2c66affSColin Finck * FLOATOBJ_SetLong - implemented, tested
54c2c66affSColin Finck * FLOATOBJ_GetFloat - implemented, tested
55*12dfa8ceSJérôme Gardou * FLOATOBJ_GetLong - implemented in C
56c2c66affSColin Finck * FLOATOBJ_Equal - implemented, tested
57c2c66affSColin Finck * FLOATOBJ_EqualLong - implemented
58c2c66affSColin Finck * FLOATOBJ_GreaterThan - implemented
59c2c66affSColin Finck * FLOATOBJ_GreaterThanLong - wrapper
60c2c66affSColin Finck * FLOATOBJ_LessThan - implemented
61c2c66affSColin Finck * FLOATOBJ_LessThanLong - wrapper
62c2c66affSColin Finck * FLOATOBJ_Neg - implemented
63c2c66affSColin Finck * FLOATOBJ_Mul - implemented, tested, optimized
64c2c66affSColin Finck * FLOATOBJ_MulFloat - wrapper
65c2c66affSColin Finck * FLOATOBJ_MulLong - wrapper, could really need optimization
66c2c66affSColin Finck * FLOATOBJ_Div - implemented
67c2c66affSColin Finck * FLOATOBJ_DivFloat - wrapper
68c2c66affSColin Finck * FLOATOBJ_DivLong - wrapper
69c2c66affSColin Finck * FLOATOBJ_Add - implemented, tested
70c2c66affSColin Finck * FLOATOBJ_AddFloat - wrapper
71c2c66affSColin Finck * FLOATOBJ_AddLong - wrapper
72c2c66affSColin Finck * FLOATOBJ_Sub - implemented, tested
73c2c66affSColin Finck * FLOATOBJ_SubFloat - wrapper
74c2c66affSColin Finck * FLOATOBJ_SubLong - wrapper
75c2c66affSColin Finck */
76c2c66affSColin Finck
77c2c66affSColin Finck#define lMant 0
78c2c66affSColin Finck#define lExp 4
79c2c66affSColin Finck
80c2c66affSColin Finck#define PARAM1 8
81c2c66affSColin Finck#define PARAM2 12
82c2c66affSColin Finck
83c2c66affSColin Finck/** Globals **/
84c2c66affSColin Finck/* extern const FLOATOBJ gef0; */
85c2c66affSColin FinckPUBLIC _gef0
86c2c66affSColin Finck_gef0:
87c2c66affSColin Finck    .long 0, 0
88c2c66affSColin Finck
89c2c66affSColin Finck/* extern const FLOATOBJ gef1; */
90c2c66affSColin FinckPUBLIC _gef1
91c2c66affSColin Finck_gef1:
92c2c66affSColin Finck    .long HEX(40000000), HEX(00000002)
93c2c66affSColin Finck
94f9c06868SJérôme Gardou/* extern const FLOATOBJ gef2; */
95f9c06868SJérôme GardouPUBLIC _gef2
96f9c06868SJérôme Gardou_gef2:
97f9c06868SJérôme Gardou    .long HEX(40000000), HEX(00000003)
98f9c06868SJérôme Gardou
99c2c66affSColin Finck/* extern const FLOATOBJ gef16; */
100c2c66affSColin FinckPUBLIC _gef16
101c2c66affSColin Finck_gef16:
102c2c66affSColin Finck    .long HEX(40000000), HEX(00000006)
103c2c66affSColin Finck
104c2c66affSColin Finck/******************************************************************************
105c2c66affSColin Finck * VOID
106c2c66affSColin Finck * APIENTRY
107c2c66affSColin Finck * FLOATOBJ_SetFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
108c2c66affSColin Finck */
109c2c66affSColin Finck_FLOATOBJ_SetFloat@8:
110c2c66affSColin FinckPUBLIC _FLOATOBJ_SetFloat@8
111c2c66affSColin Finck	push ebp
112c2c66affSColin Finck	mov ebp, esp
113c2c66affSColin Finck
114c2c66affSColin Finck	mov ecx, [esp + PARAM2]		/* Load the float into ecx */
115c2c66affSColin Finck	mov eax, ecx				/* Copy float to eax for later */
116c2c66affSColin Finck
117c2c66affSColin Finck	test ecx, HEX(7f800000)		/* Check for zero exponent - 0 or denormal */
118c2c66affSColin Finck	jz SetFloat0				/* If it's all zero, ... */
119c2c66affSColin Finck
120c2c66affSColin Finck	shl ecx, 7					/* Put the bits for the mantissa in place */
121c2c66affSColin Finck
122c2c66affSColin Finck	cdq							/* Fill edx with the sign from the FLOATL in eax */
123c2c66affSColin Finck	and ecx, HEX(7fffffff)			/* Mask out invalid field in the mantissa */
124c2c66affSColin Finck
125c2c66affSColin Finck	shr eax, 23					/* Shift the exponent in eax in place */
126c2c66affSColin Finck	or ecx, HEX(40000000)		/* Set bit for 1 in the mantissa */
127c2c66affSColin Finck	and eax, HEX(0ff)			/* Mask out invalid fields in the exponent in eax */
128c2c66affSColin Finck
129c2c66affSColin Finck	xor ecx, edx				/* Make use of the sign bit expanded to full edx */
130c2c66affSColin Finck
131c2c66affSColin Finck	sub eax, 125				/* Adjust exonent bias */
132c2c66affSColin Finck
133c2c66affSColin Finck	sub ecx, edx				/* Substract -1 or add 1 if sign was set */
134c2c66affSColin Finck
135c2c66affSColin Finck	mov edx, [esp + PARAM1]		/* Load pf into edx */
136c2c66affSColin Finck	mov [edx + lMant], ecx		/* Save back mantissa */
137c2c66affSColin Finck	mov [edx + lExp], eax		/* Save back exponent */
138c2c66affSColin Finck
139c2c66affSColin Finck	pop ebp						/* Return */
140c2c66affSColin Finck	ret 8
141c2c66affSColin Finck
142c2c66affSColin FinckSetFloat0:
143c2c66affSColin Finck	mov edx, [esp + PARAM1]		/* Load pf into edx */
144c2c66affSColin Finck
145c2c66affSColin Finck	mov dword ptr [edx + lMant], 0	/* Set mantissa and exponent to 0 */
146c2c66affSColin Finck	mov dword ptr [edx + lExp], 0
147c2c66affSColin Finck
148c2c66affSColin Finck	pop ebp						/* Return */
149c2c66affSColin Finck	ret 8
150c2c66affSColin Finck
151c2c66affSColin Finck
152c2c66affSColin Finck/*******************************************************************************
153c2c66affSColin Finck * LONG
154c2c66affSColin Finck * APIENTRY
155c2c66affSColin Finck * FLOATOBJ_GetFloat(IN PFLOATOBJ pf);
156c2c66affSColin Finck *
157c2c66affSColin Finck */
158c2c66affSColin Finck_FLOATOBJ_GetFloat@4:
159c2c66affSColin FinckPUBLIC _FLOATOBJ_GetFloat@4
160c2c66affSColin Finck	push ebp
161c2c66affSColin Finck	mov ebp, esp
162c2c66affSColin Finck
163c2c66affSColin Finck	mov edx, [esp + PARAM1]		/* Load pf into edx */
164c2c66affSColin Finck	mov eax, [edx + lMant]		/* Load mantissa into eax */
165c2c66affSColin Finck	mov ecx, [edx + lExp]		/* Load exponent into ecx */
166c2c66affSColin Finck
167c2c66affSColin Finck	cdq							/* Calculate abs(mantissa) */
168c2c66affSColin Finck	xor eax, edx
169c2c66affSColin Finck
170c2c66affSColin Finck	add ecx, 125
171c2c66affSColin Finck
172c2c66affSColin Finck	sub eax, edx
173c2c66affSColin Finck	jz GetFloatRet
174c2c66affSColin Finck
175c2c66affSColin Finck	and ecx, HEX(0ff)			/* Mask out invalid fields in the exponent */
176c2c66affSColin Finck	and eax, HEX(3fffffff)		/* Mask out invalid fields in mantissa */
177c2c66affSColin Finck
178c2c66affSColin Finck	shl ecx, 23					/* Shift exponent in place */
179c2c66affSColin Finck	shr eax, 7					/* Shift mantissa in place */
180c2c66affSColin Finck
181c2c66affSColin Finck	and edx, HEX(80000000)			/* Reduce edx to sign bit only */
182c2c66affSColin Finck
183c2c66affSColin Finck	or eax, ecx					/* Set exponent in result */
184c2c66affSColin Finck	or eax, edx					/* Set sign bit in result */
185c2c66affSColin Finck
186c2c66affSColin FinckGetFloatRet:
187c2c66affSColin Finck	/* Return */
188c2c66affSColin Finck	pop ebp
189c2c66affSColin Finck	ret 4
190c2c66affSColin Finck
191c2c66affSColin Finck
192c2c66affSColin Finck
193c2c66affSColin Finck/******************************************************************************
194c2c66affSColin Finck * VOID
195c2c66affSColin Finck * APIENTRY
196c2c66affSColin Finck * FLOATOBJ_SetLong(OUT PFLOATOBJ pf, IN LONG l);
197c2c66affSColin Finck *
198c2c66affSColin Finck * Instead of using abs(l), which is 3 + 2 instructions, use a branch.
199c2c66affSColin Finck */
200c2c66affSColin Finck_FLOATOBJ_SetLong@8:
201c2c66affSColin FinckPUBLIC _FLOATOBJ_SetLong@8
202c2c66affSColin Finck	push ebp
203c2c66affSColin Finck	mov ebp, esp
204c2c66affSColin Finck
205c2c66affSColin Finck	mov eax, [esp + PARAM2]		/* Load l into eax */
206c2c66affSColin Finck	mov edx, [esp + PARAM1]		/* Load pf into edx */
207c2c66affSColin Finck
208c2c66affSColin Finck	test eax, eax				/* different handling for <0, =0 and >0 */
209c2c66affSColin Finck	js SetLongNeg
210c2c66affSColin Finck	jz SetLong0
211c2c66affSColin Finck
212c2c66affSColin Finck	bsr ecx, eax				/* Get number of most significant bit aka log2(l) */
213c2c66affSColin Finck	mov [edx + lExp], ecx		/* Safe log2(l) into exponent */
214c2c66affSColin Finck
215c2c66affSColin Finck	neg ecx						/* Calculate necessary shift */
216c2c66affSColin Finck	add ecx, 30
217c2c66affSColin Finck
218c2c66affSColin Finck	add dword ptr [edx + lExp], 2	/* Adjust exponent */
219c2c66affSColin Finck
220c2c66affSColin Finck	shl eax, cl					/* Shift mantissa in place */
221c2c66affSColin Finck	mov [edx + lMant], eax		/* Save mantissa */
222c2c66affSColin Finck
223c2c66affSColin Finck	pop ebp						/* Return */
224c2c66affSColin Finck	ret 8
225c2c66affSColin Finck
226c2c66affSColin FinckSetLongNeg:
227c2c66affSColin Finck	neg eax						/* Get absolute value of l */
228c2c66affSColin Finck	bsr ecx, eax				/* Get number of most significant bit aka log2(l) */
229c2c66affSColin Finck	neg eax						/* Back to negative */
230c2c66affSColin Finck
231c2c66affSColin Finck	mov [edx + lExp], ecx		/* Safe log2(-l) into exponent */
232c2c66affSColin Finck
233c2c66affSColin Finck	neg ecx						/* Calculate necessary shift */
234c2c66affSColin Finck	add ecx, 30
235c2c66affSColin Finck
236c2c66affSColin Finck	add dword ptr [edx + lExp], 2	/* Adjust exponent */
237c2c66affSColin Finck
238c2c66affSColin Finck	shl eax, cl					/* Shift mantissa in place */
239c2c66affSColin Finck	mov [edx + lMant], eax		/* Save mantissa */
240c2c66affSColin Finck
241c2c66affSColin Finck	pop ebp						/* Return */
242c2c66affSColin Finck	ret 8
243c2c66affSColin Finck
244c2c66affSColin FinckSetLong0:
245c2c66affSColin Finck	mov dword ptr [edx + lMant], 0	/* Set mantissa and exponent to 0 */
246c2c66affSColin Finck	mov dword ptr [edx + lExp], 0
247c2c66affSColin Finck
248c2c66affSColin Finck	pop ebp						/* Return */
249c2c66affSColin Finck	ret 8
250c2c66affSColin Finck
251c2c66affSColin Finck
252c2c66affSColin Finck/******************************************************************************
253c2c66affSColin Finck * BOOL
254c2c66affSColin Finck * APIENTRY
255c2c66affSColin Finck * FLOATOBJ_Equal(IN PFLOATOBJ pf1, IN PFLOATOBJ pf2);
256c2c66affSColin Finck */
257c2c66affSColin Finck_FLOATOBJ_Equal@8:
258c2c66affSColin FinckPUBLIC _FLOATOBJ_Equal@8
259c2c66affSColin Finck	push ebp
260c2c66affSColin Finck	mov ebp, esp
261c2c66affSColin Finck
262c2c66affSColin Finck	mov ecx, [esp + PARAM1]		/* Load pf1 into ecx */
263c2c66affSColin Finck	mov eax, [esp + PARAM2]		/* Load pf2 into ecx */
264c2c66affSColin Finck
265c2c66affSColin Finck	mov edx, [ecx + lExp]		/* Get float1 in ecx, edx */
266c2c66affSColin Finck	mov ecx, [ecx + lMant]
267c2c66affSColin Finck
268c2c66affSColin Finck	sub edx, [eax + lExp]		/* Calculate diference to float2 */
269c2c66affSColin Finck	sub ecx, [eax + lMant]
270c2c66affSColin Finck
271c2c66affSColin Finck	or edx, ecx					/* Combine */
272c2c66affSColin Finck
273c2c66affSColin Finck	mov eax, 0					/* Set eax if combination is 0 */
274c2c66affSColin Finck	setz al
275c2c66affSColin Finck
276c2c66affSColin Finck	pop ebp						/* Return */
277c2c66affSColin Finck	ret 8
278c2c66affSColin Finck
279c2c66affSColin Finck
280c2c66affSColin Finck/******************************************************************************
281c2c66affSColin Finck * BOOL
282c2c66affSColin Finck * APIENTRY
283c2c66affSColin Finck * FLOATOBJ_EqualLong(IN PFLOATOBJ pf, IN LONG l);
284c2c66affSColin Finck */
285c2c66affSColin Finck_FLOATOBJ_EqualLong@8:
286c2c66affSColin FinckPUBLIC _FLOATOBJ_EqualLong@8
287c2c66affSColin Finck	push ebp
288c2c66affSColin Finck	mov ebp, esp
289c2c66affSColin Finck
290c2c66affSColin Finck	mov eax, [esp + PARAM1]		/* Load pf into eax */
291c2c66affSColin Finck	mov ecx, 32					/* Load (32 - lExp) into ecx */
292c2c66affSColin Finck	sub ecx, [eax + lExp]
293c2c66affSColin Finck	mov edx, [eax + lMant]		/* Load mantissa into edx */
294c2c66affSColin Finck	sar edx, cl					/* Signed shift mantissa according to exponent */
295c2c66affSColin Finck	shl edx, cl					/* Shift the mantissa back */
296c2c66affSColin Finck	cmp edx, [eax + lMant]		/* Check whether bits were killed by shifting */
297c2c66affSColin Finck	jnz EqualLongFalse			/* We have truncated the mantissa, return 0 */
298c2c66affSColin Finck
299c2c66affSColin Finck	sar edx, cl					/* Shift the mantissa again */
300c2c66affSColin Finck	xor eax, eax				/* Set return value ... */
301c2c66affSColin Finck	cmp edx, [esp + PARAM2]		/* TRUE if shifted mantissa equals the LONG */
302c2c66affSColin Finck	setz al
303c2c66affSColin Finck
304c2c66affSColin Finck	pop ebp						/* Return */
305c2c66affSColin Finck	ret 8
306c2c66affSColin Finck
307c2c66affSColin FinckEqualLongFalse:
308c2c66affSColin Finck	xor eax, eax				/* Return FALSE */
309c2c66affSColin Finck	pop ebp
310c2c66affSColin Finck	ret 8
311c2c66affSColin Finck
312c2c66affSColin Finck
313c2c66affSColin Finck/******************************************************************************
314c2c66affSColin Finck * BOOL
315c2c66affSColin Finck * APIENTRY
316c2c66affSColin Finck * FLOATOBJ_GreaterThan(IN PFLOATOBJ pf, IN PFLOATOBJ pf1);
317c2c66affSColin Finck *
318c2c66affSColin Finck */
319c2c66affSColin Finck_FLOATOBJ_GreaterThan@8:
320c2c66affSColin FinckPUBLIC _FLOATOBJ_GreaterThan@8
321c2c66affSColin Finck	push ebp
322c2c66affSColin Finck	mov ebp, esp
323c2c66affSColin Finck
324c2c66affSColin Finck	mov eax, [ebp + PARAM1]		/* Load pointer to efloat1 in eax */
325c2c66affSColin Finck	mov edx, [ebp + PARAM2]		/* Load pointer to efloat2 in edx */
326c2c66affSColin Finck
327c2c66affSColin Finck	mov ecx, [eax + lMant]		/* Load mantissa1 in ecx */
328c2c66affSColin Finck	mov edx, [edx + lMant]		/* Load mantissa2 in edx */
329c2c66affSColin Finck
330c2c66affSColin Finck	sar ecx, 31					/* Calculate sign(lMant1) in ecx */
331c2c66affSColin Finck	sar edx, 31					/* Calculate sign(lMant2) in edx */
332c2c66affSColin Finck
333c2c66affSColin Finck	cmp ecx, edx				/* Branch if both have the same sign */
334c2c66affSColin Finck	je GreaterThan_2
335c2c66affSColin Finck
336c2c66affSColin Finck	/* Mantissae have different sign */
337c2c66affSColin Finck	mov eax, 0					/* Return (sign(lMant1) > sign(lMant2)) */
338c2c66affSColin Finck	setg al
339c2c66affSColin Finck	pop ebp
340c2c66affSColin Finck	ret 8
341c2c66affSColin Finck
342c2c66affSColin FinckGreaterThan_2:
343c2c66affSColin Finck	/* Mantissae have the same sign */
344c2c66affSColin Finck
345c2c66affSColin Finck	mov edx, [ebp + PARAM2]		/* Reload pointer to float2 in edx */
346c2c66affSColin Finck	test ecx, ecx				/* Branch if sign is negative */
347c2c66affSColin Finck	js GreaterThan_neg
348c2c66affSColin Finck
349c2c66affSColin Finck	/* Both mantissae are positive or 0 */
350c2c66affSColin Finck
351c2c66affSColin Finck	or ecx, [edx + lMant]		/* Branch if one mantissa is 0 */
352c2c66affSColin Finck	jz GreaterThan_pos2
353c2c66affSColin Finck
354c2c66affSColin Finck	/* Both mantissae are positive */
355c2c66affSColin Finck
356c2c66affSColin Finck	mov ecx, [eax + lExp]		/* Branch if exponents are equal */
357c2c66affSColin Finck	cmp ecx, [edx + lExp]
358c2c66affSColin Finck	je GreaterThan_pos2
359c2c66affSColin Finck
360c2c66affSColin Finck	mov eax, 0					/* Return (lExp1 > lExp2) */
361c2c66affSColin Finck	setg al
362c2c66affSColin Finck	pop ebp
363c2c66affSColin Finck	ret 8
364c2c66affSColin Finck
365c2c66affSColin FinckGreaterThan_pos2:
366c2c66affSColin Finck	/* Exponents are equal or one mantissa is 0 */
367c2c66affSColin Finck
368c2c66affSColin Finck	mov ecx, [eax + lMant]		/* Return (lMant1 > lMant2) */
369c2c66affSColin Finck	cmp ecx, [edx + lMant]
370c2c66affSColin Finck	mov eax, 0
371c2c66affSColin Finck	setg al
372c2c66affSColin Finck	pop ebp
373c2c66affSColin Finck	ret 8
374c2c66affSColin Finck
375c2c66affSColin FinckGreaterThan_neg:
376c2c66affSColin Finck	/* Both mantissae are negative */
377c2c66affSColin Finck
378c2c66affSColin Finck	mov ecx, [eax + lExp]		/* Branch if exponents are equal */
379c2c66affSColin Finck	cmp ecx, [edx + lExp]
380c2c66affSColin Finck	je GreaterThan_neg2
381c2c66affSColin Finck
382c2c66affSColin Finck	/* Both mantissae negative, exponents are different */
383c2c66affSColin Finck
384c2c66affSColin Finck	mov eax, 0					/* Return (lExp1 < lExp2) */
385c2c66affSColin Finck	setl al
386c2c66affSColin Finck	pop ebp
387c2c66affSColin Finck	ret 8
388c2c66affSColin Finck
389c2c66affSColin FinckGreaterThan_neg2:
390c2c66affSColin Finck	/* Both mantissae negative, exponents are equal */
391c2c66affSColin Finck
392c2c66affSColin Finck	mov ecx, [eax + lMant]		/* Return (lMant1 < lMant2) */
393c2c66affSColin Finck	cmp ecx, [edx + lMant]
394c2c66affSColin Finck	mov eax, 0
395c2c66affSColin Finck	setl al
396c2c66affSColin Finck	pop ebp
397c2c66affSColin Finck	ret 8
398c2c66affSColin Finck
399c2c66affSColin Finck
400c2c66affSColin Finck
401c2c66affSColin Finck/******************************************************************************
402c2c66affSColin Finck * VOID
403c2c66affSColin Finck * APIENTRY
404c2c66affSColin Finck * FLOATOBJ_GreaterThanLong(IN OUT PFLOATOBJ pf, IN LONG l);
405c2c66affSColin Finck *
406c2c66affSColin Finck * Currently implemented as a wrapper around FLOATOBJ_SetLong and
407c2c66affSColin Finck * LOATOBJ_GreaterThan
408c2c66affSColin Finck */
409c2c66affSColin Finck_FLOATOBJ_GreaterThanLong@8:
410c2c66affSColin FinckPUBLIC _FLOATOBJ_GreaterThanLong@8
411c2c66affSColin Finck	push ebp
412c2c66affSColin Finck	mov ebp, esp
413c2c66affSColin Finck
414c2c66affSColin Finck	sub esp, 8					/* Make room for a FLOATOBJ on the stack */
415c2c66affSColin Finck	mov eax, [ebp + PARAM2]		/* Load LONG into eax */
416c2c66affSColin Finck
417c2c66affSColin Finck	lea ecx, [ebp -8]			/* Load pointer to local FLOATOBJ into ecx */
418c2c66affSColin Finck
419c2c66affSColin Finck	push eax					/* Push LONG on the stack */
420c2c66affSColin Finck	push ecx					/* Push pointer to local FLOATOBJ on the stack */
421c2c66affSColin Finck	call _FLOATOBJ_SetLong@8	/* Set the local FLOATOBJ */
422c2c66affSColin Finck
423c2c66affSColin Finck	lea ecx, [ebp -8]			/* Push pointer to the local FLOATOBJ on the stack */
424c2c66affSColin Finck	push ecx
425c2c66affSColin Finck	push [ebp + PARAM1]			/* Push the FLOATOBJ param on the stack */
426c2c66affSColin Finck	call _FLOATOBJ_GreaterThan@8	/* Compare */
427c2c66affSColin Finck
428c2c66affSColin Finck	mov esp, ebp				/* Cleanup and return */
429c2c66affSColin Finck	pop ebp
430c2c66affSColin Finck	ret 8
431c2c66affSColin Finck
432c2c66affSColin Finck
433c2c66affSColin Finck/******************************************************************************
434c2c66affSColin Finck * BOOL
435c2c66affSColin Finck * APIENTRY
436c2c66affSColin Finck * FLOATOBJ_LessThan(IN PFLOATOBJ pf, IN PFLOATOBJ pf1);
437c2c66affSColin Finck *
438c2c66affSColin Finck */
439c2c66affSColin Finck_FLOATOBJ_LessThan@8:
440c2c66affSColin FinckPUBLIC _FLOATOBJ_LessThan@8
441c2c66affSColin Finck	push ebp
442c2c66affSColin Finck	mov ebp, esp
443c2c66affSColin Finck
444c2c66affSColin Finck	mov eax, [ebp + PARAM1]		/* Load pointer to floats in eax and edx */
445c2c66affSColin Finck	mov edx, [ebp + PARAM2]
446c2c66affSColin Finck
447c2c66affSColin Finck	mov ecx, [eax + lMant]		/* Load mantissae in ecx and edx */
448c2c66affSColin Finck	mov edx, [edx + lMant]
449c2c66affSColin Finck
450c2c66affSColin Finck	sar ecx, 31					/* Calculate sign(lMant1) and sign(lMant2) */
451c2c66affSColin Finck	sar edx, 31
452c2c66affSColin Finck
453c2c66affSColin Finck	cmp ecx, edx				/* Branch if both have the same sign */
454c2c66affSColin Finck	je LessThan_2
455c2c66affSColin Finck
456c2c66affSColin Finck	/* Mantissae have different sign */
457c2c66affSColin Finck
458c2c66affSColin Finck	mov eax, 0					/* Return (sign(lMant1) < sign(lMant2)) */
459c2c66affSColin Finck	setl al
460c2c66affSColin Finck	pop ebp
461c2c66affSColin Finck	ret 8
462c2c66affSColin Finck
463c2c66affSColin FinckLessThan_2:
464c2c66affSColin Finck	/* Mantissae have the same sign */
465c2c66affSColin Finck
466c2c66affSColin Finck
467c2c66affSColin Finck	mov edx, [ebp + PARAM2]		/* Reload pointer to float2 in edx */
468c2c66affSColin Finck
469c2c66affSColin Finck	test ecx, ecx				/* Branch if sign is negative */
470c2c66affSColin Finck	js LessThan_neg
471c2c66affSColin Finck
472c2c66affSColin Finck	/* Both mantissae are positive or 0 */
473c2c66affSColin Finck
474c2c66affSColin Finck	or ecx, [edx + lMant]		/* Branch if one mantissa is 0 */
475c2c66affSColin Finck	jz LessThan_pos2
476c2c66affSColin Finck
477c2c66affSColin Finck	/* Both mantissae are positive */
478c2c66affSColin Finck
479c2c66affSColin Finck	mov ecx, [eax + lExp]		/* Branch if exponents are equal */
480c2c66affSColin Finck	cmp ecx, [edx + lExp]
481c2c66affSColin Finck	je LessThan_pos2
482c2c66affSColin Finck
483c2c66affSColin Finck	mov eax, 0					/* Return (lExp1 < lExp2) */
484c2c66affSColin Finck	setl al
485c2c66affSColin Finck	pop ebp
486c2c66affSColin Finck	ret 8
487c2c66affSColin Finck
488c2c66affSColin FinckLessThan_pos2:
489c2c66affSColin Finck	/* Exponents are equal or one mantissa is 0 */
490c2c66affSColin Finck
491c2c66affSColin Finck	mov ecx, [eax + lMant]		/* Return (lMant1 < lMant2) */
492c2c66affSColin Finck	cmp ecx, [edx + lMant]
493c2c66affSColin Finck	mov eax, 0
494c2c66affSColin Finck	setl al
495c2c66affSColin Finck	pop ebp
496c2c66affSColin Finck	ret 8
497c2c66affSColin Finck
498c2c66affSColin FinckLessThan_neg:
499c2c66affSColin Finck	/* Both mantissae are negative */
500c2c66affSColin Finck
501c2c66affSColin Finck	mov ecx, [eax + lExp]		/* Branch if exponents are equal */
502c2c66affSColin Finck	cmp ecx, [edx + lExp]
503c2c66affSColin Finck	je LessThan_neg2
504c2c66affSColin Finck
505c2c66affSColin Finck	/* Both mantissae negative, exponents are different */
506c2c66affSColin Finck
507c2c66affSColin Finck	mov eax, 0					/* Return (lExp1 > lExp2) */
508c2c66affSColin Finck	setg al
509c2c66affSColin Finck	pop ebp
510c2c66affSColin Finck	ret 8
511c2c66affSColin Finck
512c2c66affSColin FinckLessThan_neg2:
513c2c66affSColin Finck	/* Both mantissae negative, exponents are equal */
514c2c66affSColin Finck
515c2c66affSColin Finck	mov ecx, [eax + lMant]		/* Return (lMant1 > lMant2) */
516c2c66affSColin Finck	cmp ecx, [edx + lMant]
517c2c66affSColin Finck	mov eax, 0
518c2c66affSColin Finck	setg al
519c2c66affSColin Finck	pop ebp
520c2c66affSColin Finck	ret 8
521c2c66affSColin Finck
522c2c66affSColin Finck
523c2c66affSColin Finck/******************************************************************************
524c2c66affSColin Finck * VOID
525c2c66affSColin Finck * APIENTRY
526c2c66affSColin Finck * FLOATOBJ_LessThanLong(IN OUT PFLOATOBJ pf, IN LONG l);
527c2c66affSColin Finck *
528c2c66affSColin Finck * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_LessThan
529c2c66affSColin Finck */
530c2c66affSColin Finck_FLOATOBJ_LessThanLong@8:
531c2c66affSColin FinckPUBLIC _FLOATOBJ_LessThanLong@8
532c2c66affSColin Finck	push ebp
533c2c66affSColin Finck	mov ebp, esp
534c2c66affSColin Finck
535c2c66affSColin Finck	sub esp, 8					/* Make room for a FLOATOBJ on the stack */
536c2c66affSColin Finck	mov eax, [ebp + PARAM2]		/* Load LONG into eax */
537c2c66affSColin Finck
538c2c66affSColin Finck	lea ecx, [ebp -8]			/* Load pointer to local FLOATOBJ into ecx */
539c2c66affSColin Finck	push eax					/* Push LONG on the stack */
540c2c66affSColin Finck	push ecx					/* Push pointer to local FLOATOBJ on the stack */
541c2c66affSColin Finck	call _FLOATOBJ_SetLong@8	/* Set the local FLOATOBJ */
542c2c66affSColin Finck
543c2c66affSColin Finck	lea ecx, [ebp -8]			/* Push pointer to the local FLOATOBJ on the stack */
544c2c66affSColin Finck	push ecx
545c2c66affSColin Finck	push [ebp + PARAM1]			/* Push the FLOATOBJ param on the stack */
546c2c66affSColin Finck	call _FLOATOBJ_LessThan@8	/* Compare */
547c2c66affSColin Finck
548c2c66affSColin Finck	mov esp, ebp				/* Cleanup and return */
549c2c66affSColin Finck	pop ebp
550c2c66affSColin Finck	ret 8
551c2c66affSColin Finck
552c2c66affSColin Finck
553c2c66affSColin Finck
554c2c66affSColin Finck/******************************************************************************
555c2c66affSColin Finck * VOID
556c2c66affSColin Finck * APIENTRY
557c2c66affSColin Finck * FLOATOBJ_Mul(IN OUT PFLOATOBJ pf1, IN PFLOATOBJ pf2);
558c2c66affSColin Finck *
559c2c66affSColin Finck *  (mant1 * 2^exp1) * (mant2 * 2^exp2) = (mant1 * mant2) * 2^(exp1 + exp2)
560c2c66affSColin Finck *  or mant = mant1 * mant2 and exp = exp1 + exp2
561c2c66affSColin Finck *  No special handling for 0, where mantissa is 0
562c2c66affSColin Finck */
563c2c66affSColin Finck_FLOATOBJ_Mul@8:
564c2c66affSColin FinckPUBLIC _FLOATOBJ_Mul@8
565c2c66affSColin Finck	push ebp
566c2c66affSColin Finck	mov ebp, esp
567c2c66affSColin Finck
568c2c66affSColin Finck	mov edx, [esp + PARAM1]		/* Load pf1 into edx */
569c2c66affSColin Finck	mov ecx, [esp + PARAM2]		/* Load pf2 into ecx */
570c2c66affSColin Finck	mov eax, [ecx + lMant]		/* Load mantissa2 into eax */
571c2c66affSColin Finck	mov ecx, [ecx + lExp]		/* Load exponent2 into ecx */
572c2c66affSColin Finck
573c2c66affSColin Finck	imul dword ptr [edx + lMant]	/* Multiply eax with mantissa 1 */
574c2c66affSColin Finck
575c2c66affSColin Finck	test edx, edx				/* Special handling for result < 0 */
576c2c66affSColin Finck	js MulNeg
577c2c66affSColin Finck
578c2c66affSColin Finck	shl edx, 2					/* Get new mantissa from bits 30 to 62 */
579c2c66affSColin Finck	shr eax, 30					/* of edx:eax into edx */
580c2c66affSColin Finck	or eax, edx
581c2c66affSColin Finck
582c2c66affSColin Finck	mov edx, ecx				/* Need ecx for the shift, safe exp2 to free edx */
583c2c66affSColin Finck	mov ecx, 0					/* Check for highest bit */
584c2c66affSColin Finck	sets cl
585c2c66affSColin Finck	shr eax, cl					/* Normalize mantissa in eax */
586c2c66affSColin Finck
587c2c66affSColin Finck	jz Mul0						/* All 0? */
588c2c66affSColin Finck
589c2c66affSColin Finck	lea edx, [edx + ecx -2]		/* Normalize exponent in edx */
590c2c66affSColin Finck
591c2c66affSColin Finck
592c2c66affSColin Finck	mov ecx, [esp + PARAM1]		/* Load pf1 into ecx */
593c2c66affSColin Finck	mov [ecx + lMant], eax		/* Save back mantissa */
594c2c66affSColin Finck	add [ecx + lExp], edx		/* Save back exponent */
595c2c66affSColin Finck
596c2c66affSColin Finck	pop ebp						/* Return */
597c2c66affSColin Finck	ret 8
598c2c66affSColin Finck
599c2c66affSColin FinckMulNeg:
600c2c66affSColin Finck
601c2c66affSColin Finck	shl edx, 2					/* Get new mantissa from bits 30 to 62 */
602c2c66affSColin Finck	shr eax, 30					/* of edx:eax into edx */
603c2c66affSColin Finck	or eax, edx
604c2c66affSColin Finck
605c2c66affSColin Finck	mov edx, ecx				/* Need ecx for the shift, safe exp2 to free edx */
606c2c66affSColin Finck
607c2c66affSColin Finck	mov ecx, 0					/* Check for highest bit */
608c2c66affSColin Finck	setns cl
609c2c66affSColin Finck	shr eax, cl					/* Normalize mantissa in eax */
610c2c66affSColin Finck
611c2c66affSColin Finck	jz Mul0						/* All 0? */
612c2c66affSColin Finck
613c2c66affSColin Finck
614c2c66affSColin Finck	lea edx, [edx + ecx -2]		/* Normalize exponent in edx */
615c2c66affSColin Finck	or eax, HEX(80000000)			/* Set sign bit */
616c2c66affSColin Finck
617c2c66affSColin Finck	mov ecx, [esp + PARAM1]		/* Load pf1 into ecx */
618c2c66affSColin Finck	mov [ecx + lMant], eax		/* Save back mantissa */
619c2c66affSColin Finck	add [ecx + lExp], edx		/* Save back exponent */
620c2c66affSColin Finck
621c2c66affSColin Finck	pop ebp						/* Return */
622c2c66affSColin Finck	ret 8
623c2c66affSColin Finck
624c2c66affSColin FinckMul0:
625c2c66affSColin Finck	mov ecx, [esp + PARAM1]		/* Load pf1 into ecx */
626c2c66affSColin Finck	mov [ecx + lMant], eax		/* Store 0 in mantissa */
627c2c66affSColin Finck	mov [ecx + lExp], eax		/* Store 0 in exponent */
628c2c66affSColin Finck
629c2c66affSColin Finck	pop ebp						/* Return */
630c2c66affSColin Finck	ret 8
631c2c66affSColin Finck
632c2c66affSColin Finck
633c2c66affSColin Finck/******************************************************************************
634c2c66affSColin Finck * VOID
635c2c66affSColin Finck * APIENTRY
636c2c66affSColin Finck * FLOATOBJ_MulFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
637c2c66affSColin Finck *
638c2c66affSColin Finck * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Mul
639c2c66affSColin Finck */
640c2c66affSColin Finck_FLOATOBJ_MulFloat@8:
641c2c66affSColin FinckPUBLIC _FLOATOBJ_MulFloat@8
642c2c66affSColin Finck	push ebp
643c2c66affSColin Finck	mov ebp, esp
644c2c66affSColin Finck
645c2c66affSColin Finck	sub esp, 8					/* Make room for a FLOATOBJ on the stack */
646c2c66affSColin Finck	mov eax, [ebp + PARAM2]		/* Load f into eax */
647c2c66affSColin Finck	lea ecx, [ebp -4]			/* Load pointer to local FLOATOBJ into ecx */
648c2c66affSColin Finck	push eax					/* Push f on the stack */
649c2c66affSColin Finck	push ecx					/* Push pointer to local FLOATOBJ on the stack */
650c2c66affSColin Finck	call _FLOATOBJ_SetFloat@8	/* Set the FLOATOBJ */
651c2c66affSColin Finck
652c2c66affSColin Finck	lea ecx, [ebp -4]			/* Push pointer to local FLOATOBJ on the stack */
653c2c66affSColin Finck	push ecx
654c2c66affSColin Finck	push [ebp + PARAM1]			/* Push the FLOATOBJ param on the stack */
655c2c66affSColin Finck	call _FLOATOBJ_Mul@8		/* Multiply */
656c2c66affSColin Finck
657c2c66affSColin Finck	mov esp, ebp				/* Cleanup and return */
658c2c66affSColin Finck	pop ebp
659c2c66affSColin Finck	ret 8
660c2c66affSColin Finck
661c2c66affSColin Finck
662c2c66affSColin Finck/******************************************************************************
663c2c66affSColin Finck * VOID
664c2c66affSColin Finck * APIENTRY
665c2c66affSColin Finck * FLOATOBJ_MulLong(IN OUT PFLOATOBJ pf, IN LONG l);
666c2c66affSColin Finck *
667c2c66affSColin Finck * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Mul
668c2c66affSColin Finck */
669c2c66affSColin Finck_FLOATOBJ_MulLong@8:
670c2c66affSColin FinckPUBLIC _FLOATOBJ_MulLong@8
671c2c66affSColin Finck	push ebp
672c2c66affSColin Finck	mov ebp, esp
673c2c66affSColin Finck
674c2c66affSColin Finck	sub esp, 8					/* Make room for a FLOATOBJ on the stack */
675c2c66affSColin Finck	mov eax, [ebp + PARAM2]		/* Load l into eax */
676c2c66affSColin Finck	lea ecx, [ebp -8]			/* Load pointer to local FLOATOBJ into ecx */
677c2c66affSColin Finck	push eax					/* Push l on the stack */
678c2c66affSColin Finck	push ecx					/* Push pointer to local FLOATOBJ on the stack */
679c2c66affSColin Finck	call _FLOATOBJ_SetLong@8	/* Set the local FLOATOBJ */
680c2c66affSColin Finck
681c2c66affSColin Finck	lea ecx, [ebp -8]			/* Push pointer to local FLOATOBJ on the stack */
682c2c66affSColin Finck	push ecx
683c2c66affSColin Finck	push [ebp + PARAM1]			/* Push the FLOATOBJ param on the stack */
684c2c66affSColin Finck	call _FLOATOBJ_Mul@8		/* Multiply */
685c2c66affSColin Finck
686c2c66affSColin Finck	mov esp, ebp				/* Cleanup and return */
687c2c66affSColin Finck	pop ebp
688c2c66affSColin Finck	ret 8
689c2c66affSColin Finck
690c2c66affSColin Finck
691c2c66affSColin Finck/*******************************************************************************
692c2c66affSColin Finck * VOID
693c2c66affSColin Finck * APIENTRY
694c2c66affSColin Finck * FLOATOBJ_Div(IN OUT PFLOATOBJ pf1, IN PFLOATOBJ pf2);
695c2c66affSColin Finck *
696c2c66affSColin Finck */
697c2c66affSColin Finck_FLOATOBJ_Div@8:
698c2c66affSColin FinckPUBLIC _FLOATOBJ_Div@8
699c2c66affSColin Finck	push ebp
700c2c66affSColin Finck	mov ebp, esp
701c2c66affSColin Finck	push ebx
702c2c66affSColin Finck
703c2c66affSColin Finck	mov eax, [ebp + PARAM2]		/* Load lMant2 into eax */
704c2c66affSColin Finck	mov eax, [eax + lMant]
705c2c66affSColin Finck
706c2c66affSColin Finck	cdq							/* Calculate abs(lMant2) */
707c2c66affSColin Finck	xor eax, edx
708c2c66affSColin Finck	sub eax, edx
709c2c66affSColin Finck	jz DivError					/* Divide by zero error! */
710c2c66affSColin Finck
711c2c66affSColin Finck	mov ebx, edx				/* Copy sign(lMant2) to ebx */
712c2c66affSColin Finck	mov ecx, eax				/* Copy abs(lMant2) to ecx */
713c2c66affSColin Finck
714c2c66affSColin Finck	mov eax, [ebp + PARAM1]		/* Load lMant1 into eax */
715c2c66affSColin Finck	mov eax, [eax + lMant]
716c2c66affSColin Finck
717c2c66affSColin Finck	cdq							/* Calculate abs(lMant1) */
718c2c66affSColin Finck	xor eax, edx
719c2c66affSColin Finck	sub eax, edx
720c2c66affSColin Finck
721c2c66affSColin Finck	jz Div0						/* Dividend is 0? */
722c2c66affSColin Finck
723c2c66affSColin Finck	xor ebx, edx				/* combine both signs in ebx */
724c2c66affSColin Finck
725c2c66affSColin Finck	mov edx, eax				/* Prepare edx:eax for integer divide */
726c2c66affSColin Finck	xor eax, eax
727c2c66affSColin Finck	shr edx, 1
728c2c66affSColin Finck	div ecx						/* Do an unsigned divide */
729c2c66affSColin Finck
730c2c66affSColin Finck	xor ecx, ecx				/* Adjust result */
731c2c66affSColin Finck	test eax, HEX(80000000)
732c2c66affSColin Finck	setnz cl
733c2c66affSColin Finck	shr eax, cl
734c2c66affSColin Finck
735c2c66affSColin Finck	xor eax, ebx				/* Correct the result's sign */
736c2c66affSColin Finck	sub eax, ebx
737c2c66affSColin Finck
738c2c66affSColin Finck	mov edx, [ebp + PARAM1]		/* Load pf1 into edx */
739c2c66affSColin Finck	mov [edx + lMant], eax		/* Safe back the mantissa */
740c2c66affSColin Finck	mov ebx, [ebp + PARAM2]		/* Load pf2 into ebx */
741c2c66affSColin Finck	sub ecx, [ebx + lExp]		/* Calculate exponent offset */
742c2c66affSColin Finck	inc ecx
743c2c66affSColin Finck	add [edx + lExp], ecx		/* Safe back exponent */
744c2c66affSColin Finck
745c2c66affSColin Finck	pop ebx						/* Return */
746c2c66affSColin Finck	pop ebp
747c2c66affSColin Finck	ret 8
748c2c66affSColin Finck
749c2c66affSColin FinckDivError:
750c2c66affSColin FinckDiv0:
751c2c66affSColin Finck	mov edx, [ebp + PARAM1]		/* Load pf into edx */
752c2c66affSColin Finck	mov [edx + lMant], eax		/* Store 0 in mantissa */
753c2c66affSColin Finck	mov [edx + lExp], eax		/* Store 0 in exponent */
754c2c66affSColin Finck
755c2c66affSColin Finck	pop ebx						/* Return */
756c2c66affSColin Finck	pop ebp
757c2c66affSColin Finck	ret 8
758c2c66affSColin Finck
759c2c66affSColin Finck
760c2c66affSColin Finck/******************************************************************************
761c2c66affSColin Finck * VOID
762c2c66affSColin Finck * APIENTRY
763c2c66affSColin Finck * FLOATOBJ_DivFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
764c2c66affSColin Finck *
765c2c66affSColin Finck * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Div
766c2c66affSColin Finck */
767c2c66affSColin Finck_FLOATOBJ_DivFloat@8:
768c2c66affSColin FinckPUBLIC _FLOATOBJ_DivFloat@8
769c2c66affSColin Finck	push ebp
770c2c66affSColin Finck	mov ebp, esp
771c2c66affSColin Finck	sub esp, 8					/* Make room for a FLOATOBJ on the stack */
772c2c66affSColin Finck
773c2c66affSColin Finck	mov eax, [ebp + PARAM2]		/* Load f into eax */
774c2c66affSColin Finck	lea ecx, [ebp -4]			/* Load pointer to local FLOATOBJ into ecx */
775c2c66affSColin Finck	push eax					/* Push f on the stack */
776c2c66affSColin Finck	push ecx					/* Push pointer to local FLOATOBJ on the stack */
777c2c66affSColin Finck	call _FLOATOBJ_SetFloat@8	/* Set the FLOATOBJ */
778c2c66affSColin Finck
779c2c66affSColin Finck	lea ecx, [ebp -4]			/* Push pointer to local FLOATOBJ on the stack */
780c2c66affSColin Finck	push ecx
781c2c66affSColin Finck	push [ebp + PARAM1]			/* Push the FLOATOBJ param on the stack */
782c2c66affSColin Finck	call _FLOATOBJ_Div@8		/* Divide */
783c2c66affSColin Finck
784c2c66affSColin Finck	mov esp, ebp				/* Cleanup and return */
785c2c66affSColin Finck	pop ebp
786c2c66affSColin Finck	ret 8
787c2c66affSColin Finck
788c2c66affSColin Finck
789c2c66affSColin Finck/******************************************************************************
790c2c66affSColin Finck * VOID
791c2c66affSColin Finck * APIENTRY
792c2c66affSColin Finck * FLOATOBJ_DivLong(IN OUT PFLOATOBJ pf, IN LONG l);
793c2c66affSColin Finck *
794c2c66affSColin Finck * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Div
795c2c66affSColin Finck */
796c2c66affSColin Finck_FLOATOBJ_DivLong@8:
797c2c66affSColin FinckPUBLIC _FLOATOBJ_DivLong@8
798c2c66affSColin Finck	push ebp
799c2c66affSColin Finck	mov ebp, esp
800c2c66affSColin Finck	sub esp, 8					/* Make room for a FLOATOBJ on the stack */
801c2c66affSColin Finck
802c2c66affSColin Finck	mov eax, [ebp + PARAM2]		/* Load l into eax */
803c2c66affSColin Finck	lea ecx, [ebp -8]			/* Load pointer to local FLOATOBJ into ecx */
804c2c66affSColin Finck	push eax					/* Push l on the stack */
805c2c66affSColin Finck	push ecx					/* Push pointer to local FLOATOBJ on the stack */
806c2c66affSColin Finck	call _FLOATOBJ_SetLong@8	/* Set the local FLOATOBJ */
807c2c66affSColin Finck
808c2c66affSColin Finck	lea ecx, [ebp -8]			/* Push pointer to the local FLOATOBJ on the stack */
809c2c66affSColin Finck	push ecx
810c2c66affSColin Finck	push [ebp + PARAM1]			/* Push the FLOATOBJ param on the stack */
811c2c66affSColin Finck	call _FLOATOBJ_Div@8		/* Divide */
812c2c66affSColin Finck
813c2c66affSColin Finck	mov esp, ebp				/* Cleanup and return */
814c2c66affSColin Finck	pop ebp
815c2c66affSColin Finck	ret 8
816c2c66affSColin Finck
817c2c66affSColin Finck/*******************************************************************************
818c2c66affSColin Finck * VOID
819c2c66affSColin Finck * APIENTRY
820c2c66affSColin Finck * FLOATOBJ_Add(IN OUT PFLOATOBJ pf1, IN PFLOATOBJ pf2);
821c2c66affSColin Finck *
822c2c66affSColin Finck */
823c2c66affSColin Finck_FLOATOBJ_Add@8:
824c2c66affSColin FinckPUBLIC _FLOATOBJ_Add@8
825c2c66affSColin Finck	push ebp
826c2c66affSColin Finck	mov ebp, esp
827c2c66affSColin Finck	push ebx
828c2c66affSColin Finck
829c2c66affSColin Finck	mov eax, [ebp + PARAM1]		/* Load pointer to pf1 in eax */
830c2c66affSColin Finck	mov ebx, [ebp + PARAM2]		/* Load pointer to pf2 in ebx */
831c2c66affSColin Finck
832c2c66affSColin Finck	mov ecx, [eax + lExp]		/* Load float1 in (eax,ecx) */
833c2c66affSColin Finck	mov edx, [ebx + lExp]
834c2c66affSColin Finck	mov eax, [eax + lMant]		/* Load float2 in (ebx,edx) */
835c2c66affSColin Finck	mov ebx, [ebx + lMant]
836c2c66affSColin Finck
837c2c66affSColin Finck	cmp ecx, edx				/* Check which one has the bigger lExp */
838c2c66affSColin Finck	jl Add2
839c2c66affSColin Finck
840c2c66affSColin Finck	sub ecx, edx				/* Calculate lExp1 - lExp2 */
841c2c66affSColin Finck	sar eax, 1					/* Shift both mantissae 1 bit right */
842c2c66affSColin Finck	sar ebx, 1
843c2c66affSColin Finck	sar ebx, cl					/* Shift lMant2 according to exponent difference */
844c2c66affSColin Finck
845c2c66affSColin Finck	add eax, ebx				/* Add the manrissae */
846c2c66affSColin Finck	jz AddIs0
847c2c66affSColin Finck
848c2c66affSColin Finck	cdq							/* Calculate abs(mantissa) */
849c2c66affSColin Finck	xor eax, edx
850c2c66affSColin Finck	sub eax, edx
851c2c66affSColin Finck
852c2c66affSColin Finck	bsr ecx, eax				/* Find most significant bit */
853c2c66affSColin Finck	neg ecx						/* and calculate needed normalize shift */
854c2c66affSColin Finck	add ecx, 30
855c2c66affSColin Finck	shl eax, cl
856c2c66affSColin Finck	dec ecx
857c2c66affSColin Finck
858c2c66affSColin Finck	xor eax, edx				/* Go back to original sign */
859c2c66affSColin Finck	sub eax, edx
860c2c66affSColin Finck
861c2c66affSColin Finck	mov edx, [ebp + PARAM1]		/* Reload pointer to float1 */
862c2c66affSColin Finck
863c2c66affSColin Finck	pop ebx
864c2c66affSColin Finck
865c2c66affSColin Finck	mov dword ptr [edx + lMant], eax	/* Safe mantissa */
866c2c66affSColin Finck	sub [edx + lExp], ecx		/* Adjust exponent */
867c2c66affSColin Finck
868c2c66affSColin Finck	pop ebp						/* Return */
869c2c66affSColin Finck	ret 8
870c2c66affSColin Finck
871c2c66affSColin FinckAdd2:
872c2c66affSColin Finck	sub edx, ecx				/* Calculate lExp2 - lExp1 and put it into ecx */
873c2c66affSColin Finck	mov ecx, edx
874c2c66affSColin Finck
875c2c66affSColin Finck	sar ebx, 1					/* Shift both mantissae 1 bit right */
876c2c66affSColin Finck	sar eax, 1
877c2c66affSColin Finck	sar eax, cl					/* Shift lMant2 according to exponent difference */
878c2c66affSColin Finck
879c2c66affSColin Finck	add eax, ebx				/* Add the manrissae */
880c2c66affSColin Finck	jz AddIs0
881c2c66affSColin Finck
882c2c66affSColin Finck	mov ebx, [ebp + PARAM1]		/* Reload pointer to float1 */
883c2c66affSColin Finck	add [ebx + lExp], ecx		/* Adjust exponent part 1 */
884c2c66affSColin Finck
885c2c66affSColin Finck	cdq							/* Calculate abs(mantissa) */
886c2c66affSColin Finck	xor eax, edx
887c2c66affSColin Finck	sub eax, edx
888c2c66affSColin Finck
889c2c66affSColin Finck	bsr ecx, eax				/* Find most significant bit */
890c2c66affSColin Finck	neg ecx						/* and calculate needed normalize shift */
891c2c66affSColin Finck	add ecx, 30
892c2c66affSColin Finck	shl eax, cl
893c2c66affSColin Finck	dec ecx
894c2c66affSColin Finck
895c2c66affSColin Finck	xor eax, edx				/* Go back to original sign */
896c2c66affSColin Finck	sub eax, edx
897c2c66affSColin Finck
898c2c66affSColin Finck	mov dword ptr [ebx + lMant], eax	/* Safe mantissa and adjust exponent */
899c2c66affSColin Finck	sub [ebx + lExp], ecx
900c2c66affSColin Finck
901c2c66affSColin Finck	pop ebx						/* Return */
902c2c66affSColin Finck	pop ebp
903c2c66affSColin Finck	ret 8
904c2c66affSColin Finck
905c2c66affSColin FinckAddIs0:
906c2c66affSColin Finck	/* Mantissa is 0, so float to (0,0) */
907c2c66affSColin Finck	mov eax, [ebp + PARAM1]
908c2c66affSColin Finck	pop ebx
909c2c66affSColin Finck	mov dword ptr [eax + lMant], 0
910c2c66affSColin Finck	mov dword ptr [eax + lExp], 0
911c2c66affSColin Finck	pop ebp
912c2c66affSColin Finck	ret 8
913c2c66affSColin Finck
914c2c66affSColin Finck/******************************************************************************
915c2c66affSColin Finck * VOID
916c2c66affSColin Finck * APIENTRY
917c2c66affSColin Finck * FLOATOBJ_AddFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
918c2c66affSColin Finck *
919c2c66affSColin Finck * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Add
920c2c66affSColin Finck */
921c2c66affSColin Finck_FLOATOBJ_AddFloat@8:
922c2c66affSColin FinckPUBLIC _FLOATOBJ_AddFloat@8
923c2c66affSColin Finck	push ebp
924c2c66affSColin Finck	mov ebp, esp
925c2c66affSColin Finck	sub esp, 8					/* Make room for a FLOATOBJ on the stack */
926c2c66affSColin Finck
927c2c66affSColin Finck	mov eax, [ebp + PARAM2]		/* Load f into eax */
928c2c66affSColin Finck	lea ecx, [ebp -4]			/* Load pointer to local FLOATOBJ into ecx */
929c2c66affSColin Finck	push eax					/* Push f on the stack */
930c2c66affSColin Finck	push ecx					/* Push pointer to local FLOATOBJ on the stack */
931c2c66affSColin Finck	call _FLOATOBJ_SetFloat@8	/* Set the FLOATOBJ */
932c2c66affSColin Finck
933c2c66affSColin Finck	lea ecx, [ebp -4]			/* Push pointer to local FLOATOBJ on the stack */
934c2c66affSColin Finck	push ecx
935c2c66affSColin Finck	push [ebp + PARAM1]			/* Push the FLOATOBJ param on the stack */
936c2c66affSColin Finck	call _FLOATOBJ_Add@8		/* Add */
937c2c66affSColin Finck
938c2c66affSColin Finck	mov esp, ebp				/* Cleanup and return */
939c2c66affSColin Finck	pop ebp
940c2c66affSColin Finck	ret 8
941c2c66affSColin Finck
942c2c66affSColin Finck
943c2c66affSColin Finck/******************************************************************************
944c2c66affSColin Finck * VOID
945c2c66affSColin Finck * APIENTRY
946c2c66affSColin Finck * FLOATOBJ_AddLong(IN OUT PFLOATOBJ pf, IN LONG l);
947c2c66affSColin Finck *
948c2c66affSColin Finck * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Add
949c2c66affSColin Finck */
950c2c66affSColin Finck_FLOATOBJ_AddLong@8:
951c2c66affSColin FinckPUBLIC _FLOATOBJ_AddLong@8
952c2c66affSColin Finck	push ebp
953c2c66affSColin Finck	mov ebp, esp
954c2c66affSColin Finck	sub esp, 8					/* Make room for a FLOATOBJ on the stack */
955c2c66affSColin Finck
956c2c66affSColin Finck	mov eax, [ebp + PARAM2]		/* Load l into eax */
957c2c66affSColin Finck	lea ecx, [ebp -8]			/* Load pointer to local FLOATOBJ into ecx */
958c2c66affSColin Finck	push eax					/* Push l on the stack */
959c2c66affSColin Finck	push ecx					/* Push pointer to local FLOATOBJ on the stack */
960c2c66affSColin Finck	call _FLOATOBJ_SetLong@8	/* Set the local FLOATOBJ */
961c2c66affSColin Finck
962c2c66affSColin Finck	lea ecx, [ebp -8]			/* Push pointer to the local FLOATOBJ on the stack */
963c2c66affSColin Finck	push ecx
964c2c66affSColin Finck	push [ebp + PARAM1]			/* Push the FLOATOBJ param on the stack */
965c2c66affSColin Finck	call _FLOATOBJ_Add@8		/* Add */
966c2c66affSColin Finck
967c2c66affSColin Finck	mov esp, ebp				/* Cleanup and return */
968c2c66affSColin Finck	pop ebp
969c2c66affSColin Finck	ret 8
970c2c66affSColin Finck
971c2c66affSColin Finck/*******************************************************************************
972c2c66affSColin Finck * VOID
973c2c66affSColin Finck * APIENTRY
974c2c66affSColin Finck * FLOATOBJ_Sub(IN OUT PFLOATOBJ pf, IN PFLOATOBJ pf1);
975c2c66affSColin Finck *
976c2c66affSColin Finck */
977c2c66affSColin Finck_FLOATOBJ_Sub@8:
978c2c66affSColin FinckPUBLIC _FLOATOBJ_Sub@8
979c2c66affSColin Finck	push ebp
980c2c66affSColin Finck	mov ebp, esp
981c2c66affSColin Finck	push ebx
982c2c66affSColin Finck
983c2c66affSColin Finck	mov eax, [ebp + PARAM1]		/* Load pointer to floats in eax and ebx */
984c2c66affSColin Finck	mov ebx, [ebp + PARAM2]
985c2c66affSColin Finck
986c2c66affSColin Finck	mov ecx, [eax + lExp]		/* Load float1 in (eax,ecx) and float2 in (ebx,edx) */
987c2c66affSColin Finck	mov edx, [ebx + lExp]
988c2c66affSColin Finck	mov eax, [eax + lMant]
989c2c66affSColin Finck	mov ebx, [ebx + lMant]
990c2c66affSColin Finck
991c2c66affSColin Finck	cmp ecx, edx				/* Check which one has the bigger lExp */
992c2c66affSColin Finck	jl Sub2
993c2c66affSColin Finck
994c2c66affSColin Finck	sub ecx, edx				/* Calculate lExp1 - lExp2 */
995c2c66affSColin Finck	sar eax, 1					/* Shift both mantissae 1 bit right */
996c2c66affSColin Finck	sar ebx, 1
997c2c66affSColin Finck	sar ebx, cl					/* Shift lMant2 according to exponent difference */
998c2c66affSColin Finck
999c2c66affSColin Finck	sub eax, ebx				/* Substract the manrissae */
1000c2c66affSColin Finck	jz SubIs0
1001c2c66affSColin Finck
1002c2c66affSColin Finck	cdq							/* Calculate abs(mantissa) */
1003c2c66affSColin Finck	xor eax, edx
1004c2c66affSColin Finck	sub eax, edx
1005c2c66affSColin Finck
1006c2c66affSColin Finck	bsr ecx, eax				/* Find most significant bit */
1007c2c66affSColin Finck	neg ecx						/* and calculate needed normalize shift */
1008c2c66affSColin Finck	add ecx, 30
1009c2c66affSColin Finck	shl eax, cl
1010c2c66affSColin Finck	dec ecx
1011c2c66affSColin Finck
1012c2c66affSColin Finck	xor eax, edx				/* Go back to original sign */
1013c2c66affSColin Finck	sub eax, edx
1014c2c66affSColin Finck
1015c2c66affSColin Finck	mov edx, [ebp + PARAM1]		/* Reload pointer to float1 */
1016c2c66affSColin Finck
1017c2c66affSColin Finck	pop ebx
1018c2c66affSColin Finck
1019c2c66affSColin Finck	mov dword ptr [edx + lMant], eax /* Safe mantissa and adjust exponent */
1020c2c66affSColin Finck	sub [edx + lExp], ecx
1021c2c66affSColin Finck
1022c2c66affSColin Finck	pop ebp
1023c2c66affSColin Finck	ret 8
1024c2c66affSColin Finck
1025c2c66affSColin FinckSub2:
1026c2c66affSColin Finck	sub edx, ecx				/* Calculate lExp2 - lExp1 and put it into ecx */
1027c2c66affSColin Finck	mov ecx, edx
1028c2c66affSColin Finck
1029c2c66affSColin Finck	sar ebx, 1					/* Shift both mantissae 1 bit right */
1030c2c66affSColin Finck	sar eax, 1
1031c2c66affSColin Finck	sar eax, cl					/* Shift lMant2 according to exponent difference */
1032c2c66affSColin Finck
1033c2c66affSColin Finck	sub eax, ebx				/* Substract the manrissae */
1034c2c66affSColin Finck	jz AddIs0
1035c2c66affSColin Finck
1036c2c66affSColin Finck	mov ebx, [ebp + PARAM1]		/* Reload pointer to float1 */
1037c2c66affSColin Finck	add [ebx + lExp], ecx		/* Adjust exponent part 1 */
1038c2c66affSColin Finck
1039c2c66affSColin Finck	cdq							/* Calculate abs(mantissa) */
1040c2c66affSColin Finck	xor eax, edx
1041c2c66affSColin Finck	sub eax, edx
1042c2c66affSColin Finck
1043c2c66affSColin Finck	bsr ecx, eax				/* Find most significant bit */
1044c2c66affSColin Finck	neg ecx						/* and calculate needed normalize shift */
1045c2c66affSColin Finck	add ecx, 30
1046c2c66affSColin Finck	shl eax, cl
1047c2c66affSColin Finck	dec ecx
1048c2c66affSColin Finck
1049c2c66affSColin Finck	xor eax, edx				/* Go back to original sign */
1050c2c66affSColin Finck	sub eax, edx
1051c2c66affSColin Finck
1052c2c66affSColin Finck	mov dword ptr [ebx + lMant], eax	/* Safe mantissa */
1053c2c66affSColin Finck	sub [ebx + lExp], ecx		/* Adjust exponent */
1054c2c66affSColin Finck
1055c2c66affSColin Finck	pop ebx						/* Return */
1056c2c66affSColin Finck	pop ebp
1057c2c66affSColin Finck	ret 8
1058c2c66affSColin Finck
1059c2c66affSColin FinckSubIs0:
1060c2c66affSColin Finck	/* Mantissa is 0, so float to (0,0) */
1061c2c66affSColin Finck	mov eax, [ebp + PARAM1]
1062c2c66affSColin Finck	pop ebx
1063c2c66affSColin Finck	mov dword ptr [eax + lMant], 0
1064c2c66affSColin Finck	mov dword ptr [eax + lExp], 0
1065c2c66affSColin Finck	pop ebp
1066c2c66affSColin Finck	ret 8
1067c2c66affSColin Finck/******************************************************************************
1068c2c66affSColin Finck * VOID
1069c2c66affSColin Finck * APIENTRY
1070c2c66affSColin Finck * FLOATOBJ_SubFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
1071c2c66affSColin Finck *
1072c2c66affSColin Finck * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Sub
1073c2c66affSColin Finck */
1074c2c66affSColin Finck_FLOATOBJ_SubFloat@8:
1075c2c66affSColin FinckPUBLIC _FLOATOBJ_SubFloat@8
1076c2c66affSColin Finck	push ebp
1077c2c66affSColin Finck	mov ebp, esp
1078c2c66affSColin Finck	sub esp, 8					/* Make room for a FLOATOBJ on the stack */
1079c2c66affSColin Finck
1080c2c66affSColin Finck	mov eax, [ebp + PARAM2]		/* Load f into eax */
1081c2c66affSColin Finck	lea ecx, [ebp -4]			/* Load pointer to local FLOATOBJ into ecx */
1082c2c66affSColin Finck	push eax					/* Push f on the stack */
1083c2c66affSColin Finck	push ecx					/* Push pointer to local FLOATOBJ on the stack */
1084c2c66affSColin Finck	call _FLOATOBJ_SetFloat@8	/* Set the FLOATOBJ */
1085c2c66affSColin Finck
1086c2c66affSColin Finck	lea ecx, [ebp -4]			/* Push pointer to local FLOATOBJ on the stack */
1087c2c66affSColin Finck	push ecx
1088c2c66affSColin Finck	push [ebp + PARAM1]			/* Push the FLOATOBJ param on the stack */
1089c2c66affSColin Finck	call _FLOATOBJ_Sub@8		/* Substract */
1090c2c66affSColin Finck
1091c2c66affSColin Finck	mov esp, ebp				/* Cleanup and return */
1092c2c66affSColin Finck	pop ebp
1093c2c66affSColin Finck	ret 8
1094c2c66affSColin Finck
1095c2c66affSColin Finck
1096c2c66affSColin Finck/******************************************************************************
1097c2c66affSColin Finck * VOID
1098c2c66affSColin Finck * APIENTRY
1099c2c66affSColin Finck * FLOATOBJ_SubLong(IN OUT PFLOATOBJ pf, IN LONG l);
1100c2c66affSColin Finck *
1101c2c66affSColin Finck * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Sub
1102c2c66affSColin Finck */
1103c2c66affSColin Finck_FLOATOBJ_SubLong@8:
1104c2c66affSColin FinckPUBLIC _FLOATOBJ_SubLong@8
1105c2c66affSColin Finck	push ebp
1106c2c66affSColin Finck	mov ebp, esp
1107c2c66affSColin Finck	sub esp, 8					/* Make room for a FLOATOBJ on the stack */
1108c2c66affSColin Finck
1109c2c66affSColin Finck	mov eax, [ebp + PARAM2]		/* Load l into eax */
1110c2c66affSColin Finck	lea ecx, [ebp -8]			/* Load pointer to local FLOATOBJ into ecx */
1111c2c66affSColin Finck	push eax					/* Push l on the stack */
1112c2c66affSColin Finck	push ecx					/* Push pointer to local FLOATOBJ on the stack */
1113c2c66affSColin Finck	call _FLOATOBJ_SetLong@8	/* Set the local FLOATOBJ */
1114c2c66affSColin Finck
1115c2c66affSColin Finck	lea ecx, [ebp -8]			/* Push pointer to the local FLOATOBJ on the stack */
1116c2c66affSColin Finck	push ecx
1117c2c66affSColin Finck	push [ebp + PARAM1]			/* Push the FLOATOBJ param on the stack */
1118c2c66affSColin Finck	call _FLOATOBJ_Sub@8		/* Substract */
1119c2c66affSColin Finck
1120c2c66affSColin Finck	mov esp, ebp				/* Cleanup and return */
1121c2c66affSColin Finck	pop ebp
1122c2c66affSColin Finck	ret 8
1123c2c66affSColin Finck
1124c2c66affSColin Finck
1125c2c66affSColin Finck/*******************************************************************************
1126c2c66affSColin Finck * VOID
1127c2c66affSColin Finck * APIENTRY
1128c2c66affSColin Finck * FLOATOBJ_Neg(IN OUT PFLOATOBJ pf);
1129c2c66affSColin Finck *
1130c2c66affSColin Finck */
1131c2c66affSColin Finck_FLOATOBJ_Neg@4:
1132c2c66affSColin FinckPUBLIC _FLOATOBJ_Neg@4
1133c2c66affSColin Finck	push ebp
1134c2c66affSColin Finck	mov ebp, esp
1135c2c66affSColin Finck
1136c2c66affSColin Finck	mov ecx, [esp + PARAM1]		/* Load pf into ecx */
1137c2c66affSColin Finck	neg dword ptr [ecx + lMant]	/* Negate lMant1 */
1138c2c66affSColin Finck
1139c2c66affSColin Finck	pop ebp						/* Return */
1140c2c66affSColin Finck	ret 4
1141c2c66affSColin Finck
1142c2c66affSColin FinckEND
1143c2c66affSColin Finck/* EOF */
1144