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