]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/or1k/lib1funcs.S
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / or1k / lib1funcs.S
1 /* Copyright (C) 2018-2023 Free Software Foundation, Inc.
2
3 This file is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 3, or (at your option) any
6 later version.
7
8 This file is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 Under Section 7 of GPL version 3, you are granted additional
14 permissions described in the GCC Runtime Library Exception, version
15 3.1, as published by the Free Software Foundation.
16
17 You should have received a copy of the GNU General Public License and
18 a copy of the GCC Runtime Library Exception along with this program;
19 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
20 <http://www.gnu.org/licenses/>. */
21
22
23 #ifdef L__mulsi3
24 .balign 4
25 .globl __mulsi3
26 .type __mulsi3, @function
27 __mulsi3:
28 l.movhi r11, 0 /* initial r */
29
30 /* Given R = X * Y ... */
31 1: l.sfeq r4, r0 /* while (y != 0) */
32 l.bf 2f
33 l.andi r5, r4, 1 /* if (y & 1) ... */
34 l.add r12, r11, r3
35 l.sfne r5, r0
36 #if defined(__or1k_cmov__)
37 l.cmov r11, r12, r11 /* ... r += x. */
38 l.srli r4, r4, 1 /* y >>= 1 */
39 #else
40 l.bnf 3f
41 l.srli r4, r4, 1 /* y >>= 1 */
42 l.ori r11, r12, 0
43 3:
44 #endif
45 l.j 1b
46 l.add r3, r3, r3 /* x <<= 1 */
47
48 2: l.jr r9
49 l.nop
50
51 .size __mulsi3, . - __mulsi3
52 #endif
53
54 #if defined(L__udivsi3) || defined(L__umodsi3) \
55 || defined(L__divsi3) || defined(L__modsi3)
56 .global __udivmodsi3_internal
57 .hidden __udivmodsi3_internal
58 .type __udivmodsi3_internal, @function
59 #endif
60
61 #ifdef L__udivsi3
62 .balign 4
63 .global __udivsi3
64 .type __udivsi3, @function
65 __udivsi3:
66 __udivmodsi3_internal:
67 /* Note that the other division routines assume that r13
68 is not clobbered by this routine, and use that as to
69 save a return address without creating a stack frame. */
70
71 l.sfeq r4, r0 /* division by zero; return 0. */
72 l.ori r11, r0, 0 /* initial quotient */
73 l.bf 9f
74 l.ori r12, r3, 0 /* initial remainder */
75
76 /* Given X/Y, shift Y left until Y >= X. */
77 l.ori r6, r0, 1 /* mask = 1 */
78 1: l.sflts r4, r0 /* y has msb set */
79 l.bf 2f
80 l.sfltu r4, r12 /* y < x */
81 l.add r4, r4, r4 /* y <<= 1 */
82 l.bf 1b
83 l.add r6, r6, r6 /* mask <<= 1 */
84
85 /* Shift Y back to the right again, subtracting from X. */
86 2: l.add r7, r11, r6 /* tmp1 = quot + mask */
87 3: l.srli r6, r6, 1 /* mask >>= 1 */
88 l.sub r8, r12, r4 /* tmp2 = x - y */
89 l.sfleu r4, r12 /* y <= x */
90 l.srli r4, r4, 1 /* y >>= 1 */
91 #if defined(__or1k_cmov__)
92 l.cmov r11, r7, r11 /* if (y <= x) quot = tmp1 */
93 l.cmov r12, r8, r12 /* if (y <= x) x = tmp2 */
94 #else
95 l.bnf 4f
96 l.nop
97 l.ori r11, r7, 0
98 l.ori r12, r8, 0
99 4:
100 #endif
101 l.sfne r6, r0 /* loop until mask == 0 */
102 l.bf 3b
103 l.add r7, r11, r6 /* delay fill from loop start */
104
105 9: l.jr r9
106 l.nop
107
108 .size __udivsi3, . - __udivsi3
109 .size __udivmodsi3_internal, . - __udivmodsi3_internal
110 #endif
111
112 #ifdef L__umodsi3
113 .balign 4
114 .global __umodsi3
115 .type __umodsi3, @function
116 .cfi_startproc
117 __umodsi3:
118 /* Know that __udivmodsi3_internal does not clobber r13. */
119 l.ori r13, r9, 0
120 .cfi_register 9, 13
121 l.jal __udivmodsi3_internal
122 l.nop
123 l.jr r13 /* return to saved lr */
124 l.ori r11, r12, 0 /* move remainder to rv */
125
126 .cfi_endproc
127 .size __umodsi3, . - __umodsi3
128 #endif
129
130 /* For signed division we do:
131
132 -x / y = x / -y = -(x / y)
133 -x % y = -(x % y)
134 x % -y = x % y
135
136 which has the property that (x/y)*y + (x%y) = x. */
137
138 #ifdef L__divsi3
139 .balign 4
140 .global __divsi3
141 .type __divsi3, @function
142 .cfi_startproc
143 __divsi3:
144 l.xor r6, r3, r4 /* need result negate? */
145
146 l.sflts r3, r0 /* abs(x) */
147 #if defined(__or1k_cmov__)
148 l.sub r5, r0, r3
149 l.cmov r3, r5, r3
150 #else
151 l.bnf 1f
152 l.sub r5, r0, r3
153 l.ori r3, r5, 0
154 1:
155 #endif
156 l.sflts r4, r0 /* abs(y) */
157 #if defined(__or1k_cmov__)
158 l.sub r5, r0, r4
159 l.cmov r4, r5, r4
160 #else
161 l.bnf 2f
162 l.sub r5, r0, r4
163 l.ori r4, r5, 0
164 2:
165 #endif
166
167 /* If the result will not require sign flip, tail call. */
168 l.sflts r6, r0
169 l.bnf __udivmodsi3_internal
170 l.ori r13, r9, 0 /* save lr */
171
172 /* Otherwise, know that __udivmodsi3_internal does not clobber r13.
173 Perform a normal call, then negate and return via saved lr. */
174 .cfi_register 9, 13
175 l.jal __udivmodsi3_internal
176 l.nop
177 l.jr r13
178 l.sub r11, r0, r11
179
180 .cfi_endproc
181 .size __divsi3, . - __divsi3
182 #endif
183
184 #ifdef L__modsi3
185 .balign 4
186 .global __modsi3
187 .type __modsi3, @function
188 .cfi_startproc
189 __modsi3:
190 l.sflts r4, r0 /* abs(y) */
191 #if defined(__or1k_cmov__)
192 l.sub r5, r0, r4
193 l.cmov r4, r5, r4
194 #else
195 l.bnf 2f
196 l.sub r5, r0, r4
197 l.ori r4, r5, 0
198 2:
199 #endif
200
201 l.sflts r3, r0 /* x negative? */
202 l.bf 1f
203 l.ori r13, r9, 0 /* save lr */
204
205 /* Know that __udivmodsi3_internal does not clobber r13. */
206 .cfi_register 9, 13
207
208 /* X positive; no negate of the result required. */
209 l.jal __udivmodsi3_internal
210 l.nop
211 l.jr r13 /* return to saved lr */
212 l.ori r11, r12, 0 /* move remainder to rv */
213
214 /* X negative; negate both X and the result. */
215 1: l.jal __udivmodsi3_internal
216 l.sub r3, r0, r3
217 l.jr r13 /* return to saved lr */
218 l.sub r11, r0, r12 /* negate remainder to rv */
219
220 .cfi_endproc
221 .size __modsi3, .- __modsi3
222 #endif