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