forked from libretro/gpsp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cpu_instrument.h
138 lines (109 loc) · 4.47 KB
/
cpu_instrument.h
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Instrumentation and debugging code
// Used to count instruction and register usage
// Also provides some tracing capabilities
#ifdef MEMORY_STATS_ANALYZE
// Collects memory stats by region, access type, etc.
u32 memory_region_access_read_u8[16];
u32 memory_region_access_read_s8[16];
u32 memory_region_access_read_u16[16];
u32 memory_region_access_read_s16[16];
u32 memory_region_access_read_u32[16];
u32 memory_region_access_write_u8[16];
u32 memory_region_access_write_u16[16];
u32 memory_region_access_write_u32[16];
#define STATS_MEMORY_ACCESS(op, size, region) \
memory_region_access_##op##_##size[region]++;
#else
#define STATS_MEMORY_ACCESS(write, u32, region)
#endif
#ifdef REGISTER_USAGE_ANALYZE
u64 instructions_total = 0;
u64 arm_reg_freq[16];
u64 arm_reg_access_total = 0;
u64 arm_instructions_total = 0;
u64 thumb_reg_freq[16];
u64 thumb_reg_access_total = 0;
u64 thumb_instructions_total = 0;
// mla/long mla's addition operand are not counted yet.
#define using_register(instruction_set, register, type) \
instruction_set##_reg_freq[register]++; \
instruction_set##_reg_access_total++ \
#define using_register_list(instruction_set, rlist, count) \
{ \
u32 i; \
for(i = 0; i < count; i++) \
{ \
if((reg_list >> i) & 0x01) \
{ \
using_register(instruction_set, i, memory_target); \
} \
} \
} \
#define using_instruction(instruction_set) \
instruction_set##_instructions_total++; \
instructions_total++ \
int sort_tagged_element(const void *_a, const void *_b)
{
const u64 *a = _a;
const u64 *b = _b;
return (int)(b[1] - a[1]);
}
void print_register_usage(void)
{
u32 i;
u64 arm_reg_freq_tagged[32];
u64 thumb_reg_freq_tagged[32];
double percent;
double percent_total = 0.0;
for(i = 0; i < 16; i++)
{
arm_reg_freq_tagged[i * 2] = i;
arm_reg_freq_tagged[(i * 2) + 1] = arm_reg_freq[i];
thumb_reg_freq_tagged[i * 2] = i;
thumb_reg_freq_tagged[(i * 2) + 1] = thumb_reg_freq[i];
}
qsort(arm_reg_freq_tagged, 16, sizeof(u64) * 2, sort_tagged_element);
qsort(thumb_reg_freq_tagged, 16, sizeof(u64) * 2, sort_tagged_element);
printf("ARM register usage (%lf%% ARM instructions):\n",
(arm_instructions_total * 100.0) / instructions_total);
for(i = 0; i < 16; i++)
{
percent = (arm_reg_freq_tagged[(i * 2) + 1] * 100.0) /
arm_reg_access_total;
percent_total += percent;
printf("r%02d: %lf%% (-- %lf%%)\n",
(u32)arm_reg_freq_tagged[(i * 2)], percent, percent_total);
}
percent_total = 0.0;
printf("\nThumb register usage (%lf%% Thumb instructions):\n",
(thumb_instructions_total * 100.0) / instructions_total);
for(i = 0; i < 16; i++)
{
percent = (thumb_reg_freq_tagged[(i * 2) + 1] * 100.0) /
thumb_reg_access_total;
percent_total += percent;
printf("r%02d: %lf%% (-- %lf%%)\n",
(u32)thumb_reg_freq_tagged[(i * 2)], percent, percent_total);
}
memset(arm_reg_freq, 0, sizeof(u64) * 16);
memset(thumb_reg_freq, 0, sizeof(u64) * 16);
arm_reg_access_total = 0;
thumb_reg_access_total = 0;
}
#else /* REGISTER_USAGE_ANALYZE */
#define using_register(instruction_set, register, type)
#define using_register_list(instruction_set, rlist, count)
#define using_instruction(instruction_set)
#endif /* REGISTER_USAGE_ANALYZE */
#ifdef TRACE_INSTRUCTIONS
static void interp_trace_instruction(u32 pc, u32 mode)
{
if (mode)
printf("Executed arm %x\n", pc);
else
printf("Executed thumb %x\n", pc);
#ifdef TRACE_REGISTERS
print_regs();
#endif
}
#endif