Matomat/firmware/lib/lib1funcs.lst

453 lines
19 KiB
Plaintext
Raw Permalink Normal View History

2015-11-15 19:18:42 +01:00
1 # 1 "lib/lib1funcs.S"
1 /*
0
0
2 * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
3 *
4 * Author: Nicolas Pitre <nico@cam.org>
5 * - contributed to gcc-3.4 on Sep 30, 2003
6 * - adapted for the Linux kernel on Oct 2, 2003
7 */
8
9 /* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
10
11 This file is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
14 later version.
15
16 In addition to the permissions in the GNU General Public License, the
17 Free Software Foundation gives you unlimited permission to link the
18 compiled version of this file into combinations with other programs,
19 and to distribute those combinations without any restriction coming
20 from the use of this file. (The General Public License restrictions
21 do apply in other respects; for example, they cover modification of
22 the file, and distribution when not linked into a combine
23 executable.)
24
25 This file is distributed in the hope that it will be useful, but
26 WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 General Public License for more details.
29
30 You should have received a copy of the GNU General Public License
31 along with this program; see the file COPYING. If not, write to
32 the Free Software Foundation, 59 Temple Place - Suite 330,
33 Boston, MA 02111-1307, USA. */
34
35
36 #include <asm/linkage.h>
1 #ifndef __ASM_LINKAGE_H
37 #include <asm/assembler.h>
1 /*
2 * linux/include/asm-arm/assembler.h
3 *
4 * Copyright (C) 1996-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This file contains arm architecture specific defines
11 * for the different processors.
12 *
13 * Do not include any C declarations in this file - it is included by
14 * assembler source.
15 */
16 #ifndef __ASSEMBLY__
17 #error "Only include this from assembly code"
18 #endif
19
20 #include <asm/ptrace.h>
1 /*
21
22 #define pull lsl
23 #define push lsr
24 #define get_byte_0 lsr #24
25 #define get_byte_1 lsr #16
26 #define get_byte_2 lsr #8
27 #define get_byte_3 lsl #0
28 #define put_byte_0 lsl #24
29 #define put_byte_1 lsl #16
30 #define put_byte_2 lsl #8
31 #define put_byte_3 lsl #0
32
33 #define PLD(code...)
34
35 #define MODE_USR USR_MODE
36 #define MODE_FIQ FIQ_MODE
37 #define MODE_IRQ IRQ_MODE
38 #define MODE_SVC SVC_MODE
39
40 #define DEFAULT_FIQ MODE_FIQ
41
42 /*
43 * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc})
44 */
45 #ifdef __STDC__
46 #define LOADREGS(cond, base, reglist...)\
47 ldm##cond base,reglist
48 #else
49 #define LOADREGS(cond, base, reglist...)\
50 ldm/**/cond base,reglist
51 #endif
52
53 /*
54 * Build a return instruction for this processor type.
55 */
56 #define RETINSTR(instr, regs...)\
57 instr regs
58
59 /*
60 * Enable and disable interrupts
61 */
62 .macro disable_irq
63 msr cpsr_c, #PSR_I_BIT | SVC_MODE
64 .endm
65
66 .macro enable_irq
67 msr cpsr_c, #SVC_MODE
68 .endm
69
70 /*
71 * Save the current IRQ state and disable IRQs. Note that this macro
72 * assumes FIQs are enabled, and that the processor is in SVC mode.
73 */
74 .macro save_and_disable_irqs, oldcpsr
75 mrs \oldcpsr, cpsr
76 disable_irq
77 .endm
78
79 /*
80 * Restore interrupt state previously stored in a register. We don't
81 * guarantee that this will preserve the flags.
82 */
83 .macro restore_irqs, oldcpsr
84 msr cpsr_c, \oldcpsr
85 .endm
86
87 /*
88 * These two are used to save LR/restore PC over a user-based access.
89 * The old 26-bit architecture requires that we do. On 32-bit
90 * architecture, we can safely ignore this requirement.
91 */
92 .macro save_lr
93 .endm
94
95 .macro restore_pc
96 mov pc, lr
97 .endm
98 ...
38
39
40 .macro ARM_DIV_BODY dividend, divisor, result, curbit
41
42 #if __LINUX_ARM_ARCH__ >= 5
43
44 clz \curbit, \divisor
45 clz \result, \dividend
46 sub \result, \curbit, \result
47 mov \curbit, #1
48 mov \divisor, \divisor, lsl \result
49 mov \curbit, \curbit, lsl \result
50 mov \result, #0
51
52 #else
53
54 @ Initially shift the divisor left 3 bits if possible,
55 @ set curbit accordingly. This allows for curbit to be located
56 @ at the left end of each 4 bit nibbles in the division loop
57 @ to save one loop in most cases.
58 tst \divisor, #0xe0000000
59 moveq \divisor, \divisor, lsl #3
60 moveq \curbit, #8
61 movne \curbit, #1
62
63 @ Unless the divisor is very big, shift it up in multiples of
64 @ four bits, since this is the amount of unwinding in the main
65 @ division loop. Continue shifting until the divisor is
66 @ larger than the dividend.
67 1: cmp \divisor, #0x10000000
68 cmplo \divisor, \dividend
69 movlo \divisor, \divisor, lsl #4
70 movlo \curbit, \curbit, lsl #4
71 blo 1b
72
73 @ For very big divisors, we must shift it a bit at a time, or
74 @ we will be in danger of overflowing.
75 1: cmp \divisor, #0x80000000
76 cmplo \divisor, \dividend
77 movlo \divisor, \divisor, lsl #1
78 movlo \curbit, \curbit, lsl #1
79 blo 1b
80
81 mov \result, #0
82
83 #endif
84
85 @ Division loop
86 1: cmp \dividend, \divisor
87 subhs \dividend, \dividend, \divisor
88 orrhs \result, \result, \curbit
89 cmp \dividend, \divisor, lsr #1
90 subhs \dividend, \dividend, \divisor, lsr #1
91 orrhs \result, \result, \curbit, lsr #1
92 cmp \dividend, \divisor, lsr #2
93 subhs \dividend, \dividend, \divisor, lsr #2
94 orrhs \result, \result, \curbit, lsr #2
95 cmp \dividend, \divisor, lsr #3
96 subhs \dividend, \dividend, \divisor, lsr #3
97 orrhs \result, \result, \curbit, lsr #3
98 cmp \dividend, #0 @ Early termination?
99 movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
100 movne \divisor, \divisor, lsr #4
101 bne 1b
102
103 .endm
104
105
106 .macro ARM_DIV2_ORDER divisor, order
107
108 #if __LINUX_ARM_ARCH__ >= 5
109
110 clz \order, \divisor
111 rsb \order, \order, #31
112
113 #else
114
115 cmp \divisor, #(1 << 16)
116 movhs \divisor, \divisor, lsr #16
117 movhs \order, #16
118 movlo \order, #0
119
120 cmp \divisor, #(1 << 8)
121 movhs \divisor, \divisor, lsr #8
122 addhs \order, \order, #8
123
124 cmp \divisor, #(1 << 4)
125 movhs \divisor, \divisor, lsr #4
126 addhs \order, \order, #4
127
128 cmp \divisor, #(1 << 2)
129 addhi \order, \order, #3
130 addls \order, \order, \divisor, lsr #1
131
132 #endif
133
134 .endm
135
136
137 .macro ARM_MOD_BODY dividend, divisor, order, spare
138
139 #if __LINUX_ARM_ARCH__ >= 5
140
141 clz \order, \divisor
142 clz \spare, \dividend
143 sub \order, \order, \spare
144 mov \divisor, \divisor, lsl \order
145
146 #else
147
148 mov \order, #0
149
150 @ Unless the divisor is very big, shift it up in multiples of
151 @ four bits, since this is the amount of unwinding in the main
152 @ division loop. Continue shifting until the divisor is
153 @ larger than the dividend.
154 1: cmp \divisor, #0x10000000
155 cmplo \divisor, \dividend
156 movlo \divisor, \divisor, lsl #4
157 addlo \order, \order, #4
158 blo 1b
159
160 @ For very big divisors, we must shift it a bit at a time, or
161 @ we will be in danger of overflowing.
162 1: cmp \divisor, #0x80000000
163 cmplo \divisor, \dividend
164 movlo \divisor, \divisor, lsl #1
165 addlo \order, \order, #1
166 blo 1b
167
168 #endif
169
170 @ Perform all needed substractions to keep only the reminder.
171 @ Do comparisons in batch of 4 first.
172 subs \order, \order, #3 @ yes, 3 is intended here
173 blt 2f
174
175 1: cmp \dividend, \divisor
176 subhs \dividend, \dividend, \divisor
177 cmp \dividend, \divisor, lsr #1
178 subhs \dividend, \dividend, \divisor, lsr #1
179 cmp \dividend, \divisor, lsr #2
180 subhs \dividend, \dividend, \divisor, lsr #2
181 cmp \dividend, \divisor, lsr #3
182 subhs \dividend, \dividend, \divisor, lsr #3
183 cmp \dividend, #1
184 mov \divisor, \divisor, lsr #4
185 subges \order, \order, #4
186 bge 1b
187
188 tst \order, #3
189 teqne \dividend, #0
190 beq 5f
191
192 @ Either 1, 2 or 3 comparison/substractions are left.
193 2: cmn \order, #2
194 blt 4f
195 beq 3f
196 cmp \dividend, \divisor
197 subhs \dividend, \dividend, \divisor
198 mov \divisor, \divisor, lsr #1
199 3: cmp \dividend, \divisor
200 subhs \dividend, \dividend, \divisor
201 mov \divisor, \divisor, lsr #1
202 4: cmp \dividend, \divisor
203 subhs \dividend, \dividend, \divisor
204 5:
205 .endm
206
207
208 /*ENTRY(__udivsi3)
209 ENTRY(__aeabi_uidiv)
210
211 subs r2, r1, #1
212 moveq pc, lr
213 bcc Ldiv0
214 cmp r0, r1
215 bls 11f
216 tst r1, r2
217 beq 12f
218
219 ARM_DIV_BODY r0, r1, r2, r3
220
221 mov r0, r2
222 mov pc, lr
223
224 11: moveq r0, #1
225 movne r0, #0
226 mov pc, lr
227
228 12: ARM_DIV2_ORDER r1, r2
229
230 mov r0, r0, lsr r2
231 mov pc, lr
232 */
233
234 ENTRY(__umodsi3)
235
236 0000 012051E2 subs r2, r1, #1 @ compare divisor with 1
237 0004 A700003A bcc Ldiv0
238 0008 01005011 cmpne r0, r1 @ compare dividend with divisor
239 000c 0000A003 moveq r0, #0
240 0010 02001181 tsthi r1, r2 @ see if divisor is power of 2
241 0014 02000000 andeq r0, r0, r2
242 0018 0EF0A091 movls pc, lr
243
244 ARM_MOD_BODY r0, r1, r2, r3
245
246 00b8 0EF0A0E1 mov pc, lr
247
248
249 ENTRY(__divsi3)
250 ENTRY(__aeabi_idiv)
251
252 00bc 000051E3 cmp r1, #0
253 00c0 01C020E0 eor ip, r0, r1 @ save the sign of the result.
254 00c4 7700000A beq Ldiv0
255 00c8 00106142 rsbmi r1, r1, #0 @ loops below use unsigned.
256 00cc 012051E2 subs r2, r1, #1 @ division by 1 or -1 ?
257 00d0 2700000A beq 10f
258 00d4 0030B0E1 movs r3, r0
259 00d8 00306042 rsbmi r3, r0, #0 @ positive dividend value
260 00dc 010053E1 cmp r3, r1
261 00e0 2600009A bls 11f
262 00e4 020011E1 tst r1, r2 @ divisor is power of 2 ?
263 00e8 2800000A beq 12f
264
265 ARM_DIV_BODY r3, r1, r0, r2
266
267 0168 00005CE3 cmp ip, #0
268 016c 00006042 rsbmi r0, r0, #0
269 0170 0EF0A0E1 mov pc, lr
270
271 0174 00003CE1 10: teq ip, r0 @ same sign ?
272 0178 00006042 rsbmi r0, r0, #0
273 017c 0EF0A0E1 mov pc, lr
274
275 0180 0000A033 11: movlo r0, #0
276 0184 CC0FA001 moveq r0, ip, asr #31
277 0188 01008003 orreq r0, r0, #1
278 018c 0EF0A0E1 mov pc, lr
279
280 12: ARM_DIV2_ORDER r1, r2
281
282 01c4 00005CE3 cmp ip, #0
283 01c8 3302A0E1 mov r0, r3, lsr r2
284 01cc 00006042 rsbmi r0, r0, #0
285 01d0 0EF0A0E1 mov pc, lr
286
287
288 ENTRY(__modsi3)
289
290 01d4 000051E3 cmp r1, #0
291 01d8 3200000A beq Ldiv0
292 01dc 00106142 rsbmi r1, r1, #0 @ loops below use unsigned.
293 01e0 00C0B0E1 movs ip, r0 @ preserve sign of dividend
294 01e4 00006042 rsbmi r0, r0, #0 @ if negative make positive
295 01e8 012051E2 subs r2, r1, #1 @ compare divisor with 1
296 01ec 01005011 cmpne r0, r1 @ compare dividend with divisor
297 01f0 0000A003 moveq r0, #0
298 01f4 02001181 tsthi r1, r2 @ see if divisor is power of 2
299 01f8 02000000 andeq r0, r0, r2
300 01fc 2600009A bls 10f
301
302 ARM_MOD_BODY r0, r1, r2, r3
303
304 029c 00005CE3 10: cmp ip, #0
305 02a0 00006042 rsbmi r0, r0, #0
306 02a4 0EF0A0E1 mov pc, lr
307
308 #ifdef CONFIG_AEABI
309
310 ENTRY(__aeabi_uidivmod)
311
312 stmfd sp!, {r0, r1, ip, lr}
313 bl __aeabi_uidiv
314 ldmfd sp!, {r1, r2, ip, lr}
315 mul r3, r0, r2
316 sub r1, r1, r3
317 mov pc, lr
318
319 ENTRY(__aeabi_idivmod)
320
321 stmfd sp!, {r0, r1, ip, lr}
322 bl __aeabi_idiv
323 ldmfd sp!, {r1, r2, ip, lr}
324 mul r3, r0, r2
325 sub r1, r1, r3
326 mov pc, lr
327
328 #endif
329
330 Ldiv0:
331
332 02a8 08E02DE5 str lr, [sp, #-8]!
333 02ac FEFFFFEB bl __div0
334 02b0 0000A0E3 mov r0, #0 @ About as wrong as it could be.
335 02b4 08F09DE4 ldr pc, [sp], #8
336
337 ENTRY(__div0)
338 02b8 0EF0A0E1 mov pc, lr
DEFINED SYMBOLS
lib/lib1funcs.S:234 .text:00000000 __umodsi3
lib/lib1funcs.S:234 .text:00000000 $a
lib/lib1funcs.S:330 .text:000002a8 Ldiv0
lib/lib1funcs.S:249 .text:000000bc __divsi3
lib/lib1funcs.S:250 .text:000000bc __aeabi_idiv
lib/lib1funcs.S:288 .text:000001d4 __modsi3
lib/lib1funcs.S:337 .text:000002b8 __div0
.debug_aranges:0000000c $d
NO UNDEFINED SYMBOLS