1 | /* Shift a limb left, low level routine. |
2 | Copyright (C) 1996-2024 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <sysdep.h> |
20 | |
21 | /* mp_limb_t mpn_lshift (mp_ptr wp, mp_srcptr up, mp_size_t usize, |
22 | unsigned int cnt) */ |
23 | |
24 | EALIGN (__mpn_lshift, 3, 0) |
25 | |
26 | mtctr r5 # copy size into CTR |
27 | cmplwi cr0,r5,16 # is size < 16 |
28 | slwi r0,r5,2 |
29 | add r7,r3,r0 # make r7 point at end of res |
30 | add r4,r4,r0 # make r4 point at end of s1 |
31 | lwzu r11,-4(r4) # load first s1 limb |
32 | subfic r8,r6,32 |
33 | srw r3,r11,r8 # compute function return value |
34 | bge cr0,L(big) # branch if size >= 16 |
35 | |
36 | bdz L(end1) |
37 | |
38 | L(0): lwzu r10,-4(r4) |
39 | slw r9,r11,r6 |
40 | srw r12,r10,r8 |
41 | or r9,r9,r12 |
42 | stwu r9,-4(r7) |
43 | bdz L(end2) |
44 | lwzu r11,-4(r4) |
45 | slw r9,r10,r6 |
46 | srw r12,r11,r8 |
47 | or r9,r9,r12 |
48 | stwu r9,-4(r7) |
49 | bdnz L(0) |
50 | |
51 | L(end1):slw r0,r11,r6 |
52 | stw r0,-4(r7) |
53 | blr |
54 | |
55 | |
56 | /* Guaranteed not to succeed. */ |
57 | L(boom): tweq r0,r0 |
58 | |
59 | /* We imitate a case statement, by using (yuk!) fixed-length code chunks, |
60 | of size 4*12 bytes. We have to do this (or something) to make this PIC. */ |
61 | L(big): mflr r9 |
62 | cfi_register(lr,r9) |
63 | bltl- cr0,L(boom) # Never taken, only used to set LR. |
64 | slwi r10,r6,4 |
65 | mflr r12 |
66 | add r10,r12,r10 |
67 | slwi r8,r6,5 |
68 | add r10,r8,r10 |
69 | mtctr r10 |
70 | addi r5,r5,-1 |
71 | mtlr r9 |
72 | cfi_same_value (lr) |
73 | bctr |
74 | |
75 | L(end2):slw r0,r10,r6 |
76 | stw r0,-4(r7) |
77 | blr |
78 | |
79 | #define DO_LSHIFT(n) \ |
80 | mtctr r5; \ |
81 | L(n): lwzu r10,-4(r4); \ |
82 | slwi r9,r11,n; \ |
83 | inslwi r9,r10,n,32-n; \ |
84 | stwu r9,-4(r7); \ |
85 | bdz- L(end2); \ |
86 | lwzu r11,-4(r4); \ |
87 | slwi r9,r10,n; \ |
88 | inslwi r9,r11,n,32-n; \ |
89 | stwu r9,-4(r7); \ |
90 | bdnz L(n); \ |
91 | b L(end1) |
92 | |
93 | DO_LSHIFT(1) |
94 | DO_LSHIFT(2) |
95 | DO_LSHIFT(3) |
96 | DO_LSHIFT(4) |
97 | DO_LSHIFT(5) |
98 | DO_LSHIFT(6) |
99 | DO_LSHIFT(7) |
100 | DO_LSHIFT(8) |
101 | DO_LSHIFT(9) |
102 | DO_LSHIFT(10) |
103 | DO_LSHIFT(11) |
104 | DO_LSHIFT(12) |
105 | DO_LSHIFT(13) |
106 | DO_LSHIFT(14) |
107 | DO_LSHIFT(15) |
108 | DO_LSHIFT(16) |
109 | DO_LSHIFT(17) |
110 | DO_LSHIFT(18) |
111 | DO_LSHIFT(19) |
112 | DO_LSHIFT(20) |
113 | DO_LSHIFT(21) |
114 | DO_LSHIFT(22) |
115 | DO_LSHIFT(23) |
116 | DO_LSHIFT(24) |
117 | DO_LSHIFT(25) |
118 | DO_LSHIFT(26) |
119 | DO_LSHIFT(27) |
120 | DO_LSHIFT(28) |
121 | DO_LSHIFT(29) |
122 | DO_LSHIFT(30) |
123 | DO_LSHIFT(31) |
124 | |
125 | END (__mpn_lshift) |
126 | |