os/security/crypto/weakcryptospi/source/bigint/gcchelp.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
sl@0
    19
/**
sl@0
    20
 @file
sl@0
    21
*/
sl@0
    22
sl@0
    23
sl@0
    24
#include <kernel\u32std.h>	// need this for __NAKED__, __JUMP and __POPRET
sl@0
    25
sl@0
    26
extern "C" {
sl@0
    27
#ifdef __GCC32__
sl@0
    28
__NAKED__ long long __divdi3(long long /*dividend*/, long long /*divisor*/)
sl@0
    29
//
sl@0
    30
// Dividend in r1:r0, divisor in r3:r2, Return quotient in r1:r0
sl@0
    31
//
sl@0
    32
	{
sl@0
    33
	asm("stmfd sp!, {r4-r8,lr} ");
sl@0
    34
	asm("eor r8, r1, r3 ");				// sign of result into r8
sl@0
    35
	asm("movs r1, r1 ");
sl@0
    36
	asm("bpl 1f ");
sl@0
    37
	asm("rsbs r0, r0, #0 ");			// ABS(dividend)
sl@0
    38
	asm("rsc r1, r1, #0 ");
sl@0
    39
	asm("1: ");
sl@0
    40
	asm("movs r3, r3 ");
sl@0
    41
	asm("bpl 2f ");
sl@0
    42
	asm("rsbs r2, r2, #0 ");			// ABS(divisor)
sl@0
    43
	asm("rsc r3, r3, #0 ");
sl@0
    44
	asm("2: ");
sl@0
    45
	asm("bl UDiv01 ");					// do the division, result in r4,r5
sl@0
    46
	asm("eors r0, r4, r8, asr #32 ");	// quotient into r1:r0, inverted if quotient -ve
sl@0
    47
	asm("eors r1, r5, r8, asr #32 ");
sl@0
    48
	asm("adcs r0, r0, #0 ");		// if quotient -ve, add 1
sl@0
    49
	asm("adcs r1, r1, #0 ");
sl@0
    50
	__POPRET("r4-r8,");
sl@0
    51
	}
sl@0
    52
sl@0
    53
__NAKED__ long long __moddi3(long long /*dividend*/, long long /*divisor*/)	/* signed */
sl@0
    54
	{
sl@0
    55
	asm("stmfd sp!, {r4-r8,lr} ");
sl@0
    56
	asm("movs r8, r1 ");				// sign of remainder (=sign of dividend) into r8
sl@0
    57
	asm("bpl 1f ");
sl@0
    58
	asm("rsbs r0, r0, #0 ");			// ABS(dividend)
sl@0
    59
	asm("rsc r1, r1, #0 ");
sl@0
    60
	asm("1: ");
sl@0
    61
	asm("movs r3, r3 ");
sl@0
    62
	asm("bpl 2f ");
sl@0
    63
	asm("rsbs r2, r2, #0 ");			// ABS(divisor)
sl@0
    64
	asm("rsc r3, r3, #0 ");
sl@0
    65
	asm("2: ");
sl@0
    66
	asm("bl UDiv01 ");					// do the division, remainder in r3,r6
sl@0
    67
	asm("eors r0, r3, r8, asr #32 ");	// remainder into r1:r0, inverted if dividend -ve
sl@0
    68
	asm("eors r1, r6, r8, asr #32 ");
sl@0
    69
	asm("adcs r0, r0, #0 ");			// if dividend -ve, add 1
sl@0
    70
	asm("adcs r1, r1, #0 ");
sl@0
    71
	__POPRET("r4-r8,");
sl@0
    72
	}
sl@0
    73
sl@0
    74
__NAKED__ long long __umoddi3(unsigned long long /*dividend*/, unsigned long long /*divisor*/)	/* unsigned */
sl@0
    75
	{
sl@0
    76
	asm("stmfd sp!, {r4-r7,lr} ");
sl@0
    77
	asm("bl UDiv01 ");					// do the division, remainder in r6:r3
sl@0
    78
	asm("mov r0, r3 ");
sl@0
    79
	asm("mov r1, r6 ");
sl@0
    80
	__POPRET("r4-r7,");
sl@0
    81
	}
sl@0
    82
sl@0
    83
__NAKED__ long long __ashrdi3(long long /*value*/, unsigned int /*count*/)
sl@0
    84
	{
sl@0
    85
	asm("cmp r2, #63 ");
sl@0
    86
	asm("movhi r2, #63 ");			// count>63 same as count=63
sl@0
    87
	asm("cmp r2, #32 ");
sl@0
    88
	asm("bcs Asr01 ");				// jump if shift count >=32
sl@0
    89
	asm("rsb r12, r2, #32 ");		// r12=32-shift count
sl@0
    90
	asm("mov r0, r0, lsr r2 ");		// shift ls word right
sl@0
    91
	asm("orr r0, r0, r1, lsl r12 ");	// or in bits shifted out of ms word
sl@0
    92
	asm("mov r1, r1, asr r2 ");		// shift ms word right
sl@0
    93
	__JUMP(,lr);
sl@0
    94
	asm("Asr01: ");
sl@0
    95
	asm("sub r2, r2, #32 ");		// r2=shift count-32
sl@0
    96
	asm("mov r0, r1, asr r2 ");		// ls word = ms word >> (count-32)
sl@0
    97
	asm("mov r1, r1, asr #32 ");	// ms word of result=sign extension of r1
sl@0
    98
	__JUMP(,lr);
sl@0
    99
	}
sl@0
   100
sl@0
   101
__NAKED__ long long __ashldi3(long long /*value*/, unsigned int /*count*/)
sl@0
   102
	{
sl@0
   103
	asm("cmp r2, #63 ");
sl@0
   104
	asm("movhi r2, #64 ");			// count>63 same as count=64
sl@0
   105
	asm("cmp r2, #32 ");
sl@0
   106
	asm("bcs Asl01 ");				// jump if shift count >=32
sl@0
   107
	asm("rsb r12, r2, #32 ");		// r12=32-shift count
sl@0
   108
	asm("mov r1, r1, asl r2 ");		// shift ms word left
sl@0
   109
	asm("orr r1, r1, r0, lsr r12 ");	// or in bits shifted out of ls word
sl@0
   110
	asm("mov r0, r0, asl r2 ");		// shift ls word left
sl@0
   111
	__JUMP(,lr);
sl@0
   112
	asm("Asl01: ");
sl@0
   113
	asm("sub r2, r2, #32 ");		// r2=shift count-32
sl@0
   114
	asm("mov r1, r0, asl r2 ");		// result ms word = ls word << (count-32)
sl@0
   115
	asm("mov r0, #0 ");				// ls word of result is zero
sl@0
   116
	__JUMP(,lr);
sl@0
   117
	}
sl@0
   118
sl@0
   119
__NAKED__ unsigned long long __lshrdi3(unsigned long long /*value*/, unsigned int /*count*/)
sl@0
   120
	{
sl@0
   121
	asm("cmp r2, #63 ");
sl@0
   122
	asm("movhi r2, #64 ");			// count>63 same as count=64
sl@0
   123
	asm("cmp r2, #32 ");
sl@0
   124
	asm("bcs Lsr01 ");				// jump if shift count >=32
sl@0
   125
	asm("rsb r12, r2, #32 ");		// r12=32-shift count
sl@0
   126
	asm("mov r0, r0, lsr r2 ");		// shift ls word right
sl@0
   127
	asm("orr r0, r0, r1, lsl r12 ");	// or in bits shifted out of ms word
sl@0
   128
	asm("mov r1, r1, lsr r2 ");		// shift ms word right
sl@0
   129
	__JUMP(,lr);
sl@0
   130
	asm("Lsr01: ");
sl@0
   131
	asm("sub r2, r2, #32 ");		// r2=shift count-32
sl@0
   132
	asm("mov r0, r1, lsr r2 ");		// ls word = ms word >> (count-32)
sl@0
   133
	asm("mov r1, #0 ");				// ms word of result = 0
sl@0
   134
	__JUMP(,lr);
sl@0
   135
	}
sl@0
   136
sl@0
   137
__NAKED__ long long __muldi3(long long /*multiplicand*/, long long /*multiplier*/)
sl@0
   138
	{
sl@0
   139
	asm("mul r1, r2, r1 ");				// r1=low2*high1
sl@0
   140
	asm("mov ip, r0 ");					// ip=low1
sl@0
   141
	asm("mla r1, r0, r3, r1 ");			// r1+=low1*high2
sl@0
   142
	asm("mov r0, #0 ");
sl@0
   143
	asm("umlal r0, r1, r2, ip ");		// r1:r0 += high1*low1
sl@0
   144
	__JUMP(,lr);
sl@0
   145
	}
sl@0
   146
sl@0
   147
__NAKED__ long long __negdi2(long long /*argument*/)
sl@0
   148
	{
sl@0
   149
	asm("rsbs r0, r0, #0 ");		// r0=0-r0, set carry
sl@0
   150
	asm("rscs r1, r1, #0 ");		// r1=0-r1-(1-C)
sl@0
   151
	__JUMP(,lr);
sl@0
   152
	}
sl@0
   153
sl@0
   154
__NAKED__ unsigned long long __udivmoddi4 (unsigned long long /*dividend*/,
sl@0
   155
													unsigned long long /*divisor*/,
sl@0
   156
													unsigned long long* /*p_remainder*/)
sl@0
   157
	{
sl@0
   158
	asm("stmfd sp!, {r4-r7,lr} ");
sl@0
   159
	asm("bl UDiv01 ");					// do the division, quotient in r5:r4 remainder in r6:r3
sl@0
   160
	asm("ldr r7, [sp, #20] ");			// r7=p_remainder
sl@0
   161
	asm("mov r0, r4 ");					// r0=quotient low
sl@0
   162
	asm("stmia r7, {r3,r6} ");			// store remainder
sl@0
   163
	asm("mov r1, r5 ");					// r0=quotient high
sl@0
   164
	__POPRET("r4-r7,");
sl@0
   165
	}
sl@0
   166
sl@0
   167
__NAKED__ int __cmpdi2(long long /*a*/, long long /*b*/)
sl@0
   168
	{
sl@0
   169
	// return 0 if a<b, 1 if a=b, 2 if a>b
sl@0
   170
	asm("subs r0, r2, r0 ");
sl@0
   171
	asm("sbcs r1, r3, r1 ");			// r1:r0 = b-a, set flags
sl@0
   172
	asm("movlt r0, #2 ");				// if b<a r0=2
sl@0
   173
	__JUMP(lt,lr);						// if b<a return
sl@0
   174
	asm("cmpeq r0, #0 ");				// if top word of difference=0, look at bottom
sl@0
   175
	asm("moveq r0, #1 ");				// if a=b, r0=1
sl@0
   176
	asm("movne r0, #0 ");				// else r=0
sl@0
   177
	__JUMP(,lr);
sl@0
   178
	}
sl@0
   179
sl@0
   180
__NAKED__ int __ucmpdi2(unsigned long long /*a*/, unsigned long long /*b*/)
sl@0
   181
	{
sl@0
   182
	// return 0 if a<b, 1 if a=b, 2 if a>b
sl@0
   183
	asm("cmp r1, r3 ");
sl@0
   184
	asm("cmpeq r0, r2 ");				// compare r1:r0 - r3:r2
sl@0
   185
	asm("movhi r0, #2 ");				// r0=2 if a>b
sl@0
   186
	asm("moveq r0, #1 ");				// r0=1 if a=b
sl@0
   187
	asm("movlo r0, #0 ");				// r0=0 if a<b
sl@0
   188
	__JUMP(,lr);
sl@0
   189
	}
sl@0
   190
#endif
sl@0
   191
sl@0
   192
#if defined(__GCC32__)
sl@0
   193
void __division_by_zero();
sl@0
   194
#define DIV_BY_ZERO " __division_by_zero "
sl@0
   195
#elif defined(__ARMCC__)
sl@0
   196
void __rt_div0 (void);
sl@0
   197
#define DIV_BY_ZERO " __cpp(__rt_div0) "
sl@0
   198
#endif
sl@0
   199
sl@0
   200
void __division_by_zero()
sl@0
   201
	{
sl@0
   202
	RThread().RaiseException(EExcIntegerDivideByZero);
sl@0
   203
    }
sl@0
   204
sl@0
   205
__NAKED__ unsigned long long __udivdi3(unsigned long long /*dividend*/, unsigned long long /*divisor*/)
sl@0
   206
//
sl@0
   207
// Dividend in r1:r0, divisor in r3:r2, Return quotient in r1:r0
sl@0
   208
//
sl@0
   209
	{
sl@0
   210
	asm("stmfd sp!, {r4-r7,lr} ");
sl@0
   211
	asm("bl UDiv01 ");					// do the division, result in r4,r5
sl@0
   212
	asm("mov r0, r4 ");
sl@0
   213
	asm("mov r1, r5 ");
sl@0
   214
	__POPRET("r4-r7,");
sl@0
   215
sl@0
   216
	// Unsigned 64-bit division. Dividend in r0,r1, divisor in r2,r3
sl@0
   217
	// Quotient returned in r4,r5, Remainder in r3,r6
sl@0
   218
	// Registers r0-r7,r12 used, r8-r11 unmodified
sl@0
   219
	asm(".global UDiv01 ");
sl@0
   220
	asm("UDiv01: ");
sl@0
   221
	asm("movs r3, r3 ");				// check if divisor fits in 32 bits
sl@0
   222
	asm("bne udiv64a ");				// branch if not
sl@0
   223
	asm("movs r2, r2 ");				// check if divisor fits in 31 bits
sl@0
   224
	asm("bmi udiv64e ");				// branch if not
sl@0
   225
	asm("beq udiv64_divby0 ");			// if divisor=0, branch to error routine
sl@0
   226
sl@0
   227
	// Divisor is <0x80000000
sl@0
   228
	// This means that a 32-bit accumulator is sufficient
sl@0
   229
	asm("mov r4, #0 ");					// use r3 as acc, result in r4, r5
sl@0
   230
	asm("mov r5, #0 ");
sl@0
   231
	asm("mov r6, #8 ");					// do 2 set of 32 iterations
sl@0
   232
	asm("udiv64b: ");
sl@0
   233
	asm("adds r1, r1, r1 ");			// shift dividend left into acc
sl@0
   234
	asm("adcs r3, r3, r3 ");
sl@0
   235
	asm("subs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   236
	asm("adc r5, r5, r5 ");				// shift result bit left into quotient
sl@0
   237
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   238
	asm("adds r1, r1, r1 ");			// shift dividend left into acc
sl@0
   239
	asm("adcs r3, r3, r3 ");
sl@0
   240
	asm("subs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   241
	asm("adc r5, r5, r5 ");				// shift result bit left into quotient
sl@0
   242
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   243
	asm("adds r1, r1, r1 ");			// shift dividend left into acc
sl@0
   244
	asm("adcs r3, r3, r3 ");
sl@0
   245
	asm("subs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   246
	asm("adc r5, r5, r5 ");				// shift result bit left into quotient
sl@0
   247
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   248
	asm("adds r1, r1, r1 ");			// shift dividend left into acc
sl@0
   249
	asm("adcs r3, r3, r3 ");
sl@0
   250
	asm("subs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   251
	asm("adc r5, r5, r5 ");				// shift result bit left into quotient
sl@0
   252
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   253
	asm("subs r6, r6, #1 ");			// loop
sl@0
   254
	asm("bne udiv64b ");
sl@0
   255
	asm("mov r6, #8 ");					// 2nd set of 32 iterations
sl@0
   256
	asm("udiv64c: ");
sl@0
   257
	asm("adds r0, r0, r0 ");			// shift dividend left into acc
sl@0
   258
	asm("adcs r3, r3, r3 ");
sl@0
   259
	asm("subs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   260
	asm("adc r4, r4, r4 ");				// shift result bit left into quotient
sl@0
   261
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   262
	asm("adds r0, r0, r0 ");			// shift dividend left into acc
sl@0
   263
	asm("adcs r3, r3, r3 ");
sl@0
   264
	asm("subs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   265
	asm("adc r4, r4, r4 ");				// shift result bit left into quotient
sl@0
   266
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   267
	asm("adds r0, r0, r0 ");			// shift dividend left into acc
sl@0
   268
	asm("adcs r3, r3, r3 ");
sl@0
   269
	asm("subs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   270
	asm("adc r4, r4, r4 ");				// shift result bit left into quotient
sl@0
   271
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   272
	asm("adds r0, r0, r0 ");			// shift dividend left into acc
sl@0
   273
	asm("adcs r3, r3, r3 ");
sl@0
   274
	asm("subs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   275
	asm("adc r4, r4, r4 ");				// shift result bit left into quotient
sl@0
   276
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   277
	asm("subs r6, r6, #1 ");			// loop
sl@0
   278
	asm("bne udiv64c ");
sl@0
   279
	__JUMP(,lr);
sl@0
   280
sl@0
   281
	// 2^31 <= Divisor < 2^32
sl@0
   282
	// Need 33-bit accumulator - use carry flag as 33rd bit
sl@0
   283
	asm("udiv64e: ");
sl@0
   284
	asm("mov r4, #0 ");					// use r3 as acc, result in r4, r5
sl@0
   285
	asm("mov r5, #0 ");
sl@0
   286
	asm("mov r6, #8 ");					// do 2 set of 32 iterations
sl@0
   287
	asm("udiv64f: ");
sl@0
   288
	asm("adds r1, r1, r1 ");			// shift dividend left into acc
sl@0
   289
	asm("adcs r3, r3, r3 ");
sl@0
   290
	asm("subcs r3, r3, r2 ");
sl@0
   291
	asm("subccs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   292
	asm("adc r5, r5, r5 ");				// shift result bit left into quotient
sl@0
   293
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   294
	asm("adds r1, r1, r1 ");			// shift dividend left into acc
sl@0
   295
	asm("adcs r3, r3, r3 ");
sl@0
   296
	asm("subcs r3, r3, r2 ");
sl@0
   297
	asm("subccs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   298
	asm("adc r5, r5, r5 ");				// shift result bit left into quotient
sl@0
   299
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   300
	asm("adds r1, r1, r1 ");			// shift dividend left into acc
sl@0
   301
	asm("adcs r3, r3, r3 ");
sl@0
   302
	asm("subcs r3, r3, r2 ");
sl@0
   303
	asm("subccs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   304
	asm("adc r5, r5, r5 ");				// shift result bit left into quotient
sl@0
   305
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   306
	asm("adds r1, r1, r1 ");			// shift dividend left into acc
sl@0
   307
	asm("adcs r3, r3, r3 ");
sl@0
   308
	asm("subcs r3, r3, r2 ");
sl@0
   309
	asm("subccs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   310
	asm("adc r5, r5, r5 ");				// shift result bit left into quotient
sl@0
   311
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   312
	asm("subs r6, r6, #1 ");			// loop
sl@0
   313
	asm("bne udiv64f ");
sl@0
   314
	asm("mov r6, #8 ");					// 2nd set of 32 iterations
sl@0
   315
	asm("udiv64g: ");
sl@0
   316
	asm("adds r0, r0, r0 ");			// shift dividend left into acc
sl@0
   317
	asm("adcs r3, r3, r3 ");
sl@0
   318
	asm("subcs r3, r3, r2 ");
sl@0
   319
	asm("subccs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   320
	asm("adc r4, r4, r4 ");				// shift result bit left into quotient
sl@0
   321
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   322
	asm("adds r0, r0, r0 ");			// shift dividend left into acc
sl@0
   323
	asm("adcs r3, r3, r3 ");
sl@0
   324
	asm("subcs r3, r3, r2 ");
sl@0
   325
	asm("subccs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   326
	asm("adc r4, r4, r4 ");				// shift result bit left into quotient
sl@0
   327
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   328
	asm("adds r0, r0, r0 ");			// shift dividend left into acc
sl@0
   329
	asm("adcs r3, r3, r3 ");
sl@0
   330
	asm("subcs r3, r3, r2 ");
sl@0
   331
	asm("subccs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   332
	asm("adc r4, r4, r4 ");				// shift result bit left into quotient
sl@0
   333
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   334
	asm("adds r0, r0, r0 ");			// shift dividend left into acc
sl@0
   335
	asm("adcs r3, r3, r3 ");
sl@0
   336
	asm("subcs r3, r3, r2 ");
sl@0
   337
	asm("subccs r3, r3, r2 ");			// subtract divisor from acc
sl@0
   338
	asm("adc r4, r4, r4 ");				// shift result bit left into quotient
sl@0
   339
	asm("addcc r3, r3, r2 ");			// if borrow, add back
sl@0
   340
	asm("subs r6, r6, #1 ");			// loop
sl@0
   341
	asm("bne udiv64g ");
sl@0
   342
	__JUMP(,lr);
sl@0
   343
	
sl@0
   344
	// Divisor >= 2^32, so quotient < 2^32
sl@0
   345
	// Use 64 bit accumulator, 32 bit quotient
sl@0
   346
	asm("udiv64a: ");
sl@0
   347
	asm("mov r4, #0 ");					// quotient in r4, use r1, r6 as accumulator
sl@0
   348
	asm("mov r6, #0 ");
sl@0
   349
	asm("mov r5, #8 ");					// do 32 iterations
sl@0
   350
	asm("udiv64d: ");
sl@0
   351
	asm("adds r0, r0, r0 ");			// shift dividend left into acc
sl@0
   352
	asm("adcs r1, r1, r1 ");
sl@0
   353
	asm("adcs r6, r6, r6 ");
sl@0
   354
	asm("subs r7, r1, r2 ");			// subtract divisor from acc, result into r7,r12
sl@0
   355
	asm("sbcs r12, r6, r3 ");
sl@0
   356
	asm("adc r4, r4, r4 ");				// shift result bit left into quotient
sl@0
   357
	asm("movcs r1, r7 ");				// if no borrow, update acc
sl@0
   358
	asm("movcs r6, r12 ");
sl@0
   359
	asm("adds r0, r0, r0 ");			// shift dividend left into acc
sl@0
   360
	asm("adcs r1, r1, r1 ");
sl@0
   361
	asm("adcs r6, r6, r6 ");
sl@0
   362
	asm("subs r7, r1, r2 ");			// subtract divisor from acc, result into r7,r12
sl@0
   363
	asm("sbcs r12, r6, r3 ");
sl@0
   364
	asm("adc r4, r4, r4 ");				// shift result bit left into quotient
sl@0
   365
	asm("movcs r1, r7 ");				// if no borrow, update acc
sl@0
   366
	asm("movcs r6, r12 ");
sl@0
   367
	asm("adds r0, r0, r0 ");			// shift dividend left into acc
sl@0
   368
	asm("adcs r1, r1, r1 ");
sl@0
   369
	asm("adcs r6, r6, r6 ");
sl@0
   370
	asm("subs r7, r1, r2 ");			// subtract divisor from acc, result into r7,r12
sl@0
   371
	asm("sbcs r12, r6, r3 ");
sl@0
   372
	asm("adc r4, r4, r4 ");				// shift result bit left into quotient
sl@0
   373
	asm("movcs r1, r7 ");				// if no borrow, update acc
sl@0
   374
	asm("movcs r6, r12 ");
sl@0
   375
	asm("adds r0, r0, r0 ");			// shift dividend left into acc
sl@0
   376
	asm("adcs r1, r1, r1 ");
sl@0
   377
	asm("adcs r6, r6, r6 ");
sl@0
   378
	asm("subs r7, r1, r2 ");			// subtract divisor from acc, result into r7,r12
sl@0
   379
	asm("sbcs r12, r6, r3 ");
sl@0
   380
	asm("adc r4, r4, r4 ");				// shift result bit left into quotient
sl@0
   381
	asm("movcs r1, r7 ");				// if no borrow, update acc
sl@0
   382
	asm("movcs r6, r12 ");
sl@0
   383
	asm("subs r5, r5, #1 ");			// loop
sl@0
   384
	asm("bne udiv64d ");
sl@0
   385
	asm("mov r3, r1 ");					// remainder in r3,r6
sl@0
   386
	__JUMP(,lr);
sl@0
   387
sl@0
   388
	asm("udiv64_divby0: ");
sl@0
   389
	asm("str lr, [sp, #-4]! ");
sl@0
   390
	asm("bl " DIV_BY_ZERO);
sl@0
   391
	__POPRET("");
sl@0
   392
	}
sl@0
   393
sl@0
   394
}
sl@0
   395