1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/include/x86hlp_gcc.inl Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,455 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\common\x86\x86hlp_gcc.inl
1.18 +// If there are no exports then GCC 3.4.x does not generate a .reloc
1.19 +// section, without which rombuild can't relocate the .code section
1.20 +// to its ROM address. Your ROM then goes boom early in the boot sequence.
1.21 +// This unused export forces the PE to be generated with a .reloc section.
1.22 +//
1.23 +//
1.24 +
1.25 +EXPORT_C void __ignore_this_export()
1.26 + {
1.27 + }
1.28 +
1.29 +static void DivisionByZero()
1.30 + {
1.31 + asm("int 0");
1.32 + }
1.33 +
1.34 +extern "C" {
1.35 +
1.36 +void __NAKED__ _alloca()
1.37 +{
1.38 + // GCC passes the param in eax and expects no return value
1.39 + asm("pop ecx");
1.40 + asm("sub esp, eax");
1.41 + asm("push ecx");
1.42 + asm("ret");
1.43 +}
1.44 +
1.45 +void __NAKED__ _allmul()
1.46 +//
1.47 +// Multiply two 64 bit integers returning a 64 bit result
1.48 +// On entry:
1.49 +// [esp+4], [esp+8] = arg 1
1.50 +// [esp+12], [esp+16] = arg 1
1.51 +// Return result in edx:eax
1.52 +// Remove arguments from stack
1.53 +//
1.54 + {
1.55 + asm("mov eax, [esp+4]"); // eax = low1
1.56 + asm("mul dword ptr [esp+16]"); // edx:eax = low1*high2
1.57 + asm("mov ecx, eax"); // keep low 32 bits of product
1.58 + asm("mov eax, [esp+8]"); // eax = high1
1.59 + asm("mul dword ptr [esp+12]"); // edx:eax = high1*low2
1.60 + asm("add ecx, eax"); // accumulate low 32 bits of product
1.61 + asm("mov eax, [esp+4]"); // eax = low1
1.62 + asm("mul dword ptr [esp+12]"); // edx:eax = low1*low2
1.63 + asm("add edx, ecx"); // add cross terms to high 32 bits
1.64 + asm("ret");
1.65 + }
1.66 +
1.67 +void __NAKED__ udiv64_divby0()
1.68 + {
1.69 + asm("int 0"); // division by zero exception
1.70 + asm("ret");
1.71 + }
1.72 +
1.73 +__NAKED__ /*LOCAL_C*/ void UDiv64()
1.74 + {
1.75 + // unsigned divide edx:eax by edi:esi
1.76 + // quotient in ebx:eax, remainder in edi:edx
1.77 + // ecx, ebp, esi also modified
1.78 + asm("test edi, edi");
1.79 + asm("jnz short UDiv64a"); // branch if divisor >= 2^32
1.80 + asm("test esi, esi");
1.81 + asm("jz %a0": : "i"(&DivisionByZero)); // if divisor=0, branch to error routine
1.82 + asm("mov ebx, eax"); // ebx=dividend low
1.83 + asm("mov eax, edx"); // eax=dividend high
1.84 + asm("xor edx, edx"); // edx=0
1.85 + asm("div esi"); // quotient high now in eax
1.86 + asm("xchg eax, ebx"); // quotient high in ebx, dividend low in eax
1.87 + asm("div esi"); // quotient now in ebx:eax, remainder in edi:edx
1.88 + asm("ret");
1.89 + asm("UDiv64e:");
1.90 + asm("xor eax, eax"); // set result to 0xFFFFFFFF
1.91 + asm("dec eax");
1.92 + asm("jmp short UDiv64f");
1.93 + asm("UDiv64a:");
1.94 + asm("js short UDiv64b"); // skip if divisor msb set
1.95 + asm("bsr ecx, edi"); // ecx=bit number of divisor msb - 32
1.96 + asm("inc cl");
1.97 + asm("push edi"); // save divisor high
1.98 + asm("push esi"); // save divisor low
1.99 + asm("shrd esi, edi, cl"); // shift divisor right so that msb is bit 31
1.100 + asm("mov ebx, edx"); // dividend into ebx:ebp
1.101 + asm("mov ebp, eax");
1.102 + asm("shrd eax, edx, cl"); // shift dividend right same number of bits
1.103 + asm("shr edx, cl");
1.104 + asm("cmp edx, esi"); // check if approx quotient will be 2^32
1.105 + asm("jae short UDiv64e"); // if so, true result must be 0xFFFFFFFF
1.106 + asm("div esi"); // approximate quotient now in eax
1.107 + asm("UDiv64f:");
1.108 + asm("mov ecx, eax"); // into ecx
1.109 + asm("mul edi"); // multiply approx. quotient by divisor high
1.110 + asm("mov esi, eax"); // ls dword into esi, ms into edi
1.111 + asm("mov edi, edx");
1.112 + asm("mov eax, ecx"); // approx. quotient into eax
1.113 + asm("mul dword ptr [esp]"); // multiply approx. quotient by divisor low
1.114 + asm("add edx, esi"); // edi:edx:eax now equals approx. quotient * divisor
1.115 + asm("adc edi, 0");
1.116 + asm("xor esi, esi");
1.117 + asm("sub ebp, eax"); // subtract dividend - approx. quotient *divisor
1.118 + asm("sbb ebx, edx");
1.119 + asm("sbb esi, edi");
1.120 + asm("jnc short UDiv64c"); // if no borrow, result OK
1.121 + asm("dec ecx"); // else result is one too big
1.122 + asm("add ebp, [esp]"); // and add divisor to get correct remainder
1.123 + asm("adc ebx, [esp+4]");
1.124 + asm("UDiv64c:");
1.125 + asm("mov eax, ecx"); // result into ebx:eax, remainder into edi:edx
1.126 + asm("mov edi, ebx");
1.127 + asm("mov edx, ebp");
1.128 + asm("xor ebx, ebx");
1.129 + asm("add esp, 8"); // remove temporary values from stack
1.130 + asm("ret");
1.131 + asm("UDiv64b:");
1.132 + asm("mov ebx, 1");
1.133 + asm("sub eax, esi"); // subtract divisor from dividend
1.134 + asm("sbb edx, edi");
1.135 + asm("jnc short UDiv64d"); // if no borrow, result=1, remainder in edx:eax
1.136 + asm("add eax, esi"); // else add back
1.137 + asm("adc edx, edi");
1.138 + asm("dec ebx"); // and decrement quotient
1.139 + asm("UDiv64d:");
1.140 + asm("mov edi, edx"); // remainder into edi:edx
1.141 + asm("mov edx, eax");
1.142 + asm("mov eax, ebx"); // result in ebx:eax
1.143 + asm("xor ebx, ebx");
1.144 + asm("ret");
1.145 + }
1.146 +
1.147 +__NAKED__ void _aulldvrm()
1.148 +//
1.149 +// Divide two 64 bit unsigned integers, returning a 64 bit result
1.150 +// and a 64 bit remainder
1.151 +//
1.152 +// On entry:
1.153 +// [esp+4], [esp+8] = dividend
1.154 +// [esp+12], [esp+16] = divisor
1.155 +//
1.156 +// Return (dividend / divisor) in edx:eax
1.157 +// Return (dividend % divisor) in ebx:ecx
1.158 +//
1.159 +// Remove arguments from stack
1.160 +//
1.161 + {
1.162 + asm("push ebp");
1.163 + asm("push edi");
1.164 + asm("push esi");
1.165 + asm("mov eax, [esp+16]");
1.166 + asm("mov edx, [esp+20]");
1.167 + asm("mov esi, [esp+24]");
1.168 + asm("mov edi, [esp+28]");
1.169 + asm("call %a0": : "i"(&UDiv64));
1.170 + asm("mov ecx, edx");
1.171 + asm("mov edx, ebx");
1.172 + asm("mov ebx, edi");
1.173 + asm("pop esi");
1.174 + asm("pop edi");
1.175 + asm("pop ebp");
1.176 + asm("ret");
1.177 + }
1.178 +
1.179 +__NAKED__ void _alldvrm()
1.180 +//
1.181 +// Divide two 64 bit signed integers, returning a 64 bit result
1.182 +// and a 64 bit remainder
1.183 +//
1.184 +// On entry:
1.185 +// [esp+4], [esp+8] = dividend
1.186 +// [esp+12], [esp+16] = divisor
1.187 +//
1.188 +// Return (dividend / divisor) in edx:eax
1.189 +// Return (dividend % divisor) in ebx:ecx
1.190 +//
1.191 +// Remove arguments from stack
1.192 +//
1.193 + {
1.194 + asm("push ebp");
1.195 + asm("push edi");
1.196 + asm("push esi");
1.197 + asm("mov eax, [esp+16]");
1.198 + asm("mov edx, [esp+20]");
1.199 + asm("mov esi, [esp+24]");
1.200 + asm("mov edi, [esp+28]");
1.201 + asm("test edx, edx");
1.202 + asm("jns alldrvm_dividend_nonnegative");
1.203 + asm("neg edx");
1.204 + asm("neg eax");
1.205 + asm("sbb edx, 0");
1.206 + asm("alldrvm_dividend_nonnegative:");
1.207 + asm("test edi, edi");
1.208 + asm("jns alldrvm_divisor_nonnegative");
1.209 + asm("neg edi");
1.210 + asm("neg esi");
1.211 + asm("sbb edi, 0");
1.212 + asm("alldrvm_divisor_nonnegative:");
1.213 + asm("call %a0": : "i"(&UDiv64));
1.214 + asm("mov ebp, [esp+20]");
1.215 + asm("mov ecx, edx");
1.216 + asm("xor ebp, [esp+28]");
1.217 + asm("mov edx, ebx");
1.218 + asm("mov ebx, edi");
1.219 + asm("jns alldrvm_quotient_nonnegative");
1.220 + asm("neg edx");
1.221 + asm("neg eax");
1.222 + asm("sbb edx, 0");
1.223 + asm("alldrvm_quotient_nonnegative:");
1.224 + asm("cmp dword ptr [esp+20], 0");
1.225 + asm("jns alldrvm_rem_nonnegative");
1.226 + asm("neg ebx");
1.227 + asm("neg ecx");
1.228 + asm("sbb ebx, 0");
1.229 + asm("alldrvm_rem_nonnegative:");
1.230 + asm("pop esi");
1.231 + asm("pop edi");
1.232 + asm("pop ebp");
1.233 + asm("ret");
1.234 + }
1.235 +
1.236 +//__NAKED__ void _aulldiv()
1.237 +__NAKED__ void __udivdi3 ()
1.238 +//
1.239 +// Divide two 64 bit unsigned integers returning a 64 bit result
1.240 +// On entry:
1.241 +// [esp+4], [esp+8] = dividend
1.242 +// [esp+12], [esp+16] = divisor
1.243 +// Return result in edx:eax
1.244 +// Remove arguments from stack
1.245 +//
1.246 + {
1.247 + asm("push ebp");
1.248 + asm("push edi");
1.249 + asm("push esi");
1.250 + asm("push ebx");
1.251 + asm("mov eax, [esp+20]");
1.252 + asm("mov edx, [esp+24]");
1.253 + asm("mov esi, [esp+28]");
1.254 + asm("mov edi, [esp+32]");
1.255 + asm("call %a0": : "i"(&UDiv64));
1.256 + asm("mov edx, ebx");
1.257 + asm("pop ebx");
1.258 + asm("pop esi");
1.259 + asm("pop edi");
1.260 + asm("pop ebp");
1.261 + asm("ret");
1.262 + }
1.263 +
1.264 +
1.265 +__NAKED__ void __divdi3()
1.266 +
1.267 +//
1.268 +// Divide two 64 bit signed integers returning a 64 bit result
1.269 +// On entry:
1.270 +// [esp+4], [esp+8] = dividend
1.271 +// [esp+12], [esp+16] = divisor
1.272 +// Return result in edx:eax
1.273 +// Remove arguments from stack
1.274 +//
1.275 + {
1.276 + asm("push ebp");
1.277 + asm("push edi");
1.278 + asm("push esi");
1.279 + asm("push ebx");
1.280 + asm("mov eax, [esp+20]");
1.281 + asm("mov edx, [esp+24]");
1.282 + asm("mov esi, [esp+28]");
1.283 + asm("mov edi, [esp+32]");
1.284 + asm("test edx, edx");
1.285 + asm("jns divdi_dividend_nonnegative");
1.286 + asm("neg edx");
1.287 + asm("neg eax");
1.288 + asm("sbb edx, 0");
1.289 + asm("divdi_dividend_nonnegative:");
1.290 + asm("test edi, edi");
1.291 + asm("jns divdi_divisor_nonnegative");
1.292 + asm("neg edi");
1.293 + asm("neg esi");
1.294 + asm("sbb edi, 0");
1.295 + asm("divdi_divisor_nonnegative:");
1.296 + asm("call %a0": : "i"(&UDiv64));
1.297 + asm("mov ecx, [esp+24]");
1.298 + asm("mov edx, ebx");
1.299 + asm("xor ecx, [esp+32]");
1.300 + asm("jns divdi_quotient_nonnegative");
1.301 + asm("neg edx");
1.302 + asm("neg eax");
1.303 + asm("sbb edx, 0");
1.304 + asm("divdi_quotient_nonnegative:");
1.305 + asm("pop ebx");
1.306 + asm("pop esi");
1.307 + asm("pop edi");
1.308 + asm("pop ebp");
1.309 + asm("ret");
1.310 + }
1.311 +
1.312 +__NAKED__ void __umoddi3()
1.313 +//
1.314 +// Divide two 64 bit unsigned integers and return 64 bit remainder
1.315 +// On entry:
1.316 +// [esp+4], [esp+8] = dividend
1.317 +// [esp+12], [esp+16] = divisor
1.318 +// Return result in edx:eax
1.319 +// Remove arguments from stack
1.320 +//
1.321 + {
1.322 + asm("push ebp");
1.323 + asm("push edi");
1.324 + asm("push esi");
1.325 + asm("push ebx");
1.326 + asm("mov eax, [esp+20]");
1.327 + asm("mov edx, [esp+24]");
1.328 + asm("mov esi, [esp+28]");
1.329 + asm("mov edi, [esp+32]");
1.330 + asm("call %a0": : "i"(&UDiv64));
1.331 + asm("mov eax, edx");
1.332 + asm("mov edx, edi");
1.333 + asm("pop ebx");
1.334 + asm("pop esi");
1.335 + asm("pop edi");
1.336 + asm("pop ebp");
1.337 + asm("ret");
1.338 + }
1.339 +
1.340 +__NAKED__ void __moddi3()
1.341 +//
1.342 +// Divide two 64 bit signed integers and return 64 bit remainder
1.343 +// On entry:
1.344 +// [esp+4], [esp+8] = dividend
1.345 +// [esp+12], [esp+16] = divisor
1.346 +// Return result in edx:eax
1.347 +// Remove arguments from stack
1.348 +//
1.349 + {
1.350 + asm("push ebp");
1.351 + asm("push edi");
1.352 + asm("push esi");
1.353 + asm("push ebx");
1.354 + asm("mov eax, [esp+20]");
1.355 + asm("mov edx, [esp+24]");
1.356 + asm("mov esi, [esp+28]");
1.357 + asm("mov edi, [esp+32]");
1.358 + asm("test edx, edx");
1.359 + asm("jns dividend_nonnegative");
1.360 + asm("neg edx");
1.361 + asm("neg eax");
1.362 + asm("sbb edx, 0");
1.363 + asm("dividend_nonnegative:");
1.364 + asm("test edi, edi");
1.365 + asm("jns divisor_nonnegative");
1.366 + asm("neg edi");
1.367 + asm("neg esi");
1.368 + asm("sbb edi, 0");
1.369 + asm("divisor_nonnegative:");
1.370 + asm("call %a0": : "i"(&UDiv64));
1.371 + asm("mov eax, edx");
1.372 + asm("mov edx, edi");
1.373 + asm("cmp dword ptr [esp+24], 0");
1.374 + asm("jns rem_nonnegative");
1.375 + asm("neg edx");
1.376 + asm("neg eax");
1.377 + asm("sbb edx, 0");
1.378 + asm("rem_nonnegative:");
1.379 + asm("pop ebx");
1.380 + asm("pop esi");
1.381 + asm("pop edi");
1.382 + asm("pop ebp");
1.383 + asm("ret");
1.384 + }
1.385 +
1.386 +__NAKED__ void _allshr()
1.387 +//
1.388 +// Arithmetic shift right EDX:EAX by CL
1.389 +//
1.390 + {
1.391 + asm("cmp cl, 64");
1.392 + asm("jae asr_count_ge_64");
1.393 + asm("cmp cl, 32");
1.394 + asm("jae asr_count_ge_32");
1.395 + asm("shrd eax, edx, cl");
1.396 + asm("sar edx, cl");
1.397 + asm("ret");
1.398 + asm("asr_count_ge_32:");
1.399 + asm("sub cl, 32");
1.400 + asm("mov eax, edx");
1.401 + asm("cdq");
1.402 + asm("sar eax, cl");
1.403 + asm("ret");
1.404 + asm("asr_count_ge_64:");
1.405 + asm("sar edx, 32");
1.406 + asm("mov eax, edx");
1.407 + asm("ret");
1.408 + }
1.409 +
1.410 +__NAKED__ void _allshl()
1.411 +//
1.412 +// shift left EDX:EAX by CL
1.413 +//
1.414 + {
1.415 + asm("cmp cl, 64");
1.416 + asm("jae lsl_count_ge_64");
1.417 + asm("cmp cl, 32");
1.418 + asm("jae lsl_count_ge_32");
1.419 + asm("shld edx, eax, cl");
1.420 + asm("shl eax, cl");
1.421 + asm("ret");
1.422 + asm("lsl_count_ge_32:");
1.423 + asm("sub cl, 32");
1.424 + asm("mov edx, eax");
1.425 + asm("xor eax, eax");
1.426 + asm("shl edx, cl");
1.427 + asm("ret");
1.428 + asm("lsl_count_ge_64:");
1.429 + asm("xor edx, edx");
1.430 + asm("xor eax, eax");
1.431 + asm("ret");
1.432 + }
1.433 +
1.434 +__NAKED__ void _aullshr()
1.435 +//
1.436 +// Logical shift right EDX:EAX by CL
1.437 +//
1.438 + {
1.439 + asm("cmp cl, 64");
1.440 + asm("jae lsr_count_ge_64");
1.441 + asm("cmp cl, 32");
1.442 + asm("jae lsr_count_ge_32");
1.443 + asm("shrd eax, edx, cl");
1.444 + asm("shr edx, cl");
1.445 + asm("ret");
1.446 + asm("lsr_count_ge_32:");
1.447 + asm("sub cl, 32");
1.448 + asm("mov eax, edx");
1.449 + asm("xor edx, edx");
1.450 + asm("shr eax, cl");
1.451 + asm("ret");
1.452 + asm("lsr_count_ge_64:");
1.453 + asm("xor edx, edx");
1.454 + asm("xor eax, eax");
1.455 + asm("ret");
1.456 + }
1.457 +
1.458 +}