]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/arm/bpabi.S
bpabi.S (__aeabi_uldivmod): Perform division using call to __udivmoddi4.
[thirdparty/gcc.git] / libgcc / config / arm / bpabi.S
1 /* Miscellaneous BPABI functions.
2
3 Copyright (C) 2003-2014 Free Software Foundation, Inc.
4 Contributed by CodeSourcery, LLC.
5
6 This file is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
9 later version.
10
11 This file is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
19
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
24
25 #ifdef __ARM_EABI__
26 /* Some attributes that are common to all routines in this file. */
27 /* Tag_ABI_align_needed: This code does not require 8-byte
28 alignment from the caller. */
29 /* .eabi_attribute 24, 0 -- default setting. */
30 /* Tag_ABI_align_preserved: This code preserves 8-byte
31 alignment in any callee. */
32 .eabi_attribute 25, 1
33 #endif /* __ARM_EABI__ */
34
35 #ifdef L_aeabi_lcmp
36
37 ARM_FUNC_START aeabi_lcmp
38 cmp xxh, yyh
39 do_it lt
40 movlt r0, #-1
41 do_it gt
42 movgt r0, #1
43 do_it ne
44 RETc(ne)
45 subs r0, xxl, yyl
46 do_it lo
47 movlo r0, #-1
48 do_it hi
49 movhi r0, #1
50 RET
51 FUNC_END aeabi_lcmp
52
53 #endif /* L_aeabi_lcmp */
54
55 #ifdef L_aeabi_ulcmp
56
57 ARM_FUNC_START aeabi_ulcmp
58 cmp xxh, yyh
59 do_it lo
60 movlo r0, #-1
61 do_it hi
62 movhi r0, #1
63 do_it ne
64 RETc(ne)
65 cmp xxl, yyl
66 do_it lo
67 movlo r0, #-1
68 do_it hi
69 movhi r0, #1
70 do_it eq
71 moveq r0, #0
72 RET
73 FUNC_END aeabi_ulcmp
74
75 #endif /* L_aeabi_ulcmp */
76
77 .macro test_div_by_zero signed
78 /* Tail-call to divide-by-zero handlers which may be overridden by the user,
79 so unwinding works properly. */
80 #if defined(__thumb2__)
81 cbnz yyh, 1f
82 cbnz yyl, 1f
83 cmp xxh, #0
84 do_it eq
85 cmpeq xxl, #0
86 .ifc \signed, unsigned
87 beq 2f
88 mov xxh, #0xffffffff
89 mov xxl, xxh
90 2:
91 .else
92 do_it lt, t
93 movlt xxl, #0
94 movlt xxh, #0x80000000
95 do_it gt, t
96 movgt xxh, #0x7fffffff
97 movgt xxl, #0xffffffff
98 .endif
99 b SYM (__aeabi_ldiv0) __PLT__
100 1:
101 #else
102 /* Note: Thumb-1 code calls via an ARM shim on processors which
103 support ARM mode. */
104 cmp yyh, #0
105 cmpeq yyl, #0
106 bne 2f
107 cmp xxh, #0
108 cmpeq xxl, #0
109 .ifc \signed, unsigned
110 movne xxh, #0xffffffff
111 movne xxl, #0xffffffff
112 .else
113 movlt xxh, #0x80000000
114 movlt xxl, #0
115 movgt xxh, #0x7fffffff
116 movgt xxl, #0xffffffff
117 .endif
118 b SYM (__aeabi_ldiv0) __PLT__
119 2:
120 #endif
121 .endm
122
123 /* we can use STRD/LDRD on v5TE and later, and any Thumb-2 architecture. */
124 #if (defined(__ARM_EABI__) \
125 && (defined(__thumb2__) \
126 || (__ARM_ARCH >= 5 && defined(__TARGET_FEATURE_DSP))))
127 #define CAN_USE_LDRD 1
128 #else
129 #define CAN_USE_LDRD 0
130 #endif
131
132 /* set up stack from for call to __udivmoddi4. At the end of the macro the
133 stack is arranged as follows:
134 sp+12 / space for remainder
135 sp+8 \ (written by __udivmoddi4)
136 sp+4 lr
137 sp+0 sp+8 [rp (remainder pointer) argument for __udivmoddi4]
138
139 */
140 .macro push_for_divide fname
141 #if defined(__thumb2__) && CAN_USE_LDRD
142 sub ip, sp, #8
143 strd ip, lr, [sp, #-16]!
144 #else
145 sub sp, sp, #8
146 do_push {sp, lr}
147 #endif
148 98: cfi_push 98b - \fname, 0xe, -0xc, 0x10
149 .endm
150
151 /* restore stack */
152 .macro pop_for_divide
153 ldr lr, [sp, #4]
154 #if CAN_USE_LDRD
155 ldrd r2, r3, [sp, #8]
156 add sp, sp, #16
157 #else
158 add sp, sp, #8
159 do_pop {r2, r3}
160 #endif
161 .endm
162
163 #ifdef L_aeabi_ldivmod
164
165 /* Perform 64 bit signed division.
166 Inputs:
167 r0:r1 numerator
168 r2:r3 denominator
169 Outputs:
170 r0:r1 quotient
171 r2:r3 remainder
172 */
173 ARM_FUNC_START aeabi_ldivmod
174 cfi_start __aeabi_ldivmod, LSYM(Lend_aeabi_ldivmod)
175 test_div_by_zero signed
176
177 sub sp, sp, #8
178 #if defined(__thumb2__)
179 mov ip, sp
180 push {ip, lr}
181 #else
182 do_push {sp, lr}
183 #endif
184 98: cfi_push 98b - __aeabi_ldivmod, 0xe, -0xc, 0x10
185 bl SYM(__gnu_ldivmod_helper) __PLT__
186 ldr lr, [sp, #4]
187 add sp, sp, #8
188 do_pop {r2, r3}
189 RET
190 cfi_end LSYM(Lend_aeabi_ldivmod)
191
192 #endif /* L_aeabi_ldivmod */
193
194 #ifdef L_aeabi_uldivmod
195
196 /* Perform 64 bit signed division.
197 Inputs:
198 r0:r1 numerator
199 r2:r3 denominator
200 Outputs:
201 r0:r1 quotient
202 r2:r3 remainder
203 */
204 ARM_FUNC_START aeabi_uldivmod
205 cfi_start __aeabi_uldivmod, LSYM(Lend_aeabi_uldivmod)
206 test_div_by_zero unsigned
207
208 push_for_divide __aeabi_uldivmod
209 /* arguments in (r0:r1), (r2:r3) and *sp */
210 bl SYM(__udivmoddi4) __PLT__
211 pop_for_divide
212 RET
213 cfi_end LSYM(Lend_aeabi_uldivmod)
214
215 #endif /* L_aeabi_divmod */
216