11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* libgcc1 routines for 68000 w/o floating-point hardware. 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThis file is part of GNU CC. 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsGNU CC is free software; you can redistribute it and/or modify it 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunder the terms of the GNU General Public License as published by the 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsFree Software Foundation; either version 2, or (at your option) any 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslater version. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIn addition to the permissions in the GNU General Public License, the 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsFree Software Foundation gives you unlimited permission to link the 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscompiled version of this file with other programs, and to distribute 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsthose programs without any restriction coming from the use of this 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfile. (The General Public License restrictions do apply in other 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrespects; for example, they cover modification of the file, and 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdistribution when not linked into another program.) 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThis file is distributed in the hope that it will be useful, but 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsWITHOUT ANY WARRANTY; without even the implied warranty of 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsGeneral Public License for more details. 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsYou should have received a copy of the GNU General Public License 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsalong with this program; see the file COPYING. If not, write to 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsthe Free Software Foundation, 59 Temple Place - Suite 330, 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsBoston, MA 02111-1307, USA. */ 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* As a special exception, if you link this library with files 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compiled with GCC to produce an executable, this does not cause 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the resulting executable to be covered by the GNU General Public License. 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This exception does not however invalidate any other reasons why 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the executable file might be covered by the GNU General Public License. */ 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Use this one for any 680x0; assumes no floating point hardware. 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Some of this code comes from MINIX, via the folks at ericsson. 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These are predefined by new versions of GNU cpp. */ 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef __USER_LABEL_PREFIX__ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define __USER_LABEL_PREFIX__ _ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef __REGISTER_PREFIX__ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define __REGISTER_PREFIX__ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef __IMMEDIATE_PREFIX__ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define __IMMEDIATE_PREFIX__ # 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ANSI concatenation macros. */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONCAT1(a, b) CONCAT2(a, b) 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONCAT2(a, b) a ## b 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Use the right prefix for global labels. */ 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Use the right prefix for registers. */ 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Use the right prefix for immediate values. */ 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define d0 REG (d0) 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define d1 REG (d1) 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define d2 REG (d2) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define d3 REG (d3) 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define d4 REG (d4) 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define d5 REG (d5) 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define d6 REG (d6) 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define d7 REG (d7) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define a0 REG (a0) 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define a1 REG (a1) 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define a2 REG (a2) 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define a3 REG (a3) 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define a4 REG (a4) 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define a5 REG (a5) 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define a6 REG (a6) 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define fp REG (fp) 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sp REG (sp) 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .text 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .proc 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .globl SYM (__udivsi3) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsSYM (__udivsi3): 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if !(defined(__mcf5200__) || defined(__mcoldfire__)) 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds movel d2, sp@- 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds movel sp@(12), d1 /* d1 = divisor */ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds movel sp@(8), d0 /* d0 = dividend */ 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmpl IMM (0x10000), d1 /* divisor >= 2 ^ 16 ? */ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds jcc L3 /* then try next algorithm */ 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds movel d0, d2 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clrw d2 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds swap d2 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds divu d1, d2 /* high quotient in lower word */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds movew d2, d0 /* save high quotient */ 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds swap d0 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds movew sp@(10), d2 /* get low dividend + high rest */ 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds divu d1, d2 /* low quotient */ 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds movew d2, d0 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds jra L6 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL3: movel d1, d2 /* use d2 as divisor backup */ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL4: lsrl IMM (1), d1 /* shift divisor */ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lsrl IMM (1), d0 /* shift dividend */ 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmpl IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ? */ 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds jcc L4 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds divu d1, d0 /* now we have 16 bit divisor */ 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds andl IMM (0xffff), d0 /* mask out divisor, ignore remainder */ 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Multiply the 16 bit tentative quotient with the 32 bit divisor. Because of 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the operand ranges, this might give a 33 bit product. If this product is 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds greater than the dividend, the tentative quotient was too large. */ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds movel d2, d1 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mulu d0, d1 /* low part, 32 bits */ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds swap d2 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mulu d0, d2 /* high part, at most 17 bits */ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds swap d2 /* align high part with low part */ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tstw d2 /* high part 17 bits? */ 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds jne L5 /* if 17 bits, quotient was too large */ 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addl d2, d1 /* add parts */ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds jcs L5 /* if sum is 33 bits, quotient was too large */ 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmpl sp@(8), d1 /* compare the sum with the dividend */ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds jls L6 /* if sum > dividend, quotient was too large */ 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL5: subql IMM (1), d0 /* adjust quotient */ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL6: movel sp@+, d2 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* __mcf5200__ || __mcoldfire__ */ 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Coldfire implementation of non-restoring division algorithm from 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Hennessy & Patterson, Appendix A. */ 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link a6,IMM (-12) 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moveml d2-d4,sp@ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds movel a6@(8),d0 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds movel a6@(12),d1 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clrl d2 | clear p 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moveq IMM (31),d4 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL1: addl d0,d0 | shift reg pair (p,a) one bit left 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addxl d2,d2 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds movl d2,d3 | subtract b from p, store in tmp. 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds subl d1,d3 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds jcs L2 | if no carry, 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bset IMM (0),d0 | set the low order bit of a to 1, 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds movl d3,d2 | and store tmp in p. 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL2: subql IMM (1),d4 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds jcc L1 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds moveml sp@,d2-d4 | restore data registers 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlk a6 | and return 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rts 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* __mcf5200__ || __mcoldfire__ */ 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 163