When a D register is given in REPD, the number of repeats will be 0 if D=0, which still means the code executes ONCE. If D=1, it will repeat once, making TWO executions of the looped code.
Yes, but how do I know if it is actually repeating? If the REPS instruction were treated as a NOP the code would still work. Under what circumstances will that last JMP instruction be executed normally?
It will execute after 511 passes through the repeating code.
Yes, but how do I know if it is actually repeating? If the REPS instruction were treated as a NOP the code would still work. Under what circumstances will that last JMP instruction be executed normally?
You should get the same benchmark result as with the jmpd version (same instruction count), or only a bit slower because of the additional jump after 511 repeats.
You should get the same benchmark result as with the jmpd version (same instruction count), or only a bit slower because of the additional jump after 511 repeats.
Well, if that's the case, then something must be wrong. I'll keep looking. Thanks!
In all cases of REPS/REPD, all values (constants and register contents) are such that 0 means 1, on upwards. If you put %000000 in the instructions-to-repeat field, it means 1. %111111 means 64. Same deal with the loop counts: 0 means 1 (because of the initial fall-through), while $FFFF_FFFF would mean $1_0000_0000 block executions.
Table 12: 'Extended Miscellaneous Flow Control Instructions
Machine Code | Mnemonic | Operand | Operation
----------------------------------------------------------------------------------------------
000011 zcn 1 cccc nnnnnnnnn [B]0100iiiii [/B] | REPD | D/#n ,i | Delayed repeat of the following i (0-31) instructions the
| value in register D(0-511) or n(0-511) times.
| The pipeline causes a delay of three instructions before
[B] ???? [/B] | the repeated set of instructions begins to execute
000011 zcn 1 cccc nnnnnnnnn [COLOR=#ff0000][B]0100iiiii [/B][/COLOR] | REPS | D/#n ,i | Repeat of the following i (0-31) instructions the
| value in register D(0-511) or n(0-511) times.
000011 zcn 1 cccc nnnnnnnnn 010100000 | NOPX | D/#n | Repeat the NOP instruction the value in register D(0-511)
| or n(0-511) times.
000011 zcn 1 cccc dddnnnnnn 011101011 | SETSKIP | D/#n | Executes up to the next 32 instructions as NOPs described by the
| set bit pattern of a register D(0-511) or literal N(0-63).
There are two repeat instructions:
REPS #loops,#ins - executes early in the pipeline, uses a 14-bit constant, needs only one spacer instruction
REPD D,#ins - executes late in the pipeline, uses D or a 9-bit constant, needs three spacer instructions,
if D is $1FF then infinite repeat
If REPS is used by a task that has at least one other task(s) between its own time slots, no spacers are needed.
If REPD is used by a task that has at least three other task(s) between its own time slots, no spacers are needed.
For infinite repeat, you must do REPD $1FF,#x. When the hardware sees register address $1FF, that means infinite.
When a D register is given in REPD, the number of repeats will be 0 if D=0, which still means the code executes ONCE.
If D=1, it will repeat once, making TWO executions of the looped code.
Code:
Fast loading from HUB to COG ram can be done with just a few instructions:
Load 64 longs from HUB memory (@PTRA) into COG-$100
REPS #64,#1
SETINDA #$100
RDLONGC INDA++,PTRA++
This way, you can load as much or as little as you please, to wherever in the COG you´d like.
Then, you can jump to it.
In all cases of REPS/REPD, all values (constants and register contents) are such that 0 means 1, on upwards. If you put %000000 in the instructions-to-repeat field, it means 1. %111111 means 64. Same deal with the loop counts: 0 means 1 (because of the initial fall-through), while $FFFF_FFFF would mean $1_0000_0000 block executions.
Ah, then that's my problem. Off by one in both fields. Thanks!!!!
In all cases of REPS/REPD, all values (constants and register contents) are such that 0 means 1, on upwards. If you put %000000 in the instructions-to-repeat field, it means 1. %111111 means 64. Same deal with the loop counts: 0 means 1 (because of the initial fall-through), while $FFFF_FFFF would mean $1_0000_0000 block executions.
I've been thinking about this and it seems that PNut.exe must subtract 1 from the value supplied for the immediate before encoding it into the instruction because Andy gave the following example:
REPS #511,#5 encodes to: $0DC3FC44 with the PNUT assembler.
This seems like it might be awkward if the same rule is applied to the REPD instruction since it can take the repeat count in a register. Will the register's contents also be decremented by 1 before being used as the repeat count? If not then the value you need to load into the register for the D form will have to be different than the value you supply as a constant in the immediate form for the same loop count.
I'm going to try to write the documentation for this right now and post it in an hour, or so. As of now, PNUT.EXE doesn't support the 'REPD #i' syntax for infinite repeat, so you must type 'REPD $1FF,#i'.
I've been thinking about this and it seems that PNut.exe must subtract 1 from the value supplied for the immediate before encoding it into the instruction because Andy gave the following example:
This seems like it might be awkward if the same rule is applied to the REPD instruction since it can take the repeat count in a register. Will the register's contents also be decremented by 1 before being used as the repeat count? If not then the value you need to load into the register for the D form will have to be different than the value you supply as a constant in the immediate form for the same loop count.
That's right, the way the constant is interpreted and the way the register's contents are interpreted for REPD loops is the same: 0 -> 1 loop (actually, no loops - just the initial fall through).
I'm going to try to write the documentation for this right now and post it in an hour, or so. As of now, PNUT.EXE doesn't support the 'REPD #i' syntax for infinite repeat, so you must type 'REPD $1FF,#i'.
I'm going to try to write the documentation for this right now and post it in an hour, or so. As of now, PNUT.EXE doesn't support the 'REPD #i' syntax for infinite repeat, so you must type 'REPD $1FF,#i'.
Chip: How can you use 6 "i" bits because the other instructions cannot decode this???
I think this is only the case with REPD 511,#xx.
But REPD needs 3 delay slots before the loop, so it is slower when the LMM support funtions jump back to the LMM loop.
That's right, the way the constant is interpreted and the way the register's contents are interpreted for REPD loops is the same: 0 -> 1 loop (actually, no loops - just the initial fall through).
Yes, I understand that the constant encoded in the instruction and the register value are treated in the same way. My point though has to do with how this is handled in the assembler. It seems that in PNut, if you give the parameter #5, it gets encoded into the instruction as $4. That means that the following two sequences do the same thing:
I finally had a chance to add REPD to gas so was able to run the following LMM loop. Note that gas does not subtract one from the immediate values so #7 will repeat 8 instructions.
REPD & REPS:
Thinking about this some more, could the instruction mnemonics be changed to REP1D and REP1S (I would prefer REP1Q for quick or F for fast) and do not change thecompiler to subtract 1 from # values ???
Then a just place a warning that the REP1x instructions execute the instructions 1+ the repeated number.
What's the chances of wangling the REP instructions to parallel initialise along side the first instructions in the loop letting them tack the place of the spacer instructions? Ie: If there is more than three instructions in the loop then no pre-loop spacers are needed for a REPD.
I see this as possible, although probably too late for the Prop2.
Comments
It will execute after 511 passes through the repeating code.
You should get the same benchmark result as with the jmpd version (same instruction count), or only a bit slower because of the additional jump after 511 repeats.
So this should do the same:
I have $0dc3fe48 for REPS #511,#8.
Can You verify this.
Andy
I have same time.
But will not sleep in some more time
Here are the current encodings:
I'm going to try to write the documentation for this right now and post it in an hour, or so. As of now, PNUT.EXE doesn't support the 'REPD #i' syntax for infinite repeat, so you must type 'REPD $1FF,#i'.
That's right, the way the constant is interpreted and the way the register's contents are interpreted for REPD loops is the same: 0 -> 1 loop (actually, no loops - just the initial fall through).
Thanks
Chip: How can you use 6 "i" bits because the other instructions cannot decode this??? This is my writeup (lost a bit of formatting in the past)...
Opcodes got changed around since that document was written. Here are the new encodings:
Ok, so you can use 16,383 instead of 511.
This seems a bit odd to me.
Thinking about this some more, could the instruction mnemonics be changed to REP1D and REP1S (I would prefer REP1Q for quick or F for fast) and do not change thecompiler to subtract 1 from # values ???
Then a just place a warning that the REP1x instructions execute the instructions 1+ the repeated number.
What's the chances of wangling the REP instructions to parallel initialise along side the first instructions in the loop letting them tack the place of the spacer instructions? Ie: If there is more than three instructions in the loop then no pre-loop spacers are needed for a REPD.
I see this as possible, although probably too late for the Prop2.
Of course this would likely make REPS redundant.
EDIT: Reworded.