2 * COPYRIGHT: LGPL, see LGPL.txt in the top level directory
3 * PROJECT: ReactOS Win32 subsystem
4 * PURPOSE: FLOATOBJ floating point emulation functions for x86
5 * FILE: subsystems/win32/win32k/objects/i386/floatobj.S
6 * PROGRAMMER: Timo Kreuzer
10 /*******************************************************************************
11 * IEEE 754-1985 single precision floating point
13 * | 31 | 30...23 | 22...0 |
14 * |sign| exponent | fraction |
16 * mantissa = 1 + (fraction / 2^23)
17 * f = (-1)^sign * mantissa * 2 ^ (exponent - bias)
20 *******************************************************************************
21 * win32k x86 floating point emulation
29 * f = (lMant / 0x40000000) * 2 ^ (lExp - 2)
30 * = lMant * 2 ^ (lExp - 32)
32 *******************************************************************************
35 * - shld is slow (4 cycles) and not pairable, mov + shl is faster
36 * - esp is used, because it's available earlier
37 * - bsr is very slow on old cpus (up to 72 cycles on a p1) while being much
38 * faster on modern cpus (2-11 cycles). Workarounds using branch trees or
39 * table lookups are of no use nowadays.
40 *******************************************************************************
41 * Compatibility notes:
42 * - There are issues with very large size values near integer overflow.
43 * Floating point values are behaving different there. This behavior isn't
44 * simulated yet. Difference is < 10^-5 %
45 * - The result of a multiplication can differ from Windows result in the
46 * least significant bit, that is a difference of 1 / 2^30 or ~10^-9
47 *******************************************************************************
48 * Implementation status:
50 * FLOATOBJ_SetFloat - implemented, tested
51 * FLOATOBJ_SetLong - implemented, tested
52 * FLOATOBJ_GetFloat - implemented, tested
53 * FLOATOBJ_GetLong - implemented, tested
54 * FLOATOBJ_Equal - implemented, tested
55 * FLOATOBJ_EqualLong - implemented
56 * FLOATOBJ_GreaterThan - implemented
57 * FLOATOBJ_GreaterThanLong - wrapper
58 * FLOATOBJ_LessThan - implemented
59 * FLOATOBJ_LessThanLong - wrapper
60 * FLOATOBJ_Neg - implemented
61 * FLOATOBJ_Mul - implemented, tested, optimized
62 * FLOATOBJ_MulFloat - wrapper
63 * FLOATOBJ_MulLong - wrapper, could really need optimization
64 * FLOATOBJ_Div - implemented
65 * FLOATOBJ_DivFloat - wrapper
66 * FLOATOBJ_DivLong - wrapper
67 * FLOATOBJ_Add - implemented, tested
68 * FLOATOBJ_AddFloat - wrapper
69 * FLOATOBJ_AddLong - wrapper
70 * FLOATOBJ_Sub - implemented, tested
71 * FLOATOBJ_SubFloat - wrapper
72 * FLOATOBJ_SubLong - wrapper
75 .intel_syntax noprefix
84 /******************************************************************************
87 * FLOATOBJ_SetFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
90 .global _FLOATOBJ_SetFloat@8
94 mov ecx, [esp + PARAM2] /* Load the float into ecx */
95 mov eax, ecx /* Copy float to eax for later */
97 test ecx, 0x7f800000 /* Check for zero exponent - 0 or denormal */
98 jz SetFloat0 /* If it's all zero, ... */
100 shl ecx, 7 /* Put the bits for the mantissa in place */
102 cdq /* Fill edx with the sign from the FLOATL in eax */
103 and ecx, 0x7fffffff /* Mask out invalid field in the mantissa */
105 shr eax, 23 /* Shift the exponent in eax in place */
106 or ecx, 0x40000000 /* Set bit for 1 in the mantissa */
107 and eax, 0xff /* Mask out invalid fields in the exponent in eax */
109 xor ecx, edx /* Make use of the sign bit expanded to full edx */
111 sub eax, 125 /* Adjust exonent bias */
113 sub ecx, edx /* Substract -1 or add 1 if sign was set */
115 mov edx, [esp + PARAM1] /* Load pf into edx */
116 mov [edx + lMant], ecx /* Save back mantissa */
117 mov [edx + lExp], eax /* Save back exponent */
123 mov edx, [esp + PARAM1] /* Load pf into edx */
125 mov dword ptr [edx + lMant], 0 /* Set mantissa and exponent to 0 */
126 mov dword ptr [edx + lExp], 0
132 /*******************************************************************************
135 * FLOATOBJ_GetFloat(IN PFLOATOBJ pf);
138 _FLOATOBJ_GetFloat@4:
139 .global _FLOATOBJ_GetFloat@4
143 mov edx, [esp + PARAM1] /* Load pf into edx */
144 mov eax, [edx + lMant] /* Load mantissa into eax */
145 mov ecx, [edx + lExp] /* Load exponent into ecx */
147 cdq /* Calculate abs(mantissa) */
155 and ecx, 0xff /* Mask out invalid fields in the exponent */
156 and eax, 0x3fffffff /* Mask out invalid fields in mantissa */
158 shl ecx, 23 /* Shift exponent in place */
159 shr eax, 7 /* Shift mantissa in place */
161 and edx, 0x80000000 /* Reduce edx to sign bit only */
163 or eax, ecx /* Set exponent in result */
164 or eax, edx /* Set sign bit in result */
173 /******************************************************************************
176 * FLOATOBJ_SetLong(OUT PFLOATOBJ pf, IN LONG l);
178 * Instead of using abs(l), which is 3 + 2 instructions, use a branch.
181 .global _FLOATOBJ_SetLong@8
185 mov eax, [esp + PARAM2] /* Load l into eax */
186 mov edx, [esp + PARAM1] /* Load pf into edx */
188 test eax, eax /* different handling for <0, =0 and >0 */
192 bsr ecx, eax /* Get number of most significant bit aka log2(l) */
193 mov [edx + lExp], ecx /* Safe log2(l) into exponent */
195 neg ecx /* Calculate necessary shift */
198 add dword ptr [edx + lExp], 2 /* Adjust exponent */
200 shl eax, cl /* Shift mantissa in place */
201 mov [edx + lMant], eax /* Save mantissa */
207 neg eax /* Get absolute value of l */
208 bsr ecx, eax /* Get number of most significant bit aka log2(l) */
209 neg eax /* Back to negative */
211 mov [edx + lExp], ecx /* Safe log2(-l) into exponent */
213 neg ecx /* Calculate necessary shift */
216 add dword ptr [edx + lExp], 2 /* Adjust exponent */
218 shl eax, cl /* Shift mantissa in place */
219 mov [edx + lMant], eax /* Save mantissa */
225 mov dword ptr [edx + lMant], 0 /* Set mantissa and exponent to 0 */
226 mov dword ptr [edx + lExp], 0
232 /*******************************************************************************
235 * FLOATOBJ_GetLong(IN PFLOATOBJ pf);
239 .global _FLOATOBJ_GetLong@4
243 mov edx, [ebp + PARAM1] /* Load pf into edx */
244 mov ecx, 32 /* Load (32 - lExp) into ecx */
245 sub ecx, [edx + lExp]
246 jle short GetLong2 /* Check for Overflow */
248 mov eax, [edx + lMant] /* Load mantissa into eax */
249 sar eax, cl /* Signed shift mantissa according to exponent */
255 xor eax, eax /* Overflow, return 0 */
260 /******************************************************************************
263 * FLOATOBJ_Equal(IN PFLOATOBJ pf1, IN PFLOATOBJ pf2);
266 .global _FLOATOBJ_Equal@8
270 mov ecx, [esp + PARAM1] /* Load pf1 into ecx */
271 mov eax, [esp + PARAM2] /* Load pf2 into ecx */
273 mov edx, [ecx + lExp] /* Get float1 in ecx, edx */
274 mov ecx, [ecx + lMant]
276 sub edx, [eax + lExp] /* Calculate diference to float2 */
277 sub ecx, [eax + lMant]
279 or edx, ecx /* Combine */
281 mov eax, 0 /* Set eax if combination is 0 */
288 /******************************************************************************
291 * FLOATOBJ_EqualLong(IN PFLOATOBJ pf, IN LONG l);
293 _FLOATOBJ_EqualLong@8:
294 .global _FLOATOBJ_EqualLong@8
298 mov eax, [esp + PARAM1] /* Load pf into eax */
299 mov ecx, 32 /* Load (32 - lExp) into ecx */
300 sub ecx, [eax + lExp]
301 mov edx, [eax + lMant] /* Load mantissa into edx */
302 sar edx, cl /* Signed shift mantissa according to exponent */
303 shl edx, cl /* Shift the mantissa back */
304 cmp edx, [eax + lMant] /* Check whether bits were killed by shifting */
305 jnz EqualLongFalse /* We have truncated the mantissa, return 0 */
307 sar edx, cl /* Shift the mantissa again */
308 xor eax, eax /* Set return value ... */
309 cmp edx, [esp + PARAM2] /* TRUE if shifted mantissa equals the LONG */
316 xor eax, eax /* Return FALSE */
321 /******************************************************************************
324 * FLOATOBJ_GreaterThan(IN PFLOATOBJ pf, IN PFLOATOBJ pf1);
327 _FLOATOBJ_GreaterThan@8:
328 .global _FLOATOBJ_GreaterThan@8
332 mov eax, [ebp + PARAM1] /* Load pointer to efloat1 in eax */
333 mov edx, [ebp + PARAM2] /* Load pointer to efloat2 in edx */
335 mov ecx, [eax + lMant] /* Load mantissa1 in ecx */
336 mov edx, [edx + lMant] /* Load mantissa2 in edx */
338 sar ecx, 31 /* Calculate sign(lMant1) in ecx */
339 sar edx, 31 /* Calculate sign(lMant2) in edx */
341 cmp ecx, edx /* Branch if both have the same sign */
344 /* Mantissae have different sign */
345 mov eax, 0 /* Return (sign(lMant1) > sign(lMant2)) */
351 /* Mantissae have the same sign */
353 mov edx, [ebp + PARAM2] /* Reload pointer to float2 in edx */
354 test ecx, ecx /* Branch if sign is negative */
357 /* Both mantissae are positive or 0 */
359 or ecx, [edx + lMant] /* Branch if one mantissa is 0 */
362 /* Both mantissae are positive */
364 mov ecx, [eax + lExp] /* Branch if exponents are equal */
365 cmp ecx, [edx + lExp]
368 mov eax, 0 /* Return (lExp1 > lExp2) */
374 /* Exponents are equal or one mantissa is 0 */
376 mov ecx, [eax + lMant] /* Return (lMant1 > lMant2) */
377 cmp ecx, [edx + lMant]
384 /* Both mantissae are negative */
386 mov ecx, [eax + lExp] /* Branch if exponents are equal */
387 cmp ecx, [edx + lExp]
390 /* Both mantissae negative, exponents are different */
392 mov eax, 0 /* Return (lExp1 < lExp2) */
398 /* Both mantissae negative, exponents are equal */
400 mov ecx, [eax + lMant] /* Return (lMant1 < lMant2) */
401 cmp ecx, [edx + lMant]
409 /******************************************************************************
412 * FLOATOBJ_GreaterThanLong(IN OUT PFLOATOBJ pf, IN LONG l);
414 * Currently implemented as a wrapper around FLOATOBJ_SetLong and
415 * LOATOBJ_GreaterThan
417 _FLOATOBJ_GreaterThanLong@8:
418 .global _FLOATOBJ_GreaterThanLong@8
422 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
423 mov eax, [ebp + PARAM2] /* Load LONG into eax */
425 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
427 push eax /* Push LONG on the stack */
428 push ecx /* Push pointer to local FLOATOBJ on the stack */
429 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
431 lea ecx, [ebp -8] /* Push pointer to the local FLOATOBJ on the stack */
433 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
434 call _FLOATOBJ_GreaterThan@8 /* Compare */
436 mov esp, ebp /* Cleanup and return */
441 /******************************************************************************
444 * FLOATOBJ_LessThan(IN PFLOATOBJ pf, IN PFLOATOBJ pf1);
447 _FLOATOBJ_LessThan@8:
448 .global _FLOATOBJ_LessThan@8
452 mov eax, [ebp + PARAM1] /* Load pointer to floats in eax and edx */
453 mov edx, [ebp + PARAM2]
455 mov ecx, [eax + lMant] /* Load mantissae in ecx and edx */
456 mov edx, [edx + lMant]
458 sar ecx, 31 /* Calculate sign(lMant1) and sign(lMant2) */
461 cmp ecx, edx /* Branch if both have the same sign */
464 /* Mantissae have different sign */
466 mov eax, 0 /* Return (sign(lMant1) < sign(lMant2)) */
472 /* Mantissae have the same sign */
475 mov edx, [ebp + PARAM2] /* Reload pointer to float2 in edx */
477 test ecx, ecx /* Branch if sign is negative */
480 /* Both mantissae are positive or 0 */
482 or ecx, [edx + lMant] /* Branch if one mantissa is 0 */
485 /* Both mantissae are positive */
487 mov ecx, [eax + lExp] /* Branch if exponents are equal */
488 cmp ecx, [edx + lExp]
491 mov eax, 0 /* Return (lExp1 < lExp2) */
497 /* Exponents are equal or one mantissa is 0 */
499 mov ecx, [eax + lMant] /* Return (lMant1 < lMant2) */
500 cmp ecx, [edx + lMant]
507 /* Both mantissae are negative */
509 mov ecx, [eax + lExp] /* Branch if exponents are equal */
510 cmp ecx, [edx + lExp]
513 /* Both mantissae negative, exponents are different */
515 mov eax, 0 /* Return (lExp1 > lExp2) */
521 /* Both mantissae negative, exponents are equal */
523 mov ecx, [eax + lMant] /* Return (lMant1 > lMant2) */
524 cmp ecx, [edx + lMant]
531 /******************************************************************************
534 * FLOATOBJ_LessThanLong(IN OUT PFLOATOBJ pf, IN LONG l);
536 * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_LessThan
538 _FLOATOBJ_LessThanLong@8:
539 .global _FLOATOBJ_LessThanLong@8
543 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
544 mov eax, [ebp + PARAM2] /* Load LONG into eax */
546 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
547 push eax /* Push LONG on the stack */
548 push ecx /* Push pointer to local FLOATOBJ on the stack */
549 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
551 lea ecx, [ebp -8] /* Push pointer to the local FLOATOBJ on the stack */
553 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
554 call _FLOATOBJ_LessThan@8 /* Compare */
556 mov esp, ebp /* Cleanup and return */
562 /******************************************************************************
565 * FLOATOBJ_Mul(IN OUT PFLOATOBJ pf1, IN PFLOATOBJ pf2);
567 * (mant1 * 2^exp1) * (mant2 * 2^exp2) = (mant1 * mant2) * 2^(exp1 + exp2)
568 * or mant = mant1 * mant2 and exp = exp1 + exp2
569 * No special handling for 0, where mantissa is 0
572 .global _FLOATOBJ_Mul@8
576 mov edx, [esp + PARAM1] /* Load pf1 into edx */
577 mov ecx, [esp + PARAM2] /* Load pf2 into ecx */
578 mov eax, [ecx + lMant] /* Load mantissa2 into eax */
579 mov ecx, [ecx + lExp] /* Load exponent2 into ecx */
581 imul dword ptr [edx + lMant] /* Multiply eax with mantissa 1 */
583 test edx, edx /* Special handling for result < 0 */
586 shl edx, 2 /* Get new mantissa from bits 30 to 62 */
587 shr eax, 30 /* of edx:eax into edx */
590 mov edx, ecx /* Need ecx for the shift, safe exp2 to free edx */
591 mov ecx, 0 /* Check for highest bit */
593 shr eax, cl /* Normalize mantissa in eax */
597 lea edx, [edx + ecx -2] /* Normalize exponent in edx */
600 mov ecx, [esp + PARAM1] /* Load pf1 into ecx */
601 mov [ecx + lMant], eax /* Save back mantissa */
602 add [ecx + lExp], edx /* Save back exponent */
609 shl edx, 2 /* Get new mantissa from bits 30 to 62 */
610 shr eax, 30 /* of edx:eax into edx */
613 mov edx, ecx /* Need ecx for the shift, safe exp2 to free edx */
615 mov ecx, 0 /* Check for highest bit */
617 shr eax, cl /* Normalize mantissa in eax */
622 lea edx, [edx + ecx -2] /* Normalize exponent in edx */
623 or eax, 0x80000000 /* Set sign bit */
625 mov ecx, [esp + PARAM1] /* Load pf1 into ecx */
626 mov [ecx + lMant], eax /* Save back mantissa */
627 add [ecx + lExp], edx /* Save back exponent */
633 mov ecx, [esp + PARAM1] /* Load pf1 into ecx */
634 mov [ecx + lMant], eax /* Store 0 in mantissa */
635 mov [ecx + lExp], eax /* Store 0 in exponent */
641 /******************************************************************************
644 * FLOATOBJ_MulFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
646 * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Mul
648 _FLOATOBJ_MulFloat@8:
649 .global _FLOATOBJ_MulFloat@8
653 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
654 mov eax, [ebp + PARAM2] /* Load f into eax */
655 lea ecx, [ebp -4] /* Load pointer to local FLOATOBJ into ecx */
656 push eax /* Push f on the stack */
657 push ecx /* Push pointer to local FLOATOBJ on the stack */
658 call _FLOATOBJ_SetFloat@8 /* Set the FLOATOBJ */
660 lea ecx, [ebp -4] /* Push pointer to local FLOATOBJ on the stack */
662 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
663 call _FLOATOBJ_Mul@8 /* Multiply */
665 mov esp, ebp /* Cleanup and return */
670 /******************************************************************************
673 * FLOATOBJ_MulLong(IN OUT PFLOATOBJ pf, IN LONG l);
675 * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Mul
678 .global _FLOATOBJ_MulLong@8
682 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
683 mov eax, [ebp + PARAM2] /* Load l into eax */
684 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
685 push eax /* Push l on the stack */
686 push ecx /* Push pointer to local FLOATOBJ on the stack */
687 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
689 lea ecx, [ebp -8] /* Push pointer to local FLOATOBJ on the stack */
691 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
692 call _FLOATOBJ_Mul@8 /* Multiply */
694 mov esp, ebp /* Cleanup and return */
699 /*******************************************************************************
702 * FLOATOBJ_Div(IN OUT PFLOATOBJ pf1, IN PFLOATOBJ pf2);
706 .global _FLOATOBJ_Div@8
711 mov eax, [ebp + PARAM2] /* Load lMant2 into eax */
712 mov eax, [eax + lMant]
714 cdq /* Calculate abs(lMant2) */
717 jz DivError /* Divide by zero error! */
719 mov ebx, edx /* Copy sign(lMant2) to ebx */
720 mov ecx, eax /* Copy abs(lMant2) to ecx */
722 mov eax, [ebp + PARAM1] /* Load lMant1 into eax */
723 mov eax, [eax + lMant]
725 cdq /* Calculate abs(lMant1) */
729 jz Div0 /* Dividend is 0? */
731 xor ebx, edx /* combine both signs in ebx */
733 mov edx, eax /* Prepare edx:eax for integer divide */
736 div ecx /* Do an unsigned divide */
738 xor ecx, ecx /* Adjust result */
743 xor eax, ebx /* Correct the result's sign */
746 mov edx, [ebp + PARAM1] /* Load pf1 into edx */
747 mov [edx + lMant], eax /* Safe back the mantissa */
748 mov ebx, [ebp + PARAM2] /* Load pf2 into ebx */
749 sub ecx, [ebx + lExp] /* Calculate exponent offset */
751 add [edx + lExp], ecx /* Safe back exponent */
759 mov edx, [ebp + PARAM1] /* Load pf into edx */
760 mov [edx + lMant], eax /* Store 0 in mantissa */
761 mov [edx + lExp], eax /* Store 0 in exponent */
768 /******************************************************************************
771 * FLOATOBJ_DivFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
773 * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Div
775 _FLOATOBJ_DivFloat@8:
776 .global _FLOATOBJ_DivFloat@8
779 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
781 mov eax, [ebp + PARAM2] /* Load f into eax */
782 lea ecx, [ebp -4] /* Load pointer to local FLOATOBJ into ecx */
783 push eax /* Push f on the stack */
784 push ecx /* Push pointer to local FLOATOBJ on the stack */
785 call _FLOATOBJ_SetFloat@8 /* Set the FLOATOBJ */
787 lea ecx, [ebp -4] /* Push pointer to local FLOATOBJ on the stack */
789 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
790 call _FLOATOBJ_Div@8 /* Divide */
792 mov esp, ebp /* Cleanup and return */
797 /******************************************************************************
800 * FLOATOBJ_DivLong(IN OUT PFLOATOBJ pf, IN LONG l);
802 * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Div
805 .global _FLOATOBJ_DivLong@8
808 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
810 mov eax, [ebp + PARAM2] /* Load l into eax */
811 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
812 push eax /* Push l on the stack */
813 push ecx /* Push pointer to local FLOATOBJ on the stack */
814 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
816 lea ecx, [ebp -8] /* Push pointer to the local FLOATOBJ on the stack */
818 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
819 call _FLOATOBJ_Div@8 /* Divide */
821 pop ebp /* Cleanup and return */
825 /*******************************************************************************
828 * FLOATOBJ_Add(IN OUT PFLOATOBJ pf1, IN PFLOATOBJ pf2);
832 .global _FLOATOBJ_Add@8
837 mov eax, [ebp + PARAM1] /* Load pointer to pf1 in eax */
838 mov ebx, [ebp + PARAM2] /* Load pointer to pf2 in ebx */
840 mov ecx, [eax + lExp] /* Load float1 in (eax,ecx) */
841 mov edx, [ebx + lExp]
842 mov eax, [eax + lMant] /* Load float2 in (ebx,edx) */
843 mov ebx, [ebx + lMant]
845 cmp ecx, edx /* Check which one has the bigger lExp */
848 sub ecx, edx /* Calculate lExp1 - lExp2 */
849 sar eax, 1 /* Shift both mantissae 1 bit right */
851 sar ebx, cl /* Shift lMant2 according to exponent difference */
853 add eax, ebx /* Add the manrissae */
856 cdq /* Calculate abs(mantissa) */
860 bsr ecx, eax /* Find most significant bit */
861 neg ecx /* and calculate needed normalize shift */
866 xor eax, edx /* Go back to original sign */
869 mov edx, [ebp + PARAM1] /* Reload pointer to float1 */
873 mov dword ptr [edx + lMant], eax /* Safe mantissa */
874 sub [edx + lExp], ecx /* Adjust exponent */
880 sub edx, ecx /* Calculate lExp2 - lExp1 and put it into ecx */
883 sar ebx, 1 /* Shift both mantissae 1 bit right */
885 sar eax, cl /* Shift lMant2 according to exponent difference */
887 add eax, ebx /* Add the manrissae */
890 mov ebx, [ebp + PARAM1] /* Reload pointer to float1 */
891 add [ebx + lExp], ecx /* Adjust exponent part 1 */
893 cdq /* Calculate abs(mantissa) */
897 bsr ecx, eax /* Find most significant bit */
898 neg ecx /* and calculate needed normalize shift */
903 xor eax, edx /* Go back to original sign */
906 mov dword ptr [ebx + lMant], eax /* Safe mantissa and adjust exponent */
907 sub [ebx + lExp], ecx
914 /* Mantissa is 0, so float to (0,0) */
915 mov eax, [ebp + PARAM1]
917 mov dword ptr [eax + lMant], 0
918 mov dword ptr [eax + lExp], 0
923 /******************************************************************************
926 * FLOATOBJ_AddFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
928 * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Add
930 _FLOATOBJ_AddFloat@8:
931 .global _FLOATOBJ_AddFloat@8
934 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
936 mov eax, [ebp + PARAM2] /* Load f into eax */
937 lea ecx, [ebp -4] /* Load pointer to local FLOATOBJ into ecx */
938 push eax /* Push f on the stack */
939 push ecx /* Push pointer to local FLOATOBJ on the stack */
940 call _FLOATOBJ_SetFloat@8 /* Set the FLOATOBJ */
942 lea ecx, [ebp -4] /* Push pointer to local FLOATOBJ on the stack */
944 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
945 call _FLOATOBJ_Add@8 /* Add */
947 mov esp, ebp /* Cleanup and return */
952 /******************************************************************************
955 * FLOATOBJ_AddLong(IN OUT PFLOATOBJ pf, IN LONG l);
957 * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Add
960 .global _FLOATOBJ_AddLong@8
963 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
965 mov eax, [ebp + PARAM2] /* Load l into eax */
966 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
967 push eax /* Push l on the stack */
968 push ecx /* Push pointer to local FLOATOBJ on the stack */
969 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
971 lea ecx, [ebp -8] /* Push pointer to the local FLOATOBJ on the stack */
973 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
974 call _FLOATOBJ_Add@8 /* Add */
976 mov esp, ebp /* Cleanup and return */
981 /*******************************************************************************
984 * FLOATOBJ_Sub(IN OUT PFLOATOBJ pf, IN PFLOATOBJ pf1);
988 .global _FLOATOBJ_Sub@8
993 mov eax, [ebp + PARAM1] /* Load pointer to floats in eax and ebx */
994 mov ebx, [ebp + PARAM2]
996 mov ecx, [eax + lExp] /* Load float1 in (eax,ecx) and float2 in (ebx,edx) */
997 mov edx, [ebx + lExp]
998 mov eax, [eax + lMant]
999 mov ebx, [ebx + lMant]
1001 cmp ecx, edx /* Check which one has the bigger lExp */
1004 sub ecx, edx /* Calculate lExp1 - lExp2 */
1005 sar eax, 1 /* Shift both mantissae 1 bit right */
1007 sar ebx, cl /* Shift lMant2 according to exponent difference */
1009 sub eax, ebx /* Substract the manrissae */
1012 cdq /* Calculate abs(mantissa) */
1016 bsr ecx, eax /* Find most significant bit */
1017 neg ecx /* and calculate needed normalize shift */
1022 xor eax, edx /* Go back to original sign */
1025 mov edx, [ebp + PARAM1] /* Reload pointer to float1 */
1029 mov dword ptr [edx + lMant], eax /* Safe mantissa and adjust exponent */
1030 sub [edx + lExp], ecx
1036 sub edx, ecx /* Calculate lExp2 - lExp1 and put it into ecx */
1039 sar ebx, 1 /* Shift both mantissae 1 bit right */
1041 sar eax, cl /* Shift lMant2 according to exponent difference */
1043 sub eax, ebx /* Substract the manrissae */
1046 mov ebx, [ebp + PARAM1] /* Reload pointer to float1 */
1047 add [ebx + lExp], ecx /* Adjust exponent part 1 */
1049 cdq /* Calculate abs(mantissa) */
1053 bsr ecx, eax /* Find most significant bit */
1054 neg ecx /* and calculate needed normalize shift */
1059 xor eax, edx /* Go back to original sign */
1062 mov dword ptr [ebx + lMant], eax /* Safe mantissa */
1063 sub [ebx + lExp], ecx /* Adjust exponent */
1065 pop ebx /* Return */
1070 /* Mantissa is 0, so float to (0,0) */
1071 mov eax, [ebp + PARAM1]
1073 mov dword ptr [eax + lMant], 0
1074 mov dword ptr [eax + lExp], 0
1078 /******************************************************************************
1081 * FLOATOBJ_SubFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
1083 * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Sub
1085 _FLOATOBJ_SubFloat@8:
1086 .global _FLOATOBJ_SubFloat@8
1089 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
1091 mov eax, [ebp + PARAM2] /* Load f into eax */
1092 lea ecx, [ebp -4] /* Load pointer to local FLOATOBJ into ecx */
1093 push eax /* Push f on the stack */
1094 push ecx /* Push pointer to local FLOATOBJ on the stack */
1095 call _FLOATOBJ_SetFloat@8 /* Set the FLOATOBJ */
1097 lea ecx, [ebp -4] /* Push pointer to local FLOATOBJ on the stack */
1099 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
1100 call _FLOATOBJ_Sub@8 /* Substract */
1102 mov esp, ebp /* Cleanup and return */
1107 /******************************************************************************
1110 * FLOATOBJ_SubLong(IN OUT PFLOATOBJ pf, IN LONG l);
1112 * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Sub
1114 _FLOATOBJ_SubLong@8:
1115 .global _FLOATOBJ_SubLong@8
1118 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
1120 mov eax, [ebp + PARAM2] /* Load l into eax */
1121 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
1122 push eax /* Push l on the stack */
1123 push ecx /* Push pointer to local FLOATOBJ on the stack */
1124 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
1126 lea ecx, [ebp -8] /* Push pointer to the local FLOATOBJ on the stack */
1128 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
1129 call _FLOATOBJ_Sub@8 /* Substract */
1131 mov esp, ebp /* Cleanup and return */
1136 /*******************************************************************************
1139 * FLOATOBJ_Neg(IN OUT PFLOATOBJ pf);
1143 .global _FLOATOBJ_Neg@4
1147 mov ecx, [esp + PARAM1] /* Load pf into ecx */
1148 neg dword ptr [ecx + lMant] /* Negate lMant1 */
1150 pop ebp /* Return */