INCMOD P2 Instruction

tomcrawfordtomcrawford Posts: 1,054
edited 2019-03-15 - 17:17:54 in Propeller 2
I couldn't find a description anywhere of the P2 Incmod instruction, so I decided to fiddle with it. Here is the program I used:
CON            
    oscmode = $010c3f04               'all the standard stuff
    freq    = 160_000_000     
    baud = 230400
    #62, tx_pin, rx_pin
           
OBJ
   ser: "spin/SmartSerial"  

var
    long  command                   '31..16: current, '15..0 modulo                                    
    long status[3]                  'result, zero flag, carry
    long param[2]                   'pass addresses to cog
    byte cog, x
      
pub main
     clkset(oscmode, freq)
     ser.start(rx_pin, tx_pin, 0, baud)       'start up serial terminal
     ser.str(string("hello, world"))
     ser.nl

     param[0] := @command
     param[1] := @status

     command := 1                         'pasm cog will clear this when ready 
     cog := cognew(@entry, @param)        'send ADDRESS of param list
     repeat until command == 0            'wait for cog to get started
     ser.str(string("cog started: "))
     ser.dec(cog)
     ser.nl

     repeat x from -1 to 18       'try a bunch of values
       doit(x, 11)
     repeat                       'stay alive  

pub  doit(value, modulo)
     command := value<<16 | modulo       'send inputs to PASM cog
     repeat until command == 0           'wait until he is done
     ser.nl                              'now display everthing
     ser.str(string("Input Value: "))
     ser.dec(value)
     ser.str(string("   Modulo: "))
     ser.dec(modulo)
     ser.str(string("   Result: "))
     ser.dec(status)
     ser.str(string("   ZeroFlag: "))
     ser.dec(status[1])
     ser.str(string("   Carry: "))
     ser.dec(status[2])
                 
DAT
entry     ORG 0
          rdlong CmdAdrs, ptra++          'address of command
          rdlong Stat0Adrs, ptra          'status in hub (I will return results here)
          wrlong zero, CmdAdrs            'report cog is started
tarry     rdlong MyCommand, CmdAdrs wz    'await a set of parameters
    if_Z  jmp #tarry
          mov ptra, Stat0Adrs             'nice fresh copy of status address   
          mov dest, MyCommand             'isolate parameters
          sar dest, #16
          mov source, MyCommand
          and source, ##$FFFF
          incmod dest, source wcz         'execute it
          wrlong dest, PTRA++             'the result   
   if_C   wrlong one, PTRA++              'and the flags
  if_NC   wrlong zero, PTRA++
   if_Z   wrlong one, PTRA
  if_NZ   wrlong zero, PTRA
          wrlong zero, CmdAdrs            'and we are done
          jmp #tarry  
 
Zero      long  0 
One       long  1
Cmdadrs   res  1             'address in hub memory of command
stat0Adrs res  1             'address of first servo's status              
MyCommand res  1             'current command
dest      res  1
source    res  1

It adds one to the destination and compares the result to the source. It compares the source to the destination and if they are the same, it sets the destination to 0 and sets both flags (if wcz). If they are NOT equal, it increments the destination and resets both flags (if wcz). I had thought it might do a real modulo (5 mod 4 = 1), but on thinking about it, realized that would have required a division. So it does something besides just increment only in the one case of equality. I figure decmod is similar.
Re-inventing the wheel is not a waste of time if, when you are done, you understand why it is round.

Comments

  • jmgjmg Posts: 13,603
    This was also mentioned in another thread, and that opcode name really should change, as using MODulus in there, gives quite the wrong clues.
    It would be better called INCWRAP, or something, to avoid any MODulus confusion.
  • Mark_TMark_T Posts: 1,981
    edited 2019-03-15 - 21:17:16
  • jmg wrote: »
    This was also mentioned in another thread, and that opcode name really should change, as using MODulus in there, gives quite the wrong clues.
    It would be better called INCWRAP, or something, to avoid any MODulus confusion.

    Yes, they probably should be renamed, especially to get away from the incorrect use of modulus rather than modulo, and also to cover the fact that if D > S the operation performed isn't a true modulo operation no matter how modulo is interpreted.

    Given the comparison occurs before the increment or decrement I'd suggest something more like WRAPINC and WRAPDEC, or WRAP++ and WRAP-- if that isn't seen as too 'C-like'.
  • The names seem perfectly good to me, its a very common operation to keep a counter modulo a constant N,
    which is what the instructions do - so long as the counter starts off modulo N, it remains so - the
    operation is closed modulo N.

    The confusing bit is that the source operand is interpreted as N-1, not N, but that feature allows the instruction
    to work when N = 2^32.
  • jmgjmg Posts: 13,603
    edited 2019-03-16 - 20:48:45
    Mark_T wrote: »
    The names seem perfectly good to me, its a very common operation to keep a counter modulo a constant N,
    which is what the instructions do - so long as the counter starts off modulo N, it remains so - the
    operation is closed modulo N.

    The confusing bit is that the source operand is interpreted as N-1, not N, but that feature allows the instruction
    to work when N = 2^32.

    .. but did you check the details of the exact numeric range of that MOD operator ?
    Type MOD into your calculator, and you see N MOD M does not include M, it is 0..M-1
    AJL wrote: »
    .. and also to cover the fact that if D > S the operation performed isn't a true modulo operation no matter how modulo is interpreted.

    Given the comparison occurs before the increment or decrement I'd suggest something more like WRAPINC and WRAPDEC, or WRAP++ and WRAP-- if that isn't seen as too 'C-like'.

    Either is fine for me..

  • .. but did you check the details of the exact numeric range of that MOD operator ?
    Type MOD into your calculator, and you see N MOD M does not include M, it is 0..M-1

    Did you read what I said? I said the confusing thing about incmod is that the source operand
    denotes N-1, not N as might be expected (until you realized that the way it is allows N to
    equal 2^32, and avoids the issue of mod zero being meaningless since you can't denote N=0).
  • Mark_T wrote: »
    .. but did you check the details of the exact numeric range of that MOD operator ?
    Type MOD into your calculator, and you see N MOD M does not include M, it is 0..M-1

    Did you read what I said? I said the confusing thing about incmod is that the source operand
    denotes N-1, not N as might be expected (until you realized that the way it is allows N to
    equal 2^32, and avoids the issue of mod zero being meaningless since you can't denote N=0).

    indeed it is and bit me hard with my buffer routines.

    Mike
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • jmgjmg Posts: 13,603
    Mark_T wrote: »
    ... I said the confusing thing about incmod is that the source operand
    denotes N-1, not N as might be expected ...
    Then we both agree it is confusing.
    That is exactly why it needs a change of name.

  • It's not a proper mod. It should not be called mod.
    Wrap is probably better.
  • INCWRAP
    DECWRAP
  • RaymanRayman Posts: 9,482
    edited 2019-03-18 - 13:15:34
    If you set S to -1, then would be just like a plain "INC", right?

    Might be nice to have INC and DEC instruction aliases...
    Too bad it takes 2 clocks to get -1 into S... Better with ADD, SUB...
    Ok, never mind, this is nonsense...
    Prop Info and Apps: http://www.rayslogic.com/
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 22,361
    edited 2019-03-18 - 18:24:11
    I guess it depends upon when the comparison is done relative to the operation. If done like this, xxxMOD is a correct mnemonic:
    INCMOD:
      If (++D) == S then D := 0
    
    DECMOD:
      If D-- == 0 then D += S
    

    Of course, that begs the question on whether two operations on D are possible during one instruction or if there's room to hold an intermediate result before the final assignment -- if, in fact, the result is to be written.

    -Phil
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
  • jmgjmg Posts: 13,603
    cgracey wrote: »
    INCWRAP
    DECWRAP

    That's fine.
    Of course, that begs the question on whether two operations on D are possible during one instruction or if there's room to hold an intermediate result before the final assignment -- if, in fact, the result is to be written.
    There is no time to do two things, and an equals tests is the simplest/fastest test in logic.
    That's why the opcode tests for ==, and then decides whether to INC or wrap to zero, of course, that simplicity means the sweep range includes the == value, which MOD does not, and that's why the name change is needed.

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 22,361
    edited 2019-03-18 - 22:04:41
    jmg wrote:
    There is no time to do two things...
    ...as I suspected might be the case. I guess there's still room for INCMOD and DECMOD pseudo-ops when S is an immediate value, which is probably the majority case anyway: just assemble an xxxWRAP instruction with a source value one less than #S.

    -Phil
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
Sign In or Register to comment.