{File: <>*>*>FloatPrimitives.mc Created by Toru Tokunaga 25-Feb-85 19:45:19 This file includes all primitves concerning with floating point operation. Edit History: Toru Tokunaga 26-Jun-85 14:23:02 Toru Tokunaga 25-Apr-85 21:44:52 Correct the timesTwoPower Primitive Toru Tokunaga 9-Apr-85 10:25:48 return linkage change for otMap1Bank0 Toru Tokunaga 9-Apr-85 8:50:08 finish debugging( truncate, fractionPart, exponent, timesTwoPower) Toru Tokunaga 8-Apr-85 21:18:11 finish the all coding(truncate, fractionPart, exponent, timesTwoPower) Toru Tokunaga 5-Apr-85 20:03:43 add the table for primitive No.52 ~ 54 Toru Tokunaga 5-Apr-85 15:02:01 add floatTruncated primitive Toru Tokunaga 2-Apr-85 16:07:55 If FPP status = ~OK or ~InExact --> primitive fail Toru Tokunaga 1-Apr-85 16:50:22 add float division primitive Toru Tokunaga 21-Mar-85 14:18:56 modification for moving this microcode from bank1 to bank0 Toru Tokunaga 8-Mar-85 14:30:36 correct stack ACCESS, stackLow + 1 --> stackLow - 1; Toru Tokunaga 7-Mar-85 17:51:57 if SmallInt > 0 --> Q _0, otherwise Q _ 0FFFF in primitiveAsFloat Toru Tokunaga 7-Mar-85 15:06:03 make base of bank2 and bank3 in this file Toru Tokunaga 5-Mar-85 20:41:52 add the Floating comparison Primitive Toru Tokunaga 26-Feb-85 16:55:13 Add Asfloat Primitve } L4 _ unaryMessage, GOTO[primitiveAsFloat], c3, at[ 8, 10, bank2InBank0];{AsFloat } temp1Low _ floatAdd, GOTO[floatBinaryMessage], c3, at[ 9, 10, bank2InBank0];{floatAdd} temp1Low _ floatSub, GOTO[floatBinaryMessage], c3, at[0A, 10, bank2InBank0];{floatSubtract} temp1Low _ floatLessThan, GOTO[floatBinaryMessage], c3, at[0b, 10, bank2InBank0];{floatLessThan} temp1Low _ floatGreaterThan, GOTO[floatBinaryMessage], c3, at[0c, 10, bank2InBank0];{floatGreaterThan} temp1Low _ floatLessOrEqual, GOTO[floatBinaryMessage], c3, at[0d, 10, bank2InBank0];{floatLessOrEqual} temp1Low _ floatGreaterOrEqual, GOTO[floatBinaryMessage], c3, at[0e, 10, bank2InBank0];{floatGreaterOrEqual} temp1Low _ floatEqual, GOTO[floatBinaryMessage], c3, at[0f, 10, bank2InBank0];{floatEqual} temp1Low _ floatNotEqual, GOTO[floatBinaryMessage], c3, at[ 0, 10, bank3InBank0];{floatEqual} temp1Low _ floatMultiply, GOTO[floatBinaryMessage], c3, at[ 1, 10, bank3InBank0];{floatMultiply} temp1Low _ floatDivide, GOTO[floatBinaryMessage], c3, at[ 2, 10, bank3InBank0];{float divide} temp1Low _ floatTruncated, GOTO[floatUnaryMessage], c3, at[ 3, 10, bank3InBank0];{float Truncated} temp1Low _ floatFractional, GOTO[floatUnaryMessage], c3, at[ 4, 10, bank3InBank0];{fractional part} temp1Low _ floatExponent, GOTO[floatUnaryMessage], c3, at[ 5, 10, bank3InBank0];{exponent } L4 _ binaryMessage, GOTO[primitiveTimesTwoPower], c3, at[ 6, 10, bank3InBank0];{ floatTwotimes } { L4 indicates that the message is binary message or unary message } floatUnaryMessage: MAR _ [stackHigh, stackLow + 0], L1 _ getUnaryFloatReceiver, c1; uPPsave _ temp1Low, c2; { save the indicator for what kind of primitive } otLow _ MD, CALL[otMapBank0], c3; { get Oop & to get the real address of Object } temp1Low _ temp1Low + firstFieldOfObject, c1, at[getUnaryFloatReceiver, 10, otMapBank0-return]; L4 _ unaryMessage, c2; { indicate this primitive = unarymessage } Q _ 0FF + 1, c3; { preparation for float truncated Primitive } MAR _ [temp1High, temp1Low + 0], c1; temp1Low _ temp1Low + 1,CANCELBR[$,2], c2; temp2Low _ MD, c3; { get the high half of floating point } MAR _ [temp1High, temp1Low + 0], c1; Xbus _ uPPsave, XDisp, CANCELBR[$,2], c2; { dispatching for what kind of primitive in unarymessage } temp3Low _ MD, DISP4[whatKindOfUnaryPrimitive, 0C], c3; { get the low half of flaoting point } floatBinaryMessage: L4 _ binaryMessage, c1; uPPsave _ temp1Low, c2; { save temp1Low indicating the actual operation (i.e. + - / * etc} GOTO[floatBinary], c3; { } { Since floating operation needs two number(receiver,argument),the routine described below common for operation for floating arithmetic , etc At entry point, L4 has indicator of distinguishing the message pattern (ie: 0 -> UnaryMessage, 1 -> BinaryMessage) and temp1Low has what kind of primitive we execute } floatBinary: MAR _ [stackHigh, stackLow + 0] , L2 _ getFloatClass c1; { read argument } temp2Low _ classFloatPointer, c2; { temp2Low has Oop of the FloatCalss to check whether argument's class is floatClass} otLow _ MD, XDisp, CALL[getClassBank0], c3; { to check the smallinteger or Oop -- commonroutines.mc} [] _ temp3Low - temp2Low, ZeroBr, c1, at[getFloatClass, 10, getClassBank0-return]; { Class is Float ??} temp1Low _ temp1Low + firstFieldOfObject, BRANCH[notFloatClass,$], c2; { Point the receiver of real object area -- no header } Noop, c3; { temp1High,,temp1Low has the address of object } MAR _ [temp1High, temp1Low + 0], c1; { get the Floating number -- Argument } temp1Low _ temp1Low + 1, c2; temp2Low _ MD, c3; { High half of Floaitng number} MAR _ [temp1High, temp1Low + 0], c1; stackLow _ stackLow - 1, c2; { to get Receiver's Oop } temp3Low _ MD, L1 _ getFloatReceiver, c3; { Low half of Floating number } MAR _ [stackHigh, stackLow + 0], c1; { to get Oop of receiver} uArg2Hi _ temp2Low, c2; { save high half of argument } otLow _ MD, CALL[otMapBank0], c3; temp1Low _ temp1Low + firstFieldOfObject, c1, at[getFloatReceiver, 10, otMapBank0-return]; stackLow _ stackLow + 1, c2; { reset the stack pointer } Q _ 0FF, c3; { prepare for Float Divide operation } getFloatNumberHigh: MAR _ [temp1High, temp1Low + 0 ], c1; { get the Float number} temp1Low _ temp1Low + 1, c2; temp2Low _ MD, c3; { get high half (16bits) } MAR _ [temp1High, temp1Low + 0], c1; uArg2Lo _ temp3Low, CANCELBR[$,2], c2; { save lowhalf of argument } temp3Low _ MD, c3; { get low half (16 bits) } Xbus _ uPPsave, XDisp, c1; DISP4[whatKindOfBinaryPrimitive], c2; GOTO[startFloatOperation], c3, at[ 0, 10, whatKindOfBinaryPrimitive]; { FloatAdd } GOTO[startFloatOperation], c3, at[ 1, 10, whatKindOfBinaryPrimitive]; { FloatSubtract } { at[ 2, 10, whatKindOfBinaryPrimitive]; { FloatLessThan } at[ 3, 10, whatKindOfBinaryPrimitive]; { FloatGreaterThan } at[ 4, 10, whatKindOfBinaryPrimitive]; { FloatLessThanOrEqual } at[ 5, 10, whatKindOfBinaryPrimitive]; { FloatGreaterThanOrEqual } at[ 6, 10, whatKindOfBinaryPrimitive]; { FloatEqual } at[ 7, 10, whatKindOfBinaryPrimitive]; { FloatNotEqual } } GOTO[startFloatOperation], c3, at[ 8, 10, whatKindOfBinaryPrimitive]; { FloatMultiply } { at[ 9, 10, whatKindOfBinaryPrimitive]; } { FloatDivide } { So far, we do not use } { at[ 0A, 10, whatKindOfBinaryPrimitive]; at[ 0B, 10, whatKindOfBinaryPrimitive]; at[ 0C, 10, whatKindOfBinaryPrimitive]; at[ 0D, 10, whatKindOfBinaryPrimitive]; at[ 0E, 10, whatKindOfBinaryPrimitive]; at[ 0F, 10, whatKindOfBinaryPrimitive]; } startFloatOperation: Q _ 0FF + 1, c1; { to get the FPP status } PPort _ ~Q, c2; { bus direction = input mode } Noop,{Q _ uFloatMode,} c3; {} Xbus _ uPPsave, XDisp, c1; { } FloatMode.RN.PI.IEEE, FloatFLOW, DISP4[FloatOp], c2; { Dispatch to prepare something for each float primitive operation, and If operation is Arithmetic(+ - *) Come back to FloatArithCommon --- see below} FloatArithCommon: FloatA _ temp3Low LRot0, c1; FloatStartFlow, c2; temp3Low _ classFloatPointer, c3; {wait} uClassToInstantiate _ temp3Low, c1; temp3Low _ 2, c2; { Object size except header } FloatUnloadS, Float.M, c3; { to get the result of high half(16 bits)} FloatUnloadS, Float.L, c1; { to get the result of low half(16 bits)} nowGetResult: Q _ PPort, c2; { Get the Status : note -- real state is complemented } uNewValHi _ FloatResult, c3; { actually get the result of highhalf} uNewValLo _ FloatResult c1; { actually get the result of lowhalf } uFloatComResult _ Q, YDisp, c2; { Check status } Q _ temp1Low xor ~temp1Low, DISP4[FPPStatus, 1], c3; {Q = all 1} { You may think that it is waste of the control store, if you think so, please delete this dipatch table. I think it is very useful to debug the microcode. } ok: PPort _ Q, GOTO[FPOK], c1, at[0F, 10, FPPStatus]; { Status OK!! Bus direction is BXbus <-- Xbus :: DEFAULT} inexact: PPort _ Q, GOTO[FPOK], c1, at[0D, 10, FPPStatus]; { Inexact occur } unf: PPort _ Q, GOTO[floatPrimitiveFail2], c1, at[0B, 10, FPPStatus]; { Underflow } unfinex: PPort _ Q, GOTO[floatPrimitiveFail2], c1, at[09, 10, FPPStatus]; { Underflow + Inexact } unused: PPort _ Q, GOTO[floatPrimitiveFail2], c1, at[07, 10, FPPStatus]; { Unused } ovf: PPort _ Q, GOTO[floatPrimitiveFail2], c1, at[05, 10, FPPStatus]; { Overflow } invalid: PPort _ Q, GOTO[floatPrimitiveFail2], c1, at[03, 10, FPPStatus]; { Invalid operand } denormal: PPort _ Q, GOTO[FPOK], c1, at[01, 10, FPPStatus]; { Denormalized operand } FPOK: temp3High _ creatingFloatInstance, c2; {the return link for creating the instance in temp3High} CALL[createInstanceWithWordsInBank0], c3; { Now, we have the object body pointed by temp1High,,temp1Low and new Oop stored in otLow} retrunFromCreate: L1 _ floatReturn, c1, at[creatingFloatInstance, 10, createInstanceInBank0-return]; Noop, c2; { otLow must have the Oop and temp1High,temp1Low will have the first address of object } CALL[otMapBank0], c3; returnFromCreate2: temp1Low _ temp1Low + firstFieldOfObject, c1,at[floatReturn, 10, otMapBank0-return]; Noop, c2; Noop, c3; MAR _ [temp1High,temp1Low + 0], c1; { store the highhalf of the Float number } MDR _ uNewValHi, CANCELBR[$,2], LOOPHOLE[wok], c2; temp1Low _ temp1Low + 1, c3; MAR _ [temp1High, temp1Low + 0], c1; { store the lowhalf of the float number } MDR _ uNewValLo, CANCELBR[$,2], LOOPHOLE[wok], L4Disp, c2; { L4 has unary or binary } temp1Low _ nilPointer, BRANCH[unaryMessageReturn,binaryMessageReturn, 0E], c3; {floatTemp has already have the same value as uNewObject} compareReturn: Noop, c2; temp1Low _ nilPointer,GOTO[binaryMessageReturn], c3; unaryMessageReturn: MAR _ [stackHigh, stackLow + 0], c1; { store the Oop of the float number to stack} MDR _ floatTemp, c2; GOTO[nextByteCodeInBank0], c3; { go to bank1 & dispatch to next bytecode } binaryMessageReturn: MAR _ [stackHigh, stackLow + 0], c1; MDR _ temp1Low, c2; {floatTemp must have nilPointer} stackLow _ stackLow - 1, GOTO[unaryMessageReturn], c3; notFloatClass: CANCELBR[floatPrimitiveFail1], c3; { since stackLow will increase by 1 at destination } { Floationg primitive fail } floatPrimitiveFail1: Noop, c1; floatPrimitiveFail2: Noop, c2; floatPrimitiveFail3: temp1Low _ 1, GOTO[saveSmalltalkStateBank0],{GOTO[activateNewMethodInBank0],} c3; {=== begin: primitive 40 - AsFloat ===} primitiveAsFloat: MAR _ [stackHigh, stackLow + 0] , c1; {start read receiver} Q _ 0, c2; {used for High 8 bit of smallinteger} temp1Low _ MD, XDisp, c3; {get and check the receiver is smallInteger} primitiveAsFloat1: [] _ temp1Low LRot0, XHDisp, { Determine sign of Receiver} BRANCH[PrimFailAsFloat,$,0E], c1; temp3High _ creatingFloatInstance, BRANCH[positiveInteger,negativeInteger, 2], c2; { return link for createInstanceWithWords} positiveInteger: uFloat _ Q, { since positive, high 16bits = all 0} c3; temp1Low _ RShift1 temp1Low, SE _ 0, GOTO[startFloat], c1; { adjust to real positive smallinteger } negativeInteger: uFloat _ ~Q, { since negative, high 16bits = all 1} c3; temp1Low _ RShift1 temp1Low, SE _ 1, GOTO[startFloat] c1; { adjust to real negative smallinteger } startFloat: { In this routine, I never check the status of Floating point Processor } FloatMode.RN.PI.IEEE, FloatFLOW, c2;{ Round to nearest, Projective mode, IEEE } FloatA _ uFloat, FLFloatA, c3;{ high half } FloatA _ temp1Low LRot0, c1;{ Low 16bits } FloatStartFlow, c2; temp3Low _ classFloatPointer, c3; uClassToInstantiate _ temp3Low, c1; temp3Low _ 2, c2; { number of needed words for Floating point object } FloatUnloadS, Float.M, c3; { to Load High half of the floating point and set the retrun address for creating the instance in temp3High} FloatUnloadS, Float.L, c1; { to load low half of the floaing point} uNewValHi _ FloatResult, c2; { load the high result } uNewValLo _ FloatResult, CALL[createInstanceWithWordsInBank0], c3; { load the Low result & GO!! Create Floating Point Instance -- Memorymanglement.mc } { At return, otLow and uNewObject have the Oop of new created instance, and uNewValHi,,uNewValLo have the 32bits Floating point number} PrimFailAsFloat: CANCELBR[floatPrimitiveFail3], c2; { primitive fail and since stackLow will increase by 1 at destination } {=== end: primitive 40 - AsFloat ===} {=== begin: primitive 41 - FloatAdd ===} primitiveFloatAdd: uFloatPlus _ temp2Low , c3, at[floatAdd, 10, FloatOp];{ use ufloatPlus, why? -- see MI format for floating point processor} FloatAB _ uArg2Hi, c1; FloatAB _ uArg2Lo, c2; FloatA _ uFloatPlus, FLPlus, GOTO[FloatArithCommon], c3; {=== end: primitive 41 - FloatAdd ===} {=== begin: primitive 42 - FloatSubtract ===} primitiveFloatSubtract: uFloatMinus _ temp2Low, c3, at[floatSub, 10, FloatOp]; { use ufloatMinus, why ? -- see MI format for floating point processor} FloatAB _ uArg2Hi, c1; FloatAB _ uArg2Lo, c2; FloatA _ uFloatMinus, FLAMinusB, GOTO[FloatArithCommon], c3; {=== end: primitive 42 - FloatSubtract ===} {=== begin: primitive 43 - FloatLessThan ===} primitiveFloatLessThan: L2 _ L2.floatLessThan, c3, at[floatLessThan, 10, whatKindOfBinaryPrimitive]; CALL[floatCompare], c1; [] _ floatTemp, NegBr, c2, at[L2.floatLessThan, 10, floatCompare-ret]; BRANCH[lessThanFalse, lessThanTrue], c3; lessThanFalse: floatTemp _ falsePointer, GOTO[compareReturn], c1; lessThanTrue: floatTemp _ truePointer, GOTO[compareReturn], c1; {=== end: primitive 43 - FloatLessThan ===} {=== begin: primitive 44 - FloatGreaterThan ===} primitiveFloatGreaterThan: L2 _ L2.floatGreaterThan, c3, at[floatGreaterThan, 10, whatKindOfBinaryPrimitive]; CALL[floatCompare], c1; [] _ floatTemp xor 1, ZeroBr, c2, at[ L2.floatGreaterThan, 10, floatCompare-ret]; BRANCH[greaterThanFalse, greaterThanTrue], c3; greaterThanTrue: floatTemp _ truePointer, GOTO[compareReturn], c1; greaterThanFalse: floatTemp _ falsePointer, GOTO[compareReturn] , c1; {=== end: primitive 44 - FloatGreaterThan ===} {=== begin: primitive 45 - FloatLessOrEqual ===} primitiveFloatLessOrEqual: L2 _ L2.floatLessOrEqual, c3, at[floatLessOrEqual, 10, whatKindOfBinaryPrimitive]; CALL[floatCompare], c1; [] _ floatTemp xor 1, ZeroBr, c2, at[ L2.floatLessOrEqual, 10, floatCompare-ret]; BRANCH[lessOrEqualTrue, lessOrEqualFalse], c3; lessOrEqualTrue: floatTemp _ truePointer, GOTO[compareReturn], c1; lessOrEqualFalse: floatTemp _ falsePointer, GOTO[compareReturn], c1; {=== end: primitive 45 - FloatLessOrEqual ===} {=== begin: primitive 46 - FloatGreaterOrEqual ===} primitiveFloatGreaterOrEqual: L2 _ L2.floatGreaterOrEqual, c3, at[floatGreaterOrEqual, 10, whatKindOfBinaryPrimitive]; CALL[floatCompare], c1; [] _ floatTemp, NegBr, c2, at[L2.floatGreaterOrEqual, 10, floatCompare-ret]; BRANCH[greaterOrEqualTrue, greaterOrEqualFalse], c3; greaterOrEqualTrue: floatTemp _ truePointer, GOTO[compareReturn], c1; greaterOrEqualFalse: floatTemp _ falsePointer, GOTO[compareReturn], c1; {=== end: primitive 46 - FloatGreaterOrEqual ===} {=== begin: primitive 47 - FloatEqual ===} primitiveFloatEqual: L2 _ L2.floatEqual, c3, at[floatEqual, 10, whatKindOfBinaryPrimitive]; CALL[floatCompare], c1; [] _ floatTemp, ZeroBr, c2, at[L2.floatEqual, 10, floatCompare-ret]; BRANCH[equalFalse, equalTrue], c3; equalTrue: floatTemp _ truePointer, GOTO[compareReturn], c1; equalFalse: floatTemp _ falsePointer, GOTO[compareReturn], c1; {=== end: primitive 47 - FloatEqual ===} {=== begin: primitive 48 - FloatNotEqual ===} primitiveFloatNotEqual: L2 _ L2.floatNotEqual, c3, at[floatNotEqual, 10, whatKindOfBinaryPrimitive]; CALL[floatCompare], c1; [] _ floatTemp, ZeroBr, c2, at[L2.floatNotEqual, 10, floatCompare-ret]; BRANCH[notEqualTrue, notEqualFalse], c3; notEqualTrue: floatTemp _ truePointer, GOTO[compareReturn], c1; notEqualFalse: floatTemp _ falsePointer, GOTO[compareReturn], c1; {=== end: primitive 48 - FloatNotEqual ===} {=== begin: primitive 49 - FloatMultiply ===} primitiveFloatMultiply: uFloatMultiply _ temp2Low, c3, at[floatMultiply, 10, FloatOp]; FloatAB _ uArg2Hi, c1; FloatAB _ uArg2Lo, c2; FloatA _ uFloatMultiply, FLTimes.A.B, c3; FloatA _ temp3Low LRot0, c1; FloatStartFlow, c2; temp3Low _ classFloatPointer, c3; uClassToInstantiate _ temp3Low, c1; temp3Low _ 2, c2; FloatUnloadP, Float.M, c3; FloatUnloadP, Float.L, GOTO[nowGetResult], c1; {=== end: pimitive 49 - FloatMultiply ===} {=== begin: primitive 50 - FloatDivide ===} primitiveFloatDivide: {at this point, Q = 0FF, temp2Low,,temp3Low have the receiver's value, and uArg2Hi,uArg2Lo havethe argument value} uArg1Hi _ temp2Low, c3, at[ 9, 10, whatKindOfBinaryPrimitive]; { FloatDivide } uArg1Lo _ temp3Low, c1; { uArg1High,,uArg1Low have Receiver } L1 _ L1.checkReceiver, c2; CALL[checkFloatType], c3; { Retrun point: floatTemp has the value respectively Zero : 0 Normal or denormalized number: 1 Infinity: 2 NAN: 3 Also, the component of floating number is stored in temp1Low,temp2Low,temp3Low separately. ** in fixed pitch, -- font: Gatch,system ** 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 temp1Low: E E E E E E E E - - - - - - - S temp2Low: - - - - - - - - - F F F F F F F temp3Low: F F F F F F F F F F F F F F F F } Go1: Ybus _ floatTemp xor floatNan, ZeroBr, c1, at[ L1.checkReceiver, 10, checkFloatType-return]; { to check if receiver = NAN } uFloatComResult _ floatTemp, BRANCH[$, receiverIsNan], c2; floatTemp _ temp1Low and 1, c3; uSign1 _ floatTemp, c1; { uSign1 = receiver's sign } Q _ 0FF, c2; temp1Low _ (temp1Low LRot8) and Q, c3; { receiver's Exponent } uExp1 _ temp1Low, c1; temp2Low _ temp2Low LRot8, c2; floatTemp _ (temp3Low LRot8) and Q, c3; floatTemp _ temp2Low or floatTemp, c1; { High 16 bit of fractional part -- except leading bit } uHighHalf1 _ floatTemp, c2; floatTemp _ temp3Low LRot8, c3; Q _ ~Q, c1; floatTemp _ floatTemp and Q, c2; uLowHalf1 _ floatTemp, c3; { Low 8 bit of fractional part } temp2Low _ uArg2Hi, c1; temp3Low _ uArg2Lo, L1 _ L1.checkArgument, c2; CALL[checkFloatType], c3; { check argument TYPE} Go8: Ybus _ floatTemp xor floatNan, ZeroBr, c1, at[L1.checkArgument, 10, checkFloatType-return]; floatTemp _ (LShift1 floatTemp),SE _ 0, BRANCH[$, argumentIsNan], c2; floatTemp _ LShift1 floatTemp , SE _ 0, c3; floatTemp _ floatTemp or uFloatComResult, c1; [] _ floatTemp, YDisp, c2; Q _ 0FF,DISP4[floatDivideType], c3; { Q : to make NAN } {According to IEEE standard, NAN must be returned in case of 0.0 / 0.0 operation, but Mesa coded primitive create the ZERO Division } GOTO[zeroDivision], c1,at[ 0, 10, floatDivideType]; { 0.0 / 0.0 }{primitive Fail - Zero Division } GOTO[zeroDivision], c1,at[ 1, 10, floatDivideType]; { W / 0.0 }{primitive Fail - Zero Division } temp1Low _ temp1Low and 1, GOTO[returnInf1], c1,at[ 2, 10, floatDivideType]; { INF / 0.0 }{return INF(receiver:check sign)} { at[ 3, 10, floatDivideType];} { NAN / 0.0 }{return NAN} temp3Low _ uSign1, GOTO[returnZero], c1,at[ 4, 10, floatDivideType]; { 0.0 / W }{return Zero(check sign)} floatTemp _ temp1Low LRot8,GOTO[prepareDivide], c1,at[ 5, 10, floatDivideType]; { W / W }{to check exponent of argument } temp1Low _ temp1Low and 1,GOTO[returnInf1], c1,at[ 6, 10, floatDivideType]; { INF / W }{return INF(receiver:check sign)} { at[ 7, 10, floatDivideType];} { NAN / W }{return NAN} temp3Low _ uSign1, GOTO[returnZero], c1,at[ 8, 10, floatDivideType]; { 0.0 / INF }{return Zero(check sign)} temp3Low _ uSign1, GOTO[returnZero], c1,at[ 9, 10, floatDivideType]; { W / INF }{return Zero(check sign)} floatTemp _ floatNan,GOTO[returnNan], c1,at[0A, 10, floatDivideType]; { INF / INF }{return NAN} { at[0B, 10, floatDivideType];} { NAN / INF }{return NAN} { at[0C, 10, floatDivideType];} { 0.0 / NAN }{return NAN} { at[0D, 10, floatDivideType];} { W / NAN }{return NAN} { at[0E, 10, floatDivideType];} { INF / NAN }{return NAN} { at[0F, 10, floatDivideType];} { NAN / NAN }{return NAN} {------ preparing for returning Nan -----------} receiverIsNan: floatTemp _ floatNan,GOTO[returnNan1], c3; { to make a Nan : fractional high part} argumentIsNan: floatTemp _ floatNan, c3; { to make a Nan : fractional high part} returnNan1: Q _ 0FF,GOTO[returnNan], c1; { to make a Nan : exponent } returnNan: {floatTemp = floatNan, Q = 0FF } temp1Low _ Q, c2; { exponent part = 0FF } temp3Low _ uSign1, GOTO[finalPack], c3; { packing to make 32 bit floating point format } zeroDivision: GOTO[floatPrimitiveFail3], c2; returnInf1: { floatTemp has the argument's sign xor receiver's sign,and Q = 0FF } temp3Low _ floatTemp, c2; { store the new sign } temp1Low _ Q, c3; { exponent for infinity } floatTemp _ floatTemp xor floatTemp, c1; { make high half of fractional part ZERO } Q _ floatTemp, c2; { make low half of fractional part } GOTO[finalPack], c3; returnZero: temp3Low _ temp1Low xor temp3Low, c2; temp3Low _ temp3Low and 1, c3; { new Sign } temp1Low _ 0, c1; { clear exponent } floatTemp _ 0, c2; { clear high half of fractional part } Q _ 0,GOTO[finalPack], c3; { clear low half of fractional part } {dePack the floating point number uSign2,uExp2, uHighHalf2, uLowhalf2 } prepareDivide: floatTemp _ floatTemp and Q, ZeroBr, c2; {check argument's exponent = 0 , Q = 0FF} uExp2 _ floatTemp, BRANCH[argNormal, $], c3; { store exponent part } {According to IEEE standards, return value must be NAN in this case. If I return the Nan, it make system trouble, so I ask help to Molasses in this case } GOTO[floatPrimitiveFail2], c1; { if argment = denormalized number then return the NAN } argNormal: floatTemp _ temp1Low and 1, c1; { Sign bit } uSign2 _ floatTemp, c2; {sign of argument} temp2Low _ temp2Low or 80, c3; {leading bit = 1 for argument} argNormal1: floatTemp _ ~Q, c1; floatTemp _ temp3Low and floatTemp, c2; floatTemp _ temp2Low or floatTemp, c3; floatTemp _ floatTemp LRot8, c1; { high half of fractional part -- argument } uHighHalf2 _ floatTemp, c2; temp3Low _ temp3Low LRot8, c3; temp3Low _ temp3Low and ~0FF, c1; uLowHalf2 _ temp3Low, c2; { low half of fractional part -- argument : Low byte = 0 } [] _ uExp1 and Q, ZeroBr, c3; { check receiver's exponent = 0 } argNormal3: temp1Low _ uHighHalf1, BRANCH[$, doDivide], c1; temp2Low _ 80, c2; { to make leading bit =1 for receiver } floatTemp _ temp2Low LRot8, c3; argNormal6: temp1Low _ temp1Low or floatTemp, c1; {receiver's leading bit = 1 } uHighHalf1 _ temp1Low, GOTO[doDivide0], c2; { Now, Receiver = uSign1, uExp1, uHighHalf1,uLowHalf1 ... Argument = uSign2, uExp2, uHighHalf2,uLowHalf2 } doDivide: Noop, c2; doDivide0: uSaveHomeLow _ homeLow, c3; { to use the homeLow-register for dividing loop } temp2Low _ uExp1, c1; temp1Low _ uExp2, c2; temp2Low _ temp2Low - temp1Low, c3; temp2Low _ temp2Low + 127'd, c1; { re-bias } uExp1 _ temp2Low, c2; { result of exponent is stored in uExp1 } floatTemp _ uSign1, c3; Q _ uSign2, c1; uSign1 _ floatTemp xor Q, c2; { result of sign is stored in uSign1 } divisorHigh _ uHighHalf2, c3; Q _ ~uLowHalf2, c1; divisorHigh _ DRShift1 divisorHigh, SE _ 0, c2; { loads the operand and 1 right shiftto allow room shift left during divide loop} divisorLow _ ~Q, c3; floatT _ uHighHalf1, c1; Q _ ~uLowHalf1, c2; { loads the operand and 1 right shiftto allow room shift left during divide loop} floatT _ DRShift1 floatT, SE _ 0, c3; {As per Ed Tafts Drado codem we will fo a total 26 iterations, 24 for quatinent, 2 guards bit. They are done by first doing 16 iterations, then 10 iterations} doDivide6: Q _ ~Q, L3 _ L3.divide1, c1; divCount _ 16'd, CALL[fptDivideLoopC3], c2; { 16 times loop } uHighHalf1 _ divResult, c2, at[L3.divide1, 10, fptDivLoopRets]; floatT _ DLShift1 floatT, SE _ 1,{Q.15 _ 0} L3 _ L3.divide2, c3; {remainder did not get its last left shift} doDivide7: divCount _ 10'd, CALL[fptDivideLoopC2], c1; { 10 times loop } divResult _ divResult LRot4, c2, at[L3.divide2, 10, fptDivLoopRets]; [] _ floatT or Q, NZeroBr, c3; doDivide8: divResult _ LShift1 (divResult), SE _ 0, BRANCH[fptDivD, fptDivE], c1; { Now, we install the correct sticky bit } fptDivD: divResult _ LShift1 (divResult), SE _ 0, GOTO[fptDivF], c2; fptDivE: divResult _ LShift1 (divResult), SE _ 1, GOTO[fptDivF], c2; fptDivF: uLowHalf1 _ divResult, GOTO[fptDivExit], c3; fptDivExit: homeLow _ uSaveHomeLow, c1; { restore the homeLow } uStickyBit _ 0, c2; rePackC3: floatTemp _ uHighHalf1, c3; Q _ uLowHalf1, c1; {nominal value = (-1)^uSighn1 * *2^(uExp1 - 127)} temp1Low _ uExp1, c2; temp1Low _ temp1Low - 2, c3; Ybus _ temp1Low, NegBr, c1; { check exponent = 1} {nominal value = (-1)^uSign1* *2^(temp1Low +2 -127)} normLoop: Ybus _ floatTemp, NegBr, BRANCH[$, lowExp], c2; temp1Low _ temp1Low - 1,NegBr, BRANCH[$, normed], c3; floatTemp _ DLShift1 floatTemp, SE _ 1, BRANCH[normLoop, smallNumber], c1; {At normed: nominal value = (-1)^uSign1**2^(temp1Low=3-127) and floatTemp[0]=1, therefore nominal exponent = temp1Low + 2, and nominal fraction = floatTemp[1],,Q[7]} {At smallNumber: nominal value = (-1)^uSign1**2^(temp1Low+2-127) and floatTemp = -1, therefore niminal fraction = floatTemp[1],,Q[7]. and nominal exponent= 1 if floatTemp[0]=1, else 0, i.e. -- niminal exponent = floatTemp[0]} {At LowExp: nominal value = (-1)^uSign1**2^(temp1Low+2-127) and temp1Low < 0} {we will shift right one bit , and add 1 to temp1Low, until temp1low = -1, then go to small number} {Note: this cose is very painful for an exponent of 1, maybe I should avoid arriving here under those conditions?} lowExp: temp2Low _ 25'd, CANCELBR[$], c3; Ybus _ temp1Low + temp2Low, NegBr, c1; temp2Low _ 1, BRANCH[$, veryLowExp], c2; Q _ ~Q, L3 _ L3.rePack1, c3; { to allow for complementing on right shifts } temp1Low _ -temp1Low - 1, CALL[deNormC2], c1; veryLowExp: GOTO[floatPrimitiveFail1], c3; smallNumberC1: Noop, c1, at[L3.rePack1, 10, deNormRets]; smallNumber: temp1Low _ RRot1 1, c2; temp1Low _ LRot1 (temp1Low and floatTemp), c3;{ temp1Low _ nominal exponent = floatTemp[0]} temp2Low _ RRot1 1, c1; floatTemp _ floatTemp or temp2Low, c2;{ floatTemp[0] _ 1} temp1Low _ temp1Low - 3, GOTO[normed], c3;{normed wants temp1Low to hold nominal exponent - 3} { nominal value = (-1)^uSign1**2^(temp1Low+3-127) and floatTemp[0]=1, therefore nominal exponent = temp1Low + 2, and nominal fraction = floatTemp[1]..Q[7]} {also entered from smallnumber, arranged so that nominal Fracrion =, floatTemp[0] = 1, and nominal exponent = temp1Low = 3} normed: CANCELBR[$], c1; {******************************** rounding code ************************** enter with L3 -- return link, uSticky prepared data if inexact result , will generate trap, or set sticky register bit, depending on contents of sticky register **************************************************************************} round: Ybus _ uStickyBit, NZeroBr, c2; temp2Low _ 377'b, BRANCH[roundA, roundB], c3; roundA: GOTO[roundC], c1; roundB: Q _ Q or 1, GOTO[roundC], c1; roundC: Ybus _ Q and temp2Low, ZeroBr, c2; temp2Low _ 200'b, BRANCH[inExact, roundExit1], c3; {now We round to nearest } inExact: Q _ Q + temp2Low, CarryBr, c1; temp2Low _ 177'b, BRANCH[$, inExact1], c2; Ybus _ Q and temp2Low, ZeroBr, c3; temp2Low _ LShift1 200'b, SE _ 0, BRANCH[roundExit2, $], c1; Q _ Q and ~temp2Low, GOTO[roundExit], c2; {Q[7] _ 0} {round off carried across word boundary } inExact1: floatTemp _ floatTemp + 1, CarryBr, c3; { overflow Branch since floatTemp[0]=1} BRANCH[roundExit2A, $], c1; temp1Low _ temp1Low + 1, GOTO[roundExit], c2; { round off overflowed, adjust exponent } roundExit2A: GOTO[roundExit], c2; roundExit1: Noop, c1; roundExit2: Noop, c2; roundExit: Noop, c3; {Now, we check for overflow and underflow } temp1Low _ temp1Low + 3, c1; temp2Low _ 376'b, c2; Ybus _ temp2Low - temp1Low, NegBr, c3; { branch if temp1Low >= 377'B} Ybus _ temp1Low, ZeroBr,BRANCH[$, overFlowOccur], c1; BRANCH[$, underFlowOccur], c2; temp3Low _ uSign1,GOTO[finalPack], c3; { temp3Low has the final sign } overFlowOccur: CANCELBR[floatPrimitiveFail3], c2; underFlowOccur: GOTO[floatPrimitiveFail1], c3; {sign = temp3Low, exponent = temp1Low, fractional part = floatTemp[1]...Q[7], floatTemp[0] = 1} finalPack: temp2Low _ 0FF, c1; Q _ Q and ~ temp2Low, c2; { bottom 8 bits of final result } temp2Low _ floatTemp and temp2Low, c3; { next 8 bits of final result } temp2Low _ temp2Low or Q, c1; temp2Low _ temp2Low LRot8, c2; { Low half of fractional part } uNewValLo _ temp2Low, c3; { store } temp1Low _ temp1Low LRot8, c1; temp1Low _ RRot1(temp1Low or temp3Low), c2; { sign,exponent part} floatTemp _ floatTemp LRot8, c3; floatTemp _ floatTemp and 7F, c1; { create high 7 bits of fractinal part } uNewValHi _ temp1Low or floatTemp, c2; { High half of fractional part } Noop, c3; finalPack5: Noop, c1; temp3Low _ classFloatPointer, c2; uClassToInstantiate _ temp3Low, c3; { Oop of floatClass } finalPack7: temp3Low _ 2, c1; { object size = 2 } temp3High _ creatingFloatInstance, c2; { return link for createInstance } CALL[createInstanceWithWordsInBank0], c3; { Go ! } {=== end: primitive 50 - FloatDivide ===} {=== begin: primitive 51 - Truncated ===} primitiveTruncated: { float Truncated primitive} {Q = 100'x, temp2Low = high half, temp3Low = Low half } uFloatFix _ temp2Low, c1, at[ 0D, 10, whatKindOfUnaryPrimitive]; PPort _ ~Q, c2; { to get the FPP status } FloatMode.RZ.PI.IEEE, FloatFLOW, c3; FloatA _ uFloatFix, FLFixA, c1; { High half & function } FloatA _ temp3Low LRot0, c2; { low half } FloatNop, c3; temp1Low _ 0C0, c1; temp1Low _ temp1Low LRot8, c2; { temp1Low _ 0C00 : to check the range} floatTemp _ floatTemp xor ~floatTemp, c3; { floatTemp _ FFFF : to check the range} FloatUnloadS, Float.M, c1; { to get high 8 bit of 24 bits integer } FloatUnloadS, Float.L, c2; { to get Low 16 bit of 24 bits integer } Q _ PPort, c3; { get the FPP status } temp2Low _ FloatResult, c1; temp3Low _ FloatResult, c2; [] _ Q, YDisp, c3; { dispatching by FPP Status } Q _ temp1Low xor ~ temp1Low, DISP4[FPPStatusFix,1], c1; fixOk: PPort _ Q, GOTO[checkRange], c2, at[0F, 10, FPPStatusFix]; { status OK } PPort _ Q, GOTO[checkRange], c2, at[0D, 10, FPPStatusFix]; {inexact occur: this case is for truncating the denormalized number } PPort _ Q, GOTO[floatPrimitiveFail3], c2, at[0B, 10, FPPStatusFix]; { Underflow } PPort _ Q, GOTO[floatPrimitiveFail3], c2, at[09, 10, FPPStatusFix]; { Underflow + Inexact } PPort _ Q, GOTO[floatPrimitiveFail3], c2, at[07, 10, FPPStatusFix]; { Unused } PPort _ Q, GOTO[floatPrimitiveFail3], c2, at[05, 10, FPPStatusFix]; { Overflow } PPort _ Q, GOTO[floatPrimitiveFail3], c2, at[03, 10, FPPStatusFix]; { Invalid operand } PPort _ Q, GOTO[floatPrimitiveFail3], c2, at[01, 10, FPPStatusFix]; { Denormalized operand at multiply } checkRange: { checking the fix number is in smallinteger's range } [] _ temp2Low, NegBr, c3; BRANCH[fixedNumberPlus, fixedNumberMinus], c1; fixedNumberPlus: [] _ temp2Low and floatTemp, ZeroBr, c2; [] _ temp3Low and temp1Low, ZeroBr, BRANCH[outOfRange1, $], c3; temp3Low _ LShift1 temp3Low, SE _ 1, BRANCH[outOfRange2, $], c1; { create the smallinteger } GOTO[finishFix], c2; fixedNumberMinus: [] _ temp2Low xor floatTemp, ZeroBr, c2; uSaveStackLow _ temp3Low and temp1Low, BRANCH[outOfRange3, $], c3; [] _ temp1Low xor uSaveStackLow, ZeroBr, c1; temp3Low _ LShift1 temp3Low, SE _ 1, BRANCH[outOfRange4, $], c2; { create the smallinteger } finishFix: floatTemp _ temp3Low, GOTO[unaryMessageReturn], c3; outOfRange1: CANCELBR[floatPrimitiveFail2], c1; outOfRange2: GOTO[floatPrimitiveFail3], c2; outOfRange3: CANCELBR[floatPrimitiveFail2], c1; outOfRange4: GOTO[floatPrimitiveFail1], c3; {=== end: primitive 51 - Truncated ===} {=== begin: primitive 52 - FractionalPart ===} primitiveFractionPart: { temp2Low, temp3Low has the Floating Number } temp1Low _ LRot1 temp2Low, c1, at[0E, 10, whatKindOfUnaryPrimitive]; floatTemp _ temp1Low and 1, c2; { sign } uSign1 _ floatTemp, c3; { save sign } fractionPart1: temp1Low _ temp1Low and ~0FF, c1; temp1Low _ temp1Low LRot8, c2; { Low byte = exponent} floatTemp _ temp1Low xor 0FF, c3; fractionPart2: [] _ floatTemp, ZeroBr, c1; { check Nan or Inf } floatTemp _ temp1Low, BRANCH[$, fractionPartNanOrInf], c2; temp1Low _ temp1Low - 7F, c3; fractionPart3: [] _ temp1Low, NegBr, c1; { minus the bias it means count for shift } Q _ temp3Low, BRANCH[$, returnJustReceiver], c2; { Q has low half of the fractional part} temp3Low _ temp2Low and 7F, c3; { high 7 bit of the fractional part} fractionPart4: temp1Low _ temp1Low + 1, c1; { create the shift counter } fractionPartShiftLoop: temp3Low _ DLShift1 temp3Low, SE _ 1, {Q.15 _ 0}, c2; { Left shift the fractional part } floatTemp _ floatTemp - 1, c3; { decrement the exponent } fractionPartShiftLoop1: temp1Low _ temp1Low - 1, ZeroBr, c1; { check shift counter } temp2Low _ 0FF, BRANCH[$, finishShift], c2; { temp2Low isused after shift operation is finished} Noop, c3; fractionPartShiftLoop2: GOTO[fractionPartShiftLoop], c1; finishShift: temp3Low _ temp3Low and temp2Low, c3; finishShift1: [] _ temp3Low or Q, ZeroBr, c1; { check fractional part = 0 } temp1Low _ 80, BRANCH[$, returnValueZero], c2; normalizeLoop: [] _ temp3Low and temp1Low, ZeroBr, c3; floatTemp _ floatTemp - 1, BRANCH[finishNormalize, $], c1; temp3Low _ DLShift1 temp3Low, SE _ 1,{Q.15 _ 0}, GOTO[normalizeLoop], c2; finishNormalize: floatTemp _ floatTemp + 1, c2; floatTemp _ floatTemp LRot8, c3; { expponent } floatTemp _ floatTemp or uSign1, c1; { or the sign } temp1Low _ RRot1 floatTemp, c2; temp3Low _ temp3Low and 7F, c3; { implict leading bit = 0} uNewValHi _ temp1Low or temp3Low, c1; { high half of the floating point number } uNewValLo _ Q, GOTO[returnResult3], c2; returnValueZero: uNewValHi _ temp1Low xor temp1Low, c3; uNewValLo _ temp1Low xor temp1Low, GOTO[returnResult2], c1; { creating the normal zero } returnJustReceiver: uNewValHi _ temp2Low, c3; uNewValLo _ temp3Low, GOTO[returnResult2], c1; returnResult2: Noop, c2; returnResult3: temp3High _ creatingFloatInstance, c3; temp3Low _ classFloatPointer, c1; uClassToInstantiate _ temp3Low, c2; temp3Low _ 2, CALL[createInstanceWithWordsInBank0], c3; fractionPartNanOrInf: CANCELBR[floatPrimitiveFail1], c3; {=== end: primitive 52 - FractionalPart ===} {=== begin: primitive 53 - Exponent ===} { definition: return the exponent value as a smallinteger. floating point number = normal Zero then return the -1 If receiver = Infinity or Nan then PrimitiveFail } primitiveExponent: floatTemp _ 7F, c1, at[0F, 10, whatKindOfUnaryPrimitive]; floatTemp _ floatTemp LRot8, c2; {7F00} floatTemp _ floatTemp or 0FF, c3; {make 7FFF} primitiveExponent1: floatTemp _ temp2Low and floatTemp, c1; { ignore sign} [] _ temp3Low or floatTemp, ZeroBr, c2; { check normal zero or not } BRANCH[notNormalZero, normalZero], c3; normalZero: floatTemp _ floatTemp xor ~floatTemp , GOTO[exponentReturnResult1], c1; { make the smallinteger (-1) } notNormalZero: temp2Low _ LRot1 temp2Low, c1; temp2Low _ temp2Low and ~0FF, c2; {high byte is exponent } floatTemp _ temp2Low xor ~0FF, c3; [] _ floatTemp, ZeroBr, c1; { check exponent = 0FF : Nan or Infinity } temp2Low _ temp2Low LRot8, BRANCH[$, exponentNanOrInf], c2; temp2Low _ temp2Low - 7F, c3; {NET = minus the bias from gross exponent } exponentReturnResult: floatTemp _ LShift1 temp2Low, SE _ 1, c1; exponentReturnResult1: Noop, c2; GOTO[unaryMessageReturn], c3; exponentNanOrInf: GOTO[floatPrimitiveFail1], c3; {=== endL Primitive 53 - Exponent ===} {=== begin: primitive 54 - TimesTwoPower ===} primitiveTimesTwoPower: MAR _ [stackHigh, stackLow + 0], c1; { point the argument } Noop, c2; temp1Low _ MD, XDisp, c3; { get argument and check that argument = smallinteger } [] _ temp1Low LRot0, XHDisp, {Determine the sign }BRANCH[primFailTimesTwoPower, $, 0E], c1; stackLow _ stackLow - 1, BRANCH[positiveInteger1, negativeInteger1, 2], c2; { point the receiver } positiveInteger1: temp1Low _ RShift1 temp1Low, SE _ 0, GOTO[getReceiver], c3; negativeInteger1: temp1Low _ RShift1 temp1Low, SE _ 1, c3; getReceiver: MAR _ [stackHigh, stackLow + 0], L1 _ getTimesTwoPowerReceiver, c1; uArg2Lo _ temp1Low, c2; { save the argument value } otLow _ MD, CALL[otMap1Bank0], c3; getReceiver1: temp1Low _ temp1Low + firstFieldOfObject, c1, at[getTimesTwoPowerReceiver, 10, otMap1Bank0-return]; stackLow _ stackLow + 1, c2; { reset the stack pointer } Q _ 0FF, c3; getReceiver2: MAR _ [temp1High, temp1Low + 0], c1; temp1Low _ temp1Low + 1, c2; temp2Low _ MD, c3; { get high half of the floating point number and check 0} getReceiver3: MAR _ [temp1High, temp1Low + 0], c1; floatTemp _ uArg2Lo, c2; { load the value for adding the exponent } temp3Low _ MD, c3; { get low half of the floating point number } getReciever3X: temp1Low _ 7F, c1; temp1Low _ temp1Low LRot8, c2; temp1Low _ temp1Low or 0FF, c3; { to neglect the sign } getReceiver3XX: [] _ temp1Low and temp2Low,ZeroBr, c1; [] _ temp3Low,ZeroBr, BRANCH[hHalfNonZero, hHalfZero], c2; hHalfZero: uNewValLo _ temp1Low xor temp1Low, BRANCH[lHalfNonZero, resultZero], c3; resultZero: uNewValHi _ temp1Low xor temp1Low, GOTO[storeResult], c1; hHalfNonZero: CANCELBR[getReceiver4], c3; lHalfNonZero: temp1Low _ LRot1 temp2Low,GOTO[getReceiver4X], c1; { high byte is exponent } getReceiver4: temp1Low _ LRot1 temp2Low, c1; { high byte is exponent } getReceiver4X: temp1Low _ temp1Low LRot8, c2; temp1Low _ temp1Low and Q, c3; { temp1Low has exponent } getReceiver5: [] _ temp1Low xor Q, ZeroBr, c1;{ chedk Nan or Inf } temp1Low _ temp1Low + floatTemp,NegBr,BRANCH[$, timesTwoPowerNanOrInf], c2; { Add & check Low boundary} Ybus _ temp1Low - Q,NegBr, BRANCH[$, exponentTooSmall], c3; { check high boundary } getReceiver7: uNewValLo _ temp3Low, BRANCH[exponentTooLarge, $], c1; { Low half of the floating point number } temp1Low _ temp1Low LRot8, c2; { high byte is exponent } temp2Low _ LRot1 temp2Low, c3; getReceiver8: temp2Low _ temp2Low and 0FF, c1; { clear the exponent part } temp1Low _ temp1Low or temp2Low , c2; { new exponent value is ored } temp1Low _ RRot1 temp1Low, c3; { finish the high half of the floating point } getReceiver9: uNewValHi _ temp1Low, c1; { get the high half of the result } storeResult: temp3High _ creatingFloatInstance, c2; { returnlink for createInstance } temp3Low _ classFloatPointer, c3; uClassToInstantiate _ temp3Low, c1; { class pointer for newly created object } temp3Low _ 2, c2; { temp3Low has the actual size, to create the floating point object} CALL[createInstanceWithWordsInBank0], c3; primFailTimesTwoPower: CANCELBR[floatPrimitiveFail3], c2; timesTwoPowerNanOrInf: CANCELBR[floatPrimitiveFail1], c3; exponentTooSmall: CANCELBR[floatPrimitiveFail2], c1; exponentTooLarge: GOTO[floatPrimitiveFail3], c2; {=== end: primitive 54 - TimesTwoPower ===}