1 /* libgcc routines for the MCore. 2 Copyright (C) 1993-2024 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it 7 under the terms of the GNU General Public License as published by the 8 Free Software Foundation; either version 3, or (at your option) any 9 later version. 10 11 This file is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 Under Section 7 of GPL version 3, you are granted additional 17 permissions described in the GCC Runtime Library Exception, version 18 3.1, as published by the Free Software Foundation. 19 20 You should have received a copy of the GNU General Public License and 21 a copy of the GCC Runtime Library Exception along with this program; 22 see 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) 44 SYM (\name): 45 .endm 46 47 .macro FUNC_END name 48 SIZE (\name) 49 .endm 50 51 #ifdef L_udivsi3 52 FUNC_START udiv32 53 FUNC_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 61 9: 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 68 8: 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 89 1: 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 94 2: addc r4,r4 // shift by 1 and count subtracts 95 bf 1b // if sentinel falls out of quotient, stop 96 97 4: mov r2,r4 // return quotient 98 mov r3,r1 // and piggyback the remainder 99 jmp r15 100 FUNC_END udiv32 101 FUNC_END udivsi32 102 #endif 103 104 #ifdef L_umodsi3 105 FUNC_START urem32 106 FUNC_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 112 9: 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 119 8: 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 124 1: 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 129 2: 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 133 FUNC_END urem32 134 FUNC_END umodsi3 135 #endif 136 137 #ifdef L_divsi3 138 FUNC_START div32 139 FUNC_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 149 9: 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 156 8: 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 175 1: 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 180 2: addc r4,r4 // shift by 1 and count subtracts 181 bf 1b // if sentinel falls out of quotient, stop 182 183 4: 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 189 3: jmp r15 190 FUNC_END div32 191 FUNC_END divsi3 192 #endif 193 194 #ifdef L_modsi3 195 FUNC_START rem32 196 FUNC_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 205 9: 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 212 8: 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 217 1: 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 222 2: 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 228 3: jmp r15 229 FUNC_END rem32 230 FUNC_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) 243 FUNC_START \name 244 jmpi SYM (cmpdf2) 245 FUNC_END \name 246 .endm 247 248 #ifdef L_eqdf2 249 COMPARE_DF_JUMP eqdf2 250 #endif /* L_eqdf2 */ 251 252 #ifdef L_nedf2 253 COMPARE_DF_JUMP nedf2 254 #endif /* L_nedf2 */ 255 256 #ifdef L_gtdf2 257 COMPARE_DF_JUMP gtdf2 258 #endif /* L_gtdf2 */ 259 260 #ifdef L_gedf2 261 COMPARE_DF_JUMP gedf2 262 #endif /* L_gedf2 */ 263 264 #ifdef L_ltdf2 265 COMPARE_DF_JUMP ltdf2 266 #endif /* L_ltdf2 */ 267 268 #ifdef L_ledf2 269 COMPARE_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) 276 FUNC_START \name 277 jmpi SYM (cmpsf2) 278 FUNC_END \name 279 .endm 280 281 #ifdef L_eqsf2 282 COMPARE_SF_JUMP eqsf2 283 #endif /* L_eqsf2 */ 284 285 #ifdef L_nesf2 286 COMPARE_SF_JUMP nesf2 287 #endif /* L_nesf2 */ 288 289 #ifdef L_gtsf2 290 COMPARE_SF_JUMP gtsf2 291 #endif /* L_gtsf2 */ 292 293 #ifdef L_gesf2 294 COMPARE_SF_JUMP __gesf2 295 #endif /* L_gesf2 */ 296 297 #ifdef L_ltsf2 298 COMPARE_SF_JUMP __ltsf2 299 #endif /* L_ltsf2 */ 300 301 #ifdef L_lesf2 302 COMPARE_SF_JUMP lesf2 303 #endif /* L_lesf2 */ 304