-
Notifications
You must be signed in to change notification settings - Fork 69
/
Copy pathinstruction_mix.c
491 lines (449 loc) · 12.2 KB
/
instruction_mix.c
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
/*
This file is part of MAMBO, a low-overhead dynamic binary modification tool:
https://github.com/beehive-lab/mambo
Copyright 2018 Guillermo Callaghan <guillermocallaghan at hotmail dot com>
Copyright 2018 The University of Manchester
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifdef PLUGINS_NEW
// Uncomment to count prefetch instructions
// #define COUNT_PRFM
#include <stdio.h>
#include <assert.h>
#include <locale.h>
#include <inttypes.h>
#include "../plugins.h"
struct instructions {
uint64_t integer;
uint64_t floating;
uint64_t load;
uint64_t store;
uint64_t branch;
#ifdef COUNT_PRFM
uint64_t prefetch;
#endif
#ifdef __riscv
uint64_t atomic;
#endif
};
struct instructions global_counters = {0};
// Callback function prototypes
int instruction_count_pre_thread_handler(mambo_context *ctx);
int instruction_count_pre_inst_handler(mambo_context *ctx);
int instruction_count_post_thread_handler(mambo_context *ctx);
int instruction_count_exit_handler(mambo_context *ctx);
// Auxiliary function to print the counters
void print_counters(struct instructions *counters);
// Plugin registration and event callbacks function
__attribute__((constructor)) void branch_count_init_plugin() {
mambo_context *ctx = mambo_register_plugin();
assert(ctx != NULL);
mambo_register_pre_thread_cb(ctx, &instruction_count_pre_thread_handler);
mambo_register_pre_inst_cb(ctx, &instruction_count_pre_inst_handler);
mambo_register_post_thread_cb(ctx, &instruction_count_post_thread_handler);
mambo_register_exit_cb(ctx, &instruction_count_exit_handler);
}
int instruction_count_pre_thread_handler(mambo_context *ctx) {
// Thread private counters initialisation
struct instructions *counters = mambo_alloc(ctx, sizeof(struct instructions));
assert(counters != NULL);
mambo_set_thread_plugin_data(ctx, counters);
counters->integer = 0;
counters->floating = 0;
counters->load = 0;
counters->store = 0;
counters->branch = 0;
#ifdef COUNT_PRFM
counters->prefetch = 0;
#endif
#ifdef __riscv
counters->atomic = 0;
#endif
}
int instruction_count_post_thread_handler(mambo_context *ctx) {
// On thread exit, the counters are added to the global counters
struct instructions *counters = mambo_get_thread_plugin_data(ctx);
fprintf(stderr, "Thread: %d\n", mambo_get_thread_id(ctx));
// Prints thread private counters
print_counters(counters); // comment this out if not needed
atomic_increment_u64(&global_counters.integer, counters->integer);
atomic_increment_u64(&global_counters.floating, counters->floating);
atomic_increment_u64(&global_counters.load, counters->load);
atomic_increment_u64(&global_counters.store, counters->store);
atomic_increment_u64(&global_counters.branch, counters->branch);
#ifdef COUNT_PRFM
atomic_increment_u64(&global_counters.prefetch, counters->prefetch);
#endif
#ifdef __riscv
atomic_increment_u64(&global_counters.atomic, counters->atomic);
#endif
mambo_free(ctx, counters);
}
int instruction_count_pre_inst_handler(mambo_context *ctx) {
struct instructions *counters = mambo_get_thread_plugin_data(ctx);
uint64_t *inst_counter = NULL;
#ifdef __aarch64__
// Variables are used for decoding the fields of intructions
uint32_t sf, rm, opcode, rn, rd;
// Selects the appropriate counter according to the instruction type
switch (ctx->code.inst) {
// Branches, Exception Generating and System instructions Category
// * Branches instructions
case A64_B_BL:
case A64_B_COND:
case A64_CBZ_CBNZ:
case A64_TBZ_TBNZ:
case A64_BR:
case A64_BLR:
case A64_RET:
inst_counter = &counters->branch;
break;
// * Exception Generating
case A64_SVC:
case A64_HVC:
case A64_BRK:
break;
// * System instructions
case A64_SYS:
case A64_MRS_MSR_REG:
case A64_HINT:
case A64_DSB:
case A64_DMB:
case A64_ISB:
case A64_CLREX:
break;
// Data Processing -- Immediate
case A64_ADD_SUB_IMMED:
case A64_LOGICAL_IMMED:
case A64_BFM:
case A64_ADR:
case A64_EXTR:
case A64_MOV_WIDE:
inst_counter = &counters->integer;
break;
// Loads and Stores
case A64_LDR_LIT:
case A64_LDX_STX:
case A64_LDP_STP:
case A64_LDR_STR_IMMED:
case A64_LDR_STR_REG:
case A64_LDR_STR_UNSIGNED_IMMED:
case A64_LDX_STX_MULTIPLE:
case A64_LDX_STX_MULTIPLE_POST:
case A64_LDX_STX_SINGLE:
case A64_LDX_STX_SINGLE_POST:
if (mambo_is_load(ctx)) {
inst_counter = &counters->load;
} else if (mambo_is_store(ctx)) {
inst_counter = &counters->store;
} else {
#ifdef COUNT_PRFM
inst_counter = &counters->prefetch;
#endif
}
break;
// Data Processing -- Register
case A64_ADD_SUB_EXT_REG:
case A64_ADD_SUB_SHIFT_REG:
case A64_ADC_SBC:
inst_counter = &counters->integer;
break;
case A64_DATA_PROC_REG1:
case A64_CCMP_CCMN_IMMED:
case A64_CCMP_CCMN_REG:
case A64_COND_SELECT:
case A64_LOGICAL_REG:
case A64_DATA_PROC_REG3:
inst_counter = &counters->integer;
break;
case A64_DATA_PROC_REG2:
a64_data_proc_reg2_decode_fields(ctx->code.read_address, &sf, &rm, &opcode, &rn, &rd);
if ((opcode == 2) || (opcode == 3)) { // UDIV or SDIV
inst_counter = &counters->integer;
}
break;
// Data Processing -- Scalar Floating-Point and Advanced SIMD
// * Floating point instructions
case A64_FCMP:
case A64_FCCMP:
case A64_FCSEL:
case A64_FLOAT_REG1:
case A64_FLOAT_REG2:
case A64_FLOAT_REG3:
case A64_FMOV_IMMED:
case A64_FLOAT_CVT_FIXED:
case A64_FLOAT_CVT_INT:
inst_counter = &counters->floating;
break;
// *SIMD
case A64_SIMD_ACROSS_LANE:
case A64_SIMD_COPY:
case A64_SIMD_EXTRACT:
case A64_SIMD_MODIFIED_IMMED:
case A64_SIMD_PERMUTE:
case A64_SIMD_SCALAR_COPY:
case A64_SIMD_SCALAR_PAIRWISE:
case A64_SIMD_SCALAR_SHIFT_IMMED:
case A64_SIMD_SCALAR_THREE_DIFF:
case A64_SIMD_SCALAR_THREE_SAME:
case A64_SIMD_SHIFT_IMMED:
case A64_SIMD_TABLE_LOOKUP:
case A64_SIMD_THREE_DIFF:
case A64_SIMD_THREE_SAME:
case A64_SIMD_SCALAR_TWO_REG:
case A64_SIMD_SCALAR_X_INDEXED:
case A64_SIMD_TWO_REG:
case A64_SIMD_X_INDEXED:
case A64_CRYPTO_AES:
case A64_CRYPTO_SHA_REG3:
case A64_CRYPTO_SHA_REG2:
break;
default:
break;
}
#elif __riscv
switch (ctx->code.inst) {
case RISCV_C_ADDI4SPN:
case RISCV_C_NOP:
case RISCV_C_ADDI:
case RISCV_C_ADDIW:
case RISCV_C_LI:
case RISCV_C_LUI:
case RISCV_C_SRLI:
case RISCV_C_SRAI:
case RISCV_C_ANDI:
case RISCV_C_SUB:
case RISCV_C_XOR:
case RISCV_C_OR:
case RISCV_C_AND:
case RISCV_C_SUBW:
case RISCV_C_ADDW:
case RISCV_C_ADDI16SP:
case RISCV_C_SLLI:
case RISCV_C_MV:
case RISCV_C_ADD:
case RISCV_LUI:
case RISCV_AUIPC:
case RISCV_ADDI:
case RISCV_SLTI:
case RISCV_SLTIU:
case RISCV_XORI:
case RISCV_ORI:
case RISCV_ANDI:
case RISCV_SLLI:
case RISCV_SRLI:
case RISCV_SRAI:
case RISCV_ADD:
case RISCV_SUB:
case RISCV_SLL:
case RISCV_SLT:
case RISCV_SLTU:
case RISCV_XOR:
case RISCV_SRL:
case RISCV_SRA:
case RISCV_OR:
case RISCV_AND:
case RISCV_ADDIW:
case RISCV_SLLIW:
case RISCV_SRLIW:
case RISCV_SRAIW:
case RISCV_ADDW:
case RISCV_SUBW:
case RISCV_SLLW:
case RISCV_SRLW:
case RISCV_SRAW:
case RISCV_MUL:
case RISCV_MULH:
case RISCV_MULHSU:
case RISCV_MULHU:
case RISCV_DIV:
case RISCV_DIVU:
case RISCV_REM:
case RISCV_REMU:
case RISCV_MULW:
case RISCV_DIVW:
case RISCV_DIVUW:
case RISCV_REMW:
case RISCV_REMUW:
inst_counter = &counters->integer;
break;
case RISCV_C_JAL:
case RISCV_C_J:
case RISCV_C_BEQZ:
case RISCV_C_BNEZ:
case RISCV_JAL:
case RISCV_JALR:
case RISCV_BEQ:
case RISCV_BNE:
case RISCV_BLT:
case RISCV_BGE:
case RISCV_BLTU:
case RISCV_BGEU:
case RISCV_C_JR:
case RISCV_C_JALR:
inst_counter = &counters->branch;
break;
case RISCV_C_FLD:
case RISCV_C_LW:
case RISCV_C_LD:
case RISCV_C_FLDSP:
case RISCV_C_LWSP:
case RISCV_C_FLWSP:
case RISCV_C_LDSP:
case RISCV_LB:
case RISCV_LH:
case RISCV_LW:
case RISCV_LBU:
case RISCV_LHU:
case RISCV_LWU:
case RISCV_LD:
case RISCV_LR_D:
case RISCV_LR_W:
case RISCV_FLW:
case RISCV_FLD:
inst_counter = &counters->load;
break;
case RISCV_C_FSD:
case RISCV_C_SW:
case RISCV_C_SD:
case RISCV_C_FSDSP:
case RISCV_C_SWSP:
case RISCV_C_SDSP:
case RISCV_SB:
case RISCV_SH:
case RISCV_SW:
case RISCV_SD:
case RISCV_SC_W:
case RISCV_SC_D:
case RISCV_FSW:
case RISCV_FSD:
inst_counter = &counters->store;
break;
case RISCV_C_EBREAK:
case RISCV_FENCE:
case RISCV_ECALL:
case RISCV_EBREAK:
case RISCV_FENCEI:
case RISCV_CSRRW:
case RISCV_CSRRS:
case RISCV_CSRRC:
case RISCV_CSRRWI:
case RISCV_CSRRSI:
case RISCV_CSRRCI:
break;
case RISCV_AMOSWAP_W:
case RISCV_AMOADD_W:
case RISCV_AMOXOR_W:
case RISCV_AMOAND_W:
case RISCV_AMOOR_W:
case RISCV_AMOMIN_W:
case RISCV_AMOMAX_W:
case RISCV_AMOMINU_W:
case RISCV_AMOMAXU_W:
case RISCV_AMOSWAP_D:
case RISCV_AMOADD_D:
case RISCV_AMOXOR_D:
case RISCV_AMOAND_D:
case RISCV_AMOOR_D:
case RISCV_AMOMIN_D:
case RISCV_AMOMAX_D:
case RISCV_AMOMINU_D:
case RISCV_AMOMAXU_D:
inst_counter = &counters->atomic;
break;
case RISCV_FMADD_S:
case RISCV_FMSUB_S:
case RISCV_FNMSUB_S:
case RISCV_FNMADD_S:
case RISCV_FADD_S:
case RISCV_FSUB_S:
case RISCV_FMUL_S:
case RISCV_FDIV_S:
case RISCV_FSQRT_S:
case RISCV_FSGNJ_S:
case RISCV_FSGNJN_S:
case RISCV_FSGNJX_S:
case RISCV_FMIN_S:
case RISCV_FMAX_S:
case RISCV_FCVT_W_S:
case RISCV_FCVT_WU_S:
case RISCV_FMV_X_W:
case RISCV_FEQ_S:
case RISCV_FLT_S:
case RISCV_FLE_S:
case RISCV_FCLASS_S:
case RISCV_FCVT_S_W:
case RISCV_FCVT_S_WU:
case RISCV_FMV_W_X:
case RISCV_FCVT_L_S:
case RISCV_FCVT_LU_S:
case RISCV_FCVT_S_L:
case RISCV_FCVT_S_LU:
case RISCV_FMADD_D:
case RISCV_FMSUB_D:
case RISCV_FNMSUB_D:
case RISCV_FNMADD_D:
case RISCV_FADD_D:
case RISCV_FSUB_D:
case RISCV_FMUL_D:
case RISCV_FDIV_D:
case RISCV_FSQRT_D:
case RISCV_FSGNJ_D:
case RISCV_FSGNJN_D:
case RISCV_FSGNJX_D:
case RISCV_FMIN_D:
case RISCV_FMAX_D:
case RISCV_FCVT_S_D:
case RISCV_FCVT_D_S:
case RISCV_FEQ_D:
case RISCV_FLT_D:
case RISCV_FLE_D:
case RISCV_FCLASS_D:
case RISCV_FCVT_W_D:
case RISCV_FCVT_WU_D:
case RISCV_FCVT_D_W:
case RISCV_FCVT_D_WU:
case RISCV_FCVT_L_D:
case RISCV_FCVT_LU_D:
case RISCV_FMV_X_D:
case RISCV_FCVT_D_L:
case RISCV_FCVT_D_LU:
case RISCV_FMV_D_X:
inst_counter = &counters->floating;
break;
}
#else
#error Unsupported architecture
#endif
if (inst_counter != NULL) {
emit_counter64_incr(ctx, inst_counter, 1);
}
}
int instruction_count_exit_handler(mambo_context *ctx) {
// On application exit prints the global counters
fprintf(stderr, "Total:\n");
print_counters(&global_counters);
}
void print_counters(struct instructions *counters) {
// Auxiliary function to print the counters
fprintf(stderr, " integer : %'" PRIu64 "\n", counters->integer);
fprintf(stderr, " floating: %'" PRIu64 "\n", counters->floating);
fprintf(stderr, " load : %'" PRIu64 "\n", counters->load);
fprintf(stderr, " store : %'" PRIu64 "\n", counters->store);
fprintf(stderr, " branch : %'" PRIu64 "\n", counters->branch);
#ifdef COUNT_PRFM
fprintf(stderr, " prefetch: %'" PRIu64 "\n", counters->prefetch);
#endif
#ifdef __riscv
fprintf(stderr, " atomic: %'" PRIu64 "\n", counters->atomic);
#endif
}
#endif