| #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} |