Shop OBEX P1 Docs P2 Docs Learn Events
GETNIBx,SETNIBx bug — Parallax Forums

GETNIBx,SETNIBx bug

ozpropdevozpropdev Posts: 2,793
edited 2015-09-28 13:03 in Propeller 2
Hi Chip

I've discovered a little bug in the GETNIBx instruction.
GETNIB3..GETNIB0 work Ok
GETNIB7..GETNIB4 return incorrect values.
Brian :)

Comments

  • also similar issue with SETNIBx
    SETNIB3..SETNIB0 works OK
    SETNIB7..SETNIB4 don't work.
    
  • I'm detecting a theme here. (Nibbles or is it Nybbles)
    ROLNIB0 works as expected
    ROLNIB7..ROLNIB1 seem to be broken.
    

    If I understand ROLNIBx correctly a nibble is shifted in in at nibble x
    for example
    
    regx = $12345678
    
    ROLNIB1 x,#$e
    
    should result in regx = $234567E8
    

    Is that correct?
  • What are you seeing as results from your testing? Could you provide what regx looks like going in and coming out of the instruction?

    (...and how are you inspecting values of registers, by the way? Curious wanna-be testers would like to know! I'm still just marveling at the blinking lights!)
  • What is the point of these instructions? Are they for USB or something? Are they really generally useful enough to occupy opcode space?
  • Results for all variants.
    regx=$12345678
    
    rolnib0 regx,#$e  regx = $2345678E  OK
    rolnib1 regx,#$e  regx = $23456780
    rolnib2 regx,#$e  regx = $23456780
    rolnib3 regx,#$e  regx = $23456780
    rolnib4 regx,#$e  regx = $12345678
    rolnib5 regx,#$e  regx = $12345678
    rolnib6 regx,#$e  regx = $12345678
    rolnib7 regx,#$e  regx = $12345678
    

    Code is part of a large program. I will have to edit it severely to post a usable piece.
    If time permits I will do that. :)


  • Here's a simple test program to test GETNIB.
  • Thanks for sharing, Brian!!

    Hopefully, I can try some things this afternoon!
  • I can see get/setnibx being useful for quad SPI (or other 4bit read/write situations).

    Not sure on the rolnibx one though? I would have expected it to work differently than ozpropdev is expecting. In my expectation, $12345678 would become $12345671 for rolnib0 regx, #$1. The top bit of the first nibble would rotate left one step around to the bottom bit of the first nibble. If it is really meant to "insert" the immediate value into the given nibble via rotating in 4 bits, then that seems even more oddball to me...

    Maybe the name rolnibx is just poorly chosen, and it means something else?
  • Roy Eltham wrote: »
    I can see get/setnibx being useful for quad SPI (or other 4bit read/write situations).

    Not sure on the rolnibx one though? I would have expected it to work differently than ozpropdev is expecting. In my expectation, $12345678 would become $12345671 for rolnib0 regx, #$1. The top bit of the first nibble would rotate left one step around to the bottom bit of the first nibble. If it is really meant to "insert" the immediate value into the given nibble via rotating in 4 bits, then that seems even more oddball to me...

    Maybe the name rolnibx is just poorly chosen, and it means something else?
    I thought of QuadSPI as well but it seems odd to have 16 instructions to support that one feature. Maybe just add a QuadSPI interface? (ducking and running for cover)

  • Well, instructions are on the easy path and in our design expectations, right?

    Grabbing IP, or really doing that feature right would take considerable test time.

    Done this way, we can arrive at a software solution and improve it over time.

    My .02 on it
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2015-09-28 18:40
    Well, it's really just one instruction for each, just using 3 bits of the opcode to encode what nibble.

    It could be changed to setnib n, reg, [#|reg] and getnib n, reg, [#|reg]

    I think a pass needs to be made over the instruction set to clean up the syntax/naming a bit. It's ok to have 3 operands in cases where it makes sense, instead of doing what Chip did with the 8 variants of the same instruction.
  • Well, "general purpose" instructions are certainly the Propeller way. I just wonder how general purpose these really are. I guess I should start thinking about other ways to use them! :-)
  • jmgjmg Posts: 15,175
    David Betz wrote: »
    I thought of QuadSPI as well but it seems odd to have 16 instructions to support that one feature. Maybe just add a QuadSPI interface? ...
    QuadSPI support is going to be needed for slaves, as they need to be externally clock sync'd, which means most of the HW is there for QuadSPI master.
    From Chips comments on streaming, 4b wide is on his list, and that, with simple QuadSPI HW would allow full bandwidth burst streaming over QuadSPI.
    Parts out there can go to > 100MHz
  • jmgjmg Posts: 15,175
    edited 2015-09-29 01:47
    ozpropdev wrote: »
    If I understand ROLNIBx correctly a nibble is shifted in in at nibble x
    for example
    
    regx = $12345678
    
    ROLNIB1 x,#$e
    
    should result in regx = $234567E8
    

    Is that correct?

    Only Chip knows what is 'correct' but that's not quite what I'd expect.
    I'd call the above example more an Insert Nibble operation.
    Nibbles to right of index stay, and nibble inserts and pushes higher ones left.


    I'd expect ROLNIB would work like rotate thru Carry, only with a 4 bit carry.
    ie like this :
    regx=$12345678
                                            Cy4(virtual)
    rolnib0 regx,#$e  regx = $2345678E  OK   1
    rolnib1 regx,#$e  regx = $345678E1       2
    rolnib2 regx,#$e  regx = $45678E12       3
    rolnib3 regx,#$e  regx = $5678E123       4
    rolnib4 regx,#$e  regx = $678E1234       5
    rolnib5 regx,#$e  regx = $78E12345       6
    rolnib6 regx,#$e  regx = $8E123456       7
    rolnib7 regx,#$e  regx = $E1234567       8
    
  • jmg
    I like your interpretation better than mine. :)
    rolnib7 regx,#$e  regx = $E1234567
    

    A shift nibble in from right. Very useful.
  • jmgjmg Posts: 15,175
    ozpropdev wrote: »
    jmg
    I like your interpretation better than mine. :)
    rolnib7 regx,#$e  regx = $E1234567
    

    A shift nibble in from right. Very useful.
    Where would you use this ?

    Now we wait to see what Chip intended :)

    Left open is the question of what happens to the Cy4 ?

    When you use RLC opcodes, the carry has both a write then a read bit value.
    ie is ROLNIBn intended as a 'Write only' opcode ?

  • Note also that ROLBYTx and ROLWRDx are behaving exactly the same odd way.
  • SeairthSeairth Posts: 2,474
    edited 2015-09-29 03:07
    Aha!

    ROLNIBx D, S/#

    It rotates the Xth nib from S/# into D!
    mov     regx, ##$01234567
    
    rolnib0 regx, ##$89ABCDEF  => $1234567F
    rolnib1 regx, ##$89ABCDEF  => $1234567E
    rolnib2 regx, ##$89ABCDEF  => $1234567D
    rolnib3 regx, ##$89ABCDEF  => $1234567C
    rolnib4 regx, ##$89ABCDEF  => $01234567
    rolnib5 regx, ##$89ABCDEF  => $01234567
    rolnib6 regx, ##$89ABCDEF  => $01234567
    rolnib7 regx, ##$89ABCDEF  => $01234567
    

    The ROLNIB5-7 is still broken. This is likely a real bug, since it's a different opcode. But the ROLNIB0-3 is working just fine (now that I see what it's doing)!

    ROLBYTx and ROLWRDx work correctly.
  • cgraceycgracey Posts: 14,208
    Thanks for finding this!

    I will have these fixed in the new REP release.

    ROLNIB takes nibble 0..7 from S and puts it into the lower nibble of D, while shifting D up by one nibible. It's a way to rotate a whole nibble into D.
  • Still, I wonder what this can be used for.

    I suppose this allows the QSPI-type inputs to be more flexible; just nibble-align them on INx, then you can "ROLNIBx buffer, INA" each cycle into a 32-bit buffer.

    I can also see how this would be useful for changing endianness (can't remember if there's a dedicated instruction anymore):
    rolbyt0 new, old
    rolbyt1 new, old
    rolbyt2 new, old
    rolbyt3 new, old
    
  • cgracey wrote: »
    Thanks for finding this!

    I will have these fixed in the new REP release.

    ROLNIB takes nibble 0..7 from S and puts it into the lower nibble of D, while shifting D up by one nibible. It's a way to rotate a whole nibble into D.

    Chip, make sure you look at GETNIB5-7 as well. Same issue. I haven't tested SETNIBx, but @ozpropdev mentions it in the title...
  • Seairth wrote: »
    I can also see how this would be useful for changing endianness (can't remember if there's a dedicated instruction anymore):
    rolbyt0 new, old
    rolbyt1 new, old
    rolbyt2 new, old
    rolbyt3 new, old
    

    The P2-Hot ESWAP8 is gone but MOVBYTS can do the same job.
    movbyts	regx,#%%0123
    

  • cgraceycgracey Posts: 14,208
    All the SETNIB/GETNIB/ROLNIB instructions had problems due to a typo in the instruction decoding.

    This is what is was:
    `op1(	setnib,		9'b1000000_??)		// setnib
    `op1(	getnib,		9'b1000010_??)		// getnib
    `op1(	rolnib,		9'b1000100_??)		// rolnib
    `op1(	setbyt,		9'b1000110_??)		// setbyt
    `op1(	getbyt,		9'b1000111_??)		// getbyt
    `op1(	rolbyt,		9'b1001000_??)		// rolbyt
    `op1(	setwrd,		9'b1001001_0?)		// setwrd
    `op1(	getwrd,		9'b1001001_1?)		// getwrd
    `op1(	rolwrd,		9'b1001010_0?)		// rolwrd
    

    And this is what it needed to become:
    `op1(	setnib,		9'b100000?_??)		// setnib
    `op1(	getnib,		9'b100001?_??)		// getnib
    `op1(	rolnib,		9'b100010?_??)		// rolnib
    `op1(	setbyt,		9'b1000110_??)		// setbyt
    `op1(	getbyt,		9'b1000111_??)		// getbyt
    `op1(	rolbyt,		9'b1001000_??)		// rolbyt
    `op1(	setwrd,		9'b1001001_0?)		// setwrd
    `op1(	getwrd,		9'b1001001_1?)		// getwrd
    `op1(	rolwrd,		9'b1001010_0?)		// rolwrd
    

    This used to be okay, but when I discovered the ==? operator that allows "?" wildcards, I got rid of the discrete masks I had in each of these `op1 declarations and forgot to put an extra "?" in the SETNIB/GETNIB/ROLNIB instructions.

    This bug is out of the way. Thanks for finding it!
  • cgraceycgracey Posts: 14,208
    Roy Eltham wrote: »
    Well, it's really just one instruction for each, just using 3 bits of the opcode to encode what nibble.

    It could be changed to setnib n, reg, [#|reg] and getnib n, reg, [#|reg]

    I think a pass needs to be made over the instruction set to clean up the syntax/naming a bit. It's ok to have 3 operands in cases where it makes sense, instead of doing what Chip did with the 8 variants of the same instruction.

    I know it looks silly, but the deal is that these 0..7's are constants and variables cannot be used for them. So, it seemed kind of like a teaser to have a 3rd operand. I actually used to have it this way in the assembler. I can put it back. In fact, if I do put it back, it will at least allow for some compile-time variance. That's worthwhile.
  • cgraceycgracey Posts: 14,208
    I changed the syntax for these nib/byte/word instructions:
    CCCC 100000n nnI DDDDDDDDD SSSSSSSSS        SETNIB  D,S/#,#n
    CCCC 100001n nnI DDDDDDDDD SSSSSSSSS        GETNIB  D,S/#,#n
    CCCC 100010n nnI DDDDDDDDD SSSSSSSSS        ROLNIB  D,S/#,#n
    
    CCCC 1000110 nnI DDDDDDDDD SSSSSSSSS        SETBYTE D,S/#,#n
    CCCC 1000111 nnI DDDDDDDDD SSSSSSSSS        GETBYTE D,S/#,#n
    CCCC 1001000 nnI DDDDDDDDD SSSSSSSSS        ROLBYTE D,S/#,#n
    
    CCCC 1001001 0nI DDDDDDDDD SSSSSSSSS        SETWORD D,S/#,#n
    CCCC 1001001 1nI DDDDDDDDD SSSSSSSSS        GETWORD D,S/#,#n
    CCCC 1001010 0nI DDDDDDDDD SSSSSSSSS        ROLWORD D,S/#,#n
    
  • Thanks Chip.
    I prefer the 3 operand form even if one is always a constant. It can be useful at compile time, and for using named CONs instead of numbers to impart proper meaning in context.
Sign In or Register to comment.