lib1funcs.S revision 1.1.1.11 1 1.1 mrg @ libgcc routines for ARM cpu.
2 1.1 mrg @ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
3 1.1 mrg
4 1.1.1.11 mrg /* Copyright (C) 1995-2024 Free Software Foundation, Inc.
5 1.1 mrg
6 1.1 mrg This file is free software; you can redistribute it and/or modify it
7 1.1 mrg under the terms of the GNU General Public License as published by the
8 1.1 mrg Free Software Foundation; either version 3, or (at your option) any
9 1.1 mrg later version.
10 1.1 mrg
11 1.1 mrg This file is distributed in the hope that it will be useful, but
12 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 1.1 mrg General Public License for more details.
15 1.1 mrg
16 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
17 1.1 mrg permissions described in the GCC Runtime Library Exception, version
18 1.1 mrg 3.1, as published by the Free Software Foundation.
19 1.1 mrg
20 1.1 mrg You should have received a copy of the GNU General Public License and
21 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
22 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 1.1 mrg <http://www.gnu.org/licenses/>. */
24 1.1 mrg
25 1.1.1.9 mrg /* Everything in this file should now use unified syntax. */
26 1.1.1.9 mrg
27 1.1.1.9 mrg .syntax unified
28 1.1.1.9 mrg
29 1.1 mrg /* An executable stack is *not* required for these functions. */
30 1.1 mrg #if defined(__ELF__) && defined(__linux__)
31 1.1 mrg .section .note.GNU-stack,"",%progbits
32 1.1 mrg .previous
33 1.1 mrg #endif /* __ELF__ and __linux__ */
34 1.1 mrg
35 1.1 mrg #ifdef __ARM_EABI__
36 1.1 mrg /* Some attributes that are common to all routines in this file. */
37 1.1 mrg /* Tag_ABI_align_needed: This code does not require 8-byte
38 1.1 mrg alignment from the caller. */
39 1.1 mrg /* .eabi_attribute 24, 0 -- default setting. */
40 1.1 mrg /* Tag_ABI_align_preserved: This code preserves 8-byte
41 1.1 mrg alignment in any callee. */
42 1.1 mrg .eabi_attribute 25, 1
43 1.1 mrg #endif /* __ARM_EABI__ */
44 1.1 mrg /* ------------------------------------------------------------------------ */
45 1.1 mrg
46 1.1 mrg /* We need to know what prefix to add to function names. */
47 1.1 mrg
48 1.1 mrg #ifndef __USER_LABEL_PREFIX__
49 1.1 mrg #error __USER_LABEL_PREFIX__ not defined
50 1.1 mrg #endif
51 1.1 mrg
52 1.1 mrg /* ANSI concatenation macros. */
53 1.1 mrg
54 1.1 mrg #define CONCAT1(a, b) CONCAT2(a, b)
55 1.1 mrg #define CONCAT2(a, b) a ## b
56 1.1 mrg
57 1.1 mrg /* Use the right prefix for global labels. */
58 1.1 mrg
59 1.1 mrg #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
60 1.1 mrg
61 1.1 mrg #ifdef __ELF__
62 1.1 mrg #ifdef __thumb__
63 1.1 mrg #define __PLT__ /* Not supported in Thumb assembler (for now). */
64 1.1 mrg #elif defined __vxworks && !defined __PIC__
65 1.1 mrg #define __PLT__ /* Not supported by the kernel loader. */
66 1.1 mrg #else
67 1.1 mrg #define __PLT__ (PLT)
68 1.1 mrg #endif
69 1.1 mrg #define TYPE(x) .type SYM(x),function
70 1.1 mrg #define SIZE(x) .size SYM(x), . - SYM(x)
71 1.1 mrg #define LSYM(x) .x
72 1.1 mrg #else
73 1.1 mrg #define __PLT__
74 1.1 mrg #define TYPE(x)
75 1.1 mrg #define SIZE(x)
76 1.1 mrg #define LSYM(x) x
77 1.1 mrg #endif
78 1.1 mrg
79 1.1 mrg /* Function end macros. Variants for interworking. */
80 1.1 mrg
81 1.1 mrg /* There are times when we might prefer Thumb1 code even if ARM code is
82 1.1 mrg permitted, for example, the code might be smaller, or there might be
83 1.1 mrg interworking problems with switching to ARM state if interworking is
84 1.1 mrg disabled. */
85 1.1 mrg #if (defined(__thumb__) \
86 1.1 mrg && !defined(__thumb2__) \
87 1.1 mrg && (!defined(__THUMB_INTERWORK__) \
88 1.1 mrg || defined (__OPTIMIZE_SIZE__) \
89 1.1.1.4 mrg || !__ARM_ARCH_ISA_ARM))
90 1.1 mrg # define __prefer_thumb__
91 1.1 mrg #endif
92 1.1 mrg
93 1.1.1.4 mrg #if !__ARM_ARCH_ISA_ARM && __ARM_ARCH_ISA_THUMB == 1
94 1.1.1.4 mrg #define NOT_ISA_TARGET_32BIT 1
95 1.1.1.4 mrg #endif
96 1.1.1.4 mrg
97 1.1 mrg /* How to return from a function call depends on the architecture variant. */
98 1.1 mrg
99 1.1.1.8 mrg #if (__ARM_ARCH > 4) || defined(__ARM_ARCH_4T__)
100 1.1 mrg
101 1.1 mrg # define RET bx lr
102 1.1 mrg # define RETc(x) bx##x lr
103 1.1 mrg
104 1.1 mrg /* Special precautions for interworking on armv4t. */
105 1.1.1.8 mrg # if (__ARM_ARCH == 4)
106 1.1 mrg
107 1.1 mrg /* Always use bx, not ldr pc. */
108 1.1 mrg # if (defined(__thumb__) || defined(__THUMB_INTERWORK__))
109 1.1 mrg # define __INTERWORKING__
110 1.1 mrg # endif /* __THUMB__ || __THUMB_INTERWORK__ */
111 1.1 mrg
112 1.1 mrg /* Include thumb stub before arm mode code. */
113 1.1 mrg # if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
114 1.1 mrg # define __INTERWORKING_STUBS__
115 1.1 mrg # endif /* __thumb__ && !__THUMB_INTERWORK__ */
116 1.1 mrg
117 1.1 mrg #endif /* __ARM_ARCH == 4 */
118 1.1 mrg
119 1.1 mrg #else
120 1.1 mrg
121 1.1 mrg # define RET mov pc, lr
122 1.1 mrg # define RETc(x) mov##x pc, lr
123 1.1 mrg
124 1.1 mrg #endif
125 1.1 mrg
126 1.1 mrg .macro cfi_pop advance, reg, cfa_offset
127 1.1 mrg #ifdef __ELF__
128 1.1 mrg .pushsection .debug_frame
129 1.1 mrg .byte 0x4 /* DW_CFA_advance_loc4 */
130 1.1 mrg .4byte \advance
131 1.1 mrg .byte (0xc0 | \reg) /* DW_CFA_restore */
132 1.1 mrg .byte 0xe /* DW_CFA_def_cfa_offset */
133 1.1 mrg .uleb128 \cfa_offset
134 1.1 mrg .popsection
135 1.1 mrg #endif
136 1.1 mrg .endm
137 1.1 mrg .macro cfi_push advance, reg, offset, cfa_offset
138 1.1 mrg #ifdef __ELF__
139 1.1 mrg .pushsection .debug_frame
140 1.1 mrg .byte 0x4 /* DW_CFA_advance_loc4 */
141 1.1 mrg .4byte \advance
142 1.1 mrg .byte (0x80 | \reg) /* DW_CFA_offset */
143 1.1 mrg .uleb128 (\offset / -4)
144 1.1 mrg .byte 0xe /* DW_CFA_def_cfa_offset */
145 1.1 mrg .uleb128 \cfa_offset
146 1.1 mrg .popsection
147 1.1 mrg #endif
148 1.1 mrg .endm
149 1.1 mrg .macro cfi_start start_label, end_label
150 1.1 mrg #ifdef __ELF__
151 1.1 mrg .pushsection .debug_frame
152 1.1 mrg LSYM(Lstart_frame):
153 1.1 mrg .4byte LSYM(Lend_cie) - LSYM(Lstart_cie) @ Length of CIE
154 1.1 mrg LSYM(Lstart_cie):
155 1.1 mrg .4byte 0xffffffff @ CIE Identifier Tag
156 1.1 mrg .byte 0x1 @ CIE Version
157 1.1 mrg .ascii "\0" @ CIE Augmentation
158 1.1 mrg .uleb128 0x1 @ CIE Code Alignment Factor
159 1.1 mrg .sleb128 -4 @ CIE Data Alignment Factor
160 1.1 mrg .byte 0xe @ CIE RA Column
161 1.1 mrg .byte 0xc @ DW_CFA_def_cfa
162 1.1 mrg .uleb128 0xd
163 1.1 mrg .uleb128 0x0
164 1.1 mrg
165 1.1 mrg .align 2
166 1.1 mrg LSYM(Lend_cie):
167 1.1 mrg .4byte LSYM(Lend_fde)-LSYM(Lstart_fde) @ FDE Length
168 1.1 mrg LSYM(Lstart_fde):
169 1.1 mrg .4byte LSYM(Lstart_frame) @ FDE CIE offset
170 1.1 mrg .4byte \start_label @ FDE initial location
171 1.1 mrg .4byte \end_label-\start_label @ FDE address range
172 1.1 mrg .popsection
173 1.1 mrg #endif
174 1.1 mrg .endm
175 1.1 mrg .macro cfi_end end_label
176 1.1 mrg #ifdef __ELF__
177 1.1 mrg .pushsection .debug_frame
178 1.1 mrg .align 2
179 1.1 mrg LSYM(Lend_fde):
180 1.1 mrg .popsection
181 1.1 mrg \end_label:
182 1.1 mrg #endif
183 1.1 mrg .endm
184 1.1 mrg
185 1.1 mrg /* Don't pass dirn, it's there just to get token pasting right. */
186 1.1 mrg
187 1.1 mrg .macro RETLDM regs=, cond=, unwind=, dirn=ia
188 1.1 mrg #if defined (__INTERWORKING__)
189 1.1 mrg .ifc "\regs",""
190 1.1 mrg ldr\cond lr, [sp], #8
191 1.1 mrg .else
192 1.1 mrg # if defined(__thumb2__)
193 1.1 mrg pop\cond {\regs, lr}
194 1.1 mrg # else
195 1.1 mrg ldm\cond\dirn sp!, {\regs, lr}
196 1.1 mrg # endif
197 1.1 mrg .endif
198 1.1 mrg .ifnc "\unwind", ""
199 1.1 mrg /* Mark LR as restored. */
200 1.1 mrg 97: cfi_pop 97b - \unwind, 0xe, 0x0
201 1.1 mrg .endif
202 1.1 mrg bx\cond lr
203 1.1 mrg #else
204 1.1 mrg /* Caller is responsible for providing IT instruction. */
205 1.1 mrg .ifc "\regs",""
206 1.1 mrg ldr\cond pc, [sp], #8
207 1.1 mrg .else
208 1.1 mrg # if defined(__thumb2__)
209 1.1 mrg pop\cond {\regs, pc}
210 1.1 mrg # else
211 1.1 mrg ldm\cond\dirn sp!, {\regs, pc}
212 1.1 mrg # endif
213 1.1 mrg .endif
214 1.1 mrg #endif
215 1.1 mrg .endm
216 1.1 mrg
217 1.1 mrg /* The Unified assembly syntax allows the same code to be assembled for both
218 1.1 mrg ARM and Thumb-2. However this is only supported by recent gas, so define
219 1.1 mrg a set of macros to allow ARM code on older assemblers. */
220 1.1 mrg #if defined(__thumb2__)
221 1.1 mrg .macro do_it cond, suffix=""
222 1.1 mrg it\suffix \cond
223 1.1 mrg .endm
224 1.1 mrg .macro shift1 op, arg0, arg1, arg2
225 1.1 mrg \op \arg0, \arg1, \arg2
226 1.1 mrg .endm
227 1.1 mrg #define do_push push
228 1.1 mrg #define do_pop pop
229 1.1 mrg /* Perform an arithmetic operation with a variable shift operand. This
230 1.1 mrg requires two instructions and a scratch register on Thumb-2. */
231 1.1 mrg .macro shiftop name, dest, src1, src2, shiftop, shiftreg, tmp
232 1.1 mrg \shiftop \tmp, \src2, \shiftreg
233 1.1 mrg \name \dest, \src1, \tmp
234 1.1 mrg .endm
235 1.1 mrg #else
236 1.1 mrg .macro do_it cond, suffix=""
237 1.1 mrg .endm
238 1.1 mrg .macro shift1 op, arg0, arg1, arg2
239 1.1 mrg mov \arg0, \arg1, \op \arg2
240 1.1 mrg .endm
241 1.1 mrg #define do_push stmfd sp!,
242 1.1 mrg #define do_pop ldmfd sp!,
243 1.1 mrg .macro shiftop name, dest, src1, src2, shiftop, shiftreg, tmp
244 1.1 mrg \name \dest, \src1, \src2, \shiftop \shiftreg
245 1.1 mrg .endm
246 1.1 mrg #endif
247 1.1 mrg
248 1.1.1.9 mrg #define COND(op1, op2, cond) op1 ## op2 ## cond
249 1.1.1.9 mrg
250 1.1 mrg #ifdef __ARM_EABI__
251 1.1 mrg .macro ARM_LDIV0 name signed
252 1.1 mrg cmp r0, #0
253 1.1 mrg .ifc \signed, unsigned
254 1.1 mrg movne r0, #0xffffffff
255 1.1 mrg .else
256 1.1 mrg movgt r0, #0x7fffffff
257 1.1 mrg movlt r0, #0x80000000
258 1.1 mrg .endif
259 1.1 mrg b SYM (__aeabi_idiv0) __PLT__
260 1.1 mrg .endm
261 1.1 mrg #else
262 1.1 mrg .macro ARM_LDIV0 name signed
263 1.1 mrg str lr, [sp, #-8]!
264 1.1 mrg 98: cfi_push 98b - __\name, 0xe, -0x8, 0x8
265 1.1 mrg bl SYM (__div0) __PLT__
266 1.1 mrg mov r0, #0 @ About as wrong as it could be.
267 1.1 mrg RETLDM unwind=98b
268 1.1 mrg .endm
269 1.1 mrg #endif
270 1.1 mrg
271 1.1 mrg
272 1.1 mrg #ifdef __ARM_EABI__
273 1.1 mrg .macro THUMB_LDIV0 name signed
274 1.1.1.4 mrg #ifdef NOT_ISA_TARGET_32BIT
275 1.1.1.4 mrg
276 1.1.1.4 mrg push {r0, lr}
277 1.1.1.9 mrg movs r0, #0
278 1.1.1.4 mrg bl SYM(__aeabi_idiv0)
279 1.1 mrg @ We know we are not on armv4t, so pop pc is safe.
280 1.1.1.4 mrg pop {r1, pc}
281 1.1.1.4 mrg
282 1.1 mrg #elif defined(__thumb2__)
283 1.1 mrg .syntax unified
284 1.1 mrg .ifc \signed, unsigned
285 1.1 mrg cbz r0, 1f
286 1.1 mrg mov r0, #0xffffffff
287 1.1 mrg 1:
288 1.1 mrg .else
289 1.1 mrg cmp r0, #0
290 1.1 mrg do_it gt
291 1.1 mrg movgt r0, #0x7fffffff
292 1.1 mrg do_it lt
293 1.1 mrg movlt r0, #0x80000000
294 1.1 mrg .endif
295 1.1 mrg b.w SYM(__aeabi_idiv0) __PLT__
296 1.1 mrg #else
297 1.1 mrg .align 2
298 1.1 mrg bx pc
299 1.1 mrg nop
300 1.1 mrg .arm
301 1.1 mrg cmp r0, #0
302 1.1 mrg .ifc \signed, unsigned
303 1.1 mrg movne r0, #0xffffffff
304 1.1 mrg .else
305 1.1 mrg movgt r0, #0x7fffffff
306 1.1 mrg movlt r0, #0x80000000
307 1.1 mrg .endif
308 1.1 mrg b SYM(__aeabi_idiv0) __PLT__
309 1.1 mrg .thumb
310 1.1 mrg #endif
311 1.1 mrg .endm
312 1.1 mrg #else
313 1.1 mrg .macro THUMB_LDIV0 name signed
314 1.1 mrg push { r1, lr }
315 1.1 mrg 98: cfi_push 98b - __\name, 0xe, -0x4, 0x8
316 1.1 mrg bl SYM (__div0)
317 1.1.1.9 mrg movs r0, #0 @ About as wrong as it could be.
318 1.1 mrg #if defined (__INTERWORKING__)
319 1.1 mrg pop { r1, r2 }
320 1.1 mrg bx r2
321 1.1 mrg #else
322 1.1 mrg pop { r1, pc }
323 1.1 mrg #endif
324 1.1 mrg .endm
325 1.1 mrg #endif
326 1.1 mrg
327 1.1 mrg .macro FUNC_END name
328 1.1 mrg SIZE (__\name)
329 1.1 mrg .endm
330 1.1 mrg
331 1.1 mrg .macro DIV_FUNC_END name signed
332 1.1 mrg cfi_start __\name, LSYM(Lend_div0)
333 1.1 mrg LSYM(Ldiv0):
334 1.1 mrg #ifdef __thumb__
335 1.1 mrg THUMB_LDIV0 \name \signed
336 1.1 mrg #else
337 1.1 mrg ARM_LDIV0 \name \signed
338 1.1 mrg #endif
339 1.1 mrg cfi_end LSYM(Lend_div0)
340 1.1 mrg FUNC_END \name
341 1.1 mrg .endm
342 1.1 mrg
343 1.1 mrg .macro THUMB_FUNC_START name
344 1.1 mrg .globl SYM (\name)
345 1.1 mrg TYPE (\name)
346 1.1 mrg .thumb_func
347 1.1 mrg SYM (\name):
348 1.1 mrg .endm
349 1.1 mrg
350 1.1 mrg /* Function start macros. Variants for ARM and Thumb. */
351 1.1 mrg
352 1.1 mrg #ifdef __thumb__
353 1.1 mrg #define THUMB_FUNC .thumb_func
354 1.1 mrg #define THUMB_CODE .force_thumb
355 1.1 mrg # if defined(__thumb2__)
356 1.1.1.9 mrg #define THUMB_SYNTAX
357 1.1 mrg # else
358 1.1 mrg #define THUMB_SYNTAX
359 1.1 mrg # endif
360 1.1 mrg #else
361 1.1 mrg #define THUMB_FUNC
362 1.1 mrg #define THUMB_CODE
363 1.1 mrg #define THUMB_SYNTAX
364 1.1 mrg #endif
365 1.1 mrg
366 1.1.1.8 mrg .macro FUNC_START name
367 1.1 mrg .text
368 1.1 mrg .globl SYM (__\name)
369 1.1 mrg TYPE (__\name)
370 1.1 mrg .align 0
371 1.1 mrg THUMB_CODE
372 1.1 mrg THUMB_FUNC
373 1.1 mrg THUMB_SYNTAX
374 1.1 mrg SYM (__\name):
375 1.1 mrg .endm
376 1.1 mrg
377 1.1.1.2 mrg .macro ARM_SYM_START name
378 1.1.1.2 mrg TYPE (\name)
379 1.1.1.2 mrg .align 0
380 1.1.1.2 mrg SYM (\name):
381 1.1.1.2 mrg .endm
382 1.1.1.2 mrg
383 1.1.1.2 mrg .macro SYM_END name
384 1.1.1.2 mrg SIZE (\name)
385 1.1.1.2 mrg .endm
386 1.1.1.2 mrg
387 1.1 mrg /* Special function that will always be coded in ARM assembly, even if
388 1.1 mrg in Thumb-only compilation. */
389 1.1 mrg
390 1.1 mrg #if defined(__thumb2__)
391 1.1 mrg
392 1.1 mrg /* For Thumb-2 we build everything in thumb mode. */
393 1.1.1.8 mrg .macro ARM_FUNC_START name
394 1.1.1.8 mrg FUNC_START \name
395 1.1 mrg .syntax unified
396 1.1 mrg .endm
397 1.1 mrg #define EQUIV .thumb_set
398 1.1 mrg .macro ARM_CALL name
399 1.1 mrg bl __\name
400 1.1 mrg .endm
401 1.1 mrg
402 1.1 mrg #elif defined(__INTERWORKING_STUBS__)
403 1.1 mrg
404 1.1 mrg .macro ARM_FUNC_START name
405 1.1 mrg FUNC_START \name
406 1.1 mrg bx pc
407 1.1 mrg nop
408 1.1 mrg .arm
409 1.1 mrg /* A hook to tell gdb that we've switched to ARM mode. Also used to call
410 1.1 mrg directly from other local arm routines. */
411 1.1 mrg _L__\name:
412 1.1 mrg .endm
413 1.1 mrg #define EQUIV .thumb_set
414 1.1 mrg /* Branch directly to a function declared with ARM_FUNC_START.
415 1.1 mrg Must be called in arm mode. */
416 1.1 mrg .macro ARM_CALL name
417 1.1 mrg bl _L__\name
418 1.1 mrg .endm
419 1.1 mrg
420 1.1 mrg #else /* !(__INTERWORKING_STUBS__ || __thumb2__) */
421 1.1 mrg
422 1.1.1.4 mrg #ifdef NOT_ISA_TARGET_32BIT
423 1.1 mrg #define EQUIV .thumb_set
424 1.1 mrg #else
425 1.1.1.8 mrg .macro ARM_FUNC_START name
426 1.1 mrg .text
427 1.1 mrg .globl SYM (__\name)
428 1.1 mrg TYPE (__\name)
429 1.1 mrg .align 0
430 1.1 mrg .arm
431 1.1 mrg SYM (__\name):
432 1.1 mrg .endm
433 1.1 mrg #define EQUIV .set
434 1.1 mrg .macro ARM_CALL name
435 1.1 mrg bl __\name
436 1.1 mrg .endm
437 1.1 mrg #endif
438 1.1 mrg
439 1.1 mrg #endif
440 1.1 mrg
441 1.1 mrg .macro FUNC_ALIAS new old
442 1.1 mrg .globl SYM (__\new)
443 1.1 mrg #if defined (__thumb__)
444 1.1 mrg .thumb_set SYM (__\new), SYM (__\old)
445 1.1 mrg #else
446 1.1 mrg .set SYM (__\new), SYM (__\old)
447 1.1 mrg #endif
448 1.1 mrg .endm
449 1.1 mrg
450 1.1.1.4 mrg #ifndef NOT_ISA_TARGET_32BIT
451 1.1 mrg .macro ARM_FUNC_ALIAS new old
452 1.1 mrg .globl SYM (__\new)
453 1.1 mrg EQUIV SYM (__\new), SYM (__\old)
454 1.1 mrg #if defined(__INTERWORKING_STUBS__)
455 1.1 mrg .set SYM (_L__\new), SYM (_L__\old)
456 1.1 mrg #endif
457 1.1 mrg .endm
458 1.1 mrg #endif
459 1.1 mrg
460 1.1 mrg #ifdef __ARMEB__
461 1.1 mrg #define xxh r0
462 1.1 mrg #define xxl r1
463 1.1 mrg #define yyh r2
464 1.1 mrg #define yyl r3
465 1.1 mrg #else
466 1.1 mrg #define xxh r1
467 1.1 mrg #define xxl r0
468 1.1 mrg #define yyh r3
469 1.1 mrg #define yyl r2
470 1.1 mrg #endif
471 1.1 mrg
472 1.1 mrg #ifdef __ARM_EABI__
473 1.1 mrg .macro WEAK name
474 1.1 mrg .weak SYM (__\name)
475 1.1 mrg .endm
476 1.1 mrg #endif
477 1.1 mrg
478 1.1 mrg #ifdef __thumb__
479 1.1 mrg /* Register aliases. */
480 1.1 mrg
481 1.1 mrg work .req r4 @ XXXX is this safe ?
482 1.1 mrg dividend .req r0
483 1.1 mrg divisor .req r1
484 1.1 mrg overdone .req r2
485 1.1 mrg result .req r2
486 1.1 mrg curbit .req r3
487 1.1 mrg #endif
488 1.1 mrg #if 0
489 1.1 mrg ip .req r12
490 1.1 mrg sp .req r13
491 1.1 mrg lr .req r14
492 1.1 mrg pc .req r15
493 1.1 mrg #endif
494 1.1 mrg
495 1.1 mrg /* ------------------------------------------------------------------------ */
496 1.1 mrg /* Bodies of the division and modulo routines. */
497 1.1.1.9 mrg /* ------------------------------------------------------------------------ */
498 1.1.1.9 mrg
499 1.1 mrg .macro ARM_DIV_BODY dividend, divisor, result, curbit
500 1.1 mrg
501 1.1.1.8 mrg #if defined (__ARM_FEATURE_CLZ) && ! defined (__OPTIMIZE_SIZE__)
502 1.1 mrg
503 1.1 mrg #if defined (__thumb2__)
504 1.1 mrg clz \curbit, \dividend
505 1.1 mrg clz \result, \divisor
506 1.1 mrg sub \curbit, \result, \curbit
507 1.1 mrg rsb \curbit, \curbit, #31
508 1.1 mrg adr \result, 1f
509 1.1 mrg add \curbit, \result, \curbit, lsl #4
510 1.1 mrg mov \result, #0
511 1.1 mrg mov pc, \curbit
512 1.1 mrg .p2align 3
513 1.1 mrg 1:
514 1.1 mrg .set shift, 32
515 1.1 mrg .rept 32
516 1.1 mrg .set shift, shift - 1
517 1.1 mrg cmp.w \dividend, \divisor, lsl #shift
518 1.1 mrg nop.n
519 1.1 mrg adc.w \result, \result, \result
520 1.1 mrg it cs
521 1.1 mrg subcs.w \dividend, \dividend, \divisor, lsl #shift
522 1.1 mrg .endr
523 1.1 mrg #else
524 1.1 mrg clz \curbit, \dividend
525 1.1 mrg clz \result, \divisor
526 1.1 mrg sub \curbit, \result, \curbit
527 1.1 mrg rsbs \curbit, \curbit, #31
528 1.1 mrg addne \curbit, \curbit, \curbit, lsl #1
529 1.1 mrg mov \result, #0
530 1.1 mrg addne pc, pc, \curbit, lsl #2
531 1.1 mrg nop
532 1.1 mrg .set shift, 32
533 1.1 mrg .rept 32
534 1.1 mrg .set shift, shift - 1
535 1.1 mrg cmp \dividend, \divisor, lsl #shift
536 1.1 mrg adc \result, \result, \result
537 1.1 mrg subcs \dividend, \dividend, \divisor, lsl #shift
538 1.1 mrg .endr
539 1.1 mrg #endif
540 1.1 mrg
541 1.1.1.8 mrg #else /* !defined (__ARM_FEATURE_CLZ) || defined (__OPTIMIZE_SIZE__) */
542 1.1.1.8 mrg #if defined (__ARM_FEATURE_CLZ)
543 1.1 mrg
544 1.1 mrg clz \curbit, \divisor
545 1.1 mrg clz \result, \dividend
546 1.1 mrg sub \result, \curbit, \result
547 1.1 mrg mov \curbit, #1
548 1.1 mrg mov \divisor, \divisor, lsl \result
549 1.1 mrg mov \curbit, \curbit, lsl \result
550 1.1 mrg mov \result, #0
551 1.1 mrg
552 1.1.1.8 mrg #else /* !defined (__ARM_FEATURE_CLZ) */
553 1.1 mrg
554 1.1 mrg @ Initially shift the divisor left 3 bits if possible,
555 1.1 mrg @ set curbit accordingly. This allows for curbit to be located
556 1.1 mrg @ at the left end of each 4-bit nibbles in the division loop
557 1.1 mrg @ to save one loop in most cases.
558 1.1 mrg tst \divisor, #0xe0000000
559 1.1 mrg moveq \divisor, \divisor, lsl #3
560 1.1 mrg moveq \curbit, #8
561 1.1 mrg movne \curbit, #1
562 1.1 mrg
563 1.1 mrg @ Unless the divisor is very big, shift it up in multiples of
564 1.1 mrg @ four bits, since this is the amount of unwinding in the main
565 1.1 mrg @ division loop. Continue shifting until the divisor is
566 1.1 mrg @ larger than the dividend.
567 1.1 mrg 1: cmp \divisor, #0x10000000
568 1.1 mrg cmplo \divisor, \dividend
569 1.1 mrg movlo \divisor, \divisor, lsl #4
570 1.1 mrg movlo \curbit, \curbit, lsl #4
571 1.1 mrg blo 1b
572 1.1 mrg
573 1.1 mrg @ For very big divisors, we must shift it a bit at a time, or
574 1.1 mrg @ we will be in danger of overflowing.
575 1.1 mrg 1: cmp \divisor, #0x80000000
576 1.1 mrg cmplo \divisor, \dividend
577 1.1 mrg movlo \divisor, \divisor, lsl #1
578 1.1 mrg movlo \curbit, \curbit, lsl #1
579 1.1 mrg blo 1b
580 1.1 mrg
581 1.1 mrg mov \result, #0
582 1.1 mrg
583 1.1.1.8 mrg #endif /* !defined (__ARM_FEATURE_CLZ) */
584 1.1 mrg
585 1.1 mrg @ Division loop
586 1.1 mrg 1: cmp \dividend, \divisor
587 1.1 mrg do_it hs, t
588 1.1 mrg subhs \dividend, \dividend, \divisor
589 1.1 mrg orrhs \result, \result, \curbit
590 1.1 mrg cmp \dividend, \divisor, lsr #1
591 1.1 mrg do_it hs, t
592 1.1 mrg subhs \dividend, \dividend, \divisor, lsr #1
593 1.1 mrg orrhs \result, \result, \curbit, lsr #1
594 1.1 mrg cmp \dividend, \divisor, lsr #2
595 1.1 mrg do_it hs, t
596 1.1 mrg subhs \dividend, \dividend, \divisor, lsr #2
597 1.1 mrg orrhs \result, \result, \curbit, lsr #2
598 1.1 mrg cmp \dividend, \divisor, lsr #3
599 1.1 mrg do_it hs, t
600 1.1 mrg subhs \dividend, \dividend, \divisor, lsr #3
601 1.1 mrg orrhs \result, \result, \curbit, lsr #3
602 1.1 mrg cmp \dividend, #0 @ Early termination?
603 1.1 mrg do_it ne, t
604 1.1 mrg movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
605 1.1 mrg movne \divisor, \divisor, lsr #4
606 1.1 mrg bne 1b
607 1.1 mrg
608 1.1.1.8 mrg #endif /* !defined (__ARM_FEATURE_CLZ) || defined (__OPTIMIZE_SIZE__) */
609 1.1 mrg
610 1.1 mrg .endm
611 1.1 mrg /* ------------------------------------------------------------------------ */
612 1.1 mrg .macro ARM_DIV2_ORDER divisor, order
613 1.1 mrg
614 1.1.1.8 mrg #if defined (__ARM_FEATURE_CLZ)
615 1.1 mrg
616 1.1 mrg clz \order, \divisor
617 1.1 mrg rsb \order, \order, #31
618 1.1 mrg
619 1.1 mrg #else
620 1.1 mrg
621 1.1 mrg cmp \divisor, #(1 << 16)
622 1.1 mrg movhs \divisor, \divisor, lsr #16
623 1.1 mrg movhs \order, #16
624 1.1 mrg movlo \order, #0
625 1.1 mrg
626 1.1 mrg cmp \divisor, #(1 << 8)
627 1.1 mrg movhs \divisor, \divisor, lsr #8
628 1.1 mrg addhs \order, \order, #8
629 1.1 mrg
630 1.1 mrg cmp \divisor, #(1 << 4)
631 1.1 mrg movhs \divisor, \divisor, lsr #4
632 1.1 mrg addhs \order, \order, #4
633 1.1 mrg
634 1.1 mrg cmp \divisor, #(1 << 2)
635 1.1 mrg addhi \order, \order, #3
636 1.1 mrg addls \order, \order, \divisor, lsr #1
637 1.1 mrg
638 1.1 mrg #endif
639 1.1 mrg
640 1.1 mrg .endm
641 1.1 mrg /* ------------------------------------------------------------------------ */
642 1.1 mrg .macro ARM_MOD_BODY dividend, divisor, order, spare
643 1.1 mrg
644 1.1.1.8 mrg #if defined(__ARM_FEATURE_CLZ) && ! defined (__OPTIMIZE_SIZE__)
645 1.1 mrg
646 1.1 mrg clz \order, \divisor
647 1.1 mrg clz \spare, \dividend
648 1.1 mrg sub \order, \order, \spare
649 1.1 mrg rsbs \order, \order, #31
650 1.1 mrg addne pc, pc, \order, lsl #3
651 1.1 mrg nop
652 1.1 mrg .set shift, 32
653 1.1 mrg .rept 32
654 1.1 mrg .set shift, shift - 1
655 1.1 mrg cmp \dividend, \divisor, lsl #shift
656 1.1 mrg subcs \dividend, \dividend, \divisor, lsl #shift
657 1.1 mrg .endr
658 1.1 mrg
659 1.1.1.8 mrg #else /* !defined (__ARM_FEATURE_CLZ) || defined (__OPTIMIZE_SIZE__) */
660 1.1.1.8 mrg #if defined (__ARM_FEATURE_CLZ)
661 1.1 mrg
662 1.1 mrg clz \order, \divisor
663 1.1 mrg clz \spare, \dividend
664 1.1 mrg sub \order, \order, \spare
665 1.1 mrg mov \divisor, \divisor, lsl \order
666 1.1 mrg
667 1.1.1.8 mrg #else /* !defined (__ARM_FEATURE_CLZ) */
668 1.1 mrg
669 1.1 mrg mov \order, #0
670 1.1 mrg
671 1.1 mrg @ Unless the divisor is very big, shift it up in multiples of
672 1.1 mrg @ four bits, since this is the amount of unwinding in the main
673 1.1 mrg @ division loop. Continue shifting until the divisor is
674 1.1 mrg @ larger than the dividend.
675 1.1 mrg 1: cmp \divisor, #0x10000000
676 1.1 mrg cmplo \divisor, \dividend
677 1.1 mrg movlo \divisor, \divisor, lsl #4
678 1.1 mrg addlo \order, \order, #4
679 1.1 mrg blo 1b
680 1.1 mrg
681 1.1 mrg @ For very big divisors, we must shift it a bit at a time, or
682 1.1 mrg @ we will be in danger of overflowing.
683 1.1 mrg 1: cmp \divisor, #0x80000000
684 1.1 mrg cmplo \divisor, \dividend
685 1.1 mrg movlo \divisor, \divisor, lsl #1
686 1.1 mrg addlo \order, \order, #1
687 1.1 mrg blo 1b
688 1.1 mrg
689 1.1.1.8 mrg #endif /* !defined (__ARM_FEATURE_CLZ) */
690 1.1 mrg
691 1.1 mrg @ Perform all needed substractions to keep only the reminder.
692 1.1 mrg @ Do comparisons in batch of 4 first.
693 1.1 mrg subs \order, \order, #3 @ yes, 3 is intended here
694 1.1 mrg blt 2f
695 1.1 mrg
696 1.1 mrg 1: cmp \dividend, \divisor
697 1.1 mrg subhs \dividend, \dividend, \divisor
698 1.1 mrg cmp \dividend, \divisor, lsr #1
699 1.1 mrg subhs \dividend, \dividend, \divisor, lsr #1
700 1.1 mrg cmp \dividend, \divisor, lsr #2
701 1.1 mrg subhs \dividend, \dividend, \divisor, lsr #2
702 1.1 mrg cmp \dividend, \divisor, lsr #3
703 1.1 mrg subhs \dividend, \dividend, \divisor, lsr #3
704 1.1 mrg cmp \dividend, #1
705 1.1 mrg mov \divisor, \divisor, lsr #4
706 1.1 mrg subges \order, \order, #4
707 1.1 mrg bge 1b
708 1.1 mrg
709 1.1 mrg tst \order, #3
710 1.1 mrg teqne \dividend, #0
711 1.1 mrg beq 5f
712 1.1 mrg
713 1.1 mrg @ Either 1, 2 or 3 comparison/substractions are left.
714 1.1 mrg 2: cmn \order, #2
715 1.1 mrg blt 4f
716 1.1 mrg beq 3f
717 1.1 mrg cmp \dividend, \divisor
718 1.1 mrg subhs \dividend, \dividend, \divisor
719 1.1 mrg mov \divisor, \divisor, lsr #1
720 1.1 mrg 3: cmp \dividend, \divisor
721 1.1 mrg subhs \dividend, \dividend, \divisor
722 1.1 mrg mov \divisor, \divisor, lsr #1
723 1.1 mrg 4: cmp \dividend, \divisor
724 1.1 mrg subhs \dividend, \dividend, \divisor
725 1.1 mrg 5:
726 1.1 mrg
727 1.1.1.8 mrg #endif /* !defined (__ARM_FEATURE_CLZ) || defined (__OPTIMIZE_SIZE__) */
728 1.1 mrg
729 1.1 mrg .endm
730 1.1 mrg /* ------------------------------------------------------------------------ */
731 1.1 mrg .macro THUMB_DIV_MOD_BODY modulo
732 1.1 mrg @ Load the constant 0x10000000 into our work register.
733 1.1.1.9 mrg movs work, #1
734 1.1.1.9 mrg lsls work, #28
735 1.1 mrg LSYM(Loop1):
736 1.1 mrg @ Unless the divisor is very big, shift it up in multiples of
737 1.1 mrg @ four bits, since this is the amount of unwinding in the main
738 1.1 mrg @ division loop. Continue shifting until the divisor is
739 1.1 mrg @ larger than the dividend.
740 1.1 mrg cmp divisor, work
741 1.1 mrg bhs LSYM(Lbignum)
742 1.1 mrg cmp divisor, dividend
743 1.1 mrg bhs LSYM(Lbignum)
744 1.1.1.9 mrg lsls divisor, #4
745 1.1.1.9 mrg lsls curbit, #4
746 1.1 mrg b LSYM(Loop1)
747 1.1 mrg LSYM(Lbignum):
748 1.1 mrg @ Set work to 0x80000000
749 1.1.1.9 mrg lsls work, #3
750 1.1 mrg LSYM(Loop2):
751 1.1 mrg @ For very big divisors, we must shift it a bit at a time, or
752 1.1 mrg @ we will be in danger of overflowing.
753 1.1 mrg cmp divisor, work
754 1.1 mrg bhs LSYM(Loop3)
755 1.1 mrg cmp divisor, dividend
756 1.1 mrg bhs LSYM(Loop3)
757 1.1.1.9 mrg lsls divisor, #1
758 1.1.1.9 mrg lsls curbit, #1
759 1.1 mrg b LSYM(Loop2)
760 1.1 mrg LSYM(Loop3):
761 1.1 mrg @ Test for possible subtractions ...
762 1.1 mrg .if \modulo
763 1.1 mrg @ ... On the final pass, this may subtract too much from the dividend,
764 1.1 mrg @ so keep track of which subtractions are done, we can fix them up
765 1.1 mrg @ afterwards.
766 1.1.1.9 mrg movs overdone, #0
767 1.1 mrg cmp dividend, divisor
768 1.1 mrg blo LSYM(Lover1)
769 1.1.1.9 mrg subs dividend, dividend, divisor
770 1.1 mrg LSYM(Lover1):
771 1.1.1.9 mrg lsrs work, divisor, #1
772 1.1 mrg cmp dividend, work
773 1.1 mrg blo LSYM(Lover2)
774 1.1.1.9 mrg subs dividend, dividend, work
775 1.1 mrg mov ip, curbit
776 1.1.1.9 mrg movs work, #1
777 1.1.1.9 mrg rors curbit, work
778 1.1.1.9 mrg orrs overdone, curbit
779 1.1 mrg mov curbit, ip
780 1.1 mrg LSYM(Lover2):
781 1.1.1.9 mrg lsrs work, divisor, #2
782 1.1 mrg cmp dividend, work
783 1.1 mrg blo LSYM(Lover3)
784 1.1.1.9 mrg subs dividend, dividend, work
785 1.1 mrg mov ip, curbit
786 1.1.1.9 mrg movs work, #2
787 1.1.1.9 mrg rors curbit, work
788 1.1.1.9 mrg orrs overdone, curbit
789 1.1 mrg mov curbit, ip
790 1.1 mrg LSYM(Lover3):
791 1.1.1.9 mrg lsrs work, divisor, #3
792 1.1 mrg cmp dividend, work
793 1.1 mrg blo LSYM(Lover4)
794 1.1.1.9 mrg subs dividend, dividend, work
795 1.1 mrg mov ip, curbit
796 1.1.1.9 mrg movs work, #3
797 1.1.1.9 mrg rors curbit, work
798 1.1.1.9 mrg orrs overdone, curbit
799 1.1 mrg mov curbit, ip
800 1.1 mrg LSYM(Lover4):
801 1.1 mrg mov ip, curbit
802 1.1 mrg .else
803 1.1 mrg @ ... and note which bits are done in the result. On the final pass,
804 1.1 mrg @ this may subtract too much from the dividend, but the result will be ok,
805 1.1 mrg @ since the "bit" will have been shifted out at the bottom.
806 1.1 mrg cmp dividend, divisor
807 1.1 mrg blo LSYM(Lover1)
808 1.1.1.9 mrg subs dividend, dividend, divisor
809 1.1.1.9 mrg orrs result, result, curbit
810 1.1 mrg LSYM(Lover1):
811 1.1.1.9 mrg lsrs work, divisor, #1
812 1.1 mrg cmp dividend, work
813 1.1 mrg blo LSYM(Lover2)
814 1.1.1.9 mrg subs dividend, dividend, work
815 1.1.1.9 mrg lsrs work, curbit, #1
816 1.1.1.9 mrg orrs result, work
817 1.1 mrg LSYM(Lover2):
818 1.1.1.9 mrg lsrs work, divisor, #2
819 1.1 mrg cmp dividend, work
820 1.1 mrg blo LSYM(Lover3)
821 1.1.1.9 mrg subs dividend, dividend, work
822 1.1.1.9 mrg lsrs work, curbit, #2
823 1.1.1.9 mrg orrs result, work
824 1.1 mrg LSYM(Lover3):
825 1.1.1.9 mrg lsrs work, divisor, #3
826 1.1 mrg cmp dividend, work
827 1.1 mrg blo LSYM(Lover4)
828 1.1.1.9 mrg subs dividend, dividend, work
829 1.1.1.9 mrg lsrs work, curbit, #3
830 1.1.1.9 mrg orrs result, work
831 1.1 mrg LSYM(Lover4):
832 1.1 mrg .endif
833 1.1 mrg
834 1.1 mrg cmp dividend, #0 @ Early termination?
835 1.1 mrg beq LSYM(Lover5)
836 1.1.1.9 mrg lsrs curbit, #4 @ No, any more bits to do?
837 1.1 mrg beq LSYM(Lover5)
838 1.1.1.9 mrg lsrs divisor, #4
839 1.1 mrg b LSYM(Loop3)
840 1.1 mrg LSYM(Lover5):
841 1.1 mrg .if \modulo
842 1.1 mrg @ Any subtractions that we should not have done will be recorded in
843 1.1 mrg @ the top three bits of "overdone". Exactly which were not needed
844 1.1 mrg @ are governed by the position of the bit, stored in ip.
845 1.1.1.9 mrg movs work, #0xe
846 1.1.1.9 mrg lsls work, #28
847 1.1.1.9 mrg ands overdone, work
848 1.1 mrg beq LSYM(Lgot_result)
849 1.1 mrg
850 1.1 mrg @ If we terminated early, because dividend became zero, then the
851 1.1 mrg @ bit in ip will not be in the bottom nibble, and we should not
852 1.1 mrg @ perform the additions below. We must test for this though
853 1.1 mrg @ (rather relying upon the TSTs to prevent the additions) since
854 1.1 mrg @ the bit in ip could be in the top two bits which might then match
855 1.1 mrg @ with one of the smaller RORs.
856 1.1 mrg mov curbit, ip
857 1.1.1.9 mrg movs work, #0x7
858 1.1 mrg tst curbit, work
859 1.1 mrg beq LSYM(Lgot_result)
860 1.1 mrg
861 1.1 mrg mov curbit, ip
862 1.1.1.9 mrg movs work, #3
863 1.1.1.9 mrg rors curbit, work
864 1.1 mrg tst overdone, curbit
865 1.1 mrg beq LSYM(Lover6)
866 1.1.1.9 mrg lsrs work, divisor, #3
867 1.1.1.9 mrg adds dividend, work
868 1.1 mrg LSYM(Lover6):
869 1.1 mrg mov curbit, ip
870 1.1.1.9 mrg movs work, #2
871 1.1.1.9 mrg rors curbit, work
872 1.1 mrg tst overdone, curbit
873 1.1 mrg beq LSYM(Lover7)
874 1.1.1.9 mrg lsrs work, divisor, #2
875 1.1.1.9 mrg adds dividend, work
876 1.1 mrg LSYM(Lover7):
877 1.1 mrg mov curbit, ip
878 1.1.1.9 mrg movs work, #1
879 1.1.1.9 mrg rors curbit, work
880 1.1 mrg tst overdone, curbit
881 1.1 mrg beq LSYM(Lgot_result)
882 1.1.1.9 mrg lsrs work, divisor, #1
883 1.1.1.9 mrg adds dividend, work
884 1.1 mrg .endif
885 1.1 mrg LSYM(Lgot_result):
886 1.1.1.4 mrg .endm
887 1.1.1.4 mrg
888 1.1.1.4 mrg /* If performance is preferred, the following functions are provided. */
889 1.1.1.4 mrg #if defined(__prefer_thumb__) && !defined(__OPTIMIZE_SIZE__)
890 1.1.1.4 mrg
891 1.1.1.4 mrg /* Branch to div(n), and jump to label if curbit is lo than divisior. */
892 1.1.1.4 mrg .macro BranchToDiv n, label
893 1.1.1.9 mrg lsrs curbit, dividend, \n
894 1.1.1.4 mrg cmp curbit, divisor
895 1.1.1.4 mrg blo \label
896 1.1.1.4 mrg .endm
897 1.1.1.4 mrg
898 1.1.1.4 mrg /* Body of div(n). Shift the divisor in n bits and compare the divisor
899 1.1.1.4 mrg and dividend. Update the dividend as the substruction result. */
900 1.1.1.4 mrg .macro DoDiv n
901 1.1.1.9 mrg lsrs curbit, dividend, \n
902 1.1.1.4 mrg cmp curbit, divisor
903 1.1.1.4 mrg bcc 1f
904 1.1.1.9 mrg lsls curbit, divisor, \n
905 1.1.1.9 mrg subs dividend, dividend, curbit
906 1.1.1.4 mrg
907 1.1.1.9 mrg 1: adcs result, result
908 1.1.1.4 mrg .endm
909 1.1.1.4 mrg
910 1.1.1.4 mrg /* The body of division with positive divisor. Unless the divisor is very
911 1.1.1.4 mrg big, shift it up in multiples of four bits, since this is the amount of
912 1.1.1.4 mrg unwinding in the main division loop. Continue shifting until the divisor
913 1.1.1.4 mrg is larger than the dividend. */
914 1.1.1.4 mrg .macro THUMB1_Div_Positive
915 1.1.1.9 mrg movs result, #0
916 1.1.1.4 mrg BranchToDiv #1, LSYM(Lthumb1_div1)
917 1.1.1.4 mrg BranchToDiv #4, LSYM(Lthumb1_div4)
918 1.1.1.4 mrg BranchToDiv #8, LSYM(Lthumb1_div8)
919 1.1.1.4 mrg BranchToDiv #12, LSYM(Lthumb1_div12)
920 1.1.1.4 mrg BranchToDiv #16, LSYM(Lthumb1_div16)
921 1.1.1.4 mrg LSYM(Lthumb1_div_large_positive):
922 1.1.1.9 mrg movs result, #0xff
923 1.1.1.9 mrg lsls divisor, divisor, #8
924 1.1.1.4 mrg rev result, result
925 1.1.1.9 mrg lsrs curbit, dividend, #16
926 1.1.1.4 mrg cmp curbit, divisor
927 1.1.1.4 mrg blo 1f
928 1.1.1.9 mrg asrs result, #8
929 1.1.1.9 mrg lsls divisor, divisor, #8
930 1.1.1.4 mrg beq LSYM(Ldivbyzero_waypoint)
931 1.1.1.4 mrg
932 1.1.1.9 mrg 1: lsrs curbit, dividend, #12
933 1.1.1.4 mrg cmp curbit, divisor
934 1.1.1.4 mrg blo LSYM(Lthumb1_div12)
935 1.1.1.4 mrg b LSYM(Lthumb1_div16)
936 1.1.1.4 mrg LSYM(Lthumb1_div_loop):
937 1.1.1.9 mrg lsrs divisor, divisor, #8
938 1.1.1.4 mrg LSYM(Lthumb1_div16):
939 1.1.1.4 mrg Dodiv #15
940 1.1.1.4 mrg Dodiv #14
941 1.1.1.4 mrg Dodiv #13
942 1.1.1.4 mrg Dodiv #12
943 1.1.1.4 mrg LSYM(Lthumb1_div12):
944 1.1.1.4 mrg Dodiv #11
945 1.1.1.4 mrg Dodiv #10
946 1.1.1.4 mrg Dodiv #9
947 1.1.1.4 mrg Dodiv #8
948 1.1.1.4 mrg bcs LSYM(Lthumb1_div_loop)
949 1.1.1.4 mrg LSYM(Lthumb1_div8):
950 1.1.1.4 mrg Dodiv #7
951 1.1.1.4 mrg Dodiv #6
952 1.1.1.4 mrg Dodiv #5
953 1.1.1.4 mrg LSYM(Lthumb1_div5):
954 1.1.1.4 mrg Dodiv #4
955 1.1.1.4 mrg LSYM(Lthumb1_div4):
956 1.1.1.4 mrg Dodiv #3
957 1.1.1.4 mrg LSYM(Lthumb1_div3):
958 1.1.1.4 mrg Dodiv #2
959 1.1.1.4 mrg LSYM(Lthumb1_div2):
960 1.1.1.4 mrg Dodiv #1
961 1.1.1.4 mrg LSYM(Lthumb1_div1):
962 1.1.1.9 mrg subs divisor, dividend, divisor
963 1.1.1.4 mrg bcs 1f
964 1.1.1.4 mrg cpy divisor, dividend
965 1.1.1.4 mrg
966 1.1.1.9 mrg 1: adcs result, result
967 1.1.1.4 mrg cpy dividend, result
968 1.1.1.4 mrg RET
969 1.1.1.4 mrg
970 1.1.1.4 mrg LSYM(Ldivbyzero_waypoint):
971 1.1.1.4 mrg b LSYM(Ldiv0)
972 1.1.1.4 mrg .endm
973 1.1.1.4 mrg
974 1.1.1.4 mrg /* The body of division with negative divisor. Similar with
975 1.1.1.4 mrg THUMB1_Div_Positive except that the shift steps are in multiples
976 1.1.1.4 mrg of six bits. */
977 1.1.1.4 mrg .macro THUMB1_Div_Negative
978 1.1.1.9 mrg lsrs result, divisor, #31
979 1.1.1.4 mrg beq 1f
980 1.1.1.9 mrg negs divisor, divisor
981 1.1.1.4 mrg
982 1.1.1.9 mrg 1: asrs curbit, dividend, #32
983 1.1.1.4 mrg bcc 2f
984 1.1.1.9 mrg negs dividend, dividend
985 1.1.1.4 mrg
986 1.1.1.9 mrg 2: eors curbit, result
987 1.1.1.9 mrg movs result, #0
988 1.1.1.4 mrg cpy ip, curbit
989 1.1.1.4 mrg BranchToDiv #4, LSYM(Lthumb1_div_negative4)
990 1.1.1.4 mrg BranchToDiv #8, LSYM(Lthumb1_div_negative8)
991 1.1.1.4 mrg LSYM(Lthumb1_div_large):
992 1.1.1.9 mrg movs result, #0xfc
993 1.1.1.9 mrg lsls divisor, divisor, #6
994 1.1.1.4 mrg rev result, result
995 1.1.1.9 mrg lsrs curbit, dividend, #8
996 1.1.1.4 mrg cmp curbit, divisor
997 1.1.1.4 mrg blo LSYM(Lthumb1_div_negative8)
998 1.1.1.4 mrg
999 1.1.1.9 mrg lsls divisor, divisor, #6
1000 1.1.1.9 mrg asrs result, result, #6
1001 1.1.1.4 mrg cmp curbit, divisor
1002 1.1.1.4 mrg blo LSYM(Lthumb1_div_negative8)
1003 1.1.1.4 mrg
1004 1.1.1.9 mrg lsls divisor, divisor, #6
1005 1.1.1.9 mrg asrs result, result, #6
1006 1.1.1.4 mrg cmp curbit, divisor
1007 1.1.1.4 mrg blo LSYM(Lthumb1_div_negative8)
1008 1.1.1.4 mrg
1009 1.1.1.9 mrg lsls divisor, divisor, #6
1010 1.1.1.4 mrg beq LSYM(Ldivbyzero_negative)
1011 1.1.1.9 mrg asrs result, result, #6
1012 1.1.1.4 mrg b LSYM(Lthumb1_div_negative8)
1013 1.1.1.4 mrg LSYM(Lthumb1_div_negative_loop):
1014 1.1.1.9 mrg lsrs divisor, divisor, #6
1015 1.1.1.4 mrg LSYM(Lthumb1_div_negative8):
1016 1.1.1.4 mrg DoDiv #7
1017 1.1.1.4 mrg DoDiv #6
1018 1.1.1.4 mrg DoDiv #5
1019 1.1.1.4 mrg DoDiv #4
1020 1.1.1.4 mrg LSYM(Lthumb1_div_negative4):
1021 1.1.1.4 mrg DoDiv #3
1022 1.1.1.4 mrg DoDiv #2
1023 1.1.1.4 mrg bcs LSYM(Lthumb1_div_negative_loop)
1024 1.1.1.4 mrg DoDiv #1
1025 1.1.1.9 mrg subs divisor, dividend, divisor
1026 1.1.1.4 mrg bcs 1f
1027 1.1.1.4 mrg cpy divisor, dividend
1028 1.1.1.4 mrg
1029 1.1.1.4 mrg 1: cpy curbit, ip
1030 1.1.1.9 mrg adcs result, result
1031 1.1.1.9 mrg asrs curbit, curbit, #1
1032 1.1.1.4 mrg cpy dividend, result
1033 1.1.1.4 mrg bcc 2f
1034 1.1.1.9 mrg negs dividend, dividend
1035 1.1.1.4 mrg cmp curbit, #0
1036 1.1.1.4 mrg
1037 1.1.1.4 mrg 2: bpl 3f
1038 1.1.1.9 mrg negs divisor, divisor
1039 1.1.1.4 mrg
1040 1.1.1.4 mrg 3: RET
1041 1.1.1.4 mrg
1042 1.1.1.4 mrg LSYM(Ldivbyzero_negative):
1043 1.1.1.4 mrg cpy curbit, ip
1044 1.1.1.9 mrg asrs curbit, curbit, #1
1045 1.1.1.4 mrg bcc LSYM(Ldiv0)
1046 1.1.1.9 mrg negs dividend, dividend
1047 1.1.1.4 mrg .endm
1048 1.1.1.4 mrg #endif /* ARM Thumb version. */
1049 1.1.1.4 mrg
1050 1.1 mrg /* ------------------------------------------------------------------------ */
1051 1.1 mrg /* Start of the Real Functions */
1052 1.1 mrg /* ------------------------------------------------------------------------ */
1053 1.1 mrg #ifdef L_udivsi3
1054 1.1 mrg
1055 1.1 mrg #if defined(__prefer_thumb__)
1056 1.1 mrg
1057 1.1 mrg FUNC_START udivsi3
1058 1.1 mrg FUNC_ALIAS aeabi_uidiv udivsi3
1059 1.1.1.4 mrg #if defined(__OPTIMIZE_SIZE__)
1060 1.1 mrg
1061 1.1 mrg cmp divisor, #0
1062 1.1 mrg beq LSYM(Ldiv0)
1063 1.1 mrg LSYM(udivsi3_skip_div0_test):
1064 1.1.1.9 mrg movs curbit, #1
1065 1.1.1.9 mrg movs result, #0
1066 1.1 mrg
1067 1.1 mrg push { work }
1068 1.1 mrg cmp dividend, divisor
1069 1.1 mrg blo LSYM(Lgot_result)
1070 1.1 mrg
1071 1.1 mrg THUMB_DIV_MOD_BODY 0
1072 1.1 mrg
1073 1.1.1.9 mrg movs r0, result
1074 1.1 mrg pop { work }
1075 1.1 mrg RET
1076 1.1 mrg
1077 1.1.1.4 mrg /* Implementation of aeabi_uidiv for ARMv6m. This version is only
1078 1.1.1.4 mrg used in ARMv6-M when we need an efficient implementation. */
1079 1.1.1.4 mrg #else
1080 1.1.1.4 mrg LSYM(udivsi3_skip_div0_test):
1081 1.1.1.4 mrg THUMB1_Div_Positive
1082 1.1.1.4 mrg
1083 1.1.1.4 mrg #endif /* __OPTIMIZE_SIZE__ */
1084 1.1.1.4 mrg
1085 1.1 mrg #elif defined(__ARM_ARCH_EXT_IDIV__)
1086 1.1 mrg
1087 1.1 mrg ARM_FUNC_START udivsi3
1088 1.1 mrg ARM_FUNC_ALIAS aeabi_uidiv udivsi3
1089 1.1 mrg
1090 1.1 mrg cmp r1, #0
1091 1.1 mrg beq LSYM(Ldiv0)
1092 1.1 mrg
1093 1.1 mrg udiv r0, r0, r1
1094 1.1 mrg RET
1095 1.1 mrg
1096 1.1 mrg #else /* ARM version/Thumb-2. */
1097 1.1 mrg
1098 1.1 mrg ARM_FUNC_START udivsi3
1099 1.1 mrg ARM_FUNC_ALIAS aeabi_uidiv udivsi3
1100 1.1 mrg
1101 1.1 mrg /* Note: if called via udivsi3_skip_div0_test, this will unnecessarily
1102 1.1 mrg check for division-by-zero a second time. */
1103 1.1 mrg LSYM(udivsi3_skip_div0_test):
1104 1.1 mrg subs r2, r1, #1
1105 1.1 mrg do_it eq
1106 1.1 mrg RETc(eq)
1107 1.1 mrg bcc LSYM(Ldiv0)
1108 1.1 mrg cmp r0, r1
1109 1.1 mrg bls 11f
1110 1.1 mrg tst r1, r2
1111 1.1 mrg beq 12f
1112 1.1 mrg
1113 1.1 mrg ARM_DIV_BODY r0, r1, r2, r3
1114 1.1 mrg
1115 1.1 mrg mov r0, r2
1116 1.1 mrg RET
1117 1.1 mrg
1118 1.1 mrg 11: do_it eq, e
1119 1.1 mrg moveq r0, #1
1120 1.1 mrg movne r0, #0
1121 1.1 mrg RET
1122 1.1 mrg
1123 1.1 mrg 12: ARM_DIV2_ORDER r1, r2
1124 1.1 mrg
1125 1.1 mrg mov r0, r0, lsr r2
1126 1.1 mrg RET
1127 1.1 mrg
1128 1.1 mrg #endif /* ARM version */
1129 1.1 mrg
1130 1.1 mrg DIV_FUNC_END udivsi3 unsigned
1131 1.1 mrg
1132 1.1 mrg #if defined(__prefer_thumb__)
1133 1.1 mrg FUNC_START aeabi_uidivmod
1134 1.1 mrg cmp r1, #0
1135 1.1 mrg beq LSYM(Ldiv0)
1136 1.1.1.4 mrg # if defined(__OPTIMIZE_SIZE__)
1137 1.1 mrg push {r0, r1, lr}
1138 1.1 mrg bl LSYM(udivsi3_skip_div0_test)
1139 1.1 mrg POP {r1, r2, r3}
1140 1.1.1.9 mrg muls r2, r0
1141 1.1.1.9 mrg subs r1, r1, r2
1142 1.1 mrg bx r3
1143 1.1.1.4 mrg # else
1144 1.1.1.4 mrg /* Both the quotient and remainder are calculated simultaneously
1145 1.1.1.4 mrg in THUMB1_Div_Positive. There is no need to calculate the
1146 1.1.1.4 mrg remainder again here. */
1147 1.1.1.4 mrg b LSYM(udivsi3_skip_div0_test)
1148 1.1.1.4 mrg RET
1149 1.1.1.4 mrg # endif /* __OPTIMIZE_SIZE__ */
1150 1.1.1.4 mrg
1151 1.1 mrg #elif defined(__ARM_ARCH_EXT_IDIV__)
1152 1.1 mrg ARM_FUNC_START aeabi_uidivmod
1153 1.1 mrg cmp r1, #0
1154 1.1 mrg beq LSYM(Ldiv0)
1155 1.1.1.9 mrg mov r2, r0
1156 1.1 mrg udiv r0, r0, r1
1157 1.1 mrg mls r1, r0, r1, r2
1158 1.1 mrg RET
1159 1.1 mrg #else
1160 1.1 mrg ARM_FUNC_START aeabi_uidivmod
1161 1.1 mrg cmp r1, #0
1162 1.1 mrg beq LSYM(Ldiv0)
1163 1.1 mrg stmfd sp!, { r0, r1, lr }
1164 1.1 mrg bl LSYM(udivsi3_skip_div0_test)
1165 1.1 mrg ldmfd sp!, { r1, r2, lr }
1166 1.1 mrg mul r3, r2, r0
1167 1.1 mrg sub r1, r1, r3
1168 1.1 mrg RET
1169 1.1 mrg #endif
1170 1.1 mrg FUNC_END aeabi_uidivmod
1171 1.1 mrg
1172 1.1 mrg #endif /* L_udivsi3 */
1173 1.1 mrg /* ------------------------------------------------------------------------ */
1174 1.1 mrg #ifdef L_umodsi3
1175 1.1 mrg
1176 1.1.1.4 mrg #if defined(__ARM_ARCH_EXT_IDIV__) && __ARM_ARCH_ISA_THUMB != 1
1177 1.1 mrg
1178 1.1 mrg ARM_FUNC_START umodsi3
1179 1.1 mrg
1180 1.1 mrg cmp r1, #0
1181 1.1 mrg beq LSYM(Ldiv0)
1182 1.1 mrg udiv r2, r0, r1
1183 1.1 mrg mls r0, r1, r2, r0
1184 1.1 mrg RET
1185 1.1 mrg
1186 1.1 mrg #elif defined(__thumb__)
1187 1.1 mrg
1188 1.1 mrg FUNC_START umodsi3
1189 1.1 mrg
1190 1.1 mrg cmp divisor, #0
1191 1.1 mrg beq LSYM(Ldiv0)
1192 1.1.1.9 mrg movs curbit, #1
1193 1.1 mrg cmp dividend, divisor
1194 1.1 mrg bhs LSYM(Lover10)
1195 1.1 mrg RET
1196 1.1 mrg
1197 1.1 mrg LSYM(Lover10):
1198 1.1 mrg push { work }
1199 1.1 mrg
1200 1.1 mrg THUMB_DIV_MOD_BODY 1
1201 1.1 mrg
1202 1.1 mrg pop { work }
1203 1.1 mrg RET
1204 1.1 mrg
1205 1.1 mrg #else /* ARM version. */
1206 1.1.1.4 mrg
1207 1.1 mrg FUNC_START umodsi3
1208 1.1 mrg
1209 1.1 mrg subs r2, r1, #1 @ compare divisor with 1
1210 1.1 mrg bcc LSYM(Ldiv0)
1211 1.1 mrg cmpne r0, r1 @ compare dividend with divisor
1212 1.1 mrg moveq r0, #0
1213 1.1 mrg tsthi r1, r2 @ see if divisor is power of 2
1214 1.1 mrg andeq r0, r0, r2
1215 1.1 mrg RETc(ls)
1216 1.1 mrg
1217 1.1 mrg ARM_MOD_BODY r0, r1, r2, r3
1218 1.1 mrg
1219 1.1 mrg RET
1220 1.1 mrg
1221 1.1 mrg #endif /* ARM version. */
1222 1.1 mrg
1223 1.1 mrg DIV_FUNC_END umodsi3 unsigned
1224 1.1 mrg
1225 1.1 mrg #endif /* L_umodsi3 */
1226 1.1 mrg /* ------------------------------------------------------------------------ */
1227 1.1 mrg #ifdef L_divsi3
1228 1.1 mrg
1229 1.1 mrg #if defined(__prefer_thumb__)
1230 1.1 mrg
1231 1.1.1.4 mrg FUNC_START divsi3
1232 1.1 mrg FUNC_ALIAS aeabi_idiv divsi3
1233 1.1.1.4 mrg #if defined(__OPTIMIZE_SIZE__)
1234 1.1 mrg
1235 1.1 mrg cmp divisor, #0
1236 1.1 mrg beq LSYM(Ldiv0)
1237 1.1 mrg LSYM(divsi3_skip_div0_test):
1238 1.1 mrg push { work }
1239 1.1.1.9 mrg movs work, dividend
1240 1.1.1.9 mrg eors work, divisor @ Save the sign of the result.
1241 1.1 mrg mov ip, work
1242 1.1.1.9 mrg movs curbit, #1
1243 1.1.1.9 mrg movs result, #0
1244 1.1 mrg cmp divisor, #0
1245 1.1 mrg bpl LSYM(Lover10)
1246 1.1.1.9 mrg negs divisor, divisor @ Loops below use unsigned.
1247 1.1 mrg LSYM(Lover10):
1248 1.1 mrg cmp dividend, #0
1249 1.1 mrg bpl LSYM(Lover11)
1250 1.1.1.9 mrg negs dividend, dividend
1251 1.1 mrg LSYM(Lover11):
1252 1.1 mrg cmp dividend, divisor
1253 1.1 mrg blo LSYM(Lgot_result)
1254 1.1 mrg
1255 1.1 mrg THUMB_DIV_MOD_BODY 0
1256 1.1.1.4 mrg
1257 1.1.1.9 mrg movs r0, result
1258 1.1 mrg mov work, ip
1259 1.1 mrg cmp work, #0
1260 1.1 mrg bpl LSYM(Lover12)
1261 1.1.1.9 mrg negs r0, r0
1262 1.1 mrg LSYM(Lover12):
1263 1.1 mrg pop { work }
1264 1.1 mrg RET
1265 1.1 mrg
1266 1.1.1.4 mrg /* Implementation of aeabi_idiv for ARMv6m. This version is only
1267 1.1.1.4 mrg used in ARMv6-M when we need an efficient implementation. */
1268 1.1.1.4 mrg #else
1269 1.1.1.4 mrg LSYM(divsi3_skip_div0_test):
1270 1.1.1.4 mrg cpy curbit, dividend
1271 1.1.1.9 mrg orrs curbit, divisor
1272 1.1.1.4 mrg bmi LSYM(Lthumb1_div_negative)
1273 1.1.1.4 mrg
1274 1.1.1.4 mrg LSYM(Lthumb1_div_positive):
1275 1.1.1.4 mrg THUMB1_Div_Positive
1276 1.1.1.4 mrg
1277 1.1.1.4 mrg LSYM(Lthumb1_div_negative):
1278 1.1.1.4 mrg THUMB1_Div_Negative
1279 1.1.1.4 mrg
1280 1.1.1.4 mrg #endif /* __OPTIMIZE_SIZE__ */
1281 1.1.1.4 mrg
1282 1.1 mrg #elif defined(__ARM_ARCH_EXT_IDIV__)
1283 1.1 mrg
1284 1.1 mrg ARM_FUNC_START divsi3
1285 1.1 mrg ARM_FUNC_ALIAS aeabi_idiv divsi3
1286 1.1 mrg
1287 1.1 mrg cmp r1, #0
1288 1.1 mrg beq LSYM(Ldiv0)
1289 1.1 mrg sdiv r0, r0, r1
1290 1.1 mrg RET
1291 1.1 mrg
1292 1.1 mrg #else /* ARM/Thumb-2 version. */
1293 1.1.1.4 mrg
1294 1.1.1.4 mrg ARM_FUNC_START divsi3
1295 1.1 mrg ARM_FUNC_ALIAS aeabi_idiv divsi3
1296 1.1 mrg
1297 1.1 mrg cmp r1, #0
1298 1.1 mrg beq LSYM(Ldiv0)
1299 1.1 mrg LSYM(divsi3_skip_div0_test):
1300 1.1 mrg eor ip, r0, r1 @ save the sign of the result.
1301 1.1 mrg do_it mi
1302 1.1 mrg rsbmi r1, r1, #0 @ loops below use unsigned.
1303 1.1 mrg subs r2, r1, #1 @ division by 1 or -1 ?
1304 1.1 mrg beq 10f
1305 1.1 mrg movs r3, r0
1306 1.1 mrg do_it mi
1307 1.1 mrg rsbmi r3, r0, #0 @ positive dividend value
1308 1.1 mrg cmp r3, r1
1309 1.1 mrg bls 11f
1310 1.1 mrg tst r1, r2 @ divisor is power of 2 ?
1311 1.1 mrg beq 12f
1312 1.1 mrg
1313 1.1 mrg ARM_DIV_BODY r3, r1, r0, r2
1314 1.1 mrg
1315 1.1 mrg cmp ip, #0
1316 1.1 mrg do_it mi
1317 1.1 mrg rsbmi r0, r0, #0
1318 1.1 mrg RET
1319 1.1 mrg
1320 1.1 mrg 10: teq ip, r0 @ same sign ?
1321 1.1 mrg do_it mi
1322 1.1 mrg rsbmi r0, r0, #0
1323 1.1 mrg RET
1324 1.1 mrg
1325 1.1 mrg 11: do_it lo
1326 1.1 mrg movlo r0, #0
1327 1.1 mrg do_it eq,t
1328 1.1 mrg moveq r0, ip, asr #31
1329 1.1 mrg orreq r0, r0, #1
1330 1.1 mrg RET
1331 1.1 mrg
1332 1.1 mrg 12: ARM_DIV2_ORDER r1, r2
1333 1.1 mrg
1334 1.1 mrg cmp ip, #0
1335 1.1 mrg mov r0, r3, lsr r2
1336 1.1 mrg do_it mi
1337 1.1 mrg rsbmi r0, r0, #0
1338 1.1 mrg RET
1339 1.1 mrg
1340 1.1 mrg #endif /* ARM version */
1341 1.1 mrg
1342 1.1 mrg DIV_FUNC_END divsi3 signed
1343 1.1 mrg
1344 1.1 mrg #if defined(__prefer_thumb__)
1345 1.1 mrg FUNC_START aeabi_idivmod
1346 1.1 mrg cmp r1, #0
1347 1.1 mrg beq LSYM(Ldiv0)
1348 1.1.1.4 mrg # if defined(__OPTIMIZE_SIZE__)
1349 1.1 mrg push {r0, r1, lr}
1350 1.1 mrg bl LSYM(divsi3_skip_div0_test)
1351 1.1 mrg POP {r1, r2, r3}
1352 1.1.1.9 mrg muls r2, r0
1353 1.1.1.9 mrg subs r1, r1, r2
1354 1.1 mrg bx r3
1355 1.1.1.4 mrg # else
1356 1.1.1.4 mrg /* Both the quotient and remainder are calculated simultaneously
1357 1.1.1.4 mrg in THUMB1_Div_Positive and THUMB1_Div_Negative. There is no
1358 1.1.1.4 mrg need to calculate the remainder again here. */
1359 1.1.1.4 mrg b LSYM(divsi3_skip_div0_test)
1360 1.1.1.4 mrg RET
1361 1.1.1.4 mrg # endif /* __OPTIMIZE_SIZE__ */
1362 1.1.1.4 mrg
1363 1.1 mrg #elif defined(__ARM_ARCH_EXT_IDIV__)
1364 1.1 mrg ARM_FUNC_START aeabi_idivmod
1365 1.1 mrg cmp r1, #0
1366 1.1 mrg beq LSYM(Ldiv0)
1367 1.1 mrg mov r2, r0
1368 1.1 mrg sdiv r0, r0, r1
1369 1.1 mrg mls r1, r0, r1, r2
1370 1.1 mrg RET
1371 1.1 mrg #else
1372 1.1 mrg ARM_FUNC_START aeabi_idivmod
1373 1.1 mrg cmp r1, #0
1374 1.1 mrg beq LSYM(Ldiv0)
1375 1.1 mrg stmfd sp!, { r0, r1, lr }
1376 1.1 mrg bl LSYM(divsi3_skip_div0_test)
1377 1.1 mrg ldmfd sp!, { r1, r2, lr }
1378 1.1 mrg mul r3, r2, r0
1379 1.1 mrg sub r1, r1, r3
1380 1.1 mrg RET
1381 1.1 mrg #endif
1382 1.1 mrg FUNC_END aeabi_idivmod
1383 1.1 mrg
1384 1.1 mrg #endif /* L_divsi3 */
1385 1.1 mrg /* ------------------------------------------------------------------------ */
1386 1.1 mrg #ifdef L_modsi3
1387 1.1 mrg
1388 1.1.1.4 mrg #if defined(__ARM_ARCH_EXT_IDIV__) && __ARM_ARCH_ISA_THUMB != 1
1389 1.1 mrg
1390 1.1 mrg ARM_FUNC_START modsi3
1391 1.1 mrg
1392 1.1 mrg cmp r1, #0
1393 1.1 mrg beq LSYM(Ldiv0)
1394 1.1 mrg
1395 1.1 mrg sdiv r2, r0, r1
1396 1.1 mrg mls r0, r1, r2, r0
1397 1.1 mrg RET
1398 1.1 mrg
1399 1.1 mrg #elif defined(__thumb__)
1400 1.1 mrg
1401 1.1 mrg FUNC_START modsi3
1402 1.1 mrg
1403 1.1.1.9 mrg movs curbit, #1
1404 1.1 mrg cmp divisor, #0
1405 1.1 mrg beq LSYM(Ldiv0)
1406 1.1 mrg bpl LSYM(Lover10)
1407 1.1.1.9 mrg negs divisor, divisor @ Loops below use unsigned.
1408 1.1 mrg LSYM(Lover10):
1409 1.1 mrg push { work }
1410 1.1 mrg @ Need to save the sign of the dividend, unfortunately, we need
1411 1.1 mrg @ work later on. Must do this after saving the original value of
1412 1.1 mrg @ the work register, because we will pop this value off first.
1413 1.1 mrg push { dividend }
1414 1.1 mrg cmp dividend, #0
1415 1.1 mrg bpl LSYM(Lover11)
1416 1.1.1.9 mrg negs dividend, dividend
1417 1.1 mrg LSYM(Lover11):
1418 1.1 mrg cmp dividend, divisor
1419 1.1 mrg blo LSYM(Lgot_result)
1420 1.1 mrg
1421 1.1 mrg THUMB_DIV_MOD_BODY 1
1422 1.1 mrg
1423 1.1 mrg pop { work }
1424 1.1 mrg cmp work, #0
1425 1.1 mrg bpl LSYM(Lover12)
1426 1.1.1.9 mrg negs dividend, dividend
1427 1.1 mrg LSYM(Lover12):
1428 1.1 mrg pop { work }
1429 1.1 mrg RET
1430 1.1 mrg
1431 1.1 mrg #else /* ARM version. */
1432 1.1 mrg
1433 1.1 mrg FUNC_START modsi3
1434 1.1 mrg
1435 1.1 mrg cmp r1, #0
1436 1.1 mrg beq LSYM(Ldiv0)
1437 1.1 mrg rsbmi r1, r1, #0 @ loops below use unsigned.
1438 1.1 mrg movs ip, r0 @ preserve sign of dividend
1439 1.1 mrg rsbmi r0, r0, #0 @ if negative make positive
1440 1.1 mrg subs r2, r1, #1 @ compare divisor with 1
1441 1.1 mrg cmpne r0, r1 @ compare dividend with divisor
1442 1.1 mrg moveq r0, #0
1443 1.1 mrg tsthi r1, r2 @ see if divisor is power of 2
1444 1.1 mrg andeq r0, r0, r2
1445 1.1 mrg bls 10f
1446 1.1 mrg
1447 1.1 mrg ARM_MOD_BODY r0, r1, r2, r3
1448 1.1 mrg
1449 1.1 mrg 10: cmp ip, #0
1450 1.1 mrg rsbmi r0, r0, #0
1451 1.1 mrg RET
1452 1.1 mrg
1453 1.1 mrg #endif /* ARM version */
1454 1.1 mrg
1455 1.1 mrg DIV_FUNC_END modsi3 signed
1456 1.1 mrg
1457 1.1 mrg #endif /* L_modsi3 */
1458 1.1 mrg /* ------------------------------------------------------------------------ */
1459 1.1 mrg #ifdef L_dvmd_tls
1460 1.1 mrg
1461 1.1 mrg #ifdef __ARM_EABI__
1462 1.1 mrg WEAK aeabi_idiv0
1463 1.1 mrg WEAK aeabi_ldiv0
1464 1.1 mrg FUNC_START aeabi_idiv0
1465 1.1 mrg FUNC_START aeabi_ldiv0
1466 1.1 mrg RET
1467 1.1 mrg FUNC_END aeabi_ldiv0
1468 1.1 mrg FUNC_END aeabi_idiv0
1469 1.1 mrg #else
1470 1.1 mrg FUNC_START div0
1471 1.1 mrg RET
1472 1.1 mrg FUNC_END div0
1473 1.1 mrg #endif
1474 1.1 mrg
1475 1.1 mrg #endif /* L_divmodsi_tools */
1476 1.1 mrg /* ------------------------------------------------------------------------ */
1477 1.1 mrg #ifdef L_dvmd_lnx
1478 1.1 mrg @ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
1479 1.1 mrg
1480 1.1 mrg /* Constant taken from <asm/signal.h>. */
1481 1.1 mrg #define SIGFPE 8
1482 1.1 mrg
1483 1.1 mrg #ifdef __ARM_EABI__
1484 1.1.1.3 mrg cfi_start __aeabi_ldiv0, LSYM(Lend_aeabi_ldiv0)
1485 1.1 mrg WEAK aeabi_idiv0
1486 1.1 mrg WEAK aeabi_ldiv0
1487 1.1 mrg ARM_FUNC_START aeabi_idiv0
1488 1.1 mrg ARM_FUNC_START aeabi_ldiv0
1489 1.1.1.3 mrg do_push {r1, lr}
1490 1.1.1.3 mrg 98: cfi_push 98b - __aeabi_ldiv0, 0xe, -0x4, 0x8
1491 1.1 mrg #else
1492 1.1.1.3 mrg cfi_start __div0, LSYM(Lend_div0)
1493 1.1 mrg ARM_FUNC_START div0
1494 1.1.1.3 mrg do_push {r1, lr}
1495 1.1.1.3 mrg 98: cfi_push 98b - __div0, 0xe, -0x4, 0x8
1496 1.1 mrg #endif
1497 1.1 mrg
1498 1.1 mrg mov r0, #SIGFPE
1499 1.1 mrg bl SYM(raise) __PLT__
1500 1.1.1.3 mrg RETLDM r1 unwind=98b
1501 1.1 mrg
1502 1.1 mrg #ifdef __ARM_EABI__
1503 1.1.1.3 mrg cfi_end LSYM(Lend_aeabi_ldiv0)
1504 1.1 mrg FUNC_END aeabi_ldiv0
1505 1.1 mrg FUNC_END aeabi_idiv0
1506 1.1 mrg #else
1507 1.1.1.3 mrg cfi_end LSYM(Lend_div0)
1508 1.1 mrg FUNC_END div0
1509 1.1 mrg #endif
1510 1.1 mrg
1511 1.1 mrg #endif /* L_dvmd_lnx */
1512 1.1 mrg #ifdef L_clear_cache
1513 1.1 mrg #if defined __ARM_EABI__ && defined __linux__
1514 1.1 mrg @ EABI GNU/Linux call to cacheflush syscall.
1515 1.1 mrg ARM_FUNC_START clear_cache
1516 1.1 mrg do_push {r7}
1517 1.1.1.8 mrg #if __ARM_ARCH >= 7 || defined(__ARM_ARCH_6T2__)
1518 1.1 mrg movw r7, #2
1519 1.1 mrg movt r7, #0xf
1520 1.1 mrg #else
1521 1.1 mrg mov r7, #0xf0000
1522 1.1 mrg add r7, r7, #2
1523 1.1 mrg #endif
1524 1.1 mrg mov r2, #0
1525 1.1.1.11 mrg svc 0
1526 1.1 mrg do_pop {r7}
1527 1.1 mrg RET
1528 1.1 mrg FUNC_END clear_cache
1529 1.1 mrg #else
1530 1.1 mrg #error "This is only for ARM EABI GNU/Linux"
1531 1.1 mrg #endif
1532 1.1 mrg #endif /* L_clear_cache */
1533 1.1.1.8 mrg
1534 1.1.1.8 mrg #ifdef L_speculation_barrier
1535 1.1.1.8 mrg FUNC_START speculation_barrier
1536 1.1.1.8 mrg #if __ARM_ARCH >= 7
1537 1.1.1.8 mrg isb
1538 1.1.1.8 mrg dsb sy
1539 1.1.1.8 mrg #elif defined __ARM_EABI__ && defined __linux__
1540 1.1.1.8 mrg /* We don't have a speculation barrier directly for this
1541 1.1.1.8 mrg platform/architecture variant. But we can use a kernel
1542 1.1.1.8 mrg clear_cache service routine which will emit such instructions
1543 1.1.1.8 mrg if run on a later version of the architecture. We don't
1544 1.1.1.8 mrg really want to flush the cache, but we must give it a valid
1545 1.1.1.8 mrg address, so just clear pc..pc+1. */
1546 1.1.1.8 mrg #if defined __thumb__ && !defined __thumb2__
1547 1.1.1.8 mrg push {r7}
1548 1.1.1.9 mrg movs r7, #0xf
1549 1.1.1.9 mrg lsls r7, #16
1550 1.1.1.9 mrg adds r7, #2
1551 1.1.1.8 mrg adr r0, . + 4
1552 1.1.1.9 mrg adds r1, r0, #1
1553 1.1.1.9 mrg movs r2, #0
1554 1.1.1.8 mrg svc 0
1555 1.1.1.8 mrg pop {r7}
1556 1.1.1.8 mrg #else
1557 1.1.1.8 mrg do_push {r7}
1558 1.1.1.8 mrg #ifdef __ARM_ARCH_6T2__
1559 1.1.1.8 mrg movw r7, #2
1560 1.1.1.8 mrg movt r7, #0xf
1561 1.1.1.8 mrg #else
1562 1.1.1.8 mrg mov r7, #0xf0000
1563 1.1.1.8 mrg add r7, r7, #2
1564 1.1.1.8 mrg #endif
1565 1.1.1.8 mrg add r0, pc, #0 /* ADR. */
1566 1.1.1.8 mrg add r1, r0, #1
1567 1.1.1.8 mrg mov r2, #0
1568 1.1.1.8 mrg svc 0
1569 1.1.1.8 mrg do_pop {r7}
1570 1.1.1.8 mrg #endif /* Thumb1 only */
1571 1.1.1.8 mrg #else
1572 1.1.1.8 mrg #warning "No speculation barrier defined for this platform"
1573 1.1.1.8 mrg #endif
1574 1.1.1.8 mrg RET
1575 1.1.1.8 mrg FUNC_END speculation_barrier
1576 1.1.1.8 mrg #endif
1577 1.1 mrg /* ------------------------------------------------------------------------ */
1578 1.1 mrg /* Dword shift operations. */
1579 1.1 mrg /* All the following Dword shift variants rely on the fact that
1580 1.1 mrg shft xxx, Reg
1581 1.1 mrg is in fact done as
1582 1.1 mrg shft xxx, (Reg & 255)
1583 1.1 mrg so for Reg value in (32...63) and (-1...-31) we will get zero (in the
1584 1.1 mrg case of logical shifts) or the sign (for asr). */
1585 1.1 mrg
1586 1.1 mrg #ifdef __ARMEB__
1587 1.1 mrg #define al r1
1588 1.1 mrg #define ah r0
1589 1.1 mrg #else
1590 1.1 mrg #define al r0
1591 1.1 mrg #define ah r1
1592 1.1 mrg #endif
1593 1.1 mrg
1594 1.1 mrg /* Prevent __aeabi double-word shifts from being produced on SymbianOS. */
1595 1.1 mrg #ifndef __symbian__
1596 1.1 mrg
1597 1.1 mrg #ifdef L_lshrdi3
1598 1.1 mrg
1599 1.1 mrg FUNC_START lshrdi3
1600 1.1 mrg FUNC_ALIAS aeabi_llsr lshrdi3
1601 1.1 mrg
1602 1.1 mrg #ifdef __thumb__
1603 1.1.1.9 mrg lsrs al, r2
1604 1.1.1.9 mrg movs r3, ah
1605 1.1.1.9 mrg lsrs ah, r2
1606 1.1 mrg mov ip, r3
1607 1.1.1.9 mrg subs r2, #32
1608 1.1.1.9 mrg lsrs r3, r2
1609 1.1.1.9 mrg orrs al, r3
1610 1.1.1.9 mrg negs r2, r2
1611 1.1 mrg mov r3, ip
1612 1.1.1.9 mrg lsls r3, r2
1613 1.1.1.9 mrg orrs al, r3
1614 1.1 mrg RET
1615 1.1 mrg #else
1616 1.1 mrg subs r3, r2, #32
1617 1.1 mrg rsb ip, r2, #32
1618 1.1 mrg movmi al, al, lsr r2
1619 1.1 mrg movpl al, ah, lsr r3
1620 1.1 mrg orrmi al, al, ah, lsl ip
1621 1.1 mrg mov ah, ah, lsr r2
1622 1.1 mrg RET
1623 1.1 mrg #endif
1624 1.1 mrg FUNC_END aeabi_llsr
1625 1.1 mrg FUNC_END lshrdi3
1626 1.1 mrg
1627 1.1 mrg #endif
1628 1.1 mrg
1629 1.1 mrg #ifdef L_ashrdi3
1630 1.1 mrg
1631 1.1 mrg FUNC_START ashrdi3
1632 1.1 mrg FUNC_ALIAS aeabi_lasr ashrdi3
1633 1.1 mrg
1634 1.1 mrg #ifdef __thumb__
1635 1.1.1.9 mrg lsrs al, r2
1636 1.1.1.9 mrg movs r3, ah
1637 1.1.1.9 mrg asrs ah, r2
1638 1.1.1.9 mrg subs r2, #32
1639 1.1 mrg @ If r2 is negative at this point the following step would OR
1640 1.1 mrg @ the sign bit into all of AL. That's not what we want...
1641 1.1 mrg bmi 1f
1642 1.1 mrg mov ip, r3
1643 1.1.1.9 mrg asrs r3, r2
1644 1.1.1.9 mrg orrs al, r3
1645 1.1 mrg mov r3, ip
1646 1.1 mrg 1:
1647 1.1.1.9 mrg negs r2, r2
1648 1.1.1.9 mrg lsls r3, r2
1649 1.1.1.9 mrg orrs al, r3
1650 1.1 mrg RET
1651 1.1 mrg #else
1652 1.1 mrg subs r3, r2, #32
1653 1.1 mrg rsb ip, r2, #32
1654 1.1 mrg movmi al, al, lsr r2
1655 1.1 mrg movpl al, ah, asr r3
1656 1.1 mrg orrmi al, al, ah, lsl ip
1657 1.1 mrg mov ah, ah, asr r2
1658 1.1 mrg RET
1659 1.1 mrg #endif
1660 1.1 mrg
1661 1.1 mrg FUNC_END aeabi_lasr
1662 1.1 mrg FUNC_END ashrdi3
1663 1.1 mrg
1664 1.1 mrg #endif
1665 1.1 mrg
1666 1.1 mrg #ifdef L_ashldi3
1667 1.1 mrg
1668 1.1 mrg FUNC_START ashldi3
1669 1.1 mrg FUNC_ALIAS aeabi_llsl ashldi3
1670 1.1 mrg
1671 1.1 mrg #ifdef __thumb__
1672 1.1.1.9 mrg lsls ah, r2
1673 1.1.1.9 mrg movs r3, al
1674 1.1.1.9 mrg lsls al, r2
1675 1.1 mrg mov ip, r3
1676 1.1.1.9 mrg subs r2, #32
1677 1.1.1.9 mrg lsls r3, r2
1678 1.1.1.9 mrg orrs ah, r3
1679 1.1.1.9 mrg negs r2, r2
1680 1.1 mrg mov r3, ip
1681 1.1.1.9 mrg lsrs r3, r2
1682 1.1.1.9 mrg orrs ah, r3
1683 1.1 mrg RET
1684 1.1 mrg #else
1685 1.1 mrg subs r3, r2, #32
1686 1.1 mrg rsb ip, r2, #32
1687 1.1 mrg movmi ah, ah, lsl r2
1688 1.1 mrg movpl ah, al, lsl r3
1689 1.1 mrg orrmi ah, ah, al, lsr ip
1690 1.1 mrg mov al, al, lsl r2
1691 1.1 mrg RET
1692 1.1 mrg #endif
1693 1.1 mrg FUNC_END aeabi_llsl
1694 1.1 mrg FUNC_END ashldi3
1695 1.1 mrg
1696 1.1 mrg #endif
1697 1.1 mrg
1698 1.1 mrg #endif /* __symbian__ */
1699 1.1 mrg
1700 1.1 mrg #ifdef L_clzsi2
1701 1.1.1.4 mrg #ifdef NOT_ISA_TARGET_32BIT
1702 1.1 mrg FUNC_START clzsi2
1703 1.1.1.9 mrg movs r1, #28
1704 1.1.1.9 mrg movs r3, #1
1705 1.1.1.9 mrg lsls r3, r3, #16
1706 1.1 mrg cmp r0, r3 /* 0x10000 */
1707 1.1 mrg bcc 2f
1708 1.1.1.9 mrg lsrs r0, r0, #16
1709 1.1.1.9 mrg subs r1, r1, #16
1710 1.1.1.9 mrg 2: lsrs r3, r3, #8
1711 1.1 mrg cmp r0, r3 /* #0x100 */
1712 1.1 mrg bcc 2f
1713 1.1.1.9 mrg lsrs r0, r0, #8
1714 1.1.1.9 mrg subs r1, r1, #8
1715 1.1.1.9 mrg 2: lsrs r3, r3, #4
1716 1.1 mrg cmp r0, r3 /* #0x10 */
1717 1.1 mrg bcc 2f
1718 1.1.1.9 mrg lsrs r0, r0, #4
1719 1.1.1.9 mrg subs r1, r1, #4
1720 1.1 mrg 2: adr r2, 1f
1721 1.1 mrg ldrb r0, [r2, r0]
1722 1.1.1.9 mrg adds r0, r0, r1
1723 1.1 mrg bx lr
1724 1.1 mrg .align 2
1725 1.1 mrg 1:
1726 1.1 mrg .byte 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
1727 1.1 mrg FUNC_END clzsi2
1728 1.1 mrg #else
1729 1.1 mrg ARM_FUNC_START clzsi2
1730 1.1.1.8 mrg # if defined (__ARM_FEATURE_CLZ)
1731 1.1 mrg clz r0, r0
1732 1.1 mrg RET
1733 1.1 mrg # else
1734 1.1 mrg mov r1, #28
1735 1.1 mrg cmp r0, #0x10000
1736 1.1 mrg do_it cs, t
1737 1.1 mrg movcs r0, r0, lsr #16
1738 1.1 mrg subcs r1, r1, #16
1739 1.1 mrg cmp r0, #0x100
1740 1.1 mrg do_it cs, t
1741 1.1 mrg movcs r0, r0, lsr #8
1742 1.1 mrg subcs r1, r1, #8
1743 1.1 mrg cmp r0, #0x10
1744 1.1 mrg do_it cs, t
1745 1.1 mrg movcs r0, r0, lsr #4
1746 1.1 mrg subcs r1, r1, #4
1747 1.1 mrg adr r2, 1f
1748 1.1 mrg ldrb r0, [r2, r0]
1749 1.1 mrg add r0, r0, r1
1750 1.1 mrg RET
1751 1.1 mrg .align 2
1752 1.1 mrg 1:
1753 1.1 mrg .byte 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
1754 1.1.1.8 mrg # endif /* !defined (__ARM_FEATURE_CLZ) */
1755 1.1 mrg FUNC_END clzsi2
1756 1.1 mrg #endif
1757 1.1 mrg #endif /* L_clzsi2 */
1758 1.1 mrg
1759 1.1 mrg #ifdef L_clzdi2
1760 1.1.1.8 mrg #if !defined (__ARM_FEATURE_CLZ)
1761 1.1 mrg
1762 1.1.1.4 mrg # ifdef NOT_ISA_TARGET_32BIT
1763 1.1 mrg FUNC_START clzdi2
1764 1.1 mrg push {r4, lr}
1765 1.1.1.9 mrg cmp xxh, #0
1766 1.1.1.9 mrg bne 1f
1767 1.1.1.9 mrg # ifdef __ARMEB__
1768 1.1.1.9 mrg movs r0, xxl
1769 1.1.1.9 mrg bl __clzsi2
1770 1.1.1.9 mrg adds r0, r0, #32
1771 1.1.1.9 mrg b 2f
1772 1.1.1.9 mrg 1:
1773 1.1.1.9 mrg bl __clzsi2
1774 1.1.1.9 mrg # else
1775 1.1.1.9 mrg bl __clzsi2
1776 1.1.1.9 mrg adds r0, r0, #32
1777 1.1.1.9 mrg b 2f
1778 1.1.1.9 mrg 1:
1779 1.1.1.9 mrg movs r0, xxh
1780 1.1.1.9 mrg bl __clzsi2
1781 1.1.1.9 mrg # endif
1782 1.1.1.9 mrg 2:
1783 1.1.1.9 mrg pop {r4, pc}
1784 1.1.1.9 mrg # else /* NOT_ISA_TARGET_32BIT */
1785 1.1 mrg ARM_FUNC_START clzdi2
1786 1.1 mrg do_push {r4, lr}
1787 1.1 mrg cmp xxh, #0
1788 1.1 mrg bne 1f
1789 1.1.1.9 mrg # ifdef __ARMEB__
1790 1.1 mrg mov r0, xxl
1791 1.1 mrg bl __clzsi2
1792 1.1 mrg add r0, r0, #32
1793 1.1 mrg b 2f
1794 1.1 mrg 1:
1795 1.1 mrg bl __clzsi2
1796 1.1.1.9 mrg # else
1797 1.1 mrg bl __clzsi2
1798 1.1 mrg add r0, r0, #32
1799 1.1 mrg b 2f
1800 1.1 mrg 1:
1801 1.1 mrg mov r0, xxh
1802 1.1 mrg bl __clzsi2
1803 1.1.1.9 mrg # endif
1804 1.1 mrg 2:
1805 1.1 mrg RETLDM r4
1806 1.1 mrg FUNC_END clzdi2
1807 1.1.1.9 mrg # endif /* NOT_ISA_TARGET_32BIT */
1808 1.1 mrg
1809 1.1.1.8 mrg #else /* defined (__ARM_FEATURE_CLZ) */
1810 1.1 mrg
1811 1.1 mrg ARM_FUNC_START clzdi2
1812 1.1 mrg cmp xxh, #0
1813 1.1 mrg do_it eq, et
1814 1.1 mrg clzeq r0, xxl
1815 1.1 mrg clzne r0, xxh
1816 1.1 mrg addeq r0, r0, #32
1817 1.1 mrg RET
1818 1.1 mrg FUNC_END clzdi2
1819 1.1 mrg
1820 1.1 mrg #endif
1821 1.1 mrg #endif /* L_clzdi2 */
1822 1.1 mrg
1823 1.1 mrg #ifdef L_ctzsi2
1824 1.1.1.4 mrg #ifdef NOT_ISA_TARGET_32BIT
1825 1.1 mrg FUNC_START ctzsi2
1826 1.1.1.9 mrg negs r1, r0
1827 1.1.1.9 mrg ands r0, r0, r1
1828 1.1.1.9 mrg movs r1, #28
1829 1.1.1.9 mrg movs r3, #1
1830 1.1.1.9 mrg lsls r3, r3, #16
1831 1.1 mrg cmp r0, r3 /* 0x10000 */
1832 1.1 mrg bcc 2f
1833 1.1.1.9 mrg lsrs r0, r0, #16
1834 1.1.1.9 mrg subs r1, r1, #16
1835 1.1.1.9 mrg 2: lsrs r3, r3, #8
1836 1.1 mrg cmp r0, r3 /* #0x100 */
1837 1.1 mrg bcc 2f
1838 1.1.1.9 mrg lsrs r0, r0, #8
1839 1.1.1.9 mrg subs r1, r1, #8
1840 1.1.1.9 mrg 2: lsrs r3, r3, #4
1841 1.1 mrg cmp r0, r3 /* #0x10 */
1842 1.1 mrg bcc 2f
1843 1.1.1.9 mrg lsrs r0, r0, #4
1844 1.1.1.9 mrg subs r1, r1, #4
1845 1.1 mrg 2: adr r2, 1f
1846 1.1 mrg ldrb r0, [r2, r0]
1847 1.1.1.9 mrg subs r0, r0, r1
1848 1.1 mrg bx lr
1849 1.1 mrg .align 2
1850 1.1 mrg 1:
1851 1.1 mrg .byte 27, 28, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31
1852 1.1 mrg FUNC_END ctzsi2
1853 1.1 mrg #else
1854 1.1 mrg ARM_FUNC_START ctzsi2
1855 1.1 mrg rsb r1, r0, #0
1856 1.1 mrg and r0, r0, r1
1857 1.1.1.8 mrg # if defined (__ARM_FEATURE_CLZ)
1858 1.1 mrg clz r0, r0
1859 1.1 mrg rsb r0, r0, #31
1860 1.1 mrg RET
1861 1.1 mrg # else
1862 1.1 mrg mov r1, #28
1863 1.1 mrg cmp r0, #0x10000
1864 1.1 mrg do_it cs, t
1865 1.1 mrg movcs r0, r0, lsr #16
1866 1.1 mrg subcs r1, r1, #16
1867 1.1 mrg cmp r0, #0x100
1868 1.1 mrg do_it cs, t
1869 1.1 mrg movcs r0, r0, lsr #8
1870 1.1 mrg subcs r1, r1, #8
1871 1.1 mrg cmp r0, #0x10
1872 1.1 mrg do_it cs, t
1873 1.1 mrg movcs r0, r0, lsr #4
1874 1.1 mrg subcs r1, r1, #4
1875 1.1 mrg adr r2, 1f
1876 1.1 mrg ldrb r0, [r2, r0]
1877 1.1 mrg sub r0, r0, r1
1878 1.1 mrg RET
1879 1.1 mrg .align 2
1880 1.1 mrg 1:
1881 1.1 mrg .byte 27, 28, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31
1882 1.1.1.8 mrg # endif /* !defined (__ARM_FEATURE_CLZ) */
1883 1.1 mrg FUNC_END ctzsi2
1884 1.1 mrg #endif
1885 1.1 mrg #endif /* L_clzsi2 */
1886 1.1 mrg
1887 1.1 mrg /* ------------------------------------------------------------------------ */
1888 1.1 mrg /* These next two sections are here despite the fact that they contain Thumb
1889 1.1 mrg assembler because their presence allows interworked code to be linked even
1890 1.1 mrg when the GCC library is this one. */
1891 1.1 mrg
1892 1.1 mrg /* Do not build the interworking functions when the target architecture does
1893 1.1 mrg not support Thumb instructions. (This can be a multilib option). */
1894 1.1 mrg #if defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__\
1895 1.1 mrg || defined __ARM_ARCH_5TE__ || defined __ARM_ARCH_5TEJ__ \
1896 1.1.1.8 mrg || __ARM_ARCH >= 6
1897 1.1 mrg
1898 1.1 mrg #if defined L_call_via_rX
1899 1.1 mrg
1900 1.1 mrg /* These labels & instructions are used by the Arm/Thumb interworking code.
1901 1.1 mrg The address of function to be called is loaded into a register and then
1902 1.1 mrg one of these labels is called via a BL instruction. This puts the
1903 1.1 mrg return address into the link register with the bottom bit set, and the
1904 1.1 mrg code here switches to the correct mode before executing the function. */
1905 1.1 mrg
1906 1.1 mrg .text
1907 1.1 mrg .align 0
1908 1.1 mrg .force_thumb
1909 1.1 mrg
1910 1.1 mrg .macro call_via register
1911 1.1 mrg THUMB_FUNC_START _call_via_\register
1912 1.1 mrg
1913 1.1 mrg bx \register
1914 1.1 mrg nop
1915 1.1 mrg
1916 1.1 mrg SIZE (_call_via_\register)
1917 1.1 mrg .endm
1918 1.1 mrg
1919 1.1 mrg call_via r0
1920 1.1 mrg call_via r1
1921 1.1 mrg call_via r2
1922 1.1 mrg call_via r3
1923 1.1 mrg call_via r4
1924 1.1 mrg call_via r5
1925 1.1 mrg call_via r6
1926 1.1 mrg call_via r7
1927 1.1 mrg call_via r8
1928 1.1 mrg call_via r9
1929 1.1 mrg call_via sl
1930 1.1 mrg call_via fp
1931 1.1 mrg call_via ip
1932 1.1 mrg call_via sp
1933 1.1 mrg call_via lr
1934 1.1 mrg
1935 1.1 mrg #endif /* L_call_via_rX */
1936 1.1 mrg
1937 1.1 mrg /* Don't bother with the old interworking routines for Thumb-2. */
1938 1.1 mrg /* ??? Maybe only omit these on "m" variants. */
1939 1.1.1.4 mrg #if !defined(__thumb2__) && __ARM_ARCH_ISA_ARM
1940 1.1 mrg
1941 1.1 mrg #if defined L_interwork_call_via_rX
1942 1.1 mrg
1943 1.1 mrg /* These labels & instructions are used by the Arm/Thumb interworking code,
1944 1.1 mrg when the target address is in an unknown instruction set. The address
1945 1.1 mrg of function to be called is loaded into a register and then one of these
1946 1.1 mrg labels is called via a BL instruction. This puts the return address
1947 1.1 mrg into the link register with the bottom bit set, and the code here
1948 1.1 mrg switches to the correct mode before executing the function. Unfortunately
1949 1.1 mrg the target code cannot be relied upon to return via a BX instruction, so
1950 1.1 mrg instead we have to store the resturn address on the stack and allow the
1951 1.1 mrg called function to return here instead. Upon return we recover the real
1952 1.1 mrg return address and use a BX to get back to Thumb mode.
1953 1.1 mrg
1954 1.1 mrg There are three variations of this code. The first,
1955 1.1 mrg _interwork_call_via_rN(), will push the return address onto the
1956 1.1 mrg stack and pop it in _arm_return(). It should only be used if all
1957 1.1 mrg arguments are passed in registers.
1958 1.1 mrg
1959 1.1 mrg The second, _interwork_r7_call_via_rN(), instead stores the return
1960 1.1 mrg address at [r7, #-4]. It is the caller's responsibility to ensure
1961 1.1 mrg that this address is valid and contains no useful data.
1962 1.1 mrg
1963 1.1 mrg The third, _interwork_r11_call_via_rN(), works in the same way but
1964 1.1 mrg uses r11 instead of r7. It is useful if the caller does not really
1965 1.1 mrg need a frame pointer. */
1966 1.1 mrg
1967 1.1 mrg .text
1968 1.1 mrg .align 0
1969 1.1 mrg
1970 1.1 mrg .code 32
1971 1.1 mrg .globl _arm_return
1972 1.1 mrg LSYM(Lstart_arm_return):
1973 1.1 mrg cfi_start LSYM(Lstart_arm_return) LSYM(Lend_arm_return)
1974 1.1 mrg cfi_push 0, 0xe, -0x8, 0x8
1975 1.1 mrg nop @ This nop is for the benefit of debuggers, so that
1976 1.1 mrg @ backtraces will use the correct unwind information.
1977 1.1 mrg _arm_return:
1978 1.1 mrg RETLDM unwind=LSYM(Lstart_arm_return)
1979 1.1 mrg cfi_end LSYM(Lend_arm_return)
1980 1.1 mrg
1981 1.1 mrg .globl _arm_return_r7
1982 1.1 mrg _arm_return_r7:
1983 1.1 mrg ldr lr, [r7, #-4]
1984 1.1 mrg bx lr
1985 1.1 mrg
1986 1.1 mrg .globl _arm_return_r11
1987 1.1 mrg _arm_return_r11:
1988 1.1 mrg ldr lr, [r11, #-4]
1989 1.1 mrg bx lr
1990 1.1 mrg
1991 1.1 mrg .macro interwork_with_frame frame, register, name, return
1992 1.1 mrg .code 16
1993 1.1 mrg
1994 1.1 mrg THUMB_FUNC_START \name
1995 1.1 mrg
1996 1.1 mrg bx pc
1997 1.1 mrg nop
1998 1.1 mrg
1999 1.1 mrg .code 32
2000 1.1 mrg tst \register, #1
2001 1.1 mrg streq lr, [\frame, #-4]
2002 1.1 mrg adreq lr, _arm_return_\frame
2003 1.1 mrg bx \register
2004 1.1 mrg
2005 1.1 mrg SIZE (\name)
2006 1.1 mrg .endm
2007 1.1 mrg
2008 1.1 mrg .macro interwork register
2009 1.1 mrg .code 16
2010 1.1 mrg
2011 1.1 mrg THUMB_FUNC_START _interwork_call_via_\register
2012 1.1 mrg
2013 1.1 mrg bx pc
2014 1.1 mrg nop
2015 1.1 mrg
2016 1.1 mrg .code 32
2017 1.1 mrg .globl LSYM(Lchange_\register)
2018 1.1 mrg LSYM(Lchange_\register):
2019 1.1 mrg tst \register, #1
2020 1.1 mrg streq lr, [sp, #-8]!
2021 1.1 mrg adreq lr, _arm_return
2022 1.1 mrg bx \register
2023 1.1 mrg
2024 1.1 mrg SIZE (_interwork_call_via_\register)
2025 1.1 mrg
2026 1.1 mrg interwork_with_frame r7,\register,_interwork_r7_call_via_\register
2027 1.1 mrg interwork_with_frame r11,\register,_interwork_r11_call_via_\register
2028 1.1 mrg .endm
2029 1.1 mrg
2030 1.1 mrg interwork r0
2031 1.1 mrg interwork r1
2032 1.1 mrg interwork r2
2033 1.1 mrg interwork r3
2034 1.1 mrg interwork r4
2035 1.1 mrg interwork r5
2036 1.1 mrg interwork r6
2037 1.1 mrg interwork r7
2038 1.1 mrg interwork r8
2039 1.1 mrg interwork r9
2040 1.1 mrg interwork sl
2041 1.1 mrg interwork fp
2042 1.1 mrg interwork ip
2043 1.1 mrg interwork sp
2044 1.1 mrg
2045 1.1 mrg /* The LR case has to be handled a little differently... */
2046 1.1 mrg .code 16
2047 1.1 mrg
2048 1.1 mrg THUMB_FUNC_START _interwork_call_via_lr
2049 1.1 mrg
2050 1.1 mrg bx pc
2051 1.1 mrg nop
2052 1.1 mrg
2053 1.1 mrg .code 32
2054 1.1 mrg .globl .Lchange_lr
2055 1.1 mrg .Lchange_lr:
2056 1.1 mrg tst lr, #1
2057 1.1 mrg stmeqdb r13!, {lr, pc}
2058 1.1 mrg mov ip, lr
2059 1.1 mrg adreq lr, _arm_return
2060 1.1 mrg bx ip
2061 1.1 mrg
2062 1.1 mrg SIZE (_interwork_call_via_lr)
2063 1.1 mrg
2064 1.1 mrg #endif /* L_interwork_call_via_rX */
2065 1.1 mrg #endif /* !__thumb2__ */
2066 1.1 mrg
2067 1.1 mrg /* Functions to support compact pic switch tables in thumb1 state.
2068 1.1 mrg All these routines take an index into the table in r0. The
2069 1.1 mrg table is at LR & ~1 (but this must be rounded up in the case
2070 1.1 mrg of 32-bit entires). They are only permitted to clobber r12
2071 1.1 mrg and r14 and r0 must be preserved on exit. */
2072 1.1 mrg #ifdef L_thumb1_case_sqi
2073 1.1 mrg
2074 1.1 mrg .text
2075 1.1 mrg .align 0
2076 1.1 mrg .force_thumb
2077 1.1 mrg .syntax unified
2078 1.1 mrg THUMB_FUNC_START __gnu_thumb1_case_sqi
2079 1.1 mrg push {r1}
2080 1.1 mrg mov r1, lr
2081 1.1 mrg lsrs r1, r1, #1
2082 1.1 mrg lsls r1, r1, #1
2083 1.1 mrg ldrsb r1, [r1, r0]
2084 1.1 mrg lsls r1, r1, #1
2085 1.1 mrg add lr, lr, r1
2086 1.1 mrg pop {r1}
2087 1.1 mrg bx lr
2088 1.1 mrg SIZE (__gnu_thumb1_case_sqi)
2089 1.1 mrg #endif
2090 1.1 mrg
2091 1.1 mrg #ifdef L_thumb1_case_uqi
2092 1.1 mrg
2093 1.1 mrg .text
2094 1.1 mrg .align 0
2095 1.1 mrg .force_thumb
2096 1.1 mrg .syntax unified
2097 1.1 mrg THUMB_FUNC_START __gnu_thumb1_case_uqi
2098 1.1 mrg push {r1}
2099 1.1 mrg mov r1, lr
2100 1.1 mrg lsrs r1, r1, #1
2101 1.1 mrg lsls r1, r1, #1
2102 1.1 mrg ldrb r1, [r1, r0]
2103 1.1 mrg lsls r1, r1, #1
2104 1.1 mrg add lr, lr, r1
2105 1.1 mrg pop {r1}
2106 1.1 mrg bx lr
2107 1.1 mrg SIZE (__gnu_thumb1_case_uqi)
2108 1.1 mrg #endif
2109 1.1 mrg
2110 1.1 mrg #ifdef L_thumb1_case_shi
2111 1.1 mrg
2112 1.1 mrg .text
2113 1.1 mrg .align 0
2114 1.1 mrg .force_thumb
2115 1.1 mrg .syntax unified
2116 1.1 mrg THUMB_FUNC_START __gnu_thumb1_case_shi
2117 1.1 mrg push {r0, r1}
2118 1.1 mrg mov r1, lr
2119 1.1 mrg lsrs r1, r1, #1
2120 1.1 mrg lsls r0, r0, #1
2121 1.1 mrg lsls r1, r1, #1
2122 1.1 mrg ldrsh r1, [r1, r0]
2123 1.1 mrg lsls r1, r1, #1
2124 1.1 mrg add lr, lr, r1
2125 1.1 mrg pop {r0, r1}
2126 1.1 mrg bx lr
2127 1.1 mrg SIZE (__gnu_thumb1_case_shi)
2128 1.1 mrg #endif
2129 1.1 mrg
2130 1.1 mrg #ifdef L_thumb1_case_uhi
2131 1.1 mrg
2132 1.1 mrg .text
2133 1.1 mrg .align 0
2134 1.1 mrg .force_thumb
2135 1.1 mrg .syntax unified
2136 1.1 mrg THUMB_FUNC_START __gnu_thumb1_case_uhi
2137 1.1 mrg push {r0, r1}
2138 1.1 mrg mov r1, lr
2139 1.1 mrg lsrs r1, r1, #1
2140 1.1 mrg lsls r0, r0, #1
2141 1.1 mrg lsls r1, r1, #1
2142 1.1 mrg ldrh r1, [r1, r0]
2143 1.1 mrg lsls r1, r1, #1
2144 1.1 mrg add lr, lr, r1
2145 1.1 mrg pop {r0, r1}
2146 1.1 mrg bx lr
2147 1.1 mrg SIZE (__gnu_thumb1_case_uhi)
2148 1.1 mrg #endif
2149 1.1 mrg
2150 1.1.1.11 mrg #ifdef L_sync_none
2151 1.1.1.11 mrg /* Null implementation of __sync_synchronize, for use when
2152 1.1.1.11 mrg it is known that the system is single threaded. */
2153 1.1.1.11 mrg .text
2154 1.1.1.11 mrg .align 0
2155 1.1.1.11 mrg FUNC_START sync_synchronize_none
2156 1.1.1.11 mrg bx lr
2157 1.1.1.11 mrg FUNC_END sync_synchronize_none
2158 1.1.1.11 mrg #endif
2159 1.1.1.11 mrg
2160 1.1.1.11 mrg #ifdef L_sync_dmb
2161 1.1.1.11 mrg /* Full memory barrier using DMB. Requires Armv7 (all profiles)
2162 1.1.1.11 mrg or armv6-m, or later. */
2163 1.1.1.11 mrg .text
2164 1.1.1.11 mrg .align 0
2165 1.1.1.11 mrg #if __ARM_ARCH_PROFILE == 'M'
2166 1.1.1.11 mrg .arch armv6-m
2167 1.1.1.11 mrg #else
2168 1.1.1.11 mrg .arch armv7-a
2169 1.1.1.11 mrg #endif
2170 1.1.1.11 mrg FUNC_START sync_synchronize_dmb
2171 1.1.1.11 mrg /* M-profile devices only support SY as the synchronization level,
2172 1.1.1.11 mrg but that's probably what we want here anyway. */
2173 1.1.1.11 mrg dmb
2174 1.1.1.11 mrg RET
2175 1.1.1.11 mrg FUNC_END sync_synchronize_dmb
2176 1.1.1.11 mrg #endif
2177 1.1.1.11 mrg
2178 1.1.1.11 mrg #ifdef L_sync_cp15dmb
2179 1.1.1.11 mrg #ifndef NOT_ISA_TARGET_32BIT
2180 1.1.1.11 mrg /* Implementation of DMB using CP15 operations. This was first
2181 1.1.1.11 mrg defined in Armv6, but deprecated in Armv7 and can give
2182 1.1.1.11 mrg sub-optimal performance. */
2183 1.1.1.11 mrg .text
2184 1.1.1.11 mrg .align 0
2185 1.1.1.11 mrg ARM_FUNC_START sync_synchronize_cp15dmb
2186 1.1.1.11 mrg mcr p15, 0, r0, c7, c10, 5
2187 1.1.1.11 mrg RET
2188 1.1.1.11 mrg FUNC_END sync_synchronize_cp15dmb
2189 1.1.1.11 mrg #endif
2190 1.1.1.11 mrg #endif
2191 1.1.1.11 mrg
2192 1.1.1.11 mrg #ifdef L_sync_synchronize
2193 1.1.1.11 mrg /* Generic version of the synchronization primitive. If we know
2194 1.1.1.11 mrg that DMB exists, then use it. Otherwise, arrange for a link
2195 1.1.1.11 mrg time warning explaining how to pick a suitable alternative.
2196 1.1.1.11 mrg We choose not to use CP15DMB because it is performance
2197 1.1.1.11 mrg deprecated. We only define this function if generating
2198 1.1.1.11 mrg ELF binaries as otherwise we can't rely on the warning being
2199 1.1.1.11 mrg generated. */
2200 1.1.1.11 mrg
2201 1.1.1.11 mrg #ifdef __ELF__
2202 1.1.1.11 mrg .text
2203 1.1.1.11 mrg .align 0
2204 1.1.1.11 mrg FUNC_START sync_synchronize
2205 1.1.1.11 mrg #if __ARM_ARCH >= 7 || __ARM_ARCH_PROFILE == 'M'
2206 1.1.1.11 mrg dmb
2207 1.1.1.11 mrg #endif
2208 1.1.1.11 mrg RET
2209 1.1.1.11 mrg FUNC_END sync_synchronize
2210 1.1.1.11 mrg #if !(__ARM_ARCH >= 7 || __ARM_ARCH_PROFILE == 'M')
2211 1.1.1.11 mrg .section .gnu.warning.__sync_synchronize
2212 1.1.1.11 mrg .align 0
2213 1.1.1.11 mrg .ascii "This implementation of __sync_synchronize is a stub with "
2214 1.1.1.11 mrg .ascii "no effect. Relink with\n"
2215 1.1.1.11 mrg .ascii " -specs=sync-{none,dmb,cp15dmb}.specs\n"
2216 1.1.1.11 mrg .ascii "to specify exactly which barrier format to use and avoid "
2217 1.1.1.11 mrg .ascii "this warning\0"
2218 1.1.1.11 mrg #endif
2219 1.1.1.11 mrg #endif
2220 1.1.1.11 mrg #endif
2221 1.1.1.11 mrg
2222 1.1 mrg #ifdef L_thumb1_case_si
2223 1.1 mrg
2224 1.1 mrg .text
2225 1.1 mrg .align 0
2226 1.1 mrg .force_thumb
2227 1.1 mrg .syntax unified
2228 1.1 mrg THUMB_FUNC_START __gnu_thumb1_case_si
2229 1.1 mrg push {r0, r1}
2230 1.1 mrg mov r1, lr
2231 1.1 mrg adds.n r1, r1, #2 /* Align to word. */
2232 1.1 mrg lsrs r1, r1, #2
2233 1.1 mrg lsls r0, r0, #2
2234 1.1 mrg lsls r1, r1, #2
2235 1.1 mrg ldr r0, [r1, r0]
2236 1.1 mrg adds r0, r0, r1
2237 1.1 mrg mov lr, r0
2238 1.1 mrg pop {r0, r1}
2239 1.1 mrg mov pc, lr /* We know we were called from thumb code. */
2240 1.1 mrg SIZE (__gnu_thumb1_case_si)
2241 1.1 mrg #endif
2242 1.1 mrg
2243 1.1 mrg #endif /* Arch supports thumb. */
2244 1.1 mrg
2245 1.1.1.3 mrg .macro CFI_START_FUNCTION
2246 1.1.1.3 mrg .cfi_startproc
2247 1.1.1.3 mrg .cfi_remember_state
2248 1.1.1.3 mrg .endm
2249 1.1.1.3 mrg
2250 1.1.1.3 mrg .macro CFI_END_FUNCTION
2251 1.1.1.3 mrg .cfi_restore_state
2252 1.1.1.3 mrg .cfi_endproc
2253 1.1.1.3 mrg .endm
2254 1.1.1.3 mrg
2255 1.1 mrg #ifndef __symbian__
2256 1.1.1.8 mrg /* The condition here must match the one in gcc/config/arm/elf.h and
2257 1.1.1.8 mrg libgcc/config/arm/t-elf. */
2258 1.1.1.4 mrg #ifndef NOT_ISA_TARGET_32BIT
2259 1.1 mrg #include "ieee754-df.S"
2260 1.1 mrg #include "ieee754-sf.S"
2261 1.1 mrg #include "bpabi.S"
2262 1.1.1.4 mrg #else /* NOT_ISA_TARGET_32BIT */
2263 1.1 mrg #include "bpabi-v6m.S"
2264 1.1.1.4 mrg #endif /* NOT_ISA_TARGET_32BIT */
2265 1.1 mrg #endif /* !__symbian__ */
2266