--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/symport/e32/include/x86hlp_gcc.inl Thu Jun 25 15:59:54 2009 +0100
@@ -0,0 +1,455 @@
+// 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\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");
+ }
+
+}