PS: All those related double operand slots should be freed up. There's 16 contiguous slots there. Leave only the two in/decrement-and-jump instructions I mentioned, so that'll result in 14 spare double operand slots.
And all the test-and-set instructions get put into single operand slots.
DJZ is a good complement to DJNZ, as it lets you test the loop at the top, which is sometimes necessary.
DJNS is handy because it lets you iterate down to 0, unlike DJNZ. This is nice for, say, cycling from 15 to 0 with the counting variable usable inside the loop.
DJS is to DJNS what DJZ is to DJNZ.
IJNZ is good for iterating from a negative up to 0. Sometimes useful.
IJZ is to IJNZ what DJZ is to DJNZ.
IJS is rather redundant, considering IJNZ.
IJNS is maybe worthless. Good for counting up to $7FFF_FFFF.
So, IJS and IJNS have very low worth. Together they take up one '{#}D,{#}S' instruction slot. They could go.
DJS and DJNS might as well detect $FFFF_FFFF instead of just the MSB.
Ah, I think I'll just leave all these as they are for the sake of symmetry. For inc, dec, and test, we can check Z, NZ, S, NS. And we have three other tests: odd, even, and overflow. That is all good.
I have a v29 ready with all the little fixups from the last two days.
IJNS is maybe worthless. Good for counting up to $7FFF_FFFF.
If those are fairly useless, could you easily change them to IJNQ and DJNQ, where you could use SETQ to set the non-jump condition? Of course, that assumes you're not already using Q within the loop. At which point, there's still ADD/TEST/JMP.
IJNS is maybe worthless. Good for counting up to $7FFF_FFFF.
If those are fairly useless, could you easily change them to IJNQ and DJNQ, where you could use SETQ to set the non-jump condition? Of course, that assumes you're not already using Q within the loop. At which point, there's still ADD/TEST/JMP.
The lifespan of Q is only to the next instruction. This is a pretty interesting idea. Of course, it can be done.
Seairth, the way it works now is that for DJNZ, we check D for $0000_0001 (before the decrement). This is necessary to make everything happen in time. For doing random values like Q, We'd have to have a 32-bit wide XOR, followed by a reduction NOR. I'm pretty sure there isn't time for that. I'll try it, though. And we'd only have time to check for the Q value, not the pre-decremented value like we for DJNZ. This would have some behavior ramification. I really like this line of thinking. If this doesn't work, maybe there's something else that can be done using Q.
Seairth, the way it works now is that for DJNZ, we check D for $0000_0001 (before the decrement). This is necessary to make everything happen in time. For doing random values like Q, We'd have to have a 32-bit wide XOR, followed by a reduction NOR. I'm pretty sure there isn't time for that. I'll try it, though. And we'd only have time to check for the Q value, not the pre-decremented value like we for DJNZ. This would have some behavior ramification. I really like this line of thinking. If this doesn't work, maybe there's something else that can be done using Q.
That sounds like a non-trivial effort, so I'd say don't bother. Maybe another last minute use will be realized for those instruction codes.
If those are fairly useless, could you easily change them to IJNQ and DJNQ, where you could use SETQ to set the non-jump condition? Of course, that assumes you're not already using Q within the loop. At which point, there's still ADD/TEST/JMP.
As Chip mentions, the actual test is on the pre-decrement value.
DJNZ tests for 01 and DJNS tests for 00.
Where MCU code does use JNQ type tests, that's usually something like CJNE which does not INC/DEC, in the same opcode.
Aside: I'd prefer DJNU ( decrement and jump not underflow) rather than 'not signed', as signed applies to numeric storage formats, not an outcome.
...will set C to the parity of D, without needing any other register.
So, is there a better use for WC in ONES than parity?
We have two empty 'D,S' instruction slots now. I think we should keep them empty, in case a future version of the chip could use those areas to implement something new that we haven't thought of, yet.
For the DJNS instruction (count down thru 0 to FFFF_FFFF), here are some equivalents
DJNS - decrement and jump if NOT SIGNED
DJNU - decrement and jump if NOT UNDERFLOW
DJNOV - decrement and jump if NOT OVERFLOW
DJNM - decrement and jump if NOT MINUS
DJNNEG - decrement and jump if NOT NEGATIVE
While I can see the use of this instruction, I cannot see the point in some of the others including DJO (D=odd), DJE (D=even), etc. Unless there is an imperitive reason where the code is being executed repetitively in some tight timing situation, its just a waste.
For the DJNS instruction (count down thru 0 to FFFF_FFFF), here are some equivalents
DJNS - decrement and jump if NOT SIGNED
DJNU - decrement and jump if NOT UNDERFLOW
DJNOV - decrement and jump if NOT OVERFLOW
DJNM - decrement and jump if NOT MINUS
DJNNEG - decrement and jump if NOT NEGATIVE
While I can see the use of this instruction, I cannot see the point in some of the others including DJO (D=odd), DJE (D=even), etc. Unless there is an imperitive reason where the code is being executed repetitively in some tight timing situation, its just a waste.
Yes, it would be used in a tight loop, usually.
In tight loops, though, it's better to not branch, except for the loop, itself.
I wonder if TJM/TJNM ('max'/'minus 1'/$FFFFFFFF) might be more useful than TJO/TJE. It would complement the TJZ/TJNZ instructions. Sometimes I have to test for $FFFFFFFF and it's always a pain because I need that value in a register, or else I must use ##$FFFFFFFF, which seems wasteful. Being able to do it without a big constant somewhere would be nice. I think that would be more useful that TJO/TJE. Usually, in a place where TJO/TJE might be used, a 'SHR D,#1 WC' is used to advance the data and get the next bit into C. No branching needed there.
That makes me wonder. Are TJS/TJNS very useful?
By the way, I changed DJS/DJNS to DJU/DJNU (underflow) where I just check D for zero. This gives a bigger looping range than DJS/DJNS had. That leaves TJS/TJNS lonesome sign-sensitive branches.
Sorry for this flurry of changes. This fit will be over very soon.
For the DJNS instruction (count down thru 0 to FFFF_FFFF), here are some equivalents
DJNS - decrement and jump if NOT SIGNED
DJNU - decrement and jump if NOT UNDERFLOW
DJNOV - decrement and jump if NOT OVERFLOW
DJNM - decrement and jump if NOT MINUS
DJNNEG - decrement and jump if NOT NEGATIVE
While I can see the use of this instruction, I cannot see the point in some of the others including DJO (D=odd), DJE (D=even), etc. Unless there is an imperitive reason where the code is being executed repetitively in some tight timing situation, its just a waste.
Yes, it would be used in a tight loop, usually.
In tight loops, though, it's better to not branch, except for the loop, itself.
I wonder if TJM/TJNM ('max'/'minus 1'/$FFFFFFFF) might be more useful than TJO/TJE. It would complement the TJZ/TJNZ instructions. Sometimes I have to test for $FFFFFFFF and it's always a pain because I need that value in a register, or else I must use ##$FFFFFFFF, which seems wasteful. Being able to do it without a big constant somewhere would be nice. I think that would be more useful that TJO/TJE. Usually, in a place where TJO/TJE might be used, a 'SHR D,#1 WC' is used to advance the data and get the next bit into C. No branching needed there.
That makes me wonder. Are TJS/TJNS very useful?
By the way, I changed DJS/DJNS to DJU/DJNU (underflow) where I just check D for zero. This gives a bigger looping range than DJS/DJNS had. That leaves TJS/TJNS lonesome sign-sensitive branches.
Sorry for this flurry of changes. This fit will be over very soon.
I can see the use for...
DJZ/DJNZ
DJU/DJNU (allows for jump down to and including zero - just test D for zero before decrementing else $FFFF_FFFF). Is DJU necessary?
TJM/TJNM (test for $FFFF_FFFF). 'M' seems wrong, maybe TJFF/TJNFF ?
TJNEG/TJNNEG (test b31)
I cannot see an overwhelming use for having TJO/TJE or DJO/DJE.
I wonder if TJM/TJNM ('max'/'minus 1'/$FFFFFFFF) might be more useful than TJO/TJE. It would complement the TJZ/TJNZ instructions. Sometimes I have to test for $FFFFFFFF and it's always a pain because I need that value in a register, or else I must use ##$FFFFFFFF, which seems wasteful. Being able to do it without a big constant somewhere would be nice. I think that would be more useful that TJO/TJE. Usually, in a place where TJO/TJE might be used, a 'SHR D,#1 WC' is used to advance the data and get the next bit into C. No branching needed there.
That makes me wonder. Are TJS/TJNS very useful?
By the way, I changed DJS/DJNS to DJU/DJNU (underflow) where I just check D for zero. This gives a bigger looping range than DJS/DJNS had. That leaves TJS/TJNS lonesome sign-sensitive branches.
Sorry for this flurry of changes. This fit will be over very soon.
TJS/TJNS are essential. MOV/NOT/ABS/NEG/NEGC/NEGZ/NEGNZ can write the sign bit to C, which could be used for conditional jump, but TJS/TJNS test D[31] directly without having to use C at all. Similarly for rotate/shift left.
Please don't even think about removing TJS/TJNS. Am I the only person who can see the full worth of TJx? For example when a conditional jump is required but C and Z are already in use or a jump with more than two conditions. The more TJx there are the better.
Here are v29 IJx/DJx/TJx instructions, with DJS/DJNS changed to DJU/DJNU:
ENCOD suggestion:
D = -1 if number of '1's in S = 0, then could use TJS/TJNS or TJM/TJNM for conditional jumps without involving C.
I think that would be disruptive for ENCOD when S=0. I usually use ENCOD to know how many bits are required for shifting or storage. A -1 result for 0 would frustrate things.
ENCOD suggestion:
D = -1 if number of '1's in S = 0, then could use TJS/TJNS or TJM/TJNM for conditional jumps without involving C.
I think that would be disruptive for ENCOD when S=0. I usually use ENCOD to know how many bits are required for shifting or storage. A -1 result for 0 would frustrate things.
ENCOD suggestion:
D = -1 if number of '1's in S = 0, then could use TJS/TJNS or TJM/TJNM for conditional jumps without involving C.
I think that would be disruptive for ENCOD when S=0. I usually use ENCOD to know how many bits are required for shifting or storage. A -1 result for 0 would frustrate things.
Isn't it the case that with USB, where you are getting bytes back, not bits, you'd like an efficient means to process a whole byte, and not want to piece it out, bit by bit?
Is there ever a case where the data to be CRC'd is not a multiple of 8 bits? I know the initial USB stuff is 5 bits, so it might warrant a bitwise CRC function, but isn't most everything else multiples of bytes?
Comments
And all the test-and-set instructions get put into single operand slots.
DJNZ is most useful.
DJZ is a good complement to DJNZ, as it lets you test the loop at the top, which is sometimes necessary.
DJNS is handy because it lets you iterate down to 0, unlike DJNZ. This is nice for, say, cycling from 15 to 0 with the counting variable usable inside the loop.
DJS is to DJNS what DJZ is to DJNZ.
IJNZ is good for iterating from a negative up to 0. Sometimes useful.
IJZ is to IJNZ what DJZ is to DJNZ.
IJS is rather redundant, considering IJNZ.
IJNS is maybe worthless. Good for counting up to $7FFF_FFFF.
So, IJS and IJNS have very low worth. Together they take up one '{#}D,{#}S' instruction slot. They could go.
DJS and DJNS might as well detect $FFFF_FFFF instead of just the MSB.
Ah, I think I'll just leave all these as they are for the sake of symmetry. For inc, dec, and test, we can check Z, NZ, S, NS. And we have three other tests: odd, even, and overflow. That is all good.
I have a v29 ready with all the little fixups from the last two days.
If those are fairly useless, could you easily change them to IJNQ and DJNQ, where you could use SETQ to set the non-jump condition? Of course, that assumes you're not already using Q within the loop. At which point, there's still ADD/TEST/JMP.
The lifespan of Q is only to the next instruction. This is a pretty interesting idea. Of course, it can be done.
That sounds like a non-trivial effort, so I'd say don't bother. Maybe another last minute use will be realized for those instruction codes.
As Chip mentions, the actual test is on the pre-decrement value.
DJNZ tests for 01 and DJNS tests for 00.
Where MCU code does use JNQ type tests, that's usually something like CJNE which does not INC/DEC, in the same opcode.
Aside: I'd prefer DJNU ( decrement and jump not underflow) rather than 'not signed', as signed applies to numeric storage formats, not an outcome.
Good idea.
I've been looking at the new ONES. C = lsb of D = parity of S, which means ONES can be used to test parity.
This code
is equivalent to
So why use ONES when it needs an extra register?
Because writing to C is not needed
which allows C to be used as some other condition
TJO/TJE have already justified their existence.
EDIT:
Changed first instruction to TEST (thanks Chip)
TEST D WC
...will set C to the parity of D, without needing any other register.
So, is there a better use for WC in ONES than parity?
We have two empty 'D,S' instruction slots now. I think we should keep them empty, in case a future version of the chip could use those areas to implement something new that we haven't thought of, yet.
Assuming underflow sets C, wouldn't you have better parity with DJNZ for those to be DJNC?
Underflow sets C in a SUB instruction, but DJNZ consolidates other operations, so that there's no flag reporting.
I'm confused, especially with this mention of parity! Are we talking about new mnemonics or new tests or both?
I meant parity as in "in alignment with, more similar to, etc.". The conversation was only about renaming an existing instruction.
DJNS - decrement and jump if NOT SIGNED
DJNU - decrement and jump if NOT UNDERFLOW
DJNOV - decrement and jump if NOT OVERFLOW
DJNM - decrement and jump if NOT MINUS
DJNNEG - decrement and jump if NOT NEGATIVE
While I can see the use of this instruction, I cannot see the point in some of the others including DJO (D=odd), DJE (D=even), etc. Unless there is an imperitive reason where the code is being executed repetitively in some tight timing situation, its just a waste.
Yes, it would be used in a tight loop, usually.
In tight loops, though, it's better to not branch, except for the loop, itself.
I wonder if TJM/TJNM ('max'/'minus 1'/$FFFFFFFF) might be more useful than TJO/TJE. It would complement the TJZ/TJNZ instructions. Sometimes I have to test for $FFFFFFFF and it's always a pain because I need that value in a register, or else I must use ##$FFFFFFFF, which seems wasteful. Being able to do it without a big constant somewhere would be nice. I think that would be more useful that TJO/TJE. Usually, in a place where TJO/TJE might be used, a 'SHR D,#1 WC' is used to advance the data and get the next bit into C. No branching needed there.
That makes me wonder. Are TJS/TJNS very useful?
By the way, I changed DJS/DJNS to DJU/DJNU (underflow) where I just check D for zero. This gives a bigger looping range than DJS/DJNS had. That leaves TJS/TJNS lonesome sign-sensitive branches.
Sorry for this flurry of changes. This fit will be over very soon.
DJZ/DJNZ
DJU/DJNU (allows for jump down to and including zero - just test D for zero before decrementing else $FFFF_FFFF). Is DJU necessary?
TJM/TJNM (test for $FFFF_FFFF). 'M' seems wrong, maybe TJFF/TJNFF ?
TJNEG/TJNNEG (test b31)
I cannot see an overwhelming use for having TJO/TJE or DJO/DJE.
TJS/TJNS are essential. MOV/NOT/ABS/NEG/NEGC/NEGZ/NEGNZ can write the sign bit to C, which could be used for conditional jump, but TJS/TJNS test D[31] directly without having to use C at all. Similarly for rotate/shift left.
Please don't even think about removing TJS/TJNS. Am I the only person who can see the full worth of TJx? For example when a conditional jump is required but C and Z are already in use or a jump with more than two conditions. The more TJx there are the better.
Here are v29 IJx/DJx/TJx instructions, with DJS/DJNS changed to DJU/DJNU:
It seems to be accepted that IJS/IJNS are of little value and could be done by an increment followed by TJS/TJNS. Here's what I propose:
TJx could then do the following tests:
This covers everything important very well, I think.
D = -1 if S = 0, then could use TJS/TJNS or TJM/TJNM for conditional jumps without involving C.
I think that would be disruptive for ENCOD when S=0. I usually use ENCOD to know how many bits are required for shifting or storage. A -1 result for 0 would frustrate things.
I think you will like it.
Is it D = 0 if S = 0 now?
Thanks, Chip. Could you please attach instructions_v29a.txt or whatever it's called? That's all I want from the multi-megabyte zip file.
Yes.
Just look here:
https://docs.google.com/spreadsheets/d/17ky4SI75Dd-3DpzOsUkaaTAginj7zNWp3-qWaoxh-HU/edit?usp=sharing
Isn't it the case that with USB, where you are getting bytes back, not bits, you'd like an efficient means to process a whole byte, and not want to piece it out, bit by bit?
Is there ever a case where the data to be CRC'd is not a multiple of 8 bits? I know the initial USB stuff is 5 bits, so it might warrant a bitwise CRC function, but isn't most everything else multiples of bytes?
Chip, thank you so much for taking so many of my ideas on board. There's some nice encoding of the DJx/IJx/TJx tests.
I suggest changing description of TJV to include C, from
to Elsewhere correct sign has no quotes and it might not be last add/subtract if C was not written.