P2 PASM indentation for delayed instructions and repeated instructions

Cluso99Cluso99 Posts: 15,656
edited 2013-03-18 - 16:03:38 in Propeller 2
I like the use of pasm indentation for the REP instructions, as illustrated in a number of the Video sample programs posted...
                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 buffer
Any thoughts???
My Prop boards: P8XBlade2 , RamBlade , CpuBlade , TriBlade
P1 Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
Website: www.clusos.com
P1: Tools (Index) , Emulators (Index) , ZiCog (Z80)
P2: Tools & Code , Tricks & Traps

Comments

  • cgraceycgracey Posts: 12,132
    edited 2013-03-14 - 22:48:29
    Indention certainly makes it clear, but I see one minor problem: the mnemonics are all 7 characters or less, so that an 8-space tab can be issued to get to the operand. To accommodate indention, it might be good to increase the 8-character mnemonic-start-to-operand-start to maybe 12 characters. This means something like a 4-space tab system would be better.
  • jmgjmg Posts: 14,175
    edited 2013-03-16 - 03:46:35
    Cluso99 wrote: »
    I like the use of pasm indentation for the REP instructions, as illustrated in a number of the Video sample programs posted...
    Any thoughts???

    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
       REPEAT  256
                  wrbyte tmp3, ptra++        'write one pixel and move ptra onto next one
                  add    tmp3, #1               'tmp3 keeps track of grey (0..255)
       REP_END
    
    

    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.
  • Cluso99Cluso99 Posts: 15,656
    edited 2013-03-16 - 18:59:19
    jmg wrote: »
    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
       REPEAT  256
                  wrbyte tmp3, ptra++        'write one pixel and move ptra onto next one
                  add    tmp3, #1               'tmp3 keeps track of grey (0..255)
       REP_END
    
    

    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.
    Indentation in pasm is just a way to make readability better. It is purely optional. But it is much better that we agree to a standard now, and we can all work on the same page.

    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.
    My Prop boards: P8XBlade2 , RamBlade , CpuBlade , TriBlade
    P1 Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    P1: Tools (Index) , Emulators (Index) , ZiCog (Z80)
    P2: Tools & Code , Tricks & Traps
  • jmgjmg Posts: 14,175
    edited 2013-03-17 - 12:43:50
    Cluso99 wrote: »
    Indentation in pasm is just a way to make readability better. It is purely optional. But it is much better that we agree to a standard now, and we can all work on the same page.
    Ok, as a 'convention' it makes sense
    Cluso99 wrote: »
    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.
                 reps   256 _rep_end3-$-1
                     nop
                     wrbyte tmp3, ptra++        'write one pixel and move ptra onto next one
                     add    tmp3, #1               'tmp3 keeps track of grey (0..255)
                 _rep_end3:
    

    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.
  • potatoheadpotatohead Posts: 9,957
    edited 2013-03-17 - 12:56:54
    That's basically the kind of tool Linus wrote. IMHO, a macro assembler, capable of LMM would be very potent. Instead of SPIN + PASM, it ends up PASM + PASM.
    Do not taunt Happy Fun Ball! @opengeekorg ---> Be Excellent To One Another SKYPE = acuity_doug
  • Heater.Heater. Posts: 21,233
    edited 2013-03-17 - 23:41:06
    Presumably that "spare" NOP need not be a NOP at all. It could be an instruction that does some useful work. As such the suggested macro approach would hide it and prevent you making use of that instruction.

    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?
  • Cluso99Cluso99 Posts: 15,656
    edited 2013-03-18 - 00:04:08
    Heater. wrote: »
    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.
    heater, you have never seen the ICL System 10/25 Assembler. The use of complex macros was a subject on it's own - extremely powerful!!! All the OS calls were macros, as were the FCBs (File Control Blocks).

    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).
    My Prop boards: P8XBlade2 , RamBlade , CpuBlade , TriBlade
    P1 Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    P1: Tools (Index) , Emulators (Index) , ZiCog (Z80)
    P2: Tools & Code , Tricks & Traps
  • potatoheadpotatohead Posts: 9,957
    edited 2013-03-18 - 00:13:09
    I'll second Heater's syntax comment. I really love PASM syntax "Parallax Style" as seen in Prop Tool, etc... As far as macros go, I like very light use of them personally, and that's so the reading of the code is centered on real instructions as much as possible.

    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.
    Do not taunt Happy Fun Ball! @opengeekorg ---> Be Excellent To One Another SKYPE = acuity_doug
  • Heater.Heater. Posts: 21,233
    edited 2013-03-18 - 00:43:33
    Cluso,
    The use of complex macros was a subject on it's own...

    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.
  • TorTor Posts: 1,985
    edited 2013-03-18 - 02:26:36
    I like macros, but I often don't like the way macros are done.. so I tend to instead quickly write my own macro handler in Perl and then add one step in the Makefile. Then I get the output of the macro translation stage as well as the original 'macro version' source. I do this kind of stuff for all kinds of things, not just programming. Music notation languages, for example.
  • jmgjmg Posts: 14,175
    edited 2013-03-18 - 04:21:29
    Heater. wrote: »
    Edit: After googling around for 5 minutes I haven't found any references to any "universal assembler syntax". Do you have any examples?

    You will not find it labeled that, but try and find ANY other assembler that expects this
    :loop  
              jmp #:loop     'Loop endlessly
    

    Then, try this in every Assembler I have used
    loop:
              jmp   loop   ; Loop endlessly
    

    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
  • Heater.Heater. Posts: 21,233
    edited 2013-03-18 - 05:14:41
    Well, of course there are such things as "universal assemblers", in a way.
    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.
  • potatoheadpotatohead Posts: 9,957
    edited 2013-03-18 - 08:15:49
    Well that was going to be my comment. The octothorpe is needed due to how the instruction works. It's not really a syntax problem.

    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.
    Do not taunt Happy Fun Ball! @opengeekorg ---> Be Excellent To One Another SKYPE = acuity_doug
  • tonyp12tonyp12 Posts: 1,950
    edited 2013-03-18 - 08:16:08
    >The jmp and # thing

    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.
  • jmgjmg Posts: 14,175
    edited 2013-03-18 - 12:37:29
    Heater. wrote: »
    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.

    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.
  • jmgjmg Posts: 14,175
    edited 2013-03-18 - 12:42:26
    potatohead wrote: »

    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 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.
  • tonyp12tonyp12 Posts: 1,950
    edited 2013-03-18 - 13:23:49
    >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.
  • jmgjmg Posts: 14,175
    edited 2013-03-18 - 14:12:11
    tonyp12 wrote: »
    >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.
  • Heater.Heater. Posts: 21,233
    edited 2013-03-18 - 16:03:38
    jmg,
    ...because a 'good' assembler knows labels, from registers, even with no qualifier there is no confusion.
    It will simply do what you expect.

    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.
Sign In or Register to comment.