#include "testcode.h" /* Test a simple loop of 1 million instructions */ /* Most implementations should count be correct within 1% */ /* This loop in in assembly language, as compiler generated */ /* code varies too much. */ int instructions_million(void) { #if defined(__i386__) || (defined __x86_64__) asm( " xor %%ecx,%%ecx\n" " mov $499999,%%ecx\n" "test_loop:\n" " dec %%ecx\n" " jnz test_loop\n" : /* no output registers */ : /* no inputs */ : "cc", "%ecx" /* clobbered */ ); return 0; #elif defined(__PPC__) asm( " nop # to give us an even million\n" " lis 15,499997@ha # load high 16-bits of counter\n" " addi 15,15,499997@l # load low 16-bits of counter\n" "55:\n" " addic. 15,15,-1 # decrement counter\n" " bne 0,55b # loop until zero\n" : /* no output registers */ : /* no inputs */ : "cc", "15" /* clobbered */ ); return 0; #elif defined(__ia64__) asm( " mov loc6=166666 // below is 6 instr.\n" " ;; // because of that we count 4 too few\n" "55:\n" " add loc6=-1,loc6 // decrement count\n" " ;;\n" " cmp.ne p2,p3=0,loc6\n" "(p2) br.cond.dptk 55b // if not zero, loop\n" : /* no output registers */ : /* no inputs */ : "p2", "loc6" /* clobbered */ ); return 0; #elif defined(__sparc__) asm( " sethi %%hi(333333), %%l0\n" " or %%l0,%%lo(333333),%%l0\n" "test_loop:\n" " deccc %%l0 ! decrement count\n" " bnz test_loop ! repeat until zero\n" " nop ! branch delay slot\n" : /* no output registers */ : /* no inputs */ : "cc", "l0" /* clobbered */ ); return 0; #elif defined(__arm__) asm( " ldr r2,count @ set count\n" " b test_loop\n" "count: .word 333332\n" "test_loop:\n" " add r2,r2,#-1\n" " cmp r2,#0\n" " bne test_loop @ repeat till zero\n" : /* no output registers */ : /* no inputs */ : "cc", "r2" /* clobbered */ ); return 0; #elif defined(__aarch64__) asm( " ldr x2,=333332 // set count\n" "test_loop:\n" " add x2,x2,#-1\n" " cmp x2,#0\n" " bne test_loop // repeat till zero\n" : /* no output registers */ : /* no inputs */ : "cc", "r2" /* clobbered */ ); return 0; #endif return CODE_UNIMPLEMENTED; } /* fldcw instructions are counted oddly on Pentium 4 machines */ int instructions_fldcw(void) { #if defined(__i386__) || (defined __x86_64__) int saved_cw,result,cw; double three=3.0; asm( " mov $100000,%%ecx\n" "big_loop:\n" " fldl %1 # load value onto fp stack\n" " fnstcw %0 # store control word to mem\n" " movzwl %0, %%eax # load cw from mem, zero extending\n" " movb $12, %%ah # set cw for \"round to zero\"\n" " movw %%ax, %3 # store back to memory\n" " fldcw %3 # save new rounding mode\n" " fistpl %2 # save stack value as integer to mem\n" " fldcw %0 # restore old cw\n" " loop big_loop # loop to make the count more obvious\n" : /* no output registers */ : "m"(saved_cw), "m"(three), "m"(result), "m"(cw) /* inputs */ : "cc", "%ecx","%eax" /* clobbered */ ); return 0; #endif return CODE_UNIMPLEMENTED; } /* rep instructions are counted a bit non-intuitively */ /* some tools like Valgrind and Pin may count differently than real hardware */ int instructions_rep(void) { #if defined(__i386__) || defined(__ILP32__) char buffer_out[16384]; asm( " mov $1000,%%edx\n" " cld\n" "loadstore: # test 8-bit store\n" " mov $0xd, %%al # set eax to d\n" " mov $16384, %%ecx\n" " mov %0, %%edi # set destination\n" " rep stosb # store d 16384 times, auto-increment\n" " dec %%edx\n" " jnz loadstore\n" : /* outputs */ : "rm" (buffer_out) /* inputs */ : "cc", "%esi","%edi","%edx","%ecx","%eax","memory" /* clobbered */ ); return 0; #elif defined (__x86_64__) char buffer_out[16384]; asm( " mov $1000,%%edx\n" " cld\n" "loadstore: # test 8-bit store\n" " mov $0xd, %%al # set eax to d\n" " mov $16384, %%ecx\n" " mov %0, %%rdi # set destination\n" " rep stosb # store d 16384 times, auto-increment\n" " dec %%edx\n" " jnz loadstore\n" : /* outputs */ : "rm" (buffer_out) /* inputs */ : "cc", "%esi","%edi","%edx","%ecx","%eax","memory" /* clobbered */ ); return 0; #endif return CODE_UNIMPLEMENTED; }