diff --git a/src/e2k.S b/src/e2k.S index 031ecdd..25f6b9e 100644 --- a/src/e2k.S +++ b/src/e2k.S @@ -9,11 +9,14 @@ #define PC %r4 #define CUR %r5 #define ACC %r6 -#define STATS_OPS %r7 -#define STATS_CALLS %r8 -#define STATS_BRANCHES %r9 -#define STATS_BRANCHES_TAKEN %r10 -#define STATS_CPU_CYCLES %r11 +#define STATS_ADDS %r7 +#define STATS_MOVS %r8 +#define STATS_BEQZ %r9 +#define STATS_BEQZ_TAKEN %r10 +#define STATS_BNEZ %r11 +#define STATS_BNEZ_TAKEN %r12 +#define STATS_CALLS %r13 +#define STATS_CPU_CYCLES %r14 ! Pipeline registers #define NPC_F %b[0] @@ -41,6 +44,8 @@ #define IS_NOT_BNEZ_D %pred10 #define IS_NOT_BNEZ_E %pred11 +#define IS_BEQZ_TAKEN %pred25 +#define IS_BNEZ_TAKEN %pred26 #define IS_NOT_BRANCH %pred27 #define IS_ACC_ZERO %pred28 #define IS_NOT_TAKEN %pred29 @@ -64,11 +69,16 @@ run_program_e2k: disp %ctpr1, pipeline } { - nop 3 - ldd,0 STATS, 0, STATS_OPS - ldd,2 STATS, 8, STATS_CALLS - ldd,3 STATS, 16, STATS_BRANCHES - ldd,5 STATS, 24, STATS_BRANCHES_TAKEN + ldd,0 STATS, 0, STATS_ADDS + ldd,2 STATS, 8, STATS_MOVS + ldd,3 STATS, 16, STATS_BEQZ + ldd,5 STATS, 24, STATS_BEQZ_TAKEN + } + { + nop 2 + ldd,0 STATS, 32, STATS_BNEZ + ldd,2 STATS, 40, STATS_BNEZ_TAKEN + ldd,3 STATS, 48, STATS_CALLS } { rrd,0 %clkr, STATS_CPU_CYCLES @@ -181,10 +191,13 @@ loop: landp @p0, ~@p1, @p4 landp ~@p0, ~@p2, @p5 landp ~@p4, ~@p5, @p6 + pass @p4, IS_BEQZ_TAKEN + pass @p5, IS_BNEZ_TAKEN pass @p6, IS_NOT_TAKEN } { - addd,0 STATS_OPS, 1, STATS_OPS + addd,0 STATS_ADDS, 1, STATS_ADDS ? ~IS_NOT_ADD_E + addd,5 STATS_MOVS, 1, STATS_MOVS ? ~IS_NOT_MOV_E ! Decode cmpandesb,1,sm INSN_D, OP_ADD, IS_NOT_ADD_D @@ -217,8 +230,10 @@ loop: { ldw,2,sm CODE, NPC_E, INSN_D ? ~IS_NOT_TAKEN - addd,0 STATS_BRANCHES, 1, STATS_BRANCHES ? ~IS_NOT_BRANCH - addd,1 STATS_BRANCHES_TAKEN, 1, STATS_BRANCHES_TAKEN ? ~IS_NOT_TAKEN + addd,0 STATS_BEQZ, 1, STATS_BEQZ ? ~IS_NOT_BEQZ_E + addd,1 STATS_BEQZ_TAKEN, 1, STATS_BEQZ_TAKEN ? IS_BEQZ_TAKEN + addd,3 STATS_BNEZ, 1, STATS_BNEZ ? ~IS_NOT_BNEZ_E + addd,4 STATS_BNEZ_TAKEN, 1, STATS_BNEZ_TAKEN ? IS_BNEZ_TAKEN abn abnf=0, abnt=1 abp abpf=0, abpt=1 @@ -239,23 +254,26 @@ loop: ct LOOP ? ~IS_NOT_BRANCH } { - ! remove end op from counter rrd,0 %clkr, %g16 - subd,1 STATS_OPS, 1, STATS_OPS return %ctpr3 } { subd,0 %g16, STATS_CPU_CYCLES, STATS_CPU_CYCLES - std,2 STATS_OPS, STATS, 0 - std,5 STATS_CALLS, STATS, 8 + std,2 STATS_ADDS, STATS, 0 + std,5 STATS_MOVS, STATS, 8 } { - std,2 STATS_BRANCHES, STATS, 16 - std,5 STATS_BRANCHES_TAKEN, STATS, 24 + std,2 STATS_BEQZ, STATS, 16 + std,5 STATS_BEQZ_TAKEN, STATS, 24 } { - nop 3 - std,2 STATS_CPU_CYCLES, STATS, 32 + std,2 STATS_BNEZ, STATS, 32 + std,5 STATS_BNEZ_TAKEN, STATS, 40 + } + { + nop 1 + std,2 STATS_CALLS, STATS, 48 + std,5 STATS_CPU_CYCLES, STATS, 56 } ct %ctpr3 diff --git a/src/main.c b/src/main.c index 6fd634b..aff717e 100644 --- a/src/main.c +++ b/src/main.c @@ -17,10 +17,13 @@ #define MAX_NESTING 100 typedef struct Stats { - uint64_t ops; + uint64_t adds; + uint64_t movs; + uint64_t beqz; + uint64_t beqz_taken; + uint64_t bnez; + uint64_t bnez_taken; uint64_t calls; - uint64_t branches; - uint64_t taken_branches; uint64_t cpu_cycles; } Stats; @@ -262,26 +265,27 @@ static void run_program_bc(const int32_t *code, uint8_t *tape, for (; code[pc]; ++pc) { int32_t n = insn_imm(code[pc]); - stats->ops += 1; switch (code[pc] & OP_MASK) { case OP_BEQZ: - stats->branches += 1; + stats->beqz += 1; if (cur == 0) { pc += n / 4; - stats->taken_branches += 1; + stats->beqz_taken += 1; } break; case OP_BNEZ: - stats->branches += 1; + stats->bnez += 1; if (cur != 0) { pc += n / 4; - stats->taken_branches += 1; + stats->bnez_taken += 1; } break; case OP_ADD: + stats->adds += 1; cur += n; break; case OP_MOV: + stats->movs += 1; tape[i] = cur; i += n; cur = tape[i]; @@ -396,11 +400,27 @@ int main(int argc, char *argv[], char *envp[]) { } if (opts.stats) { + uint64_t total = stats.adds + stats.movs + stats.beqz + stats.bnez + stats.calls; + uint64_t branches = stats.beqz + stats.bnez; + uint64_t branches_taken = stats.beqz_taken + stats.bnez_taken; + printf_err(" Stats\n"); - printf_err(" ops: %" PRIu64 "\n", stats.ops); + printf_err(" ops: %" PRIu64 "\n", total); + printf_err(" adds: %" PRIu64 "\n", stats.adds); + printf_err(" movs: %" PRIu64 "\n", stats.movs); + printf_err(" beqz: %" PRIu64 " (%.1f%% taken %" PRIu64 ")\n", + stats.beqz, + (double) stats.beqz_taken / stats.beqz * 100, + stats.beqz_taken); + printf_err(" bnez: %" PRIu64 " (%.1f%% taken %" PRIu64 ")\n", + stats.bnez, + (double) stats.bnez_taken / stats.bnez * 100, + stats.bnez_taken); + printf_err(" branches: %" PRIu64 " (%.1f%% taken %" PRIu64 ")\n", + branches, + (double) branches_taken / branches * 100, + branches_taken); printf_err(" calls: %" PRIu64 "\n", stats.calls); - printf_err(" branches: %" PRIu64 " (taken %" PRIu64 ")\n", - stats.branches, stats.taken_branches); if (stats.cpu_cycles) { printf_err(" cpu cycles: %" PRIu64 "\n", stats.cpu_cycles); }