Merge remote-tracking branch 'sstabellini/disk_io' into staging

* sstabellini/disk_io:
  xen_disk: when using AIO flush after the operation is completed
  xen_disk: open disk with BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO
diff --git a/Makefile b/Makefile
index 1bc3cb0..d8e1f36 100644
--- a/Makefile
+++ b/Makefile
@@ -173,6 +173,7 @@
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := $(BUILD_DIR)/qapi-generated
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
+qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 
 gen-out-type = $(subst .,-,$(suffix $@))
 
@@ -347,28 +348,29 @@
 qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"  GEN   $@")
 
+POD2MAN = pod2man --utf8
 qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu.pod && \
-	  pod2man --section=1 --center=" " --release=" " qemu.pod > $@, \
+	  $(POD2MAN) --section=1 --center=" " --release=" " qemu.pod > $@, \
 	  "  GEN   $@")
 
 qemu-img.1: qemu-img.texi qemu-img-cmds.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-img.pod && \
-	  pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@, \
+	  $(POD2MAN) --section=1 --center=" " --release=" " qemu-img.pod > $@, \
 	  "  GEN   $@")
 
 fsdev/virtfs-proxy-helper.1: fsdev/virtfs-proxy-helper.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< fsdev/virtfs-proxy-helper.pod && \
-	  pod2man --section=1 --center=" " --release=" " fsdev/virtfs-proxy-helper.pod > $@, \
+	  $(POD2MAN) --section=1 --center=" " --release=" " fsdev/virtfs-proxy-helper.pod > $@, \
 	  "  GEN   $@")
 
 qemu-nbd.8: qemu-nbd.texi
 	$(call quiet-command, \
 	  perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-nbd.pod && \
-	  pod2man --section=8 --center=" " --release=" " qemu-nbd.pod > $@, \
+	  $(POD2MAN) --section=8 --center=" " --release=" " qemu-nbd.pod > $@, \
 	  "  GEN   $@")
 
 dvi: qemu-doc.dvi qemu-tech.dvi
diff --git a/Makefile.target b/Makefile.target
index 63cf769..44b2e83 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -81,8 +81,10 @@
 libobj-$(CONFIG_TCG_INTERPRETER) += tci.o
 libobj-y += fpu/softfloat.o
 ifneq ($(TARGET_BASE_ARCH), sparc)
+ifneq ($(TARGET_BASE_ARCH), alpha)
 libobj-y += op_helper.o
 endif
+endif
 libobj-y += helper.o
 ifeq ($(TARGET_BASE_ARCH), i386)
 libobj-y += cpuid.o
@@ -96,6 +98,7 @@
 endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
+libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
 
 libobj-y += disas.o
 libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/QMP/qmp-spec.txt b/QMP/qmp-spec.txt
index 9d30a8c..1ba916c 100644
--- a/QMP/qmp-spec.txt
+++ b/QMP/qmp-spec.txt
@@ -209,13 +209,27 @@
 capabilities array (section '2.2 Server Greeting'). Thus, Clients can check
 that array and enable the capabilities they support.
 
-Additionally, Clients must not assume any particular:
+The QMP Server performs a type check on the arguments to a command.  It
+generates an error if a value does not have the expected type for its
+key, or if it does not understand a key that the Client included.  The
+strictness of the Server catches wrong assumptions of Clients about
+the Server's schema.  Clients can assume that, when such validation
+errors occur, they will be reported before the command generated any
+side effect.
 
-- Size of json-objects or length of json-arrays
+However, Clients must not assume any particular:
+
+- Length of json-arrays
+- Size of json-objects; in particular, future versions of QEMU may add
+  new keys and Clients should be able to ignore them.
 - Order of json-object members or json-array elements
 - Amount of errors generated by a command, that is, new errors can be added
   to any existing command in newer versions of the Server
 
+Of course, the Server does guarantee to send valid JSON.  But apart from
+this, a Client should be "conservative in what they send, and liberal in
+what they accept".
+
 6. Downstream extension of QMP
 ------------------------------
 
diff --git a/configure b/configure
index 8b4e3c1..14ef738 100755
--- a/configure
+++ b/configure
@@ -3608,7 +3608,7 @@
 esac
 
 case "$target_arch2" in
-  sparc*)
+  alpha | sparc*)
     echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
   ;;
 esac
diff --git a/def-helper.h b/def-helper.h
index 0e70c31..b98ff69 100644
--- a/def-helper.h
+++ b/def-helper.h
@@ -39,6 +39,7 @@
 #endif
 #define dh_alias_ptr ptr
 #define dh_alias_void void
+#define dh_alias_noreturn noreturn
 #define dh_alias_env ptr
 #define dh_alias(t) glue(dh_alias_, t)
 
@@ -52,36 +53,42 @@
 #define dh_ctype_tl target_ulong
 #define dh_ctype_ptr void *
 #define dh_ctype_void void
+#define dh_ctype_noreturn void QEMU_NORETURN
 #define dh_ctype_env CPUArchState *
 #define dh_ctype(t) dh_ctype_##t
 
 /* We can't use glue() here because it falls foul of C preprocessor
    recursive expansion rules.  */
 #define dh_retvar_decl0_void void
+#define dh_retvar_decl0_noreturn void
 #define dh_retvar_decl0_i32 TCGv_i32 retval
 #define dh_retvar_decl0_i64 TCGv_i64 retval
 #define dh_retvar_decl0_ptr TCGv_ptr retval
 #define dh_retvar_decl0(t) glue(dh_retvar_decl0_, dh_alias(t))
 
 #define dh_retvar_decl_void
+#define dh_retvar_decl_noreturn
 #define dh_retvar_decl_i32 TCGv_i32 retval,
 #define dh_retvar_decl_i64 TCGv_i64 retval,
 #define dh_retvar_decl_ptr TCGv_ptr retval,
 #define dh_retvar_decl(t) glue(dh_retvar_decl_, dh_alias(t))
 
 #define dh_retvar_void TCG_CALL_DUMMY_ARG
+#define dh_retvar_noreturn TCG_CALL_DUMMY_ARG
 #define dh_retvar_i32 GET_TCGV_i32(retval)
 #define dh_retvar_i64 GET_TCGV_i64(retval)
 #define dh_retvar_ptr GET_TCGV_ptr(retval)
 #define dh_retvar(t) glue(dh_retvar_, dh_alias(t))
 
 #define dh_is_64bit_void 0
+#define dh_is_64bit_noreturn 0
 #define dh_is_64bit_i32 0
 #define dh_is_64bit_i64 1
 #define dh_is_64bit_ptr (TCG_TARGET_REG_BITS == 64)
 #define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t))
 
 #define dh_is_signed_void 0
+#define dh_is_signed_noreturn 0
 #define dh_is_signed_i32 0
 #define dh_is_signed_s32 1
 #define dh_is_signed_i64 0
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 5831e37..ad11767 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -194,11 +194,11 @@
 
     void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp)
     {
-        GenericList *i;
+        GenericList *i, **prev = (GenericList **)obj;
 
         visit_start_list(m, name, errp);
 
-        for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
+        for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) {
             UserDefOneList *native_i = (UserDefOneList *)i;
             visit_type_UserDefOne(m, &native_i->value, NULL, errp);
         }
diff --git a/elf.h b/elf.h
index 2e05d34..36bcac4 100644
--- a/elf.h
+++ b/elf.h
@@ -216,6 +216,7 @@
 
 #define ELF_ST_BIND(x)		((x) >> 4)
 #define ELF_ST_TYPE(x)		(((unsigned int) x) & 0xf)
+#define ELF_ST_INFO(bind, type) (((bind) << 4) | ((type) & 0xf))
 #define ELF32_ST_BIND(x)	ELF_ST_BIND(x)
 #define ELF32_ST_TYPE(x)	ELF_ST_TYPE(x)
 #define ELF64_ST_BIND(x)	ELF_ST_BIND(x)
@@ -345,6 +346,21 @@
 #define R_MIPS_HIVENDOR		127
 
 
+/* SUN SPARC specific definitions.  */
+
+/* Values for Elf64_Ehdr.e_flags.  */
+
+#define EF_SPARCV9_MM           3
+#define EF_SPARCV9_TSO          0
+#define EF_SPARCV9_PSO          1
+#define EF_SPARCV9_RMO          2
+#define EF_SPARC_LEDATA         0x800000 /* little endian data */
+#define EF_SPARC_EXT_MASK       0xFFFF00
+#define EF_SPARC_32PLUS         0x000100 /* generic V8+ features */
+#define EF_SPARC_SUN_US1        0x000200 /* Sun UltraSPARC1 extensions */
+#define EF_SPARC_HAL_R1         0x000400 /* HAL R1 extensions */
+#define EF_SPARC_SUN_US3        0x000800 /* Sun UltraSPARCIII extensions */
+
 /*
  * Sparc ELF relocation types
  */
diff --git a/exec.c b/exec.c
index 265e895..6731ab8 100644
--- a/exec.c
+++ b/exec.c
@@ -636,6 +636,7 @@
     cpu_gen_init();
     code_gen_alloc(tb_size);
     code_gen_ptr = code_gen_buffer;
+    tcg_register_jit(code_gen_buffer, code_gen_buffer_size);
     page_init();
 #if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE)
     /* There's no guest base to take into account, so go ahead and
diff --git a/gdbstub.c b/gdbstub.c
index f4e97f7..6a7e2c4 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -284,7 +284,6 @@
     RS_GETLINE,
     RS_CHKSUM1,
     RS_CHKSUM2,
-    RS_SYSCALL,
 };
 typedef struct GDBState {
     CPUArchState *c_cpu; /* current CPU for step/continue ops */
@@ -304,6 +303,8 @@
     CharDriverState *chr;
     CharDriverState *mon_chr;
 #endif
+    char syscall_buf[256];
+    gdb_syscall_complete_cb current_syscall_cb;
 } GDBState;
 
 /* By default use no IRQs and no timers while single stepping so as to
@@ -346,8 +347,6 @@
 }
 #endif
 
-static gdb_syscall_complete_cb gdb_current_syscall_cb;
-
 static enum {
     GDB_SYS_UNKNOWN,
     GDB_SYS_ENABLED,
@@ -2097,8 +2096,10 @@
             if (*p == ',')
                 p++;
             type = *p;
-            if (gdb_current_syscall_cb)
-                gdb_current_syscall_cb(s->c_cpu, ret, err);
+            if (s->current_syscall_cb) {
+                s->current_syscall_cb(s->c_cpu, ret, err);
+                s->current_syscall_cb = NULL;
+            }
             if (type == 'C') {
                 put_packet(s, "T02");
             } else {
@@ -2398,7 +2399,12 @@
     const char *type;
     int ret;
 
-    if (running || s->state == RS_INACTIVE || s->state == RS_SYSCALL) {
+    if (running || s->state == RS_INACTIVE) {
+        return;
+    }
+    /* Is there a GDB syscall waiting to be sent?  */
+    if (s->current_syscall_cb) {
+        put_packet(s, s->syscall_buf);
         return;
     }
     switch (state) {
@@ -2468,8 +2474,8 @@
 void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
 {
     va_list va;
-    char buf[256];
     char *p;
+    char *p_end;
     target_ulong addr;
     uint64_t i64;
     GDBState *s;
@@ -2477,14 +2483,13 @@
     s = gdbserver_state;
     if (!s)
         return;
-    gdb_current_syscall_cb = cb;
-    s->state = RS_SYSCALL;
+    s->current_syscall_cb = cb;
 #ifndef CONFIG_USER_ONLY
     vm_stop(RUN_STATE_DEBUG);
 #endif
-    s->state = RS_IDLE;
     va_start(va, fmt);
-    p = buf;
+    p = s->syscall_buf;
+    p_end = &s->syscall_buf[sizeof(s->syscall_buf)];
     *(p++) = 'F';
     while (*fmt) {
         if (*fmt == '%') {
@@ -2492,17 +2497,17 @@
             switch (*fmt++) {
             case 'x':
                 addr = va_arg(va, target_ulong);
-                p += snprintf(p, &buf[sizeof(buf)] - p, TARGET_FMT_lx, addr);
+                p += snprintf(p, p_end - p, TARGET_FMT_lx, addr);
                 break;
             case 'l':
                 if (*(fmt++) != 'x')
                     goto bad_format;
                 i64 = va_arg(va, uint64_t);
-                p += snprintf(p, &buf[sizeof(buf)] - p, "%" PRIx64, i64);
+                p += snprintf(p, p_end - p, "%" PRIx64, i64);
                 break;
             case 's':
                 addr = va_arg(va, target_ulong);
-                p += snprintf(p, &buf[sizeof(buf)] - p, TARGET_FMT_lx "/%x",
+                p += snprintf(p, p_end - p, TARGET_FMT_lx "/%x",
                               addr, va_arg(va, int));
                 break;
             default:
@@ -2517,10 +2522,16 @@
     }
     *p = 0;
     va_end(va);
-    put_packet(s, buf);
 #ifdef CONFIG_USER_ONLY
+    put_packet(s, s->syscall_buf);
     gdb_handlesig(s->c_cpu, 0);
 #else
+    /* In this case wait to send the syscall packet until notification that
+       the CPU has stopped.  This must be done because if the packet is sent
+       now the reply from the syscall request could be received while the CPU
+       is still in the running state, which can cause packets to be dropped
+       and state transition 'T' packets to be sent while the syscall is still
+       being processed.  */
     cpu_exit(s->c_cpu);
 #endif
 }
@@ -2919,6 +2930,7 @@
     s->chr = chr;
     s->state = chr ? RS_IDLE : RS_INACTIVE;
     s->mon_chr = mon_chr;
+    s->current_syscall_cb = NULL;
 
     return 0;
 }
diff --git a/hw/blizzard.c b/hw/blizzard.c
index c7d844d..29074c4 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -937,9 +937,7 @@
 {
     BlizzardState *s = (BlizzardState *) opaque;
 
-    if (cswitch) {
-        blizzard_update_display(opaque);
-    }
+    blizzard_update_display(opaque);
     if (s && ds_get_data(s->state))
         ppm_save(filename, s->state->surface);
 }
diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index f172093..4a08e9d 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -267,9 +267,8 @@
 static void omap_screen_dump(void *opaque, const char *filename, bool cswitch)
 {
     struct omap_lcd_panel_s *omap_lcd = opaque;
-    if (cswitch) {
-        omap_update_display(opaque);
-    }
+
+    omap_update_display(opaque);
     if (omap_lcd && ds_get_data(omap_lcd->state))
         ppm_save(filename, ds_get_data(omap_lcd->state),
                 omap_lcd->width, omap_lcd->height,
diff --git a/hw/vga.c b/hw/vga.c
index 6dc98f6..f80860c 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2415,7 +2415,7 @@
 
     if (cswitch) {
         vga_invalidate_display(s);
-        vga_hw_update();
     }
+    vga_hw_update();
     ppm_save(filename, s->ds->surface);
 }
diff --git a/hw/xen_console.c b/hw/xen_console.c
index edcb31c..3794b19 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -248,6 +248,9 @@
 {
     struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
 
+    if (!xendev->dev) {
+        return;
+    }
     if (con->chr)
         qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
     xen_be_unbind_evtchn(&con->xendev);
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 9cb0253..9719395 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -726,6 +726,7 @@
         if (!blkdev->dinfo) {
             /* close/delete only if we created it ourself */
             bdrv_close(blkdev->bs);
+            bdrv_detach_dev(blkdev->bs, blkdev);
             bdrv_delete(blkdev->bs);
         }
         blkdev->bs = NULL;
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index bdc3c79..802cae3 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -682,8 +682,19 @@
     SECMODModule *module = (SECMODModule *)arg;
 
     do {
+        /*
+         * XXX - the latency value doesn't matter one bit. you only get no
+         * blocking (flags |= CKF_DONT_BLOCK) or PKCS11_WAIT_LATENCY (==500),
+         * hard coded in coolkey.  And it isn't coolkey's fault - the timeout
+         * value we pass get's dropped on the floor before C_WaitForSlotEvent
+         * is called.
+         */
         slot = SECMOD_WaitForAnyTokenEvent(module, 0, 500);
         if (slot == NULL) {
+            /* this could be just a no event indication */
+            if (PORT_GetError() == SEC_ERROR_NO_EVENT) {
+                continue;
+            }
             break;
         }
         vreader = vcard_emul_find_vreader_from_slot(slot);
@@ -994,10 +1005,10 @@
     SECMOD_GetReadLock(module_lock);
     for (mlp = module_list; mlp; mlp = mlp->next) {
         SECMODModule *module = mlp->module;
-        PRBool has_emul_slots = PR_FALSE;
 
-        if (module == NULL) {
-                continue;
+        /* Ignore the internal module */
+        if (module == NULL || module == SECMOD_GetInternalModule()) {
+            continue;
         }
 
         for (i = 0; i < module->slotCount; i++) {
@@ -1007,15 +1018,22 @@
             if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) {
                 continue;
             }
+            if (strcmp("E-Gate 0 0", PK11_GetSlotName(slot)) == 0) {
+                /*
+                 * coolkey <= 1.1.0-20 emulates this reader if it can't find
+                 * any hardware readers. This causes problems, warn user of
+                 * problems.
+                 */
+                fprintf(stderr, "known bad coolkey version - see "
+                        "https://bugzilla.redhat.com/show_bug.cgi?id=802435\n");
+                continue;
+            }
             vreader_emul = vreader_emul_new(slot, options->hw_card_type,
                                             options->hw_type_params);
             vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
                                   vreader_emul_delete);
             vreader_add_reader(vreader);
 
-            has_readers = PR_TRUE;
-            has_emul_slots = PR_TRUE;
-
             if (PK11_IsPresent(slot)) {
                 VCard *vcard;
                 vcard = vcard_emul_mirror_card(vreader);
@@ -1024,12 +1042,10 @@
                 vcard_free(vcard);
             }
         }
-        if (has_emul_slots) {
-            vcard_emul_new_event_thread(module);
-        }
+        vcard_emul_new_event_thread(module);
     }
     SECMOD_ReleaseReadLock(module_lock);
-    nss_emul_init = has_readers;
+    nss_emul_init = PR_TRUE;
 
     return VCARD_EMUL_OK;
 }
diff --git a/monitor.c b/monitor.c
index 2ff1e0b..8946a10 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4157,6 +4157,9 @@
         case 'O':
             assert(flags & QMP_ACCEPT_UNKNOWNS);
             break;
+        case 'q':
+            /* Any QObject can be passed.  */
+            break;
         case '/':
         case '.':
             /*
diff --git a/qapi-schema-test.json b/qapi-schema-test.json
index 8c7f9f7..9eae350 100644
--- a/qapi-schema-test.json
+++ b/qapi-schema-test.json
@@ -8,7 +8,7 @@
 
 # for testing nested structs
 { 'type': 'UserDefOne',
-  'data': { 'integer': 'int', 'string': 'str' } }
+  'data': { 'integer': 'int', 'string': 'str', '*enum1': 'EnumOne' } }
 
 { 'type': 'UserDefTwo',
   'data': { 'string': 'str',
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index e6b6152..74386b9 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -22,16 +22,17 @@
 
 typedef struct StackObject
 {
-    const QObject *obj;
-    const  QListEntry *entry;
+    QObject *obj;
+    const QListEntry *entry;
+    GHashTable *h;
 } StackObject;
 
 struct QmpInputVisitor
 {
     Visitor visitor;
-    QObject *obj;
     StackObject stack[QIV_STACK_SIZE];
     int nb_stack;
+    bool strict;
 };
 
 static QmpInputVisitor *to_qiv(Visitor *v)
@@ -39,21 +40,18 @@
     return container_of(v, QmpInputVisitor, visitor);
 }
 
-static const QObject *qmp_input_get_object(QmpInputVisitor *qiv,
-                                           const char *name)
+static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
+                                     const char *name)
 {
-    const QObject *qobj;
-
-    if (qiv->nb_stack == 0) {
-        qobj = qiv->obj;
-    } else {
-        qobj = qiv->stack[qiv->nb_stack - 1].obj;
-    }
+    QObject *qobj = qiv->stack[qiv->nb_stack - 1].obj;
 
     if (qobj) {
         if (name && qobject_type(qobj) == QTYPE_QDICT) {
+            if (qiv->stack[qiv->nb_stack - 1].h) {
+                g_hash_table_remove(qiv->stack[qiv->nb_stack - 1].h, name);
+            }
             return qdict_get(qobject_to_qdict(qobj), name);
-        } else if (qiv->nb_stack > 0 && qobject_type(qobj) == QTYPE_QLIST) {
+        } else if (qiv->stack[qiv->nb_stack - 1].entry) {
             return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry);
         }
     }
@@ -61,34 +59,57 @@
     return qobj;
 }
 
-static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **errp)
+static void qdict_add_key(const char *key, QObject *obj, void *opaque)
 {
-    qiv->stack[qiv->nb_stack].obj = obj;
-    if (qobject_type(obj) == QTYPE_QLIST) {
-        qiv->stack[qiv->nb_stack].entry = qlist_first(qobject_to_qlist(obj));
-    }
-    qiv->nb_stack++;
+    GHashTable *h = opaque;
+    g_hash_table_insert(h, (gpointer) key, NULL);
+}
+
+static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp)
+{
+    GHashTable *h;
 
     if (qiv->nb_stack >= QIV_STACK_SIZE) {
         error_set(errp, QERR_BUFFER_OVERRUN);
         return;
     }
+
+    qiv->stack[qiv->nb_stack].obj = obj;
+    qiv->stack[qiv->nb_stack].entry = NULL;
+    qiv->stack[qiv->nb_stack].h = NULL;
+
+    if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
+        h = g_hash_table_new(g_str_hash, g_str_equal);
+        qdict_iter(qobject_to_qdict(obj), qdict_add_key, h);
+        qiv->stack[qiv->nb_stack].h = h;
+    }
+
+    qiv->nb_stack++;
 }
 
 static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
 {
-    qiv->nb_stack--;
-    if (qiv->nb_stack < 0) {
-        error_set(errp, QERR_BUFFER_OVERRUN);
-        return;
+    GHashTableIter iter;
+    gpointer key;
+
+    if (qiv->strict && qiv->stack[qiv->nb_stack - 1].h) {
+        g_hash_table_iter_init(&iter, qiv->stack[qiv->nb_stack - 1].h);
+        if (g_hash_table_iter_next(&iter, &key, NULL)) {
+            error_set(errp, QERR_QMP_EXTRA_MEMBER, (char *) key);
+        }
+        g_hash_table_unref(qiv->stack[qiv->nb_stack - 1].h);
     }
+
+    assert(qiv->nb_stack > 0);
+    qiv->nb_stack--;
 }
 
 static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind,
                                    const char *name, size_t size, Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
+    Error *err = NULL;
 
     if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -96,8 +117,9 @@
         return;
     }
 
-    qmp_input_push(qiv, qobj, errp);
-    if (error_is_set(errp)) {
+    qmp_input_push(qiv, qobj, &err);
+    if (err) {
+        error_propagate(errp, err);
         return;
     }
 
@@ -116,7 +138,7 @@
 static void qmp_input_start_list(Visitor *v, const char *name, Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
 
     if (!qobj || qobject_type(qobj) != QTYPE_QLIST) {
         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -133,18 +155,24 @@
     QmpInputVisitor *qiv = to_qiv(v);
     GenericList *entry;
     StackObject *so = &qiv->stack[qiv->nb_stack - 1];
+    bool first;
+
+    if (so->entry == NULL) {
+        so->entry = qlist_first(qobject_to_qlist(so->obj));
+        first = true;
+    } else {
+        so->entry = qlist_next(so->entry);
+        first = false;
+    }
 
     if (so->entry == NULL) {
         return NULL;
     }
 
     entry = g_malloc0(sizeof(*entry));
-    if (*list) {
-        so->entry = qlist_next(so->entry);
-        if (so->entry == NULL) {
-            g_free(entry);
-            return NULL;
-        }
+    if (first) {
+        *list = entry;
+    } else {
         (*list)->next = entry;
     }
 
@@ -162,7 +190,7 @@
                                Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
 
     if (!qobj || qobject_type(qobj) != QTYPE_QINT) {
         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -177,7 +205,7 @@
                                 Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
 
     if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) {
         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -192,7 +220,7 @@
                                Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
 
     if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) {
         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -207,7 +235,7 @@
                                   Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
 
     if (!qobj || qobject_type(qobj) != QTYPE_QFLOAT) {
         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -222,7 +250,7 @@
                                      const char *name, Error **errp)
 {
     QmpInputVisitor *qiv = to_qiv(v);
-    const QObject *qobj = qmp_input_get_object(qiv, name);
+    QObject *qobj = qmp_input_get_object(qiv, name);
 
     if (!qobj) {
         *present = false;
@@ -239,7 +267,7 @@
 
 void qmp_input_visitor_cleanup(QmpInputVisitor *v)
 {
-    qobject_decref(v->obj);
+    qobject_decref(v->stack[0].obj);
     g_free(v);
 }
 
@@ -261,8 +289,18 @@
     v->visitor.type_number = qmp_input_type_number;
     v->visitor.start_optional = qmp_input_start_optional;
 
-    v->obj = obj;
-    qobject_incref(v->obj);
+    qmp_input_push(v, obj, NULL);
+    qobject_incref(obj);
+
+    return v;
+}
+
+QmpInputVisitor *qmp_input_visitor_new_strict(QObject *obj)
+{
+    QmpInputVisitor *v;
+
+    v = qmp_input_visitor_new(obj);
+    v->strict = true;
 
     return v;
 }
diff --git a/qapi/qmp-input-visitor.h b/qapi/qmp-input-visitor.h
index 3f798f0..e0a48a5 100644
--- a/qapi/qmp-input-visitor.h
+++ b/qapi/qmp-input-visitor.h
@@ -20,6 +20,8 @@
 typedef struct QmpInputVisitor QmpInputVisitor;
 
 QmpInputVisitor *qmp_input_visitor_new(QObject *obj);
+QmpInputVisitor *qmp_input_visitor_new_strict(QObject *obj);
+
 void qmp_input_visitor_cleanup(QmpInputVisitor *v);
 
 Visitor *qmp_input_get_visitor(QmpInputVisitor *v);
diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
index e0697b0..2bce9d5 100644
--- a/qapi/qmp-output-visitor.c
+++ b/qapi/qmp-output-visitor.c
@@ -199,14 +199,16 @@
 {
     QStackEntry *e, *tmp;
 
+    /* The bottom QStackEntry, if any, owns the root QObject. See the
+     * qmp_output_push_obj() invocations in qmp_output_add_obj(). */
+    QObject *root = QTAILQ_EMPTY(&v->stack) ? NULL : qmp_output_first(v);
+
     QTAILQ_FOREACH_SAFE(e, &v->stack, node, tmp) {
         QTAILQ_REMOVE(&v->stack, e, node);
-        if (e->value) {
-            qobject_decref(e->value);
-        }
         g_free(e);
     }
 
+    qobject_decref(root);
     g_free(v);
 }
 
diff --git a/qemu-options.hx b/qemu-options.hx
index daefce3..662f571 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -288,13 +288,21 @@
 ETEXI
 
 DEF("global", HAS_ARG, QEMU_OPTION_global,
-    "-global driver.property=value\n"
+    "-global driver.prop=value\n"
     "                set a global default for a driver property\n",
     QEMU_ARCH_ALL)
 STEXI
-@item -global
+@item -global @var{driver}.@var{prop}=@var{value}
 @findex -global
-TODO
+Set default value of @var{driver}'s property @var{prop} to @var{value}, e.g.:
+
+@example
+qemu -global ide-drive.physical_block_size=4096 -drive file=file,if=ide,index=0,media=disk
+@end example
+
+In particular, you can use this to set driver properties for devices which are 
+created automatically by the machine model. To create a device which is not 
+created automatically and set properties on it, use -@option{device}.
 ETEXI
 
 DEF("mtdblock", HAS_ARG, QEMU_OPTION_mtdblock,
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 7b2be2f..faf970d 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -12,29 +12,30 @@
  */
 
 #include <glib.h>
-
-#if defined(__linux__)
-#include <mntent.h>
-#include <linux/fs.h>
-
-#if defined(__linux__) && defined(FIFREEZE)
-#define CONFIG_FSFREEZE
-#endif
-#endif
-
 #include <sys/types.h>
 #include <sys/ioctl.h>
-#include <ifaddrs.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <sys/wait.h>
 #include "qga/guest-agent-core.h"
 #include "qga-qmp-commands.h"
 #include "qerror.h"
 #include "qemu-queue.h"
 #include "host-utils.h"
 
+#if defined(__linux__)
+#include <mntent.h>
+#include <linux/fs.h>
+#include <ifaddrs.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/wait.h>
+
+#if defined(__linux__) && defined(FIFREEZE)
+#define CONFIG_FSFREEZE
+#endif
+#endif
+
+#if defined(__linux__)
+/* TODO: use this in place of all post-fork() fclose(std*) callers */
 static void reopen_fd_to_null(int fd)
 {
     int nullfd;
@@ -50,6 +51,7 @@
         close(nullfd);
     }
 }
+#endif /* defined(__linux__) */
 
 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
 {
@@ -309,7 +311,11 @@
     QTAILQ_INIT(&guest_file_state.filehandles);
 }
 
+/* linux-specific implementations. avoid this if at all possible. */
+#if defined(__linux__)
+
 #if defined(CONFIG_FSFREEZE)
+
 static void disable_logging(void)
 {
     ga_disable_logging(ga_state);
@@ -505,38 +511,7 @@
         }
     }
 }
-#else
-/*
- * Return status of freeze/thaw
- */
-GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
-{
-    error_set(err, QERR_UNSUPPORTED);
-
-    return 0;
-}
-
-/*
- * Walk list of mounted file systems in the guest, and freeze the ones which
- * are real local file systems.
- */
-int64_t qmp_guest_fsfreeze_freeze(Error **err)
-{
-    error_set(err, QERR_UNSUPPORTED);
-
-    return 0;
-}
-
-/*
- * Walk list of frozen file systems in the guest, and thaw them.
- */
-int64_t qmp_guest_fsfreeze_thaw(Error **err)
-{
-    error_set(err, QERR_UNSUPPORTED);
-
-    return 0;
-}
-#endif
+#endif /* CONFIG_FSFREEZE */
 
 #define LINUX_SYS_STATE_FILE "/sys/power/state"
 #define SUSPEND_SUPPORTED 0
@@ -904,6 +879,52 @@
     return NULL;
 }
 
+#else /* defined(__linux__) */
+
+GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+
+    return 0;
+}
+
+int64_t qmp_guest_fsfreeze_freeze(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+
+    return 0;
+}
+
+int64_t qmp_guest_fsfreeze_thaw(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+
+    return 0;
+}
+
+void qmp_guest_suspend_disk(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+}
+
+void qmp_guest_suspend_ram(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+}
+
+void qmp_guest_suspend_hybrid(Error **err)
+{
+    error_set(err, QERR_UNSUPPORTED);
+}
+
+GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+    return NULL;
+}
+
+#endif
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
diff --git a/qmp-commands.hx b/qmp-commands.hx
index c626ba8..9447871 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -708,7 +708,7 @@
     },
     {
         .name       = "transaction",
-        .args_type  = "actions:O",
+        .args_type  = "actions:q",
         .mhandler.cmd_new = qmp_marshal_input_transaction,
     },
 
@@ -2125,7 +2125,7 @@
 
     {
         .name       = "qom-set",
-	.args_type  = "path:s,property:s,opts:O",
+	.args_type  = "path:s,property:s,value:q",
 	.mhandler.cmd_new = qmp_qom_set,
     },
 
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 3aabf61..0b4f0a0 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -42,7 +42,7 @@
     return mcgen('''
 %(ret_type)s qmp_%(name)s(%(args)sError **errp);
 ''',
-                 ret_type=c_type(ret_type), name=c_var(name), args=arglist).strip()
+                 ret_type=c_type(ret_type), name=c_fun(name), args=arglist).strip()
 
 def gen_sync_call(name, args, ret_type, indent=0):
     ret = ""
@@ -59,7 +59,7 @@
 %(retval)sqmp_%(name)s(%(args)serrp);
 
 ''',
-                name=c_var(name), args=arglist, retval=retval).rstrip()
+                name=c_fun(name), args=arglist, retval=retval).rstrip()
     if ret_type:
         ret += "\n" + mcgen(''''
 if (!error_is_set(errp)) {
@@ -74,7 +74,7 @@
 def gen_marshal_output_call(name, ret_type):
     if not ret_type:
         return ""
-    return "qmp_marshal_output_%s(retval, ret, errp);" % c_var(name)
+    return "qmp_marshal_output_%s(retval, ret, errp);" % c_fun(name)
 
 def gen_visitor_output_containers_decl(ret_type):
     ret = ""
@@ -140,7 +140,7 @@
 ''')
     else:
         ret += mcgen('''
-mi = qmp_input_visitor_new(%(obj)s);
+mi = qmp_input_visitor_new_strict(%(obj)s);
 v = qmp_input_get_visitor(mi);
 ''',
                      obj=obj)
@@ -198,16 +198,16 @@
     qapi_dealloc_visitor_cleanup(md);
 }
 ''',
-                c_ret_type=c_type(ret_type), c_name=c_var(name),
+                c_ret_type=c_type(ret_type), c_name=c_fun(name),
                 visitor=type_visitor(ret_type))
 
     return ret
 
 def gen_marshal_input_decl(name, args, ret_type, middle_mode):
     if middle_mode:
-        return 'int qmp_marshal_input_%s(Monitor *mon, const QDict *qdict, QObject **ret)' % c_var(name)
+        return 'int qmp_marshal_input_%s(Monitor *mon, const QDict *qdict, QObject **ret)' % c_fun(name)
     else:
-        return 'static void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_var(name)
+        return 'static void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_fun(name)
 
 
 
@@ -298,7 +298,7 @@
         registry += mcgen('''
 qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s);
 ''',
-                     name=cmd['command'], c_name=c_var(cmd['command']))
+                     name=cmd['command'], c_name=c_fun(cmd['command']))
     pop_indent()
     ret = mcgen('''
 static void qmp_init_marshal(void)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 727fb77..4a734f5 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -100,7 +100,7 @@
     %(abbrev)s_%(value)s = %(i)d,
 ''',
                      abbrev=de_camel_case(name).upper(),
-                     value=c_var(value).upper(),
+                     value=c_fun(value).upper(),
                      i=i)
         i += 1
 
@@ -126,7 +126,7 @@
         %(c_type)s %(c_name)s;
 ''',
                      c_type=c_type(typeinfo[key]),
-                     c_name=c_var(key))
+                     c_name=c_fun(key))
 
     ret += mcgen('''
     };
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 54117d4..8d4e94a 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -61,7 +61,13 @@
 
 void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
 {
+    if (error_is_set(errp)) {
+        return;
+    }
     visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), errp);
+    if (obj && !*obj) {
+        goto end;
+    }
 ''',
                 name=name)
     push_indent()
@@ -69,6 +75,7 @@
     pop_indent()
 
     ret += mcgen('''
+end:
     visit_end_struct(m, errp);
 }
 ''')
@@ -79,11 +86,14 @@
 
 void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp)
 {
-    GenericList *i, **head = (GenericList **)obj;
+    GenericList *i, **prev = (GenericList **)obj;
 
+    if (error_is_set(errp)) {
+        return;
+    }
     visit_start_list(m, name, errp);
 
-    for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
+    for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) {
         %(name)sList *native_i = (%(name)sList *)i;
         visit_type_%(name)s(m, &native_i->value, NULL, errp);
     }
@@ -112,7 +122,13 @@
 {
     Error *err = NULL;
 
+    if (error_is_set(errp)) {
+        return;
+    }
     visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
+    if (obj && !*obj) {
+        goto end;
+    }
     visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err);
     if (err) {
         error_propagate(errp, err);
@@ -129,9 +145,9 @@
         break;
 ''',
                 abbrev = de_camel_case(name).upper(),
-                enum = de_camel_case(key).upper(),
+                enum = c_fun(de_camel_case(key)).upper(),
                 c_type=members[key],
-                c_name=c_var(key))
+                c_name=c_fun(key))
 
     ret += mcgen('''
     default:
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 6e05469..e062336 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -131,7 +131,10 @@
     return new_name
 
 def c_var(name):
-    return '_'.join(name.split('-')).lstrip("*")
+    return name.replace('-', '_').lstrip("*")
+
+def c_fun(name):
+    return c_var(name).replace('.', '_')
 
 def c_list_type(name):
     return '%sList' % name
diff --git a/scripts/qemu-gdb.py b/scripts/qemu-gdb.py
new file mode 100644
index 0000000..8a0f305
--- /dev/null
+++ b/scripts/qemu-gdb.py
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+
+# GDB debugging support
+#
+# Copyright 2012 Red Hat, Inc. and/or its affiliates
+#
+# Authors:
+#  Avi Kivity <avi@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+#
+# Contributions after 2012-01-13 are licensed under the terms of the
+# GNU GPL, version 2 or (at your option) any later version.
+
+
+import gdb
+
+def isnull(ptr):
+    return ptr == gdb.Value(0).cast(ptr.type)
+
+def int128(p):
+    return long(p['lo']) + (long(p['hi']) << 64)
+
+class QemuCommand(gdb.Command):
+    '''Prefix for QEMU debug support commands'''
+    def __init__(self):
+        gdb.Command.__init__(self, 'qemu', gdb.COMMAND_DATA,
+                             gdb.COMPLETE_NONE, True)
+
+class MtreeCommand(gdb.Command):
+    '''Display the memory tree hierarchy'''
+    def __init__(self):
+        gdb.Command.__init__(self, 'qemu mtree', gdb.COMMAND_DATA,
+                             gdb.COMPLETE_NONE)
+        self.queue = []
+    def invoke(self, arg, from_tty):
+        self.seen = set()
+        self.queue_root('address_space_memory')
+        self.queue_root('address_space_io')
+        self.process_queue()
+    def queue_root(self, varname):
+        ptr = gdb.parse_and_eval(varname)['root']
+        self.queue.append(ptr)
+    def process_queue(self):
+        while self.queue:
+            ptr = self.queue.pop(0)
+            if long(ptr) in self.seen:
+                continue
+            self.print_item(ptr)
+    def print_item(self, ptr, offset = gdb.Value(0), level = 0):
+        self.seen.add(long(ptr))
+        addr = ptr['addr']
+        addr += offset
+        size = int128(ptr['size'])
+        alias = ptr['alias']
+        klass = ''
+        if not isnull(alias):
+            klass = ' (alias)'
+        elif not isnull(ptr['ops']):
+            klass = ' (I/O)'
+        elif bool(ptr['ram']):
+            klass = ' (RAM)'
+        gdb.write('%s%016x-%016x %s%s (@ %s)\n'
+                  % ('  ' * level,
+                     long(addr),
+                     long(addr + (size - 1)),
+                     ptr['name'].string(),
+                     klass,
+                     ptr,
+                     ),
+                  gdb.STDOUT)
+        if not isnull(alias):
+            gdb.write('%s    alias: %s@%016x (@ %s)\n' %
+                      ('  ' * level,
+                       alias['name'].string(),
+                       ptr['alias_offset'],
+                       alias,
+                       ),
+                      gdb.STDOUT)
+            self.queue.append(alias)
+        subregion = ptr['subregions']['tqh_first']
+        level += 1
+        while not isnull(subregion):
+            self.print_item(subregion, addr, level)
+            subregion = subregion['subregions_link']['tqe_next']
+
+QemuCommand()
+MtreeCommand()
diff --git a/scripts/texi2pod.pl b/scripts/texi2pod.pl
index 9ed056a..94097fb 100755
--- a/scripts/texi2pod.pl
+++ b/scripts/texi2pod.pl
@@ -36,6 +36,7 @@
 $inf = "";
 $ibase = "";
 @ipath = ();
+$encoding = undef;
 
 while ($_ = shift) {
     if (/^-D(.*)$/) {
@@ -97,6 +98,12 @@
     /^\@setfilename\s+([^.]+)/ and $fn = $1, next;
     /^\@settitle\s+([^.]+)/ and $tl = postprocess($1), next;
 
+    # Look for document encoding
+    /^\@documentencoding\s+([^.]+)/ and do {
+        $encoding = $1 unless defined $encoding;
+        next;
+    };
+
     # Identify a man title but keep only the one we are interested in.
     /^\@c\s+man\s+title\s+([A-Za-z0-9-]+)\s+(.+)/ and do {
 	if (exists $defs{$1}) {
@@ -336,6 +343,8 @@
 
 die "No filename or title\n" unless defined $fn && defined $tl;
 
+print "=encoding $encoding\n\n" if defined $encoding;
+
 $sects{NAME} = "$fn \- $tl\n";
 $sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES};
 
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 48c0fdc..6c5d28b 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -234,7 +234,6 @@
     uint8_t fpcr_exc_mask;
     uint8_t fpcr_dyn_round;
     uint8_t fpcr_flush_to_zero;
-    uint8_t fpcr_dnz;
     uint8_t fpcr_dnod;
     uint8_t fpcr_undz;
 
@@ -434,6 +433,9 @@
                                 int mmu_idx);
 #define cpu_handle_mmu_fault cpu_alpha_handle_mmu_fault
 void do_interrupt (CPUAlphaState *env);
+void do_restore_state(CPUAlphaState *, void *retaddr);
+void QEMU_NORETURN dynamic_excp(CPUAlphaState *, void *, int, int);
+void QEMU_NORETURN arith_excp(CPUAlphaState *, void *, int, uint64_t);
 
 uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env);
 void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val);
diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
new file mode 100644
index 0000000..dda1103
--- /dev/null
+++ b/target-alpha/fpu_helper.c
@@ -0,0 +1,822 @@
+/*
+ *  Helpers for floating point instructions.
+ *
+ *  Copyright (c) 2007 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "softfloat.h"
+
+#define FP_STATUS (env->fp_status)
+
+
+void helper_setroundmode(CPUAlphaState *env, uint32_t val)
+{
+    set_float_rounding_mode(val, &FP_STATUS);
+}
+
+void helper_setflushzero(CPUAlphaState *env, uint32_t val)
+{
+    set_flush_to_zero(val, &FP_STATUS);
+}
+
+void helper_fp_exc_clear(CPUAlphaState *env)
+{
+    set_float_exception_flags(0, &FP_STATUS);
+}
+
+uint32_t helper_fp_exc_get(CPUAlphaState *env)
+{
+    return get_float_exception_flags(&FP_STATUS);
+}
+
+static inline void inline_fp_exc_raise(CPUAlphaState *env, void *retaddr,
+                                       uint32_t exc, uint32_t regno)
+{
+    if (exc) {
+        uint32_t hw_exc = 0;
+
+        if (exc & float_flag_invalid) {
+            hw_exc |= EXC_M_INV;
+        }
+        if (exc & float_flag_divbyzero) {
+            hw_exc |= EXC_M_DZE;
+        }
+        if (exc & float_flag_overflow) {
+            hw_exc |= EXC_M_FOV;
+        }
+        if (exc & float_flag_underflow) {
+            hw_exc |= EXC_M_UNF;
+        }
+        if (exc & float_flag_inexact) {
+            hw_exc |= EXC_M_INE;
+        }
+
+        arith_excp(env, retaddr, hw_exc, 1ull << regno);
+    }
+}
+
+/* Raise exceptions for ieee fp insns without software completion.
+   In that case there are no exceptions that don't trap; the mask
+   doesn't apply.  */
+void helper_fp_exc_raise(CPUAlphaState *env, uint32_t exc, uint32_t regno)
+{
+    inline_fp_exc_raise(env, GETPC(), exc, regno);
+}
+
+/* Raise exceptions for ieee fp insns with software completion.  */
+void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t exc, uint32_t regno)
+{
+    if (exc) {
+        env->fpcr_exc_status |= exc;
+        exc &= ~env->fpcr_exc_mask;
+        inline_fp_exc_raise(env, GETPC(), exc, regno);
+    }
+}
+
+/* Input handing without software completion.  Trap for all
+   non-finite numbers.  */
+void helper_ieee_input(CPUAlphaState *env, uint64_t val)
+{
+    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
+    uint64_t frac = val & 0xfffffffffffffull;
+
+    if (exp == 0) {
+        /* Denormals without DNZ set raise an exception.  */
+        if (frac != 0 && !env->fp_status.flush_inputs_to_zero) {
+            arith_excp(env, GETPC(), EXC_M_UNF, 0);
+        }
+    } else if (exp == 0x7ff) {
+        /* Infinity or NaN.  */
+        /* ??? I'm not sure these exception bit flags are correct.  I do
+           know that the Linux kernel, at least, doesn't rely on them and
+           just emulates the insn to figure out what exception to use.  */
+        arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0);
+    }
+}
+
+/* Similar, but does not trap for infinities.  Used for comparisons.  */
+void helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
+{
+    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
+    uint64_t frac = val & 0xfffffffffffffull;
+
+    if (exp == 0) {
+        /* Denormals without DNZ set raise an exception.  */
+        if (frac != 0 && !env->fp_status.flush_inputs_to_zero) {
+            arith_excp(env, GETPC(), EXC_M_UNF, 0);
+        }
+    } else if (exp == 0x7ff && frac) {
+        /* NaN.  */
+        arith_excp(env, GETPC(), EXC_M_INV, 0);
+    }
+}
+
+/* F floating (VAX) */
+static uint64_t float32_to_f(float32 fa)
+{
+    uint64_t r, exp, mant, sig;
+    CPU_FloatU a;
+
+    a.f = fa;
+    sig = ((uint64_t)a.l & 0x80000000) << 32;
+    exp = (a.l >> 23) & 0xff;
+    mant = ((uint64_t)a.l & 0x007fffff) << 29;
+
+    if (exp == 255) {
+        /* NaN or infinity */
+        r = 1; /* VAX dirty zero */
+    } else if (exp == 0) {
+        if (mant == 0) {
+            /* Zero */
+            r = 0;
+        } else {
+            /* Denormalized */
+            r = sig | ((exp + 1) << 52) | mant;
+        }
+    } else {
+        if (exp >= 253) {
+            /* Overflow */
+            r = 1; /* VAX dirty zero */
+        } else {
+            r = sig | ((exp + 2) << 52);
+        }
+    }
+
+    return r;
+}
+
+static float32 f_to_float32(CPUAlphaState *env, void *retaddr, uint64_t a)
+{
+    uint32_t exp, mant_sig;
+    CPU_FloatU r;
+
+    exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
+    mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
+
+    if (unlikely(!exp && mant_sig)) {
+        /* Reserved operands / Dirty zero */
+        dynamic_excp(env, retaddr, EXCP_OPCDEC, 0);
+    }
+
+    if (exp < 3) {
+        /* Underflow */
+        r.l = 0;
+    } else {
+        r.l = ((exp - 2) << 23) | mant_sig;
+    }
+
+    return r.f;
+}
+
+uint32_t helper_f_to_memory(uint64_t a)
+{
+    uint32_t r;
+    r =  (a & 0x00001fffe0000000ull) >> 13;
+    r |= (a & 0x07ffe00000000000ull) >> 45;
+    r |= (a & 0xc000000000000000ull) >> 48;
+    return r;
+}
+
+uint64_t helper_memory_to_f(uint32_t a)
+{
+    uint64_t r;
+    r =  ((uint64_t)(a & 0x0000c000)) << 48;
+    r |= ((uint64_t)(a & 0x003fffff)) << 45;
+    r |= ((uint64_t)(a & 0xffff0000)) << 13;
+    if (!(a & 0x00004000)) {
+        r |= 0x7ll << 59;
+    }
+    return r;
+}
+
+/* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong.  We should
+   either implement VAX arithmetic properly or just signal invalid opcode.  */
+
+uint64_t helper_addf(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = f_to_float32(env, GETPC(), a);
+    fb = f_to_float32(env, GETPC(), b);
+    fr = float32_add(fa, fb, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+uint64_t helper_subf(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = f_to_float32(env, GETPC(), a);
+    fb = f_to_float32(env, GETPC(), b);
+    fr = float32_sub(fa, fb, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+uint64_t helper_mulf(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = f_to_float32(env, GETPC(), a);
+    fb = f_to_float32(env, GETPC(), b);
+    fr = float32_mul(fa, fb, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+uint64_t helper_divf(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = f_to_float32(env, GETPC(), a);
+    fb = f_to_float32(env, GETPC(), b);
+    fr = float32_div(fa, fb, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+uint64_t helper_sqrtf(CPUAlphaState *env, uint64_t t)
+{
+    float32 ft, fr;
+
+    ft = f_to_float32(env, GETPC(), t);
+    fr = float32_sqrt(ft, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+
+/* G floating (VAX) */
+static uint64_t float64_to_g(float64 fa)
+{
+    uint64_t r, exp, mant, sig;
+    CPU_DoubleU a;
+
+    a.d = fa;
+    sig = a.ll & 0x8000000000000000ull;
+    exp = (a.ll >> 52) & 0x7ff;
+    mant = a.ll & 0x000fffffffffffffull;
+
+    if (exp == 2047) {
+        /* NaN or infinity */
+        r = 1; /* VAX dirty zero */
+    } else if (exp == 0) {
+        if (mant == 0) {
+            /* Zero */
+            r = 0;
+        } else {
+            /* Denormalized */
+            r = sig | ((exp + 1) << 52) | mant;
+        }
+    } else {
+        if (exp >= 2045) {
+            /* Overflow */
+            r = 1; /* VAX dirty zero */
+        } else {
+            r = sig | ((exp + 2) << 52);
+        }
+    }
+
+    return r;
+}
+
+static float64 g_to_float64(CPUAlphaState *env, void *retaddr, uint64_t a)
+{
+    uint64_t exp, mant_sig;
+    CPU_DoubleU r;
+
+    exp = (a >> 52) & 0x7ff;
+    mant_sig = a & 0x800fffffffffffffull;
+
+    if (!exp && mant_sig) {
+        /* Reserved operands / Dirty zero */
+        dynamic_excp(env, retaddr, EXCP_OPCDEC, 0);
+    }
+
+    if (exp < 3) {
+        /* Underflow */
+        r.ll = 0;
+    } else {
+        r.ll = ((exp - 2) << 52) | mant_sig;
+    }
+
+    return r.d;
+}
+
+uint64_t helper_g_to_memory(uint64_t a)
+{
+    uint64_t r;
+    r =  (a & 0x000000000000ffffull) << 48;
+    r |= (a & 0x00000000ffff0000ull) << 16;
+    r |= (a & 0x0000ffff00000000ull) >> 16;
+    r |= (a & 0xffff000000000000ull) >> 48;
+    return r;
+}
+
+uint64_t helper_memory_to_g(uint64_t a)
+{
+    uint64_t r;
+    r =  (a & 0x000000000000ffffull) << 48;
+    r |= (a & 0x00000000ffff0000ull) << 16;
+    r |= (a & 0x0000ffff00000000ull) >> 16;
+    r |= (a & 0xffff000000000000ull) >> 48;
+    return r;
+}
+
+uint64_t helper_addg(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+    fr = float64_add(fa, fb, &FP_STATUS);
+    return float64_to_g(fr);
+}
+
+uint64_t helper_subg(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+    fr = float64_sub(fa, fb, &FP_STATUS);
+    return float64_to_g(fr);
+}
+
+uint64_t helper_mulg(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+    fr = float64_mul(fa, fb, &FP_STATUS);
+    return float64_to_g(fr);
+}
+
+uint64_t helper_divg(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+    fr = float64_div(fa, fb, &FP_STATUS);
+    return float64_to_g(fr);
+}
+
+uint64_t helper_sqrtg(CPUAlphaState *env, uint64_t a)
+{
+    float64 fa, fr;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fr = float64_sqrt(fa, &FP_STATUS);
+    return float64_to_g(fr);
+}
+
+
+/* S floating (single) */
+
+/* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg.  */
+static inline uint64_t float32_to_s_int(uint32_t fi)
+{
+    uint32_t frac = fi & 0x7fffff;
+    uint32_t sign = fi >> 31;
+    uint32_t exp_msb = (fi >> 30) & 1;
+    uint32_t exp_low = (fi >> 23) & 0x7f;
+    uint32_t exp;
+
+    exp = (exp_msb << 10) | exp_low;
+    if (exp_msb) {
+        if (exp_low == 0x7f) {
+            exp = 0x7ff;
+        }
+    } else {
+        if (exp_low != 0x00) {
+            exp |= 0x380;
+        }
+    }
+
+    return (((uint64_t)sign << 63)
+            | ((uint64_t)exp << 52)
+            | ((uint64_t)frac << 29));
+}
+
+static inline uint64_t float32_to_s(float32 fa)
+{
+    CPU_FloatU a;
+    a.f = fa;
+    return float32_to_s_int(a.l);
+}
+
+static inline uint32_t s_to_float32_int(uint64_t a)
+{
+    return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
+}
+
+static inline float32 s_to_float32(uint64_t a)
+{
+    CPU_FloatU r;
+    r.l = s_to_float32_int(a);
+    return r.f;
+}
+
+uint32_t helper_s_to_memory(uint64_t a)
+{
+    return s_to_float32_int(a);
+}
+
+uint64_t helper_memory_to_s(uint32_t a)
+{
+    return float32_to_s_int(a);
+}
+
+uint64_t helper_adds(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = s_to_float32(a);
+    fb = s_to_float32(b);
+    fr = float32_add(fa, fb, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+uint64_t helper_subs(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = s_to_float32(a);
+    fb = s_to_float32(b);
+    fr = float32_sub(fa, fb, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+uint64_t helper_muls(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = s_to_float32(a);
+    fb = s_to_float32(b);
+    fr = float32_mul(fa, fb, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+uint64_t helper_divs(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float32 fa, fb, fr;
+
+    fa = s_to_float32(a);
+    fb = s_to_float32(b);
+    fr = float32_div(fa, fb, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+uint64_t helper_sqrts(CPUAlphaState *env, uint64_t a)
+{
+    float32 fa, fr;
+
+    fa = s_to_float32(a);
+    fr = float32_sqrt(fa, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+
+/* T floating (double) */
+static inline float64 t_to_float64(uint64_t a)
+{
+    /* Memory format is the same as float64 */
+    CPU_DoubleU r;
+    r.ll = a;
+    return r.d;
+}
+
+static inline uint64_t float64_to_t(float64 fa)
+{
+    /* Memory format is the same as float64 */
+    CPU_DoubleU r;
+    r.d = fa;
+    return r.ll;
+}
+
+uint64_t helper_addt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+    fr = float64_add(fa, fb, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+uint64_t helper_subt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+    fr = float64_sub(fa, fb, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+uint64_t helper_mult(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+    fr = float64_mul(fa, fb, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+uint64_t helper_divt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb, fr;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+    fr = float64_div(fa, fb, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+uint64_t helper_sqrtt(CPUAlphaState *env, uint64_t a)
+{
+    float64 fa, fr;
+
+    fa = t_to_float64(a);
+    fr = float64_sqrt(fa, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+/* Comparisons */
+uint64_t helper_cmptun(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+
+    if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+uint64_t helper_cmpteq(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+
+    if (float64_eq_quiet(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+uint64_t helper_cmptle(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+
+    if (float64_le(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+uint64_t helper_cmptlt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+
+    if (float64_lt(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+uint64_t helper_cmpgeq(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+
+    if (float64_eq_quiet(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+uint64_t helper_cmpgle(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+
+    if (float64_le(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+uint64_t helper_cmpglt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fb = g_to_float64(env, GETPC(), b);
+
+    if (float64_lt(fa, fb, &FP_STATUS)) {
+        return 0x4000000000000000ULL;
+    } else {
+        return 0;
+    }
+}
+
+/* Floating point format conversion */
+uint64_t helper_cvtts(CPUAlphaState *env, uint64_t a)
+{
+    float64 fa;
+    float32 fr;
+
+    fa = t_to_float64(a);
+    fr = float64_to_float32(fa, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+uint64_t helper_cvtst(CPUAlphaState *env, uint64_t a)
+{
+    float32 fa;
+    float64 fr;
+
+    fa = s_to_float32(a);
+    fr = float32_to_float64(fa, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+uint64_t helper_cvtqs(CPUAlphaState *env, uint64_t a)
+{
+    float32 fr = int64_to_float32(a, &FP_STATUS);
+    return float32_to_s(fr);
+}
+
+/* Implement float64 to uint64 conversion without saturation -- we must
+   supply the truncated result.  This behaviour is used by the compiler
+   to get unsigned conversion for free with the same instruction.
+
+   The VI flag is set when overflow or inexact exceptions should be raised.  */
+
+static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
+                                    int roundmode, int VI)
+{
+    uint64_t frac, ret = 0;
+    uint32_t exp, sign, exc = 0;
+    int shift;
+
+    sign = (a >> 63);
+    exp = (uint32_t)(a >> 52) & 0x7ff;
+    frac = a & 0xfffffffffffffull;
+
+    if (exp == 0) {
+        if (unlikely(frac != 0)) {
+            goto do_underflow;
+        }
+    } else if (exp == 0x7ff) {
+        exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
+    } else {
+        /* Restore implicit bit.  */
+        frac |= 0x10000000000000ull;
+
+        shift = exp - 1023 - 52;
+        if (shift >= 0) {
+            /* In this case the number is so large that we must shift
+               the fraction left.  There is no rounding to do.  */
+            if (shift < 63) {
+                ret = frac << shift;
+                if (VI && (ret >> shift) != frac) {
+                    exc = float_flag_overflow;
+                }
+            }
+        } else {
+            uint64_t round;
+
+            /* In this case the number is smaller than the fraction as
+               represented by the 52 bit number.  Here we must think
+               about rounding the result.  Handle this by shifting the
+               fractional part of the number into the high bits of ROUND.
+               This will let us efficiently handle round-to-nearest.  */
+            shift = -shift;
+            if (shift < 63) {
+                ret = frac >> shift;
+                round = frac << (64 - shift);
+            } else {
+                /* The exponent is so small we shift out everything.
+                   Leave a sticky bit for proper rounding below.  */
+            do_underflow:
+                round = 1;
+            }
+
+            if (round) {
+                exc = (VI ? float_flag_inexact : 0);
+                switch (roundmode) {
+                case float_round_nearest_even:
+                    if (round == (1ull << 63)) {
+                        /* Fraction is exactly 0.5; round to even.  */
+                        ret += (ret & 1);
+                    } else if (round > (1ull << 63)) {
+                        ret += 1;
+                    }
+                    break;
+                case float_round_to_zero:
+                    break;
+                case float_round_up:
+                    ret += 1 - sign;
+                    break;
+                case float_round_down:
+                    ret += sign;
+                    break;
+                }
+            }
+        }
+        if (sign) {
+            ret = -ret;
+        }
+    }
+    if (unlikely(exc)) {
+        float_raise(exc, &FP_STATUS);
+    }
+
+    return ret;
+}
+
+uint64_t helper_cvttq(CPUAlphaState *env, uint64_t a)
+{
+    return inline_cvttq(env, a, FP_STATUS.float_rounding_mode, 1);
+}
+
+uint64_t helper_cvttq_c(CPUAlphaState *env, uint64_t a)
+{
+    return inline_cvttq(env, a, float_round_to_zero, 0);
+}
+
+uint64_t helper_cvttq_svic(CPUAlphaState *env, uint64_t a)
+{
+    return inline_cvttq(env, a, float_round_to_zero, 1);
+}
+
+uint64_t helper_cvtqt(CPUAlphaState *env, uint64_t a)
+{
+    float64 fr = int64_to_float64(a, &FP_STATUS);
+    return float64_to_t(fr);
+}
+
+uint64_t helper_cvtqf(CPUAlphaState *env, uint64_t a)
+{
+    float32 fr = int64_to_float32(a, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+uint64_t helper_cvtgf(CPUAlphaState *env, uint64_t a)
+{
+    float64 fa;
+    float32 fr;
+
+    fa = g_to_float64(env, GETPC(), a);
+    fr = float64_to_float32(fa, &FP_STATUS);
+    return float32_to_f(fr);
+}
+
+uint64_t helper_cvtgq(CPUAlphaState *env, uint64_t a)
+{
+    float64 fa = g_to_float64(env, GETPC(), a);
+    return float64_to_int64_round_to_zero(fa, &FP_STATUS);
+}
+
+uint64_t helper_cvtqg(CPUAlphaState *env, uint64_t a)
+{
+    float64 fr;
+    fr = int64_to_float64(a, &FP_STATUS);
+    return float64_to_g(fr);
+}
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 3f2e7c3..765e650 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -23,6 +23,7 @@
 
 #include "cpu.h"
 #include "softfloat.h"
+#include "helper.h"
 
 uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env)
 {
@@ -81,7 +82,7 @@
         break;
     }
 
-    if (env->fpcr_dnz) {
+    if (env->fp_status.flush_inputs_to_zero) {
         r |= FPCR_DNZ;
     }
     if (env->fpcr_dnod) {
@@ -150,17 +151,25 @@
     }
     env->fpcr_dyn_round = t;
 
-    env->fpcr_flush_to_zero
-      = (val & (FPCR_UNDZ|FPCR_UNFD)) == (FPCR_UNDZ|FPCR_UNFD);
-
-    env->fpcr_dnz = (val & FPCR_DNZ) != 0;
     env->fpcr_dnod = (val & FPCR_DNOD) != 0;
     env->fpcr_undz = (val & FPCR_UNDZ) != 0;
+    env->fpcr_flush_to_zero = env->fpcr_dnod & env->fpcr_undz;
+    env->fp_status.flush_inputs_to_zero = (val & FPCR_DNZ) != 0;
+}
+
+uint64_t helper_load_fpcr(CPUAlphaState *env)
+{
+    return cpu_alpha_load_fpcr(env);
+}
+
+void helper_store_fpcr(CPUAlphaState *env, uint64_t val)
+{
+    cpu_alpha_store_fpcr(env, val);
 }
 
 #if defined(CONFIG_USER_ONLY)
-int cpu_alpha_handle_mmu_fault (CPUAlphaState *env, target_ulong address, int rw,
-                                int mmu_idx)
+int cpu_alpha_handle_mmu_fault(CPUAlphaState *env, target_ulong address,
+                               int rw, int mmu_idx)
 {
     env->exception_index = EXCP_MMFAULT;
     env->trap_arg0 = address;
@@ -484,3 +493,41 @@
     }
     cpu_fprintf(f, "\n");
 }
+
+void do_restore_state(CPUAlphaState *env, void *retaddr)
+{
+    uintptr_t pc = (uintptr_t)retaddr;
+    if (pc) {
+        TranslationBlock *tb = tb_find_pc(pc);
+        if (tb) {
+            cpu_restore_state(tb, env, pc);
+        }
+    }
+}
+
+/* This should only be called from translate, via gen_excp.
+   We expect that ENV->PC has already been updated.  */
+void QEMU_NORETURN helper_excp(CPUAlphaState *env, int excp, int error)
+{
+    env->exception_index = excp;
+    env->error_code = error;
+    cpu_loop_exit(env);
+}
+
+/* This may be called from any of the helpers to set up EXCEPTION_INDEX.  */
+void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, void *retaddr,
+                                int excp, int error)
+{
+    env->exception_index = excp;
+    env->error_code = error;
+    do_restore_state(env, retaddr);
+    cpu_loop_exit(env);
+}
+
+void QEMU_NORETURN arith_excp(CPUAlphaState *env, void *retaddr,
+                              int exc, uint64_t mask)
+{
+    env->trap_arg0 = exc;
+    env->trap_arg1 = mask;
+    dynamic_excp(env, retaddr, EXCP_ARITH, 0);
+}
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index b693cee..a184def 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -1,14 +1,14 @@
 #include "def-helper.h"
 
-DEF_HELPER_2(excp, void, int, int)
-DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
+DEF_HELPER_3(excp, noreturn, env, int, int)
+DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64, env)
 
-DEF_HELPER_2(addqv, i64, i64, i64)
-DEF_HELPER_2(addlv, i64, i64, i64)
-DEF_HELPER_2(subqv, i64, i64, i64)
-DEF_HELPER_2(sublv, i64, i64, i64)
-DEF_HELPER_2(mullv, i64, i64, i64)
-DEF_HELPER_2(mulqv, i64, i64, i64)
+DEF_HELPER_3(addqv, i64, env, i64, i64)
+DEF_HELPER_3(addlv, i64, env, i64, i64)
+DEF_HELPER_3(subqv, i64, env, i64, i64)
+DEF_HELPER_3(sublv, i64, env, i64, i64)
+DEF_HELPER_3(mullv, i64, env, i64, i64)
+DEF_HELPER_3(mulqv, i64, env, i64, i64)
 DEF_HELPER_FLAGS_2(umulh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
 
 DEF_HELPER_FLAGS_1(ctpop, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
@@ -34,90 +34,89 @@
 DEF_HELPER_FLAGS_1(unpkbl, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
 DEF_HELPER_FLAGS_1(unpkbw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
 
-DEF_HELPER_FLAGS_0(load_fpcr, TCG_CALL_CONST | TCG_CALL_PURE, i64)
-DEF_HELPER_FLAGS_1(store_fpcr, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_1(load_fpcr, TCG_CALL_CONST | TCG_CALL_PURE, i64, env)
+DEF_HELPER_FLAGS_2(store_fpcr, TCG_CALL_CONST, void, env, i64)
 
 DEF_HELPER_FLAGS_1(f_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64)
 DEF_HELPER_FLAGS_1(memory_to_f, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32)
-DEF_HELPER_FLAGS_2(addf, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(subf, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(mulf, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(divf, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_1(sqrtf, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_3(addf, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(subf, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(mulf, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divf, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqrtf, TCG_CALL_CONST, i64, env, i64)
 
 DEF_HELPER_FLAGS_1(g_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
 DEF_HELPER_FLAGS_1(memory_to_g, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
-DEF_HELPER_FLAGS_2(addg, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(subg, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(mulg, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(divg, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_1(sqrtg, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_3(addg, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(subg, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(mulg, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divg, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqrtg, TCG_CALL_CONST, i64, env, i64)
 
 DEF_HELPER_FLAGS_1(s_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64)
 DEF_HELPER_FLAGS_1(memory_to_s, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32)
-DEF_HELPER_FLAGS_2(adds, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(subs, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(muls, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(divs, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_1(sqrts, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_3(adds, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(subs, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(muls, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divs, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqrts, TCG_CALL_CONST, i64, env, i64)
 
-DEF_HELPER_FLAGS_2(addt, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(subt, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(mult, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(divt, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_1(sqrtt, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_3(addt, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(subt, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(mult, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divt, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqrtt, TCG_CALL_CONST, i64, env, i64)
 
-DEF_HELPER_FLAGS_2(cmptun, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmpteq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmptle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmptlt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmpgeq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmpgle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmpglt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
+DEF_HELPER_FLAGS_3(cmptun, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmpteq, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmptle, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmptlt, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmpgeq, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmpgle, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmpglt, TCG_CALL_CONST, i64, env, i64, i64)
 
-DEF_HELPER_FLAGS_1(cvtts, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtst, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtqs, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtqt, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtqf, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtgf, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtgq, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtqg, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_2(cvtts, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtst, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtqs, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtqt, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtqf, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtgf, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtgq, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtqg, TCG_CALL_CONST, i64, env, i64)
 
-DEF_HELPER_FLAGS_1(cvttq, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvttq_c, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvttq_svic, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_2(cvttq, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvttq_c, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvttq_svic, TCG_CALL_CONST, i64, env, i64)
 
-DEF_HELPER_FLAGS_1(setroundmode, TCG_CALL_CONST, void, i32)
-DEF_HELPER_FLAGS_1(setflushzero, TCG_CALL_CONST, void, i32)
-DEF_HELPER_FLAGS_0(fp_exc_clear, TCG_CALL_CONST, void)
-DEF_HELPER_FLAGS_0(fp_exc_get, TCG_CALL_CONST | TCG_CALL_PURE, i32)
-DEF_HELPER_2(fp_exc_raise, void, i32, i32)
-DEF_HELPER_2(fp_exc_raise_s, void, i32, i32)
+DEF_HELPER_FLAGS_2(setroundmode, TCG_CALL_CONST, void, env, i32)
+DEF_HELPER_FLAGS_2(setflushzero, TCG_CALL_CONST, void, env, i32)
+DEF_HELPER_FLAGS_1(fp_exc_clear, TCG_CALL_CONST, void, env)
+DEF_HELPER_FLAGS_1(fp_exc_get, TCG_CALL_CONST | TCG_CALL_PURE, i32, env)
+DEF_HELPER_3(fp_exc_raise, void, env, i32, i32)
+DEF_HELPER_3(fp_exc_raise_s, void, env, i32, i32)
 
-DEF_HELPER_1(ieee_input, i64, i64)
-DEF_HELPER_1(ieee_input_cmp, i64, i64)
-DEF_HELPER_1(ieee_input_s, i64, i64)
+DEF_HELPER_2(ieee_input, void, env, i64)
+DEF_HELPER_2(ieee_input_cmp, void, env, i64)
 
 #if !defined (CONFIG_USER_ONLY)
-DEF_HELPER_1(hw_ret, void, i64)
+DEF_HELPER_2(hw_ret, void, env, i64)
 
 DEF_HELPER_1(ldl_phys, i64, i64)
 DEF_HELPER_1(ldq_phys, i64, i64)
-DEF_HELPER_1(ldl_l_phys, i64, i64)
-DEF_HELPER_1(ldq_l_phys, i64, i64)
+DEF_HELPER_2(ldl_l_phys, i64, env, i64)
+DEF_HELPER_2(ldq_l_phys, i64, env, i64)
 DEF_HELPER_2(stl_phys, void, i64, i64)
 DEF_HELPER_2(stq_phys, void, i64, i64)
-DEF_HELPER_2(stl_c_phys, i64, i64, i64)
-DEF_HELPER_2(stq_c_phys, i64, i64, i64)
+DEF_HELPER_3(stl_c_phys, i64, env, i64, i64)
+DEF_HELPER_3(stq_c_phys, i64, env, i64, i64)
 
-DEF_HELPER_FLAGS_0(tbia, TCG_CALL_CONST, void)
-DEF_HELPER_FLAGS_1(tbis, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_1(tbia, TCG_CALL_CONST, void, env)
+DEF_HELPER_FLAGS_2(tbis, TCG_CALL_CONST, void, env, i64)
 
 DEF_HELPER_1(halt, void, i64);
 
 DEF_HELPER_FLAGS_0(get_time, TCG_CALL_CONST, i64)
-DEF_HELPER_FLAGS_1(set_alarm, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_2(set_alarm, TCG_CALL_CONST, void, env, i64)
 #endif
 
 #include "def-helper.h"
diff --git a/target-alpha/int_helper.c b/target-alpha/int_helper.c
new file mode 100644
index 0000000..1d832f0
--- /dev/null
+++ b/target-alpha/int_helper.c
@@ -0,0 +1,319 @@
+/*
+ *  Helpers for integer and multimedia instructions.
+ *
+ *  Copyright (c) 2007 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "host-utils.h"
+
+
+uint64_t helper_umulh(uint64_t op1, uint64_t op2)
+{
+    uint64_t tl, th;
+    mulu64(&tl, &th, op1, op2);
+    return th;
+}
+
+uint64_t helper_ctpop(uint64_t arg)
+{
+    return ctpop64(arg);
+}
+
+uint64_t helper_ctlz(uint64_t arg)
+{
+    return clz64(arg);
+}
+
+uint64_t helper_cttz(uint64_t arg)
+{
+    return ctz64(arg);
+}
+
+static inline uint64_t byte_zap(uint64_t op, uint8_t mskb)
+{
+    uint64_t mask;
+
+    mask = 0;
+    mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
+    mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
+    mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
+    mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
+    mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
+    mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
+    mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
+    mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
+
+    return op & ~mask;
+}
+
+uint64_t helper_zap(uint64_t val, uint64_t mask)
+{
+    return byte_zap(val, mask);
+}
+
+uint64_t helper_zapnot(uint64_t val, uint64_t mask)
+{
+    return byte_zap(val, ~mask);
+}
+
+uint64_t helper_cmpbge(uint64_t op1, uint64_t op2)
+{
+    uint8_t opa, opb, res;
+    int i;
+
+    res = 0;
+    for (i = 0; i < 8; i++) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        if (opa >= opb) {
+            res |= 1 << i;
+        }
+    }
+    return res;
+}
+
+uint64_t helper_minub8(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint8_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        opr = opa < opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 8);
+    }
+    return res;
+}
+
+uint64_t helper_minsb8(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    int8_t opa, opb;
+    uint8_t opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        opr = opa < opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 8);
+    }
+    return res;
+}
+
+uint64_t helper_minuw4(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint16_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 4; ++i) {
+        opa = op1 >> (i * 16);
+        opb = op2 >> (i * 16);
+        opr = opa < opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 16);
+    }
+    return res;
+}
+
+uint64_t helper_minsw4(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    int16_t opa, opb;
+    uint16_t opr;
+    int i;
+
+    for (i = 0; i < 4; ++i) {
+        opa = op1 >> (i * 16);
+        opb = op2 >> (i * 16);
+        opr = opa < opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 16);
+    }
+    return res;
+}
+
+uint64_t helper_maxub8(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint8_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        opr = opa > opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 8);
+    }
+    return res;
+}
+
+uint64_t helper_maxsb8(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    int8_t opa, opb;
+    uint8_t opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        opr = opa > opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 8);
+    }
+    return res;
+}
+
+uint64_t helper_maxuw4(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint16_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 4; ++i) {
+        opa = op1 >> (i * 16);
+        opb = op2 >> (i * 16);
+        opr = opa > opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 16);
+    }
+    return res;
+}
+
+uint64_t helper_maxsw4(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    int16_t opa, opb;
+    uint16_t opr;
+    int i;
+
+    for (i = 0; i < 4; ++i) {
+        opa = op1 >> (i * 16);
+        opb = op2 >> (i * 16);
+        opr = opa > opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 16);
+    }
+    return res;
+}
+
+uint64_t helper_perr(uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint8_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        if (opa >= opb) {
+            opr = opa - opb;
+        } else {
+            opr = opb - opa;
+        }
+        res += opr;
+    }
+    return res;
+}
+
+uint64_t helper_pklb(uint64_t op1)
+{
+    return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
+}
+
+uint64_t helper_pkwb(uint64_t op1)
+{
+    return ((op1 & 0xff)
+            | ((op1 >> 8) & 0xff00)
+            | ((op1 >> 16) & 0xff0000)
+            | ((op1 >> 24) & 0xff000000));
+}
+
+uint64_t helper_unpkbl(uint64_t op1)
+{
+    return (op1 & 0xff) | ((op1 & 0xff00) << 24);
+}
+
+uint64_t helper_unpkbw(uint64_t op1)
+{
+    return ((op1 & 0xff)
+            | ((op1 & 0xff00) << 8)
+            | ((op1 & 0xff0000) << 16)
+            | ((op1 & 0xff000000) << 24));
+}
+
+uint64_t helper_addqv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+    uint64_t tmp = op1;
+    op1 += op2;
+    if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+    return op1;
+}
+
+uint64_t helper_addlv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+    uint64_t tmp = op1;
+    op1 = (uint32_t)(op1 + op2);
+    if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+    return op1;
+}
+
+uint64_t helper_subqv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+    uint64_t res;
+    res = op1 - op2;
+    if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+    return res;
+}
+
+uint64_t helper_sublv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+    uint32_t res;
+    res = op1 - op2;
+    if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+    return res;
+}
+
+uint64_t helper_mullv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+    int64_t res = (int64_t)op1 * (int64_t)op2;
+
+    if (unlikely((int32_t)res != res)) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+    return (int64_t)((int32_t)res);
+}
+
+uint64_t helper_mulqv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+    uint64_t tl, th;
+
+    muls64(&tl, &th, op1, op2);
+    /* If th != 0 && th != -1, then we had an overflow */
+    if (unlikely((th + 1) > 1)) {
+        arith_excp(env, GETPC(), EXC_M_IOV, 0);
+    }
+    return tl;
+}
diff --git a/target-alpha/mem_helper.c b/target-alpha/mem_helper.c
new file mode 100644
index 0000000..dd5ca49
--- /dev/null
+++ b/target-alpha/mem_helper.c
@@ -0,0 +1,151 @@
+/*
+ *  Helpers for loads and stores
+ *
+ *  Copyright (c) 2007 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+
+
+/* Softmmu support */
+#ifndef CONFIG_USER_ONLY
+
+uint64_t helper_ldl_phys(uint64_t p)
+{
+    return (int32_t)ldl_phys(p);
+}
+
+uint64_t helper_ldq_phys(uint64_t p)
+{
+    return ldq_phys(p);
+}
+
+uint64_t helper_ldl_l_phys(CPUAlphaState *env, uint64_t p)
+{
+    env->lock_addr = p;
+    return env->lock_value = (int32_t)ldl_phys(p);
+}
+
+uint64_t helper_ldq_l_phys(CPUAlphaState *env, uint64_t p)
+{
+    env->lock_addr = p;
+    return env->lock_value = ldq_phys(p);
+}
+
+void helper_stl_phys(uint64_t p, uint64_t v)
+{
+    stl_phys(p, v);
+}
+
+void helper_stq_phys(uint64_t p, uint64_t v)
+{
+    stq_phys(p, v);
+}
+
+uint64_t helper_stl_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
+{
+    uint64_t ret = 0;
+
+    if (p == env->lock_addr) {
+        int32_t old = ldl_phys(p);
+        if (old == (int32_t)env->lock_value) {
+            stl_phys(p, v);
+            ret = 1;
+        }
+    }
+    env->lock_addr = -1;
+
+    return ret;
+}
+
+uint64_t helper_stq_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
+{
+    uint64_t ret = 0;
+
+    if (p == env->lock_addr) {
+        uint64_t old = ldq_phys(p);
+        if (old == env->lock_value) {
+            stq_phys(p, v);
+            ret = 1;
+        }
+    }
+    env->lock_addr = -1;
+
+    return ret;
+}
+
+static void do_unaligned_access(CPUAlphaState *env, target_ulong addr,
+                                int is_write, int is_user, void *retaddr)
+{
+    uint64_t pc;
+    uint32_t insn;
+
+    do_restore_state(env, retaddr);
+
+    pc = env->pc;
+    insn = cpu_ldl_code(env, pc);
+
+    env->trap_arg0 = addr;
+    env->trap_arg1 = insn >> 26;                /* opcode */
+    env->trap_arg2 = (insn >> 21) & 31;         /* dest regno */
+    env->exception_index = EXCP_UNALIGN;
+    env->error_code = 0;
+    cpu_loop_exit(env);
+}
+
+void cpu_unassigned_access(CPUAlphaState *env, target_phys_addr_t addr,
+                           int is_write, int is_exec, int unused, int size)
+{
+    env->trap_arg0 = addr;
+    env->trap_arg1 = is_write;
+    dynamic_excp(env, NULL, EXCP_MCHK, 0);
+}
+
+#include "softmmu_exec.h"
+
+#define MMUSUFFIX _mmu
+#define ALIGNED_ONLY
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+
+/* try to fill the TLB and return an exception if error. If retaddr is
+   NULL, it means that the function was called in C code (i.e. not
+   from generated code or from helper.c) */
+/* XXX: fix it to restore all registers */
+void tlb_fill(CPUAlphaState *env, target_ulong addr, int is_write,
+              int mmu_idx, void *retaddr)
+{
+    int ret;
+
+    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx);
+    if (unlikely(ret != 0)) {
+        do_restore_state(env, retaddr);
+        /* Exception index and error code are already set */
+        cpu_loop_exit(env);
+    }
+}
+#endif /* CONFIG_USER_ONLY */
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
deleted file mode 100644
index c77f009..0000000
--- a/target-alpha/op_helper.c
+++ /dev/null
@@ -1,1379 +0,0 @@
-/*
- *  Alpha emulation cpu micro-operations helpers for qemu.
- *
- *  Copyright (c) 2007 Jocelyn Mayer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "cpu.h"
-#include "dyngen-exec.h"
-#include "host-utils.h"
-#include "softfloat.h"
-#include "helper.h"
-#include "sysemu.h"
-#include "qemu-timer.h"
-
-#define FP_STATUS (env->fp_status)
-
-/*****************************************************************************/
-/* Exceptions processing helpers */
-
-/* This should only be called from translate, via gen_excp.
-   We expect that ENV->PC has already been updated.  */
-void QEMU_NORETURN helper_excp(int excp, int error)
-{
-    env->exception_index = excp;
-    env->error_code = error;
-    cpu_loop_exit(env);
-}
-
-static void do_restore_state(void *retaddr)
-{
-    unsigned long pc = (unsigned long)retaddr;
-
-    if (pc) {
-        TranslationBlock *tb = tb_find_pc(pc);
-        if (tb) {
-            cpu_restore_state(tb, env, pc);
-        }
-    }
-}
-
-/* This may be called from any of the helpers to set up EXCEPTION_INDEX.  */
-static void QEMU_NORETURN dynamic_excp(int excp, int error)
-{
-    env->exception_index = excp;
-    env->error_code = error;
-    do_restore_state(GETPC());
-    cpu_loop_exit(env);
-}
-
-static void QEMU_NORETURN arith_excp(int exc, uint64_t mask)
-{
-    env->trap_arg0 = exc;
-    env->trap_arg1 = mask;
-    dynamic_excp(EXCP_ARITH, 0);
-}
-
-uint64_t helper_load_pcc (void)
-{
-#ifndef CONFIG_USER_ONLY
-    /* In system mode we have access to a decent high-resolution clock.
-       In order to make OS-level time accounting work with the RPCC,
-       present it with a well-timed clock fixed at 250MHz.  */
-    return (((uint64_t)env->pcc_ofs << 32)
-            | (uint32_t)(qemu_get_clock_ns(vm_clock) >> 2));
-#else
-    /* In user-mode, vm_clock doesn't exist.  Just pass through the host cpu
-       clock ticks.  Also, don't bother taking PCC_OFS into account.  */
-    return (uint32_t)cpu_get_real_ticks();
-#endif
-}
-
-uint64_t helper_load_fpcr (void)
-{
-    return cpu_alpha_load_fpcr (env);
-}
-
-void helper_store_fpcr (uint64_t val)
-{
-    cpu_alpha_store_fpcr (env, val);
-}
-
-uint64_t helper_addqv (uint64_t op1, uint64_t op2)
-{
-    uint64_t tmp = op1;
-    op1 += op2;
-    if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
-        arith_excp(EXC_M_IOV, 0);
-    }
-    return op1;
-}
-
-uint64_t helper_addlv (uint64_t op1, uint64_t op2)
-{
-    uint64_t tmp = op1;
-    op1 = (uint32_t)(op1 + op2);
-    if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
-        arith_excp(EXC_M_IOV, 0);
-    }
-    return op1;
-}
-
-uint64_t helper_subqv (uint64_t op1, uint64_t op2)
-{
-    uint64_t res;
-    res = op1 - op2;
-    if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
-        arith_excp(EXC_M_IOV, 0);
-    }
-    return res;
-}
-
-uint64_t helper_sublv (uint64_t op1, uint64_t op2)
-{
-    uint32_t res;
-    res = op1 - op2;
-    if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
-        arith_excp(EXC_M_IOV, 0);
-    }
-    return res;
-}
-
-uint64_t helper_mullv (uint64_t op1, uint64_t op2)
-{
-    int64_t res = (int64_t)op1 * (int64_t)op2;
-
-    if (unlikely((int32_t)res != res)) {
-        arith_excp(EXC_M_IOV, 0);
-    }
-    return (int64_t)((int32_t)res);
-}
-
-uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
-{
-    uint64_t tl, th;
-
-    muls64(&tl, &th, op1, op2);
-    /* If th != 0 && th != -1, then we had an overflow */
-    if (unlikely((th + 1) > 1)) {
-        arith_excp(EXC_M_IOV, 0);
-    }
-    return tl;
-}
-
-uint64_t helper_umulh (uint64_t op1, uint64_t op2)
-{
-    uint64_t tl, th;
-
-    mulu64(&tl, &th, op1, op2);
-    return th;
-}
-
-uint64_t helper_ctpop (uint64_t arg)
-{
-    return ctpop64(arg);
-}
-
-uint64_t helper_ctlz (uint64_t arg)
-{
-    return clz64(arg);
-}
-
-uint64_t helper_cttz (uint64_t arg)
-{
-    return ctz64(arg);
-}
-
-static inline uint64_t byte_zap(uint64_t op, uint8_t mskb)
-{
-    uint64_t mask;
-
-    mask = 0;
-    mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
-    mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
-    mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
-    mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
-    mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
-    mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
-    mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
-    mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
-
-    return op & ~mask;
-}
-
-uint64_t helper_zap(uint64_t val, uint64_t mask)
-{
-    return byte_zap(val, mask);
-}
-
-uint64_t helper_zapnot(uint64_t val, uint64_t mask)
-{
-    return byte_zap(val, ~mask);
-}
-
-uint64_t helper_cmpbge (uint64_t op1, uint64_t op2)
-{
-    uint8_t opa, opb, res;
-    int i;
-
-    res = 0;
-    for (i = 0; i < 8; i++) {
-        opa = op1 >> (i * 8);
-        opb = op2 >> (i * 8);
-        if (opa >= opb)
-            res |= 1 << i;
-    }
-    return res;
-}
-
-uint64_t helper_minub8 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    uint8_t opa, opb, opr;
-    int i;
-
-    for (i = 0; i < 8; ++i) {
-        opa = op1 >> (i * 8);
-        opb = op2 >> (i * 8);
-        opr = opa < opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 8);
-    }
-    return res;
-}
-
-uint64_t helper_minsb8 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    int8_t opa, opb;
-    uint8_t opr;
-    int i;
-
-    for (i = 0; i < 8; ++i) {
-        opa = op1 >> (i * 8);
-        opb = op2 >> (i * 8);
-        opr = opa < opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 8);
-    }
-    return res;
-}
-
-uint64_t helper_minuw4 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    uint16_t opa, opb, opr;
-    int i;
-
-    for (i = 0; i < 4; ++i) {
-        opa = op1 >> (i * 16);
-        opb = op2 >> (i * 16);
-        opr = opa < opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 16);
-    }
-    return res;
-}
-
-uint64_t helper_minsw4 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    int16_t opa, opb;
-    uint16_t opr;
-    int i;
-
-    for (i = 0; i < 4; ++i) {
-        opa = op1 >> (i * 16);
-        opb = op2 >> (i * 16);
-        opr = opa < opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 16);
-    }
-    return res;
-}
-
-uint64_t helper_maxub8 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    uint8_t opa, opb, opr;
-    int i;
-
-    for (i = 0; i < 8; ++i) {
-        opa = op1 >> (i * 8);
-        opb = op2 >> (i * 8);
-        opr = opa > opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 8);
-    }
-    return res;
-}
-
-uint64_t helper_maxsb8 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    int8_t opa, opb;
-    uint8_t opr;
-    int i;
-
-    for (i = 0; i < 8; ++i) {
-        opa = op1 >> (i * 8);
-        opb = op2 >> (i * 8);
-        opr = opa > opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 8);
-    }
-    return res;
-}
-
-uint64_t helper_maxuw4 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    uint16_t opa, opb, opr;
-    int i;
-
-    for (i = 0; i < 4; ++i) {
-        opa = op1 >> (i * 16);
-        opb = op2 >> (i * 16);
-        opr = opa > opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 16);
-    }
-    return res;
-}
-
-uint64_t helper_maxsw4 (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    int16_t opa, opb;
-    uint16_t opr;
-    int i;
-
-    for (i = 0; i < 4; ++i) {
-        opa = op1 >> (i * 16);
-        opb = op2 >> (i * 16);
-        opr = opa > opb ? opa : opb;
-        res |= (uint64_t)opr << (i * 16);
-    }
-    return res;
-}
-
-uint64_t helper_perr (uint64_t op1, uint64_t op2)
-{
-    uint64_t res = 0;
-    uint8_t opa, opb, opr;
-    int i;
-
-    for (i = 0; i < 8; ++i) {
-        opa = op1 >> (i * 8);
-        opb = op2 >> (i * 8);
-        if (opa >= opb)
-            opr = opa - opb;
-        else
-            opr = opb - opa;
-        res += opr;
-    }
-    return res;
-}
-
-uint64_t helper_pklb (uint64_t op1)
-{
-    return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
-}
-
-uint64_t helper_pkwb (uint64_t op1)
-{
-    return ((op1 & 0xff)
-            | ((op1 >> 8) & 0xff00)
-            | ((op1 >> 16) & 0xff0000)
-            | ((op1 >> 24) & 0xff000000));
-}
-
-uint64_t helper_unpkbl (uint64_t op1)
-{
-    return (op1 & 0xff) | ((op1 & 0xff00) << 24);
-}
-
-uint64_t helper_unpkbw (uint64_t op1)
-{
-    return ((op1 & 0xff)
-            | ((op1 & 0xff00) << 8)
-            | ((op1 & 0xff0000) << 16)
-            | ((op1 & 0xff000000) << 24));
-}
-
-/* Floating point helpers */
-
-void helper_setroundmode (uint32_t val)
-{
-    set_float_rounding_mode(val, &FP_STATUS);
-}
-
-void helper_setflushzero (uint32_t val)
-{
-    set_flush_to_zero(val, &FP_STATUS);
-}
-
-void helper_fp_exc_clear (void)
-{
-    set_float_exception_flags(0, &FP_STATUS);
-}
-
-uint32_t helper_fp_exc_get (void)
-{
-    return get_float_exception_flags(&FP_STATUS);
-}
-
-/* Raise exceptions for ieee fp insns without software completion.
-   In that case there are no exceptions that don't trap; the mask
-   doesn't apply.  */
-void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
-{
-    if (exc) {
-        uint32_t hw_exc = 0;
-
-        if (exc & float_flag_invalid) {
-            hw_exc |= EXC_M_INV;
-        }
-        if (exc & float_flag_divbyzero) {
-            hw_exc |= EXC_M_DZE;
-        }
-        if (exc & float_flag_overflow) {
-            hw_exc |= EXC_M_FOV;
-        }
-        if (exc & float_flag_underflow) {
-            hw_exc |= EXC_M_UNF;
-        }
-        if (exc & float_flag_inexact) {
-            hw_exc |= EXC_M_INE;
-        }
-
-        arith_excp(hw_exc, 1ull << regno);
-    }
-}
-
-/* Raise exceptions for ieee fp insns with software completion.  */
-void helper_fp_exc_raise_s(uint32_t exc, uint32_t regno)
-{
-    if (exc) {
-        env->fpcr_exc_status |= exc;
-
-        exc &= ~env->fpcr_exc_mask;
-        if (exc) {
-            helper_fp_exc_raise(exc, regno);
-        }
-    }
-}
-
-/* Input remapping without software completion.  Handle denormal-map-to-zero
-   and trap for all other non-finite numbers.  */
-uint64_t helper_ieee_input(uint64_t val)
-{
-    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
-    uint64_t frac = val & 0xfffffffffffffull;
-
-    if (exp == 0) {
-        if (frac != 0) {
-            /* If DNZ is set flush denormals to zero on input.  */
-            if (env->fpcr_dnz) {
-                val &= 1ull << 63;
-            } else {
-                arith_excp(EXC_M_UNF, 0);
-            }
-        }
-    } else if (exp == 0x7ff) {
-        /* Infinity or NaN.  */
-        /* ??? I'm not sure these exception bit flags are correct.  I do
-           know that the Linux kernel, at least, doesn't rely on them and
-           just emulates the insn to figure out what exception to use.  */
-        arith_excp(frac ? EXC_M_INV : EXC_M_FOV, 0);
-    }
-    return val;
-}
-
-/* Similar, but does not trap for infinities.  Used for comparisons.  */
-uint64_t helper_ieee_input_cmp(uint64_t val)
-{
-    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
-    uint64_t frac = val & 0xfffffffffffffull;
-
-    if (exp == 0) {
-        if (frac != 0) {
-            /* If DNZ is set flush denormals to zero on input.  */
-            if (env->fpcr_dnz) {
-                val &= 1ull << 63;
-            } else {
-                arith_excp(EXC_M_UNF, 0);
-            }
-        }
-    } else if (exp == 0x7ff && frac) {
-        /* NaN.  */
-        arith_excp(EXC_M_INV, 0);
-    }
-    return val;
-}
-
-/* Input remapping with software completion enabled.  All we have to do
-   is handle denormal-map-to-zero; all other inputs get exceptions as
-   needed from the actual operation.  */
-uint64_t helper_ieee_input_s(uint64_t val)
-{
-    if (env->fpcr_dnz) {
-        uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
-        if (exp == 0) {
-            val &= 1ull << 63;
-        }
-    }
-    return val;
-}
-
-/* F floating (VAX) */
-static inline uint64_t float32_to_f(float32 fa)
-{
-    uint64_t r, exp, mant, sig;
-    CPU_FloatU a;
-
-    a.f = fa;
-    sig = ((uint64_t)a.l & 0x80000000) << 32;
-    exp = (a.l >> 23) & 0xff;
-    mant = ((uint64_t)a.l & 0x007fffff) << 29;
-
-    if (exp == 255) {
-        /* NaN or infinity */
-        r = 1; /* VAX dirty zero */
-    } else if (exp == 0) {
-        if (mant == 0) {
-            /* Zero */
-            r = 0;
-        } else {
-            /* Denormalized */
-            r = sig | ((exp + 1) << 52) | mant;
-        }
-    } else {
-        if (exp >= 253) {
-            /* Overflow */
-            r = 1; /* VAX dirty zero */
-        } else {
-            r = sig | ((exp + 2) << 52);
-        }
-    }
-
-    return r;
-}
-
-static inline float32 f_to_float32(uint64_t a)
-{
-    uint32_t exp, mant_sig;
-    CPU_FloatU r;
-
-    exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
-    mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
-
-    if (unlikely(!exp && mant_sig)) {
-        /* Reserved operands / Dirty zero */
-        dynamic_excp(EXCP_OPCDEC, 0);
-    }
-
-    if (exp < 3) {
-        /* Underflow */
-        r.l = 0;
-    } else {
-        r.l = ((exp - 2) << 23) | mant_sig;
-    }
-
-    return r.f;
-}
-
-uint32_t helper_f_to_memory (uint64_t a)
-{
-    uint32_t r;
-    r =  (a & 0x00001fffe0000000ull) >> 13;
-    r |= (a & 0x07ffe00000000000ull) >> 45;
-    r |= (a & 0xc000000000000000ull) >> 48;
-    return r;
-}
-
-uint64_t helper_memory_to_f (uint32_t a)
-{
-    uint64_t r;
-    r =  ((uint64_t)(a & 0x0000c000)) << 48;
-    r |= ((uint64_t)(a & 0x003fffff)) << 45;
-    r |= ((uint64_t)(a & 0xffff0000)) << 13;
-    if (!(a & 0x00004000))
-        r |= 0x7ll << 59;
-    return r;
-}
-
-/* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong.  We should
-   either implement VAX arithmetic properly or just signal invalid opcode.  */
-
-uint64_t helper_addf (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = f_to_float32(a);
-    fb = f_to_float32(b);
-    fr = float32_add(fa, fb, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-uint64_t helper_subf (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = f_to_float32(a);
-    fb = f_to_float32(b);
-    fr = float32_sub(fa, fb, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-uint64_t helper_mulf (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = f_to_float32(a);
-    fb = f_to_float32(b);
-    fr = float32_mul(fa, fb, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-uint64_t helper_divf (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = f_to_float32(a);
-    fb = f_to_float32(b);
-    fr = float32_div(fa, fb, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-uint64_t helper_sqrtf (uint64_t t)
-{
-    float32 ft, fr;
-
-    ft = f_to_float32(t);
-    fr = float32_sqrt(ft, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-
-/* G floating (VAX) */
-static inline uint64_t float64_to_g(float64 fa)
-{
-    uint64_t r, exp, mant, sig;
-    CPU_DoubleU a;
-
-    a.d = fa;
-    sig = a.ll & 0x8000000000000000ull;
-    exp = (a.ll >> 52) & 0x7ff;
-    mant = a.ll & 0x000fffffffffffffull;
-
-    if (exp == 2047) {
-        /* NaN or infinity */
-        r = 1; /* VAX dirty zero */
-    } else if (exp == 0) {
-        if (mant == 0) {
-            /* Zero */
-            r = 0;
-        } else {
-            /* Denormalized */
-            r = sig | ((exp + 1) << 52) | mant;
-        }
-    } else {
-        if (exp >= 2045) {
-            /* Overflow */
-            r = 1; /* VAX dirty zero */
-        } else {
-            r = sig | ((exp + 2) << 52);
-        }
-    }
-
-    return r;
-}
-
-static inline float64 g_to_float64(uint64_t a)
-{
-    uint64_t exp, mant_sig;
-    CPU_DoubleU r;
-
-    exp = (a >> 52) & 0x7ff;
-    mant_sig = a & 0x800fffffffffffffull;
-
-    if (!exp && mant_sig) {
-        /* Reserved operands / Dirty zero */
-        dynamic_excp(EXCP_OPCDEC, 0);
-    }
-
-    if (exp < 3) {
-        /* Underflow */
-        r.ll = 0;
-    } else {
-        r.ll = ((exp - 2) << 52) | mant_sig;
-    }
-
-    return r.d;
-}
-
-uint64_t helper_g_to_memory (uint64_t a)
-{
-    uint64_t r;
-    r =  (a & 0x000000000000ffffull) << 48;
-    r |= (a & 0x00000000ffff0000ull) << 16;
-    r |= (a & 0x0000ffff00000000ull) >> 16;
-    r |= (a & 0xffff000000000000ull) >> 48;
-    return r;
-}
-
-uint64_t helper_memory_to_g (uint64_t a)
-{
-    uint64_t r;
-    r =  (a & 0x000000000000ffffull) << 48;
-    r |= (a & 0x00000000ffff0000ull) << 16;
-    r |= (a & 0x0000ffff00000000ull) >> 16;
-    r |= (a & 0xffff000000000000ull) >> 48;
-    return r;
-}
-
-uint64_t helper_addg (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-    fr = float64_add(fa, fb, &FP_STATUS);
-    return float64_to_g(fr);
-}
-
-uint64_t helper_subg (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-    fr = float64_sub(fa, fb, &FP_STATUS);
-    return float64_to_g(fr);
-}
-
-uint64_t helper_mulg (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-    fr = float64_mul(fa, fb, &FP_STATUS);
-    return float64_to_g(fr);
-}
-
-uint64_t helper_divg (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-    fr = float64_div(fa, fb, &FP_STATUS);
-    return float64_to_g(fr);
-}
-
-uint64_t helper_sqrtg (uint64_t a)
-{
-    float64 fa, fr;
-
-    fa = g_to_float64(a);
-    fr = float64_sqrt(fa, &FP_STATUS);
-    return float64_to_g(fr);
-}
-
-
-/* S floating (single) */
-
-/* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg.  */
-static inline uint64_t float32_to_s_int(uint32_t fi)
-{
-    uint32_t frac = fi & 0x7fffff;
-    uint32_t sign = fi >> 31;
-    uint32_t exp_msb = (fi >> 30) & 1;
-    uint32_t exp_low = (fi >> 23) & 0x7f;
-    uint32_t exp;
-
-    exp = (exp_msb << 10) | exp_low;
-    if (exp_msb) {
-        if (exp_low == 0x7f)
-            exp = 0x7ff;
-    } else {
-        if (exp_low != 0x00)
-            exp |= 0x380;
-    }
-
-    return (((uint64_t)sign << 63)
-            | ((uint64_t)exp << 52)
-            | ((uint64_t)frac << 29));
-}
-
-static inline uint64_t float32_to_s(float32 fa)
-{
-    CPU_FloatU a;
-    a.f = fa;
-    return float32_to_s_int(a.l);
-}
-
-static inline uint32_t s_to_float32_int(uint64_t a)
-{
-    return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
-}
-
-static inline float32 s_to_float32(uint64_t a)
-{
-    CPU_FloatU r;
-    r.l = s_to_float32_int(a);
-    return r.f;
-}
-
-uint32_t helper_s_to_memory (uint64_t a)
-{
-    return s_to_float32_int(a);
-}
-
-uint64_t helper_memory_to_s (uint32_t a)
-{
-    return float32_to_s_int(a);
-}
-
-uint64_t helper_adds (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = s_to_float32(a);
-    fb = s_to_float32(b);
-    fr = float32_add(fa, fb, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-uint64_t helper_subs (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = s_to_float32(a);
-    fb = s_to_float32(b);
-    fr = float32_sub(fa, fb, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-uint64_t helper_muls (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = s_to_float32(a);
-    fb = s_to_float32(b);
-    fr = float32_mul(fa, fb, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-uint64_t helper_divs (uint64_t a, uint64_t b)
-{
-    float32 fa, fb, fr;
-
-    fa = s_to_float32(a);
-    fb = s_to_float32(b);
-    fr = float32_div(fa, fb, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-uint64_t helper_sqrts (uint64_t a)
-{
-    float32 fa, fr;
-
-    fa = s_to_float32(a);
-    fr = float32_sqrt(fa, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-
-/* T floating (double) */
-static inline float64 t_to_float64(uint64_t a)
-{
-    /* Memory format is the same as float64 */
-    CPU_DoubleU r;
-    r.ll = a;
-    return r.d;
-}
-
-static inline uint64_t float64_to_t(float64 fa)
-{
-    /* Memory format is the same as float64 */
-    CPU_DoubleU r;
-    r.d = fa;
-    return r.ll;
-}
-
-uint64_t helper_addt (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-    fr = float64_add(fa, fb, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-uint64_t helper_subt (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-    fr = float64_sub(fa, fb, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-uint64_t helper_mult (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-    fr = float64_mul(fa, fb, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-uint64_t helper_divt (uint64_t a, uint64_t b)
-{
-    float64 fa, fb, fr;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-    fr = float64_div(fa, fb, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-uint64_t helper_sqrtt (uint64_t a)
-{
-    float64 fa, fr;
-
-    fa = t_to_float64(a);
-    fr = float64_sqrt(fa, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-/* Comparisons */
-uint64_t helper_cmptun (uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-
-    if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
-        return 0x4000000000000000ULL;
-    } else {
-        return 0;
-    }
-}
-
-uint64_t helper_cmpteq(uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-
-    if (float64_eq_quiet(fa, fb, &FP_STATUS))
-        return 0x4000000000000000ULL;
-    else
-        return 0;
-}
-
-uint64_t helper_cmptle(uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-
-    if (float64_le(fa, fb, &FP_STATUS))
-        return 0x4000000000000000ULL;
-    else
-        return 0;
-}
-
-uint64_t helper_cmptlt(uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = t_to_float64(a);
-    fb = t_to_float64(b);
-
-    if (float64_lt(fa, fb, &FP_STATUS))
-        return 0x4000000000000000ULL;
-    else
-        return 0;
-}
-
-uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-
-    if (float64_eq_quiet(fa, fb, &FP_STATUS))
-        return 0x4000000000000000ULL;
-    else
-        return 0;
-}
-
-uint64_t helper_cmpgle(uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-
-    if (float64_le(fa, fb, &FP_STATUS))
-        return 0x4000000000000000ULL;
-    else
-        return 0;
-}
-
-uint64_t helper_cmpglt(uint64_t a, uint64_t b)
-{
-    float64 fa, fb;
-
-    fa = g_to_float64(a);
-    fb = g_to_float64(b);
-
-    if (float64_lt(fa, fb, &FP_STATUS))
-        return 0x4000000000000000ULL;
-    else
-        return 0;
-}
-
-/* Floating point format conversion */
-uint64_t helper_cvtts (uint64_t a)
-{
-    float64 fa;
-    float32 fr;
-
-    fa = t_to_float64(a);
-    fr = float64_to_float32(fa, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-uint64_t helper_cvtst (uint64_t a)
-{
-    float32 fa;
-    float64 fr;
-
-    fa = s_to_float32(a);
-    fr = float32_to_float64(fa, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-uint64_t helper_cvtqs (uint64_t a)
-{
-    float32 fr = int64_to_float32(a, &FP_STATUS);
-    return float32_to_s(fr);
-}
-
-/* Implement float64 to uint64 conversion without saturation -- we must
-   supply the truncated result.  This behaviour is used by the compiler
-   to get unsigned conversion for free with the same instruction.
-
-   The VI flag is set when overflow or inexact exceptions should be raised.  */
-
-static inline uint64_t helper_cvttq_internal(uint64_t a, int roundmode, int VI)
-{
-    uint64_t frac, ret = 0;
-    uint32_t exp, sign, exc = 0;
-    int shift;
-
-    sign = (a >> 63);
-    exp = (uint32_t)(a >> 52) & 0x7ff;
-    frac = a & 0xfffffffffffffull;
-
-    if (exp == 0) {
-        if (unlikely(frac != 0)) {
-            goto do_underflow;
-        }
-    } else if (exp == 0x7ff) {
-        exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
-    } else {
-        /* Restore implicit bit.  */
-        frac |= 0x10000000000000ull;
-
-        shift = exp - 1023 - 52;
-        if (shift >= 0) {
-            /* In this case the number is so large that we must shift
-               the fraction left.  There is no rounding to do.  */
-            if (shift < 63) {
-                ret = frac << shift;
-                if (VI && (ret >> shift) != frac) {
-                    exc = float_flag_overflow;
-                }
-            }
-        } else {
-            uint64_t round;
-
-            /* In this case the number is smaller than the fraction as
-               represented by the 52 bit number.  Here we must think
-               about rounding the result.  Handle this by shifting the
-               fractional part of the number into the high bits of ROUND.
-               This will let us efficiently handle round-to-nearest.  */
-            shift = -shift;
-            if (shift < 63) {
-                ret = frac >> shift;
-                round = frac << (64 - shift);
-            } else {
-                /* The exponent is so small we shift out everything.
-                   Leave a sticky bit for proper rounding below.  */
-            do_underflow:
-                round = 1;
-            }
-
-            if (round) {
-                exc = (VI ? float_flag_inexact : 0);
-                switch (roundmode) {
-                case float_round_nearest_even:
-                    if (round == (1ull << 63)) {
-                        /* Fraction is exactly 0.5; round to even.  */
-                        ret += (ret & 1);
-                    } else if (round > (1ull << 63)) {
-                        ret += 1;
-                    }
-                    break;
-                case float_round_to_zero:
-                    break;
-                case float_round_up:
-                    ret += 1 - sign;
-                    break;
-                case float_round_down:
-                    ret += sign;
-                    break;
-                }
-            }
-        }
-        if (sign) {
-            ret = -ret;
-        }
-    }
-    if (unlikely(exc)) {
-        float_raise(exc, &FP_STATUS);
-    }
-
-    return ret;
-}
-
-uint64_t helper_cvttq(uint64_t a)
-{
-    return helper_cvttq_internal(a, FP_STATUS.float_rounding_mode, 1);
-}
-
-uint64_t helper_cvttq_c(uint64_t a)
-{
-    return helper_cvttq_internal(a, float_round_to_zero, 0);
-}
-
-uint64_t helper_cvttq_svic(uint64_t a)
-{
-    return helper_cvttq_internal(a, float_round_to_zero, 1);
-}
-
-uint64_t helper_cvtqt (uint64_t a)
-{
-    float64 fr = int64_to_float64(a, &FP_STATUS);
-    return float64_to_t(fr);
-}
-
-uint64_t helper_cvtqf (uint64_t a)
-{
-    float32 fr = int64_to_float32(a, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-uint64_t helper_cvtgf (uint64_t a)
-{
-    float64 fa;
-    float32 fr;
-
-    fa = g_to_float64(a);
-    fr = float64_to_float32(fa, &FP_STATUS);
-    return float32_to_f(fr);
-}
-
-uint64_t helper_cvtgq (uint64_t a)
-{
-    float64 fa = g_to_float64(a);
-    return float64_to_int64_round_to_zero(fa, &FP_STATUS);
-}
-
-uint64_t helper_cvtqg (uint64_t a)
-{
-    float64 fr;
-    fr = int64_to_float64(a, &FP_STATUS);
-    return float64_to_g(fr);
-}
-
-/* PALcode support special instructions */
-#if !defined (CONFIG_USER_ONLY)
-void helper_hw_ret (uint64_t a)
-{
-    env->pc = a & ~3;
-    env->intr_flag = 0;
-    env->lock_addr = -1;
-    if ((a & 1) == 0) {
-        env->pal_mode = 0;
-        swap_shadow_regs(env);
-    }
-}
-
-void helper_tbia(void)
-{
-    tlb_flush(env, 1);
-}
-
-void helper_tbis(uint64_t p)
-{
-    tlb_flush_page(env, p);
-}
-
-void helper_halt(uint64_t restart)
-{
-    if (restart) {
-        qemu_system_reset_request();
-    } else {
-        qemu_system_shutdown_request();
-    }
-}
-
-uint64_t helper_get_time(void)
-{
-    return qemu_get_clock_ns(rtc_clock);
-}
-
-void helper_set_alarm(uint64_t expire)
-{
-    if (expire) {
-        env->alarm_expire = expire;
-        qemu_mod_timer(env->alarm_timer, expire);
-    } else {
-        qemu_del_timer(env->alarm_timer);
-    }
-}
-#endif
-
-/*****************************************************************************/
-/* Softmmu support */
-#if !defined (CONFIG_USER_ONLY)
-uint64_t helper_ldl_phys(uint64_t p)
-{
-    return (int32_t)ldl_phys(p);
-}
-
-uint64_t helper_ldq_phys(uint64_t p)
-{
-    return ldq_phys(p);
-}
-
-uint64_t helper_ldl_l_phys(uint64_t p)
-{
-    env->lock_addr = p;
-    return env->lock_value = (int32_t)ldl_phys(p);
-}
-
-uint64_t helper_ldq_l_phys(uint64_t p)
-{
-    env->lock_addr = p;
-    return env->lock_value = ldl_phys(p);
-}
-
-void helper_stl_phys(uint64_t p, uint64_t v)
-{
-    stl_phys(p, v);
-}
-
-void helper_stq_phys(uint64_t p, uint64_t v)
-{
-    stq_phys(p, v);
-}
-
-uint64_t helper_stl_c_phys(uint64_t p, uint64_t v)
-{
-    uint64_t ret = 0;
-
-    if (p == env->lock_addr) {
-        int32_t old = ldl_phys(p);
-        if (old == (int32_t)env->lock_value) {
-            stl_phys(p, v);
-            ret = 1;
-        }
-    }
-    env->lock_addr = -1;
-
-    return ret;
-}
-
-uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
-{
-    uint64_t ret = 0;
-
-    if (p == env->lock_addr) {
-        uint64_t old = ldq_phys(p);
-        if (old == env->lock_value) {
-            stq_phys(p, v);
-            ret = 1;
-        }
-    }
-    env->lock_addr = -1;
-
-    return ret;
-}
-
-static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
-                                              int is_user, void *retaddr)
-{
-    uint64_t pc;
-    uint32_t insn;
-
-    do_restore_state(retaddr);
-
-    pc = env->pc;
-    insn = ldl_code(pc);
-
-    env->trap_arg0 = addr;
-    env->trap_arg1 = insn >> 26;                /* opcode */
-    env->trap_arg2 = (insn >> 21) & 31;         /* dest regno */
-    helper_excp(EXCP_UNALIGN, 0);
-}
-
-void QEMU_NORETURN cpu_unassigned_access(CPUAlphaState *env1,
-                                         target_phys_addr_t addr, int is_write,
-                                         int is_exec, int unused, int size)
-{
-    env = env1;
-    env->trap_arg0 = addr;
-    env->trap_arg1 = is_write;
-    dynamic_excp(EXCP_MCHK, 0);
-}
-
-#include "softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-#define ALIGNED_ONLY
-
-#define SHIFT 0
-#include "softmmu_template.h"
-
-#define SHIFT 1
-#include "softmmu_template.h"
-
-#define SHIFT 2
-#include "softmmu_template.h"
-
-#define SHIFT 3
-#include "softmmu_template.h"
-
-/* try to fill the TLB and return an exception if error. If retaddr is
-   NULL, it means that the function was called in C code (i.e. not
-   from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUAlphaState *env1, target_ulong addr, int is_write, int mmu_idx,
-              void *retaddr)
-{
-    CPUAlphaState *saved_env;
-    int ret;
-
-    saved_env = env;
-    env = env1;
-    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx);
-    if (unlikely(ret != 0)) {
-        do_restore_state(retaddr);
-        /* Exception index and error code are already set */
-        cpu_loop_exit(env);
-    }
-    env = saved_env;
-}
-#endif
diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c
new file mode 100644
index 0000000..40ca49c
--- /dev/null
+++ b/target-alpha/sys_helper.c
@@ -0,0 +1,87 @@
+/*
+ *  Helpers for system instructions.
+ *
+ *  Copyright (c) 2007 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "sysemu.h"
+#include "qemu-timer.h"
+
+
+uint64_t helper_load_pcc(CPUAlphaState *env)
+{
+#ifndef CONFIG_USER_ONLY
+    /* In system mode we have access to a decent high-resolution clock.
+       In order to make OS-level time accounting work with the RPCC,
+       present it with a well-timed clock fixed at 250MHz.  */
+    return (((uint64_t)env->pcc_ofs << 32)
+            | (uint32_t)(qemu_get_clock_ns(vm_clock) >> 2));
+#else
+    /* In user-mode, vm_clock doesn't exist.  Just pass through the host cpu
+       clock ticks.  Also, don't bother taking PCC_OFS into account.  */
+    return (uint32_t)cpu_get_real_ticks();
+#endif
+}
+
+/* PALcode support special instructions */
+#ifndef CONFIG_USER_ONLY
+void helper_hw_ret(CPUAlphaState *env, uint64_t a)
+{
+    env->pc = a & ~3;
+    env->intr_flag = 0;
+    env->lock_addr = -1;
+    if ((a & 1) == 0) {
+        env->pal_mode = 0;
+        swap_shadow_regs(env);
+    }
+}
+
+void helper_tbia(CPUAlphaState *env)
+{
+    tlb_flush(env, 1);
+}
+
+void helper_tbis(CPUAlphaState *env, uint64_t p)
+{
+    tlb_flush_page(env, p);
+}
+
+void helper_halt(uint64_t restart)
+{
+    if (restart) {
+        qemu_system_reset_request();
+    } else {
+        qemu_system_shutdown_request();
+    }
+}
+
+uint64_t helper_get_time(void)
+{
+    return qemu_get_clock_ns(rtc_clock);
+}
+
+void helper_set_alarm(CPUAlphaState *env, uint64_t expire)
+{
+    if (expire) {
+        env->alarm_expire = expire;
+        qemu_mod_timer(env->alarm_timer, expire);
+    } else {
+        qemu_del_timer(env->alarm_timer);
+    }
+}
+#endif /* CONFIG_USER_ONLY */
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index b51fe5c..1f4565d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -149,7 +149,7 @@
 
     tmp1 = tcg_const_i32(exception);
     tmp2 = tcg_const_i32(error_code);
-    gen_helper_excp(tmp1, tmp2);
+    gen_helper_excp(cpu_env, tmp1, tmp2);
     tcg_temp_free_i32(tmp2);
     tcg_temp_free_i32(tmp1);
 }
@@ -611,7 +611,8 @@
         tcg_gen_movi_i32(tmp, float_round_down);
         break;
     case QUAL_RM_D:
-        tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUAlphaState, fpcr_dyn_round));
+        tcg_gen_ld8u_i32(tmp, cpu_env,
+                         offsetof(CPUAlphaState, fpcr_dyn_round));
         break;
     }
 
@@ -641,7 +642,8 @@
     tmp = tcg_temp_new_i32();
     if (fn11) {
         /* Underflow is enabled, use the FPCR setting.  */
-        tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUAlphaState, fpcr_flush_to_zero));
+        tcg_gen_ld8u_i32(tmp, cpu_env,
+                         offsetof(CPUAlphaState, fpcr_flush_to_zero));
     } else {
         /* Underflow is disabled, force flush-to-zero.  */
         tcg_gen_movi_i32(tmp, 1);
@@ -659,15 +661,19 @@
 
 static TCGv gen_ieee_input(int reg, int fn11, int is_cmp)
 {
-    TCGv val = tcg_temp_new();
+    TCGv val;
     if (reg == 31) {
-        tcg_gen_movi_i64(val, 0);
-    } else if (fn11 & QUAL_S) {
-        gen_helper_ieee_input_s(val, cpu_fir[reg]);
-    } else if (is_cmp) {
-        gen_helper_ieee_input_cmp(val, cpu_fir[reg]);
+        val = tcg_const_i64(0);
     } else {
-        gen_helper_ieee_input(val, cpu_fir[reg]);
+        if ((fn11 & QUAL_S) == 0) {
+            if (is_cmp) {
+                gen_helper_ieee_input_cmp(cpu_env, cpu_fir[reg]);
+            } else {
+                gen_helper_ieee_input(cpu_env, cpu_fir[reg]);
+            }
+        }
+        val = tcg_temp_new();
+        tcg_gen_mov_i64(val, cpu_fir[reg]);
     }
     return val;
 }
@@ -680,7 +686,7 @@
                     offsetof(CPUAlphaState, fp_status.float_exception_flags));
     tcg_temp_free_i32(zero);
 #else
-    gen_helper_fp_exc_clear();
+    gen_helper_fp_exc_clear(cpu_env);
 #endif
 }
 
@@ -698,7 +704,7 @@
     tcg_gen_ld8u_i32(exc, cpu_env,
                      offsetof(CPUAlphaState, fp_status.float_exception_flags));
 #else
-    gen_helper_fp_exc_get(exc);
+    gen_helper_fp_exc_get(exc, cpu_env);
 #endif
 
     if (ignore) {
@@ -713,9 +719,9 @@
     reg = tcg_const_i32(rc + 32);
 
     if (fn11 & QUAL_S) {
-        gen_helper_fp_exc_raise_s(exc, reg);
+        gen_helper_fp_exc_raise_s(cpu_env, exc, reg);
     } else {
-        gen_helper_fp_exc_raise(exc, reg);
+        gen_helper_fp_exc_raise(cpu_env, exc, reg);
     }
 
     tcg_temp_free_i32(reg);
@@ -784,20 +790,20 @@
     gen_fcvtql(rb, rc);
 }
 
-#define FARITH2(name)                                   \
-static inline void glue(gen_f, name)(int rb, int rc)    \
-{                                                       \
-    if (unlikely(rc == 31)) {                           \
-        return;                                         \
-    }                                                   \
-    if (rb != 31) {                                     \
-        gen_helper_ ## name (cpu_fir[rc], cpu_fir[rb]); \
-    } else {						\
-        TCGv tmp = tcg_const_i64(0);                    \
-        gen_helper_ ## name (cpu_fir[rc], tmp);         \
-        tcg_temp_free(tmp);                             \
-    }                                                   \
-}
+#define FARITH2(name)                                                   \
+    static inline void glue(gen_f, name)(int rb, int rc)                \
+    {                                                                   \
+        if (unlikely(rc == 31)) {                                       \
+            return;                                                     \
+        }                                                               \
+        if (rb != 31) {                                                 \
+            gen_helper_ ## name(cpu_fir[rc], cpu_env, cpu_fir[rb]);     \
+        } else {                                                        \
+            TCGv tmp = tcg_const_i64(0);                                \
+            gen_helper_ ## name(cpu_fir[rc], cpu_env, tmp);             \
+            tcg_temp_free(tmp);                                         \
+        }                                                               \
+    }
 
 /* ??? VAX instruction qualifiers ignored.  */
 FARITH2(sqrtf)
@@ -807,7 +813,8 @@
 FARITH2(cvtqf)
 FARITH2(cvtqg)
 
-static void gen_ieee_arith2(DisasContext *ctx, void (*helper)(TCGv, TCGv),
+static void gen_ieee_arith2(DisasContext *ctx,
+                            void (*helper)(TCGv, TCGv_ptr, TCGv),
                             int rb, int rc, int fn11)
 {
     TCGv vb;
@@ -823,7 +830,7 @@
     gen_fp_exc_clear();
 
     vb = gen_ieee_input(rb, fn11, 0);
-    helper(cpu_fir[rc], vb);
+    helper(cpu_fir[rc], cpu_env, vb);
     tcg_temp_free(vb);
 
     gen_fp_exc_raise(rc, fn11);
@@ -859,18 +866,18 @@
        also do not have integer overflow enabled.  Special case that.  */
     switch (fn11) {
     case QUAL_RM_C:
-        gen_helper_cvttq_c(cpu_fir[rc], vb);
+        gen_helper_cvttq_c(cpu_fir[rc], cpu_env, vb);
         break;
     case QUAL_V | QUAL_RM_C:
     case QUAL_S | QUAL_V | QUAL_RM_C:
         ignore = float_flag_inexact;
         /* FALLTHRU */
     case QUAL_S | QUAL_V | QUAL_I | QUAL_RM_C:
-        gen_helper_cvttq_svic(cpu_fir[rc], vb);
+        gen_helper_cvttq_svic(cpu_fir[rc], cpu_env, vb);
         break;
     default:
         gen_qual_roundmode(ctx, fn11);
-        gen_helper_cvttq(cpu_fir[rc], vb);
+        gen_helper_cvttq(cpu_fir[rc], cpu_env, vb);
         ignore |= (fn11 & QUAL_V ? 0 : float_flag_overflow);
         ignore |= (fn11 & QUAL_I ? 0 : float_flag_inexact);
         break;
@@ -880,7 +887,8 @@
     gen_fp_exc_raise_ignore(rc, fn11, ignore);
 }
 
-static void gen_ieee_intcvt(DisasContext *ctx, void (*helper)(TCGv, TCGv),
+static void gen_ieee_intcvt(DisasContext *ctx,
+                            void (*helper)(TCGv, TCGv_ptr, TCGv),
 			    int rb, int rc, int fn11)
 {
     TCGv vb;
@@ -904,10 +912,10 @@
        inexact handling is requested.  */
     if (fn11 & QUAL_I) {
         gen_fp_exc_clear();
-        helper(cpu_fir[rc], vb);
+        helper(cpu_fir[rc], cpu_env, vb);
         gen_fp_exc_raise(rc, fn11);
     } else {
-        helper(cpu_fir[rc], vb);
+        helper(cpu_fir[rc], cpu_env, vb);
     }
 
     if (rb == 31) {
@@ -999,34 +1007,34 @@
     gen_cpys_internal(ra, rb, rc, 0, 0xFFF0000000000000ULL);
 }
 
-#define FARITH3(name)                                           \
-static inline void glue(gen_f, name)(int ra, int rb, int rc)    \
-{                                                               \
-    TCGv va, vb;                                                \
-                                                                \
-    if (unlikely(rc == 31)) {                                   \
-        return;                                                 \
-    }                                                           \
-    if (ra == 31) {                                             \
-        va = tcg_const_i64(0);                                  \
-    } else {                                                    \
-        va = cpu_fir[ra];                                       \
-    }                                                           \
-    if (rb == 31) {                                             \
-        vb = tcg_const_i64(0);                                  \
-    } else {                                                    \
-        vb = cpu_fir[rb];                                       \
-    }                                                           \
-                                                                \
-    gen_helper_ ## name (cpu_fir[rc], va, vb);                  \
-                                                                \
-    if (ra == 31) {                                             \
-        tcg_temp_free(va);                                      \
-    }                                                           \
-    if (rb == 31) {                                             \
-        tcg_temp_free(vb);                                      \
-    }                                                           \
-}
+#define FARITH3(name)                                                   \
+    static inline void glue(gen_f, name)(int ra, int rb, int rc)        \
+    {                                                                   \
+        TCGv va, vb;                                                    \
+                                                                        \
+        if (unlikely(rc == 31)) {                                       \
+            return;                                                     \
+        }                                                               \
+        if (ra == 31) {                                                 \
+            va = tcg_const_i64(0);                                      \
+        } else {                                                        \
+            va = cpu_fir[ra];                                           \
+        }                                                               \
+        if (rb == 31) {                                                 \
+            vb = tcg_const_i64(0);                                      \
+        } else {                                                        \
+            vb = cpu_fir[rb];                                           \
+        }                                                               \
+                                                                        \
+        gen_helper_ ## name(cpu_fir[rc], cpu_env, va, vb);              \
+                                                                        \
+        if (ra == 31) {                                                 \
+            tcg_temp_free(va);                                          \
+        }                                                               \
+        if (rb == 31) {                                                 \
+            tcg_temp_free(vb);                                          \
+        }                                                               \
+    }
 
 /* ??? VAX instruction qualifiers ignored.  */
 FARITH3(addf)
@@ -1042,7 +1050,7 @@
 FARITH3(cmpgle)
 
 static void gen_ieee_arith3(DisasContext *ctx,
-                            void (*helper)(TCGv, TCGv, TCGv),
+                            void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
                             int ra, int rb, int rc, int fn11)
 {
     TCGv va, vb;
@@ -1059,7 +1067,7 @@
 
     va = gen_ieee_input(ra, fn11, 0);
     vb = gen_ieee_input(rb, fn11, 0);
-    helper(cpu_fir[rc], va, vb);
+    helper(cpu_fir[rc], cpu_env, va, vb);
     tcg_temp_free(va);
     tcg_temp_free(vb);
 
@@ -1082,7 +1090,7 @@
 IEEE_ARITH3(divt)
 
 static void gen_ieee_compare(DisasContext *ctx,
-                             void (*helper)(TCGv, TCGv, TCGv),
+                             void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
                              int ra, int rb, int rc, int fn11)
 {
     TCGv va, vb;
@@ -1097,7 +1105,7 @@
 
     va = gen_ieee_input(ra, fn11, 1);
     vb = gen_ieee_input(rb, fn11, 1);
-    helper(cpu_fir[rc], va, vb);
+    helper(cpu_fir[rc], cpu_env, va, vb);
     tcg_temp_free(va);
     tcg_temp_free(vb);
 
@@ -1388,14 +1396,8 @@
         tcg_temp_free(tmp1);                                          \
     }                                                                 \
 }
-ARITH3(cmpbge)
-ARITH3(addlv)
-ARITH3(sublv)
-ARITH3(addqv)
-ARITH3(subqv)
 ARITH3(umulh)
-ARITH3(mullv)
-ARITH3(mulqv)
+ARITH3(cmpbge)
 ARITH3(minub8)
 ARITH3(minsb8)
 ARITH3(minuw4)
@@ -1406,6 +1408,43 @@
 ARITH3(maxsw4)
 ARITH3(perr)
 
+/* Code to call arith3 helpers */
+#define ARITH3_EX(name)                                                 \
+    static inline void glue(gen_, name)(int ra, int rb, int rc,         \
+                                        int islit, uint8_t lit)         \
+    {                                                                   \
+        if (unlikely(rc == 31)) {                                       \
+            return;                                                     \
+        }                                                               \
+        if (ra != 31) {                                                 \
+            if (islit) {                                                \
+                TCGv tmp = tcg_const_i64(lit);                          \
+                gen_helper_ ## name(cpu_ir[rc], cpu_env,                \
+                                    cpu_ir[ra], tmp);                   \
+                tcg_temp_free(tmp);                                     \
+            } else {                                                    \
+                gen_helper_ ## name(cpu_ir[rc], cpu_env,                \
+                                    cpu_ir[ra], cpu_ir[rb]);            \
+            }                                                           \
+        } else {                                                        \
+            TCGv tmp1 = tcg_const_i64(0);                               \
+            if (islit) {                                                \
+                TCGv tmp2 = tcg_const_i64(lit);                         \
+                gen_helper_ ## name(cpu_ir[rc], cpu_env, tmp1, tmp2);   \
+                tcg_temp_free(tmp2);                                    \
+            } else {                                                    \
+                gen_helper_ ## name(cpu_ir[rc], cpu_env, tmp1, cpu_ir[rb]); \
+            }                                                           \
+            tcg_temp_free(tmp1);                                        \
+        }                                                               \
+    }
+ARITH3_EX(addlv)
+ARITH3_EX(sublv)
+ARITH3_EX(addqv)
+ARITH3_EX(subqv)
+ARITH3_EX(mullv)
+ARITH3_EX(mulqv)
+
 #define MVIOP2(name)                                    \
 static inline void glue(gen_, name)(int rb, int rc)     \
 {                                                       \
@@ -1643,12 +1682,12 @@
     switch (regno) {
     case 255:
         /* TBIA */
-        gen_helper_tbia();
+        gen_helper_tbia(cpu_env);
         break;
 
     case 254:
         /* TBIS */
-        gen_helper_tbis(tmp);
+        gen_helper_tbis(cpu_env, tmp);
         break;
 
     case 253:
@@ -1664,7 +1703,7 @@
 
     case 251:
         /* ALARM */
-        gen_helper_set_alarm(tmp);
+        gen_helper_set_alarm(cpu_env, tmp);
         break;
 
     default:
@@ -2674,17 +2713,17 @@
         case 0x024:
             /* MT_FPCR */
             if (likely(ra != 31))
-                gen_helper_store_fpcr(cpu_fir[ra]);
+                gen_helper_store_fpcr(cpu_env, cpu_fir[ra]);
             else {
                 TCGv tmp = tcg_const_i64(0);
-                gen_helper_store_fpcr(tmp);
+                gen_helper_store_fpcr(cpu_env, tmp);
                 tcg_temp_free(tmp);
             }
             break;
         case 0x025:
             /* MF_FPCR */
             if (likely(ra != 31))
-                gen_helper_load_fpcr(cpu_fir[ra]);
+                gen_helper_load_fpcr(cpu_fir[ra], cpu_env);
             break;
         case 0x02A:
             /* FCMOVEQ */
@@ -2758,11 +2797,11 @@
             if (ra != 31) {
                 if (use_icount) {
                     gen_io_start();
-                    gen_helper_load_pcc(cpu_ir[ra]);
+                    gen_helper_load_pcc(cpu_ir[ra], cpu_env);
                     gen_io_end();
                     ret = EXIT_PC_STALE;
                 } else {
-                    gen_helper_load_pcc(cpu_ir[ra]);
+                    gen_helper_load_pcc(cpu_ir[ra], cpu_env);
                 }
             }
             break;
@@ -2832,11 +2871,11 @@
                 break;
             case 0x2:
                 /* Longword physical access with lock (hw_ldl_l/p) */
-                gen_helper_ldl_l_phys(cpu_ir[ra], addr);
+                gen_helper_ldl_l_phys(cpu_ir[ra], cpu_env, addr);
                 break;
             case 0x3:
                 /* Quadword physical access with lock (hw_ldq_l/p) */
-                gen_helper_ldq_l_phys(cpu_ir[ra], addr);
+                gen_helper_ldq_l_phys(cpu_ir[ra], cpu_env, addr);
                 break;
             case 0x4:
                 /* Longword virtual PTE fetch (hw_ldl/v) */
@@ -3108,10 +3147,10 @@
                    emulation PALcode, so continue to accept it.  */
                 TCGv tmp = tcg_temp_new();
                 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
-                gen_helper_hw_ret(tmp);
+                gen_helper_hw_ret(cpu_env, tmp);
                 tcg_temp_free(tmp);
             } else {
-                gen_helper_hw_ret(cpu_ir[rb]);
+                gen_helper_hw_ret(cpu_env, cpu_ir[rb]);
             }
             ret = EXIT_PC_UPDATED;
             break;
@@ -3145,11 +3184,11 @@
                 break;
             case 0x2:
                 /* Longword physical access with lock */
-                gen_helper_stl_c_phys(val, addr, val);
+                gen_helper_stl_c_phys(val, cpu_env, addr, val);
                 break;
             case 0x3:
                 /* Quadword physical access with lock */
-                gen_helper_stq_c_phys(val, addr, val);
+                gen_helper_stq_c_phys(val, cpu_env, addr, val);
                 break;
             case 0x4:
                 /* Longword virtual access */
@@ -3385,7 +3424,7 @@
         }
         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
             gen_io_start();
-        insn = ldl_code(ctx.pc);
+        insn = cpu_ldl_code(env, ctx.pc);
         num_insns++;
 
 	if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
@@ -3513,7 +3552,8 @@
 #if defined (CONFIG_USER_ONLY)
     env->ps = PS_USER_MODE;
     cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
-                               | FPCR_UNFD | FPCR_INED | FPCR_DNOD));
+                               | FPCR_UNFD | FPCR_INED | FPCR_DNOD
+                               | FPCR_DYN_NORMAL));
 #endif
     env->lock_addr = -1;
     env->fen = 1;
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 442f684..76fb451 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -1,7 +1,7 @@
 #include "def-helper.h"
 
-DEF_HELPER_2(raise_exception_err, void, i32, int)
-DEF_HELPER_1(raise_exception, void, i32)
+DEF_HELPER_2(raise_exception_err, noreturn, i32, int)
+DEF_HELPER_1(raise_exception, noreturn, i32)
 
 #ifdef TARGET_MIPS64
 DEF_HELPER_3(ldl, tl, tl, tl, int)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 3a20731..ce01225 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2292,7 +2292,8 @@
 
 #if !defined(CONFIG_USER_ONLY)
 
-static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
+static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
+                                              int is_user, void *retaddr);
 
 #define MMUSUFFIX _mmu
 #define ALIGNED_ONLY
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 1025752..885ad45 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -699,8 +699,9 @@
 void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit);
 trap_state* cpu_tsptr(CPUSPARCState* env);
 #endif
-void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
-                         int is_user, void *retaddr);
+void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, target_ulong addr,
+                                       int is_write, int is_user,
+                                       void *retaddr);
 
 #define TB_FLAG_FPU_ENABLED (1 << 4)
 #define TB_FLAG_AM_ENABLED (1 << 5)
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index c4d6225..e3c7fdd 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -78,7 +78,7 @@
 DEF_HELPER_1(fcmpeq_fcc2, void, env)
 DEF_HELPER_1(fcmpeq_fcc3, void, env)
 #endif
-DEF_HELPER_2(raise_exception, void, env, int)
+DEF_HELPER_2(raise_exception, noreturn, env, int)
 #define F_HELPER_0_1(name) DEF_HELPER_1(f ## name, void, env)
 
 DEF_HELPER_3(faddd, f64, env, f64, f64)
diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c
index 11fb9f5..cb73c44 100644
--- a/target-sparc/mmu_helper.c
+++ b/target-sparc/mmu_helper.c
@@ -150,18 +150,17 @@
                 case 3: /* Reserved */
                     return (3 << 8) | (4 << 2);
                 case 2: /* L3 PTE */
-                    page_offset = (address & TARGET_PAGE_MASK) &
-                        (TARGET_PAGE_SIZE - 1);
+                    page_offset = 0;
                 }
                 *page_size = TARGET_PAGE_SIZE;
                 break;
             case 2: /* L2 PTE */
-                page_offset = address & 0x3ffff;
+                page_offset = address & 0x3f000;
                 *page_size = 0x40000;
             }
             break;
         case 2: /* L1 PTE */
-            page_offset = address & 0xffffff;
+            page_offset = address & 0xfff000;
             *page_size = 0x1000000;
         }
     }
@@ -206,11 +205,11 @@
     target_ulong page_size;
     int error_code = 0, prot, access_index;
 
+    address &= TARGET_PAGE_MASK;
     error_code = get_physical_address(env, &paddr, &prot, &access_index,
                                       address, rw, mmu_idx, &page_size);
+    vaddr = address;
     if (error_code == 0) {
-        vaddr = address & TARGET_PAGE_MASK;
-        paddr &= TARGET_PAGE_MASK;
 #ifdef DEBUG_MMU
         printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
                TARGET_FMT_lx "\n", address, paddr, vaddr);
@@ -230,7 +229,6 @@
            permissions. If no mapping is available, redirect accesses to
            neverland. Fake/overridden mappings will be flushed when
            switching to normal mode. */
-        vaddr = address & TARGET_PAGE_MASK;
         prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
         tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
         return 0;
@@ -704,17 +702,16 @@
 int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
                                int mmu_idx)
 {
-    target_ulong virt_addr, vaddr;
+    target_ulong vaddr;
     target_phys_addr_t paddr;
     target_ulong page_size;
     int error_code = 0, prot, access_index;
 
+    address &= TARGET_PAGE_MASK;
     error_code = get_physical_address(env, &paddr, &prot, &access_index,
                                       address, rw, mmu_idx, &page_size);
     if (error_code == 0) {
-        virt_addr = address & TARGET_PAGE_MASK;
-        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
-                             (TARGET_PAGE_SIZE - 1));
+        vaddr = address;
 
         trace_mmu_helper_mmu_fault(address, paddr, mmu_idx, env->tl,
                                    env->dmmu.mmu_primary_context,
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index e579ef0..2885212 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -336,7 +336,7 @@
 #define INSN_COMIBF     (INSN_OP(0x23))
 
 /* supplied by libgcc */
-extern void *__canonicalize_funcptr_for_compare(void *);
+extern void *__canonicalize_funcptr_for_compare(const void *);
 
 static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
 {
@@ -628,7 +628,7 @@
     tcg_out_shd(s, ret, arg, temp, 8);    /* ret =  DCBA */
 }
 
-static void tcg_out_call(TCGContext *s, void *func)
+static void tcg_out_call(TCGContext *s, const void *func)
 {
     tcg_target_long val, hi, lo, disp;
 
@@ -1661,23 +1661,18 @@
     TCG_REG_R18
 };
 
+#define FRAME_SIZE ((-TCG_TARGET_CALL_STACK_OFFSET \
+                     + TCG_TARGET_STATIC_CALL_ARGS_SIZE \
+                     + ARRAY_SIZE(tcg_target_callee_save_regs) * 4 \
+                     + CPU_TEMP_BUF_NLONGS * sizeof(long) \
+                     + TCG_TARGET_STACK_ALIGN - 1) \
+                    & -TCG_TARGET_STACK_ALIGN)
+
 static void tcg_target_qemu_prologue(TCGContext *s)
 {
     int frame_size, i;
 
-    /* Allocate space for the fixed frame marker.  */
-    frame_size = -TCG_TARGET_CALL_STACK_OFFSET;
-    frame_size += TCG_TARGET_STATIC_CALL_ARGS_SIZE;
-
-    /* Allocate space for the saved registers.  */
-    frame_size += ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
-
-    /* Allocate space for the TCG temps. */
-    frame_size += CPU_TEMP_BUF_NLONGS * sizeof(long);
-
-    /* Align the allocated space.  */
-    frame_size = ((frame_size + TCG_TARGET_STACK_ALIGN - 1)
-                  & -TCG_TARGET_STACK_ALIGN);
+    frame_size = FRAME_SIZE;
 
     /* The return address is stored in the caller's frame.  */
     tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_CALL_STACK, -20);
@@ -1752,3 +1747,81 @@
 
     tcg_add_target_add_op_defs(hppa_op_defs);
 }
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t id;
+    uint8_t version;
+    char augmentation[1];
+    uint8_t code_align;
+    uint8_t data_align;
+    uint8_t return_column;
+} DebugFrameCIE;
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t cie_offset;
+    tcg_target_long func_start __attribute__((packed));
+    tcg_target_long func_len __attribute__((packed));
+    uint8_t def_cfa[4];
+    uint8_t ret_ofs[3];
+    uint8_t reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
+} DebugFrameFDE;
+
+typedef struct {
+    DebugFrameCIE cie;
+    DebugFrameFDE fde;
+} DebugFrame;
+
+#define ELF_HOST_MACHINE  EM_PARISC
+#define ELF_HOST_FLAGS    EFA_PARISC_1_1
+
+/* ??? BFD (and thus GDB) wants very much to distinguish between HPUX
+   and other extensions.  We don't really care, but if we don't set this
+   to *something* then the object file won't be properly matched.  */
+#define ELF_OSABI         ELFOSABI_LINUX
+
+static DebugFrame debug_frame = {
+    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+    .cie.id = -1,
+    .cie.version = 1,
+    .cie.code_align = 1,
+    .cie.data_align = 1,
+    .cie.return_column = 2,
+
+    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
+    .fde.def_cfa = {
+        0x12, 30,                       /* DW_CFA_def_cfa_sf sp, ... */
+        (-FRAME_SIZE & 0x7f) | 0x80,     /* ... sleb128 -FRAME_SIZE */
+        (-FRAME_SIZE >> 7) & 0x7f
+    },
+    .fde.ret_ofs = {
+        0x11, 2, (-20 / 4) & 0x7f       /* DW_CFA_offset_extended_sf r2, 20 */
+    },
+    .fde.reg_ofs = {
+        /* This must match the ordering in tcg_target_callee_save_regs.  */
+        0x80 + 4, 0,                    /* DW_CFA_offset r4, 0 */
+        0x80 + 5, 4,                    /* DW_CFA_offset r5, 4 */
+        0x80 + 6, 8,                    /* DW_CFA_offset r6, 8 */
+        0x80 + 7, 12,                    /* ... */
+        0x80 + 8, 16,
+        0x80 + 9, 20,
+        0x80 + 10, 24,
+        0x80 + 11, 28,
+        0x80 + 12, 32,
+        0x80 + 13, 36,
+        0x80 + 14, 40,
+        0x80 + 15, 44,
+        0x80 + 16, 48,
+        0x80 + 17, 52,
+        0x80 + 18, 56,
+    }
+};
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+    debug_frame.fde.func_start = (tcg_target_long) buf;
+    debug_frame.fde.func_len = buf_size;
+
+    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
+}
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 43a51a1..871a7e7 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1989,22 +1989,29 @@
 #endif
 };
 
+/* Compute frame size via macros, to share between tcg_target_qemu_prologue
+   and tcg_register_jit.  */
+
+#define PUSH_SIZE \
+    ((1 + ARRAY_SIZE(tcg_target_callee_save_regs)) \
+     * (TCG_TARGET_REG_BITS / 8))
+
+#define FRAME_SIZE \
+    ((PUSH_SIZE \
+      + TCG_STATIC_CALL_ARGS_SIZE \
+      + CPU_TEMP_BUF_NLONGS * sizeof(long) \
+      + TCG_TARGET_STACK_ALIGN - 1) \
+     & ~(TCG_TARGET_STACK_ALIGN - 1))
+
 /* Generate global QEMU prologue and epilogue code */
 static void tcg_target_qemu_prologue(TCGContext *s)
 {
-    int i, frame_size, push_size, stack_addend;
+    int i, stack_addend;
 
     /* TB prologue */
 
     /* Reserve some stack space, also for TCG temps.  */
-    push_size = 1 + ARRAY_SIZE(tcg_target_callee_save_regs);
-    push_size *= TCG_TARGET_REG_BITS / 8;
-
-    frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE +
-        CPU_TEMP_BUF_NLONGS * sizeof(long);
-    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
-        ~(TCG_TARGET_STACK_ALIGN - 1);
-    stack_addend = frame_size - push_size;
+    stack_addend = FRAME_SIZE - PUSH_SIZE;
     tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
                   CPU_TEMP_BUF_NLONGS * sizeof(long));
 
@@ -2070,3 +2077,92 @@
 
     tcg_add_target_add_op_defs(x86_op_defs);
 }
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t id;
+    uint8_t version;
+    char augmentation[1];
+    uint8_t code_align;
+    uint8_t data_align;
+    uint8_t return_column;
+} DebugFrameCIE;
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t cie_offset;
+    tcg_target_long func_start __attribute__((packed));
+    tcg_target_long func_len __attribute__((packed));
+    uint8_t def_cfa[4];
+    uint8_t reg_ofs[14];
+} DebugFrameFDE;
+
+typedef struct {
+    DebugFrameCIE cie;
+    DebugFrameFDE fde;
+} DebugFrame;
+
+#if TCG_TARGET_REG_BITS == 64
+#define ELF_HOST_MACHINE EM_X86_64
+static DebugFrame debug_frame = {
+    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+    .cie.id = -1,
+    .cie.version = 1,
+    .cie.code_align = 1,
+    .cie.data_align = 0x78,             /* sleb128 -8 */
+    .cie.return_column = 16,
+
+    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
+    .fde.def_cfa = {
+        12, 7,                          /* DW_CFA_def_cfa %rsp, ... */
+        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
+        (FRAME_SIZE >> 7)
+    },
+    .fde.reg_ofs = {
+        0x90, 1,                        /* DW_CFA_offset, %rip, -8 */
+        /* The following ordering must match tcg_target_callee_save_regs.  */
+        0x86, 2,                        /* DW_CFA_offset, %rbp, -16 */
+        0x83, 3,                        /* DW_CFA_offset, %rbx, -24 */
+        0x8c, 4,                        /* DW_CFA_offset, %r12, -32 */
+        0x8d, 5,                        /* DW_CFA_offset, %r13, -40 */
+        0x8e, 6,                        /* DW_CFA_offset, %r14, -48 */
+        0x8f, 7,                        /* DW_CFA_offset, %r15, -56 */
+    }
+};
+#else
+#define ELF_HOST_MACHINE EM_386
+static DebugFrame debug_frame = {
+    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+    .cie.id = -1,
+    .cie.version = 1,
+    .cie.code_align = 1,
+    .cie.data_align = 0x7c,             /* sleb128 -4 */
+    .cie.return_column = 8,
+
+    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
+    .fde.def_cfa = {
+        12, 4,                          /* DW_CFA_def_cfa %esp, ... */
+        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
+        (FRAME_SIZE >> 7)
+    },
+    .fde.reg_ofs = {
+        0x88, 1,                        /* DW_CFA_offset, %eip, -4 */
+        /* The following ordering must match tcg_target_callee_save_regs.  */
+        0x85, 2,                        /* DW_CFA_offset, %ebp, -8 */
+        0x83, 3,                        /* DW_CFA_offset, %ebx, -12 */
+        0x86, 4,                        /* DW_CFA_offset, %esi, -16 */
+        0x87, 5,                        /* DW_CFA_offset, %edi, -20 */
+    }
+};
+#endif
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+    /* We're expecting a 2 byte uleb128 encoded value.  */
+    assert(FRAME_SIZE >> 14 == 0);
+
+    debug_frame.fde.func_start = (tcg_target_long) buf;
+    debug_frame.fde.func_len = buf_size;
+
+    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
+}
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 491c979..247a278 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -1624,3 +1624,66 @@
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_O7);
     tcg_add_target_add_op_defs(sparc_op_defs);
 }
+
+#if TCG_TARGET_REG_BITS == 64
+# define ELF_HOST_MACHINE  EM_SPARCV9
+#elif defined(__sparc_v8plus__)
+# define ELF_HOST_MACHINE  EM_SPARC32PLUS
+# define ELF_HOST_FLAGS    EF_SPARC_32PLUS
+#else
+# define ELF_HOST_MACHINE  EM_SPARC
+#endif
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t id;
+    uint8_t version;
+    char augmentation[1];
+    uint8_t code_align;
+    uint8_t data_align;
+    uint8_t return_column;
+} DebugFrameCIE;
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t cie_offset;
+    tcg_target_long func_start __attribute__((packed));
+    tcg_target_long func_len __attribute__((packed));
+    uint8_t def_cfa[TCG_TARGET_REG_BITS == 64 ? 4 : 2];
+    uint8_t win_save;
+    uint8_t ret_save[3];
+} DebugFrameFDE;
+
+typedef struct {
+    DebugFrameCIE cie;
+    DebugFrameFDE fde;
+} DebugFrame;
+
+static DebugFrame debug_frame = {
+    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+    .cie.id = -1,
+    .cie.version = 1,
+    .cie.code_align = 1,
+    .cie.data_align = -sizeof(void *) & 0x7f,
+    .cie.return_column = 15,            /* o7 */
+
+    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
+    .fde.def_cfa = {
+#if TCG_TARGET_REG_BITS == 64
+        12, 30,                         /* DW_CFA_def_cfa i6, 2047 */
+        (2047 & 0x7f) | 0x80, (2047 >> 7)
+#else
+        13, 30                          /* DW_CFA_def_cfa_register i6 */
+#endif
+    },
+    .fde.win_save = 0x2d,               /* DW_CFA_GNU_window_save */
+    .fde.ret_save = { 9, 15, 31 },      /* DW_CFA_register o7, i7 */
+};
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+    debug_frame.fde.func_start = (tcg_target_long) buf;
+    debug_frame.fde.func_len = buf_size;
+
+    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
+}
diff --git a/tcg/tcg.c b/tcg/tcg.c
index ccfcd1a..ab589c7 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -28,6 +28,9 @@
 
 #include "config.h"
 
+/* Define to jump the ELF file used to communicate with GDB.  */
+#undef DEBUG_JIT
+
 #if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
 /* define it to suppress various consistency checks (faster) */
 #define NDEBUG
@@ -45,6 +48,18 @@
 #include "cpu.h"
 
 #include "tcg-op.h"
+
+#if TCG_TARGET_REG_BITS == 64
+# define ELF_CLASS  ELFCLASS64
+#else
+# define ELF_CLASS  ELFCLASS32
+#endif
+#ifdef HOST_WORDS_BIGENDIAN
+# define ELF_DATA   ELFDATA2MSB
+#else
+# define ELF_DATA   ELFDATA2LSB
+#endif
+
 #include "elf.h"
 
 #if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
@@ -57,6 +72,10 @@
 static void patch_reloc(uint8_t *code_ptr, int type, 
                         tcg_target_long value, tcg_target_long addend);
 
+static void tcg_register_jit_int(void *buf, size_t size,
+                                 void *debug_frame, size_t debug_frame_size)
+    __attribute__((unused));
+
 /* Forward declarations for functions declared and used in tcg-target.c. */
 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
 static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
@@ -2231,3 +2250,267 @@
     cpu_fprintf(f, "[TCG profiler not compiled]\n");
 }
 #endif
+
+#ifdef ELF_HOST_MACHINE
+/* In order to use this feature, the backend needs to do three things:
+
+   (1) Define ELF_HOST_MACHINE to indicate both what value to
+       put into the ELF image and to indicate support for the feature.
+
+   (2) Define tcg_register_jit.  This should create a buffer containing
+       the contents of a .debug_frame section that describes the post-
+       prologue unwind info for the tcg machine.
+
+   (3) Call tcg_register_jit_int, with the constructed .debug_frame.
+*/
+
+/* Begin GDB interface.  THE FOLLOWING MUST MATCH GDB DOCS.  */
+typedef enum {
+    JIT_NOACTION = 0,
+    JIT_REGISTER_FN,
+    JIT_UNREGISTER_FN
+} jit_actions_t;
+
+struct jit_code_entry {
+    struct jit_code_entry *next_entry;
+    struct jit_code_entry *prev_entry;
+    const void *symfile_addr;
+    uint64_t symfile_size;
+};
+
+struct jit_descriptor {
+    uint32_t version;
+    uint32_t action_flag;
+    struct jit_code_entry *relevant_entry;
+    struct jit_code_entry *first_entry;
+};
+
+void __jit_debug_register_code(void) __attribute__((noinline));
+void __jit_debug_register_code(void)
+{
+    asm("");
+}
+
+/* Must statically initialize the version, because GDB may check
+   the version before we can set it.  */
+struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
+
+/* End GDB interface.  */
+
+static int find_string(const char *strtab, const char *str)
+{
+    const char *p = strtab + 1;
+
+    while (1) {
+        if (strcmp(p, str) == 0) {
+            return p - strtab;
+        }
+        p += strlen(p) + 1;
+    }
+}
+
+static void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
+                                 void *debug_frame, size_t debug_frame_size)
+{
+    struct __attribute__((packed)) DebugInfo {
+        uint32_t  len;
+        uint16_t  version;
+        uint32_t  abbrev;
+        uint8_t   ptr_size;
+        uint8_t   cu_die;
+        uint16_t  cu_lang;
+        uintptr_t cu_low_pc;
+        uintptr_t cu_high_pc;
+        uint8_t   fn_die;
+        char      fn_name[16];
+        uintptr_t fn_low_pc;
+        uintptr_t fn_high_pc;
+        uint8_t   cu_eoc;
+    };
+
+    struct ElfImage {
+        ElfW(Ehdr) ehdr;
+        ElfW(Phdr) phdr;
+        ElfW(Shdr) shdr[7];
+        ElfW(Sym)  sym[2];
+        struct DebugInfo di;
+        uint8_t    da[24];
+        char       str[80];
+    };
+
+    struct ElfImage *img;
+
+    static const struct ElfImage img_template = {
+        .ehdr = {
+            .e_ident[EI_MAG0] = ELFMAG0,
+            .e_ident[EI_MAG1] = ELFMAG1,
+            .e_ident[EI_MAG2] = ELFMAG2,
+            .e_ident[EI_MAG3] = ELFMAG3,
+            .e_ident[EI_CLASS] = ELF_CLASS,
+            .e_ident[EI_DATA] = ELF_DATA,
+            .e_ident[EI_VERSION] = EV_CURRENT,
+            .e_type = ET_EXEC,
+            .e_machine = ELF_HOST_MACHINE,
+            .e_version = EV_CURRENT,
+            .e_phoff = offsetof(struct ElfImage, phdr),
+            .e_shoff = offsetof(struct ElfImage, shdr),
+            .e_ehsize = sizeof(ElfW(Shdr)),
+            .e_phentsize = sizeof(ElfW(Phdr)),
+            .e_phnum = 1,
+            .e_shentsize = sizeof(ElfW(Shdr)),
+            .e_shnum = ARRAY_SIZE(img->shdr),
+            .e_shstrndx = ARRAY_SIZE(img->shdr) - 1,
+#ifdef ELF_HOST_FLAGS
+            .e_flags = ELF_HOST_FLAGS,
+#endif
+#ifdef ELF_OSABI
+            .e_ident[EI_OSABI] = ELF_OSABI,
+#endif
+        },
+        .phdr = {
+            .p_type = PT_LOAD,
+            .p_flags = PF_X,
+        },
+        .shdr = {
+            [0] = { .sh_type = SHT_NULL },
+            /* Trick: The contents of code_gen_buffer are not present in
+               this fake ELF file; that got allocated elsewhere.  Therefore
+               we mark .text as SHT_NOBITS (similar to .bss) so that readers
+               will not look for contents.  We can record any address.  */
+            [1] = { /* .text */
+                .sh_type = SHT_NOBITS,
+                .sh_flags = SHF_EXECINSTR | SHF_ALLOC,
+            },
+            [2] = { /* .debug_info */
+                .sh_type = SHT_PROGBITS,
+                .sh_offset = offsetof(struct ElfImage, di),
+                .sh_size = sizeof(struct DebugInfo),
+            },
+            [3] = { /* .debug_abbrev */
+                .sh_type = SHT_PROGBITS,
+                .sh_offset = offsetof(struct ElfImage, da),
+                .sh_size = sizeof(img->da),
+            },
+            [4] = { /* .debug_frame */
+                .sh_type = SHT_PROGBITS,
+                .sh_offset = sizeof(struct ElfImage),
+            },
+            [5] = { /* .symtab */
+                .sh_type = SHT_SYMTAB,
+                .sh_offset = offsetof(struct ElfImage, sym),
+                .sh_size = sizeof(img->sym),
+                .sh_info = 1,
+                .sh_link = ARRAY_SIZE(img->shdr) - 1,
+                .sh_entsize = sizeof(ElfW(Sym)),
+            },
+            [6] = { /* .strtab */
+                .sh_type = SHT_STRTAB,
+                .sh_offset = offsetof(struct ElfImage, str),
+                .sh_size = sizeof(img->str),
+            }
+        },
+        .sym = {
+            [1] = { /* code_gen_buffer */
+                .st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC),
+                .st_shndx = 1,
+            }
+        },
+        .di = {
+            .len = sizeof(struct DebugInfo) - 4,
+            .version = 2,
+            .ptr_size = sizeof(void *),
+            .cu_die = 1,
+            .cu_lang = 0x8001,  /* DW_LANG_Mips_Assembler */
+            .fn_die = 2,
+            .fn_name = "code_gen_buffer"
+        },
+        .da = {
+            1,          /* abbrev number (the cu) */
+            0x11, 1,    /* DW_TAG_compile_unit, has children */
+            0x13, 0x5,  /* DW_AT_language, DW_FORM_data2 */
+            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
+            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
+            0, 0,       /* end of abbrev */
+            2,          /* abbrev number (the fn) */
+            0x2e, 0,    /* DW_TAG_subprogram, no children */
+            0x3, 0x8,   /* DW_AT_name, DW_FORM_string */
+            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
+            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
+            0, 0,       /* end of abbrev */
+            0           /* no more abbrev */
+        },
+        .str = "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
+               ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
+    };
+
+    /* We only need a single jit entry; statically allocate it.  */
+    static struct jit_code_entry one_entry;
+
+    uintptr_t buf = (uintptr_t)buf_ptr;
+    size_t img_size = sizeof(struct ElfImage) + debug_frame_size;
+
+    img = g_malloc(img_size);
+    *img = img_template;
+    memcpy(img + 1, debug_frame, debug_frame_size);
+
+    img->phdr.p_vaddr = buf;
+    img->phdr.p_paddr = buf;
+    img->phdr.p_memsz = buf_size;
+
+    img->shdr[1].sh_name = find_string(img->str, ".text");
+    img->shdr[1].sh_addr = buf;
+    img->shdr[1].sh_size = buf_size;
+
+    img->shdr[2].sh_name = find_string(img->str, ".debug_info");
+    img->shdr[3].sh_name = find_string(img->str, ".debug_abbrev");
+
+    img->shdr[4].sh_name = find_string(img->str, ".debug_frame");
+    img->shdr[4].sh_size = debug_frame_size;
+
+    img->shdr[5].sh_name = find_string(img->str, ".symtab");
+    img->shdr[6].sh_name = find_string(img->str, ".strtab");
+
+    img->sym[1].st_name = find_string(img->str, "code_gen_buffer");
+    img->sym[1].st_value = buf;
+    img->sym[1].st_size = buf_size;
+
+    img->di.cu_low_pc = buf;
+    img->di.cu_high_pc = buf_size;
+    img->di.fn_low_pc = buf;
+    img->di.fn_high_pc = buf_size;
+
+#ifdef DEBUG_JIT
+    /* Enable this block to be able to debug the ELF image file creation.
+       One can use readelf, objdump, or other inspection utilities.  */
+    {
+        FILE *f = fopen("/tmp/qemu.jit", "w+b");
+        if (f) {
+            if (fwrite(img, img_size, 1, f) != img_size) {
+                /* Avoid stupid unused return value warning for fwrite.  */
+            }
+            fclose(f);
+        }
+    }
+#endif
+
+    one_entry.symfile_addr = img;
+    one_entry.symfile_size = img_size;
+
+    __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
+    __jit_debug_descriptor.relevant_entry = &one_entry;
+    __jit_debug_descriptor.first_entry = &one_entry;
+    __jit_debug_register_code();
+}
+#else
+/* No support for the feature.  Provide the entry point expected by exec.c,
+   and implement the internal function we declared earlier.  */
+
+static void tcg_register_jit_int(void *buf, size_t size,
+                                 void *debug_frame, size_t debug_frame_size)
+{
+}
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+}
+#endif /* ELF_HOST_MACHINE */
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 5f6c647..a83bdddb 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -586,3 +586,5 @@
 # define tcg_qemu_tb_exec(env, tb_ptr) \
     ((tcg_target_ulong (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
 #endif
+
+void tcg_register_jit(void *buf, size_t buf_size);
diff --git a/test-qmp-commands.c b/test-qmp-commands.c
index fa5a7bd..60cbf01 100644
--- a/test-qmp-commands.c
+++ b/test-qmp-commands.c
@@ -46,7 +46,6 @@
     resp = qmp_dispatch(QOBJECT(req));
     assert(resp != NULL);
     assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
-    g_print("\nresp: %s\n", qstring_get_str(qobject_to_json(resp)));
 
     qobject_decref(resp);
     QDECREF(req);
@@ -63,7 +62,6 @@
     resp = qmp_dispatch(QOBJECT(req));
     assert(resp != NULL);
     assert(qdict_haskey(qobject_to_qdict(resp), "error"));
-    g_print("\nresp: %s\n", qstring_get_str(qobject_to_json_pretty(resp)));
 
     qobject_decref(resp);
     QDECREF(req);
@@ -92,7 +90,6 @@
     resp = qmp_dispatch(QOBJECT(req));
     assert(resp != NULL);
     assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
-    g_print("\nresp: %s\n", qstring_get_str(qobject_to_json_pretty(resp)));
 
     qobject_decref(resp);
     QDECREF(req);
diff --git a/test-qmp-input-strict.c b/test-qmp-input-strict.c
new file mode 100644
index 0000000..f6df8cb
--- /dev/null
+++ b/test-qmp-input-strict.c
@@ -0,0 +1,234 @@
+/*
+ * QMP Input Visitor unit-tests (strict mode).
+ *
+ * Copyright (C) 2011-2012 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *  Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+
+#include "qapi/qmp-input-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestInputVisitorData {
+    QObject *obj;
+    QmpInputVisitor *qiv;
+} TestInputVisitorData;
+
+static void validate_teardown(TestInputVisitorData *data,
+                               const void *unused)
+{
+    qobject_decref(data->obj);
+    data->obj = NULL;
+
+    if (data->qiv) {
+        qmp_input_visitor_cleanup(data->qiv);
+        data->qiv = NULL;
+    }
+}
+
+/* This is provided instead of a test setup function so that the JSON
+   string used by the tests are kept in the test functions (and not
+   int main()) */
+static GCC_FMT_ATTR(2, 3)
+Visitor *validate_test_init(TestInputVisitorData *data,
+                             const char *json_string, ...)
+{
+    Visitor *v;
+    va_list ap;
+
+    va_start(ap, json_string);
+    data->obj = qobject_from_jsonv(json_string, &ap);
+    va_end(ap);
+
+    g_assert(data->obj != NULL);
+
+    data->qiv = qmp_input_visitor_new_strict(data->obj);
+    g_assert(data->qiv != NULL);
+
+    v = qmp_input_get_visitor(data->qiv);
+    g_assert(v != NULL);
+
+    return v;
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_validate_struct(TestInputVisitorData *data,
+                                  const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_free(p->string);
+    g_free(p);
+}
+
+static void test_validate_struct_nested(TestInputVisitorData *data,
+                                         const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    qapi_free_UserDefNested(udp);
+}
+
+static void test_validate_list(TestInputVisitorData *data,
+                                const void *unused)
+{
+    UserDefOneList *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    qapi_free_UserDefOneList(head);
+}
+
+static void test_validate_union(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    UserDefUnion *tmp = NULL;
+    Visitor *v;
+    Error *errp = NULL;
+
+    v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
+
+    visit_type_UserDefUnion(v, &tmp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    qapi_free_UserDefUnion(tmp);
+}
+
+static void test_validate_fail_struct(TestInputVisitorData *data,
+                                       const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    if (p) {
+        g_free(p->string);
+    }
+    g_free(p);
+}
+
+static void test_validate_fail_struct_nested(TestInputVisitorData *data,
+                                              const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    qapi_free_UserDefNested(udp);
+}
+
+static void test_validate_fail_list(TestInputVisitorData *data,
+                                     const void *unused)
+{
+    UserDefOneList *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    qapi_free_UserDefOneList(head);
+}
+
+static void test_validate_fail_union(TestInputVisitorData *data,
+                                      const void *unused)
+{
+    UserDefUnion *tmp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 }, 'extra': 'yyy' }");
+
+    visit_type_UserDefUnion(v, &tmp, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    qapi_free_UserDefUnion(tmp);
+}
+
+static void validate_test_add(const char *testpath,
+                               TestInputVisitorData *data,
+                               void (*test_func)(TestInputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+               validate_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestInputVisitorData testdata;
+
+    g_test_init(&argc, &argv, NULL);
+
+    validate_test_add("/visitor/input-strict/pass/struct",
+                       &testdata, test_validate_struct);
+    validate_test_add("/visitor/input-strict/pass/struct-nested",
+                       &testdata, test_validate_struct_nested);
+    validate_test_add("/visitor/input-strict/pass/list",
+                       &testdata, test_validate_list);
+    validate_test_add("/visitor/input-strict/pass/union",
+                       &testdata, test_validate_union);
+    validate_test_add("/visitor/input-strict/fail/struct",
+                       &testdata, test_validate_fail_struct);
+    validate_test_add("/visitor/input-strict/fail/struct-nested",
+                       &testdata, test_validate_fail_struct_nested);
+    validate_test_add("/visitor/input-strict/fail/list",
+                       &testdata, test_validate_fail_list);
+    validate_test_add("/visitor/input-strict/fail/union",
+                       &testdata, test_validate_fail_union);
+
+    g_test_run();
+
+    return 0;
+}
diff --git a/test-qmp-input-visitor.c b/test-qmp-input-visitor.c
index 1996e49..c30fdc4 100644
--- a/test-qmp-input-visitor.c
+++ b/test-qmp-input-visitor.c
@@ -258,6 +258,23 @@
                visitor_input_teardown);
 }
 
+static void test_visitor_in_errors(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    g_assert(p->string == NULL);
+
+    g_free(p->string);
+    g_free(p);
+}
+
 int main(int argc, char **argv)
 {
     TestInputVisitorData in_visitor_data;
@@ -282,6 +299,8 @@
                             &in_visitor_data, test_visitor_in_list);
     input_visitor_test_add("/visitor/input/union",
                             &in_visitor_data, test_visitor_in_union);
+    input_visitor_test_add("/visitor/input/errors",
+                            &in_visitor_data, test_visitor_in_errors);
 
     g_test_run();
 
diff --git a/test-qmp-output-visitor.c b/test-qmp-output-visitor.c
index 4d6c4d4..24a6359 100644
--- a/test-qmp-output-visitor.c
+++ b/test-qmp-output-visitor.c
@@ -274,6 +274,24 @@
     qapi_free_UserDefNested(ud2);
 }
 
+static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
+                                           const void *unused)
+{
+    EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
+    UserDefOne u = { 0 }, *pu = &u;
+    Error *errp;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
+        errp = NULL;
+        u.has_enum1 = true;
+        u.enum1 = bad_values[i];
+        visit_type_UserDefOne(data->ov, &pu, "unused", &errp);
+        g_assert(error_is_set(&errp) == true);
+        error_free(errp);
+    }
+}
+
 typedef struct TestStructList
 {
     TestStruct *value;
@@ -444,6 +462,8 @@
                             &out_visitor_data, test_visitor_out_struct);
     output_visitor_test_add("/visitor/output/struct-nested",
                             &out_visitor_data, test_visitor_out_struct_nested);
+    output_visitor_test_add("/visitor/output/struct-errors",
+                            &out_visitor_data, test_visitor_out_struct_errors);
     output_visitor_test_add("/visitor/output/list",
                             &out_visitor_data, test_visitor_out_list);
     output_visitor_test_add("/visitor/output/list-qapi-free",
diff --git a/tests/Makefile b/tests/Makefile
index c78ade1..2a2fff7 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -3,6 +3,7 @@
 CHECKS = check-qdict check-qfloat check-qint check-qstring check-qlist
 CHECKS += check-qjson test-qmp-output-visitor test-qmp-input-visitor
 CHECKS += test-string-input-visitor test-string-output-visitor test-coroutine
+CHECKS += test-qmp-commands
 CHECKS += $(SRC_PATH)/tests/qemu-iotests-quick.sh
 
 check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o test-coroutine.o: $(GENERATED_HEADERS)
@@ -15,9 +16,9 @@
 check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
 test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
 
-test-qmp-input-visitor.o test-qmp-output-visitor.o \
+test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-input-strict.o \
 test-string-input-visitor.o test-string-output-visitor.o \
-	test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
+	test-qmp-commands.o: QEMU_CFLAGS += -I $(qapi-dir)
 
 $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
@@ -36,6 +37,9 @@
 test-string-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
 test-string-input-visitor: test-string-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
 
+test-qmp-input-strict.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
+test-qmp-input-strict: test-qmp-input-strict.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+
 test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
 test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
 
diff --git a/trace-events b/trace-events
index 70f059d..db2cd39 100644
--- a/trace-events
+++ b/trace-events
@@ -726,7 +726,7 @@
 # hw/qxl.c
 disable qxl_interface_set_mm_time(int qid, uint32_t mm_time) "%d %d"
 disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t val) "%d %s addr=%u val=%u"
-qxl_create_guest_primary(int qid, uint32_t width, uint32_t height, uint64_t mem, uint32_t format, uint32_t position) "%d %dx%d mem=%lx %d,%d"
+qxl_create_guest_primary(int qid, uint32_t width, uint32_t height, uint64_t mem, uint32_t format, uint32_t position) "%d %ux%u mem=%" PRIx64 " %u,%u"
 qxl_create_guest_primary_rest(int qid, int32_t stride, uint32_t type, uint32_t flags) "%d %d,%d,%d"
 qxl_destroy_primary(int qid) "%d"
 qxl_enter_vga_mode(int qid) "%d"
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 28d6d4a..cb8a7ad 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -80,8 +80,8 @@
 
     if (async != QXL_SYNC) {
         spice_qxl_add_memslot_async(&ssd->qxl, memslot,
-                (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
-                                         QXL_IO_MEMSLOT_ADD_ASYNC));
+                (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                          QXL_IO_MEMSLOT_ADD_ASYNC));
     } else {
         ssd->worker->add_memslot(ssd->worker, memslot);
     }
@@ -100,8 +100,8 @@
     trace_qemu_spice_create_primary_surface(ssd->qxl.id, id, surface, async);
     if (async != QXL_SYNC) {
         spice_qxl_create_primary_surface_async(&ssd->qxl, id, surface,
-                (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
-                                         QXL_IO_CREATE_PRIMARY_ASYNC));
+                (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                          QXL_IO_CREATE_PRIMARY_ASYNC));
     } else {
         ssd->worker->create_primary_surface(ssd->worker, id, surface);
     }
@@ -113,8 +113,8 @@
     trace_qemu_spice_destroy_primary_surface(ssd->qxl.id, id, async);
     if (async != QXL_SYNC) {
         spice_qxl_destroy_primary_surface_async(&ssd->qxl, id,
-                (uint64_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
-                                         QXL_IO_DESTROY_PRIMARY_ASYNC));
+                (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                          QXL_IO_DESTROY_PRIMARY_ASYNC));
     } else {
         ssd->worker->destroy_primary_surface(ssd->worker, id);
     }
@@ -168,7 +168,7 @@
     drawable->bbox            = ssd->dirty;
     drawable->clip.type       = SPICE_CLIP_TYPE_NONE;
     drawable->effect          = QXL_EFFECT_OPAQUE;
-    drawable->release_info.id = (intptr_t)update;
+    drawable->release_info.id = (uintptr_t)update;
     drawable->type            = QXL_DRAW_COPY;
     drawable->surfaces_dest[0] = -1;
     drawable->surfaces_dest[1] = -1;
@@ -179,7 +179,7 @@
                       + time_space.tv_nsec / 1000 / 1000;
 
     drawable->u.copy.rop_descriptor  = SPICE_ROPD_OP_PUT;
-    drawable->u.copy.src_bitmap      = (intptr_t)image;
+    drawable->u.copy.src_bitmap      = (uintptr_t)image;
     drawable->u.copy.src_area.right  = bw;
     drawable->u.copy.src_area.bottom = bh;
 
@@ -189,7 +189,7 @@
     image->bitmap.stride     = bw * 4;
     image->descriptor.width  = image->bitmap.x = bw;
     image->descriptor.height = image->bitmap.y = bh;
-    image->bitmap.data = (intptr_t)(update->bitmap);
+    image->bitmap.data = (uintptr_t)(update->bitmap);
     image->bitmap.palette = 0;
     image->bitmap.format = SPICE_BITMAP_FMT_32BIT;
 
@@ -210,7 +210,7 @@
     }
 
     cmd->type = QXL_CMD_DRAW;
-    cmd->data = (intptr_t)drawable;
+    cmd->data = (uintptr_t)drawable;
 
     memset(&ssd->dirty, 0, sizeof(ssd->dirty));
     return update;
@@ -254,7 +254,7 @@
     surface.mouse_mode = true;
     surface.flags      = 0;
     surface.type       = 0;
-    surface.mem        = (intptr_t)ssd->buf;
+    surface.mem        = (uintptr_t)ssd->buf;
     surface.group_id   = MEMSLOT_GROUP_HOST;
 
     qemu_spice_create_primary_surface(ssd, 0, &surface, QXL_SYNC);
diff --git a/vl.c b/vl.c
index 112b0e0..0fccf50 100644
--- a/vl.c
+++ b/vl.c
@@ -3196,7 +3196,7 @@
     cpudef_init();
 
     if (cpu_model && *cpu_model == '?') {
-        list_cpus(stdout, &fprintf, optarg);
+        list_cpus(stdout, &fprintf, cpu_model);
         exit(0);
     }