Calling a Constant
Hi All;
I need to have identical assembly code in several cogs, and of course the compilerI cannot have multiple assembler DAT blocks each having identical symbol names. So to rectify that I place several identical binary blobs in the editor, and use CONstants to define the various symbol names and their cog addresses. So far so good.
Then I have various pieces of assembler for each cog that must access it's binary blob at specific label locations as defined by the CONstants. That all works fine except for the CALL instruction which causes the compiler to throw an "expected a DAT symbol" error. I presume that is because the compiler can't find the call's _RET symbol in the binary blob eventhough it is listed in the CONstants.
It would be real nice if the assembler could be forced to use CONstants as arguments..... BST will also not do what I want, it recognizes and lists the symbol, but assigns a zero for it's value.
Does anyone know of a way to trick the compiler around this problem ? (I wish not to unfold the identical binary blobs and personalize the labels of each one)
Thanks for looking.
Cheers,
Peter (pjv)
I need to have identical assembly code in several cogs, and of course the compilerI cannot have multiple assembler DAT blocks each having identical symbol names. So to rectify that I place several identical binary blobs in the editor, and use CONstants to define the various symbol names and their cog addresses. So far so good.
Then I have various pieces of assembler for each cog that must access it's binary blob at specific label locations as defined by the CONstants. That all works fine except for the CALL instruction which causes the compiler to throw an "expected a DAT symbol" error. I presume that is because the compiler can't find the call's _RET symbol in the binary blob eventhough it is listed in the CONstants.
It would be real nice if the assembler could be forced to use CONstants as arguments..... BST will also not do what I want, it recognizes and lists the symbol, but assigns a zero for it's value.
Does anyone know of a way to trick the compiler around this problem ? (I wish not to unfold the identical binary blobs and personalize the labels of each one)
Thanks for looking.
Cheers,
Peter (pjv)

Comments
Is this because each PASM instance has it's own HUB workspace? If so, I believe, you could assign HUB addresses when the cog starts.
You will need a constant for the RET position in the binary blob and then replace the call with:
Andy
If there is some configuration different to each instance why not pass than in via a par parameter block?
@Mike: The code is proprietary at this point so I can't post. To answer your question, for each cog, the binary blobs are identical, but the other assembler codes are different. So to load a blob followed by it's specific code requires a new org 0 for each instance, and each cognew instruction must reference each blob/specific section separately, hence their names must be different.
@Andy: What you describe is precisely what I am doing, and that works fine, but it is a little cryptic, so I was hoping to somehow use the CALL/RET psuedocodes to make things clearer..... Sounds like a non-starter.
@Heater: Same answer as Mike. The differences are assembly code programs.
Looks like I'll have to stick with the less obvious approach. Thanks again guys,
Cheers,
Peter (pjv)
-Phil
I'm having a bit of a hard time to explain this properly... that probably means I don't fully understand it myself, although with the JMPRET method it does work properly, it just looks messy
Each cog must have the universal binary blob, immediately followed by its specific assembler code. In order to load the various cogs from spin they each must have a unique starting address (set to org 0 as you suggest) which will then load the consecutive 512 (less SFRS) longs into the respective cog. This implies multiple copies of the identical binary blobs, yet they can all be accessed via a pre-determined list of CONstant addresses. And all this works just fine.
The only trouble is with the compiler error when I use a CALL/RET instruction into the blob. It will work if I intersperse the blob with lables at salient points, but then again the labels mut be unique for each blob, and that becomes even messier than the JMPRET approach. So I guess I have my answer.
Thanks for reading.
Cheers,
Peter (pjv)
PUB start cognew(@code0, @data0) cognew(@code1, @data0) DAT '------[ Blob data ]----------------------------------------------------------- org 1 'Blob block that gets copied to each cog data0 long 12345 data1 long 67890 data2 long 1234567890 '-------[ First cog program ]-------------------------------------------------- code0 org 0 'Beginning of first cog. jmp start0 'Jump over blob block. long 0[data2 - data0] 'Cog location of copied blob data. start0 movs loop0,par 'Setup to read blob data into cog. mov cnt0,#3 'Reading three longs. loop0 rdlong 1,#0-0 'Read a long. add loop0,_0x204 'Increment both source and destination addresses. djnz cnt0,#loop0 'Back for another. 'From here, you can address data0 .. data2 using those lobels. mov cnt0,data0 'This loads from cog location 1. _0x204 long $204 cnt0 res 1 '-------[ Second cog program ]------------------------------------------------- code1 org 0 jmp start1 'Same as above. long 0[data2 - data0] start1 movs loop0,par mov cnt1,#3 loop1 rdlong 1,#0-0 add loop1,_1x204 djnz cnt1,#loop1 'From here, you can address data0 .. data2 using those lobels. mov cnt1,data2 'This loads from cog location 3. _1x204 long $204 cnt1 res 1Since you stated that you want ed the blob located at the beginning of the cog, you don't save any hub space doing it this way, but you can address the blob data by their common names in each cog. Now, if you were to read the blob into the end of the cog, instead of the beginning, you would save hub space.
-Phil
Thank you. I have not yet decided for sure if I want my blob (actually it is my Spin-friendly multi-tasking scheduler) to reside at the beginning or at the end of the cog there are pluses and minuses to each approach.
I will need to try what you are suggesting, but I suspect that in the application code following the blob, the compiler will not let me do a CALL into the blob.
Example: call #data1
But all other instructions referencing data1 etc. ARE permitted.
Cheers,
Peter (pjv)
I'm afraid my code includes a bug. The statement,
will work only if the blob is fully located within the first 512 bytes of hub space, which is unlikely. As a consequence, you would have to store the value in par into another variable and use it at the source of the rdlong without the #. In that case two separate address increments are necessary in the transfer loop.
-Phil
The current blob (simple version scheduler) will just fit as it is 80 longs plus a dozen or so local variables. A next, more capable version will likely just be too large.
I'm wondering if by chance you have tested this with a CALL instruction into the blob ? Everything else you describe is already familiar to me. It just this silly CALL issue. I can't test it until after tomorrow.
Thanks for your interest.
Cheers,
Peter (pjv)
PUB start cognew(@code0, @data0) cognew(@code1, @data0) DAT '------[ Blob data ]----------------------------------------------------------- org 0 'Blob block that gets copied to each cog data0 long 12345 subr nop subr_ret ret data1 long 67890 data2 long 1234567890 '-------[ First cog program ]-------------------------------------------------- code0 org 0 'Beginning of first cog. jmp start0 'Jump over blob block. long 0[data2 - data0] 'Cog location of copied blob data. start0 movs addr0,par 'Setup to read blob data into cog. mov cnt0,#data2 - data0 + 1 'Reading longs. loop0 rdlong 0-0,addr0 'Read a long. add loop0,_0x200 'Increment both source and destination addresses. add addr0,#4 djnz cnt0,#loop0 'Back for another. 'From here, you can address data0 .. data2 using those labels. mov cnt0,data0 'This loads from cog location 1. _0x200 long $200 cnt0 res 1 addr0 res 1 '-------[ Second cog program ]------------------------------------------------- code1 org 0 jmp start1 'Same as above. long 0[data2 - data0] start1 movs addr1,par mov cnt1,#data2 - data0 + 1 loop1 rdlong 0-0,addr1 add loop1,_1x200 add addr1,#4 djnz cnt1,#loop1 'From here, you can address data0 .. data2 and call subr using those labels. mov cnt1,data2 'This loads from cog location 6. call #subr 'This calls the subroutine at location 2 _1x200 long $204 cnt1 res 1 addr1 res 1Note that I've fixed the rdlong ... #0-0 error and also am overwriting the jmp startx at the beginning of each cog.
This is untested code, BTW, except for verifying compilation.
-Phil
I can see that I'm still failing to describe my issue properly..... or perhaps I'm too much of bonehead !
The binary blob I have is just a DAT section of lines of hex bytes, as in byte $xx, $yy, $zz, etc for about 300 elements. Then in a CON section I have all the salient addresses defined in hex. So, there are no labels in the hex DAT section. I was hoping to CALL a routine in the blob via it's address in the CON section. This works for (I believe) all instructions, but not for a CALL.
Cheers,
Peter (pjv)
-Phil
If you mean calling some code at some address given by a constant that's something we can think about.
The problem here is that a CALL needs to save its return address somewhere. Most processors save return addresses on the stack, the propeller however stores it into the location of the return instruction of the subroutine being called. That is why you have:
someFunction ...code ...code ...code someFunction_ret RET call #someFunctionHere the return address is stored into the RET instruction at someFunction_retClearly if you are calling into a "binary blob" of code it is not possible to use a CALL instruction as it does not have any "..._ret" label at which to store a return address. That is to say the assembler cannot deal with: (Which I believe is what you mean by "calling a constant".
You would need to use JMPRET. With JMPRET you specify the lable of the function to JMP to and the lable of the place where the function can find its return address.
someFunction ...code ...code ...code JMP returnAddress JMPRET retAddr, #someFunction ...' Returns to here. ... ... retAdder long 0Here the JMPRET stores the return address at retAddr and the jumps to the function. When the function is done it jumps via the return address back to the calling code.In this case you can use constants: Problem of course now is that the binary blob and the caller have to agree on a location of retAddr (99) which will have to be fixed some how.
N.B. My PASM syntax may not be quite right here I have not hacked on this for a while.
Does this sound like what you are trying to do?
If so why do you need a binary "blob of" code with the resultant anonymous addresses fixed up by constant definitions?
DAT ' black box section org 10 s0 res 4 s0_ret org 20 s1 res 9 s1_ret DAT org 0 ' active code entry call #s0 call #s1I'm truly sorry for all the confusion... this thread has turned into a bit of a mess.
Heater has the right idea. I have code as a list of BYTEs in a DAT block. I have CONstants defined as address labels for some locations in the code (my binary blob). Several of those CONstants are named as CALL/RET pairs such as PAUSE and PAUSE_RET, or SUSPEND and SUSPEND_RET. Then further down, outside of the binary blob I wish to make calls to and returns from those PAUSE/PAUSE_RET etc. labels. And THAT'S the part that will not compile, and is the basis of my query. Only a CALL instruction into the blob using the CON defined labels will not compile, all others seem to be OK.
My reason for enclosing the blob as anonymous hex in a DAT block is that it is a small scheduler intended for use by others, and should not be messed with because it is quite convoluted. So, as stated earlier, instead of CALLs to those blob locations, JMPRETs will work, its just more confusing for other users I think.
Sorry again folks, I had not intended to abuse the forum or the respondents this way.
Cheers,
Peter (pjv)
IIRC, orgs don't work that way, since the address pointer changes after the org. This might work, however:
DAT org 10 blob1 org 14 blob1_ret-Phil
Dave and Phil, this is precisely the "trick" I was hoping for. It works perfectly.
Many thanks to all contributors ! Oh how I love this forum and this chip. Yet another case of making it do what was not intended. Marvelous.
Cheers,
Peter (pjv)
DAT ' black box section org 10 s0 res 4 s0_ret org 20 s1 res 9 s1_retI had not picked up sufficiently on your suggestion..... so far I have not (needed to) use the res directive.
But what you offer will probably work, I will try it..... Your suggestions are always well thought out, and deserve serious consideration.
Thank you.
Peter (pjv)
As expected, your suggestion works perfectly.
Both, Dave's as well as yours produce identical results, as per:
All is well, and it does considerably visually clean up my applications that CALL into the binary blob.
Thanks again all.
Cheers,
Peter (pjv)