It seems that someone wanted to build flt_arith with a compiler that had long but not unsigned long. This required extra code to accomplish unsigned right shift, unsigned division, and unsigned comparison using the signed operations. Now that we use uint32_t, we can simply use the unsigned operations and remove the ucmp() function. We have similar code in mach/proto/fp/ and in lang/cem/libcc.ansi/stdlib/ext_comp.c where we use the unsigned operations. Some long variables become uint32_t, and some masks with 0xFFFFFFFF disappear because uint32_t has only 32 bits. Update flt_arith.3 to show that mantissa uses uint32_t. Provide a target to install modules/src/flt_arith/test.c as flt_test so I can run the tests.
80 lines
1.6 KiB
C
80 lines
1.6 KiB
C
/*
|
|
(c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
*/
|
|
|
|
/* $Id$ */
|
|
|
|
#include <stdint.h>
|
|
#include "flt_misc.h"
|
|
|
|
void
|
|
flt_mul(e1,e2,e3)
|
|
register flt_arith *e1,*e2,*e3;
|
|
{
|
|
/* Multiply the extended numbers e1 and e2, and put the
|
|
result in e3.
|
|
*/
|
|
register int i,j; /* loop control */
|
|
unsigned short mp[4];
|
|
unsigned short mc[4];
|
|
unsigned short result[8]; /* result */
|
|
|
|
register unsigned short *pres;
|
|
|
|
flt_status = 0;
|
|
|
|
/* first save the sign (XOR) */
|
|
e3->flt_sign = e1->flt_sign ^ e2->flt_sign;
|
|
|
|
/* compute new exponent */
|
|
e3->flt_exp = e1->flt_exp + e2->flt_exp + 1;
|
|
|
|
/* 128 bit multiply of mantissas */
|
|
|
|
/* assign unknown long formats */
|
|
/* to known unsigned word formats */
|
|
flt_split(e1, mp);
|
|
flt_split(e2, mc);
|
|
for (i = 8; i--;) {
|
|
result[i] = 0;
|
|
}
|
|
/*
|
|
* fill registers with their components
|
|
*/
|
|
for(i=4, pres = &result[4];i--;pres--) if (mp[i]) {
|
|
unsigned short k = 0;
|
|
uint32_t mpi = mp[i];
|
|
for(j=4;j--;) {
|
|
long tmp = (uint32_t)pres[j] + k;
|
|
if (mc[j]) tmp += mpi * mc[j];
|
|
pres[j] = tmp & 0xFFFF;
|
|
k = (tmp >> 16) & 0xFFFF;
|
|
}
|
|
pres[-1] = k;
|
|
}
|
|
|
|
if (! (result[0] & 0x8000)) {
|
|
e3->flt_exp--;
|
|
for (i = 0; i <= 3; i++) {
|
|
result[i] <<= 1;
|
|
if (result[i+1]&0x8000) result[i] |= 1;
|
|
}
|
|
result[4] <<= 1;
|
|
}
|
|
/*
|
|
* combine the registers to a total
|
|
*/
|
|
e3->m1 = ((uint32_t)result[0] << 16) + result[1];
|
|
e3->m2 = ((uint32_t)result[2] << 16) + result[3];
|
|
if (result[4] & 0x8000) {
|
|
if (++e3->m2 == 0) {
|
|
e3->m2 = 0;
|
|
if (++e3->m1 == 0) {
|
|
e3->m1 = 0x80000000;
|
|
e3->flt_exp++;
|
|
}
|
|
}
|
|
}
|
|
flt_chk(e3);
|
|
}
|