1 /*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #ifndef _PICO_DIVIDER_H
8 #define _PICO_DIVIDER_H
9
10 #include "pico.h"
11 #include "hardware/divider.h"
12
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16
17 /**
18 * \defgroup pico_divider pico_divider
19 * \brief Optimized 32 and 64 bit division functions accelerated by the RP2040 hardware divider
20 *
21 * Additionally provides integration with the C `/` and `%` operators
22 */
23
24 /** \file pico/divider.h
25 * \brief High level APIs including combined quotient and remainder functions for 32 and 64 bit accelerated by the hardware divider
26 * \ingroup pico_divider
27 *
28 * These functions all call __aeabi_idiv0 or __aebi_ldiv0 on division by zero
29 * passing the largest applicably signed value
30 *
31 * Functions with unsafe in their name do not save/restore divider state, so are unsafe to call from interrupts. Unsafe functions are slightly faster.
32 */
33
34 /**
35 * \brief Integer divide of two signed 32-bit values
36 * \ingroup pico_divider
37 *
38 * \param a Dividend
39 * \param b Divisor
40 * \return quotient
41 */
42 int32_t div_s32s32(int32_t a, int32_t b);
43
44 /**
45 * \brief Integer divide of two signed 32-bit values, with remainder
46 * \ingroup pico_divider
47 *
48 * \param a Dividend
49 * \param b Divisor
50 * \param [out] rem The remainder of dividend/divisor
51 * \return Quotient result of dividend/divisor
52 */
divmod_s32s32_rem(int32_t a,int32_t b,int32_t * rem)53 static inline int32_t divmod_s32s32_rem(int32_t a, int32_t b, int32_t *rem) {
54 divmod_result_t r = hw_divider_divmod_s32(a, b);
55 *rem = to_remainder_s32(r);
56 return to_quotient_s32(r);
57 }
58
59 /**
60 * \brief Integer divide of two signed 32-bit values
61 * \ingroup pico_divider
62 *
63 * \param a Dividend
64 * \param b Divisor
65 * \return quotient in low word/r0, remainder in high word/r1
66 */
67 divmod_result_t divmod_s32s32(int32_t a, int32_t b);
68
69 /**
70 * \brief Integer divide of two unsigned 32-bit values
71 * \ingroup pico_divider
72 *
73 * \param a Dividend
74 * \param b Divisor
75 * \return Quotient
76 */
77 uint32_t div_u32u32(uint32_t a, uint32_t b);
78
79 /**
80 * \brief Integer divide of two unsigned 32-bit values, with remainder
81 * \ingroup pico_divider
82 *
83 * \param a Dividend
84 * \param b Divisor
85 * \param [out] rem The remainder of dividend/divisor
86 * \return Quotient result of dividend/divisor
87 */
divmod_u32u32_rem(uint32_t a,uint32_t b,uint32_t * rem)88 static inline uint32_t divmod_u32u32_rem(uint32_t a, uint32_t b, uint32_t *rem) {
89 divmod_result_t r = hw_divider_divmod_u32(a, b);
90 *rem = to_remainder_u32(r);
91 return to_quotient_u32(r);
92 }
93
94 /**
95 * \brief Integer divide of two unsigned 32-bit values
96 * \ingroup pico_divider
97 *
98 * \param a Dividend
99 * \param b Divisor
100 * \return quotient in low word/r0, remainder in high word/r1
101 */
102 divmod_result_t divmod_u32u32(uint32_t a, uint32_t b);
103
104 /**
105 * \brief Integer divide of two signed 64-bit values
106 * \ingroup pico_divider
107 *
108 * \param a Dividend
109 * \param b Divisor
110 * \return Quotient
111 */
112 int64_t div_s64s64(int64_t a, int64_t b);
113
114 /**
115 * \brief Integer divide of two signed 64-bit values, with remainder
116 * \ingroup pico_divider
117 *
118 * \param a Dividend
119 * \param b Divisor
120 * \param [out] rem The remainder of dividend/divisor
121 * \return Quotient result of dividend/divisor
122 */
123 int64_t divmod_s64s64_rem(int64_t a, int64_t b, int64_t *rem);
124
125 /**
126 * \brief Integer divide of two signed 64-bit values
127 * \ingroup pico_divider
128 *
129 * \param a Dividend
130 * \param b Divisor
131 * \return quotient in result (r0,r1), remainder in regs (r2, r3)
132 */
133 int64_t divmod_s64s64(int64_t a, int64_t b);
134
135 /**
136 * \brief Integer divide of two unsigned 64-bit values
137 * \ingroup pico_divider
138 *
139 * \param a Dividend
140 * \param b Divisor
141 * \return Quotient
142 */
143 uint64_t div_u64u64(uint64_t a, uint64_t b);
144
145 /**
146 * \brief Integer divide of two unsigned 64-bit values, with remainder
147 * \ingroup pico_divider
148 *
149 * \param a Dividend
150 * \param b Divisor
151 * \param [out] rem The remainder of dividend/divisor
152 * \return Quotient result of dividend/divisor
153 */
154 uint64_t divmod_u64u64_rem(uint64_t a, uint64_t b, uint64_t *rem);
155
156
157 /**
158 * \brief Integer divide of two signed 64-bit values
159 * \ingroup pico_divider
160 *
161 * \param a Dividend
162 * \param b Divisor
163 * \return quotient in result (r0,r1), remainder in regs (r2, r3)
164 */
165 uint64_t divmod_u64u64(uint64_t a, uint64_t b);
166
167 // -----------------------------------------------------------------------
168 // these "unsafe" functions are slightly faster, but do not save the divider state,
169 // so are not generally safe to be called from interrupts
170 // -----------------------------------------------------------------------
171
172 /**
173 * \brief Unsafe integer divide of two signed 32-bit values
174 * \ingroup pico_divider
175 *
176 * \param a Dividend
177 * \param b Divisor
178 * \return quotient
179 *
180 * Do not use in interrupts
181 */
182 int32_t div_s32s32_unsafe(int32_t a, int32_t b);
183
184 /**
185 * \brief Unsafe integer divide of two signed 32-bit values, with remainder
186 * \ingroup pico_divider
187 *
188 * \param a Dividend
189 * \param b Divisor
190 * \param [out] rem The remainder of dividend/divisor
191 * \return Quotient result of dividend/divisor
192 *
193 * Do not use in interrupts
194 */
195 int32_t divmod_s32s32_rem_unsafe(int32_t a, int32_t b, int32_t *rem);
196
197 /**
198 * \brief Unsafe integer divide of two unsigned 32-bit values
199 * \ingroup pico_divider
200 *
201 * \param a Dividend
202 * \param b Divisor
203 * \return quotient in low word/r0, remainder in high word/r1
204 *
205 * Do not use in interrupts
206 */
207 divmod_result_t divmod_s32s32_unsafe(int32_t a, int32_t b);
208
209 /**
210 * \brief Unsafe integer divide of two unsigned 32-bit values
211 * \ingroup pico_divider
212 *
213 * \param a Dividend
214 * \param b Divisor
215 * \return Quotient
216 *
217 * Do not use in interrupts
218 */
219 uint32_t div_u32u32_unsafe(uint32_t a, uint32_t b);
220
221 /**
222 * \brief Unsafe integer divide of two unsigned 32-bit values, with remainder
223 * \ingroup pico_divider
224 *
225 * \param a Dividend
226 * \param b Divisor
227 * \param [out] rem The remainder of dividend/divisor
228 * \return Quotient result of dividend/divisor
229 *
230 * Do not use in interrupts
231 */
232 uint32_t divmod_u32u32_rem_unsafe(uint32_t a, uint32_t b, uint32_t *rem);
233
234 /**
235 * \brief Unsafe integer divide of two unsigned 32-bit values
236 * \ingroup pico_divider
237 *
238 * \param a Dividend
239 * \param b Divisor
240 * \return quotient in low word/r0, remainder in high word/r1
241 *
242 * Do not use in interrupts
243 */
244 divmod_result_t divmod_u32u32_unsafe(uint32_t a, uint32_t b);
245
246 /**
247 * \brief Unsafe integer divide of two signed 64-bit values
248 * \ingroup pico_divider
249 *
250 * \param a Dividend
251 * \param b Divisor
252 * \return Quotient
253 *
254 * Do not use in interrupts
255 */
256 int64_t div_s64s64_unsafe(int64_t a, int64_t b);
257
258 /**
259 * \brief Unsafe integer divide of two signed 64-bit values, with remainder
260 * \ingroup pico_divider
261 *
262 * \param a Dividend
263 * \param b Divisor
264 * \param [out] rem The remainder of dividend/divisor
265 * \return Quotient result of dividend/divisor
266 *
267 * Do not use in interrupts
268 */
269 int64_t divmod_s64s64_rem_unsafe(int64_t a, int64_t b, int64_t *rem);
270
271 /**
272 * \brief Unsafe integer divide of two signed 64-bit values
273 * \ingroup pico_divider
274 *
275 * \param a Dividend
276 * \param b Divisor
277 * \return quotient in result (r0,r1), remainder in regs (r2, r3)
278 *
279 * Do not use in interrupts
280 */
281 int64_t divmod_s64s64_unsafe(int64_t a, int64_t b);
282
283 /**
284 * \brief Unsafe integer divide of two unsigned 64-bit values
285 * \ingroup pico_divider
286 *
287 * \param a Dividend
288 * \param b Divisor
289 * \return Quotient
290 *
291 * Do not use in interrupts
292 */
293 uint64_t div_u64u64_unsafe(uint64_t a, uint64_t b);
294
295 /**
296 * \brief Unsafe integer divide of two unsigned 64-bit values, with remainder
297 * \ingroup pico_divider
298 *
299 * \param a Dividend
300 * \param b Divisor
301 * \param [out] rem The remainder of dividend/divisor
302 * \return Quotient result of dividend/divisor
303 *
304 * Do not use in interrupts
305 */
306 uint64_t divmod_u64u64_rem_unsafe(uint64_t a, uint64_t b, uint64_t *rem);
307
308 /**
309 * \brief Unsafe integer divide of two signed 64-bit values
310 * \ingroup pico_divider
311 *
312 * \param a Dividend
313 * \param b Divisor
314 * \return quotient in result (r0,r1), remainder in regs (r2, r3)
315 *
316 * Do not use in interrupts
317 */
318 uint64_t divmod_u64u64_unsafe(uint64_t a, uint64_t b);
319
320 #ifdef __cplusplus
321 }
322 #endif
323 #endif
324