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