Is there a better description of the p2 instructions than the Rev B doc and spreadsheet?
Steve_Hatch
Posts: 19
in Propeller 2
I am looking for a better description of the PASM instructions for the P2 than what is in the documentation for the Rev B silicon and the instruction spreadsheet. I'm having a hard time understanding the documentation. Abbreviations are used without explanation. There is a lot of assumed knowledge that I don't have. In the old P1 book, there was a fair explanation for each instruction that included some examples of usage. More than the ddddddddd sssssssss type of discussion. I am assuming because the P2 is so new that this type of documentation hasn't been developed yet, although if I wait it will become available. I'm just too impatient. I am just wondering if there is something I'm not aware of.
Steve
Steve
Comments
You'll likely find a lot of answers in Propeller 2 forum threads, although sure - that can be a lot of digging sometimes!
Best advice for now, is to ask anything you need in the Propeller 2 thread, or use the Search box. There's lot's of experts here that have the knowledge you seek!
It has some details that I don't think are anywhere else...
Actually, I guess that isn't much help...
I guess the good news is that P2 ASM is largely a superset of P1 ASM.
So, the reads and moves and shifts work more or less the same way.
One thing about the spreadsheet is that it often has exact FPGA code for the result. So, if you can read Verilog (I think it was), then you're in good shape.
The documentation file is a pretty good resource though.
What abbreviations need explaining?
I think anybody can make notes in the documentation if more explanation is needed...
Note that many of the P2 base instructions are the same as the P1 base instructions, with just the bit positions being different, and of course there is no 'NR' bit, and the no-op condition '0000' is now an implied _RET_.
Most condition flags are the same, but not all.
The more complex instructions are explicitly documented in the big google doc. Things like how to use all the ALTx instructions, uses of SETQ and it's Q register, HUBSET, COGINIT, SKIP, REP, RDFAST, ... SETCMOD colour space config. How to config events and interrupts. Even the Cordic instructions have their section. Streamers and smartpins too of course.
Also, a lot of people would write "mov 0-0,sp" on the next line where "0-0" just means that it is a value that will be overwritten...
Steve
Is this just a test or are you trying to do something because there is a small 8 deep stack internally in each COG that supports calls/returns as well as push/pop. There are also registers PTRA/PTRB/PA/PB that can be used as pointers to registers with auto increment/decrement that can be useful for creating stacks especially in HUB and possibly in COG or LUT too.
I'd guess Steve is just using a stacking mechanism to test out the ALTx instructions.
I've reproduced your code with comments updated to cover what actually happens and some efficiencies added
Here's code that is closer to what I think you want, if you specifically want to use cog ram (a limited resource) for your stack:
lut ram is also worth considering for stacks as you have the rdlut and wrlut instructions that can update the pointer automatically as part of the operation. and as @Cluso99 has mentioned, there's a hardware stack in each cog, and hubram is a viable option for stacks too.
Here is the link to the static pubdoc version too.
If so, it would be nice if this was documented in the P2 documentation (if it hasn't already been changed). Searching the forums for this type of information is iffy at best.
The biggie here is that the P1 JMPRET/CALL/RET (and JMP) instructions are completely different in P2. You just cannot replace them, as each case requires understanding the P1 code. I should have pushed for a JMPRET instruction equivalent on P2 much earlier but it’s now too late. As we are now finding, nothing translates easily, so we are basically back to a new code write. P2 is a new animal that shares some common ideas with P1.
The instruction spreadsheet alludes to a stack "K". But I don't see any definition of that stack.
The docs mention the stack - in passing - as part of the EXECF instruction documentation. Yes, I am learning that the hard way. My 1130 emulator instruction decoding was based on altering a JMP instruction. Boy, that didn't work on the P2!
I am having major difficulties understanding switching between cog and hub execution. I believe it has something to do with relative vs. absolute addressing but have not yet gotten this to work properly (other than my issue with cog initialization, which works fine, the issue is with calling hub subroutines once I've returned to cog execution). I've make sure to use ORGH $400 and the like without any success.
Does anyone have some sample code that shows cog-to-hub subroutine calls?
Umm, isn't CALLD basically P2's JMPRET ?
There's really nothing to switching between cog and hub: the processor does it automatically based on the PC (if the PC is 0-$1ff, then code runs from COG; if it's $200-$3ff then it runs from LUT; if it's $400 and above it runs from HUB). Any program compiled by fastspin does this at startup automatically: the initial setup code is in COG memory, it calls the main user program in HUB memory, and if that returns then the COG program does a cogstop. So the really stripped down version would look like:
It's similar but not the same. On a P1 a JMPRET would only patch the S field in the destination register with the return address, and the destination register written would typically already be an actual JMP #S instruction. On a P2 a CALLD will write the PC (and flags) into the entire register and so it cannot remain a JMP instruction after this. You will need an additional indirect JMP instruction to emulate the P1's "RET" pseudo instruction which is actually just the JMP #S anyway.
Now I think Cluso has had problems translating his P1 PASM code because of this particular difference. There are certainly some ways in the P2 to try to emulate it but they all basically take up additional code space.
Here's your code, modified to show progress (or lack of it). When I run this (with PNut v34Q), both led's 61 & 62 are lit, but 56 does not. In addition, there should be a 1/4 second pause between 61 & 62 being lit; there is none.
Edit: When I run this with FlexGUI 4.1.3, it does work.
So it appears to me that the subroutine "my_hubcode" is never called with PNut.
Note that there is a compile message: "warning: orgh with explicit origin does not work if Spin methods are present".
If that still doesn't help, then you should probably report a bug to Chip, because I think it should work (and, as you discovered, it does work when compiled with fastspin/flexgui).
I wouldn't be surprised if Spin2 needs some tweaks to make it all right.
Therefore your hubcode is being assigned a address of $18. So the P2 assumes a cog address (<$400) which has no valid code at that address.
Your code works fine in PASM only form.
You can also pad out hubram with a LONG statement after the orgh directive.
Pnut seems to put DAT blocks before the spin interpreter code.
See this for calling the ROM monitor routines
https://forums.parallax.com/discussion/comment/1450717/#Comment_1450717
Yes, that worked for me. @cgracey, this seems to be an issue with PNut v34Q not handling the orgh correctly for spin2 + pasm. Not a major issue (other than my bald spot is getting larger).
Here's a simple way to do it, by passing the 'hubcode' through PTRA (3rd term in COGINIT):
You can also use PTRB, which will contain the absolute address of 'cogcode' on entry, as a base to which you add the offset of 'hubcode'. Both 'cogcode' and 'hubcode' addresses in PASM are relative to the start of the object they exist in, not the absolute addresses of where they wind up at:
You will need to modify the ptrb for every hub-call, which is ugly, slow and needs a lot of unnecessary cog code.
It would all be so much easier if we get the real hub address with @ in DAT blocks.
Andy