diff --git a/Makefile b/Makefile
index 5975926..2831dc3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 # Makefile for QEMU.
 
-GENERATED_HEADERS = config-host.h trace.h trace-helper.h trace-helper.c
+GENERATED_HEADERS = config-host.h trace.h trace-helper.h trace-helper.c trace-gen.h
 
 ifneq ($(wildcard config-host.mak),)
 # Put the all: rule here so that config-host.mak can contain dependencies.
@@ -130,6 +130,11 @@ trace-helper.c-timestamp: $(SRC_PATH)/trace-events config-host.mak
 
 trace-helper.o: trace-helper.c $(GENERATED_HEADERS)
 
+trace-gen.h: trace-gen.h-timestamp
+trace-gen.h-timestamp: $(SRC_PATH)/trace-events config-host.mak
+	$(call quiet-command,sh $(SRC_PATH)/tracetool $(TRACETOOL_EXTRA) --gen --$(TRACE_BACKEND) -h < $< > $@,"  GEN   trace-gen.h")
+	@cmp -s $@ trace-gen.h || cp $@ trace-gen.h
+
 simpletrace.o: simpletrace.c $(GENERATED_HEADERS)
 
 version.o: $(SRC_PATH)/version.rc config-host.mak
@@ -167,6 +172,7 @@ clean:
 	rm -f qemu-img-cmds.h
 	rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp
 	rm -f trace-helper.c trace-helper.h trace-helper.h-timestamp trace-helper.c-timestamp
+	rm -f trace-gen.h-timestamp trace-gen.c-timestamp
 	$(MAKE) -C tests clean
 	for d in $(ALL_SUBDIRS) libhw32 libhw64 libuser libdis libdis-user; do \
 	if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
diff --git a/trace-events b/trace-events
index 4a89d97..a54fa03 100644
--- a/trace-events
+++ b/trace-events
@@ -43,6 +43,9 @@
 #   Provide trace events suitable for using during TCG code generation.
 #   Generates TCG function helpers reachable through 'helper_trace_gen_##name'
 #   which proxy their calls onto 'trace_##name'.
+#   As an extra aid, functions named 'trace_gen_##name' are generated into
+#   "trace-gen.h", which can be reched through 'trace_gen_##name##_backend' when
+#   the event is instrumented.
 
 # qemu-malloc.c
 disable qemu_malloc(size_t size, void *ptr) "size %zu ptr %p"
diff --git a/tracetool b/tracetool
index 588f442..e99da0c 100755
--- a/tracetool
+++ b/tracetool
@@ -602,6 +602,134 @@ void helper_trace_proxy_$name($args)
 EOF
 }
 
+### Gen - H
+traceto_h_gen()
+{
+     cat <<EOF
+#ifndef TRACE_GEN_H
+#define TRACE_GEN_H
+
+/* This file is autogenerated by tracetool, do not edit. */
+EOF
+
+    convert h $1 nil
+
+    if [ "$had_instrument" = "1" ]; then
+        echo '#include "trace-instrument.h"'
+    fi
+    echo "#endif /* TRACE_GEN_H */"
+}
+
+line_h_gen_parse_pre()
+{
+    case "$3" in
+        "uint32_t") echo "TCGv_i32 __arg_$1 = tcg_const_i32($2);" ;;
+        "uint64_t") echo "TCGv_i64 __arg_$1 = tcg_const_i64($2);" ;;
+        "void *")   echo "TCGv_ptr __arg_$1 = tcg_const_ptr((int64_t)$2);" ;;
+    esac
+}
+
+line_h_gen_parse_args()
+{
+    case "$3" in
+        "uint64_t") echo "__arg_$1" ;;
+        "uint32_t") echo "__arg_$1" ;;
+        "void *")   echo "__arg_$1" ;;
+        *)          echo "$2"       ;;
+    esac
+}
+
+line_h_gen_parse_post()
+{
+    case "$3" in
+        "uint32_t") echo "tcg_temp_free_i32(__arg_$1);" ;;
+        "uint64_t") echo "tcg_temp_free_i64(__arg_$1);" ;;
+        "void *")   echo "tcg_temp_free_i64(__arg_$1);" ;;
+    esac
+}
+ 
+line_h_gen()
+{
+    local gen
+    gen=$(get_property "$1" "gen")
+    [ "$gen" = "1" ] || return
+
+    local name args
+    name=$(get_event_name "$1")
+    args=$(get_args "$1")
+
+    local gen_pre gen_post gen_args i
+    gen_pre=""
+    gen_post=""
+    gen_args=""
+
+    local argname
+    i=1
+    for argname in $(get_argnames "$1"); do
+        argname=${argname%,}
+        eval __argname_$i=$argname
+        i=$(($i + 1))
+    done
+
+    local argtypes argtype accum _pre _arg _post
+    argtypes=$(get_argtypes "$1")
+    i=1
+    accum=""
+    for argtype in $argtypes; do
+        accum="$accum ${argtype%,}"
+        if [ "$argtype" = "${argtype%,}" ]; then
+            continue
+        fi
+        argtype="${accum# }"
+        accum=""
+
+        eval argname=\$__argname_$i
+
+        _pre=$(line_h_gen_parse_pre $i $argname "$argtype")
+        gen_pre="$gen_pre
+$_pre"
+        _arg=$(line_h_gen_parse_arg $i $argname "$argtype")
+        gen_args="$gen_args$_arg"
+        _post=$(line_h_gen_parse_post $i $argname "$argtype")
+        gen_post="$gen_post
+$_post"
+
+        i=$(($i + 1))
+    done
+    argtype="${accum# }"
+    eval argname=\$__argname_$i
+
+    _pre=$(line_h_gen_parse_pre $i $argname "$argtype")
+    gen_pre="$gen_pre
+$_pre"
+    _arg=$(line_h_gen_parse_args $i $argname "$argtype")
+    gen_args="$gen_args, $_arg"
+    _post=$(line_h_gen_parse_post $i $argname "$argtype")
+    gen_post="$gen_post
+$_post"
+
+    gen_args="${gen_args#, }"
+
+    cat <<EOF
+static inline void trace_gen_${name}_backend($args)
+{
+$gen_pre
+    gen_helper_trace_proxy_$name($gen_args);
+$gen_post
+}
+EOF
+
+    # XXX: should still provide instrumentation if event is disabled?
+    local instrument
+    instrument=$(get_property "$1" "instrument")
+    if [ "$instrument" = "1" ]; then
+        had_instrument="1"
+        return
+    fi
+
+    echo "#define trace_gen_$name trace_gen_${name}_backend"
+}
+
 ################################################################################
 ### Generic code
 
@@ -663,7 +791,7 @@ EOF
 while [ $# -gt 0 ]; do
     case $1 in
         "--instrument") enable_instrument="1" ;;
-        "--regular"|"--helper") frontend="${1#--}" ;;
+        "--regular"|"--helper"|"--gen") frontend="${1#--}" ;;
         "--nop"|"--simple"|"--ust") backend="${1#--}" ;;
         "-h"|"-c") output="${1#-}" ;;
         "--check-backend") check=1 ;; # used by ./configure to test for backend
