1222656Sed// This file is dual licensed under the MIT and the University of Illinois Open 2222656Sed// Source Licenses. See LICENSE.TXT for details. 3214152Sed 4214152Sed#include "../assembly.h" 5214152Sed 6214152Sed// di_int __ashrdi3(di_int input, int count); 7214152Sed 8214152Sed#ifdef __i386__ 9214152Sed#ifdef __SSE2__ 10214152Sed 11214152Sed.text 12214152Sed.align 4 13214152SedDEFINE_COMPILERRT_FUNCTION(__ashrdi3) 14214152Sed movd 12(%esp), %xmm2 // Load count 15214152Sed movl 8(%esp), %eax 16214152Sed#ifndef TRUST_CALLERS_USE_64_BIT_STORES 17214152Sed movd 4(%esp), %xmm0 18214152Sed movd 8(%esp), %xmm1 19214152Sed punpckldq %xmm1, %xmm0 // Load input 20214152Sed#else 21214152Sed movq 4(%esp), %xmm0 // Load input 22214152Sed#endif 23214152Sed 24214152Sed psrlq %xmm2, %xmm0 // unsigned shift input by count 25214152Sed 26214152Sed testl %eax, %eax // check the sign-bit of the input 27214152Sed jns 1f // early out for positive inputs 28214152Sed 29214152Sed // If the input is negative, we need to construct the shifted sign bit 30214152Sed // to or into the result, as xmm does not have a signed right shift. 31214152Sed pcmpeqb %xmm1, %xmm1 // -1ULL 32214152Sed psrlq $58, %xmm1 // 0x3f 33214152Sed pandn %xmm1, %xmm2 // 63 - count 34214152Sed pcmpeqb %xmm1, %xmm1 // -1ULL 35214152Sed psubq %xmm1, %xmm2 // 64 - count 36214152Sed psllq %xmm2, %xmm1 // -1 << (64 - count) = leading sign bits 37214152Sed por %xmm1, %xmm0 38214152Sed 39214152Sed // Move the result back to the general purpose registers and return 40214152Sed1: movd %xmm0, %eax 41214152Sed psrlq $32, %xmm0 42214152Sed movd %xmm0, %edx 43214152Sed ret 44214152Sed 45214152Sed#else // Use GPRs instead of SSE2 instructions, if they aren't available. 46214152Sed 47214152Sed.text 48214152Sed.align 4 49214152SedDEFINE_COMPILERRT_FUNCTION(__ashrdi3) 50214152Sed movl 12(%esp), %ecx // Load count 51214152Sed movl 8(%esp), %edx // Load high 52214152Sed movl 4(%esp), %eax // Load low 53214152Sed 54214152Sed testl $0x20, %ecx // If count >= 32 55214152Sed jnz 1f // goto 1 56214152Sed 57214152Sed shrdl %cl, %edx, %eax // right shift low by count 58214152Sed sarl %cl, %edx // right shift high by count 59214152Sed ret 60214152Sed 61214152Sed1: movl %edx, %eax // Move high to low 62214152Sed sarl $31, %edx // clear high 63214152Sed sarl %cl, %eax // shift low by count - 32 64214152Sed ret 65214152Sed 66214152Sed#endif // __SSE2__ 67214152Sed#endif // __i386__ 68