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.<br>
<br><div>e.g.</div><div><br></div><div><div>nfib</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>"long fib(long n) { return n <= 1 ? 1 : fib(n-1) + fib(n-2) + 1; }</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> as compiled by arm-elf-gnuabi-gcc fib.c -c -marm</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>also, the jumps are changed by hand."</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>"| bat nfib ip |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>bat := GdbARMAlienTests new.</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>nfib := bat nfib asWordArray.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>ip := 0.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>23 timesRepeat:</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>[bat processor disassembleInstructionAt: ip In: nfib into:</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>[:da :len|</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>Transcript nextPutAll: da; cr; flush.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>ip := ip + len]]"</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>^#("00000000 <fib>:</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> 0:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re92d4810 <span class="Apple-tab-span" style="white-space:pre">                </span>"push<span class="Apple-tab-span" style="white-space:pre">        </span>{r4, fp, lr}<span class="Apple-tab-span" style="white-space:pre">        </span>fp = r11, sp is changed in this command</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 4:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re28db008 <span class="Apple-tab-span" style="white-space:pre">                </span>"add<span class="Apple-tab-span" style="white-space:pre">        </span>fp, sp, #8<span class="Apple-tab-span" style="white-space:pre">        </span>now, the frame pointer is changed</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 8:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re24dd00c <span class="Apple-tab-span" style="white-space:pre">                </span>"sub<span class="Apple-tab-span" style="white-space:pre">        </span>sp, sp, #12</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> c:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re50b0010 <span class="Apple-tab-span" style="white-space:pre">                </span>"str<span class="Apple-tab-span" style="white-space:pre">        </span>r0, [fp, #-16]</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 10:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re51b3010 <span class="Apple-tab-span" style="white-space:pre">                </span>"ldr<span class="Apple-tab-span" style="white-space:pre">        </span>r3, [fp, #-16]<span class="Apple-tab-span" style="white-space:pre">        </span>r3 <- [fp-16] <- r0</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 14:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re3530001 <span class="Apple-tab-span" style="white-space:pre">                </span>"cmp<span class="Apple-tab-span" style="white-space:pre">        </span>r3, #1</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 18:"<span class="Apple-tab-span" style="white-space:pre">                </span>16rda00000c <span class="Apple-tab-span" style="white-space:pre">                </span>"ble<span class="Apple-tab-span" style="white-space:pre">        </span>50 <fib+0x50></div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 1c:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re51b3010 <span class="Apple-tab-span" style="white-space:pre">                </span>"ldr<span class="Apple-tab-span" style="white-space:pre">        </span>r3, [fp, #-16]</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 20:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re2433001 <span class="Apple-tab-span" style="white-space:pre">                </span>"sub<span class="Apple-tab-span" style="white-space:pre">        </span>r3, r3, #1</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 24:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re1a00003 <span class="Apple-tab-span" style="white-space:pre">                </span>"mov<span class="Apple-tab-span" style="white-space:pre">        </span>r0, r3</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 28:"<span class="Apple-tab-span" style="white-space:pre">                </span>16rebfffff4 <span class="Apple-tab-span" style="white-space:pre">                </span>"bl<span class="Apple-tab-span" style="white-space:pre">        </span>0 <fib></div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 2c:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re1a04000 <span class="Apple-tab-span" style="white-space:pre">                </span>"mov<span class="Apple-tab-span" style="white-space:pre">        </span>r4, r0</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 30:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re51b3010 <span class="Apple-tab-span" style="white-space:pre">                </span>"ldr<span class="Apple-tab-span" style="white-space:pre">        </span>r3, [fp, #-16]</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 34:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re2433002<span class="Apple-tab-span" style="white-space:pre">        </span> <span class="Apple-tab-span" style="white-space:pre">        </span>"sub<span class="Apple-tab-span" style="white-space:pre">        </span>r3, r3, #2</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 38:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re1a00003 <span class="Apple-tab-span" style="white-space:pre">                </span>"mov<span class="Apple-tab-span" style="white-space:pre">        </span>r0, r3</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 3c:"<span class="Apple-tab-span" style="white-space:pre">                </span>16rebffffef <span class="Apple-tab-span" style="white-space:pre">                </span>"bl<span class="Apple-tab-span" style="white-space:pre">        </span>0 <fib></div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 40:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re1a03000 <span class="Apple-tab-span" style="white-space:pre">                </span>"mov<span class="Apple-tab-span" style="white-space:pre">        </span>r3, r0</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 44:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re0843003 <span class="Apple-tab-span" style="white-space:pre">                </span>"add<span class="Apple-tab-span" style="white-space:pre">        </span>r3, r4, r3</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 48:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re2833001 <span class="Apple-tab-span" style="white-space:pre">                </span>"add<span class="Apple-tab-span" style="white-space:pre">        </span>r3, r3, #1</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 4c:"<span class="Apple-tab-span" style="white-space:pre">                </span>16rea000000 <span class="Apple-tab-span" style="white-space:pre">                </span>"b<span class="Apple-tab-span" style="white-space:pre">        </span>54 <fib+0x54></div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 50:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re3a03001 <span class="Apple-tab-span" style="white-space:pre">                </span>"mov<span class="Apple-tab-span" style="white-space:pre">        </span>r3, #1</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 54:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re1a00003 <span class="Apple-tab-span" style="white-space:pre">                </span>"mov<span class="Apple-tab-span" style="white-space:pre">        </span>r0, r3</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 58:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re24bd008 <span class="Apple-tab-span" style="white-space:pre">                </span>"sub<span class="Apple-tab-span" style="white-space:pre">        </span>sp, fp, #8</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> 5c:"<span class="Apple-tab-span" style="white-space:pre">                </span>16re8bd8810 <span class="Apple-tab-span" style="white-space:pre">                </span>"pop<span class="Apple-tab-span" style="white-space:pre">        </span>{r4, fp, pc}")</div>
<div><br></div><div class="gmail_quote">On Wed, Jul 11, 2012 at 12:47 PM, <span dir="ltr"><<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Eliot Miranda uploaded a new version of Cog to project VM Maker:<br>
<a href="http://source.squeak.org/VMMaker/Cog-lw.48.mcz" target="_blank">http://source.squeak.org/VMMaker/Cog-lw.48.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Cog-lw.48<br>
Author: lw<br>
Time: 11 July 2012, 9:13:45.865 pm<br>
UUID: 5ae3e465-4b2c-2349-9b88-77b8f53d5acd<br>
Ancestors: Cog-eem.47<br>
<br>
Added the GdbARMAlien, together with its tests and the plugin.<br>
Additionally, introduced CogProcessorAlien as a common superclass for BochsIA32Alien and GdbARMAlien to increase code reusage.<br>
<br>
The same might be possible for the Plugins (BochsIA32/GdbARM), because they are also identical.<br>
<br>
=============== Diff against Cog-eem.47 ===============<br>
<br>
Item was changed:<br>
+ CogProcessorAlien variableByteSubclass: #BochsIA32Alien<br>
- Alien variableByteSubclass: #BochsIA32Alien<br>
instanceVariableNames: ''<br>
classVariableNames: 'OpcodeExceptionMap PostBuildStackDelta'<br>
poolDictionaries: ''<br>
category: 'Cog-Processors'!<br>
<br>
!BochsIA32Alien commentStamp: '<historical>' prior: 0!<br>
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.<br>
<br>
Here is the configure script for the configuration this code assumes. Offsets of fields will change with different configurations so they must agree.<br>
<br>
----8<---- conf.COG ----8<----<br>
#!!/bin/sh<br>
<br>
# this sets up the compile for Cog. Disable as much inessential stuff<br>
# as possible leaving only the cpu/fpu & memory interface<br>
<br>
set echo<br>
# 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"<br>
CFLAGS="-m32 $CFLAGS"<br>
CFLAGS="-Dlongjmp=_longjmp -Dsetjmp=_setjmp $CFLAGS"<br>
CFLAGS="-pipe -O3 -fomit-frame-pointer -finline-functions $CFLAGS"<br>
CFLAGS="-g $CFLAGS"<br>
CPATH="/sw/include"<br>
CPPFLAGS=""<br>
CXXFLAGS="$CFLAGS"<br>
LDFLAGS="-L/sw/lib"<br>
<br>
export CFLAGS<br>
export CPATH<br>
export CPPFLAGS<br>
export CXXFLAGS<br>
export LDFLAGS<br>
<br>
./configure --enable-Cog \<br>
--enable-cpu-level=6 \<br>
--enable-sse=2 \<br>
--enable-assert-checks \<br>
--with-nogui \<br>
--disable-x86-64 \<br>
--disable-pae \<br>
--disable-large-pages \<br>
--disable-global-pages \<br>
--disable-mtrr \<br>
--disable-sb16 \<br>
--disable-ne2000 \<br>
--disable-pci \<br>
--disable-acpi \<br>
--disable-apic \<br>
--disable-clgd54xx \<br>
--disable-usb \<br>
--disable-plugins \<br>
${CONFIGURE_ARGS}<br>
<br>
# apic == Advanced programmable Interrupt Controller<br>
# acpi == Advanced Configuration and Power Interface<br>
# pci == Peripheral Component Interconnect local bus<br>
# clgd54xx == Cirrus Logic GD54xx video card<br>
----8<---- conf.COG ----8<----!<br>
<br>
Item was removed:<br>
- ----- Method: BochsIA32Alien>>disassembleFrom:to:in:on: (in category 'disassembly') -----<br>
- disassembleFrom: startAddress to: endAddress in: memory on: aStream<br>
- | address |<br>
- address := startAddress.<br>
- [address < endAddress] whileTrue:<br>
- [[:size :string|<br>
- aStream nextPutAll: string; cr; flush.<br>
- address := address + size]<br>
- valueWithArguments: (self<br>
- primitiveDisassembleAt: address<br>
- inMemory: memory)]!<br>
<br>
Item was removed:<br>
- ----- Method: BochsIA32Alien>>disassembleInstructionAt:In: (in category 'disassembly') -----<br>
- disassembleInstructionAt: pc In: memory<br>
- ^(self primitiveDisassembleAt: pc inMemory: memory) last!<br>
<br>
Item was removed:<br>
- ----- Method: BochsIA32Alien>>disassembleInstructionAt:In:into: (in category 'disassembly') -----<br>
- disassembleInstructionAt: ip In: memory into: aBlock<br>
- | lenAndDi |<br>
- lenAndDi := self primitiveDisassembleAt: ip inMemory: memory.<br>
- ^aBlock value: lenAndDi last value: lenAndDi first!<br>
<br>
Item was removed:<br>
- ----- Method: BochsIA32Alien>>disassembleNextInstructionIn: (in category 'disassembly') -----<br>
- disassembleNextInstructionIn: memory<br>
- ^(self primitiveDisassembleAt: self eip inMemory: memory) last!<br>
<br>
Item was removed:<br>
- ----- Method: BochsIA32Alien>>runInMemory: (in category 'execution') -----<br>
- runInMemory: aMemory<br>
- | result |<br>
- result := self primitiveRunInMemory: aMemory minimumAddress: 0 readOnlyBelow: 0.<br>
- result ~~ self ifTrue:<br>
- [self error: 'eek!!']!<br>
<br>
Item was removed:<br>
- ----- Method: BochsIA32Alien>>runInMemory:minimumAddress:readOnlyBelow: (in category 'execution') -----<br>
- runInMemory: aMemory minimumAddress: minimumAddress readOnlyBelow: minimumWritableAddress<br>
- | result |<br>
- result := self primitiveRunInMemory: aMemory<br>
- minimumAddress: minimumAddress<br>
- readOnlyBelow: minimumWritableAddress.<br>
- result ~~ self ifTrue:<br>
- [self error: 'eek!!']!<br>
<br>
Item was removed:<br>
- ----- Method: BochsIA32Alien>>runInMemory:readExecuteOnlyBelow: (in category 'execution') -----<br>
- runInMemory: aMemory readExecuteOnlyBelow: minWriteMaxExecAddr<br>
- | result |<br>
- result := self primitiveRunInMemory: aMemory minimumAddress: 0 readOnlyBelow: minWriteMaxExecAddr.<br>
- result ~~ self ifTrue:<br>
- [self error: 'eek!!']!<br>
<br>
Item was removed:<br>
- ----- Method: BochsIA32Alien>>singleStepIn: (in category 'execution') -----<br>
- singleStepIn: aMemory<br>
- | result |<br>
- result := self primitiveSingleStepInMemory: aMemory minimumAddress: 0 readOnlyBelow: aMemory size.<br>
- result ~~ self ifTrue:<br>
- [self error: 'eek!!']!<br>
<br>
Item was removed:<br>
- ----- Method: BochsIA32Alien>>singleStepIn:minimumAddress:readOnlyBelow: (in category 'execution') -----<br>
- singleStepIn: aMemory minimumAddress: minimumAddress readOnlyBelow: minimumWritableAddress<br>
- | result |<br>
- result := self primitiveSingleStepInMemory: aMemory<br>
- minimumAddress: minimumAddress<br>
- readOnlyBelow: minimumWritableAddress.<br>
- result ~~ self ifTrue:<br>
- [self error: 'eek!!']!<br>
<br>
Item was removed:<br>
- ----- Method: BochsIA32Alien>>singleStepIn:readExecuteOnlyBelow: (in category 'execution') -----<br>
- singleStepIn: aMemory readExecuteOnlyBelow: minWriteMaxExecAddr<br>
- | result |<br>
- result := self primitiveSingleStepInMemory: aMemory minimumAddress: 0 readOnlyBelow: minWriteMaxExecAddr.<br>
- result ~~ self ifTrue:<br>
- [self error: 'eek!!']!<br>
<br>
Item was added:<br>
+ Alien variableByteSubclass: #CogProcessorAlien<br>
+ instanceVariableNames: ''<br>
+ classVariableNames: ''<br>
+ poolDictionaries: ''<br>
+ category: 'Cog-Processors'!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>abstractInstructionCompilerClass (in category 'Cog API') -----<br>
+ abstractInstructionCompilerClass<br>
+ self subclassResponsibility!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>callOpcode (in category 'opcodes') -----<br>
+ callOpcode<br>
+ self subclassResponsibility.!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>disassembleFrom:to:in:on: (in category 'disassembly') -----<br>
+ disassembleFrom: startAddress to: endAddress in: memory on: aStream<br>
+ | address |<br>
+ address := startAddress.<br>
+ [address < endAddress] whileTrue:<br>
+ [[:size :string|<br>
+ aStream nextPutAll: string; cr; flush.<br>
+ address := address + size]<br>
+ valueWithArguments: (self<br>
+ primitiveDisassembleAt: address<br>
+ inMemory: memory)]!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>disassembleInstructionAt:In: (in category 'disassembly') -----<br>
+ disassembleInstructionAt: pc In: memory<br>
+ ^(self primitiveDisassembleAt: pc inMemory: memory) last!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>disassembleInstructionAt:In:into: (in category 'disassembly') -----<br>
+ disassembleInstructionAt: ip In: memory into: aBlock<br>
+ | lenAndDi |<br>
+ lenAndDi := self primitiveDisassembleAt: ip inMemory: memory.<br>
+ ^aBlock value: lenAndDi last value: lenAndDi first!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>disassembleNextInstructionIn: (in category 'disassembly') -----<br>
+ disassembleNextInstructionIn: memory<br>
+ ^(self primitiveDisassembleAt: self pc inMemory: memory) last!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>nopOpcode (in category 'opcodes') -----<br>
+ nopOpcode<br>
+ self subclassResponsibility.!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>printRegisterState:on: (in category 'printing') -----<br>
+ printRegisterState: registerStateVector on: aStream<br>
+<br>
+ self subclassResponsibility.!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>printRegistersOn: (in category 'printing') -----<br>
+ printRegistersOn: aStream<br>
+ self printRegisterState: self registerState on: aStream.<br>
+ aStream flush!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>reportPrimitiveFailure (in category 'error handling') -----<br>
+ reportPrimitiveFailure<br>
+ | errorAndLog |<br>
+ errorAndLog := self primitiveErrorAndLog.<br>
+ self error: 'Error ', errorAndLog first printString, (errorAndLog last ifNil: [''] ifNotNil: [:log| ': ', log])!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>runInMemory: (in category 'execution') -----<br>
+ runInMemory: aMemory<br>
+ | result |<br>
+ result := self primitiveRunInMemory: aMemory minimumAddress: 0 readOnlyBelow: 0.<br>
+ result ~~ self ifTrue:<br>
+ [self error: 'eek!!']!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>runInMemory:minimumAddress:readOnlyBelow: (in category 'execution') -----<br>
+ runInMemory: aMemory minimumAddress: minimumAddress readOnlyBelow: minimumWritableAddress<br>
+ | result |<br>
+ result := self primitiveRunInMemory: aMemory<br>
+ minimumAddress: minimumAddress<br>
+ readOnlyBelow: minimumWritableAddress.<br>
+ result ~~ self ifTrue:<br>
+ [self error: 'eek!!']!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>runInMemory:readExecuteOnlyBelow: (in category 'execution') -----<br>
+ runInMemory: aMemory readExecuteOnlyBelow: minWriteMaxExecAddr<br>
+ | result |<br>
+ result := self primitiveRunInMemory: aMemory minimumAddress: 0 readOnlyBelow: minWriteMaxExecAddr.<br>
+ result ~~ self ifTrue:<br>
+ [self error: 'eek!!']!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>singleStepIn: (in category 'execution') -----<br>
+ singleStepIn: aMemory<br>
+ | result |<br>
+ result := self primitiveSingleStepInMemory: aMemory minimumAddress: 0 readOnlyBelow: aMemory size.<br>
+ result ~~ self ifTrue:<br>
+ [self error: 'eek!!']!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>singleStepIn:minimumAddress:readOnlyBelow: (in category 'execution') -----<br>
+ singleStepIn: aMemory minimumAddress: minimumAddress readOnlyBelow: minimumWritableAddress<br>
+ | result |<br>
+ result := self primitiveSingleStepInMemory: aMemory<br>
+ minimumAddress: minimumAddress<br>
+ readOnlyBelow: minimumWritableAddress.<br>
+ result ~~ self ifTrue:<br>
+ [self error: 'eek!!']!<br>
<br>
Item was added:<br>
+ ----- Method: CogProcessorAlien>>singleStepIn:readExecuteOnlyBelow: (in category 'execution') -----<br>
+ singleStepIn: aMemory readExecuteOnlyBelow: minWriteMaxExecAddr<br>
+ | result |<br>
+ result := self primitiveSingleStepInMemory: aMemory minimumAddress: 0 readOnlyBelow: minWriteMaxExecAddr.<br>
+ result ~~ self ifTrue:<br>
+ [self error: 'eek!!']!<br>
<br>
Item was added:<br>
+ CogProcessorAlien variableByteSubclass: #GdbARMAlien<br>
+ instanceVariableNames: ''<br>
+ classVariableNames: 'OpcodeExceptionMap PostBuildStackDelta'<br>
+ poolDictionaries: ''<br>
+ category: 'Cog-Processors'!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien class>>dataSize (in category 'instance creation') -----<br>
+ dataSize<br>
+<br>
+ ^1536!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien class>>defaultIntegerBaseInDebugger (in category 'debugger') -----<br>
+ defaultIntegerBaseInDebugger<br>
+ ^16!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien class>>new (in category 'instance creation') -----<br>
+ new<br>
+ ^(self atAddress: self primitiveNewCPU) reset!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien class>>primitiveNewCPU (in category 'primitives') -----<br>
+ primitiveNewCPU<br>
+ "Answer the address of a new ARMulator C type ARMul_State instance."<br>
+ <primitive: 'primitiveNewCPU' module: 'GdbARMPlugin'><br>
+ ^self primitiveFailed!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>abstractInstructionCompilerClass (in category 'Cog API') -----<br>
+ abstractInstructionCompilerClass<br>
+ ^CogARMCompiler!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>branchAndLinkOpcodeWithOffset: (in category 'opcodes') -----<br>
+ branchAndLinkOpcodeWithOffset: aNumber<br>
+<br>
+ | offset |<br>
+ offset := (aNumber - 8) asInteger >> 2.<br>
+ (offset bitAnd: 16rFF000000) ~= 0 ifTrue: [self error: 'The offset is to far. ARM does not support such far jumps.'].<br>
+ ^ 16reb000000 bitOr: (offset bitAnd: 16r00FFFFFF)!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>callOpcode (in category 'opcodes') -----<br>
+ callOpcode<br>
+ "The call command does not generally exist. The most similar would be bl <offset>"<br>
+ ^ self branchAndLinkOpcodeWithOffset: 0.!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>cflag (in category 'accessing') -----<br>
+ cflag<br>
+ ^self unsignedLongAt: 577!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>eflags (in category 'accessing') -----<br>
+ eflags<br>
+<br>
+ ^ (((self nflag << 5 bitOr: self zflag << 4)<br>
+ bitOr: self cflag << 3)<br>
+ bitOr: self vflag << 2)<br>
+ bitOr: self ifflags!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>handleExecutionPrimitiveFailureIn:minimumAddress:readOnlyBelow: (in category 'error handling') -----<br>
+ handleExecutionPrimitiveFailureIn: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "<Integer>" readOnlyBelow: minimumWritableAddress "<Integer>"<br>
+ "Handle an execution primitive failure. Convert out-of-range call and absolute<br>
+ memory read into register instructions into ProcessorSimulationTrap signals."<br>
+ "self printIntegerRegistersOn: Transcript"<br>
+ "self printRegistersOn: Transcript"<br>
+<br>
+ "| pc opcode |<br>
+ ((pc := self pc) between: minimumAddress and: memoryArray byteSize - 1) ifTrue:<br>
+ [opcode := memoryArray byteAt: pc + 1.<br>
+ ^self<br>
+ perform: (OpcodeExceptionMap at: opcode + 1)<br>
+ with: pc<br>
+ with: memoryArray<br>
+ with: minimumWritableAddress]."<br>
+ ^self reportPrimitiveFailure!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>ifflags (in category 'accessing') -----<br>
+ ifflags<br>
+ ^self unsignedLongAt: 585!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>integerRegisterState (in category 'accessing-abstract') -----<br>
+ integerRegisterState<br>
+ ^{ self r0. self r1. self r2. self r3. self r4. self r5. self r6. self r7. self r8.<br>
+ self r9. self r10. self r11. self r12. self sp. self lr. self pc}!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>lr (in category 'accessing') -----<br>
+ lr<br>
+ ^self unsignedLongAt: 69!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>lr: (in category 'accessing') -----<br>
+ lr: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 69 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>nflag (in category 'accessing') -----<br>
+ nflag<br>
+ ^self unsignedLongAt: 569!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>nopOpcode (in category 'opcodes') -----<br>
+ nopOpcode<br>
+ "mov r0, r0"<br>
+ ^ 16rE1A01001!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>pc (in category 'accessing') -----<br>
+ pc<br>
+ ^self unsignedLongAt: 73!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>pc: (in category 'accessing') -----<br>
+ pc: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 73 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>primitiveDisassembleAt:inMemory: (in category 'primitives') -----<br>
+ primitiveDisassembleAt: address inMemory: memoryArray "<Bitmap|ByteArray>"<br>
+ "Answer an Array of the size and the disassembled code string for the instruction at the current instruction pointer in memory."<br>
+ <primitive: 'primitiveDisassembleAtInMemory' module: 'GdbARMPlugin'><br>
+ ^self primitiveFailed!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>primitiveErrorAndLog (in category 'primitives') -----<br>
+ primitiveErrorAndLog<br>
+ "Answer an array of the current error code and log contents"<br>
+ <primitive: 'primitiveErrorAndLog' module: 'GdbARMPlugin'><br>
+ ^self primitiveFailed!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>primitiveResetCPU (in category 'primitives') -----<br>
+ primitiveResetCPU<br>
+ "Reset the receiver to registers all zero, and protected 32-bit mode."<br>
+ <primitive: 'primitiveResetCPU' module: 'GdbARMPlugin'><br>
+ ^self reportPrimitiveFailure!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>primitiveRunInMemory:minimumAddress:readOnlyBelow: (in category 'primitives') -----<br>
+ primitiveRunInMemory: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "<Integer>" readOnlyBelow: minimumWritableAddress "<Integer>"<br>
+ "Run the receiver using the argument as the store. Origin the argument at 0. i.e. the first byte of the<br>
+ memoryArray is address 0. Make addresses below minimumAddress illegal. Convert out-of-range<br>
+ call, jump and memory read/writes into register instructions into ProcessorSimulationTrap signals."<br>
+ <primitive: 'primitiveRunInMemoryMinimumAddressReadWrite' module: 'GdbARMPlugin' error: ec><br>
+ ^ec == #'inappropriate operation'<br>
+ ifTrue: [self handleExecutionPrimitiveFailureIn: memoryArray<br>
+ minimumAddress: minimumAddress<br>
+ readOnlyBelow: minimumWritableAddress]<br>
+ ifFalse: [self reportPrimitiveFailure]<br>
+<br>
+ "self printRegistersOn: Transcript"!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>primitiveSingleStepInMemory:minimumAddress:readOnlyBelow: (in category 'primitives') -----<br>
+ primitiveSingleStepInMemory: memoryArray "<Bitmap|ByteArray>" minimumAddress: minimumAddress "<Integer>" readOnlyBelow: minimumWritableAddress "<Integer>"<br>
+ "Single-step the receiver using the argument as the store. Origin the argument at 0. i.e. the first byte of the<br>
+ memoryArray is address 0. Make addresses below minimumAddress illegal. Convert out-of-range<br>
+ call, jump and memory read/writes into register instructions into ProcessorSimulationTrap signals."<br>
+ <primitive: 'primitiveSingleStepInMemoryMinimumAddressReadWrite' module: 'GdbARMPlugin' error: ec><br>
+ ^ec == #'inappropriate operation'<br>
+ ifTrue: [self handleExecutionPrimitiveFailureIn: memoryArray<br>
+ minimumAddress: minimumAddress<br>
+ readOnlyBelow: minimumWritableAddress]<br>
+ ifFalse: [self reportPrimitiveFailure]!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>printRegisterState:on: (in category 'printing') -----<br>
+ printRegisterState: registerStateVector on: aStream<br>
+ | rsvs fields|<br>
+ aStream ensureCr.<br>
+ rsvs := registerStateVector readStream.<br>
+ fields := #( r0 r1 r2 r3 r4 r5 r6 cr r7 r8 r9 r10 r11 r12 cr sp lr pc eflags cr).<br>
+ fields withIndexDo:<br>
+ [:sym :index| | val |<br>
+ sym = #cr<br>
+ ifTrue: [aStream cr]<br>
+ ifFalse:<br>
+ [(val := rsvs next) isNil ifTrue: [^self].<br>
+ aStream nextPutAll: sym; nextPut: $:; space.<br>
+ val printOn: aStream base: 16 length: 8 padded: true.<br>
+ #eflags == sym<br>
+ ifTrue:<br>
+ [aStream space.<br>
+ "'FIVCZN'"'--VCZN' withIndexDo:<br>
+ [:flag :bitIndex|<br>
+ flag ~= $- ifTrue:<br>
+ [aStream nextPut: flag; nextPutAll: 'F='; print: (val bitAnd: 1 << (bitIndex - 1)) >> (bitIndex - 1); space]]]<br>
+ ifFalse:<br>
+ [val > 16 ifTrue:<br>
+ [aStream space; nextPut: $(.<br>
+ val printOn: aStream base: 10 length: 1 padded: false.<br>
+ aStream nextPut: $)]].<br>
+ (fields at: index + 1) ~~ #cr ifTrue:<br>
+ [aStream tab]]]!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r0 (in category 'accessing') -----<br>
+ r0<br>
+ ^self unsignedLongAt: 13!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r0: (in category 'accessing') -----<br>
+ r0: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 13 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r1 (in category 'accessing') -----<br>
+ r1<br>
+ ^self unsignedLongAt: 17!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r10 (in category 'accessing') -----<br>
+ r10<br>
+ ^self unsignedLongAt: 53!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r10: (in category 'accessing') -----<br>
+ r10: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 53 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r11 (in category 'accessing') -----<br>
+ r11<br>
+ ^self unsignedLongAt: 57!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r11: (in category 'accessing') -----<br>
+ r11: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 57 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r12 (in category 'accessing') -----<br>
+ r12<br>
+ ^self unsignedLongAt: 61!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r12: (in category 'accessing') -----<br>
+ r12: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 61 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r1: (in category 'accessing') -----<br>
+ r1: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 17 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r2 (in category 'accessing') -----<br>
+ r2<br>
+ ^self unsignedLongAt: 21!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r2: (in category 'accessing') -----<br>
+ r2: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 21 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r3 (in category 'accessing') -----<br>
+ r3<br>
+ ^self unsignedLongAt: 25!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r3: (in category 'accessing') -----<br>
+ r3: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 25 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r4 (in category 'accessing') -----<br>
+ r4<br>
+ ^self unsignedLongAt: 29!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r4: (in category 'accessing') -----<br>
+ r4: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 29 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r5 (in category 'accessing') -----<br>
+ r5<br>
+ ^self unsignedLongAt: 33!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r5: (in category 'accessing') -----<br>
+ r5: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 33 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r6 (in category 'accessing') -----<br>
+ r6<br>
+ ^self unsignedLongAt: 37!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r6: (in category 'accessing') -----<br>
+ r6: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 37 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r7 (in category 'accessing') -----<br>
+ r7<br>
+ ^self unsignedLongAt: 41!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r7: (in category 'accessing') -----<br>
+ r7: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 41 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r8 (in category 'accessing') -----<br>
+ r8<br>
+ ^self unsignedLongAt: 45!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r8: (in category 'accessing') -----<br>
+ r8: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 45 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r9 (in category 'accessing') -----<br>
+ r9<br>
+ ^self unsignedLongAt: 49!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>r9: (in category 'accessing') -----<br>
+ r9: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 49 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>registerState (in category 'accessing-abstract') -----<br>
+ registerState<br>
+ ^{ self r0. self r1. self r2. self r3. self r4. self r5. self r6. self r7.<br>
+ self r8. self r0. self r10. self r11. self r12. self sp. self lr. self pc. self eflags }!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>reset (in category 'accessing') -----<br>
+ reset<br>
+ self primitiveResetCPU!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>retOpcode (in category 'opcodes') -----<br>
+ retOpcode<br>
+ "the ret command does not generally exist. the most similar would be mov pc, lr"<br>
+ ^ self halt.!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>sflag (in category 'accessing') -----<br>
+ sflag<br>
+ ^self unsignedLongAt: 589!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>sp (in category 'accessing') -----<br>
+ sp<br>
+ ^self unsignedLongAt: 65!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>sp: (in category 'accessing') -----<br>
+ sp: anUnsignedInteger<br>
+<br>
+ ^self unsignedLongAt: 65 put: anUnsignedInteger!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>vflag (in category 'accessing') -----<br>
+ vflag<br>
+ ^self unsignedLongAt: 581!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlien>>zflag (in category 'accessing') -----<br>
+ zflag<br>
+ ^self unsignedLongAt: 573!<br>
<br>
Item was added:<br>
+ TestCase subclass: #GdbARMAlienTests<br>
+ instanceVariableNames: 'processor'<br>
+ classVariableNames: ''<br>
+ poolDictionaries: ''<br>
+ category: 'Cog-Processors-Tests'!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>callTrapPerformance: (in category 'tests') -----<br>
+ callTrapPerformance: n<br>
+ "Call a function that is out-of-range. Ensure the call is trapped."<br>
+ "self new testCallTrap"<br>
+ | memory |<br>
+ "The address is out of range of memory every which way (whether relative or absolute and whether big-endian or little."<br>
+ memory := ByteArray new: 1024.<br>
+ memory replaceFrom: 1 to: 5 with: { self processor callOpcode. 0. 16r80. 16r80. 0. } asByteArray.<br>
+ self processor<br>
+ eip: 0;<br>
+ esp: (memory size - 4). "Room for return address"<br>
+ 1 to: n do:<br>
+ [:ign|<br>
+ [self processor singleStepIn: memory]<br>
+ on: ProcessorSimulationTrap<br>
+ do: [:ex|]].<br>
+<br>
+ "QSystemProfiler spyOn: [GdbARMAlienTests new callTrapPerformance: 1024*128]"<br>
+ "Time millisecondsToRun: [GdbARMAlienTests new callTrapPerformance: 1024*128] 2463"<br>
+ "Time millisecondsToRun: [1 to: 1024*1024*64 do: [:ign| nil yourself]] 636"<br>
+ "Time millisecondsToRun: [1 to: 1024*1024*64 do: [:ign| nil perform: #ifNotNilDo: with: nil]] 3639"<br>
+ "Time millisecondsToRun: [1 to: 1024*1024*64 do: [:ign| nil perform: #ifNotNilDo:ifNil: with: nil with: nil]] 12401"!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>nfib (in category 'accessing') -----<br>
+ nfib<br>
+ "long fib(long n) { return n <= 1 ? 1 : fib(n-1) + fib(n-2) + 1; }<br>
+ as compiled by arm-elf-gnuabi-gcc fib.c -c -marm<br>
+ also, the jumps are changed by hand."<br>
+ "| bat nfib ip |<br>
+ bat := GdbARMAlienTests new.<br>
+ nfib := bat nfib asWordArray.<br>
+ ip := 0.<br>
+ 23 timesRepeat:<br>
+ [bat processor disassembleInstructionAt: ip In: nfib into:<br>
+ [:da :len|<br>
+ Transcript nextPutAll: da; cr; flush.<br>
+ ip := ip + len]]"<br>
+ ^#("00000000 <fib>:<br>
+ 0:" 16re92d4810 "push {r4, fp, lr} fp = r11, sp is changed in this command<br>
+ 4:" 16re28db008 "add fp, sp, #8 now, the frame pointer is changed<br>
+ 8:" 16re24dd00c "sub sp, sp, #12<br>
+ c:" 16re50b0010 "str r0, [fp, #-16]<br>
+ 10:" 16re51b3010 "ldr r3, [fp, #-16] r3 <- [fp-16] <- r0<br>
+ 14:" 16re3530001 "cmp r3, #1<br>
+ 18:" 16rda00000c "ble 50 <fib+0x50><br>
+ 1c:" 16re51b3010 "ldr r3, [fp, #-16]<br>
+ 20:" 16re2433001 "sub r3, r3, #1<br>
+ 24:" 16re1a00003 "mov r0, r3<br>
+ 28:" 16rebfffff4 "bl 0 <fib><br>
+ 2c:" 16re1a04000 "mov r4, r0<br>
+ 30:" 16re51b3010 "ldr r3, [fp, #-16]<br>
+ 34:" 16re2433002 "sub r3, r3, #2<br>
+ 38:" 16re1a00003 "mov r0, r3<br>
+ 3c:" 16rebffffef "bl 0 <fib><br>
+ 40:" 16re1a03000 "mov r3, r0<br>
+ 44:" 16re0843003 "add r3, r4, r3<br>
+ 48:" 16re2833001 "add r3, r3, #1<br>
+ 4c:" 16rea000000 "b 54 <fib+0x54><br>
+ 50:" 16re3a03001 "mov r3, #1<br>
+ 54:" 16re1a00003 "mov r0, r3<br>
+ 58:" 16re24bd008 "sub sp, fp, #8<br>
+ 5c:" 16re8bd8810 "pop {r4, fp, pc}")!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>processor (in category 'accessing') -----<br>
+ processor<br>
+ processor ifNil:<br>
+ [processor := GdbARMAlien new].<br>
+ ^processor!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>registerGetters (in category 'accessing') -----<br>
+ registerGetters<br>
+ ^#(r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 lr sp pc)!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>registerSetters (in category 'accessing') -----<br>
+ registerSetters<br>
+ ^#(r0: r1: r2: r3: r4: r5: r6: r7: r8: r9: r10: r11: r12: lr: sp: pc:)!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>runNFib:disassemble:printRegisters: (in category 'execution') -----<br>
+ runNFib: n disassemble: disassemble printRegisters: printRegisters<br>
+ "Run nfib wth the argument. Answer the result."<br>
+ "self new runNFib: 5 disassemble: true printRegisters: true"<br>
+ | memory |<br>
+ memory := WordArray new: 1024 * 2 withAll: self processor nopOpcode.<br>
+ memory replaceFrom: 1 to: self nfib size with: self nfib asWordArray startingAt: 1.<br>
+ self processor<br>
+ r0: n;"argument n"<br>
+ lr: memory size * 2; "return address"<br>
+ pc: 0;<br>
+ sp: (memory size * 4) - 16.<br>
+ printRegisters ifTrue:<br>
+ [self processor printRegistersOn: Transcript.<br>
+ Transcript cr; flush].<br>
+ "run until something goes wrong."<br>
+ self processor runInMemory: memory readExecuteOnlyBelow: memory size / 2.<br>
+ printRegisters ifTrue:<br>
+ [self processor printRegistersOn: Transcript.<br>
+ Transcript cr; flush].<br>
+ ^self processor r0!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>singleStepNFib:disassemble:printRegisters: (in category 'execution') -----<br>
+ singleStepNFib: n disassemble: disassemble printRegisters: printRegisters<br>
+ "Run nfib wth the argument. Answer the result."<br>
+ "self new runNFib: 5 disassemble: true printRegisters: true"<br>
+ | memory |<br>
+ memory := WordArray new: 1024 * 2 withAll: self processor nopOpcode.<br>
+ memory replaceFrom: 1 to: self nfib size with: self nfib asWordArray startingAt: 1.<br>
+ self processor<br>
+ r0: n; "argument n"<br>
+ lr: self nfib size * 4; "return address"<br>
+ pc: 0;<br>
+ sp: (memory size * 4 - 12). "Room for return address, frame pointer and r4"<br>
+ printRegisters ifTrue:<br>
+ [self processor printRegistersOn: Transcript.<br>
+ Transcript cr; flush].<br>
+ [disassemble ifTrue:<br>
+ [Transcript nextPutAll: (self processor disassembleNextInstructionIn: memory); cr; flush].<br>
+ self processor singleStepIn: memory readExecuteOnlyBelow: memory size * 4 / 2.<br>
+ printRegisters ifTrue:<br>
+ [self processor printRegistersOn: Transcript.<br>
+ Transcript cr; flush].<br>
+ "stop, once we leave the nfib code and step through the nops after that."<br>
+ self processor pc < (self nfib size * 4)] whileTrue.<br>
+ ^self processor r0!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testCallTrap (in category 'tests') -----<br>
+ testCallTrap<br>
+ "Call a function that is out-of-range. Ensure the call is trapped."<br>
+ "self new testCallTrap"<br>
+ | memory |<br>
+ memory := Bitmap new: 256 withAll: self processor nopOpcode.<br>
+ memory longAt: 1 put: (self processor branchAndLinkOpcodeWithOffset: 1024) bigEndian: false.<br>
+ memory := memory asByteArray.<br>
+ self processor<br>
+ pc: 0;<br>
+ sp: (memory size - 4); "Room for return address"<br>
+ singleStepIn: memory.<br>
+ "We have to step twice, because the first step only changes the pc, but does not fetch anything from the address it points to."<br>
+ self should: [self processor singleStepIn: memory]<br>
+ raise: Error<br>
+ withExceptionDo:<br>
+ [:pst|<br>
+ self assert: self processor pc = 1024.<br>
+ self assert: self processor lr = 4.<br>
+ self assert: pst messageText = 'Error 0: Illegal Instruction fetch address (0x00000400).'].!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testDisassembling (in category 'tests') -----<br>
+ testDisassembling<br>
+<br>
+ | memory result |<br>
+ memory := WordArray new: 2.<br>
+ memory at: 1 put: 16rEF200000.<br>
+ result := self processor<br>
+ disassembleInstructionAt: 0<br>
+ In: memory<br>
+ into: [:str :len |<br>
+ self<br>
+ assert: len = 4;<br>
+ assert: str = 'svc 0x00200000'].!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testExecutionTrap (in category 'tests') -----<br>
+ testExecutionTrap<br>
+ "Execute a run of nops. test executing beyond the executable limit is trapped."<br>
+ "self new testExecutionTrap"<br>
+ | memory |<br>
+ "The address is out of range of memory every which way (whether relative or absolute and whether big-endian or little."<br>
+ memory := (Bitmap new: 1024 * 2 withAll: self processor nopOpcode) asByteArray.<br>
+ self processor<br>
+ pc: 0;<br>
+ sp: (memory size - 4). "Room for return address"<br>
+ self should: [self processor runInMemory: memory minimumAddress: 0 readOnlyBelow: memory size / 2]<br>
+ raise: Error<br>
+ withExceptionDo:<br>
+ [:err|<br>
+ self assert: self processor pc = (memory size / 2).<br>
+ self assert: ('Error 0: Illegal Instruction fetch address (0x00001000).' match: err messageText)].<br>
+ self processor pc: 0.<br>
+ self should: [[self processor singleStepIn: memory minimumAddress: 0 readOnlyBelow: memory size / 2] repeat]<br>
+ raise: Error<br>
+ withExceptionDo:<br>
+ [:err|<br>
+ self assert: self processor pc = (memory size / 2).<br>
+ self assert: ('Error 0: Illegal Instruction fetch address (0x00001000).' match: err messageText)]!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testFlags (in category 'tests') -----<br>
+ testFlags<br>
+ "self new testFlags"<br>
+ | memory |<br>
+ memory := Bitmap new: 3.<br>
+ memory longAt: 1 put: 16rE3A03001 bigEndian: false. "MOV r3, #1"<br>
+ memory longAt: 5 put: 16rE3530001 bigEndian: false. "CMP r3, #1"<br>
+ memory := memory asByteArray.<br>
+ self processor<br>
+ disassembleInstructionAt: 0<br>
+ In: memory<br>
+ into: [:str :len |<br>
+ self<br>
+ assert: len = 4;<br>
+ assert: str = 'mov r3, #1'].<br>
+ self processor<br>
+ disassembleInstructionAt: 4<br>
+ In: memory<br>
+ into: [:str :len |<br>
+ self<br>
+ assert: len = 4;<br>
+ assert: str = 'cmp r3, #1'].<br>
+ self processor<br>
+ pc: 0;<br>
+ singleStepIn: memory;<br>
+ singleStepIn: memory.<br>
+ self<br>
+ assert: self processor pc = 16r8;<br>
+ assert: self processor r3 = 1;<br>
+ assert: self processor zflag = 1;<br>
+ assert: self processor cflag = 1;<br>
+ assert: self processor vflag = 0;<br>
+ assert: self processor nflag = 0.<br>
+ self processor reset.<br>
+ self assert: self processor eflags = 3. "IFFlags are both set."!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testMOVSD (in category 'tests') -----<br>
+ testMOVSD<br>
+ "Test MOVSD indirecting through edx."<br>
+ "self new testMOVSD"<br>
+ self processor<br>
+ edx: 0;<br>
+ eip: 0;<br>
+ singleStepIn: {16rF2. 16r0F. 16r10. 16r42. 16r04. 16r90. 16r01. 16r02. 16r03. 16r04. 16r05. 16r06} asByteArray "movsd %ds:0x4(%edx), %xmm0;nop;garbage".<br>
+ self assert: self processor eip = 5.<br>
+ self assert: self processor xmm0low = 16r0605040302019004!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testNfib1 (in category 'tests') -----<br>
+ testNfib1<br>
+ "self new testNfib1"<br>
+ self should: [self runNFib: 1 disassemble: false printRegisters: true]<br>
+ raise: Error<br>
+ withExceptionDo:<br>
+ [:err| self assert: err messageText = 'Error 0: Illegal Instruction fetch address (0x00001000).'].<br>
+ self deny: (self processor pc between: 0 and: self nfib size).<br>
+ self assert: self processor r0 = 1 benchFib!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testNfib16 (in category 'tests') -----<br>
+ testNfib16<br>
+ "self new testNfib16"<br>
+ self should: [self runNFib: 16 disassemble: false printRegisters: false]<br>
+ raise: Error.<br>
+ self deny: (self processor pc between: 0 and: self nfib size).<br>
+ self assert: self processor r0 = 16 benchFib!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testNfib2 (in category 'tests') -----<br>
+ testNfib2<br>
+ "self new testNfib2"<br>
+ self should: [self runNFib: 2 disassemble: false printRegisters: false]<br>
+ raise: Error.<br>
+ self deny: (self processor pc between: 0 and: self nfib size).<br>
+ self assert: self processor r0 = 2 benchFib!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testNfib4 (in category 'tests') -----<br>
+ testNfib4<br>
+ "self new testNfib4"<br>
+ self should: [self runNFib: 4 disassemble: false printRegisters: false]<br>
+ raise: Error.<br>
+ self deny: (self processor pc between: 0 and: self nfib size).<br>
+ self assert: self processor r0 = 4 benchFib!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testResetCPU (in category 'tests') -----<br>
+ testResetCPU<br>
+ "self new testResetCPU"<br>
+ self registerSetters do:<br>
+ [:setter|<br>
+ self processor perform: setter with: 16r55555555].<br>
+ self registerGetters do:<br>
+ [:getter|<br>
+ self assert: 16r55555555 = (self processor perform: getter)].<br>
+ self processor reset.<br>
+ self registerGetters do:<br>
+ [:getter|<br>
+ self assert: 0 = (self processor perform: getter)]!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testStepNfib1 (in category 'tests') -----<br>
+ testStepNfib1<br>
+ "self new testStepNfib1"<br>
+ self singleStepNFib: 1 disassemble: false printRegisters: false.<br>
+ self assert: self processor pc = (self nfib asWordArray size * 4).<br>
+ self assert: self processor r0 = 1 benchFib!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testStepNfib2 (in category 'tests') -----<br>
+ testStepNfib2<br>
+ "self new testStepNfib2"<br>
+ self singleStepNFib: 2 disassemble: false printRegisters: false.<br>
+ self assert: self processor pc = (self nfib size * 4).<br>
+ self assert: self processor r0 = 2 benchFib!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMAlienTests>>testStepNfib4 (in category 'tests') -----<br>
+ testStepNfib4<br>
+ "self new testStepNfib4"<br>
+ self singleStepNFib: 4 disassemble: false printRegisters: false.<br>
+ self assert: self processor pc = (self nfib size * 4).<br>
+ self assert: self processor r0 = 4 benchFib!<br>
<br>
Item was added:<br>
+ SmartSyntaxInterpreterPlugin subclass: #GdbARMPlugin<br>
+ instanceVariableNames: 'prevInterruptCheckChain'<br>
+ classVariableNames: ''<br>
+ poolDictionaries: 'VMBasicConstants'<br>
+ category: 'Cog-ProcessorPlugins'!<br>
+<br>
+ !GdbARMPlugin commentStamp: '<historical>' prior: 0!<br>
+ I provide access to the ARMulator ARM emulator and the libopcodes ARM disassembler.!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMPlugin class>>declareCVarsIn: (in category 'translation') -----<br>
+ declareCVarsIn: aCCodeGenerator<br>
+ "prevInterruptCheckChain lives in sqGdbARMPlugin.c"<br>
+ super declareCVarsIn: aCCodeGenerator.<br>
+ aCCodeGenerator removeVariable: 'prevInterruptCheckChain'!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMPlugin class>>hasHeaderFile (in category 'translation') -----<br>
+ hasHeaderFile<br>
+ "We need a header to declare newcpu and pull in bochs.h & cpu.h"<br>
+ ^true!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMPlugin>>forceStopOnInterrupt (in category 'interruption') -----<br>
+ forceStopOnInterrupt<br>
+ interpreterProxy getInterruptPending ifTrue:<br>
+ [self forceStopRunning]!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMPlugin>>primitiveDisassembleAt:InMemory: (in category 'primitives') -----<br>
+ "cpuAlien <GdbARMAlien>" primitiveDisassembleAt: address "<Integer>" InMemory: memory "<Bitmap|ByteArray|WordArray>"<br>
+ "Return an Array of the instruction length and its decompilation as a string for the instruction at address in memory."<br>
+ | cpuAlien cpu instrLenOrErr resultObj log logLen logObj logObjData |<br>
+ <var: #cpu type: #'void *'><br>
+ cpuAlien := self primitive: #primitiveDisassembleAtInMemory<br>
+ parameters: #(Unsigned WordsOrBytes)<br>
+ receiver: #Oop.<br>
+ (cpu := self startOfData: cpuAlien) = 0 ifTrue:<br>
+ [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].<br>
+ instrLenOrErr := self disassembleFor: cpu<br>
+ At: address<br>
+ In: memory<br>
+ Size: (interpreterProxy byteSizeOf: memory cPtrAsOop).<br>
+ instrLenOrErr < 0 ifTrue:<br>
+ [^interpreterProxy primitiveFailFor: PrimErrInappropriate].<br>
+ log := self getlog: (self cCode: [self addressOf: logLen] inSmalltalk: [logLen := 0]).<br>
+ resultObj := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: 2.<br>
+ resultObj = 0 ifTrue:<br>
+ [^interpreterProxy primitiveFailFor: PrimErrNoMemory].<br>
+<br>
+ "Easier keeping the damn thing on the stack than using pushRemappableOop:/popRemappableOop.<br>
+ Where is topRemappableOop when you need it?"<br>
+ interpreterProxy pushRemappableOop: resultObj.<br>
+ logObj := interpreterProxy<br>
+ instantiateClass: interpreterProxy classString<br>
+ indexableSize: logLen.<br>
+ interpreterProxy failed ifTrue:<br>
+ [interpreterProxy popRemappableOop.<br>
+ ^interpreterProxy primitiveFailFor: PrimErrNoMemory].<br>
+ logObjData := interpreterProxy arrayValueOf: logObj.<br>
+ self cCode: 'memcpy(logObjData, log, logLen)' inSmalltalk: [logObjData. log].<br>
+ resultObj := interpreterProxy popRemappableOop.<br>
+ interpreterProxy<br>
+ storePointer: 0<br>
+ ofObject: resultObj<br>
+ withValue: (interpreterProxy integerObjectOf: instrLenOrErr).<br>
+ interpreterProxy storePointer: 1 ofObject: resultObj withValue: logObj.<br>
+<br>
+ ^resultObj!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMPlugin>>primitiveErrorAndLog (in category 'primitives') -----<br>
+ primitiveErrorAndLog<br>
+ | log logLen resultObj logObj logObjData |<br>
+ <var: #log type: #'char *'><br>
+ <var: #logObjData type: #'char *'><br>
+ self primitive: #primitiveErrorAndLog parameters: #().<br>
+<br>
+ log := self getlog: (self cCode: [self addressOf: logLen] inSmalltalk: [logLen := 0]).<br>
+ resultObj := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: 2.<br>
+ resultObj = 0 ifTrue:<br>
+ [^interpreterProxy primitiveFailFor: PrimErrNoMemory].<br>
+<br>
+ interpreterProxy<br>
+ storePointer: 0<br>
+ ofObject: resultObj<br>
+ withValue: (interpreterProxy integerObjectOf: self errorAcorn).<br>
+<br>
+ logLen > 0 ifTrue:<br>
+ [interpreterProxy pushRemappableOop: resultObj.<br>
+ logObj := interpreterProxy<br>
+ instantiateClass: interpreterProxy classString<br>
+ indexableSize: logLen.<br>
+ interpreterProxy failed ifTrue:<br>
+ [interpreterProxy popRemappableOop.<br>
+ ^interpreterProxy primitiveFailFor: PrimErrNoMemory].<br>
+<br>
+ resultObj := interpreterProxy popRemappableOop.<br>
+ logObjData := interpreterProxy arrayValueOf: logObj.<br>
+ self cCode: 'memcpy(logObjData, log, logLen)' inSmalltalk: [logObjData. log].<br>
+ interpreterProxy storePointer: 1 ofObject: resultObj withValue: logObj].<br>
+ interpreterProxy pop: 1 thenPush: resultObj!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMPlugin>>primitiveFlushICacheFrom:To: (in category 'primitives') -----<br>
+ "cpuAlien <GdbARMAlien>" primitiveFlushICacheFrom: startAddress "<Integer>" To: endAddress "<Integer>"<br>
+ "Flush the icache in the requested range"<br>
+ | cpuAlien cpu |<br>
+ <var: #cpu type: 'void *'><br>
+ cpuAlien := self primitive: #primitiveFlushICacheFromTo<br>
+ parameters: #(Unsigned Unsigned)<br>
+ receiver: #Oop.<br>
+ (cpu := self startOfData: cpuAlien) = 0 ifTrue:<br>
+ [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].<br>
+ self flushICache: cpu From: startAddress To: endAddress!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMPlugin>>primitiveNewCPU (in category 'primitives') -----<br>
+ primitiveNewCPU<br>
+ | cpu |<br>
+ <var: #cpu type: 'void *'><br>
+ self primitive: #primitiveNewCPU parameters: #().<br>
+<br>
+ cpu := self cCode: 'newCPU()' inSmalltalk: [0].<br>
+ cpu = 0 ifTrue:<br>
+ [^interpreterProxy primitiveFail].<br>
+ interpreterProxy<br>
+ pop: 1<br>
+ thenPush: (interpreterProxy positive32BitIntegerFor:<br>
+ (self cCoerceSimple: cpu<br>
+ to: 'unsigned long'))!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMPlugin>>primitiveResetCPU (in category 'primitives') -----<br>
+ primitiveResetCPU<br>
+ | cpuAlien cpu maybeErr |<br>
+ <var: #cpu type: 'void *'><br>
+ cpuAlien := self primitive: #primitiveResetCPU parameters: #() receiver: #Oop.<br>
+ (cpu := self startOfData: cpuAlien) = 0 ifTrue:<br>
+ [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].<br>
+ maybeErr := self resetCPU: cpu.<br>
+ maybeErr ~= 0 ifTrue:<br>
+ [^interpreterProxy primitiveFailFor: PrimErrInappropriate].<br>
+ ^cpuAlien!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMPlugin>>primitiveRunInMemory:minimumAddress:readOnlyBelow: (in category 'primitives') -----<br>
+ "cpuAlien <GdbARMAlien>" primitiveRunInMemory: memory "<Bitmap|ByteArray|WordArray>" minimumAddress: minAddress "<Integer>" readOnlyBelow: minWriteMaxExecAddress "<Integer>"<br>
+ "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."<br>
+ | cpuAlien cpu maybeErr |<br>
+ <var: #cpu type: #'void *'><br>
+ cpuAlien := self primitive: #primitiveRunInMemoryMinimumAddressReadWrite<br>
+ parameters: #(WordsOrBytes Unsigned Unsigned)<br>
+ receiver: #Oop.<br>
+ (cpu := self startOfData: cpuAlien) = 0 ifTrue:<br>
+ [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].<br>
+ prevInterruptCheckChain := interpreterProxy setInterruptCheckChain: #forceStopOnInterrupt asSymbol.<br>
+ prevInterruptCheckChain = #forceStopOnInterrupt asSymbol ifTrue:<br>
+ [prevInterruptCheckChain = 0].<br>
+ maybeErr := self runCPU: cpu<br>
+ In: memory<br>
+ Size: (interpreterProxy byteSizeOf: memory cPtrAsOop)<br>
+ MinAddressRead: minAddress<br>
+ Write: minWriteMaxExecAddress.<br>
+ interpreterProxy setInterruptCheckChain: prevInterruptCheckChain.<br>
+ maybeErr ~= 0 ifTrue:<br>
+ [^interpreterProxy primitiveFailFor: PrimErrInappropriate].<br>
+ ^cpuAlien!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMPlugin>>primitiveSingleStepInMemory:minimumAddress:readOnlyBelow: (in category 'primitives') -----<br>
+ "cpuAlien <GdbARMAlien>" primitiveSingleStepInMemory: memory "<Bitmap|ByteArray|WordArray>" minimumAddress: minAddress "<Integer>" readOnlyBelow: minWriteMaxExecAddress "<Integer>"<br>
+ "Single-step the cpu using the first argument as the memory and the following arguments defining valid addresses."<br>
+ | cpuAlien cpu maybeErr |<br>
+ <var: #cpu type: #'void *'><br>
+ cpuAlien := self primitive: #primitiveSingleStepInMemoryMinimumAddressReadWrite<br>
+ parameters: #(WordsOrBytes Unsigned Unsigned)<br>
+ receiver: #Oop.<br>
+ (cpu := self startOfData: cpuAlien) = 0 ifTrue:<br>
+ [^interpreterProxy primitiveFailFor: PrimErrBadReceiver].<br>
+ maybeErr := self singleStepCPU: cpu<br>
+ In: memory<br>
+ Size: (interpreterProxy byteSizeOf: memory cPtrAsOop)<br>
+ MinAddressRead: minAddress<br>
+ Write: minWriteMaxExecAddress.<br>
+ maybeErr ~= 0 ifTrue:<br>
+ [^interpreterProxy primitiveFailFor: PrimErrInappropriate].<br>
+ ^cpuAlien!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMPlugin>>sizeField: (in category 'alien support') -----<br>
+ sizeField: rcvr<br>
+ "Answer the first field of rcvr which is assumed to be an Alien of at least 8 bytes"<br>
+ <inline: true><br>
+ ^self longAt: rcvr + BaseHeaderSize!<br>
<br>
Item was added:<br>
+ ----- Method: GdbARMPlugin>>startOfData: (in category 'alien support') -----<br>
+ startOfData: rcvr "<Alien oop> ^<Integer>"<br>
+ "Answer the start of rcvr's data. For direct aliens this is the address of<br>
+ the second field. For indirect and pointer aliens it is what the second field points to."<br>
+ <inline: true><br>
+ ^(self sizeField: rcvr) > 0<br>
+ ifTrue: [rcvr + BaseHeaderSize + BytesPerOop]<br>
+ ifFalse: [self longAt: rcvr + BaseHeaderSize + BytesPerOop]!<br>
<br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div><br>
</div>