DIRECTORY Basics, BitOps, Dragon, DragonFP, IO; DragonFPImpl: CEDAR PROGRAM IMPORTS Basics, BitOps, Dragon, IO EXPORTS DragonFP = BEGIN OPEN DragonFP; SetMode: PUBLIC PROC[mode: Mode, function: Function] RETURNS[Mode] = { word: BitOps.BitWord _ LOOPHOLE[mode]; word _ BitOps.ICIW[function MOD 16, word,16, ((function MOD 64)/16)*4, 4]; RETURN[ LOOPHOLE[word]] }; ALU: PUBLIC PROC [aHDW, bHDW: HexDblWord, func: Function, mode: Mode] RETURNS [cHDW: HexDblWord, status: Dragon.PBusFaults] = { resDbl: BOOL _ func MOD 2 = 1; Dragon.Assert[mode.required = requiredMode]; func _ func MOD 64; SELECT func/2 FROM IN [0..24) => { aFP,bFP:FP; aFP _ HDWtoFP[aHDW]; bFP _ HDWtoFP[bHDW]; IF (func MOD 8) IN [6..7] THEN { IF (func/8) MOD 2 =1 THEN aFP.exp _ aFP.exp - WrapBias[aFP]; IF (func/16) MOD 2 =1 THEN bFP.exp _ bFP.exp - WrapBias[bFP]; [cHDW, status] _ FDiv[aFP, bFP, resDbl, mode]} ELSE { IF (func MOD 16) >7 THEN bFP _ HDWtoFP[[0,0,FALSE]]; IF (func MOD 8)/2=2 THEN aFP.sign _ bFP.sign _ FALSE; IF func/2 = 4 THEN aFP.sign _ NOT aFP.sign; IF func < 6 THEN bFP.sign _ NOT bFP.sign; IF func <32 THEN [cHDW, status] _ FAdd[aFP, bFP, resDbl, mode] ELSE [cHDW, status] _ FCmp[aFP, bFP, resDbl, mode]} }; 24 => [cHDW, status] _ UtoD [aHDW, mode, TRUE]; 25 => [cHDW, status] _ DtoW [aHDW, mode]; 26 => [cHDW, status] _ UtoD [aHDW, mode, FALSE]; 28 => [cHDW, status] _ FtoI [aHDW, mode]; 29 => [cHDW, status] _ ItoF [aHDW, mode, resDbl]; 30 => [cHDW, status] _ FtoF [aHDW, mode, resDbl]; ENDCASE => Dragon.Assert[FALSE, "Strange FP Function"]; RETURN[cHDW, status]}; MUL: PUBLIC PROC [aHDW,bHDW: HexDblWord, function: Function, mode: Mode] RETURNS [cHDW: HexDblWord, status: Dragon.PBusFaults] = { acc: ARRAY[0..8) OF CARDINAL _ ALL[0]; resDbl: BOOL _ (function MOD 2)/1 = 1; aWraped: BOOL _ (function MOD 4)/2 = 1; bWraped: BOOL _ (function MOD 8)/4 = 1; aMagnitude: BOOL _ (function MOD 16)/8 = 1; bMagnitude: BOOL _ (function MOD 32)/16 = 1; compResult: BOOL _ (function MOD 64)/32 = 1; a: FP _ HDWtoFP[aHDW]; b: FP _ HDWtoFP[bHDW]; Dragon.Assert[mode.required = requiredMode]; IF (function MOD 8)/2 = 2 THEN a.sign _ b.sign _ FALSE; IF (function MOD 64)/2 = 4 THEN a.sign _ TRUE; IF (function MOD 64) >=32 THEN b.sign _ NOT b.sign; IF compResult THEN a.sign _ NOT a.sign; IF a.type = nan AND b.type = nan THEN RETURN[FPtoHDW[a], FPabNaN]; IF a.type = nan THEN RETURN[FPtoHDW[a], FPaNaN]; IF b.type = nan THEN RETURN[FPtoHDW[b], FPaNaN]; IF a.double AND NOT resDbl THEN RETURN[FPtoHDW[a], FPinvalid]; IF b.double AND NOT resDbl THEN RETURN[FPtoHDW[b], FPinvalid]; IF a.exp 100000B THEN acc[i] _ acc[i] + 1; ENDLOOP; acc[7] _ acc[7]*2 ENDLOOP; FOR i:CARDINAL IN [0..3] DO a.m[i] _ acc[i] ENDLOOP; FOR i:CARDINAL DECREASING IN [4..7] WHILE (a.m[3] MOD 2) = 0 DO IF acc[i]#0 THEN a.m[3] _ a.m[3] +1 ENDLOOP; status _ RoundMult[a, mode]; RETURN [FPtoHDW[a], status] }; PutHexFP: PUBLIC PROC[st:IO.STREAM, hdw: HexDblWord] = { fp: FP _ HDWtoFP[hdw]; hexChar: ARRAY [0..16) OF CHARACTER _ ['0,'1,'2,'3,'4,'5,'6,'7,'8,'9,'A,'B,'C,'D,'E,'F]; charVal: ARRAY [0..16) OF CHARACTER _ ALL['0]; nonZeroCnt: CARDINAL _ 0; val, cy: CARDINAL _ 0; SELECT fp.type FROM zero => {IO.PutF[st, IF fp.sign THEN "-0.0" ELSE "+0.0"]; RETURN}; inf => {IO.PutF[st, IF fp.sign THEN "-INF" ELSE "+INF"]; RETURN}; nan => {IO.PutF[st, "NaN"]; RETURN}; ENDCASE; FOR i:CARDINAL DECREASING IN [0..4) DO val _ (fp.m[i] MOD 100000B)*2 + cy; cy _ fp.m[i] / 100000B; FOR j:CARDINAL DECREASING IN [0..4) DO charVal[i*4+j] _ hexChar[val MOD 16]; val _ val / 16; IF charVal[i*4+j] = '0 AND nonZeroCnt=0 THEN LOOP; nonZeroCnt _ nonZeroCnt+1; ENDLOOP; ENDLOOP; IF fp.sign THEN IO.PutF[st, "-" ]; IO.PutF[st, "1." ]; FOR i:CARDINAL IN [0..MAX[1, nonZeroCnt]) DO st.PutChar[charVal[i]] ENDLOOP; IF fp.exp # FPExpBias THEN IF fp.exp>FPExpBias THEN {IO.PutF[st, "e"]; val _ fp.exp-FPExpBias} ELSE {IO.PutF[st, "e-"]; val _ FPExpBias-fp.exp}; nonZeroCnt _ 0; FOR div:CARDINAL _10000B, div/16 WHILE div#0 DO IF (val/div) = 0 AND nonZeroCnt=0 THEN LOOP; st.PutChar[hexChar[val/div]]; nonZeroCnt _ nonZeroCnt+1; val _ val MOD div; ENDLOOP}; FP: TYPE = REF FPRec; FPType: TYPE = {norm, zero, den, inf, nan}; FPExpBias: CARDINAL = 16383; FPRec: TYPE = RECORD [ double: BOOL _ FALSE, type: FPType _ norm, sign: BOOL _ FALSE, exp: CARDINAL _ 0, m: ARRAY[0..4) OF CARDINAL _ ALL[0]]; FDiv: PROC [rem,dvsr: FP, dblRes:BOOL, mode:Mode] RETURNS [c:HexDblWord, status:Dragon.PBusFaults] = { FPComp: PROC[x, y: FP] RETURNS[comp: {gr,ls,eq}] = { comp _ eq; FOR i: CARDINAL IN [0..4) DO IF x.m[i] = y.m[i] THEN LOOP; RETURN[IF x.m[i]>y.m[i] THEN gr ELSE ls] ENDLOOP }; q: FP _ HDWtoFP[[0,0,NOT dblRes]]; IF rem.type=nan AND dvsr.type=nan THEN RETURN[FPtoHDW[rem], FPabNaN]; IF rem.type=nan THEN RETURN[FPtoHDW[rem], FPaNaN]; IF dvsr.type=nan THEN RETURN[FPtoHDW[dvsr], FPbNaN]; IF rem.double AND NOT dblRes THEN RETURN[FPtoHDW[rem], FPinvalid]; IF dvsr.double AND NOT dblRes THEN RETURN[FPtoHDW[dvsr], FPinvalid]; IF dvsr.type=zero THEN RETURN[FPtoHDW[dvsr], FPdivByZero]; rem.double _ dvsr.double _ dblRes; rem.sign _ dvsr.sign _ rem.sign#dvsr.sign; IF rem.type=zero THEN RETURN[FPtoHDW[rem], FPeqZeroE]; IF rem.type=inf AND dvsr.type=inf THEN {SetToNaN[rem]; RETURN[FPtoHDW[rem], FPinvalid]}; IF rem.type=inf THEN RETURN[FPtoHDW[rem], FPlsInfE] ; IF dvsr.type=inf THEN {SetToZero[dvsr]; RETURN[FPtoHDW[dvsr], FPeqZeroE]}; q.sign _ rem.sign; rem.sign _ FALSE; dvsr.sign _ TRUE; q.exp _ FPExpBias + 60 + rem.exp - dvsr.exp; dvsr.exp _ rem.exp; FOR i: CARDINAL IN [1..60] DO ShiftLt[q]; SELECT FPComp[rem, dvsr] FROM gr, eq => { cy: CARDINAL _ 1; [cy, rem.m[3]] _ ADC3[rem.m[3], Basics.BITNOT[dvsr.m[3]], cy]; [cy, rem.m[2]] _ ADC3[rem.m[2], Basics.BITNOT[dvsr.m[2]], cy]; [cy, rem.m[1]] _ ADC3[rem.m[1], Basics.BITNOT[dvsr.m[1]], cy]; [cy, rem.m[0]] _ ADC3[rem.m[0], Basics.BITNOT[dvsr.m[0]], cy]; IF SignificantBitsZero[rem] THEN SetToZero[rem] ELSE Normalize[rem]; q.m[3] _ q.m[3] + 1}; ENDCASE; dvsr.exp _ dvsr.exp - 1 ENDLOOP; Normalize[q]; status _ RoundFP[q, mode.rnd]; RETURN [ FPtoHDW[q], status ] }; FAdd: PROC [a, b: FP, dblRes: BOOL, mode: Mode] RETURNS [c: HexDblWord, status: Dragon.PBusFaults] = { FPComp: PROC[x, y: FP] RETURNS[r: {gr,ls,eq}] = { r _ eq; FOR i:CARDINAL IN [0..4) DO IF x.m[i] = y.m[i] THEN LOOP; RETURN[IF x.m[i]>y.m[i] THEN gr ELSE ls] ENDLOOP }; IF a.type=nan AND b.type=nan THEN RETURN[FPtoHDW[a], FPabNaN]; IF a.type=nan THEN RETURN[FPtoHDW[a], FPaNaN]; IF b.type=nan THEN RETURN[FPtoHDW[b], FPbNaN]; IF a.double AND NOT dblRes THEN RETURN[FPtoHDW[a], FPinvalid]; IF b.double AND NOT dblRes THEN RETURN[FPtoHDW[b], FPinvalid]; a.double _ dblRes; b.double _ dblRes; IF a.type=inf AND b.type=inf THEN IF a.sign = b.sign THEN {a.double _ dblRes; RETURN[FPtoHDW[a], FPlsInfE]} ELSE {SetToNaN[a]; RETURN[FPtoHDW[a], FPinvalid]}; IF a.type=inf THEN RETURN[FPtoHDW[a], FPlsInfE]; IF b.type=inf THEN RETURN[FPtoHDW[b], FPlsInfE]; IF a.type=zero AND b.type=zero THEN { IF a.sign#b.sign THEN a.sign _ (mode.rnd=rm); RETURN[FPtoHDW[a], FPeqZeroE]}; IF a.type=zero THEN RETURN[FPtoHDW[b], FPgrNEZeroE]; IF b.type=zero THEN RETURN[FPtoHDW[a], FPgrNEZeroE]; IF a.exp >= b.exp THEN DeNormalize[b, a.exp - b.exp] ELSE {DeNormalize[a, b.exp - a.exp]; a.exp _ b.exp}; IF a.sign = b.sign THEN { cy:CARDINAL _ 0; [cy, a.m[3]] _ ADC3[a.m[3], b.m[3], cy]; [cy, a.m[2]] _ ADC3[a.m[2], b.m[2], cy]; [cy, a.m[1]] _ ADC3[a.m[1], b.m[1], cy]; [cy, a.m[0]] _ ADC3[a.m[0], b.m[0], cy]; IF cy # 0 THEN {DeNormalize[a,1]; a.m[0] _ a.m[0]+ 100000B} } ELSE { cy:CARDINAL _ 1; IF FPComp[a,b]=ls THEN {c:FP _ a; a _ b; b _ c; a.exp _ b.exp}; [cy, a.m[3]] _ ADC3[a.m[3], Basics.BITNOT[b.m[3]], cy]; [cy, a.m[2]] _ ADC3[a.m[2], Basics.BITNOT[b.m[2]], cy]; [cy, a.m[1]] _ ADC3[a.m[1], Basics.BITNOT[b.m[1]], cy]; [cy, a.m[0]] _ ADC3[a.m[0], Basics.BITNOT[b.m[0]], cy]; IF SignificantBitsZero[a] THEN {a.sign_mode.rnd=rm; SetToZero[a]} ELSE Normalize[a]}; status _ RoundFP[a, mode.rnd]; RETURN [ FPtoHDW[a], status ] }; FCmp: PROC [a, b: FP, dblRes: BOOL, mode: Mode] RETURNS[c: HexDblWord, status: Dragon.PBusFaults] = { status _ SELECT TRUE FROM a.double AND NOT dblRes => FPinvalid, b.double AND NOT dblRes => FPinvalid, a.type=nan OR b.type=nan => FPinvalid, a.type=inf AND b.type=inf => (IF a.sign=b.sign THEN FPeqZeroE ELSE (IF a.sign THEN FPlsInfE ELSE FPgrNEZeroE)), a.type=zero AND b.type=zero => FPeqZeroE, a.type=zero OR b.type=inf => IF b.sign THEN FPgrNEZeroE ELSE FPlsInfE, b.type=zero OR a.type=inf => IF a.sign THEN FPlsInfE ELSE FPgrNEZeroE, a.sign#b.sign => IF a.sign THEN FPlsInfE ELSE FPgrNEZeroE, ENDCASE => FPres4; IF status # FPres4 THEN RETURN[[0, 0, NOT dblRes], status]; a.double _ b.double _ dblRes; IF a.exp#b.exp THEN RETURN[[0, 0, NOT dblRes], (IF ((a.exp>b.exp)=a.sign) THEN FPlsInfE ELSE FPgrNEZeroE)]; FOR i:CARDINAL IN [0..3] DO IF a.m[i]=b.m[i] THEN LOOP; RETURN[[0, 0, NOT dblRes], (IF ((a.m[i]>b.m[i])=a.sign) THEN FPlsInfE ELSE FPgrNEZeroE)]; ENDLOOP; RETURN[[0, 0, NOT dblRes], FPeqZeroE] }; UtoD: PROC [a: HexDblWord, mode: Mode, exact: BOOL] RETURNS [c: HexDblWord, status: Dragon.PBusFaults] = { fp: FP _ HDWtoFP[a]; IF fp.type#norm THEN {Dragon.Assert[FALSE, "Undefined"]; RETURN[[0, 0, a.single], FPinvalid]}; fp.exp _ fp.exp - WrapBias[fp]; IF fp.exp >= MinExp[fp] THEN {Dragon.Assert[FALSE, "Undefined"]; RETURN[[0, 0, a.single], FPinvalid]}; status _ RoundFP[fp, mode.rnd]; RETURN[FPtoHDW[fp], status] }; DtoW: PROC [a: HexDblWord, mode: Mode] RETURNS [c: HexDblWord, status: Dragon.PBusFaults] = { fp: FP _ HDWtoFP[a]; IF fp.type#den THEN {Dragon.Assert[FALSE, "Undefined"]; RETURN[[0, 0, a.single], FPinvalid]}; fp.exp _ fp.exp + WrapBias[fp]; status _ RoundFP[fp, mode.rnd]; RETURN[FPtoHDW[fp], status] }; FtoI: PROC [a: HexDblWord, mode: Mode] -- Always returns I32 RETURNS [c: HexDblWord, status: Dragon.PBusFaults] = { minInt: HexDblWord = [20000000000B, 0, FALSE]; maxInt: HexDblWord = [17777777777B, 0, FALSE]; long: Basics.LongNumber; fp: FP _ HDWtoFP[a]; rnd: FPRndMode _ IF mode.fixRZ THEN rz ELSE mode.rnd; exact: BOOL; SELECT fp.type FROM zero => RETURN[ [0, 0, FALSE], FPeqZeroE]; nan, inf => IF fp.sign THEN RETURN[minInt, FPoFlowI] ELSE RETURN[maxInt, FPoFlowI]; ENDCASE => { }; DeNormalize[fp, FPExpBias+64-3-fp.exp]; -- rs on right exact _ Fix[fp, rnd]; fp.m[3] _ Basics.BITAND[fp.m[3], 177774B]; -- Clear RS ShiftRt[fp, 2]; IF exact THEN status_FPgrNEZeroE ELSE status_FPneZeroI; IF fp.m[0]#0 OR fp.m[1]#0 OR fp.m[2]>=100000B THEN IF fp.sign THEN RETURN[ minInt, FPoFlowI] ELSE RETURN[ maxInt, FPoFlowI]; IF fp.m[2]=0 AND fp.m[3]=0 THEN RETURN[ [0, 0, FALSE], (IF exact THEN FPeqZeroE ELSE FPuFlowI)]; long.highbits _ fp.m[2]; long.lowbits _ fp.m[3]; IF fp.sign THEN long.li _ -long.li; RETURN[[long.lc, 0, FALSE], status] }; ItoF: PROC [a: HexDblWord, mode: Mode, resDbl: BOOL] RETURNS [c: HexDblWord, status: Dragon.PBusFaults] = { long: Basics.LongNumber; fp: FP _ NEW[FPRec _ []]; long.lc _ a.h; IF long.lc = 0 THEN RETURN[ [0,0,NOT resDbl], FPeqZeroE]; fp.sign _ long.li < 0; IF fp.sign THEN long.li _ -long.li; fp.m[1] _ long.lowbits; fp.m[0] _ long.highbits; fp.exp _ FPExpBias + 31; fp.double _ resDbl; Normalize[fp]; status _ RoundFP[fp, mode.rnd]; RETURN[FPtoHDW[fp], status] }; FtoF: PROC [a: HexDblWord, mode: Mode, resDbl: BOOL] RETURNS [c: HexDblWord, status: Dragon.PBusFaults] = { fp: FP _ HDWtoFP[a]; fp.double _ resDbl; status _ RoundFP[fp, mode.rnd]; RETURN[FPtoHDW[fp], status] }; HDWtoFP: PROC[hdw: HexDblWord] RETURNS[fp: FP] = { lo: BitOps.BitDWord _ Dragon.LTD[hdw.l]; hi: BitOps.BitDWord _ Dragon.LTD[hdw.h]; bitsZero: BOOL; fp _ NEW[FPRec _ []]; fp.double _ NOT hdw.single; IF fp.double THEN { fp.sign _ BitOps.EBFD[hi, 32, 0]; fp.exp _ BitOps.ECFD[hi, 32, 1, 11] + MinExp[fp] -1; fp.m[0] _ BitOps.ECFD[hi, 32, 12, 16]; fp.m[1] _ BitOps.ECFD[hi, 32, 28, 4]*4096 + BitOps.ECFD[lo, 32, 0, 12]; fp.m[2] _ BitOps.ECFD[lo, 32, 12, 16]; fp.m[3] _ BitOps.ECFD[lo, 32, 28, 4]*4096 } ELSE { fp.sign _ BitOps.EBFD[hi, 32, 0]; fp.exp _ BitOps.ECFD[hi, 32, 1, 8] + MinExp[fp]-1; fp.m[0] _ BitOps.ECFD[hi, 32, 9, 16]; fp.m[1] _ BitOps.ECFD[hi, 32, 25, 7]*512 }; bitsZero _ TRUE; FOR i:CARDINAL IN [0..3] DO IF fp.m[i]#0 THEN bitsZero _ FALSE ENDLOOP; SELECT TRUE FROM fp.exp > MaxExp[fp] AND bitsZero => {fp.type _ inf; fp.exp _ 32585}; fp.exp > MaxExp[fp] AND NOT bitsZero => {fp.type _ nan; fp.exp _ 32585}; fp.exp < MinExp[fp] AND bitsZero => {fp.type _ zero; fp.exp _ 0}; fp.exp < MinExp[fp] AND NOT bitsZero => {fp.type _ den; Normalize[fp]}; ENDCASE => { fp.type _ norm; DeNormalize[fp, 1]; fp.exp _ fp.exp-1; fp.m[0] _ fp.m[0]+100000B} }; FPtoHDW: PROC[fp: FP] RETURNS[hdw: HexDblWord] = { DblShiftLt: PROC[a, b, n: CARDINAL] RETURNS[CARDINAL] = { THROUGH (0..n] DO a _ a*2 + b/32768; b _ b*2 ENDLOOP; RETURN[a]}; exp: CARDINAL; eSize: CARDINAL _ IF fp.double THEN 11 ELSE 8; lo, hi: BitOps.BitDWord _ [0,0]; IF fp.exp IN (0..MinExp[fp]) THEN { -- denormalized, assume already rounded fp.type _ den; DeNormalize[fp, MinExp[fp]-1-fp.exp]}; SELECT fp.type FROM nan, inf => exp _ MaxExp[fp]+1-FPExpBias; zero, den => exp _ 0; ENDCASE => { -- type=norm, hide msb which should be 1 IF fp.m[0]<100000B THEN ERROR; ShiftLt[fp]; fp.exp _ fp.exp+1; -- undo decrement of exp exp _ fp.exp-(MinExp[fp]-1) }; IF fp.type=zero OR fp.type=inf THEN fp.m _ ALL[0]; IF fp.type=nan THEN fp.m _ ALL[177777B]; hi _ BitOps.IBID[fp.sign, hi, 32, 0]; hi _ BitOps.ICID[exp, hi, 32, 1, eSize]; hi _ BitOps.ICID[DblShiftLt[0, fp.m[0], 15-eSize], hi, 32, eSize+1, 15-eSize]; hi _ BitOps.ICID[DblShiftLt[fp.m[0], fp.m[1], 15-eSize], hi, 32, 16, 16]; lo _ BitOps.ICID[DblShiftLt[fp.m[1], fp.m[2], 15-eSize], lo, 32, 0, 16]; lo _ BitOps.ICID[DblShiftLt[fp.m[2], fp.m[3], 15-eSize], lo, 32, 16, 16]; hdw.single _ NOT fp.double; hdw.h _ BitOps.ELFD[hi,32,0,32]; hdw.l _ IF fp.double THEN BitOps.ELFD[lo,32,0,32] ELSE 0 }; RoundMult: PROC [fp: FP, mode: Mode] RETURNS[status: Dragon.PBusFaults] = { saveFP: FPRec _ fp^; exact: BOOL _ Round[fp, mode.rnd]; IF exact THEN status_FPgrNEZeroE ELSE status_FPneZeroI; IF fp.exp < MinExp[fp] THEN IF mode.fast THEN {SetToZero[fp]; exact _ TRUE; RETURN[FPeqZeroE]} ELSE { fp^ _ saveFP; fp.exp _ fp.exp + WrapBias[fp]; IF exact THEN RETURN[FPuFlow] ELSE RETURN[FPuFlowI] }; IF fp.exp > MaxExp[fp] THEN {RETURN[OverFlow[fp, mode.rnd]]} }; RoundFP: PROC [fp: FP, rnd: FPRndMode] RETURNS[status: Dragon.PBusFaults] = { exact: BOOL; SELECT TRUE FROM fp.type=nan => RETURN[FPinvalid]; fp.type=zero => RETURN[FPeqZeroE]; fp.type=inf => RETURN[FPlsInfE]; ENDCASE; exact _ Round[fp, rnd]; IF exact THEN status_FPgrNEZeroE ELSE status_FPneZeroI; IF fp.exp < MinExp[fp] THEN IF exact THEN RETURN[FPuFlow] ELSE RETURN[FPuFlowI]; IF fp.exp > MaxExp[fp] THEN RETURN[OverFlow[fp, rnd]] }; Round: PROC[fp: FP, rnd: FPRndMode] RETURNS[exact: BOOL] = { IF fp.exp { }; rn => IF lrs=3 OR lrs=6 OR lrs=7 THEN Add[4]; rp => IF NOT fp.sign THEN Add[3]; rm => IF fp.sign THEN Add[3]; ENDCASE; RETURN[lrs MOD 4 = 0]}; OverFlow: PROC[fp: FP, rnd: FPRndMode] RETURNS[status: Dragon.PBusFaults] = { SELECT rnd FROM rn => SetToInf[fp]; rz => SetToMax[fp]; rp => IF fp.sign THEN SetToMax[fp] ELSE SetToInf[fp]; rm => IF fp.sign THEN SetToInf[fp] ELSE SetToMax[fp]; ENDCASE; RETURN[FPoFlowI] }; Normalize: PROC [fp: FP] = { IF fp.m[0] = 0 AND fp.m[1] = 0 AND fp.m[2] = 0 AND fp.m[3]/2 = 0 THEN {SetToZero[fp]; RETURN}; WHILE fp.m[0] = 0 DO fp.m[0] _ fp.m[1]; fp.m[1] _ fp.m[2]; fp.m[2] _ fp.m[3]; fp.m[3] _ 0; IF (fp.m[2] MOD 2 = 1) THEN {fp.m[2] _ fp.m[2] - 1; fp.m[3] _ 1}; fp.exp _ fp.exp-16; ENDLOOP; WHILE fp.m[0] < 100000B DO ShiftLt[fp]; IF (fp.m[3] MOD 4 = 2) THEN fp.m[3] _ fp.m[3] - 1; ENDLOOP }; ShiftLt: PROC [fp: FP] = { FOR i:CARDINAL IN [0..2] DO fp.m[i] _ fp.m[i]*2; IF fp.m[i+1] > 77777B THEN fp.m[i] _ fp.m[i] + 1; ENDLOOP; fp.m[3] _ fp.m[3]*2; fp.exp _ fp.exp-1 }; DeNormalize: PROC [fp: FP, count: INTEGER] = { WHILE count/16 # 0 DO fp.m[3] _ fp.m[2] + (IF (fp.m[3]#0) AND ((fp.m[2] MOD 2)=0) THEN 1 ELSE 0); fp.m[2] _ fp.m[1]; fp.m[1] _ fp.m[0]; fp.m[0] _ 0; fp.exp _ fp.exp+16; count _ count-16 ENDLOOP; THROUGH (0..count] DO IF (fp.m[3] MOD 3 = 1) THEN fp.m[3] _ fp.m[3] + 2; ShiftRt[fp, 1]; ENDLOOP }; ShiftRt: PROC [fp: FP, count: CARDINAL] = { THROUGH (0..count] DO FOR i:CARDINAL DECREASING IN [1..3] DO fp.m[i] _ fp.m[i]/2; IF fp.m[i-1] MOD 2 = 1 THEN fp.m[i] _ fp.m[i] + 100000B; ENDLOOP; fp.m[0] _ fp.m[0]/2; fp.exp _ fp.exp+1; ENDLOOP }; ADC3: PROC[a, b, c: CARDINAL] RETURNS[cy, sum: CARDINAL] = { ln: Basics.LongNumber; ln.lc _ LONG[a] + LONG[b] + LONG[c]; RETURN[ln.highbits, ln.lowbits] }; SignificantBitsZero: PROC[fp:FP] RETURNS[zero:BOOL] = { IF fp.double THEN RETURN[fp.m[0]=0 AND fp.m[1]=0 AND fp.m[2]=0 AND fp.m[3]/2048=0] ELSE RETURN[fp.m[0]=0 AND fp.m[1]/256=0]}; SetToZero: PROC[fp:FP] = {fp.type_zero; fp.exp_0; fp.m_ALL[0]}; SetToNaN: PROC[fp: FP] = {fp^ _ [fp.double, nan, fp.sign, MaxExp[fp]+1, ALL[177777B]]}; SetToInf: PROC[fp: FP] = {fp^ _ [fp.double, inf, fp.sign, MaxExp[fp]+1, ALL[0]]}; SetToMax: PROC[fp: FP] = {fp^ _ [fp.double, norm, fp.sign, MaxExp[fp], ALL[0]]; IF fp.double THEN {fp.m[0]_fp.m[1]_fp.m[2]_177777B; fp.m[3]_174000B} ELSE {fp.m[0]_177777B; fp.m[1]_177400B}}; MinExp: PROC[fp:FP] RETURNS[CARDINAL] = { RETURN[(IF fp.double THEN FPExpBias-1022 ELSE FPExpBias-126)]}; MaxExp: PROC[fp:FP] RETURNS[CARDINAL] = { RETURN[(IF fp.double THEN FPExpBias+1022 ELSE FPExpBias+126)]}; WrapBias: PROC[fp:FP] RETURNS[CARDINAL] = { RETURN[IF fp.double THEN 2048 ELSE 256]}; END. JDragonFPImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Last edited by Curry, February 8, 1985 2:02:15 pm PST a and b are normal and non-zero Private: fp normalized, (not zero, not inf, not nan) Possible results: FPeqZeroE, FPlsInfE, FPgrNEZeroE, FPneZeroI, FPoFlowI, FPuFlow, FPuFlowI, FPinvalid ʘšÐbl™Jšœ Ïmœ1™šŸœŸœŸœ˜?J˜—Jšœ™JšŸœ Ÿœ˜-JšŸœ Ÿœ˜-Jšœ'˜'Jšœ˜J˜š ŸœŸ œŸ œŸœŸœÏc!˜JJšœŸœ˜š ŸœŸ œŸ œŸœŸ˜'Jšœ˜Jšœ*˜*Jšœ6˜6Jšœ˜JšŸœ˜—š ŸœŸœŸ œŸœŸœ˜/JšŸœ#˜%JšŸœ˜—JšŸœ˜—šŸœŸ˜Jšœ˜šŸœŸœŸœŸ˜Jšœ˜JšŸœŸœ˜/JšŸœ˜—Jšœ˜JšŸœ˜—Jš ŸœŸœŸœŸœŸœ˜4š ŸœŸœŸ œŸœŸœ ŸœŸ˜?JšŸœ ŸœŸœ˜,—Jšœ˜JšŸœ˜—J˜š ÐbnœŸœŸœŸœŸœ˜8JšœŸœ˜Jšœ Ÿœ ŸœŸ œ5˜XJš œ Ÿœ ŸœŸ œŸœ˜.Jšœ Ÿœ˜Jšœ Ÿœ˜šŸœ Ÿ˜Jš œ Ÿœ Ÿœ ŸœŸœ Ÿœ˜CJš œŸœ Ÿœ ŸœŸœ Ÿœ˜AJšœŸœŸœ˜$JšŸœ˜—š ŸœŸœŸ œŸœŸ˜&JšœŸœ˜#Jšœ˜š ŸœŸœŸ œŸœŸ˜&JšœŸœ˜%J˜JšŸœŸœŸœŸœ˜2Jšœ˜JšŸœ˜—JšŸœ˜—JšŸœ ŸœŸœ˜#JšŸœ˜Jš ŸœŸœŸœŸœŸœŸœ˜LšŸœŸœŸœ˜.JšŸœŸœ'˜/JšŸœŸœ)˜1—Jšœ˜šŸœŸœŸœŸ˜/JšŸœŸœŸœŸœ˜,Jšœ˜Jšœ˜Jšœ Ÿœ˜JšŸœ˜ ——J˜J˜Jš™J˜JšÐbkœŸœŸœ˜JšÏbœŸœ˜+Jš¥ œŸœ ˜š¥œŸœŸœ˜JšœŸœŸœ˜Jšœ˜JšœŸœŸœ˜JšœŸœ˜Jš œŸœŸœŸœŸœ˜'—J˜š £œŸœ Ÿœ Ÿœ Ÿœ-˜fšÏnœŸœŸœŸœ˜4Jšœ ˜ šŸœŸ œŸœŸ˜JšŸœŸœŸœ˜Jš ŸœŸœŸœŸœŸœ˜3——JšœŸœŸœ ˜"JšŸœŸœŸœŸœ˜FJšŸœŸœŸœ˜9JšŸœŸœŸœ˜:Jš Ÿœ ŸœŸœŸœŸœ˜CJš Ÿœ ŸœŸœŸœŸœ˜EJšŸœŸœŸœ˜@Jšœ"˜"Jšœ*˜*JšŸœŸœŸœ˜=JšŸœŸœŸœŸœ˜`JšŸœŸœŸœ˜Jšœ'Ÿœ˜>Jšœ'Ÿœ˜>Jšœ'Ÿœ˜>JšŸœŸœŸœ˜DJšœ˜—JšŸœ˜—Jšœ˜JšŸœ˜—Jšœ ˜ Jšœ˜JšŸœ˜ —J˜š £œŸœŸœ ŸœŸœ/˜fš¦œŸœŸœŸœ˜1Jšœ˜šŸœŸœŸœŸ˜JšŸœŸœŸœ˜Jš ŸœŸœŸœŸœŸœ˜3——JšŸœ Ÿœ ŸœŸœ˜?JšŸœŸœŸœ˜5JšŸœŸœŸœ˜4Jš Ÿœ ŸœŸœŸœŸœ˜?Jš Ÿœ ŸœŸœŸœŸœ˜?Jšœ˜Jšœ˜šŸœ Ÿœ ŸœŸœ˜4JšŸœŸœ˜;JšŸœŸœ˜8—JšŸœŸœŸœ˜7JšŸœŸœŸœ˜7šŸœ Ÿœ Ÿœ˜%JšŸœŸœ˜-Jšœ Ÿœ˜,—JšŸœŸœŸœ˜:JšŸœŸœŸœ˜:J˜šŸœ˜JšŸœ˜"JšŸœ0˜4—šŸœ˜šŸœ˜JšœŸœ˜J˜(J˜(J˜(J˜(JšŸœŸœ/˜=—šŸœ˜JšœŸœ˜JšŸœŸœŸœ#˜?Jšœ#Ÿœ˜7Jšœ#Ÿœ˜7Jšœ#Ÿœ˜7Jšœ#Ÿœ˜7šŸœ˜JšŸœ#˜'JšŸœ˜———Jšœ˜JšŸœ˜ —J˜š £œŸœŸœ ŸœŸœ.˜ešœ ŸœŸœŸ˜Jšœ ŸœŸœ˜&Jšœ ŸœŸœ˜&Jšœ Ÿœ˜'Jšœ Ÿœ˜Jš œŸœŸœ ŸœŸœŸœ Ÿœ˜SJšœ Ÿœ˜*Jš œ ŸœŸœŸœ Ÿœ ˜GJš œ ŸœŸœŸœ Ÿœ ˜GJšœŸœŸœ Ÿœ ˜>JšŸœ˜—JšŸœŸœŸœŸœ˜;Jšœ˜šŸœ ˜Jš ŸœŸœŸœŸœŸœ Ÿœ˜\—šŸœŸœŸœŸ˜JšŸœŸœŸœ˜Jš ŸœŸœŸœŸœ Ÿœ˜YJšŸœ˜—JšŸœŸœ˜(J˜—š£œŸœ$Ÿœ˜3JšŸœ/˜6JšœŸœ˜šŸœŸ˜JšœŸœŸœŸœ˜I—Jšœ˜šŸœŸ˜JšœŸœŸœŸœ˜I—Jšœ˜JšŸœ˜—J˜š£œŸœ˜&JšŸœ/˜6JšœŸœ˜šŸœ Ÿ˜JšœŸœŸœ˜I—Jšœ˜Jšœ˜JšŸœ˜—J˜š£œŸœ¢˜>JšŸœ/˜6Jšœ.˜.Jšœ.˜.Jšœ˜JšœŸœ˜JšœŸœ ŸœŸœ ˜5JšœŸœ˜ šŸœ Ÿ˜Jšœ Ÿœ$˜3šœ Ÿœ˜JšŸœŸœ˜JšŸœŸœ˜—JšŸœ ˜—Jšœ(¢˜6Jšœ˜JšœŸœ¢ œ˜6Jšœ˜JšŸœŸœŸœ˜7š Ÿœ Ÿœ ŸœŸœŸœ˜=JšŸœŸœ˜JšŸœŸœ˜ —šŸœ Ÿœ ˜Jš ŸœŸœŸœŸœ Ÿœ ˜E—Jšœ0˜0JšŸœ Ÿœ˜#JšŸœ!˜'—J˜š£œŸœ%Ÿœ˜4JšŸœ/˜6J˜JšœŸœŸœ ˜Jšœ˜JšŸœ ŸœŸœ˜9Jšœ˜JšŸœ Ÿœ˜#Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜JšŸœ˜—J˜š£œŸœ%Ÿœ˜4JšŸœ/˜6JšœŸœ˜Jšœ˜Jšœ˜JšŸœ˜—J˜J˜š£œŸœŸœŸœ˜2JšœŸ œ˜(JšœŸ œ˜(Jšœ Ÿœ˜J˜JšœŸœ ˜Jšœ Ÿœ ˜šŸœ ˜ šŸœ˜JšœŸœ ˜"JšœŸœ!˜6JšœŸœ˜&JšœŸœŸœ˜IJšœŸœ˜&JšœŸœ˜,—šŸœ˜JšœŸœ ˜!JšœŸœ˜3JšœŸœ˜%JšœŸœ˜+——Jšœ Ÿœ˜JšŸœŸœŸœŸœŸœ Ÿœ ŸœŸœ˜GšŸœŸœŸ˜JšœŸœ/˜FJšœŸœŸœ-˜HJšœŸœ,˜CJšœŸœŸœ,˜GšŸœ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜———J˜J˜š£œŸœŸœŸœ˜2š ¦ œŸœ ŸœŸœŸœ˜9JšŸœŸœŸœ˜5JšŸœ˜ —JšœŸœ˜Jš œŸœŸœ ŸœŸœ˜.Jšœ ˜ J˜šŸœŸœŸœ¢'˜LJšœ˜Jšœ&˜&—šŸœ Ÿ˜Jšœ)˜)Jšœ˜šŸœ¢(˜5JšŸœŸœŸœ˜Jšœ!¢˜9Jšœ˜——JšŸœŸœ ŸœŸœ˜2JšŸœ ŸœŸœ ˜(Jšœ Ÿœ ˜0Jšœ Ÿœ&˜6Jšœ Ÿœ@˜PJšœ Ÿœ9˜IJšœ Ÿœ:˜JJšœ Ÿœ:˜JJšœ Ÿœ ˜JšœŸœ ˜!Jš œ Ÿœ ŸœŸœ Ÿœ˜=—J˜š£ œŸœŸœŸœ˜KJš¥.™.Jšœ˜JšœŸœ˜"JšŸœŸœŸœ˜7šŸœŸœŸœ ˜(JšŸœŸœŸœ ˜5šŸœ˜Jšœ ˜ Jšœ˜Jš ŸœŸœŸœ ŸœŸœ ˜6——JšŸœŸœŸœ˜?J˜—š£œŸœŸœŸœ˜MJšœe™eJšœŸœ˜ šŸœŸœŸ˜JšœŸœ ˜$JšœŸœ ˜%JšœŸœ ˜#JšŸœ˜—Jšœ˜JšŸœŸœŸœ˜7JšŸœŸœŸœŸœŸœ ŸœŸœ ˜PJšŸœŸœŸœ˜8—J˜š £œŸœŸœŸœŸœ˜=JšŸœŸœ$˜=JšœŸœ ŸœŸœ ¢˜IJšœ˜JšœŸœ¢ œ˜6Jšœ˜JšŸœ ˜—J˜š ¦œŸœŸœŸœŸœ˜;š¦œŸœŸœ˜š ŸœŸœŸ œŸœŸ˜&Jšœ%Ÿœ˜/——JšœŸœ Ÿœ˜šŸœŸœŸœŸ˜J˜ Jš œŸœŸœŸœŸœ˜-JšœŸœŸœ Ÿœ˜#JšœŸœŸœ˜"JšŸœ˜—JšŸœŸœ ˜J˜—š£œŸœŸœŸœ˜MšŸœŸ˜Jšœ˜Jšœ˜JšœŸœ ŸœŸœ˜5JšœŸœ ŸœŸœ˜5JšŸœ˜—JšŸœ ˜J˜—š¦ œŸœŸœ˜š Ÿœ Ÿœ Ÿœ ŸœŸ˜EJšœŸœ˜—šŸœ Ÿ˜JšœE˜EJšŸœ ŸœŸœ&˜AJšœ˜JšŸœ˜—šŸœŸ˜Jšœ ˜ JšŸœ ŸœŸœ˜2JšŸœ˜ J˜——š¦œŸœŸœ˜šŸœŸœŸœŸ˜Jšœ˜JšŸœŸœ˜1JšŸœ˜—Jšœ˜šœ˜J˜——š¦ œŸœŸœŸœ˜.šŸœŸ˜Jš œŸœ Ÿœ ŸœŸœŸœ˜KJšœ2˜2Jšœ˜Jšœ˜JšŸœ˜—šŸœ Ÿ˜JšŸœ ŸœŸœ˜2Jšœ˜JšŸœ˜ J˜——š¦œŸœŸœ Ÿœ˜+šŸœ Ÿ˜š ŸœŸœŸ œŸœŸ˜&Jšœ˜JšŸœ ŸœŸœ˜8JšŸœ˜—Jšœ˜Jšœ˜JšŸœ˜ J˜——J˜š ¦œŸœ ŸœŸœ Ÿœ˜—š¦œŸœŸœ˜Jšœ/Ÿœ˜8—š¦œŸœŸœ˜Jšœ.Ÿœ˜6šŸœ ˜ JšŸœ3˜7JšŸœ%˜)——J˜š ¦œŸœŸœŸœŸœ˜)JšŸœŸœ ŸœŸœ˜?—š ¦œŸœŸœŸœŸœ˜)JšŸœŸœ ŸœŸœ˜?—š ¦œŸœŸœŸœŸœ˜+JšŸœŸœ ŸœŸœ˜)—J˜J˜JšŸœ˜J˜—J˜—…—L¸i