lib1funcs.asm (90075) | lib1funcs.asm (132718) |
---|---|
1@ libgcc routines for ARM cpu. 2@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk) 3 | 1@ libgcc routines for ARM cpu. 2@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk) 3 |
4/* Copyright 1995, 1996, 1998, 1999, 2000 Free Software Foundation, Inc. | 4/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004 5 Free Software Foundation, Inc. |
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 --- 33 unchanged lines hidden (view full) --- 46#ifdef __ELF__ 47#ifdef __thumb__ 48#define __PLT__ /* Not supported in Thumb assembler (for now). */ 49#else 50#define __PLT__ (PLT) 51#endif 52#define TYPE(x) .type SYM(x),function 53#define SIZE(x) .size SYM(x), . - SYM(x) | 6 7This file is free software; you can redistribute it and/or modify it 8under the terms of the GNU General Public License as published by the 9Free Software Foundation; either version 2, or (at your option) any 10later version. 11 12In addition to the permissions in the GNU General Public License, the 13Free Software Foundation gives you unlimited permission to link the --- 33 unchanged lines hidden (view full) --- 47#ifdef __ELF__ 48#ifdef __thumb__ 49#define __PLT__ /* Not supported in Thumb assembler (for now). */ 50#else 51#define __PLT__ (PLT) 52#endif 53#define TYPE(x) .type SYM(x),function 54#define SIZE(x) .size SYM(x), . - SYM(x) |
55#define LSYM(x) .x |
|
54#else 55#define __PLT__ 56#define TYPE(x) 57#define SIZE(x) | 56#else 57#define __PLT__ 58#define TYPE(x) 59#define SIZE(x) |
60#define LSYM(x) x |
|
58#endif 59 60/* Function end macros. Variants for 26 bit APCS and interworking. */ 61 | 61#endif 62 63/* Function end macros. Variants for 26 bit APCS and interworking. */ 64 |
65@ This selects the minimum architecture level required. 66#define __ARM_ARCH__ 3 67 68#if defined(__ARM_ARCH_3M__) || defined(__ARM_ARCH_4__) \ 69 || defined(__ARM_ARCH_4T__) 70/* We use __ARM_ARCH__ set to 4 here, but in reality it's any processor with 71 long multiply instructions. That includes v3M. */ 72# undef __ARM_ARCH__ 73# define __ARM_ARCH__ 4 74#endif 75 76#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \ 77 || defined(__ARM_ARCH_5TE__) 78# undef __ARM_ARCH__ 79# define __ARM_ARCH__ 5 80#endif 81 82/* How to return from a function call depends on the architecture variant. */ 83 |
|
62#ifdef __APCS_26__ | 84#ifdef __APCS_26__ |
85 |
|
63# define RET movs pc, lr 64# define RETc(x) mov##x##s pc, lr | 86# define RET movs pc, lr 87# define RETc(x) mov##x##s pc, lr |
65# define RETCOND ^ | 88 89#elif (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__) 90 91# define RET bx lr 92# define RETc(x) bx##x lr 93 94# if (__ARM_ARCH__ == 4) \ 95 && (defined(__thumb__) || defined(__THUMB_INTERWORK__)) 96# define __INTERWORKING__ 97# endif 98 99#else 100 101# define RET mov pc, lr 102# define RETc(x) mov##x pc, lr 103 104#endif 105 106/* Don't pass dirn, it's there just to get token pasting right. */ 107 108.macro RETLDM regs=, cond=, dirn=ia 109#ifdef __APCS_26__ 110 .ifc "\regs","" 111 ldm\cond\dirn sp!, {pc}^ 112 .else 113 ldm\cond\dirn sp!, {\regs, pc}^ 114 .endif 115#elif defined (__INTERWORKING__) 116 .ifc "\regs","" 117 ldr\cond lr, [sp], #4 118 .else 119 ldm\cond\dirn sp!, {\regs, lr} 120 .endif 121 bx\cond lr 122#else 123 .ifc "\regs","" 124 ldr\cond pc, [sp], #4 125 .else 126 ldm\cond\dirn sp!, {\regs, pc} 127 .endif 128#endif 129.endm 130 131 |
66.macro ARM_LDIV0 | 132.macro ARM_LDIV0 |
67Ldiv0: | 133LSYM(Ldiv0): |
68 str lr, [sp, #-4]! 69 bl SYM (__div0) __PLT__ 70 mov r0, #0 @ About as wrong as it could be. | 134 str lr, [sp, #-4]! 135 bl SYM (__div0) __PLT__ 136 mov r0, #0 @ About as wrong as it could be. |
71 ldmia sp!, {pc}^ | 137 RETLDM |
72.endm | 138.endm |
73#else 74# ifdef __THUMB_INTERWORK__ 75# define RET bx lr 76# define RETc(x) bx##x lr | 139 140 |
77.macro THUMB_LDIV0 | 141.macro THUMB_LDIV0 |
78Ldiv0: | 142LSYM(Ldiv0): |
79 push { lr } 80 bl SYM (__div0) 81 mov r0, #0 @ About as wrong as it could be. | 143 push { lr } 144 bl SYM (__div0) 145 mov r0, #0 @ About as wrong as it could be. |
146#if defined (__INTERWORKING__) |
|
82 pop { r1 } 83 bx r1 | 147 pop { r1 } 148 bx r1 |
84.endm 85.macro ARM_LDIV0 86Ldiv0: 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 97Ldiv0: 98 push { lr } 99 bl SYM (__div0) 100 mov r0, #0 @ About as wrong as it could be. | 149#else |
101 pop { pc } | 150 pop { pc } |
102.endm 103.macro ARM_LDIV0 104Ldiv0: 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 | 151#endif |
152.endm |
|
113 114.macro FUNC_END name | 153 154.macro FUNC_END name |
115Ldiv0: | 155 SIZE (__\name) 156.endm 157 158.macro DIV_FUNC_END name 159LSYM(Ldiv0): |
116#ifdef __thumb__ 117 THUMB_LDIV0 118#else 119 ARM_LDIV0 120#endif | 160#ifdef __thumb__ 161 THUMB_LDIV0 162#else 163 ARM_LDIV0 164#endif |
121 SIZE (__\name) | 165 FUNC_END \name |
122.endm 123 124.macro THUMB_FUNC_START name 125 .globl SYM (\name) 126 TYPE (\name) 127 .thumb_func 128SYM (\name): 129.endm --- 12 unchanged lines hidden (view full) --- 142 .text 143 .globl SYM (__\name) 144 TYPE (__\name) 145 .align 0 146 THUMB_CODE 147 THUMB_FUNC 148SYM (__\name): 149.endm | 166.endm 167 168.macro THUMB_FUNC_START name 169 .globl SYM (\name) 170 TYPE (\name) 171 .thumb_func 172SYM (\name): 173.endm --- 12 unchanged lines hidden (view full) --- 186 .text 187 .globl SYM (__\name) 188 TYPE (__\name) 189 .align 0 190 THUMB_CODE 191 THUMB_FUNC 192SYM (__\name): 193.endm |
150 | 194 195/* Special function that will always be coded in ARM assembly, even if 196 in Thumb-only compilation. */ 197 198#if defined(__thumb__) && !defined(__THUMB_INTERWORK__) 199.macro ARM_FUNC_START name 200 FUNC_START \name 201 bx pc 202 nop 203 .arm 204_L__\name: /* A hook to tell gdb that we've switched to ARM */ 205.endm 206#define EQUIV .thumb_set 207#else 208.macro ARM_FUNC_START name 209 .text 210 .globl SYM (__\name) 211 TYPE (__\name) 212 .align 0 213 .arm 214SYM (__\name): 215.endm 216#define EQUIV .set 217#endif 218 219.macro ARM_FUNC_ALIAS new old 220 .globl SYM (__\new) 221 EQUIV SYM (__\new), SYM (__\old) 222.endm 223 224#ifdef __thumb__ |
151/* Register aliases. */ 152 153work .req r4 @ XXXX is this safe ? 154dividend .req r0 155divisor .req r1 156overdone .req r2 157result .req r2 158curbit .req r3 | 225/* Register aliases. */ 226 227work .req r4 @ XXXX is this safe ? 228dividend .req r0 229divisor .req r1 230overdone .req r2 231result .req r2 232curbit .req r3 |
233#endif 234#if 0 |
|
159ip .req r12 160sp .req r13 161lr .req r14 162pc .req r15 | 235ip .req r12 236sp .req r13 237lr .req r14 238pc .req r15 |
239#endif |
|
163 164/* ------------------------------------------------------------------------ */ | 240 241/* ------------------------------------------------------------------------ */ |
165/* Bodies of the divsion and modulo routines. */ | 242/* Bodies of the division and modulo routines. */ |
166/* ------------------------------------------------------------------------ */ | 243/* ------------------------------------------------------------------------ */ |
167.macro ARM_DIV_MOD_BODY modulo 168Loop1: | 244.macro ARM_DIV_BODY dividend, divisor, result, curbit 245 246#if __ARM_ARCH__ >= 5 247 248 clz \curbit, \divisor 249 clz \result, \dividend 250 sub \result, \curbit, \result 251 mov \curbit, #1 252 mov \divisor, \divisor, lsl \result 253 mov \curbit, \curbit, lsl \result 254 mov \result, #0 255 256#else 257 258 @ Initially shift the divisor left 3 bits if possible, 259 @ set curbit accordingly. This allows for curbit to be located 260 @ at the left end of each 4 bit nibbles in the division loop 261 @ to save one loop in most cases. 262 tst \divisor, #0xe0000000 263 moveq \divisor, \divisor, lsl #3 264 moveq \curbit, #8 265 movne \curbit, #1 266 |
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. | 267 @ Unless the divisor is very big, shift it up in multiples of 268 @ four bits, since this is the amount of unwinding in the main 269 @ division loop. Continue shifting until the divisor is 270 @ larger than the dividend. |
173 cmp divisor, #0x10000000 174 cmplo divisor, dividend 175 movlo divisor, divisor, lsl #4 176 movlo curbit, curbit, lsl #4 177 blo Loop1 | 2711: cmp \divisor, #0x10000000 272 cmplo \divisor, \dividend 273 movlo \divisor, \divisor, lsl #4 274 movlo \curbit, \curbit, lsl #4 275 blo 1b |
178 | 276 |
179Lbignum: | |
180 @ For very big divisors, we must shift it a bit at a time, or 181 @ we will be in danger of overflowing. | 277 @ For very big divisors, we must shift it a bit at a time, or 278 @ we will be in danger of overflowing. |
182 cmp divisor, #0x80000000 183 cmplo divisor, dividend 184 movlo divisor, divisor, lsl #1 185 movlo curbit, curbit, lsl #1 186 blo Lbignum | 2791: cmp \divisor, #0x80000000 280 cmplo \divisor, \dividend 281 movlo \divisor, \divisor, lsl #1 282 movlo \curbit, \curbit, lsl #1 283 blo 1b |
187 | 284 |
188Loop3: 189 @ Test for possible subtractions. On the final pass, this may 190 @ subtract too much from the dividend ... | 285 mov \result, #0 286 287#endif 288 289 @ Division loop 2901: cmp \dividend, \divisor 291 subhs \dividend, \dividend, \divisor 292 orrhs \result, \result, \curbit 293 cmp \dividend, \divisor, lsr #1 294 subhs \dividend, \dividend, \divisor, lsr #1 295 orrhs \result, \result, \curbit, lsr #1 296 cmp \dividend, \divisor, lsr #2 297 subhs \dividend, \dividend, \divisor, lsr #2 298 orrhs \result, \result, \curbit, lsr #2 299 cmp \dividend, \divisor, lsr #3 300 subhs \dividend, \dividend, \divisor, lsr #3 301 orrhs \result, \result, \curbit, lsr #3 302 cmp \dividend, #0 @ Early termination? 303 movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? 304 movne \divisor, \divisor, lsr #4 305 bne 1b 306 307.endm 308/* ------------------------------------------------------------------------ */ 309.macro ARM_DIV2_ORDER divisor, order 310 311#if __ARM_ARCH__ >= 5 312 313 clz \order, \divisor 314 rsb \order, \order, #31 315 316#else 317 318 cmp \divisor, #(1 << 16) 319 movhs \divisor, \divisor, lsr #16 320 movhs \order, #16 321 movlo \order, #0 322 323 cmp \divisor, #(1 << 8) 324 movhs \divisor, \divisor, lsr #8 325 addhs \order, \order, #8 326 327 cmp \divisor, #(1 << 4) 328 movhs \divisor, \divisor, lsr #4 329 addhs \order, \order, #4 330 331 cmp \divisor, #(1 << 2) 332 addhi \order, \order, #3 333 addls \order, \order, \divisor, lsr #1 334 335#endif 336 337.endm 338/* ------------------------------------------------------------------------ */ 339.macro ARM_MOD_BODY dividend, divisor, order, spare 340 341#if __ARM_ARCH__ >= 5 342 343 clz \order, \divisor 344 clz \spare, \dividend 345 sub \order, \order, \spare 346 mov \divisor, \divisor, lsl \order |
191 | 347 |
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 196 cmp dividend, divisor 197 subhs dividend, dividend, divisor 198 cmp dividend, divisor, lsr #1 199 subhs dividend, dividend, divisor, lsr #1 200 orrhs overdone, overdone, curbit, ror #1 201 cmp dividend, divisor, lsr #2 202 subhs dividend, dividend, divisor, lsr #2 203 orrhs overdone, overdone, curbit, ror #2 204 cmp dividend, divisor, lsr #3 205 subhs dividend, dividend, divisor, lsr #3 206 orrhs overdone, overdone, curbit, ror #3 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 213 subhs dividend, dividend, divisor 214 orrhs result, result, curbit 215 cmp dividend, divisor, lsr #1 216 subhs dividend, dividend, divisor, lsr #1 217 orrhs result, result, curbit, lsr #1 218 cmp dividend, divisor, lsr #2 219 subhs dividend, dividend, divisor, lsr #2 220 orrhs result, result, curbit, lsr #2 221 cmp dividend, divisor, lsr #3 222 subhs dividend, dividend, divisor, lsr #3 223 orrhs result, result, curbit, lsr #3 224 .endif | 348#else |
225 | 349 |
226 cmp dividend, #0 @ Early termination? 227 movnes curbit, curbit, lsr #4 @ No, any more bits to do? 228 movne divisor, divisor, lsr #4 229 bne Loop3 | 350 mov \order, #0 |
230 | 351 |
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. 243 tstne ip, #0x7 244 beq Lgot_result 245 tst overdone, ip, ror #3 246 addne dividend, dividend, divisor, lsr #3 247 tst overdone, ip, ror #2 248 addne dividend, dividend, divisor, lsr #2 249 tst overdone, ip, ror #1 250 addne dividend, dividend, divisor, lsr #1 251 .endif | 352 @ Unless the divisor is very big, shift it up in multiples of 353 @ four bits, since this is the amount of unwinding in the main 354 @ division loop. Continue shifting until the divisor is 355 @ larger than the dividend. 3561: cmp \divisor, #0x10000000 357 cmplo \divisor, \dividend 358 movlo \divisor, \divisor, lsl #4 359 addlo \order, \order, #4 360 blo 1b |
252 | 361 |
253Lgot_result: | 362 @ For very big divisors, we must shift it a bit at a time, or 363 @ we will be in danger of overflowing. 3641: cmp \divisor, #0x80000000 365 cmplo \divisor, \dividend 366 movlo \divisor, \divisor, lsl #1 367 addlo \order, \order, #1 368 blo 1b 369 370#endif 371 372 @ Perform all needed substractions to keep only the reminder. 373 @ Do comparisons in batch of 4 first. 374 subs \order, \order, #3 @ yes, 3 is intended here 375 blt 2f 376 3771: cmp \dividend, \divisor 378 subhs \dividend, \dividend, \divisor 379 cmp \dividend, \divisor, lsr #1 380 subhs \dividend, \dividend, \divisor, lsr #1 381 cmp \dividend, \divisor, lsr #2 382 subhs \dividend, \dividend, \divisor, lsr #2 383 cmp \dividend, \divisor, lsr #3 384 subhs \dividend, \dividend, \divisor, lsr #3 385 cmp \dividend, #1 386 mov \divisor, \divisor, lsr #4 387 subges \order, \order, #4 388 bge 1b 389 390 tst \order, #3 391 teqne \dividend, #0 392 beq 5f 393 394 @ Either 1, 2 or 3 comparison/substractions are left. 3952: cmn \order, #2 396 blt 4f 397 beq 3f 398 cmp \dividend, \divisor 399 subhs \dividend, \dividend, \divisor 400 mov \divisor, \divisor, lsr #1 4013: cmp \dividend, \divisor 402 subhs \dividend, \dividend, \divisor 403 mov \divisor, \divisor, lsr #1 4044: cmp \dividend, \divisor 405 subhs \dividend, \dividend, \divisor 4065: |
254.endm 255/* ------------------------------------------------------------------------ */ 256.macro THUMB_DIV_MOD_BODY modulo 257 @ Load the constant 0x10000000 into our work register. 258 mov work, #1 259 lsl work, #28 | 407.endm 408/* ------------------------------------------------------------------------ */ 409.macro THUMB_DIV_MOD_BODY modulo 410 @ Load the constant 0x10000000 into our work register. 411 mov work, #1 412 lsl work, #28 |
260Loop1: | 413LSYM(Loop1): |
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 | 414 @ Unless the divisor is very big, shift it up in multiples of 415 @ four bits, since this is the amount of unwinding in the main 416 @ division loop. Continue shifting until the divisor is 417 @ larger than the dividend. 418 cmp divisor, work |
266 bhs Lbignum | 419 bhs LSYM(Lbignum) |
267 cmp divisor, dividend | 420 cmp divisor, dividend |
268 bhs Lbignum | 421 bhs LSYM(Lbignum) |
269 lsl divisor, #4 270 lsl curbit, #4 | 422 lsl divisor, #4 423 lsl curbit, #4 |
271 b Loop1 272Lbignum: | 424 b LSYM(Loop1) 425LSYM(Lbignum): |
273 @ Set work to 0x80000000 274 lsl work, #3 | 426 @ Set work to 0x80000000 427 lsl work, #3 |
275Loop2: | 428LSYM(Loop2): |
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 | 429 @ For very big divisors, we must shift it a bit at a time, or 430 @ we will be in danger of overflowing. 431 cmp divisor, work |
279 bhs Loop3 | 432 bhs LSYM(Loop3) |
280 cmp divisor, dividend | 433 cmp divisor, dividend |
281 bhs Loop3 | 434 bhs LSYM(Loop3) |
282 lsl divisor, #1 283 lsl curbit, #1 | 435 lsl divisor, #1 436 lsl curbit, #1 |
284 b Loop2 285Loop3: | 437 b LSYM(Loop2) 438LSYM(Loop3): |
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. 291 mov overdone, #0 292 cmp dividend, divisor | 439 @ Test for possible subtractions ... 440 .if \modulo 441 @ ... On the final pass, this may subtract too much from the dividend, 442 @ so keep track of which subtractions are done, we can fix them up 443 @ afterwards. 444 mov overdone, #0 445 cmp dividend, divisor |
293 blo Lover1 | 446 blo LSYM(Lover1) |
294 sub dividend, dividend, divisor | 447 sub dividend, dividend, divisor |
295Lover1: | 448LSYM(Lover1): |
296 lsr work, divisor, #1 297 cmp dividend, work | 449 lsr work, divisor, #1 450 cmp dividend, work |
298 blo Lover2 | 451 blo LSYM(Lover2) |
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 | 452 sub dividend, dividend, work 453 mov ip, curbit 454 mov work, #1 455 ror curbit, work 456 orr overdone, curbit 457 mov curbit, ip |
305Lover2: | 458LSYM(Lover2): |
306 lsr work, divisor, #2 307 cmp dividend, work | 459 lsr work, divisor, #2 460 cmp dividend, work |
308 blo Lover3 | 461 blo LSYM(Lover3) |
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 | 462 sub dividend, dividend, work 463 mov ip, curbit 464 mov work, #2 465 ror curbit, work 466 orr overdone, curbit 467 mov curbit, ip |
315Lover3: | 468LSYM(Lover3): |
316 lsr work, divisor, #3 317 cmp dividend, work | 469 lsr work, divisor, #3 470 cmp dividend, work |
318 blo Lover4 | 471 blo LSYM(Lover4) |
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 | 472 sub dividend, dividend, work 473 mov ip, curbit 474 mov work, #3 475 ror curbit, work 476 orr overdone, curbit 477 mov curbit, ip |
325Lover4: | 478LSYM(Lover4): |
326 mov ip, curbit 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 | 479 mov ip, curbit 480 .else 481 @ ... and note which bits are done in the result. On the final pass, 482 @ this may subtract too much from the dividend, but the result will be ok, 483 @ since the "bit" will have been shifted out at the bottom. 484 cmp dividend, divisor |
332 blo Lover1 | 485 blo LSYM(Lover1) |
333 sub dividend, dividend, divisor 334 orr result, result, curbit | 486 sub dividend, dividend, divisor 487 orr result, result, curbit |
335Lover1: | 488LSYM(Lover1): |
336 lsr work, divisor, #1 337 cmp dividend, work | 489 lsr work, divisor, #1 490 cmp dividend, work |
338 blo Lover2 | 491 blo LSYM(Lover2) |
339 sub dividend, dividend, work 340 lsr work, curbit, #1 341 orr result, work | 492 sub dividend, dividend, work 493 lsr work, curbit, #1 494 orr result, work |
342Lover2: | 495LSYM(Lover2): |
343 lsr work, divisor, #2 344 cmp dividend, work | 496 lsr work, divisor, #2 497 cmp dividend, work |
345 blo Lover3 | 498 blo LSYM(Lover3) |
346 sub dividend, dividend, work 347 lsr work, curbit, #2 348 orr result, work | 499 sub dividend, dividend, work 500 lsr work, curbit, #2 501 orr result, work |
349Lover3: | 502LSYM(Lover3): |
350 lsr work, divisor, #3 351 cmp dividend, work | 503 lsr work, divisor, #3 504 cmp dividend, work |
352 blo Lover4 | 505 blo LSYM(Lover4) |
353 sub dividend, dividend, work 354 lsr work, curbit, #3 355 orr result, work | 506 sub dividend, dividend, work 507 lsr work, curbit, #3 508 orr result, work |
356Lover4: | 509LSYM(Lover4): |
357 .endif 358 359 cmp dividend, #0 @ Early termination? | 510 .endif 511 512 cmp dividend, #0 @ Early termination? |
360 beq Lover5 | 513 beq LSYM(Lover5) |
361 lsr curbit, #4 @ No, any more bits to do? | 514 lsr curbit, #4 @ No, any more bits to do? |
362 beq Lover5 | 515 beq LSYM(Lover5) |
363 lsr divisor, #4 | 516 lsr divisor, #4 |
364 b Loop3 365Lover5: | 517 b LSYM(Loop3) 518LSYM(Lover5): |
366 .if \modulo 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. 370 mov work, #0xe 371 lsl work, #28 372 and overdone, work | 519 .if \modulo 520 @ Any subtractions that we should not have done will be recorded in 521 @ the top three bits of "overdone". Exactly which were not needed 522 @ are governed by the position of the bit, stored in ip. 523 mov work, #0xe 524 lsl work, #28 525 and overdone, work |
373 beq Lgot_result | 526 beq LSYM(Lgot_result) |
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 | 527 528 @ If we terminated early, because dividend became zero, then the 529 @ bit in ip will not be in the bottom nibble, and we should not 530 @ perform the additions below. We must test for this though 531 @ (rather relying upon the TSTs to prevent the additions) since 532 @ the bit in ip could be in the top two bits which might then match 533 @ with one of the smaller RORs. 534 mov curbit, ip 535 mov work, #0x7 536 tst curbit, work |
384 beq Lgot_result | 537 beq LSYM(Lgot_result) |
385 386 mov curbit, ip 387 mov work, #3 388 ror curbit, work 389 tst overdone, curbit | 538 539 mov curbit, ip 540 mov work, #3 541 ror curbit, work 542 tst overdone, curbit |
390 beq Lover6 | 543 beq LSYM(Lover6) |
391 lsr work, divisor, #3 392 add dividend, work | 544 lsr work, divisor, #3 545 add dividend, work |
393Lover6: | 546LSYM(Lover6): |
394 mov curbit, ip 395 mov work, #2 396 ror curbit, work 397 tst overdone, curbit | 547 mov curbit, ip 548 mov work, #2 549 ror curbit, work 550 tst overdone, curbit |
398 beq Lover7 | 551 beq LSYM(Lover7) |
399 lsr work, divisor, #2 400 add dividend, work | 552 lsr work, divisor, #2 553 add dividend, work |
401Lover7: | 554LSYM(Lover7): |
402 mov curbit, ip 403 mov work, #1 404 ror curbit, work 405 tst overdone, curbit | 555 mov curbit, ip 556 mov work, #1 557 ror curbit, work 558 tst overdone, curbit |
406 beq Lgot_result | 559 beq LSYM(Lgot_result) |
407 lsr work, divisor, #1 408 add dividend, work 409 .endif | 560 lsr work, divisor, #1 561 add dividend, work 562 .endif |
410Lgot_result: | 563LSYM(Lgot_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 | 564.endm 565/* ------------------------------------------------------------------------ */ 566/* Start of the Real Functions */ 567/* ------------------------------------------------------------------------ */ 568#ifdef L_udivsi3 569 570 FUNC_START udivsi3 571 572#ifdef __thumb__ 573 574 cmp divisor, #0 |
422 beq Ldiv0 | 575 beq LSYM(Ldiv0) |
423 mov curbit, #1 424 mov result, #0 425 426 push { work } 427 cmp dividend, divisor | 576 mov curbit, #1 577 mov result, #0 578 579 push { work } 580 cmp dividend, divisor |
428 blo Lgot_result | 581 blo LSYM(Lgot_result) |
429 430 THUMB_DIV_MOD_BODY 0 431 432 mov r0, result 433 pop { work } 434 RET 435 436#else /* ARM version. */ | 582 583 THUMB_DIV_MOD_BODY 0 584 585 mov r0, result 586 pop { work } 587 RET 588 589#else /* ARM version. */ |
590 591 subs r2, r1, #1 592 RETc(eq) 593 bcc LSYM(Ldiv0) 594 cmp r0, r1 595 bls 11f 596 tst r1, r2 597 beq 12f |
|
437 | 598 |
438 cmp divisor, #0 439 beq Ldiv0 440 mov curbit, #1 441 mov result, #0 442 cmp dividend, divisor 443 blo Lgot_result | 599 ARM_DIV_BODY r0, r1, r2, r3 |
444 | 600 |
445 ARM_DIV_MOD_BODY 0 446 447 mov r0, result | 601 mov r0, r2 |
448 RET 449 | 602 RET 603 |
60411: moveq r0, #1 605 movne r0, #0 606 RET 607 60812: ARM_DIV2_ORDER r1, r2 609 610 mov r0, r0, lsr r2 611 RET 612 |
|
450#endif /* ARM version */ 451 | 613#endif /* ARM version */ 614 |
452 FUNC_END udivsi3 | 615 DIV_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 | 616 617#endif /* L_udivsi3 */ 618/* ------------------------------------------------------------------------ */ 619#ifdef L_umodsi3 620 621 FUNC_START umodsi3 622 623#ifdef __thumb__ 624 625 cmp divisor, #0 |
463 beq Ldiv0 | 626 beq LSYM(Ldiv0) |
464 mov curbit, #1 465 cmp dividend, divisor | 627 mov curbit, #1 628 cmp dividend, divisor |
466 bhs Lover10 | 629 bhs LSYM(Lover10) |
467 RET 468 | 630 RET 631 |
469Lover10: | 632LSYM(Lover10): |
470 push { work } 471 472 THUMB_DIV_MOD_BODY 1 473 474 pop { work } 475 RET 476 477#else /* ARM version. */ 478 | 633 push { work } 634 635 THUMB_DIV_MOD_BODY 1 636 637 pop { work } 638 RET 639 640#else /* ARM version. */ 641 |
479 cmp divisor, #0 480 beq Ldiv0 481 cmp divisor, #1 482 cmpne dividend, divisor 483 moveq dividend, #0 484 RETc(lo) 485 mov curbit, #1 | 642 subs r2, r1, #1 @ compare divisor with 1 643 bcc LSYM(Ldiv0) 644 cmpne r0, r1 @ compare dividend with divisor 645 moveq r0, #0 646 tsthi r1, r2 @ see if divisor is power of 2 647 andeq r0, r0, r2 648 RETc(ls) |
486 | 649 |
487 ARM_DIV_MOD_BODY 1 | 650 ARM_MOD_BODY r0, r1, r2, r3 |
488 489 RET 490 491#endif /* ARM version. */ 492 | 651 652 RET 653 654#endif /* ARM version. */ 655 |
493 FUNC_END umodsi3 | 656 DIV_FUNC_END umodsi3 |
494 495#endif /* L_umodsi3 */ 496/* ------------------------------------------------------------------------ */ 497#ifdef L_divsi3 498 499 FUNC_START divsi3 500 501#ifdef __thumb__ 502 cmp divisor, #0 | 657 658#endif /* L_umodsi3 */ 659/* ------------------------------------------------------------------------ */ 660#ifdef L_divsi3 661 662 FUNC_START divsi3 663 664#ifdef __thumb__ 665 cmp divisor, #0 |
503 beq Ldiv0 | 666 beq LSYM(Ldiv0) |
504 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 | 667 668 push { work } 669 mov work, dividend 670 eor work, divisor @ Save the sign of the result. 671 mov ip, work 672 mov curbit, #1 673 mov result, #0 674 cmp divisor, #0 |
512 bpl Lover10 | 675 bpl LSYM(Lover10) |
513 neg divisor, divisor @ Loops below use unsigned. | 676 neg divisor, divisor @ Loops below use unsigned. |
514Lover10: | 677LSYM(Lover10): |
515 cmp dividend, #0 | 678 cmp dividend, #0 |
516 bpl Lover11 | 679 bpl LSYM(Lover11) |
517 neg dividend, dividend | 680 neg dividend, dividend |
518Lover11: | 681LSYM(Lover11): |
519 cmp dividend, divisor | 682 cmp dividend, divisor |
520 blo Lgot_result | 683 blo LSYM(Lgot_result) |
521 522 THUMB_DIV_MOD_BODY 0 523 524 mov r0, result 525 mov work, ip 526 cmp work, #0 | 684 685 THUMB_DIV_MOD_BODY 0 686 687 mov r0, result 688 mov work, ip 689 cmp work, #0 |
527 bpl Lover12 | 690 bpl LSYM(Lover12) |
528 neg r0, r0 | 691 neg r0, r0 |
529Lover12: | 692LSYM(Lover12): |
530 pop { work } 531 RET 532 533#else /* ARM version. */ 534 | 693 pop { work } 694 RET 695 696#else /* ARM version. */ 697 |
535 eor ip, dividend, divisor @ Save the sign of the result. 536 mov curbit, #1 537 mov result, #0 538 cmp divisor, #0 539 rsbmi divisor, divisor, #0 @ Loops below use unsigned. 540 beq Ldiv0 541 cmp dividend, #0 542 rsbmi dividend, dividend, #0 543 cmp dividend, divisor 544 blo Lgot_result | 698 cmp r1, #0 699 eor ip, r0, r1 @ save the sign of the result. 700 beq LSYM(Ldiv0) 701 rsbmi r1, r1, #0 @ loops below use unsigned. 702 subs r2, r1, #1 @ division by 1 or -1 ? 703 beq 10f 704 movs r3, r0 705 rsbmi r3, r0, #0 @ positive dividend value 706 cmp r3, r1 707 bls 11f 708 tst r1, r2 @ divisor is power of 2 ? 709 beq 12f |
545 | 710 |
546 ARM_DIV_MOD_BODY 0 | 711 ARM_DIV_BODY r3, r1, r0, r2 |
547 | 712 |
548 mov r0, result | |
549 cmp ip, #0 550 rsbmi r0, r0, #0 551 RET 552 | 713 cmp ip, #0 714 rsbmi r0, r0, #0 715 RET 716 |
71710: teq ip, r0 @ same sign ? 718 rsbmi r0, r0, #0 719 RET 720 72111: movlo r0, #0 722 moveq r0, ip, asr #31 723 orreq r0, r0, #1 724 RET 725 72612: ARM_DIV2_ORDER r1, r2 727 728 cmp ip, #0 729 mov r0, r3, lsr r2 730 rsbmi r0, r0, #0 731 RET 732 |
|
553#endif /* ARM version */ 554 | 733#endif /* ARM version */ 734 |
555 FUNC_END divsi3 | 735 DIV_FUNC_END divsi3 |
556 557#endif /* L_divsi3 */ 558/* ------------------------------------------------------------------------ */ 559#ifdef L_modsi3 560 561 FUNC_START modsi3 562 563#ifdef __thumb__ 564 565 mov curbit, #1 566 cmp divisor, #0 | 736 737#endif /* L_divsi3 */ 738/* ------------------------------------------------------------------------ */ 739#ifdef L_modsi3 740 741 FUNC_START modsi3 742 743#ifdef __thumb__ 744 745 mov curbit, #1 746 cmp divisor, #0 |
567 beq Ldiv0 568 bpl Lover10 | 747 beq LSYM(Ldiv0) 748 bpl LSYM(Lover10) |
569 neg divisor, divisor @ Loops below use unsigned. | 749 neg divisor, divisor @ Loops below use unsigned. |
570Lover10: | 750LSYM(Lover10): |
571 push { work } 572 @ Need to save the sign of the dividend, unfortunately, we need 573 @ work later on. Must do this after saving the original value of 574 @ the work register, because we will pop this value off first. 575 push { dividend } 576 cmp dividend, #0 | 751 push { work } 752 @ Need to save the sign of the dividend, unfortunately, we need 753 @ work later on. Must do this after saving the original value of 754 @ the work register, because we will pop this value off first. 755 push { dividend } 756 cmp dividend, #0 |
577 bpl Lover11 | 757 bpl LSYM(Lover11) |
578 neg dividend, dividend | 758 neg dividend, dividend |
579Lover11: | 759LSYM(Lover11): |
580 cmp dividend, divisor | 760 cmp dividend, divisor |
581 blo Lgot_result | 761 blo LSYM(Lgot_result) |
582 583 THUMB_DIV_MOD_BODY 1 584 585 pop { work } 586 cmp work, #0 | 762 763 THUMB_DIV_MOD_BODY 1 764 765 pop { work } 766 cmp work, #0 |
587 bpl Lover12 | 767 bpl LSYM(Lover12) |
588 neg dividend, dividend | 768 neg dividend, dividend |
589Lover12: | 769LSYM(Lover12): |
590 pop { work } 591 RET 592 593#else /* ARM version. */ 594 | 770 pop { work } 771 RET 772 773#else /* ARM version. */ 774 |
595 cmp divisor, #0 596 rsbmi divisor, divisor, #0 @ Loops below use unsigned. 597 beq Ldiv0 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]! 601 cmp dividend, #0 @ Test dividend against zero 602 rsbmi dividend, dividend, #0 @ If negative make positive 603 cmp dividend, divisor @ else if zero return zero 604 blo Lgot_result @ if smaller return dividend 605 mov curbit, #1 | 775 cmp r1, #0 776 beq LSYM(Ldiv0) 777 rsbmi r1, r1, #0 @ loops below use unsigned. 778 movs ip, r0 @ preserve sign of dividend 779 rsbmi r0, r0, #0 @ if negative make positive 780 subs r2, r1, #1 @ compare divisor with 1 781 cmpne r0, r1 @ compare dividend with divisor 782 moveq r0, #0 783 tsthi r1, r2 @ see if divisor is power of 2 784 andeq r0, r0, r2 785 bls 10f |
606 | 786 |
607 ARM_DIV_MOD_BODY 1 | 787 ARM_MOD_BODY r0, r1, r2, r3 |
608 | 788 |
609 ldr ip, [sp], #4 610 cmp ip, #0 611 rsbmi dividend, dividend, #0 | 78910: cmp ip, #0 790 rsbmi r0, r0, #0 |
612 RET 613 614#endif /* ARM version */ 615 | 791 RET 792 793#endif /* ARM version */ 794 |
616 FUNC_END modsi3 | 795 DIV_FUNC_END modsi3 |
617 618#endif /* L_modsi3 */ 619/* ------------------------------------------------------------------------ */ 620#ifdef L_dvmd_tls 621 622 FUNC_START div0 623 624 RET 625 | 796 797#endif /* L_modsi3 */ 798/* ------------------------------------------------------------------------ */ 799#ifdef L_dvmd_tls 800 801 FUNC_START div0 802 803 RET 804 |
626 SIZE (__div0) | 805 FUNC_END div0 |
627 628#endif /* L_divmodsi_tools */ 629/* ------------------------------------------------------------------------ */ 630#ifdef L_dvmd_lnx 631@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls 632 633/* Constants taken from <asm/unistd.h> and <asm/signal.h> */ 634#define SIGFPE 8 635#define __NR_SYSCALL_BASE 0x900000 636#define __NR_getpid (__NR_SYSCALL_BASE+ 20) 637#define __NR_kill (__NR_SYSCALL_BASE+ 37) 638 | 806 807#endif /* L_divmodsi_tools */ 808/* ------------------------------------------------------------------------ */ 809#ifdef L_dvmd_lnx 810@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls 811 812/* Constants taken from <asm/unistd.h> and <asm/signal.h> */ 813#define SIGFPE 8 814#define __NR_SYSCALL_BASE 0x900000 815#define __NR_getpid (__NR_SYSCALL_BASE+ 20) 816#define __NR_kill (__NR_SYSCALL_BASE+ 37) 817 |
818 .code 32 |
|
639 FUNC_START div0 640 641 stmfd sp!, {r1, lr} 642 swi __NR_getpid 643 cmn r0, #1000 | 819 FUNC_START div0 820 821 stmfd sp!, {r1, lr} 822 swi __NR_getpid 823 cmn r0, #1000 |
644 ldmhsfd sp!, {r1, pc}RETCOND @ not much we can do | 824 RETLDM r1 hs |
645 mov r1, #SIGFPE 646 swi __NR_kill | 825 mov r1, #SIGFPE 826 swi __NR_kill |
647#ifdef __THUMB_INTERWORK__ 648 ldmfd sp!, {r1, lr} 649 bx lr 650#else 651 ldmfd sp!, {r1, pc}RETCOND 652#endif | 827 RETLDM r1 |
653 | 828 |
654 SIZE (__div0) | 829 FUNC_END div0 |
655 656#endif /* L_dvmd_lnx */ 657/* ------------------------------------------------------------------------ */ 658/* These next two sections are here despite the fact that they contain Thumb 659 assembler because their presence allows interworked code to be linked even 660 when the GCC library is this one. */ 661 662/* Do not build the interworking functions when the target architecture does --- 52 unchanged lines hidden (view full) --- 715 called function to return here instead. Upon return we recover the real 716 return address and use a BX to get back to Thumb mode. */ 717 718 .text 719 .align 0 720 721 .code 32 722 .globl _arm_return | 830 831#endif /* L_dvmd_lnx */ 832/* ------------------------------------------------------------------------ */ 833/* These next two sections are here despite the fact that they contain Thumb 834 assembler because their presence allows interworked code to be linked even 835 when the GCC library is this one. */ 836 837/* Do not build the interworking functions when the target architecture does --- 52 unchanged lines hidden (view full) --- 890 called function to return here instead. Upon return we recover the real 891 return address and use a BX to get back to Thumb mode. */ 892 893 .text 894 .align 0 895 896 .code 32 897 .globl _arm_return |
723_arm_return: 724 ldmia r13!, {r12} 725 bx r12 | 898_arm_return: 899 RETLDM |
726 .code 16 727 | 900 .code 16 901 |
728.macro interwork register 729 .code 16 | 902.macro interwork register 903 .code 16 |
730 731 THUMB_FUNC_START _interwork_call_via_\register 732 | 904 905 THUMB_FUNC_START _interwork_call_via_\register 906 |
733 bx pc | 907 bx pc |
734 nop | 908 nop |
735 736 .code 32 737 .globl .Lchange_\register 738.Lchange_\register: | 909 910 .code 32 911 .globl LSYM(Lchange_\register) 912LSYM(Lchange_\register): |
739 tst \register, #1 | 913 tst \register, #1 |
740 stmeqdb r13!, {lr} | 914 streq lr, [sp, #-4]! |
741 adreq lr, _arm_return 742 bx \register 743 744 SIZE (_interwork_call_via_\register) 745.endm 746 747 interwork r0 748 interwork r1 --- 25 unchanged lines hidden (view full) --- 774 stmeqdb r13!, {lr} 775 mov ip, lr 776 adreq lr, _arm_return 777 bx ip 778 779 SIZE (_interwork_call_via_lr) 780 781#endif /* L_interwork_call_via_rX */ | 915 adreq lr, _arm_return 916 bx \register 917 918 SIZE (_interwork_call_via_\register) 919.endm 920 921 interwork r0 922 interwork r1 --- 25 unchanged lines hidden (view full) --- 948 stmeqdb r13!, {lr} 949 mov ip, lr 950 adreq lr, _arm_return 951 bx ip 952 953 SIZE (_interwork_call_via_lr) 954 955#endif /* L_interwork_call_via_rX */ |
956 957#include "ieee754-df.S" 958#include "ieee754-sf.S" 959 |
|