uint16 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; }