1/* libgcc routines for the MCore. 2 Copyright (C) 1993, 1999, 2000 Free Software Foundation, Inc. 3 4This file is part of GCC. 5 6GCC 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 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.) 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 27the Free Software Foundation, 51 Franklin Street, Fifth Floor, 28Boston, MA 02110-1301, USA. */ 29 30#define CONCAT1(a, b) CONCAT2(a, b) 31#define CONCAT2(a, b) a ## b 32 33/* Use the right prefix for global labels. */ 34 35#define SYM(x) CONCAT1 (__, x) 36 37#ifdef __ELF__ 38#define TYPE(x) .type SYM (x),@function 39#define SIZE(x) .size SYM (x), . - SYM (x) 40#else 41#define TYPE(x) 42#define SIZE(x) 43#endif 44 45.macro FUNC_START name 46 .text 47 .globl SYM (\name) 48 TYPE (\name) 49SYM (\name): 50.endm 51 52.macro FUNC_END name 53 SIZE (\name) 54.endm 55 56#ifdef L_udivsi3 57FUNC_START udiv32 58FUNC_START udivsi32 59 60 movi r1,0 // r1-r2 form 64 bit dividend 61 movi r4,1 // r4 is quotient (1 for a sentinel) 62 63 cmpnei r3,0 // look for 0 divisor 64 bt 9f 65 trap 3 // divide by 0 669: 67 // control iterations; skip across high order 0 bits in dividend 68 mov r7,r2 69 cmpnei r7,0 70 bt 8f 71 movi r2,0 // 0 dividend 72 jmp r15 // quick return 738: 74 ff1 r7 // figure distance to skip 75 lsl r4,r7 // move the sentinel along (with 0's behind) 76 lsl r2,r7 // and the low 32 bits of numerator 77 78// appears to be wrong... 79// tested out incorrectly in our OS work... 80// mov r7,r3 // looking at divisor 81// ff1 r7 // I can move 32-r7 more bits to left. 82// addi r7,1 // ok, one short of that... 83// mov r1,r2 84// lsr r1,r7 // bits that came from low order... 85// rsubi r7,31 // r7 == "32-n" == LEFT distance 86// addi r7,1 // this is (32-n) 87// lsl r4,r7 // fixes the high 32 (quotient) 88// lsl r2,r7 89// cmpnei r4,0 90// bf 4f // the sentinel went away... 91 92 // run the remaining bits 93 941: lslc r2,1 // 1 bit left shift of r1-r2 95 addc r1,r1 96 cmphs r1,r3 // upper 32 of dividend >= divisor? 97 bf 2f 98 sub r1,r3 // if yes, subtract divisor 992: addc r4,r4 // shift by 1 and count subtracts 100 bf 1b // if sentinel falls out of quotient, stop 101 1024: mov r2,r4 // return quotient 103 mov r3,r1 // and piggyback the remainder 104 jmp r15 105FUNC_END udiv32 106FUNC_END udivsi32 107#endif 108 109#ifdef L_umodsi3 110FUNC_START urem32 111FUNC_START umodsi3 112 movi r1,0 // r1-r2 form 64 bit dividend 113 movi r4,1 // r4 is quotient (1 for a sentinel) 114 cmpnei r3,0 // look for 0 divisor 115 bt 9f 116 trap 3 // divide by 0 1179: 118 // control iterations; skip across high order 0 bits in dividend 119 mov r7,r2 120 cmpnei r7,0 121 bt 8f 122 movi r2,0 // 0 dividend 123 jmp r15 // quick return 1248: 125 ff1 r7 // figure distance to skip 126 lsl r4,r7 // move the sentinel along (with 0's behind) 127 lsl r2,r7 // and the low 32 bits of numerator 128 1291: lslc r2,1 // 1 bit left shift of r1-r2 130 addc r1,r1 131 cmphs r1,r3 // upper 32 of dividend >= divisor? 132 bf 2f 133 sub r1,r3 // if yes, subtract divisor 1342: addc r4,r4 // shift by 1 and count subtracts 135 bf 1b // if sentinel falls out of quotient, stop 136 mov r2,r1 // return remainder 137 jmp r15 138FUNC_END urem32 139FUNC_END umodsi3 140#endif 141 142#ifdef L_divsi3 143FUNC_START div32 144FUNC_START divsi3 145 mov r5,r2 // calc sign of quotient 146 xor r5,r3 147 abs r2 // do unsigned divide 148 abs r3 149 movi r1,0 // r1-r2 form 64 bit dividend 150 movi r4,1 // r4 is quotient (1 for a sentinel) 151 cmpnei r3,0 // look for 0 divisor 152 bt 9f 153 trap 3 // divide by 0 1549: 155 // control iterations; skip across high order 0 bits in dividend 156 mov r7,r2 157 cmpnei r7,0 158 bt 8f 159 movi r2,0 // 0 dividend 160 jmp r15 // quick return 1618: 162 ff1 r7 // figure distance to skip 163 lsl r4,r7 // move the sentinel along (with 0's behind) 164 lsl r2,r7 // and the low 32 bits of numerator 165 166// tested out incorrectly in our OS work... 167// mov r7,r3 // looking at divisor 168// ff1 r7 // I can move 32-r7 more bits to left. 169// addi r7,1 // ok, one short of that... 170// mov r1,r2 171// lsr r1,r7 // bits that came from low order... 172// rsubi r7,31 // r7 == "32-n" == LEFT distance 173// addi r7,1 // this is (32-n) 174// lsl r4,r7 // fixes the high 32 (quotient) 175// lsl r2,r7 176// cmpnei r4,0 177// bf 4f // the sentinel went away... 178 179 // run the remaining bits 1801: lslc r2,1 // 1 bit left shift of r1-r2 181 addc r1,r1 182 cmphs r1,r3 // upper 32 of dividend >= divisor? 183 bf 2f 184 sub r1,r3 // if yes, subtract divisor 1852: addc r4,r4 // shift by 1 and count subtracts 186 bf 1b // if sentinel falls out of quotient, stop 187 1884: mov r2,r4 // return quotient 189 mov r3,r1 // piggyback the remainder 190 btsti r5,31 // after adjusting for sign 191 bf 3f 192 rsubi r2,0 193 rsubi r3,0 1943: jmp r15 195FUNC_END div32 196FUNC_END divsi3 197#endif 198 199#ifdef L_modsi3 200FUNC_START rem32 201FUNC_START modsi3 202 mov r5,r2 // calc sign of remainder 203 abs r2 // do unsigned divide 204 abs r3 205 movi r1,0 // r1-r2 form 64 bit dividend 206 movi r4,1 // r4 is quotient (1 for a sentinel) 207 cmpnei r3,0 // look for 0 divisor 208 bt 9f 209 trap 3 // divide by 0 2109: 211 // control iterations; skip across high order 0 bits in dividend 212 mov r7,r2 213 cmpnei r7,0 214 bt 8f 215 movi r2,0 // 0 dividend 216 jmp r15 // quick return 2178: 218 ff1 r7 // figure distance to skip 219 lsl r4,r7 // move the sentinel along (with 0's behind) 220 lsl r2,r7 // and the low 32 bits of numerator 221 2221: lslc r2,1 // 1 bit left shift of r1-r2 223 addc r1,r1 224 cmphs r1,r3 // upper 32 of dividend >= divisor? 225 bf 2f 226 sub r1,r3 // if yes, subtract divisor 2272: addc r4,r4 // shift by 1 and count subtracts 228 bf 1b // if sentinel falls out of quotient, stop 229 mov r2,r1 // return remainder 230 btsti r5,31 // after adjusting for sign 231 bf 3f 232 rsubi r2,0 2333: jmp r15 234FUNC_END rem32 235FUNC_END modsi3 236#endif 237 238 239/* GCC expects that {__eq,__ne,__gt,__ge,__le,__lt}{df2,sf2} 240 will behave as __cmpdf2. So, we stub the implementations to 241 jump on to __cmpdf2 and __cmpsf2. 242 243 All of these shortcircuit the return path so that __cmp{sd}f2 244 will go directly back to the caller. */ 245 246.macro COMPARE_DF_JUMP name 247 .import SYM (cmpdf2) 248FUNC_START \name 249 jmpi SYM (cmpdf2) 250FUNC_END \name 251.endm 252 253#ifdef L_eqdf2 254COMPARE_DF_JUMP eqdf2 255#endif /* L_eqdf2 */ 256 257#ifdef L_nedf2 258COMPARE_DF_JUMP nedf2 259#endif /* L_nedf2 */ 260 261#ifdef L_gtdf2 262COMPARE_DF_JUMP gtdf2 263#endif /* L_gtdf2 */ 264 265#ifdef L_gedf2 266COMPARE_DF_JUMP gedf2 267#endif /* L_gedf2 */ 268 269#ifdef L_ltdf2 270COMPARE_DF_JUMP ltdf2 271#endif /* L_ltdf2 */ 272 273#ifdef L_ledf2 274COMPARE_DF_JUMP ledf2 275#endif /* L_ledf2 */ 276 277/* SINGLE PRECISION FLOATING POINT STUBS */ 278 279.macro COMPARE_SF_JUMP name 280 .import SYM (cmpsf2) 281FUNC_START \name 282 jmpi SYM (cmpsf2) 283FUNC_END \name 284.endm 285 286#ifdef L_eqsf2 287COMPARE_SF_JUMP eqsf2 288#endif /* L_eqsf2 */ 289 290#ifdef L_nesf2 291COMPARE_SF_JUMP nesf2 292#endif /* L_nesf2 */ 293 294#ifdef L_gtsf2 295COMPARE_SF_JUMP gtsf2 296#endif /* L_gtsf2 */ 297 298#ifdef L_gesf2 299COMPARE_SF_JUMP __gesf2 300#endif /* L_gesf2 */ 301 302#ifdef L_ltsf2 303COMPARE_SF_JUMP __ltsf2 304#endif /* L_ltsf2 */ 305 306#ifdef L_lesf2 307COMPARE_SF_JUMP lesf2 308#endif /* L_lesf2 */ 309