VM Maker: Cog-lw.48.mcz

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

VM Maker: Cog-lw.48.mcz

commits-2
 
Eliot Miranda uploaded a new version of Cog to project VM Maker:
http://source.squeak.org/VMMaker/Cog-lw.48.mcz

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

Name: Cog-lw.48
Author: lw
Time: 11 July 2012, 9:13:45.865 pm
UUID: 5ae3e465-4b2c-2349-9b88-77b8f53d5acd
Ancestors: Cog-eem.47

Added the GdbARMAlien, together with its tests and the plugin.
Additionally, introduced CogProcessorAlien as a common superclass for BochsIA32Alien and GdbARMAlien to increase code reusage.

The same might be possible for the Plugins (BochsIA32/GdbARM), because they are also identical.

=============== Diff against Cog-eem.47 ===============

Item was changed:
+ CogProcessorAlien variableByteSubclass: #BochsIA32Alien
- Alien variableByteSubclass: #BochsIA32Alien
  instanceVariableNames: ''
  classVariableNames: 'OpcodeExceptionMap PostBuildStackDelta'
  poolDictionaries: ''
  category: 'Cog-Processors'!
 
  !BochsIA32Alien commentStamp: '<historical>' prior: 0!
  I am a wrapper around the Bochs C++ IA32 CPU emulator.  Note that currently I provide no access to the x87/mmx FPU state, only providing access to the SSE/xmm registers.
 
  Here is the configure script for the configuration this code assumes.  Offsets of fields will change with different configurations so they must agree.
 
  ----8<---- conf.COG ----8<----
  #!!/bin/sh
 
  # this sets up the compile for Cog.  Disable as much inessential stuff
  # as possible leaving only the cpu/fpu & memory interface
 
  set echo
  # CFLAGS="-pipe -O3 -fomit-frame-pointer -finline-functions -falign-loops=16 -falign-jumps=16 -falign-functions=16 -falign-labels=16 -falign-loops-max-skip=15 -falign-jumps-max-skip=15 -fprefetch-loop-arrays $CFLAGS"
  CFLAGS="-m32 $CFLAGS"
  CFLAGS="-Dlongjmp=_longjmp -Dsetjmp=_setjmp $CFLAGS"
  CFLAGS="-pipe -O3 -fomit-frame-pointer -finline-functions $CFLAGS"
  CFLAGS="-g $CFLAGS"
  CPATH="/sw/include"
  CPPFLAGS=""
  CXXFLAGS="$CFLAGS"
  LDFLAGS="-L/sw/lib"
 
  export CFLAGS
  export CPATH
  export CPPFLAGS
  export CXXFLAGS
  export LDFLAGS
 
  ./configure --enable-Cog \
  --enable-cpu-level=6 \
  --enable-sse=2 \
  --enable-assert-checks \
  --with-nogui \
  --disable-x86-64 \
  --disable-pae \
  --disable-large-pages \
  --disable-global-pages \
  --disable-mtrr \
  --disable-sb16 \
  --disable-ne2000 \
  --disable-pci \
  --disable-acpi \
  --disable-apic \
  --disable-clgd54xx \
  --disable-usb \
  --disable-plugins \
  ${CONFIGURE_ARGS}
 
  # apic == Advanced programmable Interrupt Controller
  # acpi == Advanced Configuration and Power Interface
  # pci == Peripheral Component Interconnect local bus
  # clgd54xx == Cirrus Logic GD54xx video card
  ----8<---- conf.COG ----8<----!

Item was removed:
- ----- Method: BochsIA32Alien>>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: string; cr; flush.
- address := address + size]
- valueWithArguments: (self
- primitiveDisassembleAt: address
- inMemory: memory)]!

Item was removed:
- ----- Method: BochsIA32Alien>>disassembleInstructionAt:In: (in category 'disassembly') -----
- disassembleInstructionAt: pc In: memory
- ^(self primitiveDisassembleAt: pc inMemory: memory) last!

Item was removed:
- ----- Method: BochsIA32Alien>>disassembleInstructionAt:In:into: (in category 'disassembly') -----
- disassembleInstructionAt: ip In: memory into: aBlock
- | lenAndDi |
- lenAndDi := self primitiveDisassembleAt: ip inMemory: memory.
- ^aBlock value: lenAndDi last value: lenAndDi first!

Item was removed:
- ----- Method: BochsIA32Alien>>disassembleNextInstructionIn: (in category 'disassembly') -----
- disassembleNextInstructionIn: memory
- ^(self primitiveDisassembleAt: self eip inMemory: memory) last!

Item was removed:
- ----- Method: BochsIA32Alien>>runInMemory: (in category 'execution') -----
- runInMemory: aMemory
- | result |
- result := self primitiveRunInMemory: aMemory minimumAddress: 0 readOnlyBelow: 0.
- result ~~ self ifTrue:
- [self error: 'eek!!']!

Item was removed:
- ----- Method: BochsIA32Alien>>runInMemory:minimumAddress:readOnlyBelow: (in category 'execution') -----
- runInMemory: aMemory minimumAddress: minimumAddress readOnlyBelow: minimumWritableAddress
- | result |
- result := self primitiveRunInMemory: aMemory
- minimumAddress: minimumAddress
- readOnlyBelow: minimumWritableAddress.
- result ~~ self ifTrue:
- [self error: 'eek!!']!

Item was removed:
- ----- Method: BochsIA32Alien>>runInMemory:readExecuteOnlyBelow: (in category 'execution') -----
- runInMemory: aMemory readExecuteOnlyBelow: minWriteMaxExecAddr
- | result |
- result := self primitiveRunInMemory: aMemory minimumAddress: 0 readOnlyBelow: minWriteMaxExecAddr.
- result ~~ self ifTrue:
- [self error: 'eek!!']!

Item was removed:
- ----- Method: BochsIA32Alien>>singleStepIn: (in category 'execution') -----
- singleStepIn: aMemory
- | result |
- result := self primitiveSingleStepInMemory: aMemory minimumAddress: 0 readOnlyBelow: aMemory size.
- result ~~ self ifTrue:
- [self error: 'eek!!']!

Item was removed:
- ----- Method: BochsIA32Alien>>singleStepIn:minimumAddress:readOnlyBelow: (in category 'execution') -----
- singleStepIn: aMemory minimumAddress: minimumAddress readOnlyBelow: minimumWritableAddress
- | result |
- result := self primitiveSingleStepInMemory: aMemory
- minimumAddress: minimumAddress
- readOnlyBelow: minimumWritableAddress.
- result ~~ self ifTrue:
- [self error: 'eek!!']!

Item was removed:
- ----- Method: BochsIA32Alien>>singleStepIn:readExecuteOnlyBelow: (in category 'execution') -----
- singleStepIn: aMemory readExecuteOnlyBelow: minWriteMaxExecAddr
- | result |
- result := self primitiveSingleStepInMemory: aMemory minimumAddress: 0 readOnlyBelow: minWriteMaxExecAddr.
- result ~~ self ifTrue:
- [self error: 'eek!!']!

Item was added:
+ Alien variableByteSubclass: #CogProcessorAlien
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'Cog-Processors'!

Item was added:
+ ----- Method: CogProcessorAlien>>abstractInstructionCompilerClass (in category 'Cog API') -----
+ abstractInstructionCompilerClass
+ self subclassResponsibility!

Item was added:
+ ----- Method: CogProcessorAlien>>callOpcode (in category 'opcodes') -----
+ callOpcode
+ self subclassResponsibility.!

Item was added:
+ ----- 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: string; cr; flush.
+ address := address + size]
+ valueWithArguments: (self
+ primitiveDisassembleAt: address
+ inMemory: memory)]!

Item was added:
+ ----- Method: CogProcessorAlien>>disassembleInstructionAt:In: (in category 'disassembly') -----
+ disassembleInstructionAt: pc In: memory
+ ^(self primitiveDisassembleAt: pc inMemory: memory) last!

Item was added:
+ ----- Method: CogProcessorAlien>>disassembleInstructionAt:In:into: (in category 'disassembly') -----
+ disassembleInstructionAt: ip In: memory into: aBlock
+ | lenAndDi |
+ lenAndDi := self primitiveDisassembleAt: ip inMemory: memory.
+ ^aBlock value: lenAndDi last value: lenAndDi first!

Item was added:
+ ----- Method: CogProcessorAlien>>disassembleNextInstructionIn: (in category 'disassembly') -----
+ disassembleNextInstructionIn: memory
+ ^(self primitiveDisassembleAt: self pc inMemory: memory) last!

Item was added:
+ ----- Method: CogProcessorAlien>>nopOpcode (in category 'opcodes') -----
+ nopOpcode
+ self subclassResponsibility.!

Item was added:
+ ----- Method: CogProcessorAlien>>printRegisterState:on: (in category 'printing') -----
+ printRegisterState: registerStateVector on: aStream
+
+ self subclassResponsibility.!

Item was added:
+ ----- Method: CogProcessorAlien>>printRegistersOn: (in category 'printing') -----
+ printRegistersOn: aStream
+ self printRegisterState: self registerState on: aStream.
+ aStream flush!

Item was added:
+ ----- Method: CogProcessorAlien>>reportPrimitiveFailure (in category 'error handling') -----
+ reportPrimitiveFailure
+ | errorAndLog |
+ errorAndLog := self primitiveErrorAndLog.
+ self error: 'Error ', errorAndLog first printString, (errorAndLog last ifNil: [''] ifNotNil: [:log| ': ', log])!

Item was added:
+ ----- Method: CogProcessorAlien>>runInMemory: (in category 'execution') -----
+ runInMemory: aMemory
+ | result |
+ result := self primitiveRunInMemory: aMemory minimumAddress: 0 readOnlyBelow: 0.
+ result ~~ self ifTrue:
+ [self error: 'eek!!']!

Item was added:
+ ----- Method: CogProcessorAlien>>runInMemory:minimumAddress:readOnlyBelow: (in category 'execution') -----
+ runInMemory: aMemory minimumAddress: minimumAddress readOnlyBelow: minimumWritableAddress
+ | result |
+ result := self primitiveRunInMemory: aMemory
+ minimumAddress: minimumAddress
+ readOnlyBelow: minimumWritableAddress.
+ result ~~ self ifTrue:
+ [self error: 'eek!!']!

Item was added:
+ ----- Method: CogProcessorAlien>>runInMemory:readExecuteOnlyBelow: (in category 'execution') -----
+ runInMemory: aMemory readExecuteOnlyBelow: minWriteMaxExecAddr
+ | result |
+ result := self primitiveRunInMemory: aMemory minimumAddress: 0 readOnlyBelow: minWriteMaxExecAddr.
+ result ~~ self ifTrue:
+ [self error: 'eek!!']!

Item was added:
+ ----- Method: CogProcessorAlien>>singleStepIn: (in category 'execution') -----
+ singleStepIn: aMemory
+ | result |
+ result := self primitiveSingleStepInMemory: aMemory minimumAddress: 0 readOnlyBelow: aMemory size.
+ result ~~ self ifTrue:
+ [self error: 'eek!!']!

Item was added:
+ ----- Method: CogProcessorAlien>>singleStepIn:minimumAddress:readOnlyBelow: (in category 'execution') -----
+ singleStepIn: aMemory minimumAddress: minimumAddress readOnlyBelow: minimumWritableAddress
+ | result |
+ result := self primitiveSingleStepInMemory: aMemory
+ minimumAddress: minimumAddress
+ readOnlyBelow: minimumWritableAddress.
+ result ~~ self ifTrue:
+ [self error: 'eek!!']!

Item was added:
+ ----- Method: CogProcessorAlien>>singleStepIn:readExecuteOnlyBelow: (in category 'execution') -----
+ singleStepIn: aMemory readExecuteOnlyBelow: minWriteMaxExecAddr
+ | result |
+ result := self primitiveSingleStepInMemory: aMemory minimumAddress: 0 readOnlyBelow: minWriteMaxExecAddr.
+ result ~~ self ifTrue:
+ [self error: 'eek!!']!

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

Item was added:
+ ----- Method: GdbARMAlien class>>dataSize (in category 'instance creation') -----
+ dataSize
+
+ ^1536!

Item was added:
+ ----- Method: GdbARMAlien class>>defaultIntegerBaseInDebugger (in category 'debugger') -----
+ defaultIntegerBaseInDebugger
+ ^16!

Item was added:
+ ----- Method: GdbARMAlien class>>new (in category 'instance creation') -----
+ new
+ ^(self atAddress: self primitiveNewCPU) reset!

Item was added:
+ ----- Method: GdbARMAlien class>>primitiveNewCPU (in category 'primitives') -----
+ primitiveNewCPU
+ "Answer the address of a new ARMulator C type ARMul_State instance."
+ <primitive: 'primitiveNewCPU' module: 'GdbARMPlugin'>
+ ^self primitiveFailed!

Item was added:
+ ----- Method: GdbARMAlien>>abstractInstructionCompilerClass (in category 'Cog API') -----
+ abstractInstructionCompilerClass
+ ^CogARMCompiler!

Item was added:
+ ----- Method: GdbARMAlien>>branchAndLinkOpcodeWithOffset: (in category 'opcodes') -----
+ branchAndLinkOpcodeWithOffset: aNumber
+
+ | offset |
+ 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 added:
+ ----- 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>>cflag (in category 'accessing') -----
+ cflag
+ ^self unsignedLongAt: 577!

Item was added:
+ ----- Method: GdbARMAlien>>eflags (in category 'accessing') -----
+ eflags
+
+ ^ (((self nflag << 5 bitOr: self zflag << 4)
+ bitOr: self cflag << 3)
+ bitOr: self vflag << 2)
+ bitOr: self ifflags!

Item was added:
+ ----- 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 opcode |
+ ((pc := self pc) between: minimumAddress and: memoryArray byteSize - 1) ifTrue:
+ [opcode := memoryArray byteAt: pc + 1.
+ ^self
+ perform: (OpcodeExceptionMap at: opcode + 1)
+ with: pc
+ with: memoryArray
+ with: minimumWritableAddress]."
+ ^self reportPrimitiveFailure!

Item was added:
+ ----- Method: GdbARMAlien>>ifflags (in category 'accessing') -----
+ ifflags
+ ^self unsignedLongAt: 585!

Item was added:
+ ----- Method: GdbARMAlien>>integerRegisterState (in category 'accessing-abstract') -----
+ integerRegisterState
+ ^{ self r0. self r1. self r2. self r3. self r4. self r5. self r6. self r7. self r8.
+ self r9. self r10. self r11. self r12. self sp. self lr. self pc}!

Item was added:
+ ----- Method: GdbARMAlien>>lr (in category 'accessing') -----
+ lr
+ ^self unsignedLongAt: 69!

Item was added:
+ ----- Method: GdbARMAlien>>lr: (in category 'accessing') -----
+ lr: anUnsignedInteger
+
+ ^self unsignedLongAt: 69 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>nflag (in category 'accessing') -----
+ nflag
+ ^self unsignedLongAt: 569!

Item was added:
+ ----- Method: GdbARMAlien>>nopOpcode (in category 'opcodes') -----
+ nopOpcode
+ "mov r0, r0"
+ ^ 16rE1A01001!

Item was added:
+ ----- Method: GdbARMAlien>>pc (in category 'accessing') -----
+ pc
+ ^self unsignedLongAt: 73!

Item was added:
+ ----- Method: GdbARMAlien>>pc: (in category 'accessing') -----
+ pc: anUnsignedInteger
+
+ ^self unsignedLongAt: 73 put: anUnsignedInteger!

Item was added:
+ ----- 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 primitiveFailed!

Item was added:
+ ----- Method: GdbARMAlien>>primitiveErrorAndLog (in category 'primitives') -----
+ primitiveErrorAndLog
+ "Answer an array of the current error code and log contents"
+ <primitive: 'primitiveErrorAndLog' module: 'GdbARMPlugin'>
+ ^self primitiveFailed!

Item was added:
+ ----- Method: GdbARMAlien>>primitiveResetCPU (in category 'primitives') -----
+ primitiveResetCPU
+ "Reset the receiver to registers all zero, and protected 32-bit mode."
+ <primitive: 'primitiveResetCPU' module: 'GdbARMPlugin'>
+ ^self reportPrimitiveFailure!

Item was added:
+ ----- Method: GdbARMAlien>>primitiveRunInMemory:minimumAddress:readOnlyBelow: (in category 'primitives') -----
+ primitiveRunInMemory: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "<Integer>" readOnlyBelow: minimumWritableAddress "<Integer>"
+ "Run the receiver using the argument as the store.  Origin the argument at 0. i.e. the first byte of the
+ memoryArray is address 0.  Make addresses below minimumAddress illegal.  Convert out-of-range
+ call, jump and memory read/writes into register instructions into ProcessorSimulationTrap signals."
+ <primitive: 'primitiveRunInMemoryMinimumAddressReadWrite' module: 'GdbARMPlugin' error: ec>
+ ^ec == #'inappropriate operation'
+ ifTrue: [self handleExecutionPrimitiveFailureIn: memoryArray
+ minimumAddress: minimumAddress
+ readOnlyBelow: minimumWritableAddress]
+ ifFalse: [self reportPrimitiveFailure]
+
+ "self printRegistersOn: Transcript"!

Item was added:
+ ----- Method: GdbARMAlien>>primitiveSingleStepInMemory:minimumAddress:readOnlyBelow: (in category 'primitives') -----
+ primitiveSingleStepInMemory: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "<Integer>" readOnlyBelow: minimumWritableAddress "<Integer>"
+ "Single-step the receiver using the argument as the store.  Origin the argument at 0. i.e. the first byte of the
+ memoryArray is address 0.  Make addresses below minimumAddress illegal.  Convert out-of-range
+ call, jump and memory read/writes into register instructions into ProcessorSimulationTrap signals."
+ <primitive: 'primitiveSingleStepInMemoryMinimumAddressReadWrite' module: 'GdbARMPlugin' error: ec>
+ ^ec == #'inappropriate operation'
+ ifTrue: [self handleExecutionPrimitiveFailureIn: memoryArray
+ minimumAddress: minimumAddress
+ readOnlyBelow: minimumWritableAddress]
+ ifFalse: [self reportPrimitiveFailure]!

Item was added:
+ ----- Method: GdbARMAlien>>printRegisterState:on: (in category 'printing') -----
+ printRegisterState: registerStateVector on: aStream
+ | rsvs fields|
+ aStream ensureCr.
+ rsvs := registerStateVector readStream.
+ fields := #( r0 r1 r2 r3 r4 r5 r6 cr r7 r8 r9 r10 r11 r12 cr sp lr pc eflags cr).
+ fields withIndexDo:
+ [:sym :index| | val |
+ sym = #cr
+ ifTrue: [aStream cr]
+ ifFalse:
+ [(val := rsvs next) isNil ifTrue: [^self].
+ aStream nextPutAll: sym; nextPut: $:; space.
+ val printOn: aStream base: 16 length: 8 padded: true.
+ #eflags == sym
+ ifTrue:
+ [aStream space.
+ "'FIVCZN'"'--VCZN' withIndexDo:
+ [:flag :bitIndex|
+ flag ~= $- ifTrue:
+ [aStream nextPut: flag; nextPutAll: 'F='; print: (val bitAnd: 1 << (bitIndex - 1)) >> (bitIndex - 1); space]]]
+ ifFalse:
+ [val > 16 ifTrue:
+ [aStream space; nextPut: $(.
+ val printOn: aStream base: 10 length: 1 padded: false.
+ aStream nextPut: $)]].
+ (fields at: index + 1) ~~ #cr ifTrue:
+ [aStream tab]]]!

Item was added:
+ ----- Method: GdbARMAlien>>r0 (in category 'accessing') -----
+ r0
+ ^self unsignedLongAt: 13!

Item was added:
+ ----- Method: GdbARMAlien>>r0: (in category 'accessing') -----
+ r0: anUnsignedInteger
+
+ ^self unsignedLongAt: 13 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r1 (in category 'accessing') -----
+ r1
+ ^self unsignedLongAt: 17!

Item was added:
+ ----- Method: GdbARMAlien>>r10 (in category 'accessing') -----
+ r10
+ ^self unsignedLongAt: 53!

Item was added:
+ ----- Method: GdbARMAlien>>r10: (in category 'accessing') -----
+ r10: anUnsignedInteger
+
+ ^self unsignedLongAt: 53 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r11 (in category 'accessing') -----
+ r11
+ ^self unsignedLongAt: 57!

Item was added:
+ ----- Method: GdbARMAlien>>r11: (in category 'accessing') -----
+ r11: anUnsignedInteger
+
+ ^self unsignedLongAt: 57 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r12 (in category 'accessing') -----
+ r12
+ ^self unsignedLongAt: 61!

Item was added:
+ ----- Method: GdbARMAlien>>r12: (in category 'accessing') -----
+ r12: anUnsignedInteger
+
+ ^self unsignedLongAt: 61 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r1: (in category 'accessing') -----
+ r1: anUnsignedInteger
+
+ ^self unsignedLongAt: 17 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r2 (in category 'accessing') -----
+ r2
+ ^self unsignedLongAt: 21!

Item was added:
+ ----- Method: GdbARMAlien>>r2: (in category 'accessing') -----
+ r2: anUnsignedInteger
+
+ ^self unsignedLongAt: 21 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r3 (in category 'accessing') -----
+ r3
+ ^self unsignedLongAt: 25!

Item was added:
+ ----- Method: GdbARMAlien>>r3: (in category 'accessing') -----
+ r3: anUnsignedInteger
+
+ ^self unsignedLongAt: 25 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r4 (in category 'accessing') -----
+ r4
+ ^self unsignedLongAt: 29!

Item was added:
+ ----- Method: GdbARMAlien>>r4: (in category 'accessing') -----
+ r4: anUnsignedInteger
+
+ ^self unsignedLongAt: 29 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r5 (in category 'accessing') -----
+ r5
+ ^self unsignedLongAt: 33!

Item was added:
+ ----- Method: GdbARMAlien>>r5: (in category 'accessing') -----
+ r5: anUnsignedInteger
+
+ ^self unsignedLongAt: 33 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r6 (in category 'accessing') -----
+ r6
+ ^self unsignedLongAt: 37!

Item was added:
+ ----- Method: GdbARMAlien>>r6: (in category 'accessing') -----
+ r6: anUnsignedInteger
+
+ ^self unsignedLongAt: 37 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r7 (in category 'accessing') -----
+ r7
+ ^self unsignedLongAt: 41!

Item was added:
+ ----- Method: GdbARMAlien>>r7: (in category 'accessing') -----
+ r7: anUnsignedInteger
+
+ ^self unsignedLongAt: 41 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r8 (in category 'accessing') -----
+ r8
+ ^self unsignedLongAt: 45!

Item was added:
+ ----- Method: GdbARMAlien>>r8: (in category 'accessing') -----
+ r8: anUnsignedInteger
+
+ ^self unsignedLongAt: 45 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r9 (in category 'accessing') -----
+ r9
+ ^self unsignedLongAt: 49!

Item was added:
+ ----- Method: GdbARMAlien>>r9: (in category 'accessing') -----
+ r9: anUnsignedInteger
+
+ ^self unsignedLongAt: 49 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>registerState (in category 'accessing-abstract') -----
+ registerState
+ ^{ self r0. self r1. self r2. self r3. self r4. self r5. self r6. self r7.
+ self r8. self r0. self r10. self r11. self r12. self sp. self lr. self pc. self eflags }!

Item was added:
+ ----- Method: GdbARMAlien>>reset (in category 'accessing') -----
+ reset
+ self primitiveResetCPU!

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

Item was added:
+ ----- Method: GdbARMAlien>>sflag (in category 'accessing') -----
+ sflag
+ ^self unsignedLongAt: 589!

Item was added:
+ ----- Method: GdbARMAlien>>sp (in category 'accessing') -----
+ sp
+ ^self unsignedLongAt: 65!

Item was added:
+ ----- Method: GdbARMAlien>>sp: (in category 'accessing') -----
+ sp: anUnsignedInteger
+
+ ^self unsignedLongAt: 65 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>vflag (in category 'accessing') -----
+ vflag
+ ^self unsignedLongAt: 581!

Item was added:
+ ----- Method: GdbARMAlien>>zflag (in category 'accessing') -----
+ zflag
+ ^self unsignedLongAt: 573!

Item was added:
+ TestCase subclass: #GdbARMAlienTests
+ instanceVariableNames: 'processor'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'Cog-Processors-Tests'!

Item was added:
+ ----- 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 added:
+ ----- Method: GdbARMAlienTests>>nfib (in category 'accessing') -----
+ nfib
+ "long fib(long n) { return n <= 1 ? 1 : fib(n-1) + fib(n-2) + 1; }
+ as compiled by arm-elf-gnuabi-gcc fib.c -c -marm
+ also, the jumps are changed by hand."
+ "| bat nfib ip |
+ bat := GdbARMAlienTests new.
+ nfib := bat nfib asWordArray.
+ ip := 0.
+ 23 timesRepeat:
+ [bat processor disassembleInstructionAt: ip In: nfib into:
+ [:da :len|
+ Transcript nextPutAll: da; cr; flush.
+ ip := ip + len]]"
+ ^#("00000000 <fib>:
+   0:" 16re92d4810 "push {r4, fp, lr} fp = r11, sp is changed in this command
+   4:" 16re28db008 "add fp, sp, #8 now, the frame pointer is changed
+   8:" 16re24dd00c "sub sp, sp, #12
+   c:" 16re50b0010 "str r0, [fp, #-16]
+  10:" 16re51b3010 "ldr r3, [fp, #-16] r3 <- [fp-16] <- r0
+  14:" 16re3530001 "cmp r3, #1
+  18:" 16rda00000c "ble 50 <fib+0x50>
+  1c:" 16re51b3010 "ldr r3, [fp, #-16]
+  20:" 16re2433001 "sub r3, r3, #1
+  24:" 16re1a00003 "mov r0, r3
+  28:" 16rebfffff4 "bl 0 <fib>
+  2c:" 16re1a04000 "mov r4, r0
+  30:" 16re51b3010 "ldr r3, [fp, #-16]
+  34:" 16re2433002 "sub r3, r3, #2
+  38:" 16re1a00003 "mov r0, r3
+  3c:" 16rebffffef "bl 0 <fib>
+  40:" 16re1a03000 "mov r3, r0
+  44:" 16re0843003 "add r3, r4, r3
+  48:" 16re2833001 "add r3, r3, #1
+  4c:" 16rea000000 "b 54 <fib+0x54>
+  50:" 16re3a03001 "mov r3, #1
+  54:" 16re1a00003 "mov r0, r3
+  58:" 16re24bd008 "sub sp, fp, #8
+  5c:" 16re8bd8810 "pop {r4, fp, pc}")!

Item was added:
+ ----- Method: GdbARMAlienTests>>processor (in category 'accessing') -----
+ processor
+ processor ifNil:
+ [processor := GdbARMAlien new].
+ ^processor!

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

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

Item was added:
+ ----- 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 := 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 added:
+ ----- Method: GdbARMAlienTests>>singleStepNFib:disassemble:printRegisters: (in category 'execution') -----
+ singleStepNFib: n disassemble: disassemble printRegisters: printRegisters
+ "Run nfib wth the argument. Answer the result."
+ "self new runNFib: 5 disassemble: true printRegisters: true"
+ | memory |
+ 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: self nfib size * 4;  "return address"
+ pc: 0;
+ sp: (memory size * 4 - 12). "Room for return address, frame pointer and r4"
+ printRegisters ifTrue:
+ [self processor printRegistersOn: Transcript.
+ Transcript cr; flush].
+ [disassemble ifTrue:
+ [Transcript nextPutAll: (self processor disassembleNextInstructionIn: memory); cr; flush].
+ self processor singleStepIn: memory readExecuteOnlyBelow: memory size * 4 / 2.
+ printRegisters ifTrue:
+ [self processor printRegistersOn: Transcript.
+ Transcript cr; flush].
+ "stop, once we leave the nfib code and step through the nops after that."
+ self processor pc < (self nfib size * 4)] whileTrue.
+ ^self processor r0!

Item was added:
+ ----- 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 messageText = 'Error 0: Illegal Instruction fetch address (0x00000400).'].!

Item was added:
+ ----- Method: GdbARMAlienTests>>testDisassembling (in category 'tests') -----
+ testDisassembling
+
+ | memory result |
+ memory := WordArray new: 2.
+ memory at: 1 put: 16rEF200000.
+ result := self processor
+ disassembleInstructionAt: 0
+ In: memory
+ into: [:str :len |
+ self
+ assert: len = 4;
+ assert: str = 'svc 0x00200000'].!

Item was added:
+ ----- Method: GdbARMAlienTests>>testExecutionTrap (in category 'tests') -----
+ testExecutionTrap
+ "Execute a run of nops.  test executing beyond the executable limit is trapped."
+ "self new testExecutionTrap"
+ | memory |
+ "The address is out of range of memory every which way (whether relative or absolute and whether big-endian or little."
+ memory := (Bitmap new: 1024 * 2 withAll: self processor nopOpcode) asByteArray.
+ self processor
+ pc: 0;
+ sp: (memory size - 4). "Room for return address"
+ self should: [self processor runInMemory: memory minimumAddress: 0 readOnlyBelow: memory size / 2]
+ raise: Error
+ withExceptionDo:
+ [:err|
+ self assert: self processor pc = (memory size / 2).
+ self assert: ('Error 0: Illegal Instruction fetch address (0x00001000).' match: err messageText)].
+ self processor pc: 0.
+ self should: [[self processor singleStepIn: memory minimumAddress: 0 readOnlyBelow: memory size / 2] repeat]
+ raise: Error
+ withExceptionDo:
+ [:err|
+ self assert: self processor pc = (memory size / 2).
+ self assert: ('Error 0: Illegal Instruction fetch address (0x00001000).' match: err messageText)]!

Item was added:
+ ----- Method: GdbARMAlienTests>>testFlags (in category 'tests') -----
+ testFlags
+ "self new testFlags"
+ | memory |
+ memory := Bitmap new: 3.
+ memory longAt: 1 put: 16rE3A03001 bigEndian: false. "MOV r3, #1"
+ memory longAt: 5 put: 16rE3530001 bigEndian: false. "CMP r3, #1"
+ memory := memory asByteArray.
+ self processor
+ disassembleInstructionAt: 0
+ In: memory
+ into: [:str :len |
+ self
+ assert: len = 4;
+ assert: str = 'mov r3, #1'].
+ self processor
+ disassembleInstructionAt: 4
+ In: memory
+ into: [:str :len |
+ self
+ assert: len = 4;
+ assert: str = 'cmp r3, #1'].
+ self processor
+ pc: 0;
+ singleStepIn: memory;
+ singleStepIn: memory.
+ self
+ assert: self processor pc = 16r8;
+ assert: self processor r3 = 1;
+ assert: self processor zflag = 1;
+ assert: self processor cflag = 1;
+ assert: self processor vflag = 0;
+ assert: self processor nflag = 0.
+ self processor reset.
+ self assert: self processor eflags = 3. "IFFlags are both set."!

Item was added:
+ ----- Method: GdbARMAlienTests>>testMOVSD (in category 'tests') -----
+ testMOVSD
+ "Test MOVSD indirecting through edx."
+ "self new testMOVSD"
+ self processor
+ edx: 0;
+ eip: 0;
+ singleStepIn: {16rF2. 16r0F. 16r10. 16r42. 16r04. 16r90. 16r01. 16r02. 16r03. 16r04. 16r05. 16r06} asByteArray "movsd %ds:0x4(%edx), %xmm0;nop;garbage".
+ self assert: self processor eip = 5.
+ self assert: self processor xmm0low = 16r0605040302019004!

Item was added:
+ ----- Method: GdbARMAlienTests>>testNfib1 (in category 'tests') -----
+ testNfib1
+ "self new testNfib1"
+ self should: [self runNFib: 1 disassemble: false printRegisters: true]
+ raise: Error
+ withExceptionDo:
+ [:err| self assert: err messageText = 'Error 0: Illegal Instruction fetch address (0x00001000).'].
+ self deny: (self processor pc between: 0 and: self nfib size).
+ self assert: self processor r0 = 1 benchFib!

Item was added:
+ ----- Method: GdbARMAlienTests>>testNfib16 (in category 'tests') -----
+ testNfib16
+ "self new testNfib16"
+ self should: [self runNFib: 16 disassemble: false printRegisters: false]
+ raise: Error.
+ self deny: (self processor pc between: 0 and: self nfib size).
+ self assert: self processor r0 = 16 benchFib!

Item was added:
+ ----- Method: GdbARMAlienTests>>testNfib2 (in category 'tests') -----
+ testNfib2
+ "self new testNfib2"
+ self should: [self runNFib: 2 disassemble: false printRegisters: false]
+ raise: Error.
+ self deny: (self processor pc between: 0 and: self nfib size).
+ self assert: self processor r0 = 2 benchFib!

Item was added:
+ ----- Method: GdbARMAlienTests>>testNfib4 (in category 'tests') -----
+ testNfib4
+ "self new testNfib4"
+ self should: [self runNFib: 4 disassemble: false printRegisters: false]
+ raise: Error.
+ self deny: (self processor pc between: 0 and: self nfib size).
+ self assert: self processor r0 = 4 benchFib!

Item was added:
+ ----- Method: GdbARMAlienTests>>testResetCPU (in category 'tests') -----
+ testResetCPU
+ "self new testResetCPU"
+ self registerSetters do:
+ [:setter|
+ self processor perform: setter with: 16r55555555].
+ self registerGetters do:
+ [:getter|
+ self assert: 16r55555555 = (self processor perform: getter)].
+ self processor reset.
+ self registerGetters do:
+ [:getter|
+ self assert: 0 = (self processor perform: getter)]!

Item was added:
+ ----- Method: GdbARMAlienTests>>testStepNfib1 (in category 'tests') -----
+ testStepNfib1
+ "self new testStepNfib1"
+ self singleStepNFib: 1 disassemble: false printRegisters: false.
+ self assert: self processor pc = (self nfib asWordArray size * 4).
+ self assert: self processor r0 = 1 benchFib!

Item was added:
+ ----- Method: GdbARMAlienTests>>testStepNfib2 (in category 'tests') -----
+ testStepNfib2
+ "self new testStepNfib2"
+ self singleStepNFib: 2 disassemble: false printRegisters: false.
+ self assert: self processor pc = (self nfib size * 4).
+ self assert: self processor r0 = 2 benchFib!

Item was added:
+ ----- Method: GdbARMAlienTests>>testStepNfib4 (in category 'tests') -----
+ testStepNfib4
+ "self new testStepNfib4"
+ self singleStepNFib: 4 disassemble: false printRegisters: false.
+ self assert: self processor pc = (self nfib size * 4).
+ self assert: self processor r0 = 4 benchFib!

Item was added:
+ SmartSyntaxInterpreterPlugin subclass: #GdbARMPlugin
+ instanceVariableNames: 'prevInterruptCheckChain'
+ classVariableNames: ''
+ poolDictionaries: 'VMBasicConstants'
+ category: 'Cog-ProcessorPlugins'!
+
+ !GdbARMPlugin commentStamp: '<historical>' prior: 0!
+ I provide access to the ARMulator ARM emulator and the libopcodes ARM disassembler.!

Item was added:
+ ----- Method: GdbARMPlugin class>>declareCVarsIn: (in category 'translation') -----
+ declareCVarsIn: aCCodeGenerator
+ "prevInterruptCheckChain lives in sqGdbARMPlugin.c"
+ super declareCVarsIn: aCCodeGenerator.
+ aCCodeGenerator removeVariable: 'prevInterruptCheckChain'!

Item was added:
+ ----- Method: GdbARMPlugin class>>hasHeaderFile (in category 'translation') -----
+ hasHeaderFile
+ "We need a header to declare newcpu and pull in bochs.h & cpu.h"
+ ^true!

Item was added:
+ ----- Method: GdbARMPlugin>>forceStopOnInterrupt (in category 'interruption') -----
+ forceStopOnInterrupt
+ interpreterProxy getInterruptPending ifTrue:
+ [self forceStopRunning]!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveDisassembleAt:InMemory: (in category 'primitives') -----
+ "cpuAlien <GdbARMAlien>" primitiveDisassembleAt: address "<Integer>" InMemory: memory "<Bitmap|ByteArray|WordArray>"
+ "Return an Array of the instruction length and its decompilation as a string for the instruction at address in memory."
+ | cpuAlien cpu instrLenOrErr resultObj log logLen logObj logObjData |
+ <var: #cpu type: #'void *'>
+ cpuAlien := self primitive: #primitiveDisassembleAtInMemory
+ parameters: #(Unsigned WordsOrBytes)
+ receiver: #Oop.
+ (cpu := self startOfData: cpuAlien) = 0 ifTrue:
+ [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].
+ instrLenOrErr := self disassembleFor: cpu
+ At: address
+ In: memory
+ Size: (interpreterProxy byteSizeOf: memory cPtrAsOop).
+ instrLenOrErr < 0 ifTrue:
+ [^interpreterProxy primitiveFailFor: PrimErrInappropriate].
+ log := self getlog: (self cCode: [self addressOf: logLen] inSmalltalk: [logLen := 0]).
+ resultObj := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: 2.
+ resultObj = 0 ifTrue:
+ [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+
+ "Easier keeping the damn thing on the stack than using pushRemappableOop:/popRemappableOop.
+ Where is topRemappableOop when you need it?"
+ interpreterProxy pushRemappableOop: resultObj.
+ logObj := interpreterProxy
+ instantiateClass: interpreterProxy classString
+ indexableSize: logLen.
+ interpreterProxy failed ifTrue:
+ [interpreterProxy popRemappableOop.
+ ^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+ logObjData := interpreterProxy arrayValueOf: logObj.
+ self cCode: 'memcpy(logObjData, log, logLen)' inSmalltalk: [logObjData. log].
+ resultObj := interpreterProxy popRemappableOop.
+ interpreterProxy
+ storePointer: 0
+ ofObject: resultObj
+ withValue: (interpreterProxy integerObjectOf: instrLenOrErr).
+ interpreterProxy storePointer: 1 ofObject: resultObj withValue: logObj.
+
+ ^resultObj!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveErrorAndLog (in category 'primitives') -----
+ primitiveErrorAndLog
+ | log logLen resultObj logObj logObjData |
+ <var: #log type: #'char *'>
+ <var: #logObjData type: #'char *'>
+ self primitive: #primitiveErrorAndLog parameters: #().
+
+ log := self getlog: (self cCode: [self addressOf: logLen] inSmalltalk: [logLen := 0]).
+ resultObj := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: 2.
+ resultObj = 0 ifTrue:
+ [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+
+ interpreterProxy
+ storePointer: 0
+ ofObject: resultObj
+ withValue: (interpreterProxy integerObjectOf: self errorAcorn).
+
+ logLen > 0 ifTrue:
+ [interpreterProxy pushRemappableOop: resultObj.
+ logObj := interpreterProxy
+ instantiateClass: interpreterProxy classString
+ indexableSize: logLen.
+ interpreterProxy failed ifTrue:
+ [interpreterProxy popRemappableOop.
+ ^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+
+ resultObj := interpreterProxy popRemappableOop.
+ logObjData := interpreterProxy arrayValueOf: logObj.
+ self cCode: 'memcpy(logObjData, log, logLen)' inSmalltalk: [logObjData. log].
+ interpreterProxy storePointer: 1 ofObject: resultObj withValue: logObj].
+ interpreterProxy pop: 1 thenPush: resultObj!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveFlushICacheFrom:To: (in category 'primitives') -----
+ "cpuAlien <GdbARMAlien>" primitiveFlushICacheFrom: startAddress "<Integer>" To: endAddress "<Integer>"
+ "Flush the icache in the requested range"
+ | cpuAlien cpu |
+ <var: #cpu type: 'void *'>
+ cpuAlien := self primitive: #primitiveFlushICacheFromTo
+ parameters: #(Unsigned Unsigned)
+ receiver: #Oop.
+ (cpu := self startOfData: cpuAlien) = 0 ifTrue:
+ [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].
+ self flushICache: cpu From: startAddress To: endAddress!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveNewCPU (in category 'primitives') -----
+ primitiveNewCPU
+ | cpu |
+ <var: #cpu type: 'void *'>
+ self primitive: #primitiveNewCPU parameters: #().
+
+ cpu := self cCode: 'newCPU()' inSmalltalk: [0].
+ cpu = 0 ifTrue:
+ [^interpreterProxy primitiveFail].
+ interpreterProxy
+ pop: 1
+ thenPush: (interpreterProxy positive32BitIntegerFor:
+ (self cCoerceSimple: cpu
+ to: 'unsigned long'))!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveResetCPU (in category 'primitives') -----
+ primitiveResetCPU
+ | cpuAlien cpu maybeErr |
+ <var: #cpu type: 'void *'>
+ cpuAlien := self primitive: #primitiveResetCPU parameters: #() receiver: #Oop.
+ (cpu := self startOfData: cpuAlien) = 0 ifTrue:
+ [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].
+ maybeErr := self resetCPU: cpu.
+ maybeErr ~= 0 ifTrue:
+ [^interpreterProxy primitiveFailFor: PrimErrInappropriate].
+ ^cpuAlien!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveRunInMemory:minimumAddress:readOnlyBelow: (in category 'primitives') -----
+ "cpuAlien <GdbARMAlien>" primitiveRunInMemory: memory "<Bitmap|ByteArray|WordArray>" minimumAddress: minAddress "<Integer>" readOnlyBelow: minWriteMaxExecAddress "<Integer>"
+ "Run the cpu using the first argument as the memory and the following arguments defining valid addresses, running until it halts or hits an exception."
+ | cpuAlien cpu maybeErr |
+ <var: #cpu type: #'void *'>
+ cpuAlien := self primitive: #primitiveRunInMemoryMinimumAddressReadWrite
+ parameters: #(WordsOrBytes Unsigned Unsigned)
+ receiver: #Oop.
+ (cpu := self startOfData: cpuAlien) = 0 ifTrue:
+ [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].
+ prevInterruptCheckChain := interpreterProxy setInterruptCheckChain: #forceStopOnInterrupt asSymbol.
+ prevInterruptCheckChain = #forceStopOnInterrupt asSymbol ifTrue:
+ [prevInterruptCheckChain = 0].
+ maybeErr := self runCPU: cpu
+ In: memory
+ Size: (interpreterProxy byteSizeOf: memory cPtrAsOop)
+ MinAddressRead: minAddress
+ Write: minWriteMaxExecAddress.
+ interpreterProxy setInterruptCheckChain: prevInterruptCheckChain.
+ maybeErr ~= 0 ifTrue:
+ [^interpreterProxy primitiveFailFor: PrimErrInappropriate].
+ ^cpuAlien!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveSingleStepInMemory:minimumAddress:readOnlyBelow: (in category 'primitives') -----
+ "cpuAlien <GdbARMAlien>" primitiveSingleStepInMemory: memory "<Bitmap|ByteArray|WordArray>" minimumAddress: minAddress "<Integer>"  readOnlyBelow: minWriteMaxExecAddress "<Integer>"
+ "Single-step the cpu using the first argument as the memory and the following arguments defining valid addresses."
+ | cpuAlien cpu maybeErr |
+ <var: #cpu type: #'void *'>
+ cpuAlien := self primitive: #primitiveSingleStepInMemoryMinimumAddressReadWrite
+ parameters: #(WordsOrBytes Unsigned Unsigned)
+ receiver: #Oop.
+ (cpu := self startOfData: cpuAlien) = 0 ifTrue:
+ [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].
+ maybeErr := self singleStepCPU: cpu
+ In: memory
+ Size: (interpreterProxy byteSizeOf: memory cPtrAsOop)
+ MinAddressRead: minAddress
+ Write: minWriteMaxExecAddress.
+ maybeErr ~= 0 ifTrue:
+ [^interpreterProxy primitiveFailFor: PrimErrInappropriate].
+ ^cpuAlien!

Item was added:
+ ----- Method: GdbARMPlugin>>sizeField: (in category 'alien support') -----
+ sizeField: rcvr
+ "Answer the first field of rcvr which is assumed to be an Alien of at least 8 bytes"
+ <inline: true>
+ ^self longAt: rcvr + BaseHeaderSize!

Item was added:
+ ----- Method: GdbARMPlugin>>startOfData: (in category 'alien support') -----
+ startOfData: rcvr "<Alien oop> ^<Integer>"
+ "Answer the start of rcvr's data.  For direct aliens this is the address of
+ the second field.  For indirect and pointer aliens it is what the second field points to."
+ <inline: true>
+ ^(self sizeField: rcvr) > 0
+ ifTrue: [rcvr + BaseHeaderSize + BytesPerOop]
+ ifFalse: [self longAt: rcvr + BaseHeaderSize + BytesPerOop]!

Reply | Threaded
Open this post in threaded view
|

Re: VM Maker: Cog-lw.48.mcz

Eliot Miranda-2
 
Congratulations are due to Lars Wassermann, the GSoC student on the ARM Jitter for Squeak VM project, who has got as far as implementing a plugin for an ARM simulator that passes all its tests and can evaluate fibonacci.  Lars is making great progress.

e.g.

nfib
"long fib(long n) { return n <= 1 ? 1 : fib(n-1) + fib(n-2) + 1; }
as compiled by arm-elf-gnuabi-gcc fib.c -c -marm
also, the jumps are changed by hand."
"| bat nfib ip |
bat := GdbARMAlienTests new.
nfib := bat nfib asWordArray.
ip := 0.
23 timesRepeat:
[bat processor disassembleInstructionAt: ip In: nfib into:
[:da :len|
Transcript nextPutAll: da; cr; flush.
ip := ip + len]]"
^#("00000000 <fib>:
  0:" 16re92d4810 "push {r4, fp, lr} fp = r11, sp is changed in this command
  4:" 16re28db008 "add fp, sp, #8 now, the frame pointer is changed
  8:" 16re24dd00c "sub sp, sp, #12
  c:" 16re50b0010 "str r0, [fp, #-16]
 10:" 16re51b3010 "ldr r3, [fp, #-16] r3 <- [fp-16] <- r0
 14:" 16re3530001 "cmp r3, #1
 18:" 16rda00000c "ble 50 <fib+0x50>
 1c:" 16re51b3010 "ldr r3, [fp, #-16]
 20:" 16re2433001 "sub r3, r3, #1
 24:" 16re1a00003 "mov r0, r3
 28:" 16rebfffff4 "bl 0 <fib>
 2c:" 16re1a04000 "mov r4, r0
 30:" 16re51b3010 "ldr r3, [fp, #-16]
 34:" 16re2433002 "sub r3, r3, #2
 38:" 16re1a00003 "mov r0, r3
 3c:" 16rebffffef "bl 0 <fib>
 40:" 16re1a03000 "mov r3, r0
 44:" 16re0843003 "add r3, r4, r3
 48:" 16re2833001 "add r3, r3, #1
 4c:" 16rea000000 "b 54 <fib+0x54>
 50:" 16re3a03001 "mov r3, #1
 54:" 16re1a00003 "mov r0, r3
 58:" 16re24bd008 "sub sp, fp, #8
 5c:" 16re8bd8810 "pop {r4, fp, pc}")

On Wed, Jul 11, 2012 at 12:47 PM, <[hidden email]> wrote:

Eliot Miranda uploaded a new version of Cog to project VM Maker:
http://source.squeak.org/VMMaker/Cog-lw.48.mcz

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

Name: Cog-lw.48
Author: lw
Time: 11 July 2012, 9:13:45.865 pm
UUID: 5ae3e465-4b2c-2349-9b88-77b8f53d5acd
Ancestors: Cog-eem.47

Added the GdbARMAlien, together with its tests and the plugin.
Additionally, introduced CogProcessorAlien as a common superclass for BochsIA32Alien and GdbARMAlien to increase code reusage.

The same might be possible for the Plugins (BochsIA32/GdbARM), because they are also identical.

=============== Diff against Cog-eem.47 ===============

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

  !BochsIA32Alien commentStamp: '<historical>' prior: 0!
  I am a wrapper around the Bochs C++ IA32 CPU emulator.  Note that currently I provide no access to the x87/mmx FPU state, only providing access to the SSE/xmm registers.

  Here is the configure script for the configuration this code assumes.  Offsets of fields will change with different configurations so they must agree.

  ----8<---- conf.COG ----8<----
  #!!/bin/sh

  # this sets up the compile for Cog.  Disable as much inessential stuff
  # as possible leaving only the cpu/fpu & memory interface

  set echo
  # CFLAGS="-pipe -O3 -fomit-frame-pointer -finline-functions -falign-loops=16 -falign-jumps=16 -falign-functions=16 -falign-labels=16 -falign-loops-max-skip=15 -falign-jumps-max-skip=15 -fprefetch-loop-arrays $CFLAGS"
  CFLAGS="-m32 $CFLAGS"
  CFLAGS="-Dlongjmp=_longjmp -Dsetjmp=_setjmp $CFLAGS"
  CFLAGS="-pipe -O3 -fomit-frame-pointer -finline-functions $CFLAGS"
  CFLAGS="-g $CFLAGS"
  CPATH="/sw/include"
  CPPFLAGS=""
  CXXFLAGS="$CFLAGS"
  LDFLAGS="-L/sw/lib"

  export CFLAGS
  export CPATH
  export CPPFLAGS
  export CXXFLAGS
  export LDFLAGS

  ./configure --enable-Cog \
        --enable-cpu-level=6 \
        --enable-sse=2 \
        --enable-assert-checks \
        --with-nogui \
                --disable-x86-64 \
                --disable-pae \
                --disable-large-pages \
                --disable-global-pages \
                --disable-mtrr \
                --disable-sb16 \
                --disable-ne2000 \
                --disable-pci \
                --disable-acpi \
                --disable-apic \
                --disable-clgd54xx \
                --disable-usb \
                --disable-plugins \
        ${CONFIGURE_ARGS}

  # apic == Advanced programmable Interrupt Controller
  # acpi == Advanced Configuration and Power Interface
  # pci == Peripheral Component Interconnect local bus
  # clgd54xx == Cirrus Logic GD54xx video card
  ----8<---- conf.COG ----8<----!

Item was removed:
- ----- Method: BochsIA32Alien>>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: string; cr; flush.
-               address := address + size]
-                       valueWithArguments: (self
-                                                                       primitiveDisassembleAt: address
-                                                                       inMemory: memory)]!

Item was removed:
- ----- Method: BochsIA32Alien>>disassembleInstructionAt:In: (in category 'disassembly') -----
- disassembleInstructionAt: pc In: memory
-       ^(self primitiveDisassembleAt: pc inMemory: memory) last!

Item was removed:
- ----- Method: BochsIA32Alien>>disassembleInstructionAt:In:into: (in category 'disassembly') -----
- disassembleInstructionAt: ip In: memory into: aBlock
-       | lenAndDi |
-       lenAndDi := self primitiveDisassembleAt: ip inMemory: memory.
-       ^aBlock value: lenAndDi last value: lenAndDi first!

Item was removed:
- ----- Method: BochsIA32Alien>>disassembleNextInstructionIn: (in category 'disassembly') -----
- disassembleNextInstructionIn: memory
-       ^(self primitiveDisassembleAt: self eip inMemory: memory) last!

Item was removed:
- ----- Method: BochsIA32Alien>>runInMemory: (in category 'execution') -----
- runInMemory: aMemory
-       | result |
-       result := self primitiveRunInMemory: aMemory minimumAddress: 0 readOnlyBelow: 0.
-       result ~~ self ifTrue:
-               [self error: 'eek!!']!

Item was removed:
- ----- Method: BochsIA32Alien>>runInMemory:minimumAddress:readOnlyBelow: (in category 'execution') -----
- runInMemory: aMemory minimumAddress: minimumAddress readOnlyBelow: minimumWritableAddress
-       | result |
-       result := self primitiveRunInMemory: aMemory
-                               minimumAddress: minimumAddress
-                               readOnlyBelow: minimumWritableAddress.
-       result ~~ self ifTrue:
-               [self error: 'eek!!']!

Item was removed:
- ----- Method: BochsIA32Alien>>runInMemory:readExecuteOnlyBelow: (in category 'execution') -----
- runInMemory: aMemory readExecuteOnlyBelow: minWriteMaxExecAddr
-       | result |
-       result := self primitiveRunInMemory: aMemory minimumAddress: 0 readOnlyBelow: minWriteMaxExecAddr.
-       result ~~ self ifTrue:
-               [self error: 'eek!!']!

Item was removed:
- ----- Method: BochsIA32Alien>>singleStepIn: (in category 'execution') -----
- singleStepIn: aMemory
-       | result |
-       result := self primitiveSingleStepInMemory: aMemory minimumAddress: 0 readOnlyBelow: aMemory size.
-       result ~~ self ifTrue:
-               [self error: 'eek!!']!

Item was removed:
- ----- Method: BochsIA32Alien>>singleStepIn:minimumAddress:readOnlyBelow: (in category 'execution') -----
- singleStepIn: aMemory minimumAddress: minimumAddress readOnlyBelow: minimumWritableAddress
-       | result |
-       result := self primitiveSingleStepInMemory: aMemory
-                               minimumAddress: minimumAddress
-                               readOnlyBelow: minimumWritableAddress.
-       result ~~ self ifTrue:
-               [self error: 'eek!!']!

Item was removed:
- ----- Method: BochsIA32Alien>>singleStepIn:readExecuteOnlyBelow: (in category 'execution') -----
- singleStepIn: aMemory readExecuteOnlyBelow: minWriteMaxExecAddr
-       | result |
-       result := self primitiveSingleStepInMemory: aMemory minimumAddress: 0 readOnlyBelow: minWriteMaxExecAddr.
-       result ~~ self ifTrue:
-               [self error: 'eek!!']!

Item was added:
+ Alien variableByteSubclass: #CogProcessorAlien
+       instanceVariableNames: ''
+       classVariableNames: ''
+       poolDictionaries: ''
+       category: 'Cog-Processors'!

Item was added:
+ ----- Method: CogProcessorAlien>>abstractInstructionCompilerClass (in category 'Cog API') -----
+ abstractInstructionCompilerClass
+       self subclassResponsibility!

Item was added:
+ ----- Method: CogProcessorAlien>>callOpcode (in category 'opcodes') -----
+ callOpcode
+       self subclassResponsibility.!

Item was added:
+ ----- 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: string; cr; flush.
+               address := address + size]
+                       valueWithArguments: (self
+                                                                       primitiveDisassembleAt: address
+                                                                       inMemory: memory)]!

Item was added:
+ ----- Method: CogProcessorAlien>>disassembleInstructionAt:In: (in category 'disassembly') -----
+ disassembleInstructionAt: pc In: memory
+       ^(self primitiveDisassembleAt: pc inMemory: memory) last!

Item was added:
+ ----- Method: CogProcessorAlien>>disassembleInstructionAt:In:into: (in category 'disassembly') -----
+ disassembleInstructionAt: ip In: memory into: aBlock
+       | lenAndDi |
+       lenAndDi := self primitiveDisassembleAt: ip inMemory: memory.
+       ^aBlock value: lenAndDi last value: lenAndDi first!

Item was added:
+ ----- Method: CogProcessorAlien>>disassembleNextInstructionIn: (in category 'disassembly') -----
+ disassembleNextInstructionIn: memory
+       ^(self primitiveDisassembleAt: self pc inMemory: memory) last!

Item was added:
+ ----- Method: CogProcessorAlien>>nopOpcode (in category 'opcodes') -----
+ nopOpcode
+       self subclassResponsibility.!

Item was added:
+ ----- Method: CogProcessorAlien>>printRegisterState:on: (in category 'printing') -----
+ printRegisterState: registerStateVector on: aStream
+
+       self subclassResponsibility.!

Item was added:
+ ----- Method: CogProcessorAlien>>printRegistersOn: (in category 'printing') -----
+ printRegistersOn: aStream
+       self printRegisterState: self registerState on: aStream.
+       aStream flush!

Item was added:
+ ----- Method: CogProcessorAlien>>reportPrimitiveFailure (in category 'error handling') -----
+ reportPrimitiveFailure
+       | errorAndLog |
+       errorAndLog := self primitiveErrorAndLog.
+       self error: 'Error ', errorAndLog first printString, (errorAndLog last ifNil: [''] ifNotNil: [:log| ': ', log])!

Item was added:
+ ----- Method: CogProcessorAlien>>runInMemory: (in category 'execution') -----
+ runInMemory: aMemory
+       | result |
+       result := self primitiveRunInMemory: aMemory minimumAddress: 0 readOnlyBelow: 0.
+       result ~~ self ifTrue:
+               [self error: 'eek!!']!

Item was added:
+ ----- Method: CogProcessorAlien>>runInMemory:minimumAddress:readOnlyBelow: (in category 'execution') -----
+ runInMemory: aMemory minimumAddress: minimumAddress readOnlyBelow: minimumWritableAddress
+       | result |
+       result := self primitiveRunInMemory: aMemory
+                               minimumAddress: minimumAddress
+                               readOnlyBelow: minimumWritableAddress.
+       result ~~ self ifTrue:
+               [self error: 'eek!!']!

Item was added:
+ ----- Method: CogProcessorAlien>>runInMemory:readExecuteOnlyBelow: (in category 'execution') -----
+ runInMemory: aMemory readExecuteOnlyBelow: minWriteMaxExecAddr
+       | result |
+       result := self primitiveRunInMemory: aMemory minimumAddress: 0 readOnlyBelow: minWriteMaxExecAddr.
+       result ~~ self ifTrue:
+               [self error: 'eek!!']!

Item was added:
+ ----- Method: CogProcessorAlien>>singleStepIn: (in category 'execution') -----
+ singleStepIn: aMemory
+       | result |
+       result := self primitiveSingleStepInMemory: aMemory minimumAddress: 0 readOnlyBelow: aMemory size.
+       result ~~ self ifTrue:
+               [self error: 'eek!!']!

Item was added:
+ ----- Method: CogProcessorAlien>>singleStepIn:minimumAddress:readOnlyBelow: (in category 'execution') -----
+ singleStepIn: aMemory minimumAddress: minimumAddress readOnlyBelow: minimumWritableAddress
+       | result |
+       result := self primitiveSingleStepInMemory: aMemory
+                               minimumAddress: minimumAddress
+                               readOnlyBelow: minimumWritableAddress.
+       result ~~ self ifTrue:
+               [self error: 'eek!!']!

Item was added:
+ ----- Method: CogProcessorAlien>>singleStepIn:readExecuteOnlyBelow: (in category 'execution') -----
+ singleStepIn: aMemory readExecuteOnlyBelow: minWriteMaxExecAddr
+       | result |
+       result := self primitiveSingleStepInMemory: aMemory minimumAddress: 0 readOnlyBelow: minWriteMaxExecAddr.
+       result ~~ self ifTrue:
+               [self error: 'eek!!']!

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

Item was added:
+ ----- Method: GdbARMAlien class>>dataSize (in category 'instance creation') -----
+ dataSize
+
+       ^1536!

Item was added:
+ ----- Method: GdbARMAlien class>>defaultIntegerBaseInDebugger (in category 'debugger') -----
+ defaultIntegerBaseInDebugger
+       ^16!

Item was added:
+ ----- Method: GdbARMAlien class>>new (in category 'instance creation') -----
+ new
+       ^(self atAddress: self primitiveNewCPU) reset!

Item was added:
+ ----- Method: GdbARMAlien class>>primitiveNewCPU (in category 'primitives') -----
+ primitiveNewCPU
+       "Answer the address of a new ARMulator C type ARMul_State instance."
+       <primitive: 'primitiveNewCPU' module: 'GdbARMPlugin'>
+       ^self primitiveFailed!

Item was added:
+ ----- Method: GdbARMAlien>>abstractInstructionCompilerClass (in category 'Cog API') -----
+ abstractInstructionCompilerClass
+       ^CogARMCompiler!

Item was added:
+ ----- Method: GdbARMAlien>>branchAndLinkOpcodeWithOffset: (in category 'opcodes') -----
+ branchAndLinkOpcodeWithOffset: aNumber
+
+       | offset |
+       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 added:
+ ----- 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>>cflag (in category 'accessing') -----
+ cflag
+       ^self unsignedLongAt: 577!

Item was added:
+ ----- Method: GdbARMAlien>>eflags (in category 'accessing') -----
+ eflags
+
+       ^ (((self nflag << 5 bitOr: self zflag << 4)
+                       bitOr: self cflag << 3)
+                               bitOr: self vflag << 2)
+                                       bitOr: self ifflags!

Item was added:
+ ----- 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 opcode |
+       ((pc := self pc) between: minimumAddress and: memoryArray byteSize - 1) ifTrue:
+               [opcode := memoryArray byteAt: pc + 1.
+               ^self
+                       perform: (OpcodeExceptionMap at: opcode + 1)
+                       with: pc
+                       with: memoryArray
+                       with: minimumWritableAddress]."
+       ^self reportPrimitiveFailure!

Item was added:
+ ----- Method: GdbARMAlien>>ifflags (in category 'accessing') -----
+ ifflags
+       ^self unsignedLongAt: 585!

Item was added:
+ ----- Method: GdbARMAlien>>integerRegisterState (in category 'accessing-abstract') -----
+ integerRegisterState
+       ^{      self r0. self r1. self r2. self r3. self r4. self r5. self r6. self r7. self r8.
+               self r9. self r10. self r11. self r12. self sp. self lr. self pc}!

Item was added:
+ ----- Method: GdbARMAlien>>lr (in category 'accessing') -----
+ lr
+       ^self unsignedLongAt: 69!

Item was added:
+ ----- Method: GdbARMAlien>>lr: (in category 'accessing') -----
+ lr: anUnsignedInteger
+
+       ^self unsignedLongAt: 69 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>nflag (in category 'accessing') -----
+ nflag
+       ^self unsignedLongAt: 569!

Item was added:
+ ----- Method: GdbARMAlien>>nopOpcode (in category 'opcodes') -----
+ nopOpcode
+       "mov r0, r0"
+       ^ 16rE1A01001!

Item was added:
+ ----- Method: GdbARMAlien>>pc (in category 'accessing') -----
+ pc
+       ^self unsignedLongAt: 73!

Item was added:
+ ----- Method: GdbARMAlien>>pc: (in category 'accessing') -----
+ pc: anUnsignedInteger
+
+       ^self unsignedLongAt: 73 put: anUnsignedInteger!

Item was added:
+ ----- 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 primitiveFailed!

Item was added:
+ ----- Method: GdbARMAlien>>primitiveErrorAndLog (in category 'primitives') -----
+ primitiveErrorAndLog
+       "Answer an array of the current error code and log contents"
+       <primitive: 'primitiveErrorAndLog' module: 'GdbARMPlugin'>
+       ^self primitiveFailed!

Item was added:
+ ----- Method: GdbARMAlien>>primitiveResetCPU (in category 'primitives') -----
+ primitiveResetCPU
+       "Reset the receiver to registers all zero, and protected 32-bit mode."
+       <primitive: 'primitiveResetCPU' module: 'GdbARMPlugin'>
+       ^self reportPrimitiveFailure!

Item was added:
+ ----- Method: GdbARMAlien>>primitiveRunInMemory:minimumAddress:readOnlyBelow: (in category 'primitives') -----
+ primitiveRunInMemory: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "<Integer>" readOnlyBelow: minimumWritableAddress "<Integer>"
+       "Run the receiver using the argument as the store.  Origin the argument at 0. i.e. the first byte of the
+        memoryArray is address 0.  Make addresses below minimumAddress illegal.  Convert out-of-range
+        call, jump and memory read/writes into register instructions into ProcessorSimulationTrap signals."
+       <primitive: 'primitiveRunInMemoryMinimumAddressReadWrite' module: 'GdbARMPlugin' error: ec>
+       ^ec == #'inappropriate operation'
+               ifTrue: [self handleExecutionPrimitiveFailureIn: memoryArray
+                                       minimumAddress: minimumAddress
+                                       readOnlyBelow: minimumWritableAddress]
+               ifFalse: [self reportPrimitiveFailure]
+
+       "self printRegistersOn: Transcript"!

Item was added:
+ ----- Method: GdbARMAlien>>primitiveSingleStepInMemory:minimumAddress:readOnlyBelow: (in category 'primitives') -----
+ primitiveSingleStepInMemory: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "<Integer>" readOnlyBelow: minimumWritableAddress "<Integer>"
+       "Single-step the receiver using the argument as the store.  Origin the argument at 0. i.e. the first byte of the
+        memoryArray is address 0.  Make addresses below minimumAddress illegal.  Convert out-of-range
+        call, jump and memory read/writes into register instructions into ProcessorSimulationTrap signals."
+       <primitive: 'primitiveSingleStepInMemoryMinimumAddressReadWrite' module: 'GdbARMPlugin' error: ec>
+       ^ec == #'inappropriate operation'
+               ifTrue: [self handleExecutionPrimitiveFailureIn: memoryArray
+                                       minimumAddress: minimumAddress
+                                       readOnlyBelow: minimumWritableAddress]
+               ifFalse: [self reportPrimitiveFailure]!

Item was added:
+ ----- Method: GdbARMAlien>>printRegisterState:on: (in category 'printing') -----
+ printRegisterState: registerStateVector on: aStream
+       | rsvs fields|
+       aStream ensureCr.
+       rsvs := registerStateVector readStream.
+       fields := #(    r0 r1 r2 r3 r4 r5 r6 cr r7 r8 r9 r10 r11 r12 cr sp lr pc eflags cr).
+       fields withIndexDo:
+               [:sym :index| | val |
+               sym = #cr
+                       ifTrue: [aStream cr]
+                       ifFalse:
+                               [(val := rsvs next) isNil ifTrue: [^self].
+                               aStream nextPutAll: sym; nextPut: $:; space.
+                               val printOn: aStream base: 16 length: 8 padded: true.
+                               #eflags == sym
+                                       ifTrue:
+                                               [aStream space.
+                                                "'FIVCZN'"'--VCZN' withIndexDo:
+                                                       [:flag :bitIndex|
+                                                       flag ~= $- ifTrue:
+                                                               [aStream nextPut: flag; nextPutAll: 'F='; print: (val bitAnd: 1 << (bitIndex - 1)) >> (bitIndex - 1); space]]]
+                                       ifFalse:
+                                               [val > 16 ifTrue:
+                                                       [aStream space; nextPut: $(.
+                                                        val printOn: aStream base: 10 length: 1 padded: false.
+                                                        aStream nextPut: $)]].
+                               (fields at: index + 1) ~~ #cr ifTrue:
+                                       [aStream tab]]]!

Item was added:
+ ----- Method: GdbARMAlien>>r0 (in category 'accessing') -----
+ r0
+       ^self unsignedLongAt: 13!

Item was added:
+ ----- Method: GdbARMAlien>>r0: (in category 'accessing') -----
+ r0: anUnsignedInteger
+
+       ^self unsignedLongAt: 13 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r1 (in category 'accessing') -----
+ r1
+       ^self unsignedLongAt: 17!

Item was added:
+ ----- Method: GdbARMAlien>>r10 (in category 'accessing') -----
+ r10
+       ^self unsignedLongAt: 53!

Item was added:
+ ----- Method: GdbARMAlien>>r10: (in category 'accessing') -----
+ r10: anUnsignedInteger
+
+       ^self unsignedLongAt: 53 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r11 (in category 'accessing') -----
+ r11
+       ^self unsignedLongAt: 57!

Item was added:
+ ----- Method: GdbARMAlien>>r11: (in category 'accessing') -----
+ r11: anUnsignedInteger
+
+       ^self unsignedLongAt: 57 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r12 (in category 'accessing') -----
+ r12
+       ^self unsignedLongAt: 61!

Item was added:
+ ----- Method: GdbARMAlien>>r12: (in category 'accessing') -----
+ r12: anUnsignedInteger
+
+       ^self unsignedLongAt: 61 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r1: (in category 'accessing') -----
+ r1: anUnsignedInteger
+
+       ^self unsignedLongAt: 17 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r2 (in category 'accessing') -----
+ r2
+       ^self unsignedLongAt: 21!

Item was added:
+ ----- Method: GdbARMAlien>>r2: (in category 'accessing') -----
+ r2: anUnsignedInteger
+
+       ^self unsignedLongAt: 21 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r3 (in category 'accessing') -----
+ r3
+       ^self unsignedLongAt: 25!

Item was added:
+ ----- Method: GdbARMAlien>>r3: (in category 'accessing') -----
+ r3: anUnsignedInteger
+
+       ^self unsignedLongAt: 25 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r4 (in category 'accessing') -----
+ r4
+       ^self unsignedLongAt: 29!

Item was added:
+ ----- Method: GdbARMAlien>>r4: (in category 'accessing') -----
+ r4: anUnsignedInteger
+
+       ^self unsignedLongAt: 29 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r5 (in category 'accessing') -----
+ r5
+       ^self unsignedLongAt: 33!

Item was added:
+ ----- Method: GdbARMAlien>>r5: (in category 'accessing') -----
+ r5: anUnsignedInteger
+
+       ^self unsignedLongAt: 33 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r6 (in category 'accessing') -----
+ r6
+       ^self unsignedLongAt: 37!

Item was added:
+ ----- Method: GdbARMAlien>>r6: (in category 'accessing') -----
+ r6: anUnsignedInteger
+
+       ^self unsignedLongAt: 37 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r7 (in category 'accessing') -----
+ r7
+       ^self unsignedLongAt: 41!

Item was added:
+ ----- Method: GdbARMAlien>>r7: (in category 'accessing') -----
+ r7: anUnsignedInteger
+
+       ^self unsignedLongAt: 41 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r8 (in category 'accessing') -----
+ r8
+       ^self unsignedLongAt: 45!

Item was added:
+ ----- Method: GdbARMAlien>>r8: (in category 'accessing') -----
+ r8: anUnsignedInteger
+
+       ^self unsignedLongAt: 45 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>r9 (in category 'accessing') -----
+ r9
+       ^self unsignedLongAt: 49!

Item was added:
+ ----- Method: GdbARMAlien>>r9: (in category 'accessing') -----
+ r9: anUnsignedInteger
+
+       ^self unsignedLongAt: 49 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>registerState (in category 'accessing-abstract') -----
+ registerState
+       ^{      self r0. self r1. self r2. self r3. self r4. self r5. self r6. self r7.
+               self r8. self r0. self r10. self r11. self r12. self sp. self lr. self pc. self eflags }!

Item was added:
+ ----- Method: GdbARMAlien>>reset (in category 'accessing') -----
+ reset
+       self primitiveResetCPU!

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

Item was added:
+ ----- Method: GdbARMAlien>>sflag (in category 'accessing') -----
+ sflag
+       ^self unsignedLongAt: 589!

Item was added:
+ ----- Method: GdbARMAlien>>sp (in category 'accessing') -----
+ sp
+       ^self unsignedLongAt: 65!

Item was added:
+ ----- Method: GdbARMAlien>>sp: (in category 'accessing') -----
+ sp: anUnsignedInteger
+
+       ^self unsignedLongAt: 65 put: anUnsignedInteger!

Item was added:
+ ----- Method: GdbARMAlien>>vflag (in category 'accessing') -----
+ vflag
+       ^self unsignedLongAt: 581!

Item was added:
+ ----- Method: GdbARMAlien>>zflag (in category 'accessing') -----
+ zflag
+       ^self unsignedLongAt: 573!

Item was added:
+ TestCase subclass: #GdbARMAlienTests
+       instanceVariableNames: 'processor'
+       classVariableNames: ''
+       poolDictionaries: ''
+       category: 'Cog-Processors-Tests'!

Item was added:
+ ----- 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 added:
+ ----- Method: GdbARMAlienTests>>nfib (in category 'accessing') -----
+ nfib
+       "long fib(long n) { return n <= 1 ? 1 : fib(n-1) + fib(n-2) + 1; }
+        as compiled by arm-elf-gnuabi-gcc fib.c -c -marm
+       also, the jumps are changed by hand."
+       "| bat nfib ip |
+       bat := GdbARMAlienTests new.
+       nfib := bat nfib asWordArray.
+       ip := 0.
+       23 timesRepeat:
+               [bat processor disassembleInstructionAt: ip In: nfib into:
+                       [:da :len|
+                       Transcript nextPutAll: da; cr; flush.
+                       ip := ip + len]]"
+       ^#("00000000 <fib>:
+          0:"          16re92d4810             "push   {r4, fp, lr}    fp = r11, sp is changed in this command
+          4:"          16re28db008             "add    fp, sp, #8      now, the frame pointer is changed
+          8:"          16re24dd00c             "sub    sp, sp, #12
+          c:"          16re50b0010             "str    r0, [fp, #-16]
+         10:"          16re51b3010             "ldr    r3, [fp, #-16]  r3 <- [fp-16] <- r0
+         14:"          16re3530001             "cmp    r3, #1
+         18:"          16rda00000c             "ble    50 <fib+0x50>
+         1c:"          16re51b3010             "ldr    r3, [fp, #-16]
+         20:"          16re2433001             "sub    r3, r3, #1
+         24:"          16re1a00003             "mov    r0, r3
+         28:"          16rebfffff4             "bl     0 <fib>
+         2c:"          16re1a04000             "mov    r4, r0
+         30:"          16re51b3010             "ldr    r3, [fp, #-16]
+         34:"          16re2433002             "sub    r3, r3, #2
+         38:"          16re1a00003             "mov    r0, r3
+         3c:"          16rebffffef             "bl     0 <fib>
+         40:"          16re1a03000             "mov    r3, r0
+         44:"          16re0843003             "add    r3, r4, r3
+         48:"          16re2833001             "add    r3, r3, #1
+         4c:"          16rea000000             "b      54 <fib+0x54>
+         50:"          16re3a03001             "mov    r3, #1
+         54:"          16re1a00003             "mov    r0, r3
+         58:"          16re24bd008             "sub    sp, fp, #8
+         5c:"          16re8bd8810             "pop    {r4, fp, pc}")!

Item was added:
+ ----- Method: GdbARMAlienTests>>processor (in category 'accessing') -----
+ processor
+       processor ifNil:
+               [processor := GdbARMAlien new].
+       ^processor!

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

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

Item was added:
+ ----- 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 := 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 added:
+ ----- Method: GdbARMAlienTests>>singleStepNFib:disassemble:printRegisters: (in category 'execution') -----
+ singleStepNFib: n disassemble: disassemble printRegisters: printRegisters
+       "Run nfib wth the argument. Answer the result."
+       "self new runNFib: 5 disassemble: true printRegisters: true"
+       | memory |
+       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: self nfib size * 4;  "return address"
+               pc: 0;
+               sp: (memory size * 4 - 12). "Room for return address, frame pointer and r4"
+       printRegisters ifTrue:
+               [self processor printRegistersOn: Transcript.
+                Transcript cr; flush].
+       [disassemble ifTrue:
+               [Transcript nextPutAll: (self processor disassembleNextInstructionIn: memory); cr; flush].
+        self processor singleStepIn: memory readExecuteOnlyBelow: memory size * 4 / 2.
+        printRegisters ifTrue:
+               [self processor printRegistersOn: Transcript.
+                Transcript cr; flush].
+       "stop, once we leave the nfib code and step through the nops after that."
+        self processor pc < (self nfib size * 4)] whileTrue.
+       ^self processor r0!

Item was added:
+ ----- 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 messageText = 'Error 0: Illegal Instruction fetch address (0x00000400).'].!

Item was added:
+ ----- Method: GdbARMAlienTests>>testDisassembling (in category 'tests') -----
+ testDisassembling
+
+       | memory result |
+       memory := WordArray new: 2.
+       memory at: 1 put: 16rEF200000.
+       result := self processor
+               disassembleInstructionAt: 0
+               In: memory
+               into: [:str :len |
+                       self
+                               assert: len = 4;
+                               assert: str = 'svc      0x00200000'].!

Item was added:
+ ----- Method: GdbARMAlienTests>>testExecutionTrap (in category 'tests') -----
+ testExecutionTrap
+       "Execute a run of nops.  test executing beyond the executable limit is trapped."
+       "self new testExecutionTrap"
+       | memory |
+        "The address is out of range of memory every which way (whether relative or absolute and whether big-endian or little."
+       memory := (Bitmap new: 1024 * 2 withAll: self processor nopOpcode) asByteArray.
+       self processor
+                       pc: 0;
+                       sp: (memory size - 4). "Room for return address"
+       self should: [self processor runInMemory: memory minimumAddress: 0 readOnlyBelow: memory size / 2]
+               raise: Error
+               withExceptionDo:
+                       [:err|
+                       self assert: self processor pc = (memory size / 2).
+                       self assert: ('Error 0: Illegal Instruction fetch address (0x00001000).' match: err messageText)].
+       self processor pc: 0.
+       self should: [[self processor singleStepIn: memory minimumAddress: 0 readOnlyBelow: memory size / 2] repeat]
+               raise: Error
+               withExceptionDo:
+                       [:err|
+                       self assert: self processor pc = (memory size / 2).
+                       self assert: ('Error 0: Illegal Instruction fetch address (0x00001000).' match: err messageText)]!

Item was added:
+ ----- Method: GdbARMAlienTests>>testFlags (in category 'tests') -----
+ testFlags
+       "self new testFlags"
+       | memory |
+       memory := Bitmap new: 3.
+       memory longAt: 1 put: 16rE3A03001 bigEndian: false. "MOV r3, #1"
+       memory longAt: 5 put: 16rE3530001 bigEndian: false. "CMP r3, #1"
+       memory := memory asByteArray.
+       self processor
+               disassembleInstructionAt: 0
+               In: memory
+               into: [:str :len |
+                       self
+                               assert: len = 4;
+                               assert: str = 'mov      r3, #1'].
+       self processor
+               disassembleInstructionAt: 4
+               In: memory
+               into: [:str :len |
+                       self
+                               assert: len = 4;
+                               assert: str = 'cmp      r3, #1'].
+       self processor
+               pc: 0;
+               singleStepIn: memory;
+               singleStepIn: memory.
+       self
+               assert: self processor pc = 16r8;
+               assert: self processor r3 = 1;
+               assert: self processor zflag = 1;
+               assert: self processor cflag = 1;
+               assert: self processor vflag = 0;
+               assert: self processor nflag = 0.
+       self processor reset.
+       self assert: self processor eflags = 3. "IFFlags are both set."!

Item was added:
+ ----- Method: GdbARMAlienTests>>testMOVSD (in category 'tests') -----
+ testMOVSD
+       "Test MOVSD indirecting through edx."
+       "self new testMOVSD"
+       self processor
+               edx: 0;
+               eip: 0;
+               singleStepIn: {16rF2. 16r0F. 16r10. 16r42. 16r04. 16r90. 16r01. 16r02. 16r03. 16r04. 16r05. 16r06} asByteArray "movsd %ds:0x4(%edx), %xmm0;nop;garbage".
+       self assert: self processor eip = 5.
+       self assert: self processor xmm0low = 16r0605040302019004!

Item was added:
+ ----- Method: GdbARMAlienTests>>testNfib1 (in category 'tests') -----
+ testNfib1
+       "self new testNfib1"
+       self should: [self runNFib: 1 disassemble: false printRegisters: true]
+               raise: Error
+               withExceptionDo:
+                       [:err| self assert: err messageText = 'Error 0: Illegal Instruction fetch address (0x00001000).'].
+       self deny: (self processor pc between: 0 and: self nfib size).
+       self assert: self processor r0 = 1 benchFib!

Item was added:
+ ----- Method: GdbARMAlienTests>>testNfib16 (in category 'tests') -----
+ testNfib16
+       "self new testNfib16"
+       self should: [self runNFib: 16 disassemble: false printRegisters: false]
+               raise: Error.
+       self deny: (self processor pc between: 0 and: self nfib size).
+       self assert: self processor r0 = 16 benchFib!

Item was added:
+ ----- Method: GdbARMAlienTests>>testNfib2 (in category 'tests') -----
+ testNfib2
+       "self new testNfib2"
+       self should: [self runNFib: 2 disassemble: false printRegisters: false]
+               raise: Error.
+       self deny: (self processor pc between: 0 and: self nfib size).
+       self assert: self processor r0 = 2 benchFib!

Item was added:
+ ----- Method: GdbARMAlienTests>>testNfib4 (in category 'tests') -----
+ testNfib4
+       "self new testNfib4"
+       self should: [self runNFib: 4 disassemble: false printRegisters: false]
+               raise: Error.
+       self deny: (self processor pc between: 0 and: self nfib size).
+       self assert: self processor r0 = 4 benchFib!

Item was added:
+ ----- Method: GdbARMAlienTests>>testResetCPU (in category 'tests') -----
+ testResetCPU
+       "self new testResetCPU"
+       self registerSetters do:
+               [:setter|
+               self processor perform: setter with: 16r55555555].
+       self registerGetters do:
+               [:getter|
+               self assert: 16r55555555 = (self processor perform: getter)].
+       self processor reset.
+       self registerGetters do:
+               [:getter|
+               self assert: 0 = (self processor perform: getter)]!

Item was added:
+ ----- Method: GdbARMAlienTests>>testStepNfib1 (in category 'tests') -----
+ testStepNfib1
+       "self new testStepNfib1"
+       self singleStepNFib: 1 disassemble: false printRegisters: false.
+       self assert: self processor pc = (self nfib asWordArray size * 4).
+       self assert: self processor r0 = 1 benchFib!

Item was added:
+ ----- Method: GdbARMAlienTests>>testStepNfib2 (in category 'tests') -----
+ testStepNfib2
+       "self new testStepNfib2"
+       self singleStepNFib: 2 disassemble: false printRegisters: false.
+       self assert: self processor pc = (self nfib size * 4).
+       self assert: self processor r0 = 2 benchFib!

Item was added:
+ ----- Method: GdbARMAlienTests>>testStepNfib4 (in category 'tests') -----
+ testStepNfib4
+       "self new testStepNfib4"
+       self singleStepNFib: 4 disassemble: false printRegisters: false.
+       self assert: self processor pc = (self nfib size * 4).
+       self assert: self processor r0 = 4 benchFib!

Item was added:
+ SmartSyntaxInterpreterPlugin subclass: #GdbARMPlugin
+       instanceVariableNames: 'prevInterruptCheckChain'
+       classVariableNames: ''
+       poolDictionaries: 'VMBasicConstants'
+       category: 'Cog-ProcessorPlugins'!
+
+ !GdbARMPlugin commentStamp: '<historical>' prior: 0!
+ I provide access to the ARMulator ARM emulator and the libopcodes ARM disassembler.!

Item was added:
+ ----- Method: GdbARMPlugin class>>declareCVarsIn: (in category 'translation') -----
+ declareCVarsIn: aCCodeGenerator
+       "prevInterruptCheckChain lives in sqGdbARMPlugin.c"
+       super declareCVarsIn: aCCodeGenerator.
+       aCCodeGenerator removeVariable: 'prevInterruptCheckChain'!

Item was added:
+ ----- Method: GdbARMPlugin class>>hasHeaderFile (in category 'translation') -----
+ hasHeaderFile
+       "We need a header to declare newcpu and pull in bochs.h & cpu.h"
+       ^true!

Item was added:
+ ----- Method: GdbARMPlugin>>forceStopOnInterrupt (in category 'interruption') -----
+ forceStopOnInterrupt
+       interpreterProxy getInterruptPending ifTrue:
+               [self forceStopRunning]!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveDisassembleAt:InMemory: (in category 'primitives') -----
+ "cpuAlien <GdbARMAlien>" primitiveDisassembleAt: address "<Integer>" InMemory: memory "<Bitmap|ByteArray|WordArray>"
+       "Return an Array of the instruction length and its decompilation as a string for the instruction at address in memory."
+       | cpuAlien cpu instrLenOrErr resultObj log logLen logObj logObjData |
+       <var: #cpu type: #'void *'>
+       cpuAlien := self primitive: #primitiveDisassembleAtInMemory
+                                       parameters: #(Unsigned WordsOrBytes)
+                                       receiver: #Oop.
+       (cpu := self startOfData: cpuAlien) = 0 ifTrue:
+               [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].
+       instrLenOrErr := self disassembleFor: cpu
+                                               At: address
+                                               In: memory
+                                               Size: (interpreterProxy byteSizeOf: memory cPtrAsOop).
+       instrLenOrErr < 0 ifTrue:
+               [^interpreterProxy primitiveFailFor: PrimErrInappropriate].
+       log := self getlog: (self cCode: [self addressOf: logLen] inSmalltalk: [logLen := 0]).
+       resultObj := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: 2.
+       resultObj = 0 ifTrue:
+               [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+
+       "Easier keeping the damn thing on the stack than using pushRemappableOop:/popRemappableOop.
+        Where is topRemappableOop when you need it?"
+       interpreterProxy pushRemappableOop: resultObj.
+       logObj := interpreterProxy
+                               instantiateClass: interpreterProxy classString
+                               indexableSize: logLen.
+       interpreterProxy failed ifTrue:
+               [interpreterProxy popRemappableOop.
+                ^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+       logObjData := interpreterProxy arrayValueOf: logObj.
+       self cCode: 'memcpy(logObjData, log, logLen)' inSmalltalk: [logObjData. log].
+       resultObj := interpreterProxy popRemappableOop.
+       interpreterProxy
+               storePointer: 0
+               ofObject: resultObj
+               withValue: (interpreterProxy integerObjectOf: instrLenOrErr).
+       interpreterProxy storePointer: 1 ofObject: resultObj withValue: logObj.
+
+       ^resultObj!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveErrorAndLog (in category 'primitives') -----
+ primitiveErrorAndLog
+       | log logLen resultObj logObj logObjData |
+       <var: #log type: #'char *'>
+       <var: #logObjData type: #'char *'>
+       self primitive: #primitiveErrorAndLog parameters: #().
+
+       log := self getlog: (self cCode: [self addressOf: logLen] inSmalltalk: [logLen := 0]).
+       resultObj := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: 2.
+       resultObj = 0 ifTrue:
+               [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+
+       interpreterProxy
+               storePointer: 0
+               ofObject: resultObj
+               withValue: (interpreterProxy integerObjectOf: self errorAcorn).
+
+       logLen > 0 ifTrue:
+               [interpreterProxy pushRemappableOop: resultObj.
+               logObj := interpreterProxy
+                                       instantiateClass: interpreterProxy classString
+                                       indexableSize: logLen.
+               interpreterProxy failed ifTrue:
+                       [interpreterProxy popRemappableOop.
+                        ^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+
+               resultObj := interpreterProxy popRemappableOop.
+               logObjData := interpreterProxy arrayValueOf: logObj.
+               self cCode: 'memcpy(logObjData, log, logLen)' inSmalltalk: [logObjData. log].
+               interpreterProxy storePointer: 1 ofObject: resultObj withValue: logObj].
+       interpreterProxy pop: 1 thenPush: resultObj!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveFlushICacheFrom:To: (in category 'primitives') -----
+ "cpuAlien <GdbARMAlien>" primitiveFlushICacheFrom: startAddress "<Integer>" To: endAddress "<Integer>"
+       "Flush the icache in the requested range"
+       | cpuAlien cpu |
+       <var: #cpu type: 'void *'>
+       cpuAlien := self primitive: #primitiveFlushICacheFromTo
+                                       parameters: #(Unsigned Unsigned)
+                                       receiver: #Oop.
+       (cpu := self startOfData: cpuAlien) = 0 ifTrue:
+               [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].
+       self flushICache: cpu From: startAddress To: endAddress!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveNewCPU (in category 'primitives') -----
+ primitiveNewCPU
+       | cpu |
+       <var: #cpu type: 'void *'>
+       self primitive: #primitiveNewCPU parameters: #().
+
+       cpu := self cCode: 'newCPU()' inSmalltalk: [0].
+       cpu = 0 ifTrue:
+               [^interpreterProxy primitiveFail].
+       interpreterProxy
+               pop: 1
+               thenPush: (interpreterProxy positive32BitIntegerFor:
+                                                                               (self cCoerceSimple: cpu
+                                                                                       to: 'unsigned long'))!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveResetCPU (in category 'primitives') -----
+ primitiveResetCPU
+       | cpuAlien cpu maybeErr |
+       <var: #cpu type: 'void *'>
+       cpuAlien := self primitive: #primitiveResetCPU parameters: #() receiver: #Oop.
+       (cpu := self startOfData: cpuAlien) = 0 ifTrue:
+               [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].
+       maybeErr := self resetCPU: cpu.
+       maybeErr ~= 0 ifTrue:
+               [^interpreterProxy primitiveFailFor: PrimErrInappropriate].
+       ^cpuAlien!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveRunInMemory:minimumAddress:readOnlyBelow: (in category 'primitives') -----
+ "cpuAlien <GdbARMAlien>" primitiveRunInMemory: memory "<Bitmap|ByteArray|WordArray>" minimumAddress: minAddress "<Integer>" readOnlyBelow: minWriteMaxExecAddress "<Integer>"
+       "Run the cpu using the first argument as the memory and the following arguments defining valid addresses, running until it halts or hits an exception."
+       | cpuAlien cpu maybeErr |
+       <var: #cpu type: #'void *'>
+       cpuAlien := self primitive: #primitiveRunInMemoryMinimumAddressReadWrite
+                                       parameters: #(WordsOrBytes Unsigned Unsigned)
+                                       receiver: #Oop.
+       (cpu := self startOfData: cpuAlien) = 0 ifTrue:
+               [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].
+       prevInterruptCheckChain := interpreterProxy setInterruptCheckChain: #forceStopOnInterrupt asSymbol.
+       prevInterruptCheckChain = #forceStopOnInterrupt asSymbol ifTrue:
+               [prevInterruptCheckChain = 0].
+       maybeErr := self runCPU: cpu
+                                       In: memory
+                                       Size: (interpreterProxy byteSizeOf: memory cPtrAsOop)
+                                       MinAddressRead: minAddress
+                                       Write: minWriteMaxExecAddress.
+       interpreterProxy setInterruptCheckChain: prevInterruptCheckChain.
+       maybeErr ~= 0 ifTrue:
+               [^interpreterProxy primitiveFailFor: PrimErrInappropriate].
+       ^cpuAlien!

Item was added:
+ ----- Method: GdbARMPlugin>>primitiveSingleStepInMemory:minimumAddress:readOnlyBelow: (in category 'primitives') -----
+ "cpuAlien <GdbARMAlien>" primitiveSingleStepInMemory: memory "<Bitmap|ByteArray|WordArray>" minimumAddress: minAddress "<Integer>"  readOnlyBelow: minWriteMaxExecAddress "<Integer>"
+       "Single-step the cpu using the first argument as the memory and the following arguments defining valid addresses."
+       | cpuAlien cpu maybeErr |
+       <var: #cpu type: #'void *'>
+       cpuAlien := self primitive: #primitiveSingleStepInMemoryMinimumAddressReadWrite
+                                       parameters: #(WordsOrBytes Unsigned Unsigned)
+                                       receiver: #Oop.
+       (cpu := self startOfData: cpuAlien) = 0 ifTrue:
+               [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].
+       maybeErr := self singleStepCPU: cpu
+                                       In: memory
+                                       Size: (interpreterProxy byteSizeOf: memory cPtrAsOop)
+                                       MinAddressRead: minAddress
+                                       Write: minWriteMaxExecAddress.
+       maybeErr ~= 0 ifTrue:
+               [^interpreterProxy primitiveFailFor: PrimErrInappropriate].
+       ^cpuAlien!

Item was added:
+ ----- Method: GdbARMPlugin>>sizeField: (in category 'alien support') -----
+ sizeField: rcvr
+       "Answer the first field of rcvr which is assumed to be an Alien of at least 8 bytes"
+       <inline: true>
+       ^self longAt: rcvr + BaseHeaderSize!

Item was added:
+ ----- Method: GdbARMPlugin>>startOfData: (in category 'alien support') -----
+ startOfData: rcvr "<Alien oop> ^<Integer>"
+       "Answer the start of rcvr's data.  For direct aliens this is the address of
+        the second field.  For indirect and pointer aliens it is what the second field points to."
+       <inline: true>
+       ^(self sizeField: rcvr) > 0
+               ifTrue: [rcvr + BaseHeaderSize + BytesPerOop]
+               ifFalse: [self longAt: rcvr + BaseHeaderSize + BytesPerOop]!




--
best,
Eliot

Reply | Threaded
Open this post in threaded view
|

Re: VM Maker: Cog-lw.48.mcz

David T. Lewis
 
On Wed, Jul 11, 2012 at 01:14:28PM -0700, Eliot Miranda wrote:
>  
> Congratulations are due to Lars Wassermann, the GSoC student on the ARM
> Jitter for Squeak VM project, who has got as far as implementing a plugin
> for an ARM simulator that passes all its tests and can evaluate fibonacci.
>  Lars is making great progress.
>

Outstanding!

Lars is also now a developer on VMMaker at source.squeak.org.

Dave