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