1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
/*
* main.c
*
* Created on: 23.04.2010
* Author: sven
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#define HI(x) (x >> 16)
#define LO(x) (x & 0x0000FFFF)
void mulc(uint32_t *u, uint32_t *v, uint32_t a, uint32_t b)
{
uint32_t t;
t = LO(a) * LO(b);
*v = LO(t);
t = HI(t) + HI(a) * LO(b);
*u = HI(t);
t = LO(t) + LO(a) * HI(b);
*v |= LO(t) << 16;
*u += HI(t) + HI(a) * HI(b);
}
void mula(uint32_t *u, uint32_t *v, uint32_t a, uint32_t b)
{
asm
(
"mov %2,%%eax\n"
"mul %3\n"
"mov %%edx, %0\n"
"mov %%eax, %1"
:"=r"(*u),"=r"(*v)
:"r"(a),"r"(b)
);
}
void initRandomizer()
{
srand(time(NULL));
}
uint32_t getRandomUint32()
{
uint32_t res = rand();
if(res % 2)
{
return (res | 1<<31);
}
return res;
}
int main(int argc, char* argv[])
{
initRandomizer();
uint32_t a = getRandomUint32();
uint32_t b = getRandomUint32();
uint32_t u,v;
uint32_t counter;
uint32_t outerCnt;
const uint32_t NUM_INNER_LOOPS = 1000000;
const uint32_t NUM_OUTER_LOOPS = 1000;
struct timeval startc;
struct timeval endc;
struct timeval starta;
struct timeval enda;
long diffCsum = 0,diffAsum = 0;
for(outerCnt=0;outerCnt<NUM_OUTER_LOOPS;outerCnt++) {
gettimeofday(&startc,0);
for (counter=0; counter < NUM_INNER_LOOPS; counter++) {
mulc(&u,&v,a,b);
}
gettimeofday(&endc,0);
diffCsum += (endc.tv_sec*1000000 + endc.tv_usec) - (startc.tv_sec*1000000 + startc.tv_usec);
printf("C %u * %u = %u.%u\n",a,b,u,v);
u=0;
v=0;
gettimeofday(&starta,0);
for (counter=0; counter < NUM_INNER_LOOPS; counter++) {
mula(&u,&v,a,b);
}
gettimeofday(&enda,0);
diffAsum += (enda.tv_sec*1000000 + enda.tv_usec) - (starta.tv_sec*1000000 + starta.tv_usec);
printf("ASM %u * %u = %u.%u\n",a,b,u,v);
}
printf("C: total %ld usec, avg %ld usec\n",diffCsum,(diffCsum / NUM_OUTER_LOOPS));
printf("ASM: total %ld usec, avg %ld usec\n",diffAsum,(diffAsum / NUM_OUTER_LOOPS));
return EXIT_SUCCESS;
}
|