VM Maker: Cog-lw.53.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

VM Maker: Cog-lw.53.mcz

commits-2
 
Lars Wassermann uploaded a new version of Cog to project VM Maker:
http://source.squeak.org/VMMaker/Cog-lw.53.mcz

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

Name: Cog-lw.53
Author: lw
Time: 9 August 2012, 9:15:44.451 pm
UUID: f12f20e9-6b2f-764a-95cd-6dcae41f853a
Ancestors: Cog-lw.52

pushed up the disassemble methods from BochsIA32ProcessorAlien to CogProcessorAlien. For that to work, I also changed the specifict register names to their abstract counterpart.

Started implementing the ProcessorTrapSignal way of telling the simulator what kind of error occured in the emulator. There might be a huge problem down the road, because the ARM simulator traps branches and jumps, only after the pc has been changed. For calls, this is no problem, because we have the lr. But what about long jumps?

Removed the opcode-methods, which were only used in filling the OpcodeTable for ProcessorTraps. This way of identifying the last instruction was not applicable, because some of those opcodes are implemented in several ways, some of which require more than one ARM instruction. For now, see #instructionTypeAt:in:.

=============== Diff against Cog-lw.52 ===============

Item was removed:
- ----- Method: BochsIA32Alien>>disassembleFrom:to:in:for:labels:on: (in category 'disassembly') -----
- disassembleFrom: startAddress to: endAddress in: memory for: aSymbolManager "<Cogit>" labels: labelDictionary on: aStream
- | address |
- address := startAddress.
- [address <= endAddress] whileTrue:
- [[:size :string|
- (aSymbolManager labelForPC: address) ifNotNil:
- [:label| aStream nextPutAll: label; nextPut: $:; cr].
- (labelDictionary at: address ifAbsent: []) ifNotNil:
- [:label| aStream nextPutAll: label; nextPut: $:; cr].
- aStream nextPutAll: (self decorateDisassembly: string for: aSymbolManager); cr; flush.
- address := address + size]
- valueWithArguments: (self
- primitiveDisassembleAt: address
- inMemory: memory)]!

Item was removed:
- ----- Method: BochsIA32Alien>>disassembleNextInstructionIn:for: (in category 'disassembly') -----
- disassembleNextInstructionIn: memory for: aSymbolManager "<Cogit|nil>"
- | string |
- string := (self primitiveDisassembleAt: self eip inMemory: memory) last.
- ^aSymbolManager
- ifNil: [string]
- ifNotNil: [self decorateDisassembly: string for: aSymbolManager]!

Item was added:
+ ----- Method: CogProcessorAlien>>disassembleFrom:to:in:for:labels:on: (in category 'disassembly') -----
+ disassembleFrom: startAddress to: endAddress in: memory for: aSymbolManager "<Cogit>" labels: labelDictionary on: aStream
+ | address |
+ address := startAddress.
+ [address <= endAddress] whileTrue:
+ [[:size :string|
+ (aSymbolManager labelForPC: address) ifNotNil:
+ [:label| aStream nextPutAll: label; nextPut: $:; cr].
+ (labelDictionary at: address ifAbsent: []) ifNotNil:
+ [:label| aStream nextPutAll: label; nextPut: $:; cr].
+ aStream nextPutAll: (self decorateDisassembly: string for: aSymbolManager); cr; flush.
+ address := address + size]
+ valueWithArguments: (self
+ primitiveDisassembleAt: address
+ inMemory: memory)]!

Item was changed:
  ----- Method: CogProcessorAlien>>disassembleFrom:to:in:on: (in category 'disassembly') -----
  disassembleFrom: startAddress to: endAddress in: memory on: aStream
  | address |
  address := startAddress.
  [address < endAddress] whileTrue:
  [[:size :string|
+ aStream nextPutAll: (address printStringBase: 16 length: 8 padded: true); nextPut: $:; tab; tab; nextPutAll: string; cr; flush.
- aStream nextPutAll: (address printStringBase: 16 length: 8 padded: true); nextPut: $:; tab; nextPutAll: string; cr; flush.
  address := address + size]
  valueWithArguments: (self
  primitiveDisassembleAt: address
  inMemory: memory)]!

Item was added:
+ ----- Method: CogProcessorAlien>>disassembleNextInstructionIn:for: (in category 'disassembly') -----
+ disassembleNextInstructionIn: memory for: aSymbolManager "<Cogit|nil>"
+ | string |
+ string := (self primitiveDisassembleAt: self pc inMemory: memory) last.
+ ^aSymbolManager
+ ifNil: [string]
+ ifNotNil: [self decorateDisassembly: string for: aSymbolManager]!

Item was changed:
  CogProcessorAlien variableByteSubclass: #GdbARMAlien
  instanceVariableNames: ''
+ classVariableNames: 'PostBuildStackDelta'
- classVariableNames: 'OpcodeExceptionMap PostBuildStackDelta'
  poolDictionaries: ''
  category: 'Cog-Processors'!

Item was changed:
  ----- Method: GdbARMAlien>>branchAndLinkOpcodeWithOffset: (in category 'opcodes') -----
  branchAndLinkOpcodeWithOffset: aNumber
 
  | offset |
+ offset := (aNumber - 8) asInteger.
+ (offset between: -33554432 and: 33554428) ifFalse: [self error: 'The offset is to far. ARM does not support such far jumps.'].
+ ^ 16reb000000 bitOr: (offset >> 2 bitAnd: 16r00FFFFFF)
+ !
- offset := (aNumber - 8) asInteger >> 2.
- (offset bitAnd: 16rFF000000) ~= 0 ifTrue: [self error: 'The offset is to far. ARM does not support such far jumps.'].
- ^ 16reb000000 bitOr: (offset bitAnd: 16r00FFFFFF)!

Item was removed:
- ----- Method: GdbARMAlien>>callOpcode (in category 'opcodes') -----
- callOpcode
- "The call command does not generally exist. The most similar would be bl <offset>"
- ^ self branchAndLinkOpcodeWithOffset: 0.!

Item was added:
+ ----- Method: GdbARMAlien>>decorateDisassembly:for: (in category 'disassembly') -----
+ decorateDisassembly: anInstructionString for: aSymbolManager "<Cogit>"
+ | string i1 i2 v |
+ string := anInstructionString.
+ (i1 := string indexOfSubCollection: '%ds:0x') > 0 ifTrue:
+ [i2 := i1 + 6.
+ ['0123456789abcdef' includes: (string at: i2)] whileTrue: [i2 := i2 + 1].
+ string := string
+ copyReplaceFrom: i1 + 4
+ to: i2 - 1
+ with: (aSymbolManager lookupCHexString: (string copyFrom: i1 + 4 to: i2 - 1))].
+ (i1 := string indexOfSubCollection: '%ss:0x') > 0 ifTrue:
+ [i2 := i1 + 6.
+ ['0123456789abcdef' includes: (string at: i2)] whileTrue: [i2 := i2 + 1].
+ ((string at: i2) = $(
+ and: [(string at: i2 + 1) = $%]) ifTrue:
+ [v := Integer readFrom: (ReadStream on: string from: i1 + 6 to: i2 - 1) base: 16.
+ string := string
+ copyReplaceFrom: i1
+ to: i2 - 1
+ with: ((v bitAnd: (1 bitShift: 31) - 1) - (v bitAnd: (1 bitShift: 31))) printString]].
+ (i1 := string indexOfSubCollection: '$0x') > 0 ifTrue:
+ [i2 := i1 + 3.
+ ['0123456789abcdef' includes: (string at: i2)] whileTrue: [i2 := i2 + 1].
+ string := string
+ copyReplaceFrom: i1 + 1
+ to: i2 - 1
+ with: (aSymbolManager lookupCHexString: (string copyFrom: i1 + 1 to: i2 - 1))].
+ ((i1 := string indexOf: $() > 1
+ and: [(string at: i1 + 1) isDigit
+ and: [i1 < (i2 := string indexOf: $))]]) ifTrue:
+ [string := string
+ copyReplaceFrom: i1 + 1
+ to: i2 - 1
+ with: (aSymbolManager lookupCHexString: (string copyFrom: i1 + 1 to: i2 - 1))].
+ ^string!

Item was added:
+ ----- Method: GdbARMAlien>>handleCallFailureAt:in:readOnlyBelow: (in category 'error handling') -----
+ handleCallFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" readOnlyBelow: minimumWritableAddress "<Integer>"
+ "Convert an execution primitive failure for a call into a ProcessorSimulationTrap signal."
+ |  relativeJump callAddress |
+ ((memoryArray byteAt: pc + 4) bitAnd: 16rF) = 16rB "BL opcode"
+ ifTrue: ["short jump via BL, therefore we have a 24bit signed integer offset"
+ relativeJump := (memoryArray unsignedLongAt: pc + 1 bigEndian: false) bitAnd: 16r00FFFFFF.
+ relativeJump := (relativeJump bitAt: 24) = 1
+ ifTrue: [((relativeJump bitOr: 16r3F000000) << 2) signedIntFromLong]
+ ifFalse: [relativeJump << 2].
+ callAddress := (pc + 8 + relativeJump)]
+
+ ifFalse: ["long jump using RISCTempReg"
+ "The memoryArray starts indexing from 1, whereas the pc is based on 0-indexing, therefore all access-offsets are one greater than expected"
+ callAddress := (memoryArray byteAt: pc + 4)
+ + ((memoryArray byteAt: pc - 4) << 24)
+ + ((memoryArray byteAt: pc - 8) << 16)
+ + ((memoryArray byteAt: pc - 12) << 8)].
+ ^(ProcessorSimulationTrap
+ pc: pc
+ nextpc: pc + 4
+ address: callAddress signedIntToLong
+ type: #call)
+ signal!

Item was added:
+ ----- Method: GdbARMAlien>>handleExecutionPrimitiveFailureAt:in:readOnlyBelow: (in category 'error handling') -----
+ handleExecutionPrimitiveFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" readOnlyBelow: minimumWritableAddress "<Integer>"
+ "Handle an execution primitive failure for an unhandled opcode."
+ ^self reportPrimitiveFailure!

Item was changed:
  ----- Method: GdbARMAlien>>handleExecutionPrimitiveFailureIn:minimumAddress:readOnlyBelow: (in category 'error handling') -----
  handleExecutionPrimitiveFailureIn: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "<Integer>" readOnlyBelow: minimumWritableAddress "<Integer>"
  "Handle an execution primitive failure.  Convert out-of-range call and absolute
  memory read into register instructions into ProcessorSimulationTrap signals."
- "self printIntegerRegistersOn: Transcript"
  "self printRegistersOn: Transcript"
+ | pc |
-
- "| pc opcode |
  ((pc := self pc) between: minimumAddress and: memoryArray byteSize - 1) ifTrue:
+ [(self instructionTypeAt: pc in: memoryArray)
+ caseOf: {
+ [#Call] -> [^self handleCallFailureAt: pc in: memoryArray readOnlyBelow: minimumWritableAddress].
+ [#Jump] -> [^self handleJmpFailureAt: pc in: memoryArray readOnlyBelow: minimumWritableAddress].
+ [#MoveAwR] -> [^self handleMoveAwRFailureAt: pc in: memoryArray readOnlyBelow: minimumWritableAddress].
+ [#MoveMbrR] -> [^self handleMoveMbrRFailureAt: pc in: memoryArray readOnlyBelow: minimumWritableAddress].
+ [#MoveRAw] -> [^self handleMoveRAwFailureAt: pc in: memoryArray readOnlyBelow: minimumWritableAddress].
+ [#MoveRMbr] -> [^self handleMoveRMbrFailureAt: pc in: memoryArray readOnlyBelow: minimumWritableAddress].
+ [#Ret] -> [^self handleRetFailureAt: pc in: memoryArray readOnlyBelow: minimumWritableAddress].}
+ otherwise: [^self handleExecutionPrimitiveFailureAt: pc in: memoryArray readOnlyBelow: minimumWritableAddress]].
+ ((pc := self lr - 4) between: minimumAddress and: memoryArray byteSize - 1) ifTrue:
+ [(self instructionTypeAt: pc in: memoryArray)
+ caseOf: {
+ [#Call] -> [^self handleCallFailureAt: pc in: memoryArray readOnlyBelow: minimumWritableAddress].
+ [#Jump] -> [^self handleJmpFailureAt: pc in: memoryArray readOnlyBelow: minimumWritableAddress].
+ [#Ret] -> [^self handleRetFailureAt: pc in: memoryArray readOnlyBelow: minimumWritableAddress].}
+ otherwise: [^self handleExecutionPrimitiveFailureAt: pc in: memoryArray readOnlyBelow: minimumWritableAddress]].
- [opcode := memoryArray byteAt: pc + 1.
- ^self
- perform: (OpcodeExceptionMap at: opcode + 1)
- with: pc
- with: memoryArray
- with: minimumWritableAddress]."
  ^self reportPrimitiveFailure!

Item was added:
+ ----- Method: GdbARMAlien>>handleJmpFailureAt:in:readOnlyBelow: (in category 'error handling') -----
+ handleJmpFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" readOnlyBelow: minimumWritableAddress "<Integer>"
+ "Convert an execution primitive failure for a jmp into a ProcessorSimulationTrap signal."
+ |  relativeJump |
+ self halt.
+ relativeJump := memoryArray longAt: pc + 2 bigEndian: false.
+ ^(ProcessorSimulationTrap
+ pc: pc
+ nextpc: pc + 5
+ address: (pc + 5 + relativeJump) signedIntToLong
+ type: #jump)
+ signal!

Item was added:
+ ----- Method: GdbARMAlien>>handleMoveAwRFailureAt:in:readOnlyBelow: (in category 'error handling') -----
+ handleMoveAwRFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" readOnlyBelow: minimumWritableAddress "<Integer>"
+ "Convert an execution primitive failure for a register load from an Address into a ProcessorSimulationTrap signal."
+ ((memoryArray byteAt: pc + 4) = 16rE5  "test for E593 as the most significant two bytes"
+ and: [(memoryArray byteAt: pc + 3) = (16r90 + (CogARMCompiler classPool at: #RISCTempReg))])
+ ifTrue:
+ [(ProcessorSimulationTrap
+ pc: pc
+ nextpc: pc + 4
+ address: (memoryArray byteAt: pc + 1) "address, combined from four instructions"
+ + ((memoryArray byteAt: pc - 3) << 24)
+ + ((memoryArray byteAt: pc - 7) << 16)
+ + ((memoryArray byteAt: pc - 11) << 8)
+ type: #read
+ accessor: (self registerStateSetters at: ((memoryArray byteAt: pc + 2) >> 4) + 1))
+ signal]
+ ifFalse:
+ [self reportPrimitiveFailure]!

Item was added:
+ ----- Method: GdbARMAlien>>handleMoveMbrRFailureAt:in:readOnlyBelow: (in category 'error handling') -----
+ handleMoveMbrRFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" readOnlyBelow: minimumWritableAddress "<Integer>"
+ "Convert an execution primitive failure for a byte register load into a ProcessorSimulationTrap signal."
+ "MoveMbrR"
+ | modrmByte |
+ self halt.
+ ^(((modrmByte := memoryArray byteAt: pc + 2) bitAnd: 16rC0) = 16r80) "ModRegRegDisp32"
+ ifTrue:
+ [(ProcessorSimulationTrap
+ pc: pc
+ nextpc: pc + 6
+ address: ((self perform: (#(eax ecx edx ebx esp ebp esi edi) at: (modrmByte bitAnd: 7) + 1))
+ + (memoryArray unsignedLongAt: pc + 3 bigEndian: false)
+ bitAnd: 16rFFFFFFFF)
+ type: #read
+ accessor: (#(al: cl: dl: bl: ah: ch: dh: bh:) at: ((modrmByte >> 3 bitAnd: 7) + 1)))
+ signal]
+ ifFalse:
+ [self reportPrimitiveFailure]!

Item was added:
+ ----- Method: GdbARMAlien>>handleMoveRAwFailureAt:in:readOnlyBelow: (in category 'error handling') -----
+ handleMoveRAwFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" readOnlyBelow: minimumWritableAddress "<Integer>"
+ "Convert an execution primitive failure for a register write into Memory at a predefined address into a ProcessorSimulationTrap signal."
+ ^((memoryArray byteAt: pc + 4) = 16rE5
+ and: [(memoryArray byteAt: pc + 3) = (16r80 + (CogARMCompiler classPool at: #RISCTempReg))])
+ ifTrue:
+ [(ProcessorSimulationTrap
+ pc: pc
+ nextpc: pc + 4
+ address: (memoryArray byteAt: pc + 1)
+ + ((memoryArray byteAt: pc - 3) << 24)
+ + ((memoryArray byteAt: pc - 7) << 16)
+ + ((memoryArray byteAt: pc - 11) << 8)
+ type: #write
+ accessor: (self registerStateNames at: ((memoryArray byteAt: pc + 2) >> 4) + 1))
+ signal]
+ ifFalse:
+ [self reportPrimitiveFailure]!

Item was added:
+ ----- Method: GdbARMAlien>>handleMoveRMbrFailureAt:in:readOnlyBelow: (in category 'error handling') -----
+ handleMoveRMbrFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" readOnlyBelow: minimumWritableAddress "<Integer>"
+ "Convert an execution primitive failure for a byte register write into a ProcessorSimulationTrap signal."
+ "MoveRMbr"
+ | modrmByte |
+ self halt.
+ ^(((modrmByte := memoryArray byteAt: pc + 2) bitAnd: 16rC0) = 16r80) "ModRegRegDisp32"
+ ifTrue:
+ [(ProcessorSimulationTrap
+ pc: pc
+ nextpc: pc + 6
+ address: ((self perform: (#(eax ecx edx ebx esp ebp esi edi) at: (modrmByte bitAnd: 7) + 1))
+ + (memoryArray unsignedLongAt: pc + 3 bigEndian: false)
+ bitAnd: 16rFFFFFFFF)
+ type: #write
+ accessor: (#(al cl dl bl ah ch dh bh) at: ((modrmByte >> 3 bitAnd: 7) + 1)))
+ signal]
+ ifFalse:
+ [self reportPrimitiveFailure]!

Item was added:
+ ----- Method: GdbARMAlien>>handleRetFailureAt:in:readOnlyBelow: (in category 'error handling') -----
+ handleRetFailureAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>" readOnlyBelow: minimumWritableAddress "<Integer>"
+ "Convert an execution primitive failure for a ret into a ProcessorSimulationTrap signal."
+ self halt.
+ ^(ProcessorSimulationTrap
+ pc: pc
+ nextpc: pc + 4
+ address: (memoryArray unsignedLongAt: self sp + 1)
+ type: #return
+ accessor: #pc:)
+ signal!

Item was added:
+ ----- Method: GdbARMAlien>>instructionTypeAt:in: (in category 'error handling') -----
+ instructionTypeAt: pc "<Integer>" in: memoryArray "<Bitmap|ByteArray>"
+ "Identify which type of instruction is at pc in memoryArray. For the time beeing, only those instructions needed for PrimitiveFailure are identified."
+ | RISCTempReg lastInstruction typeOperandStatus |
+ RISCTempReg := CogARMCompiler classPool at: #RISCTempReg.
+ lastInstruction := memoryArray unsignedLongAt: pc + 1 bigEndian: false.
+ "self disassembleFrom: pc - 16 to: pc + 3 in: memoryArray on: Transcript cr"
+
+ "Ret"
+ lastInstruction = 16rE8BD8000 ifTrue: [#Ret].
+
+ "Call"
+ (((memoryArray byteAt: pc + 4) bitAnd: 16rF) = 16rB "BL opcode"
+ or: [(memoryArray unsignedLongAt: pc - 3 bigEndian: false) = 16rE1A0E00F]) ifTrue: [^#Call].
+
+ "Jump"
+ ((memoryArray byteAt: pc + 3) >> 4 = 16rA "B opcode, for short jumps"
+ or: [(lastInstruction >> 12 bitAnd: 16r0FFFF) =
+ (16r0280F + (RISCTempReg << 4)) "ADD? PC, RISCTempReg, #anything, for JumpLong-Instructions"])
+ ifTrue: [^#Jump].
+
+ typeOperandStatus := lastInstruction >> 20 bitAnd: 16rFF.
+ "MoveRMbr"
+ (typeOperandStatus = 16r54 or: [typeOperandStatus = 16r5C] or: [typeOperandStatus = 16r7C])
+ ifTrue: [^#MoveRMbr].
+
+ "MoveRAw"
+ (typeOperandStatus = 16r58 and: [(lastInstruction >> 16 bitAnd: 16rF) = RISCTempReg])
+ ifTrue: [^#MoveRAw].
+
+ "MoveMbrR"
+ (typeOperandStatus = 16r55 or: [typeOperandStatus = 16r5D] or: [typeOperandStatus = 16r7D])
+ ifTrue: [^#MoveMbrR].
+
+ "MoveAwR"
+ ((typeOperandStatus = 16r59) and: [(lastInstruction >> 16 bitAnd: 16rF) = RISCTempReg])
+ ifTrue: [^#MoveAwR].
+
+
+ ^#UnidentifiedInstruction!

Item was changed:
  ----- Method: GdbARMAlien>>primitiveDisassembleAt:inMemory: (in category 'primitives') -----
  primitiveDisassembleAt: address inMemory: memoryArray "<Bitmap|ByteArray>"
  "Answer an Array of the size and the disassembled code string for the instruction at the current instruction pointer in memory."
  <primitive: 'primitiveDisassembleAtInMemory' module: 'GdbARMPlugin'>
+ ^self reportPrimitiveFailure!
- ^self primitiveFailed!

Item was changed:
  ----- Method: GdbARMAlien>>registerStateNames (in category 'accessing-abstract') -----
  registerStateNames
+ ^#( r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 fp r12 sp lr pc eflags)!
- ^#( r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc eflags)!

Item was added:
+ ----- Method: GdbARMAlien>>registerStateSetters (in category 'accessing-abstract') -----
+ registerStateSetters
+ ^#( r0: r1: r2: r3: r4: r5: r6: r7: r8: r9: r10: fp: r12: sp: lr: pc:)!

Item was removed:
- ----- Method: GdbARMAlien>>retOpcode (in category 'opcodes') -----
- retOpcode
- "the ret command does not generally exist. the most similar would be mov pc, lr"
- ^ self notYetImplemented!

Item was added:
+ ----- Method: GdbARMAlien>>simulateCallOf:nextpc:memory: (in category 'execution simulation') -----
+ simulateCallOf: address nextpc: nextpc memory: aMemory
+ "Simulate a frame-building call of address.  Build a frame since
+ a) this is used for calls into the run-time which are unlikely to be leaf-calls, and
+ b) stack alignment needs to be realistic for assert checking for platforms such as Mac OS X"
+ self lr: nextpc.
+ self pc: address!

Item was removed:
- ----- Method: GdbARMAlienTests>>callTrapPerformance: (in category 'tests') -----
- callTrapPerformance: n
- "Call a function that is out-of-range.  Ensure the call is trapped."
- "self new testCallTrap"
- | memory |
- "The address is out of range of memory every which way (whether relative or absolute and whether big-endian or little."
- memory := ByteArray new: 1024.
- memory replaceFrom: 1 to: 5 with: { self processor callOpcode. 0. 16r80. 16r80. 0. } asByteArray.
- self processor
- eip: 0;
- esp: (memory size - 4). "Room for return address"
- 1 to: n do:
- [:ign|
- [self processor singleStepIn: memory]
- on: ProcessorSimulationTrap
- do: [:ex|]].
-
- "QSystemProfiler spyOn: [GdbARMAlienTests new callTrapPerformance: 1024*128]"
- "Time millisecondsToRun: [GdbARMAlienTests new callTrapPerformance: 1024*128] 2463"
- "Time millisecondsToRun: [1 to: 1024*1024*64 do: [:ign| nil yourself]] 636"
- "Time millisecondsToRun: [1 to: 1024*1024*64 do: [:ign| nil perform: #ifNotNilDo: with: nil]] 3639"
- "Time millisecondsToRun: [1 to: 1024*1024*64 do: [:ign| nil perform: #ifNotNilDo:ifNil: with: nil with: nil]] 12401"!

Item was changed:
  ----- Method: GdbARMAlienTests>>runNFib:disassemble:printRegisters: (in category 'execution') -----
  runNFib: n disassemble: disassemble printRegisters: printRegisters
  "Run nfib wth the argument. Answer the result."
  "self new runNFib: 5 disassemble: true printRegisters: true"
  | memory |
+ memory := Bitmap new: 1024 * 2 withAll: self processor nopOpcode.
- memory := WordArray new: 1024 * 2 withAll: self processor nopOpcode.
  memory replaceFrom: 1 to: self nfib size with: self nfib asWordArray startingAt: 1.
  self processor
  r0: n;"argument n"
  lr: memory size * 2; "return address"
  pc: 0;
  sp: (memory size * 4) - 16.
  printRegisters ifTrue:
  [self processor printRegistersOn: Transcript.
  Transcript cr; flush].
  "run until something goes wrong."
  self processor runInMemory: memory readExecuteOnlyBelow: memory size / 2.
  printRegisters ifTrue:
  [self processor printRegistersOn: Transcript.
  Transcript cr; flush].
  ^self processor r0!

Item was changed:
  ----- Method: GdbARMAlienTests>>testCallTrap (in category 'tests') -----
  testCallTrap
  "Call a function that is out-of-range.  Ensure the call is trapped."
  "self new testCallTrap"
  | memory |
  memory := Bitmap new: 256 withAll: self processor nopOpcode.
  memory longAt: 1 put: (self processor branchAndLinkOpcodeWithOffset: 1024) bigEndian: false.
  memory := memory asByteArray.
  self processor
  pc: 0;
  sp: (memory size - 4); "Room for return address"
  singleStepIn: memory.
  "We have to step twice, because the first step only changes the pc, but does not fetch anything from the address it points to."
  self should: [self processor singleStepIn: memory]
  raise: Error
  withExceptionDo:
  [:pst|
  self assert: self processor pc = 1024.
  self assert: self processor lr = 4.
+ self assert: pst pc = 0.
+ self assert: pst nextpc = 4.
+ self assert: pst address = 1024.
+ self assert: pst type = #call].!
- self assert: pst messageText = 'Error 0: Illegal Instruction fetch address (0x00000400).'].!