101 lines
2.0 KiB
C
101 lines
2.0 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 2011 Fidelity Information Services, Inc *
|
|
* *
|
|
* This source code contains the intellectual property *
|
|
* of its copyright holder(s), and is made available *
|
|
* under a license. If you do not know the terms of *
|
|
* the license, please stop and do not read further. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "mdef.h"
|
|
|
|
#include "arit.h"
|
|
#include "eb_muldiv.h"
|
|
#include "promodemo.h"
|
|
#include "op.h"
|
|
|
|
LITREF int4 ten_pwr[];
|
|
LITREF mval literal_zero;
|
|
|
|
error_def(ERR_NUMOFLOW);
|
|
|
|
void op_idiv(mval *u, mval *v, mval *q)
|
|
{
|
|
bool promo;
|
|
int4 z, c, exp;
|
|
mval w, y;
|
|
|
|
error_def (ERR_DIVZERO);
|
|
|
|
MV_FORCE_NUM(u);
|
|
MV_FORCE_NUM(v);
|
|
if ((v->mvtype & MV_INT) && v->m[1] == 0)
|
|
rts_error(VARLSTCNT(1) ERR_DIVZERO);
|
|
if (u->mvtype & MV_INT & v->mvtype)
|
|
{
|
|
promo = eb_int_div(u->m[1], v->m[1], q->m);
|
|
if (!promo)
|
|
{
|
|
q->mvtype = MV_NM | MV_INT;
|
|
return;
|
|
} else
|
|
{
|
|
w = *u;
|
|
y = *v;
|
|
promote(&w);
|
|
promote(&y);
|
|
u = &w;
|
|
v = &y;
|
|
}
|
|
} else if (u->mvtype & MV_INT)
|
|
{
|
|
w = *u;
|
|
promote(&w);
|
|
u = &w;
|
|
} else if (v->mvtype & MV_INT)
|
|
{
|
|
w = *v;
|
|
promote(&w);
|
|
v = &w;
|
|
}
|
|
exp = u->e - v->e + MV_XBIAS;
|
|
if (exp < MV_XBIAS)
|
|
*q = literal_zero;
|
|
else
|
|
{
|
|
c = eb_div(v->m, u->m, q->m);
|
|
exp += c;
|
|
if (exp <= MV_XBIAS)
|
|
*q = literal_zero;
|
|
else if (exp < EXP_IDX_BIAL)
|
|
{
|
|
assert(EXP_IDX_BIAL - exp >= 0);
|
|
z = ten_pwr[EXP_IDX_BIAL - exp];
|
|
q->m[1] = (q->m[1] / z) * z;
|
|
q->m[0] = 0;
|
|
}
|
|
else if (exp < EXP_IDX_BIAQ)
|
|
{
|
|
assert(EXP_IDX_BIAQ - exp >= 0);
|
|
z = ten_pwr[EXP_IDX_BIAQ - exp];
|
|
q->m[0] = (q->m[0] / z) * z;
|
|
}
|
|
|
|
if (exp < EXP_INT_OVERF && exp > EXP_INT_UNDERF
|
|
&& q->m[0] == 0 && (q->m[1]%ten_pwr[EXP_INT_OVERF-1-exp] == 0))
|
|
demote(q, exp, u->sgn ^ v->sgn);
|
|
else
|
|
{
|
|
assert(EXPLO <= exp);
|
|
if (EXPHI <= exp)
|
|
rts_error(VARLSTCNT(1) ERR_NUMOFLOW);
|
|
q->e = exp;
|
|
q->sgn = u->sgn ^ v->sgn;
|
|
q->mvtype = MV_NM;
|
|
}
|
|
}
|
|
assert(q->m[1] < MANT_HI);
|
|
}
|