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