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
13 /*******************************************************************************
14 * IEEE 754-1985 single precision floating point
16 * | 31 | 30...23 | 22...0 |
17 * |sign| exponent | fraction |
19 * mantissa = 1 + (fraction / 2^23)
20 * f = (-1)^sign * mantissa * 2 ^ (exponent - bias)
23 *******************************************************************************
24 * win32k x86 floating point emulation
32 * f = (lMant / 0x40000000) * 2 ^ (lExp - 2)
33 * = lMant * 2 ^ (lExp - 32)
35 *******************************************************************************
38 * - shld is slow (4 cycles) and not pairable, mov + shl is faster
39 * - esp is used, because it's available earlier
40 * - bsr is very slow on old cpus (up to 72 cycles on a p1) while being much
41 * faster on modern cpus (2-11 cycles). Workarounds using branch trees or
42 * table lookups are of no use nowadays.
43 *******************************************************************************
44 * Compatibility notes:
45 * - There are issues with very large size values near integer overflow.
46 * Floating point values are behaving different there. This behavior isn't
47 * simulated yet. Difference is < 10^-5 %
48 * - The result of a multiplication can differ from Windows result in the
49 * least significant bit, that is a difference of 1 / 2^30 or ~10^-9
50 *******************************************************************************
51 * Implementation status:
53 * FLOATOBJ_SetFloat - implemented, tested
54 * FLOATOBJ_SetLong - implemented, tested
55 * FLOATOBJ_GetFloat - implemented, tested
56 * FLOATOBJ_GetLong - implemented, tested
57 * FLOATOBJ_Equal - implemented, tested
58 * FLOATOBJ_EqualLong - implemented
59 * FLOATOBJ_GreaterThan - implemented
60 * FLOATOBJ_GreaterThanLong - wrapper
61 * FLOATOBJ_LessThan - implemented
62 * FLOATOBJ_LessThanLong - wrapper
63 * FLOATOBJ_Neg - implemented
64 * FLOATOBJ_Mul - implemented, tested, optimized
65 * FLOATOBJ_MulFloat - wrapper
66 * FLOATOBJ_MulLong - wrapper, could really need optimization
67 * FLOATOBJ_Div - implemented
68 * FLOATOBJ_DivFloat - wrapper
69 * FLOATOBJ_DivLong - wrapper
70 * FLOATOBJ_Add - implemented, tested
71 * FLOATOBJ_AddFloat - wrapper
72 * FLOATOBJ_AddLong - wrapper
73 * FLOATOBJ_Sub - implemented, tested
74 * FLOATOBJ_SubFloat - wrapper
75 * FLOATOBJ_SubLong - wrapper
84 /******************************************************************************
87 * FLOATOBJ_SetFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
90 PUBLIC _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, HEX(7f800000) /* 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, HEX(7fffffff) /* Mask out invalid field in the mantissa */
105 shr eax, 23 /* Shift the exponent in eax in place */
106 or ecx, HEX(40000000) /* Set bit for 1 in the mantissa */
107 and eax, HEX(0ff) /* 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 PUBLIC _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, HEX(0ff) /* Mask out invalid fields in the exponent */
156 and eax, HEX(3fffffff) /* 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, HEX(80000000) /* 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 PUBLIC _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 PUBLIC _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 PUBLIC _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 PUBLIC _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 PUBLIC _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 PUBLIC _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 PUBLIC _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 PUBLIC _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 PUBLIC _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, HEX(80000000) /* 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 PUBLIC _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 PUBLIC _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 PUBLIC _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 */
739 test eax, HEX(80000000)
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 PUBLIC _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 PUBLIC _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 mov esp, ebp /* Cleanup and return */
826 /*******************************************************************************
829 * FLOATOBJ_Add(IN OUT PFLOATOBJ pf1, IN PFLOATOBJ pf2);
833 PUBLIC _FLOATOBJ_Add@8
838 mov eax, [ebp + PARAM1] /* Load pointer to pf1 in eax */
839 mov ebx, [ebp + PARAM2] /* Load pointer to pf2 in ebx */
841 mov ecx, [eax + lExp] /* Load float1 in (eax,ecx) */
842 mov edx, [ebx + lExp]
843 mov eax, [eax + lMant] /* Load float2 in (ebx,edx) */
844 mov ebx, [ebx + lMant]
846 cmp ecx, edx /* Check which one has the bigger lExp */
849 sub ecx, edx /* Calculate lExp1 - lExp2 */
850 sar eax, 1 /* Shift both mantissae 1 bit right */
852 sar ebx, cl /* Shift lMant2 according to exponent difference */
854 add eax, ebx /* Add the manrissae */
857 cdq /* Calculate abs(mantissa) */
861 bsr ecx, eax /* Find most significant bit */
862 neg ecx /* and calculate needed normalize shift */
867 xor eax, edx /* Go back to original sign */
870 mov edx, [ebp + PARAM1] /* Reload pointer to float1 */
874 mov dword ptr [edx + lMant], eax /* Safe mantissa */
875 sub [edx + lExp], ecx /* Adjust exponent */
881 sub edx, ecx /* Calculate lExp2 - lExp1 and put it into ecx */
884 sar ebx, 1 /* Shift both mantissae 1 bit right */
886 sar eax, cl /* Shift lMant2 according to exponent difference */
888 add eax, ebx /* Add the manrissae */
891 mov ebx, [ebp + PARAM1] /* Reload pointer to float1 */
892 add [ebx + lExp], ecx /* Adjust exponent part 1 */
894 cdq /* Calculate abs(mantissa) */
898 bsr ecx, eax /* Find most significant bit */
899 neg ecx /* and calculate needed normalize shift */
904 xor eax, edx /* Go back to original sign */
907 mov dword ptr [ebx + lMant], eax /* Safe mantissa and adjust exponent */
908 sub [ebx + lExp], ecx
915 /* Mantissa is 0, so float to (0,0) */
916 mov eax, [ebp + PARAM1]
918 mov dword ptr [eax + lMant], 0
919 mov dword ptr [eax + lExp], 0
924 /******************************************************************************
927 * FLOATOBJ_AddFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
929 * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Add
931 _FLOATOBJ_AddFloat@8:
932 PUBLIC _FLOATOBJ_AddFloat@8
935 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
937 mov eax, [ebp + PARAM2] /* Load f into eax */
938 lea ecx, [ebp -4] /* Load pointer to local FLOATOBJ into ecx */
939 push eax /* Push f on the stack */
940 push ecx /* Push pointer to local FLOATOBJ on the stack */
941 call _FLOATOBJ_SetFloat@8 /* Set the FLOATOBJ */
943 lea ecx, [ebp -4] /* Push pointer to local FLOATOBJ on the stack */
945 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
946 call _FLOATOBJ_Add@8 /* Add */
948 mov esp, ebp /* Cleanup and return */
953 /******************************************************************************
956 * FLOATOBJ_AddLong(IN OUT PFLOATOBJ pf, IN LONG l);
958 * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Add
961 PUBLIC _FLOATOBJ_AddLong@8
964 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
966 mov eax, [ebp + PARAM2] /* Load l into eax */
967 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
968 push eax /* Push l on the stack */
969 push ecx /* Push pointer to local FLOATOBJ on the stack */
970 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
972 lea ecx, [ebp -8] /* Push pointer to the local FLOATOBJ on the stack */
974 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
975 call _FLOATOBJ_Add@8 /* Add */
977 mov esp, ebp /* Cleanup and return */
982 /*******************************************************************************
985 * FLOATOBJ_Sub(IN OUT PFLOATOBJ pf, IN PFLOATOBJ pf1);
989 PUBLIC _FLOATOBJ_Sub@8
994 mov eax, [ebp + PARAM1] /* Load pointer to floats in eax and ebx */
995 mov ebx, [ebp + PARAM2]
997 mov ecx, [eax + lExp] /* Load float1 in (eax,ecx) and float2 in (ebx,edx) */
998 mov edx, [ebx + lExp]
999 mov eax, [eax + lMant]
1000 mov ebx, [ebx + lMant]
1002 cmp ecx, edx /* Check which one has the bigger lExp */
1005 sub ecx, edx /* Calculate lExp1 - lExp2 */
1006 sar eax, 1 /* Shift both mantissae 1 bit right */
1008 sar ebx, cl /* Shift lMant2 according to exponent difference */
1010 sub eax, ebx /* Substract the manrissae */
1013 cdq /* Calculate abs(mantissa) */
1017 bsr ecx, eax /* Find most significant bit */
1018 neg ecx /* and calculate needed normalize shift */
1023 xor eax, edx /* Go back to original sign */
1026 mov edx, [ebp + PARAM1] /* Reload pointer to float1 */
1030 mov dword ptr [edx + lMant], eax /* Safe mantissa and adjust exponent */
1031 sub [edx + lExp], ecx
1037 sub edx, ecx /* Calculate lExp2 - lExp1 and put it into ecx */
1040 sar ebx, 1 /* Shift both mantissae 1 bit right */
1042 sar eax, cl /* Shift lMant2 according to exponent difference */
1044 sub eax, ebx /* Substract the manrissae */
1047 mov ebx, [ebp + PARAM1] /* Reload pointer to float1 */
1048 add [ebx + lExp], ecx /* Adjust exponent part 1 */
1050 cdq /* Calculate abs(mantissa) */
1054 bsr ecx, eax /* Find most significant bit */
1055 neg ecx /* and calculate needed normalize shift */
1060 xor eax, edx /* Go back to original sign */
1063 mov dword ptr [ebx + lMant], eax /* Safe mantissa */
1064 sub [ebx + lExp], ecx /* Adjust exponent */
1066 pop ebx /* Return */
1071 /* Mantissa is 0, so float to (0,0) */
1072 mov eax, [ebp + PARAM1]
1074 mov dword ptr [eax + lMant], 0
1075 mov dword ptr [eax + lExp], 0
1079 /******************************************************************************
1082 * FLOATOBJ_SubFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
1084 * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Sub
1086 _FLOATOBJ_SubFloat@8:
1087 PUBLIC _FLOATOBJ_SubFloat@8
1090 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
1092 mov eax, [ebp + PARAM2] /* Load f into eax */
1093 lea ecx, [ebp -4] /* Load pointer to local FLOATOBJ into ecx */
1094 push eax /* Push f on the stack */
1095 push ecx /* Push pointer to local FLOATOBJ on the stack */
1096 call _FLOATOBJ_SetFloat@8 /* Set the FLOATOBJ */
1098 lea ecx, [ebp -4] /* Push pointer to local FLOATOBJ on the stack */
1100 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
1101 call _FLOATOBJ_Sub@8 /* Substract */
1103 mov esp, ebp /* Cleanup and return */
1108 /******************************************************************************
1111 * FLOATOBJ_SubLong(IN OUT PFLOATOBJ pf, IN LONG l);
1113 * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Sub
1115 _FLOATOBJ_SubLong@8:
1116 PUBLIC _FLOATOBJ_SubLong@8
1119 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
1121 mov eax, [ebp + PARAM2] /* Load l into eax */
1122 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
1123 push eax /* Push l on the stack */
1124 push ecx /* Push pointer to local FLOATOBJ on the stack */
1125 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
1127 lea ecx, [ebp -8] /* Push pointer to the local FLOATOBJ on the stack */
1129 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
1130 call _FLOATOBJ_Sub@8 /* Substract */
1132 mov esp, ebp /* Cleanup and return */
1137 /*******************************************************************************
1140 * FLOATOBJ_Neg(IN OUT PFLOATOBJ pf);
1144 PUBLIC _FLOATOBJ_Neg@4
1148 mov ecx, [esp + PARAM1] /* Load pf into ecx */
1149 neg dword ptr [ecx + lMant] /* Negate lMant1 */
1151 pop ebp /* Return */