@web-font-path: "roboto-debian.css";
Loading...
Searching...
No Matches
divider.h
Go to the documentation of this file.
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.h"
11#include "hardware/structs/sio.h"
12
39#ifdef __cplusplus
40extern "C" {
41#endif
42
43typedef uint64_t divmod_result_t;
44
54static inline void hw_divider_divmod_s32_start(int32_t a, int32_t b) {
55 check_hw_layout( sio_hw_t, div_sdividend, SIO_DIV_SDIVIDEND_OFFSET);
56 sio_hw->div_sdividend = (uint32_t)a;
57 sio_hw->div_sdivisor = (uint32_t)b;
58}
59
69static inline void hw_divider_divmod_u32_start(uint32_t a, uint32_t b) {
70 check_hw_layout(
71 sio_hw_t, div_udividend, SIO_DIV_UDIVIDEND_OFFSET);
72 sio_hw->div_udividend = a;
73 sio_hw->div_udivisor = b;
74}
75
81static inline void hw_divider_wait_ready(void) {
82 // this is #1 in lsr below
83 static_assert(SIO_DIV_CSR_READY_BITS == 1, "");
84
85 // we use one less register and instruction than gcc which uses a TST instruction
86
87 uint32_t tmp; // allow compiler to pick scratch register
88 pico_default_asm_volatile (
89 "hw_divider_result_loop_%=:"
90 "ldr %0, [%1, %2]\n\t"
91 "lsrs %0, %0, #1\n\t"
92 "bcc hw_divider_result_loop_%=\n\t"
93 : "=&l" (tmp)
94 : "l" (sio_hw), "I" (SIO_DIV_CSR_OFFSET)
95 :
96 );
97}
98
106static inline divmod_result_t hw_divider_result_nowait(void) {
107 // as ugly as this looks it is actually quite efficient
108 divmod_result_t rc = ((divmod_result_t) sio_hw->div_remainder) << 32u;
109 rc |= sio_hw->div_quotient;
110 return rc;
111}
112
120static inline divmod_result_t hw_divider_result_wait(void) {
123}
124
132static inline uint32_t hw_divider_u32_quotient_wait(void) {
134 return sio_hw->div_quotient;
135}
136
144static inline int32_t hw_divider_s32_quotient_wait(void) {
146 return (int32_t)sio_hw->div_quotient;
147}
148
156static inline uint32_t hw_divider_u32_remainder_wait(void) {
158 uint32_t rc = sio_hw->div_remainder;
159 sio_hw->div_quotient; // must read quotient to cooperate with other SDK code
160 return rc;
161}
162
170static inline int32_t hw_divider_s32_remainder_wait(void) {
172 int32_t rc = (int32_t)sio_hw->div_remainder;
173 sio_hw->div_quotient; // must read quotient to cooperate with other SDK code
174 return rc;
175}
176
186divmod_result_t hw_divider_divmod_s32(int32_t a, int32_t b);
187
197divmod_result_t hw_divider_divmod_u32(uint32_t a, uint32_t b);
198
205inline static uint32_t to_quotient_u32(divmod_result_t r) {
206 return (uint32_t) r;
207}
208
215inline static int32_t to_quotient_s32(divmod_result_t r) {
216 return (int32_t)(uint32_t)r;
217}
218
227inline static uint32_t to_remainder_u32(divmod_result_t r) {
228 return (uint32_t)(r >> 32u);
229}
230
239inline static int32_t to_remainder_s32(divmod_result_t r) {
240 return (int32_t)(r >> 32u);
241}
242
252static inline uint32_t hw_divider_u32_quotient(uint32_t a, uint32_t b) {
254}
255
265static inline uint32_t hw_divider_u32_remainder(uint32_t a, uint32_t b) {
267}
268
278static inline int32_t hw_divider_quotient_s32(int32_t a, int32_t b) {
280}
281
291static inline int32_t hw_divider_remainder_s32(int32_t a, int32_t b) {
293}
294
298static inline void hw_divider_pause(void) {
299 pico_default_asm_volatile(
300 "b _1_%=\n"
301 "_1_%=:\n"
302 "b _2_%=\n"
303 "_2_%=:\n"
304 "b _3_%=\n"
305 "_3_%=:\n"
306 "b _4_%=\n"
307 "_4_%=:\n"
308 :::);
309}
310
320static inline uint32_t hw_divider_u32_quotient_inlined(uint32_t a, uint32_t b) {
323 return sio_hw->div_quotient;
324}
325
335static inline uint32_t hw_divider_u32_remainder_inlined(uint32_t a, uint32_t b) {
338 uint32_t rc = sio_hw->div_remainder;
339 sio_hw->div_quotient; // must read quotient to cooperate with other SDK code
340 return rc;
341}
342
352static inline int32_t hw_divider_s32_quotient_inlined(int32_t a, int32_t b) {
355 return (int32_t)sio_hw->div_quotient;
356}
357
367static inline int32_t hw_divider_s32_remainder_inlined(int32_t a, int32_t b) {
370 int32_t rc = (int32_t)sio_hw->div_remainder;
371 sio_hw->div_quotient; // must read quotient to cooperate with other SDK code
372 return rc;
373}
374
375typedef struct {
376 uint32_t values[4];
378
389
399
400#ifdef __cplusplus
401}
402#endif
403
404#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 int32_t hw_divider_quotient_s32(int32_t a, int32_t b)
Do a signed HW divide, wait for result, return quotient.
Definition divider.h:278
static uint32_t to_quotient_u32(divmod_result_t r)
Efficient extraction of unsigned quotient from 32p32 fixed point.
Definition divider.h:205
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:352
static uint32_t hw_divider_u32_remainder_wait(void)
Return result of last asynchronous HW divide, unsigned remainder only.
Definition divider.h:156
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 int32_t hw_divider_remainder_s32(int32_t a, int32_t b)
Do a signed HW divide, wait for result, return remainder.
Definition divider.h:291
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:335
static uint32_t hw_divider_u32_quotient_wait(void)
Return result of last asynchronous HW divide, unsigned quotient only.
Definition divider.h:132
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:215
static int32_t to_remainder_s32(divmod_result_t r)
Efficient extraction of signed remainder from 32p32 fixed point.
Definition divider.h:239
static void hw_divider_wait_ready(void)
Wait for a divide to complete.
Definition divider.h:81
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:367
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:252
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:265
static int32_t hw_divider_s32_quotient_wait(void)
Return result of last asynchronous HW divide, signed quotient only.
Definition divider.h:144
static divmod_result_t hw_divider_result_wait(void)
Return result of last asynchronous HW divide.
Definition divider.h:120
static void hw_divider_pause(void)
Pause for exact amount of time needed for a asynchronous divide to complete.
Definition divider.h:298
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:320
static int32_t hw_divider_s32_remainder_wait(void)
Return result of last asynchronous HW divide, signed remainder only.
Definition divider.h:170
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:227
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:375
Definition sio.h:24