]>
Commit | Line | Data |
---|---|---|
3de9f02e RM |
1 | /* mc68020 __mpn_lshift -- Shift left a low-level natural-number integer. |
2 | ||
56d7f029 | 3 | Copyright (C) 1996, 1998 Free Software Foundation, Inc. |
3de9f02e RM |
4 | |
5 | This file is part of the GNU MP Library. | |
6 | ||
7 | The GNU MP Library is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU Library General Public License as published by | |
9 | the Free Software Foundation; either version 2 of the License, or (at your | |
10 | option) any later version. | |
11 | ||
12 | The GNU MP Library is distributed in the hope that it will be useful, but | |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public | |
15 | License for more details. | |
16 | ||
17 | You should have received a copy of the GNU Library General Public License | |
18 | along with the GNU MP Library; see the file COPYING.LIB. If not, write to | |
6c07070b RM |
19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
20 | MA 02111-1307, USA. */ | |
3de9f02e RM |
21 | |
22 | /* | |
23 | INPUT PARAMETERS | |
24 | res_ptr (sp + 4) | |
25 | s_ptr (sp + 8) | |
26 | s_size (sp + 16) | |
27 | cnt (sp + 12) | |
28 | */ | |
29 | ||
30 | #include "sysdep.h" | |
31 | #include "asm-syntax.h" | |
32 | ||
33 | #define res_ptr a1 | |
34 | #define s_ptr a0 | |
35 | #define s_size d6 | |
36 | #define cnt d4 | |
37 | ||
38 | TEXT | |
56d7f029 | 39 | ENTRY(__mpn_lshift) |
3de9f02e RM |
40 | |
41 | /* Save used registers on the stack. */ | |
42 | moveml R(d2)-R(d6)/R(a2),MEM_PREDEC(sp) | |
43 | ||
44 | /* Copy the arguments to registers. */ | |
45 | movel MEM_DISP(sp,28),R(res_ptr) | |
46 | movel MEM_DISP(sp,32),R(s_ptr) | |
47 | movel MEM_DISP(sp,36),R(s_size) | |
48 | movel MEM_DISP(sp,40),R(cnt) | |
49 | ||
50 | moveql #1,R(d5) | |
51 | cmpl R(d5),R(cnt) | |
52 | bne L(Lnormal) | |
53 | cmpl R(s_ptr),R(res_ptr) | |
54 | bls L(Lspecial) /* jump if s_ptr >= res_ptr */ | |
55 | #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) | |
56 | lea MEM_INDX1(s_ptr,s_size,l,4),R(a2) | |
57 | #else /* not mc68020 */ | |
58 | movel R(s_size),R(d0) | |
59 | asll #2,R(d0) | |
60 | lea MEM_INDX(s_ptr,d0,l),R(a2) | |
61 | #endif | |
62 | cmpl R(res_ptr),R(a2) | |
63 | bls L(Lspecial) /* jump if res_ptr >= s_ptr + s_size */ | |
64 | ||
65 | L(Lnormal:) | |
66 | moveql #32,R(d5) | |
67 | subl R(cnt),R(d5) | |
68 | ||
69 | #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) | |
70 | lea MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr) | |
71 | lea MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr) | |
72 | #else /* not mc68000 */ | |
73 | movel R(s_size),R(d0) | |
74 | asll #2,R(d0) | |
75 | addl R(s_size),R(s_ptr) | |
76 | addl R(s_size),R(res_ptr) | |
77 | #endif | |
78 | movel MEM_PREDEC(s_ptr),R(d2) | |
79 | movel R(d2),R(d0) | |
80 | lsrl R(d5),R(d0) /* compute carry limb */ | |
81 | ||
82 | lsll R(cnt),R(d2) | |
83 | movel R(d2),R(d1) | |
84 | subql #1,R(s_size) | |
85 | beq L(Lend) | |
86 | lsrl #1,R(s_size) | |
87 | bcs L(L1) | |
88 | subql #1,R(s_size) | |
89 | ||
90 | L(Loop:) | |
91 | movel MEM_PREDEC(s_ptr),R(d2) | |
92 | movel R(d2),R(d3) | |
93 | lsrl R(d5),R(d3) | |
94 | orl R(d3),R(d1) | |
95 | movel R(d1),MEM_PREDEC(res_ptr) | |
96 | lsll R(cnt),R(d2) | |
97 | L(L1:) | |
98 | movel MEM_PREDEC(s_ptr),R(d1) | |
99 | movel R(d1),R(d3) | |
100 | lsrl R(d5),R(d3) | |
101 | orl R(d3),R(d2) | |
102 | movel R(d2),MEM_PREDEC(res_ptr) | |
103 | lsll R(cnt),R(d1) | |
104 | ||
105 | dbf R(s_size),L(Loop) | |
106 | subl #0x10000,R(s_size) | |
107 | bcc L(Loop) | |
108 | ||
109 | L(Lend:) | |
110 | movel R(d1),MEM_PREDEC(res_ptr) /* store least significant limb */ | |
111 | ||
112 | /* Restore used registers from stack frame. */ | |
113 | moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) | |
114 | rts | |
115 | ||
116 | /* We loop from least significant end of the arrays, which is only | |
910e2e14 | 117 | permissible if the source and destination don't overlap, since the |
3de9f02e RM |
118 | function is documented to work for overlapping source and destination. */ |
119 | ||
120 | L(Lspecial:) | |
121 | clrl R(d0) /* initialize carry */ | |
122 | eorw #1,R(s_size) | |
123 | lsrl #1,R(s_size) | |
124 | bcc L(LL1) | |
125 | subql #1,R(s_size) | |
126 | ||
127 | L(LLoop:) | |
128 | movel MEM_POSTINC(s_ptr),R(d2) | |
129 | addxl R(d2),R(d2) | |
130 | movel R(d2),MEM_POSTINC(res_ptr) | |
131 | L(LL1:) | |
132 | movel MEM_POSTINC(s_ptr),R(d2) | |
133 | addxl R(d2),R(d2) | |
134 | movel R(d2),MEM_POSTINC(res_ptr) | |
135 | ||
136 | dbf R(s_size),L(LLoop) | |
137 | addxl R(d0),R(d0) /* save cy in lsb */ | |
138 | subl #0x10000,R(s_size) | |
139 | bcs L(LLend) | |
140 | lsrl #1,R(d0) /* restore cy */ | |
141 | bra L(LLoop) | |
142 | ||
143 | L(LLend:) | |
144 | /* Restore used registers from stack frame. */ | |
145 | moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) | |
146 | rts | |
56d7f029 | 147 | END(__mpn_lshift) |