-- IeeePack.mesa -- Ieee Floating Point Package for compiler (Ieee + IeeeIOA + IeeeUtil) -- Last Modified by Satterthwaite, May 31, 1982 12:04 pm DIRECTORY Inline: TYPE USING [BITAND, BITOR, BITSHIFT, BITXOR, LongMult, LongNumber], Real: FROM "IeeeFloat" USING [ Exception, ExceptionFlags, Extended, MinusInfinity, MinusZero, Mode, NoExceptions, NumberType, PlusInfinity, PlusZero, TrapNonTrappingNaN, TrapTrappingNaN]; IeeePack: PROGRAM IMPORTS Inline EXPORTS Real = { OPEN Inline, Real; RealException: PUBLIC SIGNAL [flags: ExceptionFlags] = CODE; -- from Ieee.Mesa Details: TYPE = MACHINE DEPENDENT RECORD [ sign: BOOL, sticky: BOOL, blank: [0..7777b], type: Real.NumberType]; Ext: TYPE = RECORD [ det: Details, exp: INTEGER, frac: Inline.LongNumber]; -- constants HiBit: CARDINAL = 100000b; ExponentBias: INTEGER = 127; ExponentMask: INTEGER = 077600b; ExponentShift: INTEGER = 7; HiFractionMask: INTEGER = 177b; FractionShift: INTEGER = 8; LeastSignificandBit: INTEGER = 0400b; HiddenBit: CARDINAL = 100000b; StickyBits: CARDINAL = 77b; HalfLC: LONG CARDINAL = 20000000000b; SignBit: CARDINAL = 100000b; ExpSingleMax: INTEGER = 127; ExpSingleMin: INTEGER = -126; DenormalizedExponent: INTEGER = -127; NaNExponent: INTEGER = 128; BiasAdjust: INTEGER = 192; -- global variables fpmode: Mode = [nm: warning, round: rn]; enableFlags: ExceptionFlags = [invalidOperation: TRUE, divisionByZero: TRUE, overflow: TRUE]; thisTimeExceptions: ExceptionFlags; LN: PROC [r: LONG UNSPECIFIED] RETURNS [LongNumber] = INLINE { RETURN[LOOPHOLE[r, LongNumber]]}; BitOn: PROC [a, b: UNSPECIFIED] RETURNS [BOOL] = INLINE { RETURN[BITAND[a, b]#0]}; Normalized: PROC [g: INTEGER] RETURNS [BOOL] = INLINE { RETURN [BITAND[g, HiddenBit]#0]}; -- Add with Carry ADC3: PROC [a, b, c: CARDINAL] RETURNS [CARDINAL, CARDINAL] = INLINE { s: LongNumber; s.lc ← LONG[a]+LONG[b]+LONG[c]; RETURN[s.highbits, s.lowbits]}; -- from IeeeIOA PowTen: TYPE = RECORD [ f: LONG CARDINAL, e: INTEGER]; TenTable: TYPE = RECORD [ tens: ARRAY [0..13] OF PowTen, t26, t39: PowTen]; posTable: TenTable = [ tens: [ [ 20000000000b, 0], [ 24000000000b, 3], [ 31000000000b, 6], [ 37200000000b, 9], [ 23420000000b, 13], [ 30324000000b, 16], [ 36411000000b, 19], [ 23045500000b, 23], [ 27657020000b, 26], [ 35632624000b, 29], [ 22500574400b, 33], [ 27220733500b, 36], [ 35065122420b, 39], [ 22141163452b, 43]], t26: [24533722672b, 86], t39: [27405037645b, 129]]; negTable: TenTable = [ tens: [ [ 20000000000b, 0], [ 31463146315b, -4], [ 24365605075b, -7], [ 20304467230b, -10], [ 32155613531b, -14], [ 24761326107b, -17], [ 20615736406b, -20], [ 32657712326b, -24], [ 25363073422b, -27], [ 21134057501b, -30], [ 33371577317b, -34], [ 25772777414b, -37], [ 21457146011b, -40], [ 34113411502b, -44]], t26: [30604403045b, -87], t39: [25616276613b, -130]]; MulExtended: PROC [x, y: Ext] RETURNS [z: Ext] = { hi, lo: LongNumber; z.exp ← x.exp+y.exp+1; z.det.sign ← x.det.sign#y.det.sign; z.det.type ← normal; z.det.sticky ← x.det.sticky OR y.det.sticky; [hi, lo] ← Mul32[x.frac, y.frac]; -- normalize 64 WHILE NOT BitOn[hi.highbits, HiBit] DO hi.lc ← hi.lc+hi.lc; IF BitOn[lo.highbits, HiBit] THEN hi.lowbits ← BITOR[hi.lowbits, 1]; lo.lc ← lo.lc+lo.lc; z.exp ← z.exp-1; ENDLOOP; z.frac ← hi; -- Round to 32 bits. IF lo.lc>HalfLC OR (lo.lc=HalfLC AND BitOn[z.frac.lowbits, 1]) THEN { -- Overflow z.frac.lc ← z.frac.lc+1; IF z.frac.lc<hi.lc THEN { z.frac.lc ← RShift1in1[z.frac.lc]; z.exp ← z.exp+1}; }; IF lo.lc#0 THEN z.det.sticky ← TRUE}; Scale: PROC [x: Ext, exp10: INTEGER] RETURNS [y: Ext] = { table: TenTable; mul: PowTen; big: BOOL; IF exp10=0 THEN RETURN [x]; big ← exp10<0; table ← IF big THEN negTable ELSE posTable; exp10 ← ABS[exp10]; SELECT exp10 FROM IN [1..13] => mul ← table.tens[exp10]; IN (13..26) => { x ← MulExtended[x, CVExt[table.tens[13]]]; mul ← table.tens[exp10-13]}; =26 => mul ← table.t26; IN (26..39) => { x ← MulExtended[x, CVExt[table.t26]]; mul ← table.tens[exp10-26]}; =39 => mul ← table.t39; IN (39..52] => { x ← MulExtended[x, CVExt[table.t39]]; mul ← table.tens[exp10-39]}; ENDCASE => { WHILE exp10>52 DO x ← MulExtended[x, CVExt[table.t39]]; exp10 ← exp10-39; ENDLOOP; RETURN[Scale[x, IF big THEN -exp10 ELSE exp10]]}; y ← CVExt[mul]; y ← MulExtended[x, y]}; CVExt: PROC [t: PowTen] RETURNS [y: Ext] = { y.det.sticky ← y.det.sign ← FALSE; y.det.type ← normal; y.frac.lc ← t.f; y.exp ← t.e}; PairToReal: PUBLIC PROC [fr: LONG INTEGER, exp10: INTEGER] RETURNS [REAL] = { y: Ext; -- or: RoundingMode ← fpmode.round; -- fpmode.round ← rn; thisTimeExceptions ← NoExceptions; IF fr=0 THEN RETURN[PlusZero]; y.exp ← 31; y.det.sign ← fr<0; y.det.sticky ← FALSE; y.det.type ← normal; y.frac.li ← IF y.det.sign THEN -fr ELSE fr; PostNormalize[@y]; y ← Scale[y, exp10]; StepTwo[@y]; -- fpmode.round ← or; RETURN[Pack[@y]]}; -- from IeeeFloatA (adapted) RealToExtended: PUBLIC PROC [a: REAL] RETURNS [Real.Extended] = { ext: Ext = Unpack[a]; RETURN [[type: ext.det.type, sign: ext.det.sign, exp: ext.exp, frac: ext.frac.lc]]}; ExtendedToReal: PUBLIC PROC [e: Real.Extended] RETURNS [REAL] = { ext: Ext ← [ det: [sign: e.sign, sticky: FALSE, blank: 0, type: e.type], exp: e.exp, frac: [lc[e.frac]]]; RETURN [Pack[@ext]]}; Negate: PUBLIC PROC [a: REAL] RETURNS [REAL] = { IF LN[a] = LN[PlusZero] THEN RETURN [PlusZero]; -- Negate a LOOPHOLE[a, LongNumber].highbits ← BITXOR[LN[a].highbits, SignBit]; RETURN [a]}; Abs: PUBLIC PROC [a: REAL] RETURNS [REAL] = { RETURN [IF BitOn[LN[a].highbits, SignBit] THEN Negate[a] ELSE a]}; -- from IEEEUtil SetInexactResult: PROC = { thisTimeExceptions[inexactResult] ← TRUE}; SetInvalidOperation: PROC = { thisTimeExceptions[invalidOperation] ← TRUE}; SetUnderflow: PROC [z: POINTER TO Ext] = { thisTimeExceptions[underflow] ← TRUE}; SetOverflow: PROC [z: POINTER TO Ext] = { thisTimeExceptions[overflow] ← TRUE}; -- Separate the packed REAL into its component elements Unpack: PUBLIC PROC [r: REAL] RETURNS [z: Ext] = { z.det.sticky ← FALSE; z.det.sign ← BitOn[LN[r].highbits, HiBit]; -- first r.j. the exponent z.exp ← Inline.BITSHIFT[ Inline.BITAND[LN[r].highbits, ExponentMask], -ExponentShift]; z.exp ← z.exp - ExponentBias; z.det.type ← normal; z.frac.li ← LN[r].li; z.frac.highbits ← Inline.BITAND[HiFractionMask, z.frac.highbits]; SELECT z.exp FROM = DenormalizedExponent => { -- denormalized or zero IF z.frac.li = 0 THEN z.det.type ← zero ELSE { z.exp ← ExpSingleMin; z.frac.li ← LongShift[z.frac.li, FractionShift]; IF fpmode.nm = normalizing THEN PostNormalize[@z]}; }; = NaNExponent => { -- infinity or nan IF z.frac.li = 0 THEN z.det.type ← infinity ELSE { z.det.type ← nan; IF z.frac.lc = Real.TrapTrappingNaN THEN SetInvalidOperation[]}; }; ENDCASE => { z.frac.li ← LongShift[z.frac.li, FractionShift]; z.frac.highbits ← Inline.BITOR[HiddenBit, z.frac.highbits]}; }; -- Stuff the components back into the packed REAL. Pack: PROC [z: POINTER TO Ext] RETURNS [r: REAL] = { trap: BOOL ← FALSE; i: Exception; IF thisTimeExceptions#NoExceptions THEN { -- Possible typo in standard here!!! IF thisTimeExceptions[invalidOperation] THEN { z.det.type ← nan; IF z.frac.lc=0 THEN z.frac.lc ← TrapNonTrappingNaN}; FOR i IN Exception DO trap ← trap OR (enableFlags[i] AND thisTimeExceptions[i]); ENDLOOP ; IF trap THEN SIGNAL RealException[flags: thisTimeExceptions]; FixupProcedure[z]}; RETURN[UsualPack[z↑]]}; UsualPack: PROC [z: Ext] RETURNS [REAL] = { SELECT z.det.type FROM zero => RETURN [IF z.det.sign THEN MinusZero ELSE PlusZero]; infinity => RETURN [IF z.det.sign THEN MinusInfinity ELSE PlusInfinity]; nan => z.exp ← NaNExponent; ENDCASE => z.frac.li ← LongShift[z.frac.li, -FractionShift]; -- clear hidden bit z.frac.highbits ← BITAND[z.frac.highbits, HiFractionMask]; IF z.exp NOT IN [-127..128] THEN ERROR; z.exp ← BITSHIFT[z.exp+ExponentBias, ExponentShift]; z.frac.highbits ← BITOR[z.frac.highbits, z.exp]; IF z.det.sign THEN z.frac.highbits ← BITOR[z.frac.highbits, SignBit]; RETURN [LOOPHOLE[z.frac.li, REAL]]}; FixupProcedure: PROC [vp: POINTER TO Ext] = { IF thisTimeExceptions[underflow] THEN { DeNormalize[vp, vp.exp-ExpSingleMin]; vp.exp ← DenormalizedExponent}; IF thisTimeExceptions[overflow] THEN vp.det.type ← infinity; }; Round: PROC [z: POINTER TO Ext] = { temp: LONG CARDINAL; -- A 32 bit extended is considered to have its hidden bit as bit 0, significand as the next 29 bits, then G, then R, then S as a separate boolean. GRS computs the 3 bit number formed by the concatenation of G, R, and IF S THEN 1 ELSE 0. GRS: PROC [g: INTEGER] RETURNS [INTEGER] = { -- StickyBits are the set used for rounding to 24 bits s: BOOL ← BitOn[g, StickyBits] OR z.det.sticky; -- Should flush these constants g ← BITSHIFT[BITAND[g, 300b], -5]; IF s THEN g ← g+1; RETURN[g]}; -- The fraction should be normalized here! grs: INTEGER ← GRS[z.frac.lowbits]; IF grs=0 THEN RETURN; SetInexactResult[]; BEGIN SELECT fpmode.round FROM rn => { IF z.det.sign THEN grs ← 8-grs; IF grs>4 OR (grs=4 AND BitOn[z.frac.lowbits, LeastSignificandBit]) THEN GOTO Plus1; }; rz => NULL; rm => IF z.det.sign THEN GOTO Plus1; rp => IF NOT z.det.sign THEN GOTO Plus1; ENDCASE => ERROR; EXITS Plus1 => { temp ← z.frac.lc; z.frac.lc ← z.frac.lc+LeastSignificandBit; IF z.frac.lc<=temp THEN { -- better overflow detect! z.frac.li ← RShift1in1[z.frac.li]; z.exp ← z.exp+1}; }; END}; RShift1in1: PROC [z: LONG UNSPECIFIED] RETURNS [LONG UNSPECIFIED] = { vl: LongNumber; vl.lc ← z; vl.lowbits ← BITSHIFT[vl.lowbits, -1]; IF BitOn[vl.highbits, 1] THEN vl.lowbits ← BITOR[vl.lowbits, HiBit]; vl.highbits ← BITOR[HiddenBit, BITSHIFT[vl.highbits, -1]]; RETURN [vl.lc]}; LShift: PROC [z: LONG UNSPECIFIED] RETURNS [LONG UNSPECIFIED] = { vl: LongNumber; vl.lc ← z; vl.highbits ← BITSHIFT[vl.highbits, 1]; IF BitOn[vl.lowbits, HiBit] THEN vl.highbits ← BITOR[vl.highbits, 1]; vl.lowbits ← BITSHIFT[vl.lowbits, 1]; RETURN [vl.lc]}; StepTwo: PROC [z: POINTER TO Ext] = { IF z.det.type#normal THEN RETURN; IF z.exp<=ExpSingleMin THEN { IF z.exp<ExpSingleMin OR (NOT Normalized[z.frac.highbits]) THEN SetUnderflow[z]}; Round[z]; IF (NOT Normalized[z.frac.highbits]) AND z.exp#DenormalizedExponent AND (NOT thisTimeExceptions[underflow]) THEN SetInvalidOperation[] ELSE IF z.exp>ExpSingleMax THEN SetOverflow[z]}; Mul32: PROC [x, y: LongNumber] RETURNS [LongNumber, LongNumber] = { hi, lo, t1, t2: LongNumber; cy: CARDINAL; lo.lc ← LongMult[x.lowbits, y.lowbits]; hi.lc ← LongMult[x.highbits, y.highbits]; t1.lc ← LongMult[x.highbits, y.lowbits]; t2.lc ← LongMult[x.lowbits, y.highbits]; [cy, lo.highbits] ← ADC3[lo.highbits, t1.lowbits, t2.lowbits]; hi.lc ← hi.lc+t1.highbits+t2.highbits+cy; RETURN [hi, lo]}; -- Post Normalize. S does not participate PostNormalize: PROC [z: POINTER TO Ext] = { IF z.frac.lc=0 THEN ERROR; WHILE BITAND[z.frac.highbits, HiddenBit]=0 DO z.frac.lc ← LShift[z.frac.lc]; z.exp ← z.exp-1; ENDLOOP; }; -- positive count is left shift, negative is right shift LongShift: PROC [z: LONG UNSPECIFIED, count: INTEGER] RETURNS [LONG UNSPECIFIED] = { xl, vl: LongNumber; vl.lc ← z; SELECT count FROM NOT IN (-32..32) => RETURN [0]; 0 => RETURN [vl.lc]; IN [16..32) => { xl.highbits ← BITSHIFT[vl.lowbits,count-16]; xl.lowbits ← 0}; IN (0..16) => { xl.highbits ← BITSHIFT[vl.highbits, count] + BITSHIFT[vl.lowbits,count-16]; xl.lowbits ← BITSHIFT[vl.lowbits, count]}; IN (-16..0) => { xl.highbits ← BITSHIFT[vl.highbits, count]; xl.lowbits ← BITSHIFT[vl.lowbits, count] + BITSHIFT[vl.highbits,count+16]}; IN (-32..-16] => { xl.highbits ← 0; xl.lowbits ← BITSHIFT[vl.highbits,count+16]}; ENDCASE => ERROR; RETURN[xl.lc]}; -- DeNormalize is much like LongShift, except that it maintains the sticky bits on the right. And it only shifts right. DeNormalize: PROC [z: POINTER TO Ext, count: INTEGER] = { sMask: ARRAY [1..16) OF CARDINAL = [ 1b, 3b, 7b, 17b, 37b, 77b, 177b, 377b, 777b, 1777b, 3777b, 7777b, 17777b, 37777b, 77777b]; -- Mask off everything but the bits contributing to S, then set or clear S in the result. IF count>0 THEN ERROR; IF count=0 THEN RETURN; count ← -count; z.det.sticky ← SELECT count FROM =16 => z.frac.lowbits#0, IN [1..16) => BitOn[z.frac.lowbits, sMask[count]], IN (16..32) => z.frac.lowbits#0 OR BitOn[z.frac.highbits, sMask[count-16]], ENDCASE => z.frac.lc#0; z.frac.lc ← LongShift[z.frac.lc, -count]}; }.