Question about ALTDS implementation in new chip

ozpropdevozpropdev Posts: 2,473
edited 2014-06-29 - 09:42:35 in Propeller 2
Chip
Did these changes to ALTDS make it into the new chip?

See here

Cheers
Brian
Melbourne, Australia
«1

Comments

  • cgraceycgracey Posts: 10,988
    edited 2014-06-26 - 16:46:15
    ALTDS uses a D register for D/S field substitutions in the next instruction, while S/# modifies the D register's D and S fields and controls D/S substitution.

    ALTDS D,S/#

    D - a register whose D/S fields may be substituted for the next instructions' D/S fields
    S/# - an 8-bit code: %ABBBCDDD

    %A: 0 = don't substitute next instructions' D field with current D register's D field, 1 = substitute next instructions' D field with current D register's D field
    %BBB: 000 = leave the current D register's D field the same, 0xx = add 1/2/3 to D field, 1xx = subtract 1/2/3/4 from D field
    %C: 0 = don't substitute next instructions' S field with current D register's S field, 1 = substitute next instructions' S field with current D register's S field
    %DDD: 000 = leave the current D register's S field the same, 0xx = add 1/2/3 to S field, 1xx = subtract 1/2/3/4 from S field
  • Cluso99Cluso99 Posts: 14,828
    edited 2014-06-26 - 22:29:41
    Chip,
    In the linked post you discussed this...
    cgracey wrote: »
    Great idea!!!

    We've only got six bits specified for S/# in ALTDS, so we can use the three bits above to specify write-register alteration, with D[31:23] serving as the pointer for write redirection:

    ALTDS D,S/#

    S/# = %rrr_ddd_sss

    rrr = same as ddd/sss, but uses D[31:23] as a write redirection pointer.

    MOVI D,S/# can be used to set D[31:23]

    Now we've got it all in one instruction!!!
    This permits the additional possibilities of:
    * redirecting the result
    * redirecting the result to an unused register (maybe INx) to perform a pseudo NR

    Therefore, might it be beneficial, and would it be easy to do the following ???
    S/# = %RRRDDDSSS
    where RRR, DDD and SSS mean:
    000 = don't substitute next instructions S/D/R field, leave the current D registers S/D/I value the same
    001 = substitute next instructions S/D/R field with the current D registers S/D/I field, then add 1 to the current D registers S/D/I value
    010 = substitute next instructions S/D/R field with the current D registers S/D/I field, then add 2 to the current D registers S/D/I value
    011 = substitute next instructions S/D/R field with the current D registers S/D/I field, then add 4 to the current D registers S/D/I value
    100 = substitute next instructions S/D/R field with the current D registers S/D/I field, leave the current D registers S/D/I value the same
    101 = substitute next instructions S/D/R field with the current D registers S/D/I field, then subtract 1 from the current D registers S/D/I value
    110 = substitute next instructions S/D/R field with the current D registers S/D/I field, then subtract 2 from the current D registers S/D/I value
    111 = substitute next instructions S/D/R field with the current D registers S/D/I field, then subtract 4 from the current D registers S/D/I value

    1/2/4 covers byte/word/long in hub, and 1/2/4 longs in cog.
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • cgraceycgracey Posts: 10,988
    edited 2014-06-27 - 04:39:47
    Cluso99 wrote: »
    Chip,
    In the linked post you discussed this...

    This permits the additional possibilities of:
    * redirecting the result
    * redirecting the result to an unused register (maybe INx) to perform a pseudo NR

    Therefore, might it be beneficial, and would it be easy to do the following ???
    S/# = %RRRDDDSSS
    where RRR, DDD and SSS mean:
    000 = don't substitute next instructions S/D/R field, leave the current D registers S/D/I value the same
    001 = substitute next instructions S/D/R field with the current D registers S/D/I field, then add 1 to the current D registers S/D/I value
    010 = substitute next instructions S/D/R field with the current D registers S/D/I field, then add 2 to the current D registers S/D/I value
    011 = substitute next instructions S/D/R field with the current D registers S/D/I field, then add 4 to the current D registers S/D/I value
    100 = substitute next instructions S/D/R field with the current D registers S/D/I field, leave the current D registers S/D/I value the same
    101 = substitute next instructions S/D/R field with the current D registers S/D/I field, then subtract 1 from the current D registers S/D/I value
    110 = substitute next instructions S/D/R field with the current D registers S/D/I field, then subtract 2 from the current D registers S/D/I value
    111 = substitute next instructions S/D/R field with the current D registers S/D/I field, then subtract 4 from the current D registers S/D/I value

    1/2/4 covers byte/word/long in hub, and 1/2/4 longs in cog.


    I had forgotten about this! Yes, we'll have three 3-bit fields so that the result can be redirected, as well. Thanks for bringing this up.
  • Cluso99Cluso99 Posts: 14,828
    edited 2014-06-27 - 05:49:09
    cgracey wrote: »
    I had forgotten about this! Yes, we'll have three 3-bit fields so that the result can be redirected, as well. Thanks for bringing this up.
    Fantastic, thanks Chip :)
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • Cluso99Cluso99 Posts: 14,828
    edited 2014-06-27 - 13:29:15
    Chip,
    Would it be easy to add a special case of S=000_000_000 (effectively did nothing) to cancel the write back of the result?
    This could have its own mnemonic "NR" meaning the next instruction would be equivalent to an NR effect. This makes up for the lost NR effect in the P1. So by using a pair of instructions we could set the Z and C flags without changing the destination.
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • cgraceycgracey Posts: 10,988
    edited 2014-06-27 - 17:55:35
    Cluso99 wrote: »
    Chip,
    Would it be easy to add a special case of S=000_000_000 (effectively did nothing) to cancel the write back of the result?
    This could have its own mnemonic "NR" meaning the next instruction would be equivalent to an NR effect. This makes up for the lost NR effect in the P1. So by using a pair of instructions we could set the Z and C flags without changing the destination.


    Good idea! I'll make it do that.
  • ozpropdevozpropdev Posts: 2,473
    edited 2014-06-27 - 18:32:18
    Great Chip!
    A versatile replacement for the indirect registers of the old P2.
    Melbourne, Australia
  • Cluso99Cluso99 Posts: 14,828
    edited 2014-06-27 - 23:32:32
    Fantastic news Chip!

    How are things progressing?
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • Bill HenningBill Henning Posts: 6,445
    edited 2014-06-29 - 07:16:44
    Good idea!

    Could the same effect be achieved by redirecting the D to INA? (ie the hidden ram behind it)
    Cluso99 wrote: »
    Chip,
    Would it be easy to add a special case of S=000_000_000 (effectively did nothing) to cancel the write back of the result?
    This could have its own mnemonic "NR" meaning the next instruction would be equivalent to an NR effect. This makes up for the lost NR effect in the P1. So by using a pair of instructions we could set the Z and C flags without changing the destination.
    www.mikronauts.com / E-mail: mikronauts _at_ gmail _dot_ com / @Mikronauts on Twitter
    RoboPi: The most advanced Robot controller for the Raspberry Pi (Propeller based)
  • cgraceycgracey Posts: 10,988
    edited 2014-06-29 - 07:28:24
    Good idea!

    Could the same effect be achieved by redirecting the D to INA? (ie the hidden ram behind it)

    Yes, but you would need a register to be holding $1FA<<23. By using S=0 to do the same thing, A simple ALTDS 0,#0 could cancel the write.
  • cgraceycgracey Posts: 10,988
    edited 2014-06-29 - 07:30:51
    Cluso99 wrote: »
    Fantastic news Chip!

    How are things progressing?


    Really solidly and simply. This new design has no hard-to-think-about details, so it's not difficult to know when sections of it are completed, which is a big stress reliever.
  • Bill HenningBill Henning Posts: 6,445
    edited 2014-06-29 - 07:43:53
    Makes sense, thanks.

    FYI - I LOVE the new LOCADDR/LINK being able to load PTRA/B and six additional high registers!
    cgracey wrote: »
    Yes, but you would need a register to be holding $1FA<<23. By using S=0 to do the same thing, A simple ALTDS 0,#0 could cancel the write.
    www.mikronauts.com / E-mail: mikronauts _at_ gmail _dot_ com / @Mikronauts on Twitter
    RoboPi: The most advanced Robot controller for the Raspberry Pi (Propeller based)
  • Cluso99Cluso99 Posts: 14,828
    edited 2014-06-29 - 09:42:35
    cgracey wrote: »
    Really solidly and simply. This new design has no hard-to-think-about details, so it's not difficult to know when sections of it are completed, which is a big stress reliever.
    That's great news. Simple designs are also simpler to explain and understand too.
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • @cgracey: Is the current ALTDS implementation the same as documented here? If so, I have a few questions:

    What is the value of altering both the D and S at the same time?

    What is the value of altering the instruction bits?

    What would happen if you alter S on an instruction like COGID (where S is part of the opcode)?

    How would I go about moving data between two buffers? For instance:
                    mov count, #16
    :loop           altds ????, #%000_001_001
                    mov 0, 0
                    djnz count, #:loop
    
    dest            long    $100
    src             long    $180
    count           res     1
    
  • I think it would be:
              mov   count, #16
              mov   pntrs, initial
    :loop     altds pntrs, #%000_001_001
              mov   0, 0
              djnz  count, #:loop
    
    initial   long   $100<< 9 | $180
    pntrs     res    1
    count     res    1
    
  • Mike Green wrote: »
    I think it would be:
              mov   count, #16
              mov   pntrs, initial
    :loop     altds pntrs, #%000_001_001
              mov   0, 0
              djnz  count, #:loop
    
    initial   long   $100<< 9 | $180
    pntrs     res    1
    count     res    1
    

    I was wondering if that was the approach. If so, this would imply that just to manipulate D, you would always have to start with a 9-bit value that's shifted 9 bits.

    Actually, the more I think about this, that's the only way to do this. ALTDS has to be able to write back to a single register (unless it's going to take additional clock cycles), which would mean that both D and S values would have to be in the same register.

    Doing a slight variation of your solution, maybe something like:
                    setd indirect, dest
                    sets indirect, src
                    mov count, #16
    :loop           altds indirect, #%000_001_001
                    mov 0, 0
                    djnz count, #:loop
    
    dest            long    $100
    src             long    $180
    indirect        res     1
    count           res     1
    

  • Can you chain multiple ALTDS instructions to obtain more levels of indirection?
  • No

    You could have an ALTDS followed by another ALTDS, but the first one would affect the instruction following it which is another ALTDS and modify the destination and source addresses/operands of the second ALTDS. The modified second ALTDS would, in turn, modify the instruction following it, but that doesn't give you multiple levels of indirection.
  • ElectrodudeElectrodude Posts: 1,271
    edited 2015-09-13 - 03:55:17
    Mike Green wrote: »
    No

    You could have an ALTDS followed by another ALTDS, but the first one would affect the instruction following it which is another ALTDS and modify the destination and source addresses/operands of the second ALTDS. The modified second ALTDS would, in turn, modify the instruction following it, but that doesn't give you multiple levels of indirection.

    That sounds to me like multiple levels of indirection. What am I missing?

    From what I can tell, the following should copy the register pointed to by the register pointed to by ptr2ptr into result (result = **ptr2ptr):
    altds ptr2ptr, #%000_000_100
    altds 0-0, #%000_000_100
    mov result, 0-0
    


    EDIT: the above is wrong; the following is modified to replace the D instead of S field of the seconds ALTDS:
    altds ptr2ptr, #%000_100_000
    altds 0-0, #%000_000_100
    mov result, 0-0
    
  • SeairthSeairth Posts: 2,371
    edited 2015-09-13 - 03:23:22
    Mike Green wrote: »
    No

    You could have an ALTDS followed by another ALTDS, but the first one would affect the instruction following it which is another ALTDS and modify the destination and source addresses/operands of the second ALTDS. The modified second ALTDS would, in turn, modify the instruction following it, but that doesn't give you multiple levels of indirection.

    That sounds to me like multiple levels of indirection. What am I missing?

    From what I can tell, the following should copy the register pointed to by the register pointed to by ptr2ptr into result (result = **ptr2ptr):
    altds ptr2ptr, #%000_000_100
    altds 0-0, #%000_000_100
    mov result, 0-0
    

    The first ALTDS would replace the "%000_000_100" in the second ALTDS. But you actually need to replace the d-field. Maybe something like this:
    MOV reg2, #$100              ' pretend reg2 is at $0FF
    MOV reg1, #reg2            
    SHL reg1, #9                 ' reg1 contains %01_11111110_00000000
    ALTDS addr1, #000_001_000    ' replaces next instruction's D with $0FF (which contains $100)
    ALTDS 0-0, #000_000_001      ' replaces next instruction's S with $100
    MOV dest, 0-0                 ' becomes MOV dest, $100
    
  • SeairthSeairth Posts: 2,371
    edited 2015-09-13 - 03:22:12
    But, more to Mike's point, I think he's saying that the you cannot do double indirection simply be using two consecutive ALTDSs. You must manipulate the indirect pointers to get them to work right.
  • SeairthSeairth Posts: 2,371
    edited 2015-09-13 - 03:54:36
    Suppose you just got rid of the increment/decrement feature, as well as the third field manipulation, and did the following:
    0111000 00- CCCC --------- ---------		NR            ' for Cluso
    0111000 01I CCCC --------- SSSSSSSSS		ALTS	S/#
    0111000 10I CCCC DDDDDDDDD ---------		ALTD	D/#
    0111000 11I CCCC DDDDDDDDD SSSSSSSSS		ALTDS	D,S/#
    

    Yes, you would have to manually increment/decrement the indirect registers. But this approach would be so much simpler to understand and would not require bit shifting, configuration bits, etc. It would also let @Electrodude do double indirection.
  • ElectrodudeElectrodude Posts: 1,271
    edited 2015-09-13 - 04:20:50
    How about this?
    mov   tmp,    ptr2ptr       ' tmp = ptr2ptr
    shl   tmp,    #9            ' shift ptr2ptr into D field of tmp
    altds tmp,    #%000_100_000 ' use D field of tmp as D field of next instruction
    altds 0-0,    #%000_000_100 ' use S field of register pointed to by ptr2ptr (D of tmp)
                                '  as S field of next instruction
    mov   result, 0-0           ' result = **(D of tmp) = **ptr2ptr
    
  • evanhevanh Posts: 6,872
    edited 2015-09-13 - 04:47:28
    Just out of interest, I think the following will work for single indirection:
                   setd indirect, #$100
                   sets indirect, #$180
                   mov count, #16
    :loop          altds indirect, #%000_001_001
    indirect       mov 0-0, 0-0
                   djnz count, #:loop
    
    count          res     1
    
    The ALTDS instruction will write back after the instruction fetch of MOV so the result is still the same as a separately stored Cog pointer D/S pair.
    "There's no huge amount of massive material
    hidden in the rings that we can't see,
    the rings are almost pure ice."
  • evanhevanh Posts: 6,872
    edited 2015-09-13 - 06:10:53
    That should work nicely for RD/WRLUT as well. Running tables is the common use.

    Interestingly, ALTDS only saves one instruction in the loop. REP saves another though, so it becomes something like:
                   setd indirect, #$100
                   sets indirect, #$180
                   rep #(loopend-loop), #16
    :loop          altds indirect, #%000_001_001
    indirect       mov 0-0, 0-0
    :loopend
    

    PS: And the only reason ALTDS saves an instruction here is because both the source and destination are in the same MOV instruction. If the operation is more complicated than a single instruction then an ADD srcptr / ADD destptr instruction pair will still be as quick.

    But it does save space still, by not needing a separate pointer store, so there is that.

    PPS: To be fair, this is not full indirection but rather a limited but common use case in Cog space. Won't most full indirection be in Hub space?
    "There's no huge amount of massive material
    hidden in the rings that we can't see,
    the rings are almost pure ice."
  • Oh, an ALTDS preceding an AUGD/AUGS could be fun. Would be nice to think that the three fields can fill the entire 23 immediate bits of the AUG instructions. But I guess the PTRA/PTRB registers are intended to fill this roll.
    "There's no huge amount of massive material
    hidden in the rings that we can't see,
    the rings are almost pure ice."
  • evanhevanh Posts: 6,872
    edited 2015-09-13 - 07:12:05
    Seairth wrote: »
    The first ALTDS would replace the "%000_000_100" in the second ALTDS. But you actually need to replace the d-field. Maybe something like this:
    MOV reg2, #$100              ' pretend reg2 is at $0FF
    MOV reg1, #reg2            
    SHL reg1, #9                 ' reg1 contains %01_11111110_00000000
    ALTDS addr1, #000_001_000    ' replaces next instruction's D with $0FF (which contains $100)
    ALTDS 0-0, #000_000_001      ' replaces next instruction's S with $100
    MOV dest, 0-0                 ' becomes MOV dest, $100
    

    A tidy up would be:
                    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
    

    That's neat. I wasn't expecting this result of only a single ALTDS needed. Maybe my previous use wasn't so narrow after all.
    "There's no huge amount of massive material
    hidden in the rings that we can't see,
    the rings are almost pure ice."
  • Electrodude,
    I think you've missed a little detail. The assignment of ptr2ptr into tmp fails because you are copying the contents of ptr2ptr rather than it's address.

    And ALTDS is only capable of working with contents as it's source and writeback. That's why I've used the SETD instruction - to extract the address of reg2.
    "There's no huge amount of massive material
    hidden in the rings that we can't see,
    the rings are almost pure ice."
  • evanhevanh Posts: 6,872
    edited 2015-09-13 - 09:41:03
    Interestingly, a real example of double indirection seems to not only need two ALTDS's but also the intermediary MOV as well. Also note I couldn't use self-modifying code for storing the pointers because they are applied as S operands. EDIT: All the earlier attempts, mine included, fail because of this need to work on the S operand.
                    mov  total, #0
                    mov  ptr2ptr, #raceptrtable
                    rep  #(loopend-loop), #(racetablend-raceptrtable)
    :loop
                    altds  ptr2ptr, #000_000_001   ' apply ptr2ptr to next instruction then increment
                    mov  ptr1, 0-0                 ' use the applied pointer
                    altds  ptr1, #000_000_100      ' apply ptr1 to next instruction
                    add  total, 0-0                ' sum the list scores  - ie: use the applied pointer
    :loopend
    
    
    total           res  1
    ptr1            res  1
    ptr2ptr         res  1
    raceptrtable    long  $100,$10A,$11A,$12C,$138,$144   ' table of pointers to list of scores
    racetablend
    
    "There's no huge amount of massive material
    hidden in the rings that we can't see,
    the rings are almost pure ice."
  • evanhevanh Posts: 6,872
    edited 2015-09-13 - 11:15:28
    Err, I could save a long and have self modifying by changing the intermediate MOV to store into itself.
                    mov  total, #0
                    mov  ptr2ptr, #raceptrtable
                    rep  #(:loopend-:loop), #(racetablend-raceptrtable)
    :loop
                    altds  ptr2ptr, #000_000_001   ' apply ptr2ptr to next instruction then increment
    ptr1            sets  ptr1, 0-0                ' store a table entry right in this instruction
                    altds  ptr1, #000_000_100      ' apply ptr1 to next instruction
                    add  total, 0-0                ' sum the list scores  - ie: use the applied pointer
    :loopend
    
    
    total           res  1
    ptr2ptr         res  1
    raceptrtable    long  $100,$10A,$11A,$12C,$138,$144   ' table of pointers to list of scores
    racetablend
    
    "There's no huge amount of massive material
    hidden in the rings that we can't see,
    the rings are almost pure ice."
Sign In or Register to comment.