Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2613.mcz ==================== Summary ==================== Name: VMMaker.oscog-eem.2613 Author: eem Time: 13 December 2019, 7:35:41.153171 pm UUID: 7c2c6be5-2985-49b2-ac92-948173eef88a Ancestors: VMMaker.oscog-eem.2612 Add three register AddRRR and SubRRR and save an instruction in context creation on ARM ;-) =============== Diff against VMMaker.oscog-eem.2612 =============== Item was changed: ----- Method: CogARMCompiler>>computeMaximumSize (in category 'generate machine code') ----- computeMaximumSize "Because we don't use Thumb, each ARM 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: { "Noops & Pseudo Ops" [Label] -> [^0]. [Literal] -> [^4]. [AlignmentNops] -> [^(operands at: 0) - 4]. [Fill32] -> [^4]. [Nop] -> [^4]. "Control" [Call] -> [^4]. [CallFull] -> [^self literalLoadInstructionBytes + 4]. [JumpR] -> [^4]. [Jump] -> [^4]. [JumpFull] -> [^self literalLoadInstructionBytes + 4]. [JumpLong] -> [^4]. [JumpZero] -> [^4]. [JumpNonZero] -> [^4]. [JumpNegative] -> [^4]. [JumpNonNegative] -> [^4]. [JumpOverflow] -> [^4]. [JumpNoOverflow] -> [^4]. [JumpCarry] -> [^4]. [JumpNoCarry] -> [^4]. [JumpLess] -> [^4]. [JumpGreaterOrEqual] -> [^4]. [JumpGreater] -> [^4]. [JumpLessOrEqual] -> [^4]. [JumpBelow] -> [^4]. [JumpAboveOrEqual] -> [^4]. [JumpAbove] -> [^4]. [JumpBelowOrEqual] -> [^4]. [JumpLongZero] -> [^4]. [JumpLongNonZero] -> [^4]. [JumpFPEqual] -> [^8]. [JumpFPNotEqual] -> [^8]. [JumpFPLess] -> [^8]. [JumpFPGreaterOrEqual]-> [^8]. [JumpFPGreater] -> [^8]. [JumpFPLessOrEqual] -> [^8]. [JumpFPOrdered] -> [^8]. [JumpFPUnordered] -> [^8]. [RetN] -> [^(operands at: 0) = 0 ifTrue: [4] ifFalse: [8]]. [Stop] -> [^4]. "Arithmetic" [AddCqR] -> [^self rotateable8bitSignedImmediate: (operands at: 0) ifTrue: [:r :i :n| 4] ifFalse: [self literalLoadInstructionBytes + 4]]. [AndCqR] -> [^self rotateable8bitBitwiseImmediate: (operands at: 0) ifTrue: [:r :i :n| 4] ifFalse: [self literalLoadInstructionBytes = 4 ifTrue: [8] ifFalse: [1 << (operands at: 0) highBit = ((operands at: 0) + 1) ifTrue: [8] ifFalse: [self literalLoadInstructionBytes + 4]]]]. [AndCqRR] -> [^self rotateable8bitBitwiseImmediate: (operands at: 0) ifTrue: [:r :i :n| 4] ifFalse: [self literalLoadInstructionBytes = 4 ifTrue: [8] ifFalse: [1 << (operands at: 0) highBit = ((operands at: 0) + 1) ifTrue: [8] ifFalse: [self literalLoadInstructionBytes + 4]]]]. [CmpCqR] -> [^self rotateable8bitSignedImmediate: (operands at: 0) ifTrue: [:r :i :n| 4] ifFalse: [self literalLoadInstructionBytes + 4]]. [OrCqR] -> [^self rotateable8bitImmediate: (operands at: 0) ifTrue: [:r :i| 4] ifFalse: [self literalLoadInstructionBytes + 4]]. [SubCqR] -> [^self rotateable8bitSignedImmediate: (operands at: 0) ifTrue: [:r :i :n| 4] ifFalse: [self literalLoadInstructionBytes + 4]]. [TstCqR] -> [^self rotateable8bitImmediate: (operands at: 0) ifTrue: [:r :i| 4] ifFalse: [self literalLoadInstructionBytes + 4]]. [XorCqR] -> [^self rotateable8bitBitwiseImmediate: (operands at: 0) ifTrue: [:r :i :n| 4] ifFalse: [self literalLoadInstructionBytes = 4 ifTrue: [8] ifFalse: [1 << (operands at: 0) highBit = ((operands at: 0) + 1) ifTrue: [8] ifFalse: [self literalLoadInstructionBytes + 4]]]]. [AddCwR] -> [^self literalLoadInstructionBytes + 4]. [AndCwR] -> [^self literalLoadInstructionBytes + 4]. [CmpCwR] -> [^self literalLoadInstructionBytes + 4]. [OrCwR] -> [^self literalLoadInstructionBytes + 4]. [SubCwR] -> [^self literalLoadInstructionBytes + 4]. [XorCwR] -> [^self literalLoadInstructionBytes + 4]. + [AddRR] -> [^4]. + [AndRR] -> [^4]. - [AddRR] -> [^4]. - [AndRR] -> [^4]. [CmpRR] -> [^4]. [OrRR] -> [^4]. [XorRR] -> [^4]. + [SubRR] -> [^4]. + [AddRRR] -> [^4]. + [SubRRR] -> [^4]. - [SubRR] -> [^4]. [NegateR] -> [^4]. [LoadEffectiveAddressMwrR] -> [^self rotateable8bitImmediate: (operands at: 0) ifTrue: [:r :i| 4] ifFalse: [self literalLoadInstructionBytes + 4]]. [LogicalShiftLeftCqR] -> [^4]. [LogicalShiftRightCqR] -> [^4]. [ArithmeticShiftRightCqR] -> [^4]. [LogicalShiftLeftRR] -> [^4]. [LogicalShiftRightRR] -> [^4]. [ArithmeticShiftRightRR] -> [^4]. [AddRdRd] -> [^4]. [CmpRdRd] -> [^4]. [SubRdRd] -> [^4]. [MulRdRd] -> [^4]. [DivRdRd] -> [^4]. [SqrtRd] -> [^4]. [ClzRR] -> [^4]. "ARM Specific Arithmetic" [SMULL] -> [^4]. [MSR] -> [^4]. [CMPSMULL] -> [^4]. "special compare for genMulR:R: usage" "ARM Specific Data Movement" [PopLDM] -> [^4]. [PushSTM] -> [^4]. "Data Movement" [MoveCqR] -> [^self literalLoadInstructionBytes = 4 ifTrue: [self literalLoadInstructionBytes] ifFalse: [self rotateable8bitBitwiseImmediate: (operands at: 0) ifTrue: [:r :i :n| 4] ifFalse: [self literalLoadInstructionBytes]]]. [MoveCwR] -> [^self literalLoadInstructionBytes = 4 ifTrue: [self literalLoadInstructionBytes] ifFalse: [(self inCurrentCompilation: (operands at: 0)) ifTrue: [4] ifFalse: [self literalLoadInstructionBytes]]]. [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] -> [^self is12BitValue: (operands at: 1) ifTrue: [:u :i| 4] ifFalse: [self literalLoadInstructionBytes + 4]]. [MoveRdM64r] -> [^4]. [MoveMbrR] -> [^self is12BitValue: (operands at: 0) ifTrue: [:u :i| 4] ifFalse: [self literalLoadInstructionBytes + 4]]. [MoveRMbr] -> [^self is12BitValue: (operands at: 1) ifTrue: [:u :i| 4] ifFalse: [self literalLoadInstructionBytes + 4]]. [MoveRM16r] -> [^self is12BitValue: (operands at: 1) ifTrue: [:u :i| 4] ifFalse: [self literalLoadInstructionBytes + 4]]. [MoveM16rR] -> [^self rotateable8bitImmediate: (operands at: 0) ifTrue: [:r :i| 4] ifFalse: [self literalLoadInstructionBytes + 4]]. [MoveM64rRd] -> [^4]. [MoveMwrR] -> [^self is12BitValue: (operands at: 0) ifTrue: [:u :i| 4] ifFalse: [self literalLoadInstructionBytes + 4]]. [MoveXbrRR] -> [^4]. [MoveRXbrR] -> [^4]. [MoveXwrRR] -> [^4]. [MoveRXwrR] -> [^4]. [PopR] -> [^4]. [PushR] -> [^4]. [PushCw] -> [^self literalLoadInstructionBytes = 4 ifTrue: [self literalLoadInstructionBytes + 4] ifFalse: [(self inCurrentCompilation: (operands at: 0)) ifTrue: [8] ifFalse: [self rotateable8bitBitwiseImmediate: (operands at: 0) ifTrue: [:r :i :n| 8] ifFalse: [self literalLoadInstructionBytes + 4]]]]. [PushCq] -> [^self literalLoadInstructionBytes = 4 ifTrue: [self literalLoadInstructionBytes + 4] ifFalse: [self rotateable8bitBitwiseImmediate: (operands at: 0) ifTrue: [:r :i :n| 8] ifFalse: [self literalLoadInstructionBytes + 4]]]. [PrefetchAw] -> [^(self isAddressRelativeToVarBase: (operands at: 0)) ifTrue: [4] ifFalse: [self literalLoadInstructionBytes + 4]]. "Conversion" [ConvertRRd] -> [^8]. }. ^0 "to keep C compiler quiet" ! Item was changed: ----- Method: CogARMCompiler>>concretizeDataOperationRR: (in category 'generate machine code - concretize') ----- concretizeDataOperationRR: armOpcode "Will get inlined into concretizeAt: switch." - "Load the word into the RISCTempReg, then op R, RISCTempReg" <inline: true> | rn rd srcReg | srcReg := operands at: 0. rn := operands at: 1. rd := armOpcode = CmpOpcode ifTrue: [0] ifFalse: [rn]. self machineCodeAt: 0 put: (self type: 0 op: armOpcode set: 1 rn: rn rd: rd shifterOperand: srcReg). + ^4! - ^4.! Item was added: + ----- Method: CogARMCompiler>>concretizeDataOperationRRR: (in category 'generate machine code - concretize') ----- + concretizeDataOperationRRR: armOpcode + "Will get inlined into concretizeAt: switch." + <inline: true> + | rn rd srcReg | + srcReg := operands at: 0. + rn := operands at: 1. + rd := operands at: 2. + self machineCodeAt: 0 + put: (self type: 0 op: armOpcode set: 1 rn: rn rd: rd shifterOperand: srcReg). + ^4! Item was changed: ----- Method: CogARMCompiler>>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." conditionOrNil ifNotNil: [^self concretizeConditionalInstruction]. opcode caseOf: { "Noops & Pseudo Ops" [Label] -> [^self concretizeLabel]. [Literal] -> [^self concretizeLiteral]. [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 concretizeConditionalJump: AL]."jump within code space" [JumpLongZero] -> [^self concretizeConditionalJump: EQ]. [JumpLongNonZero] -> [^self concretizeConditionalJump: NE]. [Jump] -> [^self concretizeConditionalJump: AL]. "jump within a method, etc" [JumpZero] -> [^self concretizeConditionalJump: EQ]. [JumpNonZero] -> [^self concretizeConditionalJump: NE]. [JumpNegative] -> [^self concretizeConditionalJump: MI]. [JumpNonNegative] -> [^self concretizeConditionalJump: PL]. [JumpOverflow] -> [^self concretizeConditionalJump: VS]. [JumpNoOverflow] -> [^self concretizeConditionalJump: VC]. [JumpCarry] -> [^self concretizeConditionalJump: CS]. [JumpNoCarry] -> [^self concretizeConditionalJump: CC]. [JumpLess] -> [^self concretizeConditionalJump: LT]. [JumpGreaterOrEqual] -> [^self concretizeConditionalJump: GE]. [JumpGreater] -> [^self concretizeConditionalJump: GT]. [JumpLessOrEqual] -> [^self concretizeConditionalJump: LE]. [JumpBelow] -> [^self concretizeConditionalJump: CC]. "unsigned lower" [JumpAboveOrEqual] -> [^self concretizeConditionalJump: CS]. "unsigned greater or equal" [JumpAbove] -> [^self concretizeConditionalJump: HI]. [JumpBelowOrEqual] -> [^self concretizeConditionalJump: LS]. [JumpFPEqual] -> [^self concretizeFPConditionalJump: EQ]. [JumpFPNotEqual] -> [^self concretizeFPConditionalJump: NE]. [JumpFPLess] -> [^self concretizeFPConditionalJump: LT]. [JumpFPGreaterOrEqual] -> [^self concretizeFPConditionalJump: GE]. [JumpFPGreater] -> [^self concretizeFPConditionalJump: GT]. [JumpFPLessOrEqual] -> [^self concretizeFPConditionalJump: LE]. [JumpFPOrdered] -> [^self concretizeFPConditionalJump: VC]. [JumpFPUnordered] -> [^self concretizeFPConditionalJump: VS]. [RetN] -> [^self concretizeRetN]. [Stop] -> [^self concretizeStop]. "Arithmetic" [AddCqR] -> [^self concretizeNegateableDataOperationCqR: AddOpcode]. [AndCqR] -> [^self concretizeInvertibleDataOperationCqR: AndOpcode]. [AndCqRR] -> [^self concretizeAndCqRR]. [CmpCqR] -> [^self concretizeNegateableDataOperationCqR: CmpOpcode]. + [OrCqR] -> [^self concretizeDataOperationCqR: OrOpcode]. - [OrCqR] -> [^self concretizeDataOperationCqR: OrOpcode]. [SubCqR] -> [^self concretizeSubCqR]. [TstCqR] -> [^self concretizeTstCqR]. [XorCqR] -> [^self concretizeInvertibleDataOperationCqR: XorOpcode]. [AddCwR] -> [^self concretizeDataOperationCwR: AddOpcode]. [AndCwR] -> [^self concretizeDataOperationCwR: AndOpcode]. [CmpCwR] -> [^self concretizeDataOperationCwR: CmpOpcode]. [OrCwR] -> [^self concretizeDataOperationCwR: OrOpcode]. [SubCwR] -> [^self concretizeDataOperationCwR: SubOpcode]. [XorCwR] -> [^self concretizeDataOperationCwR: XorOpcode]. + [AddRR] -> [^self concretizeDataOperationRR: AddOpcode]. + [AndRR] -> [^self concretizeDataOperationRR: AndOpcode]. - [AddRR] -> [^self concretizeDataOperationRR: AddOpcode]. - [AndRR] -> [^self concretizeDataOperationRR: AndOpcode]. [CmpRR] -> [^self concretizeDataOperationRR: CmpOpcode]. [OrRR] -> [^self concretizeDataOperationRR: OrOpcode]. + [SubRR] -> [^self concretizeDataOperationRR: SubOpcode]. - [SubRR] -> [^self concretizeDataOperationRR: SubOpcode]. [XorRR] -> [^self concretizeDataOperationRR: XorOpcode]. + [AddRRR] -> [^self concretizeDataOperationRRR: AddOpcode]. + [SubRRR] -> [^self concretizeDataOperationRRR: SubOpcode]. [AddRdRd] -> [^self concretizeAddRdRd]. [CmpRdRd] -> [^self concretizeCmpRdRd]. [DivRdRd] -> [^self concretizeDivRdRd]. [MulRdRd] -> [^self concretizeMulRdRd]. [SubRdRd] -> [^self concretizeSubRdRd]. [SqrtRd] -> [^self concretizeSqrtRd]. [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]. "ARM Specific Arithmetic" [SMULL] -> [^self concretizeSMULL] . [CMPSMULL] -> [^self concretizeCMPSMULL]. [MSR] -> [^self concretizeMSR]. "ARM Specific Data Movement" [PopLDM] -> [^self concretizePushOrPopMultipleRegisters: false]. [PushSTM] -> [^self concretizePushOrPopMultipleRegisters: true]. "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 concretizeMoveRMbr]. [MoveRM16r] -> [^self concretizeMoveRM16r]. [MoveM16rR] -> [^self concretizeMoveM16rR]. [MoveM64rRd] -> [^self concretizeMoveM64rRd]. [MoveMwrR] -> [^self concretizeMoveMwrR]. [MoveXbrRR] -> [^self concretizeMoveXbrRR]. [MoveRXbrR] -> [^self concretizeMoveRXbrR]. [MoveXwrRR] -> [^self concretizeMoveXwrRR]. [MoveRXwrR] -> [^self concretizeMoveRXwrR]. [MoveRMwr] -> [^self concretizeMoveRMwr]. [MoveRdM64r] -> [^self concretizeMoveRdM64r]. [PopR] -> [^self concretizePopR]. [PushR] -> [^self concretizePushR]. [PushCq] -> [^self concretizePushCq]. [PushCw] -> [^self concretizePushCw]. [PrefetchAw] -> [^self concretizePrefetchAw]. "Conversion" [ConvertRRd] -> [^self concretizeConvertRRd]}. ^0 "keep Slang happy"! Item was changed: ----- Method: CogObjectRepresentationForSpur>>genGetActiveContextLarge:inBlock: (in category 'initialization') ----- genGetActiveContextLarge: isLarge inBlock: isInBlock "Create a trampoline to answer the active context that will answer it if a frame is already married, and create it otherwise. Assume numArgs is in SendNumArgsReg and ClassReg is free." | header slotSize jumpSingle loopHead jumpNeedScavenge continuation exit | <var: #jumpNeedScavenge type: #'AbstractInstruction *'> <var: #continuation type: #'AbstractInstruction *'> <var: #jumpSingle type: #'AbstractInstruction *'> <var: #loopHead type: #'AbstractInstruction *'> <var: #exit type: #'AbstractInstruction *'> cogit "load the flag; stash it in both TempReg & ClassReg; do the compare (a prime candidated for use of AndCq:R:R:)" MoveMw: FoxMethod r: FPReg R: ClassReg; AndCq: MFMethodFlagHasContextFlag R: ClassReg R: TempReg. jumpSingle := cogit JumpZero: 0. "jump if flag bit not set" cogit "since the flag bit was set, get the context in the receiver reg and return" MoveMw: FoxThisContext r: FPReg R: ReceiverResultReg; RetN: 0. jumpSingle jmpTarget: cogit Label. "OK, it doesn't exist; instantiate and initialize it" "set the hasContext flag; See CoInterpreter class>>initializeFrameIndices" cogit OrCq: MFMethodFlagHasContextFlag R: ClassReg; MoveR: ClassReg Mw: FoxMethod r: FPReg. "now get the home CogMethod into ClassReg and save for post-instantiation." isInBlock caseOf: { [InFullBlock] -> [cogit SubCq: 3 R: ClassReg]. "-3 is -(hasContext+isBlock) flags" [InVanillaBlock] -> [cogit SubCq: 3 R: ClassReg; "-3 is -(hasContext+isBlock) flags" MoveM16: 0 r: ClassReg R: TempReg; SubR: TempReg R: ClassReg]. [0] -> [cogit SubCq: 1 R: ClassReg]. "-1 is hasContext flag" }. "instantiate the context..." slotSize := isLarge ifTrue: [LargeContextSlots] ifFalse: [SmallContextSlots]. header := objectMemory headerForSlots: slotSize format: objectMemory indexablePointersFormat classIndex: ClassMethodContextCompactIndex. self flag: #endianness. cogit MoveAw: objectMemory freeStartAddress R: ReceiverResultReg. self genStoreHeader: header intoNewInstance: ReceiverResultReg using: TempReg. cogit MoveR: ReceiverResultReg R: TempReg; AddCq: (objectMemory smallObjectBytesForSlots: slotSize) R: TempReg; MoveR: TempReg Aw: objectMemory freeStartAddress; CmpCq: objectMemory getScavengeThreshold R: TempReg. jumpNeedScavenge := cogit JumpAboveOrEqual: 0. "Now initialize the fields of the context. See CoInterpreter>>marryFrame:SP:copyTemps:" "sender gets frame pointer as a SmallInteger" continuation := cogit MoveR: FPReg R: TempReg. self genSetSmallIntegerTagsIn: TempReg. cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (SenderIndex * objectMemory bytesPerOop) r: ReceiverResultReg. "pc gets frame caller as a SmallInteger" cogit MoveMw: FoxSavedFP r: FPReg R: TempReg. self genSetSmallIntegerTagsIn: TempReg. cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (InstructionPointerIndex * objectMemory bytesPerOop) r: ReceiverResultReg. "Set the method field, freeing up ClassReg again, and frame's context field," cogit MoveMw: (cogit offset: CogMethod of: #methodObject) r: ClassReg R: TempReg; MoveR: TempReg Mw: objectMemory baseHeaderSize + (MethodIndex * objectMemory wordSize) r: ReceiverResultReg; MoveR: ReceiverResultReg Mw: FoxThisContext r: FPReg. "Now compute stack pointer; this is stackPointer (- 1 for return pc if a CISC) - framePointer - wordSize (1 each for saved pc, method, context, receiver) + 1 (1-relative) + numArgs" "TPR note - the code here is actually doing context stackPointer := ((((fp - sp) / wordSize) - [3|4]) + num args) asSmallInteger" cogit + SubR: SPReg R: FPReg R: TempReg; "TempReg := FPReg - SPReg" - MoveR: FPReg R: TempReg; - SubR: SPReg R: TempReg; LogicalShiftRightCq: self log2BytesPerWord R: TempReg; SubCq: (cogit backEnd hasLinkRegister ifTrue: [3] ifFalse: [4]) R: TempReg; AddR: SendNumArgsReg R: TempReg. self genConvertIntegerToSmallIntegerInReg: TempReg. cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (StackPointerIndex * objectMemory bytesPerOop) r: ReceiverResultReg. "Set closureOrNil to either the stacked receiver or nil" isInBlock > 0 ifTrue: [cogit MoveR: SendNumArgsReg R: TempReg; AddCq: 2 R: TempReg; "+2 for saved fp and saved pc" MoveXwr: TempReg R: FPReg R: TempReg] ifFalse: [cogit genMoveNilR: TempReg]. cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (ClosureIndex * objectMemory bytesPerOop) r: ReceiverResultReg. "Set the receiver" cogit MoveMw: FoxMFReceiver r: FPReg R: TempReg; MoveR: TempReg Mw: objectMemory baseHeaderSize + (ReceiverIndex * objectMemory bytesPerOop) r: ReceiverResultReg. "Now copy the arguments. This is tricky because of the shortage of registers,. ClassReg ranges from 1 to numArgs (SendNumArgsReg), and from ReceiverIndex + 1 to ReceiverIndex + numArgs. 1 to: numArgs do: [:i| temp := longAt(FPReg + ((SendNumArgs - i + 2) * wordSize)). +2 for saved pc and savedfp longAtput(FPReg + FoxMFReceiver + (i * wordSize), temp)]" "TPR note: this is a prime candidate for passing off to the backend to do at least faintly optimal code" cogit MoveCq: 1 R: ClassReg. loopHead := cogit CmpR: SendNumArgsReg R: ClassReg. exit := cogit JumpGreater: 0. cogit MoveR: SendNumArgsReg R: TempReg; SubR: ClassReg R: TempReg; AddCq: 2 R: TempReg; "+2 for saved fp and saved pc" MoveXwr: TempReg R: FPReg R: TempReg; AddCq: ReceiverIndex + (objectMemory baseHeaderSize / objectMemory wordSize) R: ClassReg; "Now convert ClassReg from frame index to context index" MoveR: TempReg Xwr: ClassReg R: ReceiverResultReg; SubCq: ReceiverIndex + (objectMemory baseHeaderSize / objectMemory wordSize) - 1 R: ClassReg; "convert back adding 1 ;-)" Jump: loopHead. exit jmpTarget: cogit Label. "Finally nil or copy the non-argument temps. ClassReg := FPReg + FoxMFReceiver. SendNumArgsReg := SendNumArgsReg+ReceiverIndex. [ClassReg := ClassReg - wordSize. backEnd hasLinkRegister ifTrue: [ClassReg > SPReg] ifFalse: [ClassReg >= SPReg]] whileTrue: [receiver[SendNumArgsReg] := *ClassReg. SendNumArgsReg := SendNumArgsReg + 1]]" coInterpreter marryFrameCopiesTemps ifFalse: [cogit MoveCq: objectMemory nilObject R: TempReg]. cogit MoveR: FPReg R: ClassReg; AddCq: FoxMFReceiver R: ClassReg; AddCq: ReceiverIndex + 1 + (objectMemory baseHeaderSize / objectMemory wordSize) R: SendNumArgsReg. loopHead := cogit SubCq: objectMemory wordSize R: ClassReg. cogit CmpR: SPReg R: ClassReg. "If on a CISC there's a retpc for the trampoline call on top of stack; if on a RISC there isn't." exit := cogit backEnd hasLinkRegister ifTrue: [cogit JumpBelow: 0] ifFalse: [cogit JumpBelowOrEqual: 0]. coInterpreter marryFrameCopiesTemps ifTrue: [cogit MoveMw: 0 r: ClassReg R: TempReg]. cogit MoveR: TempReg Xwr: SendNumArgsReg R: ReceiverResultReg; AddCq: 1 R: SendNumArgsReg; Jump: loopHead. exit jmpTarget: cogit Label. cogit RetN: 0. jumpNeedScavenge jmpTarget: cogit Label. cogit backEnd saveAndRestoreLinkRegAround: [cogit CallRT: ceScheduleScavengeTrampoline registersToBeSavedMask: (cogit registerMaskFor: ReceiverResultReg and: SendNumArgsReg and: ClassReg)]. cogit Jump: continuation. ^0! Item was changed: SharedPool subclass: #CogRTLOpcodes instanceVariableNames: '' + classVariableNames: 'AddCqR AddCwR AddRR AddRRR AddRdRd AddRsRs AddcCqR AddcRR AlignmentNops AndCqR AndCqRR AndCwR AndRR ArithmeticShiftRightCqR 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 LogicalShiftLeftRR LogicalShiftRightCqR LogicalShiftRightRR MoveA32R MoveAbR MoveAwR MoveC32R MoveCqR MoveCwR MoveM16rR MoveM32rR MoveM32rRs MoveM64rRd MoveM8rR MoveMbrR Mo veMs8rR 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' - classVariableNames: 'AddCqR AddCwR AddRR AddRdRd AddRsRs AddcCqR AddcRR AlignmentNops AndCqR AndCqRR AndCwR AndRR ArithmeticShiftRightCqR 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 LogicalShiftLeftRR LogicalShiftRightCqR LogicalShiftRightRR MoveA32R MoveAbR MoveAwR MoveC32R MoveCqR 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 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') ----- initialize "Abstract opcodes are a compound of a one word operation specifier and zero or more operand type specifiers. The assembler is in Cogit protocol abstract instructions and uses `at&t' syntax, assigning to the register on the right. e.g. MoveRR is the Move opcode with two register operand specifiers and defines a move register to register instruction from operand 0 to operand 1. The word and register size is assumed to be either 32-bits on a 32-bit architecture or 64-bits on a 64-bit architecture. The abstract machine is mostly a 2 address machine with the odd three address instruction added to better exploit RISCs. (self initialize) The operand specifiers are R - general purpose register Rs - single-precision floating-point register Rd - double-precision floating-point register Cq - a `quick' constant that can be encoded in the minimum space possible. Cw - a constant with word size where word is the default operand size for the Smalltalk VM, 32-bits for a 32-bit VM, 64-bits for a 64-bit VM. The generated constant must occupy the default number of bits. This allows e.g. a garbage collector to update the value without invalidating the code. C32 - a constant with 32 bit size. The generated constant must occupy 32 bits. C64 - a constant with 64 bit size. The generated constant must occupy 64 bits. Aw - memory word (32-bits for a 32-bit VM, 64-bits for a 64-bit VM) at an absolute address See note about MoveAwR and MoveRAw in the opcodeNames literal array below!!!! Ab - memory byte at an absolute address A32 - memory 32-bit halfword at an absolute address Mwr - memory word whose address is at a constant offset from an address in a register Mbr - memory byte whose address is at a constant offset from an address in a register (zero-extended on read) M16r - memory 16-bit halfword whose address is at a constant offset from an address in a register M32r - memory 32-bit halfword whose address is at a constant offset from an address in a register M64r - memory 64-bit doubleword whose address is at a constant offset from an address in a register Xbr - memory byte whose address is r * byte size away from an address in a register X16r - memory 16-bit halfword whose address is r * (2 bytes size) away from an address in a register X32r - memory 32-bit halfword whose address is r * (4 bytes size) away from an address in a register (64-bit ISAs only) Xwr - memory word whose address is r * word size away from an address in a register Xowr - memory word whose address is o + (r * word size) away from an address in a register (scaled indexed) An alternative would be to decouple opcodes from operands, e.g. Move := 1. Add := 2. Sub := 3... RegisterOperand := 1. ConstantQuickOperand := 2. ConstantWordOperand := 3... But not all combinations make sense and even fewer are used so we stick with the simple compound approach. The assumption is that comparison and arithmetic instructions set condition codes (*) and that move instructions leave the condition codes unaffected. In particular LoadEffectiveAddressMwrR does not set condition codes although it can be used to do arithmetic. On processors such as MIPS this distinction is invalid; there are no condition codes. So the backend is allowed to collapse operation, branch pairs to internal instruction definitions (see senders and implementors of noteFollowingConditionalBranch:). We also assume that arithmetic sets the carry flag but that Add?R/Sub?R et al ignore the carry flag as a source operand. This is because multiple precision arithmetic is implem ented in plugins (LargeIntegerPlugins) and hence not (yet) important here. (*) the back end is not expected to set the condition codes if arithmetic is done to change the value of the stack pointer. Not all of the definitions in opcodeDefinitions below are implemented. In particular we do not implement the XowrR scaled index addressing mode since it requires 4 operands. Not all instructions make sense on all architectures. MoveRRd and MoveRdR are meaningful only on 64-bit machines. Note that there are no generic division instructions defined, but a processor may define some. Branch/Call ranges. Jump[Cond] can be generated as short as possible. Call/Jump[Cond]Long must be generated in the same number of bytes irrespective of displacement since their targets may be updated, but they need only span 16Mb, the maximum size of the code zone. This allows e.g. ARM to use single-word call and jump instructions for most calls and jumps. CallFull/JumpFull must also be generated in the same number of bytes irrespective of displacement for the same reason, but they must be able to span the full (32-bit or 64-bit) address space because they are used to call code in the C runtime, which may be distant from the code zone. CallFull/JumpFull are allowed to use the cResultRegister as a scratch if required (e.g. on x64 where there is no direct 64-bit call or jump). Byte reads. If the concrete compiler class answers true to byteReadsZeroExtend then byte reads must zero-extend the byte read into the destination register. If not, the other bits of the register should be left undisturbed and the Cogit will add an instruction to zero the register as required. Under no circumstances should byte reads sign-extend. 16-bit (and on 64-bits, 32-bit) reads. These /are/ expected to always zero-extend." | opcodeNames refs | opcodeNames := #("Noops & Pseudo Ops" Label Literal "a word-sized literal" AlignmentNops Fill32 "output four byte's worth of bytes with operand 0" Nop "Control" Call "call within the code zone" CallFull "call anywhere within the full address space" CallR RetN JumpR "Not a regular jump, i.e. not pc dependent." Stop "Halt the processor" "N.B. Jumps are contiguous. Long and Full jumps are contiguous within them. See FirstJump et al below" JumpFull "Jump anywhere within the address space" JumpLong "Jump anywhere within the 16mb code zone." JumpLongZero "a.k.a. JumpLongEqual" JumpLongNonZero "a.k.a. JumpLongNotEqual" Jump "short jumps; can be encoded in as few bytes as possible; will not be disturbed by GC or relocation." JumpZero "a.k.a. JumpEqual" JumpNonZero "a.k.a. JumpNotEqual" JumpNegative JumpNonNegative JumpOverflow JumpNoOverflow JumpCarry JumpNoCarry JumpLess "signed" JumpGreaterOrEqual JumpGreater JumpLessOrEqual JumpBelow "unsigned" JumpAboveOrEqual JumpAbove JumpBelowOrEqual JumpFPEqual JumpFPNotEqual JumpFPLess JumpFPLessOrEqual JumpFPGreater JumpFPGreaterOrEqual JumpFPOrdered JumpFPUnordered "Data Movement; destination is always last operand" MoveRR "N.B. On certain targets (including X64) MoveAwR & MoveRAw may smash TempReg if the register argument is either FPReg or SPReg!!!!" MoveAwR MoveA32R MoveRAw MoveRA32 MoveAbR MoveRAb MoveMwrR MoveRMwr MoveXwrRR MoveRXwrR "MoveXowrR MoveRXowr""Unused" MoveM8rR MoveMs8rR MoveRM8r MoveM16rR MoveRM16r MoveX16rRR MoveRX16rR MoveM32rR MoveRM32r MoveX32rRR MoveRX32rR MoveMbrR MoveRMbr MoveXbrRR MoveRXbrR MoveCqR MoveCwR MoveC32R "MoveC64R""Not used" MoveRRd MoveRdR MoveRdRd MoveM64rRd MoveRdM64r MoveRsRs MoveM32rRs MoveRsM32r PopR PushR PushCq PushCw PrefetchAw "Arithmetic; destination is always last operand except Cmp; CmpXR is SubRX with no update of result" LoadEffectiveAddressMwrR "LoadEffectiveAddressXowrR" "Variants of add/multiply" NegateR "2's complement negation" NotR ArithmeticShiftRightCqR ArithmeticShiftRightRR LogicalShiftRightCqR LogicalShiftRightRR LogicalShiftLeftCqR LogicalShiftLeftRR RotateLeftCqR RotateRightCqR CmpRR AddRR SubRR AndRR OrRR XorRR CmpCqR AddCqR SubCqR AndCqR OrCqR TstCqR XorCqR CmpCwR CmpC32R AddCwR SubCwR AndCwR OrCwR XorCwR AddcRR AddcCqR SubbRR SubbCqR + "Three address ops for RISCs; feel free to add and extend" + AndCqRR AddRRR SubRRR - AndCqRR "Three address ops for RISCs; feel free to add and extend" CmpRdRd AddRdRd SubRdRd MulRdRd DivRdRd SqrtRd XorRdRd CmpRsRs AddRsRs SubRsRs MulRsRs DivRsRs SqrtRs XorRsRs "Conversion" ConvertRRd ConvertRdR ConvertRsRd ConvertRdRs ConvertRsR ConvertRRs SignExtend8RR SignExtend16RR SignExtend32RR ZeroExtend8RR ZeroExtend16RR ZeroExtend32RR "Advanced bit manipulation (aritmetic)" ClzRR LastRTLCode). "Magic auto declaration. Add to the classPool any new variables and nuke any obsolete ones, and assign values" "Find the variables directly referenced by this method" refs := (thisContext method literals select: [:l| l isVariableBinding and: [classPool includesKey: l key]]) collect: [:ea| ea key]. "Move to Undeclared any opcodes in classPool not in opcodes or this method." (classPool keys reject: [:k| (opcodeNames includes: k) or: [refs includes: k]]) do: [:k| Undeclared declare: k from: classPool]. "Declare as class variables and number elements of opcodeArray above" opcodeNames withIndexDo: [:classVarName :value| self classPool declare: classVarName from: Undeclared; at: classVarName put: value]. "For CogAbstractInstruction>>isJump etc..." FirstJump := JumpFull. LastJump := JumpFPUnordered. FirstShortJump := Jump. "And now initialize the backends; they add their own opcodes and hence these must be reinitialized." (Smalltalk classNamed: #CogAbstractInstruction) ifNotNil: [:cogAbstractInstruction| cogAbstractInstruction allSubclasses do: [:sc| sc initialize]]! Item was added: + ----- Method: Cogit>>AddR:R:R: (in category 'abstract instructions') ----- + AddR: addendReg R: badendReg R: destReg + "destReg := addendReg + badendReg" + <inline: false> + <returnTypeC: #'AbstractInstruction *'> + | first | + <var: 'first' type: #'AbstractInstruction *'> + backEnd hasThreeAddressArithmetic ifTrue: + [^self gen: AddRRR operand: addendReg operand: badendReg operand: destReg]. + self assert: badendReg ~= destReg. + first := self gen: MoveRR operand: addendReg operand: destReg. + self gen: AddRR operand: badendReg operand: destReg. + ^first! Item was added: + ----- Method: Cogit>>SubR:R:R: (in category 'abstract instructions') ----- + SubR: subReg R: fromReg R: destReg + "destReg := fromReg - subReg" + <inline: false> + <returnTypeC: #'AbstractInstruction *'> + | first | + <var: 'first' type: #'AbstractInstruction *'> + backEnd hasThreeAddressArithmetic ifTrue: + [^self gen: SubRRR operand: subReg operand: fromReg operand: destReg]. + self assert: subReg ~= destReg. + first := self gen: MoveRR operand: fromReg operand: destReg. + self gen: SubRR operand: subReg operand: destReg. + ^first! |
Free forum by Nabble | Edit this page |