Update contrib.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\common\x86\x86hlp_gcc.inl
15 // If there are no exports then GCC 3.4.x does not generate a .reloc
16 // section, without which rombuild can't relocate the .code section
17 // to its ROM address. Your ROM then goes boom early in the boot sequence.
18 // This unused export forces the PE to be generated with a .reloc section.
22 EXPORT_C void __ignore_this_export()
26 static void DivisionByZero()
33 void __NAKED__ _alloca()
35 // GCC passes the param in eax and expects no return value
42 void __NAKED__ _allmul()
44 // Multiply two 64 bit integers returning a 64 bit result
46 // [esp+4], [esp+8] = arg 1
47 // [esp+12], [esp+16] = arg 1
48 // Return result in edx:eax
49 // Remove arguments from stack
52 asm("mov eax, [esp+4]"); // eax = low1
53 asm("mul dword ptr [esp+16]"); // edx:eax = low1*high2
54 asm("mov ecx, eax"); // keep low 32 bits of product
55 asm("mov eax, [esp+8]"); // eax = high1
56 asm("mul dword ptr [esp+12]"); // edx:eax = high1*low2
57 asm("add ecx, eax"); // accumulate low 32 bits of product
58 asm("mov eax, [esp+4]"); // eax = low1
59 asm("mul dword ptr [esp+12]"); // edx:eax = low1*low2
60 asm("add edx, ecx"); // add cross terms to high 32 bits
64 void __NAKED__ udiv64_divby0()
66 asm("int 0"); // division by zero exception
70 __NAKED__ /*LOCAL_C*/ void UDiv64()
72 // unsigned divide edx:eax by edi:esi
73 // quotient in ebx:eax, remainder in edi:edx
74 // ecx, ebp, esi also modified
76 asm("jnz short UDiv64a"); // branch if divisor >= 2^32
78 asm("jz %a0": : "i"(&DivisionByZero)); // if divisor=0, branch to error routine
79 asm("mov ebx, eax"); // ebx=dividend low
80 asm("mov eax, edx"); // eax=dividend high
81 asm("xor edx, edx"); // edx=0
82 asm("div esi"); // quotient high now in eax
83 asm("xchg eax, ebx"); // quotient high in ebx, dividend low in eax
84 asm("div esi"); // quotient now in ebx:eax, remainder in edi:edx
87 asm("xor eax, eax"); // set result to 0xFFFFFFFF
89 asm("jmp short UDiv64f");
91 asm("js short UDiv64b"); // skip if divisor msb set
92 asm("bsr ecx, edi"); // ecx=bit number of divisor msb - 32
94 asm("push edi"); // save divisor high
95 asm("push esi"); // save divisor low
96 asm("shrd esi, edi, cl"); // shift divisor right so that msb is bit 31
97 asm("mov ebx, edx"); // dividend into ebx:ebp
99 asm("shrd eax, edx, cl"); // shift dividend right same number of bits
101 asm("cmp edx, esi"); // check if approx quotient will be 2^32
102 asm("jae short UDiv64e"); // if so, true result must be 0xFFFFFFFF
103 asm("div esi"); // approximate quotient now in eax
105 asm("mov ecx, eax"); // into ecx
106 asm("mul edi"); // multiply approx. quotient by divisor high
107 asm("mov esi, eax"); // ls dword into esi, ms into edi
109 asm("mov eax, ecx"); // approx. quotient into eax
110 asm("mul dword ptr [esp]"); // multiply approx. quotient by divisor low
111 asm("add edx, esi"); // edi:edx:eax now equals approx. quotient * divisor
114 asm("sub ebp, eax"); // subtract dividend - approx. quotient *divisor
117 asm("jnc short UDiv64c"); // if no borrow, result OK
118 asm("dec ecx"); // else result is one too big
119 asm("add ebp, [esp]"); // and add divisor to get correct remainder
120 asm("adc ebx, [esp+4]");
122 asm("mov eax, ecx"); // result into ebx:eax, remainder into edi:edx
126 asm("add esp, 8"); // remove temporary values from stack
130 asm("sub eax, esi"); // subtract divisor from dividend
132 asm("jnc short UDiv64d"); // if no borrow, result=1, remainder in edx:eax
133 asm("add eax, esi"); // else add back
135 asm("dec ebx"); // and decrement quotient
137 asm("mov edi, edx"); // remainder into edi:edx
139 asm("mov eax, ebx"); // result in ebx:eax
144 __NAKED__ void _aulldvrm()
146 // Divide two 64 bit unsigned integers, returning a 64 bit result
147 // and a 64 bit remainder
150 // [esp+4], [esp+8] = dividend
151 // [esp+12], [esp+16] = divisor
153 // Return (dividend / divisor) in edx:eax
154 // Return (dividend % divisor) in ebx:ecx
156 // Remove arguments from stack
162 asm("mov eax, [esp+16]");
163 asm("mov edx, [esp+20]");
164 asm("mov esi, [esp+24]");
165 asm("mov edi, [esp+28]");
166 asm("call %a0": : "i"(&UDiv64));
176 __NAKED__ void _alldvrm()
178 // Divide two 64 bit signed integers, returning a 64 bit result
179 // and a 64 bit remainder
182 // [esp+4], [esp+8] = dividend
183 // [esp+12], [esp+16] = divisor
185 // Return (dividend / divisor) in edx:eax
186 // Return (dividend % divisor) in ebx:ecx
188 // Remove arguments from stack
194 asm("mov eax, [esp+16]");
195 asm("mov edx, [esp+20]");
196 asm("mov esi, [esp+24]");
197 asm("mov edi, [esp+28]");
198 asm("test edx, edx");
199 asm("jns alldrvm_dividend_nonnegative");
203 asm("alldrvm_dividend_nonnegative:");
204 asm("test edi, edi");
205 asm("jns alldrvm_divisor_nonnegative");
209 asm("alldrvm_divisor_nonnegative:");
210 asm("call %a0": : "i"(&UDiv64));
211 asm("mov ebp, [esp+20]");
213 asm("xor ebp, [esp+28]");
216 asm("jns alldrvm_quotient_nonnegative");
220 asm("alldrvm_quotient_nonnegative:");
221 asm("cmp dword ptr [esp+20], 0");
222 asm("jns alldrvm_rem_nonnegative");
226 asm("alldrvm_rem_nonnegative:");
233 //__NAKED__ void _aulldiv()
234 __NAKED__ void __udivdi3 ()
236 // Divide two 64 bit unsigned integers returning a 64 bit result
238 // [esp+4], [esp+8] = dividend
239 // [esp+12], [esp+16] = divisor
240 // Return result in edx:eax
241 // Remove arguments from stack
248 asm("mov eax, [esp+20]");
249 asm("mov edx, [esp+24]");
250 asm("mov esi, [esp+28]");
251 asm("mov edi, [esp+32]");
252 asm("call %a0": : "i"(&UDiv64));
262 __NAKED__ void __divdi3()
265 // Divide two 64 bit signed integers returning a 64 bit result
267 // [esp+4], [esp+8] = dividend
268 // [esp+12], [esp+16] = divisor
269 // Return result in edx:eax
270 // Remove arguments from stack
277 asm("mov eax, [esp+20]");
278 asm("mov edx, [esp+24]");
279 asm("mov esi, [esp+28]");
280 asm("mov edi, [esp+32]");
281 asm("test edx, edx");
282 asm("jns divdi_dividend_nonnegative");
286 asm("divdi_dividend_nonnegative:");
287 asm("test edi, edi");
288 asm("jns divdi_divisor_nonnegative");
292 asm("divdi_divisor_nonnegative:");
293 asm("call %a0": : "i"(&UDiv64));
294 asm("mov ecx, [esp+24]");
296 asm("xor ecx, [esp+32]");
297 asm("jns divdi_quotient_nonnegative");
301 asm("divdi_quotient_nonnegative:");
309 __NAKED__ void __umoddi3()
311 // Divide two 64 bit unsigned integers and return 64 bit remainder
313 // [esp+4], [esp+8] = dividend
314 // [esp+12], [esp+16] = divisor
315 // Return result in edx:eax
316 // Remove arguments from stack
323 asm("mov eax, [esp+20]");
324 asm("mov edx, [esp+24]");
325 asm("mov esi, [esp+28]");
326 asm("mov edi, [esp+32]");
327 asm("call %a0": : "i"(&UDiv64));
337 __NAKED__ void __moddi3()
339 // Divide two 64 bit signed integers and return 64 bit remainder
341 // [esp+4], [esp+8] = dividend
342 // [esp+12], [esp+16] = divisor
343 // Return result in edx:eax
344 // Remove arguments from stack
351 asm("mov eax, [esp+20]");
352 asm("mov edx, [esp+24]");
353 asm("mov esi, [esp+28]");
354 asm("mov edi, [esp+32]");
355 asm("test edx, edx");
356 asm("jns dividend_nonnegative");
360 asm("dividend_nonnegative:");
361 asm("test edi, edi");
362 asm("jns divisor_nonnegative");
366 asm("divisor_nonnegative:");
367 asm("call %a0": : "i"(&UDiv64));
370 asm("cmp dword ptr [esp+24], 0");
371 asm("jns rem_nonnegative");
375 asm("rem_nonnegative:");
383 __NAKED__ void _allshr()
385 // Arithmetic shift right EDX:EAX by CL
389 asm("jae asr_count_ge_64");
391 asm("jae asr_count_ge_32");
392 asm("shrd eax, edx, cl");
395 asm("asr_count_ge_32:");
401 asm("asr_count_ge_64:");
407 __NAKED__ void _allshl()
409 // shift left EDX:EAX by CL
413 asm("jae lsl_count_ge_64");
415 asm("jae lsl_count_ge_32");
416 asm("shld edx, eax, cl");
419 asm("lsl_count_ge_32:");
425 asm("lsl_count_ge_64:");
431 __NAKED__ void _aullshr()
433 // Logical shift right EDX:EAX by CL
437 asm("jae lsr_count_ge_64");
439 asm("jae lsr_count_ge_32");
440 asm("shrd eax, edx, cl");
443 asm("lsr_count_ge_32:");
449 asm("lsr_count_ge_64:");