1#include "pico/asm_helper.S"
2#include "hardware/regs/addressmap.h"
3#include "hardware/regs/sio.h"
4
5#if !PICO_RP2040
6#warning "Building hardware/divider.S on a platform with no SIO divider hardware"
7#endif
8
9pico_default_asm_setup
10
11// tag::hw_div_s32[]
12regular_func_with_section hw_divider_divmod_s32
13    ldr r3, =(SIO_BASE)
14    str r0, [r3, #SIO_DIV_SDIVIDEND_OFFSET]
15    str r1, [r3, #SIO_DIV_SDIVISOR_OFFSET]
16    b hw_divider_divmod_return
17// end::hw_div_s32[]
18
19// tag::hw_div_u32[]
20regular_func_with_section hw_divider_divmod_u32
21    ldr r3, =(SIO_BASE)
22    str r0, [r3, #SIO_DIV_UDIVIDEND_OFFSET]
23    str r1, [r3, #SIO_DIV_UDIVISOR_OFFSET]
24    b hw_divider_divmod_return
25// end::hw_div_u32[]
26
27// Common delay and return section for s32 and u32
28.section .text.hw_divider_divmod_return
29hw_divider_divmod_return:
30    // Branching here is 2 cycles, delay another 6
31    b 1f
321:  b 1f
331:  b 1f
341:  // return 64 bit value so we can efficiently return both (note quotient must be read last)
35    ldr r1, [r3, #SIO_DIV_REMAINDER_OFFSET]
36    ldr r0, [r3, #SIO_DIV_QUOTIENT_OFFSET]
37    bx lr
38
39regular_func_with_section hw_divider_save_state
40    ldr r3, =SIO_BASE
41    ldr r1, [r3, #SIO_DIV_UDIVIDEND_OFFSET]
42    ldr r2, [r3, #SIO_DIV_UDIVISOR_OFFSET]
43    stmia r0!, {r1-r2}
44    // The 8 cycles needed to guarantee that the result is ready is ensured by the preceding
45    // code of 7 cycles together with any branch to it taking at least 2 cycles.
46    ldr r1, [r3, #SIO_DIV_REMAINDER_OFFSET]
47    ldr r2, [r3, #SIO_DIV_QUOTIENT_OFFSET]
48    stmia r0!, {r1-r2}
49    bx lr
50
51regular_func_with_section hw_divider_restore_state
52    ldr r3, =SIO_BASE
53    ldmia r0!, {r1-r2}
54    str r1, [r3, #SIO_DIV_UDIVIDEND_OFFSET]
55    str r2, [r3, #SIO_DIV_UDIVISOR_OFFSET]
56    ldmia r0!, {r1-r2}
57    str r1, [r3, #SIO_DIV_REMAINDER_OFFSET]
58    str r2, [r3, #SIO_DIV_QUOTIENT_OFFSET]
59    bx lr
60