I just came across the following MIPS code at line 328 of
tls_pstm_montgomery_reduce.c:
#define PROPCARRY                     \
asm(                                  \
        " lw       $10,%1        \n\t"    \
        " addu     $10,$10,%0    \n\t"    \
        " sw       $10,%1        \n\t"    \
        " sltu     %0,$10,%0     \n\t"    \
        :"=r"(cy),"=m"(_c[0])\
        :"r"(cy),"r"(_c[0])\
        :"$10");

Notice the lack of constraint forcing the output carry
to be in the same register as the input.  This code
computes the output carry into %0, but the compiler
expects it in %2.

A second bug is the fact that the compiler provides
_c[0] in register %3, but the code fetches it from %1.
Nobody told the compiler to ensure that memory is up to
date!  It might elide a store and pass the value to this
code instead.

Even if the above isn't a bug, it's still a waste of
code, as the compiler will load the value into a register
before the asm(), which will ignore it and fetch it itself.

A third problem, although not a bug, is the use of fixed
register $10 as a temporary.  Far better to declare
a variable and let the compiler pick the register.

The correct way to write this is:
#define PROPCARRY                     \
asm(                                  \
        "addu     %1,%1,%0"    "\n\t" \
        "sltu     %2,%1,%0"           \
        :"=r"(cy), "+r"(_c[0])        \
        :"r"(cy))

Or better yet, don't use asm() at all and just write:
#define PROPCARRY                     \
        cy = (_c[0] += cy) < cy

The MIPS INNERMUL macro has the same problems; it's just
bigger and so messier to explain.

Sheesh.  The correct way to write that is:
#define INNERMUL do {                    \
        pstm_digit lo, hi;               \
        asm(                             \
        "multu    %2,%3"        "\n\t"   \
        "mflo     %0"           "\n\t"   \
        "mfhi     %1"                    \
        :"=r"(lo), "=r"(hi),             \
        :"r"(mu), "r"(*tmpm++));         \
        hi += (lo += cy) < cy;           \
        hi += (_c[0] += lo) < lo;        \
        cy = hi;                         \
} while (0)

I haven't yet checked if this is fixed in upstream
MatrixSSL.

_______________________________________________
busybox mailing list
[email protected]
https://lists.busybox.net/mailman/listinfo/busybox

Reply via email to