]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/builtins/i386/ashldi3.S
Update compiler-rt to trunk r224034. This brings a number of new
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / builtins / i386 / ashldi3.S
1 // This file is dual licensed under the MIT and the University of Illinois Open
2 // Source Licenses. See LICENSE.TXT for details.
3
4 #include "../assembly.h"
5
6 // di_int __ashldi3(di_int input, int count);
7
8 // This routine has some extra memory traffic, loading the 64-bit input via two
9 // 32-bit loads, then immediately storing it back to the stack via a single 64-bit
10 // store.  This is to avoid a write-small, read-large stall.
11 // However, if callers of this routine can be safely assumed to store the argument
12 // via a 64-bt store, this is unnecessary memory traffic, and should be avoided.
13 // It can be turned off by defining the TRUST_CALLERS_USE_64_BIT_STORES macro.
14
15 #ifdef __i386__
16 #ifdef __SSE2__
17
18 .text
19 .balign 4
20 DEFINE_COMPILERRT_FUNCTION(__ashldi3)
21         movd      12(%esp),             %xmm2   // Load count
22 #ifndef TRUST_CALLERS_USE_64_BIT_STORES
23         movd       4(%esp),             %xmm0
24         movd       8(%esp),             %xmm1
25         punpckldq       %xmm1,          %xmm0   // Load input
26 #else
27         movq       4(%esp),             %xmm0   // Load input
28 #endif
29         psllq           %xmm2,          %xmm0   // shift input by count
30         movd            %xmm0,          %eax
31         psrlq           $32,            %xmm0
32         movd            %xmm0,          %edx
33         ret
34 END_COMPILERRT_FUNCTION(__ashldi3)
35
36 #else // Use GPRs instead of SSE2 instructions, if they aren't available.
37
38 .text
39 .balign 4
40 DEFINE_COMPILERRT_FUNCTION(__ashldi3)
41         movl      12(%esp),             %ecx    // Load count
42         movl       8(%esp),             %edx    // Load high
43         movl       4(%esp),             %eax    // Load low
44
45         testl           $0x20,          %ecx    // If count >= 32
46         jnz             1f                      //    goto 1
47         shldl           %cl, %eax,      %edx    // left shift high by count
48         shll            %cl,            %eax    // left shift low by count
49         ret
50
51 1:      movl            %eax,           %edx    // Move low to high
52         xorl            %eax,           %eax    // clear low
53         shll            %cl,            %edx    // shift high by count - 32
54         ret
55 END_COMPILERRT_FUNCTION(__ashldi3)
56
57 #endif // __SSE2__
58 #endif // __i386__