1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/euser/epoc/win32/uc_realx.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,3281 @@
1.4 +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\euser\epoc\win32\uc_realx.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include "u32std.h"
1.22 +#include <e32math.h>
1.23 +
1.24 +#pragma warning (disable : 4100) // unreferenced formal parameter
1.25 +#pragma warning (disable : 4700) // local variable 'this' used without
1.26 + // having been initialised
1.27 +#pragma warning ( disable : 4414 ) // short jump to function converted to near
1.28 +
1.29 +
1.30 +#if defined(__VC32__) && (_MSC_VER==1100) // untested on MSVC++ > 5.0
1.31 +// Workaround for MSVC++ 5.0 bug; MSVC incorrectly fixes up conditional jumps
1.32 +// when the destination is a C++ function.
1.33 +#define _ASM_j(cond,dest) _asm jn##cond short $+11 _asm jmp dest
1.34 +#define _ASM_jn(cond,dest) _asm j##cond short $+11 _asm jmp dest
1.35 +#pragma optimize( "", off ) // stop MSVC murdering the code
1.36 +#else
1.37 +#define _ASM_j(cond,dest) _asm j##cond dest
1.38 +#define _ASM_jn(cond,dest) _asm jn##cond dest
1.39 +#endif
1.40 +
1.41 +//
1.42 +// 64-bit precision floating point routines
1.43 +// Register storage format:
1.44 +// edx:ebx=64 bit normalised mantissa
1.45 +// ecx bits 16-31 = 16-bit exponent, biased by 7FFF
1.46 +// ecx bit 0 = sign
1.47 +// ecx bit 8 = rounded-down flag
1.48 +// ecx bit 9 = rounded-up flag
1.49 +//
1.50 +// Memory storage format:
1.51 +// 3 doublewords per number
1.52 +// Low 32 bits of mantissa at [addr]
1.53 +// High 32 bits of mantissa at [addr+4]
1.54 +// Exponent/flags/sign at [addr+8]
1.55 +//
1.56 +
1.57 +LOCAL_C void TRealXPanic(TInt aErr)
1.58 + {
1.59 + User::Panic(_L("MATHX"),aErr);
1.60 + }
1.61 +
1.62 +__NAKED__ LOCAL_C void TRealXPanicEax(void)
1.63 + {
1.64 + _asm push eax
1.65 + _asm call TRealXPanic
1.66 + }
1.67 +
1.68 +LOCAL_C __NAKED__ void TRealXRealIndefinite(void)
1.69 + {
1.70 + // return 'real indefinite' NaN in ecx,edx:ebx
1.71 + _asm mov ecx, 0xFFFF0001 // exponent=FFFF, sign negative
1.72 + _asm mov edx, 0xC0000000 // mantissa=C0000000 00000000
1.73 + _asm xor ebx, ebx
1.74 + _asm mov eax, -6 // return KErrArgument
1.75 + _asm ret
1.76 + }
1.77 +
1.78 +LOCAL_C __NAKED__ void TRealXBinOpNaN(void)
1.79 + {
1.80 + // generic routine to process NaN's in binary operations
1.81 + // destination operand in ecx,edx:eax
1.82 + // source operand at [esi]
1.83 +
1.84 + _asm mov eax, [esi+8] // source operand into eax,edi:ebp
1.85 + _asm mov edi, [esi+4]
1.86 + _asm mov ebp, [esi]
1.87 + _asm cmp ecx, 0xFFFF0000 // check if dest is a NaN
1.88 + _asm jb short TRealXBinOpNaN1 // if not, swap them
1.89 + _asm cmp edx, 0x80000000
1.90 + _asm jne short TRealXBinOpNaN2
1.91 + _asm test ebx, ebx
1.92 + _asm jne short TRealXBinOpNaN2
1.93 + TRealXBinOpNaN1: // swap the operands
1.94 + _asm xchg ecx, eax
1.95 + _asm xchg edx, edi
1.96 + _asm xchg ebx, ebp
1.97 + TRealXBinOpNaN2:
1.98 + _asm cmp eax, 0xFFFF0000 // check if both operands are NaNs
1.99 + _asm jb short TRealXBinOpNaN4 // if not, ignore non-NaN operand
1.100 + _asm cmp edi, 0x80000000
1.101 + _asm jne short TRealXBinOpNaN3
1.102 + _asm test ebp, ebp
1.103 + _asm je short TRealXBinOpNaN4
1.104 + TRealXBinOpNaN3: // if both operands are NaN's, compare significands
1.105 + _asm cmp edx, edi
1.106 + _asm ja short TRealXBinOpNaN4
1.107 + _asm jb short TRealXBinOpNaN5
1.108 + _asm cmp ebx, ebp
1.109 + _asm jae short TRealXBinOpNaN4
1.110 + TRealXBinOpNaN5: // come here if dest is smaller - copy source to dest
1.111 + _asm mov ecx, eax
1.112 + _asm mov edx, edi
1.113 + _asm mov ebx, ebp
1.114 + TRealXBinOpNaN4: // NaN with larger significand is in ecx,edx:ebx
1.115 + _asm or edx, 0x40000000 // convert an SNaN to a QNaN
1.116 + _asm mov eax, -6 // return KErrArgument
1.117 + _asm ret
1.118 + }
1.119 +
1.120 +// Add TRealX at [esi] + ecx,edx:ebx
1.121 +// Result in ecx,edx:ebx
1.122 +// Error code in eax
1.123 +// Note: +0 + +0 = +0, -0 + -0 = -0, +0 + -0 = -0 + +0 = +0,
1.124 +// +/-0 + X = X + +/-0 = X, X + -X = -X + X = +0
1.125 +__NAKED__ LOCAL_C void TRealXAdd()
1.126 + {
1.127 + _asm xor ch, ch // clear rounding flags
1.128 + _asm cmp ecx, 0xFFFF0000 // check if dest=NaN or infinity
1.129 + _asm jnc addfpsd // branch if it is
1.130 + _asm mov eax, [esi+8] // fetch sign/exponent of source
1.131 + _asm cmp eax, 0xFFFF0000 // check if source=NaN or infinity
1.132 + _asm jnc addfpss // branch if it is
1.133 + _asm cmp eax, 0x10000 // check if source=0
1.134 + _asm jc addfp0s // branch if it is
1.135 + _asm cmp ecx, 0x10000 // check if dest=0
1.136 + _asm jc addfp0d // branch if it is
1.137 + _asm and cl, 1 // clear bits 1-7 of ecx
1.138 + _asm and al, 1 // clear bits 1-7 of eax
1.139 + _asm mov ch, cl
1.140 + _asm xor ch, al // xor of signs into ch bit 0
1.141 + _asm add ch, ch
1.142 + _asm or cl, ch // and into cl bit 1
1.143 + _asm or al, ch // and al bit 1
1.144 + _asm xor ch, ch // clear rounding flags
1.145 + _asm mov ebp, [esi] // fetch source mantissa 0-31
1.146 + _asm mov edi, [esi+4] // fetch source mantissa 32-63
1.147 + _asm ror ecx, 16 // dest exponent into cx
1.148 + _asm ror eax, 16 // source exponent into ax
1.149 + _asm push ecx // push dest exponent/sign
1.150 + _asm sub cx, ax // cx = dest exponent - source exponent
1.151 + _asm je short addfp3b // if equal, no shifting required
1.152 + _asm ja short addfp1 // branch if dest exponent >= source exponent
1.153 + _asm xchg ebx, ebp // make sure edi:ebp contains the mantissa to be shifted
1.154 + _asm xchg edx, edi //
1.155 + _asm xchg eax, [esp] // and larger exponent and corresponding sign is on the stack
1.156 + _asm neg cx // make cx positive = number of right shifts needed
1.157 + addfp1:
1.158 + _asm cmp cx, 64 // if more than 64 shifts needed
1.159 + _asm ja addfp2 // branch to output larger number
1.160 + _asm jb addfp3 // branch if <64 shifts
1.161 + _asm mov eax, edi // exactly 64 shifts needed - rounding word=mant high
1.162 + _asm test ebp, ebp // check bits lost
1.163 + _asm jz short addfp3a
1.164 + _asm or ch, 1 // if not all zero, set rounded-down flag
1.165 + addfp3a:
1.166 + _asm xor edi, edi // clear edx:ebx
1.167 + _asm xor ebp, ebp
1.168 + _asm jmp short addfp5 // finished shifting
1.169 + addfp3b: // exponents equal
1.170 + _asm xor eax, eax // set rounding word=0
1.171 + _asm jmp short addfp5
1.172 + addfp3:
1.173 + _asm cmp cl, 32 // 32 or more shifts needed ?
1.174 + _asm jb short addfp4 // skip if <32
1.175 + _asm mov eax, ebp // rounding word=mant low
1.176 + _asm mov ebp, edi // mant low=mant high
1.177 + _asm xor edi, edi // mant high=0
1.178 + _asm sub cl, 32 // reduce count by 32
1.179 + _asm jz short addfp5 // if now zero, finished shifting
1.180 + _asm shrd edi, eax, cl // shift ebp:eax:edi right by cl bits
1.181 + _asm shrd eax, ebp, cl //
1.182 + _asm shr ebp, cl //
1.183 + _asm test edi, edi // check bits lost in shift
1.184 + _asm jz short addfp5 // if all zero, finished
1.185 + _asm or ch, 1 // else set rounded-down flag
1.186 + _asm xor edi, edi // clear edx again
1.187 + _asm jmp short addfp5 // finished shifting
1.188 + addfp4: // <32 shifts needed now
1.189 + _asm xor eax, eax // clear rounding word initially
1.190 + _asm shrd eax, ebp, cl // shift edi:ebp:eax right by cl bits
1.191 + _asm shrd ebp, edi, cl //
1.192 + _asm shr edi, cl //
1.193 +
1.194 + addfp5:
1.195 + _asm mov [esp+3], ch // rounding flag into ch image on stack
1.196 + _asm pop ecx // recover sign and exponent into ecx, with rounding flag
1.197 + _asm ror ecx, 16 // into normal position
1.198 + _asm test cl, 2 // addition or subtraction needed ?
1.199 + _asm jnz short subfp1 // branch if subtraction
1.200 + _asm add ebx,ebp // addition required - add mantissas
1.201 + _asm adc edx,edi //
1.202 + _asm jnc short roundfp // branch if no carry
1.203 + _asm rcr edx,1 // shift carry right into mantissa
1.204 + _asm rcr ebx,1 //
1.205 + _asm rcr eax,1 // and into rounding word
1.206 + _asm jnc short addfp5a
1.207 + _asm or ch, 1 // if 1 shifted out, set rounded-down flag
1.208 + addfp5a:
1.209 + _asm add ecx, 0x10000 // and increment exponent
1.210 +
1.211 + // perform rounding based on rounding word in eax and rounding flag in ch
1.212 + roundfp:
1.213 + _asm cmp eax, 0x80000000
1.214 + _asm jc roundfp0 // if rounding word<80000000, round down
1.215 + _asm ja roundfp1 // if >80000000, round up
1.216 + _asm test ch, 1
1.217 + _asm jnz short roundfp1 // if rounded-down flag set, round up
1.218 + _asm test ch, 2
1.219 + _asm jnz short roundfp0 // if rounded-up flag set, round down
1.220 + _asm test bl, 1 // else test mantissa lsb
1.221 + _asm jz short roundfp0 // round down if 0, up if 1 (round to even)
1.222 + roundfp1: // Come here to round up
1.223 + _asm add ebx, 1 // increment mantissa
1.224 + _asm adc edx,0 //
1.225 + _asm jnc roundfp1a // if no carry OK
1.226 + _asm rcr edx,1 // else shift carry into mantissa (edx:ebx=0 here)
1.227 + _asm add ecx, 0x10000 // and increment exponent
1.228 + roundfp1a:
1.229 + _asm cmp ecx, 0xFFFF0000 // check for overflow
1.230 + _asm jae short addfpovfw // jump if overflow
1.231 + _asm mov ch, 2 // else set rounded-up flag
1.232 + _asm xor eax, eax // return KErrNone
1.233 + _asm ret
1.234 +
1.235 + roundfp0: // Come here to round down
1.236 + _asm cmp ecx, 0xFFFF0000 // check for overflow
1.237 + _asm jae short addfpovfw // jump if overflow
1.238 + _asm test eax, eax // else check if rounding word zero
1.239 + _asm jz short roundfp0a // if so, leave rounding flags as they are
1.240 + _asm mov ch, 1 // else set rounded-down flag
1.241 + roundfp0a:
1.242 + _asm xor eax, eax // return KErrNone
1.243 + _asm ret // exit
1.244 +
1.245 + addfpovfw: // Come here if overflow occurs
1.246 + _asm xor ch, ch // clear rounding flags, exponent=FFFF
1.247 + _asm xor ebx, ebx
1.248 + _asm mov edx, 0x80000000 // mantissa=80000000 00000000 for infinity
1.249 + _asm mov eax, -9 // return KErrOverflow
1.250 + _asm ret
1.251 +
1.252 + // exponents differ by more than 64 - output larger number
1.253 + addfp2:
1.254 + _asm pop ecx // recover exponent and sign
1.255 + _asm ror ecx, 16 // into normal position
1.256 + _asm or ch, 1 // set rounded-down flag
1.257 + _asm test cl, 2 // check if signs the same
1.258 + _asm jz addfp2a
1.259 + _asm xor ch, 3 // if not, set rounded-up flag
1.260 + addfp2a:
1.261 + _asm xor eax, eax // return KErrNone
1.262 + _asm ret
1.263 +
1.264 + // signs differ, so must subtract mantissas
1.265 + subfp1:
1.266 + _asm add ch, ch // if rounded-down flag set, change it to rounded-up
1.267 + _asm neg eax // subtract rounding word from 0
1.268 + _asm sbb ebx, ebp // and subtract mantissas with borrow
1.269 + _asm sbb edx, edi //
1.270 + _asm jnc short subfp2 // if no borrow, sign is correct
1.271 + _asm xor cl, 1 // else change sign of result
1.272 + _asm shr ch, 1 // change rounding back to rounded-down
1.273 + _asm not eax // negate rounding word
1.274 + _asm not ebx // and mantissa
1.275 + _asm not edx //
1.276 + _asm add eax,1 // two's complement negation
1.277 + _asm adc ebx,0 //
1.278 + _asm adc edx,0 //
1.279 + subfp2:
1.280 + _asm jnz short subfp3 // branch if edx non-zero at this point
1.281 + _asm mov edx, ebx // else shift ebx into edx
1.282 + _asm or edx, edx //
1.283 + _asm jz short subfp4 // if still zero, branch
1.284 + _asm mov ebx, eax // else shift rounding word into ebx
1.285 + _asm xor eax, eax // and zero rounding word
1.286 + _asm sub ecx, 0x200000 // decrease exponent by 32 due to shift
1.287 + _asm jnc short subfp3 // if no borrow, carry on
1.288 + _asm jmp short subfpundflw // if borrow here, underflow
1.289 + subfp4:
1.290 + _asm mov edx, eax // move rounding word into edx
1.291 + _asm or edx, edx // is edx still zero ?
1.292 + _asm jz short subfp0 // if so, result is precisely zero
1.293 + _asm xor ebx, ebx // else zero ebx and rounding word
1.294 + _asm xor eax, eax //
1.295 + _asm sub ecx, 0x400000 // and decrease exponent by 64 due to shift
1.296 + _asm jc short subfpundflw // if borrow, underflow
1.297 + subfp3:
1.298 + _asm mov edi, ecx // preserve sign and exponent
1.299 + _asm bsr ecx, edx // position of most significant 1 into ecx
1.300 + _asm neg ecx //
1.301 + _asm add ecx, 31 // cl = 31-position of MS 1 = number of shifts to normalise
1.302 + _asm shld edx, ebx, cl // shift edx:ebx:eax left by cl bits
1.303 + _asm shld ebx, eax, cl //
1.304 + _asm shl eax, cl //
1.305 + _asm mov ebp, ecx // bit count into ebp for subtraction
1.306 + _asm shl ebp, 16 // shift left by 16 to align with exponent
1.307 + _asm mov ecx, edi // exponent, sign, rounding flags back into ecx
1.308 + _asm sub ecx, ebp // subtract shift count from exponent
1.309 + _asm jc short subfpundflw // if borrow, underflow
1.310 + _asm cmp ecx, 0x10000 // check if exponent 0
1.311 + _asm jnc roundfp // if not, jump to round result, else underflow
1.312 +
1.313 + // come here if underflow
1.314 + subfpundflw:
1.315 + _asm and ecx, 1 // set exponent to zero, leave sign
1.316 + _asm xor edx, edx
1.317 + _asm xor ebx, ebx
1.318 + _asm mov eax, -10 // return KErrUnderflow
1.319 + _asm ret
1.320 +
1.321 + // come here to return zero result
1.322 + subfp0:
1.323 + _asm xor ecx, ecx // set exponent to zero, positive sign
1.324 + _asm xor edx, edx
1.325 + _asm xor ebx, ebx
1.326 + addfp0snzd:
1.327 + _asm xor eax, eax // return KErrNone
1.328 + _asm ret
1.329 +
1.330 + // come here if source=0 - eax=source exponent/sign
1.331 + addfp0s:
1.332 + _asm cmp ecx, 0x10000 // check if dest=0
1.333 + _asm jnc addfp0snzd // if not, return dest unaltered
1.334 + _asm and ecx, eax // else both zero, result negative iff both zeros negative
1.335 + _asm and ecx, 1
1.336 + _asm xor eax, eax // return KErrNone
1.337 + _asm ret
1.338 +
1.339 + // come here if dest=0, source nonzero
1.340 + addfp0d:
1.341 + _asm mov ebx, [esi] // return source unaltered
1.342 + _asm mov edx, [esi+4]
1.343 + _asm mov ecx, [esi+8]
1.344 + _asm xor eax, eax // return KErrNone
1.345 + _asm ret
1.346 +
1.347 + // come here if dest=NaN or infinity
1.348 + addfpsd:
1.349 + _asm cmp edx, 0x80000000 // check for infinity
1.350 + _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
1.351 + _asm test ebx, ebx
1.352 + _ASM_jn(e,TRealXBinOpNaN)
1.353 + _asm mov eax, [esi+8] // eax=second operand exponent
1.354 + _asm cmp eax, 0xFFFF0000 // check second operand for NaN or infinity
1.355 + _asm jae short addfpsd1 // branch if NaN or infinity
1.356 + addfpsd2:
1.357 + _asm mov eax, -9 // else return dest unaltered (infinity) and KErrOverflow
1.358 + _asm ret
1.359 + addfpsd1:
1.360 + _asm mov ebp, [esi] // source mantissa into edi:ebp
1.361 + _asm mov edi, [esi+4]
1.362 + _asm cmp edi, 0x80000000 // check for infinity
1.363 + _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
1.364 + _asm test ebp, ebp
1.365 + _ASM_jn(e,TRealXBinOpNaN)
1.366 + _asm xor al, cl // both operands are infinity - check signs
1.367 + _asm test al, 1
1.368 + _asm jz short addfpsd2 // if both the same, return KErrOverflow
1.369 + _asm jmp TRealXRealIndefinite // else return 'real indefinite'
1.370 +
1.371 + // come here if source=NaN or infinity, dest finite
1.372 + addfpss:
1.373 + _asm mov ebp, [esi] // source mantissa into edi:ebp
1.374 + _asm mov edi, [esi+4]
1.375 + _asm cmp edi, 0x80000000 // check for infinity
1.376 + _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
1.377 + _asm test ebp, ebp
1.378 + _ASM_jn(e,TRealXBinOpNaN)
1.379 + _asm mov ecx, eax // if source=infinity, return source unaltered
1.380 + _asm mov edx, edi
1.381 + _asm mov ebx, ebp
1.382 + _asm mov eax, -9 // return KErrOverflow
1.383 + _asm ret
1.384 + }
1.385 +
1.386 +// Subtract TRealX at [esi] - ecx,edx:ebx
1.387 +// Result in ecx,edx:ebx
1.388 +// Error code in eax
1.389 +__NAKED__ LOCAL_C void TRealXSubtract()
1.390 + {
1.391 + _asm xor cl, 1 // negate subtrahend
1.392 + _asm jmp TRealXAdd
1.393 + }
1.394 +
1.395 +// Multiply TRealX at [esi] * ecx,edx:ebx
1.396 +// Result in ecx,edx:ebx
1.397 +// Error code in eax
1.398 +__NAKED__ LOCAL_C void TRealXMultiply()
1.399 + {
1.400 + _asm xor ch, ch // clear rounding flags
1.401 + _asm mov eax, [esi+8] // fetch sign/exponent of source
1.402 + _asm xor cl, al // xor signs
1.403 + _asm cmp ecx, 0xFFFF0000 // check if dest=NaN or infinity
1.404 + _asm jnc mulfpsd // branch if it is
1.405 + _asm cmp eax, 0xFFFF0000 // check if source=NaN or infinity
1.406 + _asm jnc mulfpss // branch if it is
1.407 + _asm cmp eax, 0x10000 // check if source=0
1.408 + _asm jc mulfp0 // branch if it is
1.409 + _asm cmp ecx, 0x10000 // check if dest=0
1.410 + _asm jc mulfp0 // branch if it is
1.411 + _asm push ecx // save result sign
1.412 + _asm shr ecx, 16 // dest exponent into cx
1.413 + _asm shr eax, 16 // source exponent into ax
1.414 + _asm add eax, ecx // add exponents
1.415 + _asm sub eax, 0x7FFE // eax now contains result exponent
1.416 + _asm push eax // save it
1.417 + _asm mov edi, edx // save dest mantissa high
1.418 + _asm mov eax, ebx // dest mantissa low -> eax
1.419 + _asm mul dword ptr [esi] // dest mantissa low * source mantissa low -> edx:eax
1.420 + _asm xchg ebx, eax // result dword 0 -> ebx, dest mant low -> eax
1.421 + _asm mov ebp, edx // result dword 1 -> ebp
1.422 + _asm mul dword ptr [esi+4] // dest mant low * src mant high -> edx:eax
1.423 + _asm add ebp, eax // add in partial product to dwords 1 and 2
1.424 + _asm adc edx, 0 //
1.425 + _asm mov ecx, edx // result dword 2 -> ecx
1.426 + _asm mov eax, edi // dest mant high -> eax
1.427 + _asm mul dword ptr [esi+4] // dest mant high * src mant high -> edx:eax
1.428 + _asm add ecx, eax // add in partial product to dwords 2, 3
1.429 + _asm adc edx, 0 //
1.430 + _asm mov eax, edi // dest mant high -> eax
1.431 + _asm mov edi, edx // result dword 3 -> edi
1.432 + _asm mul dword ptr [esi] // dest mant high * src mant low -> edx:eax
1.433 + _asm add ebp, eax // add in partial product to dwords 1, 2
1.434 + _asm adc ecx, edx //
1.435 + _asm adc edi, 0 // 128-bit mantissa product is now in edi:ecx:ebp:ebx
1.436 + _asm mov edx, edi // top 64 bits into edx:ebx
1.437 + _asm mov edi, ebx
1.438 + _asm mov ebx, ecx // bottom 64 bits now in ebp:edi
1.439 + _asm pop ecx // recover exponent
1.440 + _asm js short mulfp1 // skip if mantissa normalised
1.441 + _asm add edi, edi // else shift left (only one shift will be needed)
1.442 + _asm adc ebp, ebp
1.443 + _asm adc ebx, ebx
1.444 + _asm adc edx, edx
1.445 + _asm dec ecx // and decrement exponent
1.446 + mulfp1:
1.447 + _asm cmp ebp, 0x80000000 // compare bottom 64 bits with 80000000 00000000 for rounding
1.448 + _asm ja short mulfp2 // branch to round up
1.449 + _asm jb short mulfp3 // branch to round down
1.450 + _asm test edi, edi
1.451 + _asm jnz short mulfp2 // branch to round up
1.452 + _asm test bl, 1 // if exactly half-way, test LSB of result mantissa
1.453 + _asm jz short mulfp4 // if LSB=0, round down (round to even)
1.454 + mulfp2:
1.455 + _asm add ebx, 1 // round up - increment mantissa
1.456 + _asm adc edx, 0
1.457 + _asm jnc short mulfp2a
1.458 + _asm rcr edx, 1
1.459 + _asm inc ecx
1.460 + mulfp2a:
1.461 + _asm mov al, 2 // set rounded-up flag
1.462 + _asm jmp short mulfp5
1.463 + mulfp3: // round down
1.464 + _asm xor al, al // clear rounding flags
1.465 + _asm or ebp, edi // check for exact result
1.466 + _asm jz short mulfp5 // skip if exact
1.467 + mulfp4: // come here to round down when we know result inexact
1.468 + _asm mov al, 1 // else set rounded-down flag
1.469 + mulfp5: // final mantissa now in edx:ebx, exponent in ecx
1.470 + _asm cmp ecx, 0xFFFF // check for overflow
1.471 + _asm jge short mulfp6 // branch if overflow
1.472 + _asm cmp ecx, 0 // check for underflow
1.473 + _asm jle short mulfp7 // branch if underflow
1.474 + _asm shl ecx, 16 // else exponent up to top end of ecx
1.475 + _asm mov ch, al // rounding flags into ch
1.476 + _asm pop eax // recover result sign
1.477 + _asm mov cl, al // into cl
1.478 + _asm xor eax, eax // return KErrNone
1.479 + _asm ret
1.480 +
1.481 + // come here if overflow
1.482 + mulfp6:
1.483 + _asm pop eax // recover result sign
1.484 + _asm mov ecx, 0xFFFF0000 // exponent=FFFF
1.485 + _asm mov cl, al // sign into cl
1.486 + _asm mov edx, 0x80000000 // set mantissa to 80000000 00000000 for infinity
1.487 + _asm xor ebx, ebx
1.488 + _asm mov eax, -9 // return KErrOverflow
1.489 + _asm ret
1.490 +
1.491 + // come here if underflow
1.492 + mulfp7:
1.493 + _asm pop eax // recover result sign
1.494 + _asm xor ecx, ecx // exponent=0
1.495 + _asm mov cl, al // sign into cl
1.496 + _asm xor edx, edx
1.497 + _asm xor ebx, ebx
1.498 + _asm mov eax, -10 // return KErrUnderflow
1.499 + _asm ret
1.500 +
1.501 + // come here if either operand zero
1.502 + mulfp0:
1.503 + _asm and ecx, 1 // set exponent=0, keep sign
1.504 + _asm xor edx, edx
1.505 + _asm xor ebx, ebx
1.506 + _asm xor eax, eax // return KErrNone
1.507 + _asm ret
1.508 +
1.509 + // come here if destination operand NaN or infinity
1.510 + mulfpsd:
1.511 + _asm cmp edx, 0x80000000 // check for infinity
1.512 + _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
1.513 + _asm test ebx, ebx
1.514 + _ASM_jn(e,TRealXBinOpNaN)
1.515 + _asm cmp eax, 0xFFFF0000 // check second operand for NaN or infinity
1.516 + _asm jae short mulfpsd1 // branch if NaN or infinity
1.517 + _asm cmp eax, 0x10000 // check if second operand zero
1.518 + _ASM_j(c,TRealXRealIndefinite) // if so, return 'real indefinite'
1.519 + _asm mov eax, -9 // else return dest (infinity) with xor sign and KErrOverflow
1.520 + _asm ret
1.521 + mulfpsd1:
1.522 + _asm mov ebp, [esi] // source mantissa into edi:ebp
1.523 + _asm mov edi, [esi+4]
1.524 + _asm cmp edi, 0x80000000 // check for infinity
1.525 + _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
1.526 + _asm test ebp, ebp
1.527 + _ASM_jn(e,TRealXBinOpNaN)
1.528 + _asm mov eax, -9 // both operands infinity - return infinity with xor sign
1.529 + _asm ret // and KErrOverflow
1.530 +
1.531 + // come here if source operand NaN or infinity, destination finite
1.532 + mulfpss:
1.533 + _asm mov ebp, [esi] // source mantissa into edi:ebp
1.534 + _asm mov edi, [esi+4]
1.535 + _asm cmp edi, 0x80000000 // check for infinity
1.536 + _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
1.537 + _asm test ebp, ebp
1.538 + _ASM_jn(e,TRealXBinOpNaN)
1.539 + _asm cmp ecx, 0x10000 // source=infinity, check if dest=0
1.540 + _ASM_j(c,TRealXRealIndefinite) // if so, return 'real indefinite'
1.541 + _asm or ecx, 0xFFFF0000 // set exp=FFFF, leave xor sign in cl
1.542 + _asm mov edx, edi // set mantissa for infinity
1.543 + _asm mov ebx, ebp
1.544 + _asm mov eax, -9 // return KErrOverflow
1.545 + _asm ret
1.546 + }
1.547 +
1.548 +// Divide 96-bit unsigned dividend EDX:EAX:0 by 64-bit unsigned divisor ECX:EBX
1.549 +// Assume ECX bit 31 = 1, ie 2^63 <= divisor < 2^64
1.550 +// Assume the quotient fits in 32 bits
1.551 +// Return 32 bit quotient in EDI
1.552 +// Return 64 bit remainder in EBP:ESI
1.553 +__NAKED__ LOCAL_C void LongDivide(void)
1.554 + {
1.555 + _asm push edx // save dividend
1.556 + _asm push eax //
1.557 + _asm cmp edx, ecx // check if truncation of divisor will overflow DIV instruction
1.558 + _asm jb short longdiv1 // skip if not
1.559 + _asm xor eax, eax // else return quotient of 0xFFFFFFFF
1.560 + _asm dec eax //
1.561 + _asm jmp short longdiv2 //
1.562 + longdiv1:
1.563 + _asm div ecx // divide EDX:EAX by ECX to give approximate quotient in EAX
1.564 + longdiv2:
1.565 + _asm mov edi, eax // save approx quotient
1.566 + _asm mul ebx // multiply approx quotient by full divisor ECX:EBX
1.567 + _asm mov esi, eax // first partial product into EBP:ESI
1.568 + _asm mov ebp, edx //
1.569 + _asm mov eax, edi // approx quotient back into eax
1.570 + _asm mul ecx // upper partial product now in EDX:EAX
1.571 + _asm add eax, ebp // add to form 96-bit product in EDX:EAX:ESI
1.572 + _asm adc edx, 0 //
1.573 + _asm neg esi // remainder = dividend - approx quotient * divisor
1.574 + _asm mov ebp, [esp] // fetch dividend bits 32-63
1.575 + _asm sbb ebp, eax //
1.576 + _asm mov eax, [esp+4] // fetch dividend bits 64-95
1.577 + _asm sbb eax, edx // remainder is now in EAX:EBP:ESI
1.578 + _asm jns short longdiv4 // if remainder positive, quotient is correct, so exit
1.579 + longdiv3:
1.580 + _asm dec edi // else quotient is too big, so decrement it
1.581 + _asm add esi, ebx // and add divisor to remainder
1.582 + _asm adc ebp, ecx //
1.583 + _asm adc eax, 0 //
1.584 + _asm js short longdiv3 // if still negative, repeat (requires <4 iterations)
1.585 + longdiv4:
1.586 + _asm add esp, 8 // remove dividend from stack
1.587 + _asm ret // return with quotient in EDI, remainder in EBP:ESI
1.588 + }
1.589 +
1.590 +// Divide TRealX at [esi] / ecx,edx:ebx
1.591 +// Result in ecx,edx:ebx
1.592 +// Error code in eax
1.593 +__NAKED__ LOCAL_C void TRealXDivide(void)
1.594 + {
1.595 + _asm xor ch, ch // clear rounding flags
1.596 + _asm mov eax, [esi+8] // fetch sign/exponent of dividend
1.597 + _asm xor cl, al // xor signs
1.598 + _asm cmp eax, 0xFFFF0000 // check if dividend=NaN or infinity
1.599 + _asm jnc divfpss // branch if it is
1.600 + _asm cmp ecx, 0xFFFF0000 // check if divisor=NaN or infinity
1.601 + _asm jnc divfpsd // branch if it is
1.602 + _asm cmp ecx, 0x10000 // check if divisor=0
1.603 + _asm jc divfpdv0 // branch if it is
1.604 + _asm cmp eax, 0x10000 // check if dividend=0
1.605 + _asm jc divfpdd0 // branch if it is
1.606 + _asm push esi // save pointer to dividend
1.607 + _asm push ecx // save result sign
1.608 + _asm shr ecx, 16 // divisor exponent into cx
1.609 + _asm shr eax, 16 // dividend exponent into ax
1.610 + _asm sub eax, ecx // subtract exponents
1.611 + _asm add eax, 0x7FFE // eax now contains result exponent
1.612 + _asm push eax // save it
1.613 + _asm mov ecx, edx // divisor mantissa into ecx:ebx
1.614 + _asm mov edx, [esi+4] // dividend mantissa into edx:eax
1.615 + _asm mov eax, [esi]
1.616 + _asm xor edi, edi // clear edi initially
1.617 + _asm cmp edx, ecx // compare EDX:EAX with ECX:EBX
1.618 + _asm jb short divfp1 // if EDX:EAX < ECX:EBX, leave everything as is
1.619 + _asm ja short divfp2 //
1.620 + _asm cmp eax, ebx // if EDX=ECX, then compare ls dwords
1.621 + _asm jb short divfp1 // if dividend mant < divisor mant, leave everything as is
1.622 + divfp2:
1.623 + _asm sub eax, ebx // else dividend mant -= divisor mant
1.624 + _asm sbb edx, ecx //
1.625 + _asm inc edi // and EDI=1 (bit 0 of EDI is the integer part of the result)
1.626 + _asm inc dword ptr [esp] // also increment result exponent
1.627 + divfp1:
1.628 + _asm push edi // save top bit of result
1.629 + _asm call LongDivide // divide EDX:EAX:0 by ECX:EBX to give next 32 bits of result in EDI
1.630 + _asm push edi // save next 32 bits of result
1.631 + _asm mov edx, ebp // remainder from EBP:ESI into EDX:EAX
1.632 + _asm mov eax, esi //
1.633 + _asm call LongDivide // divide EDX:EAX:0 by ECX:EBX to give next 32 bits of result in EDI
1.634 + _asm test byte ptr [esp+4], 1 // test integer bit of result
1.635 + _asm jnz short divfp4 // if set, no need to calculate another bit
1.636 + _asm xor eax, eax //
1.637 + _asm add esi, esi // 2*remainder into EAX:EBP:ESI
1.638 + _asm adc ebp, ebp //
1.639 + _asm adc eax, eax //
1.640 + _asm sub esi, ebx // subtract divisor to generate final quotient bit
1.641 + _asm sbb ebp, ecx //
1.642 + _asm sbb eax, 0 //
1.643 + _asm jnc short divfp3 // skip if no borrow - in this case eax=0
1.644 + _asm add esi, ebx // if borrow add back - final remainder now in EBP:ESI
1.645 + _asm adc ebp, ecx //
1.646 + _asm adc eax, 0 // eax will be zero after this and carry will be set
1.647 + divfp3:
1.648 + _asm cmc // final bit = 1-C
1.649 + _asm rcr eax, 1 // shift it into eax bit 31
1.650 + _asm mov ebx, edi // result into EDX:EBX:EAX, remainder in EBP:ESI
1.651 + _asm pop edx
1.652 + _asm add esp, 4 // discard integer bit (zero)
1.653 + _asm jmp short divfp5 // branch to round
1.654 +
1.655 + divfp4: // integer bit was set
1.656 + _asm mov ebx, edi // result into EDX:EBX:EAX
1.657 + _asm pop edx //
1.658 + _asm pop eax // integer part of result into eax (=1)
1.659 + _asm stc // shift a 1 into top end of mantissa
1.660 + _asm rcr edx,1 //
1.661 + _asm rcr ebx,1 //
1.662 + _asm rcr eax,1 // bottom bit into eax bit 31
1.663 +
1.664 + // when we get to here we have 65 bits of quotient mantissa in
1.665 + // EDX:EBX:EAX (bottom bit in eax bit 31)
1.666 + // and the remainder is in EBP:ESI
1.667 + divfp5:
1.668 + _asm pop ecx // recover result exponent
1.669 + _asm add eax, eax // test rounding bit
1.670 + _asm jnc short divfp6 // branch to round down
1.671 + _asm or ebp, esi // test remainder to see if we are exactly half-way
1.672 + _asm jnz short divfp7 // if not, round up
1.673 + _asm test bl, 1 // exactly halfway - test LSB of mantissa
1.674 + _asm jz short divfp8 // round down if LSB=0 (round to even)
1.675 + divfp7:
1.676 + _asm add ebx, 1 // round up - increment mantissa
1.677 + _asm adc edx, 0
1.678 + _asm jnc short divfp7a
1.679 + _asm rcr edx, 1 // if carry, shift 1 into mantissa MSB
1.680 + _asm inc ecx // and increment exponent
1.681 + divfp7a:
1.682 + _asm mov al, 2 // set rounded-up flag
1.683 + _asm jmp short divfp9
1.684 + divfp6:
1.685 + _asm xor al, al // round down - first clear rounding flags
1.686 + _asm or ebp, esi // test if result exact
1.687 + _asm jz short divfp9 // skip if exact
1.688 + divfp8: // come here to round down when we know result is inexact
1.689 + _asm mov al, 1 // set rounded-down flag
1.690 + divfp9: // final mantissa now in edx:ebx, exponent in ecx
1.691 + _asm cmp ecx, 0xFFFF // check for overflow
1.692 + _asm jge short divfp10 // branch if overflow
1.693 + _asm cmp ecx, 0 // check for underflow
1.694 + _asm jle short divfp11 // branch if underflow
1.695 + _asm shl ecx, 16 // else exponent up to top end of ecx
1.696 + _asm mov ch, al // rounding flags into ch
1.697 + _asm pop eax // recover result sign
1.698 + _asm mov cl, al // into cl
1.699 + _asm pop esi // recover dividend pointer
1.700 + _asm xor eax, eax // return KErrNone
1.701 + _asm ret
1.702 +
1.703 + // come here if overflow
1.704 + divfp10:
1.705 + _asm pop eax // recover result sign
1.706 + _asm mov ecx, 0xFFFF0000 // exponent=FFFF
1.707 + _asm mov cl, al // sign into cl
1.708 + _asm mov edx, 0x80000000 // set mantissa to 80000000 00000000 for infinity
1.709 + _asm xor ebx, ebx
1.710 + _asm mov eax, -9 // return KErrOverflow
1.711 + _asm pop esi // recover dividend pointer
1.712 + _asm ret
1.713 +
1.714 + // come here if underflow
1.715 + divfp11:
1.716 + _asm pop eax // recover result sign
1.717 + _asm xor ecx, ecx // exponent=0
1.718 + _asm mov cl, al // sign into cl
1.719 + _asm xor edx, edx
1.720 + _asm xor ebx, ebx
1.721 + _asm mov eax, -10 // return KErrUnderflow
1.722 + _asm pop esi // recover dividend pointer
1.723 + _asm ret
1.724 +
1.725 +
1.726 + // come here if divisor=0, dividend finite
1.727 + divfpdv0:
1.728 + _asm cmp eax, 0x10000 // check if dividend also zero
1.729 + _ASM_j(c,TRealXRealIndefinite) // if so, return 'real indefinite'
1.730 + _asm or ecx, 0xFFFF0000 // else set exponent=FFFF, leave xor sign in cl
1.731 + _asm mov edx, 0x80000000 // set mantissa for infinity
1.732 + _asm xor ebx, ebx
1.733 + _asm mov eax, -41 // return KErrDivideByZero
1.734 + _asm ret
1.735 +
1.736 + // come here if dividend=0, divisor finite and nonzero
1.737 + divfpdd0:
1.738 + _asm and ecx, 1 // exponent=0, leave xor sign in cl
1.739 + _asm xor eax, eax // return KErrNone
1.740 + _asm ret
1.741 +
1.742 + // come here if dividend is a NaN or infinity
1.743 + divfpss:
1.744 + _asm mov ebp, [esi] // dividend mantissa into edi:ebp
1.745 + _asm mov edi, [esi+4]
1.746 + _asm cmp edi, 0x80000000 // check for infinity
1.747 + _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
1.748 + _asm test ebp, ebp
1.749 + _ASM_jn(e,TRealXBinOpNaN)
1.750 + _asm cmp ecx, 0xFFFF0000 // check divisor for NaN or infinity
1.751 + _asm jae short divfpss1 // branch if NaN or infinity
1.752 + _asm or ecx, 0xFFFF0000 // infinity/finite - return infinity with xor sign
1.753 + _asm mov edx, 0x80000000
1.754 + _asm xor ebx, ebx
1.755 + _asm mov eax, -9 // return KErrOverflow
1.756 + _asm ret
1.757 + divfpss1:
1.758 + _asm cmp edx, 0x80000000 // check for infinity
1.759 + _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
1.760 + _asm test ebx, ebx
1.761 + _ASM_jn(e,TRealXBinOpNaN)
1.762 + _asm jmp TRealXRealIndefinite // if both operands infinite, return 'real indefinite'
1.763 +
1.764 + // come here if divisor is a NaN or infinity, dividend finite
1.765 + divfpsd:
1.766 + _asm cmp edx, 0x80000000 // check for infinity
1.767 + _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
1.768 + _asm test ebx, ebx
1.769 + _ASM_jn(e,TRealXBinOpNaN)
1.770 + _asm and ecx, 1 // dividend is finite, divisor=infinity, so return 0 with xor sign
1.771 + _asm xor edx, edx
1.772 + _asm xor ebx, ebx
1.773 + _asm xor eax, eax // return KErrNone
1.774 + _asm ret
1.775 + }
1.776 +
1.777 +// TRealX modulo - dividend at [esi], divisor in ecx,edx:ebx
1.778 +// Result in ecx,edx:ebx
1.779 +// Error code in eax
1.780 +__NAKED__ LOCAL_C void TRealXModulo(void)
1.781 + {
1.782 + _asm mov eax, [esi+8] // fetch sign/exponent of dividend
1.783 + _asm mov cl, al // result sign=dividend sign
1.784 + _asm xor ch, ch // clear rounding flags
1.785 + _asm cmp eax, 0xFFFF0000 // check if dividend=NaN or infinity
1.786 + _asm jnc modfpss // branch if it is
1.787 + _asm cmp ecx, 0xFFFF0000 // check if divisor=NaN or infinity
1.788 + _asm jnc modfpsd // branch if it is
1.789 + _asm cmp ecx, 0x10000 // check if divisor=0
1.790 + _ASM_j(c,TRealXRealIndefinite) // if so, return 'real indefinite'
1.791 + _asm shr eax, 16 // ax=dividend exponent
1.792 + _asm ror ecx, 16 // cx=divisor exponent
1.793 + _asm sub ax, cx // ax=dividend exponent-divisor exponent
1.794 + _asm jc modfpdd0 // if dividend exponent is smaller, return dividend
1.795 + _asm cmp ax, 64 // check if exponents differ by >= 64 bits
1.796 + _asm jnc modfplp // if so, underflow
1.797 + _asm mov ah, 0 // ah bit 0 acts as 65th accumulator bit
1.798 + _asm mov ebp, [esi] // edi:ebp=dividend mantissa
1.799 + _asm mov edi, [esi+4] //
1.800 + _asm jmp short modfp2 // skip left shift on first iteration
1.801 + modfp1:
1.802 + _asm add ebp, ebp // shift accumulator left (65 bits)
1.803 + _asm adc edi, edi
1.804 + _asm adc ah, ah
1.805 + modfp2:
1.806 + _asm sub ebp, ebx // subtract divisor from dividend
1.807 + _asm sbb edi, edx
1.808 + _asm sbb ah, 0
1.809 + _asm jnc short modfp3 // skip if no borrow
1.810 + _asm add ebp, ebx // else add back
1.811 + _asm adc edi, edx
1.812 + _asm adc ah, 0
1.813 + modfp3:
1.814 + _asm dec al // any more bits to do?
1.815 + _asm jns short modfp1 // loop if there are
1.816 + _asm mov edx, edi // result mantissa (not yet normalised) into edx:ebx
1.817 + _asm mov ebx, ebp
1.818 + _asm or edi, ebx // check for zero
1.819 + _asm jz modfp0 // jump if result zero
1.820 + _asm or edx, edx // check if ms dword zero
1.821 + _asm jnz short modfp4
1.822 + _asm mov edx, ebx // if so, shift left by 32
1.823 + _asm xor ebx, ebx
1.824 + _asm sub cx, 32 // and decrement exponent by 32
1.825 + _asm jbe modfpund // if borrow or exponent zero, underflow
1.826 + modfp4:
1.827 + _asm mov edi, ecx // preserve sign and exponent
1.828 + _asm bsr ecx, edx // position of most significant 1 into ecx
1.829 + _asm neg ecx //
1.830 + _asm add ecx, 31 // cl = 31-position of MS 1 = number of shifts to normalise
1.831 + _asm shld edx, ebx, cl // shift edx:ebx left by cl bits
1.832 + _asm shl ebx, cl //
1.833 + _asm mov ebp, ecx // bit count into ebp for subtraction
1.834 + _asm mov ecx, edi // exponent & sign back into ecx
1.835 + _asm sub cx, bp // subtract shift count from exponent
1.836 + _asm jbe short modfpund // if borrow or exponent 0, underflow
1.837 + _asm rol ecx, 16 // else ecx=exponent:sign
1.838 + _asm xor eax, eax // normal exit, result in ecx,edx:ebx
1.839 + _asm ret
1.840 +
1.841 + // dividend=NaN or infinity
1.842 + modfpss:
1.843 + _asm mov ebp, [esi] // dividend mantissa into edi:ebp
1.844 + _asm mov edi, [esi+4]
1.845 + _asm cmp edi, 0x80000000 // check for infinity
1.846 + _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
1.847 + _asm test ebp, ebp
1.848 + _ASM_jn(e,TRealXBinOpNaN)
1.849 + _asm cmp ecx, 0xFFFF0000 // check divisor for NaN or infinity
1.850 + _ASM_j(b,TRealXRealIndefinite) // infinity%finite - return 'real indefinite'
1.851 + _asm cmp edx, 0x80000000 // check for divisor=infinity
1.852 + _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
1.853 + _asm test ebx, ebx
1.854 + _ASM_jn(e,TRealXBinOpNaN)
1.855 + _asm jmp TRealXRealIndefinite // if both operands infinite, return 'real indefinite'
1.856 +
1.857 + // divisor=NaN or infinity, dividend finite
1.858 + modfpsd:
1.859 + _asm cmp edx, 0x80000000 // check for infinity
1.860 + _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
1.861 + _asm test ebx, ebx
1.862 + _ASM_jn(e,TRealXBinOpNaN)
1.863 + // finite%infinity - return dividend unaltered
1.864 +
1.865 + modfpdd0:
1.866 + _asm mov ebx, [esi] // normal exit, return dividend unaltered
1.867 + _asm mov edx, [esi+4]
1.868 + _asm mov ecx, [esi+8]
1.869 + _asm xor eax, eax
1.870 + _asm ret
1.871 +
1.872 + modfp0:
1.873 + _asm shr ecx, 16 // normal exit, result 0
1.874 + _asm xor eax, eax
1.875 + _asm ret
1.876 +
1.877 + modfpund:
1.878 + _asm shr ecx, 16 // underflow, result 0
1.879 + _asm mov eax, -10 // return KErrUnderflow
1.880 + _asm ret
1.881 +
1.882 + modfplp:
1.883 + _asm shr ecx, 16 // loss of precision, result 0
1.884 + _asm mov eax, -7 // return KErrTotalLossOfPrecision
1.885 + _asm ret
1.886 + }
1.887 +
1.888 +
1.889 +
1.890 +
1.891 +__NAKED__ EXPORT_C TRealX::TRealX()
1.892 +/**
1.893 +Constructs a default extended precision object.
1.894 +
1.895 +This sets the value to zero.
1.896 +*/
1.897 + {
1.898 + _asm xor eax, eax
1.899 + _asm mov [ecx], eax // set value to zero
1.900 + _asm mov [ecx+4], eax
1.901 + _asm mov [ecx+8], eax
1.902 + _asm mov eax, ecx // must return this
1.903 + _asm ret
1.904 + }
1.905 +
1.906 +
1.907 +
1.908 +
1.909 +__NAKED__ EXPORT_C TRealX::TRealX(TUint /*aExp*/, TUint /*aMantHi*/, TUint /*aMantLo*/)
1.910 +/**
1.911 +Constructs an extended precision object from an explicit exponent and
1.912 +a 64 bit mantissa.
1.913 +
1.914 +@param aExp The exponent
1.915 +@param aMantHi The high order 32 bits of the 64 bit mantissa
1.916 +@param aMantLo The low order 32 bits of the 64 bit mantissa
1.917 +*/
1.918 + {
1.919 + _asm mov eax, [esp+4] // eax=aExp
1.920 + _asm mov [ecx+8], eax
1.921 + _asm mov eax, [esp+8] // eax=aMantHi
1.922 + _asm mov [ecx+4], eax
1.923 + _asm mov eax, [esp+12] // eax=aMantLo
1.924 + _asm mov [ecx], eax
1.925 + _asm mov eax, ecx // must return this
1.926 + _asm ret 12
1.927 + }
1.928 +
1.929 +
1.930 +
1.931 +
1.932 +__NAKED__ EXPORT_C TInt TRealX::Set(TInt /*aInt*/)
1.933 +/**
1.934 +Gives this extended precision object a new value taken
1.935 +from a signed integer.
1.936 +
1.937 +@param aInt The signed integer value.
1.938 +
1.939 +@return KErrNone, always.
1.940 +*/
1.941 + {
1.942 + // on entry ecx=this, [esp+4]=aInt, return code in eax
1.943 + _asm mov edx, [esp+4] // edx=aInt
1.944 + _asm or edx, edx // test sign/zero
1.945 + _asm mov eax, 0x7FFF
1.946 + _asm jz short trealxfromint0 // branch if 0
1.947 + _asm jns short trealxfromint1 // skip if positive
1.948 + _asm neg edx // take absolute value
1.949 + _asm add eax, 0x10000 // sign bit in eax bit 16
1.950 + trealxfromint1:
1.951 + _asm push ecx // save this
1.952 + _asm bsr ecx, edx // bit number of edx MSB into ecx
1.953 + _asm add eax, ecx // add to eax to form result exponent
1.954 + _asm neg cl
1.955 + _asm add cl, 31 // 31-bit number = number of shifts to normalise edx
1.956 + _asm shl edx, cl // normalise edx
1.957 + _asm pop ecx // this back into ecx
1.958 + _asm ror eax, 16 // sign/exponent into normal positions
1.959 + _asm mov [ecx+4], edx // store mantissa high word
1.960 + _asm mov [ecx+8], eax // store sign/exponent
1.961 + _asm xor eax, eax
1.962 + _asm mov [ecx], eax // zero mantissa low word
1.963 + _asm ret 4 // return KErrNone
1.964 + trealxfromint0:
1.965 + _asm mov [ecx], edx
1.966 + _asm mov [ecx+4], edx // store mantissa high word=0
1.967 + _asm mov [ecx+8], edx // store sign/exponent=0
1.968 + _asm xor eax, eax // return KErrNone
1.969 + _asm ret 4
1.970 + }
1.971 +
1.972 +
1.973 +
1.974 +
1.975 +__NAKED__ EXPORT_C TInt TRealX::Set(TUint /*aInt*/)
1.976 +/**
1.977 +Gives this extended precision object a new value taken from
1.978 +an unsigned integer.
1.979 +
1.980 +@param aInt The unsigned integer value.
1.981 +
1.982 +@return KErrNone, always.
1.983 +*/
1.984 + {
1.985 + // on entry ecx=this, [esp+4]=aInt, return code in eax
1.986 + _asm mov edx, [esp+4] // edx=aInt
1.987 + _asm mov eax, 0x7FFF
1.988 + _asm or edx, edx // test for 0
1.989 + _asm jz short trealxfromuint0 // branch if 0
1.990 + _asm push ecx // save this
1.991 + _asm bsr ecx, edx // bit number of edx MSB into ecx
1.992 + _asm add eax, ecx // add to eax to form result exponent
1.993 + _asm neg cl
1.994 + _asm add cl, 31 // 31-bit number = number of shifts to normalise edx
1.995 + _asm shl edx, cl // normalise edx
1.996 + _asm pop ecx // this back into ecx
1.997 + _asm shl eax, 16 // exponent into normal position
1.998 + _asm mov [ecx+4], edx // store mantissa high word
1.999 + _asm mov [ecx+8], eax // store exponent
1.1000 + _asm xor eax, eax
1.1001 + _asm mov [ecx], eax // zero mantissa low word
1.1002 + _asm ret 4 // return KErrNone
1.1003 + trealxfromuint0:
1.1004 + _asm mov [ecx], edx
1.1005 + _asm mov [ecx+4], edx // store mantissa high word=0
1.1006 + _asm mov [ecx+8], edx // store sign/exponent=0
1.1007 + _asm xor eax, eax // return KErrNone
1.1008 + _asm ret 4
1.1009 + }
1.1010 +
1.1011 +
1.1012 +
1.1013 +
1.1014 +__NAKED__ LOCAL_C void TRealXFromTInt64(void)
1.1015 + {
1.1016 + // Convert TInt64 in edx:ebx to TRealX in ecx,edx:ebx
1.1017 + _asm mov eax, 0x7FFF
1.1018 + _asm or edx, edx // test sign/zero
1.1019 + _asm jz short trealxfromtint64a // branch if top word zero
1.1020 + _asm jns short trealxfromtint64b
1.1021 + _asm add eax, 0x10000 // sign bit into eax bit 16
1.1022 + _asm neg edx // take absolute value
1.1023 + _asm neg ebx
1.1024 + _asm sbb edx, 0
1.1025 + _asm jz short trealxfromtint64d // branch if top word zero
1.1026 + trealxfromtint64b:
1.1027 + _asm bsr ecx, edx // ecx=bit number of edx MSB
1.1028 + _asm add eax, ecx // add to exponent in eax
1.1029 + _asm add eax, 32
1.1030 + _asm neg cl
1.1031 + _asm add cl, 31 // 31-bit number = number of left shifts to normalise
1.1032 + _asm shld edx, ebx, cl // shift left to normalise edx:ebx
1.1033 + _asm shl ebx, cl
1.1034 + _asm mov ecx, eax // sign/exponent into ecx
1.1035 + _asm ror ecx, 16 // and into normal positions
1.1036 + _asm ret
1.1037 + trealxfromtint64a: // come here if top word zero
1.1038 + _asm or ebx, ebx // test for bottom word also zero
1.1039 + _asm jz short trealxfromtint64c // branch if it is
1.1040 + trealxfromtint64d: // come here if top word zero, bottom word not
1.1041 + _asm mov edx, ebx // shift edx:ebx left 32
1.1042 + _asm xor ebx, ebx
1.1043 + _asm bsr ecx, edx // ecx=bit number of edx MSB
1.1044 + _asm add eax, ecx // add to exponent in eax
1.1045 + _asm neg cl
1.1046 + _asm add cl, 31 // 31-bit number = number of left shifts to normalise
1.1047 + _asm shl edx, cl // normalise
1.1048 + _asm mov ecx, eax // sign/exponent into ecx
1.1049 + _asm ror ecx, 16 // and into normal positions
1.1050 + _asm ret
1.1051 + trealxfromtint64c: // entire number is zero
1.1052 + _asm xor ecx, ecx
1.1053 + _asm ret
1.1054 + }
1.1055 +
1.1056 +
1.1057 +
1.1058 +
1.1059 +__NAKED__ EXPORT_C TInt TRealX::Set(const TInt64& /*aInt*/)
1.1060 +/**
1.1061 +Gives this extended precision object a new value taken from
1.1062 +a 64 bit integer.
1.1063 +
1.1064 +@param aInt The 64 bit integer value.
1.1065 +
1.1066 +@return KErrNone, always.
1.1067 +*/
1.1068 + {
1.1069 + // on entry ecx=this, [esp+4]=address of aInt, return code in eax
1.1070 + _asm push ebx
1.1071 + _asm push ecx
1.1072 + _asm mov edx, [esp+12] // edx=address of aInt
1.1073 + _asm mov ebx, [edx]
1.1074 + _asm mov edx, [edx+4] // edx:ebx=aInt
1.1075 + _asm call TRealXFromTInt64 // convert to TRealX in ecx,edx:ebx
1.1076 + _asm pop eax // eax=this
1.1077 + _asm mov [eax], ebx // store result
1.1078 + _asm mov [eax+4], edx
1.1079 + _asm mov [eax+8], ecx
1.1080 + _asm xor eax, eax // return KErrNone
1.1081 + _asm pop ebx
1.1082 + _asm ret 4
1.1083 + }
1.1084 +
1.1085 +
1.1086 +
1.1087 +
1.1088 +__NAKED__ LOCAL_C void __6TRealXi()
1.1089 + {
1.1090 + // common function for int to TRealX
1.1091 + _asm mov edx, [esp+4] // edx=aInt
1.1092 + _asm or edx, edx // test sign/zero
1.1093 + _asm mov eax, 0x7FFF
1.1094 + _asm jz short trealxfromint0 // branch if 0
1.1095 + _asm jns short trealxfromint1 // skip if positive
1.1096 + _asm neg edx // take absolute value
1.1097 + _asm add eax, 0x10000 // sign bit in eax bit 16
1.1098 + trealxfromint1:
1.1099 + _asm push ecx // save this
1.1100 + _asm bsr ecx, edx // bit number of edx MSB into ecx
1.1101 + _asm add eax, ecx // add to eax to form result exponent
1.1102 + _asm neg cl
1.1103 + _asm add cl, 31 // 31-bit number = number of shifts to normalise edx
1.1104 + _asm shl edx, cl // normalise edx
1.1105 + _asm pop ecx // this back into ecx
1.1106 + _asm ror eax, 16 // sign/exponent into normal positions
1.1107 + _asm mov [ecx+4], edx // store mantissa high word
1.1108 + _asm mov [ecx+8], eax // store sign/exponent
1.1109 + _asm xor eax, eax
1.1110 + _asm mov [ecx], eax // zero mantissa low word
1.1111 + _asm mov eax, ecx // return eax=this
1.1112 + _asm ret 4
1.1113 + trealxfromint0:
1.1114 + _asm mov [ecx], edx
1.1115 + _asm mov [ecx+4], edx // store mantissa high word=0
1.1116 + _asm mov [ecx+8], edx // store sign/exponent=0
1.1117 + _asm mov eax, ecx // return eax=this
1.1118 + _asm ret 4
1.1119 + }
1.1120 +
1.1121 +
1.1122 +
1.1123 +
1.1124 +__NAKED__ EXPORT_C TRealX::TRealX(TInt /*aInt*/)
1.1125 +/**
1.1126 +Constructs an extended precision object from a signed integer value.
1.1127 +
1.1128 +@param aInt The signed integer value.
1.1129 +*/
1.1130 + {
1.1131 + // on entry ecx=this, [esp+4]=aInt, return eax=this
1.1132 + _asm jmp __6TRealXi
1.1133 + }
1.1134 +
1.1135 +
1.1136 +
1.1137 +
1.1138 +__NAKED__ EXPORT_C TRealX& TRealX::operator=(TInt /*aInt*/)
1.1139 +/**
1.1140 +Assigns the specified signed integer value to this extended precision object.
1.1141 +
1.1142 +@param aInt The signed integer value.
1.1143 +
1.1144 +@return A reference to this extended precision object.
1.1145 +*/
1.1146 + {
1.1147 + // on entry ecx=this, [esp+4]=aInt, return eax=this
1.1148 + _asm jmp __6TRealXi
1.1149 + }
1.1150 +
1.1151 +
1.1152 +
1.1153 +
1.1154 +__NAKED__ LOCAL_C void __6TRealXui()
1.1155 + {
1.1156 + // common function for unsigned int to TRealX
1.1157 + _asm mov edx, [esp+4] // edx=aInt
1.1158 + _asm mov eax, 0x7FFF
1.1159 + _asm or edx, edx // test for zero
1.1160 + _asm jz short trealxfromuint0 // branch if 0
1.1161 + _asm push ecx // save this
1.1162 + _asm bsr ecx, edx // bit number of edx MSB into ecx
1.1163 + _asm add eax, ecx // add to eax to form result exponent
1.1164 + _asm neg cl
1.1165 + _asm add cl, 31 // 31-bit number = number of shifts to normalise edx
1.1166 + _asm shl edx, cl // normalise edx
1.1167 + _asm pop ecx // this back into ecx
1.1168 + _asm shl eax, 16 // exponent into normal position
1.1169 + _asm mov [ecx+4], edx // store mantissa high word
1.1170 + _asm mov [ecx+8], eax // store exponent
1.1171 + _asm xor eax, eax
1.1172 + _asm mov [ecx], eax // zero mantissa low word
1.1173 + _asm mov eax, ecx // return eax=this
1.1174 + _asm ret 4
1.1175 + trealxfromuint0:
1.1176 + _asm mov [ecx], edx
1.1177 + _asm mov [ecx+4], edx // store mantissa high word=0
1.1178 + _asm mov [ecx+8], edx // store sign/exponent=0
1.1179 + _asm mov eax, ecx // return eax=this
1.1180 + _asm ret 4
1.1181 + }
1.1182 +
1.1183 +
1.1184 +
1.1185 +
1.1186 +__NAKED__ EXPORT_C TRealX::TRealX(TUint /*aInt*/)
1.1187 +/**
1.1188 +Constructs an extended precision object from an unsigned integer value.
1.1189 +
1.1190 +@param aInt The unsigned integer value.
1.1191 +*/
1.1192 + {
1.1193 + // on entry ecx=this, [esp+4]=aInt, return eax=this
1.1194 + _asm jmp __6TRealXui
1.1195 + }
1.1196 +
1.1197 +
1.1198 +
1.1199 +
1.1200 +__NAKED__ EXPORT_C TRealX& TRealX::operator=(TUint /*aInt*/)
1.1201 +/**
1.1202 +Assigns the specified unsigned integer value to this extended precision object.
1.1203 +
1.1204 +@param aInt The unsigned integer value.
1.1205 +
1.1206 +@return A reference to this extended precision object.
1.1207 +*/
1.1208 + {
1.1209 + // on entry ecx=this, [esp+4]=aInt, return eax=this
1.1210 + _asm jmp __6TRealXui
1.1211 + }
1.1212 +
1.1213 +
1.1214 +
1.1215 +
1.1216 +__NAKED__ LOCAL_C void __6TRealXRC6TInt64()
1.1217 + {
1.1218 + // common function for TInt64 to TRealX
1.1219 + _asm push ebx // preserve ebx
1.1220 + _asm push ecx // save this
1.1221 + _asm mov edx, [esp+12] // edx=address of aInt
1.1222 + _asm mov ebx, [edx]
1.1223 + _asm mov edx, [edx+4] // edx:ebx=aInt
1.1224 + _asm call TRealXFromTInt64 // convert to TRealX in ecx,edx:ebx
1.1225 + _asm pop eax // eax=this
1.1226 + _asm mov [eax], ebx // store result
1.1227 + _asm mov [eax+4], edx
1.1228 + _asm mov [eax+8], ecx
1.1229 + _asm pop ebx // restore ebx
1.1230 + _asm ret 4 // return this in eax
1.1231 + }
1.1232 +
1.1233 +
1.1234 +
1.1235 +
1.1236 +__NAKED__ EXPORT_C TRealX::TRealX(const TInt64& /*aInt*/)
1.1237 +/**
1.1238 +Constructs an extended precision object from a 64 bit integer.
1.1239 +
1.1240 +@param aInt A reference to a 64 bit integer.
1.1241 +*/
1.1242 + {
1.1243 + // on entry ecx=this, [esp+4]=address of aInt, return eax=this
1.1244 + _asm jmp __6TRealXRC6TInt64
1.1245 + }
1.1246 +
1.1247 +
1.1248 +
1.1249 +
1.1250 +__NAKED__ EXPORT_C TRealX& TRealX::operator=(const TInt64& /*aInt*/)
1.1251 +/**
1.1252 +Assigns the specified 64 bit integer value to this extended precision object.
1.1253 +
1.1254 +@param aInt A reference to a 64 bit integer.
1.1255 +
1.1256 +@return A reference to this extended precision object.
1.1257 +*/
1.1258 + {
1.1259 + // on entry ecx=this, [esp+4]=address of aInt, return eax=this
1.1260 + _asm jmp __6TRealXRC6TInt64
1.1261 + }
1.1262 +
1.1263 +
1.1264 +
1.1265 +
1.1266 +__NAKED__ LOCAL_C void ConvertTReal32ToTRealX(void)
1.1267 + {
1.1268 + // Convert TReal32 in edx to TRealX in ecx:edx,ebx
1.1269 + _asm xor ebx, ebx // mant low always zero
1.1270 + _asm mov eax, edx
1.1271 + _asm shr eax, 23 // exponent now in al, sign in ah bit 0
1.1272 + _asm test al, al // check for denormal/zero
1.1273 + _asm jz short treal32totrealx2 // branch if denormal/zero
1.1274 + _asm xor ecx, ecx
1.1275 + _asm mov cl, al
1.1276 + _asm add ecx, 0x7F80 // bias exponent correctly for TRealX
1.1277 + _asm cmp al, 0xFF // check for infinity/NaN
1.1278 + _asm jnz short treal32totrealx1 // skip if neither
1.1279 + _asm mov cl, al // else set TRealX exponent to FFFF
1.1280 + _asm mov ch, al
1.1281 + treal32totrealx1:
1.1282 + _asm shl edx, 8 // left-justify mantissa in edx
1.1283 + _asm or edx, 0x80000000 // put in implied integer bit
1.1284 + _asm shl ecx, 16 // exponent into ecx bits 16-31
1.1285 + _asm mov cl, ah // sign into ecx bit 0
1.1286 + _asm ret
1.1287 + treal32totrealx2: // come here if exponent 0
1.1288 + _asm shl edx, 9 // left-justify mantissa in edx (shift out integer bit as well)
1.1289 + _asm jnz short treal32totrealx3 // jump if denormal
1.1290 + _asm xor ecx, ecx // else return 0
1.1291 + _asm mov cl, ah // with same sign as input value
1.1292 + _asm ret
1.1293 + treal32totrealx3: // come here if denormal
1.1294 + _asm bsr ecx, edx // ecx=bit number of MSB of edx
1.1295 + _asm neg ecx
1.1296 + _asm add ecx, 31 // ecx=number of left shifts to normalise edx
1.1297 + _asm shl edx, cl // normalise
1.1298 + _asm neg ecx
1.1299 + _asm add ecx, 0x7F80 // exponent=7F80-number of shifts
1.1300 + _asm shl ecx, 16 // exponent into ecx bits 16-31
1.1301 + _asm mov cl, ah // sign into ecx bit 0
1.1302 + _asm ret
1.1303 + }
1.1304 +
1.1305 +__NAKED__ LOCAL_C void ConvertTReal64ToTRealX(void)
1.1306 + {
1.1307 + // Convert TReal64 in edx:ebx to TRealX in ecx:edx,ebx
1.1308 + _asm mov eax, edx
1.1309 + _asm shr eax, 20
1.1310 + _asm mov ecx, 0x7FF
1.1311 + _asm and ecx, eax // ecx=exponent
1.1312 + _asm jz short treal64totrealx1 // branch if zero/denormal
1.1313 + _asm add ecx, 0x7C00 // else bias exponent correctly for TRealX
1.1314 + _asm cmp ecx, 0x83FF // check for infinity/NaN
1.1315 + _asm jnz short treal64totrealx2
1.1316 + _asm mov ch, cl // if so, set exponent to FFFF
1.1317 + treal64totrealx2:
1.1318 + _asm shl ecx, 16 // exponent into ecx bits 16-31
1.1319 + _asm mov cl, 11 // number of shifts needed to justify mantissa correctly
1.1320 + _asm shld edx, ebx, cl // shift mantissa left
1.1321 + _asm shl ebx, cl
1.1322 + _asm or edx, 0x80000000 // put in implied integer bit
1.1323 + _asm shr eax, 11 // sign bit into al bit 0
1.1324 + _asm mov cl, al // into ecx bit 0
1.1325 + _asm ret
1.1326 + treal64totrealx1: // come here if zero/denormal
1.1327 + _asm mov cl, 12 // number of shifts needed to justify mantissa correctly
1.1328 + _asm shld edx, ebx, cl // shift mantissa left
1.1329 + _asm shl ebx, cl
1.1330 + _asm test edx, edx // check for zero
1.1331 + _asm jnz short treal64totrealx3
1.1332 + _asm test ebx, ebx
1.1333 + _asm jnz short treal64totrealx4
1.1334 + _asm shr eax, 11 // sign bit into eax bit 0, rest of eax=0
1.1335 + _asm mov ecx, eax // return 0 result with correct sign
1.1336 + _asm ret
1.1337 + treal64totrealx4: // come here if denormal, edx=0
1.1338 + _asm mov edx, ebx // shift mantissa left 32
1.1339 + _asm xor ebx, ebx
1.1340 + _asm bsr ecx, edx // ecx=bit number of MSB of edx
1.1341 + _asm neg ecx
1.1342 + _asm add ecx, 31 // ecx=number of left shifts to normalise edx
1.1343 + _asm shl edx, cl // normalise
1.1344 + _asm neg ecx
1.1345 + _asm add ecx, 0x7BE0 // exponent=7BE0-number of shifts
1.1346 + _asm shl ecx, 16 // exponent into bits 16-31 of ecx
1.1347 + _asm shr eax, 11
1.1348 + _asm mov cl, al // sign into bit 0 of ecx
1.1349 + _asm ret
1.1350 + treal64totrealx3: // come here if denormal, edx nonzero
1.1351 + _asm bsr ecx, edx // ecx=bit number of MSB of edx
1.1352 + _asm neg ecx
1.1353 + _asm add ecx, 31 // ecx=number of left shifts to normalise edx:ebx
1.1354 + _asm shld edx, ebx, cl // normalise
1.1355 + _asm shl ebx, cl
1.1356 + _asm neg ecx
1.1357 + _asm add ecx, 0x7C00 // exponent=7C00-number of shifts
1.1358 + _asm shl ecx, 16 // exponent into bits 16-31 of ecx
1.1359 + _asm shr eax, 11
1.1360 + _asm mov cl, al // sign into bit 0 of ecx
1.1361 + _asm ret
1.1362 + }
1.1363 +
1.1364 +
1.1365 +
1.1366 +
1.1367 +__NAKED__ EXPORT_C TInt TRealX::Set(TReal32 /*aReal*/)
1.1368 +/**
1.1369 +Gives this extended precision object a new value taken from
1.1370 +a single precision floating point number.
1.1371 +
1.1372 +@param aReal The single precision floating point value.
1.1373 +
1.1374 +@return KErrNone, if a valid number;
1.1375 + KErrOverflow, if the number is infinite;
1.1376 + KErrArgument, if not a number.
1.1377 +*/
1.1378 + {
1.1379 + // on entry, ecx=this and aReal is in [esp+4]
1.1380 + // on exit, error code in eax
1.1381 + _asm push ebx // save ebx
1.1382 + _asm push ecx // save this
1.1383 + _asm mov edx, [esp+12] // aReal into edx
1.1384 + _asm call ConvertTReal32ToTRealX
1.1385 + _asm pop eax // eax=this
1.1386 + _asm mov [eax], ebx // store result
1.1387 + _asm mov [eax+4], edx
1.1388 + _asm mov [eax+8], ecx
1.1389 + _asm xor eax, eax // error code=KErrNone initially
1.1390 + _asm cmp ecx, 0xFFFF0000 // check for infinity/NaN
1.1391 + _asm jb short trealxsettreal32a // if neither, return KErrNone
1.1392 + _asm mov eax, -9 // eax=KErrOverflow
1.1393 + _asm cmp edx, 0x80000000 // check for infinity
1.1394 + _asm je short trealxsettreal32a // if infinity, return KErrOverflow
1.1395 + _asm mov eax, -6 // if NaN, return KErrArgument
1.1396 + trealxsettreal32a:
1.1397 + _asm pop ebx
1.1398 + _asm ret 4
1.1399 + }
1.1400 +
1.1401 +
1.1402 +
1.1403 +
1.1404 +__NAKED__ EXPORT_C TInt TRealX::Set(TReal64 /*aReal*/)
1.1405 +/**
1.1406 +Gives this extended precision object a new value taken from
1.1407 +a double precision floating point number.
1.1408 +
1.1409 +@param aReal The double precision floating point value.
1.1410 +
1.1411 +@return KErrNone, if a valid number;
1.1412 + KErrOverflow, if the number is infinite;
1.1413 + KErrArgument, if not a number.
1.1414 +*/
1.1415 + {
1.1416 + // on entry, ecx=this and aReal is in [esp+4] (mant low) and [esp+8] (sign/exp/mant high)
1.1417 + // on exit, error code in eax
1.1418 + _asm push ebx // save ebx
1.1419 + _asm push ecx // save this
1.1420 + _asm mov ebx, [esp+12] // aReal into edx:ebx
1.1421 + _asm mov edx, [esp+16]
1.1422 + _asm call ConvertTReal64ToTRealX
1.1423 + _asm pop eax // eax=this
1.1424 + _asm mov [eax], ebx // store result
1.1425 + _asm mov [eax+4], edx
1.1426 + _asm mov [eax+8], ecx
1.1427 + _asm xor eax, eax // error code=KErrNone initially
1.1428 + _asm cmp ecx, 0xFFFF0000 // check for infinity/NaN
1.1429 + _asm jb short trealxsettreal64a // if neither, return KErrNone
1.1430 + _asm mov eax, -9 // eax=KErrOverflow
1.1431 + _asm cmp edx, 0x80000000 // check for infinity
1.1432 + _asm jne short trealxsettreal64b // branch if NaN
1.1433 + _asm test ebx, ebx
1.1434 + _asm je short trealxsettreal64a // if infinity, return KErrOverflow
1.1435 + trealxsettreal64b:
1.1436 + _asm mov eax, -6 // if NaN, return KErrArgument
1.1437 + trealxsettreal64a:
1.1438 + _asm pop ebx
1.1439 + _asm ret 8
1.1440 + }
1.1441 +
1.1442 +
1.1443 +
1.1444 +
1.1445 +__NAKED__ LOCAL_C void __6TRealXf()
1.1446 + {
1.1447 + // common function for float to TRealX
1.1448 + _asm push ebx // save ebx
1.1449 + _asm push ecx // save this
1.1450 + _asm mov edx, [esp+12] // aReal into edx
1.1451 + _asm call ConvertTReal32ToTRealX
1.1452 + _asm pop eax // eax=this
1.1453 + _asm mov [eax], ebx // store result
1.1454 + _asm mov [eax+4], edx
1.1455 + _asm mov [eax+8], ecx
1.1456 + _asm pop ebx
1.1457 + _asm ret 4
1.1458 + }
1.1459 +
1.1460 +
1.1461 +
1.1462 +
1.1463 +__NAKED__ EXPORT_C TRealX::TRealX(TReal32 /*aReal*/)
1.1464 +/**
1.1465 +Constructs an extended precision object from
1.1466 +a single precision floating point number.
1.1467 +
1.1468 +@param aReal The single precision floating point value.
1.1469 +*/
1.1470 + {
1.1471 + // on entry, ecx=this and aReal is in [esp+4]
1.1472 + // on exit, eax=this
1.1473 + _asm jmp __6TRealXf
1.1474 + }
1.1475 +
1.1476 +
1.1477 +
1.1478 +
1.1479 +__NAKED__ EXPORT_C TRealX& TRealX::operator=(TReal32 /*aReal*/)
1.1480 +/**
1.1481 +Assigns the specified single precision floating point number to
1.1482 +this extended precision object.
1.1483 +
1.1484 +@param aReal The single precision floating point value.
1.1485 +
1.1486 +@return A reference to this extended precision object.
1.1487 +*/
1.1488 + {
1.1489 + // on entry, ecx=this and aReal is in [esp+4]
1.1490 + // on exit, eax=this
1.1491 + _asm jmp __6TRealXf
1.1492 + }
1.1493 +
1.1494 +
1.1495 +
1.1496 +
1.1497 +__NAKED__ LOCAL_C void __6TRealXd()
1.1498 + {
1.1499 + // common function for double to TRealX
1.1500 + _asm push ebx // save ebx
1.1501 + _asm push ecx // save this
1.1502 + _asm mov ebx, [esp+12] // aReal into edx:ebx
1.1503 + _asm mov edx, [esp+16]
1.1504 + _asm call ConvertTReal64ToTRealX
1.1505 + _asm pop eax // eax=this
1.1506 + _asm mov [eax], ebx // store result
1.1507 + _asm mov [eax+4], edx
1.1508 + _asm mov [eax+8], ecx
1.1509 + _asm pop ebx
1.1510 + _asm ret 8
1.1511 + }
1.1512 +
1.1513 +
1.1514 +
1.1515 +
1.1516 +__NAKED__ EXPORT_C TRealX::TRealX(TReal64 /*aReal*/)
1.1517 +/**
1.1518 +Constructs an extended precision object from
1.1519 +a double precision floating point number.
1.1520 +
1.1521 +@param aReal The double precision floating point value.
1.1522 +*/
1.1523 + {
1.1524 + // on entry, ecx=this and aReal is in [esp+4] (mant low) and [esp+8] (sign/exp/mant high)
1.1525 + // on exit, eax=this
1.1526 + _asm jmp __6TRealXd
1.1527 + }
1.1528 +
1.1529 +
1.1530 +
1.1531 +
1.1532 +__NAKED__ EXPORT_C TRealX& TRealX::operator=(TReal64 /*aReal*/)
1.1533 +/**
1.1534 +Assigns the specified double precision floating point number to
1.1535 +this extended precision object.
1.1536 +
1.1537 +@param aReal The double precision floating point value.
1.1538 +
1.1539 +@return A reference to this extended precision object.
1.1540 +*/
1.1541 + {
1.1542 + // on entry, ecx=this and aReal is in [esp+4] (mant low) and [esp+8] (sign/exp/mant high)
1.1543 + // on exit, eax=this
1.1544 + _asm jmp __6TRealXd
1.1545 + }
1.1546 +
1.1547 +
1.1548 +
1.1549 +
1.1550 +__NAKED__ EXPORT_C TRealX::operator TInt() const
1.1551 +/**
1.1552 +Gets the extended precision value as a signed integer value.
1.1553 +
1.1554 +The operator returns:
1.1555 +
1.1556 +1. zero , if the extended precision value is not a number
1.1557 +
1.1558 +2. 0x7FFFFFFF, if the value is positive and too big to fit into a TInt.
1.1559 +
1.1560 +3. 0x80000000, if the value is negative and too big to fit into a TInt.
1.1561 +*/
1.1562 + {
1.1563 + // on entry ecx=this, return value in eax
1.1564 + _asm mov edx, [ecx] // edx=mantissa low
1.1565 + _asm mov eax, [ecx+4] // eax=mantissa high
1.1566 + _asm mov ecx, [ecx+8] // ecx=exponent/sign
1.1567 + _asm ror ecx, 16 // exponent into cx
1.1568 + _asm cmp cx, 0xFFFF
1.1569 + _asm jz short trealxtoint1 // branch if exp=FFFF
1.1570 + _asm mov dx, cx
1.1571 + _asm mov cx, 0x801E
1.1572 + _asm sub cx, dx // cx=number of right shifts needed to convert mantissa to int
1.1573 + _asm jbe short trealxtoint2 // if exp>=801E, saturate result
1.1574 + _asm cmp cx, 31 // more than 31 shifts needed?
1.1575 + _asm ja short trealxtoint0 // if so, underflow to zero
1.1576 + _asm shr eax, cl // else ABS(result)=eax>>cl
1.1577 + _asm test ecx, 0x10000 // test sign
1.1578 + _asm jz short trealxtoint3 // skip if +
1.1579 + _asm neg eax
1.1580 + trealxtoint3:
1.1581 + _asm ret
1.1582 + trealxtoint1: // come here if exponent=FFFF
1.1583 + _asm cmp eax, 0x80000000 // check for infinity
1.1584 + _asm jnz short trealxtoint0 // if NaN, return 0
1.1585 + _asm test edx, edx
1.1586 + _asm jnz short trealxtoint0 // if NaN, return 0
1.1587 + trealxtoint2: // come here if argument too big for 32-bit integer
1.1588 + _asm mov eax, 0x7FFFFFFF
1.1589 + _asm shr ecx, 17 // sign bit into carry flag
1.1590 + _asm adc eax, 0 // eax=7FFFFFFF if +, 80000000 if -
1.1591 + _asm ret // return saturated value
1.1592 + trealxtoint0: // come here if INT(argument)=0 or NaN
1.1593 + _asm xor eax, eax // return 0
1.1594 + _asm ret
1.1595 + }
1.1596 +
1.1597 +
1.1598 +
1.1599 +
1.1600 +__NAKED__ EXPORT_C TRealX::operator TUint() const
1.1601 +/**
1.1602 +Returns the extended precision value as an unsigned signed integer value.
1.1603 +
1.1604 +The operator returns:
1.1605 +
1.1606 +1. zero, if the extended precision value is not a number
1.1607 +
1.1608 +2. 0xFFFFFFFF, if the value is positive and too big to fit into a TUint.
1.1609 +
1.1610 +3. zero, if the value is negative and too big to fit into a TUint.
1.1611 +*/
1.1612 + {
1.1613 + // on entry ecx=this, return value in eax
1.1614 + _asm mov edx, [ecx] // edx=mantissa low
1.1615 + _asm mov eax, [ecx+4] // eax=mantissa high
1.1616 + _asm mov ecx, [ecx+8] // ecx=exponent/sign
1.1617 + _asm ror ecx, 16 // exponent into cx
1.1618 + _asm cmp cx, 0xFFFF
1.1619 + _asm jz short trealxtouint1 // branch if exp=FFFF
1.1620 + _asm mov dx, cx
1.1621 + _asm mov cx, 0x801E
1.1622 + _asm sub cx, dx // cx=number of right shifts needed to convert mantissa to int
1.1623 + _asm jb short trealxtouint2 // if exp>801E, saturate result
1.1624 + _asm cmp cx, 31 // more than 31 shifts needed?
1.1625 + _asm ja short trealxtouint0 // if so, underflow to zero
1.1626 + _asm test ecx, 0x10000 // test sign
1.1627 + _asm jnz short trealxtouint0 // if -, return 0
1.1628 + _asm shr eax, cl // else result=eax>>cl
1.1629 + _asm ret
1.1630 + trealxtouint1: // come here if exponent=FFFF
1.1631 + _asm cmp eax, 0x80000000 // check for infinity
1.1632 + _asm jnz short trealxtouint0 // if NaN, return 0
1.1633 + _asm test edx, edx
1.1634 + _asm jnz short trealxtouint0 // if NaN, return 0
1.1635 + trealxtouint2: // come here if argument too big for 32-bit integer
1.1636 + _asm mov eax, 0xFFFFFFFF
1.1637 + _asm shr ecx, 17 // sign bit into carry flag
1.1638 + _asm adc eax, 0 // eax=FFFFFFFF if +, 0 if -
1.1639 + _asm ret // return saturated value
1.1640 + trealxtouint0: // come here if INT(argument)=0 or NaN
1.1641 + _asm xor eax, eax // return 0
1.1642 + _asm ret
1.1643 + }
1.1644 +
1.1645 +
1.1646 +
1.1647 +
1.1648 +__NAKED__ LOCAL_C void ConvertTRealXToTInt64(void)
1.1649 + {
1.1650 + // Convert TRealX in ecx,edx:ebx to TInt64 in edx:ebx
1.1651 + _asm ror ecx, 16 // exponent into cx
1.1652 + _asm cmp cx, 0xFFFF
1.1653 + _asm jz short trealxtoint64a // branch if exp=FFFF
1.1654 + _asm mov ax, cx
1.1655 + _asm mov cx, 0x803E
1.1656 + _asm sub cx, ax // cx=number of right shifts needed to convert mantissa to int
1.1657 + _asm jbe short trealxtoint64b // if exp>=803E, saturate result
1.1658 + _asm cmp cx, 63 // more than 63 shifts needed?
1.1659 + _asm ja short trealxtoint64z // if so, underflow to zero
1.1660 + _asm cmp cl, 31 // more than 31 shifts needed?
1.1661 + _asm jbe short trealxtoint64d // branch if not
1.1662 + _asm sub cl, 32 // cl=shift count - 32
1.1663 + _asm mov ebx, edx // shift right by 32
1.1664 + _asm xor edx, edx
1.1665 + trealxtoint64d:
1.1666 + _asm shrd ebx, edx, cl // shift edx:ebx right by cl to give ABS(result)
1.1667 + _asm shr edx, cl
1.1668 + _asm test ecx, 0x10000 // test sign
1.1669 + _asm jz short trealxtoint64c // skip if +
1.1670 + _asm neg edx // if -, negate
1.1671 + _asm neg ebx
1.1672 + _asm sbb edx, 0
1.1673 + trealxtoint64c:
1.1674 + _asm ret
1.1675 + trealxtoint64a: // come here if exponent=FFFF
1.1676 + _asm cmp edx, 0x80000000 // check for infinity
1.1677 + _asm jnz short trealxtoint64z // if NaN, return 0
1.1678 + _asm test ebx, ebx
1.1679 + _asm jnz short trealxtoint64z // if NaN, return 0
1.1680 + trealxtoint64b: // come here if argument too big for 32-bit integer
1.1681 + _asm mov edx, 0x7FFFFFFF
1.1682 + _asm mov ebx, 0xFFFFFFFF
1.1683 + _asm shr ecx, 17 // sign bit into carry flag
1.1684 + _asm adc ebx, 0 // edx:ebx=7FFFFFFF FFFFFFFF if +,
1.1685 + _asm adc edx, 0 // or 80000000 00000000 if -
1.1686 + _asm ret // return saturated value
1.1687 + trealxtoint64z: // come here if INT(argument)=0 or NaN
1.1688 + _asm xor edx, edx // return 0
1.1689 + _asm xor ebx, ebx
1.1690 + _asm ret
1.1691 + }
1.1692 +
1.1693 +
1.1694 +
1.1695 +
1.1696 +/**
1.1697 +Returns the extended precision value as a 64 bit integer value.
1.1698 +
1.1699 +The operator returns:
1.1700 +
1.1701 +1. zero, if the extended precision value is not a number
1.1702 +
1.1703 +2. 0x7FFFFFFF FFFFFFFF, if the value is positive and too big to fit
1.1704 + into a TInt64
1.1705 +
1.1706 +3. 0x80000000 00000000, if the value is negative and too big to fit
1.1707 + into a TInt64.
1.1708 +*/
1.1709 +__NAKED__ EXPORT_C TRealX::operator TInt64() const
1.1710 + {
1.1711 + // on entry, ecx=this, return value in edx:eax
1.1712 + _asm push ebx
1.1713 + _asm mov ebx, [ecx] // get TRealX value into ecx,edx:ebx
1.1714 + _asm mov edx, [ecx+4]
1.1715 + _asm mov ecx, [ecx+8]
1.1716 + _asm call ConvertTRealXToTInt64
1.1717 + _asm mov eax, ebx // store low result into eax
1.1718 + _asm pop ebx
1.1719 + _asm ret
1.1720 + }
1.1721 +
1.1722 +
1.1723 +
1.1724 +
1.1725 +__NAKED__ LOCAL_C void TRealXGetTReal32(void)
1.1726 + {
1.1727 + // Convert TRealX in ecx,edx:ebx to TReal32 in edx
1.1728 + // Return error code in eax
1.1729 + _asm cmp ecx, 0xFFFF0000 // check for infinity/NaN
1.1730 + _asm jnc short trealxgettreal32a
1.1731 + _asm xor eax, eax
1.1732 + _asm ror ecx, 16 // exponent into cx
1.1733 + _asm sub cx, 0x7F80 // cx=result exponent if normalised
1.1734 + _asm jbe short trealxgettreal32b // jump if denormal, zero or underflow
1.1735 + _asm cmp cx, 0xFF // check if overflow
1.1736 + _asm jb short trealxgettreal32c // jump if not
1.1737 + trealxgettreal32d: // come here if overflow
1.1738 + _asm xor edx, edx // set mantissa=0 to generate infinity
1.1739 + _asm ror ecx, 16 // ecx back to normal format
1.1740 + trealxgettreal32a: // come here if infinity or NaN
1.1741 + _asm shr edx, 7
1.1742 + _asm or edx, 0xFF000000 // set exponent to FF
1.1743 + _asm shr ecx, 1 // sign bit -> carry
1.1744 + _asm rcr edx, 1 // sign bit -> MSB of result
1.1745 + _asm mov eax, edx
1.1746 + _asm shl eax, 9 // test for infinity or NaN
1.1747 + _asm mov eax, -9 // eax=KErrOverflow
1.1748 + _asm jz short trealxgettreal32e
1.1749 + _asm mov eax, -6 // if NaN, eax=KErrArgument
1.1750 + trealxgettreal32e:
1.1751 + _asm ret
1.1752 + trealxgettreal32b: // come here if exponent<=7F80
1.1753 + _asm cmp cx, -24 // check for zero or total underflow
1.1754 + _asm jle short trealxgettreal32z
1.1755 + _asm neg cl
1.1756 + _asm inc cl // cl=number of right shifts to form denormal mantissa
1.1757 + _asm shrd eax, ebx, cl // shift mantissa right into eax
1.1758 + _asm shrd ebx, edx, cl
1.1759 + _asm shr edx, cl
1.1760 + _asm or edx, 0x80000000 // set top bit to ensure correct rounding up
1.1761 + _asm xor cl, cl // cl=result exponent=0
1.1762 + trealxgettreal32c: // come here if result normalised
1.1763 + _asm cmp dl, 0x80 // check rounding bits
1.1764 + _asm ja short trealxgettreal32f // branch to round up
1.1765 + _asm jb short trealxgettreal32g // branch to round down
1.1766 + _asm test ebx, ebx
1.1767 + _asm jnz short trealxgettreal32f // branch to round up
1.1768 + _asm test eax, eax
1.1769 + _asm jnz short trealxgettreal32f // branch to round up
1.1770 + _asm test ecx, 0x01000000 // check rounded-down flag
1.1771 + _asm jnz short trealxgettreal32f // branch to round up
1.1772 + _asm test ecx, 0x02000000 // check rounded-up flag
1.1773 + _asm jnz short trealxgettreal32g // branch to round down
1.1774 + _asm test dh, 1 // else round to even
1.1775 + _asm jz short trealxgettreal32g // branch to round down if LSB=0
1.1776 + trealxgettreal32f: // come here to round up
1.1777 + _asm add edx, 0x100 // increment mantissa
1.1778 + _asm jnc short trealxgettreal32g
1.1779 + _asm rcr edx, 1
1.1780 + _asm inc cl // if carry, increment exponent
1.1781 + _asm cmp cl, 0xFF // and check for overflow
1.1782 + _asm jz short trealxgettreal32d // branch out if overflow
1.1783 + trealxgettreal32g: // come here to round down
1.1784 + _asm xor dl, dl
1.1785 + _asm add edx, edx // shift out integer bit
1.1786 + _asm mov dl, cl
1.1787 + _asm ror edx, 8 // exponent->edx bits 24-31, mantissa in 23-1
1.1788 + _asm test edx, edx // check if underflow
1.1789 + _asm jz short trealxgettreal32h // branch out if underflow
1.1790 + _asm shr ecx, 17 // sign bit->carry
1.1791 + _asm rcr edx, 1 // ->edx bit 31, exp->edx bits 23-30, mant->edx bits 22-0
1.1792 + _asm xor eax, eax // return KErrNone
1.1793 + _asm ret
1.1794 + trealxgettreal32z: // come here if zero or underflow
1.1795 + _asm xor eax, eax
1.1796 + _asm cmp cx, 0x8080 // check for zero
1.1797 + _asm jz short trealxgettreal32y // if zero, return KErrNone
1.1798 + trealxgettreal32h: // come here if underflow after rounding
1.1799 + _asm mov eax, -10 // eax=KErrUnderflow
1.1800 + trealxgettreal32y:
1.1801 + _asm xor edx, edx
1.1802 + _asm shr ecx, 17
1.1803 + _asm rcr edx, 1 // sign bit into edx bit 31, rest of edx=0
1.1804 + _asm ret
1.1805 + }
1.1806 +
1.1807 +
1.1808 +
1.1809 +
1.1810 +__NAKED__ LOCAL_C void TRealXGetTReal64(void)
1.1811 + {
1.1812 + // Convert TRealX in ecx,edx:ebx to TReal64 in edx:ebx
1.1813 + // Return error code in eax
1.1814 + // edi, esi also modified
1.1815 + _asm ror ecx, 16 // exponent into cx
1.1816 + _asm cmp cx, 0xFFFF // check for infinity/NaN
1.1817 + _asm jnc short trealxgettreal64a
1.1818 + _asm xor eax, eax
1.1819 + _asm xor edi, edi
1.1820 + _asm sub cx, 0x7C00 // cx=result exponent if normalised
1.1821 + _asm jbe short trealxgettreal64b // jump if denormal, zero or underflow
1.1822 + _asm cmp cx, 0x07FF // check if overflow
1.1823 + _asm jb short trealxgettreal64c // jump if not
1.1824 + trealxgettreal64d: // come here if overflow
1.1825 + _asm xor edx, edx // set mantissa=0 to generate infinity
1.1826 + _asm xor ebx, ebx
1.1827 + trealxgettreal64a: // come here if infinity or NaN
1.1828 + _asm mov cl, 10
1.1829 + _asm shrd ebx, edx, cl
1.1830 + _asm shr edx, cl
1.1831 + _asm or edx, 0xFFE00000 // set exponent to 7FF
1.1832 + _asm shr ecx, 17 // sign bit -> carry
1.1833 + _asm rcr edx, 1 // sign bit -> MSB of result
1.1834 + _asm rcr ebx, 1
1.1835 + _asm mov eax, edx
1.1836 + _asm shl eax, 12 // test for infinity or NaN
1.1837 + _asm mov eax, -9 // eax=KErrOverflow
1.1838 + _asm jnz short trealxgettreal64n
1.1839 + _asm test ebx, ebx
1.1840 + _asm jz short trealxgettreal64e
1.1841 + trealxgettreal64n:
1.1842 + _asm mov eax, -6 // if NaN, eax=KErrArgument
1.1843 + trealxgettreal64e:
1.1844 + _asm ret
1.1845 + trealxgettreal64b: // come here if exponent<=7C00
1.1846 + _asm cmp cx, -53 // check for zero or total underflow
1.1847 + _asm jle trealxgettreal64z
1.1848 + _asm neg cl
1.1849 + _asm inc cl // cl=number of right shifts to form denormal mantissa
1.1850 + _asm cmp cl, 32
1.1851 + _asm jb trealxgettreal64x
1.1852 + _asm mov eax, ebx // if >=32 shifts, do 32 shifts and decrement count by 32
1.1853 + _asm mov ebx, edx
1.1854 + _asm xor edx, edx
1.1855 + trealxgettreal64x:
1.1856 + _asm shrd edi, eax, cl
1.1857 + _asm shrd eax, ebx, cl // shift mantissa right into eax
1.1858 + _asm shrd ebx, edx, cl
1.1859 + _asm shr edx, cl
1.1860 + _asm or edx, 0x80000000 // set top bit to ensure correct rounding up
1.1861 + _asm xor cx, cx // cx=result exponent=0
1.1862 + trealxgettreal64c: // come here if result normalised
1.1863 + _asm mov esi, ebx
1.1864 + _asm and esi, 0x7FF // esi=rounding bits
1.1865 + _asm cmp esi, 0x400 // check rounding bits
1.1866 + _asm ja short trealxgettreal64f // branch to round up
1.1867 + _asm jb short trealxgettreal64g // branch to round down
1.1868 + _asm test eax, eax
1.1869 + _asm jnz short trealxgettreal64f // branch to round up
1.1870 + _asm test edi, edi
1.1871 + _asm jnz short trealxgettreal64f // branch to round up
1.1872 + _asm test ecx, 0x01000000 // check rounded-down flag
1.1873 + _asm jnz short trealxgettreal64f // branch to round up
1.1874 + _asm test ecx, 0x02000000 // check rounded-up flag
1.1875 + _asm jnz short trealxgettreal64g // branch to round down
1.1876 + _asm test ebx, 0x800 // else round to even
1.1877 + _asm jz short trealxgettreal64g // branch to round down if LSB=0
1.1878 + trealxgettreal64f: // come here to round up
1.1879 + _asm add ebx, 0x800 // increment mantissa
1.1880 + _asm adc edx, 0
1.1881 + _asm jnc short trealxgettreal64g
1.1882 + _asm rcr edx, 1
1.1883 + _asm inc cx // if carry, increment exponent
1.1884 + _asm cmp cx, 0x7FF // and check for overflow
1.1885 + _asm jz trealxgettreal64d // branch out if overflow
1.1886 + trealxgettreal64g: // come here to round down
1.1887 + _asm xor bl, bl // clear rounding bits
1.1888 + _asm and bh, 0xF8
1.1889 + _asm mov di, cx // save exponent
1.1890 + _asm mov cl, 10
1.1891 + _asm and edx, 0x7FFFFFFF // clear integer bit
1.1892 + _asm shrd ebx, edx, cl // shift mantissa right by 10
1.1893 + _asm shr edx, cl
1.1894 + _asm shl edi, 21 // exponent into edi bits 21-31
1.1895 + _asm or edx, edi // into edx bits 21-31
1.1896 + _asm test edx, edx // check if underflow
1.1897 + _asm jnz short trealxgettreal64i
1.1898 + _asm test ebx, ebx
1.1899 + _asm jz short trealxgettreal64h // branch out if underflow
1.1900 + trealxgettreal64i:
1.1901 + _asm shr ecx, 17 // sign bit->carry
1.1902 + _asm rcr edx, 1 // ->edx bit 31, exp->edx bits 20-30, mant->edx bits 20-0
1.1903 + _asm rcr ebx, 1
1.1904 + _asm xor eax, eax // return KErrNone
1.1905 + _asm ret
1.1906 + trealxgettreal64z: // come here if zero or underflow
1.1907 + _asm xor eax, eax
1.1908 + _asm cmp cx, 0x8400 // check for zero
1.1909 + _asm jz short trealxgettreal64y // if zero, return KErrNone
1.1910 + trealxgettreal64h: // come here if underflow after rounding
1.1911 + _asm mov eax, -10 // eax=KErrUnderflow
1.1912 + trealxgettreal64y:
1.1913 + _asm xor edx, edx
1.1914 + _asm xor ebx, ebx
1.1915 + _asm shr ecx, 17
1.1916 + _asm rcr edx, 1 // sign bit into edx bit 31, rest of edx=0, ebx=0
1.1917 + _asm ret
1.1918 + }
1.1919 +
1.1920 +
1.1921 +
1.1922 +
1.1923 +__NAKED__ EXPORT_C TRealX::operator TReal32() const
1.1924 +/**
1.1925 +Returns the extended precision value as
1.1926 +a single precision floating point value.
1.1927 +*/
1.1928 + {
1.1929 + // On entry, ecx=this
1.1930 + // On exit, TReal32 value on top of FPU stack
1.1931 + _asm push ebx
1.1932 + _asm mov ebx, [ecx] // *this into ecx,edx:ebx
1.1933 + _asm mov edx, [ecx+4]
1.1934 + _asm mov ecx, [ecx+8]
1.1935 + _asm call TRealXGetTReal32 // Convert to TReal32 in edx
1.1936 + _asm push edx // push TReal32 onto stack
1.1937 + _asm fld dword ptr [esp] // push TReal32 onto FPU stack
1.1938 + _asm pop edx
1.1939 + _asm pop ebx
1.1940 + _asm ret
1.1941 + }
1.1942 +
1.1943 +
1.1944 +
1.1945 +
1.1946 +__NAKED__ EXPORT_C TRealX::operator TReal64() const
1.1947 +/**
1.1948 +Returns the extended precision value as
1.1949 +a double precision floating point value.
1.1950 +*/
1.1951 + {
1.1952 + // On entry, ecx=this
1.1953 + // On exit, TReal64 value on top of FPU stack
1.1954 + _asm push ebx
1.1955 + _asm push esi
1.1956 + _asm push edi
1.1957 + _asm mov ebx, [ecx] // *this into ecx,edx:ebx
1.1958 + _asm mov edx, [ecx+4]
1.1959 + _asm mov ecx, [ecx+8]
1.1960 + _asm call TRealXGetTReal64 // Convert to TReal32 in edx:ebx
1.1961 + _asm push edx // push TReal64 onto stack
1.1962 + _asm push ebx
1.1963 + _asm fld qword ptr [esp] // push TReal64 onto FPU stack
1.1964 + _asm add esp, 8
1.1965 + _asm pop edi
1.1966 + _asm pop esi
1.1967 + _asm pop ebx
1.1968 + _asm ret
1.1969 + }
1.1970 +
1.1971 +
1.1972 +
1.1973 +
1.1974 +__NAKED__ EXPORT_C TInt TRealX::GetTReal(TReal32& /*aVal*/) const
1.1975 +/**
1.1976 +Extracts the extended precision value as
1.1977 +a single precision floating point value.
1.1978 +
1.1979 +@param aVal A reference to a single precision object which contains
1.1980 + the result of the operation.
1.1981 +
1.1982 +@return KErrNone, if the operation is successful;
1.1983 + KErrOverflow, if the operation results in overflow;
1.1984 + KErrUnderflow, if the operation results in underflow.
1.1985 +*/
1.1986 + {
1.1987 + // On entry, ecx=this, [esp+4]=address of aVal
1.1988 + // On exit, eax=return code
1.1989 + _asm push ebx
1.1990 + _asm mov ebx, [ecx] // *this into ecx,edx:ebx
1.1991 + _asm mov edx, [ecx+4]
1.1992 + _asm mov ecx, [ecx+8]
1.1993 + _asm call TRealXGetTReal32
1.1994 + _asm mov ecx, [esp+8] // ecx=address of aVal
1.1995 + _asm mov [ecx], edx // store result
1.1996 + _asm pop ebx
1.1997 + _asm ret 4 // return with error code in eax
1.1998 + }
1.1999 +
1.2000 +
1.2001 +
1.2002 +
1.2003 +__NAKED__ EXPORT_C TInt TRealX::GetTReal(TReal64& /*aVal*/) const
1.2004 +/**
1.2005 +Extracts the extended precision value as
1.2006 +a double precision floating point value.
1.2007 +
1.2008 +@param aVal A reference to a double precision object which
1.2009 + contains the result of the operation.
1.2010 +
1.2011 +@return KErrNone, if the operation is successful;
1.2012 + KErrOverflow, if the operation results in overflow;
1.2013 + KErrUnderflow, if the operation results in underflow.
1.2014 +*/
1.2015 + {
1.2016 + // On entry, ecx=this, [esp+4]=address of aVal
1.2017 + // On exit, eax=return code
1.2018 + _asm push ebx
1.2019 + _asm push esi
1.2020 + _asm push edi
1.2021 + _asm mov ebx, [ecx] // *this into ecx,edx:ebx
1.2022 + _asm mov edx, [ecx+4]
1.2023 + _asm mov ecx, [ecx+8]
1.2024 + _asm call TRealXGetTReal64
1.2025 + _asm mov ecx, [esp+16] // ecx=address of aVal
1.2026 + _asm mov [ecx], ebx // store result
1.2027 + _asm mov [ecx+4], edx
1.2028 + _asm pop edi
1.2029 + _asm pop esi
1.2030 + _asm pop ebx
1.2031 + _asm ret 4 // return with error code in eax
1.2032 + }
1.2033 +
1.2034 +
1.2035 +
1.2036 +
1.2037 +__NAKED__ EXPORT_C void TRealX::SetZero(TBool /*aNegative*/)
1.2038 +/**
1.2039 +Sets the value of this extended precision object to zero.
1.2040 +
1.2041 +@param aNegative ETrue, the value is a negative zero;
1.2042 + EFalse, the value is a positive zero, this is the default.
1.2043 +*/
1.2044 + {
1.2045 + _asm mov edx, [esp+4] // aNegative into edx
1.2046 + _asm xor eax, eax // eax=0
1.2047 + _asm mov [ecx], eax
1.2048 + _asm mov [ecx+4], eax
1.2049 + _asm test edx, edx
1.2050 + _asm jz short setzero1
1.2051 + _asm inc eax // eax=1 if aNegative!=0
1.2052 + setzero1:
1.2053 + _asm mov [ecx+8], eax // generate positive or negative zero
1.2054 + _asm ret 4
1.2055 + }
1.2056 +
1.2057 +
1.2058 +
1.2059 +
1.2060 +__NAKED__ EXPORT_C void TRealX::SetNaN()
1.2061 +/**
1.2062 +Sets the value of this extended precision object to 'not a number'.
1.2063 +*/
1.2064 + {
1.2065 + _asm xor eax, eax // set *this to 'real indefinite'
1.2066 + _asm mov [ecx], eax
1.2067 + _asm mov eax, 0xC0000000
1.2068 + _asm mov [ecx+4], eax
1.2069 + _asm mov eax, 0xFFFF0001
1.2070 + _asm mov [ecx+8], eax
1.2071 + _asm ret
1.2072 + }
1.2073 +
1.2074 +
1.2075 +
1.2076 +
1.2077 +__NAKED__ EXPORT_C void TRealX::SetInfinite(TBool /*aNegative*/)
1.2078 +/**
1.2079 +Sets the value of this extended precision object to infinity.
1.2080 +
1.2081 +@param aNegative ETrue, the value is a negative zero;
1.2082 + EFalse, the value is a positive zero.
1.2083 +*/
1.2084 + {
1.2085 + _asm mov edx, [esp+4] // aNegative into edx
1.2086 + _asm mov eax, 0xFFFF0000 // exponent=FFFF, sign=0 initially
1.2087 + _asm test edx, edx
1.2088 + _asm jz short setinf1
1.2089 + _asm inc eax // sign=1 if aNegative!=0
1.2090 + setinf1:
1.2091 + _asm mov [ecx+8], eax // generate positive or negative infinity
1.2092 + _asm mov eax, 0x80000000
1.2093 + _asm mov [ecx+4], eax
1.2094 + _asm xor eax, eax
1.2095 + _asm mov [ecx], eax
1.2096 + _asm ret 4
1.2097 + }
1.2098 +
1.2099 +
1.2100 +
1.2101 +
1.2102 +__NAKED__ EXPORT_C TBool TRealX::IsZero() const
1.2103 +/**
1.2104 +Determines whether the extended precision value is zero.
1.2105 +
1.2106 +@return True, if the extended precision value is zero, false, otherwise.
1.2107 +*/
1.2108 + {
1.2109 + _asm mov eax, [ecx+8] // check exponent
1.2110 + _asm shr eax, 16 // move exponent into ax
1.2111 + _asm jz short iszero1 // branch if zero
1.2112 + _asm xor eax, eax // else return 0
1.2113 + _asm ret
1.2114 + iszero1:
1.2115 + _asm inc eax // if zero, return 1
1.2116 + _asm ret
1.2117 + }
1.2118 +
1.2119 +
1.2120 +
1.2121 +
1.2122 +__NAKED__ EXPORT_C TBool TRealX::IsNaN() const
1.2123 +/**
1.2124 +Determines whether the extended precision value is 'not a number'.
1.2125 +
1.2126 +@return True, if the extended precision value is 'not a number',
1.2127 + false, otherwise.
1.2128 +*/
1.2129 + {
1.2130 + _asm mov eax, [ecx+8] // check exponent
1.2131 + _asm cmp eax, 0xFFFF0000
1.2132 + _asm jc short isnan0 // branch if not FFFF
1.2133 + _asm mov eax, [ecx+4]
1.2134 + _asm cmp eax, 0x80000000 // check for infinity
1.2135 + _asm jne short isnan1
1.2136 + _asm mov eax, [ecx]
1.2137 + _asm test eax, eax
1.2138 + _asm jne short isnan1
1.2139 + isnan0:
1.2140 + _asm xor eax, eax // return 0 if not NaN
1.2141 + _asm ret
1.2142 + isnan1:
1.2143 + _asm mov eax, 1 // return 1 if NaN
1.2144 + _asm ret
1.2145 + }
1.2146 +
1.2147 +
1.2148 +
1.2149 +
1.2150 +__NAKED__ EXPORT_C TBool TRealX::IsInfinite() const
1.2151 +/**
1.2152 +Determines whether the extended precision value has a finite value.
1.2153 +
1.2154 +@return True, if the extended precision value is finite,
1.2155 + false, if the value is 'not a number' or is infinite,
1.2156 +*/
1.2157 + {
1.2158 + _asm mov eax, [ecx+8] // check exponent
1.2159 + _asm cmp eax, 0xFFFF0000
1.2160 + _asm jc short isinf0 // branch if not FFFF
1.2161 + _asm mov eax, [ecx+4]
1.2162 + _asm cmp eax, 0x80000000 // check for infinity
1.2163 + _asm jne short isinf0
1.2164 + _asm mov eax, [ecx]
1.2165 + _asm test eax, eax
1.2166 + _asm jne short isinf0
1.2167 + _asm inc eax // return 1 if infinity
1.2168 + _asm ret
1.2169 + isinf0:
1.2170 + _asm xor eax, eax // return 0 if not infinity
1.2171 + _asm ret
1.2172 + }
1.2173 +
1.2174 +
1.2175 +
1.2176 +
1.2177 +__NAKED__ EXPORT_C TBool TRealX::IsFinite() const
1.2178 +/**
1.2179 +Determines whether the extended precision value has a finite value.
1.2180 +
1.2181 +@return True, if the extended precision value is finite,
1.2182 + false, if the value is 'not a number' or is infinite,
1.2183 +*/
1.2184 + {
1.2185 + _asm mov eax, [ecx+8] // check exponent
1.2186 + _asm cmp eax, 0xFFFF0000 // check for NaN or infinity
1.2187 + _asm jnc short isfinite0 // branch if NaN or infinity
1.2188 + _asm mov eax, 1 // return 1 if finite
1.2189 + _asm ret
1.2190 + isfinite0:
1.2191 + _asm xor eax, eax // return 0 if NaN or infinity
1.2192 + _asm ret
1.2193 + }
1.2194 +
1.2195 +
1.2196 +
1.2197 +
1.2198 +__NAKED__ EXPORT_C const TRealX& TRealX::operator+=(const TRealX& /*aVal*/)
1.2199 +/**
1.2200 +Adds an extended precision value to this extended precision number.
1.2201 +
1.2202 +@param aVal The extended precision value to be added.
1.2203 +
1.2204 +@return A reference to this object.
1.2205 +
1.2206 +@panic MATHX KErrOverflow if the operation results in overflow.
1.2207 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2208 +*/
1.2209 + {
1.2210 + // on entry ecx=this, [esp+4]=address of aVal
1.2211 + _asm push ebx // save registers
1.2212 + _asm push ebp
1.2213 + _asm push esi
1.2214 + _asm push edi
1.2215 + _asm mov esi, ecx // this into esi
1.2216 + _asm mov ecx, [esp+20] // address of aVal into ecx
1.2217 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2218 + _asm mov edx, [ecx+4]
1.2219 + _asm mov ecx, [ecx+8]
1.2220 + _asm call TRealXAdd // do addition, result in ecx,edx:ebx, error code in eax
1.2221 + _asm mov [esi], ebx // store result in *this
1.2222 + _asm mov [esi+4], edx
1.2223 + _asm mov [esi+8], ecx
1.2224 + _asm test eax, eax
1.2225 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2226 + _asm mov eax, esi // return this in eax
1.2227 + _asm pop edi // restore registers
1.2228 + _asm pop esi
1.2229 + _asm pop ebp
1.2230 + _asm pop ebx
1.2231 + _asm ret 4
1.2232 + }
1.2233 +
1.2234 +
1.2235 +
1.2236 +
1.2237 +__NAKED__ EXPORT_C const TRealX& TRealX::operator-=(const TRealX& /*aVal*/)
1.2238 +/**
1.2239 +Subtracts an extended precision value from this extended precision number.
1.2240 +
1.2241 +@param aVal The extended precision value to be subtracted.
1.2242 +
1.2243 +@return A reference to this object.
1.2244 +
1.2245 +@panic MATHX KErrOverflow if the operation results in overflow.
1.2246 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2247 +*/
1.2248 + {
1.2249 + // on entry ecx=this, [esp+4]=address of aVal
1.2250 + _asm push ebx // save registers
1.2251 + _asm push ebp
1.2252 + _asm push esi
1.2253 + _asm push edi
1.2254 + _asm mov esi, ecx // this into esi
1.2255 + _asm mov ecx, [esp+20] // address of aVal into ecx
1.2256 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2257 + _asm mov edx, [ecx+4]
1.2258 + _asm mov ecx, [ecx+8]
1.2259 + _asm call TRealXSubtract // do subtraction, result in ecx,edx:ebx, error code in eax
1.2260 + _asm mov [esi], ebx // store result in *this
1.2261 + _asm mov [esi+4], edx
1.2262 + _asm mov [esi+8], ecx
1.2263 + _asm test eax, eax
1.2264 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2265 + _asm mov eax, esi // return this in eax
1.2266 + _asm pop edi // restore registers
1.2267 + _asm pop esi
1.2268 + _asm pop ebp
1.2269 + _asm pop ebx
1.2270 + _asm ret 4
1.2271 + }
1.2272 +
1.2273 +
1.2274 +
1.2275 +
1.2276 +__NAKED__ EXPORT_C const TRealX& TRealX::operator*=(const TRealX& /*aVal*/)
1.2277 +/**
1.2278 +Multiplies this extended precision number by an extended precision value.
1.2279 +
1.2280 +@param aVal The extended precision value to be subtracted.
1.2281 +
1.2282 +@return A reference to this object.
1.2283 +
1.2284 +@panic MATHX KErrOverflow if the operation results in overflow.
1.2285 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2286 +*/
1.2287 + {
1.2288 + // on entry ecx=this, [esp+4]=address of aVal
1.2289 + _asm push ebx // save registers
1.2290 + _asm push ebp
1.2291 + _asm push esi
1.2292 + _asm push edi
1.2293 + _asm mov esi, ecx // this into esi
1.2294 + _asm mov ecx, [esp+20] // address of aVal into ecx
1.2295 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2296 + _asm mov edx, [ecx+4]
1.2297 + _asm mov ecx, [ecx+8]
1.2298 + _asm call TRealXMultiply // do multiplication, result in ecx,edx:ebx, error code in eax
1.2299 + _asm mov [esi], ebx // store result in *this
1.2300 + _asm mov [esi+4], edx
1.2301 + _asm mov [esi+8], ecx
1.2302 + _asm test eax, eax
1.2303 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2304 + _asm mov eax, esi // return this in eax
1.2305 + _asm pop edi // restore registers
1.2306 + _asm pop esi
1.2307 + _asm pop ebp
1.2308 + _asm pop ebx
1.2309 + _asm ret 4
1.2310 + }
1.2311 +
1.2312 +
1.2313 +
1.2314 +
1.2315 +__NAKED__ EXPORT_C const TRealX& TRealX::operator/=(const TRealX& /*aVal*/)
1.2316 +/**
1.2317 +Divides this extended precision number by an extended precision value.
1.2318 +
1.2319 +@param aVal The extended precision value to be used as the divisor.
1.2320 +
1.2321 +@return A reference to this object.
1.2322 +
1.2323 +@panic MATHX KErrOverflow if the operation results in overflow.
1.2324 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2325 +@panic MATHX KErrDivideByZero if the divisor is zero.
1.2326 +*/
1.2327 + {
1.2328 + // on entry ecx=this, [esp+4]=address of aVal
1.2329 + _asm push ebx // save registers
1.2330 + _asm push ebp
1.2331 + _asm push esi
1.2332 + _asm push edi
1.2333 + _asm mov esi, ecx // this into esi
1.2334 + _asm mov ecx, [esp+20] // address of aVal into ecx
1.2335 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2336 + _asm mov edx, [ecx+4]
1.2337 + _asm mov ecx, [ecx+8]
1.2338 + _asm call TRealXDivide // do division, result in ecx,edx:ebx, error code in eax
1.2339 + _asm mov [esi], ebx // store result in *this
1.2340 + _asm mov [esi+4], edx
1.2341 + _asm mov [esi+8], ecx
1.2342 + _asm test eax, eax
1.2343 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2344 + _asm mov eax, esi // return this in eax
1.2345 + _asm pop edi // restore registers
1.2346 + _asm pop esi
1.2347 + _asm pop ebp
1.2348 + _asm pop ebx
1.2349 + _asm ret 4
1.2350 + }
1.2351 +
1.2352 +
1.2353 +
1.2354 +
1.2355 +__NAKED__ EXPORT_C const TRealX& TRealX::operator%=(const TRealX& /*aVal*/)
1.2356 +/**
1.2357 +Modulo-divides this extended precision number by an extended precision value.
1.2358 +
1.2359 +@param aVal The extended precision value to be used as the divisor.
1.2360 +
1.2361 +@return A reference to this object.
1.2362 +
1.2363 +@panic MATHX KErrTotalLossOfPrecision panic if precision is lost.
1.2364 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2365 +*/
1.2366 + {
1.2367 + // on entry ecx=this, [esp+4]=address of aVal
1.2368 + _asm push ebx // save registers
1.2369 + _asm push ebp
1.2370 + _asm push esi
1.2371 + _asm push edi
1.2372 + _asm mov esi, ecx // this into esi
1.2373 + _asm mov ecx, [esp+20] // address of aVal into ecx
1.2374 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2375 + _asm mov edx, [ecx+4]
1.2376 + _asm mov ecx, [ecx+8]
1.2377 + _asm call TRealXModulo // do modulo, result in ecx,edx:ebx, error code in eax
1.2378 + _asm mov [esi], ebx // store result in *this
1.2379 + _asm mov [esi+4], edx
1.2380 + _asm mov [esi+8], ecx
1.2381 + _asm test eax, eax
1.2382 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2383 + _asm mov eax, esi // return this in eax
1.2384 + _asm pop edi // restore registers
1.2385 + _asm pop esi
1.2386 + _asm pop ebp
1.2387 + _asm pop ebx
1.2388 + _asm ret 4
1.2389 + }
1.2390 +
1.2391 +
1.2392 +
1.2393 +
1.2394 +__NAKED__ EXPORT_C TInt TRealX::AddEq(const TRealX& /*aVal*/)
1.2395 +/**
1.2396 +Adds an extended precision value to this extended precision number.
1.2397 +
1.2398 +@param aVal The extended precision value to be added.
1.2399 +
1.2400 +@return KErrNone, if the operation is successful;
1.2401 + KErrOverflow,if the operation results in overflow;
1.2402 + KErrUnderflow, if the operation results in underflow.
1.2403 +*/
1.2404 + {
1.2405 + // on entry ecx=this, [esp+4]=address of aVal
1.2406 + _asm push ebx // save registers
1.2407 + _asm push ebp
1.2408 + _asm push esi
1.2409 + _asm push edi
1.2410 + _asm mov esi, ecx // this into esi
1.2411 + _asm mov ecx, [esp+20] // address of aVal into ecx
1.2412 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2413 + _asm mov edx, [ecx+4]
1.2414 + _asm mov ecx, [ecx+8]
1.2415 + _asm call TRealXAdd // do addition, result in ecx,edx:ebx, error code in eax
1.2416 + _asm mov [esi], ebx // store result
1.2417 + _asm mov [esi+4], edx
1.2418 + _asm mov [esi+8], ecx
1.2419 + _asm pop edi // restore registers
1.2420 + _asm pop esi
1.2421 + _asm pop ebp
1.2422 + _asm pop ebx
1.2423 + _asm ret 4 // return with error code in eax
1.2424 + }
1.2425 +
1.2426 +
1.2427 +
1.2428 +
1.2429 +__NAKED__ EXPORT_C TInt TRealX::SubEq(const TRealX& /*aVal*/)
1.2430 +/**
1.2431 +Subtracts an extended precision value from this extended precision number.
1.2432 +
1.2433 +@param aVal The extended precision value to be subtracted.
1.2434 +
1.2435 +@return KErrNone, if the operation is successful;
1.2436 + KErrOverflow, if the operation results in overflow;
1.2437 + KErrUnderflow, if the operation results in underflow.
1.2438 +*/
1.2439 + {
1.2440 + // on entry ecx=this, [esp+4]=address of aVal
1.2441 + _asm push ebx // save registers
1.2442 + _asm push ebp
1.2443 + _asm push esi
1.2444 + _asm push edi
1.2445 + _asm mov esi, ecx // this into esi
1.2446 + _asm mov ecx, [esp+20] // address of aVal into ecx
1.2447 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2448 + _asm mov edx, [ecx+4]
1.2449 + _asm mov ecx, [ecx+8]
1.2450 + _asm call TRealXSubtract // do subtraction, result in ecx,edx:ebx, error code in eax
1.2451 + _asm mov [esi], ebx // store result
1.2452 + _asm mov [esi+4], edx
1.2453 + _asm mov [esi+8], ecx
1.2454 + _asm pop edi // restore registers
1.2455 + _asm pop esi
1.2456 + _asm pop ebp
1.2457 + _asm pop ebx
1.2458 + _asm ret 4 // return with error code in eax
1.2459 + }
1.2460 +
1.2461 +
1.2462 +
1.2463 +
1.2464 +__NAKED__ EXPORT_C TInt TRealX::MultEq(const TRealX& /*aVal*/)
1.2465 +/**
1.2466 +Multiplies this extended precision number by an extended precision value.
1.2467 +
1.2468 +@param aVal The extended precision value to be used as the multiplier.
1.2469 +
1.2470 +@return KErrNone, if the operation is successful;
1.2471 + KErrOverflow, if the operation results in overflow;
1.2472 + KErrUnderflow, if the operation results in underflow
1.2473 +*/
1.2474 + {
1.2475 + // on entry ecx=this, [esp+4]=address of aVal
1.2476 + _asm push ebx // save registers
1.2477 + _asm push ebp
1.2478 + _asm push esi
1.2479 + _asm push edi
1.2480 + _asm mov esi, ecx // this into esi
1.2481 + _asm mov ecx, [esp+20] // address of aVal into ecx
1.2482 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2483 + _asm mov edx, [ecx+4]
1.2484 + _asm mov ecx, [ecx+8]
1.2485 + _asm call TRealXMultiply // do multiplication, result in ecx,edx:ebx, error code in eax
1.2486 + _asm mov [esi], ebx // store result
1.2487 + _asm mov [esi+4], edx
1.2488 + _asm mov [esi+8], ecx
1.2489 + _asm pop edi // restore registers
1.2490 + _asm pop esi
1.2491 + _asm pop ebp
1.2492 + _asm pop ebx
1.2493 + _asm ret 4 // return with error code in eax
1.2494 + }
1.2495 +
1.2496 +
1.2497 +
1.2498 +
1.2499 +__NAKED__ EXPORT_C TInt TRealX::DivEq(const TRealX& /*aVal*/)
1.2500 +/**
1.2501 +Divides this extended precision number by an extended precision value.
1.2502 +
1.2503 +@param aVal The extended precision value to be used as the divisor.
1.2504 +
1.2505 +@return KErrNone, if the operation is successful;
1.2506 + KErrOverflow, if the operation results in overflow;
1.2507 + KErrUnderflow, if the operation results in underflow;
1.2508 + KErrDivideByZero, if the divisor is zero.
1.2509 +*/
1.2510 + {
1.2511 + // on entry ecx=this, [esp+4]=address of aVal
1.2512 + _asm push ebx // save registers
1.2513 + _asm push ebp
1.2514 + _asm push esi
1.2515 + _asm push edi
1.2516 + _asm mov esi, ecx // this into esi
1.2517 + _asm mov ecx, [esp+20] // address of aVal into ecx
1.2518 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2519 + _asm mov edx, [ecx+4]
1.2520 + _asm mov ecx, [ecx+8]
1.2521 + _asm call TRealXDivide // do division, result in ecx,edx:ebx, error code in eax
1.2522 + _asm mov [esi], ebx // store result
1.2523 + _asm mov [esi+4], edx
1.2524 + _asm mov [esi+8], ecx
1.2525 + _asm pop edi // restore registers
1.2526 + _asm pop esi
1.2527 + _asm pop ebp
1.2528 + _asm pop ebx
1.2529 + _asm ret 4 // return with error code in eax
1.2530 + }
1.2531 +
1.2532 +
1.2533 +
1.2534 +
1.2535 +__NAKED__ EXPORT_C TInt TRealX::ModEq(const TRealX& /*aVal*/)
1.2536 +/**
1.2537 +Modulo-divides this extended precision number by an extended precision value.
1.2538 +
1.2539 +@param aVal The extended precision value to be used as the divisor.
1.2540 +
1.2541 +@return KErrNone, if the operation is successful;
1.2542 + KErrTotalLossOfPrecision, if precision is lost;
1.2543 + KErrUnderflow, if the operation results in underflow.
1.2544 +*/
1.2545 + {
1.2546 + // on entry ecx=this, [esp+4]=address of aVal
1.2547 + _asm push ebx // save registers
1.2548 + _asm push ebp
1.2549 + _asm push esi
1.2550 + _asm push edi
1.2551 + _asm mov esi, ecx // this into esi
1.2552 + _asm mov ecx, [esp+20] // address of aVal into ecx
1.2553 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2554 + _asm mov edx, [ecx+4]
1.2555 + _asm mov ecx, [ecx+8]
1.2556 + _asm call TRealXModulo // do modulo, result in ecx,edx:ebx, error code in eax
1.2557 + _asm mov [esi], ebx // store result
1.2558 + _asm mov [esi+4], edx
1.2559 + _asm mov [esi+8], ecx
1.2560 + _asm pop edi // restore registers
1.2561 + _asm pop esi
1.2562 + _asm pop ebp
1.2563 + _asm pop ebx
1.2564 + _asm ret 4 // return with error code in eax
1.2565 + }
1.2566 +
1.2567 +
1.2568 +
1.2569 +
1.2570 +__NAKED__ EXPORT_C TRealX TRealX::operator+() const
1.2571 +/**
1.2572 +Returns this extended precision number unchanged.
1.2573 +
1.2574 +Note that this may also be referred to as a unary plus operator.
1.2575 +
1.2576 +@return The extended precision number.
1.2577 +*/
1.2578 + {
1.2579 + _asm mov eax, [esp+4] // eax=address to write return value
1.2580 + _asm mov edx, [ecx]
1.2581 + _asm mov [eax], edx
1.2582 + _asm mov edx, [ecx+4]
1.2583 + _asm mov [eax+4], edx
1.2584 + _asm mov edx, [ecx+8]
1.2585 + _asm mov [eax+8], edx
1.2586 + _asm ret 4 // return address of return value in eax
1.2587 + }
1.2588 +
1.2589 +
1.2590 +
1.2591 +
1.2592 +__NAKED__ EXPORT_C TRealX TRealX::operator-() const
1.2593 +/**
1.2594 +Negates this extended precision number.
1.2595 +
1.2596 +This may also be referred to as a unary minus operator.
1.2597 +
1.2598 +@return The negative of the extended precision number.
1.2599 +*/
1.2600 + {
1.2601 + _asm mov eax, [esp+4] // eax=address to write return value
1.2602 + _asm mov edx, [ecx]
1.2603 + _asm mov [eax], edx
1.2604 + _asm mov edx, [ecx+4]
1.2605 + _asm mov [eax+4], edx
1.2606 + _asm mov edx, [ecx+8]
1.2607 + _asm xor dl, 1 // change sign bit
1.2608 + _asm mov [eax+8], edx
1.2609 + _asm ret 4 // return address of return value in eax
1.2610 + }
1.2611 +
1.2612 +
1.2613 +
1.2614 +
1.2615 +__NAKED__ EXPORT_C TRealX& TRealX::operator++()
1.2616 +/**
1.2617 +Increments this extended precision number by one,
1.2618 +and then returns a reference to it.
1.2619 +
1.2620 +This is also referred to as a prefix operator.
1.2621 +
1.2622 +@return A reference to this object.
1.2623 +
1.2624 +@panic MATHX KErrOverflow if the operation results in overflow.
1.2625 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2626 +*/
1.2627 + {
1.2628 + // pre-increment
1.2629 + // on entry ecx=this, return this in eax
1.2630 + _asm push ebx // save registers
1.2631 + _asm push ebp
1.2632 + _asm push esi
1.2633 + _asm push edi
1.2634 + _asm mov esi, ecx // this into esi
1.2635 + _asm mov ecx, 0x7FFF0000 // set ecx,edx:ebx to 1.0
1.2636 + _asm mov edx, 0x80000000
1.2637 + _asm xor ebx, ebx
1.2638 + _asm call TRealXAdd // add 1 to *this
1.2639 + _asm mov [esi], ebx // store result
1.2640 + _asm mov [esi+4], edx
1.2641 + _asm mov [esi+8], ecx
1.2642 + _asm test eax, eax // check error code
1.2643 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2644 + _asm mov eax, esi // else return this in eax
1.2645 + _asm pop edi
1.2646 + _asm pop esi
1.2647 + _asm pop ebp
1.2648 + _asm pop ebx
1.2649 + _asm ret
1.2650 + }
1.2651 +
1.2652 +
1.2653 +
1.2654 +
1.2655 +__NAKED__ EXPORT_C TRealX TRealX::operator++(TInt)
1.2656 +/**
1.2657 +Returns this extended precision number before incrementing it by one.
1.2658 +
1.2659 +This is also referred to as a postfix operator.
1.2660 +
1.2661 +@return A reference to this object.
1.2662 +
1.2663 +@panic MATHX KErrOverflow if the operation results in overflow.
1.2664 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2665 +*/
1.2666 + {
1.2667 + // post-increment
1.2668 + // on entry ecx=this, [esp+4]=address of return value, [esp+8]=dummy int
1.2669 + _asm push ebx // save registers
1.2670 + _asm push ebp
1.2671 + _asm push esi
1.2672 + _asm push edi
1.2673 + _asm mov esi, ecx // this into esi
1.2674 + _asm mov edi, [esp+20] // address of return value into edi
1.2675 + _asm mov eax, [ecx] // copy initial value of *this into [edi]
1.2676 + _asm mov [edi], eax
1.2677 + _asm mov eax, [ecx+4]
1.2678 + _asm mov [edi+4], eax
1.2679 + _asm mov eax, [ecx+8]
1.2680 + _asm mov [edi+8], eax
1.2681 + _asm mov ecx, 0x7FFF0000 // set ecx,edx:ebx to 1.0
1.2682 + _asm mov edx, 0x80000000
1.2683 + _asm xor ebx, ebx
1.2684 + _asm call TRealXAdd // add 1 to *this
1.2685 + _asm mov [esi], ebx // store result in *this
1.2686 + _asm mov [esi+4], edx
1.2687 + _asm mov [esi+8], ecx
1.2688 + _asm test eax, eax // check error code
1.2689 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2690 + _asm mov eax, [esp+20] // address of return value into eax
1.2691 + _asm pop edi
1.2692 + _asm pop esi
1.2693 + _asm pop ebp
1.2694 + _asm pop ebx
1.2695 + _asm ret 8
1.2696 + }
1.2697 +
1.2698 +
1.2699 +
1.2700 +
1.2701 +__NAKED__ EXPORT_C TRealX& TRealX::operator--()
1.2702 +/**
1.2703 +Decrements this extended precision number by one,
1.2704 +and then returns a reference to it.
1.2705 +
1.2706 +This is also referred to as a prefix operator.
1.2707 +
1.2708 +@return A reference to this object.
1.2709 +
1.2710 +@panic MATHX KErrOverflow if the operation results in overflow.
1.2711 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2712 +*/
1.2713 + {
1.2714 + // pre-decrement
1.2715 + // on entry ecx=this, return this in eax
1.2716 + _asm push ebx // save registers
1.2717 + _asm push ebp
1.2718 + _asm push esi
1.2719 + _asm push edi
1.2720 + _asm mov esi, ecx // this into esi
1.2721 + _asm mov ecx, 0x7FFF0001 // set ecx,edx:ebx to -1.0
1.2722 + _asm mov edx, 0x80000000
1.2723 + _asm xor ebx, ebx
1.2724 + _asm call TRealXAdd // add -1 to *this
1.2725 + _asm mov [esi], ebx // store result
1.2726 + _asm mov [esi+4], edx
1.2727 + _asm mov [esi+8], ecx
1.2728 + _asm test eax, eax // check error code
1.2729 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2730 + _asm mov eax, esi // else return this in eax
1.2731 + _asm pop edi
1.2732 + _asm pop esi
1.2733 + _asm pop ebp
1.2734 + _asm pop ebx
1.2735 + _asm ret
1.2736 + }
1.2737 +
1.2738 +
1.2739 +
1.2740 +
1.2741 +__NAKED__ EXPORT_C TRealX TRealX::operator--(TInt)
1.2742 +/**
1.2743 +Returns this extended precision number before decrementing it by one.
1.2744 +
1.2745 +This is also referred to as a postfix operator.
1.2746 +
1.2747 +@return A reference to this object.
1.2748 +
1.2749 +@panic MATHX KErrOverflow if the operation results in overflow.
1.2750 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2751 +*/
1.2752 + {
1.2753 + // post-decrement
1.2754 + // on entry ecx=this, [esp+4]=address of return value, [esp+8]=dummy int
1.2755 + _asm push ebx // save registers
1.2756 + _asm push ebp
1.2757 + _asm push esi
1.2758 + _asm push edi
1.2759 + _asm mov esi, ecx // this into esi
1.2760 + _asm mov edi, [esp+20] // address of return value into edi
1.2761 + _asm mov eax, [ecx] // copy initial value of *this into [edi]
1.2762 + _asm mov [edi], eax
1.2763 + _asm mov eax, [ecx+4]
1.2764 + _asm mov [edi+4], eax
1.2765 + _asm mov eax, [ecx+8]
1.2766 + _asm mov [edi+8], eax
1.2767 + _asm mov ecx, 0x7FFF0001 // set ecx,edx:ebx to -1.0
1.2768 + _asm mov edx, 0x80000000
1.2769 + _asm xor ebx, ebx
1.2770 + _asm call TRealXAdd // add -1 to *this
1.2771 + _asm mov [esi], ebx // store result in *this
1.2772 + _asm mov [esi+4], edx
1.2773 + _asm mov [esi+8], ecx
1.2774 + _asm test eax, eax // check error code
1.2775 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2776 + _asm mov eax, [esp+20] // address of return value into eax
1.2777 + _asm pop edi
1.2778 + _asm pop esi
1.2779 + _asm pop ebp
1.2780 + _asm pop ebx
1.2781 + _asm ret 8
1.2782 + }
1.2783 +
1.2784 +
1.2785 +
1.2786 +
1.2787 +__NAKED__ EXPORT_C TRealX TRealX::operator+(const TRealX& /*aVal*/) const
1.2788 +/**
1.2789 +Adds an extended precision value to this extended precision number.
1.2790 +
1.2791 +@param aVal The extended precision value to be added.
1.2792 +
1.2793 +@return An extended precision object containing the result.
1.2794 +
1.2795 +@panic MATHX KErrOverflow if the operation results in overflow.
1.2796 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2797 +*/
1.2798 + {
1.2799 + // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
1.2800 + _asm push ebx // save registers
1.2801 + _asm push ebp
1.2802 + _asm push esi
1.2803 + _asm push edi
1.2804 + _asm mov esi, ecx // this into esi
1.2805 + _asm mov ecx, [esp+24] // address of aVal into ecx
1.2806 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2807 + _asm mov edx, [ecx+4]
1.2808 + _asm mov ecx, [ecx+8]
1.2809 + _asm call TRealXAdd // do addition, result in ecx,edx:ebx, error code in eax
1.2810 + _asm mov esi, [esp+20] // esi=address of return value
1.2811 + _asm mov [esi], ebx // store result
1.2812 + _asm mov [esi+4], edx
1.2813 + _asm mov [esi+8], ecx
1.2814 + _asm test eax, eax
1.2815 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2816 + _asm mov eax, esi // return address of return value in eax
1.2817 + _asm pop edi // restore registers
1.2818 + _asm pop esi
1.2819 + _asm pop ebp
1.2820 + _asm pop ebx
1.2821 + _asm ret 8
1.2822 + }
1.2823 +
1.2824 +
1.2825 +
1.2826 +
1.2827 +__NAKED__ EXPORT_C TRealX TRealX::operator-(const TRealX& /*aVal*/) const
1.2828 +/**
1.2829 +Subtracts an extended precision value from this extended precision number.
1.2830 +
1.2831 +@param aVal The extended precision value to be subtracted.
1.2832 +
1.2833 +@return An extended precision object containing the result.
1.2834 +
1.2835 +@panic MATHX KErrOverflow if the operation results in overflow.
1.2836 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2837 +*/
1.2838 + {
1.2839 + // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
1.2840 + _asm push ebx // save registers
1.2841 + _asm push ebp
1.2842 + _asm push esi
1.2843 + _asm push edi
1.2844 + _asm mov esi, ecx // this into esi
1.2845 + _asm mov ecx, [esp+24] // address of aVal into ecx
1.2846 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2847 + _asm mov edx, [ecx+4]
1.2848 + _asm mov ecx, [ecx+8]
1.2849 + _asm call TRealXSubtract // do subtraction, result in ecx,edx:ebx, error code in eax
1.2850 + _asm mov esi, [esp+20] // esi=address of return value
1.2851 + _asm mov [esi], ebx // store result
1.2852 + _asm mov [esi+4], edx
1.2853 + _asm mov [esi+8], ecx
1.2854 + _asm test eax, eax
1.2855 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2856 + _asm mov eax, esi // return address of return value in eax
1.2857 + _asm pop edi // restore registers
1.2858 + _asm pop esi
1.2859 + _asm pop ebp
1.2860 + _asm pop ebx
1.2861 + _asm ret 8
1.2862 + }
1.2863 +
1.2864 +
1.2865 +
1.2866 +
1.2867 +__NAKED__ EXPORT_C TRealX TRealX::operator*(const TRealX& /*aVal*/) const
1.2868 +/**
1.2869 +Multiplies this extended precision number by an extended precision value.
1.2870 +
1.2871 +@param aVal The extended precision value to be used as the multiplier.
1.2872 +
1.2873 +@return An extended precision object containing the result.
1.2874 +
1.2875 +@panic MATHX KErrOverflow if the operation results in overflow.
1.2876 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2877 +*/
1.2878 + {
1.2879 + // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
1.2880 + _asm push ebx // save registers
1.2881 + _asm push ebp
1.2882 + _asm push esi
1.2883 + _asm push edi
1.2884 + _asm mov esi, ecx // this into esi
1.2885 + _asm mov ecx, [esp+24] // address of aVal into ecx
1.2886 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2887 + _asm mov edx, [ecx+4]
1.2888 + _asm mov ecx, [ecx+8]
1.2889 + _asm call TRealXMultiply // do multiplication, result in ecx,edx:ebx, error code in eax
1.2890 + _asm mov esi, [esp+20] // esi=address of return value
1.2891 + _asm mov [esi], ebx // store result
1.2892 + _asm mov [esi+4], edx
1.2893 + _asm mov [esi+8], ecx
1.2894 + _asm test eax, eax
1.2895 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2896 + _asm mov eax, esi // return address of return value in eax
1.2897 + _asm pop edi // restore registers
1.2898 + _asm pop esi
1.2899 + _asm pop ebp
1.2900 + _asm pop ebx
1.2901 + _asm ret 8
1.2902 + }
1.2903 +
1.2904 +
1.2905 +
1.2906 +
1.2907 +__NAKED__ EXPORT_C TRealX TRealX::operator/(const TRealX& /*aVal*/) const
1.2908 +/**
1.2909 +Divides this extended precision number by an extended precision value.
1.2910 +
1.2911 +@param aVal The extended precision value to be used as the divisor.
1.2912 +
1.2913 +@return An extended precision object containing the result.
1.2914 +
1.2915 +@panic MATHX KErrOverflow if the operation results in overflow.
1.2916 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2917 +@panic MATHX KErrDivideByZero if the divisor is zero.
1.2918 +*/
1.2919 + {
1.2920 + // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
1.2921 + _asm push ebx // save registers
1.2922 + _asm push ebp
1.2923 + _asm push esi
1.2924 + _asm push edi
1.2925 + _asm mov esi, ecx // this into esi
1.2926 + _asm mov ecx, [esp+24] // address of aVal into ecx
1.2927 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2928 + _asm mov edx, [ecx+4]
1.2929 + _asm mov ecx, [ecx+8]
1.2930 + _asm call TRealXDivide // do division, result in ecx,edx:ebx, error code in eax
1.2931 + _asm mov esi, [esp+20] // esi=address of return value
1.2932 + _asm mov [esi], ebx // store result
1.2933 + _asm mov [esi+4], edx
1.2934 + _asm mov [esi+8], ecx
1.2935 + _asm test eax, eax
1.2936 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2937 + _asm mov eax, esi // return address of return value in eax
1.2938 + _asm pop edi // restore registers
1.2939 + _asm pop esi
1.2940 + _asm pop ebp
1.2941 + _asm pop ebx
1.2942 + _asm ret 8
1.2943 + }
1.2944 +
1.2945 +
1.2946 +
1.2947 +
1.2948 +__NAKED__ EXPORT_C TRealX TRealX::operator%(const TRealX& /*aVal*/) const
1.2949 +/**
1.2950 +Modulo-divides this extended precision number by an extended precision value.
1.2951 +
1.2952 +@param aVal The extended precision value to be used as the divisor.
1.2953 +
1.2954 +@return An extended precision object containing the result.
1.2955 +
1.2956 +@panic MATHX KErrTotalLossOfPrecision if precision is lost.
1.2957 +@panic MATHX KErrUnderflow if the operation results in underflow.
1.2958 +*/
1.2959 + {
1.2960 + // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
1.2961 + _asm push ebx // save registers
1.2962 + _asm push ebp
1.2963 + _asm push esi
1.2964 + _asm push edi
1.2965 + _asm mov esi, ecx // this into esi
1.2966 + _asm mov ecx, [esp+24] // address of aVal into ecx
1.2967 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.2968 + _asm mov edx, [ecx+4]
1.2969 + _asm mov ecx, [ecx+8]
1.2970 + _asm call TRealXModulo // do modulo, result in ecx,edx:ebx, error code in eax
1.2971 + _asm mov esi, [esp+20] // esi=address of return value
1.2972 + _asm mov [esi], ebx // store result
1.2973 + _asm mov [esi+4], edx
1.2974 + _asm mov [esi+8], ecx
1.2975 + _asm test eax, eax
1.2976 + _ASM_jn(z,TRealXPanicEax) // panic if error
1.2977 + _asm mov eax, esi // return address of return value in eax
1.2978 + _asm pop edi // restore registers
1.2979 + _asm pop esi
1.2980 + _asm pop ebp
1.2981 + _asm pop ebx
1.2982 + _asm ret 8
1.2983 + }
1.2984 +
1.2985 +
1.2986 +
1.2987 +
1.2988 +__NAKED__ EXPORT_C TInt TRealX::Add(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
1.2989 +/**
1.2990 +Adds an extended precision value to this extended precision number.
1.2991 +
1.2992 +@param aResult On return, a reference to an extended precision object
1.2993 + containing the result of the operation.
1.2994 +@param aVal The extended precision value to be added.
1.2995 +
1.2996 +@return KErrNone, if the operation is successful;
1.2997 + KErrOverflow, if the operation results in overflow;
1.2998 + KErrUnderflow, if the operation results in underflow.
1.2999 +*/
1.3000 + {
1.3001 + // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
1.3002 + _asm push ebx // save registers
1.3003 + _asm push ebp
1.3004 + _asm push esi
1.3005 + _asm push edi
1.3006 + _asm mov esi, ecx // this into esi
1.3007 + _asm mov ecx, [esp+24] // address of aVal into ecx
1.3008 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.3009 + _asm mov edx, [ecx+4]
1.3010 + _asm mov ecx, [ecx+8]
1.3011 + _asm call TRealXAdd // do addition, result in ecx,edx:ebx, error code in eax
1.3012 + _asm mov esi, [esp+20] // esi=address of aResult
1.3013 + _asm mov [esi], ebx // store result
1.3014 + _asm mov [esi+4], edx
1.3015 + _asm mov [esi+8], ecx
1.3016 + _asm pop edi // restore registers
1.3017 + _asm pop esi
1.3018 + _asm pop ebp
1.3019 + _asm pop ebx
1.3020 + _asm ret 8 // return with error code in eax
1.3021 + }
1.3022 +
1.3023 +
1.3024 +
1.3025 +
1.3026 +__NAKED__ EXPORT_C TInt TRealX::Sub(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
1.3027 +/**
1.3028 +Subtracts an extended precision value from this extended precision number.
1.3029 +
1.3030 +@param aResult On return, a reference to an extended precision object
1.3031 + containing the result of the operation.
1.3032 +@param aVal The extended precision value to be subtracted.
1.3033 +
1.3034 +@return KErrNone, if the operation is successful;
1.3035 + KErrOverflow, if the operation results in overflow;
1.3036 + KErrUnderflow, if the operation results in underflow.
1.3037 +*/
1.3038 + {
1.3039 + // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
1.3040 + _asm push ebx // save registers
1.3041 + _asm push ebp
1.3042 + _asm push esi
1.3043 + _asm push edi
1.3044 + _asm mov esi, ecx // this into esi
1.3045 + _asm mov ecx, [esp+24] // address of aVal into ecx
1.3046 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.3047 + _asm mov edx, [ecx+4]
1.3048 + _asm mov ecx, [ecx+8]
1.3049 + _asm call TRealXSubtract // do subtraction, result in ecx,edx:ebx, error code in eax
1.3050 + _asm mov esi, [esp+20] // esi=address of aResult
1.3051 + _asm mov [esi], ebx // store result
1.3052 + _asm mov [esi+4], edx
1.3053 + _asm mov [esi+8], ecx
1.3054 + _asm pop edi // restore registers
1.3055 + _asm pop esi
1.3056 + _asm pop ebp
1.3057 + _asm pop ebx
1.3058 + _asm ret 8 // return with error code in eax
1.3059 + }
1.3060 +
1.3061 +
1.3062 +
1.3063 +
1.3064 +__NAKED__ EXPORT_C TInt TRealX::Mult(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
1.3065 +/**
1.3066 +Multiplies this extended precision number by an extended precision value.
1.3067 +
1.3068 +@param aResult On return, a reference to an extended precision object
1.3069 + containing the result of the operation.
1.3070 +@param aVal The extended precision value to be used as the multiplier.
1.3071 +
1.3072 +@return KErrNone, if the operation is successful;
1.3073 + KErrOverflow, if the operation results in overflow;
1.3074 + KErrUnderflow, if the operation results in underflow.
1.3075 +*/
1.3076 + {
1.3077 + // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
1.3078 + _asm push ebx // save registers
1.3079 + _asm push ebp
1.3080 + _asm push esi
1.3081 + _asm push edi
1.3082 + _asm mov esi, ecx // this into esi
1.3083 + _asm mov ecx, [esp+24] // address of aVal into ecx
1.3084 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.3085 + _asm mov edx, [ecx+4]
1.3086 + _asm mov ecx, [ecx+8]
1.3087 + _asm call TRealXMultiply // do multiplication, result in ecx,edx:ebx, error code in eax
1.3088 + _asm mov esi, [esp+20] // esi=address of aResult
1.3089 + _asm mov [esi], ebx // store result
1.3090 + _asm mov [esi+4], edx
1.3091 + _asm mov [esi+8], ecx
1.3092 + _asm pop edi // restore registers
1.3093 + _asm pop esi
1.3094 + _asm pop ebp
1.3095 + _asm pop ebx
1.3096 + _asm ret 8 // return with error code in eax
1.3097 + }
1.3098 +
1.3099 +
1.3100 +
1.3101 +
1.3102 +__NAKED__ EXPORT_C TInt TRealX::Div(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
1.3103 +/**
1.3104 +Divides this extended precision number by an extended precision value.
1.3105 +
1.3106 +@param aResult On return, a reference to an extended precision object
1.3107 + containing the result of the operation.
1.3108 +@param aVal The extended precision value to be used as the divisor.
1.3109 +
1.3110 +@return KErrNone, if the operation is successful;
1.3111 + KErrOverflow, if the operation results in overflow;
1.3112 + KErrUnderflow, if the operation results in underflow;
1.3113 + KErrDivideByZero, if the divisor is zero.
1.3114 +*/
1.3115 + {
1.3116 + // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
1.3117 + _asm push ebx // save registers
1.3118 + _asm push ebp
1.3119 + _asm push esi
1.3120 + _asm push edi
1.3121 + _asm mov esi, ecx // this into esi
1.3122 + _asm mov ecx, [esp+24] // address of aVal into ecx
1.3123 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.3124 + _asm mov edx, [ecx+4]
1.3125 + _asm mov ecx, [ecx+8]
1.3126 + _asm call TRealXDivide // do division, result in ecx,edx:ebx, error code in eax
1.3127 + _asm mov esi, [esp+20] // esi=address of aResult
1.3128 + _asm mov [esi], ebx // store result
1.3129 + _asm mov [esi+4], edx
1.3130 + _asm mov [esi+8], ecx
1.3131 + _asm pop edi // restore registers
1.3132 + _asm pop esi
1.3133 + _asm pop ebp
1.3134 + _asm pop ebx
1.3135 + _asm ret 8 // return with error code in eax
1.3136 + }
1.3137 +
1.3138 +
1.3139 +
1.3140 +
1.3141 +__NAKED__ EXPORT_C TInt TRealX::Mod(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
1.3142 +/**
1.3143 +Modulo-divides this extended precision number by an extended precision value.
1.3144 +
1.3145 +@param aResult On return, a reference to an extended precision object
1.3146 + containing the result of the operation.
1.3147 +
1.3148 +@param aVal The extended precision value to be used as the divisor.
1.3149 +
1.3150 +@return KErrNone, if the operation is successful;
1.3151 + KErrTotalLossOfPrecision, if precision is lost;
1.3152 + KErrUnderflow, if the operation results in underflow.
1.3153 +*/
1.3154 + {
1.3155 + // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
1.3156 + _asm push ebx // save registers
1.3157 + _asm push ebp
1.3158 + _asm push esi
1.3159 + _asm push edi
1.3160 + _asm mov esi, ecx // this into esi
1.3161 + _asm mov ecx, [esp+24] // address of aVal into ecx
1.3162 + _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
1.3163 + _asm mov edx, [ecx+4]
1.3164 + _asm mov ecx, [ecx+8]
1.3165 + _asm call TRealXModulo // do modulo, result in ecx,edx:ebx, error code in eax
1.3166 + _asm mov esi, [esp+20] // esi=address of aResult
1.3167 + _asm mov [esi], ebx // store result
1.3168 + _asm mov [esi+4], edx
1.3169 + _asm mov [esi+8], ecx
1.3170 + _asm pop edi // restore registers
1.3171 + _asm pop esi
1.3172 + _asm pop ebp
1.3173 + _asm pop ebx
1.3174 + _asm ret 8 // return with error code in eax
1.3175 + }
1.3176 +
1.3177 +// Compare TRealX in ecx,edx:ebx (op1) to TRealX at [esi] (op2)
1.3178 +// Return 1 if op1<op2
1.3179 +// Return 2 if op1=op2
1.3180 +// Return 4 if op1>op2
1.3181 +// Return 8 if unordered
1.3182 +// Return value in eax
1.3183 +__NAKED__ LOCAL_C void TRealXCompare(void)
1.3184 + {
1.3185 + _asm cmp ecx, 0xFFFF0000 // check if op1=NaN or infinity
1.3186 + _asm jc short fpcmp1 // branch if not
1.3187 + _asm cmp edx, 0x80000000 // check for infinity
1.3188 + _asm jnz short fpcmpunord // branch if NaN
1.3189 + _asm test ebx, ebx
1.3190 + _asm jz short fpcmp1 // if infinity, process normally
1.3191 + fpcmpunord: // come here if unordered
1.3192 + _asm mov eax, 8 // return 8
1.3193 + _asm ret
1.3194 + fpcmp1: // op1 is not a NaN
1.3195 + _asm mov eax, [esi+8] // get op2 into eax,edi:ebp
1.3196 + _asm mov edi, [esi+4]
1.3197 + _asm mov ebp, [esi]
1.3198 + _asm cmp eax, 0xFFFF0000 // check for NaN or infinity
1.3199 + _asm jc short fpcmp2 // branch if neither
1.3200 + _asm cmp edi, 0x80000000 // check for infinity
1.3201 + _asm jnz short fpcmpunord // branch if NaN
1.3202 + _asm test ebp, ebp
1.3203 + _asm jnz short fpcmpunord
1.3204 + fpcmp2: // neither operand is a NaN
1.3205 + _asm cmp ecx, 0x10000 // check if op1=0
1.3206 + _asm jc short fpcmpop1z // branch if it is
1.3207 + _asm cmp eax, 0x10000 // check if op2=0
1.3208 + _asm jc short fpcmp4 // branch if it is
1.3209 + _asm xor al, cl // check if signs the same
1.3210 + _asm test al, 1
1.3211 + _asm jnz short fpcmp4 // branch if different
1.3212 + _asm push ecx
1.3213 + _asm shr ecx, 16 // op1 exponent into cx
1.3214 + _asm shr eax, 16 // op2 exponent into ax
1.3215 + _asm cmp ecx, eax // compare exponents
1.3216 + _asm pop ecx
1.3217 + _asm ja short fpcmp4 // if op1 exp > op2 exp op1>op2 if +ve
1.3218 + _asm jb short fpcmp5 // if op1 exp < op2 exp op1<op2 if +ve
1.3219 + _asm cmp edx, edi // else compare mantissa high words
1.3220 + _asm ja short fpcmp4
1.3221 + _asm jb short fpcmp5
1.3222 + _asm cmp ebx, ebp // if equal compare mantissa low words
1.3223 + _asm ja short fpcmp4
1.3224 + _asm jb short fpcmp5
1.3225 + fpcmp0:
1.3226 + _asm mov eax, 2 // numbers exactly equal
1.3227 + _asm ret
1.3228 + fpcmp4: // come here if ABS(op1)>ABS(op2) or if signs different
1.3229 + // or if op2 zero, op1 nonzero
1.3230 + _asm mov eax, 4 // return 4 if +ve
1.3231 + _asm test cl, 1 // check sign
1.3232 + _asm jz short fpcmp4a // skip if +
1.3233 + _asm mov al, 1 // return 1 if -ve
1.3234 + fpcmp4a:
1.3235 + _asm ret
1.3236 + fpcmp5: // come here if ABS(op1)<ABS(op2)
1.3237 + _asm mov eax, 1 // return 1 if +ve
1.3238 + _asm test cl, 1 // check sign
1.3239 + _asm jz short fpcmp5a // skip if +
1.3240 + _asm mov al, 4 // return 4 if -ve
1.3241 + fpcmp5a:
1.3242 + _asm ret
1.3243 + fpcmpop1z: // come here if op1=0
1.3244 + _asm cmp eax, 0x10000 // check if op2 also zero
1.3245 + _asm jc short fpcmp0 // if so, they are equal
1.3246 + _asm test al, 1 // test sign of op 2
1.3247 + _asm mov eax, 4 // if -, return 4
1.3248 + _asm jnz short fpcmpop1z2n // skip if -
1.3249 + _asm mov al, 1 // else return 1
1.3250 + fpcmpop1z2n:
1.3251 + _asm ret
1.3252 + }
1.3253 +
1.3254 +
1.3255 +
1.3256 +
1.3257 +__NAKED__ EXPORT_C TRealX::TRealXOrder TRealX::Compare(const TRealX& /*aVal*/) const
1.3258 +/**
1.3259 +*/
1.3260 + {
1.3261 + // On entry ecx=this, [esp+4]=address of aVal
1.3262 + _asm push ebx // save registers
1.3263 + _asm push ebp
1.3264 + _asm push esi
1.3265 + _asm push edi
1.3266 + _asm mov esi, [esp+20] // address of aVal into esi
1.3267 + _asm mov ebx, [ecx] // *this into ecx,edx:ebx
1.3268 + _asm mov edx, [ecx+4]
1.3269 + _asm mov ecx, [ecx+8]
1.3270 + _asm call TRealXCompare // result in eax
1.3271 + _asm pop edi
1.3272 + _asm pop esi
1.3273 + _asm pop ebp
1.3274 + _asm pop ebx
1.3275 + _asm ret 4
1.3276 + }
1.3277 +
1.3278 +
1.3279 +
1.3280 +
1.3281 +#pragma warning (default : 4100) // unreferenced formal parameter
1.3282 +#pragma warning (default : 4414) // short jump converted to near
1.3283 +#pragma warning (default : 4700) // local variable 'this' used without having been initialised
1.3284 +