P2 instructions and the path to GCC/binutils
ntosme2
Posts: 38
I thought I'd try to parse through all of the P2 instructions to see what would be required for a proper binutils implementation, kind of following how some other instruction sets are defined and I came up with this.
There are at least 17 different patterns for instructions, not including form 9 which is really just the free-for-all hard-coded section.
I'm getting the feeling that this could take a while!
There are at least 17 different patterns for instructions, not including form 9 which is really just the free-for-all hard-coded section.
I'm getting the feeling that this could take a while!
/* The propeller 2 has a veritable cornucopia of instruction forms: In most instructions bits are grouped as follows: 1 2 3 4 5 0000 0000000 000 000000000 000000000 1) instruction prefix, used to skip execution of this instruction based on a variety of test cases 2) opcode for standard-length opcodes 3) 000 == CZI C - generally used as a carry flag Z - the boolean result of some expression, varies by instruction I - 0 means load the value from register at 9-bit address SSSSSSSSS 1 means use 9-bit literal value A '#' prefix to the SSSSSSSSS operand is used to indicate I = 1, else 0 For certain opcodes a I = 0 indicates a unary operator, meaning source and destination are the same. 4) 9-bit destination register 5) 9-bit source register Form 1: NOP - all zeroes 0000 0000000 000 000000000 000000000 Form 2: Classic P1 style eeee ooooooo czi ddddddddd sssssssss Form 3: Unary eeee ooooooo cz0 ddddddddd ddddddddd Form 4a: 3 operands - SETNIB, GETNIB, ROLNIB eeee oooooon nni ddddddddd sssssssss Form 4b: 1 operand, 1 implicit operand from ALTSN instruction - SETNIB eeee ooooooo 00i 000000000 sssssssss Form 4c: 1 operand, 1 implicit operand from ALTGN instruction - GETNIB, ROLNIB eeee ooooooo 000 ddddddddd 000000000 Form 5a: 3 operands - SETBYTE, GETBYTE, ROLBYTE eeee ooooooo nni ddddddddd sssssssss Form 5b: 1 operand, 1 implicit operand from ALTSB instruction - SETBYTE eeee ooooooo 00i 000000000 sssssssss Form 5c: 1 operand, 1 implicit operand from ALTGB instruction - GETBYTE, ROLBYTE eeee ooooooo 000 ddddddddd 000000000 Form 6a: 3 operands - SETWORD, GETWORD, ROLWORD eeee ooooooo oni ddddddddd sssssssss Form 6b: 1 operand, 1 implicit operand from ALTSW instruction - SETWORD eeee ooooooo o0i 000000000 sssssssss Form 6c: 1 operand, 1 implicit operand from ALTGW instruction - GETWORD, ROLWORD eeee ooooooo o00 ddddddddd 000000000 Form 7: 9-bit instruction, 2 operands eeee ooooooo ooi ddddddddd sssssssss Form 8: 9-bit instruction, unary eeee ooooooo oo1 ddddddddd 000000000 Form 9: free-form crazy instructions ALTI - "Execute D in place of next instruction. D stays same." eeee 1001101 001 ddddddddd 101100100 POPA - "Read long from hub address --PTRA into D. C = MSB of long. *" eeee 1011000 cz1 ddddddddd 101011111 POPB - Read long from hub address --PTRB into D. C = MSB of long. * eeee 1011000 tz1 ddddddddd 111011111 RESI3 - "Resume from INT3. (CALLD $1F0,$1F1 WC,WZ)" eeee 1011001 110 111110000 111110001 RESI2 - "Resume from INT2. (CALLD $1F2,$1F3 WC,WZ)" eeee 1011001 110 111110010 111110011 RESI1 - "Resume from INT1. (CALLD $1F4,$1F5 WC,WZ)" eeee 1011001 110 111110100 111110101 RESI0 - "Resume from INT0. (CALLD $1FE,$1FF WC,WZ)" eeee 1011001 110 111111110 111111111 RETI3 - "Return from INT3. (CALLD $1FF,$1F1 WC,WZ)" eeee 1011001 110 111111111 111110001 RETI2 - "Return from INT2. (CALLD $1FF,$1F3 WC,WZ)" eeee 1011001 110 111111111 111110011 RETI1 - "Return from INT1. (CALLD $1FF,$1F5 WC,WZ)" eeee 1011001 110 111111111 111110101 RETI0 - "Return from INT0. (CALLD $1FF,$1FF WC,WZ)" eeee 1011001 110 111111111 111111111 AKPIN - "Acknowledge smart pin S[5:0]." eeee 1100000 01I 000000001 sssssssss PUSHA - "Write long in D[31:0] to hub address PTRA++." eeee 1100011 0l1 ddddddddd 101100001 PUSHB - "Write long in D[31:0] to hub address PTRB++." eeee 1100011 0l1 ddddddddd 111100001 XSTOP - "Stop streamer immediately." eeee 1100101 011 000000000 000000000 Form 10a: 8-bit instructions with z flag eeee ooooooo ozi ddddddddd sssssssss Form 10b: 8-bit instructions with c flag eeee ooooooo ozi ddddddddd sssssssss Form 10c: 8-bit instructions with optional immediate D (L flag) and immediate S (I flag) eeee ooooooo oli ddddddddd sssssssss Form 11: special branch-if-flag set instructions eeee 1011110 01i 0000ooooo sssssssss Form 12: extended-set unary instructions eeee 1101011 czl ddddddddd ooooooooo Form 13: extended-set event instructions with only flag side-effects eeee 1101011 cz0 0000ooooo 000100100 Form 14: extended-set interrupt instructions eeee 1101011 000 000100ooo 000100100 Form 15: extended-set branch RET* instructions eeee 1101011 cz1 000000000 0001011oo Form 15: MOD{C,Z,CZ} eeee 1101011 cz1 0cccczzzz 001101111 Form 16: branch A eeee 11011oo raa aaaaaaaaa aaaaaaaaa Form 17: AUG{S,D} eeee 1111onn nnn nnnnnnnnn nnnnnnnnn */
Comments
Z is generally used as the zero result flag. When set, means Zero, clear means NonZero.
I is generally used as an immediate modifier (#) modifier for the S operand.
L is used as an immediate (#) modifier for the D operand. IIRC it usually replaces the C or Z flag.
I did a different breakdown of the instruction into a spreadsheet showing the relationships between instructions based on other parameters. I’ll see if I can find where I posted it (I am overseas atm so don’t have access to my pc)
The first 128 instructions are base instructions following the normal
EEEE IIIIIII CZI DDDDDDDDD SSSSSSSSS
format where
EEEE is an execution modifier based on the Z and C settings where
1111 = always execute
0000 = always execute, and when complete, pop the internal stack (8 deep) and use this as the return address (ie jump to this address). The “_RET_” is used in assembler as the prefix to an instruction.
Other values have instruction prefixes such as “IF_C_AND_Z”
You are missing some details provided in the comments:
POPx and PUSHx use PTRx increment/decrement encodings which repurpose the S field, so are special cases of RDLONG and WRLONG respectively with the relevant pointer operations built-in.
RESIx and RETIx are special cases of CALLD, with the D and S fields and WC and WZ conditions predetermined.
More information can be gleaned from the Parallax Propeller 2 Documentation v32:
ALTI D is a special case of ALTI D, {#}S where the D register content is executed in place of the next instruction in the current code block, with no D or S field substitutions.
AKPIN appears to be differentiated from WRPIN by having the low bit of the D field set
XSTOP is a special case of XINIT; technically is sets the streamer to DDS/Goertzel mode with no outputs, base pin 0, NCO count of 0 which stops the streamer.