summaryrefslogblamecommitdiffstats
path: root/private/mvdm/softpc.new/base/ccpu386/c_div64.c
blob: ae5826b56f19984e51cc6adbb7ba729c75839bb1 (plain) (tree)


















































































































































                                                                                 
/*[

c_div64.c

LOCAL CHAR SccsID[]="@(#)c_div64.c	1.5 02/09/94";

64-bit Divide Functions.
------------------------

]*/


#include <insignia.h>

#include <host_def.h>
#include <xt.h>
#include <c_main.h>
#include <c_addr.h>
#include <c_bsic.h>
#include <c_prot.h>
#include <c_seg.h>
#include <c_stack.h>
#include <c_xcptn.h>
#include	<c_reg.h>
#include <c_div64.h>
#include <c_neg64.h>


/*
   =====================================================================
   EXTERNAL FUNCTIONS START HERE.
   =====================================================================
 */


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Do 64bit = 64bit / 32bit Divide (Signed).                          */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GLOBAL VOID
div64
       		    		        		                         
IFN4(
	IS32 *, hr,	/* High 32 bits of dividend/quotient */
	IS32 *, lr,	/* Low 32 bits of dividend/quotient */
	IS32, divisor,
	IS32 *, rem	/* Remainder */
    )


   {
   if ( *hr & BIT31_MASK )
      {
      if ( divisor & BIT31_MASK )
	 {
	 /* Negative Dividend :: Negative Divisor */
	 neg64(hr, lr);
	 divisor = -divisor;
	 divu64((IU32 *)hr, (IU32 *)lr, (IU32)divisor, (IU32 *)rem);
	 *rem = -*rem;
	 }
      else
	 {
	 /* Negative Dividend :: Positive Divisor */
	 neg64(hr, lr);
	 divu64((IU32 *)hr, (IU32 *)lr, (IU32)divisor, (IU32 *)rem);
	 neg64(hr, lr);
	 *rem = -*rem;
	 }
      }
   else
      {
      if ( divisor & BIT31_MASK )
	 {
	 /* Positive Dividend :: Negative Divisor */
	 divisor = -divisor;
	 divu64((IU32 *)hr, (IU32 *)lr, (IU32)divisor, (IU32 *)rem);
	 neg64(hr, lr);
	 }
      else
	 {
	 /* Positive Dividend :: Positive Divisor */
	 divu64((IU32 *)hr, (IU32 *)lr, (IU32)divisor, (IU32 *)rem);
	 }
      }
   }

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Do 64bit = 64bit / 32bit Divide (Unsigned).                        */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GLOBAL VOID
divu64
       		    		        		                         
IFN4(
	IU32 *, hr,	/* High 32 bits of dividend/quotient */
	IU32 *, lr,	/* Low 32 bits of dividend/quotient */
	IU32, divisor,
	IU32 *, rem	/* Remainder */
    )


   {
   ISM32 count;
   IU32 hd;   /* High 32 bits of dividend/quotient */
   IU32 ld;   /* Low 32 bits of dividend/quotient */
   IU32 par_div;   /* partial dividend */
   IU32 carry1;
   IU32 carry2;
   IU32 carry3;

   hd = *hr;	/* Get local copies */
   ld = *lr;
   count = 64;	/* Initialise */
   par_div = 0;

   while ( count != 0 )
      {
      /* shift <par_div:dividend> left.
	    We have to watch out for carries from
	       ld<bit31> to hd<bit0>      (carry1) and
	       hd<bit31> to par_div<bit0> (carry2) and
	       par_div<bit31> to 'carry'  (carry3).
       */
      carry1 = carry2 = carry3 = 0;
      if ( ld & BIT31_MASK )
	 carry1 = 1;
      if ( hd & BIT31_MASK )
	 carry2 = 1;
      if ( par_div & BIT31_MASK )
	 carry3 = 1;
      ld = ld << 1;
      hd = hd << 1 | carry1;
      par_div = par_div << 1 | carry2;

      /* check if divisor 'goes into' partial dividend */
      if ( carry3 || divisor <= par_div )
	 {
	 /* Yes it does */
	 par_div = par_div - divisor;
	 ld = ld | 1;   /* output a 1 bit */
	 }
      count--;
      }

   *rem = par_div;	/* Return results */
   *hr = hd;
   *lr = ld;
   }