1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/mmu/t_imb.cia Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,479 @@
1.4 +// Copyright (c) 1995-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 +// e32test\mmu\t_imb.cia
1.18 +//
1.19 +//
1.20 +
1.21 +#include <e32test.h>
1.22 +#include <u32std.h>
1.23 +#include <e32math.h>
1.24 +
1.25 +#ifdef __CPU_ARM
1.26 +__NAKED__ TInt Sqrt(TReal& /*aDest*/, const TReal& /*aSrc*/)
1.27 + {
1.28 + // r0=address of aDest, r1=address of aSrc
1.29 + asm("stmfd sp!, {r4-r10,lr} ");
1.30 +#ifdef __DOUBLE_WORDS_SWAPPED__
1.31 + asm("ldmia r1, {r3,r4} "); // low mant into r4, sign:exp:high mant into r3
1.32 +#else
1.33 + asm("ldr r3, [r1, #4] ");
1.34 + asm("ldr r4, [r1, #0] ");
1.35 +#endif
1.36 + asm("bic r5, r3, #0xFF000000 ");
1.37 + asm("bic r5, r5, #0x00F00000 "); // high word of mantissa into r5
1.38 + asm("mov r2, r3, lsr #20 ");
1.39 + asm("bics r2, r2, #0x800 "); // exponent now in r2
1.40 + asm("beq fastsqrt1 "); // branch if exponent zero (zero or denormal)
1.41 + asm("mov r6, #0xFF ");
1.42 + asm("orr r6, r6, #0x700 ");
1.43 + asm("cmp r2, r6 "); // check for infinity or NaN
1.44 + asm("beq fastsqrt2 "); // branch if infinity or NaN
1.45 + asm("movs r3, r3 "); // test sign
1.46 + asm("bmi fastsqrtn "); // branch if negative
1.47 + asm("sub r2, r2, #0xFF "); // unbias the exponent
1.48 + asm("sub r2, r2, #0x300 "); //
1.49 + asm("fastsqrtd1: ");
1.50 + asm("mov r1, #0x40000000 "); // value for comparison
1.51 + asm("mov r3, #27 "); // loop counter (number of bits/2)
1.52 + asm("movs r2, r2, asr #1 "); // divide exponent by 2, LSB into CF
1.53 + asm("movcs r7, r5, lsl #11 "); // mantissa into r6,r7 with MSB in MSB of r7
1.54 + asm("orrcs r7, r7, r4, lsr #21 ");
1.55 + asm("movcs r6, r4, lsl #11 ");
1.56 + asm("movcs r4, #0 "); // r4, r5 will hold result mantissa
1.57 + asm("orrcs r7, r7, #0x80000000 "); // if exponent odd, restore MSB of mantissa
1.58 + asm("movcc r7, r5, lsl #12 "); // mantissa into r6,r7 with MSB in MSB of r7
1.59 + asm("orrcc r7, r7, r4, lsr #20 "); // if exponent even, shift mantissa left an extra
1.60 + asm("movcc r6, r4, lsl #12 "); // place, lose top bit, and
1.61 + asm("movcc r4, #1 "); // set MSB of result, and
1.62 + asm("mov r5, #0 "); // r4, r5 will hold result mantissa
1.63 + asm("mov r8, #0 "); // r8, r9 will be comparison accumulator
1.64 + asm("mov r9, #0 ");
1.65 + asm("bcc fastsqrt4 "); // if exponent even, calculate one less bit
1.66 + // as result MSB already known
1.67 +
1.68 + // Main mantissa square-root loop
1.69 + asm("fastsqrt3: "); // START OF MAIN LOOP
1.70 + asm("subs r10, r7, r1 "); // subtract result:01 from acc:mant
1.71 + asm("sbcs r12, r8, r4 "); // result into r14:r12:r10
1.72 + asm("sbcs r14, r9, r5 ");
1.73 + asm("movcs r7, r10 "); // if no borrow replace accumulator with result
1.74 + asm("movcs r8, r12 ");
1.75 + asm("movcs r9, r14 ");
1.76 + asm("adcs r4, r4, r4 "); // shift result left one, putting in next bit
1.77 + asm("adcs r5, r5, r5 ");
1.78 + asm("mov r9, r9, lsl #2 "); // shift acc:mant left by 2 bits
1.79 + asm("orr r9, r9, r8, lsr #30 ");
1.80 + asm("mov r8, r8, lsl #2 ");
1.81 + asm("orr r8, r8, r7, lsr #30 ");
1.82 + asm("mov r7, r7, lsl #2 ");
1.83 + asm("orr r7, r7, r6, lsr #30 ");
1.84 + asm("mov r6, r6, lsl #2 ");
1.85 + asm("fastsqrt4: "); // Come in here if we need to do one less iteration
1.86 + asm("subs r10, r7, r1 "); // subtract result:01 from acc:mant
1.87 + asm("sbcs r12, r8, r4 "); // result into r14:r12:r10
1.88 + asm("sbcs r14, r9, r5 ");
1.89 + asm("movcs r7, r10 "); // if no borrow replace accumulator with result
1.90 + asm("movcs r8, r12 ");
1.91 + asm("movcs r9, r14 ");
1.92 + asm("adcs r4, r4, r4 "); // shift result left one, putting in next bit
1.93 + asm("adcs r5, r5, r5 ");
1.94 + asm("mov r9, r9, lsl #2 "); // shift acc:mant left by 2 bits
1.95 + asm("orr r9, r9, r8, lsr #30 ");
1.96 + asm("mov r8, r8, lsl #2 ");
1.97 + asm("orr r8, r8, r7, lsr #30 ");
1.98 + asm("mov r7, r7, lsl #2 ");
1.99 + asm("orr r7, r7, r6, lsr #30 ");
1.100 + asm("mov r6, r6, lsl #2 ");
1.101 + asm("subs r3, r3, #1 "); // decrement loop counter
1.102 + asm("bne fastsqrt3 "); // do necessary number of iterations
1.103 +
1.104 + asm("movs r4, r4, lsr #1 "); // shift result mantissa right 1 place
1.105 + asm("orr r4, r4, r5, lsl #31 "); // LSB (=rounding bit) into carry
1.106 + asm("mov r5, r5, lsr #1 ");
1.107 + asm("adcs r4, r4, #0 "); // round the mantissa to 53 bits
1.108 + asm("adcs r5, r5, #0 ");
1.109 + asm("cmp r5, #0x00200000 "); // check for mantissa overflow
1.110 + asm("addeq r2, r2, #1 "); // if so, increment exponent - can never overflow
1.111 + asm("bic r5, r5, #0x00300000 "); // remove top bit of mantissa - it is implicit
1.112 + asm("add r2, r2, #0xFF "); // re-bias the exponent
1.113 + asm("add r3, r2, #0x300 "); // and move into r3
1.114 + asm("orr r3, r5, r3, lsl #20 "); // r3 now contains exponent + top of mantissa
1.115 + asm("fastsqrt_ok: ");
1.116 +#ifdef __DOUBLE_WORDS_SWAPPED__
1.117 + asm("stmia r0, {r3,r4} "); // store the result
1.118 +#else
1.119 + asm("str r3, [r0, #4] ");
1.120 + asm("str r4, [r0, #0] ");
1.121 +#endif
1.122 + asm("mov r0, #0 "); // error code KErrNone
1.123 + __POPRET("r4-r10,");
1.124 +
1.125 + asm("fastsqrt1: ");
1.126 + asm("orrs r6, r5, r4 "); // exponent zero - test mantissa
1.127 + asm("beq fastsqrt_ok "); // if zero, return 0
1.128 +
1.129 + asm("movs r3, r3 "); // denormal - test sign
1.130 + asm("bmi fastsqrtn "); // branch out if negative
1.131 + asm("sub r2, r2, #0xFE "); // unbias the exponent
1.132 + asm("sub r2, r2, #0x300 "); //
1.133 + asm("fastsqrtd: ");
1.134 + asm("adds r4, r4, r4 "); // shift mantissa left
1.135 + asm("adcs r5, r5, r5 ");
1.136 + asm("sub r2, r2, #1 "); // and decrement exponent
1.137 + asm("tst r5, #0x00100000 "); // test if normalised
1.138 + asm("beq fastsqrtd "); // loop until normalised
1.139 + asm("b fastsqrtd1 "); // now treat as a normalised number
1.140 + asm("fastsqrt2: "); // get here if infinity or NaN
1.141 + asm("orrs r6, r5, r4 "); // if mantissa zero, infinity
1.142 + asm("bne fastsqrtnan "); // branch if not - must be NaN
1.143 + asm("movs r3, r3 "); // test sign of infinity
1.144 + asm("bmi fastsqrtn "); // branch if -ve
1.145 +#ifdef __DOUBLE_WORDS_SWAPPED__
1.146 + asm("stmia r0, {r3,r4} "); // store the result
1.147 +#else
1.148 + asm("str r3, [r0, #4] ");
1.149 + asm("str r4, [r0, #0] ");
1.150 +#endif
1.151 + asm("mov r0, #-9 "); // return KErrOverflow
1.152 + asm("b fastsqrt_end ");
1.153 +
1.154 + asm("fastsqrtn: "); // get here if negative or QNaN operand
1.155 + asm("mov r3, #0xFF000000 "); // generate "real indefinite" QNaN
1.156 + asm("orr r3, r3, #0x00F80000 "); // sign=1, exp=7FF, mantissa = 1000...0
1.157 + asm("mov r4, #0 ");
1.158 + asm("fastsqrtxa: ");
1.159 +#ifdef __DOUBLE_WORDS_SWAPPED__
1.160 + asm("stmia r0, {r3,r4} "); // store the result
1.161 +#else
1.162 + asm("str r3, [r0, #4] ");
1.163 + asm("str r4, [r0, #0] ");
1.164 +#endif
1.165 + asm("mov r0, #-6 "); // return KErrArgument
1.166 + asm("fastsqrt_end: ");
1.167 + __POPRET("r4-r10,");
1.168 +
1.169 + asm("fastsqrtnan: "); // operand is a NaN
1.170 + asm("tst r5, #0x00080000 "); // test MSB of mantissa
1.171 + asm("bne fastsqrtn "); // if set it is a QNaN - so return "real indefinite"
1.172 + asm("bic r3, r3, #0x00080000 "); // else convert SNaN to QNaN
1.173 + asm("b fastsqrtxa "); // and return KErrArgument
1.174 +
1.175 + asm("Sqrt__FRdRCd_end: ");
1.176 +
1.177 + }
1.178 +
1.179 +__NAKED__ TUint Sqrt_Length()
1.180 + {
1.181 + asm("adr r0, Sqrt__FRdRCd_end ");
1.182 + asm("adr r1, Sqrt__FRdRCd ");
1.183 + asm("sub r0, r0, r1 ");
1.184 + __JUMP(,lr);
1.185 + }
1.186 +
1.187 +__NAKED__ TInt Divide(TRealX& /*aDividend*/, const TRealX& /*aDivisor*/)
1.188 + {
1.189 + asm("stmfd sp!, {r0,r4-r9,lr} ");
1.190 + asm("ldmia r1, {r4,r5,r6} ");
1.191 + asm("ldmia r0, {r1,r2,r3} ");
1.192 + asm("bl TRealXDivide ");
1.193 + asm("ldmfd sp!, {r0,r4-r9,lr} ");
1.194 + asm("stmia r0, {r1,r2,r3} ");
1.195 + asm("mov r0, r12 ");
1.196 + __JUMP(,lr);
1.197 +
1.198 + // TRealX division r1,r2,r3 / r4,r5,r6 result in r1,r2,r3
1.199 + // Error code returned in r12
1.200 + // Registers r0-r9,r12 modified
1.201 + // NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
1.202 + asm("TRealXDivide: ");
1.203 + asm("mov r12, #0 "); // initialise return value to KErrNone
1.204 + asm("bic r3, r3, #0x300 "); // clear rounding flags
1.205 + asm("tst r6, #1 ");
1.206 + asm("eorne r3, r3, #1 "); // Exclusive-OR signs
1.207 + asm("cmn r3, #0x10000 "); // check if dividend is NaN or infinity
1.208 + asm("bcs TRealXDivide1 "); // branch if it is
1.209 + asm("cmn r6, #0x10000 "); // check if divisor is NaN or infinity
1.210 + asm("bcs TRealXDivide2 "); // branch if it is
1.211 + asm("cmp r6, #0x10000 "); // check if divisor zero
1.212 + asm("bcc TRealXDivide3 "); // branch if it is
1.213 + asm("cmp r3, #0x10000 "); // check if dividend zero
1.214 + __JUMP(cc,lr); // if zero, exit
1.215 + asm("tst r3, #1 ");
1.216 + asm("orrne lr, lr, #1 "); // save sign in bottom bit of lr
1.217 +
1.218 + // calculate result exponent
1.219 + asm("mov r0, r3, lsr #16 "); // r0=dividend exponent
1.220 + asm("sub r0, r0, r6, lsr #16 "); // r0=dividend exponent - divisor exponent
1.221 + asm("add r0, r0, #0x7F00 ");
1.222 + asm("add r0, r0, #0x00FF "); // r0 now contains result exponent
1.223 + asm("mov r6, r1 "); // move dividend into r6,r7,r8
1.224 + asm("mov r7, r2 ");
1.225 + asm("mov r8, #0 "); // use r8 to hold extra bit shifted up
1.226 + // r2:r1 will hold result mantissa
1.227 + asm("mov r2, #1 "); // we will make sure first bit is 1
1.228 + asm("cmp r7, r5 "); // compare dividend mantissa to divisor mantissa
1.229 + asm("cmpeq r6, r4 ");
1.230 + asm("bcs TRealXDivide4 "); // branch if dividend >= divisor
1.231 + asm("adds r6, r6, r6 "); // else shift dividend left one
1.232 + asm("adcs r7, r7, r7 "); // ignore carry here
1.233 + asm("sub r0, r0, #1 "); // decrement result exponent by one
1.234 + asm("TRealXDivide4: ");
1.235 + asm("subs r6, r6, r4 "); // subtract divisor from dividend
1.236 + asm("sbcs r7, r7, r5 ");
1.237 +
1.238 + // Main mantissa division code
1.239 + // First calculate the top 32 bits of the result
1.240 + // Top bit is 1, do 10 lots of 3 bits the one more bit
1.241 + asm("mov r12, #10 ");
1.242 + asm("TRealXDivide5: ");
1.243 + asm("adds r6, r6, r6 "); // shift accumulator left by one
1.244 + asm("adcs r7, r7, r7 ");
1.245 + asm("adcs r8, r8, r8 ");
1.246 + asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3
1.247 + asm("sbcs r3, r7, r5 ");
1.248 + asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift
1.249 + asm("movcs r6, r9 "); // if no borrow, replace accumulator with result
1.250 + asm("movcs r7, r3 ");
1.251 + asm("adcs r2, r2, r2 "); // shift in new result bit
1.252 + asm("adds r6, r6, r6 "); // shift accumulator left by one
1.253 + asm("adcs r7, r7, r7 ");
1.254 + asm("adcs r8, r8, r8 ");
1.255 + asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3
1.256 + asm("sbcs r3, r7, r5 ");
1.257 + asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift
1.258 + asm("movcs r6, r9 "); // if no borrow, replace accumulator with result
1.259 + asm("movcs r7, r3 ");
1.260 + asm("adcs r2, r2, r2 "); // shift in new result bit
1.261 + asm("adds r6, r6, r6 "); // shift accumulator left by one
1.262 + asm("adcs r7, r7, r7 ");
1.263 + asm("adcs r8, r8, r8 ");
1.264 + asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3
1.265 + asm("sbcs r3, r7, r5 ");
1.266 + asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift
1.267 + asm("movcs r6, r9 "); // if no borrow, replace accumulator with result
1.268 + asm("movcs r7, r3 ");
1.269 + asm("adcs r2, r2, r2 "); // shift in new result bit
1.270 + asm("subs r12, r12, #1 ");
1.271 + asm("bne TRealXDivide5 "); // iterate the loop
1.272 + asm("adds r6, r6, r6 "); // shift accumulator left by one
1.273 + asm("adcs r7, r7, r7 ");
1.274 + asm("adcs r8, r8, r8 ");
1.275 + asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3
1.276 + asm("sbcs r3, r7, r5 ");
1.277 + asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift
1.278 + asm("movcs r6, r9 "); // if no borrow, replace accumulator with result
1.279 + asm("movcs r7, r3 ");
1.280 + asm("adcs r2, r2, r2 "); // shift in new result bit - now have 32 bits
1.281 +
1.282 + // Now calculate the bottom 32 bits of the result
1.283 + // Do 8 lots of 4 bits
1.284 + asm("mov r12, #8 ");
1.285 + asm("TRealXDivide5a: ");
1.286 + asm("adds r6, r6, r6 "); // shift accumulator left by one
1.287 + asm("adcs r7, r7, r7 ");
1.288 + asm("adcs r8, r8, r8 ");
1.289 + asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3
1.290 + asm("sbcs r3, r7, r5 ");
1.291 + asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift
1.292 + asm("movcs r6, r9 "); // if no borrow, replace accumulator with result
1.293 + asm("movcs r7, r3 ");
1.294 + asm("adcs r1, r1, r1 "); // shift in new result bit
1.295 + asm("adds r6, r6, r6 "); // shift accumulator left by one
1.296 + asm("adcs r7, r7, r7 ");
1.297 + asm("adcs r8, r8, r8 ");
1.298 + asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3
1.299 + asm("sbcs r3, r7, r5 ");
1.300 + asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift
1.301 + asm("movcs r6, r9 "); // if no borrow, replace accumulator with result
1.302 + asm("movcs r7, r3 ");
1.303 + asm("adcs r1, r1, r1 "); // shift in new result bit
1.304 + asm("adds r6, r6, r6 "); // shift accumulator left by one
1.305 + asm("adcs r7, r7, r7 ");
1.306 + asm("adcs r8, r8, r8 ");
1.307 + asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3
1.308 + asm("sbcs r3, r7, r5 ");
1.309 + asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift
1.310 + asm("movcs r6, r9 "); // if no borrow, replace accumulator with result
1.311 + asm("movcs r7, r3 ");
1.312 + asm("adcs r1, r1, r1 "); // shift in new result bit
1.313 + asm("adds r6, r6, r6 "); // shift accumulator left by one
1.314 + asm("adcs r7, r7, r7 ");
1.315 + asm("adcs r8, r8, r8 ");
1.316 + asm("subs r9, r6, r4 "); // subtract divisor from accumulator, result in r9,r3
1.317 + asm("sbcs r3, r7, r5 ");
1.318 + asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift
1.319 + asm("movcs r6, r9 "); // if no borrow, replace accumulator with result
1.320 + asm("movcs r7, r3 ");
1.321 + asm("adcs r1, r1, r1 "); // shift in new result bit
1.322 + asm("subs r12, r12, #1 ");
1.323 + asm("bne TRealXDivide5a "); // iterate the loop
1.324 +
1.325 + // r2:r1 now contains a 64-bit normalised mantissa
1.326 + // need to do rounding now
1.327 + asm("and r3, lr, #1 "); // result sign back into r3
1.328 + asm("orrs r9, r6, r7 "); // check if accumulator zero
1.329 + asm("beq TRealXDivide6 "); // if it is, result is exact, else generate next bit
1.330 + asm("adds r6, r6, r6 "); // shift accumulator left by one
1.331 + asm("adcs r7, r7, r7 ");
1.332 + asm("adcs r8, r8, r8 ");
1.333 + asm("subs r6, r6, r4 "); // subtract divisor from accumulator
1.334 + asm("sbcs r7, r7, r5 ");
1.335 + asm("movccs r8, r8, lsr #1 "); // if borrow, check for carry from shift
1.336 + asm("orrcc r3, r3, #0x100 "); // if borrow, round down and set round-down flag
1.337 + asm("bcc TRealXDivide6 ");
1.338 + asm("orrs r9, r6, r7 "); // if no borrow, check if exactly half-way
1.339 + asm("moveqs r9, r1, lsr #1 "); // if exactly half-way, round to even
1.340 + asm("orrcc r3, r3, #0x100 "); // if C=0, round result down and set round-down flag
1.341 + asm("bcc TRealXDivide6 ");
1.342 + asm("orr r3, r3, #0x200 "); // else set round-up flag
1.343 + asm("adds r1, r1, #1 "); // and round mantissa up
1.344 + asm("adcs r2, r2, #0 ");
1.345 + asm("movcs r2, #0x80000000 "); // if carry, mantissa = 80000000 00000000
1.346 + asm("addcs r0, r0, #1 "); // and increment exponent
1.347 +
1.348 + // check for overflow or underflow and assemble final result
1.349 + asm("TRealXDivide6: ");
1.350 + asm("add r4, r0, #1 "); // need to add 1 to get usable threshold
1.351 + asm("cmp r4, #0x10000 "); // check if exponent >= 0xFFFF
1.352 + asm("bge TRealXMultiply6 "); // if so, overflow
1.353 + asm("cmp r0, #0 "); // check for underflow
1.354 + asm("orrgt r3, r3, r0, lsl #16 "); // if no underflow, result exponent into r3, ...
1.355 + asm("movgt r12, #0 "); // ... return KErrNone ...
1.356 + __JUMP(gt,lr);
1.357 +
1.358 + // underflow
1.359 + asm("and r3, r3, #1 "); // set exponent=0, keep sign
1.360 + asm("mvn r12, #9 "); // return KErrUnderflow
1.361 + __JUMP(,lr);
1.362 +
1.363 + // come here if divisor is zero, dividend finite
1.364 + asm("TRealXDivide3: ");
1.365 + asm("cmp r3, #0x10000 "); // check if dividend also zero
1.366 + asm("bcc TRealXRealIndefinite "); // if so, return 'real indefinite'
1.367 + asm("orr r3, r3, #0xFF000000 "); // else return infinity with xor sign
1.368 + asm("orr r3, r3, #0x00FF0000 ");
1.369 + asm("mov r2, #0x80000000 ");
1.370 + asm("mov r1, #0 ");
1.371 + asm("mvn r12, #40 "); // return KErrDivideByZero
1.372 + __JUMP(,lr);
1.373 +
1.374 + // Dividend is NaN or infinity
1.375 + asm("TRealXDivide1: ");
1.376 + asm("cmp r2, #0x80000000 "); // check for infinity
1.377 + asm("cmpeq r1, #0 ");
1.378 + asm("bne TRealXBinOpNan "); // branch if NaN
1.379 + asm("cmn r6, #0x10000 "); // check 2nd operand for NaN/infinity
1.380 + asm("mvncc r12, #8 "); // if not, return KErrOverflow
1.381 + __JUMP(cc,lr);
1.382 +
1.383 + // Dividend=infinity, divisor=NaN or infinity
1.384 + asm("cmp r5, #0x80000000 "); // check 2nd operand for infinity
1.385 + asm("cmpeq r4, #0 ");
1.386 + asm("bne TRealXBinOpNan "); // branch if NaN
1.387 + asm("b TRealXRealIndefinite "); // else return 'real indefinite'
1.388 +
1.389 + // Divisor is NaN or infinity, dividend finite
1.390 + asm("TRealXDivide2: ");
1.391 + asm("cmp r5, #0x80000000 "); // check for infinity
1.392 + asm("cmpeq r4, #0 ");
1.393 + asm("bne TRealXBinOpNan "); // branch if NaN
1.394 + asm("and r3, r3, #1 "); // else return zero with xor sign
1.395 + __JUMP(,lr);
1.396 +
1.397 + asm("TRealXBinOpNan: "); // generic routine to process NaNs in binary
1.398 + // operations
1.399 + asm("cmn r3, #0x10000 "); // check if first operand is NaN
1.400 + asm("movcc r0, r1 "); // if not, swap the operands
1.401 + asm("movcc r1, r4 ");
1.402 + asm("movcc r4, r0 ");
1.403 + asm("movcc r0, r2 ");
1.404 + asm("movcc r2, r5 ");
1.405 + asm("movcc r5, r0 ");
1.406 + asm("movcc r0, r3 ");
1.407 + asm("movcc r3, r6 ");
1.408 + asm("movcc r6, r0 ");
1.409 + asm("cmn r6, #0x10000 "); // both operands NaNs?
1.410 + asm("bcc TRealXBinOpNan1 "); // skip if not
1.411 + asm("cmp r2, r5 "); // if so, compare the significands
1.412 + asm("cmpeq r1, r4 ");
1.413 + asm("movcc r1, r4 "); // r1,r2,r3 will get NaN with larger significand
1.414 + asm("movcc r2, r5 ");
1.415 + asm("movcc r3, r6 ");
1.416 + asm("TRealXBinOpNan1: ");
1.417 + asm("orr r2, r2, #0x40000000 "); // convert an SNaN to a QNaN
1.418 + asm("mvn r12, #5 "); // return KErrArgument
1.419 + __JUMP(,lr);
1.420 +
1.421 + // Return 'real indefinite'
1.422 + asm("TRealXRealIndefinite: ");
1.423 + asm("ldr r3, __RealIndefiniteExponent ");
1.424 + asm("mov r2, #0xC0000000 ");
1.425 + asm("mov r1, #0 ");
1.426 + asm("mvn r12, #5 "); // return KErrArgument
1.427 + __JUMP(,lr);
1.428 +
1.429 + // overflow
1.430 + asm("TRealXMultiply6: ");
1.431 + asm("bic r3, r3, #0x0000FF00 "); // clear rounding flags
1.432 + asm("orr r3, r3, #0xFF000000 "); // make exponent FFFF for infinity
1.433 + asm("orr r3, r3, #0x00FF0000 ");
1.434 + asm("mov r2, #0x80000000 "); // mantissa = 80000000 00000000
1.435 + asm("mov r1, #0 ");
1.436 + asm("mvn r12, #8 "); // return KErrOverflow
1.437 + __JUMP(,lr);
1.438 +
1.439 + asm("__RealIndefiniteExponent: ");
1.440 + asm(".word 0xFFFF0001 ");
1.441 +
1.442 + asm("Divide__FR6TRealXRC6TRealX_end: ");
1.443 + }
1.444 +
1.445 +__NAKED__ TUint Divide_Length()
1.446 + {
1.447 + asm("adr r0, Divide__FR6TRealXRC6TRealX_end ");
1.448 + asm("adr r1, Divide__FR6TRealXRC6TRealX ");
1.449 + asm("sub r0, r0, r1 ");
1.450 + __JUMP(,lr);
1.451 + }
1.452 +
1.453 +__NAKED__ TInt SDummy(TInt)
1.454 + {
1.455 + __JUMP(,lr);
1.456 + asm("SDummy__Fi_end: ");
1.457 + }
1.458 +
1.459 +__NAKED__ TUint SDummy_Length()
1.460 + {
1.461 + asm("adr r0, SDummy__Fi_end ");
1.462 + asm("adr r1, SDummy__Fi ");
1.463 + asm("sub r0, r0, r1 ");
1.464 + __JUMP(,lr);
1.465 + }
1.466 +
1.467 +__NAKED__ TInt Increment(TInt)
1.468 + {
1.469 + asm("add r0, r0, #1 ");
1.470 + __JUMP(,lr);
1.471 + asm("Increment__Fi_end: ");
1.472 + }
1.473 +
1.474 +__NAKED__ TUint Increment_Length()
1.475 + {
1.476 + asm("adr r0, Increment__Fi_end ");
1.477 + asm("adr r1, Increment__Fi ");
1.478 + asm("sub r0, r0, r1 ");
1.479 + __JUMP(,lr);
1.480 + }
1.481 +
1.482 +#endif