diff -r 8873e6835f7b -r dd83586b62d6 crypto/weakcrypto/source/bigint/vchelp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crypto/weakcrypto/source/bigint/vchelp.cpp Fri Jun 11 15:32:35 2010 +0300 @@ -0,0 +1,351 @@ +/* +* Copyright (c) 1995-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 "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* e32\nklib\x86\vchelp.cpp +* +*/ + + +#ifndef __NAKED__ +#define __NAKED__ __declspec(naked) +#endif + +#include + +#pragma warning ( disable : 4414 ) // short jump to function converted to near + +extern "C" { +__NAKED__ void _allmul() +// +// Multiply two 64 bit integers returning a 64 bit result +// On entry: +// [esp+4], [esp+8] = arg 1 +// [esp+12], [esp+16] = arg 1 +// Return result in edx:eax +// Remove arguments from stack +// + { + _asm mov eax, [esp+4] // eax = low1 + _asm mul dword ptr [esp+16] // edx:eax = low1*high2 + _asm mov ecx, eax // keep low 32 bits of product + _asm mov eax, [esp+8] // eax = high1 + _asm mul dword ptr [esp+12] // edx:eax = high1*low2 + _asm add ecx, eax // accumulate low 32 bits of product + _asm mov eax, [esp+4] // eax = low1 + _asm mul dword ptr [esp+12] // edx:eax = low1*low2 + _asm add edx, ecx // add cross terms to high 32 bits + _asm ret 16 + } + +void udiv64_divby0() + { + _asm int 0 // division by zero exception + _asm ret + } + +__NAKED__ void UDiv64() + { + // unsigned divide edx:eax by edi:esi + // quotient in ebx:eax, remainder in edi:edx + // ecx, ebp, esi also modified + _asm test edi, edi + _asm jnz short UDiv64a // branch if divisor >= 2^32 + _asm test esi, esi +// _ASM_j(z,DivisionByZero) // if divisor=0, branch to error routine + _asm jz udiv64_divby0 + _asm mov ebx, eax // ebx=dividend low + _asm mov eax, edx // eax=dividend high + _asm xor edx, edx // edx=0 + _asm div esi // quotient high now in eax + _asm xchg eax, ebx // quotient high in ebx, dividend low in eax + _asm div esi // quotient now in ebx:eax, remainder in edi:edx + _asm ret + UDiv64e: + _asm xor eax, eax // set result to 0xFFFFFFFF + _asm dec eax + _asm jmp short UDiv64f + UDiv64a: + _asm js short UDiv64b // skip if divisor msb set + _asm bsr ecx, edi // ecx=bit number of divisor msb - 32 + _asm inc cl + _asm push edi // save divisor high + _asm push esi // save divisor low + _asm shrd esi, edi, cl // shift divisor right so that msb is bit 31 + _asm mov ebx, edx // dividend into ebx:ebp + _asm mov ebp, eax + _asm shrd eax, edx, cl // shift dividend right same number of bits + _asm shr edx, cl + _asm cmp edx, esi // check if approx quotient will be 2^32 + _asm jae short UDiv64e // if so, true result must be 0xFFFFFFFF + _asm div esi // approximate quotient now in eax + UDiv64f: + _asm mov ecx, eax // into ecx + _asm mul edi // multiply approx. quotient by divisor high + _asm mov esi, eax // ls dword into esi, ms into edi + _asm mov edi, edx + _asm mov eax, ecx // approx. quotient into eax + _asm mul dword ptr [esp] // multiply approx. quotient by divisor low + _asm add edx, esi // edi:edx:eax now equals approx. quotient * divisor + _asm adc edi, 0 + _asm xor esi, esi + _asm sub ebp, eax // subtract dividend - approx. quotient *divisor + _asm sbb ebx, edx + _asm sbb esi, edi + _asm jnc short UDiv64c // if no borrow, result OK + _asm dec ecx // else result is one too big + _asm add ebp, [esp] // and add divisor to get correct remainder + _asm adc ebx, [esp+4] + UDiv64c: + _asm mov eax, ecx // result into ebx:eax, remainder into edi:edx + _asm mov edi, ebx + _asm mov edx, ebp + _asm xor ebx, ebx + _asm add esp, 8 // remove temporary values from stack + _asm ret + UDiv64b: + _asm mov ebx, 1 + _asm sub eax, esi // subtract divisor from dividend + _asm sbb edx, edi + _asm jnc short UDiv64d // if no borrow, result=1, remainder in edx:eax + _asm add eax, esi // else add back + _asm adc edx, edi + _asm dec ebx // and decrement quotient + UDiv64d: + _asm mov edi, edx // remainder into edi:edx + _asm mov edx, eax + _asm mov eax, ebx // result in ebx:eax + _asm xor ebx, ebx + _asm ret + } + +__NAKED__ void _aulldiv() +// +// Divide two 64 bit unsigned integers returning a 64 bit result +// On entry: +// [esp+4], [esp+8] = dividend +// [esp+12], [esp+16] = divisor +// Return result in edx:eax +// Remove arguments from stack +// + { + _asm push ebp + _asm push edi + _asm push esi + _asm push ebx + _asm mov eax, [esp+20] + _asm mov edx, [esp+24] + _asm mov esi, [esp+28] + _asm mov edi, [esp+32] + _asm call UDiv64 + _asm mov edx, ebx + _asm pop ebx + _asm pop esi + _asm pop edi + _asm pop ebp + _asm ret 16 + } + +__NAKED__ void _alldiv() +// +// Divide two 64 bit signed integers returning a 64 bit result +// On entry: +// [esp+4], [esp+8] = dividend +// [esp+12], [esp+16] = divisor +// Return result in edx:eax +// Remove arguments from stack +// + { + _asm push ebp + _asm push edi + _asm push esi + _asm push ebx + _asm mov eax, [esp+20] + _asm mov edx, [esp+24] + _asm mov esi, [esp+28] + _asm mov edi, [esp+32] + _asm test edx, edx + _asm jns dividend_nonnegative + _asm neg edx + _asm neg eax + _asm sbb edx, 0 + dividend_nonnegative: + _asm test edi, edi + _asm jns divisor_nonnegative + _asm neg edi + _asm neg esi + _asm sbb edi, 0 + divisor_nonnegative: + _asm call UDiv64 + _asm mov ecx, [esp+24] + _asm mov edx, ebx + _asm xor ecx, [esp+32] + _asm jns quotient_nonnegative + _asm neg edx + _asm neg eax + _asm sbb edx, 0 + quotient_nonnegative: + _asm pop ebx + _asm pop esi + _asm pop edi + _asm pop ebp + _asm ret 16 + } + +__NAKED__ void _aullrem() +// +// Divide two 64 bit unsigned integers and return 64 bit remainder +// On entry: +// [esp+4], [esp+8] = dividend +// [esp+12], [esp+16] = divisor +// Return result in edx:eax +// Remove arguments from stack +// + { + _asm push ebp + _asm push edi + _asm push esi + _asm push ebx + _asm mov eax, [esp+20] + _asm mov edx, [esp+24] + _asm mov esi, [esp+28] + _asm mov edi, [esp+32] + _asm call UDiv64 + _asm mov eax, edx + _asm mov edx, edi + _asm pop ebx + _asm pop esi + _asm pop edi + _asm pop ebp + _asm ret 16 + } + +__NAKED__ void _allrem() +// +// Divide two 64 bit signed integers and return 64 bit remainder +// On entry: +// [esp+4], [esp+8] = dividend +// [esp+12], [esp+16] = divisor +// Return result in edx:eax +// Remove arguments from stack +// + { + _asm push ebp + _asm push edi + _asm push esi + _asm push ebx + _asm mov eax, [esp+20] + _asm mov edx, [esp+24] + _asm mov esi, [esp+28] + _asm mov edi, [esp+32] + _asm test edx, edx + _asm jns dividend_nonnegative + _asm neg edx + _asm neg eax + _asm sbb edx, 0 + dividend_nonnegative: + _asm test edi, edi + _asm jns divisor_nonnegative + _asm neg edi + _asm neg esi + _asm sbb edi, 0 + divisor_nonnegative: + _asm call UDiv64 + _asm mov eax, edx + _asm mov edx, edi + _asm cmp dword ptr [esp+24], 0 + _asm jns rem_nonnegative + _asm neg edx + _asm neg eax + _asm sbb edx, 0 + rem_nonnegative: + _asm pop ebx + _asm pop esi + _asm pop edi + _asm pop ebp + _asm ret 16 + } + +__NAKED__ void _allshr() +// +// Arithmetic shift right EDX:EAX by ECX +// + { + _asm cmp ecx, 64 + _asm jae asr_count_ge_64 + _asm cmp cl, 32 + _asm jae asr_count_ge_32 + _asm shrd eax, edx, cl + _asm sar edx, cl + _asm ret + asr_count_ge_32: + _asm sub cl, 32 + _asm mov eax, edx + _asm cdq + _asm sar eax, cl + _asm ret + asr_count_ge_64: + _asm sar edx, 32 + _asm mov eax, edx + _asm ret + } + +__NAKED__ void _allshl() +// +// shift left EDX:EAX by ECX +// + { + _asm cmp ecx, 64 + _asm jae lsl_count_ge_64 + _asm cmp cl, 32 + _asm jae lsl_count_ge_32 + _asm shld edx, eax, cl + _asm shl eax, cl + _asm ret + lsl_count_ge_32: + _asm sub cl, 32 + _asm mov edx, eax + _asm xor eax, eax + _asm shl edx, cl + _asm ret + lsl_count_ge_64: + _asm xor edx, edx + _asm xor eax, eax + _asm ret + } + +__NAKED__ void _aullshr() +// +// Logical shift right EDX:EAX by ECX +// + { + _asm cmp ecx, 64 + _asm jae lsr_count_ge_64 + _asm cmp cl, 32 + _asm jae lsr_count_ge_32 + _asm shrd eax, edx, cl + _asm shr edx, cl + _asm ret + lsr_count_ge_32: + _asm sub cl, 32 + _asm mov eax, edx + _asm xor edx, edx + _asm shr eax, cl + _asm ret + lsr_count_ge_64: + _asm xor edx, edx + _asm xor eax, eax + _asm ret + } +} +