diff -r c55016431358 -r 0a7b44b10206 symport/e32/euser/epoc/x86/uc_i64.cia --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symport/e32/euser/epoc/x86/uc_i64.cia Thu Jun 25 15:59:54 2009 +0100 @@ -0,0 +1,233 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32\euser\epoc\x86\uc_i64.cia +// +// + +#include "u32std.h" +#include + +extern "C" void UDiv64(); + +EXPORT_C __NAKED__ void Math::Mul64(Int64 /*aX*/, Int64 /*aY*/, Int64& /*aOutH*/, Uint64& /*aOutL*/) +/** +Multiply aX by aY to generate a 128 bit result. + +The high order 64 bits of this calculation are stored in aOutH, +and the low order 64 bits are stored in aOutL. + +@param aX The first 64-bit operand. +@param aY The second 64-bit operand. +@param aOutH The high order 64 bits of the result. +@param aOutL The low order 64 bits of the result. +*/ + { + asm("mov eax, [esp+4]"); + asm("mul dword ptr [esp+12]"); // edx:eax = x0*y0 + asm("push edi"); + asm("push esi"); + asm("push ebx"); // [esp+16]=&aX, [esp+24]=&aY, [esp+32]=&aOutH, [esp+36]=&aOutL + asm("mov ecx, eax"); + asm("mov ebx, edx"); // ebx:ecx = x0*y0 + asm("mov eax, [esp+16]"); + asm("mul dword ptr [esp+28]"); // edx:eax = x0*y1 + asm("xor esi, esi"); + asm("add ebx, eax"); + asm("adc esi, edx"); // esi:ebx:ecx = x0*y + asm("mov eax, [esp+20]"); // eax=x1 + asm("imul dword ptr [esp+28]"); // edx:eax = x1*y1 + asm("mov edi, edx"); + asm("add esi, eax"); + asm("adc edi, 0"); // partial result in edi:esi:ebx:ecx + asm("cmp dword ptr [esp+28],0");// y<0 ? + asm("jns mul64_ypos"); + asm("sub esi, [esp+16]"); // if so, subtract x0<<64 + asm("sbb edi, 0"); + asm("mul64_ypos:"); + asm("mov eax, [esp+20]"); // eax=x1 + asm("cmp eax, 0"); // x<0 ? + asm("jns mul64_xpos"); + asm("sub esi, [esp+24]"); // if so, subtract y0<<64 + asm("sbb edi, 0"); + asm("mul64_xpos:"); + asm("mul dword ptr [esp+24]"); // edx:eax = x1*y0 + asm("add ebx, eax"); + asm("mov eax, [esp+32]"); // eax=&aOutH + asm("adc esi, edx"); + asm("mov edx, [esp+36]"); // edx=&aOutL + asm("adc edi, 0"); // full result now in edi:esi:ebx:ecx + asm("mov [eax], esi"); + asm("mov [eax+4], edi"); // store high 64 + asm("mov [edx], ecx"); + asm("mov [edx+4], ebx"); // store low 64 + asm("pop ebx"); + asm("pop esi"); + asm("pop edi"); + asm("ret"); + } + + + + +EXPORT_C __NAKED__ void Math::UMul64(Uint64 /*aX*/, Uint64 /*aY*/, Uint64& /*aOutH*/, Uint64& /*aOutL*/) +/** +Multiply aX by aY to generate a 128 bit result. + +The high order 64 bits of this calculation are stored in aOutH, +and the low order 64 bits are stored in aOutL. + +@param aX The first 64-bit operand. +@param aY The second 64-bit operand. +@param aOutH The high order 64 bits of the result. +@param aOutL The low order 64 bits of the result. +*/ + { + asm("mov eax, [esp+4]"); + asm("mul dword ptr [esp+12]"); // edx:eax = x0*y0 + asm("push edi"); + asm("push esi"); + asm("push ebx"); // [esp+16]=&aX, [esp+24]=&aY, [esp+32]=&aOutH, [esp+36]=&aOutL + asm("mov ecx, eax"); + asm("mov ebx, edx"); // ebx:ecx = x0*y0 + asm("mov eax, [esp+16]"); + asm("mul dword ptr [esp+28]"); // edx:eax = x0*y1 + asm("xor esi, esi"); + asm("add ebx, eax"); + asm("adc esi, edx"); // esi:ebx:ecx = x0*y + asm("mov eax, [esp+20]"); // eax=x1 + asm("mul dword ptr [esp+28]"); // edx:eax = x1*y1 + asm("mov edi, edx"); + asm("add esi, eax"); + asm("adc edi, 0"); // partial result in edi:esi:ebx:ecx + asm("mov eax, [esp+20]"); + asm("mul dword ptr [esp+24]"); // edx:eax = x1*y0 + asm("add ebx, eax"); + asm("mov eax, [esp+32]"); // eax=&aOutH + asm("adc esi, edx"); + asm("mov edx, [esp+36]"); // edx=&aOutL + asm("adc edi, 0"); // full result now in edi:esi:ebx:ecx + asm("mov [eax], esi"); + asm("mov [eax+4], edi"); // store high 64 + asm("mov [edx], ecx"); + asm("mov [edx+4], ebx"); // store low 64 + asm("pop ebx"); + asm("pop esi"); + asm("pop edi"); + asm("ret"); + } + + + + +EXPORT_C __NAKED__ Int64 Math::DivMod64(Int64 /*aDividend*/, Int64 /*aDivisor*/, Int64& /*aRemainder*/) +/** +Divides aDividend by aDivisor. + +The quotient is returned, and the remainder is stored in aRemainder. +The remainder has same sign as the dividend. + +@param aDividend The 64-bit dividend. +@param aDivisor The 64-bit divisor. +@param aRemainder The 64-bit remainder. + +@return The 64-bit quotient. +*/ + { + asm("mov eax, [esp+4]"); + asm("mov edx, [esp+8]"); // edx:eax = dividend + asm("cmp edx, 0"); + asm("jns divmod64_0"); + asm("neg edx"); + asm("neg eax"); + asm("sbb edx, 0"); + + asm("divmod64_0:"); // edx:eax = ABS{dividend} + asm("push edi"); + asm("push esi"); + asm("push ebx"); + asm("push ebp"); + asm("mov esi, [esp+28]"); + asm("mov edi, [esp+32]"); // edi:esi = dividend + asm("cmp edi, 0"); + asm("jns divmod64_1"); + asm("neg edi"); + asm("neg esi"); + asm("sbb edi, 0"); // edi:esi = ABS{dividend} + + asm("divmod64_1:"); + asm("call %a0": : "i"(&UDiv64)); // do division, quotient in ebx:eax remainder in edi:edx + asm("xchg ebx, edx"); // quotient in edx:eax, remainder in edi:ebx + asm("mov ecx, [esp+24]"); // ecx=dividend high + asm("xor ecx, [esp+32]"); // ecx=dividend high ^ divisor high + asm("jns divmod64_2"); + asm("neg edx"); + asm("neg eax"); + asm("sbb edx, 0"); + + asm("divmod64_2:"); // edx:eax = quotient with correct sign + asm("cmp dword ptr [esp+24], 0"); + asm("jns divmod64_3"); + asm("neg edi"); + asm("neg ebx"); + asm("sbb edi, 0"); + + asm("divmod64_3:"); // edi:ebx = remainder with correct sign + asm("mov ecx, [esp+36]"); // ecx=&aRemainder + asm("mov [ecx], ebx"); + asm("mov [ecx+4], edi"); + asm("pop ebp"); + asm("pop ebx"); + asm("pop esi"); + asm("pop edi"); + asm("ret"); + } + + + + +EXPORT_C __NAKED__ Uint64 Math::UDivMod64(Uint64 /*aDividend*/, Uint64 /*aDivisor*/, Uint64& /*aRemainder*/) +/** +Divides aDividend by aDivisor. + +The quotient is returned, and the remainder is stored in aRemainder. + +@param aDividend The 64-bit dividend. +@param aDivisor The 64-bit divisor. +@param aRemainder The 64-bit remainder. + +@return The 64-bit quotient. +*/ + { + asm("mov eax, [esp+4]"); + asm("mov edx, [esp+8]"); // edx:eax = dividend + asm("push edi"); + asm("push esi"); + asm("push ebx"); + asm("push ebp"); + asm("mov esi, [esp+28]"); + asm("mov edi, [esp+32]"); // edi:esi = dividend + asm("call %a0": : "i"(&UDiv64)); // do division, quotient in ebx:eax remainder in edi:edx + asm("xchg ebx, edx"); // quotient in edx:eax, remainder in edi:ebx + asm("mov ecx, [esp+36]"); // ecx=&aRemainder + asm("mov [ecx], ebx"); + asm("mov [ecx+4], edi"); + asm("pop ebp"); + asm("pop ebx"); + asm("pop esi"); + asm("pop edi"); + asm("ret"); + } + + +