divider.h
1/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef _HARDWARE_DIVIDER_H
8#define _HARDWARE_DIVIDER_H
9
10#include "pico/types.h"
11
12typedef uint64_t divmod_result_t;
13
14static inline int __sign_of(int32_t v) {
15 return v > 0 ? 1 : (v < 0 ? -1 : 0);
16}
17
18// divides unsigned values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0
19static inline uint64_t hw_divider_divmod_u32(uint32_t a, uint32_t b) {
20 if (!b) return (((uint64_t)a)<<32u) | (uint32_t)(-1); // todo check this
21 return (((uint64_t)(a%b))<<32u) | (a/b);
22}
23
24// divides signed values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0
25static inline uint64_t hw_divider_divmod_s32(int32_t a, int32_t b) {
26 if (!b) return (((uint64_t)a)<<32u) | (uint32_t)(-__sign_of(a));
27 return (((uint64_t)(a%b))<<32u) | (uint32_t)(a/b);
28}
29
30extern __thread divmod_result_t hw_divider_result_threadlocal;
31
32static inline void hw_divider_divmod_s32_start(int32_t a, int32_t b) {
33 hw_divider_result_threadlocal = hw_divider_divmod_s32(a, b);
34}
35
36static inline void hw_divider_divmod_u32_start(uint32_t a, uint32_t b) {
37 hw_divider_result_threadlocal = hw_divider_divmod_u32(a, b);
38}
39
40static inline divmod_result_t hw_divider_result_wait() {
41 return hw_divider_result_threadlocal;
42}
43
44static inline uint64_t hw_divider_result_nowait() {
45 return hw_divider_result_threadlocal;
46}
47
48inline static uint32_t to_quotient_u32(unsigned long long int r) {
49 return (uint32_t) r;
50}
51
52inline static int32_t to_quotient_s32(unsigned long long int r) {
53 return (int32_t)(uint32_t)r;
54}
55
56inline static uint32_t to_remainder_u32(unsigned long long int r) {
57 return (uint32_t)(r >> 32u);
58}
59
60inline static int32_t to_remainder_s32(unsigned long long int r) {
61 return (int32_t)(r >> 32u);
62}
63
64static inline uint32_t hw_divider_u32_quotient_wait() {
66}
67
68static inline uint32_t hw_divider_u32_remainder_wait() {
70}
71
72static inline int32_t hw_divider_s32_quotient_wait() {
74}
75
76static inline int32_t hw_divider_s32_remainder_wait() {
78}
79
80static inline uint32_t hw_divider_u32_quotient(uint32_t a, uint32_t b) {
81 return b ? (a / b) : (uint32_t)(-1);
82}
83
84static inline uint32_t hw_divider_u32_remainder(uint32_t a, uint32_t b) {
85 return b ? (a % b) : a;
86}
87
88static inline int32_t hw_divider_s32_quotient(int32_t a, int32_t b) {
89 return b ? (a / b) : -__sign_of(a);
90}
91
92static inline int32_t hw_divider_s32_remainder(int32_t a, int32_t b) {
93 return b ? (a % b) : a;
94}
95
96static inline uint32_t hw_divider_u32_quotient_inlined(uint32_t a, uint32_t b) {
97 return hw_divider_u32_quotient(a,b);
98}
99
100static inline uint32_t hw_divider_u32_remainder_inlined(uint32_t a, uint32_t b) {
101 return hw_divider_u32_remainder(a,b);
102}
103
104static inline int32_t hw_divider_s32_quotient_inlined(int32_t a, int32_t b) {
105 return hw_divider_s32_quotient(a,b);
106}
107
108static inline int32_t hw_divider_s32_remainder_inlined(int32_t a, int32_t b) {
109 return hw_divider_s32_remainder(a,b);
110}
111
112typedef uint64_t hw_divider_state_t;
113
114static inline void hw_divider_save_state(hw_divider_state_t *dest) {
115 *dest = hw_divider_result_threadlocal;
116}
117
118static inline void hw_divider_restore_state(hw_divider_state_t *src) {
119 hw_divider_result_threadlocal = *src;
120}
121
122#endif // _HARDWARE_DIVIDER_H
divmod_result_t hw_divider_divmod_u32(uint32_t a, uint32_t b)
Do an unsigned HW divide and wait for result.
static uint32_t to_quotient_u32(divmod_result_t r)
Efficient extraction of unsigned quotient from 32p32 fixed point.
Definition: divider.h:204
static int32_t hw_divider_s32_quotient_inlined(int32_t a, int32_t b)
Do a hardware signed HW divide, wait for result, return quotient.
Definition: divider.h:351
static uint32_t hw_divider_u32_remainder_wait(void)
Return result of last asynchronous HW divide, unsigned remainder only.
Definition: divider.h:155
static void hw_divider_divmod_u32_start(uint32_t a, uint32_t b)
Start an unsigned asynchronous divide.
Definition: divider.h:69
static void hw_divider_divmod_s32_start(int32_t a, int32_t b)
Start a signed asynchronous divide.
Definition: divider.h:54
static uint32_t hw_divider_u32_remainder_inlined(uint32_t a, uint32_t b)
Do a hardware unsigned HW divide, wait for result, return remainder.
Definition: divider.h:334
static uint32_t hw_divider_u32_quotient_wait(void)
Return result of last asynchronous HW divide, unsigned quotient only.
Definition: divider.h:131
static divmod_result_t hw_divider_result_nowait(void)
Return result of HW divide, nowait.
Definition: divider.h:106
static int32_t to_quotient_s32(divmod_result_t r)
Efficient extraction of signed quotient from 32p32 fixed point.
Definition: divider.h:214
static int32_t to_remainder_s32(divmod_result_t r)
Efficient extraction of signed remainder from 32p32 fixed point.
Definition: divider.h:238
static int32_t hw_divider_s32_remainder_inlined(int32_t a, int32_t b)
Do a hardware signed HW divide, wait for result, return remainder.
Definition: divider.h:366
static uint32_t hw_divider_u32_quotient(uint32_t a, uint32_t b)
Do an unsigned HW divide, wait for result, return quotient.
Definition: divider.h:251
static uint32_t hw_divider_u32_remainder(uint32_t a, uint32_t b)
Do an unsigned HW divide, wait for result, return remainder.
Definition: divider.h:264
static int32_t hw_divider_s32_quotient_wait(void)
Return result of last asynchronous HW divide, signed quotient only.
Definition: divider.h:143
static divmod_result_t hw_divider_result_wait(void)
Return result of last asynchronous HW divide.
Definition: divider.h:119
static uint32_t hw_divider_u32_quotient_inlined(uint32_t a, uint32_t b)
Do a hardware unsigned HW divide, wait for result, return quotient.
Definition: divider.h:319
static int32_t hw_divider_s32_remainder_wait(void)
Return result of last asynchronous HW divide, signed remainder only.
Definition: divider.h:169
divmod_result_t hw_divider_divmod_s32(int32_t a, int32_t b)
Do a signed HW divide and wait for result.
static uint32_t to_remainder_u32(divmod_result_t r)
Efficient extraction of unsigned remainder from 32p32 fixed point.
Definition: divider.h:226
void hw_divider_save_state(hw_divider_state_t *dest)
Save the calling cores hardware divider state.
void hw_divider_restore_state(hw_divider_state_t *src)
Load a saved hardware divider state into the current core's hardware divider.
Definition: divider.h:374