INCMOD P2 Instruction
tomcrawford
Posts: 1,126
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...
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