rendered paste bodyuint16 gcd(uint16 a, uint16 b)
{
uint16 res;
asm volatile (
// Count trailing zeros of a
"addi r3,%1,-1\n"
"andc r3,r3,%1\n"
"cntlzw r3,r3\n"
"subfic r3,r3,32\n"
// Count trailing zeros of b
"addi r4,%2,-1\n"
"andc r4,r4,%2\n"
"cntlzw r4,r4\n"
"subfic r4,r4,32\n"
// Compute min(ctz(a),ctz(b))
"subfc %0,r4,r3\n"
"subfe %0,%0,%0\n"
"andc r4,r4,%0\n"
"and %0,r3,%0\n"
"or %0,r4,%0\n"
// Remove trailing zeros from a and b
"srw %1,%1,%0\n"
"srw %2,%2,%0\n"
// Main loop
"loop%=:\n"
"cmplw %1,%2\n"
"beq end%=\n"
// (a,b) = (min(a,b),|a-b|)
"subfc r3,%2,%1\n"
"subfe r4,r4,r4\n"
"and %1,%1,r4\n"
"andc %2,%2,r4\n"
"or %1,%1,%2\n"
"xor %2,r3,r4\n"
"sub %2,%2,r4\n"
// Remove trailing zeros from b
"addi r4,%2,-1\n"
"andc r4,r4,%2\n"
"cntlzw r4,r4\n"
"subfic r4,r4,32\n"
"srw %2,%2,r4\n"
"b loop%=\n"
// Done. Add factors of two removed at the beginning
"end%=:\n"
"slw %0,%1,%0\n"
: "=&r"(res), "+r"(a), "+r"(b)
:
: "r3", "r4"
);
return res;
}