Shop OBEX P1 Docs P2 Docs Learn Events
C after CMPS/CMPSX/ADDS/ADDSX/SUBS/SUBSX - Page 5 — Parallax Forums

C after CMPS/CMPSX/ADDS/ADDSX/SUBS/SUBSX

1235

Comments

  • evanhevanh Posts: 15,126
    That's the neat thing with conditional execution. Jumping at all becomes optional. It doesn't get used enough, imho.
  • evanhevanh Posts: 15,126
    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.
  • cgraceycgracey Posts: 14,133
    edited 2017-12-14 09:22
    The two I use a lot are DJNZ and DJNS.

    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.
  • cgracey wrote: »
    IJS is rather redundant, considering IJNZ.

    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.
  • cgraceycgracey Posts: 14,133
    Seairth wrote: »
    cgracey wrote: »
    IJS is rather redundant, considering IJNZ.

    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.
  • cgraceycgracey Posts: 14,133
    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.
  • cgracey wrote: »
    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.
  • jmgjmg Posts: 15,140
    Seairth wrote: »
    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.
  • cgraceycgracey Posts: 14,133
    jmg wrote: »
    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.
  • TonyB_TonyB_ Posts: 2,108
    edited 2017-12-18 23:06
    It should be 'sign' instead of 'signed', TJS test and jump on sign, TJNS test and jump on not sign.
  • TonyB_TonyB_ Posts: 2,108
    edited 2017-12-15 00:53
    Chip, many thanks for implementing three of my new TJx ideas: TJO/TJE/TJV. Will the empty slot created above SETPAT stay empty?

    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
    	TEST	reg1		WC
    IF_C	JMP	#parity_odd
    
    is equivalent to
    	ONES	reg2,reg1	WC
    IF_C	JMP	#parity_odd
    
    So why use ONES when it needs an extra register?
    Because writing to C is not needed
    	ONES	reg2,reg1
    	TJO	reg2,#parity_odd
    
    which allows C to be used as some other condition
    	ONES	reg2,reg1
    IF_C	TJO	reg2,#parity_odd	'Jump if parity odd and C
    
    TJO/TJE have already justified their existence.

    EDIT:
    Changed first instruction to TEST (thanks Chip)
  • cgraceycgracey Posts: 14,133
    edited 2017-12-14 23:41
    TonyB_,

    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.
  • cgracey wrote: »
    jmg wrote: »
    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.

    Assuming underflow sets C, wouldn't you have better parity with DJNZ for those to be DJNC?
  • cgraceycgracey Posts: 14,133
    edited 2017-12-14 23:54
    Seairth wrote: »
    cgracey wrote: »
    jmg wrote: »
    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.

    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.
  • TonyB_TonyB_ Posts: 2,108
    edited 2017-12-15 01:01
    cgracey wrote: »
    Seairth wrote: »
    cgracey wrote: »
    jmg wrote: »
    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.

    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?
  • TonyB_ wrote: »
    cgracey wrote: »
    Seairth wrote: »
    cgracey wrote: »
    jmg wrote: »
    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.

    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.
  • Cluso99Cluso99 Posts: 18,066
    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.
  • cgraceycgracey Posts: 14,133
    Cluso99 wrote: »
    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.
  • Cluso99Cluso99 Posts: 18,066
    edited 2017-12-15 04:51
    cgracey wrote: »
    Cluso99 wrote: »
    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.
  • TonyB_TonyB_ Posts: 2,108
    edited 2017-12-15 20:09
    cgracey wrote: »

    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:
    EEEE 1011011 00I DDDDDDDDD SSSSSSSSS        IJZ     D,S/#rel9
    EEEE 1011011 01I DDDDDDDDD SSSSSSSSS        IJNZ    D,S/#rel9
    EEEE 1011011 10I DDDDDDDDD SSSSSSSSS        IJS     D,S/#rel9
    EEEE 1011011 11I DDDDDDDDD SSSSSSSSS        IJNS    D,S/#rel9
    
    EEEE 1011100 00I DDDDDDDDD SSSSSSSSS        DJZ     D,S/#rel9
    EEEE 1011100 01I DDDDDDDDD SSSSSSSSS        DJNZ    D,S/#rel9
    EEEE 1011100 10I DDDDDDDDD SSSSSSSSS        DJU     D,S/#rel9
    EEEE 1011100 11I DDDDDDDDD SSSSSSSSS        DJNU    D,S/#rel9
    
    EEEE 1011101 00I DDDDDDDDD SSSSSSSSS        TJZ     D,S/#rel9
    EEEE 1011101 01I DDDDDDDDD SSSSSSSSS        TJNZ    D,S/#rel9
    EEEE 1011101 10I DDDDDDDDD SSSSSSSSS        TJS     D,S/#rel9
    EEEE 1011101 11I DDDDDDDDD SSSSSSSSS        TJNS    D,S/#rel9
    
    EEEE 1011110 00I DDDDDDDDD SSSSSSSSS        TJO     D,S/#rel9
    EEEE 1011110 01I DDDDDDDDD SSSSSSSSS        TJE     D,S/#rel9
    EEEE 1011110 10I DDDDDDDDD SSSSSSSSS        TJV     D,S/#rel9
    
    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:
    EEEE 1011011 00I DDDDDDDDD SSSSSSSSS    *   DJZ     D,S/#rel9
    EEEE 1011011 01I DDDDDDDDD SSSSSSSSS    *   DJNZ    D,S/#rel9
    EEEE 1011011 10I DDDDDDDDD SSSSSSSSS    *   DJU     D,S/#rel9
    EEEE 1011011 11I DDDDDDDDD SSSSSSSSS    *   DJNU    D,S/#rel9
    
    EEEE 1011100 00I DDDDDDDDD SSSSSSSSS    *   IJZ     D,S/#rel9
    EEEE 1011100 01I DDDDDDDDD SSSSSSSSS    *   IJNZ    D,S/#rel9
    EEEE 1011100 10I DDDDDDDDD SSSSSSSSS    *   TJO     D,S/#rel9
    EEEE 1011100 11I DDDDDDDDD SSSSSSSSS    *   TJE     D,S/#rel9
    
    EEEE 1011101 00I DDDDDDDDD SSSSSSSSS        TJZ     D,S/#rel9
    EEEE 1011101 01I DDDDDDDDD SSSSSSSSS        TJNZ    D,S/#rel9
    EEEE 1011101 10I DDDDDDDDD SSSSSSSSS        TJS     D,S/#rel9
    EEEE 1011101 11I DDDDDDDDD SSSSSSSSS        TJNS    D,S/#rel9
    
    EEEE 1011110 00I DDDDDDDDD SSSSSSSSS   **   TJM     D,S/#rel9
    EEEE 1011110 01I DDDDDDDDD SSSSSSSSS   **   TJNM    D,S/#rel9
    EEEE 1011110 10I DDDDDDDDD SSSSSSSSS        TJV     D,S/#rel9
    
     * = moved
    ** = new
    
    TJx could then do the following tests:
    All bits high or low	TJM/TJZ
    Any bit  high or low	TJNZ/TJNM
    Msb      high or low	TJS/TJNS
    Lsb      high or low	TJO/TJE
    Overflow		TJV
    
    This covers everything important very well, I think.
  • TonyB_TonyB_ Posts: 2,108
    edited 2017-12-15 22:34
    ENCOD suggestion:
    D = -1 if S = 0, then could use TJS/TJNS or TJM/TJNM for conditional jumps without involving C.
  • cgraceycgracey Posts: 14,133
    edited 2017-12-15 22:36
    TonyB_ wrote: »
    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.
  • cgraceycgracey Posts: 14,133
    edited 2017-12-15 22:37
    I will post the new map soon.

    I think you will like it.
  • cgracey wrote: »
    TonyB_ wrote: »
    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.

    Is it D = 0 if S = 0 now?
  • cgracey wrote: »
    I will post the new map soon.

    I think you will like it.

    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.

  • cgraceycgracey Posts: 14,133
    TonyB_ wrote: »
    cgracey wrote: »
    TonyB_ wrote: »
    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.

    Is it D = 0 if S = 0 now?

    Yes.
  • cgraceycgracey Posts: 14,133
    TonyB_ wrote: »
    cgracey wrote: »
    I will post the new map soon.

    I think you will like it.

    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.

    Just look here:

    https://docs.google.com/spreadsheets/d/17ky4SI75Dd-3DpzOsUkaaTAginj7zNWp3-qWaoxh-HU/edit?usp=sharing
  • cgraceycgracey Posts: 14,133
    edited 2017-12-15 23:50
    Here is the current instructions.txt file. Just look for the * characters. They denote the changed instructions:

    instructions.txt

  • cgraceycgracey Posts: 14,133
    Cluso99 and Garryj,

    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?
  • cgracey wrote: »
    Here is the current instructions.txt file. Just look for the * characters. They denote the changed instructions:

    instructions.txt

    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
    Test D and jump to S** if D overflowed (D[31] != 'correct sign' from last addition/subtraction).
    
    to
    Test D and jump to S** if D overflowed (D[31] != C, correct sign from addition/subtraction).
    
    Elsewhere correct sign has no quotes and it might not be last add/subtract if C was not written.
Sign In or Register to comment.