[Vm-dev] VM Maker: VMMaker.oscog-tpr.719.mcz

commits at source.squeak.org commits at source.squeak.org
Thu May 15 21:51:59 UTC 2014


tim Rowledge uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-tpr.719.mcz

==================== Summary ====================

Name: VMMaker.oscog-tpr.719
Author: tpr
Time: 15 May 2014, 1:52:11.316 pm
UUID: 25cb5d93-f8cf-4efe-874f-7f363c5b7a84
Ancestors: VMMaker.oscog-tpr.718

This *should* be a merge of the latest Eliot-cog with the latest tpr-ARM-cog. Hope it merged ok... and uploaded ;-)

=============== Diff against VMMaker.oscog-eem.717 ===============

Item was added:
+ ----- Method: CogARMCompiler class>>ARMTempReg (in category 'accessing') -----
+ ARMTempReg
+ "return the name of the general temp reg in the ARM APCS convention"
+ 	^RISCTempReg!

Item was changed:
  ----- Method: CogARMCompiler class>>initialize (in category 'class initialization') -----
  initialize
  	
  	"Initialize various ARM instruction-related constants."
  	"CogARMCompiler initialize"
  	
  	| specificOpcodes refs conditionCodes |
  	super initialize.
  	self ~~ CogARMCompiler ifTrue: [^self].
  	
+ 	R0 := 0.
+ 	R1 := 1.
+ 	R2 := 2.
+ 	R3 := 3.
+ 	R4 := 4.
+ 	R5 := 5.
+ 	R6 := 6.
+ 	R7 := 7.
+ 	R8 := 8.
+ 	R9 := 9.
+ 	R10 := 10.
+ 	R11 := 11.
+ 	R12 := 12..
+ 	SP := 13..
- 	R0 := 0. R1 := 1.
- 	R2 := 2. R3 := 3.
- 	R4 := 4. R5 := 5.
- 	R6 := 6. R7 := 7.
- 	R8 := 8. R9 := 9.
- 	R10 := 10. R11 := 11.
- 	R12 := 12.
- 	SP := 13.
  	LR := 14.
  	PC := 15.
  	
+ 	CArg0Reg := 0.
+ 	CArg1Reg := 1.
+ 	CArg2Reg := 2.
+ 	CArg3Reg := 3.
- 	CArg0Reg := 0. CArg1Reg := 1. CArg2Reg := 2. CArg3Reg := 3.
  	
  	RISCTempReg := R10.
  	
+ 	"Condition Codes. Note that cc=16rF is NOT ALLOWED as a condition; it specifies an extension instruction. See e.g.ARM_ARM v5 DDI01001.pdf A3.2.1"
- 	"Condition Codes"
  	conditionCodes := #(EQ NE CS CC MI PL VS VC HI LS GE LT GT LE AL).
+ 	"this is a somewhat odd way to set class variables - were they originally globals?"
  	conditionCodes withIndexDo: [ :classVarName :value | 
  		self classPool
  			declare: classVarName from: Undeclared;
  			at: classVarName put: value - 1].
  	
  	"Specific instructions"
  	LastRTLCode isNil ifTrue:
  		[CogRTLOpcodes initialize].
  	specificOpcodes := #(LDMFD STMFD).
  	refs := (thisContext method literals select: [:l| l isVariableBinding and: [classPool includesKey: l key]]) collect:
  				[:ea| ea key].
  	(classPool keys reject: [:k| (specificOpcodes includes: k) or: [refs includes: k] or: [conditionCodes includes: k]]) do:
  		[:k|
  		Undeclared declare: k from: classPool].
  	specificOpcodes withIndexDo:
  		[:classVarName :value|
  		self classPool
  			declare: classVarName from: Undeclared;
  			at: classVarName put: value + LastRTLCode - 1]!

Item was added:
+ ----- Method: CogARMCompiler>>add:rn:imm:ror: (in category 'ARM convenience instructions') -----
+ add: destReg rn: srcReg imm: immediate ror: rot
+ "return an ADD destReg, srcReg, immediat ROR rot instruction"
+ 
+ 	^self type: 1 op: 4 set: 0 rn: srcReg rd: destReg shifterOperand: (rot <<8 bitOr: immediate)!

Item was added:
+ ----- Method: CogARMCompiler>>addRd:rn:imm:ror: (in category 'ARM convenience instructions') -----
+ addRd: destReg rn: srcReg imm: immediate ror: rot
+ "return an ADD destReg, srcReg, immediat ROR rot instruction"
+ 
+ 	^self type: 1 op: 4 set: 0 rn: srcReg rd: destReg shifterOperand: (rot <<8 bitOr: immediate)!

Item was added:
+ ----- Method: CogARMCompiler>>addRd:rn:rm: (in category 'ARM convenience instructions') -----
+ addRd: destReg rn: srcReg rm: addReg
+ "return an ADD destReg, srcReg, addReg instruction"
+ 
+ 	^self type: 0 op: 4 set: 0 rn: srcReg rd: destReg shifterOperand: addReg!

Item was added:
+ ----- Method: CogARMCompiler>>adds:rn:imm:ror: (in category 'ARM convenience instructions') -----
+ adds: destReg rn: srcReg imm: immediate ror: rot
+ "return an ADDS destReg, srcReg, immediat ROR rot instruction"
+ 
+ 	^self type: 1 op: 4 set: 1 rn: srcReg rd: destReg shifterOperand: (rot <<8 bitOr: immediate)!

Item was changed:
  ----- Method: CogARMCompiler>>at:moveCw:intoR: (in category 'generate machine code - concretize') -----
  at: offset moveCw: constant intoR: destReg
  	"This loads aWord into the inter-opcode temporary register. Because most ARM instruction enable using a (8-12bit) offset relative to a register, the LS Byte can be included in that instruction, saving one instruction. This is done in a decorator, e.g. CmpCqR"
  	"Generates:along the lines of
  	MOV destReg, #<constantByte3>, 12
  	ORR destReg, destReg, #<constantByte2>, 8
  	ORR destReg, destReg, #<constantByte1>, 4
  	ORR destReg, destReg, #<constantByte0>, 0
  	with minimal choice of the rotation (last digit)"
  	"The same area can be modified multiple times, because the opperation is (inclusive) or."
  	<inline: true>
+ 	"self assert: destReg < 12."
+ 
+ 	self machineCodeAt: offset put: (self mov: destReg imm: (constant >>24 bitAnd: 16rFF) ror: 8).
+ 	self machineCodeAt: offset +4 put: (self orr: destReg imm: (constant >> 16 bitAnd: 16rFF) ror: 16).
+ 	self machineCodeAt: offset +8 put: (self orr: destReg imm: (constant >> 8 bitAnd: 16rFF) ror: 24).
+ 	self machineCodeAt: offset +12 put: (self orr: destReg imm: (constant bitAnd: 16rFF) ror: 0).
- 	0 to: 12 by: 4 do: [ :i | | rightRingRotation |
- 		rightRingRotation := self minimalRightRingRotationFor: constant initialRotation: 12 - i.
- 		machineCode
- 			at: offset + i + 3 put: 16rE3;
- 			at: offset + i + 2 put: (16r80 bitOr: destReg);
- 			at: offset + i + 1 put: ((rightRingRotation at: 1) bitOr: destReg << 4);
- 			at: offset + i"+0"put: (rightRingRotation at: 2).
- 		].
- 	machineCode at: offset + 2 put: 16rA0. "only the first operation need be MOV"
  	^16!

Item was added:
+ ----- Method: CogARMCompiler>>b: (in category 'ARM convenience instructions') -----
+ b: offset
+ "return a B offset instruction"
+ 	^self cond: AL br: 0 offset: offset
+ !

Item was added:
+ ----- Method: CogARMCompiler>>bl: (in category 'ARM convenience instructions') -----
+ bl: offset
+ "return a BL offset instruction"
+ 	^self cond: AL br: 1 offset: offset
+ !

Item was added:
+ ----- Method: CogARMCompiler>>blx: (in category 'ARM convenience instructions') -----
+ blx: targetReg
+ "return a BX targetReg instruction"
+ 	^self cond: AL bx: 1 target: targetReg
+ !

Item was added:
+ ----- Method: CogARMCompiler>>bx: (in category 'ARM convenience instructions') -----
+ bx: targetReg
+ "return a BX targetReg instruction"
+ 	^self cond: AL bx: 0 target: targetReg
+ !

Item was removed:
- ----- Method: CogARMCompiler>>c:t:o:s: (in category 'encoding') -----
- c: c t: t o: o s: s
- 	"c : 4 bit, t: 3 bit, o: 4 bit, s: 1bit"
- 	"the leftmost 12bit of (most) ARM instruction"
- 	<inline: true>
- 	^ c << 28 bitOr: ((t << 25) bitOr: ((o << 21) bitOr: (s << 20)))!

Item was removed:
- ----- Method: CogARMCompiler>>c:t:o:s:rn:rd: (in category 'encoding') -----
- c: conditionCode t: type o: flagsOrOpcode s: doUpdateStatusRegister rn:  sourceRegister rd: targetRegister
- 	<inline: true>
- 	^(self c: conditionCode t: type o: flagsOrOpcode s: doUpdateStatusRegister) 
- 		bitOr: (sourceRegister << 16 bitOr: targetRegister << 12)!

Item was removed:
- ----- Method: CogARMCompiler>>c:t:o:s:rn:rd:shifterOperand: (in category 'encoding') -----
- c: conditionCode t: type o: flagsOrOpcode s: doUpdateStatusRegister rn:  sourceRegister rd: targetRegister shifterOperand: so
- 	<inline: true>
- 	^(self c: conditionCode t: type o: flagsOrOpcode s: doUpdateStatusRegister rn: sourceRegister rd: targetRegister) bitOr: so!

Item was changed:
  ----- Method: CogARMCompiler>>callTargetFromReturnAddress: (in category 'inline cacheing') -----
  callTargetFromReturnAddress: callSiteReturnAddress
  	"Answer the address the call immediately preceeding callSiteReturnAddress will jump to."
+ 	"this is also used by #jumpLongTargetBeforeFOllowingAddress: and so we check for both call and jump related instructions; later on we can use simpler tests once it feels safe to assume we get here always with a call/jump in the proper place"
  	| callDistance call |
  	call := self instructionBeforeAddress: callSiteReturnAddress.
  	self assert: call ~= 0. "andeq r0, r0 will not be generated, not even as nops"
+ 	((self instructionIsB: call) or:[self instructionIsBL: call])
+ 		ifTrue: [ "a short call/jump" callDistance := self extractOffsetFromBL: call]
+ 		ifFalse: [ "A Long Call/Jump. Extract the value saved to RISCTempReg from all the instructions before."
+ 			((self instructionIsBX: call) or:[self instructionIsBLX: call])
+ 				ifTrue:[self extractOffsetFromBXAt: self halt].
- 	(self isBranch: call)
- 		ifTrue: [ callDistance := (call bitAnd: 16r00FFFFFF) << 2.
- 			"The distance is a signed 24bit number. Therefore, the highest (26th) bit has to be expanded"
- 			(callDistance bitAnd: 16r02000000) ~= 0 
- 				ifTrue: [callDistance := callDistance bitOr: 16rFC000000]]
- 		ifFalse: [ "A Long Jump. Extract the value saved to RISCTempReg from all the instructions before."
  			self notYetImplemented ].
  	^callSiteReturnAddress + 4 + callDistance signedIntFromLong!

Item was changed:
  ----- Method: CogARMCompiler>>computeMaximumSize (in category 'generate machine code') -----
  computeMaximumSize
  	"Because we don't use Thumb, each ARM instruction has 4 bytes. Some abstract opcodes need more than one instruction."
  	
  	| rotateableAt0then4or20Block |
  	rotateableAt0then4or20Block := [^self rotateable8bitImmediate: (operands at: 0)
  											ifTrue: [:r :i| maxSize := 4]
  											ifFalse: [maxSize := 20]].
  	
  	
  	(opcode between: FirstShortJump and: LastJump) ifTrue: [^maxSize := 16].
  	
  	opcode
  		caseOf: {
  			[Label]					-> [^maxSize := 0].
  			[AlignmentNops]		-> [^maxSize := (operands at: 0) - 1].
+ 			[MoveAwR]				-> [^maxSize := 20].
- 			[MoveAwR]				-> [^maxSize := 16].
  			[MoveCqR]				-> [^self rotateable8bitImmediate: (operands at: 0)
  											ifTrue: [:r :i| maxSize := 4]
  											ifFalse: [maxSize := 16]].
  			[MoveCwR]				-> [^maxSize := 16].
+ 			[MoveRAw]				-> [^maxSize := 20].
- 			[MoveRAw]				-> [^maxSize := 16].
  			[MoveRMwr]			-> [self is12BitValue: (operands at: 1)
  											ifTrue: [ :u :i | ^maxSize := 4]
  											ifFalse: [ ^maxSize := 20 ]].
  			[MoveRMbr]				-> [self is12BitValue: (operands at: 1)
  											ifTrue: [ :u :i | ^maxSize := 4]
  											ifFalse: [ ^maxSize := 20 ]].
  			[MoveMwrR]			-> [self is12BitValue: (operands at: 0)
  											ifTrue: [ :u :i | ^maxSize := 4]
  											ifFalse: [ ^maxSize := 20 ]].
  			[MoveMbrR]				-> [self is12BitValue: (operands at: 0)
  											ifTrue: [ :u :i | ^maxSize := 4]
  											ifFalse: [ ^maxSize := 20 ]].
+ 			[PrefetchAw] 			-> [^maxSize := 20].
- 			[PrefetchAw] 			-> [^maxSize := 16].
  			[Call]					-> [^maxSize := 20 "recomputed in #sizePCDependentInstruction."].
  			[RetN]					-> [^(operands at: 0) = 0 
  											ifTrue: [maxSize := 4]
  											ifFalse: [maxSize := 8]].
  			[CmpCqR]				-> [rotateableAt0then4or20Block value].
  			[AddCqR]				-> [rotateableAt0then4or20Block value].
  			[SubCqR]				-> [rotateableAt0then4or20Block value].
  			[AndCqR]				-> [rotateableAt0then4or20Block value].
  			[OrCqR]					-> [rotateableAt0then4or20Block value].
  			[XorCqR]				-> [rotateableAt0then4or20Block value].
  			[CmpCwR]				-> [^maxSize := 20].
  			[AddCwR]				-> [^maxSize := 20].
  			[SubCwR]				-> [^maxSize := 20].
  			[AndCwR]				-> [^maxSize := 20].
  			[OrCwR]				-> [^maxSize := 20].
  			[XorCwR]				-> [^maxSize := 20].
  			[JumpR]					-> [^maxSize := 4].
  			[JumpFPEqual]			-> [^maxSize := 8].
  			[JumpFPNotEqual]		-> [^maxSize := 8].
  			[JumpFPLess]			-> [^maxSize := 8].
  			[JumpFPGreaterOrEqual]-> [^maxSize := 8].
  			[JumpFPGreater]		-> [^maxSize := 8].
  			[JumpFPLessOrEqual]	-> [^maxSize := 8].
  			[JumpFPOrdered]		-> [^maxSize := 8].
  			[JumpFPUnordered]		-> [^maxSize := 8].
+ 			[JumpLong]				-> [^maxSize := 20].
+ 			[JumpLongZero]		-> [^maxSize := 20].
+ 			[JumpLongNonZero]	-> [^maxSize := 20].
- 			[JumpLong]				-> [^maxSize := 16].
- 			[JumpLongZero]		-> [^maxSize := 16].
- 			[JumpLongNonZero]	-> [^maxSize := 16].
  			[LoadEffectiveAddressMwrR] -> [rotateableAt0then4or20Block value].
  			[PushCw]				-> [^maxSize := 20].
  		}
  		otherwise: [^maxSize := 4].
  	^4 "to keep C compiler quiet"
  !

Item was changed:
  ----- Method: CogARMCompiler>>concretizeAddCqR (in category 'generate machine code - concretize') -----
  concretizeAddCqR
  	"Will get inlined into concretizeAt: switch."
  	"Try whether the quick constant is a small negative number. If it is, optimize."
  	<inline: true>
  	self rotateable8bitImmediate: (operands at: 0)
  		ifTrue: [ :rot :immediate | | reg |
  			reg := self concreteRegister: (operands at: 1).
+ 			self machineCodeAt: 0 put: (self adds: reg rn: reg imm: immediate ror: rot).
- 			self machineCodeAt: 0 put: ((self t: 1 o: 4 s: 1) bitOr: reg << 16).
- 			machineCode at: 0 put: immediate.
- 			machineCode at: 1 put: (reg << 4 bitOr: rot).
  			^machineCodeSize := 4]
  		ifFalse: [
  			self rotateable8bitImmediate: (operands at: 0) negated
  				ifTrue: [ :r :i | 
  						opcode := SubCqR.
  						operands at: 0 put: (operands at: 0) negated.
  						^self concretizeDataOperationCqR: 2]
  				ifFalse: [^self concretizeDataOperationCwR: 4]]!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeAlignmentNops (in category 'generate machine code - concretize') -----
  concretizeAlignmentNops
  	<inline: true>
+ 	"fill any slots with NOPs - in this case mov  r0, r0 - which is the NOP I always used to use"
  	self assert: machineCodeSize \\ 4 = 0.
  	0 to: machineCodeSize - 1 by: 4 do:
+ 		[:p| machineCode 
+ 			at: p put: 16r0;
+ 			at: p+1 put: 16r0;
+ 			at: p+2 put: 16rA0;
+ 			at: p+3 put: 16rE1]!
- 		[:p| objectMemory 
- 			byteAt: p put: 16r01;
- 			byteAt: p+1 put: 16r10;
- 			byteAt: p+2 put: 16rA0;
- 			byteAt: p+3 put: 16rE1]!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeArithmeticShiftRightCqR (in category 'generate machine code - concretize') -----
  concretizeArithmeticShiftRightCqR
  	"Will get inlined into concretizeAt: switch."
+ 	"this is an unfortunate waste of an instruction in most cases since the shift can usually be done in a subsequent arithmetic instruction. 
+ 	Handle for now with a MOV reg, reg, ASR #distance"
  	<inline: true>
  	| distance reg |
  	distance := (operands at: 0) min: 31.
  	reg := self concreteRegister: (operands at: 1).
  	"cond 000 1101 0 0000 dest dist -100 srcR"
+ 	self machineCodeAt: 0 put: (self type: 0 op: 16rD set: 0 rn: 0 rd: reg 
+ 									shifterOperand: (distance << 7 bitOr: (64 "flag for arithmetic" bitOr: reg))).
- 	self machineCodeAt: 0 put: (self t: 0 o: 16rD s: 0 rn: 0 rd: reg 
- 									shifterOperand: (distance << 7 bitOr: (64 bitOr: reg))).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeArithmeticShiftRightRR (in category 'generate machine code - concretize') -----
  concretizeArithmeticShiftRightRR
  	"Will get inlined into concretizeAt: switch."
+ 	"this is an unfortunate waste of an instruction in most cases since the shift can usually be done in a subsequent arithmetic instruction. 
+ 	Handle for now with a MOV reg, reg, ASR distReg"
  	<inline: true>
  	| destReg distReg |
  	distReg := self concreteRegister: (operands at: 0).
  	destReg := self concreteRegister: (operands at: 1).
+ 	"cond 000 1101 0 0000 destR distR 0101 srcR"
+ 	self machineCodeAt: 0 put: (self type: 0 op: 16rD set: 0 rn: 0 rd: destReg 
- 	"cond 000 1101 0 0000 dest dist 0101 srcR"
- 	self machineCodeAt: 0 put: (self t: 0 o: 16rD s: 0 rn: 0 rd: destReg 
  									shifterOperand: (distReg << 8 bitOr: (80 bitOr: destReg))).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeCall (in category 'generate machine code - concretize') -----
  concretizeCall
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
  	| offset |
  	self assert: (operands at: 0) ~= 0.
  	self assert: (operands at: 0) \\ 4 = 0.
  	offset := (operands at: 0) signedIntFromLong - (address + 8 "normal pc offset") signedIntFromLong.
  	(self isQuick: offset)
  		ifTrue: [
+ 			self machineCodeAt: 0 put: (self bl: offset). "BL offset"
- 			self machineCodeAt: 0 put: (self t: 5 o: 8) + (offset >> 2 bitAnd: 16r00FFFFFF). "BL offset"
  			^machineCodeSize := 4]
  		ifFalse: [
+ 			"self error: 'While we know how to generate a long distance call, we can''t update such a send site yet. Please restart with smaller cache size'."
+ 			^self concretizeLongCall]!
- 			self error: 'While we know how to generate a long distance call, we can''t update such a send site yet. Please restart with smaller cache size'.
- 			self concretizeConditionalJumpLong: AL.
- 			"move the actual jump two instructions further, inserting the pc back-up to lr and the pc push."
- 			self machineCodeAt: 16 put: (self machineCodeAt: 12).
- 		"Because the pc always points to the actual address + 8, the value at pc is the address of the instruction after the branch"
- 			"mov lr, pc"
- 			self machineCodeAt: 12 put: (self t: 0 o: 16rD s: 0 rn: 0 rd: LR shifterOperand: PC).
- 			^machineCodeSize := 20]!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeConditionalJump: (in category 'generate machine code - concretize') -----
  concretizeConditionalJump: conditionCode
  	"Will get inlined into concretizeAt: switch."
  	"Sizing/generating jumps.
  		Jump targets can be to absolute addresses or other abstract instructions.
  		Generating initial trampolines instructions may have no maxSize and be to absolute addresses.
  		Otherwise instructions must have a machineCodeSize which must be kept to."
  	<inline: true>
  	| offset |
  	offset := self computeJumpTargetOffsetPlus: 8.
   	(self isQuick: offset)
  		ifTrue: [
+ 			self machineCodeAt: 0 put: (self cond: conditionCode br: 0 offset: offset). "B offset"
- 			self machineCodeAt: 0 put: (self c: conditionCode t: 5 o: 0 s: 0) + (offset >> 2 bitAnd: 16r00FFFFFF). "B offset"
  			^machineCodeSize := 4]
  		ifFalse: [
  			^self concretizeConditionalJumpLong: conditionCode]!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeConditionalJumpLong: (in category 'generate machine code - concretize') -----
  concretizeConditionalJumpLong: conditionCode
  	"Will get inlined into concretizeAt: switch."
  	"Sizing/generating jumps.
  		Jump targets can be to absolute addresses or other abstract instructions.
  		Generating initial trampolines instructions may have no maxSize and be to absolute addresses.
  		Otherwise instructions must have a machineCodeSize which must be kept to."
  	<inline: true>
+ 	| jumpTarget instrOffset|
- 	| jumpTarget |
  	<var: #jumpTarget type: #'AbstractInstruction *'>
  	jumpTarget := self longJumpTargetAddress.
+ 	instrOffset := self at: 0 moveCw: jumpTarget intoR: RISCTempReg.
+ 	"bx RISCTempReg"
+ 	self machineCodeAt: instrOffset put: (self bx: RISCTempReg).
+ 	^machineCodeSize := instrOffset + 4!
- 	self at: 0 moveCw: jumpTarget intoR: RISCTempReg.
- 	"add pc, r3, #<byte 0>"
- 	self machineCodeAt: 12 put: (self c: conditionCode t: 1 o: 4 s: 0 rn: RISCTempReg rd: PC shifterOperand: (jumpTarget bitAnd: 16rFF)).
- 	^machineCodeSize := 16!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeDataOperationCqR: (in category 'generate machine code - concretize') -----
  concretizeDataOperationCqR: opcode
  	"Will get inlined into concretizeAt: switch."
  	"4 == Add, 2 == Sub, Xor == 1, And == 0, Or == 12"
  	<inline: true>
  	self 
  		rotateable8bitImmediate: (operands at: 0) 
  		ifTrue: [:rot :immediate | | reg |
  			reg := self concreteRegister: (operands at: 1).
+ 			self machineCodeAt: 0 put: (self type: 1 op: opcode set: 1 rn: reg rd: reg shifterOperand: (rot << 8 bitOr: immediate)).
- 			self machineCodeAt: 0 put: ((self t: 1 o: opcode s: 1) bitOr: reg << 16).
- 			machineCode at: 0 put: immediate.
- 			machineCode at: 1 put: (reg << 4 bitOr: rot).
  			^machineCodeSize := 4]
  		ifFalse: [^self concretizeDataOperationCwR: opcode].
  	!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeDataOperationCwR: (in category 'generate machine code - concretize') -----
  concretizeDataOperationCwR: opcode
  	"Will get inlined into concretizeAt: switch."
  	"Load the word into the RISCTempReg, then cmp R, RISCTempReg"
  	<inline: true>
+ 	| constant srcDestReg instrOffset|
- 	| constant srcDestReg |
  	constant := operands at: 0.
  	srcDestReg := (self concreteRegister: (operands at: 1)).
+ 	instrOffset := self at: 0 moveCw: constant intoR: RISCTempReg.
+ 	self machineCodeAt: instrOffset 
+ 		put: (self type: 0 op: opcode set: 1 rn: srcDestReg rd: srcDestReg shifterOperand: RISCTempReg).
+ 	^machineCodeSize := instrOffset + 4!
- 	self at: 0 moveCw: constant intoR: RISCTempReg.
- 	self machineCodeAt: 16 
- 		put: ((self t: 0 o: opcode s: 1) bitOr: ((srcDestReg << 16 bitOr: srcDestReg <<12) bitOr: RISCTempReg)).
- 	^machineCodeSize := 20.!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeDataOperationRR: (in category 'generate machine code - concretize') -----
  concretizeDataOperationRR: opcode
  	"Will get inlined into concretizeAt: switch."
  	"Load the word into the RISCTempReg, then cmp R, RISCTempReg"
  	<inline: true>
  	| destReg srcReg |
  	srcReg := self concreteRegister: (operands at: 0).
  	destReg := (self concreteRegister: (operands at: 1)).
  	self machineCodeAt: 0 
+ 		put: (self type: 0 op: opcode set: 1 rn: destReg rd: destReg shifterOperand: srcReg).
- 		put: (self t: 0 o: opcode s: 1 rn: destReg rd: destReg shifterOperand: srcReg).
  	^machineCodeSize := 4.!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeFPConditionalJump: (in category 'generate machine code - concretize') -----
  concretizeFPConditionalJump: conditionCode
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
  	| offset |
  	self assert: (operands at: 0) ~= 0.
  	offset := ((operands at: 0) - (address + 8)) signedIntFromLong "signed-conversion for range assertion".
  	self assert: offset <= 33554428 & (offset >= -33554432).
+ 	self machineCodeAt: 0 put: self fmstat. "FMSTAT: copy the FPSCR to CPSR"
+ 	self machineCodeAt: 4 put: (self cond: conditionCode br: 0 offset: offset). "B offset"
- 	self machineCodeAt: 0 put: 16rEF1FA10. "FMSTAT: copy the FPSCR to CPSR"
- 	self machineCodeAt: 4 put: (self c: conditionCode t: 5 o: 0 s: 0) + (offset >> 2 bitAnd: 16r00FFFFFF). "B offset"
  	^machineCodeSize := 8!

Item was added:
+ ----- Method: CogARMCompiler>>concretizeFill16 (in category 'generate machine code') -----
+ concretizeFill16
+ 	"fill with (operand 0 bitAnd: 16rFFFF) according to the processor's endianness"
+ 	self halt: 'unused opcode?'!

Item was added:
+ ----- Method: CogARMCompiler>>concretizeFill32 (in category 'generate machine code') -----
+ concretizeFill32
+ 	"fill with operand 0 according to the processor's endianness"
+ 	| word |
+ 	<var: #word type: #'unsigned long'>
+ 	word := operands at: 0.
+ 	machineCode at: 0 put: (word bitAnd: 16rFF).
+ 	machineCode at: 1 put: (word >> 8bitAnd: 16rFF)..
+ 	machineCode at: 2 put: (word >> 16bitAnd: 16rFF)..
+ 	machineCode at: 3 put: (word >> 24bitAnd: 16rFF)..
+ 	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeJumpR (in category 'generate machine code - concretize') -----
  concretizeJumpR
  	"Will get inlined into concretizeAt: switch."
  	"Sizing/generating jumps.
  		Jump targets can be to absolute addresses or other abstract instructions.
  		Generating initial trampolines instructions may have no maxSize and be to absolute addresses.
  		Otherwise instructions must have a machineCodeSize which must be kept to."
  	<inline: true>
  	| reg |
  	reg := self concreteRegister: (operands at: 0).
+ 	"bx reg"
+ 	self machineCodeAt: 0 put: (self bx: reg).
- 	"mov pc, r?, #0"
- 	self machineCodeAt: 0 put: (self t: 0 o: 16rD s: 0 rn: 0 rd: PC shifterOperand: reg).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeLoadEffectiveAddressMwrR (in category 'generate machine code - concretize') -----
  concretizeLoadEffectiveAddressMwrR
  	"Will get inlined into concretizeAt: switch."
+ 	"destReg = srcReg (which contains an address) + offset"
- 	"destReg = destReg + offset"
  	<inline: true>
+ 	| srcReg offset destReg instrOffset |
- 	| srcReg offset destReg |
  	offset := operands at: 0.
  	srcReg := self concreteRegister: (operands at: 1).
  	destReg := self concreteRegister: (operands at: 2).
  	self rotateable8bitImmediate: offset
  		ifTrue: [ :rot :immediate | 
  			self machineCodeAt: 0 
+ 				"add destReg, srcReg, #immediate ROR rot"
+ 				put: (self add: destReg rn: srcReg imm: immediate ror: rot).
- 				"add destReg, srcReg, #immediate"
- 				put: (self t: 1 o: 4 s: 0 rn: srcReg rd: destReg shifterOperand: (rot <<8 bitOr: immediate)).
  			^machineCodeSize := 4]
  		ifFalse: [ 
+ 			instrOffset := self at: 0 moveCw: offset intoR: RISCTempReg.
- 			self at: 0 moveCw: offset intoR: RISCTempReg.
  			"add destReg, srcReg, RISCTempReg"
+ 			self machineCodeAt: 16 put: (self addRd: destReg rn: srcReg rm: RISCTempReg).
+ 			^machineCodeSize := instrOffset + 4 ]!
- 			self machineCodeAt: 16 put: (self t: 0 o: 4 s: 0 rn: srcReg rd: destReg shifterOperand: RISCTempReg).
- 			^machineCodeSize := 20 ]!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeLogicalShiftLeftCqR (in category 'generate machine code - concretize') -----
  concretizeLogicalShiftLeftCqR
  	"Will get inlined into concretizeAt: switch."
+ 	"this is an unfortunate waste of an instruction in most cases since the shift can usually be done in a subsequent arithmetic instruction. 
+ 	Handle for now with a MOV reg, reg, LSL #distance"
  	<inline: true>
  	| distance reg |
  	distance := (operands at: 0) min: 31.
  	reg := self concreteRegister: (operands at: 1).
  	"cond 000 1101 0 0000 dest dista 000 srcR"
+ 	self machineCodeAt: 0 put: (self type: 0 op: 16rD set: 0 rn: 0 rd: reg shifterOperand: (distance << 7 bitOr: reg)).
- 	self machineCodeAt: 0 put: (self t: 0 o: 16rD s: 0 rn: 0 rd: reg shifterOperand: (distance << 7 bitOr: reg)).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeLogicalShiftLeftRR (in category 'generate machine code - concretize') -----
  concretizeLogicalShiftLeftRR
  	"Will get inlined into concretizeAt: switch."
+ 	"this is an unfortunate waste of an instruction in most cases since the shift can usually be done in a subsequent arithmetic instruction. 
+ 	Handle for now with a MOV reg, reg, LSL distReg"
  	<inline: true>
  	| destReg distReg |
  	distReg := self concreteRegister: (operands at: 0).
  	destReg := self concreteRegister: (operands at: 1).
  	"cond 000 1101 0 0000 dest dist 0001 srcR"
+ 	self machineCodeAt: 0 put: (self type: 0 op: 16rD set: 0 rn: 0 rd: destReg 
- 	self machineCodeAt: 0 put: (self t: 0 o: 16rD s: 0 rn: 0 rd: destReg 
  									shifterOperand: (distReg << 8 bitOr: (16 bitOr: destReg))).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeLogicalShiftRightCqR (in category 'generate machine code - concretize') -----
  concretizeLogicalShiftRightCqR
  	"Will get inlined into concretizeAt: switch."
+ 	"this is an unfortunate waste of an instruction in most cases since the shift can usually be done in a subsequent arithmetic instruction. 
+ 	Handle for now with a MOV reg, reg, LSR #distance"
  	<inline: true>
  	| distance reg |
  	distance := (operands at: 0) min: 31.
  	reg := self concreteRegister: (operands at: 1).
  	"cond 000 1101 0 0000 dest dist -010 srcR"
+ 	self machineCodeAt: 0 put: (self type: 0 op: 16rD set: 0 rn: 0 rd: reg 
- 	self machineCodeAt: 0 put: (self t: 0 o: 16rD s: 0 rn: 0 rd: reg 
  									shifterOperand: (distance << 7 bitOr: (32 bitOr: reg))).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeLogicalShiftRightRR (in category 'generate machine code - concretize') -----
  concretizeLogicalShiftRightRR
  	"Will get inlined into concretizeAt: switch."
+ 	"this is an unfortunate waste of an instruction in most cases since the shift can usually be done in a subsequent arithmetic instruction. 
+ 	Handle for now with a MOV reg, reg, LSR distReg"
  	<inline: true>
  	| destReg distReg |
  	distReg := self concreteRegister: (operands at: 0).
  	destReg := self concreteRegister: (operands at: 1).
  	"cond 000 1101 0 0000 dest dist 0011 srcR"
+ 	self machineCodeAt: 0 put: (self type: 0 op: 16rD set: 0 rn: 0 rd: destReg 
- 	self machineCodeAt: 0 put: (self t: 0 o: 16rD s: 0 rn: 0 rd: destReg 
  									shifterOperand: (distReg << 8 bitOr: (48 bitOr: destReg))).
  	^machineCodeSize := 4!

Item was added:
+ ----- Method: CogARMCompiler>>concretizeLongCall (in category 'generate machine code - concretize') -----
+ concretizeLongCall
+ 	"Will get inlined into concretizeAt: switch."
+ 	"Sizing/generating calls.
+ 		Jump targets can be to absolute addresses or other abstract instructions.
+ 		Generating initial trampolines instructions may have no maxSize and be to absolute addresses.
+ 		Otherwise instructions must have a machineCodeSize which must be kept to."
+ 	<inline: true>
+ 	| jumpTarget instrOffset|
+ 	<var: #jumpTarget type: #'AbstractInstruction *'>
+ 	jumpTarget := self longJumpTargetAddress.
+ 	instrOffset := self at: 0 moveCw: jumpTarget intoR: RISCTempReg.
+ 	"blx RISCTempReg"
+ 	self machineCodeAt: instrOffset put: (self blx: RISCTempReg).
+ 	^machineCodeSize := instrOffset + 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveAwR (in category 'generate machine code - concretize') -----
  concretizeMoveAwR
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
+ 	| srcAddr destReg instrOffset|
- 	| srcAddr destReg |
  	srcAddr := operands at: 0.
  	destReg := self concreteRegister: (operands at: 1).
  	"load the address into RISCTempReg"
+ 	instrOffset := self at: 0 moveCw: srcAddr intoR: RISCTempReg.
+ 	"We *could* overwrite the last instruction above with a LDR a, b, last-byte-of-srcAddr BUT that would break if we change to loading literals instead of forming long constants"
+ 	self machineCodeAt: instrOffset put: (self ldr: destReg rn: RISCTempReg plusImm: 0).
+ 	^machineCodeSize := instrOffset + 4!
- 	self at: 0 moveCw: srcAddr intoR: RISCTempReg.
- 	"Moving allows building an 8bit offset, so the lowest byte can be used in this instruction and we save 4 byte."
- 	machineCode
- 		at: 15 put: 16rE5; "LDR srcReg, [R3, +LSB(addr)]"
- 		at: 14 put: (16r90 bitOr: RISCTempReg);
- 		at: 13 put: (destReg << 4).
- 	^machineCodeSize := 16!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveCqR (in category 'generate machine code - concretize') -----
  concretizeMoveCqR
  	"Will get inlined into concretizeAt: switch."
  	"If the quick constant is in fact a shiftable 8bit, generate the apropriate MOV, otherwise do what is necessary for a whole word."
  	<inline: true>
  	self 
  		rotateable8bitImmediate: (operands at: 0) 
  		ifTrue: [:rot :immediate | | reg |
  			reg := self concreteRegister: (operands at: 1).
+ 			self machineCodeAt: 0 put: (self type: 1 op: 16rD set: 0 rn: 0 rd: reg shifterOperand: (rot << 8 bitOr: immediate)).
- 			self machineCodeAt: 0 put: (self t: 1 o: 16rD s: 0).
- 			machineCode at: 0 put: immediate.
- 			machineCode at: 1 put: (reg << 4 bitOr: rot).
  			^machineCodeSize := 4]
  		ifFalse: [^self concretizeMoveCwR].
  	!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveCwR (in category 'generate machine code - concretize') -----
  concretizeMoveCwR
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
  	| constant destReg |
  	constant := operands at: 0.
  	destReg := self concreteRegister: (operands at: 1).
+ 	^machineCodeSize :=self at: 0 moveCw: constant intoR: destReg!
- 	self at: 0 moveCw: constant intoR: destReg.
- 	^machineCodeSize := 16.!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveMbrR (in category 'generate machine code - concretize') -----
  concretizeMoveMbrR
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
+ 	| srcReg offset destReg instrOffset|
- 	| srcReg offset destReg |
  	offset := operands at: 0.
  	srcReg := self concreteRegister: (operands at: 1).
  	destReg := self concreteRegister: (operands at: 2).
  	self is12BitValue: offset
  		ifTrue: [ :u :immediate | 
  			self machineCodeAt: 0 
+ 				"ldrb destReg, [srcReg, #immediate]"
+ 				put: (self ldrb: destReg rn: srcReg plus: u imm: immediate).
- 				"ldr destReg, [srcReg, #immediate]"
- 				put: (self t: 2 o: (16rA bitOr: u <<2) s: 1 rn: srcReg rd: destReg shifterOperand: immediate).
  			^machineCodeSize := 4]
  		ifFalse: [ 
+ 			instrOffset := self at: 0 moveCw: offset intoR: RISCTempReg.
+ 			"ldrb destReg, [srcReg, RISCTempReg]"
+ 			self machineCodeAt: instrOffset put: (self ldrb: destReg rn: srcReg rm: RISCTempReg).
+ 			^machineCodeSize := instrOffset + 4 ]!
- 			self at: 0 moveCw: offset intoR: RISCTempReg.
- 			"ldr destReg, [srcReg, RISCTempReg]"
- 			self machineCodeAt: 16 put: (self t: 3 o: 16rE s: 1 rn: srcReg rd: destReg shifterOperand: RISCTempReg).
- 			^machineCodeSize := 20 ]!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveMwrR (in category 'generate machine code - concretize') -----
  concretizeMoveMwrR
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
+ 	| srcReg offset destReg instrOffset|
- 	| srcReg offset destReg |
  	offset := operands at: 0.
  	srcReg := self concreteRegister: (operands at: 1).
  	destReg := self concreteRegister: (operands at: 2).
  	self is12BitValue: offset
  		ifTrue: [ :u :immediate | 
  			self machineCodeAt: 0 
  				"ldr destReg, [srcReg, #immediate]"
+ 				put: (self ldr: destReg rn: srcReg plus: u imm: immediate).
- 				put: (self t: 2 o: (8 bitOr: u <<2) s: 1 rn: srcReg rd: destReg shifterOperand: immediate).
  			^machineCodeSize := 4]
  		ifFalse: [ 
+ 			instrOffset := self at: 0 moveCw: offset intoR: RISCTempReg.
- 			self at: 0 moveCw: offset intoR: RISCTempReg.
  			"ldr destReg, [srcReg, RISCTempReg]"
+ 			self machineCodeAt: instrOffset put: (self ldr: destReg rn: srcReg rm: RISCTempReg).
+ 			^machineCodeSize := instrOffset +4 ]!
- 			self machineCodeAt: 16 put: (self t: 3 o: 16rC s: 1 rn: srcReg rd: destReg shifterOperand: RISCTempReg).
- 			^machineCodeSize := 20 ]!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveRAw (in category 'generate machine code - concretize') -----
  concretizeMoveRAw
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
+ 	| srcReg destAddr instrOffset|
- 	| srcReg destAddr |
  	srcReg := self concreteRegister: (operands at: 0).
  	destAddr := operands at: 1.
+ 	"load the address into RISCTempReg"
+ 	instrOffset := self at: 0 moveCw: destAddr intoR: RISCTempReg.
+ 	"We *could* overwrite the last instruction above with a LDR a, b, last-byte-of-srcAddr BUT that would break if we change to loading literals instead of forming long constants"
+ 	self machineCodeAt: instrOffset put: (self str: srcReg rn: RISCTempReg plusImm: 0).
+ 	^machineCodeSize := instrOffset + 4!
- 	"load the address into R3"
- 	self at: 0 moveCw: destAddr intoR: RISCTempReg.
- 	machineCode 
- 		at: 15 put: 16rE5; "STR srcReg, [R3, +LSB(addr)]"
- 		at: 14 put: (16r80 bitOr: RISCTempReg);
- 		at: 13 put: (srcReg << 4).
- 	^machineCodeSize := 16!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveRMbr (in category 'generate machine code - concretize') -----
  concretizeMoveRMbr
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
+ 	| srcReg offset baseReg instrOffset|
- 	| srcReg offset destReg |
  	srcReg := self concreteRegister: (operands at: 0).
  	offset := operands at: 1.
+ 	baseReg := self concreteRegister: (operands at: 2).
- 	destReg := self concreteRegister: (operands at: 2).
  	self is12BitValue: offset
  		ifTrue: [ :u :immediate | 
  			self machineCodeAt: 0 
+ 				"strb 	srcReg, [baseReg, #immediate]"
+ 				put: (self strb: srcReg rn: baseReg plus: u imm: immediate).
- 			"strb 	destReg, [srcReg, #immediate]"
- 				put: (self t: 2 o: (16rA bitOr: u<<2) s: 0 rn: destReg rd: srcReg shifterOperand: immediate).
  			^machineCodeSize := 4]
  		ifFalse: [ 
+ 			instrOffset := self at: 0 moveCw: offset intoR: RISCTempReg.
+ 			"strb 	srcReg, [baseReg, RISCTempReg]"
+ 			self machineCodeAt: instrOffset put: (self strb: srcReg rn: baseReg rm: RISCTempReg).
+ 			^machineCodeSize := instrOffset + 4 ]!
- 			self at: 0 moveCw: offset intoR: RISCTempReg.
- 			"strb 	destReg, [srcReg, RISCTempReg]"
- 			self machineCodeAt: 16 put: (self t: 3 o: 16rE s: 0 rn: srcReg rd: destReg shifterOperand: RISCTempReg).
- 			^machineCodeSize := 20 ]!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveRMwr (in category 'generate machine code - concretize') -----
  concretizeMoveRMwr
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
+ 	| srcReg offset baseReg instrOffset|
- 	| srcReg offset destReg |
  	srcReg := self concreteRegister: (operands at: 0).
  	offset := operands at: 1.
+ 	baseReg := self concreteRegister: (operands at: 2).
- 	destReg := self concreteRegister: (operands at: 2).
  	self is12BitValue: offset
  		ifTrue: [ :u :immediate | 
  			self machineCodeAt: 0 
+ 				"str 	srcReg, [baseReg, #immediate]"
+ 				put: (self str: srcReg rn: baseReg plus: u imm: immediate).
- 			"strb 	destReg, [srcReg, #immediate]"
- 				put: (self t: 2 o: (8 bitOr: u<<2) s: 0 rn: destReg rd: srcReg shifterOperand: immediate).
  			^machineCodeSize := 4]
  		ifFalse: [ 
+ 			instrOffset := self at: 0 moveCw: offset intoR: RISCTempReg.
+ 			"str srcReg, [baseReg, RISCTempReg]"
+ 			self machineCodeAt: instrOffset put: (self str: srcReg rn: baseReg rm: RISCTempReg).
+ 			^machineCodeSize := instrOffset + 4 ]!
- 			self at: 0 moveCw: offset intoR: RISCTempReg.
- 			"strb 	destReg, [srcReg, RISCTempReg]"
- 			self machineCodeAt: 16 put: (self t: 3 o: 16rC s: 0 rn: srcReg rd: destReg shifterOperand: RISCTempReg).
- 			^machineCodeSize := 20 ]!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveRR (in category 'generate machine code - concretize') -----
  concretizeMoveRR
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
  	| srcReg destReg |
  	srcReg := self concreteRegister: (operands at: 0).
  	destReg := self concreteRegister: (operands at: 1).
  	"cond 000 1101 0 0000 dest 0000 0000 srcR"
+ 	self machineCodeAt: 0 put: (self type: 0 op: 16rD set: 0 rn: 0 rd: destReg shifterOperand: srcReg).
- 	self machineCodeAt: 0 put: (self t: 0 o: 16rD s: 0 rn: 0 rd: destReg shifterOperand: srcReg).
  	^machineCodeSize := 4!

Item was removed:
- ----- Method: CogARMCompiler>>concretizeMoveRX16rR (in category 'generate machine code - concretize') -----
- concretizeMoveRX16rR
- 	"Will get inlined into concretizeAt: switch."
- 	"Write the word in R(src) into memory at address (base+2*index)"
- 	<inline: true>
- 	| index base src |
- 	src := self concreteRegister: (operands at: 0).
- 	index := self concreteRegister: (operands at: 1).
- 	base := self concreteRegister: (operands at: 2).
- 	"str		src, [base, +index, LSL #1]"
- 	"cond 011 1100 0 base srcR 00001 00 0 inde"
- 	self machineCodeAt: 0 put: (self t: 3 o: 16rC s: 0 rn: base rd: src shifterOperand: (16r080 bitOr: index)).
- 	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveRXbrR (in category 'generate machine code - concretize') -----
  concretizeMoveRXbrR
  	"Will get inlined into concretizeAt: switch."
  	"Write the word in R(src) into memory at address (base+1*index)"
  	<inline: true>
  	| index base src |
  	src := self concreteRegister: (operands at: 0).
  	index := self concreteRegister: (operands at: 1).
  	base := self concreteRegister: (operands at: 2).
  	"str		src, [base, +index, LSL #0]"
  	"cond 011 1100 0 base srcR 00000 00 0 inde"
+ 	self machineCodeAt: 0 put: (self type: 3 op: 16rC set: 0 rn: base rd: src shifterOperand: index).
- 	self machineCodeAt: 0 put: (self t: 3 o: 16rC s: 0 rn: base rd: src shifterOperand: index).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveRXwrR (in category 'generate machine code - concretize') -----
  concretizeMoveRXwrR
  	"Will get inlined into concretizeAt: switch."
  	"Write the word in R(src) into memory at address (base+4*index)"
  	<inline: true>
  	| index base src |
  	src := self concreteRegister: (operands at: 0).
  	index := self concreteRegister: (operands at: 1).
  	base := self concreteRegister: (operands at: 2).
  	"str		src, [base, +index, LSL #2]"
  	"cond 011 1100 0 base srcR 00010 00 0 inde"
+ 	self machineCodeAt: 0 put: (self type: 3 op: 16rC set: 0 rn: base rd: src shifterOperand: (16r100 bitOr: index)).
- 	self machineCodeAt: 0 put: (self t: 3 o: 16rC s: 0 rn: base rd: src shifterOperand: (16r100 bitOr: index)).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveXbrRR (in category 'generate machine code - concretize') -----
  concretizeMoveXbrRR
  	"Will get inlined into concretizeAt: switch."
  	
  	<inline: true>
  	| index base dest |
  	index := self concreteRegister: (operands at: 0).
  	base := self concreteRegister: (operands at: 1).
  	dest := self concreteRegister: (operands at: 2).
  	"LDR	dest, [base, +index, LSL #0]"
  	"cond 011 1100 1 base dest 00000 00 0 inde"
+ 	self machineCodeAt: 0 put: (self type: 3 op: 16rC set: 1 rn: base rd: dest shifterOperand: index).
- 	self machineCodeAt: 0 put: (self t: 3 o: 16rC s: 1 rn: base rd: dest shifterOperand: index).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeMoveXwrRR (in category 'generate machine code - concretize') -----
  concretizeMoveXwrRR
  	"Will get inlined into concretizeAt: switch."
  	
  	<inline: true>
  	| index base dest |
  	index := self concreteRegister: (operands at: 0).
  	base := self concreteRegister: (operands at: 1).
  	dest := self concreteRegister: (operands at: 2).
  	"LDR	dest, [base, +index, LSL #2]"
  	"cond 011 1100 1 base dest 00010 00 0 inde"
+ 	self machineCodeAt: 0 put: (self type: 3 op: 16rC set: 1 rn: base rd: dest shifterOperand: (16r100 bitOr: index)).
- 	self machineCodeAt: 0 put: (self t: 3 o: 16rC s: 1 rn: base rd: dest shifterOperand: (16r100 bitOr: index)).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeNegateR (in category 'generate machine code - concretize') -----
  concretizeNegateR
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
  	| reg |
  	reg := self concreteRegister: (operands at: 0).
  	"rsb r?, r?, #0"
+ 	self machineCodeAt: 0 put: (self type: 1 op: 3 set: 0 rn: reg rd: reg).
- 	self machineCodeAt: 0 put: (self t: 1 o: 3 s: 0 rn: reg rd: reg).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeNop (in category 'generate machine code - concretize') -----
  concretizeNop
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
+ 	"MOV r0, r0"
+ 	self machineCodeAt: 0 put: 16rE1A00000.
- 	self machineCodeAt: 0 put: 16rE1A01001.
  	^machineCodeSize := 4
  			!

Item was changed:
  ----- Method: CogARMCompiler>>concretizePopR (in category 'generate machine code - concretize') -----
  concretizePopR
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
  	| destReg |
  	destReg := self concreteRegister: (operands at: 0).
  	"cond | 010 | 0100 | 1 | -Rn- | -Rd- | 0000 0000 0100 " "LDR destReg, [SP], #4"
+ 	self machineCodeAt: 0 put: (self popR: destReg).
- 	self machineCodeAt: 0 put: (self t: 2 o: 4 s: 1 rn: SP rd: destReg shifterOperand: 4).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizePrefetchAw (in category 'generate machine code - concretize') -----
  concretizePrefetchAw
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
+ 	| addressOperand instrOffset|
- 	| addressOperand |
  	addressOperand := operands at: 0.
+ 	instrOffset := self at: 0 moveCw: addressOperand intoR: RISCTempReg.
+ 	"pld	[RISCTempReg]"
+ 	self machineCodeAt: instrOffset put: (self pld: RISCTempReg plus: 1offset: 0).
+ 	^machineCodeSize := instrOffset + 4!
- 	self at: 0 moveCw: addressOperand intoR: RISCTempReg.
- 	"pld	[RISCTempReg, +<byte 0>]"
- 	"u = 1, I = 0"
- 	"1111 0101 1101 RTem 1111 0000 byte"
- 	machineCode
- 		at: 15 put: 16rF5;
- 		at: 14 put: (16rD0 bitOr: RISCTempReg);
- 		at: 13 put: 16rF0.
- 	^machineCodeSize := 16!

Item was changed:
  ----- Method: CogARMCompiler>>concretizePushCw (in category 'generate machine code - concretize') -----
  concretizePushCw
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
+ 	| word instrOffset|
- 	| word |
  	word := operands at: 0.
+ 	instrOffset := self at: 0 moveCw: word intoR: RISCTempReg.
+ 	self machineCodeAt: instrOffset put: (self pushR: RISCTempReg).
+ 	^machineCodeSize := instrOffset + 4!
- 	self at: 0 moveCw: word intoR: RISCTempReg.
- 	self machineCodeAt: 16 put: (self t: 2 o: 9 s: 0 rn: SP rd: RISCTempReg shifterOperand: 4).
- 	^machineCodeSize := 20!

Item was changed:
  ----- Method: CogARMCompiler>>concretizePushR (in category 'generate machine code - concretize') -----
  concretizePushR
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
  	| srcReg |
  	srcReg := self concreteRegister: (operands at: 0).
  	"cond | 010 | 1001 | 0 | -Rn- | -Rd- | 0000 0000 0100" "STR srcReg, [sp, #-4]"
+ 	self machineCodeAt: 0 put: (self type: 2 op: 9 set: 0 rn: SP rd: srcReg shifterOperand: 4).
- 	self machineCodeAt: 0 put: (self t: 2 o: 9 s: 0 rn: SP rd: srcReg shifterOperand: 4).
  	^machineCodeSize := 4!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeRetN (in category 'generate machine code - concretize') -----
  concretizeRetN
  	"Will get inlined into concretizeAt: switch."
  	<inline: true>
  	| offset |
  	offset := operands at: 0.
  	offset = 0 ifTrue:
+ 		[self machineCodeAt: 0 put: (self popR: PC). "pop	{pc}"
- 		[self machineCodeAt: 0 put: 16rE8BD8000. "pop	{pc}"
  		^machineCodeSize := 4].
  	self assert: offset < 32. "We have an 8 bit immediate. If needed, we could rotate it less than 30 bit."
+ 	"add sp, sp, #n, ROR (15<<2) <- ie shift left 2 to convert words to bytes"
+ 	self machineCodeAt: 0 put: (self add: SP rn: SP imm: offset ror: 30).
+ 	self machineCodeAt: 4 put: (self popR: PC).  "pop	{pc}"
- 	self machineCodeAt: 0 put: 16rE28DDFFF. "add sp, sp, #n, 14"
- 	machineCode
- 		at: 0 put: offset. "no bit-mask needed, because of the assert"
- 	self machineCodeAt: 4 put: 16rE8BD8000.  "pop	{pc}"
  	^machineCodeSize := 8!

Item was changed:
  ----- Method: CogARMCompiler>>concretizeSubCqR (in category 'generate machine code - concretize') -----
  concretizeSubCqR
  	"Will get inlined into concretizeAt: switch."
  	"Try whether the quick constant is a small negative number. If it is, optimize."
  	<inline: true>
  	self rotateable8bitImmediate: (operands at: 0)
  		ifTrue: [ :rot :immediate | | reg |
  			reg := self concreteRegister: (operands at: 1).
+ 			self machineCodeAt: 0 put: (self type: 1 op: 2 set: 1 rn: reg rd: reg shifterOperand: (rot << 8 bitOr: immediate)).
- 			self machineCodeAt: 0 put: ((self t: 1 o: 2 s: 1) bitOr: reg << 16).
- 			machineCode at: 0 put: immediate.
- 			machineCode at: 1 put: (reg << 4 bitOr: rot).
  			^machineCodeSize := 4]
  		ifFalse: [
  			self rotateable8bitImmediate: (operands at: 0) negated
  				ifTrue: [ :r :i | 
  						opcode := AddCqR.
  						operands at: 0 put: (operands at: 0) negated.
  						^self concretizeDataOperationCqR: 4]
  				ifFalse: [^self concretizeDataOperationCwR: 2]]!

Item was added:
+ ----- Method: CogARMCompiler>>cond:br:offset: (in category 'encoding') -----
+ cond: c br: link offset: offset
+ 	"c : 4 bit, opcode = 10 bitOr: link, offset >>2, limited to 24 bits (which are sign-extended, shifted left 2 and added to 8 + pc to make the resulting address)"
+ 	"single instr Branch, no link"
+ 	<inline: true>
+ 	^ c << 28 bitOr: (((2r1010 bitOr: (link bitAnd: 1)) << 24) bitOr: (offset >> 2 bitAnd: 16r00FFFFFF))!

Item was added:
+ ----- Method: CogARMCompiler>>cond:bx:target: (in category 'encoding') -----
+ cond: c bx: link target: targetReg
+ 	"c : 4 bit, opcode = 10 bitOr: link, offset >>2, limited to 24 bits (which are sign-extended, shifted left 2 and added to 8 + pc to make the resulting address)"
+ 	"BX targetReg or BLX targetReg"
+ 	<inline: true>
+ 	^ c << 28 bitOr: ( (16r12FFF10  bitOr: (link bitAnd: 1) <<5 ) bitOr: targetReg)!

Item was added:
+ ----- Method: CogARMCompiler>>cond:type:op:set: (in category 'encoding') -----
+ cond: c type: t op: o set: s
+ 	"c : 4 bit, t: 3 bit, o: 4 bit, s: 1bit"
+ 	"cccctttoooos + oxFFFFF - the leftmost 12bit of (most) ARM instruction"
+ 	<inline: true>
+ 	^ c << 28 bitOr: ((t << 25) bitOr: ((o << 21) bitOr: (s << 20)))!

Item was added:
+ ----- Method: CogARMCompiler>>cond:type:op:set:rn:rd: (in category 'encoding') -----
+ cond: conditionCode type: type op: flagsOrOpcode set: doUpdateStatusRegister rn:  sourceRegister rd: targetRegister
+ "build an instruction - cccctttoooo + source + target"
+ 	<inline: true>
+ 	^(self cond: conditionCode type: type op: flagsOrOpcode set: doUpdateStatusRegister) 
+ 		bitOr: (sourceRegister << 16 bitOr: targetRegister << 12)!

Item was added:
+ ----- Method: CogARMCompiler>>cond:type:op:set:rn:rd:shifterOperand: (in category 'encoding') -----
+ cond: conditionCode type: type op: flagsOrOpcode set: doUpdateStatusRegister rn:  sourceRegister rd: targetRegister shifterOperand: so
+ 	<inline: true>
+ 	^(self cond: conditionCode type: type op: flagsOrOpcode set: doUpdateStatusRegister rn: sourceRegister rd: targetRegister) bitOr: (so bitAnd: 16rFFF)!

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."
  	<returnTypeC: #void>
  	opcode caseOf: {
  		"Noops & Pseudo Ops"
  		[Label]					-> [^self concretizeLabel].
  		[AlignmentNops]		-> [^self concretizeAlignmentNops].
  		[Fill16]					-> [^self concretizeFill16].
  		[Fill32]					-> [^self concretizeFill32].
  		[FillFromWord]			-> [^self concretizeFillFromWord].
  		[Nop]					-> [^self concretizeNop].
  		"Specific Control/Data Movement"
  		"[LDM]					-> [^self concretizeLDM].
  		[STM]					-> [^self concretizeSTM]."
  		"Control"
  		[Call]						-> [^self concretizeCall].
  		[JumpR]						-> [^self concretizeJumpR].
  		[JumpLong]					-> [^self concretizeConditionalJumpLong: AL].
  		[JumpLongZero]			-> [^self concretizeConditionalJumpLong: EQ].
  		[JumpLongNonZero]		-> [^self concretizeConditionalJumpLong: NE].
  		[Jump]						-> [^self concretizeConditionalJump: AL].
  		[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].
  		"Arithmetic"
  		[AddCqR]					-> [^self concretizeAddCqR].
  		[AddCwR]					-> [^self concretizeDataOperationCwR: 4].
  		[AddRR]						-> [^self concretizeDataOperationRR: 4].
  		"[AddRdRd]					-> [^self concretizeSEE2OpRdRd: 16r58]."
  		[AndCqR]					-> [^self concretizeDataOperationCqR: 0].
  		[AndCwR]					-> [^self concretizeDataOperationCwR: 0].
  		[AndRR]						-> [^self concretizeDataOperationRR: 0].
  		[CmpCqR]					-> [^self concretizeCmpCqR].
  		[CmpCwR]					-> [^self concretizeCmpCwR].
  		[CmpRR]					-> [^self concretizeCmpRR].
  		[CmpRdRd]					-> [^self concretizeCmpRdRd].
  		"[DivRdRd]					-> [^self concretizeSEE2OpRdRd: 16r5E].
  		[MulRdRd]					-> [^self concretizeSEE2OpRdRd: 16r59]."
  		[OrCqR]						-> [^self concretizeDataOperationCqR: 16rC].
  		[OrCwR]					-> [^self concretizeDataOperationCwR: 16rC].
  		[OrRR]						-> [^self concretizeDataOperationRR: 16rC].
  		[SubCqR]					-> [^self concretizeSubCqR].
  		[SubCwR]					-> [^self concretizeDataOperationCwR: 2].
  		[SubRR]						-> [^self concretizeDataOperationRR: 2].
  		"[SubRdRd]					-> [^self concretizeSEE2OpRdRd: 16r5C]."
  		[SqrtRd]						-> [^self concretizeSqrtRd].
  		[XorCqR]						-> [^self concretizeDataOperationCqR: 1].
  		[XorCwR]						-> [^self concretizeDataOperationCwR: 1].
  		[XorRR]							-> [^self concretizeDataOperationRR: 1].
  		[NegateR]						-> [^self concretizeNegateR].
  		[LoadEffectiveAddressMwrR]	-> [^self concretizeLoadEffectiveAddressMwrR].
  		[ArithmeticShiftRightCqR]		-> [^self concretizeArithmeticShiftRightCqR].
  		[LogicalShiftRightCqR]			-> [^self concretizeLogicalShiftRightCqR].
  		[LogicalShiftLeftCqR]			-> [^self concretizeLogicalShiftLeftCqR].
  		[ArithmeticShiftRightRR]			-> [^self concretizeArithmeticShiftRightRR].
  		[LogicalShiftLeftRR]				-> [^self concretizeLogicalShiftLeftRR].
  		[LogicalShiftRightRR]			-> [^self concretizeLogicalShiftRightRR].
  		"Data Movement"
  		[MoveCqR]			-> [^self concretizeMoveCqR].
  		[MoveCwR]			-> [^self concretizeMoveCwR].
  		[MoveRR]			-> [^self concretizeMoveRR].
  		[MoveAwR]			-> [^self concretizeMoveAwR].
  		[MoveRAw]			-> [^self concretizeMoveRAw].
  		"While the two MoveMbR and MoveMwR are quite similar (off by 1 bit), they differ way more to
  		MoveM16R and MoveM64R. Because of that, they are not merged."
  		[MoveMbrR]			-> [^self concretizeMoveMbrR].
  		[MoveRMbr]			-> [^self concretizeMoveRMbr].
  		[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].
  		[PushCw]			-> [^self concretizePushCw].
  		[PrefetchAw]		-> [^self concretizePrefetchAw].
  		"Conversion"
  		[ConvertRRd]		-> [^self concretizeConvertRRd].
  		"ARM specific opcodes" 
  		[LDMFD]			-> [^self concretizeLDMFD].
  		[STMFD]			-> [^self concretizeSTMFD]	}!

Item was added:
+ ----- Method: CogARMCompiler>>extractOffsetFromBL: (in category 'testing') -----
+ extractOffsetFromBL: instr
+ "we are told this is a BL <offset> instruction, so work out the offset it encodes"
+ 	| relativeJump |
+ 	relativeJump := instr bitAnd: 16r00FFFFFF.
+ 	relativeJump := (relativeJump bitAt: 24) = 1 
+ 						ifTrue: [((relativeJump bitOr: 16r3F000000) << 2) signedIntFromLong]
+ 						ifFalse: [relativeJump << 2].
+ 	^relativeJump!

Item was added:
+ ----- Method: CogARMCompiler>>extractOffsetFromBXAt: (in category 'testing') -----
+ extractOffsetFromBXAt: address
+ "this should return the long call/jump target"
+ 	self notYetImplemented!

Item was added:
+ ----- Method: CogARMCompiler>>fmstat (in category 'ARM convenience instructions') -----
+ fmstat
+ 	"unconditional transfer FP status to cpsr to choose jumps etc. Manually fudged for now"
+ 	<inline: true>
+ 	^16rEF1FA10!

Item was added:
+ ----- Method: CogARMCompiler>>inlineCacheTagAt: (in category 'inline cacheing') -----
+ inlineCacheTagAt: callSiteReturnAddress
+ 	"Answer the inline cache tag for the return address of a send."
+ 	^self literalBeforeFollowingAddress: callSiteReturnAddress -4  !

Item was changed:
  ----- Method: CogARMCompiler>>instructionBeforeAddress: (in category 'inline cacheing') -----
  instructionBeforeAddress: followingAddress
  	"Answer the instruction immediately preceeding followingAddress."
+ 	^objectMemory longAt: followingAddress -4
+ 
+ 	" old version - ^  ((objectMemory byteAt: followingAddress - 1 235) << 24)
- 	^  ((objectMemory byteAt: followingAddress - 1) << 24)
  	+  ((objectMemory byteAt: followingAddress - 2) << 16)
  	+  ((objectMemory byteAt: followingAddress - 3) << 8)
+ 	+   (objectMemory byteAt: followingAddress - 4)"
- 	+   (objectMemory byteAt: followingAddress - 4)
  !

Item was added:
+ ----- Method: CogARMCompiler>>instructionIsB: (in category 'testing') -----
+ instructionIsB: instr
+ "is this a B <offset> instruction?"
+ 	^instr >> 28 < 16rF "test for allowed condcode - 0xF is extension" and: [(instr bitAnd: (16rF<<24)) = (16rA<<24)]!

Item was added:
+ ----- Method: CogARMCompiler>>instructionIsBL: (in category 'testing') -----
+ instructionIsBL: instr
+ "is this a BL <offset> instruction?"
+ 	^instr >> 28 < 16rF "test for allowed condcode - 0xF is extension" and: [(instr bitAnd: (16rF<<24)) = (16rB<<24)]!

Item was added:
+ ----- Method: CogARMCompiler>>instructionIsBLX: (in category 'testing') -----
+ instructionIsBLX: instr
+ "is this a BLX <targetReg> instruction?"
+ 	^instr >> 28 < 16rF "test for allowed condcode - 0xF is extension" and: [(instr bitAnd: 16r0FFFFFF0) = 16r12FFF30]!

Item was added:
+ ----- Method: CogARMCompiler>>instructionIsBX: (in category 'testing') -----
+ instructionIsBX: instr
+ "is this a BX <targetReg> instruction?"
+ 	^instr >> 28 < 16rF "test for allowed condcode - 0xF is extension" and: [(instr bitAnd: 16r0FFFFFF0) = 16r12FFF10]!

Item was changed:
  ----- Method: CogARMCompiler>>isCallPreceedingReturnPC: (in category 'testing') -----
  isCallPreceedingReturnPC: mcpc
  	"Assuming mcpc is a return pc answer if the instruction before it is a call."
+ 	"There are two types of calls: BL and/BLX encoding"
+ 	| call |
+ 	call := self instructionBeforeAddress: mcpc.
+ 	^(self instructionIsBX: call) or:[self instructionIsBLX: call]!
- 	"There are two types of calls: BL and (MOV, ORR, ORR, ADD, ADD)"
- 	"PUSH {pc} is not sufficient as a test, because pc may be pushed using the PushR opcode"
- 	^ (objectMemory byteAt: mcpc - 3) >> 4 = 16rB "BL" 
- 			or: [ (objectMemory longAt: mcpc - 4) >> 12 = ((self t: 1 o: 4 s: 0 rn: RISCTempReg rd: PC)"add pc, r3, 0" >> 12) ]!

Item was added:
+ ----- Method: CogARMCompiler>>jumpLongTargetBeforeFollowingAddress: (in category 'inline cacheing') -----
+ jumpLongTargetBeforeFollowingAddress: mcpc 
+ 	"Answer the target address for the long jump immediately preceeding mcpc"
+ 	^self callTargetFromReturnAddress: mcpc!

Item was added:
+ ----- Method: CogARMCompiler>>ldr:rn:plus:imm: (in category 'ARM convenience instructions') -----
+ ldr: destReg rn: baseReg plus: u imm: immediate12bitValue
+ "return a LDR destReg, [baseReg, 'u' immediate12bitValue]"
+ 	^self memMxr: AL reg: destReg  base: baseReg u: u b: 0 l: 1 imm: immediate12bitValue!

Item was added:
+ ----- Method: CogARMCompiler>>ldr:rn:plusImm: (in category 'ARM convenience instructions') -----
+ ldr: destReg rn: baseReg plusImm: immediate12bitValue
+ "return a LDR destReg, [baseReg, +immediate12bitValue]"
+ 	^self memMxr: AL reg: destReg  base: baseReg u: 1 b: 0 l: 1 imm: immediate12bitValue!

Item was added:
+ ----- Method: CogARMCompiler>>ldr:rn:rm: (in category 'ARM convenience instructions') -----
+ ldr: destReg rn: baseReg rm: offsetReg
+ "return a LDR destReg, [baseReg, + offsetReg] The contents of offsetReg are assumed to be correctly signed"
+ 	^self memMxr: AL reg: destReg  base: baseReg p: 1 u: 1 b: 0 w: 0 l: 1 rm: offsetReg!

Item was added:
+ ----- Method: CogARMCompiler>>ldrb:rn:plus:imm: (in category 'ARM convenience instructions') -----
+ ldrb: destReg rn: baseReg plus: u imm: immediate12bitValue
+ "return a LDRB destReg, [baseReg, 'u' immediate12bitValue]"
+ 	^self memMxr: AL reg: destReg  base: baseReg u: u b: 1 l: 1 imm: immediate12bitValue!

Item was added:
+ ----- Method: CogARMCompiler>>ldrb:rn:rm: (in category 'ARM convenience instructions') -----
+ ldrb: destReg rn: baseReg rm: offsetReg
+ "return a LDR destReg, [baseReg, + offsetReg] The contents of offsetReg are assumed to be correctly signed"
+ 	^self memMxr: AL reg: destReg  base: baseReg p: 1 u: 1 b: 1 w: 0 l: 1 rm: offsetReg!

Item was added:
+ ----- Method: CogARMCompiler>>literalBeforeFollowingAddress: (in category 'inline cacheing') -----
+ literalBeforeFollowingAddress: followingAddress
+ 	"Answer the long constant loaded by a MOV/ORR/ORR/ORR sequence just before this address:"
+ 	^  ((objectMemory byteAt: followingAddress - 16) << 24)
+ 	+  ((objectMemory byteAt: followingAddress - 12) << 16)
+ 	+  ((objectMemory byteAt: followingAddress - 8) << 8)
+ 	+   (objectMemory byteAt: followingAddress - 4) !

Item was added:
+ ----- Method: CogARMCompiler>>memMxr:reg:base:p:u:b:w:l:imm: (in category 'encoding') -----
+ memMxr: cond reg: destReg base: baseReg p: postpreoffset u: updown b: byteword w: weirdstuff l: loadstore imm: offset
+ 	"build an ARM [base +/- offset] memory instruction
+ 	p -> pre-index (1) or post-index (0) the offset. Combines with W to do some odd things.
+ 	u -> up (1) or down (0) ie + or - for the offset
+ 	b -> byte(1) or word (0)
+ 	w -> write-back (1) if pre-indexing. 
+ 	l -> load (1) or store (0)"
+ 	^ cond << 28
+ 		bitOr: (2 << 25
+ 		bitOr: (postpreoffset << 24
+ 		bitOr: (updown << 23
+ 		bitOr: (byteword << 22
+ 		bitOr: (weirdstuff << 21
+ 		bitOr: (loadstore << 20
+ 		bitOr: (baseReg << 16
+ 		bitOr: (destReg << 12 bitOr: offset))))))))!

Item was added:
+ ----- Method: CogARMCompiler>>memMxr:reg:base:p:u:b:w:l:rm: (in category 'encoding') -----
+ memMxr: cond reg: destReg base: baseReg p: postpreoffset u: updown b: byteword w: weirdstuff l: loadstore rm: offsetReg 
+ 	"build an ARM [base +/- offsetReg] memory instruction
+ 	p -> pre-index (1) or post-index (0) the offset. Combines with W to do some odd things.
+ 	u -> up (1) or down (0) ie + or - for the offset
+ 	b -> byte(1) or word (0)
+ 	w -> write-back (1) if pre-indexing. 
+ 	l -> load (1) or store (0)"
+ 	^ cond << 28
+ 		bitOr: (3 << 25
+ 		bitOr: (postpreoffset << 24
+ 		bitOr: (updown << 23
+ 		bitOr: (byteword << 22
+ 		bitOr: (weirdstuff << 21
+ 		bitOr: (loadstore << 20
+ 		bitOr: (baseReg << 16
+ 		bitOr: (destReg << 12 bitOr: offsetReg))))))))!

Item was added:
+ ----- Method: CogARMCompiler>>memMxr:reg:base:u:b:l:imm: (in category 'encoding') -----
+ memMxr: cond reg: destReg  base: baseReg u: updown b: byteword l: loadstore imm: immediate12bitValue
+ "build an ARM [base +/- immediate 12bit offset] memory instruction
+ u -> up (1) or down (0) ie + or - for the offset
+ b -> byte(1) or word (0)
+ l -> load (1) or store (0)"
+ 
+ 	^ cond << 28
+ 		bitOr: (5<<24
+ 		bitOr: (updown << 23
+ 		bitOr:(byteword<<22
+ 		bitOr:(loadstore<<20
+ 		bitOr:(baseReg<<16
+ 		bitOr:(destReg<<12
+ 		bitOr: immediate12bitValue))))))!

Item was added:
+ ----- Method: CogARMCompiler>>mov:imm:ror: (in category 'ARM convenience instructions') -----
+ mov: destReg imm: immediate8bitValue ror: rotateRightBy
+ 	"return the ARM instruction MOV destReg, #immediate8BitValue ROR rotateRightBy"
+ 	^self type: 1 op: 16rD set: 0 rn: 0 rd: destReg shifterOperand: ((rotateRightBy>>1) <<8 bitOr: immediate8bitValue)!

Item was added:
+ ----- Method: CogARMCompiler>>movRd:imm:ror: (in category 'ARM convenience instructions') -----
+ movRd: destReg imm: immediate8bitValue ror: rotateRightBy
+ 	"return the ARM instruction MOV destReg, #immediate8BitValue ROR rotateRightBy"
+ 	^self type: 1 op: 16rD set: 0 rn: destReg rd: destReg shifterOperand: (rotateRightBy <<8 bitOr: immediate8bitValue)!

Item was changed:
  ----- Method: CogARMCompiler>>nopsFrom:to: (in category 'generate machine code - concretize') -----
  nopsFrom: startAddr to: endAddr
+ "fill with MOV R0, R0 no-op instructions"
  	self assert: endAddr - startAddr + 1 \\ 4 = 0.
  	startAddr to: endAddr by: 4 do:
  		[:p| objectMemory 
+ 			byteAt: p put: 16r0;
+ 			byteAt: p+1 put: 16r0;
- 			byteAt: p put: 16r01;
- 			byteAt: p+1 put: 16r10;
  			byteAt: p+2 put: 16rA0;
  			byteAt: p+3 put: 16rE1]!

Item was added:
+ ----- Method: CogARMCompiler>>orr:imm:ror: (in category 'ARM convenience instructions') -----
+ orr: destReg imm: immediate8bitValue ror: rotateRightBy
+ 	"return the ARM instruction ORR destReg, #immediate8BitValue ROR rotateRightBy"
+ 	^self type: 1 op: 16rC set: 0 rn: destReg rd: destReg shifterOperand: ((rotateRightBy>>1) <<8 bitOr: immediate8bitValue)!

Item was added:
+ ----- Method: CogARMCompiler>>orrRd:imm:ror: (in category 'ARM convenience instructions') -----
+ orrRd: destReg imm: immediate8bitValue ror: rotateRightBy
+ 	"return the ARM instruction ORR destReg, #immediate8BitValue ROR rotateRightBy"
+ 	^self type: 1 op: 16rB set: 0 rn: destReg rd: destReg shifterOperand: (rotateRightBy <<8 bitOr: immediate8bitValue)!

Item was added:
+ ----- Method: CogARMCompiler>>pld:plus:offset: (in category 'encoding') -----
+ pld: baseReg plus: u offset: immediate
+ 	"hint to memory that we will want to read from baseReg +/- imediate sometime soon"
+ 	<inline: true>
+ 	^ 2r11110101010100001111000000000000 bitOr: (baseReg<<16 bitOr:(u <<23 bitOr: immediate))!

Item was added:
+ ----- Method: CogARMCompiler>>popR: (in category 'ARM convenience instructions') -----
+ popR: dstReg
+ "return a pop - LDR srcReg, [sp] #4"
+ 	^self memMxr: AL reg: dstReg base: SP p: 0 u: 1 b: 0 w: 0 l: 1 imm: 4!

Item was added:
+ ----- Method: CogARMCompiler>>pushR: (in category 'ARM convenience instructions') -----
+ pushR: srcReg
+ "return a push - STR srcReg, [sp, #-4]!!"
+ 	^self memMxr: AL reg: srcReg base: SP p: 1 u: 0 b: 0 w: 1l: 0 imm: 4!

Item was changed:
  ----- Method: CogARMCompiler>>rewriteInlineCacheAt:tag:target: (in category 'inline cacheing') -----
  rewriteInlineCacheAt: callSiteReturnAddress tag: cacheTag target: callTargetAddress
  	"Rewrite an inline cache to call a different target for a new tag.  This variant is used
  	 to link unlinked sends in ceSend:to:numArgs: et al.  Answer the extent of the code
  	 change which is used to compute the range of the icache to flush."
  	
  	"chacheTag contains an oop to the selector which need be loaded before jumping"
  	<var: #callSiteReturnAddress type: #usqInt>
  	<var: #callTargetAddress type: #usqInt>
  	| call callDistance |
+ 	"cogit disassembleFrom: callSiteReturnAddress - 40 to: callSiteReturnAddress + 9"
- 	"self cCode: ''
- 		inSmalltalk: [cogit disassembleFrom: callSiteReturnAddress - 20 to: callSiteReturnAddress -1]."
  	false
  		ifTrue: [self assert: callTargetAddress >= cogit minCallAddress]
  		ifFalse: [callTargetAddress >= cogit minCallAddress ifFalse:
  					[self error: 'linking callsite to invalid address']].
  	callDistance := (callTargetAddress - (callSiteReturnAddress + 8 "pc offset"- 4 "return offset")) signedIntToLong.
  	
  	self assert: (self isQuick: callDistance). "we don't support long call updates, yet"
+ 	call := self cond: AL br: 1 offset: callDistance.
+ 	objectMemory longAt:  callSiteReturnAddress - 4 put: call.
- 	call := (self t: 5 o: 8)"BL" + (callDistance >> 2 bitAnd: 16rFFFFFF).
- 	objectMemory
- 		byteAt: callSiteReturnAddress - 1 put: (call >> 24 bitAnd: 16rFF);
- 		byteAt: callSiteReturnAddress - 2 put: (call >> 16 bitAnd: 16rFF);
- 		byteAt: callSiteReturnAddress - 3 put: (call >>   8 bitAnd: 16rFF);
- 		byteAt: callSiteReturnAddress - 4 put: (call            bitAnd: 16rFF).
  	
  	"The cacheTag is loaded byte by byte. Each byte needs to be encoded with minimal right ring rotation. See also #at:moveCw:intoR:"
+ 	objectMemory byteAt: callSiteReturnAddress - 20 put: (cacheTag >> 24 bitAnd: 16rFF).
+ 	objectMemory byteAt: callSiteReturnAddress - 16 put: (cacheTag >> 16 bitAnd: 16rFF).
+ 	objectMemory byteAt: callSiteReturnAddress - 12 put: (cacheTag >> 8 bitAnd: 16rFF).
+ 	objectMemory byteAt: callSiteReturnAddress - 8 put: (cacheTag  bitAnd: 16rFF).
- 	-20 to: -8 by: 4 do: [ :offset || rotation |
- 		rotation := self minimalRightRingRotationFor: cacheTag initialRotation: (offset + 8) negated.
- 		(offset + 8) ~= 0 ifTrue: [ "in case of decoration which may change the last instrution, we should not overwrite bits 9 to 12"
- 			objectMemory 
- 				byteAt: callSiteReturnAddress + offset + 1 
- 				put: (((objectMemory byteAt: callSiteReturnAddress - offset + 1) 
- 							bitAnd: 16rF0)
- 						bitOr: (rotation at: 1))].
- 		objectMemory
- 			byteAt: callSiteReturnAddress + offset
- 			put: (rotation at: 2)].
  
  	self assert: (self callTargetFromReturnAddress: callSiteReturnAddress) signedIntToLong = callTargetAddress.
  	"self cCode: ''
  		inSmalltalk: [cogit disassembleFrom: callSiteReturnAddress - 20 to: callSiteReturnAddress - 1]."
  	^20!

Item was changed:
  ----- Method: CogARMCompiler>>sizePCDependentInstructionAt: (in category 'generate machine code') -----
  sizePCDependentInstructionAt: eventualAbsoluteAddress
  	"Size a jump and set its address.  The target may be another instruction
  	 or an absolute address.  On entry the address inst var holds our virtual
  	 address. On exit address is set to eventualAbsoluteAddress, which is
  	 where this instruction will be output.  The span of a jump to a following
  	 instruction is therefore between that instruction's address and this
  	 instruction's address ((which are both still their virtual addresses), but the
  	 span of a jump to a preceeding instruction or to an absolute address is
  	 between that instruction's address (which by now is its eventual absolute
  	 address) or absolute address and eventualAbsoluteAddress."
  
  	| target maximumSpan abstractInstruction |
  	<var: #abstractInstruction type: #'AbstractInstruction *'>
  	opcode = AlignmentNops ifTrue:
  		[| alignment |
  		 address := eventualAbsoluteAddress.
  		 alignment := operands at: 0.
  		 ^machineCodeSize := (eventualAbsoluteAddress + (alignment - 1) bitAnd: alignment negated)
  							   - eventualAbsoluteAddress].
  	self assert: (self isJump or: [opcode = Call]).
  	self isJump ifTrue: [self resolveJumpTarget].
  	target := operands at: 0.
  	abstractInstruction := cogit cCoerceSimple: target to: #'AbstractInstruction *'.
  	"maximumSpan calculation copied from CogIA32Compiler TODO: extract method?"
  	(self isAnInstruction: abstractInstruction)
  		ifTrue:
  			[maximumSpan := abstractInstruction address
  							- (((cogit abstractInstruction: self follows: abstractInstruction)
  								ifTrue: [eventualAbsoluteAddress]
  								ifFalse: [address]) + 2)]
  		ifFalse:
  			[maximumSpan := target - (eventualAbsoluteAddress + 2)].
  	address := eventualAbsoluteAddress.
  	^machineCodeSize := opcode = Call 
  				ifTrue: [(self isQuick: maximumSpan) ifTrue: [4] ifFalse: [20]]
  				ifFalse: [(self isLongJump not and: [self isQuick: maximumSpan])
  								ifTrue: [4]
+ 								ifFalse: [20]] "load address to register, add"!
- 								ifFalse: [16]] "load address to register, add"!

Item was added:
+ ----- Method: CogARMCompiler>>str:rn:plus:imm: (in category 'ARM convenience instructions') -----
+ str: destReg rn: baseReg plus: u imm: immediate12bitValue
+ "return a STR destReg, [baseReg, 'u' immediate12bitValue]"
+ 	^self memMxr: AL reg: destReg  base: baseReg u: u b: 0 l: 0 imm: immediate12bitValue!

Item was added:
+ ----- Method: CogARMCompiler>>str:rn:plusImm: (in category 'ARM convenience instructions') -----
+ str: srcReg rn: baseReg plusImm: immediate12bitValue
+ "return a STR srcReg, [baseReg, +immediate12bitValue]"
+ 	^self memMxr: AL reg: srcReg  base: baseReg u: 1 b: 0 l: 0 imm: immediate12bitValue!

Item was added:
+ ----- Method: CogARMCompiler>>str:rn:rm: (in category 'ARM convenience instructions') -----
+ str: srcReg rn: baseReg rm: offsetReg
+ "return a STR srcReg, [baseReg, + offsetReg] The contents of offsetReg are assumed to be correctly signed"
+ 	^self memMxr: AL reg: srcReg  base: baseReg p: 1 u: 1 b: 0 w: 0 l: 0 rm: offsetReg!

Item was added:
+ ----- Method: CogARMCompiler>>strb:rn:plus:imm: (in category 'ARM convenience instructions') -----
+ strb: destReg rn: baseReg plus: u imm: immediate12bitValue
+ "return a STRB destReg, [baseReg, 'u' immediate12bitValue]"
+ 	^self memMxr: AL reg: destReg  base: baseReg u: u b: 1 l: 0 imm: immediate12bitValue!

Item was added:
+ ----- Method: CogARMCompiler>>strb:rn:rm: (in category 'ARM convenience instructions') -----
+ strb: srcReg rn: baseReg rm: offsetReg
+ "return a STRB srcReg, [baseReg, + offsetReg] The contents of offsetReg are assumed to be correctly signed"
+ 	^self memMxr: AL reg: srcReg  base: baseReg p: 1 u: 1 b: 1 w: 0 l: 0 rm: offsetReg!

Item was removed:
- ----- Method: CogARMCompiler>>t:o: (in category 'encoding') -----
- t: type o: flagsOrOpcode
- 	<inline: true>
- 	^self c: AL t: type o: flagsOrOpcode s: 0!

Item was removed:
- ----- Method: CogARMCompiler>>t:o:s: (in category 'encoding') -----
- t: type o: flagsOrOpcode s: doUpdateStatusRegister
- 	<inline: true>
- 	^self c: AL t: type o: flagsOrOpcode s: doUpdateStatusRegister!

Item was removed:
- ----- Method: CogARMCompiler>>t:o:s:rn:rd: (in category 'encoding') -----
- t: type o: flagsOrOpcode s: doUpdateStatusRegister rn:  sourceRegister rd: targetRegister
- 	<inline: true>
- 	^(self c: AL t: type o: flagsOrOpcode s: doUpdateStatusRegister) 
- 		bitOr: (sourceRegister << 16 bitOr: targetRegister << 12)!

Item was removed:
- ----- Method: CogARMCompiler>>t:o:s:rn:rd:shifterOperand: (in category 'encoding') -----
- t: type o: flagsOrOpcode s: doUpdateStatusRegister rn:  sourceRegister rd: targetRegister shifterOperand: so
- 	<inline: true>
- 	^(self t: type o: flagsOrOpcode s: doUpdateStatusRegister rn: sourceRegister rd: targetRegister) bitOr: so!

Item was added:
+ ----- Method: CogARMCompiler>>type:op:set:rn:rd: (in category 'encoding') -----
+ type: type op: flagsOrOpcode set: doUpdateStatusRegister rn:  sourceRegister rd: targetRegister
+ 	<inline: true>
+ 	^(self cond: AL type: type op: flagsOrOpcode set: doUpdateStatusRegister) 
+ 		bitOr: (sourceRegister << 16 bitOr: targetRegister << 12)!

Item was added:
+ ----- Method: CogARMCompiler>>type:op:set:rn:rd:shifterOperand: (in category 'encoding') -----
+ type: type op: flagsOrOpcode set: doUpdateStatusRegister rn:  sourceRegister rd: targetRegister shifterOperand: so
+ 	<inline: true>
+ 	^(self type: type op: flagsOrOpcode set: doUpdateStatusRegister rn: sourceRegister rd: targetRegister) bitOr: (so bitAnd: 16rFFF)!

Item was changed:
  ----- Method: CogARMCompilerTests>>strip: (in category 'accessing') -----
  strip: aFancyDisassembledInstruction
+ 	"When an immediate > 15, the disassembler appends '	; 0x\d\d'. That is stripped. Also strip any prepended stuff delimted by $: - perhaps memory addresses etc?"
- 	"When havin an immediate > 15, the disassembler appends '	; 0x\d\d'. That is stripped."
  	^((aFancyDisassembledInstruction 
+ 		allButFirst: (aFancyDisassembledInstruction indexOf: $: ifAbsent:[-1]) + 1)
- 		allButFirst: (aFancyDisassembledInstruction indexOf: $:) + 1)
  			copyUpTo: $;) withBlanksTrimmed!

Item was changed:
  ----- Method: CogVMSimulator>>ceSend:super:to:numArgs: (in category 'trampolines') -----
+ ceSend: selector super: superNormalBar to: rcvr numArgs: numArgs 
+ 	self break.
- ceSend: selector super: superNormalBar to: rcvr numArgs: numArgs
- 	"self stringOf: selector"
- 	"self printOop: rcvr"
- 	"(superNormalBar ~= 0 and: [(self stringOf: selector) = #bitShift:]) ifTrue:
- 		[self halt]."
  	self logSend: selector.
  	cogit assertCStackWellAligned.
+ 	self
+ 		maybeCheckStackDepth: numArgs + 1
+ 		sp: stackPointer
+ 		pc: (stackPages longAt: stackPointer).
+ 	^ super
+ 		ceSend: selector
+ 		super: superNormalBar
+ 		to: rcvr
+ 		numArgs: numArgs!
- 	self maybeCheckStackDepth: numArgs + 1 sp: stackPointer pc: (stackPages longAt: stackPointer).
- 	^super ceSend: selector super: superNormalBar to: rcvr numArgs: numArgs!

Item was changed:
  ----- Method: Cogit>>genMethodAbortTrampoline (in category 'initialization') -----
  genMethodAbortTrampoline
  	"Generate the abort for a method.  This abort performs either a call of ceSICMiss:
  	 to handle a single-in-line cache miss or a call of ceStackOverflow: to handle a
  	 stack overflow.  It distinguishes the two by testing ResultReceiverReg.  If the
  	 register is zero then this is a stack-overflow because a) the receiver has already
  	 been pushed and so can be set to zero before calling the abort, and b) the
  	 receiver must always contain an object (and hence be non-zero) on SIC miss."
  	| jumpSICMiss |
  	<var: #jumpSICMiss type: #'AbstractInstruction *'>
  	opcodeIndex := 0.
  	self CmpCq: 0 R: ReceiverResultReg.
  	jumpSICMiss := self JumpNonZero: 0.
+ 	"on machines with a link register, pop the stack if the receiverresulteg = 0"
+ 		backEnd hasLinkRegister ifTrue:
+ 			[self AddCq: BytesPerWord R: SPReg].
+ 
  	self compileTrampolineFor: #ceStackOverflow:
  		callJumpBar: true
  		numArgs: 1
  		arg: SendNumArgsReg
  		arg: nil
  		arg: nil
  		arg: nil
  		saveRegs: false
  		resultReg: nil.
  	jumpSICMiss jmpTarget: self Label.
  	^self genTrampolineFor: #ceSICMiss:
  		called: 'ceMethodAbort'
  		callJumpBar: true
  		numArgs: 1
  		arg: ReceiverResultReg
  		arg: nil
  		arg: nil
  		arg: nil
  		saveRegs: false
  		resultReg: nil
  		appendOpcodes: true!

Item was added:
+ ----- Method: CompiledMethod>>usesAlternateBytecodeSet (in category '*VMMaker-support') -----
+ usesAlternateBytecodeSet
+ 	"only an issue in vmcompiledmethodproxy stuff"
+ 	^false!



More information about the Vm-dev mailing list