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