mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
3.3 KiB
147 lines
3.3 KiB
/*[
|
|
|
|
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;
|
|
}
|