1*404b540aSrobert/* libgcc routines for the MCore. 2*404b540aSrobert Copyright (C) 1993, 1999, 2000 Free Software Foundation, Inc. 3*404b540aSrobert 4*404b540aSrobertThis file is part of GCC. 5*404b540aSrobert 6*404b540aSrobertGCC is free software; you can redistribute it and/or modify it 7*404b540aSrobertunder the terms of the GNU General Public License as published by the 8*404b540aSrobertFree Software Foundation; either version 2, or (at your option) any 9*404b540aSrobertlater version. 10*404b540aSrobert 11*404b540aSrobertIn addition to the permissions in the GNU General Public License, the 12*404b540aSrobertFree Software Foundation gives you unlimited permission to link the 13*404b540aSrobertcompiled version of this file into combinations with other programs, 14*404b540aSrobertand to distribute those combinations without any restriction coming 15*404b540aSrobertfrom the use of this file. (The General Public License restrictions 16*404b540aSrobertdo apply in other respects; for example, they cover modification of 17*404b540aSrobertthe file, and distribution when not linked into a combine 18*404b540aSrobertexecutable.) 19*404b540aSrobert 20*404b540aSrobertThis file is distributed in the hope that it will be useful, but 21*404b540aSrobertWITHOUT ANY WARRANTY; without even the implied warranty of 22*404b540aSrobertMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23*404b540aSrobertGeneral Public License for more details. 24*404b540aSrobert 25*404b540aSrobertYou should have received a copy of the GNU General Public License 26*404b540aSrobertalong with this program; see the file COPYING. If not, write to 27*404b540aSrobertthe Free Software Foundation, 51 Franklin Street, Fifth Floor, 28*404b540aSrobertBoston, MA 02110-1301, USA. */ 29*404b540aSrobert 30*404b540aSrobert#define CONCAT1(a, b) CONCAT2(a, b) 31*404b540aSrobert#define CONCAT2(a, b) a ## b 32*404b540aSrobert 33*404b540aSrobert/* Use the right prefix for global labels. */ 34*404b540aSrobert 35*404b540aSrobert#define SYM(x) CONCAT1 (__, x) 36*404b540aSrobert 37*404b540aSrobert#ifdef __ELF__ 38*404b540aSrobert#define TYPE(x) .type SYM (x),@function 39*404b540aSrobert#define SIZE(x) .size SYM (x), . - SYM (x) 40*404b540aSrobert#else 41*404b540aSrobert#define TYPE(x) 42*404b540aSrobert#define SIZE(x) 43*404b540aSrobert#endif 44*404b540aSrobert 45*404b540aSrobert.macro FUNC_START name 46*404b540aSrobert .text 47*404b540aSrobert .globl SYM (\name) 48*404b540aSrobert TYPE (\name) 49*404b540aSrobertSYM (\name): 50*404b540aSrobert.endm 51*404b540aSrobert 52*404b540aSrobert.macro FUNC_END name 53*404b540aSrobert SIZE (\name) 54*404b540aSrobert.endm 55*404b540aSrobert 56*404b540aSrobert#ifdef L_udivsi3 57*404b540aSrobertFUNC_START udiv32 58*404b540aSrobertFUNC_START udivsi32 59*404b540aSrobert 60*404b540aSrobert movi r1,0 // r1-r2 form 64 bit dividend 61*404b540aSrobert movi r4,1 // r4 is quotient (1 for a sentinel) 62*404b540aSrobert 63*404b540aSrobert cmpnei r3,0 // look for 0 divisor 64*404b540aSrobert bt 9f 65*404b540aSrobert trap 3 // divide by 0 66*404b540aSrobert9: 67*404b540aSrobert // control iterations; skip across high order 0 bits in dividend 68*404b540aSrobert mov r7,r2 69*404b540aSrobert cmpnei r7,0 70*404b540aSrobert bt 8f 71*404b540aSrobert movi r2,0 // 0 dividend 72*404b540aSrobert jmp r15 // quick return 73*404b540aSrobert8: 74*404b540aSrobert ff1 r7 // figure distance to skip 75*404b540aSrobert lsl r4,r7 // move the sentinel along (with 0's behind) 76*404b540aSrobert lsl r2,r7 // and the low 32 bits of numerator 77*404b540aSrobert 78*404b540aSrobert// appears to be wrong... 79*404b540aSrobert// tested out incorrectly in our OS work... 80*404b540aSrobert// mov r7,r3 // looking at divisor 81*404b540aSrobert// ff1 r7 // I can move 32-r7 more bits to left. 82*404b540aSrobert// addi r7,1 // ok, one short of that... 83*404b540aSrobert// mov r1,r2 84*404b540aSrobert// lsr r1,r7 // bits that came from low order... 85*404b540aSrobert// rsubi r7,31 // r7 == "32-n" == LEFT distance 86*404b540aSrobert// addi r7,1 // this is (32-n) 87*404b540aSrobert// lsl r4,r7 // fixes the high 32 (quotient) 88*404b540aSrobert// lsl r2,r7 89*404b540aSrobert// cmpnei r4,0 90*404b540aSrobert// bf 4f // the sentinel went away... 91*404b540aSrobert 92*404b540aSrobert // run the remaining bits 93*404b540aSrobert 94*404b540aSrobert1: lslc r2,1 // 1 bit left shift of r1-r2 95*404b540aSrobert addc r1,r1 96*404b540aSrobert cmphs r1,r3 // upper 32 of dividend >= divisor? 97*404b540aSrobert bf 2f 98*404b540aSrobert sub r1,r3 // if yes, subtract divisor 99*404b540aSrobert2: addc r4,r4 // shift by 1 and count subtracts 100*404b540aSrobert bf 1b // if sentinel falls out of quotient, stop 101*404b540aSrobert 102*404b540aSrobert4: mov r2,r4 // return quotient 103*404b540aSrobert mov r3,r1 // and piggyback the remainder 104*404b540aSrobert jmp r15 105*404b540aSrobertFUNC_END udiv32 106*404b540aSrobertFUNC_END udivsi32 107*404b540aSrobert#endif 108*404b540aSrobert 109*404b540aSrobert#ifdef L_umodsi3 110*404b540aSrobertFUNC_START urem32 111*404b540aSrobertFUNC_START umodsi3 112*404b540aSrobert movi r1,0 // r1-r2 form 64 bit dividend 113*404b540aSrobert movi r4,1 // r4 is quotient (1 for a sentinel) 114*404b540aSrobert cmpnei r3,0 // look for 0 divisor 115*404b540aSrobert bt 9f 116*404b540aSrobert trap 3 // divide by 0 117*404b540aSrobert9: 118*404b540aSrobert // control iterations; skip across high order 0 bits in dividend 119*404b540aSrobert mov r7,r2 120*404b540aSrobert cmpnei r7,0 121*404b540aSrobert bt 8f 122*404b540aSrobert movi r2,0 // 0 dividend 123*404b540aSrobert jmp r15 // quick return 124*404b540aSrobert8: 125*404b540aSrobert ff1 r7 // figure distance to skip 126*404b540aSrobert lsl r4,r7 // move the sentinel along (with 0's behind) 127*404b540aSrobert lsl r2,r7 // and the low 32 bits of numerator 128*404b540aSrobert 129*404b540aSrobert1: lslc r2,1 // 1 bit left shift of r1-r2 130*404b540aSrobert addc r1,r1 131*404b540aSrobert cmphs r1,r3 // upper 32 of dividend >= divisor? 132*404b540aSrobert bf 2f 133*404b540aSrobert sub r1,r3 // if yes, subtract divisor 134*404b540aSrobert2: addc r4,r4 // shift by 1 and count subtracts 135*404b540aSrobert bf 1b // if sentinel falls out of quotient, stop 136*404b540aSrobert mov r2,r1 // return remainder 137*404b540aSrobert jmp r15 138*404b540aSrobertFUNC_END urem32 139*404b540aSrobertFUNC_END umodsi3 140*404b540aSrobert#endif 141*404b540aSrobert 142*404b540aSrobert#ifdef L_divsi3 143*404b540aSrobertFUNC_START div32 144*404b540aSrobertFUNC_START divsi3 145*404b540aSrobert mov r5,r2 // calc sign of quotient 146*404b540aSrobert xor r5,r3 147*404b540aSrobert abs r2 // do unsigned divide 148*404b540aSrobert abs r3 149*404b540aSrobert movi r1,0 // r1-r2 form 64 bit dividend 150*404b540aSrobert movi r4,1 // r4 is quotient (1 for a sentinel) 151*404b540aSrobert cmpnei r3,0 // look for 0 divisor 152*404b540aSrobert bt 9f 153*404b540aSrobert trap 3 // divide by 0 154*404b540aSrobert9: 155*404b540aSrobert // control iterations; skip across high order 0 bits in dividend 156*404b540aSrobert mov r7,r2 157*404b540aSrobert cmpnei r7,0 158*404b540aSrobert bt 8f 159*404b540aSrobert movi r2,0 // 0 dividend 160*404b540aSrobert jmp r15 // quick return 161*404b540aSrobert8: 162*404b540aSrobert ff1 r7 // figure distance to skip 163*404b540aSrobert lsl r4,r7 // move the sentinel along (with 0's behind) 164*404b540aSrobert lsl r2,r7 // and the low 32 bits of numerator 165*404b540aSrobert 166*404b540aSrobert// tested out incorrectly in our OS work... 167*404b540aSrobert// mov r7,r3 // looking at divisor 168*404b540aSrobert// ff1 r7 // I can move 32-r7 more bits to left. 169*404b540aSrobert// addi r7,1 // ok, one short of that... 170*404b540aSrobert// mov r1,r2 171*404b540aSrobert// lsr r1,r7 // bits that came from low order... 172*404b540aSrobert// rsubi r7,31 // r7 == "32-n" == LEFT distance 173*404b540aSrobert// addi r7,1 // this is (32-n) 174*404b540aSrobert// lsl r4,r7 // fixes the high 32 (quotient) 175*404b540aSrobert// lsl r2,r7 176*404b540aSrobert// cmpnei r4,0 177*404b540aSrobert// bf 4f // the sentinel went away... 178*404b540aSrobert 179*404b540aSrobert // run the remaining bits 180*404b540aSrobert1: lslc r2,1 // 1 bit left shift of r1-r2 181*404b540aSrobert addc r1,r1 182*404b540aSrobert cmphs r1,r3 // upper 32 of dividend >= divisor? 183*404b540aSrobert bf 2f 184*404b540aSrobert sub r1,r3 // if yes, subtract divisor 185*404b540aSrobert2: addc r4,r4 // shift by 1 and count subtracts 186*404b540aSrobert bf 1b // if sentinel falls out of quotient, stop 187*404b540aSrobert 188*404b540aSrobert4: mov r2,r4 // return quotient 189*404b540aSrobert mov r3,r1 // piggyback the remainder 190*404b540aSrobert btsti r5,31 // after adjusting for sign 191*404b540aSrobert bf 3f 192*404b540aSrobert rsubi r2,0 193*404b540aSrobert rsubi r3,0 194*404b540aSrobert3: jmp r15 195*404b540aSrobertFUNC_END div32 196*404b540aSrobertFUNC_END divsi3 197*404b540aSrobert#endif 198*404b540aSrobert 199*404b540aSrobert#ifdef L_modsi3 200*404b540aSrobertFUNC_START rem32 201*404b540aSrobertFUNC_START modsi3 202*404b540aSrobert mov r5,r2 // calc sign of remainder 203*404b540aSrobert abs r2 // do unsigned divide 204*404b540aSrobert abs r3 205*404b540aSrobert movi r1,0 // r1-r2 form 64 bit dividend 206*404b540aSrobert movi r4,1 // r4 is quotient (1 for a sentinel) 207*404b540aSrobert cmpnei r3,0 // look for 0 divisor 208*404b540aSrobert bt 9f 209*404b540aSrobert trap 3 // divide by 0 210*404b540aSrobert9: 211*404b540aSrobert // control iterations; skip across high order 0 bits in dividend 212*404b540aSrobert mov r7,r2 213*404b540aSrobert cmpnei r7,0 214*404b540aSrobert bt 8f 215*404b540aSrobert movi r2,0 // 0 dividend 216*404b540aSrobert jmp r15 // quick return 217*404b540aSrobert8: 218*404b540aSrobert ff1 r7 // figure distance to skip 219*404b540aSrobert lsl r4,r7 // move the sentinel along (with 0's behind) 220*404b540aSrobert lsl r2,r7 // and the low 32 bits of numerator 221*404b540aSrobert 222*404b540aSrobert1: lslc r2,1 // 1 bit left shift of r1-r2 223*404b540aSrobert addc r1,r1 224*404b540aSrobert cmphs r1,r3 // upper 32 of dividend >= divisor? 225*404b540aSrobert bf 2f 226*404b540aSrobert sub r1,r3 // if yes, subtract divisor 227*404b540aSrobert2: addc r4,r4 // shift by 1 and count subtracts 228*404b540aSrobert bf 1b // if sentinel falls out of quotient, stop 229*404b540aSrobert mov r2,r1 // return remainder 230*404b540aSrobert btsti r5,31 // after adjusting for sign 231*404b540aSrobert bf 3f 232*404b540aSrobert rsubi r2,0 233*404b540aSrobert3: jmp r15 234*404b540aSrobertFUNC_END rem32 235*404b540aSrobertFUNC_END modsi3 236*404b540aSrobert#endif 237*404b540aSrobert 238*404b540aSrobert 239*404b540aSrobert/* GCC expects that {__eq,__ne,__gt,__ge,__le,__lt}{df2,sf2} 240*404b540aSrobert will behave as __cmpdf2. So, we stub the implementations to 241*404b540aSrobert jump on to __cmpdf2 and __cmpsf2. 242*404b540aSrobert 243*404b540aSrobert All of these shortcircuit the return path so that __cmp{sd}f2 244*404b540aSrobert will go directly back to the caller. */ 245*404b540aSrobert 246*404b540aSrobert.macro COMPARE_DF_JUMP name 247*404b540aSrobert .import SYM (cmpdf2) 248*404b540aSrobertFUNC_START \name 249*404b540aSrobert jmpi SYM (cmpdf2) 250*404b540aSrobertFUNC_END \name 251*404b540aSrobert.endm 252*404b540aSrobert 253*404b540aSrobert#ifdef L_eqdf2 254*404b540aSrobertCOMPARE_DF_JUMP eqdf2 255*404b540aSrobert#endif /* L_eqdf2 */ 256*404b540aSrobert 257*404b540aSrobert#ifdef L_nedf2 258*404b540aSrobertCOMPARE_DF_JUMP nedf2 259*404b540aSrobert#endif /* L_nedf2 */ 260*404b540aSrobert 261*404b540aSrobert#ifdef L_gtdf2 262*404b540aSrobertCOMPARE_DF_JUMP gtdf2 263*404b540aSrobert#endif /* L_gtdf2 */ 264*404b540aSrobert 265*404b540aSrobert#ifdef L_gedf2 266*404b540aSrobertCOMPARE_DF_JUMP gedf2 267*404b540aSrobert#endif /* L_gedf2 */ 268*404b540aSrobert 269*404b540aSrobert#ifdef L_ltdf2 270*404b540aSrobertCOMPARE_DF_JUMP ltdf2 271*404b540aSrobert#endif /* L_ltdf2 */ 272*404b540aSrobert 273*404b540aSrobert#ifdef L_ledf2 274*404b540aSrobertCOMPARE_DF_JUMP ledf2 275*404b540aSrobert#endif /* L_ledf2 */ 276*404b540aSrobert 277*404b540aSrobert/* SINGLE PRECISION FLOATING POINT STUBS */ 278*404b540aSrobert 279*404b540aSrobert.macro COMPARE_SF_JUMP name 280*404b540aSrobert .import SYM (cmpsf2) 281*404b540aSrobertFUNC_START \name 282*404b540aSrobert jmpi SYM (cmpsf2) 283*404b540aSrobertFUNC_END \name 284*404b540aSrobert.endm 285*404b540aSrobert 286*404b540aSrobert#ifdef L_eqsf2 287*404b540aSrobertCOMPARE_SF_JUMP eqsf2 288*404b540aSrobert#endif /* L_eqsf2 */ 289*404b540aSrobert 290*404b540aSrobert#ifdef L_nesf2 291*404b540aSrobertCOMPARE_SF_JUMP nesf2 292*404b540aSrobert#endif /* L_nesf2 */ 293*404b540aSrobert 294*404b540aSrobert#ifdef L_gtsf2 295*404b540aSrobertCOMPARE_SF_JUMP gtsf2 296*404b540aSrobert#endif /* L_gtsf2 */ 297*404b540aSrobert 298*404b540aSrobert#ifdef L_gesf2 299*404b540aSrobertCOMPARE_SF_JUMP __gesf2 300*404b540aSrobert#endif /* L_gesf2 */ 301*404b540aSrobert 302*404b540aSrobert#ifdef L_ltsf2 303*404b540aSrobertCOMPARE_SF_JUMP __ltsf2 304*404b540aSrobert#endif /* L_ltsf2 */ 305*404b540aSrobert 306*404b540aSrobert#ifdef L_lesf2 307*404b540aSrobertCOMPARE_SF_JUMP lesf2 308*404b540aSrobert#endif /* L_lesf2 */ 309