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: win32ss/gdi/eng/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
85 /* extern const FLOATOBJ gef0; */
90 /* extern const FLOATOBJ gef1; */
93 .long HEX(40000000), HEX(00000002)
95 /* extern const FLOATOBJ gef16; */
98 .long HEX(40000000), HEX(00000006)
100 /******************************************************************************
103 * FLOATOBJ_SetFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
105 _FLOATOBJ_SetFloat@8:
106 PUBLIC _FLOATOBJ_SetFloat@8
110 mov ecx, [esp + PARAM2] /* Load the float into ecx */
111 mov eax, ecx /* Copy float to eax for later */
113 test ecx, HEX(7f800000) /* Check for zero exponent - 0 or denormal */
114 jz SetFloat0 /* If it's all zero, ... */
116 shl ecx, 7 /* Put the bits for the mantissa in place */
118 cdq /* Fill edx with the sign from the FLOATL in eax */
119 and ecx, HEX(7fffffff) /* Mask out invalid field in the mantissa */
121 shr eax, 23 /* Shift the exponent in eax in place */
122 or ecx, HEX(40000000) /* Set bit for 1 in the mantissa */
123 and eax, HEX(0ff) /* Mask out invalid fields in the exponent in eax */
125 xor ecx, edx /* Make use of the sign bit expanded to full edx */
127 sub eax, 125 /* Adjust exonent bias */
129 sub ecx, edx /* Substract -1 or add 1 if sign was set */
131 mov edx, [esp + PARAM1] /* Load pf into edx */
132 mov [edx + lMant], ecx /* Save back mantissa */
133 mov [edx + lExp], eax /* Save back exponent */
139 mov edx, [esp + PARAM1] /* Load pf into edx */
141 mov dword ptr [edx + lMant], 0 /* Set mantissa and exponent to 0 */
142 mov dword ptr [edx + lExp], 0
148 /*******************************************************************************
151 * FLOATOBJ_GetFloat(IN PFLOATOBJ pf);
154 _FLOATOBJ_GetFloat@4:
155 PUBLIC _FLOATOBJ_GetFloat@4
159 mov edx, [esp + PARAM1] /* Load pf into edx */
160 mov eax, [edx + lMant] /* Load mantissa into eax */
161 mov ecx, [edx + lExp] /* Load exponent into ecx */
163 cdq /* Calculate abs(mantissa) */
171 and ecx, HEX(0ff) /* Mask out invalid fields in the exponent */
172 and eax, HEX(3fffffff) /* Mask out invalid fields in mantissa */
174 shl ecx, 23 /* Shift exponent in place */
175 shr eax, 7 /* Shift mantissa in place */
177 and edx, HEX(80000000) /* Reduce edx to sign bit only */
179 or eax, ecx /* Set exponent in result */
180 or eax, edx /* Set sign bit in result */
189 /******************************************************************************
192 * FLOATOBJ_SetLong(OUT PFLOATOBJ pf, IN LONG l);
194 * Instead of using abs(l), which is 3 + 2 instructions, use a branch.
197 PUBLIC _FLOATOBJ_SetLong@8
201 mov eax, [esp + PARAM2] /* Load l into eax */
202 mov edx, [esp + PARAM1] /* Load pf into edx */
204 test eax, eax /* different handling for <0, =0 and >0 */
208 bsr ecx, eax /* Get number of most significant bit aka log2(l) */
209 mov [edx + lExp], ecx /* Safe log2(l) into exponent */
211 neg ecx /* Calculate necessary shift */
214 add dword ptr [edx + lExp], 2 /* Adjust exponent */
216 shl eax, cl /* Shift mantissa in place */
217 mov [edx + lMant], eax /* Save mantissa */
223 neg eax /* Get absolute value of l */
224 bsr ecx, eax /* Get number of most significant bit aka log2(l) */
225 neg eax /* Back to negative */
227 mov [edx + lExp], ecx /* Safe log2(-l) into exponent */
229 neg ecx /* Calculate necessary shift */
232 add dword ptr [edx + lExp], 2 /* Adjust exponent */
234 shl eax, cl /* Shift mantissa in place */
235 mov [edx + lMant], eax /* Save mantissa */
241 mov dword ptr [edx + lMant], 0 /* Set mantissa and exponent to 0 */
242 mov dword ptr [edx + lExp], 0
248 /*******************************************************************************
251 * FLOATOBJ_GetLong(IN PFLOATOBJ pf);
255 PUBLIC _FLOATOBJ_GetLong@4
259 mov edx, [ebp + PARAM1] /* Load pf into edx */
260 mov ecx, 32 /* Load (32 - lExp) into ecx */
261 sub ecx, [edx + lExp]
262 jle short GetLong2 /* Check for Overflow */
264 mov eax, [edx + lMant] /* Load mantissa into eax */
265 sar eax, cl /* Signed shift mantissa according to exponent */
271 xor eax, eax /* Overflow, return 0 */
276 /******************************************************************************
279 * FLOATOBJ_Equal(IN PFLOATOBJ pf1, IN PFLOATOBJ pf2);
282 PUBLIC _FLOATOBJ_Equal@8
286 mov ecx, [esp + PARAM1] /* Load pf1 into ecx */
287 mov eax, [esp + PARAM2] /* Load pf2 into ecx */
289 mov edx, [ecx + lExp] /* Get float1 in ecx, edx */
290 mov ecx, [ecx + lMant]
292 sub edx, [eax + lExp] /* Calculate diference to float2 */
293 sub ecx, [eax + lMant]
295 or edx, ecx /* Combine */
297 mov eax, 0 /* Set eax if combination is 0 */
304 /******************************************************************************
307 * FLOATOBJ_EqualLong(IN PFLOATOBJ pf, IN LONG l);
309 _FLOATOBJ_EqualLong@8:
310 PUBLIC _FLOATOBJ_EqualLong@8
314 mov eax, [esp + PARAM1] /* Load pf into eax */
315 mov ecx, 32 /* Load (32 - lExp) into ecx */
316 sub ecx, [eax + lExp]
317 mov edx, [eax + lMant] /* Load mantissa into edx */
318 sar edx, cl /* Signed shift mantissa according to exponent */
319 shl edx, cl /* Shift the mantissa back */
320 cmp edx, [eax + lMant] /* Check whether bits were killed by shifting */
321 jnz EqualLongFalse /* We have truncated the mantissa, return 0 */
323 sar edx, cl /* Shift the mantissa again */
324 xor eax, eax /* Set return value ... */
325 cmp edx, [esp + PARAM2] /* TRUE if shifted mantissa equals the LONG */
332 xor eax, eax /* Return FALSE */
337 /******************************************************************************
340 * FLOATOBJ_GreaterThan(IN PFLOATOBJ pf, IN PFLOATOBJ pf1);
343 _FLOATOBJ_GreaterThan@8:
344 PUBLIC _FLOATOBJ_GreaterThan@8
348 mov eax, [ebp + PARAM1] /* Load pointer to efloat1 in eax */
349 mov edx, [ebp + PARAM2] /* Load pointer to efloat2 in edx */
351 mov ecx, [eax + lMant] /* Load mantissa1 in ecx */
352 mov edx, [edx + lMant] /* Load mantissa2 in edx */
354 sar ecx, 31 /* Calculate sign(lMant1) in ecx */
355 sar edx, 31 /* Calculate sign(lMant2) in edx */
357 cmp ecx, edx /* Branch if both have the same sign */
360 /* Mantissae have different sign */
361 mov eax, 0 /* Return (sign(lMant1) > sign(lMant2)) */
367 /* Mantissae have the same sign */
369 mov edx, [ebp + PARAM2] /* Reload pointer to float2 in edx */
370 test ecx, ecx /* Branch if sign is negative */
373 /* Both mantissae are positive or 0 */
375 or ecx, [edx + lMant] /* Branch if one mantissa is 0 */
378 /* Both mantissae are positive */
380 mov ecx, [eax + lExp] /* Branch if exponents are equal */
381 cmp ecx, [edx + lExp]
384 mov eax, 0 /* Return (lExp1 > lExp2) */
390 /* Exponents are equal or one mantissa is 0 */
392 mov ecx, [eax + lMant] /* Return (lMant1 > lMant2) */
393 cmp ecx, [edx + lMant]
400 /* Both mantissae are negative */
402 mov ecx, [eax + lExp] /* Branch if exponents are equal */
403 cmp ecx, [edx + lExp]
406 /* Both mantissae negative, exponents are different */
408 mov eax, 0 /* Return (lExp1 < lExp2) */
414 /* Both mantissae negative, exponents are equal */
416 mov ecx, [eax + lMant] /* Return (lMant1 < lMant2) */
417 cmp ecx, [edx + lMant]
425 /******************************************************************************
428 * FLOATOBJ_GreaterThanLong(IN OUT PFLOATOBJ pf, IN LONG l);
430 * Currently implemented as a wrapper around FLOATOBJ_SetLong and
431 * LOATOBJ_GreaterThan
433 _FLOATOBJ_GreaterThanLong@8:
434 PUBLIC _FLOATOBJ_GreaterThanLong@8
438 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
439 mov eax, [ebp + PARAM2] /* Load LONG into eax */
441 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
443 push eax /* Push LONG on the stack */
444 push ecx /* Push pointer to local FLOATOBJ on the stack */
445 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
447 lea ecx, [ebp -8] /* Push pointer to the local FLOATOBJ on the stack */
449 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
450 call _FLOATOBJ_GreaterThan@8 /* Compare */
452 mov esp, ebp /* Cleanup and return */
457 /******************************************************************************
460 * FLOATOBJ_LessThan(IN PFLOATOBJ pf, IN PFLOATOBJ pf1);
463 _FLOATOBJ_LessThan@8:
464 PUBLIC _FLOATOBJ_LessThan@8
468 mov eax, [ebp + PARAM1] /* Load pointer to floats in eax and edx */
469 mov edx, [ebp + PARAM2]
471 mov ecx, [eax + lMant] /* Load mantissae in ecx and edx */
472 mov edx, [edx + lMant]
474 sar ecx, 31 /* Calculate sign(lMant1) and sign(lMant2) */
477 cmp ecx, edx /* Branch if both have the same sign */
480 /* Mantissae have different sign */
482 mov eax, 0 /* Return (sign(lMant1) < sign(lMant2)) */
488 /* Mantissae have the same sign */
491 mov edx, [ebp + PARAM2] /* Reload pointer to float2 in edx */
493 test ecx, ecx /* Branch if sign is negative */
496 /* Both mantissae are positive or 0 */
498 or ecx, [edx + lMant] /* Branch if one mantissa is 0 */
501 /* Both mantissae are positive */
503 mov ecx, [eax + lExp] /* Branch if exponents are equal */
504 cmp ecx, [edx + lExp]
507 mov eax, 0 /* Return (lExp1 < lExp2) */
513 /* Exponents are equal or one mantissa is 0 */
515 mov ecx, [eax + lMant] /* Return (lMant1 < lMant2) */
516 cmp ecx, [edx + lMant]
523 /* Both mantissae are negative */
525 mov ecx, [eax + lExp] /* Branch if exponents are equal */
526 cmp ecx, [edx + lExp]
529 /* Both mantissae negative, exponents are different */
531 mov eax, 0 /* Return (lExp1 > lExp2) */
537 /* Both mantissae negative, exponents are equal */
539 mov ecx, [eax + lMant] /* Return (lMant1 > lMant2) */
540 cmp ecx, [edx + lMant]
547 /******************************************************************************
550 * FLOATOBJ_LessThanLong(IN OUT PFLOATOBJ pf, IN LONG l);
552 * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_LessThan
554 _FLOATOBJ_LessThanLong@8:
555 PUBLIC _FLOATOBJ_LessThanLong@8
559 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
560 mov eax, [ebp + PARAM2] /* Load LONG into eax */
562 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
563 push eax /* Push LONG on the stack */
564 push ecx /* Push pointer to local FLOATOBJ on the stack */
565 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
567 lea ecx, [ebp -8] /* Push pointer to the local FLOATOBJ on the stack */
569 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
570 call _FLOATOBJ_LessThan@8 /* Compare */
572 mov esp, ebp /* Cleanup and return */
578 /******************************************************************************
581 * FLOATOBJ_Mul(IN OUT PFLOATOBJ pf1, IN PFLOATOBJ pf2);
583 * (mant1 * 2^exp1) * (mant2 * 2^exp2) = (mant1 * mant2) * 2^(exp1 + exp2)
584 * or mant = mant1 * mant2 and exp = exp1 + exp2
585 * No special handling for 0, where mantissa is 0
588 PUBLIC _FLOATOBJ_Mul@8
592 mov edx, [esp + PARAM1] /* Load pf1 into edx */
593 mov ecx, [esp + PARAM2] /* Load pf2 into ecx */
594 mov eax, [ecx + lMant] /* Load mantissa2 into eax */
595 mov ecx, [ecx + lExp] /* Load exponent2 into ecx */
597 imul dword ptr [edx + lMant] /* Multiply eax with mantissa 1 */
599 test edx, edx /* Special handling for result < 0 */
602 shl edx, 2 /* Get new mantissa from bits 30 to 62 */
603 shr eax, 30 /* of edx:eax into edx */
606 mov edx, ecx /* Need ecx for the shift, safe exp2 to free edx */
607 mov ecx, 0 /* Check for highest bit */
609 shr eax, cl /* Normalize mantissa in eax */
613 lea edx, [edx + ecx -2] /* Normalize exponent in edx */
616 mov ecx, [esp + PARAM1] /* Load pf1 into ecx */
617 mov [ecx + lMant], eax /* Save back mantissa */
618 add [ecx + lExp], edx /* Save back exponent */
625 shl edx, 2 /* Get new mantissa from bits 30 to 62 */
626 shr eax, 30 /* of edx:eax into edx */
629 mov edx, ecx /* Need ecx for the shift, safe exp2 to free edx */
631 mov ecx, 0 /* Check for highest bit */
633 shr eax, cl /* Normalize mantissa in eax */
638 lea edx, [edx + ecx -2] /* Normalize exponent in edx */
639 or eax, HEX(80000000) /* Set sign bit */
641 mov ecx, [esp + PARAM1] /* Load pf1 into ecx */
642 mov [ecx + lMant], eax /* Save back mantissa */
643 add [ecx + lExp], edx /* Save back exponent */
649 mov ecx, [esp + PARAM1] /* Load pf1 into ecx */
650 mov [ecx + lMant], eax /* Store 0 in mantissa */
651 mov [ecx + lExp], eax /* Store 0 in exponent */
657 /******************************************************************************
660 * FLOATOBJ_MulFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
662 * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Mul
664 _FLOATOBJ_MulFloat@8:
665 PUBLIC _FLOATOBJ_MulFloat@8
669 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
670 mov eax, [ebp + PARAM2] /* Load f into eax */
671 lea ecx, [ebp -4] /* Load pointer to local FLOATOBJ into ecx */
672 push eax /* Push f on the stack */
673 push ecx /* Push pointer to local FLOATOBJ on the stack */
674 call _FLOATOBJ_SetFloat@8 /* Set the FLOATOBJ */
676 lea ecx, [ebp -4] /* Push pointer to local FLOATOBJ on the stack */
678 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
679 call _FLOATOBJ_Mul@8 /* Multiply */
681 mov esp, ebp /* Cleanup and return */
686 /******************************************************************************
689 * FLOATOBJ_MulLong(IN OUT PFLOATOBJ pf, IN LONG l);
691 * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Mul
694 PUBLIC _FLOATOBJ_MulLong@8
698 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
699 mov eax, [ebp + PARAM2] /* Load l into eax */
700 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
701 push eax /* Push l on the stack */
702 push ecx /* Push pointer to local FLOATOBJ on the stack */
703 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
705 lea ecx, [ebp -8] /* Push pointer to local FLOATOBJ on the stack */
707 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
708 call _FLOATOBJ_Mul@8 /* Multiply */
710 mov esp, ebp /* Cleanup and return */
715 /*******************************************************************************
718 * FLOATOBJ_Div(IN OUT PFLOATOBJ pf1, IN PFLOATOBJ pf2);
722 PUBLIC _FLOATOBJ_Div@8
727 mov eax, [ebp + PARAM2] /* Load lMant2 into eax */
728 mov eax, [eax + lMant]
730 cdq /* Calculate abs(lMant2) */
733 jz DivError /* Divide by zero error! */
735 mov ebx, edx /* Copy sign(lMant2) to ebx */
736 mov ecx, eax /* Copy abs(lMant2) to ecx */
738 mov eax, [ebp + PARAM1] /* Load lMant1 into eax */
739 mov eax, [eax + lMant]
741 cdq /* Calculate abs(lMant1) */
745 jz Div0 /* Dividend is 0? */
747 xor ebx, edx /* combine both signs in ebx */
749 mov edx, eax /* Prepare edx:eax for integer divide */
752 div ecx /* Do an unsigned divide */
754 xor ecx, ecx /* Adjust result */
755 test eax, HEX(80000000)
759 xor eax, ebx /* Correct the result's sign */
762 mov edx, [ebp + PARAM1] /* Load pf1 into edx */
763 mov [edx + lMant], eax /* Safe back the mantissa */
764 mov ebx, [ebp + PARAM2] /* Load pf2 into ebx */
765 sub ecx, [ebx + lExp] /* Calculate exponent offset */
767 add [edx + lExp], ecx /* Safe back exponent */
775 mov edx, [ebp + PARAM1] /* Load pf into edx */
776 mov [edx + lMant], eax /* Store 0 in mantissa */
777 mov [edx + lExp], eax /* Store 0 in exponent */
784 /******************************************************************************
787 * FLOATOBJ_DivFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
789 * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Div
791 _FLOATOBJ_DivFloat@8:
792 PUBLIC _FLOATOBJ_DivFloat@8
795 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
797 mov eax, [ebp + PARAM2] /* Load f into eax */
798 lea ecx, [ebp -4] /* Load pointer to local FLOATOBJ into ecx */
799 push eax /* Push f on the stack */
800 push ecx /* Push pointer to local FLOATOBJ on the stack */
801 call _FLOATOBJ_SetFloat@8 /* Set the FLOATOBJ */
803 lea ecx, [ebp -4] /* Push pointer to local FLOATOBJ on the stack */
805 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
806 call _FLOATOBJ_Div@8 /* Divide */
808 mov esp, ebp /* Cleanup and return */
813 /******************************************************************************
816 * FLOATOBJ_DivLong(IN OUT PFLOATOBJ pf, IN LONG l);
818 * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Div
821 PUBLIC _FLOATOBJ_DivLong@8
824 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
826 mov eax, [ebp + PARAM2] /* Load l into eax */
827 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
828 push eax /* Push l on the stack */
829 push ecx /* Push pointer to local FLOATOBJ on the stack */
830 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
832 lea ecx, [ebp -8] /* Push pointer to the local FLOATOBJ on the stack */
834 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
835 call _FLOATOBJ_Div@8 /* Divide */
837 mov esp, ebp /* Cleanup and return */
842 /*******************************************************************************
845 * FLOATOBJ_Add(IN OUT PFLOATOBJ pf1, IN PFLOATOBJ pf2);
849 PUBLIC _FLOATOBJ_Add@8
854 mov eax, [ebp + PARAM1] /* Load pointer to pf1 in eax */
855 mov ebx, [ebp + PARAM2] /* Load pointer to pf2 in ebx */
857 mov ecx, [eax + lExp] /* Load float1 in (eax,ecx) */
858 mov edx, [ebx + lExp]
859 mov eax, [eax + lMant] /* Load float2 in (ebx,edx) */
860 mov ebx, [ebx + lMant]
862 cmp ecx, edx /* Check which one has the bigger lExp */
865 sub ecx, edx /* Calculate lExp1 - lExp2 */
866 sar eax, 1 /* Shift both mantissae 1 bit right */
868 sar ebx, cl /* Shift lMant2 according to exponent difference */
870 add eax, ebx /* Add the manrissae */
873 cdq /* Calculate abs(mantissa) */
877 bsr ecx, eax /* Find most significant bit */
878 neg ecx /* and calculate needed normalize shift */
883 xor eax, edx /* Go back to original sign */
886 mov edx, [ebp + PARAM1] /* Reload pointer to float1 */
890 mov dword ptr [edx + lMant], eax /* Safe mantissa */
891 sub [edx + lExp], ecx /* Adjust exponent */
897 sub edx, ecx /* Calculate lExp2 - lExp1 and put it into ecx */
900 sar ebx, 1 /* Shift both mantissae 1 bit right */
902 sar eax, cl /* Shift lMant2 according to exponent difference */
904 add eax, ebx /* Add the manrissae */
907 mov ebx, [ebp + PARAM1] /* Reload pointer to float1 */
908 add [ebx + lExp], ecx /* Adjust exponent part 1 */
910 cdq /* Calculate abs(mantissa) */
914 bsr ecx, eax /* Find most significant bit */
915 neg ecx /* and calculate needed normalize shift */
920 xor eax, edx /* Go back to original sign */
923 mov dword ptr [ebx + lMant], eax /* Safe mantissa and adjust exponent */
924 sub [ebx + lExp], ecx
931 /* Mantissa is 0, so float to (0,0) */
932 mov eax, [ebp + PARAM1]
934 mov dword ptr [eax + lMant], 0
935 mov dword ptr [eax + lExp], 0
940 /******************************************************************************
943 * FLOATOBJ_AddFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
945 * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Add
947 _FLOATOBJ_AddFloat@8:
948 PUBLIC _FLOATOBJ_AddFloat@8
951 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
953 mov eax, [ebp + PARAM2] /* Load f into eax */
954 lea ecx, [ebp -4] /* Load pointer to local FLOATOBJ into ecx */
955 push eax /* Push f on the stack */
956 push ecx /* Push pointer to local FLOATOBJ on the stack */
957 call _FLOATOBJ_SetFloat@8 /* Set the FLOATOBJ */
959 lea ecx, [ebp -4] /* Push pointer to local FLOATOBJ on the stack */
961 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
962 call _FLOATOBJ_Add@8 /* Add */
964 mov esp, ebp /* Cleanup and return */
969 /******************************************************************************
972 * FLOATOBJ_AddLong(IN OUT PFLOATOBJ pf, IN LONG l);
974 * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Add
977 PUBLIC _FLOATOBJ_AddLong@8
980 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
982 mov eax, [ebp + PARAM2] /* Load l into eax */
983 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
984 push eax /* Push l on the stack */
985 push ecx /* Push pointer to local FLOATOBJ on the stack */
986 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
988 lea ecx, [ebp -8] /* Push pointer to the local FLOATOBJ on the stack */
990 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
991 call _FLOATOBJ_Add@8 /* Add */
993 mov esp, ebp /* Cleanup and return */
998 /*******************************************************************************
1001 * FLOATOBJ_Sub(IN OUT PFLOATOBJ pf, IN PFLOATOBJ pf1);
1005 PUBLIC _FLOATOBJ_Sub@8
1010 mov eax, [ebp + PARAM1] /* Load pointer to floats in eax and ebx */
1011 mov ebx, [ebp + PARAM2]
1013 mov ecx, [eax + lExp] /* Load float1 in (eax,ecx) and float2 in (ebx,edx) */
1014 mov edx, [ebx + lExp]
1015 mov eax, [eax + lMant]
1016 mov ebx, [ebx + lMant]
1018 cmp ecx, edx /* Check which one has the bigger lExp */
1021 sub ecx, edx /* Calculate lExp1 - lExp2 */
1022 sar eax, 1 /* Shift both mantissae 1 bit right */
1024 sar ebx, cl /* Shift lMant2 according to exponent difference */
1026 sub eax, ebx /* Substract the manrissae */
1029 cdq /* Calculate abs(mantissa) */
1033 bsr ecx, eax /* Find most significant bit */
1034 neg ecx /* and calculate needed normalize shift */
1039 xor eax, edx /* Go back to original sign */
1042 mov edx, [ebp + PARAM1] /* Reload pointer to float1 */
1046 mov dword ptr [edx + lMant], eax /* Safe mantissa and adjust exponent */
1047 sub [edx + lExp], ecx
1053 sub edx, ecx /* Calculate lExp2 - lExp1 and put it into ecx */
1056 sar ebx, 1 /* Shift both mantissae 1 bit right */
1058 sar eax, cl /* Shift lMant2 according to exponent difference */
1060 sub eax, ebx /* Substract the manrissae */
1063 mov ebx, [ebp + PARAM1] /* Reload pointer to float1 */
1064 add [ebx + lExp], ecx /* Adjust exponent part 1 */
1066 cdq /* Calculate abs(mantissa) */
1070 bsr ecx, eax /* Find most significant bit */
1071 neg ecx /* and calculate needed normalize shift */
1076 xor eax, edx /* Go back to original sign */
1079 mov dword ptr [ebx + lMant], eax /* Safe mantissa */
1080 sub [ebx + lExp], ecx /* Adjust exponent */
1082 pop ebx /* Return */
1087 /* Mantissa is 0, so float to (0,0) */
1088 mov eax, [ebp + PARAM1]
1090 mov dword ptr [eax + lMant], 0
1091 mov dword ptr [eax + lExp], 0
1095 /******************************************************************************
1098 * FLOATOBJ_SubFloat(IN OUT PFLOATOBJ pf, IN FLOATL f);
1100 * Currently implemented as a wrapper around FLOATOBJ_SetFloat and FLOATOBJ_Sub
1102 _FLOATOBJ_SubFloat@8:
1103 PUBLIC _FLOATOBJ_SubFloat@8
1106 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
1108 mov eax, [ebp + PARAM2] /* Load f into eax */
1109 lea ecx, [ebp -4] /* Load pointer to local FLOATOBJ into ecx */
1110 push eax /* Push f on the stack */
1111 push ecx /* Push pointer to local FLOATOBJ on the stack */
1112 call _FLOATOBJ_SetFloat@8 /* Set the FLOATOBJ */
1114 lea ecx, [ebp -4] /* Push pointer to local FLOATOBJ on the stack */
1116 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
1117 call _FLOATOBJ_Sub@8 /* Substract */
1119 mov esp, ebp /* Cleanup and return */
1124 /******************************************************************************
1127 * FLOATOBJ_SubLong(IN OUT PFLOATOBJ pf, IN LONG l);
1129 * Currently implemented as a wrapper around FLOATOBJ_SetLong and FLOATOBJ_Sub
1131 _FLOATOBJ_SubLong@8:
1132 PUBLIC _FLOATOBJ_SubLong@8
1135 sub esp, 8 /* Make room for a FLOATOBJ on the stack */
1137 mov eax, [ebp + PARAM2] /* Load l into eax */
1138 lea ecx, [ebp -8] /* Load pointer to local FLOATOBJ into ecx */
1139 push eax /* Push l on the stack */
1140 push ecx /* Push pointer to local FLOATOBJ on the stack */
1141 call _FLOATOBJ_SetLong@8 /* Set the local FLOATOBJ */
1143 lea ecx, [ebp -8] /* Push pointer to the local FLOATOBJ on the stack */
1145 push [ebp + PARAM1] /* Push the FLOATOBJ param on the stack */
1146 call _FLOATOBJ_Sub@8 /* Substract */
1148 mov esp, ebp /* Cleanup and return */
1153 /*******************************************************************************
1156 * FLOATOBJ_Neg(IN OUT PFLOATOBJ pf);
1160 PUBLIC _FLOATOBJ_Neg@4
1164 mov ecx, [esp + PARAM1] /* Load pf into ecx */
1165 neg dword ptr [ecx + lMant] /* Negate lMant1 */
1167 pop ebp /* Return */