This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SK-AM64B: PRU: Deprecation of SUC and RSC

Part Number: SK-AM64B

Hi,

Regarding the plan to deprecate SUC and RSC instructions for PRU:

> I am able to confirm that there is a bug in both SUC and RSC assembly commands for all currently released processors with a PRU ...
> ... currently we are planning to deprecate those two instructions for all existing PRU devices.

Isn't outright deprecation a bit extreme? I'm concerned that multi-word arithmetic might be slowed down if those instructions are deprecated.

Can you please consider to simply document the CARRY restrictions and semantics? Is CARRY is working correctly if being used always in ADD/ADC or SUB/SUC or RSB/RSC pairs, as is typical in multi-word arithmetic? If so, then issuing an errata to forbid ADD/SUC sequences is preferred over outright deprecating of SUC and RSC.


Regards,
Dimitar

  • Dimitar,

    As Nick mentioned in the post on the related Thread

    https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1244359/sk-am64b-am64x-pru-assembler-how-works-this-bloody-carry

    "I am working with other teams to get our documentation updated, PRU compiler updated, etc. Exact documentation changes are TBD, but currently we are planning to deprecate those two instructions for all existing PRU devices."

    Nick can you please add More details to the workflow and the plans for updating the documentation.

    I will let Nick add more details to the response.

    Regards

    Anshu

  • Thank you. I hope my suggestion is considered.

  • Hello Dimitar,

    Baseline - what we know so far

    The carry bit works as expected with ADD, ADC, SUB, RSB.

    As far as I can tell from looking at the SUC source code (and in alignment with Michel's tests here: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1244359/sk-am64b-am64x-pru-assembler-how-works-this-bloody-carry/4754696#4754696 ), SUC uses the carry bit improperly: if there IS a carry bit, no carry math happens, and if there is NOT a carry bit, then 1 is subtracted from the result.

    From Michel's test code:

    LDI32 r4, 0xfffffffe
    ADD r5, r4, 1 ; no carry expected
    SUC r5, r5, 0 ; so should not change the result, 0xffffffff expected

    R4: 0xFFFFFFFE
    R5: 0xFFFFFFFE

    LDI32 r6, 0xffffffff
    ADD r7, r6, 1 ; carry expected
    SUC r7, r7, 0 ; so should subtract 1 and return to 0xffffffff

    R6: 0xFFFFFFFF
    R7: 0x00000000

    RSC is coded the same way as SUC, so it should have the same issues.

    Multi-word arithmetic 

    Do you have specific multi-word arithmetic pairs with SUC and RSC that you have validated provide correct outputs? If so, please let us know so we can take that information into account!

    So far, I have only looked at the most basic 64 bit subtracts, which should give the wrong outputs:

    sub64(reg64 dst, reg64 src1, reg64 src2)
    expands out to
    { sub32(dst.bits00_31, src1.bits00_31, src2.bits00_31);
    suc32(dst.bits32_63, src1.bits32_63, src2.bits32_63); }

    and

    rsb64(reg64 dst, reg64 src1, reg64 src2)
    expands out to
    rsb32(dst.bits00_31, src1.bits00_31, src2.bits00_31);
    rsc32(dst.bits32_63, src1.bits32_63, src2.bits32_63);

    Regards,

    Nick

  • I tested the following function written in assembly. It returns value 0 in r14. So to me it looks like carry works correctly if used in SUB/SUC pairs to implement multi-word arithmetic.

            .text
            .global test
    test:

            ldi     r14, 0                  # Return result. 0 on success.

            # Test carry
            ldi     r0, 0x0100
            ldi     r1, 0x0001

            sub     r20.b0, r0.b0, r1.b0    # Multi-word arithmetic
            suc     r20.b1, r0.b1, r1.b1
            sub     r21.w0, r0.w0, r1.w0    # Single-word arithmetic
            xor     r20, r20.w0, r21.w0
            max     r14, r14, r20           # Catch non-zero result in r20.


            # Test no carry
            ldi     r0, 0x0102
            ldi     r1, 0x0001

            sub     r20.b0, r0.b0, r1.b0    # Multi-word arithmetic
            suc     r20.b1, r0.b1, r1.b1
            sub     r21.w0, r0.w0, r1.w0    # Single-word arithmetic
            xor     r20, r20.w0, r21.w0
            max     r14, r14, r20           # Catch non-zero result in r20.

            ret


  • Hello Dimitar,

    I will try to replicate your tests on my side tomorrow.

    Regards,

    Nick

  • Hello Dimitar,

    First off, thank you for creating this post.

    I have not had time to run tests on hardware yet, but spent some time chatting with other folks about this issue. I think you might be correct with your statement that SUC and RSC were only designed to be used with specific instructions.

    There is only a single carry bit that can be used. And the same carry bit is used for both ADC and SUC. However, the nature of the carry bit is different for 64 bit adds than it is for subtracts (where the carry output of ADD is a positive 1, and the carry output of SUB should be a negative one). So I can see why a designer might not consider passing the output of ADD into SUC during the design process, if SUC is expecting a negative carry instead of a positive carry.

    If these carry bits are treated differently under the hood, maybe that could lead to the observed behavior (e.g., if ADD outputting a positive carry means carry_bit=1, while SUB outputting a negative carry means carry_bit=0). I am following up with some teammates to try to dig a bit deeper into the low-level behavior.

    Feel free to ping the thread if I have not provided an update towards the middle or end of the week.

    Regards,

    Nick

  • Hello Dimitar,

    It looks like you are correct, thank you for creating this post. I have also updated the other post based on your input: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1244359/sk-am64b-am64x-pru-assembler-how-works-this-bloody-carry/4788111#4788111 

    How stuff works

    For ADC, carry_bit = 1 means there is a carry bit
    For SUC/RSC, carry_bit = 0 means there is a carry bit

    This is by design, since SUB uses a carry_bit value of 1 to help implement 2's complement subtraction. Reference https://stackoverflow.com/questions/41253124/i-cant-understand-some-instructions-in-arm-sbc-rsc 

    Since ADC and SUC/RSC use the carry_bit differently, that means each one can only be used with instructions that provide an output that is in a format that they recognize. Thus, SUC/RSC can accept inputs from SUB, but not ADD. Similarly, ADC can accept inputs from ADD, but not SUB.

    Regards,

    Nick