1 |
#include <stdio.h> |
2 |
#include <stdlib.h> |
3 |
#include <sys/types.h> |
4 |
#include <sys/time.h> |
5 |
#include <sys/resource.h> |
6 |
|
7 |
/* #define N_CALLS_PER_PAGE 1024 */ |
8 |
#define N_CALLS_PER_PAGE 128 |
9 |
|
10 |
#define MHZ 533 |
11 |
|
12 |
struct cpu; |
13 |
|
14 |
struct instr_call { |
15 |
void (*f)(struct cpu *cpu, struct instr_call *ic); |
16 |
/* int instr_len; */ |
17 |
void *arg[3]; |
18 |
}; |
19 |
|
20 |
struct cpu { |
21 |
void *curpage; |
22 |
int orig_nloops; |
23 |
int nloops; |
24 |
|
25 |
struct instr_call *next_instr_call; |
26 |
}; |
27 |
|
28 |
void r(struct cpu *cpu) |
29 |
{ |
30 |
struct instr_call *ic; |
31 |
|
32 |
for (;;) { |
33 |
ic = cpu->next_instr_call++; |
34 |
ic->f(cpu, ic); |
35 |
|
36 |
ic = cpu->next_instr_call++; |
37 |
ic->f(cpu, ic); |
38 |
|
39 |
ic = cpu->next_instr_call++; |
40 |
ic->f(cpu, ic); |
41 |
|
42 |
ic = cpu->next_instr_call++; |
43 |
ic->f(cpu, ic); |
44 |
|
45 |
ic = cpu->next_instr_call++; |
46 |
ic->f(cpu, ic); |
47 |
|
48 |
ic = cpu->next_instr_call++; |
49 |
ic->f(cpu, ic); |
50 |
|
51 |
ic = cpu->next_instr_call++; |
52 |
ic->f(cpu, ic); |
53 |
|
54 |
ic = cpu->next_instr_call++; |
55 |
ic->f(cpu, ic); |
56 |
} |
57 |
} |
58 |
|
59 |
|
60 |
void f_add(struct cpu *cpu, struct instr_call *ic) |
61 |
{ |
62 |
#if 0 |
63 |
#if 0 |
64 |
int *a = (int *) ic->arg[0]; |
65 |
int *b = (int *) ic->arg[1]; |
66 |
int *c = (int *) ic->arg[2]; |
67 |
|
68 |
*a = (*b) + (*c); |
69 |
#else |
70 |
int *a = (int *) ic->arg[0]; |
71 |
int *b = (int *) ic->arg[1]; |
72 |
int *c = (int *) ic->arg[2]; |
73 |
int *d, *e, *f; |
74 |
|
75 |
ic = cpu->next_instr_call++; |
76 |
d = (int *) ic->arg[0]; |
77 |
e = (int *) ic->arg[1]; |
78 |
f = (int *) ic->arg[2]; |
79 |
|
80 |
*a = (*b) + (*c); |
81 |
*d = (*e) + (*f); |
82 |
#endif |
83 |
#endif |
84 |
} |
85 |
|
86 |
|
87 |
void f_sub(struct cpu *cpu, struct instr_call *ic) |
88 |
{ |
89 |
int *a = (int *) ic->arg[0]; |
90 |
int *b = (int *) ic->arg[1]; |
91 |
int *c = (int *) ic->arg[2]; |
92 |
*a = (*b) - (*c); |
93 |
} |
94 |
|
95 |
|
96 |
void f_and(struct cpu *cpu, struct instr_call *ic) |
97 |
{ |
98 |
int *a = (int *) ic->arg[0]; |
99 |
int *b = (int *) ic->arg[1]; |
100 |
int *c = (int *) ic->arg[2]; |
101 |
*a = (*b) & (*c); |
102 |
} |
103 |
|
104 |
|
105 |
void f_or(struct cpu *cpu, struct instr_call *ic) |
106 |
{ |
107 |
int *a = (int *) ic->arg[0]; |
108 |
int *b = (int *) ic->arg[1]; |
109 |
int *c = (int *) ic->arg[2]; |
110 |
*a = (*b) | (*c); |
111 |
} |
112 |
|
113 |
|
114 |
void f_end(struct cpu *cpu, struct instr_call *ic) |
115 |
{ |
116 |
struct rusage rusage; |
117 |
double t, mips; |
118 |
|
119 |
cpu->nloops--; |
120 |
if (cpu->nloops > 0) { |
121 |
cpu->next_instr_call = cpu->curpage; |
122 |
return; |
123 |
} |
124 |
|
125 |
getrusage(RUSAGE_SELF, &rusage); |
126 |
t = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec / 1000000.0; |
127 |
mips = (float)(N_CALLS_PER_PAGE * cpu->orig_nloops) / t |
128 |
/ 1000000.0; |
129 |
|
130 |
printf("%.2f user seconds = %.1f MIPS. %.1f cycles/emulated " |
131 |
"instruction on a %i MHz machine\n", (float)t, (float)mips, |
132 |
(float)MHZ/mips, MHZ); |
133 |
exit(1); |
134 |
} |
135 |
|
136 |
|
137 |
int main(int argc, char *argv[]) |
138 |
{ |
139 |
int32_t tmp_a, tmp_b, tmp_c; |
140 |
struct instr_call *call_array; |
141 |
int i, ncalls; |
142 |
struct cpu *cpu = malloc(sizeof(struct cpu)); |
143 |
|
144 |
if (argc <= 1) { |
145 |
fprintf(stderr, "usage: %s n\n", argv[0]); |
146 |
exit(1); |
147 |
} |
148 |
|
149 |
cpu->orig_nloops = cpu->nloops = atoi(argv[1]); |
150 |
ncalls = N_CALLS_PER_PAGE + 1; |
151 |
|
152 |
/* Fill a range of nonsense calls: */ |
153 |
call_array = malloc(sizeof(struct instr_call) * ncalls); |
154 |
cpu->curpage = call_array; |
155 |
|
156 |
printf("ncalls = %i\n", ncalls); |
157 |
for (i=0; i<ncalls; i++) { |
158 |
if (i == ncalls-1) { |
159 |
call_array[i].f = f_end; |
160 |
} else { |
161 |
#if 0 |
162 |
switch (i & 3) { |
163 |
case 0: call_array[i].f = f_add; |
164 |
case 1: call_array[i].f = f_sub; |
165 |
case 2: call_array[i].f = f_and; |
166 |
case 3: call_array[i].f = f_or; |
167 |
} |
168 |
#else |
169 |
call_array[i].f = f_add; |
170 |
#endif |
171 |
|
172 |
call_array[i].arg[0] = &tmp_a; |
173 |
call_array[i].arg[1] = &tmp_b; |
174 |
call_array[i].arg[2] = &tmp_c; |
175 |
} |
176 |
} |
177 |
|
178 |
printf("running...\n"); |
179 |
cpu->next_instr_call = &call_array[0]; |
180 |
r(cpu); |
181 |
|
182 |
printf("ERROR!\n"); |
183 |
return 0; |
184 |
} |
185 |
|