INCMOD P2 Instruction

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:
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.
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.
Comments
It would be better called INCWRAP, or something, to avoid any MODulus confusion.
[ column F ]
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'.
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
Either is fine for me..
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
That is exactly why it needs a change of name.
Wrap is probably better.
DECWRAP
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...
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
That's fine.
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