Welcome to the Parallax Discussion Forums, sign-up to participate.

Posts: 5,943
edited 2014-03-15 - 10:04:47
I thought I would start a thread to ask about undocumented P2 instructions. There are several instructions in Prop2_Docs.txt where the opcode is shown, but there is no other information.

So my first question is what does SCL do? I assume it's a scaled multiply, but how exactly does it work?
«1

• Posts: 9,771
edited 2014-03-09 - 19:55:11
Do not taunt Happy Fun Ball! @opengeekorg ---> Be Excellent To One Another SKYPE = acuity_doug
Parallax colors simplified: https://forums.parallax.com/discussion/123709/commented-graphics-demo-spin<br>
• Posts: 5,943
edited 2014-03-09 - 20:11:18
I didn't see an description of the SCL instruction on that page, or +/2 pages around it.
• Posts: 9,771
edited 2014-03-09 - 20:16:06
I had it bookmarked when I saw the instruction discussed with the intent to go back and parse it later, or start asking as you have. Good idea BTW. I may well be asking for info on some instructions myself.

MUL, MACA, and MACB all do signed 20x20-bit (lower 20 bits of D and S) integer multiplications which yield signed 40-bit products. Only SCL does the 2.18 x 2.18-bit signed multiplication.

Looks to me, like SCL does a fixed point multiply with D & S in 2.18 bit format. You get the result:
SCL returns bits 39..18, sign-extended, into D.
Do not taunt Happy Fun Ball! @opengeekorg ---> Be Excellent To One Another SKYPE = acuity_doug
Parallax colors simplified: https://forums.parallax.com/discussion/123709/commented-graphics-demo-spin<br>
• Posts: 5,943
edited 2014-03-09 - 20:28:40
OK, thanks for the information.
• Posts: 2,211
edited 2014-03-10 - 03:35:23
SCL is a fractional multiply. Something like ** in Spin:

SCL a,b ' a = (a * b) ~> 18

a and b are 20bit numbers and the result is the 40bit product shifted right by 18 = 22 bits signed. (as potatohead says)

Andy
• Posts: 5,943
edited 2014-03-10 - 06:06:44
I can't find anything on CMPR. What does that do?
• Posts: 1,698
edited 2014-03-10 - 06:27:58
Dave Hein wrote: »
I can't find anything on CMPR. What does that do?

Clusso99 mentions it here:

http://forums.parallax.com/archive/index.php/t-146797.html

C.W.
• Posts: 5,943
edited 2014-03-10 - 06:44:31
That's for the link to CMPR. It's funny that I had already coded SUBR in spinsim, but somehow I didn't make the connection to CMPR.

Now I'm looking at ESWAP8 and ESWAP4. So ESWAP8 does an endian swap on bytes, correct? Does ESWAP4 swap nybbles in a similar manner? Seems odd to devote an instruction for that. Would anybody ever use it?
• Posts: 5,943
edited 2014-03-10 - 09:53:02
I'm assuming SETX sets D[22..18] with the bits in S[4..0], correct?

What do INCPAT and DECPAT do? The documentation I found says that it sets D to the next/previous value with the same number of ones and zeros. Is this a sequential pattern where the sequence starting with 111 would be {111, 1011, 1101, 1110, 10011, ...}?

What does SETBYTS do?
• Posts: 2,211
edited 2014-03-10 - 11:01:17
Dave Hein wrote: »
I'm assuming SETX sets D[22..18] with the bits in S[4..0], correct?

What do INCPAT and DECPAT do? The documentation I found says that it sets D to the next/previous value with the same number of ones and zeros. Is this a sequential pattern where the sequence starting with 111 would be {111, 1011, 1101, 1110, 10011, ...}?

What does SETBYTS do?

SETX, INCPAT and DECPAT are correct (don't ask me for what INCPAT and DECPAT is good)

Here is waht I have found with some Tests on the FPGA:
ESWAP8: input:\$12345678  output:\$78563412  Z=result==0  C=Bit31 before swap
ESWAP4: input:\$12345678  output:\$87654321  Z=result==0  C=Bit31 before swap

MOVBYTS D,#%%3210: input:\$12345678  output:\$12345678  Z=result==0  C=Bit31 of input
MOVBYTS D,#%%0123: input:\$12345678  output:\$78563412  Z=result==0  C=Bit31 of input
MOVBYTS D,#%%0011: input:\$12345678  output:\$78785656  Z=result==0  C=Bit31 of input
-> output.byte[0] = input.byte[S[1..0]]
output.byte[1] = input.byte[S[3..2]]
output.byte[2] = input.byte[S[5..4]]
output.byte[3] = input.byte[S[7..6]]

SETBYTS D,S: set S[7..0] to all 4 bytes in D  Z=result==0  C=Bit31 of input

I don't know for what ESWAP4 is good. A nibble swap in every byte in D would perhaps be more useful
MOVBYTS D,#%%0123 does the same as ESWAP8 so the latter may be removed

Andy
• Posts: 5,943
edited 2014-03-10 - 11:18:06
Thanks. It would be good to have some of this information added to Prop2_Docs.txt.
• Posts: 11,651
edited 2014-03-10 - 15:10:27
Dave Hein wrote: »
Thanks. It would be good to have some of this information added to Prop2_Docs.txt.

I know. I'm about to start the doc work, so I'll address those. I'm just testing the T3SAVE/T3LOAD instructions now.
• Posts: 2,547
edited 2014-03-10 - 16:59:47
ESWAP4 is useful for swapping 4 bit color offsets for sending to the pixel shifter.
It also works well with ROLNIB to form a RORNIB substitute.

On the subject of instructions usage.
The INCMOD D,#n will increment D. If D=#n on increment D is set to 0 (z=1) and C=1(Rollover). If D > #n no rollover occurs.
Same applies to DECMOD, the D value must initially be in the range of 0 to #n for correct operation.
Melbourne, Australia
• Posts: 2,652
edited 2014-03-10 - 17:24:37
ozpropdev,
Re: INCMOD/DECMOD That sounds like a bug to me. In any case it's not intuitive at all. the value of D should be MODed regardless of it's starting value. Otherwise it's not a true MOD and the instruction should have a different name.
• Posts: 15,355
edited 2014-03-10 - 17:35:19
I thought (from asking a while ago) that INCMOD & DECMOD increment and decrement to the next/previous binary number with the same number of ones and zeros.
Sort of similar to the grey encoding where only 1 bit changes at a time.
My Prop boards:
Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
Website: www.clusos.com
• Posts: 2,652
edited 2014-03-10 - 17:38:15
Cluso99,
That's what INCPAT/DECPAT do.
• Posts: 9,771
edited 2014-03-10 - 17:40:22
Heh, my first thought too... Clearly this is a great thread! We will get the instructions sorted and maybe find some bugs.

@roy: Thanks.
Do not taunt Happy Fun Ball! @opengeekorg ---> Be Excellent To One Another SKYPE = acuity_doug
Parallax colors simplified: https://forums.parallax.com/discussion/123709/commented-graphics-demo-spin<br>
• Posts: 2,547
edited 2014-03-10 - 18:25:44
Roy Eltham wrote: »
ozpropdev,
Re: INCMOD/DECMOD That sounds like a bug to me. In any case it's not intuitive at all. the value of D should be MODed regardless of it's starting value. Otherwise it's not a true MOD and the instruction should have a different name.

I'm assuming the definition for INCMOD and DECMOD is quite simple at the moment.

INCMOD : if d=#n then d=0 else add d,#1
DECMOD : if d=0 then d=#n else sub d,#1

This did trip me up for a while. I accidently had a out of range value once which upset things a bit.
Making them allow for out of range input values would add a lot more gates/silicon?
Melbourne, Australia
• Posts: 6,506
edited 2014-03-10 - 19:05:53
Ariba wrote: »
SETX, INCPAT and DECPAT are correct (don't ask me for what INCPAT and DECPAT is good)

Here is waht I have found with some Tests on the FPGA:
ESWAP8: input:\$12345678  output:\$78563412  Z=result==0  C=Bit31 before swap
ESWAP4: input:\$12345678  output:\$87654321  Z=result==0  C=Bit31 before swap

MOVBYTS D,#%%3210: input:\$12345678  output:\$12345678  Z=result==0  C=Bit31 of input
MOVBYTS D,#%%0123: input:\$12345678  output:\$78563412  Z=result==0  C=Bit31 of input
MOVBYTS D,#%%0011: input:\$12345678  output:\$78785656  Z=result==0  C=Bit31 of input
-> output.byte[0] = input.byte[S[1..0]]
output.byte[1] = input.byte[S[3..2]]
output.byte[2] = input.byte[S[5..4]]
output.byte[3] = input.byte[S[7..6]]

SETBYTS D,S: set S[7..0] to all 4 bytes in D  Z=result==0  C=Bit31 of input

I don't know for what ESWAP4 is good. A nibble swap in every byte in D would perhaps be more useful
MOVBYTS D,#%%0123 does the same as ESWAP8 so the latter may be removed

Andy

Andy,

Do you have a nice little test rig you use to run single instructions or blocks of code and print out results? That looks pretty handy!!
MOV OUTA, PEACE <div>Rick </div><div>"I've stopped using programming languages with Garbage Collection, they keep deleting my source code!!"</div>
• Posts: 5,943
edited 2014-03-10 - 19:24:36
In the case of MOVBYTS and SETBYTS are the Z and C flags written? The latest document shows that the flags are not written.
• Posts: 2,547
edited 2014-03-10 - 19:42:52
Dave Hein wrote: »
In the case of MOVBYTS and SETBYTS are the Z and C flags written? The latest document shows that the flags are not written.

Results for SETBYTS show flags are not written. Also Pnut doesn't allow effects in source for SETBYTS.
P2 Test Toolbox V1.3
>O
Before:  Pass #0  Log: OFF=0
Instruction: 1010010_00_0_1111_000001100_000001101 \$00C,\$00D 12,13
Flags: Z=1 C=0
D=\$0000_0000  %0000_0000_0000_0000_0000_0000_0000_0000  0
S=\$0000_002A  %0000_0000_0000_0000_0000_0000_0010_1010  42

After:   Pass #1  Log: OFF=0
Instruction: 1010010_00_0_1111_000001100_000001101 \$00C,\$00D 12,13
Flags: Z=1 C=0
D=\$2A2A_2A2A  %0010_1010_0010_1010_0010_1010_0010_1010  77406378
S=\$0000_002A  %0000_0000_0000_0000_0000_0000_0010_1010  42

Melbourne, Australia
• Posts: 11,651
edited 2014-03-10 - 19:55:55
ozpropdev wrote: »
I'm assuming the definition for INCMOD and DECMOD is quite simple at the moment.

INCMOD : if d=#n then d=0 else add d,#1
DECMOD : if d=0 then d=#n else sub d,#1

This did trip me up for a while. I accidently had a out of range value once which upset things a bit.
Making them allow for out of range input values would add a lot more gates/silicon?

It would add a magnitude comparator, which is bigger and slower than the current equality comparator. Regardless, I don't see why you would ever introduce an out-of-range initial value that would need to be limited on the first iteration. These instruction will set C if the limit was reached and the value was reset. For example 'INCMOD reg,#2 WC' will set the carry on every 3rd iteration (of course, you'd need to start with a value 0..2, with 0 being the likely candidate).
• Posts: 2,652
edited 2014-03-10 - 20:58:25
Typical use case for a MOD instruction is to take a value larger than the range and mod it into range. It's really odd that an instruction that is doing a MOD as part of it's operation, only does so for values starting in the range.

It's not really a MOD operation. It probably shouldn't be using MOD in the name. Maybe, INCWRAP/DECWRAP ?
• Posts: 11,651
edited 2014-03-10 - 23:01:56
Roy Eltham wrote: »
Typical use case for a MOD instruction is to take a value larger than the range and mod it into range. It's really odd that an instruction that is doing a MOD as part of it's operation, only does so for values starting in the range.

It's not really a MOD operation. It probably shouldn't be using MOD in the name. Maybe, INCWRAP/DECWRAP ?

INCMOD and DECMOD create modulus counter functions, so I don't think the names are too far off-base. From a software-background standpoint, I can see the issue. In software, macro things happen, while in hardware, micro things happen.
• Posts: 13,843
edited 2014-03-10 - 23:44:47
Roy Eltham wrote: »
Typical use case for a MOD instruction is to take a value larger than the range and mod it into range. It's really odd that an instruction that is doing a MOD as part of it's operation, only does so for values starting in the range.

It's not really a MOD operation. It probably shouldn't be using MOD in the name. Maybe, INCWRAP/DECWRAP ?

I'd agree with this summary. MOD has explicit and expected numeric outcomes.
• Posts: 11,651
edited 2014-03-11 - 00:10:54
jmg wrote: »
I'd agree with this summary. MOD has explicit and expected numeric outcomes.

In software, yes, I agree. But this is hardware-level and it seems to me that instructions to increment and decrement modulus counters could be named aptly. I mean, how would INC and MOD even fit together in the software paradigm? They are two mutually exclusive concepts, aren't they?
• Posts: 2,652
edited 2014-03-11 - 00:24:01
Except, based on the description, the instructions do not even do a MOD at all. The inc variant increments the D input, and if the result is equal to the N input, then it sets the result to 0. There is no modulus anything in any of that. The behavior happens to look like a MOD of an incrementing input, but ONLY if the starting input is between 0 and the N input. I totally get the usefulness of this, and having it be cheap and fast is good.

It has nothing to do with it being hardware or software. It's just what the expected behavior is for a fundamental math operation (modulus).

Mark my words, people will have bugs in their P2 code because of this, and they'll be confused and angry when they find out a MOD instruction doesn't actually do a MOD operation.

Since it's a lot more expensive to do the proper MOD, then I think the best action to take is to rename the instructions.

I'm sorry to be pressing this issue, but I think it's important. The P2 has become a beast of a MCU with so many instructions, and so many "special considerations" for working with those instructions, that I think it's really important to make sure as much as possible is clear and makes sense. Having to go back and read minutia details about every instruction while coding to make sure you got it right is anything but fun.
• Posts: 2,652
edited 2014-03-11 - 00:28:30
cgracey wrote: »
In software, yes, I agree. But this is hardware-level and it seems to me that instructions to increment and decrement modulus counters could be named aptly. I mean, how would INC and MOD even fit together in the software paradigm? They are two mutually exclusive concepts, aren't they?

Chip?! These are instructions for PASM2 that we will use in our SOFTWARE. Just because it's combining what would normally be two things into an atomic operation, doesn't mean it's not software anymore!
• Posts: 9,771
edited 2014-03-11 - 00:32:48
Interesting discussion.

Take the case of a power of two. Say we want to increment something with a three bit wrap around.

That's something basic like:

add count, #1 (or some other value really)
and count, #%111

That's a modulo increment, but it's limited to a power of two.

In PASM, and assembly language in general, we do that kind of thing all the time. Generalizing that to work with any modulo value is handy.

Requiring a bounds check isn't a big deal. Once that is done, the concept of modulo works just fine otherwise. Modulo or wrap around is a basic assembly language concept. It happens in pages, it happens in data sizes, nibbles, bytes, words, etc... too.

From a PASM standpoint the instruction name makes perfect sense. Put the bounds checking into the instruction documentation, and leave it to the programmer as to whether or not they feel it necessary to perform clipping around the instruction to handle unplanned values and such; otherwise, the instruction performs that basic assembly language modulo / wrap around on values other than a power of two, and that is something I think is well worth having in the instruction set.

Besides, don't we have a whole pile of basic things which employ that basic idea? Small ring buffers, some DSP related things... Seems to me we do, and I can't count the number of times I wish I could have used AND to get that done outside of a power of two, but couldn't. The work around was to go ahead and factor things into a power of two, or fall back on CMP and get it done as a more instruction heavy bounds check routine.

Most assembly programmers are going to grok the instruction, and MOD works in that context because of how so many things work anyway. Once we are above PASM, then who really cares? Other representations will make better sense as they should.

I say leave it. The instruction is just fine as is, name included.
Do not taunt Happy Fun Ball! @opengeekorg ---> Be Excellent To One Another SKYPE = acuity_doug
Parallax colors simplified: https://forums.parallax.com/discussion/123709/commented-graphics-demo-spin<br>
• Posts: 2,652
edited 2014-03-11 - 00:49:31