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