blob: df0e275171e849bcdc25158a069e0b10a56c2608 [file] [log] [blame]
Austin Schuh208337d2022-01-01 14:29:11 -08001/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include "pico/divider.h"
8
9// These functions save/restore divider state, so are safe to call from interrupts
10int32_t div_s32s32(int32_t a, int32_t b) {
11 return hw_divider_s32_quotient(a, b);
12}
13
14divmod_result_t divmod_s32s32(int32_t a, int32_t b) {
15 return hw_divider_divmod_s32(a, b);
16}
17
18uint32_t div_u32u32(uint32_t a, uint32_t b) {
19 return hw_divider_u32_quotient(a, b);
20}
21
22divmod_result_t divmod_u32u32(uint32_t a, uint32_t b) {
23 return hw_divider_divmod_u32(a, b);
24}
25
26static inline int __sign_of_64(int32_t v) {
27 return v > 0 ? 1 : (v < 0 ? -1 : 0);
28}
29
30typedef struct {
31 uint64_t quotient;
32 uint64_t remainder;
33} qr_u64;
34
35typedef struct {
36 int64_t quotient;
37 int64_t remainder;
38} qr_s64;
39
40// divides unsigned values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0
41static inline qr_u64 udiv64(uint64_t a, uint64_t b) {
42 qr_u64 rc;
43 if (!b) {
44 rc.quotient = (uint64_t)-1; // todo check this
45 rc.remainder = a;
46 } else {
47 rc.quotient = a/b;
48 rc.remainder = a%b;
49 }
50 return rc;
51}
52
53// divides signed values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0
54static inline qr_s64 div64(int64_t a, int64_t b) {
55 qr_s64 rc;
56 if (!b) {
57 rc.quotient = (uint64_t)(-__sign_of_64(a));
58 rc.remainder = a;
59 } else {
60 rc.quotient = a/b;
61 rc.remainder = a%b;
62 }
63 return rc;
64}
65
66int64_t div_s64s64(int64_t a, int64_t b) {
67 qr_s64 qr = div64(a, b);
68 return qr.quotient;
69}
70
71int64_t divmod_s64s64_rem(int64_t a, int64_t b, int64_t *rem) {
72 qr_s64 qr = div64(a, b);
73 *rem = qr.remainder;
74 return qr.quotient;
75}
76
77int64_t divmod_s64s64(int64_t a, int64_t b) {
78 qr_s64 qr = div64(a, b);
79 return qr.quotient;
80}
81
82uint64_t div_u64u64(uint64_t a, uint64_t b) {
83 qr_u64 qr = udiv64(a, b);
84 return qr.quotient;
85}
86
87uint64_t divmod_u64u64_rem(uint64_t a, uint64_t b, uint64_t *rem) {
88 qr_u64 qr = udiv64(a, b);
89 *rem = qr.remainder;
90 return qr.quotient;
91}
92
93uint64_t divmod_u64u64(uint64_t a, uint64_t b) {
94 qr_u64 qr = udiv64(a, b);
95 return qr.quotient;
96}
97
98// these functions are slightly faster, but unsafe the divider state, so are not generally safe to be called from interrupts
99
100int32_t div_s32s32_unsafe(int32_t a, int32_t b) { return div_s32s32(a,b); }
101int32_t divmod_s32s32_rem_unsafe(int32_t a, int32_t b, int32_t *rem) { return divmod_s32s32_rem(a, b, rem); }
102int64_t divmod_s32s32_unsafe(int32_t a, int32_t b) { return divmod_s32s32(a, b); }
103
104uint32_t div_u32u32_unsafe(uint32_t a, uint32_t b) { return div_u32u32(a, b); }
105uint32_t divmod_u32u32_rem_unsafe(uint32_t a, uint32_t b, uint32_t *rem) { return divmod_u32u32_rem(a, b, rem); }
106uint64_t divmod_u32u32_unsafe(uint32_t a, uint32_t b) { return divmod_u32u32(a, b); }
107
108int64_t div_s64s64_unsafe(int64_t a, int64_t b) { return div_s64s64(a, b); }
109int64_t divmod_s64s64_rem_unsafe(int64_t a, int64_t b, int64_t *rem) { return divmod_s64s64_rem(a, b, rem); }
110int64_t divmod_s64s64_unsafe(int64_t a, int64_t b) { return divmod_s64s64(a, b); }
111
112uint64_t div_u64u64_unsafe(uint64_t a, uint64_t b) { return div_u64u64(a, b); }
113uint64_t divmod_u64u64_rem_unsafe(uint64_t a, uint64_t b, uint64_t *rem) { return divmod_u64u64_rem(a, b, rem); }
114uint64_t divmod_u64u64_unsafe(uint64_t a, uint64_t b) { return divmod_u64u64(a, b); }