|
Packit |
5c3484 |
dnl ARM mpn_udiv_qrnnd -- divide a two limb dividend and a one limb divisor.
|
|
Packit |
5c3484 |
dnl Return quotient and store remainder through a supplied pointer.
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
dnl Copyright 2001, 2012 Free Software Foundation, Inc.
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
dnl This file is part of the GNU MP Library.
|
|
Packit |
5c3484 |
dnl
|
|
Packit |
5c3484 |
dnl The GNU MP Library is free software; you can redistribute it and/or modify
|
|
Packit |
5c3484 |
dnl it under the terms of either:
|
|
Packit |
5c3484 |
dnl
|
|
Packit |
5c3484 |
dnl * the GNU Lesser General Public License as published by the Free
|
|
Packit |
5c3484 |
dnl Software Foundation; either version 3 of the License, or (at your
|
|
Packit |
5c3484 |
dnl option) any later version.
|
|
Packit |
5c3484 |
dnl
|
|
Packit |
5c3484 |
dnl or
|
|
Packit |
5c3484 |
dnl
|
|
Packit |
5c3484 |
dnl * the GNU General Public License as published by the Free Software
|
|
Packit |
5c3484 |
dnl Foundation; either version 2 of the License, or (at your option) any
|
|
Packit |
5c3484 |
dnl later version.
|
|
Packit |
5c3484 |
dnl
|
|
Packit |
5c3484 |
dnl or both in parallel, as here.
|
|
Packit |
5c3484 |
dnl
|
|
Packit |
5c3484 |
dnl The GNU MP Library is distributed in the hope that it will be useful, but
|
|
Packit |
5c3484 |
dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
Packit |
5c3484 |
dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
Packit |
5c3484 |
dnl for more details.
|
|
Packit |
5c3484 |
dnl
|
|
Packit |
5c3484 |
dnl You should have received copies of the GNU General Public License and the
|
|
Packit |
5c3484 |
dnl GNU Lesser General Public License along with the GNU MP Library. If not,
|
|
Packit |
5c3484 |
dnl see https://www.gnu.org/licenses/.
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
include(`../config.m4')
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
C INPUT PARAMETERS
|
|
Packit |
5c3484 |
define(`rem_ptr',`r0')
|
|
Packit |
5c3484 |
define(`n1',`r1')
|
|
Packit |
5c3484 |
define(`n0',`r2')
|
|
Packit |
5c3484 |
define(`d',`r3')
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
C divstep -- develop one quotient bit. Dividend in $1$2, divisor in $3.
|
|
Packit |
5c3484 |
C Quotient bit is shifted into $2.
|
|
Packit |
5c3484 |
define(`divstep',
|
|
Packit |
5c3484 |
`adcs $2, $2, $2
|
|
Packit |
5c3484 |
adc $1, $1, $1
|
|
Packit |
5c3484 |
cmp $1, $3
|
|
Packit |
5c3484 |
subcs $1, $1, $3')
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
ASM_START()
|
|
Packit |
5c3484 |
PROLOGUE(mpn_udiv_qrnnd)
|
|
Packit |
5c3484 |
mov r12, #8 C loop counter for both loops below
|
|
Packit |
5c3484 |
cmp d, #0x80000000 C check divisor msb and clear carry
|
|
Packit |
5c3484 |
bcs L(_large_divisor)
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
L(oop): divstep(n1,n0,d)
|
|
Packit |
5c3484 |
divstep(n1,n0,d)
|
|
Packit |
5c3484 |
divstep(n1,n0,d)
|
|
Packit |
5c3484 |
divstep(n1,n0,d)
|
|
Packit |
5c3484 |
sub r12, r12, #1
|
|
Packit |
5c3484 |
teq r12, #0
|
|
Packit |
5c3484 |
bne L(oop)
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
str n1, [rem_ptr] C store remainder
|
|
Packit |
5c3484 |
adc r0, n0, n0 C quotient: add last carry from divstep
|
|
Packit |
5c3484 |
ret lr
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
L(_large_divisor):
|
|
Packit |
5c3484 |
stmfd sp!, { r8, lr }
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
and r8, n0, #1 C save lsb of dividend
|
|
Packit |
5c3484 |
mov lr, n1, lsl #31
|
|
Packit |
5c3484 |
orrs n0, lr, n0, lsr #1 C n0 = lo(n1n0 >> 1)
|
|
Packit |
5c3484 |
mov n1, n1, lsr #1 C n1 = hi(n1n0 >> 1)
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
and lr, d, #1 C save lsb of divisor
|
|
Packit |
5c3484 |
movs d, d, lsr #1 C d = floor(orig_d / 2)
|
|
Packit |
5c3484 |
adc d, d, #0 C d = ceil(orig_d / 2)
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
L(oop2):
|
|
Packit |
5c3484 |
divstep(n1,n0,d)
|
|
Packit |
5c3484 |
divstep(n1,n0,d)
|
|
Packit |
5c3484 |
divstep(n1,n0,d)
|
|
Packit |
5c3484 |
divstep(n1,n0,d)
|
|
Packit |
5c3484 |
sub r12, r12, #1
|
|
Packit |
5c3484 |
teq r12, #0
|
|
Packit |
5c3484 |
bne L(oop2)
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
adc n0, n0, n0 C shift and add last carry from divstep
|
|
Packit |
5c3484 |
add n1, r8, n1, lsl #1 C shift in omitted dividend lsb
|
|
Packit |
5c3484 |
tst lr, lr C test saved divisor lsb
|
|
Packit |
5c3484 |
beq L(_even_divisor)
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
rsb d, lr, d, lsl #1 C restore orig d value
|
|
Packit |
5c3484 |
adds n1, n1, n0 C fix remainder for omitted divisor lsb
|
|
Packit |
5c3484 |
addcs n0, n0, #1 C adjust quotient if rem. fix carried
|
|
Packit |
5c3484 |
subcs n1, n1, d C adjust remainder accordingly
|
|
Packit |
5c3484 |
cmp n1, d C remainder >= divisor?
|
|
Packit |
5c3484 |
subcs n1, n1, d C adjust remainder
|
|
Packit |
5c3484 |
addcs n0, n0, #1 C adjust quotient
|
|
Packit |
5c3484 |
|
|
Packit |
5c3484 |
L(_even_divisor):
|
|
Packit |
5c3484 |
str n1, [rem_ptr] C store remainder
|
|
Packit |
5c3484 |
mov r0, n0 C quotient
|
|
Packit |
5c3484 |
ldmfd sp!, { r8, pc }
|
|
Packit |
5c3484 |
EPILOGUE(mpn_udiv_qrnnd)
|