Nicolas Cellier uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-nice.2712.mcz ==================== Summary ==================== Name: VMMaker.oscog-nice.2712 Author: nice Time: 17 February 2020, 9:43:10.142295 pm UUID: da64ef0b-fb0a-4770-ac16-f9b448234615 Ancestors: VMMaker.oscog-nice.2711 Fix alternative code generation for highBit via BSR for Spur32: Previous opcode is a Label, so we cannot test if it setsConditionCodesFor: JumpNegative. We have to force a CmpCq:R:. For X64, it's OK, previous opcode is an arithmetic shift. Fix simulation of primitiveHighBit by sending #numSmallIntegerTagBits to the objectMemory which knows this kind of memory layout detail. While at it, change the order of BSR registers maskReg -> destReg, like any other CogRTLOpcodes, rather than destReg <- maskReg. =============== Diff against VMMaker.oscog-nice.2711 =============== Item was changed: ----- Method: CogIA32Compiler>>concretizeBSR (in category 'generate machine code - concretize') ----- concretizeBSR "Bit Scan Reverse + First operand is input register (mask) + Second operand is output register (dest)" - First operand is output register (dest) - Second operand is input register (mask)" "BSR" <inline: true> | dest mask | + mask := operands at: 0. + dest := operands at: 1. - dest := operands at: 0. - mask := operands at: 1. machineCode at: 0 put: 16r0F; at: 1 put: 16rBD; at: 2 put: (self mod: ModReg RM: dest RO: mask). ^3! Item was changed: ----- Method: CogIA32Compiler>>genHighBitAlternativeIn:ofSmallIntegerOopWithSingleTagBit: (in category 'abstract instructions') ----- genHighBitAlternativeIn: destReg ofSmallIntegerOopWithSingleTagBit: srcReg "When CLZ is not available, we can use BSR (Bit Scan Reverse) instruction" <inline: true> | jumpNegativeReceiver | <var: #jumpNegativeReceiver type: #'AbstractInstruction *'> <returnTypeC: #'AbstractInstruction *'> "The primitive must fail if receiver is negative" + cogit CmpCq: 0 R: srcReg. "N.B. FLAGS := srcReg - 0" - (cogit lastOpcode setsConditionCodesFor: JumpNegative) ifFalse: - [cogit CmpCq: 0 R: srcReg]. "N.B. FLAGS := srcReg - 0" jumpNegativeReceiver := cogit JumpNegative: 0. + cogit gen: BSR operand: srcReg operand: destReg. - cogit gen: BSR operand: destReg operand: srcReg. "theoretically we should handle case when srcReg is zero, but we do not care because it is never zero thanks to the tagBit" "and thanks to the tag bit, the +1 operation for getting 1-based rank instead of 0-based rank is not necessary, so we are done" ^jumpNegativeReceiver! Item was changed: ----- Method: CogX64Compiler>>concretizeBSR (in category 'generate machine code - concretize') ----- concretizeBSR "Bit Scan Reverse + First operand is input register (mask) + Second operand is output register (dest)" - First operand is output register (dest) - Second operand is input register (mask)" "BSR" <inline: true> | dest mask | + mask := operands at: 0. + dest := operands at: 1. - dest := operands at: 0. - mask := operands at: 1. (dest <= 7 and: [mask <= 7]) ifTrue: [machineCode at: 0 put: (self rexw: true r: 0 x: 0 b: 0)] ifFalse: ["Beware: operation is on 32bits for R8-15"machineCode at: 0 put: (self rexw: false r: 0 x: 0 b: 0)]. machineCode at: 1 put: 16r0F; at: 2 put: 16rBD; at: 3 put: (self mod: ModReg RM: dest RO: mask). ^4! Item was changed: ----- Method: CogX64Compiler>>genHighBitAlternativeIn:ofSmallIntegerOopWithSingleTagBit: (in category 'abstract instructions') ----- genHighBitAlternativeIn: destReg ofSmallIntegerOopWithSingleTagBit: srcReg "When CLZ is not available, we can use BSR (Bit Scan Reverse) instruction. BEWARE: make sure that srcReg has a single tag bit." <inline: true> | jumpNegativeReceiver | <var: #jumpNegativeReceiver type: #'AbstractInstruction *'> <returnTypeC: #'AbstractInstruction *'> "The primitive must fail if receiver is negative" (cogit lastOpcode setsConditionCodesFor: JumpNegative) ifFalse: [cogit CmpCq: 0 R: srcReg]. "N.B. FLAGS := srcReg - 0" jumpNegativeReceiver := cogit JumpNegative: 0. + cogit gen: BSR operand: srcReg operand: destReg. - cogit gen: BSR operand: destReg operand: srcReg. "theoretically we should handle case when srcReg is zero, but we do not care because it is never zero thanks to the tagBit" "and thanks to the tag bit, the +1 operation for getting 1-based rank instead of 0-based rank is not necessary, so we are done" ^jumpNegativeReceiver! Item was changed: ----- Method: InterpreterPrimitives>>primitiveHighBit (in category 'arithmetic integer primitives') ----- primitiveHighBit | integerReceiverOop leadingZeroCount highestBitZeroBased | integerReceiverOop := self stackTop. "Convert the receiver Oop to use a single tag bit" + objectMemory numSmallIntegerTagBits > 1 - self numSmallIntegerTagBits > 1 ifTrue: [integerReceiverOop := (integerReceiverOop >>> (self numSmallIntegerTagBits-1) bitOr: 1)]. self cppIf: #'__GNUC__' defined ifTrue: ["Note: in gcc, result is undefined if input is zero (for compatibility with BSR fallback when no CLZ instruction available). but input is never zero because we pass the oop with tag bits set, so we are safe" objectMemory wordSize = 4 ifTrue: [leadingZeroCount := self __builtin_clz: integerReceiverOop] ifFalse: [leadingZeroCount := self __builtin_clzll: integerReceiverOop]. leadingZeroCount = 0 ifTrue: ["highBit is not defined for negative Integer" self primitiveFail] ifFalse: ["Nice bit trick: 1-based high-bit is (32 - clz) - 1 to account for tag bit. This is like two-complement - clz - 1 on 5 bits, or in other words a bit-invert operation clz ^16r1F" self pop: 1 thenPushInteger: (leadingZeroCount bitXor: (BytesPerWord * 8 - 1))]. ^self]. self cppIf: #'__GNUC__' defined not & (#'_MSC_VER' defined | #'__ICC' defined) ifTrue: ["In MSVC, _lzcnt and _lzcnt64 builtins do not fallback to BSR when not supported by CPU Instead of messing with __cpuid() we always use the BSR intrinsic" "Trick: we test the oop sign rather than the integerValue. Assume oop are signed (so far, they are, sqInt are signed)" integerReceiverOop < 0 ifTrue: [self primitiveFail] ifFalse: [ "Setting this variable is useless, but VMMaker will generate it at a worse place" highestBitZeroBased := 0. "We do not even test the return value, because integerReceiverOop is never zero" self cCode: [objectMemory wordSize = 4 ifTrue: [self _BitScanReverse: highestBitZeroBased address _: integerReceiverOop] ifFalse: [self _BitScanReverse64: highestBitZeroBased address _: integerReceiverOop]] inSmalltalk: [highestBitZeroBased := integerReceiverOop highBit - 1]. "thanks to the tag bit, the +1 operation for getting 1-based rank is not necessary" self pop: 1 thenPushInteger: highestBitZeroBased]. ^self]. self cppIf: #'__GNUC__' defined not & #'_MSC_VER' defined not & #'__ICC' defined not ifTrue: ["not gcc/clang, nor MSVC/ICC, you have to implement if your compiler provide useful builtins" self cCode: [self primitiveFail] inSmalltalk: "Simulate so that the simulatror is closer to the actual VM" [integerReceiverOop < 0 ifTrue: [self primitiveFail] ifFalse: [self pop: 1 thenPushInteger: integerReceiverOop highBit - 1]]]! |
Free forum by Nabble | Edit this page |