...... The @ could become some other character for this use case.
My personal preference is to have no special char prefixes on any labels, when used as labels (aka code destinations), as that is what every other assembler I use does.
I know the old P1 assembler was different, but it is not hard to support the wider use, and deprecate the older form - Older code can be supported with a Assembler switch,
Removing label prefixes also allows Assemblers like gas, yasm et al ( & Maybe PNUT?) to segment check for illegal destinations.
Coding in (some) ASM on P2 is going to be common, so safety nets matter.
It's a backward reference label. Every other label is a forward reference label. That is what is special about it.
The "exit" bit was just misunderstanding.
As for hard edits, every other label works in the same way, meaning people are generally going to put them on the same line as the target, and or operate with the forward reference assumption. (which isn't an entirely safe assumption)
Would be nice to make sure an unambiguous use were permitted though. (label on line) Guess I'll be using line count and indent.
No worries. If it remains backward reference, people will ask why, and I'm perfectly happy to explain all of it to them.
:P
Edit: Just saw this on Peter's Tachyon thread:
rep @.L0,tos1
wfbyte tos
.L0 jmp #DROP3
I'm NOT happy. That's a backward reference. Every other reference is a forward one. Not cool.
Yeah, your post right above mine sucks. It's a backward reference. Literally every other label in Propeller land is a forward reference. And to make things worse, the best practice is to not put labels on a line by themselves in assembly land. Why? For this exact reason. But, if labels are allowed on a line by themselves, they all need to behave the same way. Now they don't.
Guess I'll call those the jmg labels. I'll bookmark this for later. It's stupid. A lot of P1 users will misread these.
rep @.L0,tos1
wfbyte tos
.L0 jmp #DROP3
rep @.L0,tos1
wfbyte tos
.L0
jmp #DROP3
rep @.L0,tos1
wfbyte tos
' Comment can go here
.L0 ' Comment can go here
'Comment can go here
jmp #DROP3
The first one is a forward reference in that the label references the next eligible item. It being on the same line makes that unambiguous, and that idea goes way back in assembly land. I learned about it all in the early 80's. And in a packed code listing, that forward reference idea is the only idea that makes any sense. Who wants to think about a label referencing the line above? It's confusing, which is why it's not done the very vast majority of the time.
The second one, given an assembler that treats labels as a forward reference, will include jmp in the rep loop. But, we've now carved out an exception to label handling. So this label would reference the thing preceding it. And that's not necessarily "any assembler" at all. Maybe some you have used, but I'll bet a cookie they are filled with a bunch of other difficult to think about stuff.
Principle of least surprise here too:
[Here is how labels work. simple forward reference rule]
Student: Ok, so it's the next thing. Got it. Cool. Next. (that's literally all they need to know)
[example of rep shown]
Student: But why is that one backward?
[but see? It's easy to read...]
Student: But it doesn't work the same. Can't I just always put a label on a line and know it will work every single time?
[discussion on sadly, no because....]
Now there is a more complicated discussion on references, the concept of a block, etc... And the end result really doesn't add any more value, and will actually confuse existing PASM users, who until now could operate with a simple, global forward reference rule.
The third one is a cluster**** and isn't really worth any discussion, save to say it's technically no different than the second one, due to comments being transparent.
As for "any assembler" the P1 tools would get those label references wrong, as would the P2 tools, because the standard in Propeller land is to always forward reference labels. Now it's that, except for this thing.
I almost always put labels on lines by themselves. To me it is easier to edit and since i've been doing it so long, it reads correctly. Currently, my P2 code is a mess of begged, borrowed, stolen and patched up stuff. Once i'm back in rhythm it should look better.
Historically, I do it because of punched cards. It's much easier to edit card decks if your label is on its own card.
The current implementation makes sense to me so far as i've used it.
Hmmmm, what's the problem? I didn't see any problem in coding and it didn't confuse me either. In all assembly I've ever done that I jump to a label then that label is not the instruction itself, just the address of the instruction, it still has to be executed. So if I rep to a label then it's to an address, not an "instruction". Labels only resolve to addresses, not instructions.
Chip mentioned two modes, reading and writing and the possibility of a label that moves! That's even worse! Now stuff isn't where a person puts it, and we now have to talk about modes and states...
By contrast, the simple forward reference label rule takes about two seconds, and the person is done with understanding labels, until they are ready for local labels, which they will be after writing a little code filled with loop1, loop2, etc... or they want to make pre-written snippets, etc... And if they learn that rule and apply it, they get it right nearly all the time with about zero effort.
Except for rep. See how that all works?
The bizarre thing is I agree with you on a label case, and I agree in that it avoids line counting too. All good.
Hosing up labels wasn't worth that though. It's not worth it, because the most obvious use, that will occur to people when they learn about labels is the one people actually can't use because one of us thought a backward reference was a good idea for one case.
I'm not sure what the problem really is. To me there is only one sane way for labels to behave:
label instr
next_instr
*must* behave the same as
label
instr
next_instr
As for forward/backward, I don't think it's right to think about two kinds of labels. REP is a bit special as far as instructions go, but I don't see any problem understanding the code, *if* the label behaves as above. Which, if I have not misunderstood, is what jmg wants.
I almost always put labels on lines by themselves. To me it is easier to edit and since i've been doing it so long, it reads correctly.
Yup, I tend to place major branch labels on their own lines, (often with a comment) and sometimes I'll place local short labels, on the same line as an ASM statement.
HLL generated code tends to use own-line-labels.
HLL example 1
Well, maybe this helps to understand where the friction is.
$0000 nop
$0004 label 'forward reference rule applied. A backward reference would be label address $0000
$0004 add
As far as I can recall, I've not seen any PASM anywhere that references the thing before the address of a label. (programmer can make expression for that, if they want) It's always the thing AT or CONTAINED in the address assigned to the label, which in text, visual form, is the forward reference rule.
Rep will use the address before, and I suppose this is just like the count from 0 inherent in the rep instruction. Both are similar ambiguities. It's the only thing that uses the address before the label, as it stands right now too.
If I perform a jmp to label above, I land on the add instruction. It's contained in the memory at address $0004. If I do a rep targeting the label above, I get the nop instruction as the end of the loop, which is not contained by the memory at the address assigned to the label.
Every other label use will reference the add, except for REP.
In very simple terms, if I want to reference something except for REP as it stands now, I can apply the same rule. Put that thing and it's label on the same line and it's gonna work. Seems to me the best case is to keep that rule consistent. Which means labeling the end of the loop, not the thing after the end of the loop.
Doing that makes as much sense as counting the number of instructions to loop from 0. And the goal of it all was to make more sense.
Seems to me, one "doesn't make sense" was seen as a potential source of ambiguity, and rightfully so, only to be replaced with another one.
Users do not care what the binary level opcode is, and REP simply and clearly uses the label as the place it goes when done.
Implicit in that is that yes, rep includes the line above that label in the loop, the label is an exit location, which is what labels commonly are.
Destinations to jump to.
There is nothing special in the REP label use here, unless you expect REP to operate differently.
Every other label use will reference the add, except for REP.
Nope, REP also references the add just fine, but treats it as a destination when done, the add is not included inside the REP loop, as it comes after the Label.
(scratch the other comments. Rep is just going to be odd)
@jmg, in every one of those examples, the label address contains the item following the text of the label in the assembly file. In fact, that's the case for everything but REP.
Oh well. We've got much better things to do.
Seriously. "exit location" or "when REP is done, you will be here" both will work to resolve the question, and that's better than "jmg label" I'll take it, but I don't like it. Seems like we didn't have this issue with REP on the "hot" design pass...
Re: Labels on individual lines. Yes! Given the behavior is consistent, it's all good. I suppose I just see REP differently, and that's making the label no-conforming to me. I really do see that as a backward reference, as in the pointer to the last instruction in the REP loop. If one is doing the line count, the count has nothing to do with anything beyond the intended series of instructions for REP to operate on.
Edit: Yes. that's it exactly.
It's the difference between:
"put the label on the instruction you want to execute after REP is done" as opposed to, "put the label on the last instruction in the set to be repeated"
Another way to think of it, "repeat these" as opposed to "go here after repeating these..."
I'm good now. Thanks. Most all of you are seeing it as the next thing to do. I really didn't see it that way at all.
I for sure don't want the label that moves... ugh!
Yep, I'm busy doing it and that way you either get used to something, or you like it or you hate it. Either way it shouldn't stop you from doing something. Personally I'm happy with the way REP has turned out, both with the count=count plus the end=end
Personally I'm happy with the way REP has turned out, both with the count=count plus the end=end
Yes, and the old leading dummy opcode that was not-actually-loop-executed is also gone too, so the new REP is much more user friendly and less error prone. It's a cool opcode
Personally I'd use
REP LabelWhenDoneName,Count
and dispense with the @, as a cleaner version, but that's a minor detail.
0=forever is also nice to have.
There are test & generate cases where you may want a COG to simply loop-forever with minimal overhead.
Doesn't @ now mean address-of, like it does on the P1, and not offset-to as it did for a time? Or did you not release that version yet? (I don't have an FPGA, so I don't remember what the latest released version is like) What's a REP look like now?
I'm good. Please don't futz with it on my account Chip. How it is right now works.
So we have two cases:
REP [number of instructions to repeat - 1], [number of iterations]
, and
REP [@label of instruction executed immediately after operation complete], [number of iterations]
And I think we need to wordsmith that second case some when we get closer to that stage in the process.
I got seriously hung up on the idea of the label pointing to the loop instructions directly, rather than it being implied by the one to get executed next. It really did seem like a backward reference, and I really was not OK with that idea at all.
It's kind of amazing how a perception or expectation difference can alter things! We are very right to hash out syntax, etc... Getting after that is going to pay dividends. I believe that completely, and it's those dividends I want.
On this one, I was totally experiencing very genuine concern over what appeared to be a matter of genuine ambiguity, and I got snarky. Could not believe no one saw it. --which is always a clue, but one that can be difficult for the one having the struggle to see.
(which I find humorous after it's all said and done, jmg If we can't laugh at ourselves, things get kind of ugly. So, I'm laughing! )
This: Yes, and the old leading dummy opcode that was not-actually-loop-executed is also gone too
Totally. That's a P1 thing many have found difficult. Stuffing things into unused "slots" Most common was making the most of the HUB access. Big win here with REP.
Maybe. One could supply a COG register there too. (D/#) Can't just put label name there, because that means "Destination value sourced in COG register at address of label"
CCCC 1100110 1LI DDDDDDDDD SSSSSSSSS REP D/#,S/#
One could have a short and long rep loop, and specify that difference with a COG register. That seems an odd case though, it might make sense for some kind of self-generating / modifying routine or other, running in a COG for speed. Seems a bit crazy. I'm curious what any of you would have in mind for that use case.
"REP D/#, S/#" doesn't allow for a label, given "#" is the line count; thus, "@" at present.
I don't care how we resolve this, or if we do. It's enough to get past the label trouble as far as I'm concerned, but it is an exception to the addressing scheme.
I wondered if the operands should have been swapped to
REP [#]count, [next]/[#instructions-1]
My reasoning is that the DJNZ counter, next
and JMPRET returnaddr, next
In each case, "next" is the next instruction to be executed (ie a goto)
and the "count/return-address" is the "operation".
Now, the "next" part of the REP instruction would be the goto address after the loop is done.
If you really want to take this further, move REP to the end of the block and have the label refer to the beginning of the block. The assembler can then insert the REP in the proper location (at the beginning) in the compiled code. That way, the REP will look like all of the other branch instructions and the label discussion will be moot.
Comments
My personal preference is to have no special char prefixes on any labels, when used as labels (aka code destinations), as that is what every other assembler I use does.
I know the old P1 assembler was different, but it is not hard to support the wider use, and deprecate the older form - Older code can be supported with a Assembler switch,
Removing label prefixes also allows Assemblers like gas, yasm et al ( & Maybe PNUT?) to segment check for illegal destinations.
Coding in (some) ASM on P2 is going to be common, so safety nets matter.
The "exit" bit was just misunderstanding.
As for hard edits, every other label works in the same way, meaning people are generally going to put them on the same line as the target, and or operate with the forward reference assumption. (which isn't an entirely safe assumption)
Would be nice to make sure an unambiguous use were permitted though. (label on line) Guess I'll be using line count and indent.
No worries. If it remains backward reference, people will ask why, and I'm perfectly happy to explain all of it to them.
:P
Edit: Just saw this on Peter's Tachyon thread:
I'm NOT happy. That's a backward reference. Every other reference is a forward one. Not cool.
That's exactly what I've been trying to say, if you are happy now, that's great
See? I misread that one, why?
Because every other freaking label is a forward reference and now we have a backwards one.
Not happy, and I'll edit the above.
?? read them more carefully.
To me, Peter's code is fine, exactly as I expected from Chip's comments.
As too, is this code-style alternative - identical binary.
Yeah, your post right above mine sucks. It's a backward reference. Literally every other label in Propeller land is a forward reference. And to make things worse, the best practice is to not put labels on a line by themselves in assembly land. Why? For this exact reason. But, if labels are allowed on a line by themselves, they all need to behave the same way. Now they don't.
Guess I'll call those the jmg labels. I'll bookmark this for later. It's stupid. A lot of P1 users will misread these.
This is all the same code to any Assembler
I'm lost, how is it backwards ? - it is just a label.
The assembler takes the code the user has written, and creates the binary needed for the opcode.
Chip has this working fine now.
Peter coded fine, and I can read his intent exactly.
The first one is a forward reference in that the label references the next eligible item. It being on the same line makes that unambiguous, and that idea goes way back in assembly land. I learned about it all in the early 80's. And in a packed code listing, that forward reference idea is the only idea that makes any sense. Who wants to think about a label referencing the line above? It's confusing, which is why it's not done the very vast majority of the time.
The second one, given an assembler that treats labels as a forward reference, will include jmp in the rep loop. But, we've now carved out an exception to label handling. So this label would reference the thing preceding it. And that's not necessarily "any assembler" at all. Maybe some you have used, but I'll bet a cookie they are filled with a bunch of other difficult to think about stuff.
Principle of least surprise here too:
[Here is how labels work. simple forward reference rule]
Student: Ok, so it's the next thing. Got it. Cool. Next. (that's literally all they need to know)
[example of rep shown]
Student: But why is that one backward?
[but see? It's easy to read...]
Student: But it doesn't work the same. Can't I just always put a label on a line and know it will work every single time?
[discussion on sadly, no because....]
Now there is a more complicated discussion on references, the concept of a block, etc... And the end result really doesn't add any more value, and will actually confuse existing PASM users, who until now could operate with a simple, global forward reference rule.
The third one is a cluster**** and isn't really worth any discussion, save to say it's technically no different than the second one, due to comments being transparent.
As for "any assembler" the P1 tools would get those label references wrong, as would the P2 tools, because the standard in Propeller land is to always forward reference labels. Now it's that, except for this thing.
Historically, I do it because of punched cards. It's much easier to edit card decks if your label is on its own card.
The current implementation makes sense to me so far as i've used it.
Chip mentioned two modes, reading and writing and the possibility of a label that moves! That's even worse! Now stuff isn't where a person puts it, and we now have to talk about modes and states...
By contrast, the simple forward reference label rule takes about two seconds, and the person is done with understanding labels, until they are ready for local labels, which they will be after writing a little code filled with loop1, loop2, etc... or they want to make pre-written snippets, etc... And if they learn that rule and apply it, they get it right nearly all the time with about zero effort.
Except for rep. See how that all works?
The bizarre thing is I agree with you on a label case, and I agree in that it avoids line counting too. All good.
Hosing up labels wasn't worth that though. It's not worth it, because the most obvious use, that will occur to people when they learn about labels is the one people actually can't use because one of us thought a backward reference was a good idea for one case.
None of the assemblers I use do that, and I have no idea why you think this somehow happens here.
?? Why do you imagine that ??
It is the same code as Peter's which does not include JMP in the rep loop.
The address of the label in the MAP file is identical in both cases.
LOTS of P1 code uses labels on their own lines, some uses same-line labels. Adding CrLf does not break any code.
Yup, I tend to place major branch labels on their own lines, (often with a comment) and sometimes I'll place local short labels, on the same line as an ASM statement.
HLL generated code tends to use own-line-labels.
HLL example 1
HLL example 2
$0000 nop
$0004 label 'forward reference rule applied. A backward reference would be label address $0000
$0004 add
As far as I can recall, I've not seen any PASM anywhere that references the thing before the address of a label. (programmer can make expression for that, if they want) It's always the thing AT or CONTAINED in the address assigned to the label, which in text, visual form, is the forward reference rule.
Rep will use the address before, and I suppose this is just like the count from 0 inherent in the rep instruction. Both are similar ambiguities. It's the only thing that uses the address before the label, as it stands right now too.
If I perform a jmp to label above, I land on the add instruction. It's contained in the memory at address $0004. If I do a rep targeting the label above, I get the nop instruction as the end of the loop, which is not contained by the memory at the address assigned to the label.
Every other label use will reference the add, except for REP.
In very simple terms, if I want to reference something except for REP as it stands now, I can apply the same rule. Put that thing and it's label on the same line and it's gonna work. Seems to me the best case is to keep that rule consistent. Which means labeling the end of the loop, not the thing after the end of the loop.
Doing that makes as much sense as counting the number of instructions to loop from 0. And the goal of it all was to make more sense.
Seems to me, one "doesn't make sense" was seen as a potential source of ambiguity, and rightfully so, only to be replaced with another one.
END: still working!
-OR -
done what I need to do
END
REP is only concerned about an END as it may never get there anyway in an infinite loop.
Users do not care what the binary level opcode is, and REP simply and clearly uses the label as the place it goes when done.
Implicit in that is that yes, rep includes the line above that label in the loop, the label is an exit location, which is what labels commonly are.
Destinations to jump to.
There is nothing special in the REP label use here, unless you expect REP to operate differently.
Nope, REP also references the add just fine, but treats it as a destination when done, the add is not included inside the REP loop, as it comes after the Label.
@jmg, in every one of those examples, the label address contains the item following the text of the label in the assembly file. In fact, that's the case for everything but REP.
Oh well. We've got much better things to do.
Seriously. "exit location" or "when REP is done, you will be here" both will work to resolve the question, and that's better than "jmg label" I'll take it, but I don't like it. Seems like we didn't have this issue with REP on the "hot" design pass...
Re: Labels on individual lines. Yes! Given the behavior is consistent, it's all good. I suppose I just see REP differently, and that's making the label no-conforming to me. I really do see that as a backward reference, as in the pointer to the last instruction in the REP loop. If one is doing the line count, the count has nothing to do with anything beyond the intended series of instructions for REP to operate on.
Edit: Yes. that's it exactly.
It's the difference between:
"put the label on the instruction you want to execute after REP is done" as opposed to, "put the label on the last instruction in the set to be repeated"
Another way to think of it, "repeat these" as opposed to "go here after repeating these..."
I'm good now. Thanks. Most all of you are seeing it as the next thing to do. I really didn't see it that way at all.
I for sure don't want the label that moves... ugh!
Yep, I'm busy doing it and that way you either get used to something, or you like it or you hate it. Either way it shouldn't stop you from doing something. Personally I'm happy with the way REP has turned out, both with the count=count plus the end=end
Yes, the label used in REP is the next thing to do, aka the REP-exit location.
Yes, and the old leading dummy opcode that was not-actually-loop-executed is also gone too, so the new REP is much more user friendly and less error prone. It's a cool opcode
Personally I'd use
REP LabelWhenDoneName,Count
and dispense with the @, as a cleaner version, but that's a minor detail.
0=forever is also nice to have.
There are test & generate cases where you may want a COG to simply loop-forever with minimal overhead.
So we have two cases:
REP [number of instructions to repeat - 1], [number of iterations]
, and
REP [@label of instruction executed immediately after operation complete], [number of iterations]
And I think we need to wordsmith that second case some when we get closer to that stage in the process.
I got seriously hung up on the idea of the label pointing to the loop instructions directly, rather than it being implied by the one to get executed next. It really did seem like a backward reference, and I really was not OK with that idea at all.
It's kind of amazing how a perception or expectation difference can alter things! We are very right to hash out syntax, etc... Getting after that is going to pay dividends. I believe that completely, and it's those dividends I want.
On this one, I was totally experiencing very genuine concern over what appeared to be a matter of genuine ambiguity, and I got snarky. Could not believe no one saw it. --which is always a clue, but one that can be difficult for the one having the struggle to see.
(which I find humorous after it's all said and done, jmg If we can't laugh at ourselves, things get kind of ugly. So, I'm laughing! )
This: Yes, and the old leading dummy opcode that was not-actually-loop-executed is also gone too
Totally. That's a P1 thing many have found difficult. Stuffing things into unused "slots" Most common was making the most of the HUB access. Big win here with REP.
'@' prefix could be looked at, but that's not urgent.
If # means (LinesofLongs-1), then LabelName (no @) has no parsing ambiguity ?
One could have a short and long rep loop, and specify that difference with a COG register. That seems an odd case though, it might make sense for some kind of self-generating / modifying routine or other, running in a COG for speed. Seems a bit crazy. I'm curious what any of you would have in mind for that use case.
"REP D/#, S/#" doesn't allow for a label, given "#" is the line count; thus, "@" at present.
I don't care how we resolve this, or if we do. It's enough to get past the label trouble as far as I'm concerned, but it is an exception to the addressing scheme.
REP [#]count, [next]/[#instructions-1]
My reasoning is that the DJNZ counter, next
and JMPRET returnaddr, next
In each case, "next" is the next instruction to be executed (ie a goto)
and the "count/return-address" is the "operation".
Now, the "next" part of the REP instruction would be the goto address after the loop is done.
Yes, either works, easily changed.
If you really want to take this further, move REP to the end of the block and have the label refer to the beginning of the block. The assembler can then insert the REP in the proper location (at the beginning) in the compiled code. That way, the REP will look like all of the other branch instructions and the label discussion will be moot.