| /* |
| * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| #include "pico/asm_helper.S" |
| #include "pico/bootrom.h" |
| #include "pico/runtime_init.h" |
| |
| pico_default_asm_setup |
| |
| .macro bits_section name |
| #if PICO_BITS_IN_RAM |
| .section RAM_SECTION_NAME(\name), "ax" |
| #else |
| .section SECTION_NAME(\name), "ax" |
| #endif |
| .endm |
| |
| #if PICO_RP2040 |
| PICO_RUNTIME_INIT_FUNC_RUNTIME(__aeabi_bits_init, PICO_RUNTIME_INIT_AEABI_BIT_OPS) |
| |
| .section .data.aeabi_bits_funcs |
| .global aeabi_bits_funcs, aeabi_bits_funcs_end |
| .equ BITS_FUNC_COUNT, 4 |
| .align 4 |
| aeabi_bits_funcs: |
| .word ROM_FUNC_POPCOUNT32 |
| .word ROM_FUNC_CLZ32 |
| .word ROM_FUNC_CTZ32 |
| .word ROM_FUNC_REVERSE32 |
| aeabi_bits_funcs_end: |
| |
| .section .text |
| .thumb_func |
| __aeabi_bits_init: |
| ldr r0, =aeabi_bits_funcs |
| movs r1, #BITS_FUNC_COUNT |
| ldr r3, =rom_funcs_lookup |
| bx r3 |
| |
| .equ POPCOUNT32, 0 |
| .equ CLZ32, 4 |
| .equ CTZ32, 8 |
| .equ REVERSE32, 12 |
| |
| bits_section clzsi |
| wrapper_func __clz |
| wrapper_func __clzl |
| wrapper_func __clzsi2 |
| ldr r3, =aeabi_bits_funcs |
| ldr r3, [r3, #CLZ32] |
| bx r3 |
| |
| bits_section ctzsi |
| wrapper_func __ctzsi2 |
| ldr r3, =aeabi_bits_funcs |
| ldr r3, [r3, #CTZ32] |
| bx r3 |
| |
| bits_section popcountsi |
| wrapper_func __popcountsi2 |
| ldr r3, =aeabi_bits_funcs |
| ldr r3, [r3, #POPCOUNT32] |
| bx r3 |
| |
| bits_section clzdi |
| wrapper_func __clzll |
| wrapper_func __clzdi2 |
| ldr r3, =aeabi_bits_funcs |
| ldr r3, [r3, #CLZ32] |
| cmp r1, #0 |
| bne 1f |
| push {lr} |
| blx r3 |
| adds r0, #32 |
| pop {pc} |
| 1: |
| mov r0, r1 |
| bx r3 |
| |
| bits_section ctzdi |
| wrapper_func __ctzdi2 |
| ldr r3, =aeabi_bits_funcs |
| ldr r3, [r3, #CTZ32] |
| cmp r0, #0 |
| beq 1f |
| bx r3 |
| 1: |
| push {lr} |
| mov r0, r1 |
| blx r3 |
| adds r0, #32 |
| pop {pc} |
| |
| bits_section popcountdi |
| wrapper_func __popcountdi2 |
| ldr r3, =aeabi_bits_funcs |
| ldr r3, [r3, #POPCOUNT32] |
| push {r1, r3, lr} |
| blx r3 |
| mov ip, r0 |
| pop {r0, r3} |
| blx r3 |
| mov r1, ip |
| add r0, r1 |
| pop {pc} |
| |
| bits_section __rev |
| regular_func __rev |
| regular_func __revl |
| regular_func reverse32 |
| ldr r3, =aeabi_bits_funcs |
| ldr r3, [r3, #REVERSE32] |
| bx r3 |
| |
| bits_section __revll |
| regular_func __revll |
| regular_func reverse64 |
| push {lr} |
| ldr r3, =aeabi_bits_funcs |
| ldr r3, [r3, #REVERSE32] |
| push {r1, r3} |
| blx r3 |
| mov ip, r0 // reverse32 preserves ip |
| pop {r0, r3} |
| blx r3 |
| mov r1, ip |
| pop {pc} |
| |
| #else // RP2350 |
| |
| bits_section __rev |
| regular_func __rev |
| regular_func __revl |
| regular_func reverse32 |
| #ifdef __riscv |
| rev8 a0, a0 |
| brev8 a0, a0 |
| ret |
| #else |
| rbit r0, r0 |
| bx lr |
| #endif |
| |
| bits_section __revll |
| regular_func __revll |
| regular_func reverse64 |
| #ifdef __riscv |
| rev8 a0, a0 |
| brev8 a0, a0 |
| rev8 a1, a1 |
| brev8 a1, a1 |
| mv a2, a0 |
| mv a0, a1 |
| mv a1, a2 |
| ret |
| #else |
| mov r2, r1 |
| rbit r1, r0 |
| rbit r0, r2 |
| bx lr |
| #endif |
| |
| // todo gcc riscv version is nuts; we'll provide both versions for simplicity in CMakeLists.txt |
| // (also gcc arm version is a bit pants) |
| bits_section ctzdi |
| wrapper_func __ctzdi2 |
| #ifdef __riscv |
| beqz a0, 1f |
| ctz a0, a0 |
| ret |
| 1: |
| ctz a0, a1 |
| addi a0, a0, 32 |
| ret |
| #else |
| cbz r0, 1f |
| rbit r0, r0 |
| clz r0, r0 |
| bx lr |
| 1: |
| rbit r0, r1 |
| clz r0, r0 |
| adds r0, #32 |
| bx lr |
| #endif |
| |
| #endif |