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