xref: /linux/arch/powerpc/boot/div64.S (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*2874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */
294b212c2SPaul Mackerras/*
394b212c2SPaul Mackerras * Divide a 64-bit unsigned number by a 32-bit unsigned number.
494b212c2SPaul Mackerras * This routine assumes that the top 32 bits of the dividend are
594b212c2SPaul Mackerras * non-zero to start with.
694b212c2SPaul Mackerras * On entry, r3 points to the dividend, which get overwritten with
794b212c2SPaul Mackerras * the 64-bit quotient, and r4 contains the divisor.
894b212c2SPaul Mackerras * On exit, r3 contains the remainder.
994b212c2SPaul Mackerras *
1094b212c2SPaul Mackerras * Copyright (C) 2002 Paul Mackerras, IBM Corp.
1194b212c2SPaul Mackerras */
1294b212c2SPaul Mackerras#include "ppc_asm.h"
1394b212c2SPaul Mackerras
1494b212c2SPaul Mackerras	.globl __div64_32
1594b212c2SPaul Mackerras__div64_32:
1694b212c2SPaul Mackerras	lwz	r5,0(r3)	# get the dividend into r5/r6
1794b212c2SPaul Mackerras	lwz	r6,4(r3)
1894b212c2SPaul Mackerras	cmplw	r5,r4
1994b212c2SPaul Mackerras	li	r7,0
2094b212c2SPaul Mackerras	li	r8,0
2194b212c2SPaul Mackerras	blt	1f
2294b212c2SPaul Mackerras	divwu	r7,r5,r4	# if dividend.hi >= divisor,
2394b212c2SPaul Mackerras	mullw	r0,r7,r4	# quotient.hi = dividend.hi / divisor
2494b212c2SPaul Mackerras	subf.	r5,r0,r5	# dividend.hi %= divisor
2594b212c2SPaul Mackerras	beq	3f
2694b212c2SPaul Mackerras1:	mr	r11,r5		# here dividend.hi != 0
2794b212c2SPaul Mackerras	andis.	r0,r5,0xc000
2894b212c2SPaul Mackerras	bne	2f
2994b212c2SPaul Mackerras	cntlzw	r0,r5		# we are shifting the dividend right
3094b212c2SPaul Mackerras	li	r10,-1		# to make it < 2^32, and shifting
3194b212c2SPaul Mackerras	srw	r10,r10,r0	# the divisor right the same amount,
32acbfd58eSBenjamin Herrenschmidt	addc	r9,r4,r10	# rounding up (so the estimate cannot
3394b212c2SPaul Mackerras	andc	r11,r6,r10	# ever be too large, only too small)
3494b212c2SPaul Mackerras	andc	r9,r9,r10
35acbfd58eSBenjamin Herrenschmidt	addze	r9,r9
3694b212c2SPaul Mackerras	or	r11,r5,r11
3794b212c2SPaul Mackerras	rotlw	r9,r9,r0
3894b212c2SPaul Mackerras	rotlw	r11,r11,r0
3994b212c2SPaul Mackerras	divwu	r11,r11,r9	# then we divide the shifted quantities
4094b212c2SPaul Mackerras2:	mullw	r10,r11,r4	# to get an estimate of the quotient,
4194b212c2SPaul Mackerras	mulhwu	r9,r11,r4	# multiply the estimate by the divisor,
4294b212c2SPaul Mackerras	subfc	r6,r10,r6	# take the product from the divisor,
4394b212c2SPaul Mackerras	add	r8,r8,r11	# and add the estimate to the accumulated
4494b212c2SPaul Mackerras	subfe.	r5,r9,r5	# quotient
4594b212c2SPaul Mackerras	bne	1b
4694b212c2SPaul Mackerras3:	cmplw	r6,r4
4794b212c2SPaul Mackerras	blt	4f
4894b212c2SPaul Mackerras	divwu	r0,r6,r4	# perform the remaining 32-bit division
4994b212c2SPaul Mackerras	mullw	r10,r0,r4	# and get the remainder
5094b212c2SPaul Mackerras	add	r8,r8,r0
5194b212c2SPaul Mackerras	subf	r6,r10,r6
5294b212c2SPaul Mackerras4:	stw	r7,0(r3)	# return the quotient in *r3
5394b212c2SPaul Mackerras	stw	r8,4(r3)
5494b212c2SPaul Mackerras	mr	r3,r6		# return the remainder in r3
5594b212c2SPaul Mackerras	blr
56e32a0329STony Breeds
57e32a0329STony Breeds/*
58e32a0329STony Breeds * Extended precision shifts.
59e32a0329STony Breeds *
60e32a0329STony Breeds * Updated to be valid for shift counts from 0 to 63 inclusive.
61e32a0329STony Breeds * -- Gabriel
62e32a0329STony Breeds *
63e32a0329STony Breeds * R3/R4 has 64 bit value
64e32a0329STony Breeds * R5    has shift count
65e32a0329STony Breeds * result in R3/R4
66e32a0329STony Breeds *
67e32a0329STony Breeds *  ashrdi3: arithmetic right shift (sign propagation)
68e32a0329STony Breeds *  lshrdi3: logical right shift
69e32a0329STony Breeds *  ashldi3: left shift
70e32a0329STony Breeds */
71e32a0329STony Breeds	.globl __ashrdi3
72e32a0329STony Breeds__ashrdi3:
73e32a0329STony Breeds	subfic	r6,r5,32
74e32a0329STony Breeds	srw	r4,r4,r5	# LSW = count > 31 ? 0 : LSW >> count
75e32a0329STony Breeds	addi	r7,r5,32	# could be xori, or addi with -32
76e32a0329STony Breeds	slw	r6,r3,r6	# t1 = count > 31 ? 0 : MSW << (32-count)
77e32a0329STony Breeds	rlwinm	r8,r7,0,32	# t3 = (count < 32) ? 32 : 0
78e32a0329STony Breeds	sraw	r7,r3,r7	# t2 = MSW >> (count-32)
79e32a0329STony Breeds	or	r4,r4,r6	# LSW |= t1
80e32a0329STony Breeds	slw	r7,r7,r8	# t2 = (count < 32) ? 0 : t2
81e32a0329STony Breeds	sraw	r3,r3,r5	# MSW = MSW >> count
82e32a0329STony Breeds	or	r4,r4,r7	# LSW |= t2
83e32a0329STony Breeds	blr
84e32a0329STony Breeds
85e32a0329STony Breeds	.globl __ashldi3
86e32a0329STony Breeds__ashldi3:
87e32a0329STony Breeds	subfic	r6,r5,32
88e32a0329STony Breeds	slw	r3,r3,r5	# MSW = count > 31 ? 0 : MSW << count
89e32a0329STony Breeds	addi	r7,r5,32	# could be xori, or addi with -32
90e32a0329STony Breeds	srw	r6,r4,r6	# t1 = count > 31 ? 0 : LSW >> (32-count)
91e32a0329STony Breeds	slw	r7,r4,r7	# t2 = count < 32 ? 0 : LSW << (count-32)
92e32a0329STony Breeds	or	r3,r3,r6	# MSW |= t1
93e32a0329STony Breeds	slw	r4,r4,r5	# LSW = LSW << count
94e32a0329STony Breeds	or	r3,r3,r7	# MSW |= t2
95e32a0329STony Breeds	blr
96e32a0329STony Breeds
97e32a0329STony Breeds	.globl __lshrdi3
98e32a0329STony Breeds__lshrdi3:
99e32a0329STony Breeds	subfic	r6,r5,32
100e32a0329STony Breeds	srw	r4,r4,r5	# LSW = count > 31 ? 0 : LSW >> count
101e32a0329STony Breeds	addi	r7,r5,32	# could be xori, or addi with -32
102e32a0329STony Breeds	slw	r6,r3,r6	# t1 = count > 31 ? 0 : MSW << (32-count)
103e32a0329STony Breeds	srw	r7,r3,r7	# t2 = count < 32 ? 0 : MSW >> (count-32)
104e32a0329STony Breeds	or	r4,r4,r6	# LSW |= t1
105e32a0329STony Breeds	srw	r3,r3,r5	# MSW = MSW >> count
106e32a0329STony Breeds	or	r4,r4,r7	# LSW |= t2
107e32a0329STony Breeds	blr
108