xref: /optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_shift.c (revision b5fed1a5386ffb7cc11a822043a7bc229b2fbbb0)
1 /*
2  * Copyright (c) 2015, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 union dword {
29 	unsigned long long dw;
30 	unsigned long w[2];
31 };
32 
33 long long __aeabi_llsl(long long a, int shift);
34 long long __aeabi_llsl(long long a, int shift)
35 {
36 	union dword dword = { .dw = a };
37 	unsigned long hi = dword.w[1];
38 	unsigned long lo = dword.w[0];
39 
40 	if (shift >= 32) {
41 		hi = lo << (shift - 32);
42 		lo = 0;
43 	} else if (shift > 0) {
44 		hi = (hi << shift) | (lo >> (32 - shift));
45 		lo = lo << shift;
46 	}
47 
48 	dword.w[1] = hi;
49 	dword.w[0] = lo;
50 	return dword.dw;
51 }
52 
53 long long __aeabi_llsr(long long a, int shift);
54 long long __aeabi_llsr(long long a, int shift)
55 {
56 	union dword dword = { .dw = a };
57 	unsigned long hi = dword.w[1];
58 	unsigned long lo = dword.w[0];
59 
60 	if (shift >= 32) {
61 		lo = hi >> (shift - 32);
62 		hi = 0;
63 	} else if (shift > 0) {
64 		lo = (lo >> shift) | (hi << (32 - shift));
65 		hi = hi >> shift;
66 	}
67 
68 	dword.w[1] = hi;
69 	dword.w[0] = lo;
70 	return dword.dw;
71 }
72