77 lines
1.9 KiB
ArmAsm
77 lines
1.9 KiB
ArmAsm
#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}
|