summaryrefslogtreecommitdiff
path: root/bsp/raspberry-pico/libraries/pico-sdk/src/rp2_common/hardware_divider/divider.S
blob: b9389c514a76a805a3779ef0b15caf8601368e17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include "pico/asm_helper.S"
#include "hardware/regs/addressmap.h"
#include "hardware/regs/sio.h"

.syntax unified
.cpu cortex-m0plus
.thumb

// tag::hw_div_s32[]

.macro __divider_delay
    // delay 8 cycles
    b 1f
1:  b 1f
1:  b 1f
1:  b 1f
1:
.endm

.align 2

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]
    __divider_delay
    // 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
// end::hw_div_s32[]

.align 2

// 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]
    __divider_delay
    // 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
// end::hw_div_u32[]

#if SIO_DIV_CSR_READY_LSB == 0
.equ SIO_DIV_CSR_READY_SHIFT_FOR_CARRY, 1
#else
#error need to change SHIFT above
#endif

regular_func_with_section hw_divider_save_state
    push {r4, r5, lr}
    ldr r5, =SIO_BASE
    ldr r4, [r5, #SIO_DIV_CSR_OFFSET]
    # wait for results as we can't save signed-ness of operation
1:
    lsrs r4, #SIO_DIV_CSR_READY_SHIFT_FOR_CARRY
    bcc 1b
    ldr r1, [r5, #SIO_DIV_UDIVIDEND_OFFSET]
    ldr r2, [r5, #SIO_DIV_UDIVISOR_OFFSET]
    ldr r3, [r5, #SIO_DIV_REMAINDER_OFFSET]
    ldr r4, [r5, #SIO_DIV_QUOTIENT_OFFSET]
    stmia r0!, {r1-r4}
    pop {r4, r5, pc}

regular_func_with_section hw_divider_restore_state
    push {r4, r5, lr}
    ldr r5, =SIO_BASE
    ldmia r0!, {r1-r4}
    str r1, [r5, #SIO_DIV_UDIVIDEND_OFFSET]
    str r2, [r5, #SIO_DIV_UDIVISOR_OFFSET]
    str r3, [r5, #SIO_DIV_REMAINDER_OFFSET]
    str r4, [r5, #SIO_DIV_QUOTIENT_OFFSET]
    pop {r4, r5, pc}