Nicolas Cellier uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-nice.2554.mcz ==================== Summary ==================== Name: VMMaker.oscog-nice.2554 Author: nice Time: 6 September 2019, 8:02:06.906867 am UUID: 3c78a4ab-c017-48a8-a05d-f388052996de Ancestors: VMMaker.oscog-eem.2552 Undo the changes made in VMMaker.oscog-nice.2549 that broke jitted Float nan < 2.0 Replay Eliot's refactoring on old versions s/self genPrimitiveDoMixedArithmetic/coInterpreter primitiveDoMixedArithmetic/ Note: Float comparison are tricky on IA32/X64! The operator < (jb jump below) test for the carry flag (CF) like a jc, but this carry flag is also set when comparison is unordered !!! So we must first test the case of unordered, which also set (PF) with a jp. This is not necessary when using operators > (above) we can just ja (which is a jnc, case of unordered will set the carry and thus answer false). By transforming < into >, we avoid a JP conditional jump. Clever! In VMMaker.oscog-nice.2549, I wanted to simplify this, because I was not aware of this extra complexity. I'm not sure why nan >= works, because from what i read, unordered case also set the zero flag (ZF)... But since it works I stopped the analysis there... A short explanation should better be in code comments rather than just this commit message in order to prevent future wild refactorers to break it again ;) Fortunately we have test cases :) =============== Diff against VMMaker.oscog-eem.2552 =============== Item was removed: - ----- Method: CogObjectRepresentation>>genDoubleComparison: (in category 'primitive generators') ----- - genDoubleComparison: jumpOpcodeGenerator - - - | jumpFail jumpImmediate jumpNonInt jumpCond compare | - - - - - - cogit processorHasDoublePrecisionFloatingPointSupport ifFalse: - [^UnimplementedPrimitive]. - cogit genLoadArgAtDepth: 0 into: Arg0Reg. - self genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0. - jumpImmediate := self genJumpImmediate: Arg0Reg. - self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg. - self genCmpClassFloatCompactIndexR: SendNumArgsReg. - jumpFail := cogit JumpNonZero: 0. - self genGetDoubleValueOf: Arg0Reg into: DPFPReg1. - compare := cogit CmpRd: DPFPReg1 Rd: DPFPReg0. - jumpCond := cogit perform: jumpOpcodeGenerator with: 0. "FP jumps are a little weird" - cogit genMoveFalseR: ReceiverResultReg. - cogit genPrimReturn. - jumpCond jmpTarget: (cogit genMoveTrueR: ReceiverResultReg). - cogit genPrimReturn. - jumpImmediate jmpTarget: cogit Label. - self maybeGenConvertIfSmallFloatIn: Arg0Reg scratchReg: TempReg into: DPFPReg1 andJumpTo: compare. - self smallIntegerIsOnlyImmediateType ifFalse: - [jumpNonInt := self genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg]. - self genConvertSmallIntegerToIntegerInReg: Arg0Reg. - cogit ConvertR: Arg0Reg Rd: DPFPReg1. - cogit Jump: compare. - jumpFail jmpTarget: cogit Label. - self smallIntegerIsOnlyImmediateType ifFalse: - [jumpNonInt jmpTarget: jumpFail getJmpTarget]. - ^CompletePrimitive! Item was added: + ----- Method: CogObjectRepresentation>>genDoubleComparison:invert: (in category 'primitive generators') ----- + genDoubleComparison: jumpOpcodeGenerator invert: invertComparison + + + | jumpFail jumpImmediate jumpNonInt jumpCond compare | + + + + + + cogit processorHasDoublePrecisionFloatingPointSupport ifFalse: + [^UnimplementedPrimitive]. + cogit genLoadArgAtDepth: 0 into: Arg0Reg. + self genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0. + jumpImmediate := self genJumpImmediate: Arg0Reg. + self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg. + self genCmpClassFloatCompactIndexR: SendNumArgsReg. + jumpFail := cogit JumpNonZero: 0. + self genGetDoubleValueOf: Arg0Reg into: DPFPReg1. + invertComparison "May need to invert for NaNs" + ifTrue: [compare := cogit CmpRd: DPFPReg0 Rd: DPFPReg1] + ifFalse: [compare := cogit CmpRd: DPFPReg1 Rd: DPFPReg0]. + jumpCond := cogit perform: jumpOpcodeGenerator with: 0. "FP jumps are a little weird" + cogit genMoveFalseR: ReceiverResultReg. + cogit genPrimReturn. + jumpCond jmpTarget: (cogit genMoveTrueR: ReceiverResultReg). + cogit genPrimReturn. + jumpImmediate jmpTarget: cogit Label. + self maybeGenConvertIfSmallFloatIn: Arg0Reg scratchReg: TempReg into: DPFPReg1 andJumpTo: compare. + self smallIntegerIsOnlyImmediateType ifFalse: + [jumpNonInt := self genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg]. + self genConvertSmallIntegerToIntegerInReg: Arg0Reg. + cogit ConvertR: Arg0Reg Rd: DPFPReg1. + cogit Jump: compare. + jumpFail jmpTarget: cogit Label. + self smallIntegerIsOnlyImmediateType ifFalse: + [jumpNonInt jmpTarget: jumpFail getJmpTarget]. + ^CompletePrimitive! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveEqual (in category 'primitive generators') ----- genPrimitiveEqual ^coInterpreter primitiveDoMixedArithmetic ifTrue: [self genSmallIntegerComparison: JumpZero + orDoubleComparison: #JumpFPEqual: + invert: false] - orDoubleComparison: #JumpFPEqual:] ifFalse: [self genSmallIntegerComparison: JumpZero]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveFloatEqual (in category 'primitive generators') ----- genPrimitiveFloatEqual ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genDoubleComparison: #JumpFPEqual: invert: false] + ifFalse: [self genPureDoubleComparison: #JumpFPEqual: invert: false]! - ifTrue: [self genDoubleComparison: #JumpFPEqual:] - ifFalse: [self genPureDoubleComparison: #JumpFPEqual:]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveFloatGreaterOrEqual (in category 'primitive generators') ----- genPrimitiveFloatGreaterOrEqual ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genDoubleComparison: #JumpFPGreaterOrEqual: invert: false] + ifFalse: [self genPureDoubleComparison: #JumpFPGreaterOrEqual: invert: false]! - ifTrue: [self genDoubleComparison: #JumpFPGreaterOrEqual:] - ifFalse: [self genPureDoubleComparison: #JumpFPGreaterOrEqual:]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveFloatGreaterThan (in category 'primitive generators') ----- genPrimitiveFloatGreaterThan ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genDoubleComparison: #JumpFPGreater: invert: false] + ifFalse: [self genPureDoubleComparison: #JumpFPGreater: invert: false]! - ifTrue: [self genDoubleComparison: #JumpFPGreater:] - ifFalse: [self genPureDoubleComparison: #JumpFPGreater:]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveFloatLessOrEqual (in category 'primitive generators') ----- genPrimitiveFloatLessOrEqual ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genDoubleComparison: #JumpFPGreaterOrEqual: invert: true] + ifFalse: [self genPureDoubleComparison: #JumpFPGreaterOrEqual: invert: true]! - ifTrue: [self genDoubleComparison: #JumpFPLessOrEqual:] - ifFalse: [self genPureDoubleComparison: #JumpFPLessOrEqual:]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveFloatLessThan (in category 'primitive generators') ----- genPrimitiveFloatLessThan ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genDoubleComparison: #JumpFPGreater: invert: true] + ifFalse: [self genPureDoubleComparison: #JumpFPGreater: invert: true]! - ifTrue: [self genDoubleComparison: #JumpFPLess:] - ifFalse: [self genPureDoubleComparison: #JumpFPLess:]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveFloatNotEqual (in category 'primitive generators') ----- genPrimitiveFloatNotEqual ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genDoubleComparison: #JumpFPNotEqual: invert: false] + ifFalse: [self genPureDoubleComparison: #JumpFPNotEqual: invert: false]! - ifTrue: [self genDoubleComparison: #JumpFPNotEqual:] - ifFalse: [self genPureDoubleComparison: #JumpFPNotEqual:]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveGreaterOrEqual (in category 'primitive generators') ----- genPrimitiveGreaterOrEqual ^coInterpreter primitiveDoMixedArithmetic ifTrue: [self genSmallIntegerComparison: JumpGreaterOrEqual + orDoubleComparison: #JumpFPGreaterOrEqual: + invert: false] - orDoubleComparison: #JumpFPGreaterOrEqual:] ifFalse: [self genSmallIntegerComparison: JumpGreaterOrEqual]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveGreaterThan (in category 'primitive generators') ----- genPrimitiveGreaterThan ^coInterpreter primitiveDoMixedArithmetic ifTrue: [self genSmallIntegerComparison: JumpGreater + orDoubleComparison: #JumpFPGreater: + invert: false] - orDoubleComparison: #JumpFPGreater:] ifFalse: [self genSmallIntegerComparison: JumpGreater]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveLessOrEqual (in category 'primitive generators') ----- genPrimitiveLessOrEqual ^coInterpreter primitiveDoMixedArithmetic ifTrue: [self genSmallIntegerComparison: JumpLessOrEqual + orDoubleComparison: #JumpFPGreaterOrEqual: + invert: true] - orDoubleComparison: #JumpFPLessOrEqual:] ifFalse: [self genSmallIntegerComparison: JumpLessOrEqual]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveLessThan (in category 'primitive generators') ----- genPrimitiveLessThan ^coInterpreter primitiveDoMixedArithmetic ifTrue: [self genSmallIntegerComparison: JumpLess + orDoubleComparison: #JumpFPGreater: + invert: true] - orDoubleComparison: #JumpFPLess:] ifFalse: [self genSmallIntegerComparison: JumpLess]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveNotEqual (in category 'primitive generators') ----- genPrimitiveNotEqual ^coInterpreter primitiveDoMixedArithmetic ifTrue: [self genSmallIntegerComparison: JumpNonZero + orDoubleComparison: #JumpFPNotEqual: + invert: false] - orDoubleComparison: #JumpFPNotEqual:] ifFalse: [self genSmallIntegerComparison: JumpNonZero]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveSmallFloatEqual (in category 'primitive generators') ----- genPrimitiveSmallFloatEqual ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genSmallFloatComparison: #JumpFPEqual: orIntegerComparison: JumpZero invert: false] + ifFalse: [self genPureSmallFloatComparison: #JumpFPEqual: invert: false]! - ifTrue: [self genSmallFloatComparison: #JumpFPEqual: orIntegerComparison: JumpZero] - ifFalse: [self genPureSmallFloatComparison: #JumpFPEqual:]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveSmallFloatGreaterOrEqual (in category 'primitive generators') ----- genPrimitiveSmallFloatGreaterOrEqual ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genSmallFloatComparison: #JumpFPGreaterOrEqual: orIntegerComparison: JumpGreaterOrEqual invert: false] + ifFalse: [self genPureSmallFloatComparison: #JumpFPGreaterOrEqual: invert: false]! - ifTrue: [self genSmallFloatComparison: #JumpFPGreaterOrEqual: orIntegerComparison: JumpGreaterOrEqual ] - ifFalse: [self genPureSmallFloatComparison: #JumpFPGreaterOrEqual: ]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveSmallFloatGreaterThan (in category 'primitive generators') ----- genPrimitiveSmallFloatGreaterThan ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genSmallFloatComparison: #JumpFPGreater: orIntegerComparison: JumpGreater invert: false] + ifFalse: [self genPureSmallFloatComparison: #JumpFPGreater: invert: false]! - ifTrue: [self genSmallFloatComparison: #JumpFPGreater: orIntegerComparison: JumpGreater ] - ifFalse: [self genPureSmallFloatComparison: #JumpFPGreater: ]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveSmallFloatLessOrEqual (in category 'primitive generators') ----- genPrimitiveSmallFloatLessOrEqual ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genSmallFloatComparison: #JumpFPGreaterOrEqual: orIntegerComparison: JumpLessOrEqual invert: true] + ifFalse: [self genPureSmallFloatComparison: #JumpFPGreaterOrEqual: invert: true]! - ifTrue: [self genSmallFloatComparison: #JumpFPLessOrEqual: orIntegerComparison: JumpLessOrEqual ] - ifFalse: [self genPureSmallFloatComparison: #JumpFPLessOrEqual: ]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveSmallFloatLessThan (in category 'primitive generators') ----- genPrimitiveSmallFloatLessThan ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genSmallFloatComparison: #JumpFPGreater: orIntegerComparison: JumpLess invert: true] + ifFalse: [self genPureSmallFloatComparison: #JumpFPGreater: invert: true]! - ifTrue: [self genSmallFloatComparison: #JumpFPLess: orIntegerComparison: JumpLess ] - ifFalse: [self genPureSmallFloatComparison: #JumpFPLess: ]! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveSmallFloatNotEqual (in category 'primitive generators') ----- genPrimitiveSmallFloatNotEqual ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genSmallFloatComparison: #JumpFPNotEqual: orIntegerComparison: JumpNonZero invert: false] + ifFalse: [self genPureSmallFloatComparison: #JumpFPNotEqual: invert: false]! - ifTrue: [self genSmallFloatComparison: #JumpFPNotEqual: orIntegerComparison: JumpNonZero] - ifFalse: [self genPureSmallFloatComparison: #JumpFPNotEqual:]! Item was removed: - ----- Method: CogObjectRepresentation>>genPureDoubleComparison: (in category 'primitive generators') ----- - genPureDoubleComparison: jumpOpcodeGenerator - "In the Pure version, mixed arithmetic with SmallInteger is forbidden" - - - | jumpFail jumpImmediate jumpCond compare | - - - - - cogit processorHasDoublePrecisionFloatingPointSupport ifFalse: - [^UnimplementedPrimitive]. - cogit genLoadArgAtDepth: 0 into: Arg0Reg. - self genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0. - jumpImmediate := self genJumpImmediate: Arg0Reg. - self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg. - self genCmpClassFloatCompactIndexR: SendNumArgsReg. - jumpFail := cogit JumpNonZero: 0. - self genGetDoubleValueOf: Arg0Reg into: DPFPReg1. - compare := cogit CmpRd: DPFPReg1 Rd: DPFPReg0. - jumpCond := cogit perform: jumpOpcodeGenerator with: 0. "FP jumps are a little weird" - cogit genMoveFalseR: ReceiverResultReg. - cogit genPrimReturn. - jumpCond jmpTarget: (cogit genMoveTrueR: ReceiverResultReg). - cogit genPrimReturn. - jumpImmediate jmpTarget: cogit Label. - self maybeGenConvertIfSmallFloatIn: Arg0Reg scratchReg: TempReg into: DPFPReg1 andJumpTo: compare. - jumpFail jmpTarget: cogit Label. - ^CompletePrimitive! Item was added: + ----- Method: CogObjectRepresentation>>genPureDoubleComparison:invert: (in category 'primitive generators') ----- + genPureDoubleComparison: jumpOpcodeGenerator invert: invertComparison + "In the Pure version, mixed arithmetic with SmallInteger is forbidden" + + + | jumpFail jumpImmediate jumpCond compare | + + + + + cogit processorHasDoublePrecisionFloatingPointSupport ifFalse: + [^UnimplementedPrimitive]. + cogit genLoadArgAtDepth: 0 into: Arg0Reg. + self genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0. + jumpImmediate := self genJumpImmediate: Arg0Reg. + self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg. + self genCmpClassFloatCompactIndexR: SendNumArgsReg. + jumpFail := cogit JumpNonZero: 0. + self genGetDoubleValueOf: Arg0Reg into: DPFPReg1. + invertComparison "May need to invert for NaNs" + ifTrue: [compare := cogit CmpRd: DPFPReg0 Rd: DPFPReg1] + ifFalse: [compare := cogit CmpRd: DPFPReg1 Rd: DPFPReg0]. + jumpCond := cogit perform: jumpOpcodeGenerator with: 0. "FP jumps are a little weird" + cogit genMoveFalseR: ReceiverResultReg. + cogit genPrimReturn. + jumpCond jmpTarget: (cogit genMoveTrueR: ReceiverResultReg). + cogit genPrimReturn. + jumpImmediate jmpTarget: cogit Label. + self maybeGenConvertIfSmallFloatIn: Arg0Reg scratchReg: TempReg into: DPFPReg1 andJumpTo: compare. + jumpFail jmpTarget: cogit Label. + ^CompletePrimitive! Item was removed: - ----- Method: CogObjectRepresentation>>genSmallIntegerComparison:orDoubleComparison: (in category 'primitive generators') ----- - genSmallIntegerComparison: jumpOpcode orDoubleComparison: jumpFPOpcodeGenerator - "Stack looks like - return address" - | jumpNonInt jumpFail jumpCond r | - - - - - r := self genSmallIntegerComparison: jumpOpcode. - r < 0 ifTrue: - [^r]. - self cppIf: #DPFPReg0 defined ifTrue: - "Fall through on non-SmallInteger argument. Argument may be a Float : let us check or fail" - [self smallIntegerIsOnlyImmediateType ifFalse: - [jumpNonInt := self genJumpImmediate: Arg0Reg]. - self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg. - self genCmpClassFloatCompactIndexR: SendNumArgsReg. - jumpFail := cogit JumpNonZero: 0. - - "It was a Float, so convert the receiver to double and perform the operation" - self genConvertSmallIntegerToIntegerInReg: ReceiverResultReg. - cogit ConvertR: ReceiverResultReg Rd: DPFPReg0. - self genGetDoubleValueOf: Arg0Reg into: DPFPReg1. - cogit CmpRd: DPFPReg1 Rd: DPFPReg0. - jumpCond := cogit perform: jumpFPOpcodeGenerator with: 0. "FP jumps are a little weird" - cogit genMoveFalseR: ReceiverResultReg. - cogit genPrimReturn. - jumpCond jmpTarget: (cogit genMoveTrueR: ReceiverResultReg). - cogit genPrimReturn. - - self smallIntegerIsOnlyImmediateType - ifTrue: [jumpFail jmpTarget: cogit Label] - ifFalse: [jumpNonInt jmpTarget: (jumpFail jmpTarget: cogit Label)]]. - ^CompletePrimitive! Item was added: + ----- Method: CogObjectRepresentation>>genSmallIntegerComparison:orDoubleComparison:invert: (in category 'primitive generators') ----- + genSmallIntegerComparison: jumpOpcode orDoubleComparison: jumpFPOpcodeGenerator invert: invertComparison + "Stack looks like + return address" + | jumpNonInt jumpFail jumpCond r | + + + + + r := self genSmallIntegerComparison: jumpOpcode. + r < 0 ifTrue: + [^r]. + self cppIf: #DPFPReg0 defined ifTrue: + "Fall through on non-SmallInteger argument. Argument may be a Float : let us check or fail" + [self smallIntegerIsOnlyImmediateType ifFalse: + [jumpNonInt := self genJumpImmediate: Arg0Reg]. + self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg. + self genCmpClassFloatCompactIndexR: SendNumArgsReg. + jumpFail := cogit JumpNonZero: 0. + + "It was a Float, so convert the receiver to double and perform the operation" + self genConvertSmallIntegerToIntegerInReg: ReceiverResultReg. + cogit ConvertR: ReceiverResultReg Rd: DPFPReg0. + self genGetDoubleValueOf: Arg0Reg into: DPFPReg1. + invertComparison "May need to invert for NaNs" + ifTrue: [cogit CmpRd: DPFPReg0 Rd: DPFPReg1] + ifFalse: [cogit CmpRd: DPFPReg1 Rd: DPFPReg0]. + jumpCond := cogit perform: jumpFPOpcodeGenerator with: 0. "FP jumps are a little weird" + cogit genMoveFalseR: ReceiverResultReg. + cogit genPrimReturn. + jumpCond jmpTarget: (cogit genMoveTrueR: ReceiverResultReg). + cogit genPrimReturn. + + self smallIntegerIsOnlyImmediateType + ifTrue: [jumpFail jmpTarget: cogit Label] + ifFalse: [jumpNonInt jmpTarget: (jumpFail jmpTarget: cogit Label)]]. + ^CompletePrimitive! Item was removed: - ----- Method: CogObjectRepresentationFor64BitSpur>>genDoubleComparison:orIntegerComparison: (in category 'primitive generators') ----- - genDoubleComparison: jumpOpcodeGenerator orIntegerComparison: jumpOpcode - - ^self genFloatComparison: jumpOpcodeGenerator orIntegerComparison: jumpOpcode boxed: true! Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>genDoubleComparison:orIntegerComparison:invert: (in category 'primitive generators') ----- + genDoubleComparison: jumpOpcodeGenerator orIntegerComparison: jumpOpcode invert: invertComparison + + ^self genFloatComparison: jumpOpcodeGenerator orIntegerComparison: jumpOpcode invert: invertComparison boxed: true! Item was removed: - ----- Method: CogObjectRepresentationFor64BitSpur>>genFloatComparison:orIntegerComparison:boxed: (in category 'primitive generators') ----- - genFloatComparison: jumpFPOpcodeGenerator orIntegerComparison: jumpOpcode boxed: rcvrBoxed - - - | jumpImmediate jumpNotSmallFloat jumpNotSmallInteger jumpNotBoxedFloat jumpCond compareFloat jumpNotAmbiguous jumpTrue returnTrue | - - - - - - - - - - cogit genLoadArgAtDepth: 0 into: Arg0Reg. - rcvrBoxed - ifTrue: [self genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0] - ifFalse: [self genGetSmallFloatValueOf: ReceiverResultReg scratch: TempReg into: DPFPReg0]. - jumpNotSmallFloat := self genJumpNotSmallFloat: Arg0Reg. - self genGetSmallFloatValueOf: Arg0Reg scratch: TempReg into: DPFPReg1. - compareFloat := cogit CmpRd: DPFPReg1 Rd: DPFPReg0. - jumpCond := cogit perform: jumpFPOpcodeGenerator with: 0. "FP jumps are a little weird" - cogit genMoveFalseR: ReceiverResultReg. - cogit genPrimReturn. - jumpCond jmpTarget: (returnTrue := cogit genMoveTrueR: ReceiverResultReg). - cogit genPrimReturn. - - jumpNotSmallFloat jmpTarget: cogit Label. - jumpNotSmallInteger := self genJumpNotSmallInteger: Arg0Reg. - "Test for ambiguity, that is when floatRcvr == (double) intArg" - self genConvertSmallIntegerToIntegerInReg: Arg0Reg. - cogit ConvertR: Arg0Reg Rd: DPFPReg1. - cogit CmpRd: DPFPReg1 Rd: DPFPReg0. - "If floatRcvr !!= (double) intArg then use compareFloat(floatRcvr,(double) intArg)" - "else use compareInt(intArg,(int64) floatRcvr)" - jumpNotAmbiguous := cogit perform: #JumpFPNotEqual: with: 0. - "Case of non ambiguity, use compareFloat(floatRcvr,(double) intArg)" - jumpNotAmbiguous jmpTarget: compareFloat. - "Case of ambiguity, use compareInt((int64) floatRcvr, intArg)" - cogit ConvertRd: DPFPReg0 R: ReceiverResultReg. - cogit CmpR: Arg0Reg R: ReceiverResultReg. "N.B. FLAGS := RRReg - Arg0Reg" - jumpTrue := cogit genConditionalBranch: jumpOpcode operand: 0. - cogit genMoveFalseR: ReceiverResultReg. - cogit genPrimReturn. - jumpTrue jmpTarget: returnTrue. - - "not a Small Float, nor Small Integer, check for Boxed Float argument" - jumpNotSmallInteger jmpTarget: cogit Label. - jumpImmediate := self genJumpImmediate: Arg0Reg. - self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg. - self genCmpClassFloatCompactIndexR: SendNumArgsReg. - jumpNotBoxedFloat := cogit JumpNonZero: 0. - self genGetDoubleValueOf: Arg0Reg into: DPFPReg1. - cogit Jump: compareFloat. - - jumpImmediate jmpTarget: - (jumpNotBoxedFloat jmpTarget: cogit Label). - ^CompletePrimitive! Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>genFloatComparison:orIntegerComparison:invert:boxed: (in category 'primitive generators') ----- + genFloatComparison: jumpFPOpcodeGenerator orIntegerComparison: jumpOpcode invert: invertComparison boxed: rcvrBoxed + + + | jumpImmediate jumpNotSmallFloat jumpNotSmallInteger jumpNotBoxedFloat jumpCond compareFloat jumpAmbiguous jumpTrue returnTrue | + + + + + + + + + + cogit genLoadArgAtDepth: 0 into: Arg0Reg. + rcvrBoxed + ifTrue: [self genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0] + ifFalse: [self genGetSmallFloatValueOf: ReceiverResultReg scratch: TempReg into: DPFPReg0]. + jumpNotSmallFloat := self genJumpNotSmallFloat: Arg0Reg. + self genGetSmallFloatValueOf: Arg0Reg scratch: TempReg into: DPFPReg1. + compareFloat := invertComparison "May need to invert for NaNs" + ifTrue: [cogit CmpRd: DPFPReg0 Rd: DPFPReg1] + ifFalse: [cogit CmpRd: DPFPReg1 Rd: DPFPReg0]. + jumpCond := cogit perform: jumpFPOpcodeGenerator with: 0. "FP jumps are a little weird" + cogit genMoveFalseR: ReceiverResultReg. + cogit genPrimReturn. + jumpCond jmpTarget: (returnTrue := cogit genMoveTrueR: ReceiverResultReg). + cogit genPrimReturn. + + jumpNotSmallFloat jmpTarget: cogit Label. + jumpNotSmallInteger := self genJumpNotSmallInteger: Arg0Reg. + "Test for ambiguity, that is when floatRcvr == (double) intArg" + self genConvertSmallIntegerToIntegerInReg: Arg0Reg. + cogit ConvertR: Arg0Reg Rd: DPFPReg1. + cogit CmpRd: DPFPReg0 Rd: DPFPReg1. + "If floatRcvr == (double) intArg then use compareInt(intArg,(int64) floatRcvr)" + "else use compareFloat(floatRcvr,(double) intArg)" + jumpAmbiguous := cogit perform: #JumpFPEqual: with: 0. + "Case of non ambiguity, use compareFloat(floatRcvr,(double) intArg)" + cogit Jump: compareFloat. + "Case of ambiguity, use compareInt((int64) floatRcvr, intArg)" + jumpAmbiguous jmpTarget: (cogit ConvertRd: DPFPReg0 R: ReceiverResultReg). + cogit CmpR: Arg0Reg R: ReceiverResultReg. "N.B. FLAGS := RRReg - Arg0Reg" + jumpTrue := cogit genConditionalBranch: jumpOpcode operand: 0. + cogit genMoveFalseR: ReceiverResultReg. + cogit genPrimReturn. + jumpTrue jmpTarget: returnTrue. + + "not a Small Float, nor Small Integer, check for Boxed Float argument" + jumpNotSmallInteger jmpTarget: cogit Label. + jumpImmediate := self genJumpImmediate: Arg0Reg. + self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg. + self genCmpClassFloatCompactIndexR: SendNumArgsReg. + jumpNotBoxedFloat := cogit JumpNonZero: 0. + self genGetDoubleValueOf: Arg0Reg into: DPFPReg1. + cogit Jump: compareFloat. + + jumpImmediate jmpTarget: + (jumpNotBoxedFloat jmpTarget: cogit Label). + ^CompletePrimitive! Item was changed: ----- Method: CogObjectRepresentationFor64BitSpur>>genPrimitiveFloatEqual (in category 'primitive generators') ----- genPrimitiveFloatEqual ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genDoubleComparison: #JumpFPEqual: orIntegerComparison: JumpZero invert: false] + ifFalse: [self genPureDoubleComparison: #JumpFPEqual: invert: false]! - ifTrue: [self genDoubleComparison: #JumpFPEqual: orIntegerComparison: JumpZero] - ifFalse: [self genPureDoubleComparison: #JumpFPEqual:]! Item was changed: ----- Method: CogObjectRepresentationFor64BitSpur>>genPrimitiveFloatGreaterOrEqual (in category 'primitive generators') ----- genPrimitiveFloatGreaterOrEqual ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genDoubleComparison: #JumpFPGreaterOrEqual: orIntegerComparison: JumpGreaterOrEqual invert: false] + ifFalse: [self genPureDoubleComparison: #JumpFPGreaterOrEqual: invert: false]! - ifTrue: [self genDoubleComparison: #JumpFPGreaterOrEqual: orIntegerComparison: JumpGreaterOrEqual] - ifFalse: [self genPureDoubleComparison: #JumpFPGreaterOrEqual:]! Item was changed: ----- Method: CogObjectRepresentationFor64BitSpur>>genPrimitiveFloatGreaterThan (in category 'primitive generators') ----- genPrimitiveFloatGreaterThan ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genDoubleComparison: #JumpFPGreater: orIntegerComparison: JumpGreater invert: false] + ifFalse: [self genPureDoubleComparison: #JumpFPGreater: invert: false]! - ifTrue: [self genDoubleComparison: #JumpFPGreater: orIntegerComparison: JumpGreater] - ifFalse: [self genPureDoubleComparison: #JumpFPGreater:]! Item was changed: ----- Method: CogObjectRepresentationFor64BitSpur>>genPrimitiveFloatLessOrEqual (in category 'primitive generators') ----- genPrimitiveFloatLessOrEqual ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genDoubleComparison: #JumpFPGreaterOrEqual: orIntegerComparison: JumpLessOrEqual invert: true] + ifFalse: [self genPureDoubleComparison: #JumpFPGreaterOrEqual: invert: true]! - ifTrue: [self genDoubleComparison: #JumpFPLessOrEqual: orIntegerComparison: JumpLessOrEqual] - ifFalse: [self genPureDoubleComparison: #JumpFPLessOrEqual:]! Item was changed: ----- Method: CogObjectRepresentationFor64BitSpur>>genPrimitiveFloatLessThan (in category 'primitive generators') ----- genPrimitiveFloatLessThan ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genDoubleComparison: #JumpFPGreater: orIntegerComparison: JumpLess invert: true] + ifFalse: [self genPureDoubleComparison: #JumpFPGreater: invert: true]! - ifTrue: [self genDoubleComparison: #JumpFPLess: orIntegerComparison: JumpLess] - ifFalse: [self genPureDoubleComparison: #JumpFPLess:]! Item was changed: ----- Method: CogObjectRepresentationFor64BitSpur>>genPrimitiveFloatNotEqual (in category 'primitive generators') ----- genPrimitiveFloatNotEqual ^coInterpreter primitiveDoMixedArithmetic + ifTrue: [self genDoubleComparison: #JumpFPNotEqual: orIntegerComparison: JumpNonZero invert: false] + ifFalse: [self genPureDoubleComparison: #JumpFPNotEqual: invert: false]! - ifTrue: [self genDoubleComparison: #JumpFPNotEqual: orIntegerComparison: JumpNonZero] - ifFalse: [self genPureDoubleComparison: #JumpFPNotEqual:]! Item was removed: - ----- Method: CogObjectRepresentationFor64BitSpur>>genPureDoubleComparison: (in category 'primitive generators') ----- - genPureDoubleComparison: jumpOpcodeGenerator - "In the Pure version, mixed arithmetic with SmallInteger is forbidden" - - ^self genPureFloatComparison: jumpOpcodeGenerator boxed: true! Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>genPureDoubleComparison:invert: (in category 'primitive generators') ----- + genPureDoubleComparison: jumpOpcodeGenerator invert: invertComparison + "In the Pure version, mixed arithmetic with SmallInteger is forbidden" + + ^self genPureFloatComparison: jumpOpcodeGenerator invert: invertComparison boxed: true! Item was removed: - ----- Method: CogObjectRepresentationFor64BitSpur>>genPureFloatComparison:boxed: (in category 'primitive generators') ----- - genPureFloatComparison: jumpFPOpcodeGenerator boxed: rcvrBoxed - "In the Pure version, mixed arithmetic with SmallInteger is forbidden" - - - | jumpImmediate jumpNotSmallFloat jumpNotBoxedFloat jumpCond compareFloat | - - - - - - cogit genLoadArgAtDepth: 0 into: Arg0Reg. - rcvrBoxed - ifTrue: [self genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0] - ifFalse: [self genGetSmallFloatValueOf: ReceiverResultReg scratch: TempReg into: DPFPReg0]. - jumpNotSmallFloat := self genJumpNotSmallFloat: Arg0Reg. - self genGetSmallFloatValueOf: Arg0Reg scratch: TempReg into: DPFPReg1. - compareFloat := cogit CmpRd: DPFPReg1 Rd: DPFPReg0. - jumpCond := cogit perform: jumpFPOpcodeGenerator with: 0. "FP jumps are a little weird" - cogit genMoveFalseR: ReceiverResultReg. - cogit genPrimReturn. - jumpCond jmpTarget: (cogit genMoveTrueR: ReceiverResultReg). - cogit genPrimReturn. - - "not a Small Float, check for Boxed Float argument" - jumpNotSmallFloat jmpTarget: cogit Label. - jumpImmediate := self genJumpImmediate: Arg0Reg. - self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg. - self genCmpClassFloatCompactIndexR: SendNumArgsReg. - jumpNotBoxedFloat := cogit JumpNonZero: 0. - self genGetDoubleValueOf: Arg0Reg into: DPFPReg1. - cogit Jump: compareFloat. - - jumpImmediate jmpTarget: - (jumpNotBoxedFloat jmpTarget: cogit Label). - ^CompletePrimitive! Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>genPureFloatComparison:invert:boxed: (in category 'primitive generators') ----- + genPureFloatComparison: jumpFPOpcodeGenerator invert: invertComparison boxed: rcvrBoxed + "In the Pure version, mixed arithmetic with SmallInteger is forbidden" + + + | jumpImmediate jumpNotSmallFloat jumpNotBoxedFloat jumpCond compareFloat | + + + + + + cogit genLoadArgAtDepth: 0 into: Arg0Reg. + rcvrBoxed + ifTrue: [self genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0] + ifFalse: [self genGetSmallFloatValueOf: ReceiverResultReg scratch: TempReg into: DPFPReg0]. + jumpNotSmallFloat := self genJumpNotSmallFloat: Arg0Reg. + self genGetSmallFloatValueOf: Arg0Reg scratch: TempReg into: DPFPReg1. + compareFloat := invertComparison "May need to invert for NaNs" + ifTrue: [cogit CmpRd: DPFPReg0 Rd: DPFPReg1] + ifFalse: [cogit CmpRd: DPFPReg1 Rd: DPFPReg0]. + jumpCond := cogit perform: jumpFPOpcodeGenerator with: 0. "FP jumps are a little weird" + cogit genMoveFalseR: ReceiverResultReg. + cogit genPrimReturn. + jumpCond jmpTarget: (cogit genMoveTrueR: ReceiverResultReg). + cogit genPrimReturn. + + "not a Small Float, check for Boxed Float argument" + jumpNotSmallFloat jmpTarget: cogit Label. + jumpImmediate := self genJumpImmediate: Arg0Reg. + self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg. + self genCmpClassFloatCompactIndexR: SendNumArgsReg. + jumpNotBoxedFloat := cogit JumpNonZero: 0. + self genGetDoubleValueOf: Arg0Reg into: DPFPReg1. + cogit Jump: compareFloat. + + jumpImmediate jmpTarget: + (jumpNotBoxedFloat jmpTarget: cogit Label). + ^CompletePrimitive! Item was removed: - ----- Method: CogObjectRepresentationFor64BitSpur>>genPureSmallFloatComparison: (in category 'primitive generators') ----- - genPureSmallFloatComparison: jumpOpcodeGenerator - "In the Pure version, mixed arithmetic with SmallInteger is forbidden" - - ^self genPureFloatComparison: jumpOpcodeGenerator boxed: false! Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>genPureSmallFloatComparison:invert: (in category 'primitive generators') ----- + genPureSmallFloatComparison: jumpOpcodeGenerator invert: invertComparison + "In the Pure version, mixed arithmetic with SmallInteger is forbidden" + + ^self genPureFloatComparison: jumpOpcodeGenerator invert: invertComparison boxed: false! Item was removed: - ----- Method: CogObjectRepresentationFor64BitSpur>>genSmallFloatComparison:orIntegerComparison: (in category 'primitive generators') ----- - genSmallFloatComparison: jumpOpcodeGenerator orIntegerComparison: jumpOpcode - - ^self genFloatComparison: jumpOpcodeGenerator orIntegerComparison: jumpOpcode boxed: false! Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>genSmallFloatComparison:orIntegerComparison:invert: (in category 'primitive generators') ----- + genSmallFloatComparison: jumpOpcodeGenerator orIntegerComparison: jumpOpcode invert: invertComparison + + ^self genFloatComparison: jumpOpcodeGenerator orIntegerComparison: jumpOpcode invert: invertComparison boxed: false! Item was removed: - ----- Method: CogObjectRepresentationFor64BitSpur>>genSmallIntegerComparison:orDoubleComparison: (in category 'primitive generators') ----- - genSmallIntegerComparison: jumpOpcode orDoubleComparison: jumpFPOpcodeGenerator - "Stack looks like - return address" - | jumpCond r compareIntFloat jumpAmbiguous jumpNotBoxedFloat jumpNotFloatAtAll jumpNotSmallFloat jumpTrue returnTrue | - - - - - - - - - - - r := self genSmallIntegerComparison: jumpOpcode. - r < 0 ifTrue: - [^r]. - self cppIf: #DPFPReg0 defined ifTrue: - "Fall through on non-SmallInteger argument. Argument may be a Float : let us check or fail" - [ - "check for Small Float argument" - jumpNotSmallFloat := self genJumpNotSmallFloat: Arg0Reg. - self genGetSmallFloatValueOf: Arg0Reg scratch: TempReg into: DPFPReg1. - - "Case of (int compare: float). Test for ambiguity, that is when (double) intRcvr == floatArg" - compareIntFloat := cogit Label. - self genConvertSmallIntegerToIntegerInReg: ReceiverResultReg. - cogit ConvertR: ReceiverResultReg Rd: DPFPReg0. - cogit CmpRd: DPFPReg0 Rd: DPFPReg1. - jumpAmbiguous := cogit perform: #JumpFPEqual: with: 0. - "Case of non ambiguity, use compareFloat((double) intRcvr,floatArg)" - cogit CmpRd: DPFPReg1 Rd: DPFPReg0. - jumpCond := cogit perform: jumpFPOpcodeGenerator with: 0. "FP jumps are a little weird" - cogit genMoveFalseR: ReceiverResultReg. - cogit genPrimReturn. - jumpCond jmpTarget: (returnTrue := cogit genMoveTrueR: ReceiverResultReg). - cogit genPrimReturn. - "Case of ambiguity, use compareInt(intRcvr , (int64) floatArg)" - jumpAmbiguous jmpTarget: (cogit ConvertRd: DPFPReg1 R: Arg0Reg). - cogit CmpR: Arg0Reg R: ReceiverResultReg. "N.B. FLAGS := RRReg - Arg0Reg" - jumpTrue := cogit genConditionalBranch: jumpOpcode operand: 0. - cogit genMoveFalseR: ReceiverResultReg. - cogit genPrimReturn. - jumpTrue jmpTarget: returnTrue. - - "not a Small Float, check for Boxed Float argument" - jumpNotSmallFloat jmpTarget: (jumpNotFloatAtAll := self genJumpImmediate: Arg0Reg). - self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg. - self genCmpClassFloatCompactIndexR: SendNumArgsReg. - jumpNotBoxedFloat := cogit JumpNonZero: 0. - "It was a Boxed Float, so convert the receiver to double and perform the (int compare: float) operation" - self genGetDoubleValueOf: Arg0Reg into: DPFPReg1. - cogit Jump: compareIntFloat. - - "not a Float, just let the primitive fall thru failure" - jumpNotBoxedFloat jmpTarget: (jumpNotFloatAtAll jmpTarget: cogit Label)]. - ^CompletePrimitive! Item was added: + ----- Method: CogObjectRepresentationFor64BitSpur>>genSmallIntegerComparison:orDoubleComparison:invert: (in category 'primitive generators') ----- + genSmallIntegerComparison: jumpOpcode orDoubleComparison: jumpFPOpcodeGenerator invert: invertComparison + "Stack looks like + return address" + | jumpCond r compareIntFloat jumpAmbiguous jumpNotBoxedFloat jumpNotFloatAtAll jumpNotSmallFloat jumpTrue returnTrue | + + + + + + + + + + + r := self genSmallIntegerComparison: jumpOpcode. + r < 0 ifTrue: + [^r]. + self cppIf: #DPFPReg0 defined ifTrue: + "Fall through on non-SmallInteger argument. Argument may be a Float : let us check or fail" + [ + "check for Small Float argument" + jumpNotSmallFloat := self genJumpNotSmallFloat: Arg0Reg. + self genGetSmallFloatValueOf: Arg0Reg scratch: TempReg into: DPFPReg1. + + "Case of (int compare: float). Test for ambiguity, that is when (double) intRcvr == floatArg" + compareIntFloat := cogit Label. + self genConvertSmallIntegerToIntegerInReg: ReceiverResultReg. + cogit ConvertR: ReceiverResultReg Rd: DPFPReg0. + cogit CmpRd: DPFPReg0 Rd: DPFPReg1. + jumpAmbiguous := cogit perform: #JumpFPEqual: with: 0. + "Case of non ambiguity, use compareFloat((double) intRcvr,floatArg)" + invertComparison "May need to invert for NaNs" + ifTrue: [cogit CmpRd: DPFPReg0 Rd: DPFPReg1] + ifFalse: [cogit CmpRd: DPFPReg1 Rd: DPFPReg0]. + jumpCond := cogit perform: jumpFPOpcodeGenerator with: 0. "FP jumps are a little weird" + cogit genMoveFalseR: ReceiverResultReg. + cogit genPrimReturn. + jumpCond jmpTarget: (returnTrue := cogit genMoveTrueR: ReceiverResultReg). + cogit genPrimReturn. + "Case of ambiguity, use compareInt(intRcvr , (int64) floatArg)" + jumpAmbiguous jmpTarget: (cogit ConvertRd: DPFPReg1 R: Arg0Reg). + cogit CmpR: Arg0Reg R: ReceiverResultReg. "N.B. FLAGS := RRReg - Arg0Reg" + jumpTrue := cogit genConditionalBranch: jumpOpcode operand: 0. + cogit genMoveFalseR: ReceiverResultReg. + cogit genPrimReturn. + jumpTrue jmpTarget: returnTrue. + + "not a Small Float, check for Boxed Float argument" + jumpNotSmallFloat jmpTarget: (jumpNotFloatAtAll := self genJumpImmediate: Arg0Reg). + self genGetCompactClassIndexNonImmOf: Arg0Reg into: SendNumArgsReg. + self genCmpClassFloatCompactIndexR: SendNumArgsReg. + jumpNotBoxedFloat := cogit JumpNonZero: 0. + "It was a Boxed Float, so convert the receiver to double and perform the (int compare: float) operation" + self genGetDoubleValueOf: Arg0Reg into: DPFPReg1. + cogit Jump: compareIntFloat. + + "not a Float, just let the primitive fall thru failure" + jumpNotBoxedFloat jmpTarget: (jumpNotFloatAtAll jmpTarget: cogit Label)]. + ^CompletePrimitive!