P2 PASM indentation for delayed instructions and repeated instructions
Cluso99
Posts: 18,069
I like the use of pasm indentation for the REP instructions, as illustrated in a number of the Video sample programs posted...
However, I think the delayed instructions may be better having a single indent, and the repeated instructions using a double indent.
reps #256, #2 'first 256 pixels / exactly one line nop 'spare wrbyte tmp3, ptra++ 'write one pixel and move ptra onto next one add tmp3, #1 'tmp3 keeps track of grey (0..255) djnz y,#bufwr 'loop to fill buffer
However, I think the delayed instructions may be better having a single indent, and the repeated instructions using a double indent.
reps #256, #2 'first 256 pixels / exactly one line nop 'spare wrbyte tmp3, ptra++ 'write one pixel and move ptra onto next one add tmp3, #1 'tmp3 keeps track of grey (0..255) djnz y,#bufwr 'loop to fill bufferAny thoughts???
Comments
I'm not following ? ASM usually does not care about indent, and in your example, it seems to convey no information, as there is a #2 hard coded in reps line ?
If you wanted to add some structure to ASM, it would be better to do it in a more user-portable manner.
Few users will expect column-position/indent, to matter in ASM code.
If reps always needs a NOP, then it would be clearer to add a Macro-like version where users can write
would expand (just like a macro would) to give your lines, in the LST file.
The REP_END provides the coverage, and users do not have to remember to edit in two places, when adding/commenting lines.
We now have "delayed" instructions which execute 1 or more instructions before the jump/etc is performed. If we
use a single indent then this makes it easy to know those instructions are delayed instructions. Similarly, for the repeated instructions, a suggested indent of 2 makes it easy to see which instructions are the subject of the repeat. Sure, if there are only #2 you might realise this. But isn't it easier to just look and see which instructions are indented 2 places??? And what if there are #15 repeated... you would have to count the number of instructions... much easier if they are indented as a group.
That reveals a larger problem: I think the opcode handling should automate the #2 or #15
You are right that users should not have to count instructions, but indent does not provide the #15.
I would use a Macro style, (ie generate any needed NOPs, as part of the structure), but a minimal ASM style like this would also auto-set the line count.
and I would like to see PASM dragged toward a more universal assembler syntax. Many users code in more than one Assembler.
Quirks are simply annoying (and unnecessary).
On the topic of smarter assemblers, because PASM is such a corner-stone of Props, it should allow Higher level Assembler Structure more, so
IF-ELSE-ELSIF-ENDIF coding, removes label tedium from users, but does not remove the low-level control.
In general I hate macros and the PASM syntax is one of the simplest and best of any assembler I have ever used. Aided by the regularity of the Prop's instruction set. Any "universal assembler" syntax would have to be very nice to compete.
P.S: When did this "universal assembler syntax" idea turn up? It's a few decades since I did any serious ASM programming, apart from the Propeller, and for sure there was no such thing back then.
Edit: After googling around for 5 minutes I haven't found any references to any "universal assembler syntax". Do you have any examples?
I would like to see macros for LMM use.
jmg: IF.... are in bst and homespun. We all await this and includes in the new compiler.
As for "universal assembler syntax" I have never seen such. The first thing a standard would need to do is standardise the source and destination order, and then the comment leadin character(s).
However, some people really go to town with them, producing effective, if somewhat difficult to understand code. A good macro assembler, capable of LMM would enable both of these things. Of course, that means some standard type of kernel, or a means to define one as part of the code body to be assembled too.
Exactly, as long as we are talking Spin and PASM, not C and GAS, any such complexity should be kept out of it. Spin and PASM have been designed to be simple and easy for the new or casual programmer. Put advanced features in there an soon it will infect all code in places like OBEX and the newcomer will be bewildered and give up before even starting.
I started out programming on ICL, I forget the model our Uni had initially but the next year they got a shiny, new and huge 2960. That was in ALGOL, we didn't get near assembler on that monster except via a simulator or VM for some mythical didactic architecture.
You will not find it labeled that, but try and find ANY other assembler that expects this
Then, try this in every Assembler I have used
These are not mutually exclusive, so a better PASM would support the first for legacy code, and the second for users of most other Assemblers....
Intel ASMs are some of the longest lived out there, so they are a good example of 'expected assembler syntax'.
15 seconds on Google finds this :
http://en.wikipedia.org/wiki/Assembler_%28computing%29#Assembler
I've also seen Assemblers that allow 0xAA, or 0A5H or $5A, and some better ones allow '_' as well as either 0b1111 or 1111B
Back in the day when we had no assembler for the 6809, we tried to make use of an "assembler kit" somebody at Cambridge university had made. Basically a set of tools to enable you to define your own assembler easily. That was great but would not run on the only minicomputer we had access to as it was to big!
GCC comes with GAS which has been used for many architectures of course.
PASM of course has it's quirks as you point out. Nothing you can't live with after half an hours use. The jmp and # thing is interesting in that it is consistent with all the other op codes. Making it otherwise violates the principle of least surprise.
jmp address vs jmp (address) is immediate or literal vs indirect. Most assemblers, because most CPUS work this way.
jmp #address vs jmp address is immediate or literal vs indirect. Propeller, because it works this way.
This is an artifact of how the COG addressing works. In either case, the programmer must decide where they want their jump address to come from.
*immediate or literal are both present due to terminology I've seen over the years. I believe we call it a literal in Prop Land, but the effect is the same, namely the value is contained in the instruction itself, and in the case of multi-byte instructions on byte based processors, contained immediately after the instruction opcode, which is all just one big 32 bit blob on the 32 bit Prop.
As Pasm can only handle 0-511 immediate values and as a cog jmp only have 512 possible locations to jump to anyway,
it make sense to use a immediate value for the jmp (saves a long)
As indirect jmp values are permitted so someway you have to tell the compiler what you intend, that is where the # comes in.
If you are serious about "the principle of least surprise", then you simply design an assembler that is less fussy, and simply 'works as expected'.
Prop 2 gives a chance to do it properly.
Once you have to use a quirk-qualifier like "Nothing you can't live with after half an hours use", you have an admission of failure.
This is really
jmp Label vs jmp RegName or even jmp @RegName or jmp (RegName)
because a 'good' assembler knows labels, from registers, even with no qualifier there is no confusion.
It will simply do what you expect.
Yes, future Prop Tools should be able to tell that this is label name and have a setting for auto-correct or ask for each instances.
It should also have ask if you intended to use shadow-reg to help beginners with Read-only registers.
Sounds cool.
And there you get to the crux of the issue. Because depending on how you look at it a COG is all memory and has no registers or is all registers and has no memory. How can the assembler know automatically what you intend to be a variable/register and what you intend to be a label? They all live in the same space and are totally interchangeable.
When you deal with self modifying code on the COG, which is necessary for some operations, the same label can be a label on an instruction and a variable/register at the same time.
Contrast this with most other processors where "A", "B", "r0", "r1" or whatever are always registers and "foo", "bar" are always labels on memory locations.
You can see "jmp foo" as "mov pc, foo". It's he same as "mov bar, foo" except we don't have the program counter in the address space but "bar" is user a user defined location. So we now need to distinguish between the literal value of foo as an immediate address and the contents of foo as an indirect address. Same as we do in the mov case.
For that one needs a special modifier on foo, # or @ or something. Or one needs to make a special case out of the jmp instruction, like "jmp foo" means jmp to literal vaue of foo as an immediate label. But that is inconsistent with the other instructions and, even worse. still requires a special modifier syntax for when we want to jump indirect. The worst of both worlds.
Due to all the above I think the current syntax is optimal for the Propeller architecture. The Prop is different from other CPU's in this respect and the assembler syntax reflects that.