Ah, but I think an inverse example can skip the intermediate storing:
setd ptr2ptr, #raceptrtable
rep #(:loopend-:loop), #(racetablend-raceptrtable)
:loop
mov score, #{random number} ' acquire a score - just a filler
ptr2ptr altds ptr2ptr, #000_001_000 ' apply ptr2ptr to next instruction then increment
altds 0-0, #000_100_000 ' apply the table entry to next instruction without even storing it! This works only because we are working on the D operand
mov 0-0, score ' enter a score into the list - ie: use the applied pointer
:loopend
score res 1
raceptrtable long $100,$10A,$11A,$12C,$138,$144 ' table of pointers to list of scores
racetablend
Assuming I've got this right, then maybe there can be an improvement to the ALTDS instruction that allows applying of a D data field to a S operand in particular ... or have a second instruction, say ALTSD, that has the meaning of S and D operands within the ALTDS instruction itself exchanged.
Oops, another mistake above. Trying to optimise as well . ptr2ptr can't be located in the first ALTDS like that. That D operand has to reference an incrementing pointer.
It could be located in the second ALTDS since that one has an unused/empty D operand. Or the following MOV would do as well. Neither use their respective D operand.
setd ptr2ptr, #raceptrtable
rep #(:loopend-:loop), #(racetablend-raceptrtable)
:loop
mov score, #{random number} ' acquire a score - just a filler
altds ptr2ptr, #000_001_000 ' apply ptr2ptr to next instruction then increment
ptr2ptr altds 0-0, #000_100_000 ' apply the table entry to next instruction without even storing it! This works only because we are working on the D operand
mov 0-0, score ' enter a score into the list - ie: use the applied pointer
:loopend
score res 1
raceptrtable long $100,$10A,$11A,$12C,$138,$144 ' table of pointers to list of scores
racetablend
SETD reg1, #reg2 ' Cog pointer to Cog pointer preassigned, $FF placed in D operand of the ALTDS below. If traversing a table of Cog/LUT pointers then #reg2 wouldn't be an immediate operand.
NOP ' Dummy for SETD to write back before ALTDS is fetched.
reg1 ALTDS 0-0, #000_000_100 ' replaces next instruction's S from the assigned, in this case with $100
MOV dest, 0-0 ' becomes MOV dest, $100
reg2 LONG #$100
But if you are modifying the ALTDS instruction, why not simply:
Of course, the answer is that it's not this simple when you are including increments/decrements and both D and S fields. But I'm not sure that the "traditional" way is any more complicated.
This falls somewhere between the two approaches above. It's the least amount of code, has a slightly faster loop than the first approach. But I contend that it is the easiest version of ALTDS to understand.
Of course, this is a very simple example (move "count" longs). If that loop were working on a complex structure that required multiple ALTDS with increment/decrement, then the current ALTDS would likely be more compact and efficient. On the other hand, I think the current ALTDS (at least in the example above) is more error-prone, since one could potentially forget to "write back" the s-field and d-field registers to reg2 and reg3.
Sorry I haven't been on this discussion, yet. I've been working away on the Verilog.
I will read what everyone wrote here, but first I explain how it works, currently (open to improvement, of couse).
The other day I revisited ALTDS because we had moved the CCCC bits to the front of the opcode.
The old SETI instruction now writes S[8:0] into D[27:19] (the OOOOOOOCZ bits), instead of into the top bits
opcode: CCCC OOOOOOO CZI DDDDDDDDD SSSSSSSSS
The OOOOOOOCZ bits in a variable (not an instruction) can be used to redirect result writing, while the DDDDDDDDD and SSSSSSSSS fields can redirect D and S.
It works like this:
ALTDS D,S/# 'modify D according to bits in S and possibly replace next instruction's CCCCOOOOOOOCZI / DDDDDDDDD / SSSSSSSSS fields.
In ALTDS, S provides the following pattern: %RRR_DDD_SSS
%RRR: (101 allows instruction substitution)
000 = don't affect D's CCCCOOOOOOOOOCZI field
001 = don't affect D's CCCCOOOOOOOOOCZI field, cancel write for next instruction
010 = decrement D's OOOOOOOCZ field
011 = increment D's OOOOOOOCZ field
100 = use D's OOOOOOOCZ field as the result register for the next instruction (separate from D)
101 = use D's CCCCOOOOOOOCZI field as next instruction's CCCCOOOOOOOCZI field
110 = use D's OOOOOOOCZ field as the result register for the next instruction, decrement D's OOOOOOOCZ field
111 = use D's OOOOOOOCZ field as the result register for the next instruction, increment D's OOOOOOOCZ field
%DDD
000 = don't affect D's DDDDDDDDD field
001 = copy D's SSSSSSSSS field into its DDDDDDDDD field
010 = decrement D's DDDDDDDDD field
011 = increment D's DDDDDDDDD field
100 = use D's DDDDDDDDD field as the DDDDDDDDD field for the next instruction
101 = use D's DDDDDDDDD field as the DDDDDDDDD field for the next instruction, copy D's SSSSSSSSS field into its DDDDDDDDD field
110 = use D's DDDDDDDDD field as the DDDDDDDDD field for the next instruction, decrement D's DDDDDDDDD field
111 = use D's DDDDDDDDD field as the DDDDDDDDD field for the next instruction, increment D's DDDDDDDDD field
%SSS
000 = don't affect D's SSSSSSSSS field
001 = copy D's DDDDDDDDD field into its SSSSSSSSS field
010 = decrement D's SSSSSSSSS field
011 = increment D's SSSSSSSSS field
100 = use D's SSSSSSSSS field as the SSSSSSSSS field for the next instruction
101 = use D's SSSSSSSSS field as the SSSSSSSSS field for the next instruction, copy D's DDDDDDDDD field into its SSSSSSSSS field
110 = use D's SSSSSSSSS field as the SSSSSSSSS field for the next instruction, decrement D's SSSSSSSSS field
111 = use D's SSSSSSSSS field as the SSSSSSSSS field for the next instruction, increment D's SSSSSSSSS field
You can see that when those three-bit RRR/DDD/SSS fields have their MSB's clear, they are only affecting D. When their MSB's are set, though, they additionally affect the next instruction in some way.
When RRR is 101, it actually uses D's upper bits to replace the functionality of the next instruction, which might as well be a NOP, unless its DDDDDDDDD and SSSSSSSSS fields are meaningful.
It hurts to think about, but I think, as someone proposed above, compounded indirection can be achieved. Also, some crazy instruction substitution possibilities exist. And, not being self-modifying code, this can all work from hub-exec.
However, I see that RRR=000/001 are the same.
Perhaps, RRR=001 could be used as setting NR for the next instruction, rather than S=0.
This way, D & S can still be substituted if required, and we now have the option to not write the result.
I don't think it matters that this (NR) is mutually exclusive to changing the following instruction's CCCCOOOOOOOCZ, or an alternate result D address with/without increment.
However, I see that RRR=000/001 are the same.
Perhaps, RRR=001 could be used as setting NR for the next instruction, rather than S=0.
This way, D & S can still be substituted if required, and we now have the option to not write the result.
I don't think it matters that this (NR) is mutually exclusive to changing the following instruction's CCCCOOOOOOOCZ, or an alternate result D address with/without increment.
Yes, I removed that functionality, but your proposal would be the perfect way to reintroduce it.
I got rid of it because I was thinking about why one would spend an instruction avoiding a write, when that instruction takes the same amount of RAM as a dummy register that could have been written. But, now I'm thinking that maybe there's more value in the idea. If you don't write, you can still get C/Z affected, but is it worth a whole instruction? It could take an instruction to move a value from an important register to a dummy register for a destructive operation, but it costs just as much.
Can you come up with any compelling reasons why we should do this? It's trivial to implement, and I'll go ahead and do it, but what's the practical advantage in this function? I suspect there is one, but it's eluding me.
P.S. I just made the change in the Verilog and modified my post above to reflect the new behavior.
You are correct that an NR instruction could be achieved by moving to a temporary register and then performing the instruction using the temporary register instead. The only saving is the temporary register, which often is available in a program anyway.
Perhaps there are some tricks we could do using the ALTDS with NR, looking for a bit pattern within a buffer ???
The old SETI instruction now writes S[8:0] into D[27:19] (the OOOOOOOCZ bits), instead of into the top bits
Why exclude the "I" bit?
Because we have a SETI instruction that writes the useful instruction field of OOOOOOOCZ and it is the only 9-bit writer instruction up above D and S fields. So, it's needed to set up the write redirection for ALTDS. Nothing against the "I" bit. This all stems from the 9-bit constant limitation. Better to cover the OOOOOOOCZ bits than miss the top one just to pick up "I".
You are correct that an NR instruction could be achieved by moving to a temporary register and then performing the instruction using the temporary register instead. The only saving is the temporary register, which often is available in a program anyway.
Perhaps there are some tricks we could do using the ALTDS with NR, looking for a bit pattern within a buffer ???
Yes, there must be some useful trick we can do when RRR=001.
%RRR: (101 allows instruction substitution)
000 = don't affect D's CCCCOOOOOOOOOCZI field
001 = don't affect D's CCCCOOOOOOOOOCZI field, cancel write for next instruction
010 = decrement D's OOOOOOOCZ field
011 = increment D's OOOOOOOCZ field
100 = use D's OOOOOOOCZ field as the result register for the next instruction (separate from D)
101 = use D's CCCCOOOOOOOCZI field as next instruction's CCCCOOOOOOOCZI field
110 = use D's OOOOOOOCZ field as the result register for the next instruction, decrement D's OOOOOOOCZ field
111 = use D's OOOOOOOCZ field as the result register for the next instruction, increment D's OOOOOOOCZ field
Okay. I was a bit slow on understanding %RRR. Now I get it! "R" for "Result"! Also, now I think I see why SETI is updating precisely 9 bits (excluding "I"). For clarity:
000 = don't affect D's RRRRRRRRR field
001 = don't affect D's RRRRRRRRR field, cancel write for next instruction
010 = decrement D's RRRRRRRRR field
011 = increment D's RRRRRRRRR field
100 = use D's RRRRRRRRR field as the result register for the next instruction (separate from D)
101 = use D's CCCCOOOOOOOCZI field as next instruction's CCCCOOOOOOOCZI field
110 = use D's RRRRRRRRR field as the result register for the next instruction, decrement D's RRRRRRRRR field
111 = use D's RRRRRRRRR field as the result register for the next instruction, increment D's RRRRRRRRR field
Because we have a SETI instruction that writes the useful instruction field of OOOOOOOCZ and it is the only 9-bit writer instruction up above D and S fields. So, it's needed to set up the write redirection for ALTDS. Nothing against the "I" bit. This all stems from the 9-bit constant limitation. Better to cover the OOOOOOOCZ bits than miss the top one just to pick up "I".
Maybe consider renaming SETI to SETR? I'm guessing that this will be the more likely use case (as compared to altering opcodes).
Because we have a SETI instruction that writes the useful instruction field of OOOOOOOCZ and it is the only 9-bit writer instruction up above D and S fields. So, it's needed to set up the write redirection for ALTDS. Nothing against the "I" bit. This all stems from the 9-bit constant limitation. Better to cover the OOOOOOOCZ bits than miss the top one just to pick up "I".
Maybe consider renaming SETI to SETR? I'm guessing that this will be the more likely use case (as compared to altering opcodes).
So, what is SETDS for? If this functionality can be handled with SETD and SETS, how about replacing it with GETR? That way, we would have parity for that set of instructions:
Normally the SETI (or SETR) is used for modifying the instruction, and hence the name SETI and the new GETI. These are limited to 9 bits to conform to the 9bit standard of D & S.
So, to me, SETI & GETI make more sense than SETR & GETR.
Normally the SETI (or SETR) is used for modifying the instruction, and hence the name SETI and the new GETI. These are limited to 9 bits to conform to the 9bit standard of D & S.
So, to me, SETI & GETI make more sense than SETR & GETR.
SETI does not include the "I" bit, which is certainly part of an instruction. It also does not set the all of the instruction bits of any of the alternate instruction forms. Conversely, SETR always sets 9 bits used for R.
This also clarifies the intention, as this casts the SETD/SETS (along with SETR) as primarily relating to ALTDS, and secondarily as a means to self-modify code. As Chip pointed out, this is preferred in hubexec mode.
Personally, I prefer SETI over SETR. To me SETI means "SET Instruction". SETR has little meaning to me. If the R refers to the "result" then it should set the result of the instruction's operation, which would make it equivalent to a MOV instruction. Stating that the R in SETR refers to the "result" field described in the ALTDS instruction is confusing. The description of the ALTDS instruction probably should not refer to that field as the result field, but should use some other term instead of "result".
How about changing SETI to SETINST instead? This is less ambiguous than SETI. Yes, the SETI instruction also sets the C and Z bits, but these can be interpreted as being part of the instruction, and on the P2 the C and Z bits are used to distinguish between certain instructions.
SETI was the MOVI instruction on P1, just like MOVD and MOVS are now SETD and SETS.
On the P1 MOVI replaced the 9 bit iiiiiizcr. Note here the "I" immediate bit is not replaced. IMHO the "I" bit has more to do with the S operand as a modifier than it does with the instruction. Take an example where MOVI was used in the P1... I the spin interpreter, a rdlong is changed to a wrlong. You would not change the "I"bit here as you would want it left the same as it was because its part of the S operand.
Actually, I still prefer the MOVI, MOVD and MOVS over SETI/SETR, SETD and SETS, even tho' we now also have GETI/GETR, GETD, GETS.
FWIW these are only mneumonics so they are unimportant as far as getting an FPGA image or a real P2.
Actually, there is no GETI at the moment. Regardless of what they are called, that is what I was asking about further. Could the opcode for SETDS be instead used for GETI//GETR?
Actually, there is no GETI at the moment. Regardless of what they are called, that is what I was asking about further. Could the opcode for SETDS be instead used for GETI//GETR?
Since we moved the CCCC bits to the top of the instruction, we were able to get rid of SETCCCC. I figured that SETDS was kind of superflous, too, so I got rid of it. That opened two instruction spaces. I added in SEUSSF and SEUSSR which were from the Prop2-Hot. They don't take much logic and they provide a forward and reverse bit-position-and-polarity-change function. These are kind of silly instructions, but they'll provide simple means to obfuscate data or create pseudo-random numbers from counters, etc:
Okay. Is there instruction space to add a GETI/GETR? It seems to me that having a SETI/SETR and a result field in ALTDS is weakened by not having an instruction to easily extract the RRRRRRRRR value back out like you can with GETD and GETS. If not, it's not a big deal, as the same can be accomplished in just a few instructions.
It's not often required to get back the instruction.
However, a number of times I have found the use of MOVI is nice to be able to change an instruction within a common subroutine to alter its operation (usually reverse its operation).
Since the CCCC bits have moved to 28:31 the SETCCCC (was not in the P1) is no longer required since we can do this with the nibble(?) instruction.
Chip,
If there are instruction space worries, perhaps GETD & GETS could share an instruction code using the "I" bit to select either GETD or GETS ???
GETD D,#S (I=1)
GETS D,#S (I=0)
It doesn't seem much of a restriction to make the "S" field always immediate.
Alternately the "C" flag could be used as I don't see a lot of use setting the C flag based on the result.
The "Z" flag should be retained to test the result for zero.
Okay. Is there instruction space to add a GETI/GETR? It seems to me that having a SETI/SETR and a result field in ALTDS is weakened by not having an instruction to easily extract the RRRRRRRRR value back out like you can with GETD and GETS. If not, it's not a big deal, as the same can be accomplished in just a few instructions.
MOV regR, regDS
SHR regR, #19
AND regR, #$1FF
There are no more instruction spaces in that ALU block. I could get rid of SEUSSF or SEUSSR to make room for GETI/GETR, but I'm not sure I want to do that. I don't know that reading that field would be that necessary. The same could be said of GETD/GETS, but they are much more likely to be needed.
It's not often required to get back the instruction.
However, a number of times I have found the use of MOVI is nice to be able to change an instruction within a common subroutine to alter its operation (usually reverse its operation).
Since the CCCC bits have moved to 28:31 the SETCCCC (was not in the P1) is no longer required since we can do this with the nibble(?) instruction.
Chip,
If there are instruction space worries, perhaps GETD & GETS could share an instruction code using the "I" bit to select either GETD or GETS ???
GETD D,#S (I=1)
GETS D,#S (I=0)
It doesn't seem much of a restriction to make the "S" field always immediate.
Alternately the "C" flag could be used as I don't see a lot of use setting the C flag based on the result.
The "Z" flag should be retained to test the result for zero.
That could work, but it would create a great exception in how instructions are decoded. Also, C and Z are not available for those GETD/GETS instructions. They are in an ALU block that handles all the mux-type instructions and none of those return flags.
It's not often required to get back the instruction.
However, a number of times I have found the use of MOVI is nice to be able to change an instruction within a common subroutine to alter its operation (usually reverse its operation).
Since the CCCC bits have moved to 28:31 the SETCCCC (was not in the P1) is no longer required since we can do this with the nibble(?) instruction.
Chip,
If there are instruction space worries, perhaps GETD & GETS could share an instruction code using the "I" bit to select either GETD or GETS ???
GETD D,#S (I=1)
GETS D,#S (I=0)
It doesn't seem much of a restriction to make the "S" field always immediate.
Alternately the "C" flag could be used as I don't see a lot of use setting the C flag based on the result.
The "Z" flag should be retained to test the result for zero.
That could work, but it would create a great exception in how instructions are decoded. Also, C and Z are not available for those GETD/GETS instructions. They are in an ALU block that handles all the mux-type instructions and none of those return flags.
Then it's not worth the trouble. In reality, there are probably better things to worry about than the GETI/GETD/GETS instructions. I didn't really miss them in P1.
I added in SEUSSF and SEUSSR which were from the Prop2-Hot. They don't take much logic and they provide a forward and reverse bit-position-and-polarity-change function. These are kind of silly instructions, but they'll provide simple means to obfuscate data or create pseudo-random numbers from counters, etc
Hi Chip, hi all,
What are your expectations regarding SEUSSF and SEUSSR ?
I do not expect a proper PRNG, much less a cryptographically secure PRNG.
Just that it would be nice to have a period (cycle length) of 2**30 or greater --- given that SEUSSF and SEUSSR operate on a 32-bit register (the PRNG state), that should be possible, right?
Getting somewhat evenly distributed 32-bit values would also be nice, even if (maybe) the resulting sequence would fail some statistical tests on randomness.
Determinism is not a limitation, is a feature: it's useful to have the ability to replicate an output sequence or a simulation run by using same seed 32-bit value.
But the best part, that I have not seen outside P2, is having a pair of PRNG-like instructions, giving us the ability to "go back" in a pseudo-random sequence (using SEUSSR after SEUSSF, or vice-versa).
Comments
It could be located in the second ALTDS since that one has an unused/empty D operand. Or the following MOV would do as well. Neither use their respective D operand.
But if you are modifying the ALTDS instruction, why not simply:
Of course, the answer is that it's not this simple when you are including increments/decrements and both D and S fields. But I'm not sure that the "traditional" way is any more complicated.
Here's incrementing/decrementing:
Here's d-field and s-field:
And here is the same with ALTDS:
note that it is more instructions, but a tighter/faster loop.
And, just for the fun of it, here is the code if we were to use the "simplified" ALTDS I recommend above:
This falls somewhere between the two approaches above. It's the least amount of code, has a slightly faster loop than the first approach. But I contend that it is the easiest version of ALTDS to understand.
Of course, this is a very simple example (move "count" longs). If that loop were working on a complex structure that required multiple ALTDS with increment/decrement, then the current ALTDS would likely be more compact and efficient. On the other hand, I think the current ALTDS (at least in the example above) is more error-prone, since one could potentially forget to "write back" the s-field and d-field registers to reg2 and reg3.
Anyhow... more to think about.
I will read what everyone wrote here, but first I explain how it works, currently (open to improvement, of couse).
The other day I revisited ALTDS because we had moved the CCCC bits to the front of the opcode.
The old SETI instruction now writes S[8:0] into D[27:19] (the OOOOOOOCZ bits), instead of into the top bits
opcode: CCCC OOOOOOO CZI DDDDDDDDD SSSSSSSSS
The OOOOOOOCZ bits in a variable (not an instruction) can be used to redirect result writing, while the DDDDDDDDD and SSSSSSSSS fields can redirect D and S.
It works like this:
ALTDS D,S/# 'modify D according to bits in S and possibly replace next instruction's CCCCOOOOOOOCZI / DDDDDDDDD / SSSSSSSSS fields.
In ALTDS, S provides the following pattern: %RRR_DDD_SSS
%RRR: (101 allows instruction substitution)
000 = don't affect D's CCCCOOOOOOOOOCZI field
001 = don't affect D's CCCCOOOOOOOOOCZI field, cancel write for next instruction
010 = decrement D's OOOOOOOCZ field
011 = increment D's OOOOOOOCZ field
100 = use D's OOOOOOOCZ field as the result register for the next instruction (separate from D)
101 = use D's CCCCOOOOOOOCZI field as next instruction's CCCCOOOOOOOCZI field
110 = use D's OOOOOOOCZ field as the result register for the next instruction, decrement D's OOOOOOOCZ field
111 = use D's OOOOOOOCZ field as the result register for the next instruction, increment D's OOOOOOOCZ field
%DDD
000 = don't affect D's DDDDDDDDD field
001 = copy D's SSSSSSSSS field into its DDDDDDDDD field
010 = decrement D's DDDDDDDDD field
011 = increment D's DDDDDDDDD field
100 = use D's DDDDDDDDD field as the DDDDDDDDD field for the next instruction
101 = use D's DDDDDDDDD field as the DDDDDDDDD field for the next instruction, copy D's SSSSSSSSS field into its DDDDDDDDD field
110 = use D's DDDDDDDDD field as the DDDDDDDDD field for the next instruction, decrement D's DDDDDDDDD field
111 = use D's DDDDDDDDD field as the DDDDDDDDD field for the next instruction, increment D's DDDDDDDDD field
%SSS
000 = don't affect D's SSSSSSSSS field
001 = copy D's DDDDDDDDD field into its SSSSSSSSS field
010 = decrement D's SSSSSSSSS field
011 = increment D's SSSSSSSSS field
100 = use D's SSSSSSSSS field as the SSSSSSSSS field for the next instruction
101 = use D's SSSSSSSSS field as the SSSSSSSSS field for the next instruction, copy D's DDDDDDDDD field into its SSSSSSSSS field
110 = use D's SSSSSSSSS field as the SSSSSSSSS field for the next instruction, decrement D's SSSSSSSSS field
111 = use D's SSSSSSSSS field as the SSSSSSSSS field for the next instruction, increment D's SSSSSSSSS field
You can see that when those three-bit RRR/DDD/SSS fields have their MSB's clear, they are only affecting D. When their MSB's are set, though, they additionally affect the next instruction in some way.
When RRR is 101, it actually uses D's upper bits to replace the functionality of the next instruction, which might as well be a NOP, unless its DDDDDDDDD and SSSSSSSSS fields are meaningful.
It hurts to think about, but I think, as someone proposed above, compounded indirection can be achieved. Also, some crazy instruction substitution possibilities exist. And, not being self-modifying code, this can all work from hub-exec.
I need to get my head around this again.
However, I see that RRR=000/001 are the same.
Perhaps, RRR=001 could be used as setting NR for the next instruction, rather than S=0.
This way, D & S can still be substituted if required, and we now have the option to not write the result.
I don't think it matters that this (NR) is mutually exclusive to changing the following instruction's CCCCOOOOOOOCZ, or an alternate result D address with/without increment.
Yes, I removed that functionality, but your proposal would be the perfect way to reintroduce it.
I got rid of it because I was thinking about why one would spend an instruction avoiding a write, when that instruction takes the same amount of RAM as a dummy register that could have been written. But, now I'm thinking that maybe there's more value in the idea. If you don't write, you can still get C/Z affected, but is it worth a whole instruction? It could take an instruction to move a value from an important register to a dummy register for a destructive operation, but it costs just as much.
Can you come up with any compelling reasons why we should do this? It's trivial to implement, and I'll go ahead and do it, but what's the practical advantage in this function? I suspect there is one, but it's eluding me.
P.S. I just made the change in the Verilog and modified my post above to reflect the new behavior.
Perhaps there are some tricks we could do using the ALTDS with NR, looking for a bit pattern within a buffer ???
Why exclude the "I" bit?
Because we have a SETI instruction that writes the useful instruction field of OOOOOOOCZ and it is the only 9-bit writer instruction up above D and S fields. So, it's needed to set up the write redirection for ALTDS. Nothing against the "I" bit. This all stems from the 9-bit constant limitation. Better to cover the OOOOOOOCZ bits than miss the top one just to pick up "I".
Yes, there must be some useful trick we can do when RRR=001.
Okay. I was a bit slow on understanding %RRR. Now I get it! "R" for "Result"! Also, now I think I see why SETI is updating precisely 9 bits (excluding "I"). For clarity:
000 = don't affect D's RRRRRRRRR field
001 = don't affect D's RRRRRRRRR field, cancel write for next instruction
010 = decrement D's RRRRRRRRR field
011 = increment D's RRRRRRRRR field
100 = use D's RRRRRRRRR field as the result register for the next instruction (separate from D)
101 = use D's CCCCOOOOOOOCZI field as next instruction's CCCCOOOOOOOCZI field
110 = use D's RRRRRRRRR field as the result register for the next instruction, decrement D's RRRRRRRRR field
111 = use D's RRRRRRRRR field as the result register for the next instruction, increment D's RRRRRRRRR field
RRRRRRRRR is the same bit field as OOOOOOOCZ.
Maybe consider renaming SETI to SETR? I'm guessing that this will be the more likely use case (as compared to altering opcodes).
That sounds like a good idea to me.
* GETD/SETD
* GETS/SETS
* GETR/SETR
So, to me, SETI & GETI make more sense than SETR & GETR.
SETI does not include the "I" bit, which is certainly part of an instruction. It also does not set the all of the instruction bits of any of the alternate instruction forms. Conversely, SETR always sets 9 bits used for R.
This also clarifies the intention, as this casts the SETD/SETS (along with SETR) as primarily relating to ALTDS, and secondarily as a means to self-modify code. As Chip pointed out, this is preferred in hubexec mode.
How about changing SETI to SETINST instead? This is less ambiguous than SETI. Yes, the SETI instruction also sets the C and Z bits, but these can be interpreted as being part of the instruction, and on the P2 the C and Z bits are used to distinguish between certain instructions.
On the P1 MOVI replaced the 9 bit iiiiiizcr. Note here the "I" immediate bit is not replaced. IMHO the "I" bit has more to do with the S operand as a modifier than it does with the instruction. Take an example where MOVI was used in the P1... I the spin interpreter, a rdlong is changed to a wrlong. You would not change the "I"bit here as you would want it left the same as it was because its part of the S operand.
Actually, I still prefer the MOVI, MOVD and MOVS over SETI/SETR, SETD and SETS, even tho' we now also have GETI/GETR, GETD, GETS.
FWIW these are only mneumonics so they are unimportant as far as getting an FPGA image or a real P2.
Since we moved the CCCC bits to the top of the instruction, we were able to get rid of SETCCCC. I figured that SETDS was kind of superflous, too, so I got rid of it. That opened two instruction spaces. I added in SEUSSF and SEUSSR which were from the Prop2-Hot. They don't take much logic and they provide a forward and reverse bit-position-and-polarity-change function. These are kind of silly instructions, but they'll provide simple means to obfuscate data or create pseudo-random numbers from counters, etc:
However, a number of times I have found the use of MOVI is nice to be able to change an instruction within a common subroutine to alter its operation (usually reverse its operation).
Since the CCCC bits have moved to 28:31 the SETCCCC (was not in the P1) is no longer required since we can do this with the nibble(?) instruction.
Chip,
If there are instruction space worries, perhaps GETD & GETS could share an instruction code using the "I" bit to select either GETD or GETS ???
GETD D,#S (I=1)
GETS D,#S (I=0)
It doesn't seem much of a restriction to make the "S" field always immediate.
Alternately the "C" flag could be used as I don't see a lot of use setting the C flag based on the result.
The "Z" flag should be retained to test the result for zero.
There are no more instruction spaces in that ALU block. I could get rid of SEUSSF or SEUSSR to make room for GETI/GETR, but I'm not sure I want to do that. I don't know that reading that field would be that necessary. The same could be said of GETD/GETS, but they are much more likely to be needed.
That could work, but it would create a great exception in how instructions are decoded. Also, C and Z are not available for those GETD/GETS instructions. They are in an ALU block that handles all the mux-type instructions and none of those return flags.
What are your expectations regarding SEUSSF and SEUSSR ?
Hi Chip, hi all,
What are your expectations regarding SEUSSF and SEUSSR ?
I do not expect a proper PRNG, much less a cryptographically secure PRNG.
Just that it would be nice to have a period (cycle length) of 2**30 or greater --- given that SEUSSF and SEUSSR operate on a 32-bit register (the PRNG state), that should be possible, right?
Getting somewhat evenly distributed 32-bit values would also be nice, even if (maybe) the resulting sequence would fail some statistical tests on randomness.
Determinism is not a limitation, is a feature: it's useful to have the ability to replicate an output sequence or a simulation run by using same seed 32-bit value.
But the best part, that I have not seen outside P2, is having a pair of PRNG-like instructions, giving us the ability to "go back" in a pseudo-random sequence (using SEUSSR after SEUSSF, or vice-versa).
Thanks!
Can you move that question to a separate thread? I'd hate for it to get lost inside a thread primarily related to ALTDS.
Link:
What are your expectations regarding SEUSSF and SEUSSR ?