1#include "pico/asm_helper.S"
2#include "hardware/regs/addressmap.h"
3#include "hardware/regs/sio.h"
4
5.syntax unified
6.cpu cortex-m0plus
7.thumb
8
9// tag::hw_div_s32[]
10
11.macro __divider_delay
12    // delay 8 cycles
13    b 1f
141:  b 1f
151:  b 1f
161:  b 1f
171:
18.endm
19
20.align 2
21
22regular_func_with_section hw_divider_divmod_s32
23    ldr r3, =(SIO_BASE)
24    str r0, [r3, #SIO_DIV_SDIVIDEND_OFFSET]
25    str r1, [r3, #SIO_DIV_SDIVISOR_OFFSET]
26    __divider_delay
27    // return 64 bit value so we can efficiently return both (note quotient must be read last)
28    ldr r1, [r3, #SIO_DIV_REMAINDER_OFFSET]
29    ldr r0, [r3, #SIO_DIV_QUOTIENT_OFFSET]
30    bx lr
31// end::hw_div_s32[]
32
33.align 2
34
35// tag::hw_div_u32[]
36regular_func_with_section hw_divider_divmod_u32
37    ldr r3, =(SIO_BASE)
38    str r0, [r3, #SIO_DIV_UDIVIDEND_OFFSET]
39    str r1, [r3, #SIO_DIV_UDIVISOR_OFFSET]
40    __divider_delay
41    // return 64 bit value so we can efficiently return both (note quotient must be read last)
42    ldr r1, [r3, #SIO_DIV_REMAINDER_OFFSET]
43    ldr r0, [r3, #SIO_DIV_QUOTIENT_OFFSET]
44    bx lr
45// end::hw_div_u32[]
46
47#if SIO_DIV_CSR_READY_LSB == 0
48.equ SIO_DIV_CSR_READY_SHIFT_FOR_CARRY, 1
49#else
50#error need to change SHIFT above
51#endif
52
53regular_func_with_section hw_divider_save_state
54    push {r4, r5, lr}
55    ldr r5, =SIO_BASE
56    ldr r4, [r5, #SIO_DIV_CSR_OFFSET]
57    # wait for results as we can't save signed-ness of operation
581:
59    lsrs r4, #SIO_DIV_CSR_READY_SHIFT_FOR_CARRY
60    bcc 1b
61    ldr r1, [r5, #SIO_DIV_UDIVIDEND_OFFSET]
62    ldr r2, [r5, #SIO_DIV_UDIVISOR_OFFSET]
63    ldr r3, [r5, #SIO_DIV_REMAINDER_OFFSET]
64    ldr r4, [r5, #SIO_DIV_QUOTIENT_OFFSET]
65    stmia r0!, {r1-r4}
66    pop {r4, r5, pc}
67
68regular_func_with_section hw_divider_restore_state
69    push {r4, r5, lr}
70    ldr r5, =SIO_BASE
71    ldmia r0!, {r1-r4}
72    str r1, [r5, #SIO_DIV_UDIVIDEND_OFFSET]
73    str r2, [r5, #SIO_DIV_UDIVISOR_OFFSET]
74    str r3, [r5, #SIO_DIV_REMAINDER_OFFSET]
75    str r4, [r5, #SIO_DIV_QUOTIENT_OFFSET]
76    pop {r4, r5, pc}
77