]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/lib1funcs.asm
i * libgcc1-test.c, libgcc1.c, config/i386/perform.h: Delete file.
[thirdparty/gcc.git] / gcc / config / arm / lib1funcs.asm
CommitLineData
7857f134 1@ libgcc routines for ARM cpu.
bd28bf5a 2@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
454e0249 3
7405dc37 4/* Copyright 1995, 1996, 1998, 1999, 2000 Free Software Foundation, Inc.
454e0249
DE
5
6This file is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11In addition to the permissions in the GNU General Public License, the
12Free Software Foundation gives you unlimited permission to link the
f7af368f
JL
13compiled version of this file into combinations with other programs,
14and to distribute those combinations without any restriction coming
15from the use of this file. (The General Public License restrictions
16do apply in other respects; for example, they cover modification of
17the file, and distribution when not linked into a combine
18executable.)
454e0249
DE
19
20This file is distributed in the hope that it will be useful, but
21WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23General Public License for more details.
24
25You should have received a copy of the GNU General Public License
26along with this program; see the file COPYING. If not, write to
8fb289e7
RK
27the Free Software Foundation, 59 Temple Place - Suite 330,
28Boston, MA 02111-1307, USA. */
6dcd26ea 29/* ------------------------------------------------------------------------ */
888e552f
NC
30
31/* We need to know what prefix to add to function names. */
32
2a5307b1
NC
33#ifndef __USER_LABEL_PREFIX__
34#error __USER_LABEL_PREFIX__ not defined
35#endif
36
a1e27b76
NC
37/* ANSI concatenation macros. */
38
39#define CONCAT1(a, b) CONCAT2(a, b)
40#define CONCAT2(a, b) a ## b
41
42/* Use the right prefix for global labels. */
43
44#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
45
140fa895 46#ifdef __ELF__
d5b7b3ae 47#ifdef __thumb__
6dcd26ea 48#define __PLT__ /* Not supported in Thumb assembler (for now). */
d5b7b3ae 49#else
b355a481 50#define __PLT__ (PLT)
d5b7b3ae 51#endif
b355a481
NC
52#define TYPE(x) .type SYM(x),function
53#define SIZE(x) .size SYM(x), . - SYM(x)
54#else
55#define __PLT__
56#define TYPE(x)
57#define SIZE(x)
58#endif
59
6dcd26ea 60/* Function end macros. Variants for 26 bit APCS and interworking. */
888e552f 61
6dcd26ea
RE
62#ifdef __APCS_26__
63# define RET movs pc, lr
64# define RETc(x) mov##x##s pc, lr
65# define RETCOND ^
66.macro ARM_LDIV0
67Ldiv0:
68 str lr, [sp, #-4]!
69 bl SYM (__div0) __PLT__
70 mov r0, #0 @ About as wrong as it could be.
71 ldmia sp!, {pc}^
72.endm
73#else
74# ifdef __THUMB_INTERWORK__
75# define RET bx lr
76# define RETc(x) bx##x lr
77.macro THUMB_LDIV0
888e552f 78Ldiv0:
6dcd26ea
RE
79 push { lr }
80 bl SYM (__div0)
81 mov r0, #0 @ About as wrong as it could be.
82 pop { r1 }
83 bx r1
84.endm
85.macro ARM_LDIV0
888e552f 86Ldiv0:
6dcd26ea
RE
87 str lr, [sp, #-4]!
88 bl SYM (__div0) __PLT__
89 mov r0, #0 @ About as wrong as it could be.
90 ldr lr, [sp], #4
91 bx lr
92.endm
93# else
94# define RET mov pc, lr
95# define RETc(x) mov##x pc, lr
96.macro THUMB_LDIV0
888e552f 97Ldiv0:
6dcd26ea
RE
98 push { lr }
99 bl SYM (__div0)
100 mov r0, #0 @ About as wrong as it could be.
101 pop { pc }
102.endm
103.macro ARM_LDIV0
888e552f 104Ldiv0:
6dcd26ea
RE
105 str lr, [sp, #-4]!
106 bl SYM (__div0) __PLT__
107 mov r0, #0 @ About as wrong as it could be.
108 ldmia sp!, {pc}
109.endm
110# endif
111# define RETCOND
112#endif
113
888e552f
NC
114.macro FUNC_END name
115Ldiv0:
116#ifdef __thumb__
117 THUMB_LDIV0
118#else
119 ARM_LDIV0
120#endif
121 SIZE (__\name)
122.endm
123
124.macro THUMB_FUNC_START name
125 .globl SYM (\name)
126 TYPE (\name)
127 .thumb_func
128SYM (\name):
129.endm
130
131/* Function start macros. Variants for ARM and Thumb. */
132
d5b7b3ae
RE
133#ifdef __thumb__
134#define THUMB_FUNC .thumb_func
135#define THUMB_CODE .force_thumb
136#else
137#define THUMB_FUNC
138#define THUMB_CODE
139#endif
140
d5b7b3ae
RE
141.macro FUNC_START name
142 .text
143 .globl SYM (__\name)
144 TYPE (__\name)
145 .align 0
146 THUMB_CODE
147 THUMB_FUNC
148SYM (__\name):
149.endm
6dcd26ea 150
888e552f 151/* Register aliases. */
454e0249 152
888e552f 153work .req r4 @ XXXX is this safe ?
bd28bf5a
RE
154dividend .req r0
155divisor .req r1
888e552f 156overdone .req r2
bd28bf5a
RE
157result .req r2
158curbit .req r3
159ip .req r12
160sp .req r13
161lr .req r14
162pc .req r15
454e0249 163
888e552f
NC
164/* ------------------------------------------------------------------------ */
165/* Bodies of the divsion and modulo routines. */
166/* ------------------------------------------------------------------------ */
167.macro ARM_DIV_MOD_BODY modulo
bd28bf5a
RE
168Loop1:
169 @ Unless the divisor is very big, shift it up in multiples of
170 @ four bits, since this is the amount of unwinding in the main
171 @ division loop. Continue shifting until the divisor is
172 @ larger than the dividend.
173 cmp divisor, #0x10000000
02689e18
NC
174 cmplo divisor, dividend
175 movlo divisor, divisor, lsl #4
176 movlo curbit, curbit, lsl #4
177 blo Loop1
bd28bf5a
RE
178
179Lbignum:
180 @ For very big divisors, we must shift it a bit at a time, or
181 @ we will be in danger of overflowing.
182 cmp divisor, #0x80000000
02689e18
NC
183 cmplo divisor, dividend
184 movlo divisor, divisor, lsl #1
185 movlo curbit, curbit, lsl #1
186 blo Lbignum
bd28bf5a
RE
187
188Loop3:
888e552f
NC
189 @ Test for possible subtractions. On the final pass, this may
190 @ subtract too much from the dividend ...
191
192 .if \modulo
193 @ ... so keep track of which subtractions are done in OVERDONE.
194 @ We can fix them up afterwards.
195 mov overdone, #0
bd28bf5a 196 cmp dividend, divisor
02689e18 197 subhs dividend, dividend, divisor
888e552f 198 cmp dividend, divisor, lsr #1
02689e18
NC
199 subhs dividend, dividend, divisor, lsr #1
200 orrhs overdone, overdone, curbit, ror #1
888e552f 201 cmp dividend, divisor, lsr #2
02689e18
NC
202 subhs dividend, dividend, divisor, lsr #2
203 orrhs overdone, overdone, curbit, ror #2
888e552f 204 cmp dividend, divisor, lsr #3
02689e18
NC
205 subhs dividend, dividend, divisor, lsr #3
206 orrhs overdone, overdone, curbit, ror #3
888e552f
NC
207 mov ip, curbit
208 .else
209 @ ... so keep track of which subtractions are done in RESULT.
210 @ The result will be ok, since the "bit" will have been
211 @ shifted out at the bottom.
212 cmp dividend, divisor
02689e18
NC
213 subhs dividend, dividend, divisor
214 orrhs result, result, curbit
888e552f 215 cmp dividend, divisor, lsr #1
02689e18
NC
216 subhs dividend, dividend, divisor, lsr #1
217 orrhs result, result, curbit, lsr #1
888e552f 218 cmp dividend, divisor, lsr #2
02689e18
NC
219 subhs dividend, dividend, divisor, lsr #2
220 orrhs result, result, curbit, lsr #2
888e552f 221 cmp dividend, divisor, lsr #3
02689e18
NC
222 subhs dividend, dividend, divisor, lsr #3
223 orrhs result, result, curbit, lsr #3
888e552f 224 .endif
454e0249 225
888e552f 226 cmp dividend, #0 @ Early termination?
02689e18
NC
227 movnes curbit, curbit, lsr #4 @ No, any more bits to do?
228 movne divisor, divisor, lsr #4
215e4ee7 229 bne Loop3
454e0249 230
888e552f
NC
231 .if \modulo
232Lfixup_dividend:
233 @ Any subtractions that we should not have done will be recorded in
234 @ the top three bits of OVERDONE. Exactly which were not needed
235 @ are governed by the position of the bit, stored in IP.
236 ands overdone, overdone, #0xe0000000
237 @ If we terminated early, because dividend became zero, then the
238 @ bit in ip will not be in the bottom nibble, and we should not
239 @ perform the additions below. We must test for this though
240 @ (rather relying upon the TSTs to prevent the additions) since
241 @ the bit in ip could be in the top two bits which might then match
242 @ with one of the smaller RORs.
02689e18
NC
243 tstne ip, #0x7
244 beq Lgot_result
888e552f 245 tst overdone, ip, ror #3
02689e18 246 addne dividend, dividend, divisor, lsr #3
888e552f 247 tst overdone, ip, ror #2
02689e18 248 addne dividend, dividend, divisor, lsr #2
888e552f 249 tst overdone, ip, ror #1
02689e18 250 addne dividend, dividend, divisor, lsr #1
888e552f 251 .endif
b355a481 252
888e552f
NC
253Lgot_result:
254.endm
6dcd26ea 255/* ------------------------------------------------------------------------ */
888e552f
NC
256.macro THUMB_DIV_MOD_BODY modulo
257 @ Load the constant 0x10000000 into our work register.
d5b7b3ae
RE
258 mov work, #1
259 lsl work, #28
260Loop1:
261 @ Unless the divisor is very big, shift it up in multiples of
262 @ four bits, since this is the amount of unwinding in the main
263 @ division loop. Continue shifting until the divisor is
264 @ larger than the dividend.
265 cmp divisor, work
02689e18 266 bhs Lbignum
d5b7b3ae 267 cmp divisor, dividend
02689e18 268 bhs Lbignum
d5b7b3ae 269 lsl divisor, #4
888e552f 270 lsl curbit, #4
d5b7b3ae
RE
271 b Loop1
272Lbignum:
273 @ Set work to 0x80000000
274 lsl work, #3
275Loop2:
276 @ For very big divisors, we must shift it a bit at a time, or
277 @ we will be in danger of overflowing.
278 cmp divisor, work
02689e18 279 bhs Loop3
d5b7b3ae 280 cmp divisor, dividend
02689e18 281 bhs Loop3
d5b7b3ae 282 lsl divisor, #1
888e552f 283 lsl curbit, #1
d5b7b3ae
RE
284 b Loop2
285Loop3:
888e552f
NC
286 @ Test for possible subtractions ...
287 .if \modulo
288 @ ... On the final pass, this may subtract too much from the dividend,
289 @ so keep track of which subtractions are done, we can fix them up
290 @ afterwards.
d5b7b3ae
RE
291 mov overdone, #0
292 cmp dividend, divisor
02689e18 293 blo Lover1
d5b7b3ae 294 sub dividend, dividend, divisor
888e552f 295Lover1:
d5b7b3ae
RE
296 lsr work, divisor, #1
297 cmp dividend, work
02689e18 298 blo Lover2
d5b7b3ae
RE
299 sub dividend, dividend, work
300 mov ip, curbit
301 mov work, #1
302 ror curbit, work
303 orr overdone, curbit
304 mov curbit, ip
888e552f 305Lover2:
d5b7b3ae
RE
306 lsr work, divisor, #2
307 cmp dividend, work
02689e18 308 blo Lover3
d5b7b3ae
RE
309 sub dividend, dividend, work
310 mov ip, curbit
311 mov work, #2
312 ror curbit, work
313 orr overdone, curbit
314 mov curbit, ip
888e552f 315Lover3:
d5b7b3ae
RE
316 lsr work, divisor, #3
317 cmp dividend, work
02689e18 318 blo Lover4
d5b7b3ae
RE
319 sub dividend, dividend, work
320 mov ip, curbit
321 mov work, #3
322 ror curbit, work
323 orr overdone, curbit
324 mov curbit, ip
888e552f 325Lover4:
d5b7b3ae 326 mov ip, curbit
888e552f
NC
327 .else
328 @ ... and note which bits are done in the result. On the final pass,
329 @ this may subtract too much from the dividend, but the result will be ok,
330 @ since the "bit" will have been shifted out at the bottom.
331 cmp dividend, divisor
02689e18 332 blo Lover1
888e552f
NC
333 sub dividend, dividend, divisor
334 orr result, result, curbit
335Lover1:
336 lsr work, divisor, #1
337 cmp dividend, work
02689e18 338 blo Lover2
888e552f
NC
339 sub dividend, dividend, work
340 lsr work, curbit, #1
341 orr result, work
342Lover2:
343 lsr work, divisor, #2
344 cmp dividend, work
02689e18 345 blo Lover3
888e552f
NC
346 sub dividend, dividend, work
347 lsr work, curbit, #2
348 orr result, work
349Lover3:
350 lsr work, divisor, #3
351 cmp dividend, work
02689e18 352 blo Lover4
888e552f
NC
353 sub dividend, dividend, work
354 lsr work, curbit, #3
355 orr result, work
356Lover4:
357 .endif
358
d5b7b3ae 359 cmp dividend, #0 @ Early termination?
02689e18 360 beq Lover5
888e552f 361 lsr curbit, #4 @ No, any more bits to do?
02689e18 362 beq Lover5
d5b7b3ae
RE
363 lsr divisor, #4
364 b Loop3
888e552f
NC
365Lover5:
366 .if \modulo
d5b7b3ae
RE
367 @ Any subtractions that we should not have done will be recorded in
368 @ the top three bits of "overdone". Exactly which were not needed
369 @ are governed by the position of the bit, stored in ip.
d5b7b3ae 370 mov work, #0xe
888e552f 371 lsl work, #28
d5b7b3ae 372 and overdone, work
02689e18 373 beq Lgot_result
7405dc37
NC
374
375 @ If we terminated early, because dividend became zero, then the
376 @ bit in ip will not be in the bottom nibble, and we should not
377 @ perform the additions below. We must test for this though
378 @ (rather relying upon the TSTs to prevent the additions) since
379 @ the bit in ip could be in the top two bits which might then match
380 @ with one of the smaller RORs.
381 mov curbit, ip
382 mov work, #0x7
383 tst curbit, work
02689e18 384 beq Lgot_result
7405dc37 385
d5b7b3ae
RE
386 mov curbit, ip
387 mov work, #3
388 ror curbit, work
389 tst overdone, curbit
02689e18 390 beq Lover6
d5b7b3ae 391 lsr work, divisor, #3
888e552f
NC
392 add dividend, work
393Lover6:
d5b7b3ae
RE
394 mov curbit, ip
395 mov work, #2
396 ror curbit, work
397 tst overdone, curbit
02689e18 398 beq Lover7
d5b7b3ae 399 lsr work, divisor, #2
888e552f
NC
400 add dividend, work
401Lover7:
d5b7b3ae
RE
402 mov curbit, ip
403 mov work, #1
404 ror curbit, work
405 tst overdone, curbit
02689e18 406 beq Lgot_result
d5b7b3ae 407 lsr work, divisor, #1
888e552f
NC
408 add dividend, work
409 .endif
410Lgot_result:
411.endm
412/* ------------------------------------------------------------------------ */
413/* Start of the Real Functions */
414/* ------------------------------------------------------------------------ */
415#ifdef L_udivsi3
416
417 FUNC_START udivsi3
418
419#ifdef __thumb__
420
421 cmp divisor, #0
02689e18 422 beq Ldiv0
888e552f
NC
423 mov curbit, #1
424 mov result, #0
425
426 push { work }
427 cmp dividend, divisor
02689e18 428 blo Lgot_result
888e552f
NC
429
430 THUMB_DIV_MOD_BODY 0
431
432 mov r0, result
d5b7b3ae 433 pop { work }
ef42b1dd 434 RET
888e552f
NC
435
436#else /* ARM version. */
d5b7b3ae
RE
437
438 cmp divisor, #0
02689e18 439 beq Ldiv0
d5b7b3ae 440 mov curbit, #1
888e552f 441 mov result, #0
d5b7b3ae 442 cmp dividend, divisor
02689e18 443 blo Lgot_result
888e552f
NC
444
445 ARM_DIV_MOD_BODY 0
446
447 mov r0, result
448 RET
bd28bf5a 449
888e552f 450#endif /* ARM version */
bd28bf5a 451
888e552f
NC
452 FUNC_END udivsi3
453
454#endif /* L_udivsi3 */
455/* ------------------------------------------------------------------------ */
456#ifdef L_umodsi3
457
458 FUNC_START umodsi3
459
460#ifdef __thumb__
461
462 cmp divisor, #0
02689e18 463 beq Ldiv0
888e552f 464 mov curbit, #1
bd28bf5a 465 cmp dividend, divisor
02689e18 466 bhs Lover10
888e552f 467 RET
bd28bf5a 468
888e552f
NC
469Lover10:
470 push { work }
471
472 THUMB_DIV_MOD_BODY 1
473
474 pop { work }
475 RET
476
477#else /* ARM version. */
478
479 cmp divisor, #0
02689e18 480 beq Ldiv0
888e552f 481 cmp divisor, #1
02689e18
NC
482 cmpne dividend, divisor
483 moveq dividend, #0
484 RETc(lo)
888e552f
NC
485 mov curbit, #1
486
487 ARM_DIV_MOD_BODY 1
488
d5b7b3ae 489 RET
454e0249 490
7405dc37 491#endif /* ARM version. */
d5b7b3ae 492
6dcd26ea 493 FUNC_END umodsi3
b355a481 494
bd28bf5a 495#endif /* L_umodsi3 */
6dcd26ea 496/* ------------------------------------------------------------------------ */
bd28bf5a 497#ifdef L_divsi3
454e0249 498
6dcd26ea 499 FUNC_START divsi3
d5b7b3ae
RE
500
501#ifdef __thumb__
502 cmp divisor, #0
02689e18 503 beq Ldiv0
b355a481 504
d5b7b3ae
RE
505 push { work }
506 mov work, dividend
507 eor work, divisor @ Save the sign of the result.
508 mov ip, work
509 mov curbit, #1
510 mov result, #0
511 cmp divisor, #0
02689e18 512 bpl Lover10
d5b7b3ae 513 neg divisor, divisor @ Loops below use unsigned.
888e552f 514Lover10:
d5b7b3ae 515 cmp dividend, #0
02689e18 516 bpl Lover11
d5b7b3ae 517 neg dividend, dividend
888e552f 518Lover11:
d5b7b3ae 519 cmp dividend, divisor
02689e18 520 blo Lgot_result
d5b7b3ae 521
888e552f 522 THUMB_DIV_MOD_BODY 0
d5b7b3ae 523
d5b7b3ae
RE
524 mov r0, result
525 mov work, ip
526 cmp work, #0
02689e18 527 bpl Lover12
d5b7b3ae 528 neg r0, r0
888e552f 529Lover12:
d5b7b3ae 530 pop { work }
888e552f 531 RET
454e0249 532
6dcd26ea 533#else /* ARM version. */
d5b7b3ae 534
bd28bf5a
RE
535 eor ip, dividend, divisor @ Save the sign of the result.
536 mov curbit, #1
537 mov result, #0
538 cmp divisor, #0
02689e18
NC
539 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
540 beq Ldiv0
bd28bf5a 541 cmp dividend, #0
02689e18 542 rsbmi dividend, dividend, #0
bd28bf5a 543 cmp dividend, divisor
02689e18 544 blo Lgot_result
bd28bf5a 545
888e552f
NC
546 ARM_DIV_MOD_BODY 0
547
bd28bf5a
RE
548 mov r0, result
549 cmp ip, #0
02689e18 550 rsbmi r0, r0, #0
d5b7b3ae 551 RET
454e0249 552
6dcd26ea 553#endif /* ARM version */
d5b7b3ae 554
6dcd26ea 555 FUNC_END divsi3
b355a481 556
bd28bf5a 557#endif /* L_divsi3 */
6dcd26ea 558/* ------------------------------------------------------------------------ */
454e0249
DE
559#ifdef L_modsi3
560
6dcd26ea 561 FUNC_START modsi3
d5b7b3ae
RE
562
563#ifdef __thumb__
454e0249 564
d5b7b3ae
RE
565 mov curbit, #1
566 cmp divisor, #0
02689e18
NC
567 beq Ldiv0
568 bpl Lover10
d5b7b3ae 569 neg divisor, divisor @ Loops below use unsigned.
888e552f 570Lover10:
d5b7b3ae
RE
571 push { work }
572 @ Need to save the sign of the dividend, unfortunately, we need
888e552f 573 @ work later on. Must do this after saving the original value of
d5b7b3ae
RE
574 @ the work register, because we will pop this value off first.
575 push { dividend }
576 cmp dividend, #0
02689e18 577 bpl Lover11
d5b7b3ae 578 neg dividend, dividend
888e552f 579Lover11:
d5b7b3ae 580 cmp dividend, divisor
02689e18 581 blo Lgot_result
d5b7b3ae 582
888e552f
NC
583 THUMB_DIV_MOD_BODY 1
584
d5b7b3ae
RE
585 pop { work }
586 cmp work, #0
02689e18 587 bpl Lover12
d5b7b3ae 588 neg dividend, dividend
888e552f 589Lover12:
d5b7b3ae
RE
590 pop { work }
591 RET
7405dc37 592
6dcd26ea 593#else /* ARM version. */
d5b7b3ae 594
bd28bf5a 595 cmp divisor, #0
02689e18
NC
596 rsbmi divisor, divisor, #0 @ Loops below use unsigned.
597 beq Ldiv0
bd28bf5a
RE
598 @ Need to save the sign of the dividend, unfortunately, we need
599 @ ip later on; this is faster than pushing lr and using that.
600 str dividend, [sp, #-4]!
888e552f 601 cmp dividend, #0 @ Test dividend against zero
02689e18 602 rsbmi dividend, dividend, #0 @ If negative make positive
888e552f 603 cmp dividend, divisor @ else if zero return zero
02689e18 604 blo Lgot_result @ if smaller return dividend
888e552f 605 mov curbit, #1
bd28bf5a 606
888e552f 607 ARM_DIV_MOD_BODY 1
bd28bf5a 608
bd28bf5a
RE
609 ldr ip, [sp], #4
610 cmp ip, #0
02689e18 611 rsbmi dividend, dividend, #0
d5b7b3ae 612 RET
7405dc37 613
6dcd26ea
RE
614#endif /* ARM version */
615
616 FUNC_END modsi3
b355a481 617
454e0249 618#endif /* L_modsi3 */
6dcd26ea 619/* ------------------------------------------------------------------------ */
2ecc7cad 620#ifdef L_dvmd_tls
454e0249 621
7405dc37 622 FUNC_START div0
454e0249 623
7405dc37 624 RET
d5b7b3ae 625
6dcd26ea 626 SIZE (__div0)
b355a481 627
454e0249 628#endif /* L_divmodsi_tools */
6dcd26ea 629/* ------------------------------------------------------------------------ */
75d3a15b
NC
630#ifdef L_dvmd_lnx
631@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
632
633#include <asm/unistd.h>
b355a481 634
75d3a15b
NC
635#define SIGFPE 8 @ cant use <asm/signal.h> as it
636 @ contains too much C rubbish
7405dc37 637 FUNC_START div0
d5b7b3ae 638
75d3a15b
NC
639 stmfd sp!, {r1, lr}
640 swi __NR_getpid
641 cmn r0, #1000
b355a481 642 ldmhsfd sp!, {r1, pc}RETCOND @ not much we can do
75d3a15b
NC
643 mov r1, #SIGFPE
644 swi __NR_kill
6dcd26ea
RE
645#ifdef __THUMB_INTERWORK__
646 ldmfd sp!, {r1, lr}
647 bx lr
648#else
75d3a15b 649 ldmfd sp!, {r1, pc}RETCOND
6dcd26ea 650#endif
7405dc37 651
6dcd26ea 652 SIZE (__div0)
b355a481 653
75d3a15b 654#endif /* L_dvmd_lnx */
6dcd26ea 655/* ------------------------------------------------------------------------ */
75d3a15b
NC
656/* These next two sections are here despite the fact that they contain Thumb
657 assembler because their presence allows interworked code to be linked even
658 when the GCC library is this one. */
659
c84df4c5
NC
660/* Do not build the interworking functions when the target architecture does
661 not support Thumb instructions. (This can be a multilib option). */
662#if defined L_call_via_rX && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
75d3a15b
NC
663
664/* These labels & instructions are used by the Arm/Thumb interworking code.
665 The address of function to be called is loaded into a register and then
666 one of these labels is called via a BL instruction. This puts the
667 return address into the link register with the bottom bit set, and the
668 code here switches to the correct mode before executing the function. */
669
670 .text
671 .align 0
ec8aac6f 672 .force_thumb
7405dc37 673
75d3a15b 674.macro call_via register
6dcd26ea
RE
675 THUMB_FUNC_START _call_via_\register
676
75d3a15b
NC
677 bx \register
678 nop
2a5307b1
NC
679
680 SIZE (_call_via_\register)
75d3a15b
NC
681.endm
682
683 call_via r0
684 call_via r1
685 call_via r2
686 call_via r3
687 call_via r4
688 call_via r5
689 call_via r6
690 call_via r7
691 call_via r8
692 call_via r9
693 call_via sl
694 call_via fp
695 call_via ip
696 call_via sp
697 call_via lr
698
699#endif /* L_call_via_rX */
6dcd26ea 700/* ------------------------------------------------------------------------ */
c84df4c5
NC
701/* Do not build the interworking functions when the target architecture does
702 not support Thumb instructions. (This can be a multilib option). */
703#if defined L_interwork_call_via_rX && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
7405dc37 704
75d3a15b
NC
705/* These labels & instructions are used by the Arm/Thumb interworking code,
706 when the target address is in an unknown instruction set. The address
707 of function to be called is loaded into a register and then one of these
708 labels is called via a BL instruction. This puts the return address
709 into the link register with the bottom bit set, and the code here
710 switches to the correct mode before executing the function. Unfortunately
711 the target code cannot be relied upon to return via a BX instruction, so
712 instead we have to store the resturn address on the stack and allow the
713 called function to return here instead. Upon return we recover the real
714 return address and use a BX to get back to Thumb mode. */
715
716 .text
717 .align 0
718
719 .code 32
2a5307b1 720 .globl _arm_return
75d3a15b
NC
721_arm_return:
722 ldmia r13!, {r12}
723 bx r12
724 .code 16
725
726.macro interwork register
727 .code 16
6dcd26ea
RE
728
729 THUMB_FUNC_START _interwork_call_via_\register
730
75d3a15b
NC
731 bx pc
732 nop
733
734 .code 32
735 .globl .Lchange_\register
736.Lchange_\register:
737 tst \register, #1
738 stmeqdb r13!, {lr}
739 adreq lr, _arm_return
740 bx \register
2a5307b1
NC
741
742 SIZE (_interwork_call_via_\register)
75d3a15b
NC
743.endm
744
745 interwork r0
746 interwork r1
747 interwork r2
748 interwork r3
749 interwork r4
750 interwork r5
751 interwork r6
752 interwork r7
753 interwork r8
754 interwork r9
755 interwork sl
756 interwork fp
757 interwork ip
758 interwork sp
2a5307b1 759
6dcd26ea 760 /* The LR case has to be handled a little differently... */
2a5307b1 761 .code 16
6dcd26ea
RE
762
763 THUMB_FUNC_START _interwork_call_via_lr
764
2a5307b1
NC
765 bx pc
766 nop
767
768 .code 32
769 .globl .Lchange_lr
770.Lchange_lr:
771 tst lr, #1
772 stmeqdb r13!, {lr}
773 mov ip, lr
774 adreq lr, _arm_return
775 bx ip
776
777 SIZE (_interwork_call_via_lr)
778
75d3a15b 779#endif /* L_interwork_call_via_rX */