diff mbox

[RFC] translate-all.c: add hack for coverage testing

Message ID 1392132687-18664-1-git-send-email-peter.maydell@linaro.org
State New
Headers show

Commit Message

Peter Maydell Feb. 11, 2014, 3:31 p.m. UTC
Actually this barely even rises to the level of an RFC, but
since I'm not entirely sure how or if it might be possible to
turn this into upstreamable code I thought I might as well
send it out as-is in case anybody else finds it useful.

The basic idea is that you build the linux-user binary and
run it on something (anything). Instead of actually running
code we instead just loop round feeding every possible
instruction pattern to the decoder. This lets us catch:
 * "can't happen" assertions in the wrong place
 * TCG temp leaks
 * insns which generate too many TCG ops

Obvious deficiencies here:
 * no UI for specifying that you want to test a smaller
   part of the instruction space
 * an assumption that instructions are fixed-length 32 bits
 * cheesily hardwired in

You can do a complete sweep of an entire 32-bit instruction
encoding space within a couple of hours.

thanks
-- PMM

---
 translate-all.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)
diff mbox

Patch

diff --git a/translate-all.c b/translate-all.c
index 543e1ff..716f501 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -195,6 +195,53 @@  int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr
     return 0;
 }
 
+#if 1
+static void cpu_exercise_decoder(CPUArchState *env, TranslationBlock *tb)
+{
+    fprintf(stderr, "Test mode, exercising decoder\n");
+    uint32_t insn = 0;
+    int maxops = 0, numops;
+    uint32_t insnbuf[1];
+
+    /* Force the decoder to do just one instruction at a time */
+    singlestep = 1;
+
+    for (;;) {
+        /* ARM A64 specific hack: just skip all the unallocateds */
+        if (insn && !(insn & (3 << 27))) {
+            insn++;
+            continue;
+        }
+
+        if (!(insn & 0xffff)) {
+            fprintf(stderr, "%x", insn >> 28);
+        }
+
+        tb->pc = h2g_nocheck(&insnbuf);
+        insnbuf[0] = insn;
+
+        tcg_func_start(&tcg_ctx);
+        gen_intermediate_code(env, tb);
+
+        numops = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
+        if (numops > maxops) {
+            maxops = numops;
+            fprintf(stderr, "\nNew worst case TCG ops: %d (insn %08x)\n",
+                             numops, insn);
+        }
+
+        insn++;
+        if (insn == 0) {
+            break;
+        }
+    }
+
+    fprintf(stderr, "\nExercising complete. Worst case TCG ops: %d\n", maxops);
+
+    exit(0);
+}
+#endif
+
 /* The cpu state corresponding to 'searched_pc' is restored.
  */
 static int cpu_restore_state_from_tb(TranslationBlock *tb, CPUArchState *env,
@@ -966,6 +1013,10 @@  TranslationBlock *tb_gen_code(CPUArchState *env,
     tb->cs_base = cs_base;
     tb->flags = flags;
     tb->cflags = cflags;
+#if 1
+    cpu_exercise_decoder(env, tb);
+    exit(0);
+#endif
     cpu_gen_code(env, tb, &code_gen_size);
     tcg_ctx.code_gen_ptr = (void *)(((uintptr_t)tcg_ctx.code_gen_ptr +
             code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));