blob: 1292331926779e23ef1671523863165a944685da [file] [log] [blame]
#include "pico/asm_helper.S"
#include "hardware/regs/addressmap.h"
#include "hardware/regs/sio.h"
#if !PICO_RP2040
#warning "Building hardware/divider.S on a platform with no SIO divider hardware"
#endif
pico_default_asm_setup
// tag::hw_div_s32[]
regular_func_with_section hw_divider_divmod_s32
ldr r3, =(SIO_BASE)
str r0, [r3, #SIO_DIV_SDIVIDEND_OFFSET]
str r1, [r3, #SIO_DIV_SDIVISOR_OFFSET]
b hw_divider_divmod_return
// end::hw_div_s32[]
// tag::hw_div_u32[]
regular_func_with_section hw_divider_divmod_u32
ldr r3, =(SIO_BASE)
str r0, [r3, #SIO_DIV_UDIVIDEND_OFFSET]
str r1, [r3, #SIO_DIV_UDIVISOR_OFFSET]
b hw_divider_divmod_return
// end::hw_div_u32[]
// Common delay and return section for s32 and u32
.section .text.hw_divider_divmod_return
hw_divider_divmod_return:
// Branching here is 2 cycles, delay another 6
b 1f
1: b 1f
1: b 1f
1: // return 64 bit value so we can efficiently return both (note quotient must be read last)
ldr r1, [r3, #SIO_DIV_REMAINDER_OFFSET]
ldr r0, [r3, #SIO_DIV_QUOTIENT_OFFSET]
bx lr
regular_func_with_section hw_divider_save_state
ldr r3, =SIO_BASE
ldr r1, [r3, #SIO_DIV_UDIVIDEND_OFFSET]
ldr r2, [r3, #SIO_DIV_UDIVISOR_OFFSET]
stmia r0!, {r1-r2}
// The 8 cycles needed to guarantee that the result is ready is ensured by the preceding
// code of 7 cycles together with any branch to it taking at least 2 cycles.
ldr r1, [r3, #SIO_DIV_REMAINDER_OFFSET]
ldr r2, [r3, #SIO_DIV_QUOTIENT_OFFSET]
stmia r0!, {r1-r2}
bx lr
regular_func_with_section hw_divider_restore_state
ldr r3, =SIO_BASE
ldmia r0!, {r1-r2}
str r1, [r3, #SIO_DIV_UDIVIDEND_OFFSET]
str r2, [r3, #SIO_DIV_UDIVISOR_OFFSET]
ldmia r0!, {r1-r2}
str r1, [r3, #SIO_DIV_REMAINDER_OFFSET]
str r2, [r3, #SIO_DIV_QUOTIENT_OFFSET]
bx lr