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