1
0
mirror of https://github.com/simh/simh.git synced 2026-01-25 19:56:25 +00:00

Notes For V3.5-0

The source set has been extensively overhauled.  For correct
viewing, set Visual C++ or Emacs to have tab stops every 4
characters.

1. New Features in 3.4-1

1.1 All Ethernet devices

- Added Windows user-defined adapter names (from Timothe Litt)

1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors

- Added support for SET <unit>n DISCONNECT

1.3 VAX

- Added latent QDSS support
- Revised autoconfigure to handle QDSS

1.4 PDP-11

- Revised autoconfigure to handle more casees

2. Bugs Fixed in 3.4-1

2.1 SCP and libraries

- Trim trailing spaces on all input (for example, attach file names)
- Fixed sim_sock spurious SIGPIPE error in Unix/Linux
- Fixed sim_tape misallocation of TPC map array for 64b simulators

2.2 1401

- Fixed bug, CPU reset was clearing SSB through SSG

2.3 PDP-11

- Fixed bug in VH vector display routine
- Fixed XU runt packet processing (found by Tim Chapman)

2.4 Interdata

- Fixed bug in SHOW PAS CONN/STATS
- Fixed potential integer overflow exception in divide

2.5 SDS

- Fixed bug in SHOW MUX CONN/STATS

2.6 HP

- Fixed bug in SHOW MUX CONN/STATS

2.7 PDP-8

- Fixed bug in SHOW TTIX CONN/STATS
- Fixed bug in SET/SHOW TTOXn LOG

2.8 PDP-18b

- Fixed bug in SHOW TTIX CONN/STATS
- Fixed bug in SET/SHOW TTOXn LOG

2.9 Nova, Eclipse

- Fixed potential integer overflow exception in divide
This commit is contained in:
Bob Supnik
2005-09-09 18:09:00 -07:00
committed by Mark Pizzolato
parent ec60bbf329
commit b7c1eae41f
257 changed files with 107140 additions and 97195 deletions

View File

@@ -1,6 +1,6 @@
/* id_fp.c: Interdata floating point instructions
Copyright (c) 2000-2004, Robert M. Supnik
Copyright (c) 2000-2005, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -19,8 +19,8 @@
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
The Interdata uses IBM 360 floating point format:
@@ -32,9 +32,9 @@
| fraction low | :double
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
where S = 0 for plus, 1 for minus
exponent = 16**n, in excess 64 code
fraction = .hhhhhh, seen as 6-14 hexadecimal digits
where S = 0 for plus, 1 for minus
exponent = 16**n, in excess 64 code
fraction = .hhhhhh, seen as 6-14 hexadecimal digits
Numbers can be normalized or unnormalized but are always normalized
when loaded.
@@ -52,61 +52,65 @@
are rounded, double precision operations are truncated, and the floating
point registers are kept in separate hardware arrays.
*/
#include "id_defs.h"
struct ufp { /* unpacked fp */
int32 sign; /* sign */
int32 exp; /* unbiased exp */
uint32 h; /* fr high */
uint32 l; }; /* fr low */
struct ufp { /* unpacked fp */
int32 sign; /* sign */
int32 exp; /* unbiased exp */
uint32 h; /* fr high */
uint32 l; /* fr low */
};
#define FP_V_SIGN 31 /* sign */
#define FP_M_SIGN 0x1
#define FP_GETSIGN(x) (((x) >> FP_V_SIGN) & FP_M_SIGN)
#define FP_V_EXP 24 /* exponent */
#define FP_M_EXP 0x7F
#define FP_GETEXP(x) (((x) >> FP_V_EXP) & FP_M_EXP)
#define FP_V_FRH 0 /* fraction */
#define FP_M_FRH 0xFFFFFF
#define FP_GETFRH(x) (((x) >> FP_V_FRH) & FP_M_FRH)
#define FP_GETFRL(x) (x)
#define FP_V_SIGN 31 /* sign */
#define FP_M_SIGN 0x1
#define FP_GETSIGN(x) (((x) >> FP_V_SIGN) & FP_M_SIGN)
#define FP_V_EXP 24 /* exponent */
#define FP_M_EXP 0x7F
#define FP_GETEXP(x) (((x) >> FP_V_EXP) & FP_M_EXP)
#define FP_V_FRH 0 /* fraction */
#define FP_M_FRH 0xFFFFFF
#define FP_GETFRH(x) (((x) >> FP_V_FRH) & FP_M_FRH)
#define FP_GETFRL(x) (x)
#define FP_BIAS 0x40 /* exp bias */
#define FP_CARRY (1 << FP_V_EXP ) /* carry out */
#define FP_NORM (0xF << (FP_V_EXP - 4)) /* normalized */
#define FP_ROUND 0x80000000
#define FP_BIAS 0x40 /* exp bias */
#define FP_CARRY (1 << FP_V_EXP ) /* carry out */
#define FP_NORM (0xF << (FP_V_EXP - 4)) /* normalized */
#define FP_ROUND 0x80000000
/* Double precision fraction add/subtract/compare */
#define FR_ADD(d,s) d.l = (d.l + s.l) & DMASK32; \
d.h = (d.h + s.h + (d.l < s.l)) & DMASK32
#define FR_ADD(d,s) d.l = (d.l + s.l) & DMASK32; \
d.h = (d.h + s.h + (d.l < s.l)) & DMASK32
#define FR_SUB(d,s) d.h = (d.h - s.h - (d.l < s.l)) & DMASK32; \
d.l = (d.l - s.l) & DMASK32
#define FR_SUB(d,s) d.h = (d.h - s.h - (d.l < s.l)) & DMASK32; \
d.l = (d.l - s.l) & DMASK32
#define FR_GE(s1,s2) ((s1.h > s2.h) || \
((s1.h == s2.h) && (s1.l >= s2.l)))
#define FR_GE(s1,s2) ((s1.h > s2.h) || \
((s1.h == s2.h) && (s1.l >= s2.l)))
/* Variable and constant shifts; for constants, 0 < k < 32 */
#define FR_RSH_V(v,s) if ((s) < 32) { \
v.l = ((v.l >> (s)) | \
(v.h << (32 - (s)))) & DMASK32; \
v.h = (v.h >> (s)) & DMASK32; } \
else { v.l = v.h >> ((s) - 32); \
v.h = 0; }
#define FR_RSH_V(v,s) if ((s) < 32) { \
v.l = ((v.l >> (s)) | \
(v.h << (32 - (s)))) & DMASK32; \
v.h = (v.h >> (s)) & DMASK32; \
} \
else { \
v.l = v.h >> ((s) - 32); \
v.h = 0; \
}
#define FR_RSH_K(v,s) v.l = ((v.l >> (s)) | \
(v.h << (32 - (s)))) & DMASK32; \
v.h = (v.h >> (s)) & DMASK32
#define FR_RSH_K(v,s) v.l = ((v.l >> (s)) | \
(v.h << (32 - (s)))) & DMASK32; \
v.h = (v.h >> (s)) & DMASK32
#define FR_LSH_K(v,s) v.h = ((v.h << (s)) | \
(v.l >> (32 - (s)))) & DMASK32; \
v.l = (v.l << (s)) & DMASK32
#define FR_LSH_K(v,s) v.h = ((v.h << (s)) | \
(v.l >> (32 - (s)))) & DMASK32; \
v.l = (v.l << (s)) & DMASK32
#define Q_RND(op) (OP_DPFP (op) == 0)
#define Q_RND_AS(op) ((OP_DPFP (op) == 0) && fp_in_hwre)
#define Q_RND(op) (OP_DPFP (op) == 0)
#define Q_RND_AS(op) ((OP_DPFP (op) == 0) && fp_in_hwre)
extern uint32 *R;
extern uint32 F[8];
@@ -120,15 +124,15 @@ void UnpackFPR (struct ufp *fop, uint32 op, uint32 r1);
void NormUFP (struct ufp *fop);
uint32 StoreFPR (struct ufp *fop, uint32 op, uint32 r1, uint32 rnd);
uint32 StoreFPX (struct ufp *fop, uint32 op, uint32 r1);
/* Floating point load */
uint32 f_l (uint32 op, uint32 r1, uint32 r2, uint32 ea)
{
struct ufp fop2;
ReadFP2 (&fop2, op, r2, ea); /* get op, normalize */
return StoreFPR (&fop2, op, r1, 0); /* store, chk unflo */
ReadFP2 (&fop2, op, r2, ea); /* get op, normalize */
return StoreFPR (&fop2, op, r1, 0); /* store, chk unflo */
}
/* Floating point compare */
@@ -137,105 +141,120 @@ uint32 f_c (uint32 op, uint32 r1, uint32 r2, uint32 ea)
{
struct ufp fop1, fop2;
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
UnpackFPR (&fop1, op, r1); /* get op1, norm */
if (fop1.sign ^ fop2.sign) /* signs differ? */
return (fop2.sign? CC_G: (CC_C | CC_L));
if (fop1.exp != fop2.exp) /* exps differ? */
return (((fop1.exp > fop2.exp) ^ fop1.sign)? CC_G: (CC_C | CC_L));
if (fop1.h != fop2.h) /* hi fracs differ? */
return (((fop1.h > fop2.h) ^ fop1.sign)? CC_G: (CC_C | CC_L));
if (OP_DPFP (op) && (fop1.l != fop2.l)) /* dp: low fracs diff? */
return (((fop1.l > fop2.l) ^ fop1.sign)? CC_G: (CC_C | CC_L));
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
UnpackFPR (&fop1, op, r1); /* get op1, norm */
if (fop1.sign ^ fop2.sign) /* signs differ? */
return (fop2.sign? CC_G: (CC_C | CC_L));
if (fop1.exp != fop2.exp) /* exps differ? */
return (((fop1.exp > fop2.exp) ^ fop1.sign)? CC_G: (CC_C | CC_L));
if (fop1.h != fop2.h) /* hi fracs differ? */
return (((fop1.h > fop2.h) ^ fop1.sign)? CC_G: (CC_C | CC_L));
if (OP_DPFP (op) && (fop1.l != fop2.l)) /* dp: low fracs diff? */
return (((fop1.l > fop2.l) ^ fop1.sign)? CC_G: (CC_C | CC_L));
return 0;
}
/* Floating to integer conversion */
uint32 f_fix (uint32 op, uint32 r1, uint32 r2) /* 16b */
uint32 f_fix (uint32 op, uint32 r1, uint32 r2) /* 16b */
{
struct ufp res;
uint32 cc;
UnpackFPR (&res, op, r2); /* get op2, norm */
if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */
R[r1] = 0;
return 0; }
if ((res.exp > 0x44) || /* result too big? */
UnpackFPR (&res, op, r2); /* get op2, norm */
if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */
R[r1] = 0;
return 0;
}
if ((res.exp > 0x44) || /* result too big? */
((res.exp == 0x44) && (res.h >= 0x00800000))) {
res.h = MMASK16;
cc = CC_V; }
else { res.h = res.h >> ((0x46 - res.exp) * 4); /* right align frac */
cc = 0; }
res.h = MMASK16;
cc = CC_V;
}
else {
res.h = res.h >> ((0x46 - res.exp) * 4); /* right align frac */
cc = 0;
}
if (res.sign) {
R[r1] = ((res.h ^ DMASK16) + 1) & DMASK16; /* negate result */
return cc | CC_L; }
R[r1] = ((res.h ^ DMASK16) + 1) & DMASK16; /* negate result */
return cc | CC_L;
}
R[r1] = res.h & DMASK16;
return cc | CC_G;
}
uint32 f_fix32 (uint32 op, uint32 r1, uint32 r2) /* 32b */
uint32 f_fix32 (uint32 op, uint32 r1, uint32 r2) /* 32b */
{
struct ufp res;
uint32 cc;
UnpackFPR (&res, op, r2); /* get op2, norm */
if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */
R[r1] = 0;
return 0; }
if ((res.exp > 0x48) || /* result too big? */
UnpackFPR (&res, op, r2); /* get op2, norm */
if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */
R[r1] = 0;
return 0;
}
if ((res.exp > 0x48) || /* result too big? */
((res.exp == 0x48) && (res.h >= 0x00800000))) {
res.h = MMASK32;
cc = CC_V; }
else { FR_LSH_K (res, 8); /* get all in 32b */
res.h = res.h >> ((0x48 - res.exp) * 4); /* right align frac */
cc = 0; }
res.h = MMASK32;
cc = CC_V;
}
else {
FR_LSH_K (res, 8); /* get all in 32b */
res.h = res.h >> ((0x48 - res.exp) * 4); /* right align frac */
cc = 0;
}
if (res.sign) {
R[r1] = (res.h ^ DMASK32) + 1; /* negate result */
return cc | CC_L; }
R[r1] = (res.h ^ DMASK32) + 1; /* negate result */
return cc | CC_L;
}
R[r1] = res.h;
return cc | CC_G;
}
/* Integer to floating conversion */
uint32 f_flt (uint32 op, uint32 r1, uint32 r2) /* 16b */
uint32 f_flt (uint32 op, uint32 r1, uint32 r2) /* 16b */
{
struct ufp res = { 0, 0x44, 0, 0 }; /* +, 16**4 */
struct ufp res = { 0, 0x44, 0, 0 }; /* +, 16**4 */
uint32 cc;
if (R[r2] == 0) cc = 0; /* zero arg? */
else if (R[r2] & SIGN16) { /* neg arg? */
res.sign = FP_M_SIGN; /* set sign */
res.h = ((~R[r2] + 1) & DMASK16) << 8; /* get magnitude */
cc = CC_L; }
else { res.h = R[r2] << 8; /* pos nz arg */
cc = CC_G; }
NormUFP (&res); /* normalize */
StoreFPR (&res, op, r1, 0); /* store result */
if (R[r2] == 0) cc = 0; /* zero arg? */
else if (R[r2] & SIGN16) { /* neg arg? */
res.sign = FP_M_SIGN; /* set sign */
res.h = ((~R[r2] + 1) & DMASK16) << 8; /* get magnitude */
cc = CC_L;
}
else {
res.h = R[r2] << 8; /* pos nz arg */
cc = CC_G;
}
NormUFP (&res); /* normalize */
StoreFPR (&res, op, r1, 0); /* store result */
return cc;
}
uint32 f_flt32 (uint32 op, uint32 r1, uint32 r2) /* 32b */
uint32 f_flt32 (uint32 op, uint32 r1, uint32 r2) /* 32b */
{
struct ufp res = { 0, 0x48, 0, 0 }; /* +, 16**8 */
struct ufp res = { 0, 0x48, 0, 0 }; /* +, 16**8 */
uint32 cc, t;
t = R[r2]; /* int op */
if (t) { /* nonzero arg? */
if (t & SIGN32) { /* neg arg? */
res.sign = FP_M_SIGN; /* set sign */
t = (~t + 1) & DMASK32; /* get magnitude */
cc = CC_L; }
else cc = CC_G; /* pos nz arg */
res.h = t >> 8; /* hi frac */
res.l = t << 24; } /* lo frac */
else cc = 0; /* zero arg */
NormUFP (&res); /* normalize */
StoreFPR (&res, op, r1, 0); /* store result */
t = R[r2]; /* int op */
if (t) { /* nonzero arg? */
if (t & SIGN32) { /* neg arg? */
res.sign = FP_M_SIGN; /* set sign */
t = (~t + 1) & DMASK32; /* get magnitude */
cc = CC_L;
}
else cc = CC_G; /* pos nz arg */
res.h = t >> 8; /* hi frac */
res.l = t << 24; /* lo frac */
}
else cc = 0; /* zero arg */
NormUFP (&res); /* normalize */
StoreFPR (&res, op, r1, 0); /* store result */
return cc;
}
/* Floating point add/subtract */
uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea)
@@ -243,37 +262,44 @@ uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea)
struct ufp fop1, fop2, t;
int32 ediff;
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
UnpackFPR (&fop1, op, r1); /* get op1, norm */
if (op & 1) fop2.sign = fop2.sign ^ 1; /* if sub, inv sign2 */
if (fop1.h == 0) fop1 = fop2; /* if op1 = 0, res = op2 */
else if (fop2.h != 0) { /* if op2 = 0, no add */
if ((fop1.exp < fop2.exp) || /* |op1| < |op2|? */
((fop1.exp == fop2.exp) &&
((fop1.h < fop2.h) ||
((fop1.h == fop2.h) && (fop1.l < fop2.l))))) {
t = fop2; /* swap operands */
fop2 = fop1;
fop1 = t; }
ediff = fop1.exp - fop2.exp; /* exp difference */
if (OP_DPFP (op) || fp_in_hwre) { /* dbl prec or hwre? */
if (ediff >= 14) fop2.h = fop2.l = 0; /* diff too big? */
else if (ediff) { /* any difference? */
FR_RSH_V (fop2, ediff * 4); } } /* shift frac */
else { /* sgl prec ucode */
if (ediff >= 6) fop2.h = 0; /* diff too big? */
else if (ediff) /* any difference? */
fop2.h = fop2.h >> (ediff * 4); } /* shift frac */
if (fop1.sign ^ fop2.sign) { /* eff subtract */
FR_SUB (fop1, fop2); /* sub fractions */
NormUFP (&fop1); } /* normalize result */
else {
FR_ADD (fop1, fop2); /* add fractions */
if (fop1.h & FP_CARRY) { /* carry out? */
FR_RSH_K (fop1, 4); /* renormalize */
fop1.exp = fop1.exp + 1; } } /* incr exp */
} /* end if fop2 */
return StoreFPR (&fop1, op, r1, Q_RND_AS (op)); /* store result */
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
UnpackFPR (&fop1, op, r1); /* get op1, norm */
if (op & 1) fop2.sign = fop2.sign ^ 1; /* if sub, inv sign2 */
if (fop1.h == 0) fop1 = fop2; /* if op1 = 0, res = op2 */
else if (fop2.h != 0) { /* if op2 = 0, no add */
if ((fop1.exp < fop2.exp) || /* |op1| < |op2|? */
((fop1.exp == fop2.exp) &&
((fop1.h < fop2.h) ||
((fop1.h == fop2.h) && (fop1.l < fop2.l))))) {
t = fop2; /* swap operands */
fop2 = fop1;
fop1 = t;
}
ediff = fop1.exp - fop2.exp; /* exp difference */
if (OP_DPFP (op) || fp_in_hwre) { /* dbl prec or hwre? */
if (ediff >= 14) fop2.h = fop2.l = 0; /* diff too big? */
else if (ediff) { /* any difference? */
FR_RSH_V (fop2, ediff * 4); /* shift frac */
}
}
else { /* sgl prec ucode */
if (ediff >= 6) fop2.h = 0; /* diff too big? */
else if (ediff) /* any difference? */
fop2.h = fop2.h >> (ediff * 4); /* shift frac */
}
if (fop1.sign ^ fop2.sign) { /* eff subtract */
FR_SUB (fop1, fop2); /* sub fractions */
NormUFP (&fop1); /* normalize result */
}
else {
FR_ADD (fop1, fop2); /* add fractions */
if (fop1.h & FP_CARRY) { /* carry out? */
FR_RSH_K (fop1, 4); /* renormalize */
fop1.exp = fop1.exp + 1; /* incr exp */
}
}
} /* end if fop2 */
return StoreFPR (&fop1, op, r1, Q_RND_AS (op)); /* store result */
}
/* Floating point multiply
@@ -293,35 +319,39 @@ struct ufp fop1, fop2;
struct ufp res = { 0, 0, 0, 0 };
uint32 i;
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
UnpackFPR (&fop1, op, r1); /* get op1, norm */
if (fop1.h && fop2.h) { /* if both != 0 */
res.sign = fop1.sign ^ fop2.sign; /* sign = diff */
res.exp = fop1.exp + fop2.exp - FP_BIAS; /* exp = sum */
if ((res.exp < 0) || (res.exp > FP_M_EXP)) /* ovf/undf? */
return StoreFPX (&res, op, r1); /* early out */
if ((fop1.l | fop2.l) == 0) { /* 24b x 24b? */
for (i = 0; i < 24; i++) { /* 24 iterations */
if (fop2.h & 1) res.h = res.h + fop1.h; /* add hi only */
FR_RSH_K (res, 1); /* shift dp res */
fop2.h = fop2.h >> 1; }
}
else { /* some low 0's */
if (fop2.l != 0) { /* 56b x 56b? */
for (i = 0; i < 32; i++) { /* do low 32b */
if (fop2.l & 1) { FR_ADD (res, fop1); }
FR_RSH_K (res, 1);
fop2.l = fop2.l >> 1; } }
for (i = 0; i < 24; i++) { /* do hi 24b */
if (fop2.h & 1) { FR_ADD (res, fop1); }
FR_RSH_K (res, 1);
fop2.h = fop2.h >> 1; }
}
NormUFP (&res); /* normalize */
if (res.exp < 0) /* underflow? */
return StoreFPX (&res, op, r1); /* early out */
}
return StoreFPR (&res, op, r1, Q_RND (op)); /* store */
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
UnpackFPR (&fop1, op, r1); /* get op1, norm */
if (fop1.h && fop2.h) { /* if both != 0 */
res.sign = fop1.sign ^ fop2.sign; /* sign = diff */
res.exp = fop1.exp + fop2.exp - FP_BIAS; /* exp = sum */
if ((res.exp < 0) || (res.exp > FP_M_EXP)) /* ovf/undf? */
return StoreFPX (&res, op, r1); /* early out */
if ((fop1.l | fop2.l) == 0) { /* 24b x 24b? */
for (i = 0; i < 24; i++) { /* 24 iterations */
if (fop2.h & 1) res.h = res.h + fop1.h; /* add hi only */
FR_RSH_K (res, 1); /* shift dp res */
fop2.h = fop2.h >> 1;
}
}
else { /* some low 0's */
if (fop2.l != 0) { /* 56b x 56b? */
for (i = 0; i < 32; i++) { /* do low 32b */
if (fop2.l & 1) { FR_ADD (res, fop1); }
FR_RSH_K (res, 1);
fop2.l = fop2.l >> 1;
}
}
for (i = 0; i < 24; i++) { /* do hi 24b */
if (fop2.h & 1) { FR_ADD (res, fop1); }
FR_RSH_K (res, 1);
fop2.h = fop2.h >> 1;
}
}
NormUFP (&res); /* normalize */
if (res.exp < 0) /* underflow? */
return StoreFPX (&res, op, r1); /* early out */
}
return StoreFPR (&res, op, r1, Q_RND (op)); /* store */
}
/* Floating point divide - see overflow/underflow notes for multiply */
@@ -332,35 +362,39 @@ struct ufp fop1, fop2;
struct ufp quo = { 0, 0, 0, 0 };
int32 i;
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
UnpackFPR (&fop1, op, r1); /* get op1, norm */
if (fop2.h == 0) return CC_C | CC_V; /* div by zero? */
if (fop1.h) { /* dvd != 0? */
quo.sign = fop1.sign ^ fop2.sign; /* sign = diff */
quo.exp = fop1.exp - fop2.exp + FP_BIAS; /* exp = diff */
if ((quo.exp < 0) || (quo.exp > FP_M_EXP)) /* ovf/undf? */
return StoreFPX (&quo, op, r1); /* early out */
if (!FR_GE (fop1, fop2)) {
FR_LSH_K (fop1, 4); } /* ensure success */
else { /* exp off by 1 */
quo.exp = quo.exp + 1; /* incr exponent */
if (quo.exp > FP_M_EXP) /* overflow? */
return StoreFPX (&quo, op, r1); } /* early out */
for (i = 0; i < (OP_DPFP (op)? 14: 6); i++) { /* 6/14 hex digits */
FR_LSH_K (quo, 4); /* shift quotient */
while (FR_GE (fop1, fop2)) { /* while sub works */
FR_SUB (fop1, fop2); /* decrement */
quo.l = quo.l + 1; } /* add quo bit */
FR_LSH_K (fop1, 4); } /* shift divd */
if (!OP_DPFP (op)) { /* single? */
quo.h = quo.l; /* move quotient */
if (fop1.h >= (fop2.h << 3)) quo.l = FP_ROUND;
else quo.l = 0; }
/* don't need to normalize */
} /* end if fop1.h */
return StoreFPR (&quo, op, r1, Q_RND (op)); /* store result */
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
UnpackFPR (&fop1, op, r1); /* get op1, norm */
if (fop2.h == 0) return CC_C | CC_V; /* div by zero? */
if (fop1.h) { /* dvd != 0? */
quo.sign = fop1.sign ^ fop2.sign; /* sign = diff */
quo.exp = fop1.exp - fop2.exp + FP_BIAS; /* exp = diff */
if ((quo.exp < 0) || (quo.exp > FP_M_EXP)) /* ovf/undf? */
return StoreFPX (&quo, op, r1); /* early out */
if (!FR_GE (fop1, fop2)) {
FR_LSH_K (fop1, 4); /* ensure success */
}
else { /* exp off by 1 */
quo.exp = quo.exp + 1; /* incr exponent */
if (quo.exp > FP_M_EXP) /* overflow? */
return StoreFPX (&quo, op, r1); /* early out */
}
for (i = 0; i < (OP_DPFP (op)? 14: 6); i++) { /* 6/14 hex digits */
FR_LSH_K (quo, 4); /* shift quotient */
while (FR_GE (fop1, fop2)) { /* while sub works */
FR_SUB (fop1, fop2); /* decrement */
quo.l = quo.l + 1; /* add quo bit */
}
FR_LSH_K (fop1, 4); /* shift divd */
}
if (!OP_DPFP (op)) { /* single? */
quo.h = quo.l; /* move quotient */
if (fop1.h >= (fop2.h << 3)) quo.l = FP_ROUND;
else quo.l = 0;
} /* don't need to normalize */
} /* end if fop1.h */
return StoreFPR (&quo, op, r1, Q_RND (op)); /* store result */
}
/* Utility routines */
/* Unpack floating point number */
@@ -369,17 +403,21 @@ void UnpackFPR (struct ufp *fop, uint32 op, uint32 r1)
{
uint32 hi;
if (OP_DPFP (op)) { /* double prec? */
hi = D[r1 >> 1].h; /* get hi */
fop->l = FP_GETFRL (D[r1 >> 1].l); } /* get lo */
else { hi = ReadFReg (r1); /* single prec */
fop->l = 0; } /* lo is zero */
fop->h = FP_GETFRH (hi); /* get hi frac */
if (fop->h || fop->l) { /* non-zero? */
fop->sign = FP_GETSIGN (hi); /* get sign */
fop->exp = FP_GETEXP (hi); /* get exp */
NormUFP (fop); } /* normalize */
else fop->sign = fop->exp = 0; /* clean zero */
if (OP_DPFP (op)) { /* double prec? */
hi = D[r1 >> 1].h; /* get hi */
fop->l = FP_GETFRL (D[r1 >> 1].l); /* get lo */
}
else {
hi = ReadFReg (r1); /* single prec */
fop->l = 0; /* lo is zero */
}
fop->h = FP_GETFRH (hi); /* get hi frac */
if (fop->h || fop->l) { /* non-zero? */
fop->sign = FP_GETSIGN (hi); /* get sign */
fop->exp = FP_GETEXP (hi); /* get exp */
NormUFP (fop); /* normalize */
}
else fop->sign = fop->exp = 0; /* clean zero */
return;
}
@@ -389,22 +427,28 @@ void ReadFP2 (struct ufp *fop, uint32 op, uint32 r2, uint32 ea)
{
uint32 hi;
if (OP_TYPE (op) > OP_RR) { /* mem ref? */
hi = ReadF (ea, VR); /* get hi */
if (OP_DPFP (op)) fop->l = ReadF (ea + 4, VR); /* dp? get lo */
else fop->l = 0; } /* sp, lo = 0 */
else { if (OP_DPFP (op)) { /* RR */
hi = D[r2 >> 1].h; /* dp? get dp reg */
fop->l = D[r2 >> 1].l; }
else {
hi = ReadFReg (r2); /* get sp reg */
fop->l = 0; } }
fop->h = FP_GETFRH (hi); /* get hi frac */
if (fop->h || fop->l) { /* non-zero? */
fop->sign = FP_GETSIGN (hi); /* get sign */
fop->exp = FP_GETEXP (hi); /* get exp */
NormUFP (fop); } /* normalize */
else fop->sign = fop->exp = 0; /* clean zero */
if (OP_TYPE (op) > OP_RR) { /* mem ref? */
hi = ReadF (ea, VR); /* get hi */
if (OP_DPFP (op)) fop->l = ReadF (ea + 4, VR); /* dp? get lo */
else fop->l = 0; /* sp, lo = 0 */
}
else {
if (OP_DPFP (op)) { /* RR */
hi = D[r2 >> 1].h; /* dp? get dp reg */
fop->l = D[r2 >> 1].l;
}
else {
hi = ReadFReg (r2); /* get sp reg */
fop->l = 0;
}
}
fop->h = FP_GETFRH (hi); /* get hi frac */
if (fop->h || fop->l) { /* non-zero? */
fop->sign = FP_GETSIGN (hi); /* get sign */
fop->exp = FP_GETEXP (hi); /* get exp */
NormUFP (fop); /* normalize */
}
else fop->sign = fop->exp = 0; /* clean zero */
return;
}
@@ -412,12 +456,14 @@ return;
void NormUFP (struct ufp *fop)
{
if ((fop->h & FP_M_FRH) || fop->l) { /* any fraction? */
while ((fop->h & FP_NORM) == 0) { /* until norm */
fop->h = (fop->h << 4) | ((fop->l >> 28) & 0xF);
fop->l = fop->l << 4;
fop->exp = fop->exp - 1; } }
else fop->sign = fop->exp = 0; /* clean 0 */
if ((fop->h & FP_M_FRH) || fop->l) { /* any fraction? */
while ((fop->h & FP_NORM) == 0) { /* until norm */
fop->h = (fop->h << 4) | ((fop->l >> 28) & 0xF);
fop->l = fop->l << 4;
fop->exp = fop->exp - 1;
}
}
else fop->sign = fop->exp = 0; /* clean 0 */
return;
}
@@ -427,29 +473,39 @@ uint32 StoreFPR (struct ufp *fop, uint32 op, uint32 r1, uint32 rnd)
{
uint32 hi, cc;
if (rnd && (fop->l & FP_ROUND)) { /* round? */
fop->h = fop->h + 1; /* add 1 to frac */
if (fop->h & FP_CARRY) { /* carry out? */
fop->h = fop->h >> 4; /* renormalize */
fop->exp = fop->exp + 1; } } /* incr exp */
if (fop->h == 0) { /* result 0? */
hi = fop->l = 0; /* store clean 0 */
cc = 0; }
else if (fop->exp < 0) { /* underflow? */
hi = fop->l = 0; /* store clean 0 */
cc = CC_V; }
else if (fop->exp > FP_M_EXP) { /* overflow? */
hi = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF;
fop->l = 0xFFFFFFFF;
cc = (CC_V | ((fop->sign)? CC_L: CC_G)); }
else { hi = ((fop->sign & FP_M_SIGN) << FP_V_SIGN) | /* pack result */
((fop->exp & FP_M_EXP) << FP_V_EXP) |
((fop->h & FP_M_FRH) << FP_V_FRH);
cc = (fop->sign)? CC_L: CC_G; } /* set cc's */
if (OP_DPFP (op)) { /* double precision? */
D[r1 >> 1].h = hi;
D[r1 >> 1].l = fop->l; }
else { WriteFReg (r1, hi); }
if (rnd && (fop->l & FP_ROUND)) { /* round? */
fop->h = fop->h + 1; /* add 1 to frac */
if (fop->h & FP_CARRY) { /* carry out? */
fop->h = fop->h >> 4; /* renormalize */
fop->exp = fop->exp + 1; /* incr exp */
}
}
if (fop->h == 0) { /* result 0? */
hi = fop->l = 0; /* store clean 0 */
cc = 0;
}
else if (fop->exp < 0) { /* underflow? */
hi = fop->l = 0; /* store clean 0 */
cc = CC_V;
}
else if (fop->exp > FP_M_EXP) { /* overflow? */
hi = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF;
fop->l = 0xFFFFFFFF;
cc = (CC_V | ((fop->sign)? CC_L: CC_G));
}
else {
hi = ((fop->sign & FP_M_SIGN) << FP_V_SIGN) | /* pack result */
((fop->exp & FP_M_EXP) << FP_V_EXP) |
((fop->h & FP_M_FRH) << FP_V_FRH);
cc = (fop->sign)? CC_L: CC_G; /* set cc's */
}
if (OP_DPFP (op)) { /* double precision? */
D[r1 >> 1].h = hi;
D[r1 >> 1].l = fop->l;
}
else {
WriteFReg (r1, hi);
}
return cc;
}
@@ -459,13 +515,18 @@ uint32 StoreFPX (struct ufp *fop, uint32 op, uint32 r1)
{
uint32 cc = CC_V;
if (fop->exp < 0) fop->h = fop->l = 0; /* undf? clean 0 */
else { fop->h = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF; /* overflow */
fop->l = 0xFFFFFFFF;
cc = cc | ((fop->sign)? CC_L: CC_G); }
if (OP_DPFP (op)) { /* double precision? */
D[r1 >> 1].h = fop->h;
D[r1 >> 1].l = fop->l; }
else { WriteFReg (r1, fop->h); }
if (fop->exp < 0) fop->h = fop->l = 0; /* undf? clean 0 */
else {
fop->h = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF; /* overflow */
fop->l = 0xFFFFFFFF;
cc = cc | ((fop->sign)? CC_L: CC_G);
}
if (OP_DPFP (op)) { /* double precision? */
D[r1 >> 1].h = fop->h;
D[r1 >> 1].l = fop->l;
}
else {
WriteFReg (r1, fop->h);
}
return cc;
}