xref: /openbmc/linux/arch/m68k/lib/udivsi3.S (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
166d857b0SGreg Ungerer/* libgcc1 routines for 68000 w/o floating-point hardware.
266d857b0SGreg Ungerer   Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
366d857b0SGreg Ungerer
466d857b0SGreg UngererThis file is part of GNU CC.
566d857b0SGreg Ungerer
666d857b0SGreg UngererGNU CC is free software; you can redistribute it and/or modify it
766d857b0SGreg Ungererunder the terms of the GNU General Public License as published by the
866d857b0SGreg UngererFree Software Foundation; either version 2, or (at your option) any
966d857b0SGreg Ungererlater version.
1066d857b0SGreg Ungerer
1166d857b0SGreg UngererIn addition to the permissions in the GNU General Public License, the
1266d857b0SGreg UngererFree Software Foundation gives you unlimited permission to link the
1366d857b0SGreg Ungerercompiled version of this file with other programs, and to distribute
1466d857b0SGreg Ungererthose programs without any restriction coming from the use of this
1566d857b0SGreg Ungererfile.  (The General Public License restrictions do apply in other
1666d857b0SGreg Ungererrespects; for example, they cover modification of the file, and
1766d857b0SGreg Ungererdistribution when not linked into another program.)
1866d857b0SGreg Ungerer
1966d857b0SGreg UngererThis file is distributed in the hope that it will be useful, but
2066d857b0SGreg UngererWITHOUT ANY WARRANTY; without even the implied warranty of
2166d857b0SGreg UngererMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22d6410efaSGeert UytterhoevenGeneral Public License for more details. */
2366d857b0SGreg Ungerer
2466d857b0SGreg Ungerer/* As a special exception, if you link this library with files
2566d857b0SGreg Ungerer   compiled with GCC to produce an executable, this does not cause
2666d857b0SGreg Ungerer   the resulting executable to be covered by the GNU General Public License.
2766d857b0SGreg Ungerer   This exception does not however invalidate any other reasons why
2866d857b0SGreg Ungerer   the executable file might be covered by the GNU General Public License.  */
2966d857b0SGreg Ungerer
3066d857b0SGreg Ungerer/* Use this one for any 680x0; assumes no floating point hardware.
3166d857b0SGreg Ungerer   The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
3266d857b0SGreg Ungerer   Some of this code comes from MINIX, via the folks at ericsson.
3366d857b0SGreg Ungerer   D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
3466d857b0SGreg Ungerer*/
35*7547cbe2SMasahiro Yamada#include <linux/export.h>
3666d857b0SGreg Ungerer/* These are predefined by new versions of GNU cpp.  */
3766d857b0SGreg Ungerer
3866d857b0SGreg Ungerer#ifndef __USER_LABEL_PREFIX__
3966d857b0SGreg Ungerer#define __USER_LABEL_PREFIX__ _
4066d857b0SGreg Ungerer#endif
4166d857b0SGreg Ungerer
4266d857b0SGreg Ungerer#ifndef __REGISTER_PREFIX__
4366d857b0SGreg Ungerer#define __REGISTER_PREFIX__
4466d857b0SGreg Ungerer#endif
4566d857b0SGreg Ungerer
4666d857b0SGreg Ungerer#ifndef __IMMEDIATE_PREFIX__
4766d857b0SGreg Ungerer#define __IMMEDIATE_PREFIX__ #
4866d857b0SGreg Ungerer#endif
4966d857b0SGreg Ungerer
5066d857b0SGreg Ungerer/* ANSI concatenation macros.  */
5166d857b0SGreg Ungerer
5266d857b0SGreg Ungerer#define CONCAT1(a, b) CONCAT2(a, b)
5366d857b0SGreg Ungerer#define CONCAT2(a, b) a ## b
5466d857b0SGreg Ungerer
5566d857b0SGreg Ungerer/* Use the right prefix for global labels.  */
5666d857b0SGreg Ungerer
5766d857b0SGreg Ungerer#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
5866d857b0SGreg Ungerer
5966d857b0SGreg Ungerer/* Use the right prefix for registers.  */
6066d857b0SGreg Ungerer
6166d857b0SGreg Ungerer#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
6266d857b0SGreg Ungerer
6366d857b0SGreg Ungerer/* Use the right prefix for immediate values.  */
6466d857b0SGreg Ungerer
6566d857b0SGreg Ungerer#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
6666d857b0SGreg Ungerer
6766d857b0SGreg Ungerer#define d0 REG (d0)
6866d857b0SGreg Ungerer#define d1 REG (d1)
6966d857b0SGreg Ungerer#define d2 REG (d2)
7066d857b0SGreg Ungerer#define d3 REG (d3)
7166d857b0SGreg Ungerer#define d4 REG (d4)
7266d857b0SGreg Ungerer#define d5 REG (d5)
7366d857b0SGreg Ungerer#define d6 REG (d6)
7466d857b0SGreg Ungerer#define d7 REG (d7)
7566d857b0SGreg Ungerer#define a0 REG (a0)
7666d857b0SGreg Ungerer#define a1 REG (a1)
7766d857b0SGreg Ungerer#define a2 REG (a2)
7866d857b0SGreg Ungerer#define a3 REG (a3)
7966d857b0SGreg Ungerer#define a4 REG (a4)
8066d857b0SGreg Ungerer#define a5 REG (a5)
8166d857b0SGreg Ungerer#define a6 REG (a6)
8266d857b0SGreg Ungerer#define fp REG (fp)
8366d857b0SGreg Ungerer#define sp REG (sp)
8466d857b0SGreg Ungerer
8566d857b0SGreg Ungerer	.text
8666d857b0SGreg Ungerer	.proc
8766d857b0SGreg Ungerer	.globl	SYM (__udivsi3)
8866d857b0SGreg UngererSYM (__udivsi3):
8966d857b0SGreg Ungerer#if !(defined(__mcf5200__) || defined(__mcoldfire__))
9066d857b0SGreg Ungerer	movel	d2, sp@-
9166d857b0SGreg Ungerer	movel	sp@(12), d1	/* d1 = divisor */
9266d857b0SGreg Ungerer	movel	sp@(8), d0	/* d0 = dividend */
9366d857b0SGreg Ungerer
9466d857b0SGreg Ungerer	cmpl	IMM (0x10000), d1 /* divisor >= 2 ^ 16 ?   */
9566d857b0SGreg Ungerer	jcc	L3		/* then try next algorithm */
9666d857b0SGreg Ungerer	movel	d0, d2
9766d857b0SGreg Ungerer	clrw	d2
9866d857b0SGreg Ungerer	swap	d2
9966d857b0SGreg Ungerer	divu	d1, d2          /* high quotient in lower word */
10066d857b0SGreg Ungerer	movew	d2, d0		/* save high quotient */
10166d857b0SGreg Ungerer	swap	d0
10266d857b0SGreg Ungerer	movew	sp@(10), d2	/* get low dividend + high rest */
10366d857b0SGreg Ungerer	divu	d1, d2		/* low quotient */
10466d857b0SGreg Ungerer	movew	d2, d0
10566d857b0SGreg Ungerer	jra	L6
10666d857b0SGreg Ungerer
10766d857b0SGreg UngererL3:	movel	d1, d2		/* use d2 as divisor backup */
10866d857b0SGreg UngererL4:	lsrl	IMM (1), d1	/* shift divisor */
10966d857b0SGreg Ungerer	lsrl	IMM (1), d0	/* shift dividend */
11066d857b0SGreg Ungerer	cmpl	IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ?  */
11166d857b0SGreg Ungerer	jcc	L4
11266d857b0SGreg Ungerer	divu	d1, d0		/* now we have 16 bit divisor */
11366d857b0SGreg Ungerer	andl	IMM (0xffff), d0 /* mask out divisor, ignore remainder */
11466d857b0SGreg Ungerer
11566d857b0SGreg Ungerer/* Multiply the 16 bit tentative quotient with the 32 bit divisor.  Because of
11666d857b0SGreg Ungerer   the operand ranges, this might give a 33 bit product.  If this product is
11766d857b0SGreg Ungerer   greater than the dividend, the tentative quotient was too large. */
11866d857b0SGreg Ungerer	movel	d2, d1
11966d857b0SGreg Ungerer	mulu	d0, d1		/* low part, 32 bits */
12066d857b0SGreg Ungerer	swap	d2
12166d857b0SGreg Ungerer	mulu	d0, d2		/* high part, at most 17 bits */
12266d857b0SGreg Ungerer	swap	d2		/* align high part with low part */
12366d857b0SGreg Ungerer	tstw	d2		/* high part 17 bits? */
12466d857b0SGreg Ungerer	jne	L5		/* if 17 bits, quotient was too large */
12566d857b0SGreg Ungerer	addl	d2, d1		/* add parts */
12666d857b0SGreg Ungerer	jcs	L5		/* if sum is 33 bits, quotient was too large */
12766d857b0SGreg Ungerer	cmpl	sp@(8), d1	/* compare the sum with the dividend */
12866d857b0SGreg Ungerer	jls	L6		/* if sum > dividend, quotient was too large */
12966d857b0SGreg UngererL5:	subql	IMM (1), d0	/* adjust quotient */
13066d857b0SGreg Ungerer
13166d857b0SGreg UngererL6:	movel	sp@+, d2
13266d857b0SGreg Ungerer	rts
13366d857b0SGreg Ungerer
13466d857b0SGreg Ungerer#else /* __mcf5200__ || __mcoldfire__ */
13566d857b0SGreg Ungerer
13666d857b0SGreg Ungerer/* Coldfire implementation of non-restoring division algorithm from
13766d857b0SGreg Ungerer   Hennessy & Patterson, Appendix A. */
13866d857b0SGreg Ungerer	link	a6,IMM (-12)
13966d857b0SGreg Ungerer	moveml	d2-d4,sp@
14066d857b0SGreg Ungerer	movel	a6@(8),d0
14166d857b0SGreg Ungerer	movel	a6@(12),d1
14266d857b0SGreg Ungerer	clrl	d2		| clear p
14366d857b0SGreg Ungerer	moveq	IMM (31),d4
14466d857b0SGreg UngererL1:	addl	d0,d0		| shift reg pair (p,a) one bit left
14566d857b0SGreg Ungerer	addxl	d2,d2
14666d857b0SGreg Ungerer	movl	d2,d3		| subtract b from p, store in tmp.
14766d857b0SGreg Ungerer	subl	d1,d3
14866d857b0SGreg Ungerer	jcs	L2		| if no carry,
14966d857b0SGreg Ungerer	bset	IMM (0),d0	| set the low order bit of a to 1,
15066d857b0SGreg Ungerer	movl	d3,d2		| and store tmp in p.
15166d857b0SGreg UngererL2:	subql	IMM (1),d4
15266d857b0SGreg Ungerer	jcc	L1
15366d857b0SGreg Ungerer	moveml	sp@,d2-d4	| restore data registers
15466d857b0SGreg Ungerer	unlk	a6		| and return
15566d857b0SGreg Ungerer	rts
15666d857b0SGreg Ungerer#endif /* __mcf5200__ || __mcoldfire__ */
157d13ffb56SAl Viro	EXPORT_SYMBOL(__udivsi3)
158