sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\mmu\t_imb.cia sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #ifdef __CPU_ARM sl@0: __NAKED__ TInt Sqrt(TReal& /*aDest*/, const TReal& /*aSrc*/) sl@0: { sl@0: // r0=address of aDest, r1=address of aSrc sl@0: asm("stmfd sp!, {r4-r10,lr} "); sl@0: #ifdef __DOUBLE_WORDS_SWAPPED__ sl@0: asm("ldmia r1, {r3,r4} "); // low mant into r4, sign:exp:high mant into r3 sl@0: #else sl@0: asm("ldr r3, [r1, #4] "); sl@0: asm("ldr r4, [r1, #0] "); sl@0: #endif sl@0: asm("bic r5, r3, #0xFF000000 "); sl@0: asm("bic r5, r5, #0x00F00000 "); // high word of mantissa into r5 sl@0: asm("mov r2, r3, lsr #20 "); sl@0: asm("bics r2, r2, #0x800 "); // exponent now in r2 sl@0: asm("beq fastsqrt1 "); // branch if exponent zero (zero or denormal) sl@0: asm("mov r6, #0xFF "); sl@0: asm("orr r6, r6, #0x700 "); sl@0: asm("cmp r2, r6 "); // check for infinity or NaN sl@0: asm("beq fastsqrt2 "); // branch if infinity or NaN sl@0: asm("movs r3, r3 "); // test sign sl@0: asm("bmi fastsqrtn "); // branch if negative sl@0: asm("sub r2, r2, #0xFF "); // unbias the exponent sl@0: asm("sub r2, r2, #0x300 "); // sl@0: asm("fastsqrtd1: "); sl@0: asm("mov r1, #0x40000000 "); // value for comparison sl@0: asm("mov r3, #27 "); // loop counter (number of bits/2) sl@0: asm("movs r2, r2, asr #1 "); // divide exponent by 2, LSB into CF sl@0: asm("movcs r7, r5, lsl #11 "); // mantissa into r6,r7 with MSB in MSB of r7 sl@0: asm("orrcs r7, r7, r4, lsr #21 "); sl@0: asm("movcs r6, r4, lsl #11 "); sl@0: asm("movcs r4, #0 "); // r4, r5 will hold result mantissa sl@0: asm("orrcs r7, r7, #0x80000000 "); // if exponent odd, restore MSB of mantissa sl@0: asm("movcc r7, r5, lsl #12 "); // mantissa into r6,r7 with MSB in MSB of r7 sl@0: asm("orrcc r7, r7, r4, lsr #20 "); // if exponent even, shift mantissa left an extra sl@0: asm("movcc r6, r4, lsl #12 "); // place, lose top bit, and sl@0: asm("movcc r4, #1 "); // set MSB of result, and sl@0: asm("mov r5, #0 "); // r4, r5 will hold result mantissa sl@0: asm("mov r8, #0 "); // r8, r9 will be comparison accumulator sl@0: asm("mov r9, #0 "); sl@0: asm("bcc fastsqrt4 "); // if exponent even, calculate one less bit sl@0: // as result MSB already known sl@0: sl@0: // Main mantissa square-root loop sl@0: asm("fastsqrt3: "); // START OF MAIN LOOP sl@0: asm("subs r10, r7, r1 "); // subtract result:01 from acc:mant sl@0: asm("sbcs r12, r8, r4 "); // result into r14:r12:r10 sl@0: asm("sbcs r14, r9, r5 "); sl@0: asm("movcs r7, r10 "); // if no borrow replace accumulator with result sl@0: asm("movcs r8, r12 "); sl@0: asm("movcs r9, r14 "); sl@0: asm("adcs r4, r4, r4 "); // shift result left one, putting in next bit sl@0: asm("adcs r5, r5, r5 "); sl@0: asm("mov r9, r9, lsl #2 "); // shift acc:mant left by 2 bits sl@0: asm("orr r9, r9, r8, lsr #30 "); sl@0: asm("mov r8, r8, lsl #2 "); sl@0: asm("orr r8, r8, r7, lsr #30 "); sl@0: asm("mov r7, r7, lsl #2 "); sl@0: asm("orr r7, r7, r6, lsr #30 "); sl@0: asm("mov r6, r6, lsl #2 "); sl@0: asm("fastsqrt4: "); // Come in here if we need to do one less iteration sl@0: asm("subs r10, r7, r1 "); // subtract result:01 from acc:mant sl@0: asm("sbcs r12, r8, r4 "); // result into r14:r12:r10 sl@0: asm("sbcs r14, r9, r5 "); sl@0: asm("movcs r7, r10 "); // if no borrow replace accumulator with result sl@0: asm("movcs r8, r12 "); sl@0: asm("movcs r9, r14 "); sl@0: asm("adcs r4, r4, r4 "); // shift result left one, putting in next bit sl@0: asm("adcs r5, r5, r5 "); sl@0: asm("mov r9, r9, lsl #2 "); // shift acc:mant left by 2 bits sl@0: asm("orr r9, r9, r8, lsr #30 "); sl@0: asm("mov r8, r8, lsl #2 "); sl@0: asm("orr r8, r8, r7, lsr #30 "); sl@0: asm("mov r7, r7, lsl #2 "); sl@0: asm("orr r7, r7, r6, lsr #30 "); sl@0: asm("mov r6, r6, lsl #2 "); sl@0: asm("subs r3, r3, #1 "); // decrement loop counter sl@0: asm("bne fastsqrt3 "); // do necessary number of iterations sl@0: sl@0: asm("movs r4, r4, lsr #1 "); // shift result mantissa right 1 place sl@0: asm("orr r4, r4, r5, lsl #31 "); // LSB (=rounding bit) into carry sl@0: asm("mov r5, r5, lsr #1 "); sl@0: asm("adcs r4, r4, #0 "); // round the mantissa to 53 bits sl@0: asm("adcs r5, r5, #0 "); sl@0: asm("cmp r5, #0x00200000 "); // check for mantissa overflow sl@0: asm("addeq r2, r2, #1 "); // if so, increment exponent - can never overflow sl@0: asm("bic r5, r5, #0x00300000 "); // remove top bit of mantissa - it is implicit sl@0: asm("add r2, r2, #0xFF "); // re-bias the exponent sl@0: asm("add r3, r2, #0x300 "); // and move into r3 sl@0: asm("orr r3, r5, r3, lsl #20 "); // r3 now contains exponent + top of mantissa sl@0: asm("fastsqrt_ok: "); sl@0: #ifdef __DOUBLE_WORDS_SWAPPED__ sl@0: asm("stmia r0, {r3,r4} "); // store the result sl@0: #else sl@0: asm("str r3, [r0, #4] "); sl@0: asm("str r4, [r0, #0] "); sl@0: #endif sl@0: asm("mov r0, #0 "); // error code KErrNone sl@0: __POPRET("r4-r10,"); sl@0: sl@0: asm("fastsqrt1: "); sl@0: asm("orrs r6, r5, r4 "); // exponent zero - test mantissa sl@0: asm("beq fastsqrt_ok "); // if zero, return 0 sl@0: sl@0: asm("movs r3, r3 "); // denormal - test sign sl@0: asm("bmi fastsqrtn "); // branch out if negative sl@0: asm("sub r2, r2, #0xFE "); // unbias the exponent sl@0: asm("sub r2, r2, #0x300 "); // sl@0: asm("fastsqrtd: "); sl@0: asm("adds r4, r4, r4 "); // shift mantissa left sl@0: asm("adcs r5, r5, r5 "); sl@0: asm("sub r2, r2, #1 "); // and decrement exponent sl@0: asm("tst r5, #0x00100000 "); // test if normalised sl@0: asm("beq fastsqrtd "); // loop until normalised sl@0: asm("b fastsqrtd1 "); // now treat as a normalised number sl@0: asm("fastsqrt2: "); // get here if infinity or NaN sl@0: asm("orrs r6, r5, r4 "); // if mantissa zero, infinity sl@0: asm("bne fastsqrtnan "); // branch if not - must be NaN sl@0: asm("movs r3, r3 "); // test sign of infinity sl@0: asm("bmi fastsqrtn "); // branch if -ve sl@0: #ifdef __DOUBLE_WORDS_SWAPPED__ sl@0: asm("stmia r0, {r3,r4} "); // store the result sl@0: #else sl@0: asm("str r3, [r0, #4] "); sl@0: asm("str r4, [r0, #0] "); sl@0: #endif sl@0: asm("mov r0, #-9 "); // return KErrOverflow sl@0: asm("b fastsqrt_end "); sl@0: sl@0: asm("fastsqrtn: "); // get here if negative or QNaN operand sl@0: asm("mov r3, #0xFF000000 "); // generate "real indefinite" QNaN sl@0: asm("orr r3, r3, #0x00F80000 "); // sign=1, exp=7FF, mantissa = 1000...0 sl@0: asm("mov r4, #0 "); sl@0: asm("fastsqrtxa: "); sl@0: #ifdef __DOUBLE_WORDS_SWAPPED__ sl@0: asm("stmia r0, {r3,r4} "); // store the result sl@0: #else sl@0: asm("str r3, [r0, #4] "); sl@0: asm("str r4, [r0, #0] "); sl@0: #endif sl@0: asm("mov r0, #-6 "); // return KErrArgument sl@0: asm("fastsqrt_end: "); sl@0: __POPRET("r4-r10,"); sl@0: sl@0: asm("fastsqrtnan: "); // operand is a NaN sl@0: asm("tst r5, #0x00080000 "); // test MSB of mantissa sl@0: asm("bne fastsqrtn "); // if set it is a QNaN - so return "real indefinite" sl@0: asm("bic r3, r3, #0x00080000 "); // else convert SNaN to QNaN sl@0: asm("b fastsqrtxa "); // and return KErrArgument sl@0: sl@0: asm("Sqrt__FRdRCd_end: "); sl@0: sl@0: } sl@0: sl@0: __NAKED__ TUint Sqrt_Length() sl@0: { sl@0: asm("adr r0, Sqrt__FRdRCd_end "); sl@0: asm("adr r1, Sqrt__FRdRCd "); sl@0: asm("sub r0, r0, r1 "); sl@0: __JUMP(,lr); sl@0: } sl@0: sl@0: __NAKED__ TInt Divide(TRealX& /*aDividend*/, const TRealX& /*aDivisor*/) sl@0: { sl@0: asm("stmfd sp!, {r0,r4-r9,lr} "); sl@0: asm("ldmia r1, {r4,r5,r6} "); sl@0: asm("ldmia r0, {r1,r2,r3} "); sl@0: asm("bl TRealXDivide "); sl@0: asm("ldmfd sp!, {r0,r4-r9,lr} "); sl@0: asm("stmia r0, {r1,r2,r3} "); sl@0: asm("mov r0, r12 "); sl@0: __JUMP(,lr); sl@0: sl@0: // TRealX division r1,r2,r3 / r4,r5,r6 result in r1,r2,r3 sl@0: // Error code returned in r12 sl@0: // Registers r0-r9,r12 modified sl@0: // NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE. sl@0: asm("TRealXDivide: "); sl@0: asm("mov r12, #0 "); // initialise return value to KErrNone sl@0: asm("bic r3, r3, #0x300 "); // clear rounding flags sl@0: asm("tst r6, #1 "); sl@0: asm("eorne r3, r3, #1 "); // Exclusive-OR signs sl@0: asm("cmn r3, #0x10000 "); // check if dividend is NaN or infinity sl@0: asm("bcs TRealXDivide1 "); // branch if it is sl@0: asm("cmn r6, #0x10000 "); // check if divisor is NaN or infinity sl@0: asm("bcs TRealXDivide2 "); // branch if it is sl@0: asm("cmp r6, #0x10000 "); // check if divisor zero sl@0: asm("bcc TRealXDivide3 "); // branch if it is sl@0: asm("cmp r3, #0x10000 "); // check if dividend zero sl@0: __JUMP(cc,lr); // if zero, exit sl@0: asm("tst r3, #1 "); sl@0: asm("orrne lr, lr, #1 "); // save sign in bottom bit of lr sl@0: sl@0: // calculate result exponent sl@0: asm("mov r0, r3, lsr #16 "); // r0=dividend exponent sl@0: asm("sub r0, r0, r6, lsr #16 "); // r0=dividend exponent - divisor exponent sl@0: asm("add r0, r0, #0x7F00 "); sl@0: asm("add r0, r0, #0x00FF "); // r0 now contains result exponent sl@0: asm("mov r6, r1 "); // move dividend into r6,r7,r8 sl@0: asm("mov r7, r2 "); sl@0: asm("mov r8, #0 "); // use r8 to hold extra bit shifted up sl@0: // r2:r1 will hold result mantissa sl@0: asm("mov r2, #1 "); // we will make sure first bit is 1 sl@0: asm("cmp r7, r5 "); // compare dividend mantissa to divisor mantissa sl@0: asm("cmpeq r6, r4 "); sl@0: asm("bcs TRealXDivide4 "); // branch if dividend >= divisor sl@0: asm("adds r6, r6, r6 "); // else shift dividend left one sl@0: asm("adcs r7, r7, r7 "); // ignore carry here sl@0: asm("sub r0, r0, #1 "); // decrement result exponent by one sl@0: asm("TRealXDivide4: "); sl@0: asm("subs r6, r6, r4 "); // subtract divisor from dividend sl@0: asm("sbcs r7, r7, r5 "); sl@0: sl@0: // Main mantissa division code sl@0: // First calculate the top 32 bits of the result sl@0: // Top bit is 1, do 10 lots of 3 bits the one more bit sl@0: asm("mov r12, #10 "); sl@0: asm("TRealXDivide5: "); sl@0: asm("adds r6, r6, r6 "); // shift accumulator left by one sl@0: asm("adcs r7, r7, r7 "); sl@0: asm("adcs r8, r8, r8 "); sl@0: asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3 sl@0: asm("sbcs r3, r7, r5 "); sl@0: asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift sl@0: asm("movcs r6, r9 "); // if no borrow, replace accumulator with result sl@0: asm("movcs r7, r3 "); sl@0: asm("adcs r2, r2, r2 "); // shift in new result bit sl@0: asm("adds r6, r6, r6 "); // shift accumulator left by one sl@0: asm("adcs r7, r7, r7 "); sl@0: asm("adcs r8, r8, r8 "); sl@0: asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3 sl@0: asm("sbcs r3, r7, r5 "); sl@0: asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift sl@0: asm("movcs r6, r9 "); // if no borrow, replace accumulator with result sl@0: asm("movcs r7, r3 "); sl@0: asm("adcs r2, r2, r2 "); // shift in new result bit sl@0: asm("adds r6, r6, r6 "); // shift accumulator left by one sl@0: asm("adcs r7, r7, r7 "); sl@0: asm("adcs r8, r8, r8 "); sl@0: asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3 sl@0: asm("sbcs r3, r7, r5 "); sl@0: asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift sl@0: asm("movcs r6, r9 "); // if no borrow, replace accumulator with result sl@0: asm("movcs r7, r3 "); sl@0: asm("adcs r2, r2, r2 "); // shift in new result bit sl@0: asm("subs r12, r12, #1 "); sl@0: asm("bne TRealXDivide5 "); // iterate the loop sl@0: asm("adds r6, r6, r6 "); // shift accumulator left by one sl@0: asm("adcs r7, r7, r7 "); sl@0: asm("adcs r8, r8, r8 "); sl@0: asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3 sl@0: asm("sbcs r3, r7, r5 "); sl@0: asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift sl@0: asm("movcs r6, r9 "); // if no borrow, replace accumulator with result sl@0: asm("movcs r7, r3 "); sl@0: asm("adcs r2, r2, r2 "); // shift in new result bit - now have 32 bits sl@0: sl@0: // Now calculate the bottom 32 bits of the result sl@0: // Do 8 lots of 4 bits sl@0: asm("mov r12, #8 "); sl@0: asm("TRealXDivide5a: "); sl@0: asm("adds r6, r6, r6 "); // shift accumulator left by one sl@0: asm("adcs r7, r7, r7 "); sl@0: asm("adcs r8, r8, r8 "); sl@0: asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3 sl@0: asm("sbcs r3, r7, r5 "); sl@0: asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift sl@0: asm("movcs r6, r9 "); // if no borrow, replace accumulator with result sl@0: asm("movcs r7, r3 "); sl@0: asm("adcs r1, r1, r1 "); // shift in new result bit sl@0: asm("adds r6, r6, r6 "); // shift accumulator left by one sl@0: asm("adcs r7, r7, r7 "); sl@0: asm("adcs r8, r8, r8 "); sl@0: asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3 sl@0: asm("sbcs r3, r7, r5 "); sl@0: asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift sl@0: asm("movcs r6, r9 "); // if no borrow, replace accumulator with result sl@0: asm("movcs r7, r3 "); sl@0: asm("adcs r1, r1, r1 "); // shift in new result bit sl@0: asm("adds r6, r6, r6 "); // shift accumulator left by one sl@0: asm("adcs r7, r7, r7 "); sl@0: asm("adcs r8, r8, r8 "); sl@0: asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3 sl@0: asm("sbcs r3, r7, r5 "); sl@0: asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift sl@0: asm("movcs r6, r9 "); // if no borrow, replace accumulator with result sl@0: asm("movcs r7, r3 "); sl@0: asm("adcs r1, r1, r1 "); // shift in new result bit sl@0: asm("adds r6, r6, r6 "); // shift accumulator left by one sl@0: asm("adcs r7, r7, r7 "); sl@0: asm("adcs r8, r8, r8 "); sl@0: asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3 sl@0: asm("sbcs r3, r7, r5 "); sl@0: asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift sl@0: asm("movcs r6, r9 "); // if no borrow, replace accumulator with result sl@0: asm("movcs r7, r3 "); sl@0: asm("adcs r1, r1, r1 "); // shift in new result bit sl@0: asm("subs r12, r12, #1 "); sl@0: asm("bne TRealXDivide5a "); // iterate the loop sl@0: sl@0: // r2:r1 now contains a 64-bit normalised mantissa sl@0: // need to do rounding now sl@0: asm("and r3, lr, #1 "); // result sign back into r3 sl@0: asm("orrs r9, r6, r7 "); // check if accumulator zero sl@0: asm("beq TRealXDivide6 "); // if it is, result is exact, else generate next bit sl@0: asm("adds r6, r6, r6 "); // shift accumulator left by one sl@0: asm("adcs r7, r7, r7 "); sl@0: asm("adcs r8, r8, r8 "); sl@0: asm("subs r6, r6, r4 "); // subtract divisor from accumulator sl@0: asm("sbcs r7, r7, r5 "); sl@0: asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift sl@0: asm("orrcc r3, r3, #0x100 "); // if borrow, round down and set round-down flag sl@0: asm("bcc TRealXDivide6 "); sl@0: asm("orrs r9, r6, r7 "); // if no borrow, check if exactly half-way sl@0: asm("moveqs r9, r1, lsr #1 "); // if exactly half-way, round to even sl@0: asm("orrcc r3, r3, #0x100 "); // if C=0, round result down and set round-down flag sl@0: asm("bcc TRealXDivide6 "); sl@0: asm("orr r3, r3, #0x200 "); // else set round-up flag sl@0: asm("adds r1, r1, #1 "); // and round mantissa up sl@0: asm("adcs r2, r2, #0 "); sl@0: asm("movcs r2, #0x80000000 "); // if carry, mantissa = 80000000 00000000 sl@0: asm("addcs r0, r0, #1 "); // and increment exponent sl@0: sl@0: // check for overflow or underflow and assemble final result sl@0: asm("TRealXDivide6: "); sl@0: asm("add r4, r0, #1 "); // need to add 1 to get usable threshold sl@0: asm("cmp r4, #0x10000 "); // check if exponent >= 0xFFFF sl@0: asm("bge TRealXMultiply6 "); // if so, overflow sl@0: asm("cmp r0, #0 "); // check for underflow sl@0: asm("orrgt r3, r3, r0, lsl #16 "); // if no underflow, result exponent into r3, ... sl@0: asm("movgt r12, #0 "); // ... return KErrNone ... sl@0: __JUMP(gt,lr); sl@0: sl@0: // underflow sl@0: asm("and r3, r3, #1 "); // set exponent=0, keep sign sl@0: asm("mvn r12, #9 "); // return KErrUnderflow sl@0: __JUMP(,lr); sl@0: sl@0: // come here if divisor is zero, dividend finite sl@0: asm("TRealXDivide3: "); sl@0: asm("cmp r3, #0x10000 "); // check if dividend also zero sl@0: asm("bcc TRealXRealIndefinite "); // if so, return 'real indefinite' sl@0: asm("orr r3, r3, #0xFF000000 "); // else return infinity with xor sign sl@0: asm("orr r3, r3, #0x00FF0000 "); sl@0: asm("mov r2, #0x80000000 "); sl@0: asm("mov r1, #0 "); sl@0: asm("mvn r12, #40 "); // return KErrDivideByZero sl@0: __JUMP(,lr); sl@0: sl@0: // Dividend is NaN or infinity sl@0: asm("TRealXDivide1: "); sl@0: asm("cmp r2, #0x80000000 "); // check for infinity sl@0: asm("cmpeq r1, #0 "); sl@0: asm("bne TRealXBinOpNan "); // branch if NaN sl@0: asm("cmn r6, #0x10000 "); // check 2nd operand for NaN/infinity sl@0: asm("mvncc r12, #8 "); // if not, return KErrOverflow sl@0: __JUMP(cc,lr); sl@0: sl@0: // Dividend=infinity, divisor=NaN or infinity sl@0: asm("cmp r5, #0x80000000 "); // check 2nd operand for infinity sl@0: asm("cmpeq r4, #0 "); sl@0: asm("bne TRealXBinOpNan "); // branch if NaN sl@0: asm("b TRealXRealIndefinite "); // else return 'real indefinite' sl@0: sl@0: // Divisor is NaN or infinity, dividend finite sl@0: asm("TRealXDivide2: "); sl@0: asm("cmp r5, #0x80000000 "); // check for infinity sl@0: asm("cmpeq r4, #0 "); sl@0: asm("bne TRealXBinOpNan "); // branch if NaN sl@0: asm("and r3, r3, #1 "); // else return zero with xor sign sl@0: __JUMP(,lr); sl@0: sl@0: asm("TRealXBinOpNan: "); // generic routine to process NaNs in binary sl@0: // operations sl@0: asm("cmn r3, #0x10000 "); // check if first operand is NaN sl@0: asm("movcc r0, r1 "); // if not, swap the operands sl@0: asm("movcc r1, r4 "); sl@0: asm("movcc r4, r0 "); sl@0: asm("movcc r0, r2 "); sl@0: asm("movcc r2, r5 "); sl@0: asm("movcc r5, r0 "); sl@0: asm("movcc r0, r3 "); sl@0: asm("movcc r3, r6 "); sl@0: asm("movcc r6, r0 "); sl@0: asm("cmn r6, #0x10000 "); // both operands NaNs? sl@0: asm("bcc TRealXBinOpNan1 "); // skip if not sl@0: asm("cmp r2, r5 "); // if so, compare the significands sl@0: asm("cmpeq r1, r4 "); sl@0: asm("movcc r1, r4 "); // r1,r2,r3 will get NaN with larger significand sl@0: asm("movcc r2, r5 "); sl@0: asm("movcc r3, r6 "); sl@0: asm("TRealXBinOpNan1: "); sl@0: asm("orr r2, r2, #0x40000000 "); // convert an SNaN to a QNaN sl@0: asm("mvn r12, #5 "); // return KErrArgument sl@0: __JUMP(,lr); sl@0: sl@0: // Return 'real indefinite' sl@0: asm("TRealXRealIndefinite: "); sl@0: asm("ldr r3, __RealIndefiniteExponent "); sl@0: asm("mov r2, #0xC0000000 "); sl@0: asm("mov r1, #0 "); sl@0: asm("mvn r12, #5 "); // return KErrArgument sl@0: __JUMP(,lr); sl@0: sl@0: // overflow sl@0: asm("TRealXMultiply6: "); sl@0: asm("bic r3, r3, #0x0000FF00 "); // clear rounding flags sl@0: asm("orr r3, r3, #0xFF000000 "); // make exponent FFFF for infinity sl@0: asm("orr r3, r3, #0x00FF0000 "); sl@0: asm("mov r2, #0x80000000 "); // mantissa = 80000000 00000000 sl@0: asm("mov r1, #0 "); sl@0: asm("mvn r12, #8 "); // return KErrOverflow sl@0: __JUMP(,lr); sl@0: sl@0: asm("__RealIndefiniteExponent: "); sl@0: asm(".word 0xFFFF0001 "); sl@0: sl@0: asm("Divide__FR6TRealXRC6TRealX_end: "); sl@0: } sl@0: sl@0: __NAKED__ TUint Divide_Length() sl@0: { sl@0: asm("adr r0, Divide__FR6TRealXRC6TRealX_end "); sl@0: asm("adr r1, Divide__FR6TRealXRC6TRealX "); sl@0: asm("sub r0, r0, r1 "); sl@0: __JUMP(,lr); sl@0: } sl@0: sl@0: __NAKED__ TInt SDummy(TInt) sl@0: { sl@0: __JUMP(,lr); sl@0: asm("SDummy__Fi_end: "); sl@0: } sl@0: sl@0: __NAKED__ TUint SDummy_Length() sl@0: { sl@0: asm("adr r0, SDummy__Fi_end "); sl@0: asm("adr r1, SDummy__Fi "); sl@0: asm("sub r0, r0, r1 "); sl@0: __JUMP(,lr); sl@0: } sl@0: sl@0: __NAKED__ TInt Increment(TInt) sl@0: { sl@0: asm("add r0, r0, #1 "); sl@0: __JUMP(,lr); sl@0: asm("Increment__Fi_end: "); sl@0: } sl@0: sl@0: __NAKED__ TUint Increment_Length() sl@0: { sl@0: asm("adr r0, Increment__Fi_end "); sl@0: asm("adr r1, Increment__Fi "); sl@0: asm("sub r0, r0, r1 "); sl@0: __JUMP(,lr); sl@0: } sl@0: sl@0: #endif