Initial Release
This commit is contained in:
1
src/host/hardware_divider/CMakeLists.txt
Normal file
1
src/host/hardware_divider/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
||||
pico_simple_hardware_target(divider)
|
9
src/host/hardware_divider/divider.c
Normal file
9
src/host/hardware_divider/divider.c
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "hardware/divider.h"
|
||||
|
||||
__thread uint64_t hw_divider_result_threadlocal;
|
122
src/host/hardware_divider/include/hardware/divider.h
Normal file
122
src/host/hardware_divider/include/hardware/divider.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef _HARDWARE_DIVIDER_H
|
||||
#define _HARDWARE_DIVIDER_H
|
||||
|
||||
#include "pico/types.h"
|
||||
|
||||
typedef uint64_t divmod_result_t;
|
||||
|
||||
static inline int __sign_of(int32_t v) {
|
||||
return v > 0 ? 1 : (v < 0 ? -1 : 0);
|
||||
}
|
||||
|
||||
// divides unsigned values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0
|
||||
static inline uint64_t hw_divider_divmod_u32(uint32_t a, uint32_t b) {
|
||||
if (!b) return (((uint64_t)a)<<32u) | (uint32_t)(-1); // todo check this
|
||||
return (((uint64_t)(a%b))<<32u) | (a/b);
|
||||
}
|
||||
|
||||
// divides signed values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0
|
||||
static inline uint64_t hw_divider_divmod_s32(int32_t a, int32_t b) {
|
||||
if (!b) return (((uint64_t)a)<<32u) | (uint32_t)(-__sign_of(a));
|
||||
return (((uint64_t)(a%b))<<32u) | (uint32_t)(a/b);
|
||||
}
|
||||
|
||||
extern __thread divmod_result_t hw_divider_result_threadlocal;
|
||||
|
||||
static inline void hw_divider_divmod_s32_start(int32_t a, int32_t b) {
|
||||
hw_divider_result_threadlocal = hw_divider_divmod_s32(a, b);
|
||||
}
|
||||
|
||||
static inline void hw_divider_divmod_u32_start(uint32_t a, uint32_t b) {
|
||||
hw_divider_result_threadlocal = hw_divider_divmod_u32(a, b);
|
||||
}
|
||||
|
||||
static inline divmod_result_t hw_divider_result_wait() {
|
||||
return hw_divider_result_threadlocal;
|
||||
}
|
||||
|
||||
static inline uint64_t hw_divider_result_nowait() {
|
||||
return hw_divider_result_threadlocal;
|
||||
}
|
||||
|
||||
inline static uint32_t to_quotient_u32(unsigned long long int r) {
|
||||
return (uint32_t) r;
|
||||
}
|
||||
|
||||
inline static int32_t to_quotient_s32(unsigned long long int r) {
|
||||
return (int32_t)(uint32_t)r;
|
||||
}
|
||||
|
||||
inline static uint32_t to_remainder_u32(unsigned long long int r) {
|
||||
return (uint32_t)(r >> 32u);
|
||||
}
|
||||
|
||||
inline static int32_t to_remainder_s32(unsigned long long int r) {
|
||||
return (int32_t)(r >> 32u);
|
||||
}
|
||||
|
||||
static inline uint32_t hw_divider_u32_quotient_wait() {
|
||||
return to_quotient_u32(hw_divider_result_wait());
|
||||
}
|
||||
|
||||
static inline uint32_t hw_divider_u32_remainder_wait() {
|
||||
return to_remainder_u32(hw_divider_result_wait());
|
||||
}
|
||||
|
||||
static inline int32_t hw_divider_s32_quotient_wait() {
|
||||
return to_quotient_s32(hw_divider_result_wait());
|
||||
}
|
||||
|
||||
static inline int32_t hw_divider_s32_remainder_wait() {
|
||||
return to_remainder_s32(hw_divider_result_wait());
|
||||
}
|
||||
|
||||
static inline uint32_t hw_divider_u32_quotient(uint32_t a, uint32_t b) {
|
||||
return b ? (a / b) : -1;
|
||||
}
|
||||
|
||||
static inline uint32_t hw_divider_u32_remainder(uint32_t a, uint32_t b) {
|
||||
return b ? (a % b) : a;
|
||||
}
|
||||
|
||||
static inline int32_t hw_divider_s32_quotient(int32_t a, int32_t b) {
|
||||
return b ? (a / b) : -__sign_of(a);
|
||||
}
|
||||
|
||||
static inline int32_t hw_divider_s32_remainder(int32_t a, int32_t b) {
|
||||
return b ? (a % b) : a;
|
||||
}
|
||||
|
||||
static inline uint32_t hw_divider_u32_quotient_inlined(uint32_t a, uint32_t b) {
|
||||
return hw_divider_u32_quotient(a,b);
|
||||
}
|
||||
|
||||
static inline uint32_t hw_divider_u32_remainder_inlined(uint32_t a, uint32_t b) {
|
||||
return hw_divider_u32_remainder(a,b);
|
||||
}
|
||||
|
||||
static inline int32_t hw_divider_s32_quotient_inlined(int32_t a, int32_t b) {
|
||||
return hw_divider_s32_quotient(a,b);
|
||||
}
|
||||
|
||||
static inline int32_t hw_divider_s32_remainder_inlined(int32_t a, int32_t b) {
|
||||
return hw_divider_s32_remainder(a,b);
|
||||
}
|
||||
|
||||
typedef uint64_t hw_divider_state_t;
|
||||
|
||||
static inline void hw_divider_save_state(hw_divider_state_t *dest) {
|
||||
*dest = hw_divider_result_threadlocal;
|
||||
}
|
||||
|
||||
static inline void hw_divider_restore_state(hw_divider_state_t *src) {
|
||||
hw_divider_result_threadlocal = *src;
|
||||
}
|
||||
|
||||
#endif // _HARDWARE_DIVIDER_H
|
Reference in New Issue
Block a user