1/* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 */ 9/* $NetBSD: divsi3.S,v 1.5 2005/02/26 22:58:56 perry Exp $ */ 10 11/* 12 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 13 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 16 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 17 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 18 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 19 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 20 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 21 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 22 * SUCH DAMAGE. 23 */ 24 25/* 26 * stack is aligned as there's a possibility of branching to L_overflow 27 * which makes a C call 28 */ 29 .text 30 .align 0 31 .globl __umodsi3 32 .type __umodsi3 , function 33__umodsi3: 34 stmfd sp!, {lr} 35 sub sp, sp, #4 /* align stack */ 36 bl .L_udivide 37 add sp, sp, #4 /* unalign stack */ 38 mov r0, r1 39 ldmfd sp!, {pc} 40 41 .text 42 .align 0 43 .globl __modsi3 44 .type __modsi3 , function 45__modsi3: 46 stmfd sp!, {lr} 47 sub sp, sp, #4 /* align stack */ 48 bl .L_divide 49 add sp, sp, #4 /* unalign stack */ 50 mov r0, r1 51 ldmfd sp!, {pc} 52 53.L_overflow: 54 /* XXX should cause a fatal error */ 55 mvn r0, #0 56 mov pc, lr 57 58 .text 59 .align 0 60 .globl __udivsi3 61 .type __udivsi3 , function 62__udivsi3: 63.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ 64 eor r0, r1, r0 65 eor r1, r0, r1 66 eor r0, r1, r0 67 /* r0 = r1 / r0; r1 = r1 % r0 */ 68 cmp r0, #1 69 bcc .L_overflow 70 beq .L_divide_l0 71 mov ip, #0 72 movs r1, r1 73 bpl .L_divide_l1 74 orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ 75 movs r1, r1, lsr #1 76 orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ 77 b .L_divide_l1 78 79.L_divide_l0: /* r0 == 1 */ 80 mov r0, r1 81 mov r1, #0 82 mov pc, lr 83 84 .text 85 .align 0 86 .globl __divsi3 87 .type __divsi3 , function 88__divsi3: 89.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ 90 eor r0, r1, r0 91 eor r1, r0, r1 92 eor r0, r1, r0 93 /* r0 = r1 / r0; r1 = r1 % r0 */ 94 cmp r0, #1 95 bcc .L_overflow 96 beq .L_divide_l0 97 ands ip, r0, #0x80000000 98 rsbmi r0, r0, #0 99 ands r2, r1, #0x80000000 100 eor ip, ip, r2 101 rsbmi r1, r1, #0 102 orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ 103 /* ip bit 0x80000000 = -ve remainder */ 104 105.L_divide_l1: 106 mov r2, #1 107 mov r3, #0 108 109 /* 110 * If the highest bit of the dividend is set, we have to be 111 * careful when shifting the divisor. Test this. 112 */ 113 movs r1,r1 114 bpl .L_old_code 115 116 /* 117 * At this point, the highest bit of r1 is known to be set. 118 * We abuse this below in the tst instructions. 119 */ 120 tst r1, r0 /*, lsl #0 */ 121 bmi .L_divide_b1 122 tst r1, r0, lsl #1 123 bmi .L_divide_b2 124 tst r1, r0, lsl #2 125 bmi .L_divide_b3 126 tst r1, r0, lsl #3 127 bmi .L_divide_b4 128 tst r1, r0, lsl #4 129 bmi .L_divide_b5 130 tst r1, r0, lsl #5 131 bmi .L_divide_b6 132 tst r1, r0, lsl #6 133 bmi .L_divide_b7 134 tst r1, r0, lsl #7 135 bmi .L_divide_b8 136 tst r1, r0, lsl #8 137 bmi .L_divide_b9 138 tst r1, r0, lsl #9 139 bmi .L_divide_b10 140 tst r1, r0, lsl #10 141 bmi .L_divide_b11 142 tst r1, r0, lsl #11 143 bmi .L_divide_b12 144 tst r1, r0, lsl #12 145 bmi .L_divide_b13 146 tst r1, r0, lsl #13 147 bmi .L_divide_b14 148 tst r1, r0, lsl #14 149 bmi .L_divide_b15 150 tst r1, r0, lsl #15 151 bmi .L_divide_b16 152 tst r1, r0, lsl #16 153 bmi .L_divide_b17 154 tst r1, r0, lsl #17 155 bmi .L_divide_b18 156 tst r1, r0, lsl #18 157 bmi .L_divide_b19 158 tst r1, r0, lsl #19 159 bmi .L_divide_b20 160 tst r1, r0, lsl #20 161 bmi .L_divide_b21 162 tst r1, r0, lsl #21 163 bmi .L_divide_b22 164 tst r1, r0, lsl #22 165 bmi .L_divide_b23 166 tst r1, r0, lsl #23 167 bmi .L_divide_b24 168 tst r1, r0, lsl #24 169 bmi .L_divide_b25 170 tst r1, r0, lsl #25 171 bmi .L_divide_b26 172 tst r1, r0, lsl #26 173 bmi .L_divide_b27 174 tst r1, r0, lsl #27 175 bmi .L_divide_b28 176 tst r1, r0, lsl #28 177 bmi .L_divide_b29 178 tst r1, r0, lsl #29 179 bmi .L_divide_b30 180 tst r1, r0, lsl #30 181 bmi .L_divide_b31 182/* 183 * instead of: 184 * tst r1, r0, lsl #31 185 * bmi .L_divide_b32 186 */ 187 b .L_divide_b32 188 189.L_old_code: 190 cmp r1, r0 191 bcc .L_divide_b0 192 cmp r1, r0, lsl #1 193 bcc .L_divide_b1 194 cmp r1, r0, lsl #2 195 bcc .L_divide_b2 196 cmp r1, r0, lsl #3 197 bcc .L_divide_b3 198 cmp r1, r0, lsl #4 199 bcc .L_divide_b4 200 cmp r1, r0, lsl #5 201 bcc .L_divide_b5 202 cmp r1, r0, lsl #6 203 bcc .L_divide_b6 204 cmp r1, r0, lsl #7 205 bcc .L_divide_b7 206 cmp r1, r0, lsl #8 207 bcc .L_divide_b8 208 cmp r1, r0, lsl #9 209 bcc .L_divide_b9 210 cmp r1, r0, lsl #10 211 bcc .L_divide_b10 212 cmp r1, r0, lsl #11 213 bcc .L_divide_b11 214 cmp r1, r0, lsl #12 215 bcc .L_divide_b12 216 cmp r1, r0, lsl #13 217 bcc .L_divide_b13 218 cmp r1, r0, lsl #14 219 bcc .L_divide_b14 220 cmp r1, r0, lsl #15 221 bcc .L_divide_b15 222 cmp r1, r0, lsl #16 223 bcc .L_divide_b16 224 cmp r1, r0, lsl #17 225 bcc .L_divide_b17 226 cmp r1, r0, lsl #18 227 bcc .L_divide_b18 228 cmp r1, r0, lsl #19 229 bcc .L_divide_b19 230 cmp r1, r0, lsl #20 231 bcc .L_divide_b20 232 cmp r1, r0, lsl #21 233 bcc .L_divide_b21 234 cmp r1, r0, lsl #22 235 bcc .L_divide_b22 236 cmp r1, r0, lsl #23 237 bcc .L_divide_b23 238 cmp r1, r0, lsl #24 239 bcc .L_divide_b24 240 cmp r1, r0, lsl #25 241 bcc .L_divide_b25 242 cmp r1, r0, lsl #26 243 bcc .L_divide_b26 244 cmp r1, r0, lsl #27 245 bcc .L_divide_b27 246 cmp r1, r0, lsl #28 247 bcc .L_divide_b28 248 cmp r1, r0, lsl #29 249 bcc .L_divide_b29 250 cmp r1, r0, lsl #30 251 bcc .L_divide_b30 252.L_divide_b32: 253 cmp r1, r0, lsl #31 254 subhs r1, r1,r0, lsl #31 255 addhs r3, r3,r2, lsl #31 256.L_divide_b31: 257 cmp r1, r0, lsl #30 258 subhs r1, r1,r0, lsl #30 259 addhs r3, r3,r2, lsl #30 260.L_divide_b30: 261 cmp r1, r0, lsl #29 262 subhs r1, r1,r0, lsl #29 263 addhs r3, r3,r2, lsl #29 264.L_divide_b29: 265 cmp r1, r0, lsl #28 266 subhs r1, r1,r0, lsl #28 267 addhs r3, r3,r2, lsl #28 268.L_divide_b28: 269 cmp r1, r0, lsl #27 270 subhs r1, r1,r0, lsl #27 271 addhs r3, r3,r2, lsl #27 272.L_divide_b27: 273 cmp r1, r0, lsl #26 274 subhs r1, r1,r0, lsl #26 275 addhs r3, r3,r2, lsl #26 276.L_divide_b26: 277 cmp r1, r0, lsl #25 278 subhs r1, r1,r0, lsl #25 279 addhs r3, r3,r2, lsl #25 280.L_divide_b25: 281 cmp r1, r0, lsl #24 282 subhs r1, r1,r0, lsl #24 283 addhs r3, r3,r2, lsl #24 284.L_divide_b24: 285 cmp r1, r0, lsl #23 286 subhs r1, r1,r0, lsl #23 287 addhs r3, r3,r2, lsl #23 288.L_divide_b23: 289 cmp r1, r0, lsl #22 290 subhs r1, r1,r0, lsl #22 291 addhs r3, r3,r2, lsl #22 292.L_divide_b22: 293 cmp r1, r0, lsl #21 294 subhs r1, r1,r0, lsl #21 295 addhs r3, r3,r2, lsl #21 296.L_divide_b21: 297 cmp r1, r0, lsl #20 298 subhs r1, r1,r0, lsl #20 299 addhs r3, r3,r2, lsl #20 300.L_divide_b20: 301 cmp r1, r0, lsl #19 302 subhs r1, r1,r0, lsl #19 303 addhs r3, r3,r2, lsl #19 304.L_divide_b19: 305 cmp r1, r0, lsl #18 306 subhs r1, r1,r0, lsl #18 307 addhs r3, r3,r2, lsl #18 308.L_divide_b18: 309 cmp r1, r0, lsl #17 310 subhs r1, r1,r0, lsl #17 311 addhs r3, r3,r2, lsl #17 312.L_divide_b17: 313 cmp r1, r0, lsl #16 314 subhs r1, r1,r0, lsl #16 315 addhs r3, r3,r2, lsl #16 316.L_divide_b16: 317 cmp r1, r0, lsl #15 318 subhs r1, r1,r0, lsl #15 319 addhs r3, r3,r2, lsl #15 320.L_divide_b15: 321 cmp r1, r0, lsl #14 322 subhs r1, r1,r0, lsl #14 323 addhs r3, r3,r2, lsl #14 324.L_divide_b14: 325 cmp r1, r0, lsl #13 326 subhs r1, r1,r0, lsl #13 327 addhs r3, r3,r2, lsl #13 328.L_divide_b13: 329 cmp r1, r0, lsl #12 330 subhs r1, r1,r0, lsl #12 331 addhs r3, r3,r2, lsl #12 332.L_divide_b12: 333 cmp r1, r0, lsl #11 334 subhs r1, r1,r0, lsl #11 335 addhs r3, r3,r2, lsl #11 336.L_divide_b11: 337 cmp r1, r0, lsl #10 338 subhs r1, r1,r0, lsl #10 339 addhs r3, r3,r2, lsl #10 340.L_divide_b10: 341 cmp r1, r0, lsl #9 342 subhs r1, r1,r0, lsl #9 343 addhs r3, r3,r2, lsl #9 344.L_divide_b9: 345 cmp r1, r0, lsl #8 346 subhs r1, r1,r0, lsl #8 347 addhs r3, r3,r2, lsl #8 348.L_divide_b8: 349 cmp r1, r0, lsl #7 350 subhs r1, r1,r0, lsl #7 351 addhs r3, r3,r2, lsl #7 352.L_divide_b7: 353 cmp r1, r0, lsl #6 354 subhs r1, r1,r0, lsl #6 355 addhs r3, r3,r2, lsl #6 356.L_divide_b6: 357 cmp r1, r0, lsl #5 358 subhs r1, r1,r0, lsl #5 359 addhs r3, r3,r2, lsl #5 360.L_divide_b5: 361 cmp r1, r0, lsl #4 362 subhs r1, r1,r0, lsl #4 363 addhs r3, r3,r2, lsl #4 364.L_divide_b4: 365 cmp r1, r0, lsl #3 366 subhs r1, r1,r0, lsl #3 367 addhs r3, r3,r2, lsl #3 368.L_divide_b3: 369 cmp r1, r0, lsl #2 370 subhs r1, r1,r0, lsl #2 371 addhs r3, r3,r2, lsl #2 372.L_divide_b2: 373 cmp r1, r0, lsl #1 374 subhs r1, r1,r0, lsl #1 375 addhs r3, r3,r2, lsl #1 376.L_divide_b1: 377 cmp r1, r0 378 subhs r1, r1, r0 379 addhs r3, r3, r2 380.L_divide_b0: 381 382 tst ip, #0x20000000 383 bne .L_udivide_l1 384 mov r0, r3 385 cmp ip, #0 386 rsbmi r1, r1, #0 387 movs ip, ip, lsl #1 388 bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ 389 rsbmi r0, r0, #0 390 mov pc, lr 391 392.L_udivide_l1: 393 tst ip, #0x10000000 394 mov r1, r1, lsl #1 395 orrne r1, r1, #1 396 mov r3, r3, lsl #1 397 cmp r1, r0 398 subhs r1, r1, r0 399 addhs r3, r3, r2 400 mov r0, r3 401 mov pc, lr 402