symport/e32/euser/epoc/x86/uc_i64.cia
changeset 1 0a7b44b10206
child 2 806186ab5e14
equal deleted inserted replaced
0:c55016431358 1:0a7b44b10206
       
     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 "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-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 
       
   155 	asm("divmod64_0:");				// edx:eax = ABS{dividend}
       
   156 	asm("push edi");
       
   157 	asm("push esi");
       
   158 	asm("push ebx");
       
   159 	asm("push ebp");
       
   160 	asm("mov esi, [esp+28]");
       
   161 	asm("mov edi, [esp+32]");		// edi:esi = dividend
       
   162 	asm("cmp edi, 0");
       
   163 	asm("jns divmod64_1");
       
   164 	asm("neg edi");
       
   165 	asm("neg esi");
       
   166 	asm("sbb edi, 0"); // edi:esi = ABS{dividend}
       
   167 
       
   168 	asm("divmod64_1:");
       
   169 	asm("call %a0": : "i"(&UDiv64));	// do division, quotient in ebx:eax remainder in edi:edx
       
   170 	asm("xchg ebx, edx");			// quotient in edx:eax, remainder in edi:ebx
       
   171 	asm("mov ecx, [esp+24]");		// ecx=dividend high
       
   172 	asm("xor ecx, [esp+32]");		// ecx=dividend high ^ divisor high
       
   173 	asm("jns divmod64_2");
       
   174 	asm("neg edx");
       
   175 	asm("neg eax");
       
   176 	asm("sbb edx, 0");
       
   177 
       
   178 	asm("divmod64_2:");				// edx:eax = quotient with correct sign
       
   179 	asm("cmp dword ptr [esp+24], 0");
       
   180 	asm("jns divmod64_3");
       
   181 	asm("neg edi");
       
   182 	asm("neg ebx");
       
   183 	asm("sbb edi, 0");
       
   184 
       
   185 	asm("divmod64_3:");				// edi:ebx = remainder with correct sign
       
   186 	asm("mov ecx, [esp+36]");		// ecx=&aRemainder
       
   187 	asm("mov [ecx], ebx");
       
   188 	asm("mov [ecx+4], edi");
       
   189 	asm("pop ebp");
       
   190 	asm("pop ebx");
       
   191 	asm("pop esi");
       
   192 	asm("pop edi");
       
   193 	asm("ret");
       
   194 	}
       
   195 
       
   196 
       
   197 
       
   198 
       
   199 EXPORT_C __NAKED__ Uint64 Math::UDivMod64(Uint64 /*aDividend*/, Uint64 /*aDivisor*/, Uint64& /*aRemainder*/)
       
   200 /**
       
   201 Divides aDividend by aDivisor.
       
   202 
       
   203 The quotient is returned, and the remainder is stored in aRemainder.
       
   204 
       
   205 @param aDividend The 64-bit dividend.
       
   206 @param aDivisor  The 64-bit divisor.
       
   207 @param aRemainder The 64-bit remainder.
       
   208 
       
   209 @return The 64-bit quotient.
       
   210 */
       
   211 	{
       
   212 	asm("mov eax, [esp+4]");
       
   213 	asm("mov edx, [esp+8]");		// edx:eax = dividend
       
   214 	asm("push edi");
       
   215 	asm("push esi");
       
   216 	asm("push ebx");
       
   217 	asm("push ebp");
       
   218 	asm("mov esi, [esp+28]");
       
   219 	asm("mov edi, [esp+32]");		// edi:esi = dividend
       
   220 	asm("call %a0": : "i"(&UDiv64));	// do division, quotient in ebx:eax remainder in edi:edx
       
   221 	asm("xchg ebx, edx");			// quotient in edx:eax, remainder in edi:ebx
       
   222 	asm("mov ecx, [esp+36]");		// ecx=&aRemainder
       
   223 	asm("mov [ecx], ebx");
       
   224 	asm("mov [ecx+4], edi");
       
   225 	asm("pop ebp");
       
   226 	asm("pop ebx");
       
   227 	asm("pop esi");
       
   228 	asm("pop edi");
       
   229 	asm("ret");
       
   230 	}
       
   231 
       
   232 
       
   233