blob: f202abfe434824f41098f31f5ac83030bdce0464 [file] [log] [blame]
Austin Schuhbb1338c2024-06-15 19:31:16 -07001dnl mc68020 mpn_lshift -- mpn left shift.
2
3dnl Copyright 1996, 1999-2003 Free Software Foundation, Inc.
4
5dnl This file is part of the GNU MP Library.
6dnl
7dnl The GNU MP Library is free software; you can redistribute it and/or modify
8dnl it under the terms of either:
9dnl
10dnl * the GNU Lesser General Public License as published by the Free
11dnl Software Foundation; either version 3 of the License, or (at your
12dnl option) any later version.
13dnl
14dnl or
15dnl
16dnl * the GNU General Public License as published by the Free Software
17dnl Foundation; either version 2 of the License, or (at your option) any
18dnl later version.
19dnl
20dnl or both in parallel, as here.
21dnl
22dnl The GNU MP Library is distributed in the hope that it will be useful, but
23dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25dnl for more details.
26dnl
27dnl You should have received copies of the GNU General Public License and the
28dnl GNU Lesser General Public License along with the GNU MP Library. If not,
29dnl see https://www.gnu.org/licenses/.
30
31include(`../config.m4')
32
33
34C cycles/limb
35C shift==1 shift>1
36C 68040: 5 12
37
38
39C mp_limb_t mpn_lshift (mp_ptr res_ptr, mp_srcptr s_ptr, mp_size_t s_size,
40C unsigned cnt);
41C
42C The "cnt" parameter is either 16 bits or 32 bits depending on
43C SIZEOF_UNSIGNED (see ABI notes in mpn/m68k/README). The value is of
44C course only 1 to 31. When loaded as 16 bits there's garbage in the upper
45C half, hence the use of cmpw. The shift instructions take the their count
46C modulo 64, so the upper part doesn't matter to them either.
47C
48
49C INPUT PARAMETERS
50C res_ptr (sp + 4)
51C s_ptr (sp + 8)
52C s_size (sp + 12)
53C cnt (sp + 16)
54
55define(res_ptr, `a1')
56define(s_ptr, `a0')
57define(s_size, `d6')
58define(cnt, `d4')
59
60ifdef(`SIZEOF_UNSIGNED',,
61`m4_error(`SIZEOF_UNSIGNED not defined, should be in config.m4
62')')
63
64PROLOGUE(mpn_lshift)
65C Save used registers on the stack.
66 moveml d2-d6/a2, M(-,sp)
67
68C Copy the arguments to registers.
69 movel M(sp,28), res_ptr
70 movel M(sp,32), s_ptr
71 movel M(sp,36), s_size
72ifelse(SIZEOF_UNSIGNED,2,
73` movew M(sp,40), cnt',
74` movel M(sp,40), cnt')
75
76 moveql #1, d5
77 cmpw d5, cnt
78 bne L(Lnormal)
79 cmpl s_ptr, res_ptr
80 bls L(Lspecial) C jump if s_ptr >= res_ptr
81
82ifelse(scale_available_p,1,`
83 lea M(s_ptr,s_size,l,4), a2
84',`
85 movel s_size, d0
86 asll #2, d0
87 lea M(s_ptr,d0,l), a2
88')
89 cmpl res_ptr, a2
90 bls L(Lspecial) C jump if res_ptr >= s_ptr + s_size
91
92L(Lnormal):
93 moveql #32, d5
94 subl cnt, d5
95
96ifelse(scale_available_p,1,`
97 lea M(s_ptr,s_size,l,4), s_ptr
98 lea M(res_ptr,s_size,l,4), res_ptr
99',`
100 movel s_size, d0
101 asll #2, d0
102 addl d0, s_ptr
103 addl d0, res_ptr
104')
105 movel M(-,s_ptr), d2
106 movel d2, d0
107 lsrl d5, d0 C compute carry limb
108
109 lsll cnt, d2
110 movel d2, d1
111 subql #1, s_size
112 beq L(Lend)
113 lsrl #1, s_size
114 bcs L(L1)
115 subql #1, s_size
116
117L(Loop):
118 movel M(-,s_ptr), d2
119 movel d2, d3
120 lsrl d5, d3
121 orl d3, d1
122 movel d1, M(-,res_ptr)
123 lsll cnt, d2
124L(L1):
125 movel M(-,s_ptr), d1
126 movel d1, d3
127 lsrl d5, d3
128 orl d3, d2
129 movel d2, M(-,res_ptr)
130 lsll cnt, d1
131
132 dbf s_size, L(Loop)
133 subl #0x10000, s_size
134 bcc L(Loop)
135
136L(Lend):
137 movel d1, M(-,res_ptr) C store least significant limb
138
139C Restore used registers from stack frame.
140 moveml M(sp,+), d2-d6/a2
141 rts
142
143C We loop from least significant end of the arrays, which is only
144C permissable if the source and destination don't overlap, since the
145C function is documented to work for overlapping source and destination.
146
147L(Lspecial):
148 clrl d0 C initialize carry
149 eorw #1, s_size
150 lsrl #1, s_size
151 bcc L(LL1)
152 subql #1, s_size
153
154L(LLoop):
155 movel M(s_ptr,+), d2
156 addxl d2, d2
157 movel d2, M(res_ptr,+)
158L(LL1):
159 movel M(s_ptr,+), d2
160 addxl d2, d2
161 movel d2, M(res_ptr,+)
162
163 dbf s_size, L(LLoop)
164 addxl d0, d0 C save cy in lsb
165 subl #0x10000, s_size
166 bcs L(LLend)
167 lsrl #1, d0 C restore cy
168 bra L(LLoop)
169
170L(LLend):
171C Restore used registers from stack frame.
172 moveml M(sp,+), d2-d6/a2
173 rts
174
175EPILOGUE(mpn_lshift)