os/kernelhwsrv/kernel/eka/euser/epoc/x86/uc_i64.cia
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2007-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 // e32\euser\epoc\x86\uc_i64.cia
    15 // 
    16 //
    17 
    18 #include "u32std.h"
    19 #include <e32math.h>
    20 
    21 extern "C" void UDiv64();
    22 
    23 EXPORT_C __NAKED__ void Math::Mul64(Int64 /*aX*/, Int64 /*aY*/, Int64& /*aOutH*/, Uint64& /*aOutL*/)
    24 /**
    25 Multiply aX by aY to generate a 128 bit result.
    26 
    27 The high order 64 bits of this calculation are stored in aOutH,
    28 and the low order 64 bits are stored in aOutL.
    29 
    30 @param aX     The first 64-bit operand.
    31 @param aY     The second 64-bit operand.
    32 @param aOutH  The high order 64 bits of the result.
    33 @param aOutL  The low order  64 bits of the result.
    34 */
    35 	{
    36 	asm("mov eax, [esp+4]");
    37 	asm("mul dword ptr [esp+12]");	// edx:eax = x0*y0
    38 	asm("push edi");
    39 	asm("push esi");
    40 	asm("push ebx");				// [esp+16]=&aX, [esp+24]=&aY, [esp+32]=&aOutH, [esp+36]=&aOutL
    41 	asm("mov ecx, eax");
    42 	asm("mov ebx, edx");			// ebx:ecx = x0*y0
    43 	asm("mov eax, [esp+16]");
    44 	asm("mul dword ptr [esp+28]");	// edx:eax = x0*y1
    45 	asm("xor esi, esi");
    46 	asm("add ebx, eax");
    47 	asm("adc esi, edx");			// esi:ebx:ecx = x0*y
    48 	asm("mov eax, [esp+20]");		// eax=x1
    49 	asm("imul dword ptr [esp+28]");	// edx:eax = x1*y1
    50 	asm("mov edi, edx");
    51 	asm("add esi, eax");
    52 	asm("adc edi, 0");				// partial result in edi:esi:ebx:ecx
    53 	asm("cmp dword ptr [esp+28],0");// y<0 ?
    54 	asm("jns mul64_ypos");
    55 	asm("sub esi, [esp+16]");		// if so, subtract x0<<64
    56 	asm("sbb edi, 0");
    57 	asm("mul64_ypos:");
    58 	asm("mov eax, [esp+20]");		// eax=x1
    59 	asm("cmp eax, 0");				// x<0 ?
    60 	asm("jns mul64_xpos");
    61 	asm("sub esi, [esp+24]");		// if so, subtract y0<<64
    62 	asm("sbb edi, 0");
    63 	asm("mul64_xpos:");
    64 	asm("mul dword ptr [esp+24]");	// edx:eax = x1*y0
    65 	asm("add ebx, eax");
    66 	asm("mov eax, [esp+32]");		// eax=&aOutH
    67 	asm("adc esi, edx");
    68 	asm("mov edx, [esp+36]");		// edx=&aOutL
    69 	asm("adc edi, 0");				// full result now in edi:esi:ebx:ecx
    70 	asm("mov [eax], esi");
    71 	asm("mov [eax+4], edi");		// store high 64
    72 	asm("mov [edx], ecx");
    73 	asm("mov [edx+4], ebx");		// store low 64
    74 	asm("pop ebx");
    75 	asm("pop esi");
    76 	asm("pop edi");
    77 	asm("ret");
    78 	}
    79 
    80 
    81 
    82 
    83 EXPORT_C __NAKED__ void Math::UMul64(Uint64 /*aX*/, Uint64 /*aY*/, Uint64& /*aOutH*/, Uint64& /*aOutL*/)
    84 /**
    85 Multiply aX by aY to generate a 128 bit result.
    86 
    87 The high order 64 bits of this calculation are stored in aOutH,
    88 and the low order 64 bits are stored in aOutL.
    89 
    90 @param aX     The first 64-bit operand.
    91 @param aY     The second 64-bit operand.
    92 @param aOutH  The high order 64 bits of the result.
    93 @param aOutL  The low order  64 bits of the result.
    94 */
    95 	{
    96 	asm("mov eax, [esp+4]");
    97 	asm("mul dword ptr [esp+12]");	// edx:eax = x0*y0
    98 	asm("push edi");
    99 	asm("push esi");
   100 	asm("push ebx");				// [esp+16]=&aX, [esp+24]=&aY, [esp+32]=&aOutH, [esp+36]=&aOutL
   101 	asm("mov ecx, eax");
   102 	asm("mov ebx, edx");			// ebx:ecx = x0*y0
   103 	asm("mov eax, [esp+16]");
   104 	asm("mul dword ptr [esp+28]");	// edx:eax = x0*y1
   105 	asm("xor esi, esi");
   106 	asm("add ebx, eax");
   107 	asm("adc esi, edx");			// esi:ebx:ecx = x0*y
   108 	asm("mov eax, [esp+20]");		// eax=x1
   109 	asm("mul dword ptr [esp+28]");	// edx:eax = x1*y1
   110 	asm("mov edi, edx");
   111 	asm("add esi, eax");
   112 	asm("adc edi, 0");				// partial result in edi:esi:ebx:ecx
   113 	asm("mov eax, [esp+20]");
   114 	asm("mul dword ptr [esp+24]");	// edx:eax = x1*y0
   115 	asm("add ebx, eax");
   116 	asm("mov eax, [esp+32]");		// eax=&aOutH
   117 	asm("adc esi, edx");
   118 	asm("mov edx, [esp+36]");		// edx=&aOutL
   119 	asm("adc edi, 0");				// full result now in edi:esi:ebx:ecx
   120 	asm("mov [eax], esi");
   121 	asm("mov [eax+4], edi");		// store high 64
   122 	asm("mov [edx], ecx");
   123 	asm("mov [edx+4], ebx");		// store low 64
   124 	asm("pop ebx");
   125 	asm("pop esi");
   126 	asm("pop edi");
   127 	asm("ret");
   128 	}
   129 
   130 
   131 
   132 
   133 EXPORT_C __NAKED__ Int64 Math::DivMod64(Int64 /*aDividend*/, Int64 /*aDivisor*/, Int64& /*aRemainder*/)
   134 /**
   135 Divides aDividend by aDivisor.
   136 
   137 The quotient is returned, and the remainder is stored in aRemainder.
   138 The remainder has same sign as the dividend.
   139 
   140 @param aDividend The 64-bit dividend.
   141 @param aDivisor  The 64-bit divisor.
   142 @param aRemainder The 64-bit remainder.
   143 
   144 @return The 64-bit quotient.
   145 */
   146 	{
   147 	asm("mov eax, [esp+4]");
   148 	asm("mov edx, [esp+8]");		// edx:eax = dividend
   149 	asm("cmp edx, 0");
   150 	asm("jns divmod64_0");
   151 	asm("neg edx");
   152 	asm("neg eax");
   153 	asm("sbb edx, 0");
   154 	asm("divmod64_0:");				// edx:eax = ABS{dividend}
   155 	asm("push edi");
   156 	asm("push esi");
   157 	asm("push ebx");
   158 	asm("push ebp");
   159 	asm("mov esi, [esp+28]");
   160 	asm("mov edi, [esp+32]");		// edi:esi = dividend
   161 	asm("cmp edi, 0");
   162 	asm("jns divmod64_1");
   163 	asm("neg edi");
   164 	asm("neg esi");
   165 	asm("sbb edi, 0");				// edi:esi = ABS{dividend}
   166 	asm("divmod64_1:");	
   167 	asm("call %a0": : "i"(&UDiv64));	// do division, quotient in ebx:eax remainder in edi:edx
   168 	asm("xchg ebx, edx");			// quotient in edx:eax, remainder in edi:ebx
   169 	asm("mov ecx, [esp+24]");		// ecx=dividend high
   170 	asm("xor ecx, [esp+32]");		// ecx=dividend high ^ divisor high
   171 	asm("jns divmod64_2");
   172 	asm("neg edx");
   173 	asm("neg eax");
   174 	asm("sbb edx, 0");
   175 	asm("divmod64_2:");				// edx:eax = quotient with correct sign
   176 	asm("cmp dword ptr [esp+24], 0");
   177 	asm("jns divmod64_3");
   178 	asm("neg edi");
   179 	asm("neg ebx");
   180 	asm("sbb edi, 0");
   181 	asm("divmod64_3:");				// edi:ebx = remainder with correct sign
   182 	asm("mov ecx, [esp+36]");		// ecx=&aRemainder
   183 	asm("mov [ecx], ebx");
   184 	asm("mov [ecx+4], edi");
   185 	asm("pop ebp");
   186 	asm("pop ebx");
   187 	asm("pop esi");
   188 	asm("pop edi");
   189 	asm("ret");
   190 	}
   191 
   192 
   193 
   194 
   195 EXPORT_C __NAKED__ Uint64 Math::UDivMod64(Uint64 /*aDividend*/, Uint64 /*aDivisor*/, Uint64& /*aRemainder*/)
   196 /**
   197 Divides aDividend by aDivisor.
   198 
   199 The quotient is returned, and the remainder is stored in aRemainder.
   200 
   201 @param aDividend The 64-bit dividend.
   202 @param aDivisor  The 64-bit divisor.
   203 @param aRemainder The 64-bit remainder.
   204 
   205 @return The 64-bit quotient.
   206 */
   207 	{
   208 	asm("mov eax, [esp+4]");
   209 	asm("mov edx, [esp+8]");		// edx:eax = dividend
   210 	asm("push edi");
   211 	asm("push esi");
   212 	asm("push ebx");
   213 	asm("push ebp");
   214 	asm("mov esi, [esp+28]");
   215 	asm("mov edi, [esp+32]");		// edi:esi = dividend
   216 	asm("call %a0": : "i"(&UDiv64));	// do division, quotient in ebx:eax remainder in edi:edx
   217 	asm("xchg ebx, edx");			// quotient in edx:eax, remainder in edi:ebx
   218 	asm("mov ecx, [esp+36]");		// ecx=&aRemainder
   219 	asm("mov [ecx], ebx");
   220 	asm("mov [ecx+4], edi");
   221 	asm("pop ebp");
   222 	asm("pop ebx");
   223 	asm("pop esi");
   224 	asm("pop edi");
   225 	asm("ret");
   226 	}
   227 
   228 
   229