1/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include "pico/asm_helper.S"
8#include "pico/bootrom.h"
9#include "pico/runtime_init.h"
10
11pico_default_asm_setup
12
13.macro bits_section name
14#if PICO_BITS_IN_RAM
15.section RAM_SECTION_NAME(\name), "ax"
16#else
17.section SECTION_NAME(\name), "ax"
18#endif
19.endm
20
21#if PICO_RP2040
22PICO_RUNTIME_INIT_FUNC_RUNTIME(__aeabi_bits_init, PICO_RUNTIME_INIT_AEABI_BIT_OPS)
23
24.section .data.aeabi_bits_funcs
25.global aeabi_bits_funcs, aeabi_bits_funcs_end
26.equ BITS_FUNC_COUNT, 4
27.align 4
28aeabi_bits_funcs:
29    .word ROM_FUNC_POPCOUNT32
30    .word ROM_FUNC_CLZ32
31    .word ROM_FUNC_CTZ32
32    .word ROM_FUNC_REVERSE32
33aeabi_bits_funcs_end:
34
35.section .text
36.thumb_func
37__aeabi_bits_init:
38    ldr r0, =aeabi_bits_funcs
39    movs r1, #BITS_FUNC_COUNT
40    ldr r3, =rom_funcs_lookup
41    bx r3
42
43.equ POPCOUNT32, 0
44.equ CLZ32, 4
45.equ CTZ32, 8
46.equ REVERSE32, 12
47
48bits_section clzsi
49wrapper_func __clz
50wrapper_func __clzl
51wrapper_func __clzsi2
52    ldr r3, =aeabi_bits_funcs
53    ldr r3, [r3, #CLZ32]
54    bx r3
55
56bits_section ctzsi
57wrapper_func __ctzsi2
58    ldr r3, =aeabi_bits_funcs
59    ldr r3, [r3, #CTZ32]
60    bx r3
61
62bits_section popcountsi
63wrapper_func __popcountsi2
64    ldr r3, =aeabi_bits_funcs
65    ldr r3, [r3, #POPCOUNT32]
66    bx r3
67
68bits_section clzdi
69wrapper_func __clzll
70wrapper_func __clzdi2
71    ldr r3, =aeabi_bits_funcs
72    ldr r3, [r3, #CLZ32]
73    cmp r1, #0
74    bne 1f
75    push {lr}
76    blx r3
77    adds r0, #32
78    pop {pc}
791:
80    mov r0, r1
81    bx r3
82
83bits_section ctzdi
84wrapper_func __ctzdi2
85    ldr r3, =aeabi_bits_funcs
86    ldr r3, [r3, #CTZ32]
87    cmp r0, #0
88    beq 1f
89    bx r3
901:
91    push {lr}
92    mov r0, r1
93    blx r3
94    adds r0, #32
95    pop {pc}
96
97bits_section popcountdi
98wrapper_func __popcountdi2
99    ldr r3, =aeabi_bits_funcs
100    ldr r3, [r3, #POPCOUNT32]
101    push {r1, r3, lr}
102    blx r3
103    mov ip, r0
104    pop {r0, r3}
105    blx r3
106    mov r1, ip
107    add r0, r1
108    pop {pc}
109
110bits_section __rev
111regular_func __rev
112regular_func __revl
113regular_func reverse32
114    ldr r3, =aeabi_bits_funcs
115    ldr r3, [r3, #REVERSE32]
116    bx r3
117
118bits_section __revll
119regular_func __revll
120regular_func reverse64
121    push {lr}
122    ldr r3, =aeabi_bits_funcs
123    ldr r3, [r3, #REVERSE32]
124    push {r1, r3}
125    blx r3
126    mov ip, r0 // reverse32 preserves ip
127    pop {r0, r3}
128    blx r3
129    mov r1, ip
130    pop {pc}
131
132#else // RP2350
133
134bits_section __rev
135regular_func __rev
136regular_func __revl
137regular_func reverse32
138#ifdef __riscv
139    rev8 a0, a0
140    brev8 a0, a0
141    ret
142#else
143    rbit r0, r0
144    bx lr
145#endif
146
147bits_section __revll
148regular_func __revll
149regular_func reverse64
150#ifdef __riscv
151    rev8 a0, a0
152    brev8 a0, a0
153    rev8 a1, a1
154    brev8 a1, a1
155    mv a2, a0
156    mv a0, a1
157    mv a1, a2
158    ret
159#else
160    mov r2, r1
161    rbit r1, r0
162    rbit r0, r2
163    bx lr
164#endif
165
166// todo gcc riscv version is nuts; we'll provide both versions for simplicity in CMakeLists.txt
167//  (also gcc arm version is a bit pants)
168bits_section ctzdi
169wrapper_func __ctzdi2
170#ifdef __riscv
171    beqz a0, 1f
172    ctz a0, a0
173    ret
1741:
175    ctz a0, a1
176    addi a0, a0, 32
177    ret
178#else
179    cbz r0, 1f
180    rbit r0, r0
181    clz r0, r0
182    bx	lr
1831:
184    rbit r0, r1
185    clz r0, r0
186    adds r0, #32
187    bx	lr
188#endif
189
190#endif