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