]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/compiler-rt/lib/i386/lshrdi3.S
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / compiler-rt / lib / i386 / lshrdi3.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 __lshrdi3(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 .align 4
20 DEFINE_COMPILERRT_FUNCTION(__lshrdi3)
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         psrlq           %xmm2,          %xmm0   // shift input by count
30         movd            %xmm0,          %eax
31         psrlq           $32,            %xmm0
32         movd            %xmm0,          %edx
33         ret
34
35 #else // Use GPRs instead of SSE2 instructions, if they aren't available.
36
37 .text
38 .align 4
39 DEFINE_COMPILERRT_FUNCTION(__lshrdi3)
40         movl      12(%esp),             %ecx    // Load count
41         movl       8(%esp),             %edx    // Load high
42         movl       4(%esp),             %eax    // Load low
43         
44         testl           $0x20,          %ecx    // If count >= 32
45         jnz                     1f                                      //    goto 1
46
47         shrdl           %cl, %edx,      %eax    // right shift low by count
48         shrl            %cl,            %edx    // right shift high by count
49         ret
50         
51 1:      movl            %edx,           %eax    // Move high to low
52         xorl            %edx,           %edx    // clear high
53         shrl            %cl,            %eax    // shift low by count - 32
54         ret
55         
56 #endif // __SSE2__
57 #endif // __i386__