1/* libgcc routines for the MCore. 2 Copyright (C) 1993-2022 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 3, or (at your option) any 9later version. 10 11This file is distributed in the hope that it will be useful, but 12WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14General Public License for more details. 15 16Under Section 7 of GPL version 3, you are granted additional 17permissions described in the GCC Runtime Library Exception, version 183.1, as published by the Free Software Foundation. 19 20You should have received a copy of the GNU General Public License and 21a copy of the GCC Runtime Library Exception along with this program; 22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23<http://www.gnu.org/licenses/>. */ 24 25#define CONCAT1(a, b) CONCAT2(a, b) 26#define CONCAT2(a, b) a ## b 27 28/* Use the right prefix for global labels. */ 29 30#define SYM(x) CONCAT1 (__, x) 31 32#ifdef __ELF__ 33#define TYPE(x) .type SYM (x),@function 34#define SIZE(x) .size SYM (x), . - SYM (x) 35#else 36#define TYPE(x) 37#define SIZE(x) 38#endif 39 40.macro FUNC_START name 41 .text 42 .globl SYM (\name) 43 TYPE (\name) 44SYM (\name): 45.endm 46 47.macro FUNC_END name 48 SIZE (\name) 49.endm 50 51#ifdef L_udivsi3 52FUNC_START udiv32 53FUNC_START udivsi32 54 55 movi r1,0 // r1-r2 form 64 bit dividend 56 movi r4,1 // r4 is quotient (1 for a sentinel) 57 58 cmpnei r3,0 // look for 0 divisor 59 bt 9f 60 trap 3 // divide by 0 619: 62 // control iterations; skip across high order 0 bits in dividend 63 mov r7,r2 64 cmpnei r7,0 65 bt 8f 66 movi r2,0 // 0 dividend 67 jmp r15 // quick return 688: 69 ff1 r7 // figure distance to skip 70 lsl r4,r7 // move the sentinel along (with 0's behind) 71 lsl r2,r7 // and the low 32 bits of numerator 72 73// appears to be wrong... 74// tested out incorrectly in our OS work... 75// mov r7,r3 // looking at divisor 76// ff1 r7 // I can move 32-r7 more bits to left. 77// addi r7,1 // ok, one short of that... 78// mov r1,r2 79// lsr r1,r7 // bits that came from low order... 80// rsubi r7,31 // r7 == "32-n" == LEFT distance 81// addi r7,1 // this is (32-n) 82// lsl r4,r7 // fixes the high 32 (quotient) 83// lsl r2,r7 84// cmpnei r4,0 85// bf 4f // the sentinel went away... 86 87 // run the remaining bits 88 891: lslc r2,1 // 1 bit left shift of r1-r2 90 addc r1,r1 91 cmphs r1,r3 // upper 32 of dividend >= divisor? 92 bf 2f 93 sub r1,r3 // if yes, subtract divisor 942: addc r4,r4 // shift by 1 and count subtracts 95 bf 1b // if sentinel falls out of quotient, stop 96 974: mov r2,r4 // return quotient 98 mov r3,r1 // and piggyback the remainder 99 jmp r15 100FUNC_END udiv32 101FUNC_END udivsi32 102#endif 103 104#ifdef L_umodsi3 105FUNC_START urem32 106FUNC_START umodsi3 107 movi r1,0 // r1-r2 form 64 bit dividend 108 movi r4,1 // r4 is quotient (1 for a sentinel) 109 cmpnei r3,0 // look for 0 divisor 110 bt 9f 111 trap 3 // divide by 0 1129: 113 // control iterations; skip across high order 0 bits in dividend 114 mov r7,r2 115 cmpnei r7,0 116 bt 8f 117 movi r2,0 // 0 dividend 118 jmp r15 // quick return 1198: 120 ff1 r7 // figure distance to skip 121 lsl r4,r7 // move the sentinel along (with 0's behind) 122 lsl r2,r7 // and the low 32 bits of numerator 123 1241: lslc r2,1 // 1 bit left shift of r1-r2 125 addc r1,r1 126 cmphs r1,r3 // upper 32 of dividend >= divisor? 127 bf 2f 128 sub r1,r3 // if yes, subtract divisor 1292: addc r4,r4 // shift by 1 and count subtracts 130 bf 1b // if sentinel falls out of quotient, stop 131 mov r2,r1 // return remainder 132 jmp r15 133FUNC_END urem32 134FUNC_END umodsi3 135#endif 136 137#ifdef L_divsi3 138FUNC_START div32 139FUNC_START divsi3 140 mov r5,r2 // calc sign of quotient 141 xor r5,r3 142 abs r2 // do unsigned divide 143 abs r3 144 movi r1,0 // r1-r2 form 64 bit dividend 145 movi r4,1 // r4 is quotient (1 for a sentinel) 146 cmpnei r3,0 // look for 0 divisor 147 bt 9f 148 trap 3 // divide by 0 1499: 150 // control iterations; skip across high order 0 bits in dividend 151 mov r7,r2 152 cmpnei r7,0 153 bt 8f 154 movi r2,0 // 0 dividend 155 jmp r15 // quick return 1568: 157 ff1 r7 // figure distance to skip 158 lsl r4,r7 // move the sentinel along (with 0's behind) 159 lsl r2,r7 // and the low 32 bits of numerator 160 161// tested out incorrectly in our OS work... 162// mov r7,r3 // looking at divisor 163// ff1 r7 // I can move 32-r7 more bits to left. 164// addi r7,1 // ok, one short of that... 165// mov r1,r2 166// lsr r1,r7 // bits that came from low order... 167// rsubi r7,31 // r7 == "32-n" == LEFT distance 168// addi r7,1 // this is (32-n) 169// lsl r4,r7 // fixes the high 32 (quotient) 170// lsl r2,r7 171// cmpnei r4,0 172// bf 4f // the sentinel went away... 173 174 // run the remaining bits 1751: lslc r2,1 // 1 bit left shift of r1-r2 176 addc r1,r1 177 cmphs r1,r3 // upper 32 of dividend >= divisor? 178 bf 2f 179 sub r1,r3 // if yes, subtract divisor 1802: addc r4,r4 // shift by 1 and count subtracts 181 bf 1b // if sentinel falls out of quotient, stop 182 1834: mov r2,r4 // return quotient 184 mov r3,r1 // piggyback the remainder 185 btsti r5,31 // after adjusting for sign 186 bf 3f 187 rsubi r2,0 188 rsubi r3,0 1893: jmp r15 190FUNC_END div32 191FUNC_END divsi3 192#endif 193 194#ifdef L_modsi3 195FUNC_START rem32 196FUNC_START modsi3 197 mov r5,r2 // calc sign of remainder 198 abs r2 // do unsigned divide 199 abs r3 200 movi r1,0 // r1-r2 form 64 bit dividend 201 movi r4,1 // r4 is quotient (1 for a sentinel) 202 cmpnei r3,0 // look for 0 divisor 203 bt 9f 204 trap 3 // divide by 0 2059: 206 // control iterations; skip across high order 0 bits in dividend 207 mov r7,r2 208 cmpnei r7,0 209 bt 8f 210 movi r2,0 // 0 dividend 211 jmp r15 // quick return 2128: 213 ff1 r7 // figure distance to skip 214 lsl r4,r7 // move the sentinel along (with 0's behind) 215 lsl r2,r7 // and the low 32 bits of numerator 216 2171: lslc r2,1 // 1 bit left shift of r1-r2 218 addc r1,r1 219 cmphs r1,r3 // upper 32 of dividend >= divisor? 220 bf 2f 221 sub r1,r3 // if yes, subtract divisor 2222: addc r4,r4 // shift by 1 and count subtracts 223 bf 1b // if sentinel falls out of quotient, stop 224 mov r2,r1 // return remainder 225 btsti r5,31 // after adjusting for sign 226 bf 3f 227 rsubi r2,0 2283: jmp r15 229FUNC_END rem32 230FUNC_END modsi3 231#endif 232 233 234/* GCC expects that {__eq,__ne,__gt,__ge,__le,__lt}{df2,sf2} 235 will behave as __cmpdf2. So, we stub the implementations to 236 jump on to __cmpdf2 and __cmpsf2. 237 238 All of these shortcircuit the return path so that __cmp{sd}f2 239 will go directly back to the caller. */ 240 241.macro COMPARE_DF_JUMP name 242 .import SYM (cmpdf2) 243FUNC_START \name 244 jmpi SYM (cmpdf2) 245FUNC_END \name 246.endm 247 248#ifdef L_eqdf2 249COMPARE_DF_JUMP eqdf2 250#endif /* L_eqdf2 */ 251 252#ifdef L_nedf2 253COMPARE_DF_JUMP nedf2 254#endif /* L_nedf2 */ 255 256#ifdef L_gtdf2 257COMPARE_DF_JUMP gtdf2 258#endif /* L_gtdf2 */ 259 260#ifdef L_gedf2 261COMPARE_DF_JUMP gedf2 262#endif /* L_gedf2 */ 263 264#ifdef L_ltdf2 265COMPARE_DF_JUMP ltdf2 266#endif /* L_ltdf2 */ 267 268#ifdef L_ledf2 269COMPARE_DF_JUMP ledf2 270#endif /* L_ledf2 */ 271 272/* SINGLE PRECISION FLOATING POINT STUBS */ 273 274.macro COMPARE_SF_JUMP name 275 .import SYM (cmpsf2) 276FUNC_START \name 277 jmpi SYM (cmpsf2) 278FUNC_END \name 279.endm 280 281#ifdef L_eqsf2 282COMPARE_SF_JUMP eqsf2 283#endif /* L_eqsf2 */ 284 285#ifdef L_nesf2 286COMPARE_SF_JUMP nesf2 287#endif /* L_nesf2 */ 288 289#ifdef L_gtsf2 290COMPARE_SF_JUMP gtsf2 291#endif /* L_gtsf2 */ 292 293#ifdef L_gesf2 294COMPARE_SF_JUMP __gesf2 295#endif /* L_gesf2 */ 296 297#ifdef L_ltsf2 298COMPARE_SF_JUMP __ltsf2 299#endif /* L_ltsf2 */ 300 301#ifdef L_lesf2 302COMPARE_SF_JUMP lesf2 303#endif /* L_lesf2 */ 304