ack/mach/proto/fp/mul_ext.c

99 lines
2.2 KiB
C
Raw Permalink Normal View History

1988-04-07 11:40:46 +00:00
/*
(c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
See the copyright notice in the ACK home directory, in the file "Copyright".
*/
1994-06-24 14:02:31 +00:00
/* $Id$ */
1988-04-07 11:40:46 +00:00
1988-04-07 10:57:49 +00:00
/*
ROUTINE TO MULTIPLY TWO EXTENDED FORMAT NUMBERS
*/
# include "FP_bias.h"
# include "FP_trap.h"
# include "FP_types.h"
1989-07-25 14:21:09 +00:00
# include "FP_shift.h"
1988-04-07 10:57:49 +00:00
1993-01-05 12:06:58 +00:00
void
1988-04-07 10:57:49 +00:00
mul_ext(e1,e2)
EXTEND *e1,*e2;
{
1988-08-11 14:50:18 +00:00
register int i,j; /* loop control */
1989-07-25 14:21:09 +00:00
unsigned short mp[4]; /* multiplier */
unsigned short mc[4]; /* multipcand */
unsigned short result[8]; /* result */
1988-08-11 14:50:18 +00:00
register unsigned short *pres;
1988-04-07 10:57:49 +00:00
/* first save the sign (XOR) */
e1->sign ^= e2->sign;
1989-07-25 14:21:09 +00:00
/* compute new exponent */
e1->exp += e2->exp + 1;
1988-04-07 10:57:49 +00:00
/* 128 bit multiply of mantissas */
/* assign unknown long formats */
/* to known unsigned word formats */
mp[0] = e1->m1 >> 16;
mp[1] = (unsigned short) e1->m1;
mp[2] = e1->m2 >> 16;
mp[3] = (unsigned short) e1->m2;
mc[0] = e2->m1 >> 16;
mc[1] = (unsigned short) e2->m1;
mc[2] = e2->m2 >> 16;
mc[3] = (unsigned short) e2->m2;
1988-08-11 14:50:18 +00:00
for (i = 8; i--;) {
result[i] = 0;
}
1988-04-07 10:57:49 +00:00
/*
* fill registers with their components
*/
1988-08-11 14:50:18 +00:00
for(i=4, pres = &result[4];i--;pres--) if (mp[i]) {
unsigned short k = 0;
unsigned long mpi = mp[i];
for(j=4;j--;) {
unsigned long tmp = (unsigned long)pres[j] + k;
if (mc[j]) tmp += mpi * mc[j];
pres[j] = tmp;
k = tmp >> 16;
1988-04-07 10:57:49 +00:00
}
1988-08-11 14:50:18 +00:00
pres[-1] = k;
}
1989-07-25 14:21:09 +00:00
if (! (result[0] & 0x8000)) {
e1->exp--;
for (i = 0; i <= 3; i++) {
result[i] <<= 1;
if (result[i+1]&0x8000) result[i] |= 1;
}
result[4] <<= 1;
}
1988-04-07 10:57:49 +00:00
/*
* combine the registers to a total
*/
1988-08-11 14:50:18 +00:00
e1->m1 = ((unsigned long)(result[0]) << 16) + result[1];
e1->m2 = ((unsigned long)(result[2]) << 16) + result[3];
if (result[4] & 0x8000) {
1988-04-07 10:57:49 +00:00
if (++e1->m2 == 0)
1989-07-25 14:21:09 +00:00
if (++e1->m1 == 0) {
e1->m1 = NORMBIT;
e1->exp++;
}
1988-08-11 14:50:18 +00:00
}
1988-04-07 10:57:49 +00:00
1989-07-25 14:21:09 +00:00
/* check for overflow */
if (e1->exp >= EXT_MAX) {
trap(EFOVFL);
/* if caught */
/* return signed infinity */
e1->exp = EXT_MAX;
infinity: e1->m1 = e1->m2 =0L;
return;
}
/* check for underflow */
if (e1->exp < EXT_MIN) {
trap(EFUNFL);
e1->exp = EXT_MIN;
goto infinity;
}
1988-04-07 10:57:49 +00:00
}