Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// 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 "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\common\x86\x86hlp_gcc.inl
// If there are no exports then GCC 3.4.x does not generate a .reloc
// section, without which rombuild can't relocate the .code section
// to its ROM address. Your ROM then goes boom early in the boot sequence.
// This unused export forces the PE to be generated with a .reloc section.
//
//
EXPORT_C void __ignore_this_export()
{
}
static void DivisionByZero()
{
asm("int 0");
}
extern "C" {
void __NAKED__ _alloca()
{
// GCC passes the param in eax and expects no return value
asm("pop ecx");
asm("sub esp, eax");
asm("push ecx");
asm("ret");
}
void __NAKED__ _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");
}
void __NAKED__ udiv64_divby0()
{
asm("int 0"); // division by zero exception
asm("ret");
}
__NAKED__ /*LOCAL_C*/ 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("jz %a0": : "i"(&DivisionByZero)); // if divisor=0, branch to error routine
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");
asm("UDiv64e:");
asm("xor eax, eax"); // set result to 0xFFFFFFFF
asm("dec eax");
asm("jmp short UDiv64f");
asm("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
asm("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]");
asm("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");
asm("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
asm("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 _aulldvrm()
//
// Divide two 64 bit unsigned integers, returning a 64 bit result
// and a 64 bit remainder
//
// On entry:
// [esp+4], [esp+8] = dividend
// [esp+12], [esp+16] = divisor
//
// Return (dividend / divisor) in edx:eax
// Return (dividend % divisor) in ebx:ecx
//
// Remove arguments from stack
//
{
asm("push ebp");
asm("push edi");
asm("push esi");
asm("mov eax, [esp+16]");
asm("mov edx, [esp+20]");
asm("mov esi, [esp+24]");
asm("mov edi, [esp+28]");
asm("call %a0": : "i"(&UDiv64));
asm("mov ecx, edx");
asm("mov edx, ebx");
asm("mov ebx, edi");
asm("pop esi");
asm("pop edi");
asm("pop ebp");
asm("ret");
}
__NAKED__ void _alldvrm()
//
// Divide two 64 bit signed integers, returning a 64 bit result
// and a 64 bit remainder
//
// On entry:
// [esp+4], [esp+8] = dividend
// [esp+12], [esp+16] = divisor
//
// Return (dividend / divisor) in edx:eax
// Return (dividend % divisor) in ebx:ecx
//
// Remove arguments from stack
//
{
asm("push ebp");
asm("push edi");
asm("push esi");
asm("mov eax, [esp+16]");
asm("mov edx, [esp+20]");
asm("mov esi, [esp+24]");
asm("mov edi, [esp+28]");
asm("test edx, edx");
asm("jns alldrvm_dividend_nonnegative");
asm("neg edx");
asm("neg eax");
asm("sbb edx, 0");
asm("alldrvm_dividend_nonnegative:");
asm("test edi, edi");
asm("jns alldrvm_divisor_nonnegative");
asm("neg edi");
asm("neg esi");
asm("sbb edi, 0");
asm("alldrvm_divisor_nonnegative:");
asm("call %a0": : "i"(&UDiv64));
asm("mov ebp, [esp+20]");
asm("mov ecx, edx");
asm("xor ebp, [esp+28]");
asm("mov edx, ebx");
asm("mov ebx, edi");
asm("jns alldrvm_quotient_nonnegative");
asm("neg edx");
asm("neg eax");
asm("sbb edx, 0");
asm("alldrvm_quotient_nonnegative:");
asm("cmp dword ptr [esp+20], 0");
asm("jns alldrvm_rem_nonnegative");
asm("neg ebx");
asm("neg ecx");
asm("sbb ebx, 0");
asm("alldrvm_rem_nonnegative:");
asm("pop esi");
asm("pop edi");
asm("pop ebp");
asm("ret");
}
//__NAKED__ void _aulldiv()
__NAKED__ void __udivdi3 ()
//
// 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 %a0": : "i"(&UDiv64));
asm("mov edx, ebx");
asm("pop ebx");
asm("pop esi");
asm("pop edi");
asm("pop ebp");
asm("ret");
}
__NAKED__ void __divdi3()
//
// 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 divdi_dividend_nonnegative");
asm("neg edx");
asm("neg eax");
asm("sbb edx, 0");
asm("divdi_dividend_nonnegative:");
asm("test edi, edi");
asm("jns divdi_divisor_nonnegative");
asm("neg edi");
asm("neg esi");
asm("sbb edi, 0");
asm("divdi_divisor_nonnegative:");
asm("call %a0": : "i"(&UDiv64));
asm("mov ecx, [esp+24]");
asm("mov edx, ebx");
asm("xor ecx, [esp+32]");
asm("jns divdi_quotient_nonnegative");
asm("neg edx");
asm("neg eax");
asm("sbb edx, 0");
asm("divdi_quotient_nonnegative:");
asm("pop ebx");
asm("pop esi");
asm("pop edi");
asm("pop ebp");
asm("ret");
}
__NAKED__ void __umoddi3()
//
// 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 %a0": : "i"(&UDiv64));
asm("mov eax, edx");
asm("mov edx, edi");
asm("pop ebx");
asm("pop esi");
asm("pop edi");
asm("pop ebp");
asm("ret");
}
__NAKED__ void __moddi3()
//
// 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");
asm("dividend_nonnegative:");
asm("test edi, edi");
asm("jns divisor_nonnegative");
asm("neg edi");
asm("neg esi");
asm("sbb edi, 0");
asm("divisor_nonnegative:");
asm("call %a0": : "i"(&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");
asm("rem_nonnegative:");
asm("pop ebx");
asm("pop esi");
asm("pop edi");
asm("pop ebp");
asm("ret");
}
__NAKED__ void _allshr()
//
// Arithmetic shift right EDX:EAX by CL
//
{
asm("cmp cl, 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");
asm("asr_count_ge_32:");
asm("sub cl, 32");
asm("mov eax, edx");
asm("cdq");
asm("sar eax, cl");
asm("ret");
asm("asr_count_ge_64:");
asm("sar edx, 32");
asm("mov eax, edx");
asm("ret");
}
__NAKED__ void _allshl()
//
// shift left EDX:EAX by CL
//
{
asm("cmp cl, 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");
asm("lsl_count_ge_32:");
asm("sub cl, 32");
asm("mov edx, eax");
asm("xor eax, eax");
asm("shl edx, cl");
asm("ret");
asm("lsl_count_ge_64:");
asm("xor edx, edx");
asm("xor eax, eax");
asm("ret");
}
__NAKED__ void _aullshr()
//
// Logical shift right EDX:EAX by CL
//
{
asm("cmp cl, 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");
asm("lsr_count_ge_32:");
asm("sub cl, 32");
asm("mov eax, edx");
asm("xor edx, edx");
asm("shr eax, cl");
asm("ret");
asm("lsr_count_ge_64:");
asm("xor edx, edx");
asm("xor eax, eax");
asm("ret");
}
}