+#include "misc.h"
+
+#ifdef CYCLE_STATS
+static const char * id_names[] = {
+ "RXO_unknown",
+ "RXO_mov", /* d = s (signed) */
+ "RXO_movbi", /* d = [s,s2] (signed) */
+ "RXO_movbir", /* [s,s2] = d (signed) */
+ "RXO_pushm", /* s..s2 */
+ "RXO_popm", /* s..s2 */
+ "RXO_xchg", /* s <-> d */
+ "RXO_stcc", /* d = s if cond(s2) */
+ "RXO_rtsd", /* rtsd, 1=imm, 2-0 = reg if reg type */
+
+ /* These are all either d OP= s or, if s2 is set, d = s OP s2. Note
+ that d may be "None". */
+ "RXO_and",
+ "RXO_or",
+ "RXO_xor",
+ "RXO_add",
+ "RXO_sub",
+ "RXO_mul",
+ "RXO_div",
+ "RXO_divu",
+ "RXO_shll",
+ "RXO_shar",
+ "RXO_shlr",
+
+ "RXO_adc", /* d = d + s + carry */
+ "RXO_sbb", /* d = d - s - ~carry */
+ "RXO_abs", /* d = |s| */
+ "RXO_max", /* d = max(d,s) */
+ "RXO_min", /* d = min(d,s) */
+ "RXO_emul", /* d:64 = d:32 * s */
+ "RXO_emulu", /* d:64 = d:32 * s (unsigned) */
+
+ "RXO_rolc", /* d <<= 1 through carry */
+ "RXO_rorc", /* d >>= 1 through carry*/
+ "RXO_rotl", /* d <<= #s without carry */
+ "RXO_rotr", /* d >>= #s without carry*/
+ "RXO_revw", /* d = revw(s) */
+ "RXO_revl", /* d = revl(s) */
+ "RXO_branch", /* pc = d if cond(s) */
+ "RXO_branchrel",/* pc += d if cond(s) */
+ "RXO_jsr", /* pc = d */
+ "RXO_jsrrel", /* pc += d */
+ "RXO_rts",
+ "RXO_nop",
+ "RXO_nop2",
+ "RXO_nop3",
+ "RXO_nop4",
+ "RXO_nop5",
+ "RXO_nop6",
+ "RXO_nop7",
+
+ "RXO_scmpu",
+ "RXO_smovu",
+ "RXO_smovb",
+ "RXO_suntil",
+ "RXO_swhile",
+ "RXO_smovf",
+ "RXO_sstr",
+
+ "RXO_rmpa",
+ "RXO_mulhi",
+ "RXO_mullo",
+ "RXO_machi",
+ "RXO_maclo",
+ "RXO_mvtachi",
+ "RXO_mvtaclo",
+ "RXO_mvfachi",
+ "RXO_mvfacmi",
+ "RXO_mvfaclo",
+ "RXO_racw",
+
+ "RXO_sat", /* sat(d) */
+ "RXO_satr",
+
+ "RXO_fadd", /* d op= s */
+ "RXO_fcmp",
+ "RXO_fsub",
+ "RXO_ftoi",
+ "RXO_fmul",
+ "RXO_fdiv",
+ "RXO_round",
+ "RXO_itof",
+
+ "RXO_bset", /* d |= (1<<s) */
+ "RXO_bclr", /* d &= ~(1<<s) */
+ "RXO_btst", /* s & (1<<s2) */
+ "RXO_bnot", /* d ^= (1<<s) */
+ "RXO_bmcc", /* d<s> = cond(s2) */
+
+ "RXO_clrpsw", /* flag index in d */
+ "RXO_setpsw", /* flag index in d */
+ "RXO_mvtipl", /* new IPL in s */
+
+ "RXO_rtfi",
+ "RXO_rte",
+ "RXO_rtd", /* undocumented */
+ "RXO_brk",
+ "RXO_dbt", /* undocumented */
+ "RXO_int", /* vector id in s */
+ "RXO_stop",
+ "RXO_wait",
+
+ "RXO_sccnd", /* d = cond(s) ? 1 : 0 */
+};
+
+static const char * optype_names[] = {
+ " - ",
+ "#Imm", /* #addend */
+ " Rn ", /* Rn */
+ "[Rn]", /* [Rn + addend] */
+ "Ps++", /* [Rn+] */
+ "--Pr", /* [-Rn] */
+ " cc ", /* eq, gtu, etc */
+ "Flag", /* [UIOSZC] */
+ "RbRi" /* [Rb + scale * Ri] */
+};
+
+#define N_RXO ARRAY_SIZE (id_names)
+#define N_RXT ARRAY_SIZE (optype_names)
+#define N_MAP 90
+
+static unsigned long long benchmark_start_cycle;
+static unsigned long long benchmark_end_cycle;
+
+static int op_cache[N_RXT][N_RXT][N_RXT];
+static int op_cache_rev[N_MAP];
+static int op_cache_idx = 0;
+
+static int
+op_lookup (int a, int b, int c)
+{
+ if (op_cache[a][b][c])
+ return op_cache[a][b][c];
+ op_cache_idx ++;
+ if (op_cache_idx >= N_MAP)
+ {
+ printf("op_cache_idx exceeds %d\n", N_MAP);
+ exit(1);
+ }
+ op_cache[a][b][c] = op_cache_idx;
+ op_cache_rev[op_cache_idx] = (a<<8) | (b<<4) | c;
+ return op_cache_idx;
+}
+
+static char *
+op_cache_string (int map)
+{
+ static int ci;
+ static char cb[5][20];
+ int a, b, c;
+
+ map = op_cache_rev[map];
+ a = (map >> 8) & 15;
+ b = (map >> 4) & 15;
+ c = (map >> 0) & 15;
+ ci = (ci + 1) % 5;
+ sprintf(cb[ci], "%s %s %s", optype_names[a], optype_names[b], optype_names[c]);
+ return cb[ci];
+}
+
+static unsigned long long cycles_per_id[N_RXO][N_MAP];
+static unsigned long long times_per_id[N_RXO][N_MAP];
+static unsigned long long memory_stalls;
+static unsigned long long register_stalls;
+static unsigned long long branch_stalls;
+static unsigned long long branch_alignment_stalls;
+static unsigned long long fast_returns;
+
+static unsigned long times_per_pair[N_RXO][N_MAP][N_RXO][N_MAP];
+static int prev_opcode_id = RXO_unknown;
+static int po0;