Clarification on P2 OpCode Identification.
__red__
Posts: 470
in Propeller 2
I'm trying to better understand the P2ASM OpCodes and am confused by the block on lines #35-42 and #43-50
Picking one example:
EEEE 0100000 CZI DDDDDDDDD SSSSSSSSS TESTB D,{#}S WC/WZ Test bit S[4:0] of D, write to C/Z. C/Z = D[S[4:0]].
vs
EEEE 0100000 CZI DDDDDDDDD SSSSSSSSS BITL D,{#}S {WCZ} Bit S[4:0] of D = 0, C,Z = D[S[4:0]].
How does one differentiate between the two before performing the action in Column F of the spreadsheet?
Thanks,
Red
Picking one example:
EEEE 0100000 CZI DDDDDDDDD SSSSSSSSS TESTB D,{#}S WC/WZ Test bit S[4:0] of D, write to C/Z. C/Z = D[S[4:0]].
vs
EEEE 0100000 CZI DDDDDDDDD SSSSSSSSS BITL D,{#}S {WCZ} Bit S[4:0] of D = 0, C,Z = D[S[4:0]].
How does one differentiate between the two before performing the action in Column F of the spreadsheet?
Thanks,
Red
Comments
This table might help.
(Oh, I guess it could be logic puzzle implied by saying you won't have a test without storing the result or a bitl that stores to only one of them.)
Thanks ozpropdev!
Helps a ton.
I should have something to share soonish I hope which people may be amused by.
Glad it was helpful.
http://forums.parallax.com/discussion/comment/1448159/#Comment_1448159
Typically the I flag would determine if the # was present or not.
How can I decode the difference between D, S and D, #S?
The difference is when an immediate source is used, I = 1.
For the first case here of NOT D {wc,wz,wcz} the compiler will actually use S=D and I=0
ie NOT D,D {wc,wz ,wcz}
So if I = 0, NOT D. That's clear.
It's the difference between
NOT D, S
and
NOT D, #S
Maybe it's my understanding of the DDDDDDDDD DDDDDDDDD?
I thought that meant an 18 bit number. Is there an implication that that should be two 9 bit numbers that are always equal?
If so, what happens if I=1 and they are not?
S represents the 9 bit address of a cog register which stores the 32 bit number, and the I bit = 0.
It's all one instruction. The alias mnemonic is just tidy way of showing register D being both source and destination. The extra 9 D's is a representative illusion, it's still 9 S's but with duplicate register number. The reason for the I=0 is because that specific case can only be true for register direct addressing.
My last check was 79% coverage this morning so making good progress.
My current peculiarity is decoding jmp/call/calld arguments and trying to end up with the same result as p2dump.
I read the docs so I understand that cog ram addresses as longs and hub ram as bytes and that apparently I have to increment PC by 1 (or 4) when doing relative calls.
I have about 5% of them ending up with results in the wilderness so I just need to apply more time to the problem.
My validation is literal text comparison between the two tools so every whitespace is special. (The disadvantage of this approach is that if there are any bugs in p2dump I will be explicitly replicating them)
I de-lurked my project on Twitter yesterday for those following me there. Right now all my code is in a testing namespace.
I'll post a project thread when I'm near 100% coverage and moved into a real namespace.
If you look in the util/verify directory you will see a few files that I use to do the verification. The script runall tests 33 different spin2 files, and runrand tests 10 Mbytes of random data. BTW, when the disassembler encounters data that produces invalid or ambiguous instructions it will just generate a LONG value with the original data.
I'm impatiently waiting for the end of the work day so I can try and get to 100%
I'm doing my development on a Chromebook which adds a second level of fun to the builds.
Yup - confirmed. Apparently the algorithm for converting from numbers to addresses differs under 0x400 which makes sense as that's where the cog RAM / hub RAM boundary is.
So, cogram ($200 longs) + lutram (another $200 longs) = 4 kB, but $400 bytes in hubram addressing is only 1 kB.
Therefore, hubexec operates from 1 kB up. cogexec below that.
I see this in the output:
I'm not saying mine is correct (it's likely not), but I'm not sure what to make of the results from p2dump either.
In the end, the most complicated part of working out that equation was whether or not the opcode needed you to increase the PC or not when you did the divide. Some did, some didn't.
I use the same disassembler code in spinsim, and it will generate a "rdlong $e, ptra[8]" because it uses more relaxed rules. However, I should flag the instruction as questionable in spinsim.
By default, p2dump assumes that the first $400 bytes run in cog memory, and anything after that runs in hub RAM. This boundary can be adjusted using the -hub option. If you run p2dump without the -data option it will generate DAT, ORG and ORGH instructions, which allow the output file to be assembled by p2asm.
I see that PTRA and PTRB are defined as pointers in HUB RAM.
I also see that cog RAM maps 0x1EF is COG Register, 0x200-0x3F0 COG LUT, 0x400-0xFFFFF is HUB RAM.
What happens if I try to jmp to ptra and ptra < 0x400?
0x200-0x3FF is LUT
0x00000-0x00FFF is HUB but code cannot execute from here (HUB is addressed as bytes)
0x01000-0xFFFFF is HUB where code (hubexec) can be executed from
Note in the current P2 silicon HUB is only 512KB and the top 16KB is also mapped to the top of the 1MB address range
hubexec starts at $400
We can't check for C if we mandate that C is zero? right?