P2 instructions and the path to GCC/binutils

ntosme2ntosme2 Posts: 12
edited 2019-08-15 - 02:48:30 in Propeller 2
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!
/*
    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

  • Cluso99Cluso99 Posts: 15,235
    edited 2019-08-13 - 06:16:26
    C is generally the carry, but is also used as a parity flag in some instructions.

    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”
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • ntosme2 wrote: »

    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

    [/code]

    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.


Sign In or Register to comment.