PDA

View Full Version : MOVD instruction bug?



ozpropdev
02-07-2007, 04:26 PM
Hi guys

I beleive I have discovered a bug with the MOVD instruction. My application like most others requires the passing of pointers from one cog (running SPIN code) to another (running Propeller assembly code). Basically i have an array containg pointers to all the varaibles i wish to access.

The first pointer is to a variable that contains the number of pointers to follow.
This seems simple enough using a loop implementing self modifying code to sequentially retreive the pointers and place them in COG ram.

start·· mov·fx,par··'get pointer to my array
········ rdlong· ax,fx··'get pointer to number of entries
········ rdlong· cx,ax··'get number of entries
······· ·mov···· bx,#pointer0·'set start of cog ram storage area
again· movd··· zzz,bx··'set destination··'
zzz···· rdlong· 0,fx··'read/store pointer
········ add···· bx,#1··'increment destination
········ add···· fx,#4··'adjust pointrer
········ djnz··· cx,#again·'repeat (cx) times
········ jmp·#somewhere_else
.
.
ax·········res·1
bx········ res·1
cx········ res·1
fx········· res·1
poinrer0· res·1
poinrer1· res·1
poinrer2· res·1
.
.
poinrer9· res·1

Not a big program as you can see but it failed!
Further investigation revealed the first RDLONG at address ZZZ returned a LONG from an incorrect address. All subsequent RDLONG operations worked
fine. Extensive testing of this program showed no change in outcome regardless of pointer addresses or cog ram origin. Even using a different cog
had no effect.

The bug seems to be related to modifying code that is the next instruction to be processed. Simply placing a NOP instruction between the MOVD and RDLONG instructions fixed the problem!

Any ideas out there?
·

Paul Baker
02-07-2007, 04:44 PM
The issue is you didnt place an instruction between MOVD and it's target instruction. Because the next instruction is fetched before the results of the previous instruction are written you need to have an intervening instruction.

The way I do this without having to insert a NOP is to place the MOVD after the target instruction, so you would place the MOVD immediately before the DJNZ, then insert·an intialization MOVD above your loop where there is at least 1 instruction·in between it and the loop. This way you dont have to waste an extra·4 cycles in each iteration and it consumes the same amount of space as the NOP technique. Ive demonstrated this in the following code, the bold lines signify the changes.


start mov fx,par 'get pointer to my array
mov bx,#pointer0 'set start of cog ram storage area
movd again,bx
rdlong ax,fx 'get pointer to number of entries
rdlong cx,ax 'get number of entries
again rdlong 0,fx 'read/store pointer
add bx,#1 'increment destination
add fx,#4 'adjust pointrer
movd again,bx 'set destination '
djnz cx,#again 'repeat (cx) times
jmp #somewhere_else
.
.
ax res 1
bx res 1
cx res 1
fx res 1
poinrer0 res 1
poinrer1 res 1
poinrer2 res 1
.
.
poinrer9 res 1


Check out the Tricks & Traps sticky thread, it covers this and many other "gotchas" commonly encountered.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker (mailto:pbaker@parallax.com)
Propeller Applications Engineer
[/url][url=http://www.parallax.com] (http://www.parallax.com)
Parallax, Inc. (http://www.parallax.com)

Post Edited (Paul Baker (Parallax)) : 2/7/2007 10:00:38 AM GMT

ozpropdev
02-07-2007, 06:09 PM
Thanks Paul for your quick response.
I must of missed that bit in the tricks and traps document... Oops!