diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 0394e989d06..2f7ade495e2 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1775,6 +1775,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
     tb->cflags = cflags;
     tb->trace_vcpu_dstate = *cpu->trace_dstate;
     tcg_ctx->tb_cflags = cflags;
+    tcg_ctx->notes = g_array_set_size(tcg_ctx->notes, 0);
  tb_overflow:
 
 #ifdef CONFIG_PROFILER
@@ -1896,7 +1897,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
             size_t data_size = gen_code_size - code_size;
             size_t i;
 
-            log_disas(tb->tc.ptr, code_size);
+            log_disas(tb->tc.ptr, code_size, tcg_ctx);
 
             for (i = 0; i < data_size; i += sizeof(tcg_target_ulong)) {
                 if (sizeof(tcg_target_ulong) == 8) {
@@ -1910,7 +1911,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
                 }
             }
         } else {
-            log_disas(tb->tc.ptr, gen_code_size);
+            log_disas(tb->tc.ptr, gen_code_size, tcg_ctx);
         }
         qemu_log("\n");
         qemu_log_flush();
diff --git a/disas.c b/disas.c
index c0f57284a43..edf4462846f 100644
--- a/disas.c
+++ b/disas.c
@@ -342,7 +342,7 @@ static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size)
 }
 
 /* Disassemble SIZE bytes at CODE for the host.  */
-static bool cap_disas_host(disassemble_info *info, void *code, size_t size)
+static bool cap_disas_host(disassemble_info *info, void *code, size_t size, void *opaque)
 {
     csh handle;
     const uint8_t *cbuf;
@@ -359,6 +359,7 @@ static bool cap_disas_host(disassemble_info *info, void *code, size_t size)
 
     while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) {
        cap_dump_insn(info, insn);
+       tcg_disas_annotation(stderr, opaque, pc);
     }
     if (size != 0) {
         (*info->fprintf_func)(info->stream,
@@ -416,7 +417,7 @@ static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count)
 #endif /* !CONFIG_USER_ONLY */
 #else
 # define cap_disas_target(i, p, s)  false
-# define cap_disas_host(i, p, s)  false
+# define cap_disas_host(i, p, s, o)  false
 # define cap_disas_monitor(i, p, c)  false
 #endif /* CONFIG_CAPSTONE */
 
@@ -462,7 +463,6 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code,
     for (pc = code; size > 0; pc += count, size -= count) {
 	fprintf(out, "0x" TARGET_FMT_lx ":  ", pc);
 	count = s.info.print_insn(pc, &s.info);
-	fprintf(out, "\n");
 	if (count < 0)
 	    break;
         if (size < count) {
@@ -477,7 +477,7 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code,
 
 
 /* Disassemble this for me please... (debugging). */
-void disas(FILE *out, void *code, unsigned long size)
+void disas(FILE *out, void *code, unsigned long size, void *opaque)
 {
     uintptr_t pc;
     int count;
@@ -555,7 +555,7 @@ void disas(FILE *out, void *code, unsigned long size)
     print_insn = print_insn_hppa;
 #endif
 
-    if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) {
+    if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size, opaque)) {
         return;
     }
 
@@ -565,9 +565,10 @@ void disas(FILE *out, void *code, unsigned long size)
     for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
         fprintf(out, "0x%08" PRIxPTR ":  ", pc);
         count = print_insn(pc, &s.info);
-	fprintf(out, "\n");
-	if (count < 0)
-	    break;
+        tcg_disas_annotation(out, opaque, pc);
+        fprintf(out, "\n");
+        if (count < 0)
+            break;
     }
 }
 
diff --git a/include/disas/disas.h b/include/disas/disas.h
index 15da511f49c..c2f75c759f1 100644
--- a/include/disas/disas.h
+++ b/include/disas/disas.h
@@ -5,8 +5,10 @@
 #ifdef NEED_CPU_H
 #include "cpu.h"
 
+void tcg_disas_annotation(FILE *out, void *opaque, uintptr_t pc);
+
 /* Disassemble this for me please... (debugging). */
-void disas(FILE *out, void *code, unsigned long size);
+void disas(FILE *out, void *code, unsigned long size, void *s);
 void target_disas(FILE *out, CPUState *cpu, target_ulong code,
                   target_ulong size);
 
diff --git a/include/exec/log.h b/include/exec/log.h
index de067f173b8..9fe239fa8c3 100644
--- a/include/exec/log.h
+++ b/include/exec/log.h
@@ -43,11 +43,13 @@ static inline void log_target_disas(CPUState *cpu, target_ulong start,
     target_disas(qemu_logfile, cpu, start, len);
 }
 
-static inline void log_disas(void *code, unsigned long size)
+static inline void log_disas(void *code, unsigned long size, void *s)
 {
-    disas(qemu_logfile, code, size);
+    disas(qemu_logfile, code, size, s);
 }
 
+void tcg_disas_annotation(FILE *out, void *opaque, uintptr_t pc);
+
 #if defined(CONFIG_USER_ONLY)
 /* page_dump() output to the log file: */
 static inline void log_page_dump(void)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 46b31a2f68b..301408ff511 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -781,6 +781,8 @@ void tcg_register_thread(void)
     g_assert(n < ms->smp.max_cpus);
     atomic_set(&tcg_ctxs[n], s);
 
+    s->notes = g_array_new(true, false, sizeof(TCGNote));
+
     tcg_ctx = s;
     qemu_mutex_lock(&region.lock);
     err = tcg_region_initial_alloc__locked(tcg_ctx);
@@ -977,6 +979,8 @@ void tcg_context_init(TCGContext *s)
         indirect_reg_alloc_order[i] = tcg_target_reg_alloc_order[i];
     }
 
+    s->notes = g_array_new(true, false, sizeof(TCGNote));
+
     tcg_ctx = s;
     /*
      * In user-mode we simply share the init context among threads, since we
@@ -1078,7 +1082,7 @@ void tcg_prologue_init(TCGContext *s)
             size_t data_size = prologue_size - code_size;
             size_t i;
 
-            log_disas(buf0, code_size);
+            log_disas(buf0, code_size, s);
 
             for (i = 0; i < data_size; i += sizeof(tcg_target_ulong)) {
                 if (sizeof(tcg_target_ulong) == 8) {
@@ -1092,7 +1096,7 @@ void tcg_prologue_init(TCGContext *s)
                 }
             }
         } else {
-            log_disas(buf0, prologue_size);
+            log_disas(buf0, prologue_size, s);
         }
         qemu_log("\n");
         qemu_log_flush();
@@ -3124,6 +3128,10 @@ static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs,
             /* fallthrough */
 
         case TEMP_VAL_REG:
+        {
+            TCGNote n = { REGISTER_SPILL, s->code_ptr };
+            g_array_append_val(s->notes, n);
+            
             tcg_out_st(s, ts->type, ts->reg,
                        ts->mem_base->reg, ts->mem_offset);
 
@@ -3132,7 +3140,7 @@ static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs,
                 atomic_inc(&s->current_tb->tb_stats->code.spills);
             }
             break;
-
+        }
         case TEMP_VAL_MEM:
             break;
 
@@ -4133,6 +4141,9 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
             tcg_reg_alloc_dup(s, op);
             break;
         case INDEX_op_insn_start:
+        {
+            TCGNote n = { INSN_START, s->code_ptr };
+            g_array_append_val(s->notes, n);
             if (num_insns >= 0) {
                 size_t off = tcg_current_code_size(s);
                 s->gen_insn_end_off[num_insns] = off;
@@ -4150,6 +4161,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
                 s->gen_insn_data[num_insns][i] = a;
             }
             break;
+        }
         case INDEX_op_discard:
             temp_dead(s, arg_temp(op->args[0]));
             break;
@@ -4221,6 +4233,27 @@ void tcg_dump_info(void)
     dump_jit_profile_info(s);
 }
 
+void tcg_disas_annotation(FILE *out, void *opaque, uintptr_t pc)
+{
+    TCGContext *s = (TCGContext *) opaque;
+    int i;
+
+    for (i = 0; i < s->notes->len; i++) {
+        TCGNote *n = &g_array_index(s->notes, TCGNote, i);
+        if (n->start == (tcg_insn_unit *) pc) {
+            switch (n->e) {
+            case INSN_START:
+                fprintf(out, "\tinsn");
+                break;
+            case REGISTER_SPILL:
+                fprintf(out, "\tspill");
+                break;
+            }
+        }
+    }
+}
+
+
 #ifdef ELF_HOST_MACHINE
 /* In order to use this feature, the backend needs to do three things:
 
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 026a066b9a1..b4fcf7f7170 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -653,6 +653,21 @@ typedef struct TCGProfile {
     int64_t table_op_count[NB_OPS];
 } TCGProfile;
 
+/*
+ * TCGNote entries are used to track points in the outgoing instruction stream
+ * for better debug output.
+ */
+
+typedef enum {
+    INSN_START,
+    REGISTER_SPILL
+} TCGEvent;
+
+typedef struct {
+    TCGEvent e;
+    tcg_insn_unit *start;
+} TCGNote;
+
 struct TCGContext {
     uint8_t *pool_cur, *pool_end;
     TCGPool *pool_first, *pool_current, *pool_first_large;
@@ -687,6 +702,8 @@ struct TCGContext {
     const TCGOpcode *vecop_list;
 #endif
 
+    GArray *notes;
+
     /* Code generation.  Note that we specifically do not use tcg_insn_unit
        here, because there's too much arithmetic throughout that relies
        on addition and subtraction working on bytes.  Rely on the GCC
