Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2675.mcz ==================== Summary ==================== Name: VMMaker.oscog-eem.2675 Author: eem Time: 23 January 2020, 4:57:20.930803 pm UUID: ac4a578f-84c7-491c-924d-ca554ddc19a9 Ancestors: VMMaker.oscog-eem.2674 Cogit: Correct the definition of genPrimitiveHighBit. If there is no implementation of LZCNT then it should return UnimplementedPrimitive, not CompletedPrimtiive. Reverse the order of operands in ClzR:R:; this is a left-to-right assembler, not an ATT syntax right-to-left one. Implement OrCq:R:R: to save an instruction in genPrimitiveHighBit. Move genHighBitIn:ofSmallIntegerOopWithSingleTagBit: into the backEnd where it belongs. Nuke the useless genHighBitAlternativeIn:ofSmallIntegerOopWithSingleTagBit:. =============== Diff against VMMaker.oscog-eem.2674 =============== Item was changed: ----- Method: CogARMCompiler>>concretizeClzRR (in category 'generate machine code - concretize') ----- concretizeClzRR "Count leading zeros First operand is output (dest) Second operand is input (mask)" "v5 CLZ cond 0001 0110 SBO Rd SBO 0001 Rm That is hexa 16rE16FxF1x for cond = AL" "v7 CLZ 11111-010-1-011 Rm(4bits) 1111 Rd(4bits) 1000 Rm(4bits) That is hexa 16rFABxFx8x" <inline: true> + | maskReg dest | + maskReg := operands at: 0. + dest := operands at: 1. - | dest mask | - dest := operands at: 0. - mask := operands at: 1. self machineCodeAt: 0 put: AL << 28 + 16r16F0F10 + + (dest << 12) + maskReg. - + (dest << 12) + mask. ^4! Item was removed: - ----- Method: CogAbstractInstruction>>genHighBitAlternativeIn:ofSmallIntegerOopWithSingleTagBit: (in category 'abstract instructions') ----- - genHighBitAlternativeIn: destReg ofSmallIntegerOopWithSingleTagBit: srcReg - "Use an alternative - if any for generating highBit of SmallInteger oop. - Default implementation is no-op - there is no universal alternative to CLZ. - Some target architecture might offer more..." - <inline: true> - <returnTypeC: #'AbstractInstruction *'> - ^0! Item was changed: ----- Method: CogAbstractInstruction>>genHighBitClzIn:ofSmallIntegerOopWithSingleTagBit: (in category 'abstract instructions') ----- genHighBitClzIn: destReg ofSmallIntegerOopWithSingleTagBit: srcReg "Use CLZ instruction for generating highBit of SmallInteger oop. It is sender responsibility to make sure that such CLZ instruction is available." <inline: true> | jumpNegativeReceiver | <var: #jumpNegativeReceiver type: #'AbstractInstruction *'> + cogit ClzR: srcReg R: destReg. - cogit ClzR: destReg R: srcReg. (cogit lastOpcode setsConditionCodesFor: JumpZero) ifFalse: [cogit CmpCq: 0 R: destReg]. "N.B. FLAGS := destReg - 0" jumpNegativeReceiver := cogit JumpZero: 0. "Note the nice bit trick below: highBit_1based_of_small_int_value = (BytesPerWord * 8) - leadingZeroCout_of_oop - 1 toAccountForTagBit. This is like 2 complements (- reg - 1) on (BytesPerWord * 8) log2 bits, or exactly a bit invert operation..." cogit XorCw: BytesPerWord * 8 - 1 R: destReg. ^jumpNegativeReceiver! Item was added: + ----- Method: CogAbstractInstruction>>genHighBitIn:ofSmallIntegerOopWithSingleTagBit: (in category 'abstract instructions') ----- + genHighBitIn: destReg ofSmallIntegerOopWithSingleTagBit: srcReg + "Generate code for storing in destReg the 1-based highBit of srcReg. + Assume that srcReg contains a SmallInteger Oop with a single tag bit set to 1. + Sender should preprocess Oop when cog representation use numSmallIntegerTagBits > 1. + Return the jump instruction necessary for handling case of negative integer value. + Return null pointer if the abstract highBit operation is not implemented." + <inline: true> + self hasLZCNTInstructions ifTrue: + [^self genHighBitClzIn: destReg ofSmallIntegerOopWithSingleTagBit: srcReg]. + ^0! Item was changed: ----- Method: CogIA32Compiler>>concretizeClzRR (in category 'generate machine code - concretize') ----- concretizeClzRR "Count leading zeros First operand is output (dest) Second operand is input (mask)" "LZCNT" <inline: true> + | maskReg dest | + maskReg := operands at: 0. + dest := operands at: 1. - | dest mask | - dest := operands at: 0. - mask := operands at: 1. machineCode at: 0 put: 16rF3; at: 1 put: 16r0F; at: 2 put: 16rBD; + at: 3 put: (self mod: ModReg RM: dest RO: maskReg). - at: 3 put: (self mod: ModReg RM: dest RO: mask). ^4! Item was changed: ----- Method: CogMIPSELCompiler>>computeMaximumSize (in category 'generate machine code') ----- computeMaximumSize "Each MIPS instruction has 4 bytes. Many abstract opcodes need more than one instruction. Instructions that refer to constants and/or literals depend on literals being stored in-line or out-of-line. N.B. The ^N forms are to get around the bytecode compiler's long branch limits which are exceeded when each case jumps around the otherwise." opcode caseOf: { [BrEqualRR] -> [^8]. [BrNotEqualRR] -> [^8]. [BrUnsignedLessRR] -> [^12]. [BrUnsignedLessEqualRR] -> [^12]. [BrUnsignedGreaterRR] -> [^12]. [BrUnsignedGreaterEqualRR] -> [^12]. [BrSignedLessRR] -> [^12]. [BrSignedLessEqualRR] -> [^12]. [BrSignedGreaterRR] -> [^12]. [BrSignedGreaterEqualRR] -> [^12]. [BrLongEqualRR] -> [^16]. [BrLongNotEqualRR] -> [^16]. [MulRR] -> [^4]. [DivRR] -> [^4]. [MoveLowR] -> [^4]. [MoveHighR] -> [^4]. "Noops & Pseudo Ops" [Label] -> [^0]. [Literal] -> [^4]. [AlignmentNops] -> [^(operands at: 0) - 4]. [Fill32] -> [^4]. [Nop] -> [^4]. "Control" [Call] -> [^self literalLoadInstructionBytes + 8]. [CallFull] -> [^self literalLoadInstructionBytes + 8]. [JumpR] -> [^8]. [Jump] -> [^8]. [JumpFull] -> [^self literalLoadInstructionBytes + 8]. [JumpLong] -> [^self literalLoadInstructionBytes + 8]. [JumpZero] -> [^8]. [JumpNonZero] -> [^8]. [JumpNegative] -> [^8]. [JumpNonNegative] -> [^8]. [JumpOverflow] -> [^8]. [JumpNoOverflow] -> [^8]. [JumpCarry] -> [^8]. [JumpNoCarry] -> [^8]. [JumpLess] -> [^8]. [JumpGreaterOrEqual] -> [^8]. [JumpGreater] -> [^8]. [JumpLessOrEqual] -> [^8]. [JumpBelow] -> [^8]. [JumpAboveOrEqual] -> [^8]. [JumpAbove] -> [^8]. [JumpBelowOrEqual] -> [^8]. [JumpLongZero] -> [^self literalLoadInstructionBytes + 8]. [JumpLongNonZero] -> [^self literalLoadInstructionBytes + 8]. [JumpFPEqual] -> [^8]. [JumpFPNotEqual] -> [^8]. [JumpFPLess] -> [^8]. [JumpFPGreaterOrEqual]-> [^8]. [JumpFPGreater] -> [^8]. [JumpFPLessOrEqual] -> [^8]. [JumpFPOrdered] -> [^8]. [JumpFPUnordered] -> [^8]. [RetN] -> [^8]. [Stop] -> [^4]. "Arithmetic" [AddCqR] -> [^12]. [AndCqR] -> [^16]. + [OrCqR] -> [^16]. [AndCqRR] -> [^12]. [CmpCqR] -> [^28]. [OrCqR] -> [^12]. [SubCqR] -> [^12]. [TstCqR] -> [^12]. [XorCqR] -> [^12]. [AddCwR] -> [^12]. [AndCwR] -> [^12]. [CmpCwR] -> [^28]. [OrCwR] -> [^12]. [SubCwR] -> [^12]. [XorCwR] -> [^12]. [AddRR] -> [^4]. [AndRR] -> [^4]. [CmpRR] -> [^20]. [OrRR] -> [^4]. [XorRR] -> [^4]. [SubRR] -> [^4]. [NegateR] -> [^4]. [LoadEffectiveAddressMwrR] -> [^12]. [LogicalShiftLeftCqR] -> [^4]. [LogicalShiftRightCqR] -> [^4]. [ArithmeticShiftRightCqR] -> [^4]. [LogicalShiftLeftRR] -> [^4]. [LogicalShiftRightRR] -> [^4]. [ArithmeticShiftRightRR] -> [^4]. [AddRdRd] -> [^4]. [CmpRdRd] -> [^4]. [SubRdRd] -> [^4]. [MulRdRd] -> [^4]. [DivRdRd] -> [^4]. [SqrtRd] -> [^4]. [AddCheckOverflowCqR] -> [^28]. [AddCheckOverflowRR] -> [^20]. [SubCheckOverflowCqR] -> [^28]. [SubCheckOverflowRR] -> [^20]. [MulCheckOverflowRR] -> [^20]. [ClzRR] -> [^4]. "Data Movement" [MoveCqR] -> [^8 "or 4"]. [MoveCwR] -> [^8]. [MoveRR] -> [^4]. [MoveRdRd] -> [^4]. [MoveAwR] -> [^(self isAddressRelativeToVarBase: (operands at: 0)) ifTrue: [4] ifFalse: [self literalLoadInstructionBytes + 4]]. [MoveRAw] -> [^(self isAddressRelativeToVarBase: (operands at: 1)) ifTrue: [4] ifFalse: [self literalLoadInstructionBytes + 4]]. [MoveAbR] -> [^(self isAddressRelativeToVarBase: (operands at: 0)) ifTrue: [4] ifFalse: [self literalLoadInstructionBytes + 4]]. [MoveRAb] -> [^(self isAddressRelativeToVarBase: (operands at: 1)) ifTrue: [4] ifFalse: [self literalLoadInstructionBytes + 4]]. [MoveRMwr] -> [^16]. [MoveRdM64r] -> [^self literalLoadInstructionBytes + 4]. [MoveMbrR] -> [^4]. [MoveRMbr] -> [^4]. [MoveM16rR] -> [^4]. [MoveRM16r] -> [^4]. [MoveM64rRd] -> [^self literalLoadInstructionBytes + 4]. [MoveMwrR] -> [^16]. [MoveXbrRR] -> [^8]. [MoveRXbrR] -> [^8]. [MoveXwrRR] -> [^12]. [MoveRXwrR] -> [^12]. [PopR] -> [^8]. [PushR] -> [^8]. [PushCw] -> [^16]. [PushCq] -> [^16]. [PrefetchAw] -> [^12]. "Conversion" [ConvertRRd] -> [^8]. }. ^0 "to keep C compiler quiet" ! Item was changed: ----- Method: CogMIPSELCompiler>>concretizeClzRR (in category 'generate machine code - concretize') ----- concretizeClzRR + | maskReg destReg rightReg | + maskReg := operands at: 0. + destReg := rightReg := operands at: 1. + self machineCodeAt: 0 put: (self clzR: destReg R: maskReg R: rightReg). - | destReg leftReg rightReg | - destReg := rightReg := operands at: 0. - leftReg := operands at: 1. - self machineCodeAt: 0 put: (self clzR: destReg R: leftReg R: rightReg). ^4! Item was added: + ----- Method: CogMIPSELCompiler>>concretizeOrCqRR (in category 'generate machine code - concretize') ----- + concretizeOrCqRR + | value srcReg dstReg | + value := operands at: 0. + srcReg := operands at: 1. + dstReg := operands at: 2. + self machineCodeAt: 0 put: (self luiR: AT C: (self high16BitsOf: value)). + self machineCodeAt: 4 put: (self oriR: AT R: AT C: (self low16BitsOf: value)). + self machineCodeAt: 8 put: (self orR: dstReg R: srcReg R: AT). + ^12! Item was changed: ----- Method: CogMIPSELCompiler>>dispatchConcretize (in category 'generate machine code') ----- dispatchConcretize "Attempt to generate concrete machine code for the instruction at address. This is the inner dispatch of concretizeAt: actualAddress which exists only to get around the branch size limits in the SqueakV3 (blue book derived) bytecode set." opcode caseOf: { [BrEqualRR] -> [^self concretizeBrEqualRR]. [BrNotEqualRR] -> [^self concretizeBrNotEqualRR]. [BrUnsignedLessRR] -> [^self concretizeBrUnsignedLessRR]. [BrUnsignedLessEqualRR] -> [^self concretizeBrUnsignedLessEqualRR]. [BrUnsignedGreaterRR] -> [^self concretizeBrUnsignedGreaterRR]. [BrUnsignedGreaterEqualRR] -> [^self concretizeBrUnsignedGreaterEqualRR]. [BrSignedLessRR] -> [^self concretizeBrSignedLessRR]. [BrSignedLessEqualRR] -> [^self concretizeBrSignedLessEqualRR]. [BrSignedGreaterRR] -> [^self concretizeBrSignedGreaterRR]. [BrSignedGreaterEqualRR] -> [^self concretizeBrSignedGreaterEqualRR]. [BrLongEqualRR] -> [^self concretizeBrLongEqualRR]. [BrLongNotEqualRR] -> [^self concretizeBrLongNotEqualRR]. [MulRR] -> [^self concretizeUnimplemented]. [DivRR] -> [^self concretizeDivRR]. [MoveLowR] -> [^self concretizeMoveLowR]. [MoveHighR] -> [^self concretizeMoveHighR]. "Noops & Pseudo Ops" [Label] -> [^self concretizeLabel]. [AlignmentNops] -> [^self concretizeAlignmentNops]. [Fill32] -> [^self concretizeFill32]. [Nop] -> [^self concretizeNop]. "Control" [Call] -> [^self concretizeCall]. "call code within code space" [CallFull] -> [^self concretizeCallFull]. "call code anywhere in address space" [JumpR] -> [^self concretizeJumpR]. [JumpFull] -> [^self concretizeJumpFull]."jump within address space" [JumpLong] -> [^self concretizeJumpLong]."jumps witihn code space" [JumpLongZero] -> [^self concretizeJumpLongZero]. [JumpLongNonZero] -> [^self concretizeJumpLongNonZero]. [Jump] -> [^self concretizeJump]. [JumpZero] -> [^self concretizeJumpZero]. [JumpNonZero] -> [^self concretizeJumpNonZero]. [JumpNegative] -> [^self concretizeUnimplemented]. [JumpNonNegative] -> [^self concretizeUnimplemented]. [JumpOverflow] -> [^self concretizeJumpOverflow]. [JumpNoOverflow] -> [^self concretizeJumpNoOverflow]. [JumpCarry] -> [^self concretizeUnimplemented]. [JumpNoCarry] -> [^self concretizeUnimplemented]. [JumpLess] -> [^self concretizeJumpSignedLessThan]. [JumpGreaterOrEqual] -> [^self concretizeJumpSignedGreaterEqual]. [JumpGreater] -> [^self concretizeJumpSignedGreaterThan]. [JumpLessOrEqual] -> [^self concretizeJumpSignedLessEqual]. [JumpBelow] -> [^self concretizeJumpUnsignedLessThan]. [JumpAboveOrEqual] -> [^self concretizeJumpUnsignedGreaterEqual]. [JumpAbove] -> [^self concretizeJumpUnsignedGreaterThan]. [JumpBelowOrEqual] -> [^self concretizeJumpUnsignedLessEqual]. [JumpFPEqual] -> [^self concretizeUnimplemented]. [JumpFPNotEqual] -> [^self concretizeUnimplemented]. [JumpFPLess] -> [^self concretizeUnimplemented]. [JumpFPGreaterOrEqual] -> [^self concretizeUnimplemented]. [JumpFPGreater] -> [^self concretizeUnimplemented]. [JumpFPLessOrEqual] -> [^self concretizeUnimplemented]. [JumpFPOrdered] -> [^self concretizeUnimplemented]. [JumpFPUnordered] -> [^self concretizeUnimplemented]. [RetN] -> [^self concretizeRetN]. [Stop] -> [^self concretizeStop]. "Arithmetic" [AddCqR] -> [^self concretizeAddCqR]. [AndCqR] -> [^self concretizeAndCqR]. [AndCqRR] -> [^self concretizeAndCqRR]. + [AndCqRR] -> [^self concretizeOrCqRR]. [CmpCqR] -> [^self concretizeCmpCqR]. + [OrCqR] -> [^self concretizeOrCqR]. - [OrCqR] -> [^self concretizeOrCqR]. [SubCqR] -> [^self concretizeSubCqR]. [TstCqR] -> [^self concretizeTstCqR]. [XorCqR] -> [^self concretizeUnimplemented]. [AddCwR] -> [^self concretizeAddCwR]. [AndCwR] -> [^self concretizeAndCwR]. [CmpCwR] -> [^self concretizeCmpCwR]. [OrCwR] -> [^self concretizeOrCwR]. [SubCwR] -> [^self concretizeSubCwR]. [XorCwR] -> [^self concretizeXorCwR]. [AddRR] -> [^self concretizeAddRR]. [AndRR] -> [^self concretizeAndRR]. [CmpRR] -> [^self concretizeCmpRR]. [OrRR] -> [^self concretizeOrRR]. [SubRR] -> [^self concretizeSubRR]. [XorRR] -> [^self concretizeXorRR]. [AddRdRd] -> [^self concretizeUnimplemented]. [CmpRdRd] -> [^self concretizeUnimplemented]. [DivRdRd] -> [^self concretizeUnimplemented]. [MulRdRd] -> [^self concretizeUnimplemented]. [SubRdRd] -> [^self concretizeUnimplemented]. [SqrtRd] -> [^self concretizeUnimplemented]. [NegateR] -> [^self concretizeNegateR]. [LoadEffectiveAddressMwrR] -> [^self concretizeLoadEffectiveAddressMwrR]. [ArithmeticShiftRightCqR] -> [^self concretizeArithmeticShiftRightCqR]. [LogicalShiftRightCqR] -> [^self concretizeLogicalShiftRightCqR]. [LogicalShiftLeftCqR] -> [^self concretizeLogicalShiftLeftCqR]. [ArithmeticShiftRightRR] -> [^self concretizeArithmeticShiftRightRR]. [LogicalShiftLeftRR] -> [^self concretizeLogicalShiftLeftRR]. [LogicalShiftRightRR] -> [^self concretizeLogicalShiftRightRR]. [ClzRR] -> [^self concretizeClzRR]. "Data Movement" [MoveCqR] -> [^self concretizeMoveCqR]. [MoveCwR] -> [^self concretizeMoveCwR]. [MoveRR] -> [^self concretizeMoveRR]. [MoveAwR] -> [^self concretizeMoveAwR]. [MoveRAw] -> [^self concretizeMoveRAw]. [MoveAbR] -> [^self concretizeMoveAbR]. [MoveRAb] -> [^self concretizeMoveRAb]. [MoveMbrR] -> [^self concretizeMoveMbrR]. [MoveRMbr] -> [^self concretizeUnimplemented]. [MoveM16rR] -> [^self concretizeMoveM16rR]. [MoveRM16r] -> [^self concretizeMoveRM16r]. [MoveM64rRd] -> [^self concretizeUnimplemented]. [MoveMwrR] -> [^self concretizeMoveMwrR]. [MoveXbrRR] -> [^self concretizeMoveXbrRR]. [MoveRXbrR] -> [^self concretizeMoveRXbrR]. [MoveXwrRR] -> [^self concretizeMoveXwrRR]. [MoveRXwrR] -> [^self concretizeMoveRXwrR]. [MoveRMwr] -> [^self concretizeMoveRMwr]. [MoveRdM64r] -> [^self concretizeUnimplemented]. [PopR] -> [^self concretizePopR]. [PushR] -> [^self concretizePushR]. [PushCq] -> [^self concretizePushCq]. [PushCw] -> [^self concretizePushCw]. [PrefetchAw] -> [^self concretizePrefetchAw]. [AddCheckOverflowCqR] -> [^self concretizeAddCheckOverflowCqR]. [AddCheckOverflowRR] -> [^self concretizeAddCheckOverflowRR]. [SubCheckOverflowCqR] -> [^self concretizeSubCheckOverflowCqR]. [SubCheckOverflowRR] -> [^self concretizeSubCheckOverflowRR]. [MulCheckOverflowRR] -> [^self concretizeMulCheckOverflowRR]. "Conversion" [ConvertRRd] -> [^self concretizeUnimplemented]}. ^0 "keep Slang happy"! Item was changed: ----- Method: CogMIPSELCompiler>>noteFollowingConditionalBranch: (in category 'abstract instructions') ----- noteFollowingConditionalBranch: branch "Support for processors without condition codes, such as the MIPS. Answer the branch opcode. Modify the receiver and the branch to implement a suitable conditional branch that doesn't depend on condition codes being set by the receiver." <returnTypeC: #'AbstractInstruction *'> <var: #branch type: #'AbstractInstruction *'> | newBranchLeft newBranchOpcode newBranchRight | ((branch opcode = JumpOverflow) or: [branch opcode = JumpNoOverflow]) ifTrue: [^self noteFollowingOverflowBranch: branch]. newBranchOpcode := branch opcode caseOf: { [JumpZero] -> [BrEqualRR]. [JumpNonZero] -> [BrNotEqualRR]. [JumpBelow] -> [BrUnsignedLessRR]. [JumpBelowOrEqual] -> [BrUnsignedLessEqualRR]. [JumpAbove] -> [BrUnsignedGreaterRR]. [JumpAboveOrEqual] -> [BrUnsignedGreaterEqualRR]. [JumpLess] -> [BrSignedLessRR]. [JumpLessOrEqual] -> [BrSignedLessEqualRR]. [JumpGreater] -> [BrSignedGreaterRR]. [JumpGreaterOrEqual] -> [BrSignedGreaterEqualRR]. [JumpLongZero] -> [BrLongEqualRR]. [JumpLongNonZero] -> [BrLongNotEqualRR]. [JumpNegative] -> [BrSignedLessRR]. } otherwise: [self unreachable. 0]. opcode caseOf: { [BrEqualRR] -> ["I.e., two jumps after a compare." newBranchLeft := operands at: 1. newBranchRight := operands at: 2]. [BrUnsignedLessRR] -> ["I.e., two jumps after a compare." newBranchLeft := operands at: 1. newBranchRight := operands at: 2]. [CmpRR] -> [newBranchLeft := operands at: 1. newBranchRight := operands at: 0. opcode := Label]. [CmpCqR] -> [newBranchLeft := operands at: 1. newBranchRight := AT. opcode := MoveCqR. operands at: 1 put: AT]. [CmpCwR] -> [newBranchLeft := operands at: 1. newBranchRight := AT. opcode := MoveCwR. operands at: 1 put: AT]. [TstCqR] -> [newBranchLeft := Cmp. newBranchRight := ZR]. [AndCqR] -> [newBranchLeft := operands at: 1. newBranchRight := ZR]. [AndCqRR] -> [newBranchLeft := operands at: 2. newBranchRight := ZR]. + [OrCqRR] -> [newBranchLeft := operands at: 2. + newBranchRight := ZR]. [OrRR] -> [newBranchLeft := operands at: 1. newBranchRight := ZR]. [XorRR] -> [newBranchLeft := operands at: 1. newBranchRight := ZR]. [SubCwR] -> [newBranchLeft := operands at: 1. newBranchRight := ZR]. [SubCqR] -> [newBranchLeft := operands at: 1. newBranchRight := ZR]. [ArithmeticShiftRightCqR] -> [newBranchLeft := operands at: 1. newBranchRight := ZR]. [ClzRR] -> [newBranchLeft := operands at: 0. "we test if the destination register is zero" newBranchRight := ZR]. } otherwise: [self unreachable]. branch rewriteOpcode: newBranchOpcode with: newBranchLeft with: newBranchRight. ^branch! Item was changed: ----- Method: CogObjectRepresentation>>genPrimitiveHighBit (in category 'primitive generators') ----- genPrimitiveHighBit "Implementation notes: there are two reasons to use TempReg -1) if primitive fails, ReceiverResultReg must remain unchanged (we CompletePrimitive) -2) CLZ/BSR only work on 64bits for registers R0-R7 on Intel X64. But Win64 uses R9 Normally, this should be backEnd dependent, but for now we have a single 64bits target..." | jumpNegativeReceiver | <var: #jumpNegativeReceiver type: #'AbstractInstruction *'> "remove excess tag bits from the receiver oop" - cogit MoveR: ReceiverResultReg R: TempReg. self numSmallIntegerTagBits > 1 ifTrue: + [cogit OrCq: 1 << self numSmallIntegerTagBits - 1 R: ReceiverResultReg R: TempReg. + cogit ArithmeticShiftRightCq: self numSmallIntegerTagBits - 1 R: TempReg. + jumpNegativeReceiver := cogit backEnd genHighBitIn: TempReg ofSmallIntegerOopWithSingleTagBit: TempReg] - [cogit OrCq: 1 << self numSmallIntegerTagBits - 1 R: TempReg. - cogit ArithmeticShiftRightCq: self numSmallIntegerTagBits - 1 R: TempReg]. - "and use the abstract cogit facility for case of single tag-bit" - jumpNegativeReceiver := cogit genHighBitIn: TempReg ofSmallIntegerOopWithSingleTagBit: TempReg. - "Jump is NULL if above operation is not implemented, else return the result" - jumpNegativeReceiver = 0 ifFalse: + ["and use the abstract cogit facility for case of single tag-bit" + jumpNegativeReceiver := cogit backEnd genHighBitIn: TempReg ofSmallIntegerOopWithSingleTagBit: ReceiverResultReg]. + + "Jump is NULL if above operation is not implemented, else return the result" + jumpNegativeReceiver = 0 ifTrue: + [^UnimplementedPrimitive]. + + cogit MoveR: TempReg R: ReceiverResultReg. + self genConvertIntegerToSmallIntegerInReg: ReceiverResultReg. + cogit genPrimReturn. + jumpNegativeReceiver jmpTarget: cogit Label. - [cogit MoveR: TempReg R: ReceiverResultReg. - cogit genConvertIntegerToSmallIntegerInReg: ReceiverResultReg. - cogit genPrimReturn. - jumpNegativeReceiver jmpTarget: cogit Label]. ^CompletePrimitive! Item was changed: ----- Method: CogOutOfLineLiteralsARMCompiler>>usesOutOfLineLiteral (in category 'testing') ----- usesOutOfLineLiteral "Answer if the receiver uses an out-of-line literal. Needs only to work for the opcodes created with gen:literal:operand: et al." opcode caseOf: { [CallFull] -> [^true]. [JumpFull] -> [^true]. "Arithmetic" [AddCqR] -> [^self rotateable8bitSignedImmediate: (operands at: 0) ifTrue: [:r :i :n| false] ifFalse: [true]]. [AddCqRR] -> [^self rotateable8bitSignedImmediate: (operands at: 0) ifTrue: [:r :i :n| false] ifFalse: [true]]. [AndCqR] -> [^self rotateable8bitBitwiseImmediate: (operands at: 0) ifTrue: [:r :i :n| false] ifFalse: [1 << (operands at: 0) highBit ~= ((operands at: 0) + 1)]]. [AndCqRR] -> [^self rotateable8bitBitwiseImmediate: (operands at: 0) ifTrue: [:r :i :n| false] ifFalse: [1 << (operands at: 0) highBit ~= ((operands at: 0) + 1)]]. + [OrCqRR] -> [^self rotateable8bitBitwiseImmediate: (operands at: 0) + ifTrue: [:r :i :n| false] + ifFalse: [1 << (operands at: 0) highBit ~= ((operands at: 0) + 1)]]. [CmpCqR] -> [^self rotateable8bitSignedImmediate: (operands at: 0) ifTrue: [:r :i :n| false] ifFalse: [true]]. [OrCqR] -> [^self rotateable8bitImmediate: (operands at: 0) ifTrue: [:r :i| false] ifFalse: [true]]. [SubCqR] -> [^self rotateable8bitSignedImmediate: (operands at: 0) ifTrue: [:r :i :n| false] ifFalse: [true]]. [TstCqR] -> [^self rotateable8bitImmediate: (operands at: 0) ifTrue: [:r :i| false] ifFalse: [true]]. [XorCqR] -> [^self rotateable8bitBitwiseImmediate: (operands at: 0) ifTrue: [:r :i :n| false] ifFalse: [true]]. [AddCwR] -> [^true]. [AndCwR] -> [^true]. [CmpCwR] -> [^true]. [OrCwR] -> [^true]. [SubCwR] -> [^true]. [XorCwR] -> [^true]. [LoadEffectiveAddressMwrR] -> [^self rotateable8bitImmediate: (operands at: 0) ifTrue: [:r :i| false] ifFalse: [true]]. "Data Movement" [MoveCqR] -> [^self rotateable8bitImmediate: (operands at: 0) ifTrue: [:r :i| false] ifFalse: [true]]. [MoveCwR] -> [^(self inCurrentCompilation: (operands at: 0)) not]. [MoveAwR] -> [^(self isAddressRelativeToVarBase: (operands at: 0)) ifTrue: [false] ifFalse: [true]]. [MoveRAw] -> [^(self isAddressRelativeToVarBase: (operands at: 1)) ifTrue: [false] ifFalse: [true]]. [MoveAbR] -> [^(self isAddressRelativeToVarBase: (operands at: 0)) ifTrue: [false] ifFalse: [true]]. [MoveRAb] -> [^(self isAddressRelativeToVarBase: (operands at: 1)) ifTrue: [false] ifFalse: [true]]. [MoveRMwr] -> [^self is12BitValue: (operands at: 1) ifTrue: [:u :i| false] ifFalse: [true]]. [MoveRdM64r] -> [^self is12BitValue: (operands at: 1) ifTrue: [:u :i| false] ifFalse: [true]]. [MoveMbrR] -> [^self is12BitValue: (operands at: 0) ifTrue: [:u :i| false] ifFalse: [true]]. [MoveRMbr] -> [^self is12BitValue: (operands at: 1) ifTrue: [:u :i| false] ifFalse: [true]]. [MoveM16rR] -> [^self rotateable8bitImmediate: (operands at: 0) ifTrue: [:r :i| false] ifFalse: [true]]. [MoveRM16r] -> [^self is12BitValue: (operands at: 1) ifTrue: [:u :i| false] ifFalse: [true]]. [MoveM64rRd] -> [^self is12BitValue: (operands at: 0) ifTrue: [:u :i| false] ifFalse: [true]]. [MoveMwrR] -> [^self is12BitValue: (operands at: 0) ifTrue: [:u :i| false] ifFalse: [true]]. [PushCw] -> [^(self inCurrentCompilation: (operands at: 0)) not]. [PushCq] -> [^self rotateable8bitImmediate: (operands at: 0) ifTrue: [:r :i| false] ifFalse: [true]]. [PrefetchAw] -> [^(self isAddressRelativeToVarBase: (operands at: 0)) ifTrue: [false] ifFalse: [true]]. } otherwise: [self assert: false]. ^false "to keep C compiler quiet" ! Item was changed: SharedPool subclass: #CogRTLOpcodes instanceVariableNames: '' + classVariableNames: 'AddCqR AddCqRR AddCwR AddRR AddRRR AddRdRd AddRsRs AddcCqR AddcRR AlignmentNops AndCqR AndCqRR AndCwR AndRR ArithmeticShiftRightCqR ArithmeticShiftRightCqRR ArithmeticShiftRightRR Call CallFull CallR ClzRR CmpC32R CmpCqR CmpCwR CmpRR CmpRdRd CmpRsRs ConvertRRd ConvertRRs ConvertRdR ConvertRdRs ConvertRsR ConvertRsRd DivRdRd DivRsRs Fill32 FirstJump FirstShortJump Jump JumpAbove JumpAboveOrEqual JumpBelow JumpBelowOrEqual JumpCarry JumpFPEqual JumpFPGreater JumpFPGreaterOrEqual JumpFPLess JumpFPLessOrEqual JumpFPNotEqual JumpFPOrdered JumpFPUnordered JumpFull JumpGreater JumpGreaterOrEqual JumpLess JumpLessOrEqual JumpLong JumpLongNonZero JumpLongZero JumpNegative JumpNoCarry JumpNoOverflow JumpNonNegative JumpNonZero JumpOverflow JumpR JumpZero Label LastJump LastRTLCode Literal LoadEffectiveAddressMwrR LogicalShiftLeftCqR LogicalShiftLeftCqRR LogicalShiftLeftRR LogicalShiftRightCqR LogicalShiftRightCqRR LogicalShiftRightRR MoveA32R MoveAbR MoveAwR MoveC32R Mo veCqR MoveCwR MoveM16rR MoveM32rR MoveM32rRs MoveM64rRd MoveM8rR MoveMbrR MoveMs8rR MoveMwrR MoveRA32 MoveRAb MoveRAw MoveRM16r MoveRM32r MoveRM8r MoveRMbr MoveRMwr MoveRR MoveRRd MoveRX16rR MoveRX32rR MoveRXbrR MoveRXwrR MoveRdM64r MoveRdR MoveRdRd MoveRsM32r MoveRsRs MoveX16rRR MoveX32rRR MoveXbrRR MoveXwrRR MulRdRd MulRsRs NegateR Nop NotR OrCqR OrCqRR OrCwR OrRR PopR PrefetchAw PushCq PushCw PushR RetN RotateLeftCqR RotateRightCqR SignExtend16RR SignExtend32RR SignExtend8RR SqrtRd SqrtRs Stop SubCqR SubCwR SubRR SubRRR SubRdRd SubRsRs SubbCqR SubbRR TstCqR XorCqR XorCwR XorRR XorRdRd XorRsRs ZeroExtend16RR ZeroExtend32RR ZeroExtend8RR' - classVariableNames: 'AddCqR AddCqRR AddCwR AddRR AddRRR AddRdRd AddRsRs AddcCqR AddcRR AlignmentNops AndCqR AndCqRR AndCwR AndRR ArithmeticShiftRightCqR ArithmeticShiftRightCqRR ArithmeticShiftRightRR Call CallFull CallR ClzRR CmpC32R CmpCqR CmpCwR CmpRR CmpRdRd CmpRsRs ConvertRRd ConvertRRs ConvertRdR ConvertRdRs ConvertRsR ConvertRsRd DivRdRd DivRsRs Fill32 FirstJump FirstShortJump Jump JumpAbove JumpAboveOrEqual JumpBelow JumpBelowOrEqual JumpCarry JumpFPEqual JumpFPGreater JumpFPGreaterOrEqual JumpFPLess JumpFPLessOrEqual JumpFPNotEqual JumpFPOrdered JumpFPUnordered JumpFull JumpGreater JumpGreaterOrEqual JumpLess JumpLessOrEqual JumpLong JumpLongNonZero JumpLongZero JumpNegative JumpNoCarry JumpNoOverflow JumpNonNegative JumpNonZero JumpOverflow JumpR JumpZero Label LastJump LastRTLCode Literal LoadEffectiveAddressMwrR LogicalShiftLeftCqR LogicalShiftLeftCqRR LogicalShiftLeftRR LogicalShiftRightCqR LogicalShiftRightCqRR LogicalShiftRightRR MoveA32R MoveAbR MoveAwR MoveC32R Mo veCqR MoveCwR MoveM16rR MoveM32rR MoveM32rRs MoveM64rRd MoveM8rR MoveMbrR MoveMs8rR MoveMwrR MoveRA32 MoveRAb MoveRAw MoveRM16r MoveRM32r MoveRM8r MoveRMbr MoveRMwr MoveRR MoveRRd MoveRX16rR MoveRX32rR MoveRXbrR MoveRXwrR MoveRdM64r MoveRdR MoveRdRd MoveRsM32r MoveRsRs MoveX16rRR MoveX32rRR MoveXbrRR MoveXwrRR MulRdRd MulRsRs NegateR Nop NotR OrCqR OrCwR OrRR PopR PrefetchAw PushCq PushCw PushR RetN RotateLeftCqR RotateRightCqR SignExtend16RR SignExtend32RR SignExtend8RR SqrtRd SqrtRs Stop SubCqR SubCwR SubRR SubRRR SubRdRd SubRsRs SubbCqR SubbRR TstCqR XorCqR XorCwR XorRR XorRdRd XorRsRs ZeroExtend16RR ZeroExtend32RR ZeroExtend8RR' poolDictionaries: '' category: 'VMMaker-JIT'! !CogRTLOpcodes commentStamp: 'eem 12/26/2015 14:00' prior: 0! I am a pool for the Register-Transfer-Language to which Cog compiles. I define unique integer values for all RTL opcodes. See CogAbstractInstruction for instances of instructions with the opcodes that I define.! Item was changed: ----- Method: CogRTLOpcodes class>>initialize (in category 'class initialization') ----- (excessive size, no diff calculated) Item was changed: ----- Method: CogX64Compiler>>concretizeClzRR (in category 'generate machine code - concretize') ----- concretizeClzRR "Count leading zeros First operand is output (dest) Second operand is input (mask)" "LZCNT" <inline: true> + | maskReg dest | + maskReg := operands at: 0. + dest := operands at: 1. - | dest mask | - dest := operands at: 0. - mask := operands at: 1. machineCode + at: 0 put: 16rF3; + at: 1 put: (self rexw: true r: 0 x: 0 b: 0); - at: 0 put: 16rF3. - (dest <= 7 and: [mask <= 7]) - ifTrue: [machineCode at: 1 put: (self rexw: true r: 0 x: 0 b: 0)] - ifFalse: [machineCode at: 1 put: (self rexw: false r: 0 x: 0 b: 0)]. - - machineCode at: 2 put: 16r0F; at: 3 put: 16rBD; + at: 4 put: (self mod: ModReg RM: dest RO: maskReg). - at: 4 put: (self mod: ModReg RM: dest RO: mask). ^5! Item was changed: ----- Method: Cogit>>ClzR:R: (in category 'abstract instructions') ----- ClzR: reg1 R: reg2 + "reg2 := reg1 countLeadingZeros" <inline: true> <returnTypeC: #'AbstractInstruction *'> ^self gen: ClzRR operand: reg1 operand: reg2! Item was added: + ----- Method: Cogit>>OrCq:R:R: (in category 'abstract instructions') ----- + OrCq: quickConstant R: srcReg R: destReg + <inline: false> + <returnTypeC: #'AbstractInstruction *'> + | first | + backEnd hasThreeAddressArithmetic ifTrue: + [^self gen: OrCqRR quickConstant: quickConstant operand: srcReg operand: destReg]. + srcReg = destReg ifTrue: + [^self gen: OrCqR quickConstant: quickConstant operand: destReg]. + first := self gen: MoveRR operand: srcReg operand: destReg. + self gen: OrCqR quickConstant: quickConstant operand: destReg. + ^first! Item was removed: - ----- Method: Cogit>>genHighBitIn:ofSmallIntegerOopWithSingleTagBit: (in category 'abstract instructions') ----- - genHighBitIn: destReg ofSmallIntegerOopWithSingleTagBit: srcReg - "Generate code for storing in destReg the 1-based highBit of srcReg. - Assume that srcReg contains a SmallInteger Oop with a single tag bit set to 1. - Sender should preprocess Oop when cog representation use numSmallIntegerTagBits > 1. - Return the jump instruction necessary for handling case of negative integer value. - Return null pointer if the abstract highBit operation is not implemented. - - The implementation depends on availability of instructions on the target architecture, - so delegate to the backend." - <inline: true> - <returnTypeC: #'AbstractInstruction *'> - backEnd hasLZCNTInstructions - ifTrue: [^self genHighBitClzIn: destReg ofSmallIntegerOopWithSingleTagBit: srcReg] - ifFalse: [^self genHighBitAlternativeIn: destReg ofSmallIntegerOopWithSingleTagBit: srcReg]! Item was added: + ----- Method: CurrentImageCoInterpreterFacade>>highBit: (in category 'cog jit support') ----- + highBit: anInteger + ^anInteger highBit! |
Hi Eliot, Le ven. 24 janv. 2020 à 01:57, <[hidden email]> a écrit :
+1 Reverse the order of operands in ClzR:R:; this is a left-to-right assembler, not an ATT syntax right-to-left one. +1, case of brain failure to mimic existing operations... For some low level ops, it seems I would make an equally bright choice by flipping a coin ;) Implement OrCq:R:R: to save an instruction in genPrimitiveHighBit. +1, it probably ended here at the beginning of my iterations, then code generation is lax enough so I forgot it's always a problem to know where to put the slang code (since it does rarely use receiver) Nuke the useless genHighBitAlternativeIn:ofSmallIntegerOopWithSingleTagBit:. +/- 1 ? genHighBitAlternativeIn:ofSmallIntegerOopWithSingleTagBit: was for using the BSR instruction when there is no LZCNT Do you mean useless because those µproc are obsolete enough to not bother?
Maybe update the comment: left operand is input (mask), right operand is output (dest) "LZCNT" Does this mean that it's sender responsibility to provide registers <= 7? - at: 0 put: 16rF3. + "reg2 := reg1 countLeadingZeros" and maybe rename parameters as maskReg (or srcReg) and destReg like OrCqR:R: below... <inline: true> |
Hi Nicolas, On Fri, Jan 24, 2020 at 1:06 PM Nicolas Cellier <[hidden email]> wrote:
Yes. Thus was perhaps not my best choice. Early on I was exposed to left-to-right assemblers and found right-to-left assembler, such as that for the ARM, distasteful. Now that I've spent so much time with the ARMv8 I'm starting to change my mind. But since we have what we have, we should be consistent. The most maddening thing for me is CmpR:R: CmpCq:R: et al. I still can't understand which way is which and continually have to look at examples to get it right. Sigh...
Oops! I did not realize that's what it was for. I only looked deep enough to see that it answered zero and thought OK let's nuke it. I apologize! This would have been good to comment, as in "This is a place-holder for an implementation that uses BSR when LZCNT is unavailable.". I'll restore it soon (but right now I've discovered that I *can* get around the memory protections against self-modifying code in current linux, and in an elegant way, and I have only hours before tomorrow's meet in Palo Alto, so I'm under the gun :-) )
[snip] _,,,^..^,,,_ best, Eliot |
Free forum by Nabble | Edit this page |