
/* This file contains excerpts of libgcc to support 64-bit division without
	having to link against libgcc. */

/* More subroutines needed by GCC output code on some machines.  */
/* Compile this one with gcc.  */
/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.

This file is part of GNU CC.

GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING.  If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */

/* As a special exception, if you link this software with other files,
   some of which are compiled with GCC, to produce an executable,
   this software does not by itself cause the resulting executable
   to be covered by the GNU General Public License.
   This exception does not however invalidate any other reasons why
   the executable file might be covered by the GNU General Public License.  */

/* It is incorrect to include config.h here, because this file is being
   compiled for the target, and hence definitions concerning only the host
   do not apply.  */

#define inhibit_libc

/* We disable this when inhibit_libc, so that gcc can still be built without
   needing header files first.  */
/* ??? This is not a good solution, since prototypes may be required in
   some cases for correct code.  See also frame.c.  */
#ifndef inhibit_libc
/* fixproto guarantees these system headers exist. */
#include <stdlib.h>
#include <unistd.h>
#endif


#ifndef L_trampoline

#endif

/* Don't use `fancy_abort' here even if config.h says to use it.  */
#ifdef abort
#undef abort
#endif

#if (SUPPORTS_WEAK == 1) && (defined (ASM_OUTPUT_DEF) || defined (ASM_OUTPUT_WEAK_ALIAS))
#define WEAK_ALIAS
#endif

/* In a cross-compilation situation, default to inhibiting compilation
   of routines that use libc.  */

#if defined(CROSS_COMPILE) && !defined(inhibit_libc)
#define inhibit_libc
#endif

/* Permit the tm.h file to select the endianness to use just for this
   file.  This is used when the endianness is determined when the
   compiler is run.  */

#ifdef __powerpc__
#define WORDS_BIG_ENDIAN 1
#endif

#ifndef LIBGCC2_WORDS_BIG_ENDIAN
#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
#endif

#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
#endif

/* In the first part of this file, we are interfacing to calls generated
   by the compiler itself.  These calls pass values into these routines
   which have very specific modes (rather than very specific types), and
   these compiler-generated calls also expect any return values to have
   very specific modes (rather than very specific types).  Thus, we need
   to avoid using regular C language type names in this part of the file
   because the sizes for those types can be configured to be anything.
   Instead we use the following special type names.  */

typedef unsigned int UQItype __attribute__ ((mode(QI)));
typedef int SItype __attribute__ ((mode(SI)));
typedef unsigned int USItype __attribute__ ((mode(SI)));
typedef int DItype __attribute__ ((mode(DI)));
typedef unsigned int UDItype __attribute__ ((mode(DI)));


typedef int word_type __attribute__ ((mode(__word__)));

/* Make sure that we don't accidentally use any normal C language built-in
   type names in the first part of this file.  Instead we want to use *only*
   the type names defined above.  The following macro definitions insure
   that if we *do* accidentally use some normal C language built-in type name,
   we will get a syntax error.  */

#define char bogus_type
#define short bogus_type
#define int bogus_type
#define long bogus_type
#define unsigned bogus_type
#define float bogus_type
#define double bogus_type

#define BITS_PER_UNIT 8
#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)

/* DIstructs are pairs of SItype values in the order determined by
   LIBGCC2_WORDS_BIG_ENDIAN.  */

#if LIBGCC2_WORDS_BIG_ENDIAN
struct DIstruct {
    SItype high, low;
};
#else
struct DIstruct {
    SItype low, high;
};
#endif

/* We need this union to unpack/pack DImode values, since we don't have
   any arithmetic yet.  Incoming DImode parameters are stored into the
   `ll' field, and the unpacked result is read from the struct `s'.  */

typedef union {
    struct DIstruct s;
    DItype ll;
} DIunion;

static inline DItype __negdi2(DItype u)
{
    DIunion w;
    DIunion uu;

    uu.ll = u;

    w.s.low = -uu.s.low;
    w.s.high = -uu.s.high - ((USItype) w.s.low > 0);

    return w.ll;
}

#include "longlong.h"


static const UQItype __clz_tab[] = {
    0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
    5, 5, 5, 5, 5, 5, 5, 5,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 8, 8, 8, 8,
};

static inline UDItype __udivmoddi4(UDItype n, UDItype d, UDItype * rp)
{
    DIunion ww;
    DIunion nn, dd;
    DIunion rr;
    USItype d0, d1, n0, n1, n2;
    USItype q0, q1;
    USItype b, bm;

    nn.ll = n;
    dd.ll = d;

    d0 = dd.s.low;
    d1 = dd.s.high;
    n0 = nn.s.low;
    n1 = nn.s.high;

#if !UDIV_NEEDS_NORMALIZATION
    if (d1 == 0) {
	if (d0 > n1) {
	    /* 0q = nn / 0D */

	    udiv_qrnnd(q0, n0, n1, n0, d0);
	    q1 = 0;

	    /* Remainder in n0.  */
	} else {
	    /* qq = NN / 0d */

	    if (d0 == 0)
		d0 = 1 / d0;	/* Divide intentionally by zero.  */

	    udiv_qrnnd(q1, n1, 0, n1, d0);
	    udiv_qrnnd(q0, n0, n1, n0, d0);

	    /* Remainder in n0.  */
	}

	if (rp != 0) {
	    rr.s.low = n0;
	    rr.s.high = 0;
	    *rp = rr.ll;
	}
    }
#else				/* UDIV_NEEDS_NORMALIZATION */

    if (d1 == 0) {
	if (d0 > n1) {
	    /* 0q = nn / 0D */

	    count_leading_zeros(bm, d0);

	    if (bm != 0) {
		/* Normalize, i.e. make the most significant bit of the
		   denominator set.  */

		d0 = d0 << bm;
		n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
		n0 = n0 << bm;
	    }

	    udiv_qrnnd(q0, n0, n1, n0, d0);
	    q1 = 0;

	    /* Remainder in n0 >> bm.  */
	} else {
	    /* qq = NN / 0d */

	    if (d0 == 0)
		d0 = 1 / d0;	/* Divide intentionally by zero.  */

	    count_leading_zeros(bm, d0);

	    if (bm == 0) {
		/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
		   conclude (the most significant bit of n1 is set) /\ (the
		   leading quotient digit q1 = 1).

		   This special case is necessary, not an optimization.
		   (Shifts counts of SI_TYPE_SIZE are undefined.)  */

		n1 -= d0;
		q1 = 1;
	    } else {
		/* Normalize.  */

		b = SI_TYPE_SIZE - bm;

		d0 = d0 << bm;
		n2 = n1 >> b;
		n1 = (n1 << bm) | (n0 >> b);
		n0 = n0 << bm;

		udiv_qrnnd(q1, n1, n2, n1, d0);
	    }

	    /* n1 != d0...  */

	    udiv_qrnnd(q0, n0, n1, n0, d0);

	    /* Remainder in n0 >> bm.  */
	}

	if (rp != 0) {
	    rr.s.low = n0 >> bm;
	    rr.s.high = 0;
	    *rp = rr.ll;
	}
    }
#endif				/* UDIV_NEEDS_NORMALIZATION */

    else {
	if (d1 > n1) {
	    /* 00 = nn / DD */

	    q0 = 0;
	    q1 = 0;

	    /* Remainder in n1n0.  */
	    if (rp != 0) {
		rr.s.low = n0;
		rr.s.high = n1;
		*rp = rr.ll;
	    }
	} else {
	    /* 0q = NN / dd */

	    count_leading_zeros(bm, d1);
	    if (bm == 0) {
		/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
		   conclude (the most significant bit of n1 is set) /\ (the
		   quotient digit q0 = 0 or 1).

		   This special case is necessary, not an optimization.  */

		/* The condition on the next line takes advantage of that
		   n1 >= d1 (true due to program flow).  */
		if (n1 > d1 || n0 >= d0) {
		    q0 = 1;
		    sub_ddmmss(n1, n0, n1, n0, d1, d0);
		} else
		    q0 = 0;

		q1 = 0;

		if (rp != 0) {
		    rr.s.low = n0;
		    rr.s.high = n1;
		    *rp = rr.ll;
		}
	    } else {
		USItype m1, m0;
		/* Normalize.  */

		b = SI_TYPE_SIZE - bm;

		d1 = (d1 << bm) | (d0 >> b);
		d0 = d0 << bm;
		n2 = n1 >> b;
		n1 = (n1 << bm) | (n0 >> b);
		n0 = n0 << bm;

		udiv_qrnnd(q0, n1, n2, n1, d1);
		umul_ppmm(m1, m0, q0, d0);

		if (m1 > n1 || (m1 == n1 && m0 > n0)) {
		    q0--;
		    sub_ddmmss(m1, m0, m1, m0, d1, d0);
		}

		q1 = 0;

		/* Remainder in (n1n0 - m1m0) >> bm.  */
		if (rp != 0) {
		    sub_ddmmss(n1, n0, n1, n0, m1, m0);
		    rr.s.low = (n1 << b) | (n0 >> bm);
		    rr.s.high = n1 >> bm;
		    *rp = rr.ll;
		}
	    }
	}
    }

    ww.s.low = q0;
    ww.s.high = q1;
    return ww.ll;
}

UDItype __udivdi3(UDItype n, UDItype d)
{
    return __udivmoddi4(n, d, (UDItype *) 0);
}
