#include <stdio.h>
#include <inttypes.h>
#include <limits.h>

__asm__ (
/* support both environments that does and doesn't add underscore before function name */
"loop_asm:\n"
"_loop_asm:\n"
"push %ebp\n"
"mov %esp, %ebp\n"
"push %esi\n"
"push %edi\n"
"push %ebx\n"

"# x at %ebp+8, n at %ebp+12\n"
"movl 8(%ebp), %esi\n"
"movl 12(%ebp), %ebx\n"
"movl $-1, %edi\n"
"movl $1, %edx\n"
".L2_test:\n" /* rename .L2 to .L2_test to avoid collision */
"movl %edx, %eax\n"
"andl %esi, %eax\n"
"xorl %eax, %edi\n"
"movl %ebx, %ecx\n"
"sall %cl, %edx\n"
"testl %edx, %edx\n"
"jne .L2_test\n"
"movl %edi, %eax\n"

"pop %ebx\n"
"pop %edi\n"
"pop %esi\n"
"leave\n"
"ret\n"
);

uint32_t loop_asm(uint32_t, uint32_t);

uint32_t loop_convert(uint32_t x, uint32_t n) {
    uint32_t result = -1;
    uint32_t mask;
    for (mask = 1; mask != 0; mask <<= n & 31) {
        result ^= mask & x;
    }
    return result;
}

int mask;
    int loop(int x, int n){

    int result = -1;

    for (mask = 1; mask >= result; mask = x&1) {

    result ^= n;

    }
return result;
}

int main(void) {
    int x, n;
    uint32_t raw, test, conv;
    int miss_count = 0;
    /* search for mismatch in some range */
    for (n = 1; n < 32; n++) {
        uint32_t x_test;
        for (x_test = 0; x_test < UINT32_C(100000); x_test++) {
            if (loop_asm(x, n) != loop_convert(x, n)) {
                printf("mismatch at x=%"PRIu32", n=%d\n", x_test, n);
                if (miss_count < INT_MAX) miss_count++;
            }
        }
    }
    printf("%d mismatch(es) found.\n", miss_count);
    /* print some examples */
    x = 100;
    n = 5;
    raw = loop_asm(x, n);
    conv = loop_convert(x, n);
    printf("loop_asm(%d, %d) = %"PRIu32"\n", x, n, raw);
    printf("loop_convert(%d, %d) = %"PRIu32"\n", x, n, conv);
    fflush(stdout);
    test = loop(x, n);
    printf("loop(%d, %d) = %"PRIu32"\n", x, n, test);
    return 0;
}
