{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 * <floatTemp[0].floatTemp[1],,,Q[7]>*2↑(uExp1 - 127)} temp1Low ← uExp1, c2; temp1Low ← temp1Low - 2, c3; Ybus ← temp1Low, NegBr, c1; { check exponent = 1} {nominal value = (-1)↑uSign1* <floatTemp[0].floatTemp[1],,Q[7]> *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*<floatTemp[0].floatTemp[1],,Q[7]>*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*<floatTemp[0].floatTemp[1],,Q[7]>*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*<floatTemp[0].floatTemp[1]..Q[7]>*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*<floatTemp[0].floatTemp[1],,..>*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[1]....>, floatTemp[0] = 1, and nominal exponent = temp1Low = 3} normed: CANCELBR[$], c1; {******************************** rounding code ************************** enter with L3 -- return link, uSticky prepared data <floatTemp,Q> 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 ===}