View Full Version : Pointers in DAT space

08-30-2007, 05:37 PM
G'day all,
this one has me wondering.

If I declare a table in DAT space.. something like


word $0000, $0001, $0002

I can reference it from spin

somevar := @crctable
and that works fine


somevar long @crctable

does not if I reference it from within its cog in asm.. (see further down for a contrived example)

I end up having to declare a variable in spin, use somevar := @crctable and pass the address of somvar in my par block
then read it from assembler in the cog.

long somevar
PUB start
somevar := @crctable
coginit (@asmcode, @somevar)

asmcode org
rdlong Pcrctable, par

Pcrctable res 1

Most frustrating.. is there something I'm doing wrong? or do I have to pass pointers to all my globally declared data using the par blocks?

I'm doing a 16 bit crc in the cog asm code,

crc16byte ' dc has the byte to add to the crc
xor dc, crc ' 3
and dc, #$FF ' 4
shl dc, #1 ' 5
add dc, Pcrcmask ' 6
rdword db, dc ' 11.5
shr crc, #8 ' 12.5
xor crc, db ' 13.5
crc16byte_ret ret ' 14.5

My problem is I have to pass "Pcrcmask" into the cog using spin, I just can't seem to get a pointer to the table at compile time in the DAT block....

The CRC table and the cog code are all in the same object, in the same DAT block. That, at least works...

08-30-2007, 05:55 PM

you have to use the following code to reference the table in your assembly code.


somevar long crctable

But I don't know why it should be necessary. You can access the table also in your program.

mov tableptr,#crctable

The @ operator is only used in spin to reference a memory address.

08-30-2007, 08:01 PM
Hmm, that won't work for me. I perhaps did not make myself as clear as I might have.

The crc table is 256 words (128 longs) and resides in the HUB, not in the cog running the code. Thus I need to know the address of the table in HUB locations.

I was somewhat hoping to be able to put that into the cog variables at compile time.

Thanks for the thought though.

08-30-2007, 09:13 PM

sorry, this fact was not well known from your code snippets.
But then you could use the following code.

PUB start
somevar := @crctable
coginit (@asmcode, 0)


somevar long 0

You don't need a variable in spin. So the second argument on coginit is free for other use.

08-30-2007, 10:23 PM
Duh, now why didn't I think of that!

Lovely! that should do it nicely.

I'm already using a pretty big parameter block for passing large buffers back and forward, this way I don't have to make it even bigger.

08-30-2007, 10:31 PM
I shall add this to the "Best Practices Section" in the tutorial. I did not not consider it neccesary - as being obvious - but I see the same questions and answers here week for week...

08-30-2007, 11:15 PM
I hadn't really thought it obvious. I was more struggling to understand why the compiler would do one thing when compiling spin, and something completely different when compiling the DAT area.

What would be the use of @ in the DAT area? Or more accurately, what does it do?

Paul Baker
08-30-2007, 11:30 PM
Brad, it has to do with scope. The only addresses which are automatically resolved for a assembly cog are those addresses which fall within it's own 496 long boundry. Since your reference DAT section is outside this area you must explicitly communicate it's location to the assembly code.

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)) : 8/30/2007 4:57:17 PM GMT

08-30-2007, 11:40 PM
Right, Brad, it is NOT obvious. But there are many components involved here...
I just copy some lines I posted some days ago:
There are four (!) sorts of @ in SPIN

(-1) One is used to find the address-offset of a DAT-Variable as a constant. This is a little bit tricky. There is something like a "constant-context" during the SPIN compilation, where all constant expressions are evaluated; this happens most notably in the CON section, but also whenever the directive constant(…) is used in
PUB/PRI, between the square brackets in the VAR section, and for all presets in the DAT section. (However these four situations are NOT ALWAYS handled equally by the compiler, e.g. DAT references can only be used in DAT itself and within constant(…); and the names of I/O registers (which have a value between ($1f0 and $1ff) in DAT only. I think this is an unnecessary artificial restriction.)

Notably for presetting DAT cells address-offsets are very handy (@datname), it can be added to them, or even differences can be stated (@end-@start or constant(@end-@start)); most other operations are more or less dangerous http://forums.parallax.com/images/smilies/smile.gif

However these are not (HUB-)addresses, but just some numbers (relative byte addresses to be precise) to be offset later! The reason is, that during the evaluation of constants the compiler is not yet in the situation to understand where the addressed variables will be allocated to!

(-2) The second kind of @ is the address of DAT variables as such (@datname NOT in a constant context); this number is known by the compiler when generating the code.

(-3) The third kind of @ is an address of VAR variables. Why is there a difference? Well you can instantiate more one object, which will lead to a multiplication of the VAR section, but there will be only ONE code section. Thus the poor code cannot know for which object it will have to work. This has to be computed from case to case dynamically!

(-4) The fourth kind of @ is the address of a "local" variable (or a routine parameter). As SPIN routines can be called recursively this is an address in the stack, different from call to call, but independent of the object instantiation.

(-5) What? Fifth? Well, there is a SPIN Operator called @@ …
For the situation (1) - and for this situation only! - that address offset can be converted to a value corresponding to situation (2)

X := constant(@datvar)
Y := @datvar
Z := @@X

Now : X < Y and Y == Z http://forums.parallax.com/images/smilies/smile.gif