kerneltest/e32test/mmu/t_imb.cia
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\mmu\t_imb.cia
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <e32test.h>
       
    19 #include <u32std.h>
       
    20 #include <e32math.h>
       
    21 
       
    22 #ifdef __CPU_ARM
       
    23 __NAKED__ TInt Sqrt(TReal& /*aDest*/, const TReal& /*aSrc*/)
       
    24 	{
       
    25 	// r0=address of aDest, r1=address of aSrc
       
    26 	asm("stmfd sp!, {r4-r10,lr} ");
       
    27 #ifdef __DOUBLE_WORDS_SWAPPED__
       
    28 	asm("ldmia r1, {r3,r4} ");			// low mant into r4, sign:exp:high mant into r3
       
    29 #else
       
    30 	asm("ldr r3, [r1, #4] ");
       
    31 	asm("ldr r4, [r1, #0] ");
       
    32 #endif
       
    33 	asm("bic r5, r3, #0xFF000000 ");
       
    34 	asm("bic r5, r5, #0x00F00000 ");	// high word of mantissa into r5
       
    35 	asm("mov r2, r3, lsr #20 ");
       
    36 	asm("bics r2, r2, #0x800 ");		// exponent now in r2
       
    37 	asm("beq fastsqrt1 ");				// branch if exponent zero (zero or denormal)
       
    38 	asm("mov r6, #0xFF ");
       
    39 	asm("orr r6, r6, #0x700 ");
       
    40 	asm("cmp r2, r6 ");					// check for infinity or NaN
       
    41 	asm("beq fastsqrt2 ");				// branch if infinity or NaN
       
    42 	asm("movs r3, r3 ");				// test sign
       
    43 	asm("bmi fastsqrtn ");				// branch if negative
       
    44 	asm("sub r2, r2, #0xFF ");			// unbias the exponent
       
    45 	asm("sub r2, r2, #0x300 ");			//
       
    46 	asm("fastsqrtd1: ");
       
    47 	asm("mov r1, #0x40000000 ");		// value for comparison
       
    48 	asm("mov r3, #27 ");				// loop counter (number of bits/2)
       
    49 	asm("movs r2, r2, asr #1 ");		// divide exponent by 2, LSB into CF
       
    50 	asm("movcs r7, r5, lsl #11 ");		// mantissa into r6,r7 with MSB in MSB of r7
       
    51 	asm("orrcs r7, r7, r4, lsr #21 ");
       
    52 	asm("movcs r6, r4, lsl #11 ");
       
    53 	asm("movcs r4, #0 ");				// r4, r5 will hold result mantissa
       
    54 	asm("orrcs r7, r7, #0x80000000 ");	// if exponent odd, restore MSB of mantissa
       
    55 	asm("movcc r7, r5, lsl #12 ");		// mantissa into r6,r7 with MSB in MSB of r7
       
    56 	asm("orrcc r7, r7, r4, lsr #20 ");	// if exponent even, shift mantissa left an extra
       
    57 	asm("movcc r6, r4, lsl #12 ");		// place, lose top bit, and
       
    58 	asm("movcc r4, #1 ");				// set MSB of result, and
       
    59 	asm("mov r5, #0 ");					// r4, r5 will hold result mantissa
       
    60 	asm("mov r8, #0 ");					// r8, r9 will be comparison accumulator
       
    61 	asm("mov r9, #0 ");
       
    62 	asm("bcc fastsqrt4 ");				// if exponent even, calculate one less bit
       
    63 										// as result MSB already known
       
    64 
       
    65 	// Main mantissa square-root loop
       
    66 	asm("fastsqrt3: ");					// START OF MAIN LOOP
       
    67 	asm("subs r10, r7, r1 ");			// subtract result:01 from acc:mant
       
    68 	asm("sbcs r12, r8, r4 ");			// result into r14:r12:r10
       
    69 	asm("sbcs r14, r9, r5 ");
       
    70 	asm("movcs r7, r10 ");				// if no borrow replace accumulator with result
       
    71 	asm("movcs r8, r12 ");
       
    72 	asm("movcs r9, r14 ");
       
    73 	asm("adcs r4, r4, r4 ");			// shift result left one, putting in next bit
       
    74 	asm("adcs r5, r5, r5 ");
       
    75 	asm("mov r9, r9, lsl #2 ");			// shift acc:mant left by 2 bits
       
    76 	asm("orr r9, r9, r8, lsr #30 ");
       
    77 	asm("mov r8, r8, lsl #2 ");
       
    78 	asm("orr r8, r8, r7, lsr #30 ");
       
    79 	asm("mov r7, r7, lsl #2 ");
       
    80 	asm("orr r7, r7, r6, lsr #30 ");
       
    81 	asm("mov r6, r6, lsl #2 ");
       
    82 	asm("fastsqrt4: ");					// Come in here if we need to do one less iteration
       
    83 	asm("subs r10, r7, r1 ");			// subtract result:01 from acc:mant
       
    84 	asm("sbcs r12, r8, r4 ");			// result into r14:r12:r10
       
    85 	asm("sbcs r14, r9, r5 ");
       
    86 	asm("movcs r7, r10 ");				// if no borrow replace accumulator with result
       
    87 	asm("movcs r8, r12 ");
       
    88 	asm("movcs r9, r14 ");
       
    89 	asm("adcs r4, r4, r4 ");			// shift result left one, putting in next bit
       
    90 	asm("adcs r5, r5, r5 ");
       
    91 	asm("mov r9, r9, lsl #2 ");			// shift acc:mant left by 2 bits
       
    92 	asm("orr r9, r9, r8, lsr #30 ");
       
    93 	asm("mov r8, r8, lsl #2 ");
       
    94 	asm("orr r8, r8, r7, lsr #30 ");
       
    95 	asm("mov r7, r7, lsl #2 ");
       
    96 	asm("orr r7, r7, r6, lsr #30 ");
       
    97 	asm("mov r6, r6, lsl #2 ");
       
    98 	asm("subs r3, r3, #1 ");			// decrement loop counter
       
    99 	asm("bne fastsqrt3 ");				// do necessary number of iterations
       
   100 
       
   101 	asm("movs r4, r4, lsr #1 ");		// shift result mantissa right 1 place
       
   102 	asm("orr r4, r4, r5, lsl #31 ");	// LSB (=rounding bit) into carry
       
   103 	asm("mov r5, r5, lsr #1 ");
       
   104 	asm("adcs r4, r4, #0 ");			// round the mantissa to 53 bits
       
   105 	asm("adcs r5, r5, #0 ");
       
   106 	asm("cmp r5, #0x00200000 ");		// check for mantissa overflow
       
   107 	asm("addeq r2, r2, #1 ");			// if so, increment exponent - can never overflow
       
   108 	asm("bic r5, r5, #0x00300000 ");	// remove top bit of mantissa - it is implicit
       
   109 	asm("add r2, r2, #0xFF ");			// re-bias the exponent
       
   110 	asm("add r3, r2, #0x300 ");			// and move into r3
       
   111 	asm("orr r3, r5, r3, lsl #20 ");	// r3 now contains exponent + top of mantissa
       
   112 	asm("fastsqrt_ok: ");
       
   113 #ifdef __DOUBLE_WORDS_SWAPPED__
       
   114 	asm("stmia r0, {r3,r4} ");			// store the result
       
   115 #else
       
   116 	asm("str r3, [r0, #4] ");
       
   117 	asm("str r4, [r0, #0] ");
       
   118 #endif
       
   119 	asm("mov r0, #0 ");					// error code KErrNone
       
   120 	__POPRET("r4-r10,");
       
   121 
       
   122 	asm("fastsqrt1: ");
       
   123 	asm("orrs r6, r5, r4 ");			// exponent zero - test mantissa
       
   124 	asm("beq fastsqrt_ok ");			// if zero, return 0
       
   125 
       
   126 	asm("movs r3, r3 ");				// denormal - test sign
       
   127 	asm("bmi fastsqrtn ");				// branch out if negative
       
   128 	asm("sub r2, r2, #0xFE ");			// unbias the exponent
       
   129 	asm("sub r2, r2, #0x300 ");			//
       
   130 	asm("fastsqrtd: ");
       
   131 	asm("adds r4, r4, r4 ");			// shift mantissa left
       
   132 	asm("adcs r5, r5, r5 ");
       
   133 	asm("sub r2, r2, #1 ");				// and decrement exponent
       
   134 	asm("tst r5, #0x00100000 ");		// test if normalised
       
   135 	asm("beq fastsqrtd ");				// loop until normalised
       
   136 	asm("b fastsqrtd1 ");				// now treat as a normalised number
       
   137 	asm("fastsqrt2: ");					// get here if infinity or NaN
       
   138 	asm("orrs r6, r5, r4 ");			// if mantissa zero, infinity
       
   139 	asm("bne fastsqrtnan ");			// branch if not - must be NaN
       
   140 	asm("movs r3, r3 ");				// test sign of infinity
       
   141 	asm("bmi fastsqrtn ");				// branch if -ve
       
   142 #ifdef __DOUBLE_WORDS_SWAPPED__
       
   143 	asm("stmia r0, {r3,r4} ");			// store the result
       
   144 #else
       
   145 	asm("str r3, [r0, #4] ");
       
   146 	asm("str r4, [r0, #0] ");
       
   147 #endif
       
   148 	asm("mov r0, #-9 ");				// return KErrOverflow
       
   149 	asm("b fastsqrt_end ");
       
   150 
       
   151 	asm("fastsqrtn: ");					// get here if negative or QNaN operand
       
   152 	asm("mov r3, #0xFF000000 ");		// generate "real indefinite" QNaN
       
   153 	asm("orr r3, r3, #0x00F80000 ");	// sign=1, exp=7FF, mantissa = 1000...0
       
   154 	asm("mov r4, #0 ");
       
   155 	asm("fastsqrtxa: ");
       
   156 #ifdef __DOUBLE_WORDS_SWAPPED__
       
   157 	asm("stmia r0, {r3,r4} ");			// store the result
       
   158 #else
       
   159 	asm("str r3, [r0, #4] ");
       
   160 	asm("str r4, [r0, #0] ");
       
   161 #endif
       
   162 	asm("mov r0, #-6 ");				// return KErrArgument
       
   163 	asm("fastsqrt_end: ");
       
   164 	__POPRET("r4-r10,");
       
   165 
       
   166 	asm("fastsqrtnan: ");				// operand is a NaN
       
   167 	asm("tst r5, #0x00080000 ");		// test MSB of mantissa
       
   168 	asm("bne fastsqrtn ");				// if set it is a QNaN - so return "real indefinite"
       
   169 	asm("bic r3, r3, #0x00080000 ");	// else convert SNaN to QNaN
       
   170 	asm("b fastsqrtxa ");				// and return KErrArgument
       
   171 
       
   172 	asm("Sqrt__FRdRCd_end: ");
       
   173 
       
   174 	}
       
   175 
       
   176 __NAKED__ TUint Sqrt_Length()
       
   177 	{
       
   178 	asm("adr r0, Sqrt__FRdRCd_end ");
       
   179 	asm("adr r1, Sqrt__FRdRCd ");
       
   180 	asm("sub r0, r0, r1 ");
       
   181 	__JUMP(,lr);
       
   182 	}
       
   183 
       
   184 __NAKED__ TInt Divide(TRealX& /*aDividend*/, const TRealX& /*aDivisor*/)
       
   185 	{
       
   186 	asm("stmfd sp!, {r0,r4-r9,lr} ");
       
   187 	asm("ldmia r1, {r4,r5,r6} ");
       
   188 	asm("ldmia r0, {r1,r2,r3} ");
       
   189 	asm("bl TRealXDivide ");
       
   190 	asm("ldmfd sp!, {r0,r4-r9,lr} ");
       
   191 	asm("stmia r0, {r1,r2,r3} ");
       
   192 	asm("mov r0, r12 ");
       
   193 	__JUMP(,lr);
       
   194 
       
   195 	// TRealX division r1,r2,r3 / r4,r5,r6 result in r1,r2,r3
       
   196 	// Error code returned in r12
       
   197 	// Registers r0-r9,r12 modified
       
   198 	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
       
   199 	asm("TRealXDivide: ");
       
   200 	asm("mov r12, #0 ");					// initialise return value to KErrNone
       
   201 	asm("bic r3, r3, #0x300 ");				// clear rounding flags
       
   202 	asm("tst r6, #1 ");
       
   203 	asm("eorne r3, r3, #1 ");				// Exclusive-OR signs
       
   204 	asm("cmn r3, #0x10000 ");				// check if dividend is NaN or infinity
       
   205 	asm("bcs TRealXDivide1 ");				// branch if it is
       
   206 	asm("cmn r6, #0x10000 ");				// check if divisor is NaN or infinity
       
   207 	asm("bcs TRealXDivide2 ");				// branch if it is
       
   208 	asm("cmp r6, #0x10000 ");				// check if divisor zero
       
   209 	asm("bcc TRealXDivide3 ");				// branch if it is
       
   210 	asm("cmp r3, #0x10000 ");				// check if dividend zero
       
   211 	__JUMP(cc,lr);					// if zero, exit
       
   212 	asm("tst r3, #1 ");
       
   213 	asm("orrne lr, lr, #1 ");				// save sign in bottom bit of lr
       
   214 
       
   215 	// calculate result exponent
       
   216 	asm("mov r0, r3, lsr #16 ");			// r0=dividend exponent
       
   217 	asm("sub r0, r0, r6, lsr #16 ");		// r0=dividend exponent - divisor exponent
       
   218 	asm("add r0, r0, #0x7F00 ");
       
   219 	asm("add r0, r0, #0x00FF ");			// r0 now contains result exponent
       
   220 	asm("mov r6, r1 ");						// move dividend into r6,r7,r8
       
   221 	asm("mov r7, r2 ");
       
   222 	asm("mov r8, #0 ");						// use r8 to hold extra bit shifted up
       
   223 											// r2:r1 will hold result mantissa
       
   224 	asm("mov r2, #1 ");						// we will make sure first bit is 1
       
   225 	asm("cmp r7, r5 ");						// compare dividend mantissa to divisor mantissa
       
   226 	asm("cmpeq r6, r4 ");
       
   227 	asm("bcs TRealXDivide4 ");				// branch if dividend >= divisor
       
   228 	asm("adds r6, r6, r6 ");				// else shift dividend left one
       
   229 	asm("adcs r7, r7, r7 ");				// ignore carry here
       
   230 	asm("sub r0, r0, #1 ");					// decrement result exponent by one
       
   231 	asm("TRealXDivide4: ");
       
   232 	asm("subs r6, r6, r4 ");				// subtract divisor from dividend
       
   233 	asm("sbcs r7, r7, r5 ");
       
   234 
       
   235 	// Main mantissa division code
       
   236 	// First calculate the top 32 bits of the result
       
   237 	// Top bit is 1, do 10 lots of 3 bits the one more bit
       
   238 	asm("mov r12, #10 ");
       
   239 	asm("TRealXDivide5: ");
       
   240 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
       
   241 	asm("adcs r7, r7, r7 ");
       
   242 	asm("adcs r8, r8, r8 ");
       
   243 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
       
   244 	asm("sbcs r3, r7, r5 ");
       
   245 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
       
   246 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
       
   247 	asm("movcs r7, r3 ");
       
   248 	asm("adcs r2, r2, r2 ");				// shift in new result bit
       
   249 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
       
   250 	asm("adcs r7, r7, r7 ");
       
   251 	asm("adcs r8, r8, r8 ");
       
   252 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
       
   253 	asm("sbcs r3, r7, r5 ");
       
   254 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
       
   255 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
       
   256 	asm("movcs r7, r3 ");
       
   257 	asm("adcs r2, r2, r2 ");				// shift in new result bit
       
   258 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
       
   259 	asm("adcs r7, r7, r7 ");
       
   260 	asm("adcs r8, r8, r8 ");
       
   261 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
       
   262 	asm("sbcs r3, r7, r5 ");
       
   263 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
       
   264 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
       
   265 	asm("movcs r7, r3 ");
       
   266 	asm("adcs r2, r2, r2 ");				// shift in new result bit
       
   267 	asm("subs r12, r12, #1 ");
       
   268 	asm("bne TRealXDivide5 ");				// iterate the loop
       
   269 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
       
   270 	asm("adcs r7, r7, r7 ");
       
   271 	asm("adcs r8, r8, r8 ");
       
   272 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
       
   273 	asm("sbcs r3, r7, r5 ");
       
   274 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
       
   275 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
       
   276 	asm("movcs r7, r3 ");
       
   277 	asm("adcs r2, r2, r2 ");				// shift in new result bit - now have 32 bits
       
   278 
       
   279 	// Now calculate the bottom 32 bits of the result
       
   280 	// Do 8 lots of 4 bits
       
   281 	asm("mov r12, #8 ");
       
   282 	asm("TRealXDivide5a: ");
       
   283 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
       
   284 	asm("adcs r7, r7, r7 ");
       
   285 	asm("adcs r8, r8, r8 ");
       
   286 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
       
   287 	asm("sbcs r3, r7, r5 ");
       
   288 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
       
   289 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
       
   290 	asm("movcs r7, r3 ");
       
   291 	asm("adcs r1, r1, r1 ");				// shift in new result bit
       
   292 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
       
   293 	asm("adcs r7, r7, r7 ");
       
   294 	asm("adcs r8, r8, r8 ");
       
   295 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
       
   296 	asm("sbcs r3, r7, r5 ");
       
   297 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
       
   298 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
       
   299 	asm("movcs r7, r3 ");
       
   300 	asm("adcs r1, r1, r1 ");				// shift in new result bit
       
   301 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
       
   302 	asm("adcs r7, r7, r7 ");
       
   303 	asm("adcs r8, r8, r8 ");
       
   304 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
       
   305 	asm("sbcs r3, r7, r5 ");
       
   306 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
       
   307 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
       
   308 	asm("movcs r7, r3 ");
       
   309 	asm("adcs r1, r1, r1 ");				// shift in new result bit
       
   310 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
       
   311 	asm("adcs r7, r7, r7 ");
       
   312 	asm("adcs r8, r8, r8 ");
       
   313 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
       
   314 	asm("sbcs r3, r7, r5 ");
       
   315 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
       
   316 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
       
   317 	asm("movcs r7, r3 ");
       
   318 	asm("adcs r1, r1, r1 ");				// shift in new result bit
       
   319 	asm("subs r12, r12, #1 ");
       
   320 	asm("bne TRealXDivide5a ");				// iterate the loop
       
   321 
       
   322 	// r2:r1 now contains a 64-bit normalised mantissa
       
   323 	// need to do rounding now
       
   324 	asm("and r3, lr, #1 ");					// result sign back into r3
       
   325 	asm("orrs r9, r6, r7 ");				// check if accumulator zero
       
   326 	asm("beq TRealXDivide6 ");				// if it is, result is exact, else generate next bit
       
   327 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
       
   328 	asm("adcs r7, r7, r7 ");
       
   329 	asm("adcs r8, r8, r8 ");
       
   330 	asm("subs r6, r6, r4 ");				// subtract divisor from accumulator
       
   331 	asm("sbcs r7, r7, r5 ");
       
   332 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
       
   333 	asm("orrcc r3, r3, #0x100 ");			// if borrow, round down and set round-down flag
       
   334 	asm("bcc TRealXDivide6 ");
       
   335 	asm("orrs r9, r6, r7 ");				// if no borrow, check if exactly half-way
       
   336 	asm("moveqs r9, r1, lsr #1 ");			// if exactly half-way, round to even
       
   337 	asm("orrcc r3, r3, #0x100 ");			// if C=0, round result down and set round-down flag
       
   338 	asm("bcc TRealXDivide6 ");
       
   339 	asm("orr r3, r3, #0x200 ");				// else set round-up flag
       
   340 	asm("adds r1, r1, #1 ");				// and round mantissa up
       
   341 	asm("adcs r2, r2, #0 ");
       
   342 	asm("movcs r2, #0x80000000 ");			// if carry, mantissa = 80000000 00000000
       
   343 	asm("addcs r0, r0, #1 ");				// and increment exponent
       
   344 
       
   345 	// check for overflow or underflow and assemble final result
       
   346 	asm("TRealXDivide6: ");
       
   347 	asm("add r4, r0, #1 ");					// need to add 1 to get usable threshold
       
   348 	asm("cmp r4, #0x10000 ");				// check if exponent >= 0xFFFF
       
   349 	asm("bge TRealXMultiply6 ");			// if so, overflow
       
   350 	asm("cmp r0, #0 ");						// check for underflow
       
   351 	asm("orrgt r3, r3, r0, lsl #16 ");		// if no underflow, result exponent into r3, ...
       
   352 	asm("movgt r12, #0 ");					// ... return KErrNone ...
       
   353 	__JUMP(gt,lr);
       
   354 
       
   355 	// underflow
       
   356 	asm("and r3, r3, #1 ");					// set exponent=0, keep sign
       
   357 	asm("mvn r12, #9 ");					// return KErrUnderflow
       
   358 	__JUMP(,lr);
       
   359 
       
   360 	// come here if divisor is zero, dividend finite
       
   361 	asm("TRealXDivide3: ");
       
   362 	asm("cmp r3, #0x10000 ");				// check if dividend also zero
       
   363 	asm("bcc TRealXRealIndefinite ");		// if so, return 'real indefinite'
       
   364 	asm("orr r3, r3, #0xFF000000 ");		// else return infinity with xor sign
       
   365 	asm("orr r3, r3, #0x00FF0000 ");
       
   366 	asm("mov r2, #0x80000000 ");
       
   367 	asm("mov r1, #0 ");
       
   368 	asm("mvn r12, #40 ");					// return KErrDivideByZero
       
   369 	__JUMP(,lr);
       
   370 
       
   371 	// Dividend is NaN or infinity
       
   372 	asm("TRealXDivide1: ");
       
   373 	asm("cmp r2, #0x80000000 ");			// check for infinity
       
   374 	asm("cmpeq r1, #0 ");
       
   375 	asm("bne TRealXBinOpNan ");				// branch if NaN
       
   376 	asm("cmn r6, #0x10000 ");				// check 2nd operand for NaN/infinity
       
   377 	asm("mvncc r12, #8 ");					// if not, return KErrOverflow
       
   378 	__JUMP(cc,lr);
       
   379 
       
   380 	// Dividend=infinity, divisor=NaN or infinity
       
   381 	asm("cmp r5, #0x80000000 ");			// check 2nd operand for infinity
       
   382 	asm("cmpeq r4, #0 ");
       
   383 	asm("bne TRealXBinOpNan ");				// branch if NaN
       
   384 	asm("b TRealXRealIndefinite ");			// else return 'real indefinite'
       
   385 
       
   386 	// Divisor is NaN or infinity, dividend finite
       
   387 	asm("TRealXDivide2: ");
       
   388 	asm("cmp r5, #0x80000000 ");			// check for infinity
       
   389 	asm("cmpeq r4, #0 ");
       
   390 	asm("bne TRealXBinOpNan ");				// branch if NaN
       
   391 	asm("and r3, r3, #1 ");					// else return zero with xor sign
       
   392 	__JUMP(,lr);
       
   393 
       
   394 	asm("TRealXBinOpNan: ");				// generic routine to process NaNs in binary
       
   395 											// operations
       
   396 	asm("cmn r3, #0x10000 ");				// check if first operand is NaN
       
   397 	asm("movcc r0, r1 ");					// if not, swap the operands
       
   398 	asm("movcc r1, r4 ");
       
   399 	asm("movcc r4, r0 ");
       
   400 	asm("movcc r0, r2 ");
       
   401 	asm("movcc r2, r5 ");
       
   402 	asm("movcc r5, r0 ");
       
   403 	asm("movcc r0, r3 ");
       
   404 	asm("movcc r3, r6 ");
       
   405 	asm("movcc r6, r0 ");
       
   406 	asm("cmn r6, #0x10000 ");				// both operands NaNs?
       
   407 	asm("bcc TRealXBinOpNan1 ");			// skip if not
       
   408 	asm("cmp r2, r5 ");						// if so, compare the significands
       
   409 	asm("cmpeq r1, r4 ");
       
   410 	asm("movcc r1, r4 ");					// r1,r2,r3 will get NaN with larger significand
       
   411 	asm("movcc r2, r5 ");
       
   412 	asm("movcc r3, r6 ");
       
   413 	asm("TRealXBinOpNan1: ");
       
   414 	asm("orr r2, r2, #0x40000000 ");		// convert an SNaN to a QNaN
       
   415 	asm("mvn r12, #5 ");					// return KErrArgument
       
   416 	__JUMP(,lr);
       
   417 
       
   418 	// Return 'real indefinite'
       
   419 	asm("TRealXRealIndefinite: ");
       
   420 	asm("ldr r3, __RealIndefiniteExponent ");
       
   421 	asm("mov r2, #0xC0000000 ");
       
   422 	asm("mov r1, #0 ");
       
   423 	asm("mvn r12, #5 ");					// return KErrArgument
       
   424 	__JUMP(,lr);
       
   425 
       
   426 	// overflow
       
   427 	asm("TRealXMultiply6: ");
       
   428 	asm("bic r3, r3, #0x0000FF00 ");		// clear rounding flags
       
   429 	asm("orr r3, r3, #0xFF000000 ");		// make exponent FFFF for infinity
       
   430 	asm("orr r3, r3, #0x00FF0000 ");
       
   431 	asm("mov r2, #0x80000000 ");			// mantissa = 80000000 00000000
       
   432 	asm("mov r1, #0 ");
       
   433 	asm("mvn r12, #8 ");					// return KErrOverflow
       
   434 	__JUMP(,lr);
       
   435 
       
   436 	asm("__RealIndefiniteExponent: ");
       
   437 	asm(".word 0xFFFF0001 ");
       
   438 
       
   439 	asm("Divide__FR6TRealXRC6TRealX_end: ");
       
   440 	}
       
   441 
       
   442 __NAKED__ TUint Divide_Length()
       
   443 	{
       
   444 	asm("adr r0, Divide__FR6TRealXRC6TRealX_end ");
       
   445 	asm("adr r1, Divide__FR6TRealXRC6TRealX ");
       
   446 	asm("sub r0, r0, r1 ");
       
   447 	__JUMP(,lr);
       
   448 	}
       
   449 
       
   450 __NAKED__ TInt SDummy(TInt)
       
   451 	{
       
   452 	__JUMP(,lr);
       
   453 	asm("SDummy__Fi_end: ");
       
   454 	}
       
   455 
       
   456 __NAKED__ TUint SDummy_Length()
       
   457 	{
       
   458 	asm("adr r0, SDummy__Fi_end ");
       
   459 	asm("adr r1, SDummy__Fi ");
       
   460 	asm("sub r0, r0, r1 ");
       
   461 	__JUMP(,lr);
       
   462 	}
       
   463 
       
   464 __NAKED__ TInt Increment(TInt)
       
   465 	{
       
   466 	asm("add r0, r0, #1 ");
       
   467 	__JUMP(,lr);
       
   468 	asm("Increment__Fi_end: ");
       
   469 	}
       
   470 
       
   471 __NAKED__ TUint Increment_Length()
       
   472 	{
       
   473 	asm("adr r0, Increment__Fi_end ");
       
   474 	asm("adr r1, Increment__Fi ");
       
   475 	asm("sub r0, r0, r1 ");
       
   476 	__JUMP(,lr);
       
   477 	}
       
   478 
       
   479 #endif