[Spice-commits] 224 commits - Makefile.objs Makefile.target arch_init.c async.c block-migration.c block.c block.h block/qcow.c block/raw-posix.c block/raw.c block/sheepdog.c block/vvfat.c block_int.h buffered_file.c compatfd.c configure cpus.c cpus.h default-configs/alpha-softmmu.mak default-configs/i386-softmmu.mak default-configs/mips-softmmu.mak default-configs/mips64-softmmu.mak default-configs/mips64el-softmmu.mak default-configs/mipsel-softmmu.mak default-configs/ppc-softmmu.mak default-configs/ppc64-softmmu.mak default-configs/ppcemb-softmmu.mak default-configs/x86_64-softmmu.mak default-configs/xtensa-softmmu.mak default-configs/xtensaeb-softmmu.mak exec-all.h exec.c fsdev/file-op-9p.h fsdev/qemu-fsdev.c fsdev/qemu-fsdev.h hpet.h hw/9pfs hw/an5206.c hw/apic.c hw/arm11mpcore.c hw/arm_gic.c hw/arm_pic.c hw/collie.c hw/cris_pic_cpu.c hw/devices.h hw/ds1225y.c hw/etraxfs.h hw/fdc.c hw/g364fb.c hw/gus.c hw/hw.h hw/i8259.c hw/ide hw/ioapic.h hw/isa-bus.c hw/isa.h hw/lan9118.c hw/l m32_pic.c hw/lm32_pic.h hw/m48t59.c hw/mac_dbdma.c hw/mac_dbdma.h hw/mc146818rtc.c hw/microblaze_pic_cpu.c hw/ne2000-isa.c hw/omap2.c hw/opencores_eth.c hw/palm.c hw/parallel.c hw/pc.c hw/pc.h hw/pc_piix.c hw/pci.c hw/pci_bridge.c hw/petalogix_ml605_mmu.c hw/petalogix_s3adsp1800_mmu.c hw/ppc405_boards.c hw/ppc_newworld.c hw/ppc_oldworld.c hw/ppc_prep.c hw/ppce500_mpc8544ds.c hw/pxa.h hw/pxa2xx.c hw/qdev-properties.c hw/qdev.h hw/qxl.c hw/r2d.c hw/realview.c hw/s390-virtio.c hw/sb16.c hw/scsi-disk.c hw/shix.c hw/sm501.c hw/spapr.c hw/spitz.c hw/strongarm.c hw/strongarm.h hw/sun4m.c hw/sun4m.h hw/sun4u.c hw/syborg.c hw/tc6393xb.c hw/tcx.c hw/tosa.c hw/usb-ehci.c hw/usb-hid.c hw/usb-hub.c hw/usb-msd.c hw/usb-ohci.c hw/usb-uhci.c hw/usb.c hw/usb.h hw/versatile_pci.c hw/versatilepb.c hw/vga-isa.c hw/vga-pci.c hw/vga.c hw/vga_int.h hw/virtio-blk.c hw/virtio-pci.c hw/virtio-pci.h hw/vmport.c hw/vmware_vga.c hw/xtensa_dc232b.c hw/xtensa_lx60.c hw/xtensa_pic.c hw/xtensa_sample.c hw/x tensa_sim.c iohandler.c ioport.c ioport.h linux-aio.c linux-user/main.c main-loop.c main-loop.h memory.c migration-exec.c migration-fd.c migration-tcp.c migration-unix.c migration.c migration.h monitor.c os-win32.c qemu-char.c qemu-char.h qemu-common.h qemu-config.c qemu-coroutine-lock.c qemu-doc.texi qemu-options.hx qemu-os-posix.h qemu-os-win32.h qemu-tech.texi qemu-timer.c qemu-timer.h qmp-commands.hx savevm.c scripts/analyse-9p-simpletrace.py slirp/libslirp.h sysemu.h target-sparc/cc_helper.c target-sparc/cpu.h target-sparc/cpu_init.c target-sparc/fop_helper.c target-sparc/helper.c target-sparc/helper.h target-sparc/int32_helper.c target-sparc/int64_helper.c target-sparc/op_helper.c target-sparc/translate.c target-sparc/vis_helper.c target-sparc/win_helper.c target-xtensa/core-dc232b target-xtensa/core-dc232b.c target-xtensa/core-fsf target-xtensa/core-fsf.c target-xtensa/cpu.h target-xtensa/gdb-config-dc232b.c target-xtensa/gdb-config-sample-xtensa-core.c target-xtensa/ helper.c target-xtensa/op_helper.c target-xtensa/overlay_tool.h target-xtensa/translate.c tcg/tcg.h tests/xtensa trace-events ui/spice-core.c usb-linux.c vl.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Tue Oct 25 05:12:32 PDT 2011


 Makefile.objs                                 |    8 
 Makefile.target                               |   24 
 arch_init.c                                   |   17 
 async.c                                       |    1 
 block-migration.c                             |   35 
 block.c                                       |  424 +---
 block.h                                       |   10 
 block/qcow.c                                  |    2 
 block/raw-posix.c                             |  301 ---
 block/raw.c                                   |   32 
 block/sheepdog.c                              |    2 
 block/vvfat.c                                 |  109 -
 block_int.h                                   |    1 
 buffered_file.c                               |   44 
 compatfd.c                                    |   12 
 configure                                     |   33 
 cpus.c                                        |  508 ++---
 cpus.h                                        |    3 
 default-configs/alpha-softmmu.mak             |    1 
 default-configs/i386-softmmu.mak              |    1 
 default-configs/mips-softmmu.mak              |    1 
 default-configs/mips64-softmmu.mak            |    1 
 default-configs/mips64el-softmmu.mak          |    1 
 default-configs/mipsel-softmmu.mak            |    1 
 default-configs/ppc-softmmu.mak               |    1 
 default-configs/ppc64-softmmu.mak             |    1 
 default-configs/ppcemb-softmmu.mak            |    1 
 default-configs/x86_64-softmmu.mak            |    1 
 default-configs/xtensa-softmmu.mak            |    3 
 default-configs/xtensaeb-softmmu.mak          |    3 
 exec-all.h                                    |   14 
 exec.c                                        |    3 
 fsdev/file-op-9p.h                            |   51 
 fsdev/qemu-fsdev.c                            |   69 
 fsdev/qemu-fsdev.h                            |   20 
 hpet.h                                        |   22 
 hw/9pfs/cofile.c                              |   24 
 hw/9pfs/cofs.c                                |    2 
 hw/9pfs/virtio-9p-coth.h                      |    3 
 hw/9pfs/virtio-9p-debug.c                     |  646 ------
 hw/9pfs/virtio-9p-debug.h                     |    6 
 hw/9pfs/virtio-9p-device.c                    |   70 
 hw/9pfs/virtio-9p-handle.c                    |  120 -
 hw/9pfs/virtio-9p-local.c                     |  126 -
 hw/9pfs/virtio-9p.c                           |  170 +
 hw/9pfs/virtio-9p.h                           |   35 
 hw/an5206.c                                   |   10 
 hw/apic.c                                     |    4 
 hw/arm11mpcore.c                              |   13 
 hw/arm_gic.c                                  |   16 
 hw/arm_pic.c                                  |   13 
 hw/collie.c                                   |    4 
 hw/cris_pic_cpu.c                             |    6 
 hw/devices.h                                  |    3 
 hw/ds1225y.c                                  |   28 
 hw/etraxfs.h                                  |    1 
 hw/fdc.c                                      |   34 
 hw/g364fb.c                                   |    4 
 hw/gus.c                                      |   38 
 hw/hw.h                                       |    4 
 hw/i8259.c                                    |  397 ++-
 hw/ide/core.c                                 |   32 
 hw/ide/internal.h                             |    3 
 hw/ide/isa.c                                  |    4 
 hw/ide/piix.c                                 |    7 
 hw/ide/via.c                                  |    7 
 hw/ioapic.h                                   |    7 
 hw/isa-bus.c                                  |   45 
 hw/isa.h                                      |   40 
 hw/lan9118.c                                  |   29 
 hw/lm32_pic.c                                 |    4 
 hw/lm32_pic.h                                 |    3 
 hw/m48t59.c                                   |   19 
 hw/mac_dbdma.c                                |    5 
 hw/mac_dbdma.h                                |    1 
 hw/mc146818rtc.c                              |   15 
 hw/microblaze_pic_cpu.c                       |    6 
 hw/ne2000-isa.c                               |    5 
 hw/omap2.c                                    |    5 
 hw/opencores_eth.c                            |  728 +++++++
 hw/palm.c                                     |   53 
 hw/parallel.c                                 |   47 
 hw/pc.c                                       |   40 
 hw/pc.h                                       |   29 
 hw/pc_piix.c                                  |   30 
 hw/pci.c                                      |   13 
 hw/pci_bridge.c                               |    2 
 hw/petalogix_ml605_mmu.c                      |   15 
 hw/petalogix_s3adsp1800_mmu.c                 |   18 
 hw/ppc405_boards.c                            |   85 
 hw/ppc_newworld.c                             |   39 
 hw/ppc_oldworld.c                             |   13 
 hw/ppc_prep.c                                 |  109 -
 hw/ppce500_mpc8544ds.c                        |    5 
 hw/pxa.h                                      |    6 
 hw/pxa2xx.c                                   |  264 +-
 hw/qdev-properties.c                          |   29 
 hw/qdev.h                                     |    3 
 hw/qxl.c                                      |    2 
 hw/r2d.c                                      |   35 
 hw/realview.c                                 |   66 
 hw/s390-virtio.c                              |   19 
 hw/sb16.c                                     |   32 
 hw/scsi-disk.c                                |    2 
 hw/shix.c                                     |   11 
 hw/sm501.c                                    |  143 -
 hw/spapr.c                                    |    9 
 hw/spitz.c                                    |   48 
 hw/strongarm.c                                |  171 -
 hw/strongarm.h                                |    6 
 hw/sun4m.c                                    |   53 
 hw/sun4m.h                                    |    4 
 hw/sun4u.c                                    |   30 
 hw/syborg.c                                   |    8 
 hw/tc6393xb.c                                 |   71 
 hw/tcx.c                                      |  152 -
 hw/tosa.c                                     |    2 
 hw/usb-ehci.c                                 |    4 
 hw/usb-hid.c                                  |   11 
 hw/usb-hub.c                                  |   12 
 hw/usb-msd.c                                  |    5 
 hw/usb-ohci.c                                 |   41 
 hw/usb-uhci.c                                 |    2 
 hw/usb.c                                      |   12 
 hw/usb.h                                      |    1 
 hw/versatile_pci.c                            |   42 
 hw/versatilepb.c                              |   12 
 hw/vga-isa.c                                  |   17 
 hw/vga-pci.c                                  |    2 
 hw/vga.c                                      |   77 
 hw/vga_int.h                                  |    7 
 hw/virtio-blk.c                               |    2 
 hw/virtio-pci.c                               |    5 
 hw/virtio-pci.h                               |    5 
 hw/vmport.c                                   |   16 
 hw/vmware_vga.c                               |    7 
 hw/xtensa_dc232b.c                            |  116 -
 hw/xtensa_lx60.c                              |  233 ++
 hw/xtensa_pic.c                               |   49 
 hw/xtensa_sample.c                            |  107 -
 hw/xtensa_sim.c                               |  116 +
 iohandler.c                                   |   55 
 ioport.c                                      |  108 +
 ioport.h                                      |   21 
 linux-aio.c                                   |   21 
 linux-user/main.c                             |   19 
 main-loop.c                                   |  495 ++++
 main-loop.h                                   |  351 +++
 memory.c                                      |   18 
 migration-exec.c                              |   39 
 migration-fd.c                                |   42 
 migration-tcp.c                               |   76 
 migration-unix.c                              |  113 -
 migration.c                                   |  441 ++--
 migration.h                                   |   85 
 monitor.c                                     |   27 
 os-win32.c                                    |  123 -
 qemu-char.c                                   |  235 ++
 qemu-char.h                                   |   12 
 qemu-common.h                                 |   37 
 qemu-config.c                                 |   14 
 qemu-coroutine-lock.c                         |    1 
 qemu-doc.texi                                 |   55 
 qemu-options.hx                               |  126 -
 qemu-os-posix.h                               |    4 
 qemu-os-win32.h                               |   17 
 qemu-tech.texi                                |   40 
 qemu-timer.c                                  |  489 ----
 qemu-timer.h                                  |   31 
 qmp-commands.hx                               |   14 
 savevm.c                                      |  254 +-
 scripts/analyse-9p-simpletrace.py             |  142 +
 slirp/libslirp.h                              |   11 
 sysemu.h                                      |    4 
 target-sparc/cc_helper.c                      |  485 ++++
 target-sparc/cpu.h                            |    7 
 target-sparc/cpu_init.c                       |  848 ++++++++
 target-sparc/fop_helper.c                     |  394 +++
 target-sparc/helper.c                         | 1074 ----------
 target-sparc/helper.h                         |  180 -
 target-sparc/int32_helper.c                   |  125 +
 target-sparc/int64_helper.c                   |  164 +
 target-sparc/op_helper.c                      | 2590 ++++----------------------
 target-sparc/translate.c                      |  314 +--
 target-sparc/vis_helper.c                     |  406 ++++
 target-sparc/win_helper.c                     |  518 +++++
 target-xtensa/core-dc232b.c                   |   28 
 target-xtensa/core-dc232b/core-isa.h          |  423 ++++
 target-xtensa/core-dc232b/gdb-config.c        |  261 ++
 target-xtensa/core-fsf.c                      |   22 
 target-xtensa/core-fsf/core-isa.h             |  361 +++
 target-xtensa/cpu.h                           |   19 
 target-xtensa/gdb-config-dc232b.c             |  261 --
 target-xtensa/gdb-config-sample-xtensa-core.c |  375 ---
 target-xtensa/helper.c                        |  249 --
 target-xtensa/op_helper.c                     |   18 
 target-xtensa/overlay_tool.h                  |  534 +++++
 target-xtensa/translate.c                     |  149 +
 tcg/tcg.h                                     |    2 
 tests/xtensa/Makefile                         |    3 
 tests/xtensa/test_mac16.S                     |  243 ++
 tests/xtensa/test_timer.S                     |   63 
 trace-events                                  |   60 
 ui/spice-core.c                               |    4 
 usb-linux.c                                   |  176 +
 vl.c                                          |  245 --
 206 files changed, 11909 insertions(+), 9280 deletions(-)

New commits:
commit 952e849c150b4f1b89f8728cba00f925c1d6e75b
Merge: db418a0... 9943590...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Oct 24 10:51:12 2011 -0500

    Merge remote-tracking branch 'bonzini/split-main-loop-for-anthony' into staging

commit db418a0a7ef5887ea0f3d167584e6f500bb0c4c5
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Thu Oct 6 16:37:51 2011 +0200

    Add stdio char device on windows
    
    Simple implementation of an stdio char device on Windows.
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-char.c b/qemu-char.c
index fb9e058..9fd94d1 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -538,6 +538,9 @@ int send_all(int fd, const void *_buf, int len1)
 }
 #endif /* !_WIN32 */
 
+#define STDIO_MAX_CLIENTS 1
+static int stdio_nb_clients;
+
 #ifndef _WIN32
 
 typedef struct {
@@ -545,8 +548,6 @@ typedef struct {
     int max_size;
 } FDCharDriver;
 
-#define STDIO_MAX_CLIENTS 1
-static int stdio_nb_clients = 0;
 
 static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
@@ -1451,6 +1452,8 @@ static int qemu_chr_open_pp(QemuOpts *opts, CharDriverState **_chr)
 
 #else /* _WIN32 */
 
+static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
+
 typedef struct {
     int max_size;
     HANDLE hcom, hrecv, hsend;
@@ -1459,6 +1462,14 @@ typedef struct {
     DWORD len;
 } WinCharState;
 
+typedef struct {
+    HANDLE  hStdIn;
+    HANDLE  hInputReadyEvent;
+    HANDLE  hInputDoneEvent;
+    HANDLE  hInputThread;
+    uint8_t win_stdio_buf;
+} WinStdioCharState;
+
 #define NSENDBUF 2048
 #define NRECVBUF 2048
 #define MAXCONNECT 1
@@ -1809,6 +1820,217 @@ static int qemu_chr_open_win_file_out(QemuOpts *opts, CharDriverState **_chr)
 
     return qemu_chr_open_win_file(fd_out, _chr);
 }
+
+static int win_stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    HANDLE  hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+    DWORD   dwSize;
+    int     len1;
+
+    len1 = len;
+
+    while (len1 > 0) {
+        if (!WriteFile(hStdOut, buf, len1, &dwSize, NULL)) {
+            break;
+        }
+        buf  += dwSize;
+        len1 -= dwSize;
+    }
+
+    return len - len1;
+}
+
+static void win_stdio_wait_func(void *opaque)
+{
+    CharDriverState   *chr   = opaque;
+    WinStdioCharState *stdio = chr->opaque;
+    INPUT_RECORD       buf[4];
+    int                ret;
+    DWORD              dwSize;
+    int                i;
+
+    ret = ReadConsoleInput(stdio->hStdIn, buf, sizeof(buf) / sizeof(*buf),
+                           &dwSize);
+
+    if (!ret) {
+        /* Avoid error storm */
+        qemu_del_wait_object(stdio->hStdIn, NULL, NULL);
+        return;
+    }
+
+    for (i = 0; i < dwSize; i++) {
+        KEY_EVENT_RECORD *kev = &buf[i].Event.KeyEvent;
+
+        if (buf[i].EventType == KEY_EVENT && kev->bKeyDown) {
+            int j;
+            if (kev->uChar.AsciiChar != 0) {
+                for (j = 0; j < kev->wRepeatCount; j++) {
+                    if (qemu_chr_be_can_write(chr)) {
+                        uint8_t c = kev->uChar.AsciiChar;
+                        qemu_chr_be_write(chr, &c, 1);
+                    }
+                }
+            }
+        }
+    }
+}
+
+static DWORD WINAPI win_stdio_thread(LPVOID param)
+{
+    CharDriverState   *chr   = param;
+    WinStdioCharState *stdio = chr->opaque;
+    int                ret;
+    DWORD              dwSize;
+
+    while (1) {
+
+        /* Wait for one byte */
+        ret = ReadFile(stdio->hStdIn, &stdio->win_stdio_buf, 1, &dwSize, NULL);
+
+        /* Exit in case of error, continue if nothing read */
+        if (!ret) {
+            break;
+        }
+        if (!dwSize) {
+            continue;
+        }
+
+        /* Some terminal emulator returns \r\n for Enter, just pass \n */
+        if (stdio->win_stdio_buf == '\r') {
+            continue;
+        }
+
+        /* Signal the main thread and wait until the byte was eaten */
+        if (!SetEvent(stdio->hInputReadyEvent)) {
+            break;
+        }
+        if (WaitForSingleObject(stdio->hInputDoneEvent, INFINITE)
+            != WAIT_OBJECT_0) {
+            break;
+        }
+    }
+
+    qemu_del_wait_object(stdio->hInputReadyEvent, NULL, NULL);
+    return 0;
+}
+
+static void win_stdio_thread_wait_func(void *opaque)
+{
+    CharDriverState   *chr   = opaque;
+    WinStdioCharState *stdio = chr->opaque;
+
+    if (qemu_chr_be_can_write(chr)) {
+        qemu_chr_be_write(chr, &stdio->win_stdio_buf, 1);
+    }
+
+    SetEvent(stdio->hInputDoneEvent);
+}
+
+static void qemu_chr_set_echo_win_stdio(CharDriverState *chr, bool echo)
+{
+    WinStdioCharState *stdio  = chr->opaque;
+    DWORD              dwMode = 0;
+
+    GetConsoleMode(stdio->hStdIn, &dwMode);
+
+    if (echo) {
+        SetConsoleMode(stdio->hStdIn, dwMode | ENABLE_ECHO_INPUT);
+    } else {
+        SetConsoleMode(stdio->hStdIn, dwMode & ~ENABLE_ECHO_INPUT);
+    }
+}
+
+static void win_stdio_close(CharDriverState *chr)
+{
+    WinStdioCharState *stdio = chr->opaque;
+
+    if (stdio->hInputReadyEvent != INVALID_HANDLE_VALUE) {
+        CloseHandle(stdio->hInputReadyEvent);
+    }
+    if (stdio->hInputDoneEvent != INVALID_HANDLE_VALUE) {
+        CloseHandle(stdio->hInputDoneEvent);
+    }
+    if (stdio->hInputThread != INVALID_HANDLE_VALUE) {
+        TerminateThread(stdio->hInputThread, 0);
+    }
+
+    g_free(chr->opaque);
+    g_free(chr);
+    stdio_nb_clients--;
+}
+
+static int qemu_chr_open_win_stdio(QemuOpts *opts, CharDriverState **_chr)
+{
+    CharDriverState   *chr;
+    WinStdioCharState *stdio;
+    DWORD              dwMode;
+    int                is_console = 0;
+
+    if (stdio_nb_clients >= STDIO_MAX_CLIENTS
+        || ((display_type != DT_NOGRAPHIC) && (stdio_nb_clients != 0))) {
+        return -EIO;
+    }
+
+    chr   = g_malloc0(sizeof(CharDriverState));
+    stdio = g_malloc0(sizeof(WinStdioCharState));
+
+    stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
+    if (stdio->hStdIn == INVALID_HANDLE_VALUE) {
+        fprintf(stderr, "cannot open stdio: invalid handle\n");
+        exit(1);
+    }
+
+    is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0;
+
+    chr->opaque    = stdio;
+    chr->chr_write = win_stdio_write;
+    chr->chr_close = win_stdio_close;
+
+    if (stdio_nb_clients == 0) {
+        if (is_console) {
+            if (qemu_add_wait_object(stdio->hStdIn,
+                                     win_stdio_wait_func, chr)) {
+                fprintf(stderr, "qemu_add_wait_object: failed\n");
+            }
+        } else {
+            DWORD   dwId;
+
+            stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+            stdio->hInputDoneEvent  = CreateEvent(NULL, FALSE, FALSE, NULL);
+            stdio->hInputThread     = CreateThread(NULL, 0, win_stdio_thread,
+                                            chr, 0, &dwId);
+
+            if (stdio->hInputThread == INVALID_HANDLE_VALUE
+                || stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
+                || stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) {
+                fprintf(stderr, "cannot create stdio thread or event\n");
+                exit(1);
+            }
+            if (qemu_add_wait_object(stdio->hInputReadyEvent,
+                                     win_stdio_thread_wait_func, chr)) {
+                fprintf(stderr, "qemu_add_wait_object: failed\n");
+            }
+        }
+    }
+
+    dwMode |= ENABLE_LINE_INPUT;
+
+    stdio_clients[stdio_nb_clients++] = chr;
+    if (stdio_nb_clients == 1 && is_console) {
+        /* set the terminal in raw mode */
+        /* ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS */
+        dwMode |= ENABLE_PROCESSED_INPUT;
+    }
+
+    SetConsoleMode(stdio->hStdIn, dwMode);
+
+    chr->chr_set_echo = qemu_chr_set_echo_win_stdio;
+    qemu_chr_fe_set_echo(chr, false);
+
+    *_chr = chr;
+
+    return 0;
+}
 #endif /* !_WIN32 */
 
 /***********************************************************/
@@ -2519,6 +2741,7 @@ static const struct {
     { .name = "pipe",      .open = qemu_chr_open_win_pipe },
     { .name = "console",   .open = qemu_chr_open_win_con },
     { .name = "serial",    .open = qemu_chr_open_win },
+    { .name = "stdio",     .open = qemu_chr_open_win_stdio },
 #else
     { .name = "file",      .open = qemu_chr_open_file_out },
     { .name = "pipe",      .open = qemu_chr_open_pipe },
commit 070af38404fde7a5eca87633bcbd452b5428f968
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Mon Aug 1 09:03:20 2011 +0000

    Sparc: split CWP and PSTATE op helpers
    
    Move CWP and PSTATE op helpers to win_helper.c.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index e720a12..1e90df7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -78,7 +78,7 @@ libobj-$(TARGET_SPARC64) += vis_helper.o
 libobj-$(CONFIG_NEED_MMU) += mmu.o
 libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
 ifeq ($(TARGET_BASE_ARCH), sparc)
-libobj-y += fop_helper.o cc_helper.o cpu_init.o
+libobj-y += fop_helper.o cc_helper.o win_helper.o cpu_init.o
 endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
@@ -97,7 +97,7 @@ tcg/tcg.o: cpu.h
 
 # HELPER_CFLAGS is used for all the code compiled with static register
 # variables
-op_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+op_helper.o win_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 
 # Note: this is a workaround. The real fix is to avoid compiling
 # cpu_signal_handler() in user-exec.c.
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index c9ab7e4..6bf9275 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -509,7 +509,7 @@ void gen_intermediate_code_init(CPUSPARCState *env);
 /* cpu-exec.c */
 int cpu_sparc_exec(CPUSPARCState *s);
 
-/* op_helper.c */
+/* win_helper.c */
 target_ulong cpu_get_psr(CPUState *env1);
 void cpu_put_psr(CPUState *env1, target_ulong val);
 #ifdef TARGET_SPARC64
@@ -522,6 +522,8 @@ void cpu_change_pstate(CPUState *env1, uint32_t new_pstate);
 int cpu_cwp_inc(CPUState *env1, int cwp);
 int cpu_cwp_dec(CPUState *env1, int cwp);
 void cpu_set_cwp(CPUState *env1, int new_cwp);
+
+/* op_helper.c */
 void leon3_irq_manager(void *irq_manager, int intno);
 
 /* sun4m.c, sun4u.c */
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 18a00d4..cb0bf2e 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -333,140 +333,6 @@ void helper_check_align(target_ulong addr, uint32_t align)
     }
 }
 
-static inline void memcpy32(target_ulong *dst, const target_ulong *src)
-{
-    dst[0] = src[0];
-    dst[1] = src[1];
-    dst[2] = src[2];
-    dst[3] = src[3];
-    dst[4] = src[4];
-    dst[5] = src[5];
-    dst[6] = src[6];
-    dst[7] = src[7];
-}
-
-static void set_cwp(int new_cwp)
-{
-    /* put the modified wrap registers at their proper location */
-    if (env->cwp == env->nwindows - 1) {
-        memcpy32(env->regbase, env->regbase + env->nwindows * 16);
-    }
-    env->cwp = new_cwp;
-
-    /* put the wrap registers at their temporary location */
-    if (new_cwp == env->nwindows - 1) {
-        memcpy32(env->regbase + env->nwindows * 16, env->regbase);
-    }
-    env->regwptr = env->regbase + (new_cwp * 16);
-}
-
-void cpu_set_cwp(CPUState *env1, int new_cwp)
-{
-    CPUState *saved_env;
-
-    saved_env = env;
-    env = env1;
-    set_cwp(new_cwp);
-    env = saved_env;
-}
-
-static target_ulong get_psr(void)
-{
-    helper_compute_psr(env);
-
-#if !defined (TARGET_SPARC64)
-    return env->version | (env->psr & PSR_ICC) |
-        (env->psref ? PSR_EF : 0) |
-        (env->psrpil << 8) |
-        (env->psrs ? PSR_S : 0) |
-        (env->psrps ? PSR_PS : 0) |
-        (env->psret ? PSR_ET : 0) | env->cwp;
-#else
-    return env->psr & PSR_ICC;
-#endif
-}
-
-target_ulong cpu_get_psr(CPUState *env1)
-{
-    CPUState *saved_env;
-    target_ulong ret;
-
-    saved_env = env;
-    env = env1;
-    ret = get_psr();
-    env = saved_env;
-    return ret;
-}
-
-static void put_psr(target_ulong val)
-{
-    env->psr = val & PSR_ICC;
-#if !defined (TARGET_SPARC64)
-    env->psref = (val & PSR_EF) ? 1 : 0;
-    env->psrpil = (val & PSR_PIL) >> 8;
-#endif
-#if ((!defined (TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY))
-    cpu_check_irqs(env);
-#endif
-#if !defined (TARGET_SPARC64)
-    env->psrs = (val & PSR_S) ? 1 : 0;
-    env->psrps = (val & PSR_PS) ? 1 : 0;
-    env->psret = (val & PSR_ET) ? 1 : 0;
-    set_cwp(val & PSR_CWP);
-#endif
-    env->cc_op = CC_OP_FLAGS;
-}
-
-void cpu_put_psr(CPUState *env1, target_ulong val)
-{
-    CPUState *saved_env;
-
-    saved_env = env;
-    env = env1;
-    put_psr(val);
-    env = saved_env;
-}
-
-static int cwp_inc(int cwp)
-{
-    if (unlikely(cwp >= env->nwindows)) {
-        cwp -= env->nwindows;
-    }
-    return cwp;
-}
-
-int cpu_cwp_inc(CPUState *env1, int cwp)
-{
-    CPUState *saved_env;
-    target_ulong ret;
-
-    saved_env = env;
-    env = env1;
-    ret = cwp_inc(cwp);
-    env = saved_env;
-    return ret;
-}
-
-static int cwp_dec(int cwp)
-{
-    if (unlikely(cwp < 0)) {
-        cwp += env->nwindows;
-    }
-    return cwp;
-}
-
-int cpu_cwp_dec(CPUState *env1, int cwp)
-{
-    CPUState *saved_env;
-    target_ulong ret;
-
-    saved_env = env;
-    env = env1;
-    ret = cwp_dec(cwp);
-    env = saved_env;
-    return ret;
-}
-
 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) &&   \
     defined(DEBUG_MXCC)
 static void dump_mxcc(CPUState *env)
@@ -2393,25 +2259,6 @@ target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
 }
 #endif /* TARGET_SPARC64 */
 
-#ifndef TARGET_SPARC64
-void helper_rett(void)
-{
-    unsigned int cwp;
-
-    if (env->psret == 1) {
-        helper_raise_exception(env, TT_ILL_INSN);
-    }
-
-    env->psret = 1;
-    cwp = cwp_inc(env->cwp + 1) ;
-    if (env->wim & (1 << cwp)) {
-        helper_raise_exception(env, TT_WIN_UNF);
-    }
-    set_cwp(cwp);
-    env->psrs = env->psrps;
-}
-#endif
-
 static target_ulong helper_udiv_common(target_ulong a, target_ulong b, int cc)
 {
     int overflow = 0;
@@ -2608,341 +2455,7 @@ void helper_stqf(target_ulong addr, int mem_idx)
 #endif
 }
 
-#ifndef TARGET_SPARC64
-/* XXX: use another pointer for %iN registers to avoid slow wrapping
-   handling ? */
-void helper_save(void)
-{
-    uint32_t cwp;
-
-    cwp = cwp_dec(env->cwp - 1);
-    if (env->wim & (1 << cwp)) {
-        helper_raise_exception(env, TT_WIN_OVF);
-    }
-    set_cwp(cwp);
-}
-
-void helper_restore(void)
-{
-    uint32_t cwp;
-
-    cwp = cwp_inc(env->cwp + 1);
-    if (env->wim & (1 << cwp)) {
-        helper_raise_exception(env, TT_WIN_UNF);
-    }
-    set_cwp(cwp);
-}
-
-void helper_wrpsr(target_ulong new_psr)
-{
-    if ((new_psr & PSR_CWP) >= env->nwindows) {
-        helper_raise_exception(env, TT_ILL_INSN);
-    } else {
-        cpu_put_psr(env, new_psr);
-    }
-}
-
-target_ulong helper_rdpsr(void)
-{
-    return get_psr();
-}
-
-#else
-/* XXX: use another pointer for %iN registers to avoid slow wrapping
-   handling ? */
-void helper_save(void)
-{
-    uint32_t cwp;
-
-    cwp = cwp_dec(env->cwp - 1);
-    if (env->cansave == 0) {
-        helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ?
-                                                (TT_WOTHER |
-                                                 ((env->wstate & 0x38) >> 1)) :
-                                                ((env->wstate & 0x7) << 2)));
-    } else {
-        if (env->cleanwin - env->canrestore == 0) {
-            /* XXX Clean windows without trap */
-            helper_raise_exception(env, TT_CLRWIN);
-        } else {
-            env->cansave--;
-            env->canrestore++;
-            set_cwp(cwp);
-        }
-    }
-}
-
-void helper_restore(void)
-{
-    uint32_t cwp;
-
-    cwp = cwp_inc(env->cwp + 1);
-    if (env->canrestore == 0) {
-        helper_raise_exception(env, TT_FILL | (env->otherwin != 0 ?
-                                               (TT_WOTHER |
-                                                ((env->wstate & 0x38) >> 1)) :
-                                               ((env->wstate & 0x7) << 2)));
-    } else {
-        env->cansave++;
-        env->canrestore--;
-        set_cwp(cwp);
-    }
-}
-
-void helper_flushw(void)
-{
-    if (env->cansave != env->nwindows - 2) {
-        helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ?
-                                                (TT_WOTHER |
-                                                 ((env->wstate & 0x38) >> 1)) :
-                                                ((env->wstate & 0x7) << 2)));
-    }
-}
-
-void helper_saved(void)
-{
-    env->cansave++;
-    if (env->otherwin == 0) {
-        env->canrestore--;
-    } else {
-        env->otherwin--;
-    }
-}
-
-void helper_restored(void)
-{
-    env->canrestore++;
-    if (env->cleanwin < env->nwindows - 1) {
-        env->cleanwin++;
-    }
-    if (env->otherwin == 0) {
-        env->cansave--;
-    } else {
-        env->otherwin--;
-    }
-}
-
-static target_ulong get_ccr(void)
-{
-    target_ulong psr;
-
-    psr = get_psr();
-
-    return ((env->xcc >> 20) << 4) | ((psr & PSR_ICC) >> 20);
-}
-
-target_ulong cpu_get_ccr(CPUState *env1)
-{
-    CPUState *saved_env;
-    target_ulong ret;
-
-    saved_env = env;
-    env = env1;
-    ret = get_ccr();
-    env = saved_env;
-    return ret;
-}
-
-static void put_ccr(target_ulong val)
-{
-    env->xcc = (val >> 4) << 20;
-    env->psr = (val & 0xf) << 20;
-    CC_OP = CC_OP_FLAGS;
-}
-
-void cpu_put_ccr(CPUState *env1, target_ulong val)
-{
-    CPUState *saved_env;
-
-    saved_env = env;
-    env = env1;
-    put_ccr(val);
-    env = saved_env;
-}
-
-static target_ulong get_cwp64(void)
-{
-    return env->nwindows - 1 - env->cwp;
-}
-
-target_ulong cpu_get_cwp64(CPUState *env1)
-{
-    CPUState *saved_env;
-    target_ulong ret;
-
-    saved_env = env;
-    env = env1;
-    ret = get_cwp64();
-    env = saved_env;
-    return ret;
-}
-
-static void put_cwp64(int cwp)
-{
-    if (unlikely(cwp >= env->nwindows || cwp < 0)) {
-        cwp %= env->nwindows;
-    }
-    set_cwp(env->nwindows - 1 - cwp);
-}
-
-void cpu_put_cwp64(CPUState *env1, int cwp)
-{
-    CPUState *saved_env;
-
-    saved_env = env;
-    env = env1;
-    put_cwp64(cwp);
-    env = saved_env;
-}
-
-target_ulong helper_rdccr(void)
-{
-    return get_ccr();
-}
-
-void helper_wrccr(target_ulong new_ccr)
-{
-    put_ccr(new_ccr);
-}
-
-/* CWP handling is reversed in V9, but we still use the V8 register
-   order. */
-target_ulong helper_rdcwp(void)
-{
-    return get_cwp64();
-}
-
-void helper_wrcwp(target_ulong new_cwp)
-{
-    put_cwp64(new_cwp);
-}
-
-static inline uint64_t *get_gregset(uint32_t pstate)
-{
-    switch (pstate) {
-    default:
-        DPRINTF_PSTATE("ERROR in get_gregset: active pstate bits=%x%s%s%s\n",
-                       pstate,
-                       (pstate & PS_IG) ? " IG" : "",
-                       (pstate & PS_MG) ? " MG" : "",
-                       (pstate & PS_AG) ? " AG" : "");
-        /* pass through to normal set of global registers */
-    case 0:
-        return env->bgregs;
-    case PS_AG:
-        return env->agregs;
-    case PS_MG:
-        return env->mgregs;
-    case PS_IG:
-        return env->igregs;
-    }
-}
-
-static inline void change_pstate(uint32_t new_pstate)
-{
-    uint32_t pstate_regs, new_pstate_regs;
-    uint64_t *src, *dst;
-
-    if (env->def->features & CPU_FEATURE_GL) {
-        /* PS_AG is not implemented in this case */
-        new_pstate &= ~PS_AG;
-    }
-
-    pstate_regs = env->pstate & 0xc01;
-    new_pstate_regs = new_pstate & 0xc01;
-
-    if (new_pstate_regs != pstate_regs) {
-        DPRINTF_PSTATE("change_pstate: switching regs old=%x new=%x\n",
-                       pstate_regs, new_pstate_regs);
-        /* Switch global register bank */
-        src = get_gregset(new_pstate_regs);
-        dst = get_gregset(pstate_regs);
-        memcpy32(dst, env->gregs);
-        memcpy32(env->gregs, src);
-    } else {
-        DPRINTF_PSTATE("change_pstate: regs new=%x (unchanged)\n",
-                       new_pstate_regs);
-    }
-    env->pstate = new_pstate;
-}
-
-void helper_wrpstate(target_ulong new_state)
-{
-    change_pstate(new_state & 0xf3f);
-
-#if !defined(CONFIG_USER_ONLY)
-    if (cpu_interrupts_enabled(env)) {
-        cpu_check_irqs(env);
-    }
-#endif
-}
-
-void cpu_change_pstate(CPUState *env1, uint32_t new_pstate)
-{
-    CPUState *saved_env;
-
-    saved_env = env;
-    env = env1;
-    change_pstate(new_pstate);
-    env = saved_env;
-}
-
-void helper_wrpil(target_ulong new_pil)
-{
-#if !defined(CONFIG_USER_ONLY)
-    DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
-                   env->psrpil, (uint32_t)new_pil);
-
-    env->psrpil = new_pil;
-
-    if (cpu_interrupts_enabled(env)) {
-        cpu_check_irqs(env);
-    }
-#endif
-}
-
-void helper_done(void)
-{
-    trap_state *tsptr = cpu_tsptr(env);
-
-    env->pc = tsptr->tnpc;
-    env->npc = tsptr->tnpc + 4;
-    put_ccr(tsptr->tstate >> 32);
-    env->asi = (tsptr->tstate >> 24) & 0xff;
-    change_pstate((tsptr->tstate >> 8) & 0xf3f);
-    put_cwp64(tsptr->tstate & 0xff);
-    env->tl--;
-
-    DPRINTF_PSTATE("... helper_done tl=%d\n", env->tl);
-
-#if !defined(CONFIG_USER_ONLY)
-    if (cpu_interrupts_enabled(env)) {
-        cpu_check_irqs(env);
-    }
-#endif
-}
-
-void helper_retry(void)
-{
-    trap_state *tsptr = cpu_tsptr(env);
-
-    env->pc = tsptr->tpc;
-    env->npc = tsptr->tnpc;
-    put_ccr(tsptr->tstate >> 32);
-    env->asi = (tsptr->tstate >> 24) & 0xff;
-    change_pstate((tsptr->tstate >> 8) & 0xf3f);
-    put_cwp64(tsptr->tstate & 0xff);
-    env->tl--;
-
-    DPRINTF_PSTATE("... helper_retry tl=%d\n", env->tl);
-
-#if !defined(CONFIG_USER_ONLY)
-    if (cpu_interrupts_enabled(env)) {
-        cpu_check_irqs(env);
-    }
-#endif
-}
-
+#ifdef TARGET_SPARC64
 static void do_modify_softint(const char *operation, uint32_t value)
 {
     if (env->softint != value) {
diff --git a/target-sparc/win_helper.c b/target-sparc/win_helper.c
new file mode 100644
index 0000000..8bf2123
--- /dev/null
+++ b/target-sparc/win_helper.c
@@ -0,0 +1,518 @@
+/*
+ * Helpers for CWP and PSTATE handling
+ *
+ *  Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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 "helper.h"
+
+//#define DEBUG_PSTATE
+
+#ifdef DEBUG_PSTATE
+#define DPRINTF_PSTATE(fmt, ...)                                \
+    do { printf("PSTATE: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF_PSTATE(fmt, ...) do {} while (0)
+#endif
+
+static inline void memcpy32(target_ulong *dst, const target_ulong *src)
+{
+    dst[0] = src[0];
+    dst[1] = src[1];
+    dst[2] = src[2];
+    dst[3] = src[3];
+    dst[4] = src[4];
+    dst[5] = src[5];
+    dst[6] = src[6];
+    dst[7] = src[7];
+}
+
+static void set_cwp(int new_cwp)
+{
+    /* put the modified wrap registers at their proper location */
+    if (env->cwp == env->nwindows - 1) {
+        memcpy32(env->regbase, env->regbase + env->nwindows * 16);
+    }
+    env->cwp = new_cwp;
+
+    /* put the wrap registers at their temporary location */
+    if (new_cwp == env->nwindows - 1) {
+        memcpy32(env->regbase + env->nwindows * 16, env->regbase);
+    }
+    env->regwptr = env->regbase + (new_cwp * 16);
+}
+
+void cpu_set_cwp(CPUState *env1, int new_cwp)
+{
+    CPUState *saved_env;
+
+    saved_env = env;
+    env = env1;
+    set_cwp(new_cwp);
+    env = saved_env;
+}
+
+static target_ulong get_psr(void)
+{
+    helper_compute_psr(env);
+
+#if !defined(TARGET_SPARC64)
+    return env->version | (env->psr & PSR_ICC) |
+        (env->psref ? PSR_EF : 0) |
+        (env->psrpil << 8) |
+        (env->psrs ? PSR_S : 0) |
+        (env->psrps ? PSR_PS : 0) |
+        (env->psret ? PSR_ET : 0) | env->cwp;
+#else
+    return env->psr & PSR_ICC;
+#endif
+}
+
+target_ulong cpu_get_psr(CPUState *env1)
+{
+    CPUState *saved_env;
+    target_ulong ret;
+
+    saved_env = env;
+    env = env1;
+    ret = get_psr();
+    env = saved_env;
+    return ret;
+}
+
+static void put_psr(target_ulong val)
+{
+    env->psr = val & PSR_ICC;
+#if !defined(TARGET_SPARC64)
+    env->psref = (val & PSR_EF) ? 1 : 0;
+    env->psrpil = (val & PSR_PIL) >> 8;
+#endif
+#if ((!defined(TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY))
+    cpu_check_irqs(env);
+#endif
+#if !defined(TARGET_SPARC64)
+    env->psrs = (val & PSR_S) ? 1 : 0;
+    env->psrps = (val & PSR_PS) ? 1 : 0;
+    env->psret = (val & PSR_ET) ? 1 : 0;
+    set_cwp(val & PSR_CWP);
+#endif
+    env->cc_op = CC_OP_FLAGS;
+}
+
+void cpu_put_psr(CPUState *env1, target_ulong val)
+{
+    CPUState *saved_env;
+
+    saved_env = env;
+    env = env1;
+    put_psr(val);
+    env = saved_env;
+}
+
+static int cwp_inc(int cwp)
+{
+    if (unlikely(cwp >= env->nwindows)) {
+        cwp -= env->nwindows;
+    }
+    return cwp;
+}
+
+int cpu_cwp_inc(CPUState *env1, int cwp)
+{
+    CPUState *saved_env;
+    target_ulong ret;
+
+    saved_env = env;
+    env = env1;
+    ret = cwp_inc(cwp);
+    env = saved_env;
+    return ret;
+}
+
+static int cwp_dec(int cwp)
+{
+    if (unlikely(cwp < 0)) {
+        cwp += env->nwindows;
+    }
+    return cwp;
+}
+
+int cpu_cwp_dec(CPUState *env1, int cwp)
+{
+    CPUState *saved_env;
+    target_ulong ret;
+
+    saved_env = env;
+    env = env1;
+    ret = cwp_dec(cwp);
+    env = saved_env;
+    return ret;
+}
+
+#ifndef TARGET_SPARC64
+void helper_rett(void)
+{
+    unsigned int cwp;
+
+    if (env->psret == 1) {
+        helper_raise_exception(env, TT_ILL_INSN);
+    }
+
+    env->psret = 1;
+    cwp = cwp_inc(env->cwp + 1) ;
+    if (env->wim & (1 << cwp)) {
+        helper_raise_exception(env, TT_WIN_UNF);
+    }
+    set_cwp(cwp);
+    env->psrs = env->psrps;
+}
+
+/* XXX: use another pointer for %iN registers to avoid slow wrapping
+   handling ? */
+void helper_save(void)
+{
+    uint32_t cwp;
+
+    cwp = cwp_dec(env->cwp - 1);
+    if (env->wim & (1 << cwp)) {
+        helper_raise_exception(env, TT_WIN_OVF);
+    }
+    set_cwp(cwp);
+}
+
+void helper_restore(void)
+{
+    uint32_t cwp;
+
+    cwp = cwp_inc(env->cwp + 1);
+    if (env->wim & (1 << cwp)) {
+        helper_raise_exception(env, TT_WIN_UNF);
+    }
+    set_cwp(cwp);
+}
+
+void helper_wrpsr(target_ulong new_psr)
+{
+    if ((new_psr & PSR_CWP) >= env->nwindows) {
+        helper_raise_exception(env, TT_ILL_INSN);
+    } else {
+        cpu_put_psr(env, new_psr);
+    }
+}
+
+target_ulong helper_rdpsr(void)
+{
+    return get_psr();
+}
+
+#else
+/* XXX: use another pointer for %iN registers to avoid slow wrapping
+   handling ? */
+void helper_save(void)
+{
+    uint32_t cwp;
+
+    cwp = cwp_dec(env->cwp - 1);
+    if (env->cansave == 0) {
+        helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ?
+                                                (TT_WOTHER |
+                                                 ((env->wstate & 0x38) >> 1)) :
+                                                ((env->wstate & 0x7) << 2)));
+    } else {
+        if (env->cleanwin - env->canrestore == 0) {
+            /* XXX Clean windows without trap */
+            helper_raise_exception(env, TT_CLRWIN);
+        } else {
+            env->cansave--;
+            env->canrestore++;
+            set_cwp(cwp);
+        }
+    }
+}
+
+void helper_restore(void)
+{
+    uint32_t cwp;
+
+    cwp = cwp_inc(env->cwp + 1);
+    if (env->canrestore == 0) {
+        helper_raise_exception(env, TT_FILL | (env->otherwin != 0 ?
+                                               (TT_WOTHER |
+                                                ((env->wstate & 0x38) >> 1)) :
+                                               ((env->wstate & 0x7) << 2)));
+    } else {
+        env->cansave++;
+        env->canrestore--;
+        set_cwp(cwp);
+    }
+}
+
+void helper_flushw(void)
+{
+    if (env->cansave != env->nwindows - 2) {
+        helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ?
+                                                (TT_WOTHER |
+                                                 ((env->wstate & 0x38) >> 1)) :
+                                                ((env->wstate & 0x7) << 2)));
+    }
+}
+
+void helper_saved(void)
+{
+    env->cansave++;
+    if (env->otherwin == 0) {
+        env->canrestore--;
+    } else {
+        env->otherwin--;
+    }
+}
+
+void helper_restored(void)
+{
+    env->canrestore++;
+    if (env->cleanwin < env->nwindows - 1) {
+        env->cleanwin++;
+    }
+    if (env->otherwin == 0) {
+        env->cansave--;
+    } else {
+        env->otherwin--;
+    }
+}
+
+static target_ulong get_ccr(void)
+{
+    target_ulong psr;
+
+    psr = get_psr();
+
+    return ((env->xcc >> 20) << 4) | ((psr & PSR_ICC) >> 20);
+}
+
+target_ulong cpu_get_ccr(CPUState *env1)
+{
+    CPUState *saved_env;
+    target_ulong ret;
+
+    saved_env = env;
+    env = env1;
+    ret = get_ccr();
+    env = saved_env;
+    return ret;
+}
+
+static void put_ccr(target_ulong val)
+{
+    env->xcc = (val >> 4) << 20;
+    env->psr = (val & 0xf) << 20;
+    CC_OP = CC_OP_FLAGS;
+}
+
+void cpu_put_ccr(CPUState *env1, target_ulong val)
+{
+    CPUState *saved_env;
+
+    saved_env = env;
+    env = env1;
+    put_ccr(val);
+    env = saved_env;
+}
+
+static target_ulong get_cwp64(void)
+{
+    return env->nwindows - 1 - env->cwp;
+}
+
+target_ulong cpu_get_cwp64(CPUState *env1)
+{
+    CPUState *saved_env;
+    target_ulong ret;
+
+    saved_env = env;
+    env = env1;
+    ret = get_cwp64();
+    env = saved_env;
+    return ret;
+}
+
+static void put_cwp64(int cwp)
+{
+    if (unlikely(cwp >= env->nwindows || cwp < 0)) {
+        cwp %= env->nwindows;
+    }
+    set_cwp(env->nwindows - 1 - cwp);
+}
+
+void cpu_put_cwp64(CPUState *env1, int cwp)
+{
+    CPUState *saved_env;
+
+    saved_env = env;
+    env = env1;
+    put_cwp64(cwp);
+    env = saved_env;
+}
+
+target_ulong helper_rdccr(void)
+{
+    return get_ccr();
+}
+
+void helper_wrccr(target_ulong new_ccr)
+{
+    put_ccr(new_ccr);
+}
+
+/* CWP handling is reversed in V9, but we still use the V8 register
+   order. */
+target_ulong helper_rdcwp(void)
+{
+    return get_cwp64();
+}
+
+void helper_wrcwp(target_ulong new_cwp)
+{
+    put_cwp64(new_cwp);
+}
+
+static inline uint64_t *get_gregset(uint32_t pstate)
+{
+    switch (pstate) {
+    default:
+        DPRINTF_PSTATE("ERROR in get_gregset: active pstate bits=%x%s%s%s\n",
+                       pstate,
+                       (pstate & PS_IG) ? " IG" : "",
+                       (pstate & PS_MG) ? " MG" : "",
+                       (pstate & PS_AG) ? " AG" : "");
+        /* pass through to normal set of global registers */
+    case 0:
+        return env->bgregs;
+    case PS_AG:
+        return env->agregs;
+    case PS_MG:
+        return env->mgregs;
+    case PS_IG:
+        return env->igregs;
+    }
+}
+
+static inline void change_pstate(uint32_t new_pstate)
+{
+    uint32_t pstate_regs, new_pstate_regs;
+    uint64_t *src, *dst;
+
+    if (env->def->features & CPU_FEATURE_GL) {
+        /* PS_AG is not implemented in this case */
+        new_pstate &= ~PS_AG;
+    }
+
+    pstate_regs = env->pstate & 0xc01;
+    new_pstate_regs = new_pstate & 0xc01;
+
+    if (new_pstate_regs != pstate_regs) {
+        DPRINTF_PSTATE("change_pstate: switching regs old=%x new=%x\n",
+                       pstate_regs, new_pstate_regs);
+        /* Switch global register bank */
+        src = get_gregset(new_pstate_regs);
+        dst = get_gregset(pstate_regs);
+        memcpy32(dst, env->gregs);
+        memcpy32(env->gregs, src);
+    } else {
+        DPRINTF_PSTATE("change_pstate: regs new=%x (unchanged)\n",
+                       new_pstate_regs);
+    }
+    env->pstate = new_pstate;
+}
+
+void helper_wrpstate(target_ulong new_state)
+{
+    change_pstate(new_state & 0xf3f);
+
+#if !defined(CONFIG_USER_ONLY)
+    if (cpu_interrupts_enabled(env)) {
+        cpu_check_irqs(env);
+    }
+#endif
+}
+
+void cpu_change_pstate(CPUState *env1, uint32_t new_pstate)
+{
+    CPUState *saved_env;
+
+    saved_env = env;
+    env = env1;
+    change_pstate(new_pstate);
+    env = saved_env;
+}
+
+void helper_wrpil(target_ulong new_pil)
+{
+#if !defined(CONFIG_USER_ONLY)
+    DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
+                   env->psrpil, (uint32_t)new_pil);
+
+    env->psrpil = new_pil;
+
+    if (cpu_interrupts_enabled(env)) {
+        cpu_check_irqs(env);
+    }
+#endif
+}
+
+void helper_done(void)
+{
+    trap_state *tsptr = cpu_tsptr(env);
+
+    env->pc = tsptr->tnpc;
+    env->npc = tsptr->tnpc + 4;
+    put_ccr(tsptr->tstate >> 32);
+    env->asi = (tsptr->tstate >> 24) & 0xff;
+    change_pstate((tsptr->tstate >> 8) & 0xf3f);
+    put_cwp64(tsptr->tstate & 0xff);
+    env->tl--;
+
+    DPRINTF_PSTATE("... helper_done tl=%d\n", env->tl);
+
+#if !defined(CONFIG_USER_ONLY)
+    if (cpu_interrupts_enabled(env)) {
+        cpu_check_irqs(env);
+    }
+#endif
+}
+
+void helper_retry(void)
+{
+    trap_state *tsptr = cpu_tsptr(env);
+
+    env->pc = tsptr->tpc;
+    env->npc = tsptr->tnpc;
+    put_ccr(tsptr->tstate >> 32);
+    env->asi = (tsptr->tstate >> 24) & 0xff;
+    change_pstate((tsptr->tstate >> 8) & 0xf3f);
+    put_cwp64(tsptr->tstate & 0xff);
+    env->tl--;
+
+    DPRINTF_PSTATE("... helper_retry tl=%d\n", env->tl);
+
+#if !defined(CONFIG_USER_ONLY)
+    if (cpu_interrupts_enabled(env)) {
+        cpu_check_irqs(env);
+    }
+#endif
+}
+#endif
commit 2ffd9176b10caefab5f2bade13b1b54154266b35
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Jul 3 16:01:57 2011 +0000

    Sparc: avoid AREG0 for lazy condition code helpers
    
    Make lazy condition code helpers take a parameter for CPUState instead
    of relying on global env.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index a3da238..e720a12 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -97,7 +97,7 @@ tcg/tcg.o: cpu.h
 
 # HELPER_CFLAGS is used for all the code compiled with static register
 # variables
-op_helper.o cc_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+op_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 
 # Note: this is a workaround. The real fix is to avoid compiling
 # cpu_signal_handler() in user-exec.c.
diff --git a/target-sparc/cc_helper.c b/target-sparc/cc_helper.c
index a067397..04bd2cf 100644
--- a/target-sparc/cc_helper.c
+++ b/target-sparc/cc_helper.c
@@ -18,15 +18,14 @@
  */
 
 #include "cpu.h"
-#include "dyngen-exec.h"
 #include "helper.h"
 
-static uint32_t compute_all_flags(void)
+static uint32_t compute_all_flags(CPUState *env)
 {
     return env->psr & PSR_ICC;
 }
 
-static uint32_t compute_C_flags(void)
+static uint32_t compute_C_flags(CPUState *env)
 {
     return env->psr & PSR_CARRY;
 }
@@ -44,12 +43,12 @@ static inline uint32_t get_NZ_icc(int32_t dst)
 }
 
 #ifdef TARGET_SPARC64
-static uint32_t compute_all_flags_xcc(void)
+static uint32_t compute_all_flags_xcc(CPUState *env)
 {
     return env->xcc & PSR_ICC;
 }
 
-static uint32_t compute_C_flags_xcc(void)
+static uint32_t compute_C_flags_xcc(CPUState *env)
 {
     return env->xcc & PSR_CARRY;
 }
@@ -77,7 +76,7 @@ static inline uint32_t get_V_div_icc(target_ulong src2)
     return ret;
 }
 
-static uint32_t compute_all_div(void)
+static uint32_t compute_all_div(CPUState *env)
 {
     uint32_t ret;
 
@@ -86,7 +85,7 @@ static uint32_t compute_all_div(void)
     return ret;
 }
 
-static uint32_t compute_C_div(void)
+static uint32_t compute_C_div(CPUState *env)
 {
     return 0;
 }
@@ -156,7 +155,7 @@ static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
     return ret;
 }
 
-static uint32_t compute_all_add_xcc(void)
+static uint32_t compute_all_add_xcc(CPUState *env)
 {
     uint32_t ret;
 
@@ -166,13 +165,13 @@ static uint32_t compute_all_add_xcc(void)
     return ret;
 }
 
-static uint32_t compute_C_add_xcc(void)
+static uint32_t compute_C_add_xcc(CPUState *env)
 {
     return get_C_add_xcc(CC_DST, CC_SRC);
 }
 #endif
 
-static uint32_t compute_all_add(void)
+static uint32_t compute_all_add(CPUState *env)
 {
     uint32_t ret;
 
@@ -182,13 +181,13 @@ static uint32_t compute_all_add(void)
     return ret;
 }
 
-static uint32_t compute_C_add(void)
+static uint32_t compute_C_add(CPUState *env)
 {
     return get_C_add_icc(CC_DST, CC_SRC);
 }
 
 #ifdef TARGET_SPARC64
-static uint32_t compute_all_addx_xcc(void)
+static uint32_t compute_all_addx_xcc(CPUState *env)
 {
     uint32_t ret;
 
@@ -198,7 +197,7 @@ static uint32_t compute_all_addx_xcc(void)
     return ret;
 }
 
-static uint32_t compute_C_addx_xcc(void)
+static uint32_t compute_C_addx_xcc(CPUState *env)
 {
     uint32_t ret;
 
@@ -207,7 +206,7 @@ static uint32_t compute_C_addx_xcc(void)
 }
 #endif
 
-static uint32_t compute_all_addx(void)
+static uint32_t compute_all_addx(CPUState *env)
 {
     uint32_t ret;
 
@@ -217,7 +216,7 @@ static uint32_t compute_all_addx(void)
     return ret;
 }
 
-static uint32_t compute_C_addx(void)
+static uint32_t compute_C_addx(CPUState *env)
 {
     uint32_t ret;
 
@@ -235,7 +234,7 @@ static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
     return ret;
 }
 
-static uint32_t compute_all_tadd(void)
+static uint32_t compute_all_tadd(CPUState *env)
 {
     uint32_t ret;
 
@@ -246,7 +245,7 @@ static uint32_t compute_all_tadd(void)
     return ret;
 }
 
-static uint32_t compute_all_taddtv(void)
+static uint32_t compute_all_taddtv(CPUState *env)
 {
     uint32_t ret;
 
@@ -321,7 +320,7 @@ static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
     return ret;
 }
 
-static uint32_t compute_all_sub_xcc(void)
+static uint32_t compute_all_sub_xcc(CPUState *env)
 {
     uint32_t ret;
 
@@ -331,13 +330,13 @@ static uint32_t compute_all_sub_xcc(void)
     return ret;
 }
 
-static uint32_t compute_C_sub_xcc(void)
+static uint32_t compute_C_sub_xcc(CPUState *env)
 {
     return get_C_sub_xcc(CC_SRC, CC_SRC2);
 }
 #endif
 
-static uint32_t compute_all_sub(void)
+static uint32_t compute_all_sub(CPUState *env)
 {
     uint32_t ret;
 
@@ -347,13 +346,13 @@ static uint32_t compute_all_sub(void)
     return ret;
 }
 
-static uint32_t compute_C_sub(void)
+static uint32_t compute_C_sub(CPUState *env)
 {
     return get_C_sub_icc(CC_SRC, CC_SRC2);
 }
 
 #ifdef TARGET_SPARC64
-static uint32_t compute_all_subx_xcc(void)
+static uint32_t compute_all_subx_xcc(CPUState *env)
 {
     uint32_t ret;
 
@@ -363,7 +362,7 @@ static uint32_t compute_all_subx_xcc(void)
     return ret;
 }
 
-static uint32_t compute_C_subx_xcc(void)
+static uint32_t compute_C_subx_xcc(CPUState *env)
 {
     uint32_t ret;
 
@@ -372,7 +371,7 @@ static uint32_t compute_C_subx_xcc(void)
 }
 #endif
 
-static uint32_t compute_all_subx(void)
+static uint32_t compute_all_subx(CPUState *env)
 {
     uint32_t ret;
 
@@ -382,7 +381,7 @@ static uint32_t compute_all_subx(void)
     return ret;
 }
 
-static uint32_t compute_C_subx(void)
+static uint32_t compute_C_subx(CPUState *env)
 {
     uint32_t ret;
 
@@ -390,7 +389,7 @@ static uint32_t compute_C_subx(void)
     return ret;
 }
 
-static uint32_t compute_all_tsub(void)
+static uint32_t compute_all_tsub(CPUState *env)
 {
     uint32_t ret;
 
@@ -401,7 +400,7 @@ static uint32_t compute_all_tsub(void)
     return ret;
 }
 
-static uint32_t compute_all_tsubtv(void)
+static uint32_t compute_all_tsubtv(CPUState *env)
 {
     uint32_t ret;
 
@@ -410,26 +409,26 @@ static uint32_t compute_all_tsubtv(void)
     return ret;
 }
 
-static uint32_t compute_all_logic(void)
+static uint32_t compute_all_logic(CPUState *env)
 {
     return get_NZ_icc(CC_DST);
 }
 
-static uint32_t compute_C_logic(void)
+static uint32_t compute_C_logic(CPUState *env)
 {
     return 0;
 }
 
 #ifdef TARGET_SPARC64
-static uint32_t compute_all_logic_xcc(void)
+static uint32_t compute_all_logic_xcc(CPUState *env)
 {
     return get_NZ_xcc(CC_DST);
 }
 #endif
 
 typedef struct CCTable {
-    uint32_t (*compute_all)(void); /* return all the flags */
-    uint32_t (*compute_c)(void);  /* return the C flag */
+    uint32_t (*compute_all)(CPUState *env); /* return all the flags */
+    uint32_t (*compute_c)(CPUState *env);  /* return the C flag */
 } CCTable;
 
 static const CCTable icc_table[CC_OP_NB] = {
@@ -464,23 +463,23 @@ static const CCTable xcc_table[CC_OP_NB] = {
 };
 #endif
 
-void helper_compute_psr(void)
+void helper_compute_psr(CPUState *env)
 {
     uint32_t new_psr;
 
-    new_psr = icc_table[CC_OP].compute_all();
+    new_psr = icc_table[CC_OP].compute_all(env);
     env->psr = new_psr;
 #ifdef TARGET_SPARC64
-    new_psr = xcc_table[CC_OP].compute_all();
+    new_psr = xcc_table[CC_OP].compute_all(env);
     env->xcc = new_psr;
 #endif
     CC_OP = CC_OP_FLAGS;
 }
 
-uint32_t helper_compute_C_icc(void)
+uint32_t helper_compute_C_icc(CPUState *env)
 {
     uint32_t ret;
 
-    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
+    ret = icc_table[CC_OP].compute_c(env) >> PSR_CARRY_SHIFT;
     return ret;
 }
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index fe63846..57d0073 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -159,7 +159,7 @@ VIS_CMPHELPER(cmpne);
 #undef F_HELPER_DQ_0_1
 #undef VIS_HELPER
 #undef VIS_CMPHELPER
-DEF_HELPER_0(compute_psr, void);
-DEF_HELPER_0(compute_C_icc, i32);
+DEF_HELPER_1(compute_psr, void, env);
+DEF_HELPER_1(compute_C_icc, i32, env);
 
 #include "def-helper.h"
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 33d46a4..18a00d4 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -372,7 +372,7 @@ void cpu_set_cwp(CPUState *env1, int new_cwp)
 
 static target_ulong get_psr(void)
 {
-    helper_compute_psr();
+    helper_compute_psr(env);
 
 #if !defined (TARGET_SPARC64)
     return env->version | (env->psr & PSR_ICC) |
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 8c05c44..214252a 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -428,7 +428,7 @@ static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1,
     default:
         /* We need external help to produce the carry.  */
         carry_32 = tcg_temp_new_i32();
-        gen_helper_compute_C_icc(carry_32);
+        gen_helper_compute_C_icc(carry_32, cpu_env);
         break;
     }
 
@@ -567,7 +567,7 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
     default:
         /* We need external help to produce the carry.  */
         carry_32 = tcg_temp_new_i32();
-        gen_helper_compute_C_icc(carry_32);
+        gen_helper_compute_C_icc(carry_32, cpu_env);
         break;
     }
 
@@ -1091,7 +1091,7 @@ static inline void save_state(DisasContext *dc, TCGv cond)
     /* flush pending conditional evaluations before exposing cpu state */
     if (dc->cc_op != CC_OP_FLAGS) {
         dc->cc_op = CC_OP_FLAGS;
-        gen_helper_compute_psr();
+        gen_helper_compute_psr(cpu_env);
     }
     save_npc(dc, cond);
 }
@@ -1133,7 +1133,7 @@ static inline void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond,
     case CC_OP_FLAGS:
         break;
     default:
-        gen_helper_compute_psr();
+        gen_helper_compute_psr(cpu_env);
         dc->cc_op = CC_OP_FLAGS;
         break;
     }
@@ -2106,7 +2106,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     break;
 #ifdef TARGET_SPARC64
                 case 0x2: /* V9 rdccr */
-                    gen_helper_compute_psr();
+                    gen_helper_compute_psr(cpu_env);
                     gen_helper_rdccr(cpu_dst);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
@@ -2182,7 +2182,7 @@ static void disas_sparc_insn(DisasContext * dc)
 #ifndef TARGET_SPARC64
                 if (!supervisor(dc))
                     goto priv_insn;
-                gen_helper_compute_psr();
+                gen_helper_compute_psr(cpu_env);
                 dc->cc_op = CC_OP_FLAGS;
                 gen_helper_rdpsr(cpu_dst);
 #else
@@ -3321,7 +3321,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         dc->cc_op = CC_OP_TSUBTV;
                         break;
                     case 0x24: /* mulscc */
-                        gen_helper_compute_psr();
+                        gen_helper_compute_psr(cpu_env);
                         gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2);
                         gen_movl_TN_reg(rd, cpu_dst);
                         tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
@@ -4417,7 +4417,7 @@ static void disas_sparc_insn(DisasContext * dc)
                cpu state */
             if (dc->cc_op != CC_OP_FLAGS) {
                 dc->cc_op = CC_OP_FLAGS;
-                gen_helper_compute_psr();
+                gen_helper_compute_psr(cpu_env);
             }
             cpu_src1 = get_src1(insn, cpu_src1);
             if (xop == 0x3c || xop == 0x3e) { // V9 casa/casxa
@@ -5269,6 +5269,6 @@ void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
 
     /* flush pending conditional evaluations before exposing cpu state */
     if (CC_OP != CC_OP_FLAGS) {
-        helper_compute_psr();
+        helper_compute_psr(env);
     }
 }
commit cffc581873fdb482644acfc4f61d294ad4e81cf0
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Mon Aug 1 08:37:36 2011 +0000

    Sparc: split lazy condition code handling op helpers
    
    Move lazy condition code handling op helpers to cc_helper.c.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index e333e78..a3da238 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -78,7 +78,7 @@ libobj-$(TARGET_SPARC64) += vis_helper.o
 libobj-$(CONFIG_NEED_MMU) += mmu.o
 libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
 ifeq ($(TARGET_BASE_ARCH), sparc)
-libobj-y += fop_helper.o cpu_init.o
+libobj-y += fop_helper.o cc_helper.o cpu_init.o
 endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
@@ -97,7 +97,7 @@ tcg/tcg.o: cpu.h
 
 # HELPER_CFLAGS is used for all the code compiled with static register
 # variables
-op_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+op_helper.o cc_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 
 # Note: this is a workaround. The real fix is to avoid compiling
 # cpu_signal_handler() in user-exec.c.
diff --git a/target-sparc/cc_helper.c b/target-sparc/cc_helper.c
new file mode 100644
index 0000000..a067397
--- /dev/null
+++ b/target-sparc/cc_helper.c
@@ -0,0 +1,486 @@
+/*
+ * Helpers for lazy condition code handling
+ *
+ *  Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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 "helper.h"
+
+static uint32_t compute_all_flags(void)
+{
+    return env->psr & PSR_ICC;
+}
+
+static uint32_t compute_C_flags(void)
+{
+    return env->psr & PSR_CARRY;
+}
+
+static inline uint32_t get_NZ_icc(int32_t dst)
+{
+    uint32_t ret = 0;
+
+    if (dst == 0) {
+        ret = PSR_ZERO;
+    } else if (dst < 0) {
+        ret = PSR_NEG;
+    }
+    return ret;
+}
+
+#ifdef TARGET_SPARC64
+static uint32_t compute_all_flags_xcc(void)
+{
+    return env->xcc & PSR_ICC;
+}
+
+static uint32_t compute_C_flags_xcc(void)
+{
+    return env->xcc & PSR_CARRY;
+}
+
+static inline uint32_t get_NZ_xcc(target_long dst)
+{
+    uint32_t ret = 0;
+
+    if (!dst) {
+        ret = PSR_ZERO;
+    } else if (dst < 0) {
+        ret = PSR_NEG;
+    }
+    return ret;
+}
+#endif
+
+static inline uint32_t get_V_div_icc(target_ulong src2)
+{
+    uint32_t ret = 0;
+
+    if (src2 != 0) {
+        ret = PSR_OVF;
+    }
+    return ret;
+}
+
+static uint32_t compute_all_div(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_icc(CC_DST);
+    ret |= get_V_div_icc(CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_C_div(void)
+{
+    return 0;
+}
+
+static inline uint32_t get_C_add_icc(uint32_t dst, uint32_t src1)
+{
+    uint32_t ret = 0;
+
+    if (dst < src1) {
+        ret = PSR_CARRY;
+    }
+    return ret;
+}
+
+static inline uint32_t get_C_addx_icc(uint32_t dst, uint32_t src1,
+                                      uint32_t src2)
+{
+    uint32_t ret = 0;
+
+    if (((src1 & src2) | (~dst & (src1 | src2))) & (1U << 31)) {
+        ret = PSR_CARRY;
+    }
+    return ret;
+}
+
+static inline uint32_t get_V_add_icc(uint32_t dst, uint32_t src1,
+                                     uint32_t src2)
+{
+    uint32_t ret = 0;
+
+    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1U << 31)) {
+        ret = PSR_OVF;
+    }
+    return ret;
+}
+
+#ifdef TARGET_SPARC64
+static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
+{
+    uint32_t ret = 0;
+
+    if (dst < src1) {
+        ret = PSR_CARRY;
+    }
+    return ret;
+}
+
+static inline uint32_t get_C_addx_xcc(target_ulong dst, target_ulong src1,
+                                      target_ulong src2)
+{
+    uint32_t ret = 0;
+
+    if (((src1 & src2) | (~dst & (src1 | src2))) & (1ULL << 63)) {
+        ret = PSR_CARRY;
+    }
+    return ret;
+}
+
+static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
+                                     target_ulong src2)
+{
+    uint32_t ret = 0;
+
+    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63)) {
+        ret = PSR_OVF;
+    }
+    return ret;
+}
+
+static uint32_t compute_all_add_xcc(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_xcc(CC_DST);
+    ret |= get_C_add_xcc(CC_DST, CC_SRC);
+    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_C_add_xcc(void)
+{
+    return get_C_add_xcc(CC_DST, CC_SRC);
+}
+#endif
+
+static uint32_t compute_all_add(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_icc(CC_DST);
+    ret |= get_C_add_icc(CC_DST, CC_SRC);
+    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_C_add(void)
+{
+    return get_C_add_icc(CC_DST, CC_SRC);
+}
+
+#ifdef TARGET_SPARC64
+static uint32_t compute_all_addx_xcc(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_xcc(CC_DST);
+    ret |= get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
+    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_C_addx_xcc(void)
+{
+    uint32_t ret;
+
+    ret = get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
+    return ret;
+}
+#endif
+
+static uint32_t compute_all_addx(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_icc(CC_DST);
+    ret |= get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
+    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_C_addx(void)
+{
+    uint32_t ret;
+
+    ret = get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
+{
+    uint32_t ret = 0;
+
+    if ((src1 | src2) & 0x3) {
+        ret = PSR_OVF;
+    }
+    return ret;
+}
+
+static uint32_t compute_all_tadd(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_icc(CC_DST);
+    ret |= get_C_add_icc(CC_DST, CC_SRC);
+    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
+    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_all_taddtv(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_icc(CC_DST);
+    ret |= get_C_add_icc(CC_DST, CC_SRC);
+    return ret;
+}
+
+static inline uint32_t get_C_sub_icc(uint32_t src1, uint32_t src2)
+{
+    uint32_t ret = 0;
+
+    if (src1 < src2) {
+        ret = PSR_CARRY;
+    }
+    return ret;
+}
+
+static inline uint32_t get_C_subx_icc(uint32_t dst, uint32_t src1,
+                                      uint32_t src2)
+{
+    uint32_t ret = 0;
+
+    if (((~src1 & src2) | (dst & (~src1 | src2))) & (1U << 31)) {
+        ret = PSR_CARRY;
+    }
+    return ret;
+}
+
+static inline uint32_t get_V_sub_icc(uint32_t dst, uint32_t src1,
+                                     uint32_t src2)
+{
+    uint32_t ret = 0;
+
+    if (((src1 ^ src2) & (src1 ^ dst)) & (1U << 31)) {
+        ret = PSR_OVF;
+    }
+    return ret;
+}
+
+
+#ifdef TARGET_SPARC64
+static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
+{
+    uint32_t ret = 0;
+
+    if (src1 < src2) {
+        ret = PSR_CARRY;
+    }
+    return ret;
+}
+
+static inline uint32_t get_C_subx_xcc(target_ulong dst, target_ulong src1,
+                                      target_ulong src2)
+{
+    uint32_t ret = 0;
+
+    if (((~src1 & src2) | (dst & (~src1 | src2))) & (1ULL << 63)) {
+        ret = PSR_CARRY;
+    }
+    return ret;
+}
+
+static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
+                                     target_ulong src2)
+{
+    uint32_t ret = 0;
+
+    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63)) {
+        ret = PSR_OVF;
+    }
+    return ret;
+}
+
+static uint32_t compute_all_sub_xcc(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_xcc(CC_DST);
+    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
+    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_C_sub_xcc(void)
+{
+    return get_C_sub_xcc(CC_SRC, CC_SRC2);
+}
+#endif
+
+static uint32_t compute_all_sub(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_icc(CC_DST);
+    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
+    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_C_sub(void)
+{
+    return get_C_sub_icc(CC_SRC, CC_SRC2);
+}
+
+#ifdef TARGET_SPARC64
+static uint32_t compute_all_subx_xcc(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_xcc(CC_DST);
+    ret |= get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
+    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_C_subx_xcc(void)
+{
+    uint32_t ret;
+
+    ret = get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
+    return ret;
+}
+#endif
+
+static uint32_t compute_all_subx(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_icc(CC_DST);
+    ret |= get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
+    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_C_subx(void)
+{
+    uint32_t ret;
+
+    ret = get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_all_tsub(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_icc(CC_DST);
+    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
+    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_all_tsubtv(void)
+{
+    uint32_t ret;
+
+    ret = get_NZ_icc(CC_DST);
+    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
+    return ret;
+}
+
+static uint32_t compute_all_logic(void)
+{
+    return get_NZ_icc(CC_DST);
+}
+
+static uint32_t compute_C_logic(void)
+{
+    return 0;
+}
+
+#ifdef TARGET_SPARC64
+static uint32_t compute_all_logic_xcc(void)
+{
+    return get_NZ_xcc(CC_DST);
+}
+#endif
+
+typedef struct CCTable {
+    uint32_t (*compute_all)(void); /* return all the flags */
+    uint32_t (*compute_c)(void);  /* return the C flag */
+} CCTable;
+
+static const CCTable icc_table[CC_OP_NB] = {
+    /* CC_OP_DYNAMIC should never happen */
+    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
+    [CC_OP_DIV] = { compute_all_div, compute_C_div },
+    [CC_OP_ADD] = { compute_all_add, compute_C_add },
+    [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
+    [CC_OP_TADD] = { compute_all_tadd, compute_C_add },
+    [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_add },
+    [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
+    [CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
+    [CC_OP_TSUB] = { compute_all_tsub, compute_C_sub },
+    [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_sub },
+    [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
+};
+
+#ifdef TARGET_SPARC64
+static const CCTable xcc_table[CC_OP_NB] = {
+    /* CC_OP_DYNAMIC should never happen */
+    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
+    [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
+    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
+    [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
+    [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
+    [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
+    [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
+    [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
+    [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
+    [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
+    [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
+};
+#endif
+
+void helper_compute_psr(void)
+{
+    uint32_t new_psr;
+
+    new_psr = icc_table[CC_OP].compute_all();
+    env->psr = new_psr;
+#ifdef TARGET_SPARC64
+    new_psr = xcc_table[CC_OP].compute_all();
+    env->xcc = new_psr;
+#endif
+    CC_OP = CC_OP_FLAGS;
+}
+
+uint32_t helper_compute_C_icc(void)
+{
+    uint32_t ret;
+
+    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
+    return ret;
+}
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index fd20366..33d46a4 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -333,470 +333,6 @@ void helper_check_align(target_ulong addr, uint32_t align)
     }
 }
 
-static uint32_t compute_all_flags(void)
-{
-    return env->psr & PSR_ICC;
-}
-
-static uint32_t compute_C_flags(void)
-{
-    return env->psr & PSR_CARRY;
-}
-
-static inline uint32_t get_NZ_icc(int32_t dst)
-{
-    uint32_t ret = 0;
-
-    if (dst == 0) {
-        ret = PSR_ZERO;
-    } else if (dst < 0) {
-        ret = PSR_NEG;
-    }
-    return ret;
-}
-
-#ifdef TARGET_SPARC64
-static uint32_t compute_all_flags_xcc(void)
-{
-    return env->xcc & PSR_ICC;
-}
-
-static uint32_t compute_C_flags_xcc(void)
-{
-    return env->xcc & PSR_CARRY;
-}
-
-static inline uint32_t get_NZ_xcc(target_long dst)
-{
-    uint32_t ret = 0;
-
-    if (!dst) {
-        ret = PSR_ZERO;
-    } else if (dst < 0) {
-        ret = PSR_NEG;
-    }
-    return ret;
-}
-#endif
-
-static inline uint32_t get_V_div_icc(target_ulong src2)
-{
-    uint32_t ret = 0;
-
-    if (src2 != 0) {
-        ret = PSR_OVF;
-    }
-    return ret;
-}
-
-static uint32_t compute_all_div(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_icc(CC_DST);
-    ret |= get_V_div_icc(CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_C_div(void)
-{
-    return 0;
-}
-
-static inline uint32_t get_C_add_icc(uint32_t dst, uint32_t src1)
-{
-    uint32_t ret = 0;
-
-    if (dst < src1) {
-        ret = PSR_CARRY;
-    }
-    return ret;
-}
-
-static inline uint32_t get_C_addx_icc(uint32_t dst, uint32_t src1,
-                                      uint32_t src2)
-{
-    uint32_t ret = 0;
-
-    if (((src1 & src2) | (~dst & (src1 | src2))) & (1U << 31)) {
-        ret = PSR_CARRY;
-    }
-    return ret;
-}
-
-static inline uint32_t get_V_add_icc(uint32_t dst, uint32_t src1,
-                                     uint32_t src2)
-{
-    uint32_t ret = 0;
-
-    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1U << 31)) {
-        ret = PSR_OVF;
-    }
-    return ret;
-}
-
-#ifdef TARGET_SPARC64
-static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
-{
-    uint32_t ret = 0;
-
-    if (dst < src1) {
-        ret = PSR_CARRY;
-    }
-    return ret;
-}
-
-static inline uint32_t get_C_addx_xcc(target_ulong dst, target_ulong src1,
-                                      target_ulong src2)
-{
-    uint32_t ret = 0;
-
-    if (((src1 & src2) | (~dst & (src1 | src2))) & (1ULL << 63)) {
-        ret = PSR_CARRY;
-    }
-    return ret;
-}
-
-static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
-                                     target_ulong src2)
-{
-    uint32_t ret = 0;
-
-    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63)) {
-        ret = PSR_OVF;
-    }
-    return ret;
-}
-
-static uint32_t compute_all_add_xcc(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_xcc(CC_DST);
-    ret |= get_C_add_xcc(CC_DST, CC_SRC);
-    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_C_add_xcc(void)
-{
-    return get_C_add_xcc(CC_DST, CC_SRC);
-}
-#endif
-
-static uint32_t compute_all_add(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_icc(CC_DST);
-    ret |= get_C_add_icc(CC_DST, CC_SRC);
-    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_C_add(void)
-{
-    return get_C_add_icc(CC_DST, CC_SRC);
-}
-
-#ifdef TARGET_SPARC64
-static uint32_t compute_all_addx_xcc(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_xcc(CC_DST);
-    ret |= get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
-    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_C_addx_xcc(void)
-{
-    uint32_t ret;
-
-    ret = get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-#endif
-
-static uint32_t compute_all_addx(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_icc(CC_DST);
-    ret |= get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
-    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_C_addx(void)
-{
-    uint32_t ret;
-
-    ret = get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
-{
-    uint32_t ret = 0;
-
-    if ((src1 | src2) & 0x3) {
-        ret = PSR_OVF;
-    }
-    return ret;
-}
-
-static uint32_t compute_all_tadd(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_icc(CC_DST);
-    ret |= get_C_add_icc(CC_DST, CC_SRC);
-    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
-    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_all_taddtv(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_icc(CC_DST);
-    ret |= get_C_add_icc(CC_DST, CC_SRC);
-    return ret;
-}
-
-static inline uint32_t get_C_sub_icc(uint32_t src1, uint32_t src2)
-{
-    uint32_t ret = 0;
-
-    if (src1 < src2) {
-        ret = PSR_CARRY;
-    }
-    return ret;
-}
-
-static inline uint32_t get_C_subx_icc(uint32_t dst, uint32_t src1,
-                                      uint32_t src2)
-{
-    uint32_t ret = 0;
-
-    if (((~src1 & src2) | (dst & (~src1 | src2))) & (1U << 31)) {
-        ret = PSR_CARRY;
-    }
-    return ret;
-}
-
-static inline uint32_t get_V_sub_icc(uint32_t dst, uint32_t src1,
-                                     uint32_t src2)
-{
-    uint32_t ret = 0;
-
-    if (((src1 ^ src2) & (src1 ^ dst)) & (1U << 31)) {
-        ret = PSR_OVF;
-    }
-    return ret;
-}
-
-
-#ifdef TARGET_SPARC64
-static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
-{
-    uint32_t ret = 0;
-
-    if (src1 < src2) {
-        ret = PSR_CARRY;
-    }
-    return ret;
-}
-
-static inline uint32_t get_C_subx_xcc(target_ulong dst, target_ulong src1,
-                                      target_ulong src2)
-{
-    uint32_t ret = 0;
-
-    if (((~src1 & src2) | (dst & (~src1 | src2))) & (1ULL << 63)) {
-        ret = PSR_CARRY;
-    }
-    return ret;
-}
-
-static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
-                                     target_ulong src2)
-{
-    uint32_t ret = 0;
-
-    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63)) {
-        ret = PSR_OVF;
-    }
-    return ret;
-}
-
-static uint32_t compute_all_sub_xcc(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_xcc(CC_DST);
-    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
-    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_C_sub_xcc(void)
-{
-    return get_C_sub_xcc(CC_SRC, CC_SRC2);
-}
-#endif
-
-static uint32_t compute_all_sub(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_icc(CC_DST);
-    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
-    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_C_sub(void)
-{
-    return get_C_sub_icc(CC_SRC, CC_SRC2);
-}
-
-#ifdef TARGET_SPARC64
-static uint32_t compute_all_subx_xcc(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_xcc(CC_DST);
-    ret |= get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
-    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_C_subx_xcc(void)
-{
-    uint32_t ret;
-
-    ret = get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-#endif
-
-static uint32_t compute_all_subx(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_icc(CC_DST);
-    ret |= get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
-    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_C_subx(void)
-{
-    uint32_t ret;
-
-    ret = get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_all_tsub(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_icc(CC_DST);
-    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
-    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
-    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_all_tsubtv(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_icc(CC_DST);
-    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_all_logic(void)
-{
-    return get_NZ_icc(CC_DST);
-}
-
-static uint32_t compute_C_logic(void)
-{
-    return 0;
-}
-
-#ifdef TARGET_SPARC64
-static uint32_t compute_all_logic_xcc(void)
-{
-    return get_NZ_xcc(CC_DST);
-}
-#endif
-
-typedef struct CCTable {
-    uint32_t (*compute_all)(void); /* return all the flags */
-    uint32_t (*compute_c)(void);  /* return the C flag */
-} CCTable;
-
-static const CCTable icc_table[CC_OP_NB] = {
-    /* CC_OP_DYNAMIC should never happen */
-    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
-    [CC_OP_DIV] = { compute_all_div, compute_C_div },
-    [CC_OP_ADD] = { compute_all_add, compute_C_add },
-    [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
-    [CC_OP_TADD] = { compute_all_tadd, compute_C_add },
-    [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_add },
-    [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
-    [CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
-    [CC_OP_TSUB] = { compute_all_tsub, compute_C_sub },
-    [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_sub },
-    [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
-};
-
-#ifdef TARGET_SPARC64
-static const CCTable xcc_table[CC_OP_NB] = {
-    /* CC_OP_DYNAMIC should never happen */
-    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
-    [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
-    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
-    [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
-    [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
-    [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
-    [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
-    [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
-    [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
-    [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
-    [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
-};
-#endif
-
-void helper_compute_psr(void)
-{
-    uint32_t new_psr;
-
-    new_psr = icc_table[CC_OP].compute_all();
-    env->psr = new_psr;
-#ifdef TARGET_SPARC64
-    new_psr = xcc_table[CC_OP].compute_all();
-    env->xcc = new_psr;
-#endif
-    CC_OP = CC_OP_FLAGS;
-}
-
-uint32_t helper_compute_C_icc(void)
-{
-    uint32_t ret;
-
-    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
-    return ret;
-}
-
 static inline void memcpy32(target_ulong *dst, const target_ulong *src)
 {
     dst[0] = src[0];
commit 2e2f4ade86e335ea7ffa2b5f32e3ad50619fb4e5
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Jul 3 10:42:23 2011 +0000

    Sparc: avoid AREG0 for float and VIS ops
    
    Make floating point and VIS ops take a parameter for CPUState instead
    of relying on global env.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index fc277b3..e333e78 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -97,7 +97,7 @@ tcg/tcg.o: cpu.h
 
 # HELPER_CFLAGS is used for all the code compiled with static register
 # variables
-op_helper.o fop_helper.o vis_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+op_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 
 # Note: this is a workaround. The real fix is to avoid compiling
 # cpu_signal_handler() in user-exec.c.
diff --git a/target-sparc/fop_helper.c b/target-sparc/fop_helper.c
index ddd0af9..23502f3 100644
--- a/target-sparc/fop_helper.c
+++ b/target-sparc/fop_helper.c
@@ -18,7 +18,6 @@
  */
 
 #include "cpu.h"
-#include "dyngen-exec.h"
 #include "helper.h"
 
 #define DT0 (env->dt0)
@@ -26,10 +25,11 @@
 #define QT0 (env->qt0)
 #define QT1 (env->qt1)
 
-#define F_HELPER(name, p) void helper_f##name##p(void)
+#define F_HELPER(name, p) void helper_f##name##p(CPUState *env)
 
 #define F_BINOP(name)                                           \
-    float32 helper_f ## name ## s (float32 src1, float32 src2)  \
+    float32 helper_f ## name ## s (CPUState * env, float32 src1,\
+                                   float32 src2)                \
     {                                                           \
         return float32_ ## name (src1, src2, &env->fp_status);  \
     }                                                           \
@@ -48,14 +48,14 @@ F_BINOP(mul);
 F_BINOP(div);
 #undef F_BINOP
 
-void helper_fsmuld(float32 src1, float32 src2)
+void helper_fsmuld(CPUState *env, float32 src1, float32 src2)
 {
     DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
                       float32_to_float64(src2, &env->fp_status),
                       &env->fp_status);
 }
 
-void helper_fdmulq(void)
+void helper_fdmulq(CPUState *env)
 {
     QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
                        float64_to_float128(DT1, &env->fp_status),
@@ -80,23 +80,23 @@ F_HELPER(neg, q)
 #endif
 
 /* Integer to float conversion.  */
-float32 helper_fitos(int32_t src)
+float32 helper_fitos(CPUState *env, int32_t src)
 {
     return int32_to_float32(src, &env->fp_status);
 }
 
-void helper_fitod(int32_t src)
+void helper_fitod(CPUState *env, int32_t src)
 {
     DT0 = int32_to_float64(src, &env->fp_status);
 }
 
-void helper_fitoq(int32_t src)
+void helper_fitoq(CPUState *env, int32_t src)
 {
     QT0 = int32_to_float128(src, &env->fp_status);
 }
 
 #ifdef TARGET_SPARC64
-float32 helper_fxtos(void)
+float32 helper_fxtos(CPUState *env)
 {
     return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
 }
@@ -114,64 +114,64 @@ F_HELPER(xto, q)
 #undef F_HELPER
 
 /* floating point conversion */
-float32 helper_fdtos(void)
+float32 helper_fdtos(CPUState *env)
 {
     return float64_to_float32(DT1, &env->fp_status);
 }
 
-void helper_fstod(float32 src)
+void helper_fstod(CPUState *env, float32 src)
 {
     DT0 = float32_to_float64(src, &env->fp_status);
 }
 
-float32 helper_fqtos(void)
+float32 helper_fqtos(CPUState *env)
 {
     return float128_to_float32(QT1, &env->fp_status);
 }
 
-void helper_fstoq(float32 src)
+void helper_fstoq(CPUState *env, float32 src)
 {
     QT0 = float32_to_float128(src, &env->fp_status);
 }
 
-void helper_fqtod(void)
+void helper_fqtod(CPUState *env)
 {
     DT0 = float128_to_float64(QT1, &env->fp_status);
 }
 
-void helper_fdtoq(void)
+void helper_fdtoq(CPUState *env)
 {
     QT0 = float64_to_float128(DT1, &env->fp_status);
 }
 
 /* Float to integer conversion.  */
-int32_t helper_fstoi(float32 src)
+int32_t helper_fstoi(CPUState *env, float32 src)
 {
     return float32_to_int32_round_to_zero(src, &env->fp_status);
 }
 
-int32_t helper_fdtoi(void)
+int32_t helper_fdtoi(CPUState *env)
 {
     return float64_to_int32_round_to_zero(DT1, &env->fp_status);
 }
 
-int32_t helper_fqtoi(void)
+int32_t helper_fqtoi(CPUState *env)
 {
     return float128_to_int32_round_to_zero(QT1, &env->fp_status);
 }
 
 #ifdef TARGET_SPARC64
-void helper_fstox(float32 src)
+void helper_fstox(CPUState *env, float32 src)
 {
     *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
 }
 
-void helper_fdtox(void)
+void helper_fdtox(CPUState *env)
 {
     *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
 }
 
-void helper_fqtox(void)
+void helper_fqtox(CPUState *env)
 {
     *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
 }
@@ -183,34 +183,34 @@ float32 helper_fabss(float32 src)
 }
 
 #ifdef TARGET_SPARC64
-void helper_fabsd(void)
+void helper_fabsd(CPUState *env)
 {
     DT0 = float64_abs(DT1);
 }
 
-void helper_fabsq(void)
+void helper_fabsq(CPUState *env)
 {
     QT0 = float128_abs(QT1);
 }
 #endif
 
-float32 helper_fsqrts(float32 src)
+float32 helper_fsqrts(CPUState *env, float32 src)
 {
     return float32_sqrt(src, &env->fp_status);
 }
 
-void helper_fsqrtd(void)
+void helper_fsqrtd(CPUState *env)
 {
     DT0 = float64_sqrt(DT1, &env->fp_status);
 }
 
-void helper_fsqrtq(void)
+void helper_fsqrtq(CPUState *env)
 {
     QT0 = float128_sqrt(QT1, &env->fp_status);
 }
 
 #define GEN_FCMP(name, size, reg1, reg2, FS, E)                         \
-    void glue(helper_, name) (void)                                     \
+    void glue(helper_, name) (CPUState *env)                            \
     {                                                                   \
         env->fsr &= FSR_FTT_NMASK;                                      \
         if (E && (glue(size, _is_any_nan)(reg1) ||                      \
@@ -246,7 +246,7 @@ void helper_fsqrtq(void)
         }                                                               \
     }
 #define GEN_FCMPS(name, size, FS, E)                                    \
-    void glue(helper_, name)(float32 src1, float32 src2)                \
+    void glue(helper_, name)(CPUState *env, float32 src1, float32 src2) \
     {                                                                   \
         env->fsr &= FSR_FTT_NMASK;                                      \
         if (E && (glue(size, _is_any_nan)(src1) ||                      \
@@ -318,7 +318,7 @@ GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
 #endif
 #undef GEN_FCMPS
 
-void helper_check_ieee_exceptions(void)
+void helper_check_ieee_exceptions(CPUState *env)
 {
     target_ulong status;
 
@@ -352,12 +352,12 @@ void helper_check_ieee_exceptions(void)
     }
 }
 
-void helper_clear_float_exceptions(void)
+void helper_clear_float_exceptions(CPUState *env)
 {
     set_float_exception_flags(0, &env->fp_status);
 }
 
-static inline void set_fsr(void)
+static inline void set_fsr(CPUState *env)
 {
     int rnd_mode;
 
@@ -379,16 +379,16 @@ static inline void set_fsr(void)
     set_float_rounding_mode(rnd_mode, &env->fp_status);
 }
 
-void helper_ldfsr(uint32_t new_fsr)
+void helper_ldfsr(CPUState *env, uint32_t new_fsr)
 {
     env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
-    set_fsr();
+    set_fsr(env);
 }
 
 #ifdef TARGET_SPARC64
-void helper_ldxfsr(uint64_t new_fsr)
+void helper_ldxfsr(CPUState *env, uint64_t new_fsr)
 {
     env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
-    set_fsr();
+    set_fsr(env);
 }
 #endif
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index a452666..fe63846 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -16,8 +16,8 @@ DEF_HELPER_0(rdccr, tl)
 DEF_HELPER_1(wrccr, void, tl)
 DEF_HELPER_0(rdcwp, tl)
 DEF_HELPER_1(wrcwp, void, tl)
-DEF_HELPER_2(array8, tl, tl, tl)
-DEF_HELPER_2(alignaddr, tl, tl, tl)
+DEF_HELPER_3(array8, tl, env, tl, tl)
+DEF_HELPER_3(alignaddr, tl, env, tl, tl)
 DEF_HELPER_1(popc, tl, tl)
 DEF_HELPER_3(ldda_asi, void, tl, int, int)
 DEF_HELPER_4(ldf_asi, void, tl, int, int, int)
@@ -47,116 +47,116 @@ DEF_HELPER_2(stqf, void, tl, int)
 DEF_HELPER_4(ld_asi, i64, tl, int, int, int)
 DEF_HELPER_4(st_asi, void, tl, i64, int, int)
 #endif
-DEF_HELPER_1(ldfsr, void, i32)
-DEF_HELPER_0(check_ieee_exceptions, void)
-DEF_HELPER_0(clear_float_exceptions, void)
+DEF_HELPER_2(ldfsr, void, env, i32)
+DEF_HELPER_1(check_ieee_exceptions, void, env)
+DEF_HELPER_1(clear_float_exceptions, void, env)
 DEF_HELPER_1(fabss, f32, f32)
-DEF_HELPER_1(fsqrts, f32, f32)
-DEF_HELPER_0(fsqrtd, void)
-DEF_HELPER_2(fcmps, void, f32, f32)
-DEF_HELPER_0(fcmpd, void)
-DEF_HELPER_2(fcmpes, void, f32, f32)
-DEF_HELPER_0(fcmped, void)
-DEF_HELPER_0(fsqrtq, void)
-DEF_HELPER_0(fcmpq, void)
-DEF_HELPER_0(fcmpeq, void)
+DEF_HELPER_2(fsqrts, f32, env, f32)
+DEF_HELPER_1(fsqrtd, void, env)
+DEF_HELPER_3(fcmps, void, env, f32, f32)
+DEF_HELPER_1(fcmpd, void, env)
+DEF_HELPER_3(fcmpes, void, env, f32, f32)
+DEF_HELPER_1(fcmped, void, env)
+DEF_HELPER_1(fsqrtq, void, env)
+DEF_HELPER_1(fcmpq, void, env)
+DEF_HELPER_1(fcmpeq, void, env)
 #ifdef TARGET_SPARC64
-DEF_HELPER_1(ldxfsr, void, i64)
-DEF_HELPER_0(fabsd, void)
-DEF_HELPER_2(fcmps_fcc1, void, f32, f32)
-DEF_HELPER_2(fcmps_fcc2, void, f32, f32)
-DEF_HELPER_2(fcmps_fcc3, void, f32, f32)
-DEF_HELPER_0(fcmpd_fcc1, void)
-DEF_HELPER_0(fcmpd_fcc2, void)
-DEF_HELPER_0(fcmpd_fcc3, void)
-DEF_HELPER_2(fcmpes_fcc1, void, f32, f32)
-DEF_HELPER_2(fcmpes_fcc2, void, f32, f32)
-DEF_HELPER_2(fcmpes_fcc3, void, f32, f32)
-DEF_HELPER_0(fcmped_fcc1, void)
-DEF_HELPER_0(fcmped_fcc2, void)
-DEF_HELPER_0(fcmped_fcc3, void)
-DEF_HELPER_0(fabsq, void)
-DEF_HELPER_0(fcmpq_fcc1, void)
-DEF_HELPER_0(fcmpq_fcc2, void)
-DEF_HELPER_0(fcmpq_fcc3, void)
-DEF_HELPER_0(fcmpeq_fcc1, void)
-DEF_HELPER_0(fcmpeq_fcc2, void)
-DEF_HELPER_0(fcmpeq_fcc3, void)
+DEF_HELPER_2(ldxfsr, void, env, i64)
+DEF_HELPER_1(fabsd, void, env)
+DEF_HELPER_3(fcmps_fcc1, void, env, f32, f32)
+DEF_HELPER_3(fcmps_fcc2, void, env, f32, f32)
+DEF_HELPER_3(fcmps_fcc3, void, env, f32, f32)
+DEF_HELPER_1(fcmpd_fcc1, void, env)
+DEF_HELPER_1(fcmpd_fcc2, void, env)
+DEF_HELPER_1(fcmpd_fcc3, void, env)
+DEF_HELPER_3(fcmpes_fcc1, void, env, f32, f32)
+DEF_HELPER_3(fcmpes_fcc2, void, env, f32, f32)
+DEF_HELPER_3(fcmpes_fcc3, void, env, f32, f32)
+DEF_HELPER_1(fcmped_fcc1, void, env)
+DEF_HELPER_1(fcmped_fcc2, void, env)
+DEF_HELPER_1(fcmped_fcc3, void, env)
+DEF_HELPER_1(fabsq, void, env)
+DEF_HELPER_1(fcmpq_fcc1, void, env)
+DEF_HELPER_1(fcmpq_fcc2, void, env)
+DEF_HELPER_1(fcmpq_fcc3, void, env)
+DEF_HELPER_1(fcmpeq_fcc1, void, env)
+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_0(shutdown, void)
-#define F_HELPER_0_0(name) DEF_HELPER_0(f ## name, void)
-#define F_HELPER_DQ_0_0(name)                   \
-    F_HELPER_0_0(name ## d);                    \
-    F_HELPER_0_0(name ## q)
+#define F_HELPER_0_1(name) DEF_HELPER_1(f ## name, void, env)
+#define F_HELPER_DQ_0_1(name)                   \
+    F_HELPER_0_1(name ## d);                    \
+    F_HELPER_0_1(name ## q)
 
-F_HELPER_DQ_0_0(add);
-F_HELPER_DQ_0_0(sub);
-F_HELPER_DQ_0_0(mul);
-F_HELPER_DQ_0_0(div);
+F_HELPER_DQ_0_1(add);
+F_HELPER_DQ_0_1(sub);
+F_HELPER_DQ_0_1(mul);
+F_HELPER_DQ_0_1(div);
 
-DEF_HELPER_2(fadds, f32, f32, f32)
-DEF_HELPER_2(fsubs, f32, f32, f32)
-DEF_HELPER_2(fmuls, f32, f32, f32)
-DEF_HELPER_2(fdivs, f32, f32, f32)
+DEF_HELPER_3(fadds, f32, env, f32, f32)
+DEF_HELPER_3(fsubs, f32, env, f32, f32)
+DEF_HELPER_3(fmuls, f32, env, f32, f32)
+DEF_HELPER_3(fdivs, f32, env, f32, f32)
 
-DEF_HELPER_2(fsmuld, void, f32, f32)
-F_HELPER_0_0(dmulq);
+DEF_HELPER_3(fsmuld, void, env, f32, f32)
+F_HELPER_0_1(dmulq);
 
 DEF_HELPER_1(fnegs, f32, f32)
-DEF_HELPER_1(fitod, void, s32)
-DEF_HELPER_1(fitoq, void, s32)
+DEF_HELPER_2(fitod, void, env, s32)
+DEF_HELPER_2(fitoq, void, env, s32)
 
-DEF_HELPER_1(fitos, f32, s32)
+DEF_HELPER_2(fitos, f32, env, s32)
 
 #ifdef TARGET_SPARC64
-DEF_HELPER_0(fnegd, void)
-DEF_HELPER_0(fnegq, void)
-DEF_HELPER_0(fxtos, i32)
-F_HELPER_DQ_0_0(xto);
+DEF_HELPER_1(fnegd, void, env)
+DEF_HELPER_1(fnegq, void, env)
+DEF_HELPER_1(fxtos, i32, env)
+F_HELPER_DQ_0_1(xto);
 #endif
-DEF_HELPER_0(fdtos, f32)
-DEF_HELPER_1(fstod, void, f32)
-DEF_HELPER_0(fqtos, f32)
-DEF_HELPER_1(fstoq, void, f32)
-F_HELPER_0_0(qtod);
-F_HELPER_0_0(dtoq);
-DEF_HELPER_1(fstoi, s32, f32)
-DEF_HELPER_0(fdtoi, s32)
-DEF_HELPER_0(fqtoi, s32)
+DEF_HELPER_1(fdtos, f32, env)
+DEF_HELPER_2(fstod, void, env, f32)
+DEF_HELPER_1(fqtos, f32, env)
+DEF_HELPER_2(fstoq, void, env, f32)
+F_HELPER_0_1(qtod);
+F_HELPER_0_1(dtoq);
+DEF_HELPER_2(fstoi, s32, env, f32)
+DEF_HELPER_1(fdtoi, s32, env)
+DEF_HELPER_1(fqtoi, s32, env)
 #ifdef TARGET_SPARC64
-DEF_HELPER_1(fstox, void, i32)
-F_HELPER_0_0(dtox);
-F_HELPER_0_0(qtox);
-F_HELPER_0_0(aligndata);
+DEF_HELPER_2(fstox, void, env, i32)
+F_HELPER_0_1(dtox);
+F_HELPER_0_1(qtox);
+F_HELPER_0_1(aligndata);
 
-F_HELPER_0_0(pmerge);
-F_HELPER_0_0(mul8x16);
-F_HELPER_0_0(mul8x16al);
-F_HELPER_0_0(mul8x16au);
-F_HELPER_0_0(mul8sux16);
-F_HELPER_0_0(mul8ulx16);
-F_HELPER_0_0(muld8sux16);
-F_HELPER_0_0(muld8ulx16);
-F_HELPER_0_0(expand);
+F_HELPER_0_1(pmerge);
+F_HELPER_0_1(mul8x16);
+F_HELPER_0_1(mul8x16al);
+F_HELPER_0_1(mul8x16au);
+F_HELPER_0_1(mul8sux16);
+F_HELPER_0_1(mul8ulx16);
+F_HELPER_0_1(muld8sux16);
+F_HELPER_0_1(muld8ulx16);
+F_HELPER_0_1(expand);
 #define VIS_HELPER(name)                                 \
-    F_HELPER_0_0(name##16);                              \
-    DEF_HELPER_2(f ## name ## 16s, i32, i32, i32) \
-    F_HELPER_0_0(name##32);                              \
-    DEF_HELPER_2(f ## name ## 32s, i32, i32, i32)
+    F_HELPER_0_1(name##16);                              \
+    DEF_HELPER_3(f ## name ## 16s, i32, env, i32, i32)   \
+    F_HELPER_0_1(name##32);                              \
+    DEF_HELPER_3(f ## name ## 32s, i32, env, i32, i32)
 
 VIS_HELPER(padd);
 VIS_HELPER(psub);
 #define VIS_CMPHELPER(name)                              \
-    DEF_HELPER_0(f##name##16, i64);                      \
-    DEF_HELPER_0(f##name##32, i64)
+    DEF_HELPER_1(f##name##16, i64, env);                 \
+    DEF_HELPER_1(f##name##32, i64, env)
 VIS_CMPHELPER(cmpgt);
 VIS_CMPHELPER(cmpeq);
 VIS_CMPHELPER(cmple);
 VIS_CMPHELPER(cmpne);
 #endif
-#undef F_HELPER_0_0
-#undef F_HELPER_DQ_0_0
+#undef F_HELPER_0_1
+#undef F_HELPER_DQ_0_1
 #undef VIS_HELPER
 #undef VIS_CMPHELPER
 DEF_HELPER_0(compute_psr, void);
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 9dd6b34..8c05c44 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1405,16 +1405,16 @@ static inline void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
 {
     switch (fccno) {
     case 0:
-        gen_helper_fcmps(r_rs1, r_rs2);
+        gen_helper_fcmps(cpu_env, r_rs1, r_rs2);
         break;
     case 1:
-        gen_helper_fcmps_fcc1(r_rs1, r_rs2);
+        gen_helper_fcmps_fcc1(cpu_env, r_rs1, r_rs2);
         break;
     case 2:
-        gen_helper_fcmps_fcc2(r_rs1, r_rs2);
+        gen_helper_fcmps_fcc2(cpu_env, r_rs1, r_rs2);
         break;
     case 3:
-        gen_helper_fcmps_fcc3(r_rs1, r_rs2);
+        gen_helper_fcmps_fcc3(cpu_env, r_rs1, r_rs2);
         break;
     }
 }
@@ -1423,16 +1423,16 @@ static inline void gen_op_fcmpd(int fccno)
 {
     switch (fccno) {
     case 0:
-        gen_helper_fcmpd();
+        gen_helper_fcmpd(cpu_env);
         break;
     case 1:
-        gen_helper_fcmpd_fcc1();
+        gen_helper_fcmpd_fcc1(cpu_env);
         break;
     case 2:
-        gen_helper_fcmpd_fcc2();
+        gen_helper_fcmpd_fcc2(cpu_env);
         break;
     case 3:
-        gen_helper_fcmpd_fcc3();
+        gen_helper_fcmpd_fcc3(cpu_env);
         break;
     }
 }
@@ -1441,16 +1441,16 @@ static inline void gen_op_fcmpq(int fccno)
 {
     switch (fccno) {
     case 0:
-        gen_helper_fcmpq();
+        gen_helper_fcmpq(cpu_env);
         break;
     case 1:
-        gen_helper_fcmpq_fcc1();
+        gen_helper_fcmpq_fcc1(cpu_env);
         break;
     case 2:
-        gen_helper_fcmpq_fcc2();
+        gen_helper_fcmpq_fcc2(cpu_env);
         break;
     case 3:
-        gen_helper_fcmpq_fcc3();
+        gen_helper_fcmpq_fcc3(cpu_env);
         break;
     }
 }
@@ -1459,16 +1459,16 @@ static inline void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
 {
     switch (fccno) {
     case 0:
-        gen_helper_fcmpes(r_rs1, r_rs2);
+        gen_helper_fcmpes(cpu_env, r_rs1, r_rs2);
         break;
     case 1:
-        gen_helper_fcmpes_fcc1(r_rs1, r_rs2);
+        gen_helper_fcmpes_fcc1(cpu_env, r_rs1, r_rs2);
         break;
     case 2:
-        gen_helper_fcmpes_fcc2(r_rs1, r_rs2);
+        gen_helper_fcmpes_fcc2(cpu_env, r_rs1, r_rs2);
         break;
     case 3:
-        gen_helper_fcmpes_fcc3(r_rs1, r_rs2);
+        gen_helper_fcmpes_fcc3(cpu_env, r_rs1, r_rs2);
         break;
     }
 }
@@ -1477,16 +1477,16 @@ static inline void gen_op_fcmped(int fccno)
 {
     switch (fccno) {
     case 0:
-        gen_helper_fcmped();
+        gen_helper_fcmped(cpu_env);
         break;
     case 1:
-        gen_helper_fcmped_fcc1();
+        gen_helper_fcmped_fcc1(cpu_env);
         break;
     case 2:
-        gen_helper_fcmped_fcc2();
+        gen_helper_fcmped_fcc2(cpu_env);
         break;
     case 3:
-        gen_helper_fcmped_fcc3();
+        gen_helper_fcmped_fcc3(cpu_env);
         break;
     }
 }
@@ -1495,16 +1495,16 @@ static inline void gen_op_fcmpeq(int fccno)
 {
     switch (fccno) {
     case 0:
-        gen_helper_fcmpeq();
+        gen_helper_fcmpeq(cpu_env);
         break;
     case 1:
-        gen_helper_fcmpeq_fcc1();
+        gen_helper_fcmpeq_fcc1(cpu_env);
         break;
     case 2:
-        gen_helper_fcmpeq_fcc2();
+        gen_helper_fcmpeq_fcc2(cpu_env);
         break;
     case 3:
-        gen_helper_fcmpeq_fcc3();
+        gen_helper_fcmpeq_fcc3(cpu_env);
         break;
     }
 }
@@ -1513,32 +1513,32 @@ static inline void gen_op_fcmpeq(int fccno)
 
 static inline void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2)
 {
-    gen_helper_fcmps(r_rs1, r_rs2);
+    gen_helper_fcmps(cpu_env, r_rs1, r_rs2);
 }
 
 static inline void gen_op_fcmpd(int fccno)
 {
-    gen_helper_fcmpd();
+    gen_helper_fcmpd(cpu_env);
 }
 
 static inline void gen_op_fcmpq(int fccno)
 {
-    gen_helper_fcmpq();
+    gen_helper_fcmpq(cpu_env);
 }
 
 static inline void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2)
 {
-    gen_helper_fcmpes(r_rs1, r_rs2);
+    gen_helper_fcmpes(cpu_env, r_rs1, r_rs2);
 }
 
 static inline void gen_op_fcmped(int fccno)
 {
-    gen_helper_fcmped();
+    gen_helper_fcmped(cpu_env);
 }
 
 static inline void gen_op_fcmpeq(int fccno)
 {
-    gen_helper_fcmpeq();
+    gen_helper_fcmpeq(cpu_env);
 }
 #endif
 
@@ -1584,7 +1584,7 @@ static inline void gen_op_clear_ieee_excp_and_FTT(void)
 
 static inline void gen_clear_float_exceptions(void)
 {
-    gen_helper_clear_float_exceptions();
+    gen_helper_clear_float_exceptions(cpu_env);
 }
 
 /* asi moves */
@@ -2383,8 +2383,8 @@ static void disas_sparc_insn(DisasContext * dc)
                 case 0x29: /* fsqrts */
                     CHECK_FPU_FEATURE(dc, FSQRT);
                     gen_clear_float_exceptions();
-                    gen_helper_fsqrts(cpu_tmp32, cpu_fpr[rs2]);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fsqrts(cpu_tmp32, cpu_env, cpu_fpr[rs2]);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                     gen_update_fprs_dirty(rd);
                     break;
@@ -2392,8 +2392,8 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, FSQRT);
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fsqrtd();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fsqrtd(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -2401,15 +2401,16 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fsqrtq();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fsqrtq(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x41: /* fadds */
                     gen_clear_float_exceptions();
-                    gen_helper_fadds(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fadds(cpu_tmp32, cpu_env, cpu_fpr[rs1],
+                                     cpu_fpr[rs2]);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                     gen_update_fprs_dirty(rd);
                     break;
@@ -2417,8 +2418,8 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_faddd();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_faddd(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -2427,15 +2428,16 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_QT0(QFPREG(rs1));
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_faddq();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_faddq(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x45: /* fsubs */
                     gen_clear_float_exceptions();
-                    gen_helper_fsubs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fsubs(cpu_tmp32, cpu_env, cpu_fpr[rs1],
+                                     cpu_fpr[rs2]);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                     gen_update_fprs_dirty(rd);
                     break;
@@ -2443,8 +2445,8 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fsubd();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fsubd(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -2453,16 +2455,17 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_QT0(QFPREG(rs1));
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fsubq();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fsubq(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x49: /* fmuls */
                     CHECK_FPU_FEATURE(dc, FMUL);
                     gen_clear_float_exceptions();
-                    gen_helper_fmuls(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fmuls(cpu_tmp32, cpu_env, cpu_fpr[rs1],
+                                     cpu_fpr[rs2]);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                     gen_update_fprs_dirty(rd);
                     break;
@@ -2471,8 +2474,8 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fmuld();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fmuld(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -2482,15 +2485,16 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_QT0(QFPREG(rs1));
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fmulq();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fmulq(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x4d: /* fdivs */
                     gen_clear_float_exceptions();
-                    gen_helper_fdivs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fdivs(cpu_tmp32, cpu_env, cpu_fpr[rs1],
+                                     cpu_fpr[rs2]);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                     gen_update_fprs_dirty(rd);
                     break;
@@ -2498,8 +2502,8 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fdivd();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fdivd(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -2508,16 +2512,16 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_QT0(QFPREG(rs1));
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fdivq();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fdivq(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x69: /* fsmuld */
                     CHECK_FPU_FEATURE(dc, FSMULD);
                     gen_clear_float_exceptions();
-                    gen_helper_fsmuld(cpu_fpr[rs1], cpu_fpr[rs2]);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fsmuld(cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -2526,23 +2530,23 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fdmulq();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fdmulq(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xc4: /* fitos */
                     gen_clear_float_exceptions();
-                    gen_helper_fitos(cpu_tmp32, cpu_fpr[rs2]);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fitos(cpu_tmp32, cpu_env, cpu_fpr[rs2]);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                     gen_update_fprs_dirty(rd);
                     break;
                 case 0xc6: /* fdtos */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fdtos(cpu_tmp32);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fdtos(cpu_tmp32, cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                     gen_update_fprs_dirty(rd);
                     break;
@@ -2550,18 +2554,18 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fqtos(cpu_tmp32);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fqtos(cpu_tmp32, cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                     gen_update_fprs_dirty(rd);
                     break;
                 case 0xc8: /* fitod */
-                    gen_helper_fitod(cpu_fpr[rs2]);
+                    gen_helper_fitod(cpu_env, cpu_fpr[rs2]);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xc9: /* fstod */
-                    gen_helper_fstod(cpu_fpr[rs2]);
+                    gen_helper_fstod(cpu_env, cpu_fpr[rs2]);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -2569,42 +2573,42 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fqtod();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fqtod(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xcc: /* fitoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
-                    gen_helper_fitoq(cpu_fpr[rs2]);
+                    gen_helper_fitoq(cpu_env, cpu_fpr[rs2]);
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xcd: /* fstoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
-                    gen_helper_fstoq(cpu_fpr[rs2]);
+                    gen_helper_fstoq(cpu_env, cpu_fpr[rs2]);
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xce: /* fdtoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fdtoq();
+                    gen_helper_fdtoq(cpu_env);
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xd1: /* fstoi */
                     gen_clear_float_exceptions();
-                    gen_helper_fstoi(cpu_tmp32, cpu_fpr[rs2]);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fstoi(cpu_tmp32, cpu_env, cpu_fpr[rs2]);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                     gen_update_fprs_dirty(rd);
                     break;
                 case 0xd2: /* fdtoi */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fdtoi(cpu_tmp32);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fdtoi(cpu_tmp32, cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                     gen_update_fprs_dirty(rd);
                     break;
@@ -2612,8 +2616,8 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fqtoi(cpu_tmp32);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fqtoi(cpu_tmp32, cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                     gen_update_fprs_dirty(rd);
                     break;
@@ -2637,42 +2641,42 @@ static void disas_sparc_insn(DisasContext * dc)
                     break;
                 case 0x6: /* V9 fnegd */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fnegd();
+                    gen_helper_fnegd(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x7: /* V9 fnegq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
-                    gen_helper_fnegq();
+                    gen_helper_fnegq(cpu_env);
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xa: /* V9 fabsd */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fabsd();
+                    gen_helper_fabsd(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xb: /* V9 fabsq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
-                    gen_helper_fabsq();
+                    gen_helper_fabsq(cpu_env);
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x81: /* V9 fstox */
                     gen_clear_float_exceptions();
-                    gen_helper_fstox(cpu_fpr[rs2]);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fstox(cpu_env, cpu_fpr[rs2]);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x82: /* V9 fdtox */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fdtox();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fdtox(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -2680,24 +2684,24 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fqtox();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fqtox(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x84: /* V9 fxtos */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fxtos(cpu_tmp32);
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fxtos(cpu_tmp32, cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
                     gen_update_fprs_dirty(rd);
                     break;
                 case 0x88: /* V9 fxtod */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fxtod();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fxtod(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -2705,8 +2709,8 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_clear_float_exceptions();
-                    gen_helper_fxtoq();
-                    gen_helper_check_ieee_exceptions();
+                    gen_helper_fxtoq(cpu_env);
+                    gen_helper_check_ieee_exceptions(cpu_env);
                     gen_op_store_QT0_fpr(QFPREG(rd));
                     gen_update_fprs_dirty(QFPREG(rd));
                     break;
@@ -3828,14 +3832,14 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     cpu_src1 = get_src1(insn, cpu_src1);
                     gen_movl_reg_TN(rs2, cpu_src2);
-                    gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
+                    gen_helper_array8(cpu_dst, cpu_env, cpu_src1, cpu_src2);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x012: /* VIS I array16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     cpu_src1 = get_src1(insn, cpu_src1);
                     gen_movl_reg_TN(rs2, cpu_src2);
-                    gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
+                    gen_helper_array8(cpu_dst, cpu_env, cpu_src1, cpu_src2);
                     tcg_gen_shli_i64(cpu_dst, cpu_dst, 1);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
@@ -3843,7 +3847,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     cpu_src1 = get_src1(insn, cpu_src1);
                     gen_movl_reg_TN(rs2, cpu_src2);
-                    gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
+                    gen_helper_array8(cpu_dst, cpu_env, cpu_src1, cpu_src2);
                     tcg_gen_shli_i64(cpu_dst, cpu_dst, 2);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
@@ -3851,7 +3855,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     cpu_src1 = get_src1(insn, cpu_src1);
                     gen_movl_reg_TN(rs2, cpu_src2);
-                    gen_helper_alignaddr(cpu_dst, cpu_src1, cpu_src2);
+                    gen_helper_alignaddr(cpu_dst, cpu_env, cpu_src1, cpu_src2);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x019: /* VIS II bmask */
@@ -3862,63 +3866,63 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmple16(cpu_dst);
+                    gen_helper_fcmple16(cpu_dst, cpu_env);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x022: /* VIS I fcmpne16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmpne16(cpu_dst);
+                    gen_helper_fcmpne16(cpu_dst, cpu_env);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x024: /* VIS I fcmple32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmple32(cpu_dst);
+                    gen_helper_fcmple32(cpu_dst, cpu_env);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x026: /* VIS I fcmpne32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmpne32(cpu_dst);
+                    gen_helper_fcmpne32(cpu_dst, cpu_env);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x028: /* VIS I fcmpgt16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmpgt16(cpu_dst);
+                    gen_helper_fcmpgt16(cpu_dst, cpu_env);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x02a: /* VIS I fcmpeq16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmpeq16(cpu_dst);
+                    gen_helper_fcmpeq16(cpu_dst, cpu_env);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x02c: /* VIS I fcmpgt32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmpgt32(cpu_dst);
+                    gen_helper_fcmpgt32(cpu_dst, cpu_env);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x02e: /* VIS I fcmpeq32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fcmpeq32(cpu_dst);
+                    gen_helper_fcmpeq32(cpu_dst, cpu_env);
                     gen_movl_TN_reg(rd, cpu_dst);
                     break;
                 case 0x031: /* VIS I fmul8x16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fmul8x16();
+                    gen_helper_fmul8x16(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -3926,7 +3930,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fmul8x16au();
+                    gen_helper_fmul8x16au(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -3934,7 +3938,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fmul8x16al();
+                    gen_helper_fmul8x16al(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -3942,7 +3946,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fmul8sux16();
+                    gen_helper_fmul8sux16(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -3950,7 +3954,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fmul8ulx16();
+                    gen_helper_fmul8ulx16(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -3958,7 +3962,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fmuld8sux16();
+                    gen_helper_fmuld8sux16(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -3966,7 +3970,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fmuld8ulx16();
+                    gen_helper_fmuld8ulx16(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -3980,7 +3984,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_faligndata();
+                    gen_helper_faligndata(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -3988,7 +3992,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fpmerge();
+                    gen_helper_fpmerge(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -3999,7 +4003,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fexpand();
+                    gen_helper_fexpand(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
@@ -4007,13 +4011,13 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fpadd16();
+                    gen_helper_fpadd16(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x051: /* VIS I fpadd16s */
                     CHECK_FPU_FEATURE(dc, VIS1);
-                    gen_helper_fpadd16s(cpu_fpr[rd],
+                    gen_helper_fpadd16s(cpu_env, cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_update_fprs_dirty(rd);
                     break;
@@ -4021,13 +4025,13 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fpadd32();
+                    gen_helper_fpadd32(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x053: /* VIS I fpadd32s */
                     CHECK_FPU_FEATURE(dc, VIS1);
-                    gen_helper_fpadd32s(cpu_fpr[rd],
+                    gen_helper_fpadd32s(cpu_env, cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_update_fprs_dirty(rd);
                     break;
@@ -4035,13 +4039,13 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fpsub16();
+                    gen_helper_fpsub16(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x055: /* VIS I fpsub16s */
                     CHECK_FPU_FEATURE(dc, VIS1);
-                    gen_helper_fpsub16s(cpu_fpr[rd],
+                    gen_helper_fpsub16s(cpu_env, cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_update_fprs_dirty(rd);
                     break;
@@ -4049,13 +4053,13 @@ static void disas_sparc_insn(DisasContext * dc)
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs1));
                     gen_op_load_fpr_DT1(DFPREG(rs2));
-                    gen_helper_fpsub32();
+                    gen_helper_fpsub32(cpu_env);
                     gen_op_store_DT0_fpr(DFPREG(rd));
                     gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x057: /* VIS I fpsub32s */
                     CHECK_FPU_FEATURE(dc, VIS1);
-                    gen_helper_fpsub32s(cpu_fpr[rd],
+                    gen_helper_fpsub32s(cpu_env, cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_update_fprs_dirty(rd);
                     break;
@@ -4659,16 +4663,16 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_address_mask(dc, cpu_addr);
                     if (rd == 1) {
                         tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
-                        gen_helper_ldxfsr(cpu_tmp64);
+                        gen_helper_ldxfsr(cpu_env, cpu_tmp64);
                     } else {
                         tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
                         tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
-                        gen_helper_ldfsr(cpu_tmp32);
+                        gen_helper_ldfsr(cpu_env, cpu_tmp32);
                     }
 #else
                     {
                         tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
-                        gen_helper_ldfsr(cpu_tmp32);
+                        gen_helper_ldfsr(cpu_env, cpu_tmp32);
                     }
 #endif
                     break;
diff --git a/target-sparc/vis_helper.c b/target-sparc/vis_helper.c
index 87a86ef..a22c10b 100644
--- a/target-sparc/vis_helper.c
+++ b/target-sparc/vis_helper.c
@@ -18,7 +18,6 @@
  */
 
 #include "cpu.h"
-#include "dyngen-exec.h"
 #include "helper.h"
 
 #define DT0 (env->dt0)
@@ -34,7 +33,8 @@
 #define GET_FIELD_SP(X, FROM, TO)               \
     GET_FIELD(X, 63 - (TO), 63 - (FROM))
 
-target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
+target_ulong helper_array8(CPUState *env, target_ulong pixel_addr,
+                           target_ulong cubesize)
 {
     return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
         (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
@@ -47,7 +47,8 @@ target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
         GET_FIELD_SP(pixel_addr, 11, 12);
 }
 
-target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
+target_ulong helper_alignaddr(CPUState *env, target_ulong addr,
+                              target_ulong offset)
 {
     uint64_t tmp;
 
@@ -57,7 +58,7 @@ target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
     return tmp & ~7ULL;
 }
 
-void helper_faligndata(void)
+void helper_faligndata(CPUState *env)
 {
     uint64_t tmp;
 
@@ -101,7 +102,7 @@ typedef union {
     float32 f;
 } VIS32;
 
-void helper_fpmerge(void)
+void helper_fpmerge(CPUState *env)
 {
     VIS64 s, d;
 
@@ -121,7 +122,7 @@ void helper_fpmerge(void)
     DT0 = d.d;
 }
 
-void helper_fmul8x16(void)
+void helper_fmul8x16(CPUState *env)
 {
     VIS64 s, d;
     uint32_t tmp;
@@ -145,7 +146,7 @@ void helper_fmul8x16(void)
     DT0 = d.d;
 }
 
-void helper_fmul8x16al(void)
+void helper_fmul8x16al(CPUState *env)
 {
     VIS64 s, d;
     uint32_t tmp;
@@ -169,7 +170,7 @@ void helper_fmul8x16al(void)
     DT0 = d.d;
 }
 
-void helper_fmul8x16au(void)
+void helper_fmul8x16au(CPUState *env)
 {
     VIS64 s, d;
     uint32_t tmp;
@@ -193,7 +194,7 @@ void helper_fmul8x16au(void)
     DT0 = d.d;
 }
 
-void helper_fmul8sux16(void)
+void helper_fmul8sux16(CPUState *env)
 {
     VIS64 s, d;
     uint32_t tmp;
@@ -217,7 +218,7 @@ void helper_fmul8sux16(void)
     DT0 = d.d;
 }
 
-void helper_fmul8ulx16(void)
+void helper_fmul8ulx16(CPUState *env)
 {
     VIS64 s, d;
     uint32_t tmp;
@@ -241,7 +242,7 @@ void helper_fmul8ulx16(void)
     DT0 = d.d;
 }
 
-void helper_fmuld8sux16(void)
+void helper_fmuld8sux16(CPUState *env)
 {
     VIS64 s, d;
     uint32_t tmp;
@@ -264,7 +265,7 @@ void helper_fmuld8sux16(void)
     DT0 = d.d;
 }
 
-void helper_fmuld8ulx16(void)
+void helper_fmuld8ulx16(CPUState *env)
 {
     VIS64 s, d;
     uint32_t tmp;
@@ -287,7 +288,7 @@ void helper_fmuld8ulx16(void)
     DT0 = d.d;
 }
 
-void helper_fexpand(void)
+void helper_fexpand(CPUState *env)
 {
     VIS32 s;
     VIS64 d;
@@ -303,7 +304,7 @@ void helper_fexpand(void)
 }
 
 #define VIS_HELPER(name, F)                             \
-    void name##16(void)                                 \
+    void name##16(CPUState *env)                        \
     {                                                   \
         VIS64 s, d;                                     \
                                                         \
@@ -318,7 +319,8 @@ void helper_fexpand(void)
         DT0 = d.d;                                      \
     }                                                   \
                                                         \
-    uint32_t name##16s(uint32_t src1, uint32_t src2)    \
+    uint32_t name##16s(CPUState *env, uint32_t src1,    \
+                       uint32_t src2)                   \
     {                                                   \
         VIS32 s, d;                                     \
                                                         \
@@ -331,7 +333,7 @@ void helper_fexpand(void)
         return d.l;                                     \
     }                                                   \
                                                         \
-    void name##32(void)                                 \
+    void name##32(CPUState *env)                        \
     {                                                   \
         VIS64 s, d;                                     \
                                                         \
@@ -344,7 +346,8 @@ void helper_fexpand(void)
         DT0 = d.d;                                      \
     }                                                   \
                                                         \
-    uint32_t name##32s(uint32_t src1, uint32_t src2)    \
+    uint32_t name##32s(CPUState *env, uint32_t src1,    \
+                       uint32_t src2)                   \
     {                                                   \
         VIS32 s, d;                                     \
                                                         \
@@ -362,7 +365,7 @@ VIS_HELPER(helper_fpadd, FADD)
 VIS_HELPER(helper_fpsub, FSUB)
 
 #define VIS_CMPHELPER(name, F)                                    \
-    uint64_t name##16(void)                                       \
+    uint64_t name##16(CPUState *env)                              \
     {                                                             \
         VIS64 s, d;                                               \
                                                                   \
@@ -378,7 +381,7 @@ VIS_HELPER(helper_fpsub, FSUB)
         return d.ll;                                              \
     }                                                             \
                                                                   \
-    uint64_t name##32(void)                                       \
+    uint64_t name##32(CPUState *env)                              \
     {                                                             \
         VIS64 s, d;                                               \
                                                                   \
commit 1bccec25e10e9073e21c2f71cd16a0b3ffe06c39
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Mon Aug 1 07:37:45 2011 +0000

    Sparc: split FPU and VIS op helpers
    
    Move FPU op helpers to fop_helper.c. Move VIS op helpers to vis_helper.c,
    compile it only for Sparc64.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 26c99ca..fc277b3 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -74,10 +74,11 @@ libobj-y += op_helper.o helper.o
 ifeq ($(TARGET_BASE_ARCH), i386)
 libobj-y += cpuid.o
 endif
+libobj-$(TARGET_SPARC64) += vis_helper.o
 libobj-$(CONFIG_NEED_MMU) += mmu.o
 libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
 ifeq ($(TARGET_BASE_ARCH), sparc)
-libobj-y += cpu_init.o
+libobj-y += fop_helper.o cpu_init.o
 endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
@@ -96,7 +97,7 @@ tcg/tcg.o: cpu.h
 
 # HELPER_CFLAGS is used for all the code compiled with static register
 # variables
-op_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+op_helper.o fop_helper.o vis_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 
 # Note: this is a workaround. The real fix is to avoid compiling
 # cpu_signal_handler() in user-exec.c.
diff --git a/target-sparc/fop_helper.c b/target-sparc/fop_helper.c
new file mode 100644
index 0000000..ddd0af9
--- /dev/null
+++ b/target-sparc/fop_helper.c
@@ -0,0 +1,394 @@
+/*
+ * FPU op helpers
+ *
+ *  Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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 "helper.h"
+
+#define DT0 (env->dt0)
+#define DT1 (env->dt1)
+#define QT0 (env->qt0)
+#define QT1 (env->qt1)
+
+#define F_HELPER(name, p) void helper_f##name##p(void)
+
+#define F_BINOP(name)                                           \
+    float32 helper_f ## name ## s (float32 src1, float32 src2)  \
+    {                                                           \
+        return float32_ ## name (src1, src2, &env->fp_status);  \
+    }                                                           \
+    F_HELPER(name, d)                                           \
+    {                                                           \
+        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
+    }                                                           \
+    F_HELPER(name, q)                                           \
+    {                                                           \
+        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
+    }
+
+F_BINOP(add);
+F_BINOP(sub);
+F_BINOP(mul);
+F_BINOP(div);
+#undef F_BINOP
+
+void helper_fsmuld(float32 src1, float32 src2)
+{
+    DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
+                      float32_to_float64(src2, &env->fp_status),
+                      &env->fp_status);
+}
+
+void helper_fdmulq(void)
+{
+    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
+                       float64_to_float128(DT1, &env->fp_status),
+                       &env->fp_status);
+}
+
+float32 helper_fnegs(float32 src)
+{
+    return float32_chs(src);
+}
+
+#ifdef TARGET_SPARC64
+F_HELPER(neg, d)
+{
+    DT0 = float64_chs(DT1);
+}
+
+F_HELPER(neg, q)
+{
+    QT0 = float128_chs(QT1);
+}
+#endif
+
+/* Integer to float conversion.  */
+float32 helper_fitos(int32_t src)
+{
+    return int32_to_float32(src, &env->fp_status);
+}
+
+void helper_fitod(int32_t src)
+{
+    DT0 = int32_to_float64(src, &env->fp_status);
+}
+
+void helper_fitoq(int32_t src)
+{
+    QT0 = int32_to_float128(src, &env->fp_status);
+}
+
+#ifdef TARGET_SPARC64
+float32 helper_fxtos(void)
+{
+    return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
+}
+
+F_HELPER(xto, d)
+{
+    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
+}
+
+F_HELPER(xto, q)
+{
+    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
+}
+#endif
+#undef F_HELPER
+
+/* floating point conversion */
+float32 helper_fdtos(void)
+{
+    return float64_to_float32(DT1, &env->fp_status);
+}
+
+void helper_fstod(float32 src)
+{
+    DT0 = float32_to_float64(src, &env->fp_status);
+}
+
+float32 helper_fqtos(void)
+{
+    return float128_to_float32(QT1, &env->fp_status);
+}
+
+void helper_fstoq(float32 src)
+{
+    QT0 = float32_to_float128(src, &env->fp_status);
+}
+
+void helper_fqtod(void)
+{
+    DT0 = float128_to_float64(QT1, &env->fp_status);
+}
+
+void helper_fdtoq(void)
+{
+    QT0 = float64_to_float128(DT1, &env->fp_status);
+}
+
+/* Float to integer conversion.  */
+int32_t helper_fstoi(float32 src)
+{
+    return float32_to_int32_round_to_zero(src, &env->fp_status);
+}
+
+int32_t helper_fdtoi(void)
+{
+    return float64_to_int32_round_to_zero(DT1, &env->fp_status);
+}
+
+int32_t helper_fqtoi(void)
+{
+    return float128_to_int32_round_to_zero(QT1, &env->fp_status);
+}
+
+#ifdef TARGET_SPARC64
+void helper_fstox(float32 src)
+{
+    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
+}
+
+void helper_fdtox(void)
+{
+    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
+}
+
+void helper_fqtox(void)
+{
+    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
+}
+#endif
+
+float32 helper_fabss(float32 src)
+{
+    return float32_abs(src);
+}
+
+#ifdef TARGET_SPARC64
+void helper_fabsd(void)
+{
+    DT0 = float64_abs(DT1);
+}
+
+void helper_fabsq(void)
+{
+    QT0 = float128_abs(QT1);
+}
+#endif
+
+float32 helper_fsqrts(float32 src)
+{
+    return float32_sqrt(src, &env->fp_status);
+}
+
+void helper_fsqrtd(void)
+{
+    DT0 = float64_sqrt(DT1, &env->fp_status);
+}
+
+void helper_fsqrtq(void)
+{
+    QT0 = float128_sqrt(QT1, &env->fp_status);
+}
+
+#define GEN_FCMP(name, size, reg1, reg2, FS, E)                         \
+    void glue(helper_, name) (void)                                     \
+    {                                                                   \
+        env->fsr &= FSR_FTT_NMASK;                                      \
+        if (E && (glue(size, _is_any_nan)(reg1) ||                      \
+                  glue(size, _is_any_nan)(reg2)) &&                     \
+            (env->fsr & FSR_NVM)) {                                     \
+            env->fsr |= FSR_NVC;                                        \
+            env->fsr |= FSR_FTT_IEEE_EXCP;                              \
+            helper_raise_exception(env, TT_FP_EXCP);                    \
+        }                                                               \
+        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
+        case float_relation_unordered:                                  \
+            if ((env->fsr & FSR_NVM)) {                                 \
+                env->fsr |= FSR_NVC;                                    \
+                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
+                helper_raise_exception(env, TT_FP_EXCP);                \
+            } else {                                                    \
+                env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);             \
+                env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                \
+                env->fsr |= FSR_NVA;                                    \
+            }                                                           \
+            break;                                                      \
+        case float_relation_less:                                       \
+            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
+            env->fsr |= FSR_FCC0 << FS;                                 \
+            break;                                                      \
+        case float_relation_greater:                                    \
+            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
+            env->fsr |= FSR_FCC1 << FS;                                 \
+            break;                                                      \
+        default:                                                        \
+            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
+            break;                                                      \
+        }                                                               \
+    }
+#define GEN_FCMPS(name, size, FS, E)                                    \
+    void glue(helper_, name)(float32 src1, float32 src2)                \
+    {                                                                   \
+        env->fsr &= FSR_FTT_NMASK;                                      \
+        if (E && (glue(size, _is_any_nan)(src1) ||                      \
+                  glue(size, _is_any_nan)(src2)) &&                     \
+            (env->fsr & FSR_NVM)) {                                     \
+            env->fsr |= FSR_NVC;                                        \
+            env->fsr |= FSR_FTT_IEEE_EXCP;                              \
+            helper_raise_exception(env, TT_FP_EXCP);                    \
+        }                                                               \
+        switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
+        case float_relation_unordered:                                  \
+            if ((env->fsr & FSR_NVM)) {                                 \
+                env->fsr |= FSR_NVC;                                    \
+                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
+                helper_raise_exception(env, TT_FP_EXCP);                \
+            } else {                                                    \
+                env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);             \
+                env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                \
+                env->fsr |= FSR_NVA;                                    \
+            }                                                           \
+            break;                                                      \
+        case float_relation_less:                                       \
+            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
+            env->fsr |= FSR_FCC0 << FS;                                 \
+            break;                                                      \
+        case float_relation_greater:                                    \
+            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
+            env->fsr |= FSR_FCC1 << FS;                                 \
+            break;                                                      \
+        default:                                                        \
+            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
+            break;                                                      \
+        }                                                               \
+    }
+
+GEN_FCMPS(fcmps, float32, 0, 0);
+GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
+
+GEN_FCMPS(fcmpes, float32, 0, 1);
+GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
+
+GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
+GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
+
+#ifdef TARGET_SPARC64
+GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
+GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
+GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
+
+GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
+GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
+GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
+
+GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
+GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
+GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
+
+GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
+GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
+GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
+
+GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
+GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
+GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
+
+GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
+GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
+GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
+#endif
+#undef GEN_FCMPS
+
+void helper_check_ieee_exceptions(void)
+{
+    target_ulong status;
+
+    status = get_float_exception_flags(&env->fp_status);
+    if (status) {
+        /* Copy IEEE 754 flags into FSR */
+        if (status & float_flag_invalid) {
+            env->fsr |= FSR_NVC;
+        }
+        if (status & float_flag_overflow) {
+            env->fsr |= FSR_OFC;
+        }
+        if (status & float_flag_underflow) {
+            env->fsr |= FSR_UFC;
+        }
+        if (status & float_flag_divbyzero) {
+            env->fsr |= FSR_DZC;
+        }
+        if (status & float_flag_inexact) {
+            env->fsr |= FSR_NXC;
+        }
+
+        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
+            /* Unmasked exception, generate a trap */
+            env->fsr |= FSR_FTT_IEEE_EXCP;
+            helper_raise_exception(env, TT_FP_EXCP);
+        } else {
+            /* Accumulate exceptions */
+            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
+        }
+    }
+}
+
+void helper_clear_float_exceptions(void)
+{
+    set_float_exception_flags(0, &env->fp_status);
+}
+
+static inline void set_fsr(void)
+{
+    int rnd_mode;
+
+    switch (env->fsr & FSR_RD_MASK) {
+    case FSR_RD_NEAREST:
+        rnd_mode = float_round_nearest_even;
+        break;
+    default:
+    case FSR_RD_ZERO:
+        rnd_mode = float_round_to_zero;
+        break;
+    case FSR_RD_POS:
+        rnd_mode = float_round_up;
+        break;
+    case FSR_RD_NEG:
+        rnd_mode = float_round_down;
+        break;
+    }
+    set_float_rounding_mode(rnd_mode, &env->fp_status);
+}
+
+void helper_ldfsr(uint32_t new_fsr)
+{
+    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
+    set_fsr();
+}
+
+#ifdef TARGET_SPARC64
+void helper_ldxfsr(uint64_t new_fsr)
+{
+    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
+    set_fsr();
+}
+#endif
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index f2bca77..fd20366 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -333,655 +333,6 @@ void helper_check_align(target_ulong addr, uint32_t align)
     }
 }
 
-#define F_HELPER(name, p) void helper_f##name##p(void)
-
-#define F_BINOP(name)                                           \
-    float32 helper_f ## name ## s (float32 src1, float32 src2)  \
-    {                                                           \
-        return float32_ ## name (src1, src2, &env->fp_status);  \
-    }                                                           \
-    F_HELPER(name, d)                                           \
-    {                                                           \
-        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
-    }                                                           \
-    F_HELPER(name, q)                                           \
-    {                                                           \
-        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
-    }
-
-F_BINOP(add);
-F_BINOP(sub);
-F_BINOP(mul);
-F_BINOP(div);
-#undef F_BINOP
-
-void helper_fsmuld(float32 src1, float32 src2)
-{
-    DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
-                      float32_to_float64(src2, &env->fp_status),
-                      &env->fp_status);
-}
-
-void helper_fdmulq(void)
-{
-    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
-                       float64_to_float128(DT1, &env->fp_status),
-                       &env->fp_status);
-}
-
-float32 helper_fnegs(float32 src)
-{
-    return float32_chs(src);
-}
-
-#ifdef TARGET_SPARC64
-F_HELPER(neg, d)
-{
-    DT0 = float64_chs(DT1);
-}
-
-F_HELPER(neg, q)
-{
-    QT0 = float128_chs(QT1);
-}
-#endif
-
-/* Integer to float conversion.  */
-float32 helper_fitos(int32_t src)
-{
-    return int32_to_float32(src, &env->fp_status);
-}
-
-void helper_fitod(int32_t src)
-{
-    DT0 = int32_to_float64(src, &env->fp_status);
-}
-
-void helper_fitoq(int32_t src)
-{
-    QT0 = int32_to_float128(src, &env->fp_status);
-}
-
-#ifdef TARGET_SPARC64
-float32 helper_fxtos(void)
-{
-    return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
-}
-
-F_HELPER(xto, d)
-{
-    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
-}
-
-F_HELPER(xto, q)
-{
-    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
-}
-#endif
-#undef F_HELPER
-
-/* floating point conversion */
-float32 helper_fdtos(void)
-{
-    return float64_to_float32(DT1, &env->fp_status);
-}
-
-void helper_fstod(float32 src)
-{
-    DT0 = float32_to_float64(src, &env->fp_status);
-}
-
-float32 helper_fqtos(void)
-{
-    return float128_to_float32(QT1, &env->fp_status);
-}
-
-void helper_fstoq(float32 src)
-{
-    QT0 = float32_to_float128(src, &env->fp_status);
-}
-
-void helper_fqtod(void)
-{
-    DT0 = float128_to_float64(QT1, &env->fp_status);
-}
-
-void helper_fdtoq(void)
-{
-    QT0 = float64_to_float128(DT1, &env->fp_status);
-}
-
-/* Float to integer conversion.  */
-int32_t helper_fstoi(float32 src)
-{
-    return float32_to_int32_round_to_zero(src, &env->fp_status);
-}
-
-int32_t helper_fdtoi(void)
-{
-    return float64_to_int32_round_to_zero(DT1, &env->fp_status);
-}
-
-int32_t helper_fqtoi(void)
-{
-    return float128_to_int32_round_to_zero(QT1, &env->fp_status);
-}
-
-#ifdef TARGET_SPARC64
-void helper_fstox(float32 src)
-{
-    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
-}
-
-void helper_fdtox(void)
-{
-    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
-}
-
-void helper_fqtox(void)
-{
-    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
-}
-
-void helper_faligndata(void)
-{
-    uint64_t tmp;
-
-    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
-    /* on many architectures a shift of 64 does nothing */
-    if ((env->gsr & 7) != 0) {
-        tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
-    }
-    *((uint64_t *)&DT0) = tmp;
-}
-
-#ifdef HOST_WORDS_BIGENDIAN
-#define VIS_B64(n) b[7 - (n)]
-#define VIS_W64(n) w[3 - (n)]
-#define VIS_SW64(n) sw[3 - (n)]
-#define VIS_L64(n) l[1 - (n)]
-#define VIS_B32(n) b[3 - (n)]
-#define VIS_W32(n) w[1 - (n)]
-#else
-#define VIS_B64(n) b[n]
-#define VIS_W64(n) w[n]
-#define VIS_SW64(n) sw[n]
-#define VIS_L64(n) l[n]
-#define VIS_B32(n) b[n]
-#define VIS_W32(n) w[n]
-#endif
-
-typedef union {
-    uint8_t b[8];
-    uint16_t w[4];
-    int16_t sw[4];
-    uint32_t l[2];
-    uint64_t ll;
-    float64 d;
-} VIS64;
-
-typedef union {
-    uint8_t b[4];
-    uint16_t w[2];
-    uint32_t l;
-    float32 f;
-} VIS32;
-
-void helper_fpmerge(void)
-{
-    VIS64 s, d;
-
-    s.d = DT0;
-    d.d = DT1;
-
-    /* Reverse calculation order to handle overlap */
-    d.VIS_B64(7) = s.VIS_B64(3);
-    d.VIS_B64(6) = d.VIS_B64(3);
-    d.VIS_B64(5) = s.VIS_B64(2);
-    d.VIS_B64(4) = d.VIS_B64(2);
-    d.VIS_B64(3) = s.VIS_B64(1);
-    d.VIS_B64(2) = d.VIS_B64(1);
-    d.VIS_B64(1) = s.VIS_B64(0);
-    /* d.VIS_B64(0) = d.VIS_B64(0); */
-
-    DT0 = d.d;
-}
-
-void helper_fmul8x16(void)
-{
-    VIS64 s, d;
-    uint32_t tmp;
-
-    s.d = DT0;
-    d.d = DT1;
-
-#define PMUL(r)                                                 \
-    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
-    if ((tmp & 0xff) > 0x7f) {                                  \
-        tmp += 0x100;                                           \
-    }                                                           \
-    d.VIS_W64(r) = tmp >> 8;
-
-    PMUL(0);
-    PMUL(1);
-    PMUL(2);
-    PMUL(3);
-#undef PMUL
-
-    DT0 = d.d;
-}
-
-void helper_fmul8x16al(void)
-{
-    VIS64 s, d;
-    uint32_t tmp;
-
-    s.d = DT0;
-    d.d = DT1;
-
-#define PMUL(r)                                                 \
-    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
-    if ((tmp & 0xff) > 0x7f) {                                  \
-        tmp += 0x100;                                           \
-    }                                                           \
-    d.VIS_W64(r) = tmp >> 8;
-
-    PMUL(0);
-    PMUL(1);
-    PMUL(2);
-    PMUL(3);
-#undef PMUL
-
-    DT0 = d.d;
-}
-
-void helper_fmul8x16au(void)
-{
-    VIS64 s, d;
-    uint32_t tmp;
-
-    s.d = DT0;
-    d.d = DT1;
-
-#define PMUL(r)                                                 \
-    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
-    if ((tmp & 0xff) > 0x7f) {                                  \
-        tmp += 0x100;                                           \
-    }                                                           \
-    d.VIS_W64(r) = tmp >> 8;
-
-    PMUL(0);
-    PMUL(1);
-    PMUL(2);
-    PMUL(3);
-#undef PMUL
-
-    DT0 = d.d;
-}
-
-void helper_fmul8sux16(void)
-{
-    VIS64 s, d;
-    uint32_t tmp;
-
-    s.d = DT0;
-    d.d = DT1;
-
-#define PMUL(r)                                                         \
-    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
-    if ((tmp & 0xff) > 0x7f) {                                          \
-        tmp += 0x100;                                                   \
-    }                                                                   \
-    d.VIS_W64(r) = tmp >> 8;
-
-    PMUL(0);
-    PMUL(1);
-    PMUL(2);
-    PMUL(3);
-#undef PMUL
-
-    DT0 = d.d;
-}
-
-void helper_fmul8ulx16(void)
-{
-    VIS64 s, d;
-    uint32_t tmp;
-
-    s.d = DT0;
-    d.d = DT1;
-
-#define PMUL(r)                                                         \
-    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
-    if ((tmp & 0xff) > 0x7f) {                                          \
-        tmp += 0x100;                                                   \
-    }                                                                   \
-    d.VIS_W64(r) = tmp >> 8;
-
-    PMUL(0);
-    PMUL(1);
-    PMUL(2);
-    PMUL(3);
-#undef PMUL
-
-    DT0 = d.d;
-}
-
-void helper_fmuld8sux16(void)
-{
-    VIS64 s, d;
-    uint32_t tmp;
-
-    s.d = DT0;
-    d.d = DT1;
-
-#define PMUL(r)                                                         \
-    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
-    if ((tmp & 0xff) > 0x7f) {                                          \
-        tmp += 0x100;                                                   \
-    }                                                                   \
-    d.VIS_L64(r) = tmp;
-
-    /* Reverse calculation order to handle overlap */
-    PMUL(1);
-    PMUL(0);
-#undef PMUL
-
-    DT0 = d.d;
-}
-
-void helper_fmuld8ulx16(void)
-{
-    VIS64 s, d;
-    uint32_t tmp;
-
-    s.d = DT0;
-    d.d = DT1;
-
-#define PMUL(r)                                                         \
-    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
-    if ((tmp & 0xff) > 0x7f) {                                          \
-        tmp += 0x100;                                                   \
-    }                                                                   \
-    d.VIS_L64(r) = tmp;
-
-    /* Reverse calculation order to handle overlap */
-    PMUL(1);
-    PMUL(0);
-#undef PMUL
-
-    DT0 = d.d;
-}
-
-void helper_fexpand(void)
-{
-    VIS32 s;
-    VIS64 d;
-
-    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
-    d.d = DT1;
-    d.VIS_W64(0) = s.VIS_B32(0) << 4;
-    d.VIS_W64(1) = s.VIS_B32(1) << 4;
-    d.VIS_W64(2) = s.VIS_B32(2) << 4;
-    d.VIS_W64(3) = s.VIS_B32(3) << 4;
-
-    DT0 = d.d;
-}
-
-#define VIS_HELPER(name, F)                             \
-    void name##16(void)                                 \
-    {                                                   \
-        VIS64 s, d;                                     \
-                                                        \
-        s.d = DT0;                                      \
-        d.d = DT1;                                      \
-                                                        \
-        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
-        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
-        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
-        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
-                                                        \
-        DT0 = d.d;                                      \
-    }                                                   \
-                                                        \
-    uint32_t name##16s(uint32_t src1, uint32_t src2)    \
-    {                                                   \
-        VIS32 s, d;                                     \
-                                                        \
-        s.l = src1;                                     \
-        d.l = src2;                                     \
-                                                        \
-        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
-        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
-                                                        \
-        return d.l;                                     \
-    }                                                   \
-                                                        \
-    void name##32(void)                                 \
-    {                                                   \
-        VIS64 s, d;                                     \
-                                                        \
-        s.d = DT0;                                      \
-        d.d = DT1;                                      \
-                                                        \
-        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
-        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
-                                                        \
-        DT0 = d.d;                                      \
-    }                                                   \
-                                                        \
-    uint32_t name##32s(uint32_t src1, uint32_t src2)    \
-    {                                                   \
-        VIS32 s, d;                                     \
-                                                        \
-        s.l = src1;                                     \
-        d.l = src2;                                     \
-                                                        \
-        d.l = F(d.l, s.l);                              \
-                                                        \
-        return d.l;                                     \
-    }
-
-#define FADD(a, b) ((a) + (b))
-#define FSUB(a, b) ((a) - (b))
-VIS_HELPER(helper_fpadd, FADD)
-VIS_HELPER(helper_fpsub, FSUB)
-
-#define VIS_CMPHELPER(name, F)                                    \
-    uint64_t name##16(void)                                       \
-    {                                                             \
-        VIS64 s, d;                                               \
-                                                                  \
-        s.d = DT0;                                                \
-        d.d = DT1;                                                \
-                                                                  \
-        d.VIS_W64(0) = F(s.VIS_W64(0), d.VIS_W64(0)) ? 1 : 0;     \
-        d.VIS_W64(0) |= F(s.VIS_W64(1), d.VIS_W64(1)) ? 2 : 0;    \
-        d.VIS_W64(0) |= F(s.VIS_W64(2), d.VIS_W64(2)) ? 4 : 0;    \
-        d.VIS_W64(0) |= F(s.VIS_W64(3), d.VIS_W64(3)) ? 8 : 0;    \
-        d.VIS_W64(1) = d.VIS_W64(2) = d.VIS_W64(3) = 0;           \
-                                                                  \
-        return d.ll;                                              \
-    }                                                             \
-                                                                  \
-    uint64_t name##32(void)                                       \
-    {                                                             \
-        VIS64 s, d;                                               \
-                                                                  \
-        s.d = DT0;                                                \
-        d.d = DT1;                                                \
-                                                                  \
-        d.VIS_L64(0) = F(s.VIS_L64(0), d.VIS_L64(0)) ? 1 : 0;     \
-        d.VIS_L64(0) |= F(s.VIS_L64(1), d.VIS_L64(1)) ? 2 : 0;    \
-        d.VIS_L64(1) = 0;                                         \
-                                                                  \
-        return d.ll;                                              \
-    }
-
-#define FCMPGT(a, b) ((a) > (b))
-#define FCMPEQ(a, b) ((a) == (b))
-#define FCMPLE(a, b) ((a) <= (b))
-#define FCMPNE(a, b) ((a) != (b))
-
-VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
-VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
-VIS_CMPHELPER(helper_fcmple, FCMPLE)
-VIS_CMPHELPER(helper_fcmpne, FCMPNE)
-#endif
-
-void helper_check_ieee_exceptions(void)
-{
-    target_ulong status;
-
-    status = get_float_exception_flags(&env->fp_status);
-    if (status) {
-        /* Copy IEEE 754 flags into FSR */
-        if (status & float_flag_invalid) {
-            env->fsr |= FSR_NVC;
-        }
-        if (status & float_flag_overflow) {
-            env->fsr |= FSR_OFC;
-        }
-        if (status & float_flag_underflow) {
-            env->fsr |= FSR_UFC;
-        }
-        if (status & float_flag_divbyzero) {
-            env->fsr |= FSR_DZC;
-        }
-        if (status & float_flag_inexact) {
-            env->fsr |= FSR_NXC;
-        }
-
-        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
-            /* Unmasked exception, generate a trap */
-            env->fsr |= FSR_FTT_IEEE_EXCP;
-            helper_raise_exception(env, TT_FP_EXCP);
-        } else {
-            /* Accumulate exceptions */
-            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
-        }
-    }
-}
-
-void helper_clear_float_exceptions(void)
-{
-    set_float_exception_flags(0, &env->fp_status);
-}
-
-float32 helper_fabss(float32 src)
-{
-    return float32_abs(src);
-}
-
-#ifdef TARGET_SPARC64
-void helper_fabsd(void)
-{
-    DT0 = float64_abs(DT1);
-}
-
-void helper_fabsq(void)
-{
-    QT0 = float128_abs(QT1);
-}
-#endif
-
-float32 helper_fsqrts(float32 src)
-{
-    return float32_sqrt(src, &env->fp_status);
-}
-
-void helper_fsqrtd(void)
-{
-    DT0 = float64_sqrt(DT1, &env->fp_status);
-}
-
-void helper_fsqrtq(void)
-{
-    QT0 = float128_sqrt(QT1, &env->fp_status);
-}
-
-#define GEN_FCMP(name, size, reg1, reg2, FS, E)                         \
-    void glue(helper_, name) (void)                                     \
-    {                                                                   \
-        env->fsr &= FSR_FTT_NMASK;                                      \
-        if (E && (glue(size, _is_any_nan)(reg1) ||                      \
-                  glue(size, _is_any_nan)(reg2)) &&                     \
-            (env->fsr & FSR_NVM)) {                                     \
-            env->fsr |= FSR_NVC;                                        \
-            env->fsr |= FSR_FTT_IEEE_EXCP;                              \
-            helper_raise_exception(env, TT_FP_EXCP);                    \
-        }                                                               \
-        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
-        case float_relation_unordered:                                  \
-            if ((env->fsr & FSR_NVM)) {                                 \
-                env->fsr |= FSR_NVC;                                    \
-                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
-                helper_raise_exception(env, TT_FP_EXCP);                \
-            } else {                                                    \
-                env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);             \
-                env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                \
-                env->fsr |= FSR_NVA;                                    \
-            }                                                           \
-            break;                                                      \
-        case float_relation_less:                                       \
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
-            env->fsr |= FSR_FCC0 << FS;                                 \
-            break;                                                      \
-        case float_relation_greater:                                    \
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
-            env->fsr |= FSR_FCC1 << FS;                                 \
-            break;                                                      \
-        default:                                                        \
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
-            break;                                                      \
-        }                                                               \
-    }
-#define GEN_FCMPS(name, size, FS, E)                                    \
-    void glue(helper_, name)(float32 src1, float32 src2)                \
-    {                                                                   \
-        env->fsr &= FSR_FTT_NMASK;                                      \
-        if (E && (glue(size, _is_any_nan)(src1) ||                      \
-                  glue(size, _is_any_nan)(src2)) &&                     \
-            (env->fsr & FSR_NVM)) {                                     \
-            env->fsr |= FSR_NVC;                                        \
-            env->fsr |= FSR_FTT_IEEE_EXCP;                              \
-            helper_raise_exception(env, TT_FP_EXCP);                    \
-        }                                                               \
-        switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
-        case float_relation_unordered:                                  \
-            if ((env->fsr & FSR_NVM)) {                                 \
-                env->fsr |= FSR_NVC;                                    \
-                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
-                helper_raise_exception(env, TT_FP_EXCP);                \
-            } else {                                                    \
-                env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);             \
-                env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                \
-                env->fsr |= FSR_NVA;                                    \
-            }                                                           \
-            break;                                                      \
-        case float_relation_less:                                       \
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
-            env->fsr |= FSR_FCC0 << FS;                                 \
-            break;                                                      \
-        case float_relation_greater:                                    \
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
-            env->fsr |= FSR_FCC1 << FS;                                 \
-            break;                                                      \
-        default:                                                        \
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
-            break;                                                      \
-        }                                                               \
-    }
-
-GEN_FCMPS(fcmps, float32, 0, 0);
-GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
-
-GEN_FCMPS(fcmpes, float32, 0, 1);
-GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
-
-GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
-GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
-
 static uint32_t compute_all_flags(void)
 {
     return env->psr & PSR_ICC;
@@ -1580,33 +931,6 @@ int cpu_cwp_dec(CPUState *env1, int cwp)
     return ret;
 }
 
-#ifdef TARGET_SPARC64
-GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
-GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
-GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
-
-GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
-GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
-GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
-
-GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
-GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
-GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
-
-GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
-GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
-GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
-
-GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
-GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
-GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
-
-GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
-GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
-GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
-#endif
-#undef GEN_FCMPS
-
 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) &&   \
     defined(DEBUG_MXCC)
 static void dump_mxcc(CPUState *env)
@@ -3748,42 +3072,6 @@ void helper_stqf(target_ulong addr, int mem_idx)
 #endif
 }
 
-static inline void set_fsr(void)
-{
-    int rnd_mode;
-
-    switch (env->fsr & FSR_RD_MASK) {
-    case FSR_RD_NEAREST:
-        rnd_mode = float_round_nearest_even;
-        break;
-    default:
-    case FSR_RD_ZERO:
-        rnd_mode = float_round_to_zero;
-        break;
-    case FSR_RD_POS:
-        rnd_mode = float_round_up;
-        break;
-    case FSR_RD_NEG:
-        rnd_mode = float_round_down;
-        break;
-    }
-    set_float_rounding_mode(rnd_mode, &env->fp_status);
-}
-
-void helper_ldfsr(uint32_t new_fsr)
-{
-    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
-    set_fsr();
-}
-
-#ifdef TARGET_SPARC64
-void helper_ldxfsr(uint64_t new_fsr)
-{
-    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
-    set_fsr();
-}
-#endif
-
 #ifndef TARGET_SPARC64
 /* XXX: use another pointer for %iN registers to avoid slow wrapping
    handling ? */
@@ -3993,37 +3281,6 @@ void helper_wrcwp(target_ulong new_cwp)
     put_cwp64(new_cwp);
 }
 
-/* This function uses non-native bit order */
-#define GET_FIELD(X, FROM, TO)                                  \
-    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
-
-/* This function uses the order in the manuals, i.e. bit 0 is 2^0 */
-#define GET_FIELD_SP(X, FROM, TO)               \
-    GET_FIELD(X, 63 - (TO), 63 - (FROM))
-
-target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
-{
-    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
-        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
-        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
-        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
-        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
-        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
-        (((pixel_addr >> 55) & 1) << 4) |
-        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
-        GET_FIELD_SP(pixel_addr, 11, 12);
-}
-
-target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
-{
-    uint64_t tmp;
-
-    tmp = addr + offset;
-    env->gsr &= ~7ULL;
-    env->gsr |= tmp & 7ULL;
-    return tmp & ~7ULL;
-}
-
 static inline uint64_t *get_gregset(uint32_t pstate)
 {
     switch (pstate) {
diff --git a/target-sparc/vis_helper.c b/target-sparc/vis_helper.c
new file mode 100644
index 0000000..87a86ef
--- /dev/null
+++ b/target-sparc/vis_helper.c
@@ -0,0 +1,403 @@
+/*
+ * VIS op helpers
+ *
+ *  Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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 "helper.h"
+
+#define DT0 (env->dt0)
+#define DT1 (env->dt1)
+#define QT0 (env->qt0)
+#define QT1 (env->qt1)
+
+/* This function uses non-native bit order */
+#define GET_FIELD(X, FROM, TO)                                  \
+    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
+
+/* This function uses the order in the manuals, i.e. bit 0 is 2^0 */
+#define GET_FIELD_SP(X, FROM, TO)               \
+    GET_FIELD(X, 63 - (TO), 63 - (FROM))
+
+target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
+{
+    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
+        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
+        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
+        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
+        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
+        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
+        (((pixel_addr >> 55) & 1) << 4) |
+        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
+        GET_FIELD_SP(pixel_addr, 11, 12);
+}
+
+target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
+{
+    uint64_t tmp;
+
+    tmp = addr + offset;
+    env->gsr &= ~7ULL;
+    env->gsr |= tmp & 7ULL;
+    return tmp & ~7ULL;
+}
+
+void helper_faligndata(void)
+{
+    uint64_t tmp;
+
+    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
+    /* on many architectures a shift of 64 does nothing */
+    if ((env->gsr & 7) != 0) {
+        tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
+    }
+    *((uint64_t *)&DT0) = tmp;
+}
+
+#ifdef HOST_WORDS_BIGENDIAN
+#define VIS_B64(n) b[7 - (n)]
+#define VIS_W64(n) w[3 - (n)]
+#define VIS_SW64(n) sw[3 - (n)]
+#define VIS_L64(n) l[1 - (n)]
+#define VIS_B32(n) b[3 - (n)]
+#define VIS_W32(n) w[1 - (n)]
+#else
+#define VIS_B64(n) b[n]
+#define VIS_W64(n) w[n]
+#define VIS_SW64(n) sw[n]
+#define VIS_L64(n) l[n]
+#define VIS_B32(n) b[n]
+#define VIS_W32(n) w[n]
+#endif
+
+typedef union {
+    uint8_t b[8];
+    uint16_t w[4];
+    int16_t sw[4];
+    uint32_t l[2];
+    uint64_t ll;
+    float64 d;
+} VIS64;
+
+typedef union {
+    uint8_t b[4];
+    uint16_t w[2];
+    uint32_t l;
+    float32 f;
+} VIS32;
+
+void helper_fpmerge(void)
+{
+    VIS64 s, d;
+
+    s.d = DT0;
+    d.d = DT1;
+
+    /* Reverse calculation order to handle overlap */
+    d.VIS_B64(7) = s.VIS_B64(3);
+    d.VIS_B64(6) = d.VIS_B64(3);
+    d.VIS_B64(5) = s.VIS_B64(2);
+    d.VIS_B64(4) = d.VIS_B64(2);
+    d.VIS_B64(3) = s.VIS_B64(1);
+    d.VIS_B64(2) = d.VIS_B64(1);
+    d.VIS_B64(1) = s.VIS_B64(0);
+    /* d.VIS_B64(0) = d.VIS_B64(0); */
+
+    DT0 = d.d;
+}
+
+void helper_fmul8x16(void)
+{
+    VIS64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                 \
+    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
+    if ((tmp & 0xff) > 0x7f) {                                  \
+        tmp += 0x100;                                           \
+    }                                                           \
+    d.VIS_W64(r) = tmp >> 8;
+
+    PMUL(0);
+    PMUL(1);
+    PMUL(2);
+    PMUL(3);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void helper_fmul8x16al(void)
+{
+    VIS64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                 \
+    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
+    if ((tmp & 0xff) > 0x7f) {                                  \
+        tmp += 0x100;                                           \
+    }                                                           \
+    d.VIS_W64(r) = tmp >> 8;
+
+    PMUL(0);
+    PMUL(1);
+    PMUL(2);
+    PMUL(3);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void helper_fmul8x16au(void)
+{
+    VIS64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                 \
+    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
+    if ((tmp & 0xff) > 0x7f) {                                  \
+        tmp += 0x100;                                           \
+    }                                                           \
+    d.VIS_W64(r) = tmp >> 8;
+
+    PMUL(0);
+    PMUL(1);
+    PMUL(2);
+    PMUL(3);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void helper_fmul8sux16(void)
+{
+    VIS64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                         \
+    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
+    if ((tmp & 0xff) > 0x7f) {                                          \
+        tmp += 0x100;                                                   \
+    }                                                                   \
+    d.VIS_W64(r) = tmp >> 8;
+
+    PMUL(0);
+    PMUL(1);
+    PMUL(2);
+    PMUL(3);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void helper_fmul8ulx16(void)
+{
+    VIS64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                         \
+    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
+    if ((tmp & 0xff) > 0x7f) {                                          \
+        tmp += 0x100;                                                   \
+    }                                                                   \
+    d.VIS_W64(r) = tmp >> 8;
+
+    PMUL(0);
+    PMUL(1);
+    PMUL(2);
+    PMUL(3);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void helper_fmuld8sux16(void)
+{
+    VIS64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                         \
+    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
+    if ((tmp & 0xff) > 0x7f) {                                          \
+        tmp += 0x100;                                                   \
+    }                                                                   \
+    d.VIS_L64(r) = tmp;
+
+    /* Reverse calculation order to handle overlap */
+    PMUL(1);
+    PMUL(0);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void helper_fmuld8ulx16(void)
+{
+    VIS64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                         \
+    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
+    if ((tmp & 0xff) > 0x7f) {                                          \
+        tmp += 0x100;                                                   \
+    }                                                                   \
+    d.VIS_L64(r) = tmp;
+
+    /* Reverse calculation order to handle overlap */
+    PMUL(1);
+    PMUL(0);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void helper_fexpand(void)
+{
+    VIS32 s;
+    VIS64 d;
+
+    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
+    d.d = DT1;
+    d.VIS_W64(0) = s.VIS_B32(0) << 4;
+    d.VIS_W64(1) = s.VIS_B32(1) << 4;
+    d.VIS_W64(2) = s.VIS_B32(2) << 4;
+    d.VIS_W64(3) = s.VIS_B32(3) << 4;
+
+    DT0 = d.d;
+}
+
+#define VIS_HELPER(name, F)                             \
+    void name##16(void)                                 \
+    {                                                   \
+        VIS64 s, d;                                     \
+                                                        \
+        s.d = DT0;                                      \
+        d.d = DT1;                                      \
+                                                        \
+        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
+        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
+        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
+        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
+                                                        \
+        DT0 = d.d;                                      \
+    }                                                   \
+                                                        \
+    uint32_t name##16s(uint32_t src1, uint32_t src2)    \
+    {                                                   \
+        VIS32 s, d;                                     \
+                                                        \
+        s.l = src1;                                     \
+        d.l = src2;                                     \
+                                                        \
+        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
+        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
+                                                        \
+        return d.l;                                     \
+    }                                                   \
+                                                        \
+    void name##32(void)                                 \
+    {                                                   \
+        VIS64 s, d;                                     \
+                                                        \
+        s.d = DT0;                                      \
+        d.d = DT1;                                      \
+                                                        \
+        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
+        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
+                                                        \
+        DT0 = d.d;                                      \
+    }                                                   \
+                                                        \
+    uint32_t name##32s(uint32_t src1, uint32_t src2)    \
+    {                                                   \
+        VIS32 s, d;                                     \
+                                                        \
+        s.l = src1;                                     \
+        d.l = src2;                                     \
+                                                        \
+        d.l = F(d.l, s.l);                              \
+                                                        \
+        return d.l;                                     \
+    }
+
+#define FADD(a, b) ((a) + (b))
+#define FSUB(a, b) ((a) - (b))
+VIS_HELPER(helper_fpadd, FADD)
+VIS_HELPER(helper_fpsub, FSUB)
+
+#define VIS_CMPHELPER(name, F)                                    \
+    uint64_t name##16(void)                                       \
+    {                                                             \
+        VIS64 s, d;                                               \
+                                                                  \
+        s.d = DT0;                                                \
+        d.d = DT1;                                                \
+                                                                  \
+        d.VIS_W64(0) = F(s.VIS_W64(0), d.VIS_W64(0)) ? 1 : 0;     \
+        d.VIS_W64(0) |= F(s.VIS_W64(1), d.VIS_W64(1)) ? 2 : 0;    \
+        d.VIS_W64(0) |= F(s.VIS_W64(2), d.VIS_W64(2)) ? 4 : 0;    \
+        d.VIS_W64(0) |= F(s.VIS_W64(3), d.VIS_W64(3)) ? 8 : 0;    \
+        d.VIS_W64(1) = d.VIS_W64(2) = d.VIS_W64(3) = 0;           \
+                                                                  \
+        return d.ll;                                              \
+    }                                                             \
+                                                                  \
+    uint64_t name##32(void)                                       \
+    {                                                             \
+        VIS64 s, d;                                               \
+                                                                  \
+        s.d = DT0;                                                \
+        d.d = DT1;                                                \
+                                                                  \
+        d.VIS_L64(0) = F(s.VIS_L64(0), d.VIS_L64(0)) ? 1 : 0;     \
+        d.VIS_L64(0) |= F(s.VIS_L64(1), d.VIS_L64(1)) ? 2 : 0;    \
+        d.VIS_L64(1) = 0;                                         \
+                                                                  \
+        return d.ll;                                              \
+    }
+
+#define FCMPGT(a, b) ((a) > (b))
+#define FCMPEQ(a, b) ((a) == (b))
+#define FCMPLE(a, b) ((a) <= (b))
+#define FCMPNE(a, b) ((a) != (b))
+
+VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
+VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
+VIS_CMPHELPER(helper_fcmple, FCMPLE)
+VIS_CMPHELPER(helper_fcmpne, FCMPNE)
commit 99ca02195cad858043444107acc3ab1df874edea
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Jul 3 15:22:03 2011 +0000

    Sparc: fix coding style
    
    Before the next patches, fix coding style of the areas affected.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 632850c..f2bca77 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -34,14 +34,14 @@
 #endif
 
 #ifdef DEBUG_PSTATE
-#define DPRINTF_PSTATE(fmt, ...)                                   \
+#define DPRINTF_PSTATE(fmt, ...)                                \
     do { printf("PSTATE: " fmt , ## __VA_ARGS__); } while (0)
 #else
 #define DPRINTF_PSTATE(fmt, ...) do {} while (0)
 #endif
 
 #ifdef DEBUG_CACHE_CONTROL
-#define DPRINTF_CACHE_CONTROL(fmt, ...)                                   \
+#define DPRINTF_CACHE_CONTROL(fmt, ...)                                 \
     do { printf("CACHE_CONTROL: " fmt , ## __VA_ARGS__); } while (0)
 #else
 #define DPRINTF_CACHE_CONTROL(fmt, ...) do {} while (0)
@@ -92,7 +92,7 @@ static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
 #endif
 
 #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
-// Calculates TSB pointer value for fault page size 8k or 64k
+/* Calculates TSB pointer value for fault page size 8k or 64k */
 static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
                                        uint64_t tag_access_register,
                                        int page_size)
@@ -101,14 +101,14 @@ static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
     int tsb_split = (tsb_register & 0x1000ULL) ? 1 : 0;
     int tsb_size  = tsb_register & 0xf;
 
-    // discard lower 13 bits which hold tag access context
+    /* discard lower 13 bits which hold tag access context */
     uint64_t tag_access_va = tag_access_register & ~0x1fffULL;
 
-    // now reorder bits
+    /* now reorder bits */
     uint64_t tsb_base_mask = ~0x1fffULL;
     uint64_t va = tag_access_va;
 
-    // move va bits to correct position
+    /* move va bits to correct position */
     if (page_size == 8*1024) {
         va >>= 9;
     } else if (page_size == 64*1024) {
@@ -119,7 +119,7 @@ static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
         tsb_base_mask <<= tsb_size;
     }
 
-    // calculate tsb_base mask and adjust va if split is in use
+    /* calculate tsb_base mask and adjust va if split is in use */
     if (tsb_split) {
         if (page_size == 8*1024) {
             va &= ~(1ULL << (13 + tsb_size));
@@ -132,8 +132,8 @@ static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
     return ((tsb_base & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL;
 }
 
-// Calculates tag target register value by reordering bits
-// in tag access register
+/* Calculates tag target register value by reordering bits
+   in tag access register */
 static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
 {
     return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22);
@@ -145,7 +145,7 @@ static void replace_tlb_entry(SparcTLBEntry *tlb,
 {
     target_ulong mask, size, va, offset;
 
-    // flush page range if translation is valid
+    /* flush page range if translation is valid */
     if (TTE_IS_VALID(tlb->tte)) {
 
         mask = 0xffffffffffffe000ULL;
@@ -164,7 +164,7 @@ static void replace_tlb_entry(SparcTLBEntry *tlb,
 }
 
 static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
-                      const char* strmmu, CPUState *env1)
+                      const char *strmmu, CPUState *env1)
 {
     unsigned int i;
     target_ulong mask;
@@ -172,18 +172,18 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
 
     int is_demap_context = (demap_addr >> 6) & 1;
 
-    // demap context
+    /* demap context */
     switch ((demap_addr >> 4) & 3) {
-    case 0: // primary
+    case 0: /* primary */
         context = env1->dmmu.mmu_primary_context;
         break;
-    case 1: // secondary
+    case 1: /* secondary */
         context = env1->dmmu.mmu_secondary_context;
         break;
-    case 2: // nucleus
+    case 2: /* nucleus */
         context = 0;
         break;
-    case 3: // reserved
+    case 3: /* reserved */
     default:
         return;
     }
@@ -192,14 +192,14 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
         if (TTE_IS_VALID(tlb[i].tte)) {
 
             if (is_demap_context) {
-                // will remove non-global entries matching context value
+                /* will remove non-global entries matching context value */
                 if (TTE_IS_GLOBAL(tlb[i].tte) ||
                     !tlb_compare_context(&tlb[i], context)) {
                     continue;
                 }
             } else {
-                // demap page
-                // will remove any entry matching VA
+                /* demap page
+                   will remove any entry matching VA */
                 mask = 0xffffffffffffe000ULL;
                 mask <<= 3 * ((tlb[i].tte >> 61) & 3);
 
@@ -207,7 +207,7 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
                     continue;
                 }
 
-                // entry should be global or matching context value
+                /* entry should be global or matching context value */
                 if (!TTE_IS_GLOBAL(tlb[i].tte) &&
                     !tlb_compare_context(&tlb[i], context)) {
                     continue;
@@ -225,11 +225,11 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
 
 static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
                                  uint64_t tlb_tag, uint64_t tlb_tte,
-                                 const char* strmmu, CPUState *env1)
+                                 const char *strmmu, CPUState *env1)
 {
     unsigned int i, replace_used;
 
-    // Try replacing invalid entry
+    /* Try replacing invalid entry */
     for (i = 0; i < 64; i++) {
         if (!TTE_IS_VALID(tlb[i].tte)) {
             replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
@@ -241,11 +241,11 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
         }
     }
 
-    // All entries are valid, try replacing unlocked entry
+    /* All entries are valid, try replacing unlocked entry */
 
     for (replace_used = 0; replace_used < 2; ++replace_used) {
 
-        // Used entries are not replaced on first pass
+        /* Used entries are not replaced on first pass */
 
         for (i = 0; i < 64; i++) {
             if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
@@ -253,14 +253,14 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
                 replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
 #ifdef DEBUG_MMU
                 DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
-                            strmmu, (replace_used?"used":"unused"), i);
+                            strmmu, (replace_used ? "used" : "unused"), i);
                 dump_mmu(stdout, fprintf, env1);
 #endif
                 return;
             }
         }
 
-        // Now reset used bit and search for unused entries again
+        /* Now reset used bit and search for unused entries again */
 
         for (i = 0; i < 64; i++) {
             TTE_SET_UNUSED(tlb[i].tte);
@@ -270,7 +270,7 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
 #ifdef DEBUG_MMU
     DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
 #endif
-    // error state?
+    /* error state? */
 }
 
 #endif
@@ -278,8 +278,9 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
 static inline target_ulong address_mask(CPUState *env1, target_ulong addr)
 {
 #ifdef TARGET_SPARC64
-    if (AM_CHECK(env1))
+    if (AM_CHECK(env1)) {
         addr &= 0xffffffffULL;
+    }
 #endif
     return addr;
 }
@@ -291,7 +292,7 @@ static inline int is_translating_asi(int asi)
 #ifdef TARGET_SPARC64
     /* Ultrasparc IIi translating asi
        - note this list is defined by cpu implementation
-     */
+    */
     switch (asi) {
     case 0x04 ... 0x11:
     case 0x16 ... 0x19:
@@ -325,8 +326,8 @@ void helper_check_align(target_ulong addr, uint32_t align)
 {
     if (addr & align) {
 #ifdef DEBUG_UNALIGNED
-    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
-           "\n", addr, env->pc);
+        printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
+               "\n", addr, env->pc);
 #endif
         helper_raise_exception(env, TT_UNALIGNED);
     }
@@ -517,23 +518,23 @@ typedef union {
     uint32_t l[2];
     uint64_t ll;
     float64 d;
-} vis64;
+} VIS64;
 
 typedef union {
     uint8_t b[4];
     uint16_t w[2];
     uint32_t l;
     float32 f;
-} vis32;
+} VIS32;
 
 void helper_fpmerge(void)
 {
-    vis64 s, d;
+    VIS64 s, d;
 
     s.d = DT0;
     d.d = DT1;
 
-    // Reverse calculation order to handle overlap
+    /* Reverse calculation order to handle overlap */
     d.VIS_B64(7) = s.VIS_B64(3);
     d.VIS_B64(6) = d.VIS_B64(3);
     d.VIS_B64(5) = s.VIS_B64(2);
@@ -541,14 +542,14 @@ void helper_fpmerge(void)
     d.VIS_B64(3) = s.VIS_B64(1);
     d.VIS_B64(2) = d.VIS_B64(1);
     d.VIS_B64(1) = s.VIS_B64(0);
-    //d.VIS_B64(0) = d.VIS_B64(0);
+    /* d.VIS_B64(0) = d.VIS_B64(0); */
 
     DT0 = d.d;
 }
 
 void helper_fmul8x16(void)
 {
-    vis64 s, d;
+    VIS64 s, d;
     uint32_t tmp;
 
     s.d = DT0;
@@ -556,8 +557,9 @@ void helper_fmul8x16(void)
 
 #define PMUL(r)                                                 \
     tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
-    if ((tmp & 0xff) > 0x7f)                                    \
+    if ((tmp & 0xff) > 0x7f) {                                  \
         tmp += 0x100;                                           \
+    }                                                           \
     d.VIS_W64(r) = tmp >> 8;
 
     PMUL(0);
@@ -571,7 +573,7 @@ void helper_fmul8x16(void)
 
 void helper_fmul8x16al(void)
 {
-    vis64 s, d;
+    VIS64 s, d;
     uint32_t tmp;
 
     s.d = DT0;
@@ -579,8 +581,9 @@ void helper_fmul8x16al(void)
 
 #define PMUL(r)                                                 \
     tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
-    if ((tmp & 0xff) > 0x7f)                                    \
+    if ((tmp & 0xff) > 0x7f) {                                  \
         tmp += 0x100;                                           \
+    }                                                           \
     d.VIS_W64(r) = tmp >> 8;
 
     PMUL(0);
@@ -594,7 +597,7 @@ void helper_fmul8x16al(void)
 
 void helper_fmul8x16au(void)
 {
-    vis64 s, d;
+    VIS64 s, d;
     uint32_t tmp;
 
     s.d = DT0;
@@ -602,8 +605,9 @@ void helper_fmul8x16au(void)
 
 #define PMUL(r)                                                 \
     tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
-    if ((tmp & 0xff) > 0x7f)                                    \
+    if ((tmp & 0xff) > 0x7f) {                                  \
         tmp += 0x100;                                           \
+    }                                                           \
     d.VIS_W64(r) = tmp >> 8;
 
     PMUL(0);
@@ -617,7 +621,7 @@ void helper_fmul8x16au(void)
 
 void helper_fmul8sux16(void)
 {
-    vis64 s, d;
+    VIS64 s, d;
     uint32_t tmp;
 
     s.d = DT0;
@@ -625,8 +629,9 @@ void helper_fmul8sux16(void)
 
 #define PMUL(r)                                                         \
     tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
-    if ((tmp & 0xff) > 0x7f)                                            \
+    if ((tmp & 0xff) > 0x7f) {                                          \
         tmp += 0x100;                                                   \
+    }                                                                   \
     d.VIS_W64(r) = tmp >> 8;
 
     PMUL(0);
@@ -640,7 +645,7 @@ void helper_fmul8sux16(void)
 
 void helper_fmul8ulx16(void)
 {
-    vis64 s, d;
+    VIS64 s, d;
     uint32_t tmp;
 
     s.d = DT0;
@@ -648,8 +653,9 @@ void helper_fmul8ulx16(void)
 
 #define PMUL(r)                                                         \
     tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
-    if ((tmp & 0xff) > 0x7f)                                            \
+    if ((tmp & 0xff) > 0x7f) {                                          \
         tmp += 0x100;                                                   \
+    }                                                                   \
     d.VIS_W64(r) = tmp >> 8;
 
     PMUL(0);
@@ -663,7 +669,7 @@ void helper_fmul8ulx16(void)
 
 void helper_fmuld8sux16(void)
 {
-    vis64 s, d;
+    VIS64 s, d;
     uint32_t tmp;
 
     s.d = DT0;
@@ -671,11 +677,12 @@ void helper_fmuld8sux16(void)
 
 #define PMUL(r)                                                         \
     tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
-    if ((tmp & 0xff) > 0x7f)                                            \
+    if ((tmp & 0xff) > 0x7f) {                                          \
         tmp += 0x100;                                                   \
+    }                                                                   \
     d.VIS_L64(r) = tmp;
 
-    // Reverse calculation order to handle overlap
+    /* Reverse calculation order to handle overlap */
     PMUL(1);
     PMUL(0);
 #undef PMUL
@@ -685,7 +692,7 @@ void helper_fmuld8sux16(void)
 
 void helper_fmuld8ulx16(void)
 {
-    vis64 s, d;
+    VIS64 s, d;
     uint32_t tmp;
 
     s.d = DT0;
@@ -693,11 +700,12 @@ void helper_fmuld8ulx16(void)
 
 #define PMUL(r)                                                         \
     tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
-    if ((tmp & 0xff) > 0x7f)                                            \
+    if ((tmp & 0xff) > 0x7f) {                                          \
         tmp += 0x100;                                                   \
+    }                                                                   \
     d.VIS_L64(r) = tmp;
 
-    // Reverse calculation order to handle overlap
+    /* Reverse calculation order to handle overlap */
     PMUL(1);
     PMUL(0);
 #undef PMUL
@@ -707,8 +715,8 @@ void helper_fmuld8ulx16(void)
 
 void helper_fexpand(void)
 {
-    vis32 s;
-    vis64 d;
+    VIS32 s;
+    VIS64 d;
 
     s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
     d.d = DT1;
@@ -723,7 +731,7 @@ void helper_fexpand(void)
 #define VIS_HELPER(name, F)                             \
     void name##16(void)                                 \
     {                                                   \
-        vis64 s, d;                                     \
+        VIS64 s, d;                                     \
                                                         \
         s.d = DT0;                                      \
         d.d = DT1;                                      \
@@ -738,7 +746,7 @@ void helper_fexpand(void)
                                                         \
     uint32_t name##16s(uint32_t src1, uint32_t src2)    \
     {                                                   \
-        vis32 s, d;                                     \
+        VIS32 s, d;                                     \
                                                         \
         s.l = src1;                                     \
         d.l = src2;                                     \
@@ -751,7 +759,7 @@ void helper_fexpand(void)
                                                         \
     void name##32(void)                                 \
     {                                                   \
-        vis64 s, d;                                     \
+        VIS64 s, d;                                     \
                                                         \
         s.d = DT0;                                      \
         d.d = DT1;                                      \
@@ -764,7 +772,7 @@ void helper_fexpand(void)
                                                         \
     uint32_t name##32s(uint32_t src1, uint32_t src2)    \
     {                                                   \
-        vis32 s, d;                                     \
+        VIS32 s, d;                                     \
                                                         \
         s.l = src1;                                     \
         d.l = src2;                                     \
@@ -779,10 +787,10 @@ void helper_fexpand(void)
 VIS_HELPER(helper_fpadd, FADD)
 VIS_HELPER(helper_fpsub, FSUB)
 
-#define VIS_CMPHELPER(name, F)                                        \
+#define VIS_CMPHELPER(name, F)                                    \
     uint64_t name##16(void)                                       \
     {                                                             \
-        vis64 s, d;                                               \
+        VIS64 s, d;                                               \
                                                                   \
         s.d = DT0;                                                \
         d.d = DT1;                                                \
@@ -798,7 +806,7 @@ VIS_HELPER(helper_fpsub, FSUB)
                                                                   \
     uint64_t name##32(void)                                       \
     {                                                             \
-        vis64 s, d;                                               \
+        VIS64 s, d;                                               \
                                                                   \
         s.d = DT0;                                                \
         d.d = DT1;                                                \
@@ -828,16 +836,21 @@ void helper_check_ieee_exceptions(void)
     status = get_float_exception_flags(&env->fp_status);
     if (status) {
         /* Copy IEEE 754 flags into FSR */
-        if (status & float_flag_invalid)
+        if (status & float_flag_invalid) {
             env->fsr |= FSR_NVC;
-        if (status & float_flag_overflow)
+        }
+        if (status & float_flag_overflow) {
             env->fsr |= FSR_OFC;
-        if (status & float_flag_underflow)
+        }
+        if (status & float_flag_underflow) {
             env->fsr |= FSR_UFC;
-        if (status & float_flag_divbyzero)
+        }
+        if (status & float_flag_divbyzero) {
             env->fsr |= FSR_DZC;
-        if (status & float_flag_inexact)
+        }
+        if (status & float_flag_inexact) {
             env->fsr |= FSR_NXC;
+        }
 
         if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
             /* Unmasked exception, generate a trap */
@@ -892,7 +905,7 @@ void helper_fsqrtq(void)
     {                                                                   \
         env->fsr &= FSR_FTT_NMASK;                                      \
         if (E && (glue(size, _is_any_nan)(reg1) ||                      \
-                     glue(size, _is_any_nan)(reg2)) &&                  \
+                  glue(size, _is_any_nan)(reg2)) &&                     \
             (env->fsr & FSR_NVM)) {                                     \
             env->fsr |= FSR_NVC;                                        \
             env->fsr |= FSR_FTT_IEEE_EXCP;                              \
@@ -928,7 +941,7 @@ void helper_fsqrtq(void)
     {                                                                   \
         env->fsr &= FSR_FTT_NMASK;                                      \
         if (E && (glue(size, _is_any_nan)(src1) ||                      \
-                     glue(size, _is_any_nan)(src2)) &&                  \
+                  glue(size, _is_any_nan)(src2)) &&                     \
             (env->fsr & FSR_NVM)) {                                     \
             env->fsr |= FSR_NVC;                                        \
             env->fsr |= FSR_FTT_IEEE_EXCP;                              \
@@ -1094,7 +1107,7 @@ static inline uint32_t get_C_addx_xcc(target_ulong dst, target_ulong src1,
 }
 
 static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
-                                         target_ulong src2)
+                                     target_ulong src2)
 {
     uint32_t ret = 0;
 
@@ -1476,11 +1489,11 @@ static target_ulong get_psr(void)
 
 #if !defined (TARGET_SPARC64)
     return env->version | (env->psr & PSR_ICC) |
-        (env->psref? PSR_EF : 0) |
+        (env->psref ? PSR_EF : 0) |
         (env->psrpil << 8) |
-        (env->psrs? PSR_S : 0) |
-        (env->psrps? PSR_PS : 0) |
-        (env->psret? PSR_ET : 0) | env->cwp;
+        (env->psrs ? PSR_S : 0) |
+        (env->psrps ? PSR_PS : 0) |
+        (env->psret ? PSR_ET : 0) | env->cwp;
 #else
     return env->psr & PSR_ICC;
 #endif
@@ -1502,16 +1515,16 @@ static void put_psr(target_ulong val)
 {
     env->psr = val & PSR_ICC;
 #if !defined (TARGET_SPARC64)
-    env->psref = (val & PSR_EF)? 1 : 0;
+    env->psref = (val & PSR_EF) ? 1 : 0;
     env->psrpil = (val & PSR_PIL) >> 8;
 #endif
 #if ((!defined (TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY))
     cpu_check_irqs(env);
 #endif
 #if !defined (TARGET_SPARC64)
-    env->psrs = (val & PSR_S)? 1 : 0;
-    env->psrps = (val & PSR_PS)? 1 : 0;
-    env->psret = (val & PSR_ET)? 1 : 0;
+    env->psrs = (val & PSR_S) ? 1 : 0;
+    env->psrps = (val & PSR_PS) ? 1 : 0;
+    env->psret = (val & PSR_ET) ? 1 : 0;
     set_cwp(val & PSR_CWP);
 #endif
     env->cc_op = CC_OP_FLAGS;
@@ -1594,7 +1607,7 @@ GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
 #endif
 #undef GEN_FCMPS
 
-#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
+#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) &&   \
     defined(DEBUG_MXCC)
 static void dump_mxcc(CPUState *env)
 {
@@ -1613,13 +1626,12 @@ static void dump_mxcc(CPUState *env)
 }
 #endif
 
-#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
+#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY))     \
     && defined(DEBUG_ASI)
 static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
                      uint64_t r1)
 {
-    switch (size)
-    {
+    switch (size) {
     case 1:
         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
                     addr, asi, r1 & 0xff);
@@ -1764,33 +1776,37 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
             }
             break;
         case 0x01c00a00: /* MXCC control register */
-            if (size == 8)
+            if (size == 8) {
                 ret = env->mxccregs[3];
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             break;
         case 0x01c00a04: /* MXCC control register */
-            if (size == 4)
+            if (size == 4) {
                 ret = env->mxccregs[3];
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             break;
         case 0x01c00c00: /* Module reset register */
             if (size == 8) {
                 ret = env->mxccregs[5];
-                // should we do something here?
-            } else
+                /* should we do something here? */
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             break;
         case 0x01c00f00: /* MBus port address register */
-            if (size == 8)
+            if (size == 8) {
                 ret = env->mxccregs[7];
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             break;
         default:
             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
@@ -1809,10 +1825,11 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
             int mmulev;
 
             mmulev = (addr >> 8) & 15;
-            if (mmulev > 4)
+            if (mmulev > 4) {
                 ret = 0;
-            else
+            } else {
                 ret = mmu_probe(env, addr, mmulev);
+            }
             DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
                         addr, mmulev, ret);
         }
@@ -1822,21 +1839,22 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
             int reg = (addr >> 8) & 0x1f;
 
             ret = env->mmuregs[reg];
-            if (reg == 3) /* Fault status cleared on read */
+            if (reg == 3) { /* Fault status cleared on read */
                 env->mmuregs[3] = 0;
-            else if (reg == 0x13) /* Fault status read */
+            } else if (reg == 0x13) { /* Fault status read */
                 ret = env->mmuregs[3];
-            else if (reg == 0x14) /* Fault address read */
+            } else if (reg == 0x14) { /* Fault address read */
                 ret = env->mmuregs[4];
+            }
             DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
         }
         break;
-    case 5: // Turbosparc ITLB Diagnostic
-    case 6: // Turbosparc DTLB Diagnostic
-    case 7: // Turbosparc IOTLB Diagnostic
+    case 5: /* Turbosparc ITLB Diagnostic */
+    case 6: /* Turbosparc DTLB Diagnostic */
+    case 7: /* Turbosparc IOTLB Diagnostic */
         break;
     case 9: /* Supervisor code access */
-        switch(size) {
+        switch (size) {
         case 1:
             ret = ldub_code(addr);
             break;
@@ -1853,7 +1871,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         }
         break;
     case 0xa: /* User data access */
-        switch(size) {
+        switch (size) {
         case 1:
             ret = ldub_user(addr);
             break;
@@ -1870,7 +1888,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         }
         break;
     case 0xb: /* Supervisor data access */
-        switch(size) {
+        switch (size) {
         case 1:
             ret = ldub_kernel(addr);
             break;
@@ -1892,7 +1910,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     case 0xf: /* D-cache data */
         break;
     case 0x20: /* MMU passthrough */
-        switch(size) {
+        switch (size) {
         case 1:
             ret = ldub_phys(addr);
             break;
@@ -1909,7 +1927,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         }
         break;
     case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
-        switch(size) {
+        switch (size) {
         case 1:
             ret = ldub_phys((target_phys_addr_t)addr
                             | ((target_phys_addr_t)(asi & 0xf) << 32));
@@ -1929,9 +1947,9 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
             break;
         }
         break;
-    case 0x30: // Turbosparc secondary cache diagnostic
-    case 0x31: // Turbosparc RAM snoop
-    case 0x32: // Turbosparc page table descriptor diagnostic
+    case 0x30: /* Turbosparc secondary cache diagnostic */
+    case 0x31: /* Turbosparc RAM snoop */
+    case 0x32: /* Turbosparc page table descriptor diagnostic */
     case 0x39: /* data cache diagnostic register */
         ret = 0;
         break;
@@ -1939,7 +1957,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         {
             int reg = (addr >> 8) & 3;
 
-            switch(reg) {
+            switch (reg) {
             case 0: /* Breakpoint Value (Addr) */
                 ret = env->mmubpregs[reg];
                 break;
@@ -1977,7 +1995,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         break;
     }
     if (sign) {
-        switch(size) {
+        switch (size) {
         case 1:
             ret = (int8_t) ret;
             break;
@@ -2000,7 +2018,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
 void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
 {
     helper_check_align(addr, size - 1);
-    switch(asi) {
+    switch (asi) {
     case 2: /* SuperSparc MXCC registers and Leon3 cache control */
         switch (addr) {
         case 0x00:          /* Leon3 Cache Control */
@@ -2012,39 +2030,44 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
             break;
 
         case 0x01c00000: /* MXCC stream data register 0 */
-            if (size == 8)
+            if (size == 8) {
                 env->mxccdata[0] = val;
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             break;
         case 0x01c00008: /* MXCC stream data register 1 */
-            if (size == 8)
+            if (size == 8) {
                 env->mxccdata[1] = val;
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             break;
         case 0x01c00010: /* MXCC stream data register 2 */
-            if (size == 8)
+            if (size == 8) {
                 env->mxccdata[2] = val;
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             break;
         case 0x01c00018: /* MXCC stream data register 3 */
-            if (size == 8)
+            if (size == 8) {
                 env->mxccdata[3] = val;
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             break;
         case 0x01c00100: /* MXCC stream source */
-            if (size == 8)
+            if (size == 8) {
                 env->mxccregs[0] = val;
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
                                         0);
             env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
@@ -2055,11 +2078,12 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
                                         24);
             break;
         case 0x01c00200: /* MXCC stream destination */
-            if (size == 8)
+            if (size == 8) {
                 env->mxccregs[1] = val;
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,
                      env->mxccdata[0]);
             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,
@@ -2070,34 +2094,38 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
                      env->mxccdata[3]);
             break;
         case 0x01c00a00: /* MXCC control register */
-            if (size == 8)
+            if (size == 8) {
                 env->mxccregs[3] = val;
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             break;
         case 0x01c00a04: /* MXCC control register */
-            if (size == 4)
+            if (size == 4) {
                 env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
                     | val;
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             break;
         case 0x01c00e00: /* MXCC error register  */
-            // writing a 1 bit clears the error
-            if (size == 8)
+            /* writing a 1 bit clears the error */
+            if (size == 8) {
                 env->mxccregs[6] &= ~val;
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             break;
         case 0x01c00f00: /* MBus port address register */
-            if (size == 8)
+            if (size == 8) {
                 env->mxccregs[7] = val;
-            else
+            } else {
                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
                              size);
+            }
             break;
         default:
             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
@@ -2117,13 +2145,13 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
             mmulev = (addr >> 8) & 15;
             DPRINTF_MMU("mmu flush level %d\n", mmulev);
             switch (mmulev) {
-            case 0: // flush page
+            case 0: /* flush page */
                 tlb_flush_page(env, addr & 0xfffff000);
                 break;
-            case 1: // flush segment (256k)
-            case 2: // flush region (16M)
-            case 3: // flush context (4G)
-            case 4: // flush entire
+            case 1: /* flush segment (256k) */
+            case 2: /* flush region (16M) */
+            case 3: /* flush context (4G) */
+            case 4: /* flush entire */
                 tlb_flush(env, 1);
                 break;
             default:
@@ -2140,20 +2168,21 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
             uint32_t oldreg;
 
             oldreg = env->mmuregs[reg];
-            switch(reg) {
-            case 0: // Control Register
+            switch (reg) {
+            case 0: /* Control Register */
                 env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
-                                    (val & 0x00ffffff);
-                // Mappings generated during no-fault mode or MMU
-                // disabled mode are invalid in normal mode
+                    (val & 0x00ffffff);
+                /* Mappings generated during no-fault mode or MMU
+                   disabled mode are invalid in normal mode */
                 if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
-                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
+                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm))) {
                     tlb_flush(env, 1);
+                }
                 break;
-            case 1: // Context Table Pointer Register
+            case 1: /* Context Table Pointer Register */
                 env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
                 break;
-            case 2: // Context Register
+            case 2: /* Context Register */
                 env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
                 if (oldreg != env->mmuregs[reg]) {
                     /* we flush when the MMU context changes because
@@ -2161,16 +2190,17 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
                     tlb_flush(env, 1);
                 }
                 break;
-            case 3: // Synchronous Fault Status Register with Clear
-            case 4: // Synchronous Fault Address Register
+            case 3: /* Synchronous Fault Status Register with Clear */
+            case 4: /* Synchronous Fault Address Register */
                 break;
-            case 0x10: // TLB Replacement Control Register
+            case 0x10: /* TLB Replacement Control Register */
                 env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
                 break;
-            case 0x13: // Synchronous Fault Status Register with Read and Clear
+            case 0x13: /* Synchronous Fault Status Register with Read
+                          and Clear */
                 env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
                 break;
-            case 0x14: // Synchronous Fault Address Register
+            case 0x14: /* Synchronous Fault Address Register */
                 env->mmuregs[4] = val;
                 break;
             default:
@@ -2186,12 +2216,12 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
 #endif
         }
         break;
-    case 5: // Turbosparc ITLB Diagnostic
-    case 6: // Turbosparc DTLB Diagnostic
-    case 7: // Turbosparc IOTLB Diagnostic
+    case 5: /* Turbosparc ITLB Diagnostic */
+    case 6: /* Turbosparc DTLB Diagnostic */
+    case 7: /* Turbosparc IOTLB Diagnostic */
         break;
     case 0xa: /* User data access */
-        switch(size) {
+        switch (size) {
         case 1:
             stb_user(addr, val);
             break;
@@ -2208,7 +2238,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
         }
         break;
     case 0xb: /* Supervisor data access */
-        switch(size) {
+        switch (size) {
         case 1:
             stb_kernel(addr, val);
             break;
@@ -2236,9 +2266,9 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
         break;
     case 0x17: /* Block copy, sta access */
         {
-            // val = src
-            // addr = dst
-            // copy 32 bytes
+            /* val = src
+               addr = dst
+               copy 32 bytes */
             unsigned int i;
             uint32_t src = val & ~3, dst = addr & ~3, temp;
 
@@ -2250,18 +2280,19 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
         break;
     case 0x1f: /* Block fill, stda access */
         {
-            // addr = dst
-            // fill 32 bytes with val
+            /* addr = dst
+               fill 32 bytes with val */
             unsigned int i;
             uint32_t dst = addr & 7;
 
-            for (i = 0; i < 32; i += 8, dst += 8)
+            for (i = 0; i < 32; i += 8, dst += 8) {
                 stq_kernel(dst, val);
+            }
         }
         break;
     case 0x20: /* MMU passthrough */
         {
-            switch(size) {
+            switch (size) {
             case 1:
                 stb_phys(addr, val);
                 break;
@@ -2280,7 +2311,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
         break;
     case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
         {
-            switch(size) {
+            switch (size) {
             case 1:
                 stb_phys((target_phys_addr_t)addr
                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
@@ -2301,11 +2332,11 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
             }
         }
         break;
-    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
-    case 0x31: // store buffer data, Ross RT620 I-cache flush or
-               // Turbosparc snoop RAM
-    case 0x32: // store buffer control or Turbosparc page table
-               // descriptor diagnostic
+    case 0x30: /* store buffer tags or Turbosparc secondary cache diagnostic */
+    case 0x31: /* store buffer data, Ross RT620 I-cache flush or
+                  Turbosparc snoop RAM */
+    case 0x32: /* store buffer control or Turbosparc page table
+                  descriptor diagnostic */
     case 0x36: /* I-cache flash clear */
     case 0x37: /* D-cache flash clear */
         break;
@@ -2313,7 +2344,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
         {
             int reg = (addr >> 8) & 3;
 
-            switch(reg) {
+            switch (reg) {
             case 0: /* Breakpoint Value (Addr) */
                 env->mmubpregs[reg] = (val & 0xfffffffffULL);
                 break;
@@ -2365,26 +2396,27 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     target_ulong last_addr = addr;
 #endif
 
-    if (asi < 0x80)
+    if (asi < 0x80) {
         helper_raise_exception(env, TT_PRIV_ACT);
+    }
 
     helper_check_align(addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
 
     switch (asi) {
-    case 0x82: // Primary no-fault
-    case 0x8a: // Primary no-fault LE
+    case 0x82: /* Primary no-fault */
+    case 0x8a: /* Primary no-fault LE */
         if (page_check_range(addr, size, PAGE_READ) == -1) {
 #ifdef DEBUG_ASI
             dump_asi("read ", last_addr, asi, size, ret);
 #endif
             return 0;
         }
-        // Fall through
-    case 0x80: // Primary
-    case 0x88: // Primary LE
+        /* Fall through */
+    case 0x80: /* Primary */
+    case 0x88: /* Primary LE */
         {
-            switch(size) {
+            switch (size) {
             case 1:
                 ret = ldub_raw(addr);
                 break;
@@ -2401,18 +2433,18 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
             }
         }
         break;
-    case 0x83: // Secondary no-fault
-    case 0x8b: // Secondary no-fault LE
+    case 0x83: /* Secondary no-fault */
+    case 0x8b: /* Secondary no-fault LE */
         if (page_check_range(addr, size, PAGE_READ) == -1) {
 #ifdef DEBUG_ASI
             dump_asi("read ", last_addr, asi, size, ret);
 #endif
             return 0;
         }
-        // Fall through
-    case 0x81: // Secondary
-    case 0x89: // Secondary LE
-        // XXX
+        /* Fall through */
+    case 0x81: /* Secondary */
+    case 0x89: /* Secondary LE */
+        /* XXX */
         break;
     default:
         break;
@@ -2420,11 +2452,11 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
 
     /* Convert from little endian */
     switch (asi) {
-    case 0x88: // Primary LE
-    case 0x89: // Secondary LE
-    case 0x8a: // Primary no-fault LE
-    case 0x8b: // Secondary no-fault LE
-        switch(size) {
+    case 0x88: /* Primary LE */
+    case 0x89: /* Secondary LE */
+    case 0x8a: /* Primary no-fault LE */
+    case 0x8b: /* Secondary no-fault LE */
+        switch (size) {
         case 2:
             ret = bswap16(ret);
             break;
@@ -2443,7 +2475,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
 
     /* Convert to signed number */
     if (sign) {
-        switch(size) {
+        switch (size) {
         case 1:
             ret = (int8_t) ret;
             break;
@@ -2468,17 +2500,18 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
 #ifdef DEBUG_ASI
     dump_asi("write", addr, asi, size, val);
 #endif
-    if (asi < 0x80)
+    if (asi < 0x80) {
         helper_raise_exception(env, TT_PRIV_ACT);
+    }
 
     helper_check_align(addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
 
     /* Convert to little endian */
     switch (asi) {
-    case 0x88: // Primary LE
-    case 0x89: // Secondary LE
-        switch(size) {
+    case 0x88: /* Primary LE */
+    case 0x89: /* Secondary LE */
+        switch (size) {
         case 2:
             val = bswap16(val);
             break;
@@ -2495,11 +2528,11 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
         break;
     }
 
-    switch(asi) {
-    case 0x80: // Primary
-    case 0x88: // Primary LE
+    switch (asi) {
+    case 0x80: /* Primary */
+    case 0x88: /* Primary LE */
         {
-            switch(size) {
+            switch (size) {
             case 1:
                 stb_raw(addr, val);
                 break;
@@ -2516,15 +2549,15 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
             }
         }
         break;
-    case 0x81: // Secondary
-    case 0x89: // Secondary LE
-        // XXX
+    case 0x81: /* Secondary */
+    case 0x89: /* Secondary LE */
+        /* XXX */
         return;
 
-    case 0x82: // Primary no-fault, RO
-    case 0x83: // Secondary no-fault, RO
-    case 0x8a: // Primary no-fault LE, RO
-    case 0x8b: // Secondary no-fault LE, RO
+    case 0x82: /* Primary no-fault, RO */
+    case 0x83: /* Secondary no-fault, RO */
+    case 0x8a: /* Primary no-fault LE, RO */
+    case 0x8b: /* Secondary no-fault LE, RO */
     default:
         do_unassigned_access(addr, 1, 0, 1, size);
         return;
@@ -2545,8 +2578,9 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
         || (cpu_has_hypervisor(env)
             && asi >= 0x30 && asi < 0x80
-            && !(env->hpstate & HS_PRIV)))
+            && !(env->hpstate & HS_PRIV))) {
         helper_raise_exception(env, TT_PRIV_ACT);
+    }
 
     helper_check_align(addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
@@ -2575,19 +2609,19 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     }
 
     switch (asi) {
-    case 0x10: // As if user primary
-    case 0x11: // As if user secondary
-    case 0x18: // As if user primary LE
-    case 0x19: // As if user secondary LE
-    case 0x80: // Primary
-    case 0x81: // Secondary
-    case 0x88: // Primary LE
-    case 0x89: // Secondary LE
-    case 0xe2: // UA2007 Primary block init
-    case 0xe3: // UA2007 Secondary block init
+    case 0x10: /* As if user primary */
+    case 0x11: /* As if user secondary */
+    case 0x18: /* As if user primary LE */
+    case 0x19: /* As if user secondary LE */
+    case 0x80: /* Primary */
+    case 0x81: /* Secondary */
+    case 0x88: /* Primary LE */
+    case 0x89: /* Secondary LE */
+    case 0xe2: /* UA2007 Primary block init */
+    case 0xe3: /* UA2007 Secondary block init */
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
             if (cpu_hypervisor_mode(env)) {
-                switch(size) {
+                switch (size) {
                 case 1:
                     ret = ldub_hypv(addr);
                     break;
@@ -2605,7 +2639,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
             } else {
                 /* secondary space access has lowest asi bit equal to 1 */
                 if (asi & 1) {
-                    switch(size) {
+                    switch (size) {
                     case 1:
                         ret = ldub_kernel_secondary(addr);
                         break;
@@ -2621,7 +2655,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
                         break;
                     }
                 } else {
-                    switch(size) {
+                    switch (size) {
                     case 1:
                         ret = ldub_kernel(addr);
                         break;
@@ -2641,7 +2675,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         } else {
             /* secondary space access has lowest asi bit equal to 1 */
             if (asi & 1) {
-                switch(size) {
+                switch (size) {
                 case 1:
                     ret = ldub_user_secondary(addr);
                     break;
@@ -2657,7 +2691,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
                     break;
                 }
             } else {
-                switch(size) {
+                switch (size) {
                 case 1:
                     ret = ldub_user(addr);
                     break;
@@ -2675,12 +2709,12 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
             }
         }
         break;
-    case 0x14: // Bypass
-    case 0x15: // Bypass, non-cacheable
-    case 0x1c: // Bypass LE
-    case 0x1d: // Bypass, non-cacheable LE
+    case 0x14: /* Bypass */
+    case 0x15: /* Bypass, non-cacheable */
+    case 0x1c: /* Bypass LE */
+    case 0x1d: /* Bypass, non-cacheable LE */
         {
-            switch(size) {
+            switch (size) {
             case 1:
                 ret = ldub_phys(addr);
                 break;
@@ -2697,43 +2731,43 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
             }
             break;
         }
-    case 0x24: // Nucleus quad LDD 128 bit atomic
-    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
-        //  Only ldda allowed
+    case 0x24: /* Nucleus quad LDD 128 bit atomic */
+    case 0x2c: /* Nucleus quad LDD 128 bit atomic LE
+                  Only ldda allowed */
         helper_raise_exception(env, TT_ILL_INSN);
         return 0;
-    case 0x04: // Nucleus
-    case 0x0c: // Nucleus Little Endian (LE)
-    {
-        switch(size) {
-        case 1:
-            ret = ldub_nucleus(addr);
-            break;
-        case 2:
-            ret = lduw_nucleus(addr);
-            break;
-        case 4:
-            ret = ldl_nucleus(addr);
-            break;
-        default:
-        case 8:
-            ret = ldq_nucleus(addr);
+    case 0x04: /* Nucleus */
+    case 0x0c: /* Nucleus Little Endian (LE) */
+        {
+            switch (size) {
+            case 1:
+                ret = ldub_nucleus(addr);
+                break;
+            case 2:
+                ret = lduw_nucleus(addr);
+                break;
+            case 4:
+                ret = ldl_nucleus(addr);
+                break;
+            default:
+            case 8:
+                ret = ldq_nucleus(addr);
+                break;
+            }
             break;
         }
+    case 0x4a: /* UPA config */
+        /* XXX */
         break;
-    }
-    case 0x4a: // UPA config
-        // XXX
-        break;
-    case 0x45: // LSU
+    case 0x45: /* LSU */
         ret = env->lsu;
         break;
-    case 0x50: // I-MMU regs
+    case 0x50: /* I-MMU regs */
         {
             int reg = (addr >> 3) & 0xf;
 
             if (reg == 0) {
-                // I-TSB Tag Target register
+                /* I-TSB Tag Target register */
                 ret = ultrasparc_tag_target(env->immu.tag_access);
             } else {
                 ret = env->immuregs[reg];
@@ -2741,102 +2775,102 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
 
             break;
         }
-    case 0x51: // I-MMU 8k TSB pointer
+    case 0x51: /* I-MMU 8k TSB pointer */
         {
-            // env->immuregs[5] holds I-MMU TSB register value
-            // env->immuregs[6] holds I-MMU Tag Access register value
+            /* env->immuregs[5] holds I-MMU TSB register value
+               env->immuregs[6] holds I-MMU Tag Access register value */
             ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
                                          8*1024);
             break;
         }
-    case 0x52: // I-MMU 64k TSB pointer
+    case 0x52: /* I-MMU 64k TSB pointer */
         {
-            // env->immuregs[5] holds I-MMU TSB register value
-            // env->immuregs[6] holds I-MMU Tag Access register value
+            /* env->immuregs[5] holds I-MMU TSB register value
+               env->immuregs[6] holds I-MMU Tag Access register value */
             ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
                                          64*1024);
             break;
         }
-    case 0x55: // I-MMU data access
+    case 0x55: /* I-MMU data access */
         {
             int reg = (addr >> 3) & 0x3f;
 
             ret = env->itlb[reg].tte;
             break;
         }
-    case 0x56: // I-MMU tag read
+    case 0x56: /* I-MMU tag read */
         {
             int reg = (addr >> 3) & 0x3f;
 
             ret = env->itlb[reg].tag;
             break;
         }
-    case 0x58: // D-MMU regs
+    case 0x58: /* D-MMU regs */
         {
             int reg = (addr >> 3) & 0xf;
 
             if (reg == 0) {
-                // D-TSB Tag Target register
+                /* D-TSB Tag Target register */
                 ret = ultrasparc_tag_target(env->dmmu.tag_access);
             } else {
                 ret = env->dmmuregs[reg];
             }
             break;
         }
-    case 0x59: // D-MMU 8k TSB pointer
+    case 0x59: /* D-MMU 8k TSB pointer */
         {
-            // env->dmmuregs[5] holds D-MMU TSB register value
-            // env->dmmuregs[6] holds D-MMU Tag Access register value
+            /* env->dmmuregs[5] holds D-MMU TSB register value
+               env->dmmuregs[6] holds D-MMU Tag Access register value */
             ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
                                          8*1024);
             break;
         }
-    case 0x5a: // D-MMU 64k TSB pointer
+    case 0x5a: /* D-MMU 64k TSB pointer */
         {
-            // env->dmmuregs[5] holds D-MMU TSB register value
-            // env->dmmuregs[6] holds D-MMU Tag Access register value
+            /* env->dmmuregs[5] holds D-MMU TSB register value
+               env->dmmuregs[6] holds D-MMU Tag Access register value */
             ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
                                          64*1024);
             break;
         }
-    case 0x5d: // D-MMU data access
+    case 0x5d: /* D-MMU data access */
         {
             int reg = (addr >> 3) & 0x3f;
 
             ret = env->dtlb[reg].tte;
             break;
         }
-    case 0x5e: // D-MMU tag read
+    case 0x5e: /* D-MMU tag read */
         {
             int reg = (addr >> 3) & 0x3f;
 
             ret = env->dtlb[reg].tag;
             break;
         }
-    case 0x46: // D-cache data
-    case 0x47: // D-cache tag access
-    case 0x4b: // E-cache error enable
-    case 0x4c: // E-cache asynchronous fault status
-    case 0x4d: // E-cache asynchronous fault address
-    case 0x4e: // E-cache tag data
-    case 0x66: // I-cache instruction access
-    case 0x67: // I-cache tag access
-    case 0x6e: // I-cache predecode
-    case 0x6f: // I-cache LRU etc.
-    case 0x76: // E-cache tag
-    case 0x7e: // E-cache tag
+    case 0x46: /* D-cache data */
+    case 0x47: /* D-cache tag access */
+    case 0x4b: /* E-cache error enable */
+    case 0x4c: /* E-cache asynchronous fault status */
+    case 0x4d: /* E-cache asynchronous fault address */
+    case 0x4e: /* E-cache tag data */
+    case 0x66: /* I-cache instruction access */
+    case 0x67: /* I-cache tag access */
+    case 0x6e: /* I-cache predecode */
+    case 0x6f: /* I-cache LRU etc. */
+    case 0x76: /* E-cache tag */
+    case 0x7e: /* E-cache tag */
         break;
-    case 0x5b: // D-MMU data pointer
-    case 0x48: // Interrupt dispatch, RO
-    case 0x49: // Interrupt data receive
-    case 0x7f: // Incoming interrupt vector, RO
-        // XXX
+    case 0x5b: /* D-MMU data pointer */
+    case 0x48: /* Interrupt dispatch, RO */
+    case 0x49: /* Interrupt data receive */
+    case 0x7f: /* Incoming interrupt vector, RO */
+        /* XXX */
         break;
-    case 0x54: // I-MMU data in, WO
-    case 0x57: // I-MMU demap, WO
-    case 0x5c: // D-MMU data in, WO
-    case 0x5f: // D-MMU demap, WO
-    case 0x77: // Interrupt vector, WO
+    case 0x54: /* I-MMU data in, WO */
+    case 0x57: /* I-MMU demap, WO */
+    case 0x5c: /* D-MMU data in, WO */
+    case 0x5f: /* D-MMU demap, WO */
+    case 0x77: /* Interrupt vector, WO */
     default:
         do_unassigned_access(addr, 0, 0, 1, size);
         ret = 0;
@@ -2845,13 +2879,13 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
 
     /* Convert from little endian */
     switch (asi) {
-    case 0x0c: // Nucleus Little Endian (LE)
-    case 0x18: // As if user primary LE
-    case 0x19: // As if user secondary LE
-    case 0x1c: // Bypass LE
-    case 0x1d: // Bypass, non-cacheable LE
-    case 0x88: // Primary LE
-    case 0x89: // Secondary LE
+    case 0x0c: /* Nucleus Little Endian (LE) */
+    case 0x18: /* As if user primary LE */
+    case 0x19: /* As if user secondary LE */
+    case 0x1c: /* Bypass LE */
+    case 0x1d: /* Bypass, non-cacheable LE */
+    case 0x88: /* Primary LE */
+    case 0x89: /* Secondary LE */
         switch(size) {
         case 2:
             ret = bswap16(ret);
@@ -2871,7 +2905,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
 
     /* Convert to signed number */
     if (sign) {
-        switch(size) {
+        switch (size) {
         case 1:
             ret = (int8_t) ret;
             break;
@@ -2902,22 +2936,23 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
         || (cpu_has_hypervisor(env)
             && asi >= 0x30 && asi < 0x80
-            && !(env->hpstate & HS_PRIV)))
+            && !(env->hpstate & HS_PRIV))) {
         helper_raise_exception(env, TT_PRIV_ACT);
+    }
 
     helper_check_align(addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
 
     /* Convert to little endian */
     switch (asi) {
-    case 0x0c: // Nucleus Little Endian (LE)
-    case 0x18: // As if user primary LE
-    case 0x19: // As if user secondary LE
-    case 0x1c: // Bypass LE
-    case 0x1d: // Bypass, non-cacheable LE
-    case 0x88: // Primary LE
-    case 0x89: // Secondary LE
-        switch(size) {
+    case 0x0c: /* Nucleus Little Endian (LE) */
+    case 0x18: /* As if user primary LE */
+    case 0x19: /* As if user secondary LE */
+    case 0x1c: /* Bypass LE */
+    case 0x1d: /* Bypass, non-cacheable LE */
+    case 0x88: /* Primary LE */
+    case 0x89: /* Secondary LE */
+        switch (size) {
         case 2:
             val = bswap16(val);
             break;
@@ -2934,20 +2969,20 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
         break;
     }
 
-    switch(asi) {
-    case 0x10: // As if user primary
-    case 0x11: // As if user secondary
-    case 0x18: // As if user primary LE
-    case 0x19: // As if user secondary LE
-    case 0x80: // Primary
-    case 0x81: // Secondary
-    case 0x88: // Primary LE
-    case 0x89: // Secondary LE
-    case 0xe2: // UA2007 Primary block init
-    case 0xe3: // UA2007 Secondary block init
+    switch (asi) {
+    case 0x10: /* As if user primary */
+    case 0x11: /* As if user secondary */
+    case 0x18: /* As if user primary LE */
+    case 0x19: /* As if user secondary LE */
+    case 0x80: /* Primary */
+    case 0x81: /* Secondary */
+    case 0x88: /* Primary LE */
+    case 0x89: /* Secondary LE */
+    case 0xe2: /* UA2007 Primary block init */
+    case 0xe3: /* UA2007 Secondary block init */
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
             if (cpu_hypervisor_mode(env)) {
-                switch(size) {
+                switch (size) {
                 case 1:
                     stb_hypv(addr, val);
                     break;
@@ -2965,7 +3000,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
             } else {
                 /* secondary space access has lowest asi bit equal to 1 */
                 if (asi & 1) {
-                    switch(size) {
+                    switch (size) {
                     case 1:
                         stb_kernel_secondary(addr, val);
                         break;
@@ -2981,7 +3016,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
                         break;
                     }
                 } else {
-                    switch(size) {
+                    switch (size) {
                     case 1:
                         stb_kernel(addr, val);
                         break;
@@ -3001,7 +3036,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
         } else {
             /* secondary space access has lowest asi bit equal to 1 */
             if (asi & 1) {
-                switch(size) {
+                switch (size) {
                 case 1:
                     stb_user_secondary(addr, val);
                     break;
@@ -3017,7 +3052,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
                     break;
                 }
             } else {
-                switch(size) {
+                switch (size) {
                 case 1:
                     stb_user(addr, val);
                     break;
@@ -3035,12 +3070,12 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
             }
         }
         break;
-    case 0x14: // Bypass
-    case 0x15: // Bypass, non-cacheable
-    case 0x1c: // Bypass LE
-    case 0x1d: // Bypass, non-cacheable LE
+    case 0x14: /* Bypass */
+    case 0x15: /* Bypass, non-cacheable */
+    case 0x1c: /* Bypass LE */
+    case 0x1d: /* Bypass, non-cacheable LE */
         {
-            switch(size) {
+            switch (size) {
             case 1:
                 stb_phys(addr, val);
                 break;
@@ -3057,43 +3092,43 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
             }
         }
         return;
-    case 0x24: // Nucleus quad LDD 128 bit atomic
-    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
-        //  Only ldda allowed
+    case 0x24: /* Nucleus quad LDD 128 bit atomic */
+    case 0x2c: /* Nucleus quad LDD 128 bit atomic LE
+                  Only ldda allowed */
         helper_raise_exception(env, TT_ILL_INSN);
         return;
-    case 0x04: // Nucleus
-    case 0x0c: // Nucleus Little Endian (LE)
-    {
-        switch(size) {
-        case 1:
-            stb_nucleus(addr, val);
-            break;
-        case 2:
-            stw_nucleus(addr, val);
-            break;
-        case 4:
-            stl_nucleus(addr, val);
-            break;
-        default:
-        case 8:
-            stq_nucleus(addr, val);
+    case 0x04: /* Nucleus */
+    case 0x0c: /* Nucleus Little Endian (LE) */
+        {
+            switch (size) {
+            case 1:
+                stb_nucleus(addr, val);
+                break;
+            case 2:
+                stw_nucleus(addr, val);
+                break;
+            case 4:
+                stl_nucleus(addr, val);
+                break;
+            default:
+            case 8:
+                stq_nucleus(addr, val);
+                break;
+            }
             break;
         }
-        break;
-    }
 
-    case 0x4a: // UPA config
-        // XXX
+    case 0x4a: /* UPA config */
+        /* XXX */
         return;
-    case 0x45: // LSU
+    case 0x45: /* LSU */
         {
             uint64_t oldreg;
 
             oldreg = env->lsu;
             env->lsu = val & (DMMU_E | IMMU_E);
-            // Mappings generated during D/I MMU disabled mode are
-            // invalid in normal mode
+            /* Mappings generated during D/I MMU disabled mode are
+               invalid in normal mode */
             if (oldreg != env->lsu) {
                 DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
                             oldreg, env->lsu);
@@ -3104,31 +3139,32 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
             }
             return;
         }
-    case 0x50: // I-MMU regs
+    case 0x50: /* I-MMU regs */
         {
             int reg = (addr >> 3) & 0xf;
             uint64_t oldreg;
 
             oldreg = env->immuregs[reg];
-            switch(reg) {
-            case 0: // RO
+            switch (reg) {
+            case 0: /* RO */
                 return;
-            case 1: // Not in I-MMU
+            case 1: /* Not in I-MMU */
             case 2:
                 return;
-            case 3: // SFSR
-                if ((val & 1) == 0)
-                    val = 0; // Clear SFSR
+            case 3: /* SFSR */
+                if ((val & 1) == 0) {
+                    val = 0; /* Clear SFSR */
+                }
                 env->immu.sfsr = val;
                 break;
-            case 4: // RO
+            case 4: /* RO */
                 return;
-            case 5: // TSB access
+            case 5: /* TSB access */
                 DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016"
                             PRIx64 "\n", env->immu.tsb, val);
                 env->immu.tsb = val;
                 break;
-            case 6: // Tag access
+            case 6: /* Tag access */
                 env->immu.tag_access = val;
                 break;
             case 7:
@@ -3147,12 +3183,12 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
 #endif
             return;
         }
-    case 0x54: // I-MMU data in
+    case 0x54: /* I-MMU data in */
         replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
         return;
-    case 0x55: // I-MMU data access
+    case 0x55: /* I-MMU data access */
         {
-            // TODO: auto demap
+            /* TODO: auto demap */
 
             unsigned int i = (addr >> 3) & 0x3f;
 
@@ -3164,48 +3200,48 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
 #endif
             return;
         }
-    case 0x57: // I-MMU demap
+    case 0x57: /* I-MMU demap */
         demap_tlb(env->itlb, addr, "immu", env);
         return;
-    case 0x58: // D-MMU regs
+    case 0x58: /* D-MMU regs */
         {
             int reg = (addr >> 3) & 0xf;
             uint64_t oldreg;
 
             oldreg = env->dmmuregs[reg];
-            switch(reg) {
-            case 0: // RO
+            switch (reg) {
+            case 0: /* RO */
             case 4:
                 return;
-            case 3: // SFSR
+            case 3: /* SFSR */
                 if ((val & 1) == 0) {
-                    val = 0; // Clear SFSR, Fault address
+                    val = 0; /* Clear SFSR, Fault address */
                     env->dmmu.sfar = 0;
                 }
                 env->dmmu.sfsr = val;
                 break;
-            case 1: // Primary context
+            case 1: /* Primary context */
                 env->dmmu.mmu_primary_context = val;
                 /* can be optimized to only flush MMU_USER_IDX
                    and MMU_KERNEL_IDX entries */
                 tlb_flush(env, 1);
                 break;
-            case 2: // Secondary context
+            case 2: /* Secondary context */
                 env->dmmu.mmu_secondary_context = val;
                 /* can be optimized to only flush MMU_USER_SECONDARY_IDX
                    and MMU_KERNEL_SECONDARY_IDX entries */
                 tlb_flush(env, 1);
                 break;
-            case 5: // TSB access
+            case 5: /* TSB access */
                 DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
                             PRIx64 "\n", env->dmmu.tsb, val);
                 env->dmmu.tsb = val;
                 break;
-            case 6: // Tag access
+            case 6: /* Tag access */
                 env->dmmu.tag_access = val;
                 break;
-            case 7: // Virtual Watchpoint
-            case 8: // Physical Watchpoint
+            case 7: /* Virtual Watchpoint */
+            case 8: /* Physical Watchpoint */
             default:
                 env->dmmuregs[reg] = val;
                 break;
@@ -3220,10 +3256,10 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
 #endif
             return;
         }
-    case 0x5c: // D-MMU data in
+    case 0x5c: /* D-MMU data in */
         replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
         return;
-    case 0x5d: // D-MMU data access
+    case 0x5d: /* D-MMU data access */
         {
             unsigned int i = (addr >> 3) & 0x3f;
 
@@ -3235,38 +3271,38 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
 #endif
             return;
         }
-    case 0x5f: // D-MMU demap
+    case 0x5f: /* D-MMU demap */
         demap_tlb(env->dtlb, addr, "dmmu", env);
         return;
-    case 0x49: // Interrupt data receive
-        // XXX
+    case 0x49: /* Interrupt data receive */
+        /* XXX */
         return;
-    case 0x46: // D-cache data
-    case 0x47: // D-cache tag access
-    case 0x4b: // E-cache error enable
-    case 0x4c: // E-cache asynchronous fault status
-    case 0x4d: // E-cache asynchronous fault address
-    case 0x4e: // E-cache tag data
-    case 0x66: // I-cache instruction access
-    case 0x67: // I-cache tag access
-    case 0x6e: // I-cache predecode
-    case 0x6f: // I-cache LRU etc.
-    case 0x76: // E-cache tag
-    case 0x7e: // E-cache tag
+    case 0x46: /* D-cache data */
+    case 0x47: /* D-cache tag access */
+    case 0x4b: /* E-cache error enable */
+    case 0x4c: /* E-cache asynchronous fault status */
+    case 0x4d: /* E-cache asynchronous fault address */
+    case 0x4e: /* E-cache tag data */
+    case 0x66: /* I-cache instruction access */
+    case 0x67: /* I-cache tag access */
+    case 0x6e: /* I-cache predecode */
+    case 0x6f: /* I-cache LRU etc. */
+    case 0x76: /* E-cache tag */
+    case 0x7e: /* E-cache tag */
         return;
-    case 0x51: // I-MMU 8k TSB pointer, RO
-    case 0x52: // I-MMU 64k TSB pointer, RO
-    case 0x56: // I-MMU tag read, RO
-    case 0x59: // D-MMU 8k TSB pointer, RO
-    case 0x5a: // D-MMU 64k TSB pointer, RO
-    case 0x5b: // D-MMU data pointer, RO
-    case 0x5e: // D-MMU tag read, RO
-    case 0x48: // Interrupt dispatch, RO
-    case 0x7f: // Incoming interrupt vector, RO
-    case 0x82: // Primary no-fault, RO
-    case 0x83: // Secondary no-fault, RO
-    case 0x8a: // Primary no-fault LE, RO
-    case 0x8b: // Secondary no-fault LE, RO
+    case 0x51: /* I-MMU 8k TSB pointer, RO */
+    case 0x52: /* I-MMU 64k TSB pointer, RO */
+    case 0x56: /* I-MMU tag read, RO */
+    case 0x59: /* D-MMU 8k TSB pointer, RO */
+    case 0x5a: /* D-MMU 64k TSB pointer, RO */
+    case 0x5b: /* D-MMU data pointer, RO */
+    case 0x5e: /* D-MMU tag read, RO */
+    case 0x48: /* Interrupt dispatch, RO */
+    case 0x7f: /* Incoming interrupt vector, RO */
+    case 0x82: /* Primary no-fault, RO */
+    case 0x83: /* Secondary no-fault, RO */
+    case 0x8a: /* Primary no-fault LE, RO */
+    case 0x8b: /* Secondary no-fault LE, RO */
     default:
         do_unassigned_access(addr, 1, 0, 1, size);
         return;
@@ -3279,20 +3315,22 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
         || (cpu_has_hypervisor(env)
             && asi >= 0x30 && asi < 0x80
-            && !(env->hpstate & HS_PRIV)))
+            && !(env->hpstate & HS_PRIV))) {
         helper_raise_exception(env, TT_PRIV_ACT);
+    }
 
     addr = asi_address_mask(env, asi, addr);
 
     switch (asi) {
 #if !defined(CONFIG_USER_ONLY)
-    case 0x24: // Nucleus quad LDD 128 bit atomic
-    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
+    case 0x24: /* Nucleus quad LDD 128 bit atomic */
+    case 0x2c: /* Nucleus quad LDD 128 bit atomic LE */
         helper_check_align(addr, 0xf);
         if (rd == 0) {
             env->gregs[1] = ldq_nucleus(addr + 8);
-            if (asi == 0x2c)
+            if (asi == 0x2c) {
                 bswap64s(&env->gregs[1]);
+            }
         } else if (rd < 8) {
             env->gregs[rd] = ldq_nucleus(addr);
             env->gregs[rd + 1] = ldq_nucleus(addr + 8);
@@ -3312,9 +3350,9 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
 #endif
     default:
         helper_check_align(addr, 0x3);
-        if (rd == 0)
+        if (rd == 0) {
             env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
-        else if (rd < 8) {
+        } else if (rd < 8) {
             env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
             env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
         } else {
@@ -3374,7 +3412,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
         break;
     }
 
-    switch(size) {
+    switch (size) {
     default:
     case 4:
         *((uint32_t *)&env->fpr[rd]) = helper_ld_asi(addr, asi, size, 0);
@@ -3447,7 +3485,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
         break;
     }
 
-    switch(size) {
+    switch (size) {
     default:
     case 4:
         helper_st_asi(addr, *(uint32_t *)&env->fpr[rd], asi, size);
@@ -3476,8 +3514,9 @@ target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
     val2 &= 0xffffffffUL;
     ret = helper_ld_asi(addr, asi, 4, 0);
     ret &= 0xffffffffUL;
-    if (val2 == ret)
+    if (val2 == ret) {
         helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
+    }
     return ret;
 }
 
@@ -3487,8 +3526,9 @@ target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
     target_ulong ret;
 
     ret = helper_ld_asi(addr, asi, 8, 0);
-    if (val2 == ret)
+    if (val2 == ret) {
         helper_st_asi(addr, val1, asi, 8);
+    }
     return ret;
 }
 #endif /* TARGET_SPARC64 */
@@ -3498,8 +3538,9 @@ void helper_rett(void)
 {
     unsigned int cwp;
 
-    if (env->psret == 1)
+    if (env->psret == 1) {
         helper_raise_exception(env, TT_ILL_INSN);
+    }
 
     env->psret = 1;
     cwp = cwp_inc(env->cwp + 1) ;
@@ -3563,7 +3604,7 @@ static target_ulong helper_sdiv_common(target_ulong a, target_ulong b, int cc)
 
     x0 = x0 / x1;
     if ((int32_t) x0 != x0) {
-        x0 = x0 < 0 ? 0x80000000: 0x7fffffff;
+        x0 = x0 < 0 ? 0x80000000 : 0x7fffffff;
         overflow = 1;
     }
 
@@ -3637,7 +3678,7 @@ void helper_lddf(target_ulong addr, int mem_idx)
 
 void helper_ldqf(target_ulong addr, int mem_idx)
 {
-    // XXX add 128 bit load
+    /* XXX add 128 bit load */
     CPU_QuadU u;
 
     helper_check_align(addr, 7);
@@ -3673,7 +3714,7 @@ void helper_ldqf(target_ulong addr, int mem_idx)
 
 void helper_stqf(target_ulong addr, int mem_idx)
 {
-    // XXX add 128 bit store
+    /* XXX add 128 bit store */
     CPU_QuadU u;
 
     helper_check_align(addr, 7);
@@ -3797,7 +3838,7 @@ void helper_save(void)
                                                 ((env->wstate & 0x7) << 2)));
     } else {
         if (env->cleanwin - env->canrestore == 0) {
-            // XXX Clean windows without trap
+            /* XXX Clean windows without trap */
             helper_raise_exception(env, TT_CLRWIN);
         } else {
             env->cansave--;
@@ -3837,21 +3878,24 @@ void helper_flushw(void)
 void helper_saved(void)
 {
     env->cansave++;
-    if (env->otherwin == 0)
+    if (env->otherwin == 0) {
         env->canrestore--;
-    else
+    } else {
         env->otherwin--;
+    }
 }
 
 void helper_restored(void)
 {
     env->canrestore++;
-    if (env->cleanwin < env->nwindows - 1)
+    if (env->cleanwin < env->nwindows - 1) {
         env->cleanwin++;
-    if (env->otherwin == 0)
+    }
+    if (env->otherwin == 0) {
         env->cansave--;
-    else
+    } else {
         env->otherwin--;
+    }
 }
 
 static target_ulong get_ccr(void)
@@ -3937,8 +3981,8 @@ void helper_wrccr(target_ulong new_ccr)
     put_ccr(new_ccr);
 }
 
-// CWP handling is reversed in V9, but we still use the V8 register
-// order.
+/* CWP handling is reversed in V9, but we still use the V8 register
+   order. */
 target_ulong helper_rdcwp(void)
 {
     return get_cwp64();
@@ -3949,11 +3993,11 @@ void helper_wrcwp(target_ulong new_cwp)
     put_cwp64(new_cwp);
 }
 
-// This function uses non-native bit order
+/* This function uses non-native bit order */
 #define GET_FIELD(X, FROM, TO)                                  \
     ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
 
-// This function uses the order in the manuals, i.e. bit 0 is 2^0
+/* This function uses the order in the manuals, i.e. bit 0 is 2^0 */
 #define GET_FIELD_SP(X, FROM, TO)               \
     GET_FIELD(X, 63 - (TO), 63 - (FROM))
 
@@ -3985,10 +4029,10 @@ static inline uint64_t *get_gregset(uint32_t pstate)
     switch (pstate) {
     default:
         DPRINTF_PSTATE("ERROR in get_gregset: active pstate bits=%x%s%s%s\n",
-                pstate,
-                (pstate & PS_IG) ? " IG" : "",
-                (pstate & PS_MG) ? " MG" : "",
-                (pstate & PS_AG) ? " AG" : "");
+                       pstate,
+                       (pstate & PS_IG) ? " IG" : "",
+                       (pstate & PS_MG) ? " MG" : "",
+                       (pstate & PS_AG) ? " AG" : "");
         /* pass through to normal set of global registers */
     case 0:
         return env->bgregs;
@@ -4007,7 +4051,7 @@ static inline void change_pstate(uint32_t new_pstate)
     uint64_t *src, *dst;
 
     if (env->def->features & CPU_FEATURE_GL) {
-        // PS_AG is not implemented in this case
+        /* PS_AG is not implemented in this case */
         new_pstate &= ~PS_AG;
     }
 
@@ -4017,13 +4061,12 @@ static inline void change_pstate(uint32_t new_pstate)
     if (new_pstate_regs != pstate_regs) {
         DPRINTF_PSTATE("change_pstate: switching regs old=%x new=%x\n",
                        pstate_regs, new_pstate_regs);
-        // Switch global register bank
+        /* Switch global register bank */
         src = get_gregset(new_pstate_regs);
         dst = get_gregset(pstate_regs);
         memcpy32(dst, env->gregs);
         memcpy32(env->gregs, src);
-    }
-    else {
+    } else {
         DPRINTF_PSTATE("change_pstate: regs new=%x (unchanged)\n",
                        new_pstate_regs);
     }
@@ -4067,7 +4110,7 @@ void helper_wrpil(target_ulong new_pil)
 
 void helper_done(void)
 {
-    trap_state* tsptr = cpu_tsptr(env);
+    trap_state *tsptr = cpu_tsptr(env);
 
     env->pc = tsptr->tnpc;
     env->npc = tsptr->tnpc + 4;
@@ -4088,7 +4131,7 @@ void helper_done(void)
 
 void helper_retry(void)
 {
-    trap_state* tsptr = cpu_tsptr(env);
+    trap_state *tsptr = cpu_tsptr(env);
 
     env->pc = tsptr->tpc;
     env->npc = tsptr->tnpc;
@@ -4107,7 +4150,7 @@ void helper_retry(void)
 #endif
 }
 
-static void do_modify_softint(const char* operation, uint32_t value)
+static void do_modify_softint(const char *operation, uint32_t value)
 {
     if (env->softint != value) {
         env->softint = value;
@@ -4216,29 +4259,34 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
     int fault_type;
 
 #ifdef DEBUG_UNASSIGNED
-    if (is_asi)
+    if (is_asi) {
         printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
                " asi 0x%02x from " TARGET_FMT_lx "\n",
                is_exec ? "exec" : is_write ? "write" : "read", size,
                size == 1 ? "" : "s", addr, is_asi, env->pc);
-    else
+    } else {
         printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
                " from " TARGET_FMT_lx "\n",
                is_exec ? "exec" : is_write ? "write" : "read", size,
                size == 1 ? "" : "s", addr, env->pc);
+    }
 #endif
     /* Don't overwrite translation and access faults */
     fault_type = (env->mmuregs[3] & 0x1c) >> 2;
     if ((fault_type > 4) || (fault_type == 0)) {
         env->mmuregs[3] = 0; /* Fault status register */
-        if (is_asi)
+        if (is_asi) {
             env->mmuregs[3] |= 1 << 16;
-        if (env->psrs)
+        }
+        if (env->psrs) {
             env->mmuregs[3] |= 1 << 5;
-        if (is_exec)
+        }
+        if (is_exec) {
             env->mmuregs[3] |= 1 << 6;
-        if (is_write)
+        }
+        if (is_write) {
             env->mmuregs[3] |= 1 << 7;
+        }
         env->mmuregs[3] |= (5 << 2) | 2;
         /* SuperSPARC will never place instruction fault addresses in the FAR */
         if (!is_exec) {
@@ -4251,10 +4299,11 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
     }
 
     if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
-        if (is_exec)
+        if (is_exec) {
             helper_raise_exception(env, TT_CODE_ACCESS);
-        else
+        } else {
             helper_raise_exception(env, TT_DATA_ACCESS);
+        }
     }
 
     /* flush neverland mappings created during no-fault mode,
@@ -4267,7 +4316,7 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
 #else
 #if defined(CONFIG_USER_ONLY)
 static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
-                          int is_asi, int size)
+                                 int is_asi, int size)
 #else
 static void do_unassigned_access(target_phys_addr_t addr, int is_write,
                                  int is_exec, int is_asi, int size)
@@ -4278,10 +4327,11 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
            "\n", addr, env->pc);
 #endif
 
-    if (is_exec)
+    if (is_exec) {
         helper_raise_exception(env, TT_CODE_ACCESS);
-    else
+    } else {
         helper_raise_exception(env, TT_DATA_ACCESS);
+    }
 }
 #endif
 
commit bc2653195a98ffdf44372c5ea655d5c05ea714b8
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Jul 3 08:19:42 2011 +0000

    Sparc: avoid AREG0 for raise_exception and helper_debug
    
    Make raise_exception() and helper_debug() take a parameter for
    CPUState instead of relying on global env. Move the functions
    to helper.c.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index e9182ac..7a25605 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -871,6 +871,18 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 #endif
 
 /* misc op helpers */
+void helper_raise_exception(CPUState *env, int tt)
+{
+    env->exception_index = tt;
+    cpu_loop_exit(env);
+}
+
+void helper_debug(CPUState *env)
+{
+    env->exception_index = EXCP_DEBUG;
+    cpu_loop_exit(env);
+}
+
 void helper_shutdown(void)
 {
 #if !defined(CONFIG_USER_ONLY)
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 2d36af3..a452666 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -32,7 +32,7 @@ DEF_HELPER_1(tick_get_count, i64, ptr)
 DEF_HELPER_2(tick_set_limit, void, ptr, i64)
 #endif
 DEF_HELPER_2(check_align, void, tl, i32)
-DEF_HELPER_0(debug, void)
+DEF_HELPER_1(debug, void, env)
 DEF_HELPER_0(save, void)
 DEF_HELPER_0(restore, void)
 DEF_HELPER_2(udiv, tl, tl, tl)
@@ -83,7 +83,7 @@ DEF_HELPER_0(fcmpeq_fcc1, void)
 DEF_HELPER_0(fcmpeq_fcc2, void)
 DEF_HELPER_0(fcmpeq_fcc3, void)
 #endif
-DEF_HELPER_1(raise_exception, void, int)
+DEF_HELPER_2(raise_exception, void, env, int)
 DEF_HELPER_0(shutdown, void)
 #define F_HELPER_0_0(name) DEF_HELPER_0(f ## name, void)
 #define F_HELPER_DQ_0_0(name)                   \
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 9955499..632850c 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -321,17 +321,6 @@ static inline target_ulong asi_address_mask(CPUState *env1,
     }
 }
 
-static void raise_exception(int tt)
-{
-    env->exception_index = tt;
-    cpu_loop_exit(env);
-}
-
-void HELPER(raise_exception)(int tt)
-{
-    raise_exception(tt);
-}
-
 void helper_check_align(target_ulong addr, uint32_t align)
 {
     if (addr & align) {
@@ -339,7 +328,7 @@ void helper_check_align(target_ulong addr, uint32_t align)
     printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
            "\n", addr, env->pc);
 #endif
-        raise_exception(TT_UNALIGNED);
+        helper_raise_exception(env, TT_UNALIGNED);
     }
 }
 
@@ -853,7 +842,7 @@ void helper_check_ieee_exceptions(void)
         if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
             /* Unmasked exception, generate a trap */
             env->fsr |= FSR_FTT_IEEE_EXCP;
-            raise_exception(TT_FP_EXCP);
+            helper_raise_exception(env, TT_FP_EXCP);
         } else {
             /* Accumulate exceptions */
             env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
@@ -907,14 +896,14 @@ void helper_fsqrtq(void)
             (env->fsr & FSR_NVM)) {                                     \
             env->fsr |= FSR_NVC;                                        \
             env->fsr |= FSR_FTT_IEEE_EXCP;                              \
-            raise_exception(TT_FP_EXCP);                                \
+            helper_raise_exception(env, TT_FP_EXCP);                    \
         }                                                               \
         switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
         case float_relation_unordered:                                  \
             if ((env->fsr & FSR_NVM)) {                                 \
                 env->fsr |= FSR_NVC;                                    \
                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
-                raise_exception(TT_FP_EXCP);                            \
+                helper_raise_exception(env, TT_FP_EXCP);                \
             } else {                                                    \
                 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);             \
                 env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                \
@@ -943,14 +932,14 @@ void helper_fsqrtq(void)
             (env->fsr & FSR_NVM)) {                                     \
             env->fsr |= FSR_NVC;                                        \
             env->fsr |= FSR_FTT_IEEE_EXCP;                              \
-            raise_exception(TT_FP_EXCP);                                \
+            helper_raise_exception(env, TT_FP_EXCP);                    \
         }                                                               \
         switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
         case float_relation_unordered:                                  \
             if ((env->fsr & FSR_NVM)) {                                 \
                 env->fsr |= FSR_NVC;                                    \
                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
-                raise_exception(TT_FP_EXCP);                            \
+                helper_raise_exception(env, TT_FP_EXCP);                \
             } else {                                                    \
                 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);             \
                 env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                \
@@ -2377,7 +2366,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
 #endif
 
     if (asi < 0x80)
-        raise_exception(TT_PRIV_ACT);
+        helper_raise_exception(env, TT_PRIV_ACT);
 
     helper_check_align(addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
@@ -2480,7 +2469,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
     dump_asi("write", addr, asi, size, val);
 #endif
     if (asi < 0x80)
-        raise_exception(TT_PRIV_ACT);
+        helper_raise_exception(env, TT_PRIV_ACT);
 
     helper_check_align(addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
@@ -2557,7 +2546,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         || (cpu_has_hypervisor(env)
             && asi >= 0x30 && asi < 0x80
             && !(env->hpstate & HS_PRIV)))
-        raise_exception(TT_PRIV_ACT);
+        helper_raise_exception(env, TT_PRIV_ACT);
 
     helper_check_align(addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
@@ -2578,7 +2567,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
             dump_asi("read ", last_addr, asi, size, ret);
 #endif
             /* env->exception_index is set in get_physical_address_data(). */
-            raise_exception(env->exception_index);
+            helper_raise_exception(env, env->exception_index);
         }
 
         /* convert nonfaulting load ASIs to normal load ASIs */
@@ -2711,7 +2700,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
     case 0x24: // Nucleus quad LDD 128 bit atomic
     case 0x2c: // Nucleus quad LDD 128 bit atomic LE
         //  Only ldda allowed
-        raise_exception(TT_ILL_INSN);
+        helper_raise_exception(env, TT_ILL_INSN);
         return 0;
     case 0x04: // Nucleus
     case 0x0c: // Nucleus Little Endian (LE)
@@ -2914,7 +2903,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
         || (cpu_has_hypervisor(env)
             && asi >= 0x30 && asi < 0x80
             && !(env->hpstate & HS_PRIV)))
-        raise_exception(TT_PRIV_ACT);
+        helper_raise_exception(env, TT_PRIV_ACT);
 
     helper_check_align(addr, size - 1);
     addr = asi_address_mask(env, asi, addr);
@@ -3071,7 +3060,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
     case 0x24: // Nucleus quad LDD 128 bit atomic
     case 0x2c: // Nucleus quad LDD 128 bit atomic LE
         //  Only ldda allowed
-        raise_exception(TT_ILL_INSN);
+        helper_raise_exception(env, TT_ILL_INSN);
         return;
     case 0x04: // Nucleus
     case 0x0c: // Nucleus Little Endian (LE)
@@ -3291,7 +3280,7 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
         || (cpu_has_hypervisor(env)
             && asi >= 0x30 && asi < 0x80
             && !(env->hpstate & HS_PRIV)))
-        raise_exception(TT_PRIV_ACT);
+        helper_raise_exception(env, TT_PRIV_ACT);
 
     addr = asi_address_mask(env, asi, addr);
 
@@ -3350,7 +3339,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
     case 0xf8: /* UA2007/JPS1 Block load primary LE */
     case 0xf9: /* UA2007/JPS1 Block load secondary LE */
         if (rd & 7) {
-            raise_exception(TT_ILL_INSN);
+            helper_raise_exception(env, TT_ILL_INSN);
             return;
         }
         helper_check_align(addr, 0x3f);
@@ -3370,7 +3359,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
     case 0x78: /* JPS1 Block load primary LE, user privilege */
     case 0x79: /* JPS1 Block load secondary LE, user privilege */
         if (rd & 7) {
-            raise_exception(TT_ILL_INSN);
+            helper_raise_exception(env, TT_ILL_INSN);
             return;
         }
         helper_check_align(addr, 0x3f);
@@ -3423,7 +3412,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
     case 0xf8: /* UA2007/JPS1 Block store primary LE */
     case 0xf9: /* UA2007/JPS1 Block store secondary LE */
         if (rd & 7) {
-            raise_exception(TT_ILL_INSN);
+            helper_raise_exception(env, TT_ILL_INSN);
             return;
         }
         helper_check_align(addr, 0x3f);
@@ -3443,7 +3432,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
     case 0x78: /* JPS1 Block load primary LE, user privilege */
     case 0x79: /* JPS1 Block load secondary LE, user privilege */
         if (rd & 7) {
-            raise_exception(TT_ILL_INSN);
+            helper_raise_exception(env, TT_ILL_INSN);
             return;
         }
         helper_check_align(addr, 0x3f);
@@ -3510,12 +3499,12 @@ void helper_rett(void)
     unsigned int cwp;
 
     if (env->psret == 1)
-        raise_exception(TT_ILL_INSN);
+        helper_raise_exception(env, TT_ILL_INSN);
 
     env->psret = 1;
     cwp = cwp_inc(env->cwp + 1) ;
     if (env->wim & (1 << cwp)) {
-        raise_exception(TT_WIN_UNF);
+        helper_raise_exception(env, TT_WIN_UNF);
     }
     set_cwp(cwp);
     env->psrs = env->psrps;
@@ -3532,7 +3521,7 @@ static target_ulong helper_udiv_common(target_ulong a, target_ulong b, int cc)
     x1 = (b & 0xffffffff);
 
     if (x1 == 0) {
-        raise_exception(TT_DIV_ZERO);
+        helper_raise_exception(env, TT_DIV_ZERO);
     }
 
     x0 = x0 / x1;
@@ -3569,7 +3558,7 @@ static target_ulong helper_sdiv_common(target_ulong a, target_ulong b, int cc)
     x1 = (b & 0xffffffff);
 
     if (x1 == 0) {
-        raise_exception(TT_DIV_ZERO);
+        helper_raise_exception(env, TT_DIV_ZERO);
     }
 
     x0 = x0 / x1;
@@ -3754,12 +3743,6 @@ void helper_ldxfsr(uint64_t new_fsr)
 }
 #endif
 
-void helper_debug(void)
-{
-    env->exception_index = EXCP_DEBUG;
-    cpu_loop_exit(env);
-}
-
 #ifndef TARGET_SPARC64
 /* XXX: use another pointer for %iN registers to avoid slow wrapping
    handling ? */
@@ -3769,7 +3752,7 @@ void helper_save(void)
 
     cwp = cwp_dec(env->cwp - 1);
     if (env->wim & (1 << cwp)) {
-        raise_exception(TT_WIN_OVF);
+        helper_raise_exception(env, TT_WIN_OVF);
     }
     set_cwp(cwp);
 }
@@ -3780,7 +3763,7 @@ void helper_restore(void)
 
     cwp = cwp_inc(env->cwp + 1);
     if (env->wim & (1 << cwp)) {
-        raise_exception(TT_WIN_UNF);
+        helper_raise_exception(env, TT_WIN_UNF);
     }
     set_cwp(cwp);
 }
@@ -3788,7 +3771,7 @@ void helper_restore(void)
 void helper_wrpsr(target_ulong new_psr)
 {
     if ((new_psr & PSR_CWP) >= env->nwindows) {
-        raise_exception(TT_ILL_INSN);
+        helper_raise_exception(env, TT_ILL_INSN);
     } else {
         cpu_put_psr(env, new_psr);
     }
@@ -3808,13 +3791,14 @@ void helper_save(void)
 
     cwp = cwp_dec(env->cwp - 1);
     if (env->cansave == 0) {
-        raise_exception(TT_SPILL | (env->otherwin != 0 ?
-                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
-                                    ((env->wstate & 0x7) << 2)));
+        helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ?
+                                                (TT_WOTHER |
+                                                 ((env->wstate & 0x38) >> 1)) :
+                                                ((env->wstate & 0x7) << 2)));
     } else {
         if (env->cleanwin - env->canrestore == 0) {
             // XXX Clean windows without trap
-            raise_exception(TT_CLRWIN);
+            helper_raise_exception(env, TT_CLRWIN);
         } else {
             env->cansave--;
             env->canrestore++;
@@ -3829,9 +3813,10 @@ void helper_restore(void)
 
     cwp = cwp_inc(env->cwp + 1);
     if (env->canrestore == 0) {
-        raise_exception(TT_FILL | (env->otherwin != 0 ?
-                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
-                                   ((env->wstate & 0x7) << 2)));
+        helper_raise_exception(env, TT_FILL | (env->otherwin != 0 ?
+                                               (TT_WOTHER |
+                                                ((env->wstate & 0x38) >> 1)) :
+                                               ((env->wstate & 0x7) << 2)));
     } else {
         env->cansave++;
         env->canrestore--;
@@ -3842,9 +3827,10 @@ void helper_restore(void)
 void helper_flushw(void)
 {
     if (env->cansave != env->nwindows - 2) {
-        raise_exception(TT_SPILL | (env->otherwin != 0 ?
-                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
-                                    ((env->wstate & 0x7) << 2)));
+        helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ?
+                                                (TT_WOTHER |
+                                                 ((env->wstate & 0x38) >> 1)) :
+                                                ((env->wstate & 0x7) << 2)));
     }
 }
 
@@ -4196,7 +4182,7 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
            "\n", addr, env->pc);
 #endif
     cpu_restore_state2(retaddr);
-    raise_exception(TT_UNALIGNED);
+    helper_raise_exception(env, TT_UNALIGNED);
 }
 
 /* try to fill the TLB and return an exception if error. If retaddr is
@@ -4266,9 +4252,9 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
 
     if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
         if (is_exec)
-            raise_exception(TT_CODE_ACCESS);
+            helper_raise_exception(env, TT_CODE_ACCESS);
         else
-            raise_exception(TT_DATA_ACCESS);
+            helper_raise_exception(env, TT_DATA_ACCESS);
     }
 
     /* flush neverland mappings created during no-fault mode,
@@ -4293,9 +4279,9 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
 #endif
 
     if (is_exec)
-        raise_exception(TT_CODE_ACCESS);
+        helper_raise_exception(env, TT_CODE_ACCESS);
     else
-        raise_exception(TT_DATA_ACCESS);
+        helper_raise_exception(env, TT_DATA_ACCESS);
 }
 #endif
 
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index dee67b3..9dd6b34 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -294,7 +294,7 @@ static inline void gen_add_tv(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
     tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
     r_const = tcg_const_i32(TT_TOVF);
-    gen_helper_raise_exception(r_const);
+    gen_helper_raise_exception(cpu_env, r_const);
     tcg_temp_free_i32(r_const);
     gen_set_label(l1);
     tcg_temp_free(r_temp);
@@ -310,7 +310,7 @@ static inline void gen_tag_tv(TCGv src1, TCGv src2)
     tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x3);
     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1);
     r_const = tcg_const_i32(TT_TOVF);
-    gen_helper_raise_exception(r_const);
+    gen_helper_raise_exception(cpu_env, r_const);
     tcg_temp_free_i32(r_const);
     gen_set_label(l1);
 }
@@ -492,7 +492,7 @@ static inline void gen_sub_tv(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
     tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
     r_const = tcg_const_i32(TT_TOVF);
-    gen_helper_raise_exception(r_const);
+    gen_helper_raise_exception(cpu_env, r_const);
     tcg_temp_free_i32(r_const);
     gen_set_label(l1);
     tcg_temp_free(r_temp);
@@ -719,7 +719,7 @@ static inline void gen_trap_ifdivzero_tl(TCGv divisor)
     l1 = gen_new_label();
     tcg_gen_brcondi_tl(TCG_COND_NE, divisor, 0, l1);
     r_const = tcg_const_i32(TT_DIV_ZERO);
-    gen_helper_raise_exception(r_const);
+    gen_helper_raise_exception(cpu_env, r_const);
     tcg_temp_free_i32(r_const);
     gen_set_label(l1);
 }
@@ -1549,7 +1549,7 @@ static inline void gen_op_fpexception_im(int fsr_flags)
     tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK);
     tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags);
     r_const = tcg_const_i32(TT_FP_EXCP);
-    gen_helper_raise_exception(r_const);
+    gen_helper_raise_exception(cpu_env, r_const);
     tcg_temp_free_i32(r_const);
 }
 
@@ -1561,7 +1561,7 @@ static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond)
 
         save_state(dc, r_cond);
         r_const = tcg_const_i32(TT_NFPU_INSN);
-        gen_helper_raise_exception(r_const);
+        gen_helper_raise_exception(cpu_env, r_const);
         tcg_temp_free_i32(r_const);
         dc->is_br = 1;
         return 1;
@@ -2038,7 +2038,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         gen_helper_shutdown();
 
                     } else {
-                        gen_helper_raise_exception(cpu_tmp32);
+                        gen_helper_raise_exception(cpu_env, cpu_tmp32);
                     }
                 } else if (cond != 0) {
                     TCGv r_cond = tcg_temp_new();
@@ -2068,7 +2068,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
                     tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
                     tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
-                    gen_helper_raise_exception(cpu_tmp32);
+                    gen_helper_raise_exception(cpu_env, cpu_tmp32);
 
                     gen_set_label(l1);
                     tcg_temp_free(r_cond);
@@ -4931,7 +4931,7 @@ static void disas_sparc_insn(DisasContext * dc)
 
         save_state(dc, cpu_cond);
         r_const = tcg_const_i32(TT_ILL_INSN);
-        gen_helper_raise_exception(r_const);
+        gen_helper_raise_exception(cpu_env, r_const);
         tcg_temp_free_i32(r_const);
         dc->is_br = 1;
     }
@@ -4942,7 +4942,7 @@ static void disas_sparc_insn(DisasContext * dc)
 
         save_state(dc, cpu_cond);
         r_const = tcg_const_i32(TT_UNIMP_FLUSH);
-        gen_helper_raise_exception(r_const);
+        gen_helper_raise_exception(cpu_env, r_const);
         tcg_temp_free_i32(r_const);
         dc->is_br = 1;
     }
@@ -4954,7 +4954,7 @@ static void disas_sparc_insn(DisasContext * dc)
 
         save_state(dc, cpu_cond);
         r_const = tcg_const_i32(TT_PRIV_INSN);
-        gen_helper_raise_exception(r_const);
+        gen_helper_raise_exception(cpu_env, r_const);
         tcg_temp_free_i32(r_const);
         dc->is_br = 1;
     }
@@ -4979,7 +4979,7 @@ static void disas_sparc_insn(DisasContext * dc)
 
         save_state(dc, cpu_cond);
         r_const = tcg_const_i32(TT_NCP_INSN);
-        gen_helper_raise_exception(r_const);
+        gen_helper_raise_exception(cpu_env, r_const);
         tcg_temp_free(r_const);
         dc->is_br = 1;
     }
@@ -5036,7 +5036,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
                 if (bp->pc == dc->pc) {
                     if (dc->pc != pc_start)
                         save_state(dc, cpu_cond);
-                    gen_helper_debug();
+                    gen_helper_debug(cpu_env);
                     tcg_gen_exit_tb(0);
                     dc->is_br = 1;
                     goto exit_gen_loop;
commit 2336c1f1970a5c5cfd34a1785af646c960b6f43f
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Jul 3 07:05:50 2011 +0000

    Sparc: move trivial functions from op_helper.c
    
    These functions don't need access to CPUState or already pass it,
    so relocating them from op_helper.c to helper.c and int64_helper.c
    is trivial.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 1866f63..e9182ac 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -18,6 +18,9 @@
  */
 
 #include "cpu.h"
+#include "host-utils.h"
+#include "helper.h"
+#include "sysemu.h"
 
 //#define DEBUG_MMU
 
@@ -866,3 +869,41 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
     return phys_addr;
 }
 #endif
+
+/* misc op helpers */
+void helper_shutdown(void)
+{
+#if !defined(CONFIG_USER_ONLY)
+    qemu_system_shutdown_request();
+#endif
+}
+
+#ifdef TARGET_SPARC64
+target_ulong helper_popc(target_ulong val)
+{
+    return ctpop64(val);
+}
+
+void helper_tick_set_count(void *opaque, uint64_t count)
+{
+#if !defined(CONFIG_USER_ONLY)
+    cpu_tick_set_count(opaque, count);
+#endif
+}
+
+uint64_t helper_tick_get_count(void *opaque)
+{
+#if !defined(CONFIG_USER_ONLY)
+    return cpu_tick_get_count(opaque);
+#else
+    return 0;
+#endif
+}
+
+void helper_tick_set_limit(void *opaque, uint64_t limit)
+{
+#if !defined(CONFIG_USER_ONLY)
+    cpu_tick_set_limit(opaque, limit);
+#endif
+}
+#endif
diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c
index c21dc9c..2bb1910 100644
--- a/target-sparc/int64_helper.c
+++ b/target-sparc/int64_helper.c
@@ -157,3 +157,8 @@ void do_interrupt(CPUState *env)
     env->npc = env->pc + 4;
     env->exception_index = -1;
 }
+
+trap_state *cpu_tsptr(CPUState* env)
+{
+    return &env->ts[env->tl & MAXTL_MASK];
+}
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 1102273..9955499 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -1,8 +1,6 @@
 #include "cpu.h"
 #include "dyngen-exec.h"
-#include "host-utils.h"
 #include "helper.h"
-#include "sysemu.h"
 
 #if !defined(CONFIG_USER_ONLY)
 #include "softmmu_exec.h"
@@ -334,13 +332,6 @@ void HELPER(raise_exception)(int tt)
     raise_exception(tt);
 }
 
-void helper_shutdown(void)
-{
-#if !defined(CONFIG_USER_ONLY)
-    qemu_system_shutdown_request();
-#endif
-}
-
 void helper_check_align(target_ulong addr, uint32_t align)
 {
     if (addr & align) {
@@ -4003,11 +3994,6 @@ target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
     return tmp & ~7ULL;
 }
 
-target_ulong helper_popc(target_ulong val)
-{
-    return ctpop64(val);
-}
-
 static inline uint64_t *get_gregset(uint32_t pstate)
 {
     switch (pstate) {
@@ -4164,13 +4150,6 @@ void helper_write_softint(uint64_t value)
 }
 #endif
 
-#ifdef TARGET_SPARC64
-trap_state* cpu_tsptr(CPUState* env)
-{
-    return &env->ts[env->tl & MAXTL_MASK];
-}
-#endif
-
 #if !defined(CONFIG_USER_ONLY)
 
 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
@@ -4320,32 +4299,6 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
 }
 #endif
 
-
-#ifdef TARGET_SPARC64
-void helper_tick_set_count(void *opaque, uint64_t count)
-{
-#if !defined(CONFIG_USER_ONLY)
-    cpu_tick_set_count(opaque, count);
-#endif
-}
-
-uint64_t helper_tick_get_count(void *opaque)
-{
-#if !defined(CONFIG_USER_ONLY)
-    return cpu_tick_get_count(opaque);
-#else
-    return 0;
-#endif
-}
-
-void helper_tick_set_limit(void *opaque, uint64_t limit)
-{
-#if !defined(CONFIG_USER_ONLY)
-    cpu_tick_set_limit(opaque, limit);
-#endif
-}
-#endif
-
 #if !defined(CONFIG_USER_ONLY)
 void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
                            int is_write, int is_exec, int is_asi, int size)
commit ab3b491f2131e12503d165a8ffaef5f3a488eafe
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 11 09:33:40 2011 +0000

    Sparc: split helper.c
    
    Move CPU init to cpu_init.c and interrupt handling to int32_helper.c
    for Sparc32 and int64_helper.c for Sparc64.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 417f23e..26c99ca 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -76,6 +76,11 @@ libobj-y += cpuid.o
 endif
 libobj-$(CONFIG_NEED_MMU) += mmu.o
 libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
+ifeq ($(TARGET_BASE_ARCH), sparc)
+libobj-y += cpu_init.o
+endif
+libobj-$(TARGET_SPARC) += int32_helper.o
+libobj-$(TARGET_SPARC64) += int64_helper.o
 
 libobj-y += disas.o
 
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 19de5ba..c9ab7e4 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -485,10 +485,11 @@ typedef struct CPUSPARCState {
 } CPUSPARCState;
 
 #ifndef NO_CPU_IO_DEFS
-/* helper.c */
+/* cpu_init.c */
 CPUSPARCState *cpu_sparc_init(const char *cpu_model);
 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
 void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf);
+/* helper.c */
 int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw,
                                int mmu_idx);
 #define cpu_handle_mmu_fault cpu_sparc_handle_mmu_fault
diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu_init.c
new file mode 100644
index 0000000..08b72a9
--- /dev/null
+++ b/target-sparc/cpu_init.c
@@ -0,0 +1,848 @@
+/*
+ * Sparc CPU init helpers
+ *
+ *  Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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"
+
+//#define DEBUG_FEATURES
+
+static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
+
+void cpu_reset(CPUSPARCState *env)
+{
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+        log_cpu_state(env, 0);
+    }
+
+    tlb_flush(env, 1);
+    env->cwp = 0;
+#ifndef TARGET_SPARC64
+    env->wim = 1;
+#endif
+    env->regwptr = env->regbase + (env->cwp * 16);
+    CC_OP = CC_OP_FLAGS;
+#if defined(CONFIG_USER_ONLY)
+#ifdef TARGET_SPARC64
+    env->cleanwin = env->nwindows - 2;
+    env->cansave = env->nwindows - 2;
+    env->pstate = PS_RMO | PS_PEF | PS_IE;
+    env->asi = 0x82; /* Primary no-fault */
+#endif
+#else
+#if !defined(TARGET_SPARC64)
+    env->psret = 0;
+    env->psrs = 1;
+    env->psrps = 1;
+#endif
+#ifdef TARGET_SPARC64
+    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
+    env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
+    env->tl = env->maxtl;
+    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
+    env->lsu = 0;
+#else
+    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
+    env->mmuregs[0] |= env->def->mmu_bm;
+#endif
+    env->pc = 0;
+    env->npc = env->pc + 4;
+#endif
+    env->cache_control = 0;
+}
+
+static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
+{
+    sparc_def_t def1, *def = &def1;
+
+    if (cpu_sparc_find_by_name(def, cpu_model) < 0) {
+        return -1;
+    }
+
+    env->def = g_malloc0(sizeof(*def));
+    memcpy(env->def, def, sizeof(*def));
+#if defined(CONFIG_USER_ONLY)
+    if ((env->def->features & CPU_FEATURE_FLOAT)) {
+        env->def->features |= CPU_FEATURE_FLOAT128;
+    }
+#endif
+    env->cpu_model_str = cpu_model;
+    env->version = def->iu_version;
+    env->fsr = def->fpu_version;
+    env->nwindows = def->nwindows;
+#if !defined(TARGET_SPARC64)
+    env->mmuregs[0] |= def->mmu_version;
+    cpu_sparc_set_id(env, 0);
+    env->mxccregs[7] |= def->mxcc_version;
+#else
+    env->mmu_version = def->mmu_version;
+    env->maxtl = def->maxtl;
+    env->version |= def->maxtl << 8;
+    env->version |= def->nwindows - 1;
+#endif
+    return 0;
+}
+
+static void cpu_sparc_close(CPUSPARCState *env)
+{
+    free(env->def);
+    free(env);
+}
+
+CPUSPARCState *cpu_sparc_init(const char *cpu_model)
+{
+    CPUSPARCState *env;
+
+    env = g_malloc0(sizeof(CPUSPARCState));
+    cpu_exec_init(env);
+
+    gen_intermediate_code_init(env);
+
+    if (cpu_sparc_register(env, cpu_model) < 0) {
+        cpu_sparc_close(env);
+        return NULL;
+    }
+    qemu_init_vcpu(env);
+
+    return env;
+}
+
+void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
+{
+#if !defined(TARGET_SPARC64)
+    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
+#endif
+}
+
+static const sparc_def_t sparc_defs[] = {
+#ifdef TARGET_SPARC64
+    {
+        .name = "Fujitsu Sparc64",
+        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 4,
+        .maxtl = 4,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Fujitsu Sparc64 III",
+        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 5,
+        .maxtl = 4,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Fujitsu Sparc64 IV",
+        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Fujitsu Sparc64 V",
+        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI UltraSparc I",
+        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI UltraSparc II",
+        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI UltraSparc IIi",
+        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI UltraSparc IIe",
+        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc III",
+        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc III Cu",
+        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_3,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc IIIi",
+        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc IV",
+        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_4,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc IV+",
+        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
+    },
+    {
+        .name = "Sun UltraSparc IIIi+",
+        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_3,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Sun UltraSparc T1",
+        /* defined in sparc_ifu_fdp.v and ctu.h */
+        .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_sun4v,
+        .nwindows = 8,
+        .maxtl = 6,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
+        | CPU_FEATURE_GL,
+    },
+    {
+        .name = "Sun UltraSparc T2",
+        /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
+        .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_sun4v,
+        .nwindows = 8,
+        .maxtl = 6,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
+        | CPU_FEATURE_GL,
+    },
+    {
+        .name = "NEC UltraSparc I",
+        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
+        .fpu_version = 0x00000000,
+        .mmu_version = mmu_us_12,
+        .nwindows = 8,
+        .maxtl = 5,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+#else
+    {
+        .name = "Fujitsu MB86900",
+        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 7,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Fujitsu MB86904",
+        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x00ffffc0,
+        .mmu_cxr_mask = 0x000000ff,
+        .mmu_sfsr_mask = 0x00016fff,
+        .mmu_trcr_mask = 0x00ffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Fujitsu MB86907",
+        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x000000ff,
+        .mmu_sfsr_mask = 0x00016fff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "LSI L64811",
+        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
+        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
+        .mmu_version = 0x10 << 24,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Cypress CY7C601",
+        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
+        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
+        .mmu_version = 0x10 << 24,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Cypress CY7C611",
+        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
+        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
+        .mmu_version = 0x10 << 24,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "TI MicroSparc I",
+        .iu_version = 0x41000000,
+        .fpu_version = 4 << 17,
+        .mmu_version = 0x41000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0x00016fff,
+        .mmu_trcr_mask = 0x0000003f,
+        .nwindows = 7,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
+        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FMUL,
+    },
+    {
+        .name = "TI MicroSparc II",
+        .iu_version = 0x42000000,
+        .fpu_version = 4 << 17,
+        .mmu_version = 0x02000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x00ffffc0,
+        .mmu_cxr_mask = 0x000000ff,
+        .mmu_sfsr_mask = 0x00016fff,
+        .mmu_trcr_mask = 0x00ffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI MicroSparc IIep",
+        .iu_version = 0x42000000,
+        .fpu_version = 4 << 17,
+        .mmu_version = 0x04000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x00ffffc0,
+        .mmu_cxr_mask = 0x000000ff,
+        .mmu_sfsr_mask = 0x00016bff,
+        .mmu_trcr_mask = 0x00ffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 40", /* STP1020NPGA */
+        .iu_version = 0x41000000, /* SuperSPARC 2.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 50", /* STP1020PGA */
+        .iu_version = 0x40000000, /* SuperSPARC 3.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 51",
+        .iu_version = 0x40000000, /* SuperSPARC 3.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .mxcc_version = 0x00000104,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 60", /* STP1020APGA */
+        .iu_version = 0x40000000, /* SuperSPARC 3.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc 61",
+        .iu_version = 0x44000000, /* SuperSPARC 3.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .mxcc_version = 0x00000104,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "TI SuperSparc II",
+        .iu_version = 0x40000000, /* SuperSPARC II 1.x */
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
+        .mmu_bm = 0x00002000,
+        .mmu_ctpr_mask = 0xffffffc0,
+        .mmu_cxr_mask = 0x0000ffff,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .mxcc_version = 0x00000104,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Ross RT625",
+        .iu_version = 0x1e000000,
+        .fpu_version = 1 << 17,
+        .mmu_version = 0x1e000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "Ross RT620",
+        .iu_version = 0x1f000000,
+        .fpu_version = 1 << 17,
+        .mmu_version = 0x1f000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "BIT B5010",
+        .iu_version = 0x20000000,
+        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
+        .mmu_version = 0x20000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Matsushita MN10501",
+        .iu_version = 0x50000000,
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x50000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
+        CPU_FEATURE_FSMULD,
+    },
+    {
+        .name = "Weitek W8601",
+        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
+        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
+        .mmu_version = 0x10 << 24,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES,
+    },
+    {
+        .name = "LEON2",
+        .iu_version = 0xf2000000,
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0xf2000000,
+        .mmu_bm = 0x00004000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
+    },
+    {
+        .name = "LEON3",
+        .iu_version = 0xf3000000,
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0xf3000000,
+        .mmu_bm = 0x00000000,
+        .mmu_ctpr_mask = 0x007ffff0,
+        .mmu_cxr_mask = 0x0000003f,
+        .mmu_sfsr_mask = 0xffffffff,
+        .mmu_trcr_mask = 0xffffffff,
+        .nwindows = 8,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
+        CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
+    },
+#endif
+};
+
+static const char * const feature_name[] = {
+    "float",
+    "float128",
+    "swap",
+    "mul",
+    "div",
+    "flush",
+    "fsqrt",
+    "fmul",
+    "vis1",
+    "vis2",
+    "fsmuld",
+    "hypv",
+    "cmt",
+    "gl",
+};
+
+static void print_features(FILE *f, fprintf_function cpu_fprintf,
+                           uint32_t features, const char *prefix)
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
+        if (feature_name[i] && (features & (1 << i))) {
+            if (prefix) {
+                (*cpu_fprintf)(f, "%s", prefix);
+            }
+            (*cpu_fprintf)(f, "%s ", feature_name[i]);
+        }
+    }
+}
+
+static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
+        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
+            *features |= 1 << i;
+            return;
+        }
+    }
+    fprintf(stderr, "CPU feature %s not found\n", flagname);
+}
+
+static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
+{
+    unsigned int i;
+    const sparc_def_t *def = NULL;
+    char *s = strdup(cpu_model);
+    char *featurestr, *name = strtok(s, ",");
+    uint32_t plus_features = 0;
+    uint32_t minus_features = 0;
+    uint64_t iu_version;
+    uint32_t fpu_version, mmu_version, nwindows;
+
+    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
+        if (strcasecmp(name, sparc_defs[i].name) == 0) {
+            def = &sparc_defs[i];
+        }
+    }
+    if (!def) {
+        goto error;
+    }
+    memcpy(cpu_def, def, sizeof(*def));
+
+    featurestr = strtok(NULL, ",");
+    while (featurestr) {
+        char *val;
+
+        if (featurestr[0] == '+') {
+            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
+        } else if (featurestr[0] == '-') {
+            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
+        } else if ((val = strchr(featurestr, '='))) {
+            *val = 0; val++;
+            if (!strcmp(featurestr, "iu_version")) {
+                char *err;
+
+                iu_version = strtoll(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                cpu_def->iu_version = iu_version;
+#ifdef DEBUG_FEATURES
+                fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
+#endif
+            } else if (!strcmp(featurestr, "fpu_version")) {
+                char *err;
+
+                fpu_version = strtol(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                cpu_def->fpu_version = fpu_version;
+#ifdef DEBUG_FEATURES
+                fprintf(stderr, "fpu_version %x\n", fpu_version);
+#endif
+            } else if (!strcmp(featurestr, "mmu_version")) {
+                char *err;
+
+                mmu_version = strtol(val, &err, 0);
+                if (!*val || *err) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                cpu_def->mmu_version = mmu_version;
+#ifdef DEBUG_FEATURES
+                fprintf(stderr, "mmu_version %x\n", mmu_version);
+#endif
+            } else if (!strcmp(featurestr, "nwindows")) {
+                char *err;
+
+                nwindows = strtol(val, &err, 0);
+                if (!*val || *err || nwindows > MAX_NWINDOWS ||
+                    nwindows < MIN_NWINDOWS) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                cpu_def->nwindows = nwindows;
+#ifdef DEBUG_FEATURES
+                fprintf(stderr, "nwindows %d\n", nwindows);
+#endif
+            } else {
+                fprintf(stderr, "unrecognized feature %s\n", featurestr);
+                goto error;
+            }
+        } else {
+            fprintf(stderr, "feature string `%s' not in format "
+                    "(+feature|-feature|feature=xyz)\n", featurestr);
+            goto error;
+        }
+        featurestr = strtok(NULL, ",");
+    }
+    cpu_def->features |= plus_features;
+    cpu_def->features &= ~minus_features;
+#ifdef DEBUG_FEATURES
+    print_features(stderr, fprintf, cpu_def->features, NULL);
+#endif
+    free(s);
+    return 0;
+
+ error:
+    free(s);
+    return -1;
+}
+
+void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
+        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
+                       " FPU %08x MMU %08x NWINS %d ",
+                       sparc_defs[i].name,
+                       sparc_defs[i].iu_version,
+                       sparc_defs[i].fpu_version,
+                       sparc_defs[i].mmu_version,
+                       sparc_defs[i].nwindows);
+        print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
+                       ~sparc_defs[i].features, "-");
+        print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
+                       sparc_defs[i].features, "+");
+        (*cpu_fprintf)(f, "\n");
+    }
+    (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
+    print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
+    (*cpu_fprintf)(f, "\n");
+    (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
+    print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
+    (*cpu_fprintf)(f, "\n");
+    (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
+                   "fpu_version mmu_version nwindows\n");
+}
+
+static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
+                         uint32_t cc)
+{
+    cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
+                cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
+                cc & PSR_CARRY ? 'C' : '-');
+}
+
+#ifdef TARGET_SPARC64
+#define REGS_PER_LINE 4
+#else
+#define REGS_PER_LINE 8
+#endif
+
+void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+                    int flags)
+{
+    int i, x;
+
+    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
+                env->npc);
+    cpu_fprintf(f, "General Registers:\n");
+
+    for (i = 0; i < 8; i++) {
+        if (i % REGS_PER_LINE == 0) {
+            cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
+        }
+        cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
+        if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
+            cpu_fprintf(f, "\n");
+        }
+    }
+    cpu_fprintf(f, "\nCurrent Register Window:\n");
+    for (x = 0; x < 3; x++) {
+        for (i = 0; i < 8; i++) {
+            if (i % REGS_PER_LINE == 0) {
+                cpu_fprintf(f, "%%%c%d-%d: ",
+                            x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
+                            i, i + REGS_PER_LINE - 1);
+            }
+            cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
+            if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
+                cpu_fprintf(f, "\n");
+            }
+        }
+    }
+    cpu_fprintf(f, "\nFloating Point Registers:\n");
+    for (i = 0; i < TARGET_FPREGS; i++) {
+        if ((i & 3) == 0) {
+            cpu_fprintf(f, "%%f%02d:", i);
+        }
+        cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
+        if ((i & 3) == 3) {
+            cpu_fprintf(f, "\n");
+        }
+    }
+#ifdef TARGET_SPARC64
+    cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
+                (unsigned)cpu_get_ccr(env));
+    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
+    cpu_fprintf(f, " xcc: ");
+    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
+    cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
+                env->psrpil);
+    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
+                "cleanwin: %d cwp: %d\n",
+                env->cansave, env->canrestore, env->otherwin, env->wstate,
+                env->cleanwin, env->nwindows - 1 - env->cwp);
+    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
+                TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
+#else
+    cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
+    cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
+    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
+                env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
+                env->wim);
+    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
+                env->fsr, env->y);
+#endif
+}
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 955d180..1866f63 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -16,17 +16,10 @@
  * 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 <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
 
 #include "cpu.h"
-#include "qemu-common.h"
 
 //#define DEBUG_MMU
-//#define DEBUG_FEATURES
 
 #ifdef DEBUG_MMU
 #define DPRINTF_MMU(fmt, ...) \
@@ -35,8 +28,6 @@
 #define DPRINTF_MMU(fmt, ...) do {} while (0)
 #endif
 
-static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
-
 /* Sparc MMU emulation */
 
 #if defined(CONFIG_USER_ONLY)
@@ -358,8 +349,6 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
     }
 }
 
-#if !defined(CONFIG_USER_ONLY)
-
 /* Gdb expects all registers windows to be flushed in ram. This function handles
  * reads (and only reads) in stack frames as if windows were flushed. We assume
  * that the sparc ABI is followed.
@@ -440,8 +429,6 @@ int target_memory_rw_debug(CPUState *env, target_ulong addr,
     return cpu_memory_rw_debug(env, addr, buf, len, is_write);
 }
 
-#endif  /* !defined(CONFIG_USER_ONLY) */
-
 #else /* !TARGET_SPARC64 */
 
 // 41 bit physical address space
@@ -839,10 +826,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
 }
 
 #endif /* TARGET_SPARC64 */
-#endif /* !CONFIG_USER_ONLY */
-
 
-#if !defined(CONFIG_USER_ONLY)
 static int cpu_sparc_get_phys_page(CPUState *env, target_phys_addr_t *phys,
                                    target_ulong addr, int rw, int mmu_idx)
 {
@@ -882,1069 +866,3 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
     return phys_addr;
 }
 #endif
-
-#ifdef TARGET_SPARC64
-#ifdef DEBUG_PCALL
-static const char * const excp_names[0x80] = {
-    [TT_TFAULT] = "Instruction Access Fault",
-    [TT_TMISS] = "Instruction Access MMU Miss",
-    [TT_CODE_ACCESS] = "Instruction Access Error",
-    [TT_ILL_INSN] = "Illegal Instruction",
-    [TT_PRIV_INSN] = "Privileged Instruction",
-    [TT_NFPU_INSN] = "FPU Disabled",
-    [TT_FP_EXCP] = "FPU Exception",
-    [TT_TOVF] = "Tag Overflow",
-    [TT_CLRWIN] = "Clean Windows",
-    [TT_DIV_ZERO] = "Division By Zero",
-    [TT_DFAULT] = "Data Access Fault",
-    [TT_DMISS] = "Data Access MMU Miss",
-    [TT_DATA_ACCESS] = "Data Access Error",
-    [TT_DPROT] = "Data Protection Error",
-    [TT_UNALIGNED] = "Unaligned Memory Access",
-    [TT_PRIV_ACT] = "Privileged Action",
-    [TT_EXTINT | 0x1] = "External Interrupt 1",
-    [TT_EXTINT | 0x2] = "External Interrupt 2",
-    [TT_EXTINT | 0x3] = "External Interrupt 3",
-    [TT_EXTINT | 0x4] = "External Interrupt 4",
-    [TT_EXTINT | 0x5] = "External Interrupt 5",
-    [TT_EXTINT | 0x6] = "External Interrupt 6",
-    [TT_EXTINT | 0x7] = "External Interrupt 7",
-    [TT_EXTINT | 0x8] = "External Interrupt 8",
-    [TT_EXTINT | 0x9] = "External Interrupt 9",
-    [TT_EXTINT | 0xa] = "External Interrupt 10",
-    [TT_EXTINT | 0xb] = "External Interrupt 11",
-    [TT_EXTINT | 0xc] = "External Interrupt 12",
-    [TT_EXTINT | 0xd] = "External Interrupt 13",
-    [TT_EXTINT | 0xe] = "External Interrupt 14",
-    [TT_EXTINT | 0xf] = "External Interrupt 15",
-};
-#endif
-
-void do_interrupt(CPUState *env)
-{
-    int intno = env->exception_index;
-    trap_state *tsptr;
-
-#ifdef DEBUG_PCALL
-    if (qemu_loglevel_mask(CPU_LOG_INT)) {
-        static int count;
-        const char *name;
-
-        if (intno < 0 || intno >= 0x180) {
-            name = "Unknown";
-        } else if (intno >= 0x100) {
-            name = "Trap Instruction";
-        } else if (intno >= 0xc0) {
-            name = "Window Fill";
-        } else if (intno >= 0x80) {
-            name = "Window Spill";
-        } else {
-            name = excp_names[intno];
-            if (!name) {
-                name = "Unknown";
-            }
-        }
-
-        qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
-                " SP=%016" PRIx64 "\n",
-                count, name, intno,
-                env->pc,
-                env->npc, env->regwptr[6]);
-        log_cpu_state(env, 0);
-#if 0
-        {
-            int i;
-            uint8_t *ptr;
-
-            qemu_log("       code=");
-            ptr = (uint8_t *)env->pc;
-            for (i = 0; i < 16; i++) {
-                qemu_log(" %02x", ldub(ptr + i));
-            }
-            qemu_log("\n");
-        }
-#endif
-        count++;
-    }
-#endif
-#if !defined(CONFIG_USER_ONLY)
-    if (env->tl >= env->maxtl) {
-        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
-                  " Error state", env->exception_index, env->tl, env->maxtl);
-        return;
-    }
-#endif
-    if (env->tl < env->maxtl - 1) {
-        env->tl++;
-    } else {
-        env->pstate |= PS_RED;
-        if (env->tl < env->maxtl) {
-            env->tl++;
-        }
-    }
-    tsptr = cpu_tsptr(env);
-
-    tsptr->tstate = (cpu_get_ccr(env) << 32) |
-        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
-        cpu_get_cwp64(env);
-    tsptr->tpc = env->pc;
-    tsptr->tnpc = env->npc;
-    tsptr->tt = intno;
-
-    switch (intno) {
-    case TT_IVEC:
-        cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
-        break;
-    case TT_TFAULT:
-    case TT_DFAULT:
-    case TT_TMISS ... TT_TMISS + 3:
-    case TT_DMISS ... TT_DMISS + 3:
-    case TT_DPROT ... TT_DPROT + 3:
-        cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
-        break;
-    default:
-        cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
-        break;
-    }
-
-    if (intno == TT_CLRWIN) {
-        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
-    } else if ((intno & 0x1c0) == TT_SPILL) {
-        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
-    } else if ((intno & 0x1c0) == TT_FILL) {
-        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
-    }
-    env->tbr &= ~0x7fffULL;
-    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
-    env->pc = env->tbr;
-    env->npc = env->pc + 4;
-    env->exception_index = -1;
-}
-#else
-#ifdef DEBUG_PCALL
-static const char * const excp_names[0x80] = {
-    [TT_TFAULT] = "Instruction Access Fault",
-    [TT_ILL_INSN] = "Illegal Instruction",
-    [TT_PRIV_INSN] = "Privileged Instruction",
-    [TT_NFPU_INSN] = "FPU Disabled",
-    [TT_WIN_OVF] = "Window Overflow",
-    [TT_WIN_UNF] = "Window Underflow",
-    [TT_UNALIGNED] = "Unaligned Memory Access",
-    [TT_FP_EXCP] = "FPU Exception",
-    [TT_DFAULT] = "Data Access Fault",
-    [TT_TOVF] = "Tag Overflow",
-    [TT_EXTINT | 0x1] = "External Interrupt 1",
-    [TT_EXTINT | 0x2] = "External Interrupt 2",
-    [TT_EXTINT | 0x3] = "External Interrupt 3",
-    [TT_EXTINT | 0x4] = "External Interrupt 4",
-    [TT_EXTINT | 0x5] = "External Interrupt 5",
-    [TT_EXTINT | 0x6] = "External Interrupt 6",
-    [TT_EXTINT | 0x7] = "External Interrupt 7",
-    [TT_EXTINT | 0x8] = "External Interrupt 8",
-    [TT_EXTINT | 0x9] = "External Interrupt 9",
-    [TT_EXTINT | 0xa] = "External Interrupt 10",
-    [TT_EXTINT | 0xb] = "External Interrupt 11",
-    [TT_EXTINT | 0xc] = "External Interrupt 12",
-    [TT_EXTINT | 0xd] = "External Interrupt 13",
-    [TT_EXTINT | 0xe] = "External Interrupt 14",
-    [TT_EXTINT | 0xf] = "External Interrupt 15",
-    [TT_TOVF] = "Tag Overflow",
-    [TT_CODE_ACCESS] = "Instruction Access Error",
-    [TT_DATA_ACCESS] = "Data Access Error",
-    [TT_DIV_ZERO] = "Division By Zero",
-    [TT_NCP_INSN] = "Coprocessor Disabled",
-};
-#endif
-
-void do_interrupt(CPUState *env)
-{
-    int cwp, intno = env->exception_index;
-
-#ifdef DEBUG_PCALL
-    if (qemu_loglevel_mask(CPU_LOG_INT)) {
-        static int count;
-        const char *name;
-
-        if (intno < 0 || intno >= 0x100) {
-            name = "Unknown";
-        } else if (intno >= 0x80) {
-            name = "Trap Instruction";
-        } else {
-            name = excp_names[intno];
-            if (!name) {
-                name = "Unknown";
-            }
-        }
-
-        qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
-                count, name, intno,
-                env->pc,
-                env->npc, env->regwptr[6]);
-        log_cpu_state(env, 0);
-#if 0
-        {
-            int i;
-            uint8_t *ptr;
-
-            qemu_log("       code=");
-            ptr = (uint8_t *)env->pc;
-            for (i = 0; i < 16; i++) {
-                qemu_log(" %02x", ldub(ptr + i));
-            }
-            qemu_log("\n");
-        }
-#endif
-        count++;
-    }
-#endif
-#if !defined(CONFIG_USER_ONLY)
-    if (env->psret == 0) {
-        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
-                  env->exception_index);
-        return;
-    }
-#endif
-    env->psret = 0;
-    cwp = cpu_cwp_dec(env, env->cwp - 1);
-    cpu_set_cwp(env, cwp);
-    env->regwptr[9] = env->pc;
-    env->regwptr[10] = env->npc;
-    env->psrps = env->psrs;
-    env->psrs = 1;
-    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
-    env->pc = env->tbr;
-    env->npc = env->pc + 4;
-    env->exception_index = -1;
-
-#if !defined(CONFIG_USER_ONLY)
-    /* IRQ acknowledgment */
-    if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
-        env->qemu_irq_ack(env->irq_manager, intno);
-    }
-#endif
-}
-#endif
-
-void cpu_reset(CPUSPARCState *env)
-{
-    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
-        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
-        log_cpu_state(env, 0);
-    }
-
-    tlb_flush(env, 1);
-    env->cwp = 0;
-#ifndef TARGET_SPARC64
-    env->wim = 1;
-#endif
-    env->regwptr = env->regbase + (env->cwp * 16);
-    CC_OP = CC_OP_FLAGS;
-#if defined(CONFIG_USER_ONLY)
-#ifdef TARGET_SPARC64
-    env->cleanwin = env->nwindows - 2;
-    env->cansave = env->nwindows - 2;
-    env->pstate = PS_RMO | PS_PEF | PS_IE;
-    env->asi = 0x82; /* Primary no-fault */
-#endif
-#else
-#if !defined(TARGET_SPARC64)
-    env->psret = 0;
-    env->psrs = 1;
-    env->psrps = 1;
-#endif
-#ifdef TARGET_SPARC64
-    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
-    env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
-    env->tl = env->maxtl;
-    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
-    env->lsu = 0;
-#else
-    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
-    env->mmuregs[0] |= env->def->mmu_bm;
-#endif
-    env->pc = 0;
-    env->npc = env->pc + 4;
-#endif
-    env->cache_control = 0;
-}
-
-static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
-{
-    sparc_def_t def1, *def = &def1;
-
-    if (cpu_sparc_find_by_name(def, cpu_model) < 0) {
-        return -1;
-    }
-
-    env->def = g_malloc0(sizeof(*def));
-    memcpy(env->def, def, sizeof(*def));
-#if defined(CONFIG_USER_ONLY)
-    if ((env->def->features & CPU_FEATURE_FLOAT)) {
-        env->def->features |= CPU_FEATURE_FLOAT128;
-    }
-#endif
-    env->cpu_model_str = cpu_model;
-    env->version = def->iu_version;
-    env->fsr = def->fpu_version;
-    env->nwindows = def->nwindows;
-#if !defined(TARGET_SPARC64)
-    env->mmuregs[0] |= def->mmu_version;
-    cpu_sparc_set_id(env, 0);
-    env->mxccregs[7] |= def->mxcc_version;
-#else
-    env->mmu_version = def->mmu_version;
-    env->maxtl = def->maxtl;
-    env->version |= def->maxtl << 8;
-    env->version |= def->nwindows - 1;
-#endif
-    return 0;
-}
-
-static void cpu_sparc_close(CPUSPARCState *env)
-{
-    free(env->def);
-    free(env);
-}
-
-CPUSPARCState *cpu_sparc_init(const char *cpu_model)
-{
-    CPUSPARCState *env;
-
-    env = g_malloc0(sizeof(CPUSPARCState));
-    cpu_exec_init(env);
-
-    gen_intermediate_code_init(env);
-
-    if (cpu_sparc_register(env, cpu_model) < 0) {
-        cpu_sparc_close(env);
-        return NULL;
-    }
-    qemu_init_vcpu(env);
-
-    return env;
-}
-
-void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
-{
-#if !defined(TARGET_SPARC64)
-    env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
-#endif
-}
-
-static const sparc_def_t sparc_defs[] = {
-#ifdef TARGET_SPARC64
-    {
-        .name = "Fujitsu Sparc64",
-        .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 4,
-        .maxtl = 4,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Fujitsu Sparc64 III",
-        .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 5,
-        .maxtl = 4,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Fujitsu Sparc64 IV",
-        .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Fujitsu Sparc64 V",
-        .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI UltraSparc I",
-        .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI UltraSparc II",
-        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI UltraSparc IIi",
-        .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI UltraSparc IIe",
-        .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc III",
-        .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc III Cu",
-        .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_3,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc IIIi",
-        .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc IV",
-        .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_4,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc IV+",
-        .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
-    },
-    {
-        .name = "Sun UltraSparc IIIi+",
-        .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_3,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Sun UltraSparc T1",
-        /* defined in sparc_ifu_fdp.v and ctu.h */
-        .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_sun4v,
-        .nwindows = 8,
-        .maxtl = 6,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
-        | CPU_FEATURE_GL,
-    },
-    {
-        .name = "Sun UltraSparc T2",
-        /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
-        .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_sun4v,
-        .nwindows = 8,
-        .maxtl = 6,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
-        | CPU_FEATURE_GL,
-    },
-    {
-        .name = "NEC UltraSparc I",
-        .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
-        .fpu_version = 0x00000000,
-        .mmu_version = mmu_us_12,
-        .nwindows = 8,
-        .maxtl = 5,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-#else
-    {
-        .name = "Fujitsu MB86900",
-        .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 7,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Fujitsu MB86904",
-        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x00ffffc0,
-        .mmu_cxr_mask = 0x000000ff,
-        .mmu_sfsr_mask = 0x00016fff,
-        .mmu_trcr_mask = 0x00ffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Fujitsu MB86907",
-        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x000000ff,
-        .mmu_sfsr_mask = 0x00016fff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "LSI L64811",
-        .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
-        .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
-        .mmu_version = 0x10 << 24,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Cypress CY7C601",
-        .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
-        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
-        .mmu_version = 0x10 << 24,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Cypress CY7C611",
-        .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
-        .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
-        .mmu_version = 0x10 << 24,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "TI MicroSparc I",
-        .iu_version = 0x41000000,
-        .fpu_version = 4 << 17,
-        .mmu_version = 0x41000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0x00016fff,
-        .mmu_trcr_mask = 0x0000003f,
-        .nwindows = 7,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
-        CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FMUL,
-    },
-    {
-        .name = "TI MicroSparc II",
-        .iu_version = 0x42000000,
-        .fpu_version = 4 << 17,
-        .mmu_version = 0x02000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x00ffffc0,
-        .mmu_cxr_mask = 0x000000ff,
-        .mmu_sfsr_mask = 0x00016fff,
-        .mmu_trcr_mask = 0x00ffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI MicroSparc IIep",
-        .iu_version = 0x42000000,
-        .fpu_version = 4 << 17,
-        .mmu_version = 0x04000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x00ffffc0,
-        .mmu_cxr_mask = 0x000000ff,
-        .mmu_sfsr_mask = 0x00016bff,
-        .mmu_trcr_mask = 0x00ffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 40", /* STP1020NPGA */
-        .iu_version = 0x41000000, /* SuperSPARC 2.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 50", /* STP1020PGA */
-        .iu_version = 0x40000000, /* SuperSPARC 3.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 51",
-        .iu_version = 0x40000000, /* SuperSPARC 3.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .mxcc_version = 0x00000104,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 60", /* STP1020APGA */
-        .iu_version = 0x40000000, /* SuperSPARC 3.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc 61",
-        .iu_version = 0x44000000, /* SuperSPARC 3.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .mxcc_version = 0x00000104,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "TI SuperSparc II",
-        .iu_version = 0x40000000, /* SuperSPARC II 1.x */
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
-        .mmu_bm = 0x00002000,
-        .mmu_ctpr_mask = 0xffffffc0,
-        .mmu_cxr_mask = 0x0000ffff,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .mxcc_version = 0x00000104,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Ross RT625",
-        .iu_version = 0x1e000000,
-        .fpu_version = 1 << 17,
-        .mmu_version = 0x1e000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "Ross RT620",
-        .iu_version = 0x1f000000,
-        .fpu_version = 1 << 17,
-        .mmu_version = 0x1f000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "BIT B5010",
-        .iu_version = 0x20000000,
-        .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
-        .mmu_version = 0x20000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Matsushita MN10501",
-        .iu_version = 0x50000000,
-        .fpu_version = 0 << 17,
-        .mmu_version = 0x50000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
-        CPU_FEATURE_FSMULD,
-    },
-    {
-        .name = "Weitek W8601",
-        .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
-        .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
-        .mmu_version = 0x10 << 24,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
-    },
-    {
-        .name = "LEON2",
-        .iu_version = 0xf2000000,
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0xf2000000,
-        .mmu_bm = 0x00004000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
-    },
-    {
-        .name = "LEON3",
-        .iu_version = 0xf3000000,
-        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
-        .mmu_version = 0xf3000000,
-        .mmu_bm = 0x00000000,
-        .mmu_ctpr_mask = 0x007ffff0,
-        .mmu_cxr_mask = 0x0000003f,
-        .mmu_sfsr_mask = 0xffffffff,
-        .mmu_trcr_mask = 0xffffffff,
-        .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
-        CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
-    },
-#endif
-};
-
-static const char * const feature_name[] = {
-    "float",
-    "float128",
-    "swap",
-    "mul",
-    "div",
-    "flush",
-    "fsqrt",
-    "fmul",
-    "vis1",
-    "vis2",
-    "fsmuld",
-    "hypv",
-    "cmt",
-    "gl",
-};
-
-static void print_features(FILE *f, fprintf_function cpu_fprintf,
-                           uint32_t features, const char *prefix)
-{
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
-        if (feature_name[i] && (features & (1 << i))) {
-            if (prefix) {
-                (*cpu_fprintf)(f, "%s", prefix);
-            }
-            (*cpu_fprintf)(f, "%s ", feature_name[i]);
-        }
-    }
-}
-
-static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
-{
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
-        if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
-            *features |= 1 << i;
-            return;
-        }
-    }
-    fprintf(stderr, "CPU feature %s not found\n", flagname);
-}
-
-static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
-{
-    unsigned int i;
-    const sparc_def_t *def = NULL;
-    char *s = strdup(cpu_model);
-    char *featurestr, *name = strtok(s, ",");
-    uint32_t plus_features = 0;
-    uint32_t minus_features = 0;
-    uint64_t iu_version;
-    uint32_t fpu_version, mmu_version, nwindows;
-
-    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
-        if (strcasecmp(name, sparc_defs[i].name) == 0) {
-            def = &sparc_defs[i];
-        }
-    }
-    if (!def) {
-        goto error;
-    }
-    memcpy(cpu_def, def, sizeof(*def));
-
-    featurestr = strtok(NULL, ",");
-    while (featurestr) {
-        char *val;
-
-        if (featurestr[0] == '+') {
-            add_flagname_to_bitmaps(featurestr + 1, &plus_features);
-        } else if (featurestr[0] == '-') {
-            add_flagname_to_bitmaps(featurestr + 1, &minus_features);
-        } else if ((val = strchr(featurestr, '='))) {
-            *val = 0; val++;
-            if (!strcmp(featurestr, "iu_version")) {
-                char *err;
-
-                iu_version = strtoll(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                cpu_def->iu_version = iu_version;
-#ifdef DEBUG_FEATURES
-                fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
-#endif
-            } else if (!strcmp(featurestr, "fpu_version")) {
-                char *err;
-
-                fpu_version = strtol(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                cpu_def->fpu_version = fpu_version;
-#ifdef DEBUG_FEATURES
-                fprintf(stderr, "fpu_version %x\n", fpu_version);
-#endif
-            } else if (!strcmp(featurestr, "mmu_version")) {
-                char *err;
-
-                mmu_version = strtol(val, &err, 0);
-                if (!*val || *err) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                cpu_def->mmu_version = mmu_version;
-#ifdef DEBUG_FEATURES
-                fprintf(stderr, "mmu_version %x\n", mmu_version);
-#endif
-            } else if (!strcmp(featurestr, "nwindows")) {
-                char *err;
-
-                nwindows = strtol(val, &err, 0);
-                if (!*val || *err || nwindows > MAX_NWINDOWS ||
-                    nwindows < MIN_NWINDOWS) {
-                    fprintf(stderr, "bad numerical value %s\n", val);
-                    goto error;
-                }
-                cpu_def->nwindows = nwindows;
-#ifdef DEBUG_FEATURES
-                fprintf(stderr, "nwindows %d\n", nwindows);
-#endif
-            } else {
-                fprintf(stderr, "unrecognized feature %s\n", featurestr);
-                goto error;
-            }
-        } else {
-            fprintf(stderr, "feature string `%s' not in format "
-                    "(+feature|-feature|feature=xyz)\n", featurestr);
-            goto error;
-        }
-        featurestr = strtok(NULL, ",");
-    }
-    cpu_def->features |= plus_features;
-    cpu_def->features &= ~minus_features;
-#ifdef DEBUG_FEATURES
-    print_features(stderr, fprintf, cpu_def->features, NULL);
-#endif
-    free(s);
-    return 0;
-
- error:
-    free(s);
-    return -1;
-}
-
-void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
-{
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
-        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
-                       " FPU %08x MMU %08x NWINS %d ",
-                       sparc_defs[i].name,
-                       sparc_defs[i].iu_version,
-                       sparc_defs[i].fpu_version,
-                       sparc_defs[i].mmu_version,
-                       sparc_defs[i].nwindows);
-        print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
-                       ~sparc_defs[i].features, "-");
-        print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
-                       sparc_defs[i].features, "+");
-        (*cpu_fprintf)(f, "\n");
-    }
-    (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
-    print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
-    (*cpu_fprintf)(f, "\n");
-    (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
-    print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
-    (*cpu_fprintf)(f, "\n");
-    (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
-                   "fpu_version mmu_version nwindows\n");
-}
-
-static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
-                         uint32_t cc)
-{
-    cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
-                cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
-                cc & PSR_CARRY ? 'C' : '-');
-}
-
-#ifdef TARGET_SPARC64
-#define REGS_PER_LINE 4
-#else
-#define REGS_PER_LINE 8
-#endif
-
-void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
-                    int flags)
-{
-    int i, x;
-
-    cpu_fprintf(f, "pc: " TARGET_FMT_lx "  npc: " TARGET_FMT_lx "\n", env->pc,
-                env->npc);
-    cpu_fprintf(f, "General Registers:\n");
-
-    for (i = 0; i < 8; i++) {
-        if (i % REGS_PER_LINE == 0) {
-            cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
-        }
-        cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
-        if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
-            cpu_fprintf(f, "\n");
-        }
-    }
-    cpu_fprintf(f, "\nCurrent Register Window:\n");
-    for (x = 0; x < 3; x++) {
-        for (i = 0; i < 8; i++) {
-            if (i % REGS_PER_LINE == 0) {
-                cpu_fprintf(f, "%%%c%d-%d: ",
-                            x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
-                            i, i + REGS_PER_LINE - 1);
-            }
-            cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
-            if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
-                cpu_fprintf(f, "\n");
-            }
-        }
-    }
-    cpu_fprintf(f, "\nFloating Point Registers:\n");
-    for (i = 0; i < TARGET_FPREGS; i++) {
-        if ((i & 3) == 0) {
-            cpu_fprintf(f, "%%f%02d:", i);
-        }
-        cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
-        if ((i & 3) == 3) {
-            cpu_fprintf(f, "\n");
-        }
-    }
-#ifdef TARGET_SPARC64
-    cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
-                (unsigned)cpu_get_ccr(env));
-    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
-    cpu_fprintf(f, " xcc: ");
-    cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
-    cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
-                env->psrpil);
-    cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
-                "cleanwin: %d cwp: %d\n",
-                env->cansave, env->canrestore, env->otherwin, env->wstate,
-                env->cleanwin, env->nwindows - 1 - env->cwp);
-    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
-                TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
-#else
-    cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
-    cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
-    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
-                env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
-                env->wim);
-    cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
-                env->fsr, env->y);
-#endif
-}
diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
new file mode 100644
index 0000000..219a6c6
--- /dev/null
+++ b/target-sparc/int32_helper.c
@@ -0,0 +1,125 @@
+/*
+ * Sparc32 interrupt helpers
+ *
+ *  Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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"
+
+//#define DEBUG_PCALL
+
+#ifdef DEBUG_PCALL
+static const char * const excp_names[0x80] = {
+    [TT_TFAULT] = "Instruction Access Fault",
+    [TT_ILL_INSN] = "Illegal Instruction",
+    [TT_PRIV_INSN] = "Privileged Instruction",
+    [TT_NFPU_INSN] = "FPU Disabled",
+    [TT_WIN_OVF] = "Window Overflow",
+    [TT_WIN_UNF] = "Window Underflow",
+    [TT_UNALIGNED] = "Unaligned Memory Access",
+    [TT_FP_EXCP] = "FPU Exception",
+    [TT_DFAULT] = "Data Access Fault",
+    [TT_TOVF] = "Tag Overflow",
+    [TT_EXTINT | 0x1] = "External Interrupt 1",
+    [TT_EXTINT | 0x2] = "External Interrupt 2",
+    [TT_EXTINT | 0x3] = "External Interrupt 3",
+    [TT_EXTINT | 0x4] = "External Interrupt 4",
+    [TT_EXTINT | 0x5] = "External Interrupt 5",
+    [TT_EXTINT | 0x6] = "External Interrupt 6",
+    [TT_EXTINT | 0x7] = "External Interrupt 7",
+    [TT_EXTINT | 0x8] = "External Interrupt 8",
+    [TT_EXTINT | 0x9] = "External Interrupt 9",
+    [TT_EXTINT | 0xa] = "External Interrupt 10",
+    [TT_EXTINT | 0xb] = "External Interrupt 11",
+    [TT_EXTINT | 0xc] = "External Interrupt 12",
+    [TT_EXTINT | 0xd] = "External Interrupt 13",
+    [TT_EXTINT | 0xe] = "External Interrupt 14",
+    [TT_EXTINT | 0xf] = "External Interrupt 15",
+    [TT_TOVF] = "Tag Overflow",
+    [TT_CODE_ACCESS] = "Instruction Access Error",
+    [TT_DATA_ACCESS] = "Data Access Error",
+    [TT_DIV_ZERO] = "Division By Zero",
+    [TT_NCP_INSN] = "Coprocessor Disabled",
+};
+#endif
+
+void do_interrupt(CPUState *env)
+{
+    int cwp, intno = env->exception_index;
+
+#ifdef DEBUG_PCALL
+    if (qemu_loglevel_mask(CPU_LOG_INT)) {
+        static int count;
+        const char *name;
+
+        if (intno < 0 || intno >= 0x100) {
+            name = "Unknown";
+        } else if (intno >= 0x80) {
+            name = "Trap Instruction";
+        } else {
+            name = excp_names[intno];
+            if (!name) {
+                name = "Unknown";
+            }
+        }
+
+        qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
+                count, name, intno,
+                env->pc,
+                env->npc, env->regwptr[6]);
+        log_cpu_state(env, 0);
+#if 0
+        {
+            int i;
+            uint8_t *ptr;
+
+            qemu_log("       code=");
+            ptr = (uint8_t *)env->pc;
+            for (i = 0; i < 16; i++) {
+                qemu_log(" %02x", ldub(ptr + i));
+            }
+            qemu_log("\n");
+        }
+#endif
+        count++;
+    }
+#endif
+#if !defined(CONFIG_USER_ONLY)
+    if (env->psret == 0) {
+        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
+                  env->exception_index);
+        return;
+    }
+#endif
+    env->psret = 0;
+    cwp = cpu_cwp_dec(env, env->cwp - 1);
+    cpu_set_cwp(env, cwp);
+    env->regwptr[9] = env->pc;
+    env->regwptr[10] = env->npc;
+    env->psrps = env->psrs;
+    env->psrs = 1;
+    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
+    env->pc = env->tbr;
+    env->npc = env->pc + 4;
+    env->exception_index = -1;
+
+#if !defined(CONFIG_USER_ONLY)
+    /* IRQ acknowledgment */
+    if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
+        env->qemu_irq_ack(env->irq_manager, intno);
+    }
+#endif
+}
diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c
new file mode 100644
index 0000000..c21dc9c
--- /dev/null
+++ b/target-sparc/int64_helper.c
@@ -0,0 +1,159 @@
+/*
+ * Sparc64 interrupt helpers
+ *
+ *  Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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"
+
+//#define DEBUG_PCALL
+
+#ifdef DEBUG_PCALL
+static const char * const excp_names[0x80] = {
+    [TT_TFAULT] = "Instruction Access Fault",
+    [TT_TMISS] = "Instruction Access MMU Miss",
+    [TT_CODE_ACCESS] = "Instruction Access Error",
+    [TT_ILL_INSN] = "Illegal Instruction",
+    [TT_PRIV_INSN] = "Privileged Instruction",
+    [TT_NFPU_INSN] = "FPU Disabled",
+    [TT_FP_EXCP] = "FPU Exception",
+    [TT_TOVF] = "Tag Overflow",
+    [TT_CLRWIN] = "Clean Windows",
+    [TT_DIV_ZERO] = "Division By Zero",
+    [TT_DFAULT] = "Data Access Fault",
+    [TT_DMISS] = "Data Access MMU Miss",
+    [TT_DATA_ACCESS] = "Data Access Error",
+    [TT_DPROT] = "Data Protection Error",
+    [TT_UNALIGNED] = "Unaligned Memory Access",
+    [TT_PRIV_ACT] = "Privileged Action",
+    [TT_EXTINT | 0x1] = "External Interrupt 1",
+    [TT_EXTINT | 0x2] = "External Interrupt 2",
+    [TT_EXTINT | 0x3] = "External Interrupt 3",
+    [TT_EXTINT | 0x4] = "External Interrupt 4",
+    [TT_EXTINT | 0x5] = "External Interrupt 5",
+    [TT_EXTINT | 0x6] = "External Interrupt 6",
+    [TT_EXTINT | 0x7] = "External Interrupt 7",
+    [TT_EXTINT | 0x8] = "External Interrupt 8",
+    [TT_EXTINT | 0x9] = "External Interrupt 9",
+    [TT_EXTINT | 0xa] = "External Interrupt 10",
+    [TT_EXTINT | 0xb] = "External Interrupt 11",
+    [TT_EXTINT | 0xc] = "External Interrupt 12",
+    [TT_EXTINT | 0xd] = "External Interrupt 13",
+    [TT_EXTINT | 0xe] = "External Interrupt 14",
+    [TT_EXTINT | 0xf] = "External Interrupt 15",
+};
+#endif
+
+void do_interrupt(CPUState *env)
+{
+    int intno = env->exception_index;
+    trap_state *tsptr;
+
+#ifdef DEBUG_PCALL
+    if (qemu_loglevel_mask(CPU_LOG_INT)) {
+        static int count;
+        const char *name;
+
+        if (intno < 0 || intno >= 0x180) {
+            name = "Unknown";
+        } else if (intno >= 0x100) {
+            name = "Trap Instruction";
+        } else if (intno >= 0xc0) {
+            name = "Window Fill";
+        } else if (intno >= 0x80) {
+            name = "Window Spill";
+        } else {
+            name = excp_names[intno];
+            if (!name) {
+                name = "Unknown";
+            }
+        }
+
+        qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
+                " SP=%016" PRIx64 "\n",
+                count, name, intno,
+                env->pc,
+                env->npc, env->regwptr[6]);
+        log_cpu_state(env, 0);
+#if 0
+        {
+            int i;
+            uint8_t *ptr;
+
+            qemu_log("       code=");
+            ptr = (uint8_t *)env->pc;
+            for (i = 0; i < 16; i++) {
+                qemu_log(" %02x", ldub(ptr + i));
+            }
+            qemu_log("\n");
+        }
+#endif
+        count++;
+    }
+#endif
+#if !defined(CONFIG_USER_ONLY)
+    if (env->tl >= env->maxtl) {
+        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
+                  " Error state", env->exception_index, env->tl, env->maxtl);
+        return;
+    }
+#endif
+    if (env->tl < env->maxtl - 1) {
+        env->tl++;
+    } else {
+        env->pstate |= PS_RED;
+        if (env->tl < env->maxtl) {
+            env->tl++;
+        }
+    }
+    tsptr = cpu_tsptr(env);
+
+    tsptr->tstate = (cpu_get_ccr(env) << 32) |
+        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
+        cpu_get_cwp64(env);
+    tsptr->tpc = env->pc;
+    tsptr->tnpc = env->npc;
+    tsptr->tt = intno;
+
+    switch (intno) {
+    case TT_IVEC:
+        cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
+        break;
+    case TT_TFAULT:
+    case TT_DFAULT:
+    case TT_TMISS ... TT_TMISS + 3:
+    case TT_DMISS ... TT_DMISS + 3:
+    case TT_DPROT ... TT_DPROT + 3:
+        cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
+        break;
+    default:
+        cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
+        break;
+    }
+
+    if (intno == TT_CLRWIN) {
+        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
+    } else if ((intno & 0x1c0) == TT_SPILL) {
+        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
+    } else if ((intno & 0x1c0) == TT_FILL) {
+        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
+    }
+    env->tbr &= ~0x7fffULL;
+    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
+    env->pc = env->tbr;
+    env->npc = env->pc + 4;
+    env->exception_index = -1;
+}
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 1cb0636..1102273 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -13,7 +13,6 @@
 //#define DEBUG_UNALIGNED
 //#define DEBUG_UNASSIGNED
 //#define DEBUG_ASI
-//#define DEBUG_PCALL
 //#define DEBUG_PSTATE
 //#define DEBUG_CACHE_CONTROL
 
commit c65f6fd4bc485f893cd032cd32c8f6eb2a6ae757
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 11 09:42:13 2011 +0000

    Sparc: fix coding style
    
    Before the next patch, fix coding style of the areas affected.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index c80531a..955d180 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -1144,7 +1144,7 @@ void cpu_reset(CPUSPARCState *env)
     env->cleanwin = env->nwindows - 2;
     env->cansave = env->nwindows - 2;
     env->pstate = PS_RMO | PS_PEF | PS_IE;
-    env->asi = 0x82; // Primary no-fault
+    env->asi = 0x82; /* Primary no-fault */
 #endif
 #else
 #if !defined(TARGET_SPARC64)
@@ -1172,14 +1172,16 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
 {
     sparc_def_t def1, *def = &def1;
 
-    if (cpu_sparc_find_by_name(def, cpu_model) < 0)
+    if (cpu_sparc_find_by_name(def, cpu_model) < 0) {
         return -1;
+    }
 
     env->def = g_malloc0(sizeof(*def));
     memcpy(env->def, def, sizeof(*def));
 #if defined(CONFIG_USER_ONLY)
-    if ((env->def->features & CPU_FEATURE_FLOAT))
+    if ((env->def->features & CPU_FEATURE_FLOAT)) {
         env->def->features |= CPU_FEATURE_FLOAT128;
+    }
 #endif
     env->cpu_model_str = cpu_model;
     env->version = def->iu_version;
@@ -1359,7 +1361,7 @@ static const sparc_def_t sparc_defs[] = {
     },
     {
         .name = "Sun UltraSparc T1",
-        // defined in sparc_ifu_fdp.v and ctu.h
+        /* defined in sparc_ifu_fdp.v and ctu.h */
         .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
         .fpu_version = 0x00000000,
         .mmu_version = mmu_sun4v,
@@ -1370,7 +1372,7 @@ static const sparc_def_t sparc_defs[] = {
     },
     {
         .name = "Sun UltraSparc T2",
-        // defined in tlu_asi_ctl.v and n2_revid_cust.v
+        /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
         .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
         .fpu_version = 0x00000000,
         .mmu_version = mmu_sun4v,
@@ -1512,10 +1514,10 @@ static const sparc_def_t sparc_defs[] = {
         .features = CPU_DEFAULT_FEATURES,
     },
     {
-        .name = "TI SuperSparc 40", // STP1020NPGA
-        .iu_version = 0x41000000, // SuperSPARC 2.x
+        .name = "TI SuperSparc 40", /* STP1020NPGA */
+        .iu_version = 0x41000000, /* SuperSPARC 2.x */
         .fpu_version = 0 << 17,
-        .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
+        .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
         .mmu_bm = 0x00002000,
         .mmu_ctpr_mask = 0xffffffc0,
         .mmu_cxr_mask = 0x0000ffff,
@@ -1525,10 +1527,10 @@ static const sparc_def_t sparc_defs[] = {
         .features = CPU_DEFAULT_FEATURES,
     },
     {
-        .name = "TI SuperSparc 50", // STP1020PGA
-        .iu_version = 0x40000000, // SuperSPARC 3.x
+        .name = "TI SuperSparc 50", /* STP1020PGA */
+        .iu_version = 0x40000000, /* SuperSPARC 3.x */
         .fpu_version = 0 << 17,
-        .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
+        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
         .mmu_bm = 0x00002000,
         .mmu_ctpr_mask = 0xffffffc0,
         .mmu_cxr_mask = 0x0000ffff,
@@ -1539,9 +1541,9 @@ static const sparc_def_t sparc_defs[] = {
     },
     {
         .name = "TI SuperSparc 51",
-        .iu_version = 0x40000000, // SuperSPARC 3.x
+        .iu_version = 0x40000000, /* SuperSPARC 3.x */
         .fpu_version = 0 << 17,
-        .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
+        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
         .mmu_bm = 0x00002000,
         .mmu_ctpr_mask = 0xffffffc0,
         .mmu_cxr_mask = 0x0000ffff,
@@ -1552,10 +1554,10 @@ static const sparc_def_t sparc_defs[] = {
         .features = CPU_DEFAULT_FEATURES,
     },
     {
-        .name = "TI SuperSparc 60", // STP1020APGA
-        .iu_version = 0x40000000, // SuperSPARC 3.x
+        .name = "TI SuperSparc 60", /* STP1020APGA */
+        .iu_version = 0x40000000, /* SuperSPARC 3.x */
         .fpu_version = 0 << 17,
-        .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
+        .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
         .mmu_bm = 0x00002000,
         .mmu_ctpr_mask = 0xffffffc0,
         .mmu_cxr_mask = 0x0000ffff,
@@ -1566,9 +1568,9 @@ static const sparc_def_t sparc_defs[] = {
     },
     {
         .name = "TI SuperSparc 61",
-        .iu_version = 0x44000000, // SuperSPARC 3.x
+        .iu_version = 0x44000000, /* SuperSPARC 3.x */
         .fpu_version = 0 << 17,
-        .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
+        .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
         .mmu_bm = 0x00002000,
         .mmu_ctpr_mask = 0xffffffc0,
         .mmu_cxr_mask = 0x0000ffff,
@@ -1580,9 +1582,9 @@ static const sparc_def_t sparc_defs[] = {
     },
     {
         .name = "TI SuperSparc II",
-        .iu_version = 0x40000000, // SuperSPARC II 1.x
+        .iu_version = 0x40000000, /* SuperSPARC II 1.x */
         .fpu_version = 0 << 17,
-        .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
+        .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
         .mmu_bm = 0x00002000,
         .mmu_ctpr_mask = 0xffffffc0,
         .mmu_cxr_mask = 0x0000ffff,
@@ -1711,23 +1713,26 @@ static void print_features(FILE *f, fprintf_function cpu_fprintf,
 {
     unsigned int i;
 
-    for (i = 0; i < ARRAY_SIZE(feature_name); i++)
+    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
         if (feature_name[i] && (features & (1 << i))) {
-            if (prefix)
+            if (prefix) {
                 (*cpu_fprintf)(f, "%s", prefix);
+            }
             (*cpu_fprintf)(f, "%s ", feature_name[i]);
         }
+    }
 }
 
 static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
 {
     unsigned int i;
 
-    for (i = 0; i < ARRAY_SIZE(feature_name); i++)
+    for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
         if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
             *features |= 1 << i;
             return;
         }
+    }
     fprintf(stderr, "CPU feature %s not found\n", flagname);
 }
 
@@ -1747,8 +1752,9 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
             def = &sparc_defs[i];
         }
     }
-    if (!def)
+    if (!def) {
         goto error;
+    }
     memcpy(cpu_def, def, sizeof(*def));
 
     featurestr = strtok(NULL, ",");
@@ -1839,7 +1845,8 @@ void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
     unsigned int i;
 
     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
-        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
+        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
+                       " FPU %08x MMU %08x NWINS %d ",
                        sparc_defs[i].name,
                        sparc_defs[i].iu_version,
                        sparc_defs[i].fpu_version,
@@ -1864,9 +1871,9 @@ void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
 static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
                          uint32_t cc)
 {
-    cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
-                cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
-                cc & PSR_CARRY? 'C' : '-');
+    cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
+                cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
+                cc & PSR_CARRY ? 'C' : '-');
 }
 
 #ifdef TARGET_SPARC64
@@ -1909,11 +1916,13 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
     }
     cpu_fprintf(f, "\nFloating Point Registers:\n");
     for (i = 0; i < TARGET_FPREGS; i++) {
-        if ((i & 3) == 0)
+        if ((i & 3) == 0) {
             cpu_fprintf(f, "%%f%02d:", i);
+        }
         cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
-        if ((i & 3) == 3)
+        if ((i & 3) == 3) {
             cpu_fprintf(f, "\n");
+        }
     }
 #ifdef TARGET_SPARC64
     cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
@@ -1932,8 +1941,8 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
 #else
     cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
     cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
-    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
-                env->psrps? 'P' : '-', env->psret? 'E' : '-',
+    cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
+                env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
                 env->wim);
     cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
                 env->fsr, env->y);
commit b1f88301b552dff815d9b355c1e4c073278a77c1
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Oct 15 08:05:18 2011 +0000

    m48t59: fix write access
    
    Fix incorrect order of arguments, letting writes to NVRAM succeed.
    
    It looks like guests never write to the device, only read from it, since the bug
    originates back to 819385c58b319d9f80d676cefaed0610118f03ac.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/m48t59.c b/hw/m48t59.c
index dba5796..a77937e 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -491,7 +491,7 @@ static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
         NVRAM->addr |= val << 8;
         break;
     case 3:
-        m48t59_write(NVRAM, val, NVRAM->addr);
+        m48t59_write(NVRAM, NVRAM->addr, val);
         NVRAM->addr = 0x0000;
         break;
     default:
commit 0fb56ffc5edd66f12ccfc0d71af5f9c79c0a2612
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Oct 15 07:57:49 2011 +0000

    m48t59: drop obsolete address base arithmetic
    
    Remove now incorrect address base arithmetic, missed by
    9936d6e42392f1440505dfa9df065eabd251cadf. Fixes Sparc64 boot.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/m48t59.c b/hw/m48t59.c
index f318e67..dba5796 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -480,7 +480,6 @@ static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
 {
     M48t59State *NVRAM = opaque;
 
-    addr -= NVRAM->io_base;
     NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
     switch (addr) {
     case 0:
@@ -505,7 +504,6 @@ static uint32_t NVRAM_readb (void *opaque, uint32_t addr)
     M48t59State *NVRAM = opaque;
     uint32_t retval;
 
-    addr -= NVRAM->io_base;
     switch (addr) {
     case 3:
         retval = m48t59_read(NVRAM, NVRAM->addr);
commit 52ce6f05c1d5b19a7f3e1e562e24d89183730f50
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Oct 16 14:43:00 2011 +0000

    pci_bridge: fix typo
    
    Reviewed-by: Avi Kivity <avi at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c
index b6287cd..650d165 100644
--- a/hw/pci_bridge.c
+++ b/hw/pci_bridge.c
@@ -319,7 +319,7 @@ int pci_bridge_initfn(PCIDevice *dev)
     sec_bus->parent_dev = dev;
     sec_bus->map_irq = br->map_irq;
     sec_bus->address_space_mem = &br->address_space_mem;
-    memory_region_init(&br->address_space_mem, "pci_pridge_pci", INT64_MAX);
+    memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX);
     sec_bus->address_space_io = &br->address_space_io;
     memory_region_init(&br->address_space_io, "pci_bridge_io", 65536);
     pci_bridge_region_init(br);
commit 99435906cc92a45d6c2f7e18221d31349836f90e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 12 14:03:13 2011 +0200

    simplify main loop functions
    
    Provide a clean example of how to use the main loop in the tools.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/cpus.c b/cpus.c
index b9f1573..79a7656 100644
--- a/cpus.c
+++ b/cpus.c
@@ -626,11 +626,6 @@ void qemu_init_cpu_loop(void)
     qemu_thread_get_self(&io_thread);
 }
 
-void qemu_main_loop_start(void)
-{
-    resume_all_vcpus();
-}
-
 void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
 {
     struct qemu_work_item wi;
diff --git a/cpus.h b/cpus.h
index 7422584..3525375 100644
--- a/cpus.h
+++ b/cpus.h
@@ -3,7 +3,6 @@
 
 /* cpus.c */
 void qemu_init_cpu_loop(void);
-void qemu_main_loop_start(void);
 void resume_all_vcpus(void);
 void pause_all_vcpus(void);
 void cpu_stop_current(void);
diff --git a/vl.c b/vl.c
index 7914df7..1ddb17b 100644
--- a/vl.c
+++ b/vl.c
@@ -1428,18 +1428,49 @@ void qemu_system_vmstop_request(RunState state)
 
 qemu_irq qemu_system_powerdown;
 
+static bool main_loop_should_exit(void)
+{
+    RunState r;
+    if (qemu_debug_requested()) {
+        vm_stop(RUN_STATE_DEBUG);
+    }
+    if (qemu_shutdown_requested()) {
+        qemu_kill_report();
+        monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
+        if (no_shutdown) {
+            vm_stop(RUN_STATE_SHUTDOWN);
+        } else {
+            return true;
+        }
+    }
+    if (qemu_reset_requested()) {
+        pause_all_vcpus();
+        cpu_synchronize_all_states();
+        qemu_system_reset(VMRESET_REPORT);
+        resume_all_vcpus();
+        if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
+            runstate_check(RUN_STATE_SHUTDOWN)) {
+            runstate_set(RUN_STATE_PAUSED);
+        }
+    }
+    if (qemu_powerdown_requested()) {
+        monitor_protocol_event(QEVENT_POWERDOWN, NULL);
+        qemu_irq_raise(qemu_system_powerdown);
+    }
+    if (qemu_vmstop_requested(&r)) {
+        vm_stop(r);
+    }
+    return false;
+}
+
 static void main_loop(void)
 {
     bool nonblocking;
-    int last_io __attribute__ ((unused)) = 0;
+    int last_io = 0;
 #ifdef CONFIG_PROFILER
     int64_t ti;
 #endif
-    RunState r;
-
-    qemu_main_loop_start();
-
-    for (;;) {
+    do {
         nonblocking = !kvm_enabled() && last_io > 0;
 #ifdef CONFIG_PROFILER
         ti = profile_getclock();
@@ -1448,38 +1479,7 @@ static void main_loop(void)
 #ifdef CONFIG_PROFILER
         dev_time += profile_getclock() - ti;
 #endif
-
-        if (qemu_debug_requested()) {
-            vm_stop(RUN_STATE_DEBUG);
-        }
-        if (qemu_shutdown_requested()) {
-            qemu_kill_report();
-            monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
-            if (no_shutdown) {
-                vm_stop(RUN_STATE_SHUTDOWN);
-            } else
-                break;
-        }
-        if (qemu_reset_requested()) {
-            pause_all_vcpus();
-            cpu_synchronize_all_states();
-            qemu_system_reset(VMRESET_REPORT);
-            resume_all_vcpus();
-            if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
-                runstate_check(RUN_STATE_SHUTDOWN)) {
-                runstate_set(RUN_STATE_PAUSED);
-            }
-        }
-        if (qemu_powerdown_requested()) {
-            monitor_protocol_event(QEVENT_POWERDOWN, NULL);
-            qemu_irq_raise(qemu_system_powerdown);
-        }
-        if (qemu_vmstop_requested(&r)) {
-            vm_stop(r);
-        }
-    }
-    bdrv_close_all();
-    pause_all_vcpus();
+    } while (!main_loop_should_exit());
 }
 
 static void version(void)
@@ -3445,7 +3445,10 @@ int main(int argc, char **argv, char **envp)
 
     os_setup_post();
 
+    resume_all_vcpus();
     main_loop();
+    bdrv_close_all();
+    pause_all_vcpus();
     net_cleanup();
     res_free();
 
commit be08e65e01f1c50fa1552c4f892443cb25bb98e4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 12 14:59:42 2011 +0200

    Revert to a hand-made select loop
    
    This reverts commit c82dc29a9112f34e0a51cad9a412cf6d9d05dfb2
    and 4d88a2ac8643265108ef1fb47ceee5d7b28e19f2.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/iohandler.c b/iohandler.c
index 687dc56..5640d49 100644
--- a/iohandler.c
+++ b/iohandler.c
@@ -81,64 +81,12 @@ int qemu_set_fd_handler2(int fd,
     return 0;
 }
 
-typedef struct IOTrampoline
-{
-    GIOChannel *chan;
-    IOHandler *fd_read;
-    IOHandler *fd_write;
-    void *opaque;
-    guint tag;
-} IOTrampoline;
-
-static gboolean fd_trampoline(GIOChannel *chan, GIOCondition cond, gpointer opaque)
-{
-    IOTrampoline *tramp = opaque;
-
-    if ((cond & G_IO_IN) && tramp->fd_read) {
-        tramp->fd_read(tramp->opaque);
-    }
-
-    if ((cond & G_IO_OUT) && tramp->fd_write) {
-        tramp->fd_write(tramp->opaque);
-    }
-
-    return TRUE;
-}
-
 int qemu_set_fd_handler(int fd,
                         IOHandler *fd_read,
                         IOHandler *fd_write,
                         void *opaque)
 {
-    static IOTrampoline fd_trampolines[FD_SETSIZE];
-    IOTrampoline *tramp = &fd_trampolines[fd];
-
-    if (tramp->tag != 0) {
-        g_io_channel_unref(tramp->chan);
-        g_source_remove(tramp->tag);
-        tramp->tag = 0;
-    }
-
-    if (fd_read || fd_write || opaque) {
-        GIOCondition cond = 0;
-
-        tramp->fd_read = fd_read;
-        tramp->fd_write = fd_write;
-        tramp->opaque = opaque;
-
-        if (fd_read) {
-            cond |= G_IO_IN | G_IO_ERR;
-        }
-
-        if (fd_write) {
-            cond |= G_IO_OUT | G_IO_ERR;
-        }
-
-        tramp->chan = g_io_channel_unix_new(fd);
-        tramp->tag = g_io_add_watch(tramp->chan, cond, fd_trampoline, tramp);
-    }
-
-    return 0;
+    return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
 }
 
 void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds)
commit d3b12f5dec4b27ebab58fb5797cb67bacced773b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Sep 13 10:30:52 2011 +0200

    main-loop: create main-loop.c
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 9e20778..01587c8 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -81,7 +81,7 @@ common-obj-y += $(oslib-obj-y)
 common-obj-$(CONFIG_WIN32) += os-win32.o
 common-obj-$(CONFIG_POSIX) += os-posix.o
 
-common-obj-y += tcg-runtime.o host-utils.o
+common-obj-y += tcg-runtime.o host-utils.o main-loop.o
 common-obj-y += irq.o input.o
 common-obj-$(CONFIG_PTIMER) += ptimer.o
 common-obj-$(CONFIG_MAX7310) += max7310.o
diff --git a/cpus.c b/cpus.c
index 64237b4..b9f1573 100644
--- a/cpus.c
+++ b/cpus.c
@@ -542,143 +542,10 @@ static void qemu_kvm_eat_signals(CPUState *env)
 #endif /* !CONFIG_LINUX */
 
 #ifndef _WIN32
-static int io_thread_fd = -1;
-
-static void qemu_event_increment(void)
-{
-    /* Write 8 bytes to be compatible with eventfd.  */
-    static const uint64_t val = 1;
-    ssize_t ret;
-
-    if (io_thread_fd == -1) {
-        return;
-    }
-    do {
-        ret = write(io_thread_fd, &val, sizeof(val));
-    } while (ret < 0 && errno == EINTR);
-
-    /* EAGAIN is fine, a read must be pending.  */
-    if (ret < 0 && errno != EAGAIN) {
-        fprintf(stderr, "qemu_event_increment: write() failed: %s\n",
-                strerror(errno));
-        exit (1);
-    }
-}
-
-static void qemu_event_read(void *opaque)
-{
-    int fd = (intptr_t)opaque;
-    ssize_t len;
-    char buffer[512];
-
-    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
-    do {
-        len = read(fd, buffer, sizeof(buffer));
-    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
-}
-
-static int qemu_event_init(void)
-{
-    int err;
-    int fds[2];
-
-    err = qemu_eventfd(fds);
-    if (err == -1) {
-        return -errno;
-    }
-    err = fcntl_setfl(fds[0], O_NONBLOCK);
-    if (err < 0) {
-        goto fail;
-    }
-    err = fcntl_setfl(fds[1], O_NONBLOCK);
-    if (err < 0) {
-        goto fail;
-    }
-    qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
-                         (void *)(intptr_t)fds[0]);
-
-    io_thread_fd = fds[1];
-    return 0;
-
-fail:
-    close(fds[0]);
-    close(fds[1]);
-    return err;
-}
-
 static void dummy_signal(int sig)
 {
 }
 
-/* If we have signalfd, we mask out the signals we want to handle and then
- * use signalfd to listen for them.  We rely on whatever the current signal
- * handler is to dispatch the signals when we receive them.
- */
-static void sigfd_handler(void *opaque)
-{
-    int fd = (intptr_t)opaque;
-    struct qemu_signalfd_siginfo info;
-    struct sigaction action;
-    ssize_t len;
-
-    while (1) {
-        do {
-            len = read(fd, &info, sizeof(info));
-        } while (len == -1 && errno == EINTR);
-
-        if (len == -1 && errno == EAGAIN) {
-            break;
-        }
-
-        if (len != sizeof(info)) {
-            printf("read from sigfd returned %zd: %m\n", len);
-            return;
-        }
-
-        sigaction(info.ssi_signo, NULL, &action);
-        if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
-            action.sa_sigaction(info.ssi_signo,
-                                (siginfo_t *)&info, NULL);
-        } else if (action.sa_handler) {
-            action.sa_handler(info.ssi_signo);
-        }
-    }
-}
-
-static int qemu_signal_init(void)
-{
-    int sigfd;
-    sigset_t set;
-
-    /*
-     * SIG_IPI must be blocked in the main thread and must not be caught
-     * by sigwait() in the signal thread. Otherwise, the cpu thread will
-     * not catch it reliably.
-     */
-    sigemptyset(&set);
-    sigaddset(&set, SIG_IPI);
-    pthread_sigmask(SIG_BLOCK, &set, NULL);
-
-    sigemptyset(&set);
-    sigaddset(&set, SIGIO);
-    sigaddset(&set, SIGALRM);
-    sigaddset(&set, SIGBUS);
-    pthread_sigmask(SIG_BLOCK, &set, NULL);
-
-    sigfd = qemu_signalfd(&set);
-    if (sigfd == -1) {
-        fprintf(stderr, "failed to create signalfd\n");
-        return -errno;
-    }
-
-    fcntl_setfl(sigfd, O_NONBLOCK);
-
-    qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
-                         (void *)(intptr_t)sigfd);
-
-    return 0;
-}
-
 static void qemu_kvm_init_cpu_signals(CPUState *env)
 {
     int r;
@@ -722,38 +589,6 @@ static void qemu_tcg_init_cpu_signals(void)
 }
 
 #else /* _WIN32 */
-
-HANDLE qemu_event_handle;
-
-static void dummy_event_handler(void *opaque)
-{
-}
-
-static int qemu_event_init(void)
-{
-    qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (!qemu_event_handle) {
-        fprintf(stderr, "Failed CreateEvent: %ld\n", GetLastError());
-        return -1;
-    }
-    qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
-    return 0;
-}
-
-static void qemu_event_increment(void)
-{
-    if (!SetEvent(qemu_event_handle)) {
-        fprintf(stderr, "qemu_event_increment: SetEvent failed: %ld\n",
-                GetLastError());
-        exit (1);
-    }
-}
-
-static int qemu_signal_init(void)
-{
-    return 0;
-}
-
 static void qemu_kvm_init_cpu_signals(CPUState *env)
 {
     abort();
@@ -779,33 +614,16 @@ static QemuCond qemu_cpu_cond;
 static QemuCond qemu_pause_cond;
 static QemuCond qemu_work_cond;
 
-int qemu_init_main_loop(void)
+void qemu_init_cpu_loop(void)
 {
-    int ret;
-
     qemu_init_sigbus();
-
-    ret = qemu_signal_init();
-    if (ret) {
-        return ret;
-    }
-
-    /* Note eventfd must be drained before signalfd handlers run */
-    ret = qemu_event_init();
-    if (ret) {
-        return ret;
-    }
-
     qemu_cond_init(&qemu_cpu_cond);
     qemu_cond_init(&qemu_pause_cond);
     qemu_cond_init(&qemu_work_cond);
     qemu_cond_init(&qemu_io_proceeded_cond);
     qemu_mutex_init(&qemu_global_mutex);
-    qemu_mutex_lock(&qemu_global_mutex);
 
     qemu_thread_get_self(&io_thread);
-
-    return 0;
 }
 
 void qemu_main_loop_start(void)
@@ -1129,11 +947,6 @@ void qemu_init_vcpu(void *_env)
     }
 }
 
-void qemu_notify_event(void)
-{
-    qemu_event_increment();
-}
-
 void cpu_stop_current(void)
 {
     if (cpu_single_env) {
diff --git a/cpus.h b/cpus.h
index 4ccf986..7422584 100644
--- a/cpus.h
+++ b/cpus.h
@@ -2,6 +2,7 @@
 #define QEMU_CPUS_H
 
 /* cpus.c */
+void qemu_init_cpu_loop(void);
 void qemu_main_loop_start(void);
 void resume_all_vcpus(void);
 void pause_all_vcpus(void);
diff --git a/main-loop.c b/main-loop.c
new file mode 100644
index 0000000..bfecdb7
--- /dev/null
+++ b/main-loop.c
@@ -0,0 +1,495 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "config-host.h"
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <stdbool.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <sys/select.h>
+#include <sys/stat.h>
+#include "compatfd.h"
+#endif
+
+#include <glib.h>
+
+#include "main-loop.h"
+#include "qemu-timer.h"
+#include "slirp/libslirp.h"
+
+#ifndef _WIN32
+
+static int io_thread_fd = -1;
+
+void qemu_notify_event(void)
+{
+    /* Write 8 bytes to be compatible with eventfd.  */
+    static const uint64_t val = 1;
+    ssize_t ret;
+
+    if (io_thread_fd == -1) {
+        return;
+    }
+    do {
+        ret = write(io_thread_fd, &val, sizeof(val));
+    } while (ret < 0 && errno == EINTR);
+
+    /* EAGAIN is fine, a read must be pending.  */
+    if (ret < 0 && errno != EAGAIN) {
+        fprintf(stderr, "qemu_notify_event: write() failed: %s\n",
+                strerror(errno));
+        exit(1);
+    }
+}
+
+static void qemu_event_read(void *opaque)
+{
+    int fd = (intptr_t)opaque;
+    ssize_t len;
+    char buffer[512];
+
+    /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
+    do {
+        len = read(fd, buffer, sizeof(buffer));
+    } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
+}
+
+static int qemu_event_init(void)
+{
+    int err;
+    int fds[2];
+
+    err = qemu_eventfd(fds);
+    if (err == -1) {
+        return -errno;
+    }
+    err = fcntl_setfl(fds[0], O_NONBLOCK);
+    if (err < 0) {
+        goto fail;
+    }
+    err = fcntl_setfl(fds[1], O_NONBLOCK);
+    if (err < 0) {
+        goto fail;
+    }
+    qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
+                         (void *)(intptr_t)fds[0]);
+
+    io_thread_fd = fds[1];
+    return 0;
+
+fail:
+    close(fds[0]);
+    close(fds[1]);
+    return err;
+}
+
+/* If we have signalfd, we mask out the signals we want to handle and then
+ * use signalfd to listen for them.  We rely on whatever the current signal
+ * handler is to dispatch the signals when we receive them.
+ */
+static void sigfd_handler(void *opaque)
+{
+    int fd = (intptr_t)opaque;
+    struct qemu_signalfd_siginfo info;
+    struct sigaction action;
+    ssize_t len;
+
+    while (1) {
+        do {
+            len = read(fd, &info, sizeof(info));
+        } while (len == -1 && errno == EINTR);
+
+        if (len == -1 && errno == EAGAIN) {
+            break;
+        }
+
+        if (len != sizeof(info)) {
+            printf("read from sigfd returned %zd: %m\n", len);
+            return;
+        }
+
+        sigaction(info.ssi_signo, NULL, &action);
+        if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
+            action.sa_sigaction(info.ssi_signo,
+                                (siginfo_t *)&info, NULL);
+        } else if (action.sa_handler) {
+            action.sa_handler(info.ssi_signo);
+        }
+    }
+}
+
+static int qemu_signal_init(void)
+{
+    int sigfd;
+    sigset_t set;
+
+    /*
+     * SIG_IPI must be blocked in the main thread and must not be caught
+     * by sigwait() in the signal thread. Otherwise, the cpu thread will
+     * not catch it reliably.
+     */
+    sigemptyset(&set);
+    sigaddset(&set, SIG_IPI);
+    pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGIO);
+    sigaddset(&set, SIGALRM);
+    sigaddset(&set, SIGBUS);
+    pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+    sigfd = qemu_signalfd(&set);
+    if (sigfd == -1) {
+        fprintf(stderr, "failed to create signalfd\n");
+        return -errno;
+    }
+
+    fcntl_setfl(sigfd, O_NONBLOCK);
+
+    qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
+                         (void *)(intptr_t)sigfd);
+
+    return 0;
+}
+
+#else /* _WIN32 */
+
+HANDLE qemu_event_handle;
+
+static void dummy_event_handler(void *opaque)
+{
+}
+
+static int qemu_event_init(void)
+{
+    qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (!qemu_event_handle) {
+        fprintf(stderr, "Failed CreateEvent: %ld\n", GetLastError());
+        return -1;
+    }
+    qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
+    return 0;
+}
+
+void qemu_notify_event(void)
+{
+    if (!SetEvent(qemu_event_handle)) {
+        fprintf(stderr, "qemu_notify_event: SetEvent failed: %ld\n",
+                GetLastError());
+        exit(1);
+    }
+}
+
+static int qemu_signal_init(void)
+{
+    return 0;
+}
+#endif
+
+int qemu_init_main_loop(void)
+{
+    int ret;
+
+    qemu_mutex_lock_iothread();
+    ret = qemu_signal_init();
+    if (ret) {
+        return ret;
+    }
+
+    /* Note eventfd must be drained before signalfd handlers run */
+    ret = qemu_event_init();
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+
+static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
+static int n_poll_fds;
+static int max_priority;
+
+static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds,
+                             fd_set *xfds, struct timeval *tv)
+{
+    GMainContext *context = g_main_context_default();
+    int i;
+    int timeout = 0, cur_timeout;
+
+    g_main_context_prepare(context, &max_priority);
+
+    n_poll_fds = g_main_context_query(context, max_priority, &timeout,
+                                      poll_fds, ARRAY_SIZE(poll_fds));
+    g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds));
+
+    for (i = 0; i < n_poll_fds; i++) {
+        GPollFD *p = &poll_fds[i];
+
+        if ((p->events & G_IO_IN)) {
+            FD_SET(p->fd, rfds);
+            *max_fd = MAX(*max_fd, p->fd);
+        }
+        if ((p->events & G_IO_OUT)) {
+            FD_SET(p->fd, wfds);
+            *max_fd = MAX(*max_fd, p->fd);
+        }
+        if ((p->events & G_IO_ERR)) {
+            FD_SET(p->fd, xfds);
+            *max_fd = MAX(*max_fd, p->fd);
+        }
+    }
+
+    cur_timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 500) / 1000);
+    if (timeout >= 0 && timeout < cur_timeout) {
+        tv->tv_sec = timeout / 1000;
+        tv->tv_usec = (timeout % 1000) * 1000;
+    }
+}
+
+static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds,
+                             bool err)
+{
+    GMainContext *context = g_main_context_default();
+
+    if (!err) {
+        int i;
+
+        for (i = 0; i < n_poll_fds; i++) {
+            GPollFD *p = &poll_fds[i];
+
+            if ((p->events & G_IO_IN) && FD_ISSET(p->fd, rfds)) {
+                p->revents |= G_IO_IN;
+            }
+            if ((p->events & G_IO_OUT) && FD_ISSET(p->fd, wfds)) {
+                p->revents |= G_IO_OUT;
+            }
+            if ((p->events & G_IO_ERR) && FD_ISSET(p->fd, xfds)) {
+                p->revents |= G_IO_ERR;
+            }
+        }
+    }
+
+    if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) {
+        g_main_context_dispatch(context);
+    }
+}
+
+#ifdef _WIN32
+/***********************************************************/
+/* Polling handling */
+
+typedef struct PollingEntry {
+    PollingFunc *func;
+    void *opaque;
+    struct PollingEntry *next;
+} PollingEntry;
+
+static PollingEntry *first_polling_entry;
+
+int qemu_add_polling_cb(PollingFunc *func, void *opaque)
+{
+    PollingEntry **ppe, *pe;
+    pe = g_malloc0(sizeof(PollingEntry));
+    pe->func = func;
+    pe->opaque = opaque;
+    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
+    *ppe = pe;
+    return 0;
+}
+
+void qemu_del_polling_cb(PollingFunc *func, void *opaque)
+{
+    PollingEntry **ppe, *pe;
+    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
+        pe = *ppe;
+        if (pe->func == func && pe->opaque == opaque) {
+            *ppe = pe->next;
+            g_free(pe);
+            break;
+        }
+    }
+}
+
+/***********************************************************/
+/* Wait objects support */
+typedef struct WaitObjects {
+    int num;
+    HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
+    WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
+    void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
+} WaitObjects;
+
+static WaitObjects wait_objects = {0};
+
+int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
+{
+    WaitObjects *w = &wait_objects;
+    if (w->num >= MAXIMUM_WAIT_OBJECTS) {
+        return -1;
+    }
+    w->events[w->num] = handle;
+    w->func[w->num] = func;
+    w->opaque[w->num] = opaque;
+    w->num++;
+    return 0;
+}
+
+void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
+{
+    int i, found;
+    WaitObjects *w = &wait_objects;
+
+    found = 0;
+    for (i = 0; i < w->num; i++) {
+        if (w->events[i] == handle) {
+            found = 1;
+        }
+        if (found) {
+            w->events[i] = w->events[i + 1];
+            w->func[i] = w->func[i + 1];
+            w->opaque[i] = w->opaque[i + 1];
+        }
+    }
+    if (found) {
+        w->num--;
+    }
+}
+
+static void os_host_main_loop_wait(int *timeout)
+{
+    int ret, ret2, i;
+    PollingEntry *pe;
+
+    /* XXX: need to suppress polling by better using win32 events */
+    ret = 0;
+    for (pe = first_polling_entry; pe != NULL; pe = pe->next) {
+        ret |= pe->func(pe->opaque);
+    }
+    if (ret == 0) {
+        int err;
+        WaitObjects *w = &wait_objects;
+
+        qemu_mutex_unlock_iothread();
+        ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
+        qemu_mutex_lock_iothread();
+        if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
+            if (w->func[ret - WAIT_OBJECT_0]) {
+                w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
+            }
+
+            /* Check for additional signaled events */
+            for (i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
+                /* Check if event is signaled */
+                ret2 = WaitForSingleObject(w->events[i], 0);
+                if (ret2 == WAIT_OBJECT_0) {
+                    if (w->func[i]) {
+                        w->func[i](w->opaque[i]);
+                    }
+                } else if (ret2 != WAIT_TIMEOUT) {
+                    err = GetLastError();
+                    fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
+                }
+            }
+        } else if (ret != WAIT_TIMEOUT) {
+            err = GetLastError();
+            fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
+        }
+    }
+
+    *timeout = 0;
+}
+#else
+static inline void os_host_main_loop_wait(int *timeout)
+{
+}
+#endif
+
+int main_loop_wait(int nonblocking)
+{
+    fd_set rfds, wfds, xfds;
+    int ret, nfds;
+    struct timeval tv;
+    int timeout;
+
+    if (nonblocking) {
+        timeout = 0;
+    } else {
+        timeout = qemu_calculate_timeout();
+        qemu_bh_update_timeout(&timeout);
+    }
+
+    os_host_main_loop_wait(&timeout);
+
+    tv.tv_sec = timeout / 1000;
+    tv.tv_usec = (timeout % 1000) * 1000;
+
+    /* poll any events */
+    /* XXX: separate device handlers from system ones */
+    nfds = -1;
+    FD_ZERO(&rfds);
+    FD_ZERO(&wfds);
+    FD_ZERO(&xfds);
+
+#ifdef CONFIG_SLIRP
+    slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
+#endif
+    qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
+    glib_select_fill(&nfds, &rfds, &wfds, &xfds, &tv);
+
+    if (timeout > 0) {
+        qemu_mutex_unlock_iothread();
+    }
+
+    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
+
+    if (timeout > 0) {
+        qemu_mutex_lock_iothread();
+    }
+
+    glib_select_poll(&rfds, &wfds, &xfds, (ret < 0));
+    qemu_iohandler_poll(&rfds, &wfds, &xfds, ret);
+#ifdef CONFIG_SLIRP
+    slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
+#endif
+
+    qemu_run_all_timers();
+
+    /* Check bottom-halves last in case any of the earlier events triggered
+       them.  */
+    qemu_bh_poll();
+
+    return ret;
+}
diff --git a/main-loop.h b/main-loop.h
index a73b9c0..8a716b1 100644
--- a/main-loop.h
+++ b/main-loop.h
@@ -315,6 +315,30 @@ void qemu_bh_delete(QEMUBH *bh);
 int qemu_add_child_watch(pid_t pid);
 #endif
 
+/**
+ * qemu_mutex_lock_iothread: Lock the main loop mutex.
+ *
+ * This function locks the main loop mutex.  The mutex is taken by
+ * qemu_init_main_loop and always taken except while waiting on
+ * external events (such as with select).  The mutex should be taken
+ * by threads other than the main loop thread when calling
+ * qemu_bh_new(), qemu_set_fd_handler() and basically all other
+ * functions documented in this file.
+ */
+void qemu_mutex_lock_iothread(void);
+
+/**
+ * qemu_mutex_unlock_iothread: Unlock the main loop mutex.
+ *
+ * This function unlocks the main loop mutex.  The mutex is taken by
+ * qemu_init_main_loop and always taken except while waiting on
+ * external events (such as with select).  The mutex should be unlocked
+ * as soon as possible by threads other than the main loop thread,
+ * because it prevents the main loop from processing callbacks,
+ * including timers and bottom halves.
+ */
+void qemu_mutex_unlock_iothread(void);
+
 /* internal interfaces */
 
 void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds);
diff --git a/os-win32.c b/os-win32.c
index f09f01f..7909401 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -48,129 +48,6 @@ int setenv(const char *name, const char *value, int overwrite)
     return result;
 }
 
-/***********************************************************/
-/* Polling handling */
-
-typedef struct PollingEntry {
-    PollingFunc *func;
-    void *opaque;
-    struct PollingEntry *next;
-} PollingEntry;
-
-static PollingEntry *first_polling_entry;
-
-int qemu_add_polling_cb(PollingFunc *func, void *opaque)
-{
-    PollingEntry **ppe, *pe;
-    pe = g_malloc0(sizeof(PollingEntry));
-    pe->func = func;
-    pe->opaque = opaque;
-    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
-    *ppe = pe;
-    return 0;
-}
-
-void qemu_del_polling_cb(PollingFunc *func, void *opaque)
-{
-    PollingEntry **ppe, *pe;
-    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
-        pe = *ppe;
-        if (pe->func == func && pe->opaque == opaque) {
-            *ppe = pe->next;
-            g_free(pe);
-            break;
-        }
-    }
-}
-
-/***********************************************************/
-/* Wait objects support */
-typedef struct WaitObjects {
-    int num;
-    HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
-    WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
-    void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
-} WaitObjects;
-
-static WaitObjects wait_objects = {0};
-
-int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
-{
-    WaitObjects *w = &wait_objects;
-
-    if (w->num >= MAXIMUM_WAIT_OBJECTS)
-        return -1;
-    w->events[w->num] = handle;
-    w->func[w->num] = func;
-    w->opaque[w->num] = opaque;
-    w->num++;
-    return 0;
-}
-
-void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
-{
-    int i, found;
-    WaitObjects *w = &wait_objects;
-
-    found = 0;
-    for (i = 0; i < w->num; i++) {
-        if (w->events[i] == handle)
-            found = 1;
-        if (found) {
-            w->events[i] = w->events[i + 1];
-            w->func[i] = w->func[i + 1];
-            w->opaque[i] = w->opaque[i + 1];
-        }
-    }
-    if (found)
-        w->num--;
-}
-
-void os_host_main_loop_wait(int *timeout)
-{
-    int ret, ret2, i;
-    PollingEntry *pe;
-
-    /* XXX: need to suppress polling by better using win32 events */
-    ret = 0;
-    for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
-        ret |= pe->func(pe->opaque);
-    }
-    if (ret == 0) {
-        int err;
-        WaitObjects *w = &wait_objects;
-
-        qemu_mutex_unlock_iothread();
-        ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
-        qemu_mutex_lock_iothread();
-        if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
-            if (w->func[ret - WAIT_OBJECT_0])
-                w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
-
-            /* Check for additional signaled events */
-            for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
-
-                /* Check if event is signaled */
-                ret2 = WaitForSingleObject(w->events[i], 0);
-                if(ret2 == WAIT_OBJECT_0) {
-                    if (w->func[i])
-                        w->func[i](w->opaque[i]);
-                } else if (ret2 == WAIT_TIMEOUT) {
-                } else {
-                    err = GetLastError();
-                    fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
-                }
-            }
-        } else if (ret == WAIT_TIMEOUT) {
-        } else {
-            err = GetLastError();
-            fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
-        }
-    }
-
-    *timeout = 0;
-}
-
 static BOOL WINAPI qemu_ctrl_handler(DWORD type)
 {
     exit(STATUS_CONTROL_C_EXIT);
diff --git a/qemu-common.h b/qemu-common.h
index 5997f58..1c15cb1 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -169,9 +169,6 @@ const char *path(const char *pathname);
 
 void *qemu_oom_check(void *ptr);
 
-void qemu_mutex_lock_iothread(void);
-void qemu_mutex_unlock_iothread(void);
-
 int qemu_open(const char *name, int flags, ...);
 ssize_t qemu_write_full(int fd, const void *buf, size_t count)
     QEMU_WARN_UNUSED_RESULT;
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 81fd9ab..920499d 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -26,10 +26,6 @@
 #ifndef QEMU_OS_POSIX_H
 #define QEMU_OS_POSIX_H
 
-static inline void os_host_main_loop_wait(int *timeout)
-{
-}
-
 void os_set_line_buffering(void);
 void os_set_proc_name(const char *s);
 void os_setup_signal_handling(void);
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 5a9fd5d..8eda4bd 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -33,8 +33,6 @@
 /* Declaration of ffs() is missing in MinGW's strings.h. */
 int ffs(int i);
 
-void os_host_main_loop_wait(int *timeout);
-
 static inline void os_setup_signal_handling(void) {}
 static inline void os_daemonize(void) {}
 static inline void os_setup_post(void) {}
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index a755123..890fd86 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -3,8 +3,6 @@
 
 #include "qemu-common.h"
 
-#ifdef CONFIG_SLIRP
-
 struct Slirp;
 typedef struct Slirp Slirp;
 
@@ -44,13 +42,4 @@ void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr,
 size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
                              int guest_port);
 
-#else /* !CONFIG_SLIRP */
-
-static inline void slirp_select_fill(int *pnfds, fd_set *readfds,
-                                     fd_set *writefds, fd_set *xfds) { }
-
-static inline void slirp_select_poll(fd_set *readfds, fd_set *writefds,
-                                     fd_set *xfds, int select_error) { }
-#endif /* !CONFIG_SLIRP */
-
 #endif
diff --git a/vl.c b/vl.c
index ef0936a..7914df7 100644
--- a/vl.c
+++ b/vl.c
@@ -1426,128 +1426,6 @@ void qemu_system_vmstop_request(RunState state)
     qemu_notify_event();
 }
 
-static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
-static int n_poll_fds;
-static int max_priority;
-
-static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds,
-                             fd_set *xfds, struct timeval *tv)
-{
-    GMainContext *context = g_main_context_default();
-    int i;
-    int timeout = 0, cur_timeout;
-
-    g_main_context_prepare(context, &max_priority);
-
-    n_poll_fds = g_main_context_query(context, max_priority, &timeout,
-                                      poll_fds, ARRAY_SIZE(poll_fds));
-    g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds));
-
-    for (i = 0; i < n_poll_fds; i++) {
-        GPollFD *p = &poll_fds[i];
-
-        if ((p->events & G_IO_IN)) {
-            FD_SET(p->fd, rfds);
-            *max_fd = MAX(*max_fd, p->fd);
-        }
-        if ((p->events & G_IO_OUT)) {
-            FD_SET(p->fd, wfds);
-            *max_fd = MAX(*max_fd, p->fd);
-        }
-        if ((p->events & G_IO_ERR)) {
-            FD_SET(p->fd, xfds);
-            *max_fd = MAX(*max_fd, p->fd);
-        }
-    }
-
-    cur_timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 500) / 1000);
-    if (timeout >= 0 && timeout < cur_timeout) {
-        tv->tv_sec = timeout / 1000;
-        tv->tv_usec = (timeout % 1000) * 1000;
-    }
-}
-
-static void glib_select_poll(fd_set *rfds, fd_set *wfds, fd_set *xfds,
-                             bool err)
-{
-    GMainContext *context = g_main_context_default();
-
-    if (!err) {
-        int i;
-
-        for (i = 0; i < n_poll_fds; i++) {
-            GPollFD *p = &poll_fds[i];
-
-            if ((p->events & G_IO_IN) && FD_ISSET(p->fd, rfds)) {
-                p->revents |= G_IO_IN;
-            }
-            if ((p->events & G_IO_OUT) && FD_ISSET(p->fd, wfds)) {
-                p->revents |= G_IO_OUT;
-            }
-            if ((p->events & G_IO_ERR) && FD_ISSET(p->fd, xfds)) {
-                p->revents |= G_IO_ERR;
-            }
-        }
-    }
-
-    if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) {
-        g_main_context_dispatch(context);
-    }
-}
-
-int main_loop_wait(int nonblocking)
-{
-    fd_set rfds, wfds, xfds;
-    int ret, nfds;
-    struct timeval tv;
-    int timeout;
-
-    if (nonblocking)
-        timeout = 0;
-    else {
-        timeout = qemu_calculate_timeout();
-        qemu_bh_update_timeout(&timeout);
-    }
-
-    os_host_main_loop_wait(&timeout);
-
-    tv.tv_sec = timeout / 1000;
-    tv.tv_usec = (timeout % 1000) * 1000;
-
-    /* poll any events */
-    /* XXX: separate device handlers from system ones */
-    nfds = -1;
-    FD_ZERO(&rfds);
-    FD_ZERO(&wfds);
-    FD_ZERO(&xfds);
-
-    qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
-    slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
-    glib_select_fill(&nfds, &rfds, &wfds, &xfds, &tv);
-
-    if (timeout > 0) {
-        qemu_mutex_unlock_iothread();
-    }
-
-    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
-
-    if (timeout > 0) {
-        qemu_mutex_lock_iothread();
-    }
-
-    qemu_iohandler_poll(&rfds, &wfds, &xfds, ret);
-    slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
-    glib_select_poll(&rfds, &wfds, &xfds, (ret < 0));
-
-    qemu_run_all_timers();
-
-    /* Check bottom-halves last in case any of the earlier events triggered
-       them.  */
-    qemu_bh_poll();
-
-    return ret;
-}
-
 qemu_irq qemu_system_powerdown;
 
 static void main_loop(void)
@@ -3300,6 +3178,7 @@ int main(int argc, char **argv, char **envp)
 
     configure_accelerator();
 
+    qemu_init_cpu_loop();
     if (qemu_init_main_loop()) {
         fprintf(stderr, "qemu_init_main_loop failed\n");
         exit(1);
commit 44a9b356ad12e63acc1198d1fc356870050a214d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 12 16:44:30 2011 +0200

    main-loop: create main-loop.h
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/async.c b/async.c
index ca13962..332d511 100644
--- a/async.c
+++ b/async.c
@@ -24,6 +24,7 @@
 
 #include "qemu-common.h"
 #include "qemu-aio.h"
+#include "main-loop.h"
 
 /* Anchor of the list of Bottom Halves belonging to the context */
 static struct QEMUBH *first_bh;
diff --git a/cpus.c b/cpus.c
index 1328baa..64237b4 100644
--- a/cpus.c
+++ b/cpus.c
@@ -33,17 +33,12 @@
 
 #include "qemu-thread.h"
 #include "cpus.h"
+#include "main-loop.h"
 
 #ifndef _WIN32
 #include "compatfd.h"
 #endif
 
-#ifdef SIGRTMIN
-#define SIG_IPI (SIGRTMIN+4)
-#else
-#define SIG_IPI SIGUSR1
-#endif
-
 #ifdef CONFIG_LINUX
 
 #include <sys/prctl.h>
diff --git a/cpus.h b/cpus.h
index 5885885..4ccf986 100644
--- a/cpus.h
+++ b/cpus.h
@@ -2,7 +2,6 @@
 #define QEMU_CPUS_H
 
 /* cpus.c */
-int qemu_init_main_loop(void);
 void qemu_main_loop_start(void);
 void resume_all_vcpus(void);
 void pause_all_vcpus(void);
diff --git a/iohandler.c b/iohandler.c
index 4cc1c5a..687dc56 100644
--- a/iohandler.c
+++ b/iohandler.c
@@ -26,6 +26,7 @@
 #include "qemu-common.h"
 #include "qemu-char.h"
 #include "qemu-queue.h"
+#include "main-loop.h"
 
 #ifndef _WIN32
 #include <sys/wait.h>
diff --git a/main-loop.h b/main-loop.h
new file mode 100644
index 0000000..a73b9c0
--- /dev/null
+++ b/main-loop.h
@@ -0,0 +1,327 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef QEMU_MAIN_LOOP_H
+#define QEMU_MAIN_LOOP_H 1
+
+#ifdef SIGRTMIN
+#define SIG_IPI (SIGRTMIN+4)
+#else
+#define SIG_IPI SIGUSR1
+#endif
+
+/**
+ * qemu_init_main_loop: Set up the process so that it can run the main loop.
+ *
+ * This includes setting up signal handlers.  It should be called before
+ * any other threads are created.  In addition, threads other than the
+ * main one should block signals that are trapped by the main loop.
+ * For simplicity, you can consider these signals to be safe: SIGUSR1,
+ * SIGUSR2, thread signals (SIGFPE, SIGILL, SIGSEGV, SIGBUS) and real-time
+ * signals if available.  Remember that Windows in practice does not have
+ * signals, though.
+ */
+int qemu_init_main_loop(void);
+
+/**
+ * main_loop_wait: Run one iteration of the main loop.
+ *
+ * If @nonblocking is true, poll for events, otherwise suspend until
+ * one actually occurs.  The main loop usually consists of a loop that
+ * repeatedly calls main_loop_wait(false).
+ *
+ * Main loop services include file descriptor callbacks, bottom halves
+ * and timers (defined in qemu-timer.h).  Bottom halves are similar to timers
+ * that execute immediately, but have a lower overhead and scheduling them
+ * is wait-free, thread-safe and signal-safe.
+ *
+ * It is sometimes useful to put a whole program in a coroutine.  In this
+ * case, the coroutine actually should be started from within the main loop,
+ * so that the main loop can run whenever the coroutine yields.  To do this,
+ * you can use a bottom half to enter the coroutine as soon as the main loop
+ * starts:
+ *
+ *     void enter_co_bh(void *opaque) {
+ *         QEMUCoroutine *co = opaque;
+ *         qemu_coroutine_enter(co, NULL);
+ *     }
+ *
+ *     ...
+ *     QEMUCoroutine *co = qemu_coroutine_create(coroutine_entry);
+ *     QEMUBH *start_bh = qemu_bh_new(enter_co_bh, co);
+ *     qemu_bh_schedule(start_bh);
+ *     while (...) {
+ *         main_loop_wait(false);
+ *     }
+ *
+ * (In the future we may provide a wrapper for this).
+ *
+ * @nonblocking: Whether the caller should block until an event occurs.
+ */
+int main_loop_wait(int nonblocking);
+
+/**
+ * qemu_notify_event: Force processing of pending events.
+ *
+ * Similar to signaling a condition variable, qemu_notify_event forces
+ * main_loop_wait to look at pending events and exit.  The caller of
+ * main_loop_wait will usually call it again very soon, so qemu_notify_event
+ * also has the side effect of recalculating the sets of file descriptors
+ * that the main loop waits for.
+ *
+ * Calling qemu_notify_event is rarely necessary, because main loop
+ * services (bottom halves and timers) call it themselves.  One notable
+ * exception occurs when using qemu_set_fd_handler2 (see below).
+ */
+void qemu_notify_event(void);
+
+#ifdef _WIN32
+/* return TRUE if no sleep should be done afterwards */
+typedef int PollingFunc(void *opaque);
+
+/**
+ * qemu_add_polling_cb: Register a Windows-specific polling callback
+ *
+ * Currently, under Windows some events are polled rather than waited for.
+ * Polling callbacks do not ensure that @func is called timely, because
+ * the main loop might wait for an arbitrarily long time.  If possible,
+ * you should instead create a separate thread that does a blocking poll
+ * and set a Win32 event object.  The event can then be passed to
+ * qemu_add_wait_object.
+ *
+ * Polling callbacks really have nothing Windows specific in them, but
+ * as they are a hack and are currenly not necessary under POSIX systems,
+ * they are only available when QEMU is running under Windows.
+ *
+ * @func: The function that does the polling, and returns 1 to force
+ * immediate completion of main_loop_wait.
+ * @opaque: A pointer-size value that is passed to @func.
+ */
+int qemu_add_polling_cb(PollingFunc *func, void *opaque);
+
+/**
+ * qemu_del_polling_cb: Unregister a Windows-specific polling callback
+ *
+ * This function removes a callback that was registered with
+ * qemu_add_polling_cb.
+ *
+ * @func: The function that was passed to qemu_add_polling_cb.
+ * @opaque: A pointer-size value that was passed to qemu_add_polling_cb.
+ */
+void qemu_del_polling_cb(PollingFunc *func, void *opaque);
+
+/* Wait objects handling */
+typedef void WaitObjectFunc(void *opaque);
+
+/**
+ * qemu_add_wait_object: Register a callback for a Windows handle
+ *
+ * Under Windows, the iohandler mechanism can only be used with sockets.
+ * QEMU must use the WaitForMultipleObjects API to wait on other handles.
+ * This function registers a #HANDLE with QEMU, so that it will be included
+ * in the main loop's calls to WaitForMultipleObjects.  When the handle
+ * is in a signaled state, QEMU will call @func.
+ *
+ * @handle: The Windows handle to be observed.
+ * @func: A function to be called when @handle is in a signaled state.
+ * @opaque: A pointer-size value that is passed to @func.
+ */
+int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
+
+/**
+ * qemu_del_wait_object: Unregister a callback for a Windows handle
+ *
+ * This function removes a callback that was registered with
+ * qemu_add_wait_object.
+ *
+ * @func: The function that was passed to qemu_add_wait_object.
+ * @opaque: A pointer-size value that was passed to qemu_add_wait_object.
+ */
+void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
+#endif
+
+/* async I/O support */
+
+typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
+typedef int IOCanReadHandler(void *opaque);
+typedef void IOHandler(void *opaque);
+
+/**
+ * qemu_set_fd_handler2: Register a file descriptor with the main loop
+ *
+ * This function tells the main loop to wake up whenever one of the
+ * following conditions is true:
+ *
+ * 1) if @fd_write is not %NULL, when the file descriptor is writable;
+ *
+ * 2) if @fd_read is not %NULL, when the file descriptor is readable.
+ *
+ * @fd_read_poll can be used to disable the @fd_read callback temporarily.
+ * This is useful to avoid calling qemu_set_fd_handler2 every time the
+ * client becomes interested in reading (or dually, stops being interested).
+ * A typical example is when @fd is a listening socket and you want to bound
+ * the number of active clients.  Remember to call qemu_notify_event whenever
+ * the condition may change from %false to %true.
+ *
+ * The callbacks that are set up by qemu_set_fd_handler2 are level-triggered.
+ * If @fd_read does not read from @fd, or @fd_write does not write to @fd
+ * until its buffers are full, they will be called again on the next
+ * iteration.
+ *
+ * @fd: The file descriptor to be observed.  Under Windows it must be
+ * a #SOCKET.
+ *
+ * @fd_read_poll: A function that returns 1 if the @fd_read callback
+ * should be fired.  If the function returns 0, the main loop will not
+ * end its iteration even if @fd becomes readable.
+ *
+ * @fd_read: A level-triggered callback that is fired if @fd is readable
+ * at the beginning of a main loop iteration, or if it becomes readable
+ * during one.
+ *
+ * @fd_write: A level-triggered callback that is fired when @fd is writable
+ * at the beginning of a main loop iteration, or if it becomes writable
+ * during one.
+ *
+ * @opaque: A pointer-sized value that is passed to @fd_read_poll,
+ * @fd_read and @fd_write.
+ */
+int qemu_set_fd_handler2(int fd,
+                         IOCanReadHandler *fd_read_poll,
+                         IOHandler *fd_read,
+                         IOHandler *fd_write,
+                         void *opaque);
+
+/**
+ * qemu_set_fd_handler: Register a file descriptor with the main loop
+ *
+ * This function tells the main loop to wake up whenever one of the
+ * following conditions is true:
+ *
+ * 1) if @fd_write is not %NULL, when the file descriptor is writable;
+ *
+ * 2) if @fd_read is not %NULL, when the file descriptor is readable.
+ *
+ * The callbacks that are set up by qemu_set_fd_handler are level-triggered.
+ * If @fd_read does not read from @fd, or @fd_write does not write to @fd
+ * until its buffers are full, they will be called again on the next
+ * iteration.
+ *
+ * @fd: The file descriptor to be observed.  Under Windows it must be
+ * a #SOCKET.
+ *
+ * @fd_read: A level-triggered callback that is fired if @fd is readable
+ * at the beginning of a main loop iteration, or if it becomes readable
+ * during one.
+ *
+ * @fd_write: A level-triggered callback that is fired when @fd is writable
+ * at the beginning of a main loop iteration, or if it becomes writable
+ * during one.
+ *
+ * @opaque: A pointer-sized value that is passed to @fd_read and @fd_write.
+ */
+int qemu_set_fd_handler(int fd,
+                        IOHandler *fd_read,
+                        IOHandler *fd_write,
+                        void *opaque);
+
+typedef struct QEMUBH QEMUBH;
+typedef void QEMUBHFunc(void *opaque);
+
+/**
+ * qemu_bh_new: Allocate a new bottom half structure.
+ *
+ * Bottom halves are lightweight callbacks whose invocation is guaranteed
+ * to be wait-free, thread-safe and signal-safe.  The #QEMUBH structure
+ * is opaque and must be allocated prior to its use.
+ */
+QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
+
+/**
+ * qemu_bh_schedule: Schedule a bottom half.
+ *
+ * Scheduling a bottom half interrupts the main loop and causes the
+ * execution of the callback that was passed to qemu_bh_new.
+ *
+ * Bottom halves that are scheduled from a bottom half handler are instantly
+ * invoked.  This can create an infinite loop if a bottom half handler
+ * schedules itself.
+ *
+ * @bh: The bottom half to be scheduled.
+ */
+void qemu_bh_schedule(QEMUBH *bh);
+
+/**
+ * qemu_bh_cancel: Cancel execution of a bottom half.
+ *
+ * Canceling execution of a bottom half undoes the effect of calls to
+ * qemu_bh_schedule without freeing its resources yet.  While cancellation
+ * itself is also wait-free and thread-safe, it can of course race with the
+ * loop that executes bottom halves unless you are holding the iothread
+ * mutex.  This makes it mostly useless if you are not holding the mutex.
+ *
+ * @bh: The bottom half to be canceled.
+ */
+void qemu_bh_cancel(QEMUBH *bh);
+
+/**
+ *qemu_bh_delete: Cancel execution of a bottom half and free its resources.
+ *
+ * Deleting a bottom half frees the memory that was allocated for it by
+ * qemu_bh_new.  It also implies canceling the bottom half if it was
+ * scheduled.
+ *
+ * @bh: The bottom half to be deleted.
+ */
+void qemu_bh_delete(QEMUBH *bh);
+
+#ifdef CONFIG_POSIX
+/**
+ * qemu_add_child_watch: Register a child process for reaping.
+ *
+ * Under POSIX systems, a parent process must read the exit status of
+ * its child processes using waitpid, or the operating system will not
+ * free some of the resources attached to that process.
+ *
+ * This function directs the QEMU main loop to observe a child process
+ * and call waitpid as soon as it exits; the watch is then removed
+ * automatically.  It is useful whenever QEMU forks a child process
+ * but will find out about its termination by other means such as a
+ * "broken pipe".
+ *
+ * @pid: The pid that QEMU should observe.
+ */
+int qemu_add_child_watch(pid_t pid);
+#endif
+
+/* internal interfaces */
+
+void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds);
+void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc);
+
+void qemu_bh_schedule_idle(QEMUBH *bh);
+int qemu_bh_poll(void);
+void qemu_bh_update_timeout(int *timeout);
+
+#endif
diff --git a/qemu-char.h b/qemu-char.h
index eebbdd8..7efcf99 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -7,6 +7,7 @@
 #include "qemu-config.h"
 #include "qobject.h"
 #include "qstring.h"
+#include "main-loop.h"
 
 /* character device */
 
@@ -237,15 +238,4 @@ void qemu_chr_close_mem(CharDriverState *chr);
 QString *qemu_chr_mem_to_qs(CharDriverState *chr);
 size_t qemu_chr_mem_osize(const CharDriverState *chr);
 
-/* async I/O support */
-
-int qemu_set_fd_handler2(int fd,
-                         IOCanReadHandler *fd_read_poll,
-                         IOHandler *fd_read,
-                         IOHandler *fd_write,
-                         void *opaque);
-int qemu_set_fd_handler(int fd,
-                        IOHandler *fd_read,
-                        IOHandler *fd_write,
-                        void *opaque);
 #endif
diff --git a/qemu-common.h b/qemu-common.h
index fffdefd..5997f58 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -13,7 +13,6 @@
 
 typedef struct QEMUTimer QEMUTimer;
 typedef struct QEMUFile QEMUFile;
-typedef struct QEMUBH QEMUBH;
 typedef struct DeviceState DeviceState;
 
 struct Monitor;
@@ -117,23 +116,6 @@ extern int use_icount;
 int qemu_main(int argc, char **argv, char **envp);
 #endif
 
-/* bottom halves */
-typedef void QEMUBHFunc(void *opaque);
-
-QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
-void qemu_bh_schedule(QEMUBH *bh);
-/* Bottom halfs that are scheduled from a bottom half handler are instantly
- * invoked.  This can create an infinite loop if a bottom half handler
- * schedules itself.  qemu_bh_schedule_idle() avoids this infinite loop by
- * ensuring that the bottom half isn't executed until the next main loop
- * iteration.
- */
-void qemu_bh_schedule_idle(QEMUBH *bh);
-void qemu_bh_cancel(QEMUBH *bh);
-void qemu_bh_delete(QEMUBH *bh);
-int qemu_bh_poll(void);
-void qemu_bh_update_timeout(int *timeout);
-
 void qemu_get_timedate(struct tm *tm, int offset);
 int qemu_timedate_diff(struct tm *tm);
 
@@ -196,7 +178,6 @@ ssize_t qemu_write_full(int fd, const void *buf, size_t count)
 void qemu_set_cloexec(int fd);
 
 #ifndef _WIN32
-int qemu_add_child_watch(pid_t pid);
 int qemu_eventfd(int pipefd[2]);
 int qemu_pipe(int pipefd[2]);
 #endif
@@ -211,14 +192,6 @@ int qemu_pipe(int pipefd[2]);
 
 void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
 
-/* IO callbacks.  */
-typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
-typedef int IOCanReadHandler(void *opaque);
-typedef void IOHandler(void *opaque);
-
-void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds);
-void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc);
-
 struct ParallelIOArg {
     void *buffer;
     int count;
@@ -280,9 +253,6 @@ void cpu_exec_init_all(void);
 void cpu_save(QEMUFile *f, void *opaque);
 int cpu_load(QEMUFile *f, void *opaque, int version_id);
 
-/* Force QEMU to process pending events */
-void qemu_notify_event(void);
-
 /* Unblock cpu */
 void qemu_cpu_kick(void *env);
 void qemu_cpu_kick_self(void);
diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c
index 2a385a3..6b58160 100644
--- a/qemu-coroutine-lock.c
+++ b/qemu-coroutine-lock.c
@@ -26,6 +26,7 @@
 #include "qemu-coroutine.h"
 #include "qemu-coroutine-int.h"
 #include "qemu-queue.h"
+#include "main-loop.h"
 #include "trace.h"
 
 static QTAILQ_HEAD(, Coroutine) unlock_bh_queue =
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 8a069d7..5a9fd5d 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -28,24 +28,11 @@
 
 #include <windows.h>
 #include <winsock2.h>
+#include "main-loop.h"
 
 /* Declaration of ffs() is missing in MinGW's strings.h. */
 int ffs(int i);
 
-/* Polling handling */
-
-/* return TRUE if no sleep should be done afterwards */
-typedef int PollingFunc(void *opaque);
-
-int qemu_add_polling_cb(PollingFunc *func, void *opaque);
-void qemu_del_polling_cb(PollingFunc *func, void *opaque);
-
-/* Wait objects handling */
-typedef void WaitObjectFunc(void *opaque);
-
-int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
-void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
-
 void os_host_main_loop_wait(int *timeout);
 
 static inline void os_setup_signal_handling(void) {}
diff --git a/qemu-timer.h b/qemu-timer.h
index 9f4ffed..67ca72e 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -2,6 +2,7 @@
 #define QEMU_TIMER_H
 
 #include "qemu-common.h"
+#include "main-loop.h"
 #include "notify.h"
 #include <time.h>
 #include <sys/time.h>
diff --git a/sysemu.h b/sysemu.h
index 7d288f8..22cd720 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -8,6 +8,7 @@
 #include "qemu-timer.h"
 #include "qapi-types.h"
 #include "notify.h"
+#include "main-loop.h"
 
 /* vl.c */
 
@@ -64,8 +65,6 @@ void do_info_snapshots(Monitor *mon);
 
 void qemu_announce_self(void);
 
-int main_loop_wait(int nonblocking);
-
 bool qemu_savevm_state_blocked(Monitor *mon);
 int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
                             int shared);
diff --git a/vl.c b/vl.c
index cf25d65..ef0936a 100644
--- a/vl.c
+++ b/vl.c
@@ -148,6 +148,7 @@ int main(int argc, char **argv)
 #include "qemu-objects.h"
 #include "qemu-options.h"
 #include "qmp-commands.h"
+#include "main-loop.h"
 #ifdef CONFIG_VIRTFS
 #include "fsdev/qemu-fsdev.h"
 #endif
commit fbdc14ebf8d16f00a87b6f4cdb4799ccfb6469be
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Sep 27 18:23:14 2011 +0200

    qemu-timer: do not use RunState change handlers
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index 58926dd..f11a28d 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -273,7 +273,11 @@ static QEMUClock *qemu_new_clock(int type)
 
 void qemu_clock_enable(QEMUClock *clock, int enabled)
 {
+    bool old = clock->enabled;
     clock->enabled = enabled;
+    if (enabled && !old) {
+        qemu_rearm_alarm_timer(alarm_timer);
+    }
 }
 
 int64_t qemu_clock_has_timers(QEMUClock *clock)
@@ -806,13 +810,6 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t,
 
 #endif /* _WIN32 */
 
-static void alarm_timer_on_change_state_rearm(void *opaque, int running,
-                                              RunState state)
-{
-    if (running)
-        qemu_rearm_alarm_timer((struct qemu_alarm_timer *) opaque);
-}
-
 static void quit_timers(void)
 {
     struct qemu_alarm_timer *t = alarm_timer;
@@ -842,7 +839,6 @@ int init_timer_alarm(void)
     atexit(quit_timers);
     t->pending = 1;
     alarm_timer = t;
-    qemu_add_vm_change_state_handler(alarm_timer_on_change_state_rearm, t);
 
     return 0;
 
commit 2ff68d0738768643e796ab39f007c1f3858e67f1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 12 16:21:44 2011 +0200

    qemu-timer: move more stuff out of qemu-timer.c
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index 7fa81e1..58926dd 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -266,11 +266,8 @@ static QEMUClock *qemu_new_clock(int type)
     clock = g_malloc0(sizeof(QEMUClock));
     clock->type = type;
     clock->enabled = 1;
+    clock->last = INT64_MIN;
     notifier_list_init(&clock->reset_notifiers);
-    /* required to detect & report backward jumps */
-    if (type == QEMU_CLOCK_HOST) {
-        clock->last = get_clock_realtime();
-    }
     return clock;
 }
 
@@ -344,7 +341,7 @@ void qemu_del_timer(QEMUTimer *ts)
 
 /* modify the current timer so that it will be fired when current_time
    >= expire_time. The corresponding callback will be called. */
-static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
+void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
 {
     QEMUTimer **pt, *t;
 
@@ -378,8 +375,6 @@ static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
     }
 }
 
-/* modify the current timer so that it will be fired when current_time
-   >= expire_time. The corresponding callback will be called. */
 void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
 {
     qemu_mod_timer_ns(ts, expire_time * ts->scale);
@@ -464,33 +459,11 @@ void init_clocks(void)
     rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
     vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
     host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
-
-    rtc_clock = host_clock;
 }
 
-/* save a timer */
-void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
+uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts)
 {
-    uint64_t expire_time;
-
-    if (qemu_timer_pending(ts)) {
-        expire_time = ts->expire_time;
-    } else {
-        expire_time = -1;
-    }
-    qemu_put_be64(f, expire_time);
-}
-
-void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
-{
-    uint64_t expire_time;
-
-    expire_time = qemu_get_be64(f);
-    if (expire_time != -1) {
-        qemu_mod_timer_ns(ts, expire_time);
-    } else {
-        qemu_del_timer(ts);
-    }
+    return qemu_timer_pending(ts) ? ts->expire_time : -1;
 }
 
 void qemu_run_all_timers(void)
diff --git a/qemu-timer.h b/qemu-timer.h
index b4ea201..9f4ffed 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -52,9 +52,11 @@ QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
                           QEMUTimerCB *cb, void *opaque);
 void qemu_free_timer(QEMUTimer *ts);
 void qemu_del_timer(QEMUTimer *ts);
+void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time);
 void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
 int qemu_timer_pending(QEMUTimer *ts);
 int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
+uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts);
 
 void qemu_run_all_timers(void);
 int qemu_alarm_pending(void);
diff --git a/savevm.c b/savevm.c
index cf79a56..f01838f 100644
--- a/savevm.c
+++ b/savevm.c
@@ -81,6 +81,7 @@
 #include "migration.h"
 #include "qemu_socket.h"
 #include "qemu-queue.h"
+#include "qemu-timer.h"
 #include "cpus.h"
 
 #define SELF_ANNOUNCE_ROUNDS 5
@@ -712,6 +713,30 @@ uint64_t qemu_get_be64(QEMUFile *f)
     return v;
 }
 
+
+/* timer */
+
+void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
+{
+    uint64_t expire_time;
+
+    expire_time = qemu_timer_expire_time_ns(ts);
+    qemu_put_be64(f, expire_time);
+}
+
+void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
+{
+    uint64_t expire_time;
+
+    expire_time = qemu_get_be64(f);
+    if (expire_time != -1) {
+        qemu_mod_timer_ns(ts, expire_time);
+    } else {
+        qemu_del_timer(ts);
+    }
+}
+
+
 /* bool */
 
 static int get_bool(QEMUFile *f, void *pv, size_t size)
diff --git a/vl.c b/vl.c
index 6bd7e71..cf25d65 100644
--- a/vl.c
+++ b/vl.c
@@ -2311,6 +2311,7 @@ int main(int argc, char **argv, char **envp)
     runstate_init();
 
     init_clocks();
+    rtc_clock = host_clock;
 
     qemu_cache_utils_init(envp);
 
commit 4260a7391190d2d01fac50ee3d738a15bab6b98e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 19 10:18:51 2011 +0200

    qemu-timer: use atexit for quit_timers
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index d8507e3..7fa81e1 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -840,6 +840,13 @@ static void alarm_timer_on_change_state_rearm(void *opaque, int running,
         qemu_rearm_alarm_timer((struct qemu_alarm_timer *) opaque);
 }
 
+static void quit_timers(void)
+{
+    struct qemu_alarm_timer *t = alarm_timer;
+    alarm_timer = NULL;
+    t->stop(t);
+}
+
 int init_timer_alarm(void)
 {
     struct qemu_alarm_timer *t = NULL;
@@ -859,6 +866,7 @@ int init_timer_alarm(void)
     }
 
     /* first event is at time 0 */
+    atexit(quit_timers);
     t->pending = 1;
     alarm_timer = t;
     qemu_add_vm_change_state_handler(alarm_timer_on_change_state_rearm, t);
@@ -869,13 +877,6 @@ fail:
     return err;
 }
 
-void quit_timers(void)
-{
-    struct qemu_alarm_timer *t = alarm_timer;
-    alarm_timer = NULL;
-    t->stop(t);
-}
-
 int qemu_calculate_timeout(void)
 {
     return 1000;
diff --git a/qemu-timer.h b/qemu-timer.h
index ce576b9..b4ea201 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -62,7 +62,6 @@ void configure_alarms(char const *opt);
 int qemu_calculate_timeout(void);
 void init_clocks(void);
 int init_timer_alarm(void);
-void quit_timers(void);
 
 int64_t cpu_get_ticks(void);
 void cpu_enable_ticks(void);
diff --git a/vl.c b/vl.c
index 66f70fb..6bd7e71 100644
--- a/vl.c
+++ b/vl.c
@@ -3565,7 +3565,6 @@ int main(int argc, char **argv, char **envp)
     os_setup_post();
 
     main_loop();
-    quit_timers();
     net_cleanup();
     res_free();
 
commit a5c57d64aa61b700db444c4864a1da11f1165db6
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 12 14:40:36 2011 +0200

    qemu-timer: do not refer to runstate_is_running()
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/cpus.c b/cpus.c
index 21538e6..1328baa 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1059,6 +1059,7 @@ void pause_all_vcpus(void)
 {
     CPUState *penv = first_cpu;
 
+    qemu_clock_enable(vm_clock, false);
     while (penv) {
         penv->stop = 1;
         qemu_cpu_kick(penv);
diff --git a/qemu-timer.c b/qemu-timer.c
index 8129af6..d8507e3 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -504,10 +504,7 @@ void qemu_run_all_timers(void)
     }
 
     /* vm time timers */
-    if (runstate_is_running()) {
-        qemu_run_timers(vm_clock);
-    }
-
+    qemu_run_timers(vm_clock);
     qemu_run_timers(rt_clock);
     qemu_run_timers(host_clock);
 }
commit 946fb27c1dc158f10a6e3ce0374a161dce04c27b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 12 13:57:37 2011 +0200

    qemu-timer: move icount to cpus.c
    
    None of this is needed by tools, and most of it can even be made static
    inside cpus.c.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/cpus.c b/cpus.c
index 5f5b763..21538e6 100644
--- a/cpus.c
+++ b/cpus.c
@@ -65,6 +65,281 @@
 static CPUState *next_cpu;
 
 /***********************************************************/
+/* guest cycle counter */
+
+/* Conversion factor from emulated instructions to virtual clock ticks.  */
+static int icount_time_shift;
+/* Arbitrarily pick 1MIPS as the minimum allowable speed.  */
+#define MAX_ICOUNT_SHIFT 10
+/* Compensate for varying guest execution speed.  */
+static int64_t qemu_icount_bias;
+static QEMUTimer *icount_rt_timer;
+static QEMUTimer *icount_vm_timer;
+static QEMUTimer *icount_warp_timer;
+static int64_t vm_clock_warp_start;
+static int64_t qemu_icount;
+
+typedef struct TimersState {
+    int64_t cpu_ticks_prev;
+    int64_t cpu_ticks_offset;
+    int64_t cpu_clock_offset;
+    int32_t cpu_ticks_enabled;
+    int64_t dummy;
+} TimersState;
+
+TimersState timers_state;
+
+/* Return the virtual CPU time, based on the instruction counter.  */
+int64_t cpu_get_icount(void)
+{
+    int64_t icount;
+    CPUState *env = cpu_single_env;;
+
+    icount = qemu_icount;
+    if (env) {
+        if (!can_do_io(env)) {
+            fprintf(stderr, "Bad clock read\n");
+        }
+        icount -= (env->icount_decr.u16.low + env->icount_extra);
+    }
+    return qemu_icount_bias + (icount << icount_time_shift);
+}
+
+/* return the host CPU cycle counter and handle stop/restart */
+int64_t cpu_get_ticks(void)
+{
+    if (use_icount) {
+        return cpu_get_icount();
+    }
+    if (!timers_state.cpu_ticks_enabled) {
+        return timers_state.cpu_ticks_offset;
+    } else {
+        int64_t ticks;
+        ticks = cpu_get_real_ticks();
+        if (timers_state.cpu_ticks_prev > ticks) {
+            /* Note: non increasing ticks may happen if the host uses
+               software suspend */
+            timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
+        }
+        timers_state.cpu_ticks_prev = ticks;
+        return ticks + timers_state.cpu_ticks_offset;
+    }
+}
+
+/* return the host CPU monotonic timer and handle stop/restart */
+int64_t cpu_get_clock(void)
+{
+    int64_t ti;
+    if (!timers_state.cpu_ticks_enabled) {
+        return timers_state.cpu_clock_offset;
+    } else {
+        ti = get_clock();
+        return ti + timers_state.cpu_clock_offset;
+    }
+}
+
+/* enable cpu_get_ticks() */
+void cpu_enable_ticks(void)
+{
+    if (!timers_state.cpu_ticks_enabled) {
+        timers_state.cpu_ticks_offset -= cpu_get_real_ticks();
+        timers_state.cpu_clock_offset -= get_clock();
+        timers_state.cpu_ticks_enabled = 1;
+    }
+}
+
+/* disable cpu_get_ticks() : the clock is stopped. You must not call
+   cpu_get_ticks() after that.  */
+void cpu_disable_ticks(void)
+{
+    if (timers_state.cpu_ticks_enabled) {
+        timers_state.cpu_ticks_offset = cpu_get_ticks();
+        timers_state.cpu_clock_offset = cpu_get_clock();
+        timers_state.cpu_ticks_enabled = 0;
+    }
+}
+
+/* Correlation between real and virtual time is always going to be
+   fairly approximate, so ignore small variation.
+   When the guest is idle real and virtual time will be aligned in
+   the IO wait loop.  */
+#define ICOUNT_WOBBLE (get_ticks_per_sec() / 10)
+
+static void icount_adjust(void)
+{
+    int64_t cur_time;
+    int64_t cur_icount;
+    int64_t delta;
+    static int64_t last_delta;
+    /* If the VM is not running, then do nothing.  */
+    if (!runstate_is_running()) {
+        return;
+    }
+    cur_time = cpu_get_clock();
+    cur_icount = qemu_get_clock_ns(vm_clock);
+    delta = cur_icount - cur_time;
+    /* FIXME: This is a very crude algorithm, somewhat prone to oscillation.  */
+    if (delta > 0
+        && last_delta + ICOUNT_WOBBLE < delta * 2
+        && icount_time_shift > 0) {
+        /* The guest is getting too far ahead.  Slow time down.  */
+        icount_time_shift--;
+    }
+    if (delta < 0
+        && last_delta - ICOUNT_WOBBLE > delta * 2
+        && icount_time_shift < MAX_ICOUNT_SHIFT) {
+        /* The guest is getting too far behind.  Speed time up.  */
+        icount_time_shift++;
+    }
+    last_delta = delta;
+    qemu_icount_bias = cur_icount - (qemu_icount << icount_time_shift);
+}
+
+static void icount_adjust_rt(void *opaque)
+{
+    qemu_mod_timer(icount_rt_timer,
+                   qemu_get_clock_ms(rt_clock) + 1000);
+    icount_adjust();
+}
+
+static void icount_adjust_vm(void *opaque)
+{
+    qemu_mod_timer(icount_vm_timer,
+                   qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
+    icount_adjust();
+}
+
+static int64_t qemu_icount_round(int64_t count)
+{
+    return (count + (1 << icount_time_shift) - 1) >> icount_time_shift;
+}
+
+static void icount_warp_rt(void *opaque)
+{
+    if (vm_clock_warp_start == -1) {
+        return;
+    }
+
+    if (runstate_is_running()) {
+        int64_t clock = qemu_get_clock_ns(rt_clock);
+        int64_t warp_delta = clock - vm_clock_warp_start;
+        if (use_icount == 1) {
+            qemu_icount_bias += warp_delta;
+        } else {
+            /*
+             * In adaptive mode, do not let the vm_clock run too
+             * far ahead of real time.
+             */
+            int64_t cur_time = cpu_get_clock();
+            int64_t cur_icount = qemu_get_clock_ns(vm_clock);
+            int64_t delta = cur_time - cur_icount;
+            qemu_icount_bias += MIN(warp_delta, delta);
+        }
+        if (qemu_clock_expired(vm_clock)) {
+            qemu_notify_event();
+        }
+    }
+    vm_clock_warp_start = -1;
+}
+
+void qemu_clock_warp(QEMUClock *clock)
+{
+    int64_t deadline;
+
+    /*
+     * There are too many global variables to make the "warp" behavior
+     * applicable to other clocks.  But a clock argument removes the
+     * need for if statements all over the place.
+     */
+    if (clock != vm_clock || !use_icount) {
+        return;
+    }
+
+    /*
+     * If the CPUs have been sleeping, advance the vm_clock timer now.  This
+     * ensures that the deadline for the timer is computed correctly below.
+     * This also makes sure that the insn counter is synchronized before the
+     * CPU starts running, in case the CPU is woken by an event other than
+     * the earliest vm_clock timer.
+     */
+    icount_warp_rt(NULL);
+    if (!all_cpu_threads_idle() || !qemu_clock_has_timers(vm_clock)) {
+        qemu_del_timer(icount_warp_timer);
+        return;
+    }
+
+    vm_clock_warp_start = qemu_get_clock_ns(rt_clock);
+    deadline = qemu_clock_deadline(vm_clock);
+    if (deadline > 0) {
+        /*
+         * Ensure the vm_clock proceeds even when the virtual CPU goes to
+         * sleep.  Otherwise, the CPU might be waiting for a future timer
+         * interrupt to wake it up, but the interrupt never comes because
+         * the vCPU isn't running any insns and thus doesn't advance the
+         * vm_clock.
+         *
+         * An extreme solution for this problem would be to never let VCPUs
+         * sleep in icount mode if there is a pending vm_clock timer; rather
+         * time could just advance to the next vm_clock event.  Instead, we
+         * do stop VCPUs and only advance vm_clock after some "real" time,
+         * (related to the time left until the next event) has passed.  This
+         * rt_clock timer will do this.  This avoids that the warps are too
+         * visible externally---for example, you will not be sending network
+         * packets continously instead of every 100ms.
+         */
+        qemu_mod_timer(icount_warp_timer, vm_clock_warp_start + deadline);
+    } else {
+        qemu_notify_event();
+    }
+}
+
+static const VMStateDescription vmstate_timers = {
+    .name = "timer",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT64(cpu_ticks_offset, TimersState),
+        VMSTATE_INT64(dummy, TimersState),
+        VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+void configure_icount(const char *option)
+{
+    vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
+    if (!option) {
+        return;
+    }
+
+    icount_warp_timer = qemu_new_timer_ns(rt_clock, icount_warp_rt, NULL);
+    if (strcmp(option, "auto") != 0) {
+        icount_time_shift = strtol(option, NULL, 0);
+        use_icount = 1;
+        return;
+    }
+
+    use_icount = 2;
+
+    /* 125MIPS seems a reasonable initial guess at the guest speed.
+       It will be corrected fairly quickly anyway.  */
+    icount_time_shift = 3;
+
+    /* Have both realtime and virtual time triggers for speed adjustment.
+       The realtime trigger catches emulated time passing too slowly,
+       the virtual time trigger catches emulated time passing too fast.
+       Realtime triggers occur even when idle, so use them less frequently
+       than VM triggers.  */
+    icount_rt_timer = qemu_new_timer_ms(rt_clock, icount_adjust_rt, NULL);
+    qemu_mod_timer(icount_rt_timer,
+                   qemu_get_clock_ms(rt_clock) + 1000);
+    icount_vm_timer = qemu_new_timer_ns(vm_clock, icount_adjust_vm, NULL);
+    qemu_mod_timer(icount_vm_timer,
+                   qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
+}
+
+/***********************************************************/
 void hw_error(const char *fmt, ...)
 {
     va_list ap;
@@ -686,7 +961,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
 
     while (1) {
         cpu_exec_all();
-        if (use_icount && qemu_next_icount_deadline() <= 0) {
+        if (use_icount && qemu_clock_deadline(vm_clock) <= 0) {
             qemu_notify_event();
         }
         qemu_tcg_wait_io_event();
@@ -914,7 +1189,7 @@ static int tcg_cpu_exec(CPUState *env)
         qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
         env->icount_decr.u16.low = 0;
         env->icount_extra = 0;
-        count = qemu_icount_round(qemu_next_icount_deadline());
+        count = qemu_icount_round(qemu_clock_deadline(vm_clock));
         qemu_icount += count;
         decr = (count > 0xffff) ? 0xffff : count;
         count -= decr;
@@ -1006,22 +1281,6 @@ void set_cpu_log_filename(const char *optarg)
     cpu_set_log_filename(optarg);
 }
 
-/* Return the virtual CPU time, based on the instruction counter.  */
-int64_t cpu_get_icount(void)
-{
-    int64_t icount;
-    CPUState *env = cpu_single_env;;
-
-    icount = qemu_icount;
-    if (env) {
-        if (!can_do_io(env)) {
-            fprintf(stderr, "Bad clock read\n");
-        }
-        icount -= (env->icount_decr.u16.low + env->icount_extra);
-    }
-    return qemu_icount_bias + (icount << icount_time_shift);
-}
-
 void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
 {
     /* XXX: implement xxx_cpu_list for targets that still miss it */
diff --git a/exec-all.h b/exec-all.h
index 1120f84..72ef246 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -356,4 +356,18 @@ extern int singlestep;
 /* cpu-exec.c */
 extern volatile sig_atomic_t exit_request;
 
+/* Deterministic execution requires that IO only be performed on the last
+   instruction of a TB so that interrupts take effect immediately.  */
+static inline int can_do_io(CPUState *env)
+{
+    if (!use_icount) {
+        return 1;
+    }
+    /* If not executing code then assume we are ok.  */
+    if (!env->current_tb) {
+        return 1;
+    }
+    return env->can_do_io != 0;
+}
+
 #endif
diff --git a/exec.c b/exec.c
index d0cbf15..9dc4edb 100644
--- a/exec.c
+++ b/exec.c
@@ -125,9 +125,6 @@ CPUState *cpu_single_env;
    1 = Precise instruction counting.
    2 = Adaptive rate instruction counting.  */
 int use_icount = 0;
-/* Current instruction counter.  While executing translated code this may
-   include some instructions that have not yet been executed.  */
-int64_t qemu_icount;
 
 typedef struct PageDesc {
     /* list of TBs intersecting this ram page */
diff --git a/qemu-common.h b/qemu-common.h
index 5e87bdf..fffdefd 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -96,6 +96,10 @@ static inline char *realpath(const char *path, char *resolved_path)
 }
 #endif
 
+/* icount */
+void configure_icount(const char *option);
+extern int use_icount;
+
 /* FIXME: Remove NEED_CPU_H.  */
 #ifndef NEED_CPU_H
 
diff --git a/qemu-timer.c b/qemu-timer.c
index ebb5089..8129af6 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -46,82 +46,6 @@
 
 #include "qemu-timer.h"
 
-/* Conversion factor from emulated instructions to virtual clock ticks.  */
-int icount_time_shift;
-/* Arbitrarily pick 1MIPS as the minimum allowable speed.  */
-#define MAX_ICOUNT_SHIFT 10
-/* Compensate for varying guest execution speed.  */
-int64_t qemu_icount_bias;
-static QEMUTimer *icount_rt_timer;
-static QEMUTimer *icount_vm_timer;
-
-/***********************************************************/
-/* guest cycle counter */
-
-typedef struct TimersState {
-    int64_t cpu_ticks_prev;
-    int64_t cpu_ticks_offset;
-    int64_t cpu_clock_offset;
-    int32_t cpu_ticks_enabled;
-    int64_t dummy;
-} TimersState;
-
-TimersState timers_state;
-
-/* return the host CPU cycle counter and handle stop/restart */
-int64_t cpu_get_ticks(void)
-{
-    if (use_icount) {
-        return cpu_get_icount();
-    }
-    if (!timers_state.cpu_ticks_enabled) {
-        return timers_state.cpu_ticks_offset;
-    } else {
-        int64_t ticks;
-        ticks = cpu_get_real_ticks();
-        if (timers_state.cpu_ticks_prev > ticks) {
-            /* Note: non increasing ticks may happen if the host uses
-               software suspend */
-            timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
-        }
-        timers_state.cpu_ticks_prev = ticks;
-        return ticks + timers_state.cpu_ticks_offset;
-    }
-}
-
-/* return the host CPU monotonic timer and handle stop/restart */
-static int64_t cpu_get_clock(void)
-{
-    int64_t ti;
-    if (!timers_state.cpu_ticks_enabled) {
-        return timers_state.cpu_clock_offset;
-    } else {
-        ti = get_clock();
-        return ti + timers_state.cpu_clock_offset;
-    }
-}
-
-/* enable cpu_get_ticks() */
-void cpu_enable_ticks(void)
-{
-    if (!timers_state.cpu_ticks_enabled) {
-        timers_state.cpu_ticks_offset -= cpu_get_real_ticks();
-        timers_state.cpu_clock_offset -= get_clock();
-        timers_state.cpu_ticks_enabled = 1;
-    }
-}
-
-/* disable cpu_get_ticks() : the clock is stopped. You must not call
-   cpu_get_ticks() after that.  */
-void cpu_disable_ticks(void)
-{
-    if (timers_state.cpu_ticks_enabled) {
-        timers_state.cpu_ticks_offset = cpu_get_ticks();
-        timers_state.cpu_clock_offset = cpu_get_clock();
-        timers_state.cpu_ticks_enabled = 0;
-    }
-}
-
 /***********************************************************/
 /* timers */
 
@@ -133,7 +57,6 @@ struct QEMUClock {
     int type;
     int enabled;
 
-    QEMUTimer *warp_timer;
     QEMUTimer *active_timers;
 
     NotifierList reset_notifiers;
@@ -252,61 +175,6 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
 
 #endif /* _WIN32 */
 
-/* Correlation between real and virtual time is always going to be
-   fairly approximate, so ignore small variation.
-   When the guest is idle real and virtual time will be aligned in
-   the IO wait loop.  */
-#define ICOUNT_WOBBLE (get_ticks_per_sec() / 10)
-
-static void icount_adjust(void)
-{
-    int64_t cur_time;
-    int64_t cur_icount;
-    int64_t delta;
-    static int64_t last_delta;
-    /* If the VM is not running, then do nothing.  */
-    if (!runstate_is_running())
-        return;
-
-    cur_time = cpu_get_clock();
-    cur_icount = qemu_get_clock_ns(vm_clock);
-    delta = cur_icount - cur_time;
-    /* FIXME: This is a very crude algorithm, somewhat prone to oscillation.  */
-    if (delta > 0
-        && last_delta + ICOUNT_WOBBLE < delta * 2
-        && icount_time_shift > 0) {
-        /* The guest is getting too far ahead.  Slow time down.  */
-        icount_time_shift--;
-    }
-    if (delta < 0
-        && last_delta - ICOUNT_WOBBLE > delta * 2
-        && icount_time_shift < MAX_ICOUNT_SHIFT) {
-        /* The guest is getting too far behind.  Speed time up.  */
-        icount_time_shift++;
-    }
-    last_delta = delta;
-    qemu_icount_bias = cur_icount - (qemu_icount << icount_time_shift);
-}
-
-static void icount_adjust_rt(void * opaque)
-{
-    qemu_mod_timer(icount_rt_timer,
-                   qemu_get_clock_ms(rt_clock) + 1000);
-    icount_adjust();
-}
-
-static void icount_adjust_vm(void * opaque)
-{
-    qemu_mod_timer(icount_vm_timer,
-                   qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
-    icount_adjust();
-}
-
-int64_t qemu_icount_round(int64_t count)
-{
-    return (count + (1 << icount_time_shift) - 1) >> icount_time_shift;
-}
-
 static struct qemu_alarm_timer alarm_timers[] = {
 #ifndef _WIN32
 #ifdef __linux__
@@ -411,90 +279,6 @@ void qemu_clock_enable(QEMUClock *clock, int enabled)
     clock->enabled = enabled;
 }
 
-static int64_t vm_clock_warp_start;
-
-static void icount_warp_rt(void *opaque)
-{
-    if (vm_clock_warp_start == -1) {
-        return;
-    }
-
-    if (runstate_is_running()) {
-        int64_t clock = qemu_get_clock_ns(rt_clock);
-        int64_t warp_delta = clock - vm_clock_warp_start;
-        if (use_icount == 1) {
-            qemu_icount_bias += warp_delta;
-        } else {
-            /*
-             * In adaptive mode, do not let the vm_clock run too
-             * far ahead of real time.
-             */
-            int64_t cur_time = cpu_get_clock();
-            int64_t cur_icount = qemu_get_clock_ns(vm_clock);
-            int64_t delta = cur_time - cur_icount;
-            qemu_icount_bias += MIN(warp_delta, delta);
-        }
-        if (qemu_timer_expired(vm_clock->active_timers,
-                               qemu_get_clock_ns(vm_clock))) {
-            qemu_notify_event();
-        }
-    }
-    vm_clock_warp_start = -1;
-}
-
-void qemu_clock_warp(QEMUClock *clock)
-{
-    int64_t deadline;
-
-    if (!clock->warp_timer) {
-        return;
-    }
-
-    /*
-     * There are too many global variables to make the "warp" behavior
-     * applicable to other clocks.  But a clock argument removes the
-     * need for if statements all over the place.
-     */
-    assert(clock == vm_clock);
-
-    /*
-     * If the CPUs have been sleeping, advance the vm_clock timer now.  This
-     * ensures that the deadline for the timer is computed correctly below.
-     * This also makes sure that the insn counter is synchronized before the
-     * CPU starts running, in case the CPU is woken by an event other than
-     * the earliest vm_clock timer.
-     */
-    icount_warp_rt(NULL);
-    if (!all_cpu_threads_idle() || !clock->active_timers) {
-        qemu_del_timer(clock->warp_timer);
-        return;
-    }
-
-    vm_clock_warp_start = qemu_get_clock_ns(rt_clock);
-    deadline = qemu_next_icount_deadline();
-    if (deadline > 0) {
-        /*
-         * Ensure the vm_clock proceeds even when the virtual CPU goes to
-         * sleep.  Otherwise, the CPU might be waiting for a future timer
-         * interrupt to wake it up, but the interrupt never comes because
-         * the vCPU isn't running any insns and thus doesn't advance the
-         * vm_clock.
-         *
-         * An extreme solution for this problem would be to never let VCPUs
-         * sleep in icount mode if there is a pending vm_clock timer; rather
-         * time could just advance to the next vm_clock event.  Instead, we
-         * do stop VCPUs and only advance vm_clock after some "real" time,
-         * (related to the time left until the next event) has passed.  This
-         * rt_clock timer will do this.  This avoids that the warps are too
-         * visible externally---for example, you will not be sending network
-         * packets continously instead of every 100ms.
-         */
-        qemu_mod_timer(clock->warp_timer, vm_clock_warp_start + deadline);
-    } else {
-        qemu_notify_event();
-    }
-}
-
 int64_t qemu_clock_has_timers(QEMUClock *clock)
 {
     return !!clock->active_timers;
@@ -709,52 +493,6 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
     }
 }
 
-static const VMStateDescription vmstate_timers = {
-    .name = "timer",
-    .version_id = 2,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_INT64(cpu_ticks_offset, TimersState),
-        VMSTATE_INT64(dummy, TimersState),
-        VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-void configure_icount(const char *option)
-{
-    vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
-    if (!option)
-        return;
-
-    vm_clock->warp_timer = qemu_new_timer_ns(rt_clock, icount_warp_rt, NULL);
-
-    if (strcmp(option, "auto") != 0) {
-        icount_time_shift = strtol(option, NULL, 0);
-        use_icount = 1;
-        return;
-    }
-
-    use_icount = 2;
-
-    /* 125MIPS seems a reasonable initial guess at the guest speed.
-       It will be corrected fairly quickly anyway.  */
-    icount_time_shift = 3;
-
-    /* Have both realtime and virtual time triggers for speed adjustment.
-       The realtime trigger catches emulated time passing too slowly,
-       the virtual time trigger catches emulated time passing too fast.
-       Realtime triggers occur even when idle, so use them less frequently
-       than VM triggers.  */
-    icount_rt_timer = qemu_new_timer_ms(rt_clock, icount_adjust_rt, NULL);
-    qemu_mod_timer(icount_rt_timer,
-                   qemu_get_clock_ms(rt_clock) + 1000);
-    icount_vm_timer = qemu_new_timer_ns(vm_clock, icount_adjust_vm, NULL);
-    qemu_mod_timer(icount_vm_timer,
-                   qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
-}
-
 void qemu_run_all_timers(void)
 {
     alarm_timer->pending = 0;
@@ -821,23 +559,6 @@ static void host_alarm_handler(int host_signum)
     }
 }
 
-int64_t qemu_next_icount_deadline(void)
-{
-    /* To avoid problems with overflow limit this to 2^32.  */
-    int64_t delta = INT32_MAX;
-
-    assert(use_icount);
-    if (vm_clock->active_timers) {
-        delta = vm_clock->active_timers->expire_time -
-                     qemu_get_clock_ns(vm_clock);
-    }
-
-    if (delta < 0)
-        delta = 0;
-
-    return delta;
-}
-
 #if defined(__linux__)
 
 #include "compatfd.h"
diff --git a/qemu-timer.h b/qemu-timer.h
index 4578075..ce576b9 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -58,9 +58,7 @@ int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time);
 
 void qemu_run_all_timers(void);
 int qemu_alarm_pending(void);
-int64_t qemu_next_icount_deadline(void);
 void configure_alarms(char const *opt);
-void configure_icount(const char *option);
 int qemu_calculate_timeout(void);
 void init_clocks(void);
 int init_timer_alarm(void);
@@ -153,12 +151,8 @@ void ptimer_run(ptimer_state *s, int oneshot);
 void ptimer_stop(ptimer_state *s);
 
 /* icount */
-int64_t qemu_icount_round(int64_t count);
-extern int64_t qemu_icount;
-extern int use_icount;
-extern int icount_time_shift;
-extern int64_t qemu_icount_bias;
 int64_t cpu_get_icount(void);
+int64_t cpu_get_clock(void);
 
 /*******************************************/
 /* host CPU ticks (if available) */
@@ -314,22 +308,6 @@ static inline int64_t cpu_get_real_ticks (void)
 }
 #endif
 
-#ifdef NEED_CPU_H
-/* Deterministic execution requires that IO only be performed on the last
-   instruction of a TB so that interrupts take effect immediately.  */
-static inline int can_do_io(CPUState *env)
-{
-    if (!use_icount)
-        return 1;
-
-    /* If not executing code then assume we are ok.  */
-    if (!env->current_tb)
-        return 1;
-
-    return env->can_do_io != 0;
-}
-#endif
-
 #ifdef CONFIG_PROFILER
 static inline int64_t profile_getclock(void)
 {
commit dc2dfcf0002b4e6be494959a1ed2589dd109def0
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 12 15:50:16 2011 +0200

    qemu-timer: more clock functions
    
    These will be used when moving icount accounting to cpus.c.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index e2551f3..ebb5089 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -495,6 +495,31 @@ void qemu_clock_warp(QEMUClock *clock)
     }
 }
 
+int64_t qemu_clock_has_timers(QEMUClock *clock)
+{
+    return !!clock->active_timers;
+}
+
+int64_t qemu_clock_expired(QEMUClock *clock)
+{
+    return (clock->active_timers &&
+            clock->active_timers->expire_time < qemu_get_clock_ns(clock));
+}
+
+int64_t qemu_clock_deadline(QEMUClock *clock)
+{
+    /* To avoid problems with overflow limit this to 2^32.  */
+    int64_t delta = INT32_MAX;
+
+    if (clock->active_timers) {
+        delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
+    }
+    if (delta < 0) {
+        delta = 0;
+    }
+    return delta;
+}
+
 QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
                           QEMUTimerCB *cb, void *opaque)
 {
diff --git a/qemu-timer.h b/qemu-timer.h
index 0a43469..4578075 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -38,6 +38,9 @@ extern QEMUClock *vm_clock;
 extern QEMUClock *host_clock;
 
 int64_t qemu_get_clock_ns(QEMUClock *clock);
+int64_t qemu_clock_has_timers(QEMUClock *clock);
+int64_t qemu_clock_expired(QEMUClock *clock);
+int64_t qemu_clock_deadline(QEMUClock *clock);
 void qemu_clock_enable(QEMUClock *clock, int enabled);
 void qemu_clock_warp(QEMUClock *clock);
 
commit f3fc6e2e9613d33e715624e6dd60f525f49446d1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 14 09:45:38 2011 +0100

    qemu-timer: move common code to qemu_rearm_alarm_timer
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index acf7a15..e2551f3 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -153,7 +153,7 @@ struct qemu_alarm_timer {
     char const *name;
     int (*start)(struct qemu_alarm_timer *t);
     void (*stop)(struct qemu_alarm_timer *t);
-    void (*rearm)(struct qemu_alarm_timer *t);
+    void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
 #if defined(__linux__)
     int fd;
     timer_t timer;
@@ -181,12 +181,46 @@ static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
     return !!t->rearm;
 }
 
+static int64_t qemu_next_alarm_deadline(void)
+{
+    int64_t delta;
+    int64_t rtdelta;
+
+    if (!use_icount && vm_clock->active_timers) {
+        delta = vm_clock->active_timers->expire_time -
+                     qemu_get_clock_ns(vm_clock);
+    } else {
+        delta = INT32_MAX;
+    }
+    if (host_clock->active_timers) {
+        int64_t hdelta = host_clock->active_timers->expire_time -
+                 qemu_get_clock_ns(host_clock);
+        if (hdelta < delta) {
+            delta = hdelta;
+        }
+    }
+    if (rt_clock->active_timers) {
+        rtdelta = (rt_clock->active_timers->expire_time -
+                 qemu_get_clock_ns(rt_clock));
+        if (rtdelta < delta) {
+            delta = rtdelta;
+        }
+    }
+
+    return delta;
+}
+
 static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
 {
-    if (!alarm_has_dynticks(t))
+    int64_t nearest_delta_ns;
+    assert(alarm_has_dynticks(t));
+    if (!rt_clock->active_timers &&
+        !vm_clock->active_timers &&
+        !host_clock->active_timers) {
         return;
-
-    t->rearm(t);
+    }
+    nearest_delta_ns = qemu_next_alarm_deadline();
+    t->rearm(t, nearest_delta_ns);
 }
 
 /* TODO: MIN_TIMER_REARM_NS should be optimized */
@@ -196,23 +230,23 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
 
 static int mm_start_timer(struct qemu_alarm_timer *t);
 static void mm_stop_timer(struct qemu_alarm_timer *t);
-static void mm_rearm_timer(struct qemu_alarm_timer *t);
+static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
 
 static int win32_start_timer(struct qemu_alarm_timer *t);
 static void win32_stop_timer(struct qemu_alarm_timer *t);
-static void win32_rearm_timer(struct qemu_alarm_timer *t);
+static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
 
 #else
 
 static int unix_start_timer(struct qemu_alarm_timer *t);
 static void unix_stop_timer(struct qemu_alarm_timer *t);
-static void unix_rearm_timer(struct qemu_alarm_timer *t);
+static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
 
 #ifdef __linux__
 
 static int dynticks_start_timer(struct qemu_alarm_timer *t);
 static void dynticks_stop_timer(struct qemu_alarm_timer *t);
-static void dynticks_rearm_timer(struct qemu_alarm_timer *t);
+static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
 
 #endif /* __linux__ */
 
@@ -715,8 +749,6 @@ void qemu_run_all_timers(void)
     qemu_run_timers(host_clock);
 }
 
-static int64_t qemu_next_alarm_deadline(void);
-
 #ifdef _WIN32
 static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
 #else
@@ -781,33 +813,6 @@ int64_t qemu_next_icount_deadline(void)
     return delta;
 }
 
-static int64_t qemu_next_alarm_deadline(void)
-{
-    int64_t delta;
-    int64_t rtdelta;
-
-    if (!use_icount && vm_clock->active_timers) {
-        delta = vm_clock->active_timers->expire_time -
-                     qemu_get_clock_ns(vm_clock);
-    } else {
-        delta = INT32_MAX;
-    }
-    if (host_clock->active_timers) {
-        int64_t hdelta = host_clock->active_timers->expire_time -
-                 qemu_get_clock_ns(host_clock);
-        if (hdelta < delta)
-            delta = hdelta;
-    }
-    if (rt_clock->active_timers) {
-        rtdelta = (rt_clock->active_timers->expire_time -
-                 qemu_get_clock_ns(rt_clock));
-        if (rtdelta < delta)
-            delta = rtdelta;
-    }
-
-    return delta;
-}
-
 #if defined(__linux__)
 
 #include "compatfd.h"
@@ -860,20 +865,13 @@ static void dynticks_stop_timer(struct qemu_alarm_timer *t)
     timer_delete(host_timer);
 }
 
-static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
+static void dynticks_rearm_timer(struct qemu_alarm_timer *t,
+                                 int64_t nearest_delta_ns)
 {
     timer_t host_timer = t->timer;
     struct itimerspec timeout;
-    int64_t nearest_delta_ns = INT64_MAX;
     int64_t current_ns;
 
-    assert(alarm_has_dynticks(t));
-    if (!rt_clock->active_timers &&
-        !vm_clock->active_timers &&
-        !host_clock->active_timers)
-        return;
-
-    nearest_delta_ns = qemu_next_alarm_deadline();
     if (nearest_delta_ns < MIN_TIMER_REARM_NS)
         nearest_delta_ns = MIN_TIMER_REARM_NS;
 
@@ -915,19 +913,12 @@ static int unix_start_timer(struct qemu_alarm_timer *t)
     return 0;
 }
 
-static void unix_rearm_timer(struct qemu_alarm_timer *t)
+static void unix_rearm_timer(struct qemu_alarm_timer *t,
+                             int64_t nearest_delta_ns)
 {
     struct itimerval itv;
-    int64_t nearest_delta_ns = INT64_MAX;
     int err;
 
-    assert(alarm_has_dynticks(t));
-    if (!rt_clock->active_timers &&
-        !vm_clock->active_timers &&
-        !host_clock->active_timers)
-        return;
-
-    nearest_delta_ns = qemu_next_alarm_deadline();
     if (nearest_delta_ns < MIN_TIMER_REARM_NS)
         nearest_delta_ns = MIN_TIMER_REARM_NS;
 
@@ -1014,23 +1005,14 @@ static void mm_stop_timer(struct qemu_alarm_timer *t)
     timeEndPeriod(mm_period);
 }
 
-static void mm_rearm_timer(struct qemu_alarm_timer *t)
+static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
 {
-    int nearest_delta_ms;
-
-    assert(alarm_has_dynticks(t));
-    if (!rt_clock->active_timers &&
-        !vm_clock->active_timers &&
-        !host_clock->active_timers) {
-        return;
-    }
-
-    timeKillEvent(mm_timer);
-
-    nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
+    int nearest_delta_ms = (delta + 999999) / 1000000;
     if (nearest_delta_ms < 1) {
         nearest_delta_ms = 1;
     }
+
+    timeKillEvent(mm_timer);
     mm_timer = timeSetEvent(nearest_delta_ms,
                             mm_period,
                             mm_alarm_handler,
@@ -1082,19 +1064,14 @@ static void win32_stop_timer(struct qemu_alarm_timer *t)
     }
 }
 
-static void win32_rearm_timer(struct qemu_alarm_timer *t)
+static void win32_rearm_timer(struct qemu_alarm_timer *t,
+                              int64_t nearest_delta_ns)
 {
     HANDLE hTimer = t->timer;
     int nearest_delta_ms;
     BOOLEAN success;
 
-    assert(alarm_has_dynticks(t));
-    if (!rt_clock->active_timers &&
-        !vm_clock->active_timers &&
-        !host_clock->active_timers)
-        return;
-
-    nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
+    nearest_delta_ms = (nearest_delta_ns + 999999) / 1000000;
     if (nearest_delta_ms < 1) {
         nearest_delta_ms = 1;
     }
commit 688eb3896b0b0d005271ded092dab5cb9281d8d5
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Sep 13 11:42:26 2011 +0200

    qemu-timer: remove active_timers array
    
    Embed the list in the QEMUClock instead.
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index ad1fc8b..acf7a15 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -134,6 +134,7 @@ struct QEMUClock {
     int enabled;
 
     QEMUTimer *warp_timer;
+    QEMUTimer *active_timers;
 
     NotifierList reset_notifiers;
     int64_t last;
@@ -352,14 +353,10 @@ next:
     }
 }
 
-#define QEMU_NUM_CLOCKS 3
-
 QEMUClock *rt_clock;
 QEMUClock *vm_clock;
 QEMUClock *host_clock;
 
-static QEMUTimer *active_timers[QEMU_NUM_CLOCKS];
-
 static QEMUClock *qemu_new_clock(int type)
 {
     QEMUClock *clock;
@@ -403,7 +400,7 @@ static void icount_warp_rt(void *opaque)
             int64_t delta = cur_time - cur_icount;
             qemu_icount_bias += MIN(warp_delta, delta);
         }
-        if (qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL],
+        if (qemu_timer_expired(vm_clock->active_timers,
                                qemu_get_clock_ns(vm_clock))) {
             qemu_notify_event();
         }
@@ -434,7 +431,7 @@ void qemu_clock_warp(QEMUClock *clock)
      * the earliest vm_clock timer.
      */
     icount_warp_rt(NULL);
-    if (!all_cpu_threads_idle() || !active_timers[clock->type]) {
+    if (!all_cpu_threads_idle() || !clock->active_timers) {
         qemu_del_timer(clock->warp_timer);
         return;
     }
@@ -489,7 +486,7 @@ void qemu_del_timer(QEMUTimer *ts)
 
     /* NOTE: this code must be signal safe because
        qemu_timer_expired() can be called from a signal. */
-    pt = &active_timers[ts->clock->type];
+    pt = &ts->clock->active_timers;
     for(;;) {
         t = *pt;
         if (!t)
@@ -513,7 +510,7 @@ static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
     /* add the timer in the sorted list */
     /* NOTE: this code must be signal safe because
        qemu_timer_expired() can be called from a signal. */
-    pt = &active_timers[ts->clock->type];
+    pt = &ts->clock->active_timers;
     for(;;) {
         t = *pt;
         if (!qemu_timer_expired_ns(t, expire_time)) {
@@ -526,7 +523,7 @@ static void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
     *pt = ts;
 
     /* Rearm if necessary  */
-    if (pt == &active_timers[ts->clock->type]) {
+    if (pt == &ts->clock->active_timers) {
         if (!alarm_timer->pending) {
             qemu_rearm_alarm_timer(alarm_timer);
         }
@@ -548,7 +545,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
 int qemu_timer_pending(QEMUTimer *ts)
 {
     QEMUTimer *t;
-    for(t = active_timers[ts->clock->type]; t != NULL; t = t->next) {
+    for (t = ts->clock->active_timers; t != NULL; t = t->next) {
         if (t == ts)
             return 1;
     }
@@ -569,7 +566,7 @@ static void qemu_run_timers(QEMUClock *clock)
         return;
 
     current_time = qemu_get_clock_ns(clock);
-    ptimer_head = &active_timers[clock->type];
+    ptimer_head = &clock->active_timers;
     for(;;) {
         ts = *ptimer_head;
         if (!qemu_timer_expired_ns(ts, current_time)) {
@@ -773,8 +770,8 @@ int64_t qemu_next_icount_deadline(void)
     int64_t delta = INT32_MAX;
 
     assert(use_icount);
-    if (active_timers[QEMU_CLOCK_VIRTUAL]) {
-        delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
+    if (vm_clock->active_timers) {
+        delta = vm_clock->active_timers->expire_time -
                      qemu_get_clock_ns(vm_clock);
     }
 
@@ -789,20 +786,20 @@ static int64_t qemu_next_alarm_deadline(void)
     int64_t delta;
     int64_t rtdelta;
 
-    if (!use_icount && active_timers[QEMU_CLOCK_VIRTUAL]) {
-        delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
+    if (!use_icount && vm_clock->active_timers) {
+        delta = vm_clock->active_timers->expire_time -
                      qemu_get_clock_ns(vm_clock);
     } else {
         delta = INT32_MAX;
     }
-    if (active_timers[QEMU_CLOCK_HOST]) {
-        int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time -
+    if (host_clock->active_timers) {
+        int64_t hdelta = host_clock->active_timers->expire_time -
                  qemu_get_clock_ns(host_clock);
         if (hdelta < delta)
             delta = hdelta;
     }
-    if (active_timers[QEMU_CLOCK_REALTIME]) {
-        rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time -
+    if (rt_clock->active_timers) {
+        rtdelta = (rt_clock->active_timers->expire_time -
                  qemu_get_clock_ns(rt_clock));
         if (rtdelta < delta)
             delta = rtdelta;
@@ -871,9 +868,9 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
     int64_t current_ns;
 
     assert(alarm_has_dynticks(t));
-    if (!active_timers[QEMU_CLOCK_REALTIME] &&
-        !active_timers[QEMU_CLOCK_VIRTUAL] &&
-        !active_timers[QEMU_CLOCK_HOST])
+    if (!rt_clock->active_timers &&
+        !vm_clock->active_timers &&
+        !host_clock->active_timers)
         return;
 
     nearest_delta_ns = qemu_next_alarm_deadline();
@@ -925,9 +922,9 @@ static void unix_rearm_timer(struct qemu_alarm_timer *t)
     int err;
 
     assert(alarm_has_dynticks(t));
-    if (!active_timers[QEMU_CLOCK_REALTIME] &&
-        !active_timers[QEMU_CLOCK_VIRTUAL] &&
-        !active_timers[QEMU_CLOCK_HOST])
+    if (!rt_clock->active_timers &&
+        !vm_clock->active_timers &&
+        !host_clock->active_timers)
         return;
 
     nearest_delta_ns = qemu_next_alarm_deadline();
@@ -1022,9 +1019,9 @@ static void mm_rearm_timer(struct qemu_alarm_timer *t)
     int nearest_delta_ms;
 
     assert(alarm_has_dynticks(t));
-    if (!active_timers[QEMU_CLOCK_REALTIME] &&
-        !active_timers[QEMU_CLOCK_VIRTUAL] &&
-        !active_timers[QEMU_CLOCK_HOST]) {
+    if (!rt_clock->active_timers &&
+        !vm_clock->active_timers &&
+        !host_clock->active_timers) {
         return;
     }
 
@@ -1092,9 +1089,9 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t)
     BOOLEAN success;
 
     assert(alarm_has_dynticks(t));
-    if (!active_timers[QEMU_CLOCK_REALTIME] &&
-        !active_timers[QEMU_CLOCK_VIRTUAL] &&
-        !active_timers[QEMU_CLOCK_HOST])
+    if (!rt_clock->active_timers &&
+        !vm_clock->active_timers &&
+        !host_clock->active_timers)
         return;
 
     nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000;
commit 0abc2712b842f5726fb2895859e01e2c7d8d616d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Sep 12 15:17:57 2011 +0200

    remove unused function
    
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c
index 5affdd1..1791ec1 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -661,11 +661,6 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
     ch->io.channel = ch;
 }
 
-void DBDMA_schedule(void)
-{
-    qemu_notify_event();
-}
-
 static void
 dbdma_control_write(DBDMA_channel *ch)
 {
diff --git a/hw/mac_dbdma.h b/hw/mac_dbdma.h
index 933e17c..6d1abe6 100644
--- a/hw/mac_dbdma.h
+++ b/hw/mac_dbdma.h
@@ -41,5 +41,4 @@ struct DBDMA_io {
 void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
                             DBDMA_rw rw, DBDMA_flush flush,
                             void *opaque);
-void DBDMA_schedule(void);
 void* DBDMA_init (MemoryRegion **dbdma_mem);
commit 7f84c1272b601be88daeb828ec1890890c7aae25
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Oct 13 18:45:37 2011 +0100

    compatfd.c: Don't pass NULL pointer to SYS_signalfd
    
    Don't pass a NULL pointer in to SYS_signalfd in qemu_signalfd_available():
    this isn't valid and Valgrind complains about it.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/compatfd.c b/compatfd.c
index 31654c6..02306a4 100644
--- a/compatfd.c
+++ b/compatfd.c
@@ -119,9 +119,17 @@ int qemu_signalfd(const sigset_t *mask)
 bool qemu_signalfd_available(void)
 {
 #ifdef CONFIG_SIGNALFD
+    sigset_t mask;
+    int fd;
+    bool ok;
+    sigemptyset(&mask);
     errno = 0;
-    syscall(SYS_signalfd, -1, NULL, _NSIG / 8);
-    return errno != ENOSYS;
+    fd = syscall(SYS_signalfd, -1, &mask, _NSIG / 8);
+    ok = (errno != ENOSYS);
+    if (fd >= 0) {
+        close(fd);
+    }
+    return ok;
 #else
     return false;
 #endif
commit 1386d4c0f5ce4c4391f2024a36c77eb8fb152e90
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Sep 29 15:48:12 2011 +0100

    linux-user: Fix broken "-version" option
    
    Fix the "-version" option, which was accidentally broken in commit
    fc9c541:
     * exit after printing version information rather than proceeding
       blithely onward (and likely printing the full usage message)
     * correct the cut-n-paste error in the usage message for it
     * don't insist on the presence of a following argument for
       options which don't take an argument (this was preventing
       'qemu-arm -version' from working)
     * remove a spurious argc check from the beginning of main() which
       meant 'QEMU_VERSION=1 qemu-arm' didn't work.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/linux-user/main.c b/linux-user/main.c
index 186358b..e7dad54 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3084,6 +3084,7 @@ static void handle_arg_version(const char *arg)
 {
     printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION
            ", Copyright (c) 2003-2008 Fabrice Bellard\n");
+    exit(0);
 }
 
 struct qemu_argument {
@@ -3129,7 +3130,7 @@ struct qemu_argument arg_table[] = {
     {"strace",     "QEMU_STRACE",      false, handle_arg_strace,
      "",           "log system calls"},
     {"version",    "QEMU_VERSION",     false, handle_arg_version,
-     "",           "log system calls"},
+     "",           "display version information and exit"},
     {NULL, NULL, false, NULL, NULL, NULL}
 };
 
@@ -3231,16 +3232,15 @@ static int parse_args(int argc, char **argv)
 
         for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
             if (!strcmp(r, arginfo->argv)) {
-                if (optind >= argc) {
-                    usage();
-                }
-
-                arginfo->handle_opt(argv[optind]);
-
                 if (arginfo->has_arg) {
+                    if (optind >= argc) {
+                        usage();
+                    }
+                    arginfo->handle_opt(argv[optind]);
                     optind++;
+                } else {
+                    arginfo->handle_opt(NULL);
                 }
-
                 break;
             }
         }
@@ -3276,9 +3276,6 @@ int main(int argc, char **argv, char **envp)
     int i;
     int ret;
 
-    if (argc <= 1)
-        usage();
-
     qemu_cache_utils_init(envp);
 
     if ((envlist = envlist_create()) == NULL) {
commit c2e2343e1faae7bbc77574c12a25881b1b696808
Author: Dmitry Koshelev <karaghiozis at gmail.com>
Date:   Thu Oct 20 14:48:35 2011 +0400

    hw/arm_gic.c: Fix save/load of irq_target array
    
    irq_target array saving/loading is in the wrong loop.
    Version bump.
    
    Signed-off-by: Dmitry Koshelev <karaghiozis at gmail.com>
    Acked-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 83213dd..8dd8742 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -658,9 +658,6 @@ static void gic_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, s->enabled);
     for (i = 0; i < NUM_CPU(s); i++) {
         qemu_put_be32(f, s->cpu_enabled[i]);
-#ifndef NVIC
-        qemu_put_be32(f, s->irq_target[i]);
-#endif
         for (j = 0; j < 32; j++)
             qemu_put_be32(f, s->priority1[j][i]);
         for (j = 0; j < GIC_NIRQ; j++)
@@ -674,6 +671,9 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->priority2[i]);
     }
     for (i = 0; i < GIC_NIRQ; i++) {
+#ifndef NVIC
+        qemu_put_be32(f, s->irq_target[i]);
+#endif
         qemu_put_byte(f, s->irq_state[i].enabled);
         qemu_put_byte(f, s->irq_state[i].pending);
         qemu_put_byte(f, s->irq_state[i].active);
@@ -689,15 +689,12 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
     int i;
     int j;
 
-    if (version_id != 1)
+    if (version_id != 2)
         return -EINVAL;
 
     s->enabled = qemu_get_be32(f);
     for (i = 0; i < NUM_CPU(s); i++) {
         s->cpu_enabled[i] = qemu_get_be32(f);
-#ifndef NVIC
-        s->irq_target[i] = qemu_get_be32(f);
-#endif
         for (j = 0; j < 32; j++)
             s->priority1[j][i] = qemu_get_be32(f);
         for (j = 0; j < GIC_NIRQ; j++)
@@ -711,6 +708,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->priority2[i] = qemu_get_be32(f);
     }
     for (i = 0; i < GIC_NIRQ; i++) {
+#ifndef NVIC
+        s->irq_target[i] = qemu_get_be32(f);
+#endif
         s->irq_state[i].enabled = qemu_get_byte(f);
         s->irq_state[i].pending = qemu_get_byte(f);
         s->irq_state[i].active = qemu_get_byte(f);
@@ -739,5 +739,5 @@ static void gic_init(gic_state *s)
     }
     memory_region_init_io(&s->iomem, &gic_dist_ops, s, "gic_dist", 0x1000);
     gic_reset(s);
-    register_savevm(NULL, "arm_gic", -1, 1, gic_save, gic_load, s);
+    register_savevm(NULL, "arm_gic", -1, 2, gic_save, gic_load, s);
 }
commit f45b885ffcec9489760de74d60ec92fdd876dcab
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Oct 18 16:12:54 2011 +0100

    hw/omap2: Wire up the IRQ for the 2430's fifth GPIO module
    
    The OMAP2430 version of the omap-gpio device has five GPIO modules,
    not four like the other OMAP2 versions; wire up the fifth module's
    IRQ line correctly.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/omap2.c b/hw/omap2.c
index 838c32f..5197fef 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2409,6 +2409,11 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                        qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK3));
     sysbus_connect_irq(busdev, 9,
                        qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK4));
+    if (s->mpu_model == omap2430) {
+        sysbus_connect_irq(busdev, 12,
+                           qdev_get_gpio_in(s->ih[0],
+                                            OMAP_INT_243X_GPIO_BANK5));
+    }
     ta = omap_l4ta(s->l4, 3);
     sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
     sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
commit c76eaf13975130768070ecd2d4f3107eb69ab757
Author: Stefan Weil <sw at weilnetz.de>
Date:   Thu Oct 20 21:55:58 2011 +0200

    hw/9pfs: Fix broken compilation caused by wrong trace events
    
    Commit c572f23a3e7180dbeab5e86583e43ea2afed6271 added trace events
    with mismatching format string and arguments.
    
    gcc reports these errors:
    
    In file included from trace.c:2:0:
    trace.h: In function ‘trace_v9fs_attach’:
    trace.h:2850:9: error: too many arguments for format [-Werror=format-extra-args]
    trace.h: In function ‘trace_v9fs_wstat’:
    trace.h:3039:9: error: too many arguments for format [-Werror=format-extra-args]
    trace.h: In function ‘trace_v9fs_mkdir’:
    trace.h:3088:9: error: too many arguments for format [-Werror=format-extra-args]
    trace.h: In function ‘trace_v9fs_mkdir_return’:
    trace.h:3095:9: error: too many arguments for format [-Werror=format-extra-args]
    
    Fix the format strings and also use %u instead of %d for unsigned values
    in the changed strings. There are more minor errors of this kind
    which I did not fix because that would make the review more difficult.
    
    v2: Fixed position of } for v9fs_mkdir_return.
    
    Cc: Harsh Prateek Bora <harsh at linux.vnet.ibm.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/trace-events b/trace-events
index fc13733..7f9cec4 100644
--- a/trace-events
+++ b/trace-events
@@ -557,7 +557,7 @@ open_eth_desc_write(uint32_t addr, uint32_t v) "DESC[%04x] <- %08x"
 complete_pdu(uint16_t tag, uint8_t id, int err) "tag %d id %d err %d"
 v9fs_version(uint16_t tag, uint8_t id, int32_t msize, char* version) "tag %d id %d msize %d version %s"
 v9fs_version_return(uint16_t tag, uint8_t id, int32_t msize, char* version) "tag %d id %d msize %d version %s"
-v9fs_attach(uint16_t tag, uint8_t id, int32_t fid, int32_t afid, char* uname, char* aname) "tag %d id %d fid %d afid %d aname %s"
+v9fs_attach(uint16_t tag, uint8_t id, int32_t fid, int32_t afid, char* uname, char* aname) "tag %u id %u fid %d afid %d uname %s aname %s"
 v9fs_attach_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) "tag %d id %d type %d version %d path %"PRId64""
 v9fs_stat(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
 v9fs_stat_return(uint16_t tag, uint8_t id, int32_t mode, int32_t atime, int32_t mtime, int64_t length) "tag %d id %d stat={mode %d atime %d mtime %d length %"PRId64"}"
@@ -584,15 +584,15 @@ v9fs_symlink_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int6
 v9fs_flush(uint16_t tag, uint8_t id, int16_t flush_tag) "tag %d id %d flush_tag %d"
 v9fs_link(uint16_t tag, uint8_t id, int32_t dfid, int32_t oldfid, char* name) "tag %d id %d dfid %d oldfid %d name %s"
 v9fs_remove(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
-v9fs_wstat(uint16_t tag, uint8_t id, int32_t fid, int32_t mode, int32_t atime, int32_t mtime) "tag %d id %d fid %d stat={mode %d atime %d mtime}"
+v9fs_wstat(uint16_t tag, uint8_t id, int32_t fid, int32_t mode, int32_t atime, int32_t mtime) "tag %u id %u fid %d stat={mode %d atime %d mtime %d}"
 v9fs_mknod(uint16_t tag, uint8_t id, int32_t fid, int mode, int major, int minor) "tag %d id %d fid %d mode %d major %d minor %d"
 v9fs_mknod_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) "tag %d id %d qid={type %d version %d path %"PRId64"}"
 v9fs_lock(uint16_t tag, uint8_t id, int32_t fid, uint8_t type, uint64_t start, uint64_t length) "tag %d id %d fid %d type %d start %"PRIu64" length %"PRIu64""
 v9fs_lock_return(uint16_t tag, uint8_t id, int8_t status) "tag %d id %d status %d"
 v9fs_getlock(uint16_t tag, uint8_t id, int32_t fid, uint8_t type, uint64_t start, uint64_t length)"tag %d id %d fid %d type %d start %"PRIu64" length %"PRIu64""
 v9fs_getlock_return(uint16_t tag, uint8_t id, uint8_t type, uint64_t start, uint64_t length, uint32_t proc_id) "tag %d id %d type %d start %"PRIu64" length %"PRIu64" proc_id %u"
-v9fs_mkdir(uint16_t tag, uint8_t id, int32_t fid, char* name, int mode, uint32_t gid) "tag %d id %d fid %d name %s mode %d"
-v9fs_mkdir_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int err) "tag %d id %d qid={type %d version %d path %"PRId64"}"
+v9fs_mkdir(uint16_t tag, uint8_t id, int32_t fid, char* name, int mode, uint32_t gid) "tag %u id %u fid %d name %s mode %d gid %u"
+v9fs_mkdir_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int err) "tag %u id %u qid={type %d version %d path %"PRId64"} err %d"
 v9fs_xattrwalk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, char* name) "tag %d id %d fid %d newfid %d name %s"
 v9fs_xattrwalk_return(uint16_t tag, uint8_t id, int64_t size) "tag %d id %d size %"PRId64""
 v9fs_xattrcreate(uint16_t tag, uint8_t id, int32_t fid, char* name, int64_t size, int flags) "tag %d id %d fid %d name %s size %"PRId64" flags %d"
commit a6e43daa732b90b9ca58e7c38f6faa5a82f4b176
Merge: 46cd37e... ee86c61...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Oct 20 08:46:55 2011 -0500

    Merge remote-tracking branch 'quintela/migration-pull' into staging

diff --cc migration.c
index 62b74a6,3db12ef..bdca72e
--- a/migration.c
+++ b/migration.c
@@@ -375,17 -299,14 +299,14 @@@ static void migrate_fd_put_ready(void *
          int old_vm_running = runstate_is_running();
  
          DPRINTF("done iterating\n");
 -        vm_stop(RUN_STATE_FINISH_MIGRATE);
 +        vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
  
-         if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
-             if (old_vm_running) {
-                 vm_start();
-             }
-             state = MIG_STATE_ERROR;
+         if (qemu_savevm_state_complete(s->mon, s->file) < 0) {
+             migrate_fd_error(s);
          } else {
-             state = MIG_STATE_COMPLETED;
+             migrate_fd_completed(s);
          }
-         if (migrate_fd_cleanup(s) < 0) {
+         if (s->state != MIG_STATE_COMPLETED) {
              if (old_vm_running) {
                  vm_start();
              }
diff --cc savevm.c
index abb4a60,9e9c783..cf79a56
--- a/savevm.c
+++ b/savevm.c
@@@ -1619,9 -1671,13 +1667,10 @@@ static int qemu_savevm_state(Monitor *m
      ret = qemu_savevm_state_complete(mon, f);
  
  out:
-     if (qemu_file_has_error(f))
-         ret = -EIO;
+     if (ret == 0) {
+         ret = qemu_file_get_error(f);
+     }
  
 -    if (!ret && saved_vm_running)
 -        vm_start();
 -
      return ret;
  }
  
commit 46cd37e7718f6c2c502228a61b3a0811c849c52f
Merge: 1f99b94... d08151b...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Oct 20 08:43:00 2011 -0500

    Merge remote-tracking branch 'qemu-kvm-tmp/memory/batch' into staging

commit 1f99b94932fcf0a543e46e24875fc2b3a8c304a7
Merge: 8a9236f... d9b36a6...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Oct 20 08:42:08 2011 -0500

    Merge remote-tracking branch 'aneesh/for-upstream-6' into staging
    
    Conflicts:
    	trace-events

diff --cc trace-events
index a06c6c5,cbbc4aa..fc13733
--- a/trace-events
+++ b/trace-events
@@@ -539,16 -539,48 +539,62 @@@ esp_mem_writeb_cmd_ensel(uint32_t val) 
  handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\""
  monitor_protocol_emitter(void *mon) "mon %p"
  
 +# hw/opencores_eth.c
 +open_eth_mii_write(unsigned idx, uint16_t v) "MII[%02x] <- %04x"
 +open_eth_mii_read(unsigned idx, uint16_t v) "MII[%02x] -> %04x"
 +open_eth_update_irq(uint32_t v) "IRQ <- %x"
 +open_eth_receive(unsigned len) "RX: len: %u"
 +open_eth_receive_mcast(unsigned idx, uint32_t h0, uint32_t h1) "MCAST: idx = %u, hash: %08x:%08x"
 +open_eth_receive_reject(void) "RX: rejected"
 +open_eth_receive_desc(uint32_t addr, uint32_t len_flags) "RX: %08x, len_flags: %08x"
 +open_eth_start_xmit(uint32_t addr, unsigned len, unsigned tx_len) "TX: %08x, len: %u, tx_len: %u"
 +open_eth_reg_read(uint32_t addr, uint32_t v) "MAC[%02x] -> %08x"
 +open_eth_reg_write(uint32_t addr, uint32_t v) "MAC[%02x] <- %08x"
 +open_eth_desc_read(uint32_t addr, uint32_t v) "DESC[%04x] -> %08x"
 +open_eth_desc_write(uint32_t addr, uint32_t v) "DESC[%04x] <- %08x"
++
+ # hw/9pfs/virtio-9p.c
+ complete_pdu(uint16_t tag, uint8_t id, int err) "tag %d id %d err %d"
+ v9fs_version(uint16_t tag, uint8_t id, int32_t msize, char* version) "tag %d id %d msize %d version %s"
+ v9fs_version_return(uint16_t tag, uint8_t id, int32_t msize, char* version) "tag %d id %d msize %d version %s"
+ v9fs_attach(uint16_t tag, uint8_t id, int32_t fid, int32_t afid, char* uname, char* aname) "tag %d id %d fid %d afid %d aname %s"
+ v9fs_attach_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) "tag %d id %d type %d version %d path %"PRId64""
+ v9fs_stat(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
+ v9fs_stat_return(uint16_t tag, uint8_t id, int32_t mode, int32_t atime, int32_t mtime, int64_t length) "tag %d id %d stat={mode %d atime %d mtime %d length %"PRId64"}"
+ v9fs_getattr(uint16_t tag, uint8_t id, int32_t fid, uint64_t request_mask) "tag %d id %d fid %d request_mask %"PRIu64""
+ v9fs_getattr_return(uint16_t tag, uint8_t id, uint64_t result_mask, uint32_t mode, uint32_t uid, uint32_t gid) "tag %d id %d getattr={result_mask %"PRId64" mode %u uid %u gid %u}"
+ v9fs_walk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, uint16_t nwnames) "tag %d id %d fid %d newfid %d nwnames %d"
+ v9fs_walk_return(uint16_t tag, uint8_t id, uint16_t nwnames, void* qids) "tag %d id %d nwnames %d qids %p"
+ v9fs_open(uint16_t tag, uint8_t id, int32_t fid, int32_t mode) "tag %d id %d fid %d mode %d"
+ v9fs_open_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
+ v9fs_lcreate(uint16_t tag, uint8_t id, int32_t dfid, int32_t flags, int32_t mode, uint32_t gid) "tag %d id %d dfid %d flags %d mode %d gid %u"
+ v9fs_lcreate_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int32_t iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
+ v9fs_fsync(uint16_t tag, uint8_t id, int32_t fid, int datasync) "tag %d id %d fid %d datasync %d"
+ v9fs_clunk(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
+ v9fs_read(uint16_t tag, uint8_t id, int32_t fid, int64_t off, int32_t max_count) "tag %d id %d fid %d off %"PRId64" max_count %d"
+ v9fs_read_return(uint16_t tag, uint8_t id, int32_t count, ssize_t err) "tag %d id %d count %d err %zd"
+ v9fs_readdir(uint16_t tag, uint8_t id, int32_t fid, int64_t offset, int32_t max_count) "tag %d id %d fid %d offset %"PRId64" max_count %d"
+ v9fs_readdir_return(uint16_t tag, uint8_t id, int32_t count, ssize_t retval) "tag %d id %d count %d retval %zd"
+ v9fs_write(uint16_t tag, uint8_t id, int32_t fid, int64_t off, int32_t count, int cnt) "tag %d id %d fid %d off %"PRId64" count %d cnt %d"
+ v9fs_write_return(uint16_t tag, uint8_t id, int32_t total, ssize_t err) "tag %d id %d total %d err %zd"
+ v9fs_create(uint16_t tag, uint8_t id, int32_t fid, char* name, int32_t perm, int8_t mode) "tag %d id %d fid %d name %s perm %d mode %d"
+ v9fs_create_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
+ v9fs_symlink(uint16_t tag, uint8_t id, int32_t fid,  char* name, char* symname, uint32_t gid) "tag %d id %d fid %d name %s symname %s gid %u"
+ v9fs_symlink_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) "tag %d id %d qid={type %d version %d path %"PRId64"}"
+ v9fs_flush(uint16_t tag, uint8_t id, int16_t flush_tag) "tag %d id %d flush_tag %d"
+ v9fs_link(uint16_t tag, uint8_t id, int32_t dfid, int32_t oldfid, char* name) "tag %d id %d dfid %d oldfid %d name %s"
+ v9fs_remove(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
+ v9fs_wstat(uint16_t tag, uint8_t id, int32_t fid, int32_t mode, int32_t atime, int32_t mtime) "tag %d id %d fid %d stat={mode %d atime %d mtime}"
+ v9fs_mknod(uint16_t tag, uint8_t id, int32_t fid, int mode, int major, int minor) "tag %d id %d fid %d mode %d major %d minor %d"
+ v9fs_mknod_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) "tag %d id %d qid={type %d version %d path %"PRId64"}"
+ v9fs_lock(uint16_t tag, uint8_t id, int32_t fid, uint8_t type, uint64_t start, uint64_t length) "tag %d id %d fid %d type %d start %"PRIu64" length %"PRIu64""
+ v9fs_lock_return(uint16_t tag, uint8_t id, int8_t status) "tag %d id %d status %d"
+ v9fs_getlock(uint16_t tag, uint8_t id, int32_t fid, uint8_t type, uint64_t start, uint64_t length)"tag %d id %d fid %d type %d start %"PRIu64" length %"PRIu64""
+ v9fs_getlock_return(uint16_t tag, uint8_t id, uint8_t type, uint64_t start, uint64_t length, uint32_t proc_id) "tag %d id %d type %d start %"PRIu64" length %"PRIu64" proc_id %u"
+ v9fs_mkdir(uint16_t tag, uint8_t id, int32_t fid, char* name, int mode, uint32_t gid) "tag %d id %d fid %d name %s mode %d"
+ v9fs_mkdir_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int err) "tag %d id %d qid={type %d version %d path %"PRId64"}"
+ v9fs_xattrwalk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, char* name) "tag %d id %d fid %d newfid %d name %s"
+ v9fs_xattrwalk_return(uint16_t tag, uint8_t id, int64_t size) "tag %d id %d size %"PRId64""
+ v9fs_xattrcreate(uint16_t tag, uint8_t id, int32_t fid, char* name, int64_t size, int flags) "tag %d id %d fid %d name %s size %"PRId64" flags %d"
+ v9fs_readlink(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
+ v9fs_readlink_return(uint16_t tag, uint8_t id, char* target) "tag %d id %d name %s"
commit ee86c61f285042386c0a27edf69300627a1987b4
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Feb 23 20:44:29 2011 +0100

    migration: make migration-{tcp,unix} consistent
    
    Files are almost identical in functionality, just remove the
    differences that make no sense.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-tcp.c b/migration-tcp.c
index 619df21..5aa742c 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -48,7 +48,6 @@ static int tcp_close(MigrationState *s)
     return 0;
 }
 
-
 static void tcp_wait_for_connect(void *opaque)
 {
     MigrationState *s = opaque;
@@ -84,12 +83,14 @@ int tcp_start_outgoing_migration(MigrationState *s, const char *host_port)
     if (ret < 0) {
         return ret;
     }
+
     s->get_error = socket_errno;
     s->write = socket_write;
     s->close = tcp_close;
 
     s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
     if (s->fd == -1) {
+        DPRINTF("Unable to open socket");
         return -socket_error();
     }
 
@@ -155,23 +156,27 @@ int tcp_start_incoming_migration(const char *host_port)
     int val;
     int s;
 
+    DPRINTF("Attempting to start an incoming migration\n");
+
     if (parse_host_port(&addr, host_port) < 0) {
         fprintf(stderr, "invalid host/port combination: %s\n", host_port);
         return -EINVAL;
     }
 
     s = qemu_socket(PF_INET, SOCK_STREAM, 0);
-    if (s == -1)
+    if (s == -1) {
         return -socket_error();
+    }
 
     val = 1;
     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
 
-    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
+    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
         goto err;
-
-    if (listen(s, 1) == -1)
+    }
+    if (listen(s, 1) == -1) {
         goto err;
+    }
 
     qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL,
                          (void *)(intptr_t)s);
diff --git a/migration-unix.c b/migration-unix.c
index f979b5f..8596353 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -86,7 +86,7 @@ int unix_start_outgoing_migration(MigrationState *s, const char *path)
     s->close = unix_close;
 
     s->fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
-    if (s->fd < 0) {
+    if (s->fd == -1) {
         DPRINTF("Unable to open socket");
         return -errno;
     }
@@ -129,7 +129,7 @@ static void unix_accept_incoming_migration(void *opaque)
 
     if (c == -1) {
         fprintf(stderr, "could not accept migration connection\n");
-        return;
+        goto out2;
     }
 
     f = qemu_fopen_socket(c);
@@ -141,45 +141,49 @@ static void unix_accept_incoming_migration(void *opaque)
     process_incoming_migration(f);
     qemu_fclose(f);
 out:
+    close(c);
+out2:
     qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
     close(s);
-    close(c);
 }
 
 int unix_start_incoming_migration(const char *path)
 {
-    struct sockaddr_un un;
-    int sock;
+    struct sockaddr_un addr;
+    int s;
+    int ret;
 
     DPRINTF("Attempting to start an incoming migration\n");
 
-    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
-    if (sock < 0) {
+    s = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
+    if (s == -1) {
         fprintf(stderr, "Could not open unix socket: %s\n", strerror(errno));
-        return -EINVAL;
+        return -errno;
     }
 
-    memset(&un, 0, sizeof(un));
-    un.sun_family = AF_UNIX;
-    snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
 
-    unlink(un.sun_path);
-    if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
-        fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno));
+    unlink(addr.sun_path);
+    if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+        ret = -errno;
+        fprintf(stderr, "bind(unix:%s): %s\n", addr.sun_path, strerror(errno));
         goto err;
     }
-    if (listen(sock, 1) < 0) {
-        fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno));
+    if (listen(s, 1) == -1) {
+        fprintf(stderr, "listen(unix:%s): %s\n", addr.sun_path,
+                strerror(errno));
+        ret = -errno;
         goto err;
     }
 
-    qemu_set_fd_handler2(sock, NULL, unix_accept_incoming_migration, NULL,
-			 (void *)(intptr_t)sock);
+    qemu_set_fd_handler2(s, NULL, unix_accept_incoming_migration, NULL,
+                         (void *)(intptr_t)s);
 
     return 0;
 
 err:
-    close(sock);
-
-    return -EINVAL;
+    close(s);
+    return ret;
 }
commit 8414ff3bd8bfafbcb632c670f4d81c8e4f15e703
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Feb 23 19:56:52 2011 +0100

    migration: propagate error correctly
    
    unix and tcp outgoing migration have error values, but didn't returned
    it.  Make them return the error.  Notice that EINPROGRESS & EWOULDBLOCK
    are not considered errors as call will be retry later.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-tcp.c b/migration-tcp.c
index bd3aa3a..619df21 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -90,26 +90,28 @@ int tcp_start_outgoing_migration(MigrationState *s, const char *host_port)
 
     s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
     if (s->fd == -1) {
-        return -1;
+        return -socket_error();
     }
 
     socket_set_nonblock(s->fd);
 
     do {
         ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
-        if (ret == -1)
-            ret = -(socket_error());
-
-        if (ret == -EINPROGRESS || ret == -EWOULDBLOCK)
+        if (ret == -1) {
+            ret = -socket_error();
+        }
+        if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) {
             qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
+            return 0;
+        }
     } while (ret == -EINTR);
 
-    if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) {
+    if (ret < 0) {
         DPRINTF("connect failed\n");
         migrate_fd_error(s);
-    } else if (ret >= 0)
-        migrate_fd_connect(s);
-
+        return ret;
+    }
+    migrate_fd_connect(s);
     return 0;
 }
 
diff --git a/migration-unix.c b/migration-unix.c
index ca66851..f979b5f 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -88,35 +88,29 @@ int unix_start_outgoing_migration(MigrationState *s, const char *path)
     s->fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
     if (s->fd < 0) {
         DPRINTF("Unable to open socket");
-        goto err_after_socket;
+        return -errno;
     }
 
     socket_set_nonblock(s->fd);
 
     do {
         ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
-        if (ret == -1)
+        if (ret == -1) {
             ret = -errno;
-
-        if (ret == -EINPROGRESS || ret == -EWOULDBLOCK)
+        }
+        if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) {
 	    qemu_set_fd_handler2(s->fd, NULL, NULL, unix_wait_for_connect, s);
+            return 0;
+        }
     } while (ret == -EINTR);
 
-    if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) {
+    if (ret < 0) {
         DPRINTF("connect failed\n");
-        goto err_after_open;
+        migrate_fd_error(s);
+        return ret;
     }
-
-    if (ret >= 0)
-        migrate_fd_connect(s);
-
+    migrate_fd_connect(s);
     return 0;
-
-err_after_open:
-    close(s->fd);
-
-err_after_socket:
-    return -1;
 }
 
 static void unix_accept_incoming_migration(void *opaque)
commit efab4718f4203132244758fbc76b8b0676b9d85d
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Feb 23 11:52:12 2011 +0100

    migration: Don't use callback on file defining it
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration-tcp.c b/migration-tcp.c
index f6b2288..bd3aa3a 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -58,7 +58,7 @@ static void tcp_wait_for_connect(void *opaque)
     DPRINTF("connect completed\n");
     do {
         ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize);
-    } while (ret == -1 && (s->get_error(s)) == EINTR);
+    } while (ret == -1 && (socket_error()) == EINTR);
 
     if (ret < 0) {
         migrate_fd_error(s);
@@ -98,7 +98,7 @@ int tcp_start_outgoing_migration(MigrationState *s, const char *host_port)
     do {
         ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
         if (ret == -1)
-            ret = -(s->get_error(s));
+            ret = -(socket_error());
 
         if (ret == -EINPROGRESS || ret == -EWOULDBLOCK)
             qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
diff --git a/migration-unix.c b/migration-unix.c
index bd8d40f..ca66851 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -57,7 +57,7 @@ static void unix_wait_for_connect(void *opaque)
     DPRINTF("connect completed\n");
     do {
         ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize);
-    } while (ret == -1 && (s->get_error(s)) == EINTR);
+    } while (ret == -1 && errno == EINTR);
 
     if (ret < 0) {
         migrate_fd_error(s);
@@ -96,7 +96,7 @@ int unix_start_outgoing_migration(MigrationState *s, const char *path)
     do {
         ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
         if (ret == -1)
-	    ret = -(s->get_error(s));
+            ret = -errno;
 
         if (ret == -EINPROGRESS || ret == -EWOULDBLOCK)
 	    qemu_set_fd_handler2(s->fd, NULL, NULL, unix_wait_for_connect, s);
@@ -129,7 +129,7 @@ static void unix_accept_incoming_migration(void *opaque)
 
     do {
         c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen);
-    } while (c == -1 && socket_error() == EINTR);
+    } while (c == -1 && errno == EINTR);
 
     DPRINTF("accepted migration\n");
 
commit 7dc688ed71ff7b8509d4bf8bdc4c4cb6c25a9917
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Feb 23 00:48:46 2011 +0100

    migration: Make state definitions local
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index b5929db..3db12ef 100644
--- a/migration.c
+++ b/migration.c
@@ -31,6 +31,14 @@
     do { } while (0)
 #endif
 
+enum {
+    MIG_STATE_ERROR,
+    MIG_STATE_SETUP,
+    MIG_STATE_CANCELLED,
+    MIG_STATE_ACTIVE,
+    MIG_STATE_COMPLETED,
+};
+
 #define MAX_THROTTLE  (32 << 20)      /* Migration speed throttling */
 
 static NotifierList migration_state_notifiers =
diff --git a/migration.h b/migration.h
index 23d347a..a1f80d0 100644
--- a/migration.h
+++ b/migration.h
@@ -18,14 +18,6 @@
 #include "qemu-common.h"
 #include "notify.h"
 
-enum {
-    MIG_STATE_ERROR,
-    MIG_STATE_SETUP,
-    MIG_STATE_CANCELLED,
-    MIG_STATE_ACTIVE,
-    MIG_STATE_COMPLETED,
-};
-
 typedef struct MigrationState MigrationState;
 
 struct MigrationState
commit 7073693bfbde541eca0cc778e1b2c30d43a65c4b
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Feb 23 00:43:59 2011 +0100

    migration: Export a function that tells if the migration has finished correctly
    
    This will allow us to hide the state values.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 46db37b..b5929db 100644
--- a/migration.c
+++ b/migration.c
@@ -364,9 +364,9 @@ void remove_migration_state_change_notifier(Notifier *notify)
     notifier_list_remove(&migration_state_notifiers, notify);
 }
 
-int get_migration_state(void)
+bool migration_has_finished(MigrationState *s)
 {
-    return migrate_get_current()->state;
+    return s->state == MIG_STATE_COMPLETED;
 }
 
 void migrate_fd_connect(MigrationState *s)
diff --git a/migration.h b/migration.h
index e1299b9..23d347a 100644
--- a/migration.h
+++ b/migration.h
@@ -84,7 +84,7 @@ void migrate_fd_connect(MigrationState *s);
 
 void add_migration_state_change_notifier(Notifier *notify);
 void remove_migration_state_change_notifier(Notifier *notify);
-int get_migration_state(void);
+bool migration_has_finished(MigrationState *);
 
 uint64_t ram_bytes_remaining(void);
 uint64_t ram_bytes_transferred(void);
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 3cbc721..b33366e 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -447,9 +447,9 @@ void do_info_spice(Monitor *mon, QObject **ret_data)
 
 static void migration_state_notifier(Notifier *notifier, void *data)
 {
-    int state = get_migration_state();
+    MigrationState *s = data;
 
-    if (state == MIG_STATE_COMPLETED) {
+    if (migration_has_finished(s)) {
 #if SPICE_SERVER_VERSION >= 0x000701 /* 0.7.1 */
         spice_server_migrate_switch(spice_server);
 #endif
commit e0eb7390b02228d44e873a2071593af9ce7cac82
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 5 14:27:52 2011 +0200

    migration: Pass MigrationState in migration notifiers
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 3c989ad..46db37b 100644
--- a/migration.c
+++ b/migration.c
@@ -222,7 +222,7 @@ void migrate_fd_error(MigrationState *s)
 {
     DPRINTF("setting error state\n");
     s->state = MIG_STATE_ERROR;
-    notifier_list_notify(&migration_state_notifiers, NULL);
+    notifier_list_notify(&migration_state_notifiers, s);
     migrate_fd_cleanup(s);
 }
 
@@ -235,7 +235,7 @@ static void migrate_fd_completed(MigrationState *s)
         s->state = MIG_STATE_COMPLETED;
         runstate_set(RUN_STATE_POSTMIGRATE);
     }
-    notifier_list_notify(&migration_state_notifiers, NULL);
+    notifier_list_notify(&migration_state_notifiers, s);
 }
 
 static void migrate_fd_put_notify(void *opaque)
@@ -314,7 +314,7 @@ static void migrate_fd_cancel(MigrationState *s)
     DPRINTF("cancelling migration\n");
 
     s->state = MIG_STATE_CANCELLED;
-    notifier_list_notify(&migration_state_notifiers, NULL);
+    notifier_list_notify(&migration_state_notifiers, s);
     qemu_savevm_state_cancel(s->mon, s->file);
 
     migrate_fd_cleanup(s);
@@ -452,7 +452,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return ret;
     }
 
-    notifier_list_notify(&migration_state_notifiers, NULL);
+    notifier_list_notify(&migration_state_notifiers, s);
     return 0;
 }
 
commit d0ae46c1979ab3046d7ef748340ef736e47c088e
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Feb 23 00:33:19 2011 +0100

    migration: Use bandwidth_limit directly
    
    Now that current_migration always exist, there is no reason for
    max_throotle variable.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index bcc71b4..3c989ad 100644
--- a/migration.c
+++ b/migration.c
@@ -31,8 +31,7 @@
     do { } while (0)
 #endif
 
-/* Migration speed throttling */
-static int64_t max_throttle = (32 << 20);
+#define MAX_THROTTLE  (32 << 20)      /* Migration speed throttling */
 
 static NotifierList migration_state_notifiers =
     NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
@@ -45,6 +44,7 @@ static MigrationState *migrate_get_current(void)
 {
     static MigrationState current_migration = {
         .state = MIG_STATE_SETUP,
+        .bandwidth_limit = MAX_THROTTLE,
     };
 
     return &current_migration;
@@ -391,12 +391,13 @@ void migrate_fd_connect(MigrationState *s)
     migrate_fd_put_ready(s);
 }
 
-static MigrationState *migrate_init(Monitor *mon, int64_t bandwidth_limit,
-                                    int detach, int blk, int inc)
+static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
 {
     MigrationState *s = migrate_get_current();
+    int64_t bandwidth_limit = s->bandwidth_limit;
 
     memset(s, 0, sizeof(*s));
+    s->bandwidth_limit = bandwidth_limit;
     s->blk = blk;
     s->shared = inc;
     s->mon = NULL;
@@ -429,7 +430,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return -1;
     }
 
-    s = migrate_init(mon, max_throttle, detach, blk, inc);
+    s = migrate_init(mon, detach, blk, inc);
 
     if (strstart(uri, "tcp:", &p)) {
         ret = tcp_start_outgoing_migration(s, p);
@@ -470,10 +471,10 @@ int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
     if (d < 0) {
         d = 0;
     }
-    max_throttle = d;
 
     s = migrate_get_current();
-    qemu_file_set_rate_limit(s->file, max_throttle);
+    s->bandwidth_limit = d;
+    qemu_file_set_rate_limit(s->file, s->bandwidth_limit);
 
     return 0;
 }
commit 17549e84e0cccebf405a1994d70b0e0e5438fd8f
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 5 13:50:43 2011 +0200

    migration: create accessor for current_migration
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index c852f2e..bcc71b4 100644
--- a/migration.c
+++ b/migration.c
@@ -34,11 +34,22 @@
 /* Migration speed throttling */
 static int64_t max_throttle = (32 << 20);
 
-static MigrationState *current_migration;
-
 static NotifierList migration_state_notifiers =
     NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
 
+/* When we add fault tolerance, we could have several
+   migrations at once.  For now we don't need to add
+   dynamic creation of migration */
+
+static MigrationState *migrate_get_current(void)
+{
+    static MigrationState current_migration = {
+        .state = MIG_STATE_SETUP,
+    };
+
+    return &current_migration;
+}
+
 int qemu_start_incoming_migration(const char *uri)
 {
     const char *p;
@@ -135,39 +146,36 @@ static void migrate_put_status(QDict *qdict, const char *name,
 void do_info_migrate(Monitor *mon, QObject **ret_data)
 {
     QDict *qdict;
-
-    if (current_migration) {
-        MigrationState *s = current_migration;
-
-        switch (s->state) {
-        case MIG_STATE_SETUP:
-            /* no migration has happened ever */
-            break;
-        case MIG_STATE_ACTIVE:
-            qdict = qdict_new();
-            qdict_put(qdict, "status", qstring_from_str("active"));
-
-            migrate_put_status(qdict, "ram", ram_bytes_transferred(),
-                               ram_bytes_remaining(), ram_bytes_total());
-
-            if (blk_mig_active()) {
-                migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(),
-                                   blk_mig_bytes_remaining(),
-                                   blk_mig_bytes_total());
-            }
-
-            *ret_data = QOBJECT(qdict);
-            break;
-        case MIG_STATE_COMPLETED:
-            *ret_data = qobject_from_jsonf("{ 'status': 'completed' }");
-            break;
-        case MIG_STATE_ERROR:
-            *ret_data = qobject_from_jsonf("{ 'status': 'failed' }");
-            break;
-        case MIG_STATE_CANCELLED:
-            *ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }");
-            break;
+    MigrationState *s = migrate_get_current();
+
+    switch (s->state) {
+    case MIG_STATE_SETUP:
+        /* no migration has happened ever */
+        break;
+    case MIG_STATE_ACTIVE:
+        qdict = qdict_new();
+        qdict_put(qdict, "status", qstring_from_str("active"));
+
+        migrate_put_status(qdict, "ram", ram_bytes_transferred(),
+                           ram_bytes_remaining(), ram_bytes_total());
+
+        if (blk_mig_active()) {
+            migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(),
+                               blk_mig_bytes_remaining(),
+                               blk_mig_bytes_total());
         }
+
+        *ret_data = QOBJECT(qdict);
+        break;
+    case MIG_STATE_COMPLETED:
+        *ret_data = qobject_from_jsonf("{ 'status': 'completed' }");
+        break;
+    case MIG_STATE_ERROR:
+        *ret_data = qobject_from_jsonf("{ 'status': 'failed' }");
+        break;
+    case MIG_STATE_CANCELLED:
+        *ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }");
+        break;
     }
 }
 
@@ -358,11 +366,7 @@ void remove_migration_state_change_notifier(Notifier *notify)
 
 int get_migration_state(void)
 {
-    if (current_migration) {
-        return current_migration->state;
-    } else {
-        return MIG_STATE_ERROR;
-    }
+    return migrate_get_current()->state;
 }
 
 void migrate_fd_connect(MigrationState *s)
@@ -387,11 +391,12 @@ void migrate_fd_connect(MigrationState *s)
     migrate_fd_put_ready(s);
 }
 
-static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
-                                   int detach, int blk, int inc)
+static MigrationState *migrate_init(Monitor *mon, int64_t bandwidth_limit,
+                                    int detach, int blk, int inc)
 {
-    MigrationState *s = g_malloc0(sizeof(*s));
+    MigrationState *s = migrate_get_current();
 
+    memset(s, 0, sizeof(*s));
     s->blk = blk;
     s->shared = inc;
     s->mon = NULL;
@@ -407,7 +412,7 @@ static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
 
 int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
-    MigrationState *s = NULL;
+    MigrationState *s = migrate_get_current();
     const char *p;
     int detach = qdict_get_try_bool(qdict, "detach", 0);
     int blk = qdict_get_try_bool(qdict, "blk", 0);
@@ -415,8 +420,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     const char *uri = qdict_get_str(qdict, "uri");
     int ret;
 
-    if (current_migration &&
-        current_migration->state == MIG_STATE_ACTIVE) {
+    if (s->state == MIG_STATE_ACTIVE) {
         monitor_printf(mon, "migration already in progress\n");
         return -1;
     }
@@ -425,7 +429,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return -1;
     }
 
-    s = migrate_new(mon, max_throttle, detach, blk, inc);
+    s = migrate_init(mon, max_throttle, detach, blk, inc);
 
     if (strstart(uri, "tcp:", &p)) {
         ret = tcp_start_outgoing_migration(s, p);
@@ -440,28 +444,20 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     } else {
         monitor_printf(mon, "unknown migration protocol: %s\n", uri);
         ret  = -EINVAL;
-        goto free_migrate_state;
     }
 
     if (ret < 0) {
-        monitor_printf(mon, "migration failed\n");
-        goto free_migrate_state;
+        monitor_printf(mon, "migration failed: %s\n", strerror(-ret));
+        return ret;
     }
 
-    g_free(current_migration);
-    current_migration = s;
     notifier_list_notify(&migration_state_notifiers, NULL);
     return 0;
-free_migrate_state:
-    g_free(s);
-    return -1;
 }
 
 int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
-    if (current_migration) {
-        migrate_fd_cancel(current_migration);
-    }
+    migrate_fd_cancel(migrate_get_current());
     return 0;
 }
 
@@ -476,10 +472,8 @@ int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
     }
     max_throttle = d;
 
-    s = current_migration;
-    if (s && s->file) {
-        qemu_file_set_rate_limit(s->file, max_throttle);
-    }
+    s = migrate_get_current();
+    qemu_file_set_rate_limit(s->file, max_throttle);
 
     return 0;
 }
commit cab30143337c16881973a5ceda6476153bf98360
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Feb 22 23:54:21 2011 +0100

    migration: Move exported functions to the end of the file
    
    This means we can remove the two forward declarations.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 31b6741..c852f2e 100644
--- a/migration.c
+++ b/migration.c
@@ -77,90 +77,6 @@ void process_incoming_migration(QEMUFile *f)
     }
 }
 
-static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
-                                   int detach, int blk, int inc);
-
-int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    MigrationState *s = NULL;
-    const char *p;
-    int detach = qdict_get_try_bool(qdict, "detach", 0);
-    int blk = qdict_get_try_bool(qdict, "blk", 0);
-    int inc = qdict_get_try_bool(qdict, "inc", 0);
-    const char *uri = qdict_get_str(qdict, "uri");
-    int ret;
-
-    if (current_migration &&
-        current_migration->state == MIG_STATE_ACTIVE) {
-        monitor_printf(mon, "migration already in progress\n");
-        return -1;
-    }
-
-    if (qemu_savevm_state_blocked(mon)) {
-        return -1;
-    }
-
-    s = migrate_new(mon, max_throttle, detach, blk, inc);
-
-    if (strstart(uri, "tcp:", &p)) {
-        ret = tcp_start_outgoing_migration(s, p);
-#if !defined(WIN32)
-    } else if (strstart(uri, "exec:", &p)) {
-        ret = exec_start_outgoing_migration(s, p);
-    } else if (strstart(uri, "unix:", &p)) {
-        ret = unix_start_outgoing_migration(s, p);
-    } else if (strstart(uri, "fd:", &p)) {
-        ret = fd_start_outgoing_migration(s, p);
-#endif
-    } else {
-        monitor_printf(mon, "unknown migration protocol: %s\n", uri);
-        ret  = -EINVAL;
-        goto free_migrate_state;
-    }
-
-    if (ret < 0) {
-        monitor_printf(mon, "migration failed\n");
-        goto free_migrate_state;
-    }
-
-    g_free(current_migration);
-    current_migration = s;
-    notifier_list_notify(&migration_state_notifiers, NULL);
-    return 0;
-free_migrate_state:
-    g_free(s);
-    return -1;
-}
-
-static void migrate_fd_cancel(MigrationState *s);
-
-int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    if (current_migration) {
-        migrate_fd_cancel(current_migration);
-    }
-    return 0;
-}
-
-int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    int64_t d;
-    MigrationState *s;
-
-    d = qdict_get_int(qdict, "value");
-    if (d < 0) {
-        d = 0;
-    }
-    max_throttle = d;
-
-    s = current_migration;
-    if (s && s->file) {
-        qemu_file_set_rate_limit(s->file, max_throttle);
-    }
-
-    return 0;
-}
-
 /* amount of nanoseconds we are willing to wait for migration to be down.
  * the choice of nanoseconds is because it is the maximum resolution that
  * get_clock() can achieve. It is an internal measure. All user-visible
@@ -172,18 +88,6 @@ uint64_t migrate_max_downtime(void)
     return max_downtime;
 }
 
-int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
-                            QObject **ret_data)
-{
-    double d;
-
-    d = qdict_get_double(qdict, "value") * 1e9;
-    d = MAX(0, MIN(UINT64_MAX, d));
-    max_downtime = (uint64_t)d;
-
-    return 0;
-}
-
 static void migrate_print_status(Monitor *mon, const char *name,
                                  const QDict *status_dict)
 {
@@ -500,3 +404,94 @@ static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
 
     return s;
 }
+
+int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    MigrationState *s = NULL;
+    const char *p;
+    int detach = qdict_get_try_bool(qdict, "detach", 0);
+    int blk = qdict_get_try_bool(qdict, "blk", 0);
+    int inc = qdict_get_try_bool(qdict, "inc", 0);
+    const char *uri = qdict_get_str(qdict, "uri");
+    int ret;
+
+    if (current_migration &&
+        current_migration->state == MIG_STATE_ACTIVE) {
+        monitor_printf(mon, "migration already in progress\n");
+        return -1;
+    }
+
+    if (qemu_savevm_state_blocked(mon)) {
+        return -1;
+    }
+
+    s = migrate_new(mon, max_throttle, detach, blk, inc);
+
+    if (strstart(uri, "tcp:", &p)) {
+        ret = tcp_start_outgoing_migration(s, p);
+#if !defined(WIN32)
+    } else if (strstart(uri, "exec:", &p)) {
+        ret = exec_start_outgoing_migration(s, p);
+    } else if (strstart(uri, "unix:", &p)) {
+        ret = unix_start_outgoing_migration(s, p);
+    } else if (strstart(uri, "fd:", &p)) {
+        ret = fd_start_outgoing_migration(s, p);
+#endif
+    } else {
+        monitor_printf(mon, "unknown migration protocol: %s\n", uri);
+        ret  = -EINVAL;
+        goto free_migrate_state;
+    }
+
+    if (ret < 0) {
+        monitor_printf(mon, "migration failed\n");
+        goto free_migrate_state;
+    }
+
+    g_free(current_migration);
+    current_migration = s;
+    notifier_list_notify(&migration_state_notifiers, NULL);
+    return 0;
+free_migrate_state:
+    g_free(s);
+    return -1;
+}
+
+int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    if (current_migration) {
+        migrate_fd_cancel(current_migration);
+    }
+    return 0;
+}
+
+int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    int64_t d;
+    MigrationState *s;
+
+    d = qdict_get_int(qdict, "value");
+    if (d < 0) {
+        d = 0;
+    }
+    max_throttle = d;
+
+    s = current_migration;
+    if (s && s->file) {
+        qemu_file_set_rate_limit(s->file, max_throttle);
+    }
+
+    return 0;
+}
+
+int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
+                            QObject **ret_data)
+{
+    double d;
+
+    d = qdict_get_double(qdict, "value") * 1e9;
+    d = MAX(0, MIN(UINT64_MAX, d));
+    max_downtime = (uint64_t)d;
+
+    return 0;
+}
commit 767de722589c1e6e6926a421d1a8e110ad9b059f
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue May 11 23:38:23 2010 +0200

    migration: Remove migration cancel() callback
    
    It is used only in one place
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 8dbe8df..31b6741 100644
--- a/migration.c
+++ b/migration.c
@@ -132,12 +132,12 @@ free_migrate_state:
     return -1;
 }
 
+static void migrate_fd_cancel(MigrationState *s);
+
 int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
-    MigrationState *s = current_migration;
-
-    if (s && s->state == MIG_STATE_ACTIVE) {
-        s->cancel(s);
+    if (current_migration) {
+        migrate_fd_cancel(current_migration);
     }
     return 0;
 }
@@ -488,7 +488,6 @@ static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
 {
     MigrationState *s = g_malloc0(sizeof(*s));
 
-    s->cancel = migrate_fd_cancel;
     s->blk = blk;
     s->shared = inc;
     s->mon = NULL;
diff --git a/migration.h b/migration.h
index 6be3623..e1299b9 100644
--- a/migration.h
+++ b/migration.h
@@ -38,7 +38,6 @@ struct MigrationState
     int (*get_error)(MigrationState *s);
     int (*close)(MigrationState *s);
     int (*write)(MigrationState *s, const void *buff, size_t size);
-    void (*cancel)(MigrationState *s);
     void *opaque;
     int blk;
     int shared;
commit 48a2f4d6c567275b93f6d6ef7da555ab158b12d4
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue May 11 23:28:53 2010 +0200

    migration: Remove get_status() accessor
    
    It is only used inside migration.c, and fields on that struct are
    accessed all around the place on that file.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 400ffb7..8dbe8df 100644
--- a/migration.c
+++ b/migration.c
@@ -91,7 +91,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     int ret;
 
     if (current_migration &&
-        current_migration->get_status(current_migration) == MIG_STATE_ACTIVE) {
+        current_migration->state == MIG_STATE_ACTIVE) {
         monitor_printf(mon, "migration already in progress\n");
         return -1;
     }
@@ -136,7 +136,7 @@ int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     MigrationState *s = current_migration;
 
-    if (s && s->get_status(s) == MIG_STATE_ACTIVE) {
+    if (s && s->state == MIG_STATE_ACTIVE) {
         s->cancel(s);
     }
     return 0;
@@ -235,7 +235,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data)
     if (current_migration) {
         MigrationState *s = current_migration;
 
-        switch (s->get_status(current_migration)) {
+        switch (s->state) {
         case MIG_STATE_SETUP:
             /* no migration has happened ever */
             break;
@@ -386,7 +386,7 @@ static void migrate_fd_put_ready(void *opaque)
         } else {
             migrate_fd_completed(s);
         }
-        if (s->get_status(s) != MIG_STATE_COMPLETED) {
+        if (s->state != MIG_STATE_COMPLETED) {
             if (old_vm_running) {
                 vm_start();
             }
@@ -394,11 +394,6 @@ static void migrate_fd_put_ready(void *opaque)
     }
 }
 
-static int migrate_fd_get_status(MigrationState *s)
-{
-    return s->state;
-}
-
 static void migrate_fd_cancel(MigrationState *s)
 {
     if (s->state != MIG_STATE_ACTIVE)
@@ -460,7 +455,7 @@ void remove_migration_state_change_notifier(Notifier *notify)
 int get_migration_state(void)
 {
     if (current_migration) {
-        return migrate_fd_get_status(current_migration);
+        return current_migration->state;
     } else {
         return MIG_STATE_ERROR;
     }
@@ -494,7 +489,6 @@ static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
     MigrationState *s = g_malloc0(sizeof(*s));
 
     s->cancel = migrate_fd_cancel;
-    s->get_status = migrate_fd_get_status;
     s->blk = blk;
     s->shared = inc;
     s->mon = NULL;
diff --git a/migration.h b/migration.h
index 347f321..6be3623 100644
--- a/migration.h
+++ b/migration.h
@@ -39,7 +39,6 @@ struct MigrationState
     int (*close)(MigrationState *s);
     int (*write)(MigrationState *s, const void *buff, size_t size);
     void (*cancel)(MigrationState *s);
-    int (*get_status)(MigrationState *s);
     void *opaque;
     int blk;
     int shared;
commit 92920cd782d3b36bea64d79f162567c873882c4e
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue May 11 23:18:34 2010 +0200

    migration: Our release callback was just free
    
    We called it from a single place, and always with state !=
    MIG_STATE_ACTIVE.  Just remove the whole callback.  For users of the
    notifier, notice that this is exactly the case where they don't care,
    we are just freeing the state from previous failed migration (it can't
    be a sucessful one, otherwise we would not be running on that machine
    in the first place).
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index a7c7b41..400ffb7 100644
--- a/migration.c
+++ b/migration.c
@@ -123,10 +123,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
         goto free_migrate_state;
     }
 
-    if (current_migration) {
-        current_migration->release(current_migration);
-    }
-
+    g_free(current_migration);
     current_migration = s;
     notifier_list_notify(&migration_state_notifiers, NULL);
     return 0;
@@ -416,19 +413,6 @@ static void migrate_fd_cancel(MigrationState *s)
     migrate_fd_cleanup(s);
 }
 
-static void migrate_fd_release(MigrationState *s)
-{
-
-    DPRINTF("releasing state\n");
-   
-    if (s->state == MIG_STATE_ACTIVE) {
-        s->state = MIG_STATE_CANCELLED;
-        notifier_list_notify(&migration_state_notifiers, NULL);
-        migrate_fd_cleanup(s);
-    }
-    g_free(s);
-}
-
 static void migrate_fd_wait_for_unfreeze(void *opaque)
 {
     MigrationState *s = opaque;
@@ -511,7 +495,6 @@ static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
 
     s->cancel = migrate_fd_cancel;
     s->get_status = migrate_fd_get_status;
-    s->release = migrate_fd_release;
     s->blk = blk;
     s->shared = inc;
     s->mon = NULL;
diff --git a/migration.h b/migration.h
index fed1cf1..347f321 100644
--- a/migration.h
+++ b/migration.h
@@ -40,7 +40,6 @@ struct MigrationState
     int (*write)(MigrationState *s, const void *buff, size_t size);
     void (*cancel)(MigrationState *s);
     int (*get_status)(MigrationState *s);
-    void (*release)(MigrationState *s);
     void *opaque;
     int blk;
     int shared;
commit 458cf28e6b01ff9b87a20d199d42b1c1c904cd29
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Feb 22 23:32:54 2011 +0100

    migration: Introduce migrate_fd_completed() for consistency
    
    This function is a bit different of the others that change the state,
    in the sense that if migrate_fd_cleanup() returns an error, it set the
    status to error, not completed.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index ee4ef4b..a7c7b41 100644
--- a/migration.c
+++ b/migration.c
@@ -317,6 +317,18 @@ void migrate_fd_error(MigrationState *s)
     migrate_fd_cleanup(s);
 }
 
+static void migrate_fd_completed(MigrationState *s)
+{
+    DPRINTF("setting completed state\n");
+    if (migrate_fd_cleanup(s) < 0) {
+        s->state = MIG_STATE_ERROR;
+    } else {
+        s->state = MIG_STATE_COMPLETED;
+        runstate_set(RUN_STATE_POSTMIGRATE);
+    }
+    notifier_list_notify(&migration_state_notifiers, NULL);
+}
+
 static void migrate_fd_put_notify(void *opaque)
 {
     MigrationState *s = opaque;
@@ -375,13 +387,7 @@ static void migrate_fd_put_ready(void *opaque)
         if (qemu_savevm_state_complete(s->mon, s->file) < 0) {
             migrate_fd_error(s);
         } else {
-            if (migrate_fd_cleanup(s) < 0) {
-                migrate_fd_error(s);
-            } else {
-                s->state = MIG_STATE_COMPLETED;
-                runstate_set(RUN_STATE_POSTMIGRATE);
-                notifier_list_notify(&migration_state_notifiers, NULL);
-            }
+            migrate_fd_completed(s);
         }
         if (s->get_status(s) != MIG_STATE_COMPLETED) {
             if (old_vm_running) {
commit 67afff79111f0ce1ae20010c27a30b5ec61f362c
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Feb 22 23:18:20 2011 +0100

    migration: Refactor and simplify error checking in migrate_fd_put_ready
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 281fbae..ee4ef4b 100644
--- a/migration.c
+++ b/migration.c
@@ -372,23 +372,22 @@ static void migrate_fd_put_ready(void *opaque)
         DPRINTF("done iterating\n");
         vm_stop(RUN_STATE_FINISH_MIGRATE);
 
-        if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
-            if (old_vm_running) {
-                vm_start();
+        if (qemu_savevm_state_complete(s->mon, s->file) < 0) {
+            migrate_fd_error(s);
+        } else {
+            if (migrate_fd_cleanup(s) < 0) {
+                migrate_fd_error(s);
+            } else {
+                s->state = MIG_STATE_COMPLETED;
+                runstate_set(RUN_STATE_POSTMIGRATE);
+                notifier_list_notify(&migration_state_notifiers, NULL);
             }
-            s->state = MIG_STATE_ERROR;
         }
-        if (migrate_fd_cleanup(s) < 0) {
+        if (s->get_status(s) != MIG_STATE_COMPLETED) {
             if (old_vm_running) {
                 vm_start();
             }
-            s->state = MIG_STATE_ERROR;
         }
-        if (s->state == MIG_STATE_ACTIVE) {
-            s->state = MIG_STATE_COMPLETED;
-            runstate_set(RUN_STATE_POSTMIGRATE);
-        }
-        notifier_list_notify(&migration_state_notifiers, NULL);
     }
 }
 
commit d5934dde1cc47306800558a8c8619dc6a976c11c
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue May 11 23:01:53 2010 +0200

    migration: Introduce MIG_STATE_SETUP
    
    Use MIG_STATE_ACTIVE only when migration has really started.  Use this
    new state to setup migration parameters.  Change defines for an
    anonymous struct.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index ca038ec..281fbae 100644
--- a/migration.c
+++ b/migration.c
@@ -239,6 +239,9 @@ void do_info_migrate(Monitor *mon, QObject **ret_data)
         MigrationState *s = current_migration;
 
         switch (s->get_status(current_migration)) {
+        case MIG_STATE_SETUP:
+            /* no migration has happened ever */
+            break;
         case MIG_STATE_ACTIVE:
             qdict = qdict_new();
             qdict_put(qdict, "status", qstring_from_str("active"));
@@ -478,6 +481,7 @@ void migrate_fd_connect(MigrationState *s)
 {
     int ret;
 
+    s->state = MIG_STATE_ACTIVE;
     s->file = qemu_fopen_ops_buffered(s,
                                       s->bandwidth_limit,
                                       migrate_fd_put_buffer,
@@ -507,7 +511,7 @@ static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
     s->shared = inc;
     s->mon = NULL;
     s->bandwidth_limit = bandwidth_limit;
-    s->state = MIG_STATE_ACTIVE;
+    s->state = MIG_STATE_SETUP;
 
     if (!detach) {
         migrate_fd_monitor_suspend(s, mon);
diff --git a/migration.h b/migration.h
index 14c3ebc..fed1cf1 100644
--- a/migration.h
+++ b/migration.h
@@ -18,10 +18,13 @@
 #include "qemu-common.h"
 #include "notify.h"
 
-#define MIG_STATE_ERROR		-1
-#define MIG_STATE_COMPLETED	0
-#define MIG_STATE_CANCELLED	1
-#define MIG_STATE_ACTIVE	2
+enum {
+    MIG_STATE_ERROR,
+    MIG_STATE_SETUP,
+    MIG_STATE_CANCELLED,
+    MIG_STATE_ACTIVE,
+    MIG_STATE_COMPLETED,
+};
 
 typedef struct MigrationState MigrationState;
 
commit 07af4452919fddc6dca6462828b457aad62f6387
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue May 11 22:27:45 2010 +0200

    migration: move migrate_new to do_migrate
    
    Once there, remove all parameters that don't need to be passed to
    *start_outgoing_migration() functions
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-exec.c b/migration-exec.c
index d0119c6..b7b1055 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -61,22 +61,14 @@ static int exec_close(MigrationState *s)
     return ret;
 }
 
-MigrationState *exec_start_outgoing_migration(Monitor *mon,
-                                              const char *command,
-					      int64_t bandwidth_limit,
-					      int detach,
-					      int blk,
-					      int inc)
+int exec_start_outgoing_migration(MigrationState *s, const char *command)
 {
-    MigrationState *s;
     FILE *f;
 
-    s = migrate_new(mon, bandwidth_limit, detach, blk, inc);
-
     f = popen(command, "w");
     if (f == NULL) {
         DPRINTF("Unable to popen exec target\n");
-        goto err_after_alloc;
+        goto err_after_popen;
     }
 
     s->fd = fileno(f);
@@ -94,13 +86,12 @@ MigrationState *exec_start_outgoing_migration(Monitor *mon,
     s->write = file_write;
 
     migrate_fd_connect(s);
-    return s;
+    return 0;
 
 err_after_open:
     pclose(f);
-err_after_alloc:
-    g_free(s);
-    return NULL;
+err_after_popen:
+    return -1;
 }
 
 static void exec_accept_incoming_migration(void *opaque)
diff --git a/migration-fd.c b/migration-fd.c
index 9d3ca42..d0aec89 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -50,21 +50,12 @@ static int fd_close(MigrationState *s)
     return 0;
 }
 
-MigrationState *fd_start_outgoing_migration(Monitor *mon,
-					    const char *fdname,
-					    int64_t bandwidth_limit,
-					    int detach,
-					    int blk,
-					    int inc)
+int fd_start_outgoing_migration(MigrationState *s, const char *fdname)
 {
-    MigrationState *s;
-
-    s = migrate_new(mon, bandwidth_limit, detach, blk, inc);
-
-    s->fd = monitor_get_fd(mon, fdname);
+    s->fd = monitor_get_fd(s->mon, fdname);
     if (s->fd == -1) {
         DPRINTF("fd_migration: invalid file descriptor identifier\n");
-        goto err_after_alloc;
+        goto err_after_get_fd;
     }
 
     if (fcntl(s->fd, F_SETFL, O_NONBLOCK) == -1) {
@@ -77,13 +68,12 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon,
     s->close = fd_close;
 
     migrate_fd_connect(s);
-    return s;
+    return 0;
 
 err_after_open:
     close(s->fd);
-err_after_alloc:
-    g_free(s);
-    return NULL;
+err_after_get_fd:
+    return -1;
 }
 
 static void fd_accept_incoming_migration(void *opaque)
diff --git a/migration-tcp.c b/migration-tcp.c
index 999d4c9..f6b2288 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -75,30 +75,22 @@ static void tcp_wait_for_connect(void *opaque)
     }
 }
 
-MigrationState *tcp_start_outgoing_migration(Monitor *mon,
-                                             const char *host_port,
-                                             int64_t bandwidth_limit,
-                                             int detach,
-					     int blk,
-					     int inc)
+int tcp_start_outgoing_migration(MigrationState *s, const char *host_port)
 {
     struct sockaddr_in addr;
-    MigrationState *s;
     int ret;
 
-    if (parse_host_port(&addr, host_port) < 0)
-        return NULL;
-
-    s = migrate_new(mon, bandwidth_limit, detach, blk, inc);
-
+    ret = parse_host_port(&addr, host_port);
+    if (ret < 0) {
+        return ret;
+    }
     s->get_error = socket_errno;
     s->write = socket_write;
     s->close = tcp_close;
 
     s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
     if (s->fd == -1) {
-        g_free(s);
-        return NULL;
+        return -1;
     }
 
     socket_set_nonblock(s->fd);
@@ -118,7 +110,7 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon,
     } else if (ret >= 0)
         migrate_fd_connect(s);
 
-    return s;
+    return 0;
 }
 
 static void tcp_accept_incoming_migration(void *opaque)
diff --git a/migration-unix.c b/migration-unix.c
index bee71d9..bd8d40f 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -74,22 +74,13 @@ static void unix_wait_for_connect(void *opaque)
     }
 }
 
-MigrationState *unix_start_outgoing_migration(Monitor *mon,
-                                              const char *path,
-					      int64_t bandwidth_limit,
-					      int detach,
-					      int blk,
-					      int inc)
+int unix_start_outgoing_migration(MigrationState *s, const char *path)
 {
-    MigrationState *s;
     struct sockaddr_un addr;
     int ret;
 
     addr.sun_family = AF_UNIX;
     snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
-
-    s = migrate_new(mon, bandwidth_limit, detach, blk, inc);
-
     s->get_error = unix_errno;
     s->write = unix_write;
     s->close = unix_close;
@@ -97,7 +88,7 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon,
     s->fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
     if (s->fd < 0) {
         DPRINTF("Unable to open socket");
-        goto err_after_alloc;
+        goto err_after_socket;
     }
 
     socket_set_nonblock(s->fd);
@@ -119,14 +110,13 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon,
     if (ret >= 0)
         migrate_fd_connect(s);
 
-    return s;
+    return 0;
 
 err_after_open:
     close(s->fd);
 
-err_after_alloc:
-    g_free(s);
-    return NULL;
+err_after_socket:
+    return -1;
 }
 
 static void unix_accept_incoming_migration(void *opaque)
diff --git a/migration.c b/migration.c
index 117bdb2..ca038ec 100644
--- a/migration.c
+++ b/migration.c
@@ -77,6 +77,9 @@ void process_incoming_migration(QEMUFile *f)
     }
 }
 
+static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
+                                   int detach, int blk, int inc);
+
 int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     MigrationState *s = NULL;
@@ -85,6 +88,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     int blk = qdict_get_try_bool(qdict, "blk", 0);
     int inc = qdict_get_try_bool(qdict, "inc", 0);
     const char *uri = qdict_get_str(qdict, "uri");
+    int ret;
 
     if (current_migration &&
         current_migration->get_status(current_migration) == MIG_STATE_ACTIVE) {
@@ -96,28 +100,27 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return -1;
     }
 
+    s = migrate_new(mon, max_throttle, detach, blk, inc);
+
     if (strstart(uri, "tcp:", &p)) {
-        s = tcp_start_outgoing_migration(mon, p, max_throttle, detach,
-                                         blk, inc);
+        ret = tcp_start_outgoing_migration(s, p);
 #if !defined(WIN32)
     } else if (strstart(uri, "exec:", &p)) {
-        s = exec_start_outgoing_migration(mon, p, max_throttle, detach,
-                                          blk, inc);
+        ret = exec_start_outgoing_migration(s, p);
     } else if (strstart(uri, "unix:", &p)) {
-        s = unix_start_outgoing_migration(mon, p, max_throttle, detach,
-                                          blk, inc);
+        ret = unix_start_outgoing_migration(s, p);
     } else if (strstart(uri, "fd:", &p)) {
-        s = fd_start_outgoing_migration(mon, p, max_throttle, detach, 
-                                        blk, inc);
+        ret = fd_start_outgoing_migration(s, p);
 #endif
     } else {
         monitor_printf(mon, "unknown migration protocol: %s\n", uri);
-        return -1;
+        ret  = -EINVAL;
+        goto free_migrate_state;
     }
 
-    if (s == NULL) {
+    if (ret < 0) {
         monitor_printf(mon, "migration failed\n");
-        return -1;
+        goto free_migrate_state;
     }
 
     if (current_migration) {
@@ -127,6 +130,9 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     current_migration = s;
     notifier_list_notify(&migration_state_notifiers, NULL);
     return 0;
+free_migrate_state:
+    g_free(s);
+    return -1;
 }
 
 int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
@@ -489,8 +495,8 @@ void migrate_fd_connect(MigrationState *s)
     migrate_fd_put_ready(s);
 }
 
-MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
-                                     int detach, int blk, int inc)
+static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
+                                   int detach, int blk, int inc)
 {
     MigrationState *s = g_malloc0(sizeof(*s));
 
diff --git a/migration.h b/migration.h
index 892b636..14c3ebc 100644
--- a/migration.h
+++ b/migration.h
@@ -64,47 +64,24 @@ void do_info_migrate(Monitor *mon, QObject **ret_data);
 
 int exec_start_incoming_migration(const char *host_port);
 
-MigrationState *exec_start_outgoing_migration(Monitor *mon,
-                                              const char *host_port,
-					      int64_t bandwidth_limit,
-					      int detach,
-					      int blk,
-					      int inc);
+int exec_start_outgoing_migration(MigrationState *s, const char *host_port);
 
 int tcp_start_incoming_migration(const char *host_port);
 
-MigrationState *tcp_start_outgoing_migration(Monitor *mon,
-                                             const char *host_port,
-					     int64_t bandwidth_limit,
-					     int detach,
-					     int blk,
-					     int inc);
+int tcp_start_outgoing_migration(MigrationState *s, const char *host_port);
 
 int unix_start_incoming_migration(const char *path);
 
-MigrationState *unix_start_outgoing_migration(Monitor *mon,
-                                              const char *path,
-					      int64_t bandwidth_limit,
-					      int detach,
-					      int blk,
-					      int inc);
+int unix_start_outgoing_migration(MigrationState *s, const char *path);
 
 int fd_start_incoming_migration(const char *path);
 
-MigrationState *fd_start_outgoing_migration(Monitor *mon,
-					    const char *fdname,
-					    int64_t bandwidth_limit,
-					    int detach,
-					    int blk,
-					    int inc);
+int fd_start_outgoing_migration(MigrationState *s, const char *fdname);
 
 void migrate_fd_error(MigrationState *s);
 
 void migrate_fd_connect(MigrationState *s);
 
-MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
-                            int detach, int blk, int inc);
-
 void add_migration_state_change_notifier(Notifier *notify);
 void remove_migration_state_change_notifier(Notifier *notify);
 int get_migration_state(void);
commit 8b6b99b3561b8da3b15da1871e1bb3d4ac7770ca
Author: Juan Quintela <quintela at redhat.com>
Date:   Sun Sep 11 20:28:22 2011 +0200

    migration: Make all posible migration functions static
    
    I have to move two functions postions to avoid forward declarations
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 78d0f61..117bdb2 100644
--- a/migration.c
+++ b/migration.c
@@ -274,15 +274,7 @@ static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon)
     }
 }
 
-void migrate_fd_error(MigrationState *s)
-{
-    DPRINTF("setting error state\n");
-    s->state = MIG_STATE_ERROR;
-    notifier_list_notify(&migration_state_notifiers, NULL);
-    migrate_fd_cleanup(s);
-}
-
-int migrate_fd_cleanup(MigrationState *s)
+static int migrate_fd_cleanup(MigrationState *s)
 {
     int ret = 0;
 
@@ -308,7 +300,15 @@ int migrate_fd_cleanup(MigrationState *s)
     return ret;
 }
 
-void migrate_fd_put_notify(void *opaque)
+void migrate_fd_error(MigrationState *s)
+{
+    DPRINTF("setting error state\n");
+    s->state = MIG_STATE_ERROR;
+    notifier_list_notify(&migration_state_notifiers, NULL);
+    migrate_fd_cleanup(s);
+}
+
+static void migrate_fd_put_notify(void *opaque)
 {
     MigrationState *s = opaque;
 
@@ -319,7 +319,8 @@ void migrate_fd_put_notify(void *opaque)
     }
 }
 
-ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
+static ssize_t migrate_fd_put_buffer(void *opaque, const void *data,
+                                     size_t size)
 {
     MigrationState *s = opaque;
     ssize_t ret;
@@ -342,29 +343,7 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
     return ret;
 }
 
-void migrate_fd_connect(MigrationState *s)
-{
-    int ret;
-
-    s->file = qemu_fopen_ops_buffered(s,
-                                      s->bandwidth_limit,
-                                      migrate_fd_put_buffer,
-                                      migrate_fd_put_ready,
-                                      migrate_fd_wait_for_unfreeze,
-                                      migrate_fd_close);
-
-    DPRINTF("beginning savevm\n");
-    ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared);
-    if (ret < 0) {
-        DPRINTF("failed, %d\n", ret);
-        migrate_fd_error(s);
-        return;
-    }
-    
-    migrate_fd_put_ready(s);
-}
-
-void migrate_fd_put_ready(void *opaque)
+static void migrate_fd_put_ready(void *opaque)
 {
     MigrationState *s = opaque;
     int ret;
@@ -436,7 +415,7 @@ static void migrate_fd_release(MigrationState *s)
     g_free(s);
 }
 
-void migrate_fd_wait_for_unfreeze(void *opaque)
+static void migrate_fd_wait_for_unfreeze(void *opaque)
 {
     MigrationState *s = opaque;
     int ret;
@@ -459,7 +438,7 @@ void migrate_fd_wait_for_unfreeze(void *opaque)
     }
 }
 
-int migrate_fd_close(void *opaque)
+static int migrate_fd_close(void *opaque)
 {
     MigrationState *s = opaque;
 
@@ -489,6 +468,27 @@ int get_migration_state(void)
     }
 }
 
+void migrate_fd_connect(MigrationState *s)
+{
+    int ret;
+
+    s->file = qemu_fopen_ops_buffered(s,
+                                      s->bandwidth_limit,
+                                      migrate_fd_put_buffer,
+                                      migrate_fd_put_ready,
+                                      migrate_fd_wait_for_unfreeze,
+                                      migrate_fd_close);
+
+    DPRINTF("beginning savevm\n");
+    ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared);
+    if (ret < 0) {
+        DPRINTF("failed, %d\n", ret);
+        migrate_fd_error(s);
+        return;
+    }
+    migrate_fd_put_ready(s);
+}
+
 MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
                                      int detach, int blk, int inc)
 {
diff --git a/migration.h b/migration.h
index 5f933e8..892b636 100644
--- a/migration.h
+++ b/migration.h
@@ -100,20 +100,8 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon,
 
 void migrate_fd_error(MigrationState *s);
 
-int migrate_fd_cleanup(MigrationState *s);
-
-void migrate_fd_put_notify(void *opaque);
-
-ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size);
-
 void migrate_fd_connect(MigrationState *s);
 
-void migrate_fd_put_ready(void *opaque);
-
-void migrate_fd_wait_for_unfreeze(void *opaque);
-
-int migrate_fd_close(void *opaque);
-
 MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
                             int detach, int blk, int inc);
 
commit 0edda1c42aa49dd3207f3c76bf25fd53ac16345d
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue May 11 16:28:39 2010 +0200

    migration: Refactor MigrationState creation
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-exec.c b/migration-exec.c
index 0ed5976..d0119c6 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -71,7 +71,7 @@ MigrationState *exec_start_outgoing_migration(Monitor *mon,
     MigrationState *s;
     FILE *f;
 
-    s = g_malloc0(sizeof(*s));
+    s = migrate_new(mon, bandwidth_limit, detach, blk, inc);
 
     f = popen(command, "w");
     if (f == NULL) {
@@ -92,20 +92,6 @@ MigrationState *exec_start_outgoing_migration(Monitor *mon,
     s->close = exec_close;
     s->get_error = file_errno;
     s->write = file_write;
-    s->cancel = migrate_fd_cancel;
-    s->get_status = migrate_fd_get_status;
-    s->release = migrate_fd_release;
-
-    s->blk = blk;
-    s->shared = inc;
-
-    s->state = MIG_STATE_ACTIVE;
-    s->mon = NULL;
-    s->bandwidth_limit = bandwidth_limit;
-
-    if (!detach) {
-        migrate_fd_monitor_suspend(s, mon);
-    }
 
     migrate_fd_connect(s);
     return s;
diff --git a/migration-fd.c b/migration-fd.c
index e78fd4e..9d3ca42 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -59,7 +59,7 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon,
 {
     MigrationState *s;
 
-    s = g_malloc0(sizeof(*s));
+    s = migrate_new(mon, bandwidth_limit, detach, blk, inc);
 
     s->fd = monitor_get_fd(mon, fdname);
     if (s->fd == -1) {
@@ -75,20 +75,6 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon,
     s->get_error = fd_errno;
     s->write = fd_write;
     s->close = fd_close;
-    s->cancel = migrate_fd_cancel;
-    s->get_status = migrate_fd_get_status;
-    s->release = migrate_fd_release;
-
-    s->blk = blk;
-    s->shared = inc;
-
-    s->state = MIG_STATE_ACTIVE;
-    s->mon = NULL;
-    s->bandwidth_limit = bandwidth_limit;
-
-    if (!detach) {
-        migrate_fd_monitor_suspend(s, mon);
-    }
 
     migrate_fd_connect(s);
     return s;
diff --git a/migration-tcp.c b/migration-tcp.c
index d6feb23..999d4c9 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -89,21 +89,12 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon,
     if (parse_host_port(&addr, host_port) < 0)
         return NULL;
 
-    s = g_malloc0(sizeof(*s));
+    s = migrate_new(mon, bandwidth_limit, detach, blk, inc);
 
     s->get_error = socket_errno;
     s->write = socket_write;
     s->close = tcp_close;
-    s->cancel = migrate_fd_cancel;
-    s->get_status = migrate_fd_get_status;
-    s->release = migrate_fd_release;
 
-    s->blk = blk;
-    s->shared = inc;
-
-    s->state = MIG_STATE_ACTIVE;
-    s->mon = NULL;
-    s->bandwidth_limit = bandwidth_limit;
     s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
     if (s->fd == -1) {
         g_free(s);
@@ -112,10 +103,6 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon,
 
     socket_set_nonblock(s->fd);
 
-    if (!detach) {
-        migrate_fd_monitor_suspend(s, mon);
-    }
-
     do {
         ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
         if (ret == -1)
diff --git a/migration-unix.c b/migration-unix.c
index 3b9017b..bee71d9 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -88,21 +88,12 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon,
     addr.sun_family = AF_UNIX;
     snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
 
-    s = g_malloc0(sizeof(*s));
+    s = migrate_new(mon, bandwidth_limit, detach, blk, inc);
 
     s->get_error = unix_errno;
     s->write = unix_write;
     s->close = unix_close;
-    s->cancel = migrate_fd_cancel;
-    s->get_status = migrate_fd_get_status;
-    s->release = migrate_fd_release;
 
-    s->blk = blk;
-    s->shared = inc;
-
-    s->state = MIG_STATE_ACTIVE;
-    s->mon = NULL;
-    s->bandwidth_limit = bandwidth_limit;
     s->fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
     if (s->fd < 0) {
         DPRINTF("Unable to open socket");
@@ -125,10 +116,6 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon,
         goto err_after_open;
     }
 
-    if (!detach) {
-        migrate_fd_monitor_suspend(s, mon);
-    }
-
     if (ret >= 0)
         migrate_fd_connect(s);
 
diff --git a/migration.c b/migration.c
index daf3ef6..78d0f61 100644
--- a/migration.c
+++ b/migration.c
@@ -263,7 +263,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data)
 
 /* shared migration helpers */
 
-void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon)
+static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon)
 {
     s->mon = mon;
     if (monitor_suspend(mon) == 0) {
@@ -404,12 +404,12 @@ void migrate_fd_put_ready(void *opaque)
     }
 }
 
-int migrate_fd_get_status(MigrationState *s)
+static int migrate_fd_get_status(MigrationState *s)
 {
     return s->state;
 }
 
-void migrate_fd_cancel(MigrationState *s)
+static void migrate_fd_cancel(MigrationState *s)
 {
     if (s->state != MIG_STATE_ACTIVE)
         return;
@@ -423,7 +423,7 @@ void migrate_fd_cancel(MigrationState *s)
     migrate_fd_cleanup(s);
 }
 
-void migrate_fd_release(MigrationState *s)
+static void migrate_fd_release(MigrationState *s)
 {
 
     DPRINTF("releasing state\n");
@@ -488,3 +488,24 @@ int get_migration_state(void)
         return MIG_STATE_ERROR;
     }
 }
+
+MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
+                                     int detach, int blk, int inc)
+{
+    MigrationState *s = g_malloc0(sizeof(*s));
+
+    s->cancel = migrate_fd_cancel;
+    s->get_status = migrate_fd_get_status;
+    s->release = migrate_fd_release;
+    s->blk = blk;
+    s->shared = inc;
+    s->mon = NULL;
+    s->bandwidth_limit = bandwidth_limit;
+    s->state = MIG_STATE_ACTIVE;
+
+    if (!detach) {
+        migrate_fd_monitor_suspend(s, mon);
+    }
+
+    return s;
+}
diff --git a/migration.h b/migration.h
index e24efed..5f933e8 100644
--- a/migration.h
+++ b/migration.h
@@ -98,8 +98,6 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon,
 					    int blk,
 					    int inc);
 
-void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon);
-
 void migrate_fd_error(MigrationState *s);
 
 int migrate_fd_cleanup(MigrationState *s);
@@ -112,16 +110,13 @@ void migrate_fd_connect(MigrationState *s);
 
 void migrate_fd_put_ready(void *opaque);
 
-int migrate_fd_get_status(MigrationState *mig_state);
-
-void migrate_fd_cancel(MigrationState *mig_state);
-
-void migrate_fd_release(MigrationState *mig_state);
-
 void migrate_fd_wait_for_unfreeze(void *opaque);
 
 int migrate_fd_close(void *opaque);
 
+MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
+                            int detach, int blk, int inc);
+
 void add_migration_state_change_notifier(Notifier *notify);
 void remove_migration_state_change_notifier(Notifier *notify);
 int get_migration_state(void);
commit 22f00a4445fac68b10d1cb669836eeb8d32af56d
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue May 11 15:56:35 2010 +0200

    migration: Rename FdMigrationState MigrationState
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-exec.c b/migration-exec.c
index 39fd416..0ed5976 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -32,17 +32,17 @@
     do { } while (0)
 #endif
 
-static int file_errno(FdMigrationState *s)
+static int file_errno(MigrationState *s)
 {
     return errno;
 }
 
-static int file_write(FdMigrationState *s, const void * buf, size_t size)
+static int file_write(MigrationState *s, const void * buf, size_t size)
 {
     return write(s->fd, buf, size);
 }
 
-static int exec_close(FdMigrationState *s)
+static int exec_close(MigrationState *s)
 {
     int ret = 0;
     DPRINTF("exec_close\n");
@@ -61,14 +61,14 @@ static int exec_close(FdMigrationState *s)
     return ret;
 }
 
-FdMigrationState *exec_start_outgoing_migration(Monitor *mon,
+MigrationState *exec_start_outgoing_migration(Monitor *mon,
                                               const char *command,
 					      int64_t bandwidth_limit,
 					      int detach,
 					      int blk,
 					      int inc)
 {
-    FdMigrationState *s;
+    MigrationState *s;
     FILE *f;
 
     s = g_malloc0(sizeof(*s));
diff --git a/migration-fd.c b/migration-fd.c
index c3c7b0e..e78fd4e 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -30,17 +30,17 @@
     do { } while (0)
 #endif
 
-static int fd_errno(FdMigrationState *s)
+static int fd_errno(MigrationState *s)
 {
     return errno;
 }
 
-static int fd_write(FdMigrationState *s, const void * buf, size_t size)
+static int fd_write(MigrationState *s, const void * buf, size_t size)
 {
     return write(s->fd, buf, size);
 }
 
-static int fd_close(FdMigrationState *s)
+static int fd_close(MigrationState *s)
 {
     DPRINTF("fd_close\n");
     if (s->fd != -1) {
@@ -50,14 +50,14 @@ static int fd_close(FdMigrationState *s)
     return 0;
 }
 
-FdMigrationState *fd_start_outgoing_migration(Monitor *mon,
+MigrationState *fd_start_outgoing_migration(Monitor *mon,
 					    const char *fdname,
 					    int64_t bandwidth_limit,
 					    int detach,
 					    int blk,
 					    int inc)
 {
-    FdMigrationState *s;
+    MigrationState *s;
 
     s = g_malloc0(sizeof(*s));
 
diff --git a/migration-tcp.c b/migration-tcp.c
index 5ce93d9..d6feb23 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -28,17 +28,17 @@
     do { } while (0)
 #endif
 
-static int socket_errno(FdMigrationState *s)
+static int socket_errno(MigrationState *s)
 {
     return socket_error();
 }
 
-static int socket_write(FdMigrationState *s, const void * buf, size_t size)
+static int socket_write(MigrationState *s, const void * buf, size_t size)
 {
     return send(s->fd, buf, size, 0);
 }
 
-static int tcp_close(FdMigrationState *s)
+static int tcp_close(MigrationState *s)
 {
     DPRINTF("tcp_close\n");
     if (s->fd != -1) {
@@ -51,7 +51,7 @@ static int tcp_close(FdMigrationState *s)
 
 static void tcp_wait_for_connect(void *opaque)
 {
-    FdMigrationState *s = opaque;
+    MigrationState *s = opaque;
     int val, ret;
     socklen_t valsize = sizeof(val);
 
@@ -75,7 +75,7 @@ static void tcp_wait_for_connect(void *opaque)
     }
 }
 
-FdMigrationState *tcp_start_outgoing_migration(Monitor *mon,
+MigrationState *tcp_start_outgoing_migration(Monitor *mon,
                                              const char *host_port,
                                              int64_t bandwidth_limit,
                                              int detach,
@@ -83,7 +83,7 @@ FdMigrationState *tcp_start_outgoing_migration(Monitor *mon,
 					     int inc)
 {
     struct sockaddr_in addr;
-    FdMigrationState *s;
+    MigrationState *s;
     int ret;
 
     if (parse_host_port(&addr, host_port) < 0)
diff --git a/migration-unix.c b/migration-unix.c
index 00a6ed5..3b9017b 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -28,17 +28,17 @@
     do { } while (0)
 #endif
 
-static int unix_errno(FdMigrationState *s)
+static int unix_errno(MigrationState *s)
 {
     return errno;
 }
 
-static int unix_write(FdMigrationState *s, const void * buf, size_t size)
+static int unix_write(MigrationState *s, const void * buf, size_t size)
 {
     return write(s->fd, buf, size);
 }
 
-static int unix_close(FdMigrationState *s)
+static int unix_close(MigrationState *s)
 {
     DPRINTF("unix_close\n");
     if (s->fd != -1) {
@@ -50,7 +50,7 @@ static int unix_close(FdMigrationState *s)
 
 static void unix_wait_for_connect(void *opaque)
 {
-    FdMigrationState *s = opaque;
+    MigrationState *s = opaque;
     int val, ret;
     socklen_t valsize = sizeof(val);
 
@@ -74,14 +74,14 @@ static void unix_wait_for_connect(void *opaque)
     }
 }
 
-FdMigrationState *unix_start_outgoing_migration(Monitor *mon,
+MigrationState *unix_start_outgoing_migration(Monitor *mon,
                                               const char *path,
 					      int64_t bandwidth_limit,
 					      int detach,
 					      int blk,
 					      int inc)
 {
-    FdMigrationState *s;
+    MigrationState *s;
     struct sockaddr_un addr;
     int ret;
 
diff --git a/migration.c b/migration.c
index caa9e03..daf3ef6 100644
--- a/migration.c
+++ b/migration.c
@@ -34,7 +34,7 @@
 /* Migration speed throttling */
 static int64_t max_throttle = (32 << 20);
 
-static FdMigrationState *current_migration;
+static MigrationState *current_migration;
 
 static NotifierList migration_state_notifiers =
     NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
@@ -79,7 +79,7 @@ void process_incoming_migration(QEMUFile *f)
 
 int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
-    FdMigrationState *s = NULL;
+    MigrationState *s = NULL;
     const char *p;
     int detach = qdict_get_try_bool(qdict, "detach", 0);
     int blk = qdict_get_try_bool(qdict, "blk", 0);
@@ -131,7 +131,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
 
 int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
-    FdMigrationState *s = current_migration;
+    MigrationState *s = current_migration;
 
     if (s && s->get_status(s) == MIG_STATE_ACTIVE) {
         s->cancel(s);
@@ -142,7 +142,7 @@ int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
 int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     int64_t d;
-    FdMigrationState *s;
+    MigrationState *s;
 
     d = qdict_get_int(qdict, "value");
     if (d < 0) {
@@ -230,7 +230,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data)
     QDict *qdict;
 
     if (current_migration) {
-        FdMigrationState *s = current_migration;
+        MigrationState *s = current_migration;
 
         switch (s->get_status(current_migration)) {
         case MIG_STATE_ACTIVE:
@@ -263,7 +263,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data)
 
 /* shared migration helpers */
 
-void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon)
+void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon)
 {
     s->mon = mon;
     if (monitor_suspend(mon) == 0) {
@@ -274,7 +274,7 @@ void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon)
     }
 }
 
-void migrate_fd_error(FdMigrationState *s)
+void migrate_fd_error(MigrationState *s)
 {
     DPRINTF("setting error state\n");
     s->state = MIG_STATE_ERROR;
@@ -282,7 +282,7 @@ void migrate_fd_error(FdMigrationState *s)
     migrate_fd_cleanup(s);
 }
 
-int migrate_fd_cleanup(FdMigrationState *s)
+int migrate_fd_cleanup(MigrationState *s)
 {
     int ret = 0;
 
@@ -310,7 +310,7 @@ int migrate_fd_cleanup(FdMigrationState *s)
 
 void migrate_fd_put_notify(void *opaque)
 {
-    FdMigrationState *s = opaque;
+    MigrationState *s = opaque;
 
     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
     qemu_file_put_notify(s->file);
@@ -321,7 +321,7 @@ void migrate_fd_put_notify(void *opaque)
 
 ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
 {
-    FdMigrationState *s = opaque;
+    MigrationState *s = opaque;
     ssize_t ret;
 
     if (s->state != MIG_STATE_ACTIVE) {
@@ -342,7 +342,7 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
     return ret;
 }
 
-void migrate_fd_connect(FdMigrationState *s)
+void migrate_fd_connect(MigrationState *s)
 {
     int ret;
 
@@ -366,7 +366,7 @@ void migrate_fd_connect(FdMigrationState *s)
 
 void migrate_fd_put_ready(void *opaque)
 {
-    FdMigrationState *s = opaque;
+    MigrationState *s = opaque;
     int ret;
 
     if (s->state != MIG_STATE_ACTIVE) {
@@ -404,12 +404,12 @@ void migrate_fd_put_ready(void *opaque)
     }
 }
 
-int migrate_fd_get_status(FdMigrationState *s)
+int migrate_fd_get_status(MigrationState *s)
 {
     return s->state;
 }
 
-void migrate_fd_cancel(FdMigrationState *s)
+void migrate_fd_cancel(MigrationState *s)
 {
     if (s->state != MIG_STATE_ACTIVE)
         return;
@@ -423,7 +423,7 @@ void migrate_fd_cancel(FdMigrationState *s)
     migrate_fd_cleanup(s);
 }
 
-void migrate_fd_release(FdMigrationState *s)
+void migrate_fd_release(MigrationState *s)
 {
 
     DPRINTF("releasing state\n");
@@ -438,7 +438,7 @@ void migrate_fd_release(FdMigrationState *s)
 
 void migrate_fd_wait_for_unfreeze(void *opaque)
 {
-    FdMigrationState *s = opaque;
+    MigrationState *s = opaque;
     int ret;
 
     DPRINTF("wait for unfreeze\n");
@@ -461,7 +461,7 @@ void migrate_fd_wait_for_unfreeze(void *opaque)
 
 int migrate_fd_close(void *opaque)
 {
-    FdMigrationState *s = opaque;
+    MigrationState *s = opaque;
 
     if (s->mon) {
         monitor_resume(s->mon);
diff --git a/migration.h b/migration.h
index f0caf7b..e24efed 100644
--- a/migration.h
+++ b/migration.h
@@ -23,21 +23,21 @@
 #define MIG_STATE_CANCELLED	1
 #define MIG_STATE_ACTIVE	2
 
-typedef struct FdMigrationState FdMigrationState;
+typedef struct MigrationState MigrationState;
 
-struct FdMigrationState
+struct MigrationState
 {
     int64_t bandwidth_limit;
     QEMUFile *file;
     int fd;
     Monitor *mon;
     int state;
-    int (*get_error)(struct FdMigrationState*);
-    int (*close)(struct FdMigrationState*);
-    int (*write)(struct FdMigrationState*, const void *, size_t);
-    void (*cancel)(FdMigrationState *s);
-    int (*get_status)(FdMigrationState *s);
-    void (*release)(FdMigrationState *s);
+    int (*get_error)(MigrationState *s);
+    int (*close)(MigrationState *s);
+    int (*write)(MigrationState *s, const void *buff, size_t size);
+    void (*cancel)(MigrationState *s);
+    int (*get_status)(MigrationState *s);
+    void (*release)(MigrationState *s);
     void *opaque;
     int blk;
     int shared;
@@ -64,7 +64,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data);
 
 int exec_start_incoming_migration(const char *host_port);
 
-FdMigrationState *exec_start_outgoing_migration(Monitor *mon,
+MigrationState *exec_start_outgoing_migration(Monitor *mon,
                                               const char *host_port,
 					      int64_t bandwidth_limit,
 					      int detach,
@@ -73,7 +73,7 @@ FdMigrationState *exec_start_outgoing_migration(Monitor *mon,
 
 int tcp_start_incoming_migration(const char *host_port);
 
-FdMigrationState *tcp_start_outgoing_migration(Monitor *mon,
+MigrationState *tcp_start_outgoing_migration(Monitor *mon,
                                              const char *host_port,
 					     int64_t bandwidth_limit,
 					     int detach,
@@ -82,7 +82,7 @@ FdMigrationState *tcp_start_outgoing_migration(Monitor *mon,
 
 int unix_start_incoming_migration(const char *path);
 
-FdMigrationState *unix_start_outgoing_migration(Monitor *mon,
+MigrationState *unix_start_outgoing_migration(Monitor *mon,
                                               const char *path,
 					      int64_t bandwidth_limit,
 					      int detach,
@@ -91,32 +91,32 @@ FdMigrationState *unix_start_outgoing_migration(Monitor *mon,
 
 int fd_start_incoming_migration(const char *path);
 
-FdMigrationState *fd_start_outgoing_migration(Monitor *mon,
+MigrationState *fd_start_outgoing_migration(Monitor *mon,
 					    const char *fdname,
 					    int64_t bandwidth_limit,
 					    int detach,
 					    int blk,
 					    int inc);
 
-void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon);
+void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon);
 
-void migrate_fd_error(FdMigrationState *s);
+void migrate_fd_error(MigrationState *s);
 
-int migrate_fd_cleanup(FdMigrationState *s);
+int migrate_fd_cleanup(MigrationState *s);
 
 void migrate_fd_put_notify(void *opaque);
 
 ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size);
 
-void migrate_fd_connect(FdMigrationState *s);
+void migrate_fd_connect(MigrationState *s);
 
 void migrate_fd_put_ready(void *opaque);
 
-int migrate_fd_get_status(FdMigrationState *mig_state);
+int migrate_fd_get_status(MigrationState *mig_state);
 
-void migrate_fd_cancel(FdMigrationState *mig_state);
+void migrate_fd_cancel(MigrationState *mig_state);
 
-void migrate_fd_release(FdMigrationState *mig_state);
+void migrate_fd_release(MigrationState *mig_state);
 
 void migrate_fd_wait_for_unfreeze(void *opaque);
 
commit 3f77fc557e3e1cb8aab72ca0ca91aac67d478118
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue May 11 15:51:36 2010 +0200

    migration: Fold MigrationState into FdMigrationState
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-exec.c b/migration-exec.c
index 759aa79..39fd416 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -92,12 +92,12 @@ FdMigrationState *exec_start_outgoing_migration(Monitor *mon,
     s->close = exec_close;
     s->get_error = file_errno;
     s->write = file_write;
-    s->mig_state.cancel = migrate_fd_cancel;
-    s->mig_state.get_status = migrate_fd_get_status;
-    s->mig_state.release = migrate_fd_release;
+    s->cancel = migrate_fd_cancel;
+    s->get_status = migrate_fd_get_status;
+    s->release = migrate_fd_release;
 
-    s->mig_state.blk = blk;
-    s->mig_state.shared = inc;
+    s->blk = blk;
+    s->shared = inc;
 
     s->state = MIG_STATE_ACTIVE;
     s->mon = NULL;
diff --git a/migration-fd.c b/migration-fd.c
index 8036a27..c3c7b0e 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -75,12 +75,12 @@ FdMigrationState *fd_start_outgoing_migration(Monitor *mon,
     s->get_error = fd_errno;
     s->write = fd_write;
     s->close = fd_close;
-    s->mig_state.cancel = migrate_fd_cancel;
-    s->mig_state.get_status = migrate_fd_get_status;
-    s->mig_state.release = migrate_fd_release;
+    s->cancel = migrate_fd_cancel;
+    s->get_status = migrate_fd_get_status;
+    s->release = migrate_fd_release;
 
-    s->mig_state.blk = blk;
-    s->mig_state.shared = inc;
+    s->blk = blk;
+    s->shared = inc;
 
     s->state = MIG_STATE_ACTIVE;
     s->mon = NULL;
diff --git a/migration-tcp.c b/migration-tcp.c
index 05a121f..5ce93d9 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -94,12 +94,12 @@ FdMigrationState *tcp_start_outgoing_migration(Monitor *mon,
     s->get_error = socket_errno;
     s->write = socket_write;
     s->close = tcp_close;
-    s->mig_state.cancel = migrate_fd_cancel;
-    s->mig_state.get_status = migrate_fd_get_status;
-    s->mig_state.release = migrate_fd_release;
+    s->cancel = migrate_fd_cancel;
+    s->get_status = migrate_fd_get_status;
+    s->release = migrate_fd_release;
 
-    s->mig_state.blk = blk;
-    s->mig_state.shared = inc;
+    s->blk = blk;
+    s->shared = inc;
 
     s->state = MIG_STATE_ACTIVE;
     s->mon = NULL;
diff --git a/migration-unix.c b/migration-unix.c
index 0eeedde..00a6ed5 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -93,12 +93,12 @@ FdMigrationState *unix_start_outgoing_migration(Monitor *mon,
     s->get_error = unix_errno;
     s->write = unix_write;
     s->close = unix_close;
-    s->mig_state.cancel = migrate_fd_cancel;
-    s->mig_state.get_status = migrate_fd_get_status;
-    s->mig_state.release = migrate_fd_release;
+    s->cancel = migrate_fd_cancel;
+    s->get_status = migrate_fd_get_status;
+    s->release = migrate_fd_release;
 
-    s->mig_state.blk = blk;
-    s->mig_state.shared = inc;
+    s->blk = blk;
+    s->shared = inc;
 
     s->state = MIG_STATE_ACTIVE;
     s->mon = NULL;
diff --git a/migration.c b/migration.c
index e3362b7..caa9e03 100644
--- a/migration.c
+++ b/migration.c
@@ -87,8 +87,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     const char *uri = qdict_get_str(qdict, "uri");
 
     if (current_migration &&
-        current_migration->mig_state.get_status(current_migration) ==
-        MIG_STATE_ACTIVE) {
+        current_migration->get_status(current_migration) == MIG_STATE_ACTIVE) {
         monitor_printf(mon, "migration already in progress\n");
         return -1;
     }
@@ -122,7 +121,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     }
 
     if (current_migration) {
-        current_migration->mig_state.release(current_migration);
+        current_migration->release(current_migration);
     }
 
     current_migration = s;
@@ -134,8 +133,8 @@ int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     FdMigrationState *s = current_migration;
 
-    if (s && s->mig_state.get_status(s) == MIG_STATE_ACTIVE) {
-        s->mig_state.cancel(s);
+    if (s && s->get_status(s) == MIG_STATE_ACTIVE) {
+        s->cancel(s);
     }
     return 0;
 }
@@ -231,7 +230,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data)
     QDict *qdict;
 
     if (current_migration) {
-        MigrationState *s = &current_migration->mig_state;
+        FdMigrationState *s = current_migration;
 
         switch (s->get_status(current_migration)) {
         case MIG_STATE_ACTIVE:
@@ -355,8 +354,7 @@ void migrate_fd_connect(FdMigrationState *s)
                                       migrate_fd_close);
 
     DPRINTF("beginning savevm\n");
-    ret = qemu_savevm_state_begin(s->mon, s->file, s->mig_state.blk,
-                                  s->mig_state.shared);
+    ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared);
     if (ret < 0) {
         DPRINTF("failed, %d\n", ret);
         migrate_fd_error(s);
diff --git a/migration.h b/migration.h
index b10bb6e..f0caf7b 100644
--- a/migration.h
+++ b/migration.h
@@ -23,23 +23,10 @@
 #define MIG_STATE_CANCELLED	1
 #define MIG_STATE_ACTIVE	2
 
-typedef struct MigrationState MigrationState;
-
 typedef struct FdMigrationState FdMigrationState;
 
-struct MigrationState
-{
-    /* FIXME: add more accessors to print migration info */
-    void (*cancel)(FdMigrationState *s);
-    int (*get_status)(FdMigrationState *s);
-    void (*release)(FdMigrationState *s);
-    int blk;
-    int shared;
-};
-
 struct FdMigrationState
 {
-    MigrationState mig_state;
     int64_t bandwidth_limit;
     QEMUFile *file;
     int fd;
@@ -48,7 +35,12 @@ struct FdMigrationState
     int (*get_error)(struct FdMigrationState*);
     int (*close)(struct FdMigrationState*);
     int (*write)(struct FdMigrationState*, const void *, size_t);
+    void (*cancel)(FdMigrationState *s);
+    int (*get_status)(FdMigrationState *s);
+    void (*release)(FdMigrationState *s);
     void *opaque;
+    int blk;
+    int shared;
 };
 
 void process_incoming_migration(QEMUFile *f);
@@ -130,11 +122,6 @@ void migrate_fd_wait_for_unfreeze(void *opaque);
 
 int migrate_fd_close(void *opaque);
 
-static inline FdMigrationState *migrate_to_fms(MigrationState *mig_state)
-{
-    return container_of(mig_state, FdMigrationState, mig_state);
-}
-
 void add_migration_state_change_notifier(Notifier *notify);
 void remove_migration_state_change_notifier(Notifier *notify);
 int get_migration_state(void);
commit dc7acc61b67a49ce56f6a7c93692f72a3fe0759f
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue May 11 15:46:39 2010 +0200

    migration: Use FdMigrationState instead of MigrationState when possible
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 1d0c760..e3362b7 100644
--- a/migration.c
+++ b/migration.c
@@ -34,7 +34,7 @@
 /* Migration speed throttling */
 static int64_t max_throttle = (32 << 20);
 
-static MigrationState *current_migration;
+static FdMigrationState *current_migration;
 
 static NotifierList migration_state_notifiers =
     NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
@@ -87,7 +87,8 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     const char *uri = qdict_get_str(qdict, "uri");
 
     if (current_migration &&
-        current_migration->get_status(current_migration) == MIG_STATE_ACTIVE) {
+        current_migration->mig_state.get_status(current_migration) ==
+        MIG_STATE_ACTIVE) {
         monitor_printf(mon, "migration already in progress\n");
         return -1;
     }
@@ -121,20 +122,20 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     }
 
     if (current_migration) {
-        current_migration->release(current_migration);
+        current_migration->mig_state.release(current_migration);
     }
 
-    current_migration = &s->mig_state;
+    current_migration = s;
     notifier_list_notify(&migration_state_notifiers, NULL);
     return 0;
 }
 
 int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
-    MigrationState *s = current_migration;
+    FdMigrationState *s = current_migration;
 
-    if (s && s->get_status(s) == MIG_STATE_ACTIVE) {
-        s->cancel(s);
+    if (s && s->mig_state.get_status(s) == MIG_STATE_ACTIVE) {
+        s->mig_state.cancel(s);
     }
     return 0;
 }
@@ -150,7 +151,7 @@ int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
     }
     max_throttle = d;
 
-    s = migrate_to_fms(current_migration);
+    s = current_migration;
     if (s && s->file) {
         qemu_file_set_rate_limit(s->file, max_throttle);
     }
@@ -228,10 +229,11 @@ static void migrate_put_status(QDict *qdict, const char *name,
 void do_info_migrate(Monitor *mon, QObject **ret_data)
 {
     QDict *qdict;
-    MigrationState *s = current_migration;
 
-    if (s) {
-        switch (s->get_status(s)) {
+    if (current_migration) {
+        MigrationState *s = &current_migration->mig_state;
+
+        switch (s->get_status(current_migration)) {
         case MIG_STATE_ACTIVE:
             qdict = qdict_new();
             qdict_put(qdict, "status", qstring_from_str("active"));
@@ -404,16 +406,13 @@ void migrate_fd_put_ready(void *opaque)
     }
 }
 
-int migrate_fd_get_status(MigrationState *mig_state)
+int migrate_fd_get_status(FdMigrationState *s)
 {
-    FdMigrationState *s = migrate_to_fms(mig_state);
     return s->state;
 }
 
-void migrate_fd_cancel(MigrationState *mig_state)
+void migrate_fd_cancel(FdMigrationState *s)
 {
-    FdMigrationState *s = migrate_to_fms(mig_state);
-
     if (s->state != MIG_STATE_ACTIVE)
         return;
 
@@ -426,9 +425,8 @@ void migrate_fd_cancel(MigrationState *mig_state)
     migrate_fd_cleanup(s);
 }
 
-void migrate_fd_release(MigrationState *mig_state)
+void migrate_fd_release(FdMigrationState *s)
 {
-    FdMigrationState *s = migrate_to_fms(mig_state);
 
     DPRINTF("releasing state\n");
    
diff --git a/migration.h b/migration.h
index 58354c7..b10bb6e 100644
--- a/migration.h
+++ b/migration.h
@@ -25,18 +25,18 @@
 
 typedef struct MigrationState MigrationState;
 
+typedef struct FdMigrationState FdMigrationState;
+
 struct MigrationState
 {
     /* FIXME: add more accessors to print migration info */
-    void (*cancel)(MigrationState *s);
-    int (*get_status)(MigrationState *s);
-    void (*release)(MigrationState *s);
+    void (*cancel)(FdMigrationState *s);
+    int (*get_status)(FdMigrationState *s);
+    void (*release)(FdMigrationState *s);
     int blk;
     int shared;
 };
 
-typedef struct FdMigrationState FdMigrationState;
-
 struct FdMigrationState
 {
     MigrationState mig_state;
@@ -120,11 +120,11 @@ void migrate_fd_connect(FdMigrationState *s);
 
 void migrate_fd_put_ready(void *opaque);
 
-int migrate_fd_get_status(MigrationState *mig_state);
+int migrate_fd_get_status(FdMigrationState *mig_state);
 
-void migrate_fd_cancel(MigrationState *mig_state);
+void migrate_fd_cancel(FdMigrationState *mig_state);
 
-void migrate_fd_release(MigrationState *mig_state);
+void migrate_fd_release(FdMigrationState *mig_state);
 
 void migrate_fd_wait_for_unfreeze(void *opaque);
 
commit 7be4363a2828021fd486f7f45e792aecaf909454
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue May 11 15:18:38 2010 +0200

    migration: Make *start_outgoing_migration return FdMigrationState
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-exec.c b/migration-exec.c
index 2cfb6f2..759aa79 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -61,7 +61,7 @@ static int exec_close(FdMigrationState *s)
     return ret;
 }
 
-MigrationState *exec_start_outgoing_migration(Monitor *mon,
+FdMigrationState *exec_start_outgoing_migration(Monitor *mon,
                                               const char *command,
 					      int64_t bandwidth_limit,
 					      int detach,
@@ -108,7 +108,7 @@ MigrationState *exec_start_outgoing_migration(Monitor *mon,
     }
 
     migrate_fd_connect(s);
-    return &s->mig_state;
+    return s;
 
 err_after_open:
     pclose(f);
diff --git a/migration-fd.c b/migration-fd.c
index aee690a..8036a27 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -50,7 +50,7 @@ static int fd_close(FdMigrationState *s)
     return 0;
 }
 
-MigrationState *fd_start_outgoing_migration(Monitor *mon,
+FdMigrationState *fd_start_outgoing_migration(Monitor *mon,
 					    const char *fdname,
 					    int64_t bandwidth_limit,
 					    int detach,
@@ -91,7 +91,7 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon,
     }
 
     migrate_fd_connect(s);
-    return &s->mig_state;
+    return s;
 
 err_after_open:
     close(s->fd);
diff --git a/migration-tcp.c b/migration-tcp.c
index c431e03..05a121f 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -75,7 +75,7 @@ static void tcp_wait_for_connect(void *opaque)
     }
 }
 
-MigrationState *tcp_start_outgoing_migration(Monitor *mon,
+FdMigrationState *tcp_start_outgoing_migration(Monitor *mon,
                                              const char *host_port,
                                              int64_t bandwidth_limit,
                                              int detach,
@@ -131,7 +131,7 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon,
     } else if (ret >= 0)
         migrate_fd_connect(s);
 
-    return &s->mig_state;
+    return s;
 }
 
 static void tcp_accept_incoming_migration(void *opaque)
diff --git a/migration-unix.c b/migration-unix.c
index 6dc985d..0eeedde 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -74,7 +74,7 @@ static void unix_wait_for_connect(void *opaque)
     }
 }
 
-MigrationState *unix_start_outgoing_migration(Monitor *mon,
+FdMigrationState *unix_start_outgoing_migration(Monitor *mon,
                                               const char *path,
 					      int64_t bandwidth_limit,
 					      int detach,
@@ -132,7 +132,7 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon,
     if (ret >= 0)
         migrate_fd_connect(s);
 
-    return &s->mig_state;
+    return s;
 
 err_after_open:
     close(s->fd);
diff --git a/migration.c b/migration.c
index c233b52..1d0c760 100644
--- a/migration.c
+++ b/migration.c
@@ -79,7 +79,7 @@ void process_incoming_migration(QEMUFile *f)
 
 int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
-    MigrationState *s = NULL;
+    FdMigrationState *s = NULL;
     const char *p;
     int detach = qdict_get_try_bool(qdict, "detach", 0);
     int blk = qdict_get_try_bool(qdict, "blk", 0);
@@ -124,7 +124,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
         current_migration->release(current_migration);
     }
 
-    current_migration = s;
+    current_migration = &s->mig_state;
     notifier_list_notify(&migration_state_notifiers, NULL);
     return 0;
 }
diff --git a/migration.h b/migration.h
index 050c56c..58354c7 100644
--- a/migration.h
+++ b/migration.h
@@ -72,7 +72,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data);
 
 int exec_start_incoming_migration(const char *host_port);
 
-MigrationState *exec_start_outgoing_migration(Monitor *mon,
+FdMigrationState *exec_start_outgoing_migration(Monitor *mon,
                                               const char *host_port,
 					      int64_t bandwidth_limit,
 					      int detach,
@@ -81,7 +81,7 @@ MigrationState *exec_start_outgoing_migration(Monitor *mon,
 
 int tcp_start_incoming_migration(const char *host_port);
 
-MigrationState *tcp_start_outgoing_migration(Monitor *mon,
+FdMigrationState *tcp_start_outgoing_migration(Monitor *mon,
                                              const char *host_port,
 					     int64_t bandwidth_limit,
 					     int detach,
@@ -90,7 +90,7 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon,
 
 int unix_start_incoming_migration(const char *path);
 
-MigrationState *unix_start_outgoing_migration(Monitor *mon,
+FdMigrationState *unix_start_outgoing_migration(Monitor *mon,
                                               const char *path,
 					      int64_t bandwidth_limit,
 					      int detach,
@@ -99,7 +99,7 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon,
 
 int fd_start_incoming_migration(const char *path);
 
-MigrationState *fd_start_outgoing_migration(Monitor *mon,
+FdMigrationState *fd_start_outgoing_migration(Monitor *mon,
 					    const char *fdname,
 					    int64_t bandwidth_limit,
 					    int detach,
commit 2975725f6b3d634dbe924ea9d9f4d86b8a5b217d
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 19 15:22:18 2011 +0200

    migration: make *save_live return errors
    
    Make *save_live() return negative values when there is one error, and
    updates all callers to check for the error.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 98daaf3..a411fdf 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -256,6 +256,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     uint64_t bytes_transferred_last;
     double bwidth = 0;
     uint64_t expected_time = 0;
+    int ret;
 
     if (stage < 0) {
         cpu_physical_memory_set_dirty_tracking(0);
@@ -264,7 +265,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 
     if (cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX) != 0) {
         qemu_file_set_error(f, -EINVAL);
-        return 0;
+        return -EINVAL;
     }
 
     if (stage == 1) {
@@ -300,7 +301,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     bytes_transferred_last = bytes_transferred;
     bwidth = qemu_get_clock_ns(rt_clock);
 
-    while (!qemu_file_rate_limit(f)) {
+    while ((ret = qemu_file_rate_limit(f)) == 0) {
         int bytes_sent;
 
         bytes_sent = ram_save_block(f);
@@ -310,6 +311,10 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         }
     }
 
+    if (ret < 0) {
+        return ret;
+    }
+
     bwidth = qemu_get_clock_ns(rt_clock) - bwidth;
     bwidth = (bytes_transferred - bytes_transferred_last) / bwidth;
 
diff --git a/block-migration.c b/block-migration.c
index b8d19a1..0bff075 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -557,6 +557,8 @@ static void blk_mig_cleanup(Monitor *mon)
 
 static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 {
+    int ret;
+
     DPRINTF("Enter save live stage %d submitted %d transferred %d\n",
             stage, block_mig_state.submitted, block_mig_state.transferred);
 
@@ -580,9 +582,10 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 
     flush_blks(f);
 
-    if (qemu_file_get_error(f)) {
+    ret = qemu_file_get_error(f);
+    if (ret) {
         blk_mig_cleanup(mon);
-        return 0;
+        return ret;
     }
 
     blk_mig_reset_dirty_cursor();
@@ -608,9 +611,10 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 
         flush_blks(f);
 
-        if (qemu_file_get_error(f)) {
+        ret = qemu_file_get_error(f);
+        if (ret) {
             blk_mig_cleanup(mon);
-            return 0;
+            return ret;
         }
     }
 
@@ -625,8 +629,9 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         /* report completion */
         qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
 
-        if (qemu_file_get_error(f)) {
-            return 0;
+        ret = qemu_file_get_error(f);
+        if (ret) {
+            return ret;
         }
 
         monitor_printf(mon, "Block migration completed\n");
diff --git a/savevm.c b/savevm.c
index 5b340b6..9e9c783 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1534,7 +1534,11 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
         qemu_put_be32(f, se->instance_id);
         qemu_put_be32(f, se->version_id);
 
-        se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);
+        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);
+        if (ret < 0) {
+            qemu_savevm_state_cancel(mon, f);
+            return ret;
+        }
     }
     ret = qemu_file_get_error(f);
     if (ret != 0) {
@@ -1565,7 +1569,7 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
         qemu_put_be32(f, se->section_id);
 
         ret = se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque);
-        if (!ret) {
+        if (ret <= 0) {
             /* Do not proceed to the next vmstate before this one reported
                completion of the current stage. This serializes the migration
                and reduces the probability that a faster changing state is
@@ -1586,6 +1590,7 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
 int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
 {
     SaveStateEntry *se;
+    int ret;
 
     cpu_synchronize_all_states();
 
@@ -1597,7 +1602,10 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
         qemu_put_byte(f, QEMU_VM_SECTION_END);
         qemu_put_be32(f, se->section_id);
 
-        se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);
+        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);
+        if (ret < 0) {
+            return ret;
+        }
     }
 
     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
commit 42802d47dd09c6e70763676bb2ba59136427ec6a
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 5 01:14:46 2011 +0200

    migration: use qemu_file_get_error() return value when possible
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 9128be0..98daaf3 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -371,6 +371,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
 {
     ram_addr_t addr;
     int flags;
+    int error;
 
     if (version_id < 3 || version_id > 4) {
         return -EINVAL;
@@ -451,8 +452,9 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
 
             qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
         }
-        if (qemu_file_get_error(f)) {
-            return -EIO;
+        error = qemu_file_get_error(f);
+        if (error) {
+            return error;
         }
     } while (!(flags & RAM_SAVE_FLAG_EOS));
 
diff --git a/block-migration.c b/block-migration.c
index 56907a6..b8d19a1 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -647,6 +647,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
     uint8_t *buf;
     int64_t total_sectors = 0;
     int nr_sectors;
+    int ret;
 
     do {
         addr = qemu_get_be64(f);
@@ -655,7 +656,6 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
         addr >>= BDRV_SECTOR_BITS;
 
         if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) {
-            int ret;
             /* get device name */
             len = qemu_get_byte(f);
             qemu_get_buffer(f, (uint8_t *)device_name, len);
@@ -705,8 +705,9 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
             fprintf(stderr, "Unknown flags\n");
             return -EINVAL;
         }
-        if (qemu_file_get_error(f)) {
-            return -EIO;
+        ret = qemu_file_get_error(f);
+        if (ret != 0) {
+            return ret;
         }
     } while (!(flags & BLK_MIG_FLAG_EOS));
 
diff --git a/buffered_file.c b/buffered_file.c
index 41c659c..fed9a22 100644
--- a/buffered_file.c
+++ b/buffered_file.c
@@ -71,9 +71,11 @@ static void buffered_append(QEMUFileBuffered *s,
 static void buffered_flush(QEMUFileBuffered *s)
 {
     size_t offset = 0;
+    int error;
 
-    if (qemu_file_get_error(s->file)) {
-        DPRINTF("flush when error, bailing\n");
+    error = qemu_file_get_error(s->file);
+    if (error != 0) {
+        DPRINTF("flush when error, bailing: %s\n", strerror(-error));
         return;
     }
 
@@ -108,14 +110,15 @@ static void buffered_flush(QEMUFileBuffered *s)
 static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
 {
     QEMUFileBuffered *s = opaque;
-    int offset = 0;
+    int offset = 0, error;
     ssize_t ret;
 
     DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
 
-    if (qemu_file_get_error(s->file)) {
-        DPRINTF("flush when error, bailing\n");
-        return -EINVAL;
+    error = qemu_file_get_error(s->file);
+    if (error) {
+        DPRINTF("flush when error, bailing: %s\n", strerror(-error));
+        return error;
     }
 
     DPRINTF("unfreezing output\n");
@@ -192,14 +195,16 @@ static int buffered_close(void *opaque)
  * The meaning of the return values is:
  *   0: We can continue sending
  *   1: Time to stop
- *  -1: There has been an error
+ *   negative: There has been an error
  */
 static int buffered_rate_limit(void *opaque)
 {
     QEMUFileBuffered *s = opaque;
+    int ret;
 
-    if (qemu_file_get_error(s->file)) {
-        return -1;
+    ret = qemu_file_get_error(s->file);
+    if (ret) {
+        return ret;
     }
     if (s->freeze_output)
         return 1;
diff --git a/savevm.c b/savevm.c
index 89147a6..5b340b6 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1885,8 +1885,8 @@ out:
         g_free(le);
     }
 
-    if (qemu_file_get_error(f)) {
-        ret = -EIO;
+    if (ret == 0) {
+        ret = qemu_file_get_error(f);
     }
 
     return ret;
commit 3961b4dd0e72ae70e612be1097176d8910fc3f5e
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 5 01:05:21 2011 +0200

    savevm: Rename has_error to last_error field
    
    Now the field contains the last error name, so rename acordingly.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/savevm.c b/savevm.c
index 819a6f7..89147a6 100644
--- a/savevm.c
+++ b/savevm.c
@@ -173,7 +173,7 @@ struct QEMUFile {
     int buf_size; /* 0 when writing */
     uint8_t buf[IO_BUF_SIZE];
 
-    int has_error;
+    int last_error;
 };
 
 typedef struct QEMUFileStdio
@@ -427,12 +427,12 @@ QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
 
 int qemu_file_get_error(QEMUFile *f)
 {
-    return f->has_error;
+    return f->last_error;
 }
 
 void qemu_file_set_error(QEMUFile *f, int ret)
 {
-    f->has_error = ret;
+    f->last_error = ret;
 }
 
 void qemu_fflush(QEMUFile *f)
@@ -447,7 +447,7 @@ void qemu_fflush(QEMUFile *f)
         if (len > 0)
             f->buf_offset += f->buf_index;
         else
-            f->has_error = -EINVAL;
+            f->last_error = -EINVAL;
         f->buf_index = 0;
     }
 }
@@ -476,7 +476,7 @@ static void qemu_fill_buffer(QEMUFile *f)
         f->buf_size += len;
         f->buf_offset += len;
     } else if (len != -EAGAIN)
-        f->has_error = len;
+        f->last_error = len;
 }
 
 int qemu_fclose(QEMUFile *f)
@@ -498,13 +498,13 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
 {
     int l;
 
-    if (!f->has_error && f->is_write == 0 && f->buf_index > 0) {
+    if (!f->last_error && f->is_write == 0 && f->buf_index > 0) {
         fprintf(stderr,
                 "Attempted to write to buffer while read buffer is not empty\n");
         abort();
     }
 
-    while (!f->has_error && size > 0) {
+    while (!f->last_error && size > 0) {
         l = IO_BUF_SIZE - f->buf_index;
         if (l > size)
             l = size;
@@ -520,7 +520,7 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
 
 void qemu_put_byte(QEMUFile *f, int v)
 {
-    if (!f->has_error && f->is_write == 0 && f->buf_index > 0) {
+    if (!f->last_error && f->is_write == 0 && f->buf_index > 0) {
         fprintf(stderr,
                 "Attempted to write to buffer while read buffer is not empty\n");
         abort();
commit 624b9cc20922fe7b046cd79c839d1f3a5a5fc27e
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 5 01:02:52 2011 +0200

    migration: rename qemu_file_has_error to qemu_file_get_error
    
    Now the function returned errno, so it is better the new name.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index 941d585..9128be0 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -451,7 +451,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
 
             qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
         }
-        if (qemu_file_has_error(f)) {
+        if (qemu_file_get_error(f)) {
             return -EIO;
         }
     } while (!(flags & RAM_SAVE_FLAG_EOS));
diff --git a/block-migration.c b/block-migration.c
index 325c905..56907a6 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -580,7 +580,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 
     flush_blks(f);
 
-    if (qemu_file_has_error(f)) {
+    if (qemu_file_get_error(f)) {
         blk_mig_cleanup(mon);
         return 0;
     }
@@ -608,7 +608,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 
         flush_blks(f);
 
-        if (qemu_file_has_error(f)) {
+        if (qemu_file_get_error(f)) {
             blk_mig_cleanup(mon);
             return 0;
         }
@@ -625,7 +625,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         /* report completion */
         qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
 
-        if (qemu_file_has_error(f)) {
+        if (qemu_file_get_error(f)) {
             return 0;
         }
 
@@ -705,7 +705,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
             fprintf(stderr, "Unknown flags\n");
             return -EINVAL;
         }
-        if (qemu_file_has_error(f)) {
+        if (qemu_file_get_error(f)) {
             return -EIO;
         }
     } while (!(flags & BLK_MIG_FLAG_EOS));
diff --git a/buffered_file.c b/buffered_file.c
index 94ca8d1..41c659c 100644
--- a/buffered_file.c
+++ b/buffered_file.c
@@ -72,7 +72,7 @@ static void buffered_flush(QEMUFileBuffered *s)
 {
     size_t offset = 0;
 
-    if (qemu_file_has_error(s->file)) {
+    if (qemu_file_get_error(s->file)) {
         DPRINTF("flush when error, bailing\n");
         return;
     }
@@ -113,7 +113,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in
 
     DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
 
-    if (qemu_file_has_error(s->file)) {
+    if (qemu_file_get_error(s->file)) {
         DPRINTF("flush when error, bailing\n");
         return -EINVAL;
     }
@@ -172,7 +172,7 @@ static int buffered_close(void *opaque)
 
     DPRINTF("closing\n");
 
-    while (!qemu_file_has_error(s->file) && s->buffer_size) {
+    while (!qemu_file_get_error(s->file) && s->buffer_size) {
         buffered_flush(s);
         if (s->freeze_output)
             s->wait_for_unfreeze(s->opaque);
@@ -198,7 +198,7 @@ static int buffered_rate_limit(void *opaque)
 {
     QEMUFileBuffered *s = opaque;
 
-    if (qemu_file_has_error(s->file)) {
+    if (qemu_file_get_error(s->file)) {
         return -1;
     }
     if (s->freeze_output)
@@ -213,9 +213,9 @@ static int buffered_rate_limit(void *opaque)
 static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate)
 {
     QEMUFileBuffered *s = opaque;
-    if (qemu_file_has_error(s->file))
+    if (qemu_file_get_error(s->file)) {
         goto out;
-
+    }
     if (new_rate > SIZE_MAX) {
         new_rate = SIZE_MAX;
     }
@@ -237,7 +237,7 @@ static void buffered_rate_tick(void *opaque)
 {
     QEMUFileBuffered *s = opaque;
 
-    if (qemu_file_has_error(s->file)) {
+    if (qemu_file_get_error(s->file)) {
         buffered_close(s);
         return;
     }
diff --git a/hw/hw.h b/hw/hw.h
index 6cf8cd2..ed20f5a 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -85,7 +85,7 @@ uint64_t qemu_get_be64(QEMUFile *f);
 int qemu_file_rate_limit(QEMUFile *f);
 int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
 int64_t qemu_file_get_rate_limit(QEMUFile *f);
-int qemu_file_has_error(QEMUFile *f);
+int qemu_file_get_error(QEMUFile *f);
 void qemu_file_set_error(QEMUFile *f, int error);
 
 /* Try to send any outstanding data.  This function is useful when output is
diff --git a/migration.c b/migration.c
index c1d647c..c233b52 100644
--- a/migration.c
+++ b/migration.c
@@ -313,7 +313,7 @@ void migrate_fd_put_notify(void *opaque)
 
     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
     qemu_file_put_notify(s->file);
-    if (qemu_file_has_error(s->file)) {
+    if (qemu_file_get_error(s->file)) {
         migrate_fd_error(s);
     }
 }
diff --git a/savevm.c b/savevm.c
index b2f22bd..819a6f7 100644
--- a/savevm.c
+++ b/savevm.c
@@ -425,7 +425,7 @@ QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
     return f;
 }
 
-int qemu_file_has_error(QEMUFile *f)
+int qemu_file_get_error(QEMUFile *f)
 {
     return f->has_error;
 }
@@ -1536,7 +1536,7 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
 
         se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);
     }
-    ret = qemu_file_has_error(f);
+    ret = qemu_file_get_error(f);
     if (ret != 0) {
         qemu_savevm_state_cancel(mon, f);
     }
@@ -1576,7 +1576,7 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
     if (ret != 0) {
         return ret;
     }
-    ret = qemu_file_has_error(f);
+    ret = qemu_file_get_error(f);
     if (ret != 0) {
         qemu_savevm_state_cancel(mon, f);
     }
@@ -1623,7 +1623,7 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
 
     qemu_put_byte(f, QEMU_VM_EOF);
 
-    return qemu_file_has_error(f);
+    return qemu_file_get_error(f);
 }
 
 void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f)
@@ -1664,7 +1664,7 @@ static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
 
 out:
     if (ret == 0) {
-        ret = qemu_file_has_error(f);
+        ret = qemu_file_get_error(f);
     }
 
     if (!ret && saved_vm_running)
@@ -1885,8 +1885,9 @@ out:
         g_free(le);
     }
 
-    if (qemu_file_has_error(f))
+    if (qemu_file_get_error(f)) {
         ret = -EIO;
+    }
 
     return ret;
 }
commit 3934638539c763ad23026b70483e60be34078c57
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Sep 22 11:02:14 2011 +0200

    migration: return real error code
    
    make functions propagate errno, instead of just using -EIO.  Add a
    comment about what are the return value of qemu_savevm_state_iterate().
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index d5876a9..c1d647c 100644
--- a/migration.c
+++ b/migration.c
@@ -367,6 +367,7 @@ void migrate_fd_connect(FdMigrationState *s)
 void migrate_fd_put_ready(void *opaque)
 {
     FdMigrationState *s = opaque;
+    int ret;
 
     if (s->state != MIG_STATE_ACTIVE) {
         DPRINTF("put_ready returning because of non-active state\n");
@@ -374,7 +375,10 @@ void migrate_fd_put_ready(void *opaque)
     }
 
     DPRINTF("iterate\n");
-    if (qemu_savevm_state_iterate(s->mon, s->file) == 1) {
+    ret = qemu_savevm_state_iterate(s->mon, s->file);
+    if (ret < 0) {
+        migrate_fd_error(s);
+    } else if (ret == 1) {
         int old_vm_running = runstate_is_running();
 
         DPRINTF("done iterating\n");
diff --git a/savevm.c b/savevm.c
index 5bef618..b2f22bd 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1504,6 +1504,7 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
                             int shared)
 {
     SaveStateEntry *se;
+    int ret;
 
     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         if(se->set_params == NULL) {
@@ -1535,15 +1536,21 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
 
         se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);
     }
-
-    if (qemu_file_has_error(f)) {
+    ret = qemu_file_has_error(f);
+    if (ret != 0) {
         qemu_savevm_state_cancel(mon, f);
-        return -EIO;
     }
 
-    return 0;
+    return ret;
+
 }
 
+/*
+ * this funtion has three return values:
+ *   negative: there was one error, and we have -errno.
+ *   0 : We haven't finished, caller have to go again
+ *   1 : We have finished, we can go to complete phase
+ */
 int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
 {
     SaveStateEntry *se;
@@ -1566,16 +1573,14 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
             break;
         }
     }
-
-    if (ret)
-        return 1;
-
-    if (qemu_file_has_error(f)) {
+    if (ret != 0) {
+        return ret;
+    }
+    ret = qemu_file_has_error(f);
+    if (ret != 0) {
         qemu_savevm_state_cancel(mon, f);
-        return -EIO;
     }
-
-    return 0;
+    return ret;
 }
 
 int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
@@ -1618,10 +1623,7 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
 
     qemu_put_byte(f, QEMU_VM_EOF);
 
-    if (qemu_file_has_error(f))
-        return -EIO;
-
-    return 0;
+    return qemu_file_has_error(f);
 }
 
 void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f)
@@ -1661,8 +1663,9 @@ static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
     ret = qemu_savevm_state_complete(mon, f);
 
 out:
-    if (qemu_file_has_error(f))
-        ret = -EIO;
+    if (ret == 0) {
+        ret = qemu_file_has_error(f);
+    }
 
     if (!ret && saved_vm_running)
         vm_start();
commit dcd1d224dfcad1154a516e683ab55ea848497f50
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Sep 21 23:01:54 2011 +0200

    migration: change has_error to contain errno values
    
    We normally already have an errno value.  When not, abuse EIO.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index a6c69c7..941d585 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -263,7 +263,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     }
 
     if (cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX) != 0) {
-        qemu_file_set_error(f);
+        qemu_file_set_error(f, -EINVAL);
         return 0;
     }
 
diff --git a/block-migration.c b/block-migration.c
index e2775ee..325c905 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -263,7 +263,7 @@ static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
 
 error:
     monitor_printf(mon, "Error reading sector %" PRId64 "\n", cur_sector);
-    qemu_file_set_error(f);
+    qemu_file_set_error(f, -EIO);
     g_free(blk->buf);
     g_free(blk);
     return 0;
@@ -383,6 +383,7 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
     int64_t total_sectors = bmds->total_sectors;
     int64_t sector;
     int nr_sectors;
+    int ret = -EIO;
 
     for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) {
         if (bmds_aio_inflight(bmds, sector)) {
@@ -418,8 +419,8 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
                 block_mig_state.submitted++;
                 bmds_set_aio_inflight(bmds, sector, nr_sectors, 1);
             } else {
-                if (bdrv_read(bmds->bs, sector, blk->buf,
-                              nr_sectors) < 0) {
+                ret = bdrv_read(bmds->bs, sector, blk->buf, nr_sectors);
+                if (ret < 0) {
                     goto error;
                 }
                 blk_send(f, blk);
@@ -439,7 +440,7 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
 
 error:
     monitor_printf(mon, "Error reading sector %" PRId64 "\n", sector);
-    qemu_file_set_error(f);
+    qemu_file_set_error(f, ret);
     g_free(blk->buf);
     g_free(blk);
     return 0;
@@ -473,7 +474,7 @@ static void flush_blks(QEMUFile* f)
             break;
         }
         if (blk->ret < 0) {
-            qemu_file_set_error(f);
+            qemu_file_set_error(f, blk->ret);
             break;
         }
         blk_send(f, blk);
diff --git a/buffered_file.c b/buffered_file.c
index 4f49763..94ca8d1 100644
--- a/buffered_file.c
+++ b/buffered_file.c
@@ -92,7 +92,7 @@ static void buffered_flush(QEMUFileBuffered *s)
 
         if (ret <= 0) {
             DPRINTF("error flushing data, %zd\n", ret);
-            qemu_file_set_error(s->file);
+            qemu_file_set_error(s->file, ret);
             break;
         } else {
             DPRINTF("flushed %zd byte(s)\n", ret);
@@ -138,7 +138,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in
 
         if (ret <= 0) {
             DPRINTF("error putting\n");
-            qemu_file_set_error(s->file);
+            qemu_file_set_error(s->file, ret);
             offset = -EINVAL;
             break;
         }
diff --git a/hw/hw.h b/hw/hw.h
index a124da9..6cf8cd2 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -86,7 +86,7 @@ int qemu_file_rate_limit(QEMUFile *f);
 int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
 int64_t qemu_file_get_rate_limit(QEMUFile *f);
 int qemu_file_has_error(QEMUFile *f);
-void qemu_file_set_error(QEMUFile *f);
+void qemu_file_set_error(QEMUFile *f, int error);
 
 /* Try to send any outstanding data.  This function is useful when output is
  * halted due to rate limiting or EAGAIN errors occur as it can be used to
diff --git a/migration.c b/migration.c
index a682168..d5876a9 100644
--- a/migration.c
+++ b/migration.c
@@ -455,7 +455,7 @@ void migrate_fd_wait_for_unfreeze(void *opaque)
     } while (ret == -1 && (s->get_error(s)) == EINTR);
 
     if (ret == -1) {
-        qemu_file_set_error(s->file);
+        qemu_file_set_error(s->file, -s->get_error(s));
     }
 }
 
diff --git a/savevm.c b/savevm.c
index ca9e233..5bef618 100644
--- a/savevm.c
+++ b/savevm.c
@@ -430,9 +430,9 @@ int qemu_file_has_error(QEMUFile *f)
     return f->has_error;
 }
 
-void qemu_file_set_error(QEMUFile *f)
+void qemu_file_set_error(QEMUFile *f, int ret)
 {
-    f->has_error = 1;
+    f->has_error = ret;
 }
 
 void qemu_fflush(QEMUFile *f)
@@ -447,7 +447,7 @@ void qemu_fflush(QEMUFile *f)
         if (len > 0)
             f->buf_offset += f->buf_index;
         else
-            f->has_error = 1;
+            f->has_error = -EINVAL;
         f->buf_index = 0;
     }
 }
@@ -476,7 +476,7 @@ static void qemu_fill_buffer(QEMUFile *f)
         f->buf_size += len;
         f->buf_offset += len;
     } else if (len != -EAGAIN)
-        f->has_error = 1;
+        f->has_error = len;
 }
 
 int qemu_fclose(QEMUFile *f)
commit af509450816d17b4cbfff673be21b830f05018fc
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Sep 21 22:46:36 2011 +0200

    migration: set error if select return one error
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 260e5b5..a682168 100644
--- a/migration.c
+++ b/migration.c
@@ -453,6 +453,10 @@ void migrate_fd_wait_for_unfreeze(void *opaque)
 
         ret = select(s->fd + 1, NULL, &wfds, NULL, NULL);
     } while (ret == -1 && (s->get_error(s)) == EINTR);
+
+    if (ret == -1) {
+        qemu_file_set_error(s->file);
+    }
 }
 
 int migrate_fd_close(void *opaque)
commit fdbecb5d0e6a1caca5b4a732beb68771eacc7736
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Sep 21 22:37:29 2011 +0200

    migration: don't "write" when migration is not active
    
    If migration is not active, just ignore writes.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index f41a40b..260e5b5 100644
--- a/migration.c
+++ b/migration.c
@@ -323,6 +323,10 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
     FdMigrationState *s = opaque;
     ssize_t ret;
 
+    if (s->state != MIG_STATE_ACTIVE) {
+        return -EIO;
+    }
+
     do {
         ret = s->write(s, data, size);
     } while (ret == -1 && ((s->get_error(s)) == EINTR));
commit eff28a5c3b36fdca2a15e9570f67924eecb2db4f
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Sep 21 22:32:08 2011 +0200

    buffered_file: reuse QEMUFile has_error field
    
    Instead of having two has_error fields in QEMUFile & QEMUBufferedFile,
    reuse the 1st one.  Notice that the one in buffered_file is only set
    after a file operation.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/buffered_file.c b/buffered_file.c
index decc3bf..4f49763 100644
--- a/buffered_file.c
+++ b/buffered_file.c
@@ -27,7 +27,6 @@ typedef struct QEMUFileBuffered
     BufferedCloseFunc *close;
     void *opaque;
     QEMUFile *file;
-    int has_error;
     int freeze_output;
     size_t bytes_xfer;
     size_t xfer_limit;
@@ -73,7 +72,7 @@ static void buffered_flush(QEMUFileBuffered *s)
 {
     size_t offset = 0;
 
-    if (s->has_error) {
+    if (qemu_file_has_error(s->file)) {
         DPRINTF("flush when error, bailing\n");
         return;
     }
@@ -93,7 +92,7 @@ static void buffered_flush(QEMUFileBuffered *s)
 
         if (ret <= 0) {
             DPRINTF("error flushing data, %zd\n", ret);
-            s->has_error = 1;
+            qemu_file_set_error(s->file);
             break;
         } else {
             DPRINTF("flushed %zd byte(s)\n", ret);
@@ -114,7 +113,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in
 
     DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
 
-    if (s->has_error) {
+    if (qemu_file_has_error(s->file)) {
         DPRINTF("flush when error, bailing\n");
         return -EINVAL;
     }
@@ -139,7 +138,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in
 
         if (ret <= 0) {
             DPRINTF("error putting\n");
-            s->has_error = 1;
+            qemu_file_set_error(s->file);
             offset = -EINVAL;
             break;
         }
@@ -173,7 +172,7 @@ static int buffered_close(void *opaque)
 
     DPRINTF("closing\n");
 
-    while (!s->has_error && s->buffer_size) {
+    while (!qemu_file_has_error(s->file) && s->buffer_size) {
         buffered_flush(s);
         if (s->freeze_output)
             s->wait_for_unfreeze(s->opaque);
@@ -199,7 +198,7 @@ static int buffered_rate_limit(void *opaque)
 {
     QEMUFileBuffered *s = opaque;
 
-    if (s->has_error) {
+    if (qemu_file_has_error(s->file)) {
         return -1;
     }
     if (s->freeze_output)
@@ -214,7 +213,7 @@ static int buffered_rate_limit(void *opaque)
 static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate)
 {
     QEMUFileBuffered *s = opaque;
-    if (s->has_error)
+    if (qemu_file_has_error(s->file))
         goto out;
 
     if (new_rate > SIZE_MAX) {
@@ -238,7 +237,7 @@ static void buffered_rate_tick(void *opaque)
 {
     QEMUFileBuffered *s = opaque;
 
-    if (s->has_error) {
+    if (qemu_file_has_error(s->file)) {
         buffered_close(s);
         return;
     }
commit db448a088c4b3403c74adfa9b27eb6e624181d9b
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Sep 21 18:12:58 2011 +0200

    buffered_file: Use right "opaque"
    
    buffered_close 's' variable is of type QEMUFileBuffered, and
    wait_for_unfreeze() expect to receive a MigrationState, that
    'coincidentaly' is s->opaque.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/buffered_file.c b/buffered_file.c
index 94ecbbc..decc3bf 100644
--- a/buffered_file.c
+++ b/buffered_file.c
@@ -176,7 +176,7 @@ static int buffered_close(void *opaque)
     while (!s->has_error && s->buffer_size) {
         buffered_flush(s);
         if (s->freeze_output)
-            s->wait_for_unfreeze(s);
+            s->wait_for_unfreeze(s->opaque);
     }
 
     ret = s->close(s->opaque);
commit 4fc7d8195f9c8433f8661b6156e5c57ff8d8e4fb
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Feb 23 20:17:45 2011 +0100

    migration: If there is one error, it makes no sense to continue
    
    Once there, add a comment about what each error mean.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/buffered_file.c b/buffered_file.c
index 486af57..94ecbbc 100644
--- a/buffered_file.c
+++ b/buffered_file.c
@@ -189,13 +189,19 @@ static int buffered_close(void *opaque)
     return ret;
 }
 
+/*
+ * The meaning of the return values is:
+ *   0: We can continue sending
+ *   1: Time to stop
+ *  -1: There has been an error
+ */
 static int buffered_rate_limit(void *opaque)
 {
     QEMUFileBuffered *s = opaque;
 
-    if (s->has_error)
-        return 0;
-
+    if (s->has_error) {
+        return -1;
+    }
     if (s->freeze_output)
         return 1;
 
commit 2350e13c93c28f717e2ba1b31560b49ac6f81d4d
Author: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
Date:   Wed Feb 23 00:01:24 2011 +0900

    migration: add error handling to migrate_fd_put_notify().
    
    Although migrate_fd_put_buffer() sets MIG_STATE_ERROR if it failed,
    since migrate_fd_put_notify() isn't checking error of underlying
    QEMUFile, those resources are kept open.  This patch checks it and
    calls migrate_fd_error() in case of error.
    
    Signed-off-by: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 71b8aad..f41a40b 100644
--- a/migration.c
+++ b/migration.c
@@ -313,6 +313,9 @@ void migrate_fd_put_notify(void *opaque)
 
     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
     qemu_file_put_notify(s->file);
+    if (qemu_file_has_error(s->file)) {
+        migrate_fd_error(s);
+    }
 }
 
 ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
@@ -329,9 +332,6 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
 
     if (ret == -EAGAIN) {
         qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s);
-    } else if (ret < 0) {
-        s->state = MIG_STATE_ERROR;
-        notifier_list_notify(&migration_state_notifiers, NULL);
     }
 
     return ret;
commit e6494061690df2af7368752f35f5c22b5856e83c
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue May 11 22:39:51 2010 +0200

    migration: Check that migration is active before cancel it
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 7fd6c23..71b8aad 100644
--- a/migration.c
+++ b/migration.c
@@ -133,9 +133,9 @@ int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     MigrationState *s = current_migration;
 
-    if (s)
+    if (s && s->get_status(s) == MIG_STATE_ACTIVE) {
         s->cancel(s);
-
+    }
     return 0;
 }
 
commit c0b2ba46c5ceb806a1639bb86b0b457309674b23
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Sep 13 15:11:38 2011 +0200

    migration: simplify state assignmente
    
    Once there, make sure that if we already know that there is one error,
    just call migration_fd_cleanup() with the ERROR state.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 77a51ad..7fd6c23 100644
--- a/migration.c
+++ b/migration.c
@@ -371,7 +371,6 @@ void migrate_fd_put_ready(void *opaque)
 
     DPRINTF("iterate\n");
     if (qemu_savevm_state_iterate(s->mon, s->file) == 1) {
-        int state;
         int old_vm_running = runstate_is_running();
 
         DPRINTF("done iterating\n");
@@ -381,20 +380,18 @@ void migrate_fd_put_ready(void *opaque)
             if (old_vm_running) {
                 vm_start();
             }
-            state = MIG_STATE_ERROR;
-        } else {
-            state = MIG_STATE_COMPLETED;
+            s->state = MIG_STATE_ERROR;
         }
         if (migrate_fd_cleanup(s) < 0) {
             if (old_vm_running) {
                 vm_start();
             }
-            state = MIG_STATE_ERROR;
+            s->state = MIG_STATE_ERROR;
         }
-        if (state == MIG_STATE_COMPLETED) {
+        if (s->state == MIG_STATE_ACTIVE) {
+            s->state = MIG_STATE_COMPLETED;
             runstate_set(RUN_STATE_POSTMIGRATE);
         }
-        s->state = state;
         notifier_list_notify(&migration_state_notifiers, NULL);
     }
 }
commit 3a230256e8418f5cc9761f36feb6952d7ca38d73
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Sep 13 14:41:18 2011 +0200

    ds1225y: Use stdio instead of QEMUFile
    
    QEMUFile * is only intended for migration nowadays.  Using it for
    anything else just adds pain and a layer of buffers for no good
    reason.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index 9875c44..6852a61 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -29,7 +29,7 @@ typedef struct {
     DeviceState qdev;
     uint32_t chip_size;
     char *filename;
-    QEMUFile *file;
+    FILE *file;
     uint8_t *contents;
 } NvRamState;
 
@@ -70,9 +70,9 @@ static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
 
     s->contents[addr] = val;
     if (s->file) {
-        qemu_fseek(s->file, addr, SEEK_SET);
-        qemu_put_byte(s->file, (int)val);
-        qemu_fflush(s->file);
+        fseek(s->file, addr, SEEK_SET);
+        fputc(val, s->file);
+        fflush(s->file);
     }
 }
 
@@ -108,15 +108,17 @@ static int nvram_post_load(void *opaque, int version_id)
 
     /* Close file, as filename may has changed in load/store process */
     if (s->file) {
-        qemu_fclose(s->file);
+        fclose(s->file);
     }
 
     /* Write back nvram contents */
-    s->file = qemu_fopen(s->filename, "wb");
+    s->file = fopen(s->filename, "wb");
     if (s->file) {
         /* Write back contents, as 'wb' mode cleaned the file */
-        qemu_put_buffer(s->file, s->contents, s->chip_size);
-        qemu_fflush(s->file);
+        if (fwrite(s->contents, s->chip_size, 1, s->file) != 1) {
+            printf("nvram_post_load: short write\n");
+        }
+        fflush(s->file);
     }
 
     return 0;
@@ -143,7 +145,7 @@ typedef struct {
 static int nvram_sysbus_initfn(SysBusDevice *dev)
 {
     NvRamState *s = &FROM_SYSBUS(SysBusNvRamState, dev)->nvram;
-    QEMUFile *file;
+    FILE *file;
     int s_io;
 
     s->contents = g_malloc0(s->chip_size);
@@ -153,11 +155,13 @@ static int nvram_sysbus_initfn(SysBusDevice *dev)
     sysbus_init_mmio(dev, s->chip_size, s_io);
 
     /* Read current file */
-    file = qemu_fopen(s->filename, "rb");
+    file = fopen(s->filename, "rb");
     if (file) {
         /* Read nvram contents */
-        qemu_get_buffer(file, s->contents, s->chip_size);
-        qemu_fclose(file);
+        if (fread(s->contents, s->chip_size, 1, file) != 1) {
+            printf("nvram_sysbus_initfn: short read\n");
+        }
+        fclose(file);
     }
     nvram_post_load(s, 0);
 
commit 3da9eebda96780ead8ba44b8140c54f4a54c61f6
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Sep 30 19:46:43 2011 +0200

    Revert "savevm: fix corruption in vmstate_subsection_load()."
    
    This reverts commit eb60260de0b050a5e8ab725e84d377d0b44c43ae.
    
    Conflicts:
    
    	savevm.c
    
    We changed qemu_peek_byte() prototype, just fixed the rejects.
    
    Signed-off-by: Juan Quintela<quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/savevm.c b/savevm.c
index a4cb315..ca9e233 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1704,12 +1704,6 @@ static const VMStateDescription *vmstate_get_subsection(const VMStateSubsection
 static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
                                    void *opaque)
 {
-    const VMStateSubsection *sub = vmsd->subsections;
-
-    if (!sub || !sub->needed) {
-        return 0;
-    }
-
     while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
         char idstr[256];
         int ret;
@@ -1731,7 +1725,7 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
             /* it don't have a valid subsection name */
             return 0;
         }
-        sub_vmsd = vmstate_get_subsection(sub, idstr);
+        sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
         if (sub_vmsd == NULL) {
             return -ENOENT;
         }
@@ -1740,7 +1734,6 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
         qemu_file_skip(f, len); /* idstr */
         version_id = qemu_get_be32(f);
 
-        assert(!sub_vmsd->subsections);
         ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
         if (ret) {
             return ret;
@@ -1764,7 +1757,6 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
             qemu_put_byte(f, len);
             qemu_put_buffer(f, (uint8_t *)vmsd->name, len);
             qemu_put_be32(f, vmsd->version_id);
-            assert(!vmsd->subsections);
             vmstate_save_state(f, vmsd, opaque);
         }
         sub++;
commit c63807244fb55071675907460a0ecf228c1766c8
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 4 15:28:31 2011 +0200

    savevm: improve subsections detection on load
    
    We add qemu_peek_buffer, that is identical to qemu_get_buffer, just
    that it don't update f->buf_index.
    
    We add a paramenter to qemu_peek_byte() to be able to peek more than
    one byte.
    
    Once this is done, to see if we have a subsection we look:
    - 1st byte is QEMU_VM_SUBSECTION
    - 2nd byte is a length, and is bigger than section name
    - 3rd element is a string that starts with section_name
    
    So, we shouldn't have false positives (yes, content could still get us
    wrong but probabilities are really low).
    
    v2:
    - Alex Williamsom found that we could get negative values on index.
    - Rework code to fix that part.
    - Rewrite qemu_get_buffer() using qemu_peek_buffer()
    
    v3:
    - return "done" on error case
    
    v4:
    - fix qemu_file_skip() off by one.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 0380999..a4cb315 100644
--- a/savevm.c
+++ b/savevm.c
@@ -532,59 +532,85 @@ void qemu_put_byte(QEMUFile *f, int v)
         qemu_fflush(f);
 }
 
-int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
+static void qemu_file_skip(QEMUFile *f, int size)
 {
-    int size, l;
+    if (f->buf_index + size <= f->buf_size) {
+        f->buf_index += size;
+    }
+}
+
+static int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
+{
+    int pending;
+    int index;
 
     if (f->is_write) {
         abort();
     }
 
-    size = size1;
-    while (size > 0) {
-        l = f->buf_size - f->buf_index;
-        if (l == 0) {
-            qemu_fill_buffer(f);
-            l = f->buf_size - f->buf_index;
-            if (l == 0) {
-                break;
-            }
-        }
-        if (l > size) {
-            l = size;
+    index = f->buf_index + offset;
+    pending = f->buf_size - index;
+    if (pending < size) {
+        qemu_fill_buffer(f);
+        index = f->buf_index + offset;
+        pending = f->buf_size - index;
+    }
+
+    if (pending <= 0) {
+        return 0;
+    }
+    if (size > pending) {
+        size = pending;
+    }
+
+    memcpy(buf, f->buf + index, size);
+    return size;
+}
+
+int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
+{
+    int pending = size;
+    int done = 0;
+
+    while (pending > 0) {
+        int res;
+
+        res = qemu_peek_buffer(f, buf, pending, 0);
+        if (res == 0) {
+            return done;
         }
-        memcpy(buf, f->buf + f->buf_index, l);
-        f->buf_index += l;
-        buf += l;
-        size -= l;
+        qemu_file_skip(f, res);
+        buf += res;
+        pending -= res;
+        done += res;
     }
-    return size1 - size;
+    return done;
 }
 
-static int qemu_peek_byte(QEMUFile *f)
+static int qemu_peek_byte(QEMUFile *f, int offset)
 {
+    int index = f->buf_index + offset;
+
     if (f->is_write) {
         abort();
     }
 
-    if (f->buf_index >= f->buf_size) {
+    if (index >= f->buf_size) {
         qemu_fill_buffer(f);
-        if (f->buf_index >= f->buf_size) {
+        index = f->buf_index + offset;
+        if (index >= f->buf_size) {
             return 0;
         }
     }
-    return f->buf[f->buf_index];
+    return f->buf[index];
 }
 
 int qemu_get_byte(QEMUFile *f)
 {
     int result;
 
-    result = qemu_peek_byte(f);
-
-    if (f->buf_index < f->buf_size) {
-        f->buf_index++;
-    }
+    result = qemu_peek_byte(f, 0);
+    qemu_file_skip(f, 1);
     return result;
 }
 
@@ -1684,22 +1710,36 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
         return 0;
     }
 
-    while (qemu_peek_byte(f) == QEMU_VM_SUBSECTION) {
+    while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
         char idstr[256];
         int ret;
-        uint8_t version_id, len;
+        uint8_t version_id, len, size;
         const VMStateDescription *sub_vmsd;
 
-        qemu_get_byte(f); /* subsection */
-        len = qemu_get_byte(f);
-        qemu_get_buffer(f, (uint8_t *)idstr, len);
-        idstr[len] = 0;
-        version_id = qemu_get_be32(f);
+        len = qemu_peek_byte(f, 1);
+        if (len < strlen(vmsd->name) + 1) {
+            /* subsection name has be be "section_name/a" */
+            return 0;
+        }
+        size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2);
+        if (size != len) {
+            return 0;
+        }
+        idstr[size] = 0;
 
+        if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
+            /* it don't have a valid subsection name */
+            return 0;
+        }
         sub_vmsd = vmstate_get_subsection(sub, idstr);
         if (sub_vmsd == NULL) {
             return -ENOENT;
         }
+        qemu_file_skip(f, 1); /* subsection */
+        qemu_file_skip(f, 1); /* len */
+        qemu_file_skip(f, len); /* idstr */
+        version_id = qemu_get_be32(f);
+
         assert(!sub_vmsd->subsections);
         ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
         if (ret) {
commit 65f3bb3da3d5b46daebbfc54bd41ee493fdaba86
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Oct 6 14:29:32 2011 +0200

    savevm: define qemu_get_byte() using qemu_peek_byte()
    
    Signed-off-by: Juan Quintela<quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 6e4bb3a..0380999 100644
--- a/savevm.c
+++ b/savevm.c
@@ -578,17 +578,14 @@ static int qemu_peek_byte(QEMUFile *f)
 
 int qemu_get_byte(QEMUFile *f)
 {
-    if (f->is_write) {
-        abort();
-    }
+    int result;
 
-    if (f->buf_index >= f->buf_size) {
-        qemu_fill_buffer(f);
-        if (f->buf_index >= f->buf_size) {
-            return 0;
-        }
+    result = qemu_peek_byte(f);
+
+    if (f->buf_index < f->buf_size) {
+        f->buf_index++;
     }
-    return f->buf[f->buf_index++];
+    return result;
 }
 
 int64_t qemu_ftell(QEMUFile *f)
commit b9ce1454e14ec918acb90d899ce7724f69682f45
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 4 13:55:32 2011 +0200

    savevm: some coding style cleanups
    
    This patch will make moving code on next patches and having checkpatch
    happy easier.
    
    Signed-off-by: Juan Quintela<quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/savevm.c b/savevm.c
index aa6fef0..6e4bb3a 100644
--- a/savevm.c
+++ b/savevm.c
@@ -536,8 +536,9 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
 {
     int size, l;
 
-    if (f->is_write)
+    if (f->is_write) {
         abort();
+    }
 
     size = size1;
     while (size > 0) {
@@ -545,11 +546,13 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
         if (l == 0) {
             qemu_fill_buffer(f);
             l = f->buf_size - f->buf_index;
-            if (l == 0)
+            if (l == 0) {
                 break;
+            }
         }
-        if (l > size)
+        if (l > size) {
             l = size;
+        }
         memcpy(buf, f->buf + f->buf_index, l);
         f->buf_index += l;
         buf += l;
@@ -560,26 +563,30 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
 
 static int qemu_peek_byte(QEMUFile *f)
 {
-    if (f->is_write)
+    if (f->is_write) {
         abort();
+    }
 
     if (f->buf_index >= f->buf_size) {
         qemu_fill_buffer(f);
-        if (f->buf_index >= f->buf_size)
+        if (f->buf_index >= f->buf_size) {
             return 0;
+        }
     }
     return f->buf[f->buf_index];
 }
 
 int qemu_get_byte(QEMUFile *f)
 {
-    if (f->is_write)
+    if (f->is_write) {
         abort();
+    }
 
     if (f->buf_index >= f->buf_size) {
         qemu_fill_buffer(f);
-        if (f->buf_index >= f->buf_size)
+        if (f->buf_index >= f->buf_size) {
             return 0;
+        }
     }
     return f->buf[f->buf_index++];
 }
commit 0046c45bc1c70b5b985822f8639bb718f6d535a5
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Sep 30 19:28:45 2011 +0200

    savevm: teach qemu_fill_buffer to do partial refills
    
    We will need on next patch to be able to lookahead on next patch
    
    v2: rename "used" to "pending" (Alex Williams)
    
    Signed-off-by: Juan Quintela<quintela at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/savevm.c b/savevm.c
index bf4d0e7..aa6fef0 100644
--- a/savevm.c
+++ b/savevm.c
@@ -455,6 +455,7 @@ void qemu_fflush(QEMUFile *f)
 static void qemu_fill_buffer(QEMUFile *f)
 {
     int len;
+    int pending;
 
     if (!f->get_buffer)
         return;
@@ -462,10 +463,17 @@ static void qemu_fill_buffer(QEMUFile *f)
     if (f->is_write)
         abort();
 
-    len = f->get_buffer(f->opaque, f->buf, f->buf_offset, IO_BUF_SIZE);
+    pending = f->buf_size - f->buf_index;
+    if (pending > 0) {
+        memmove(f->buf, f->buf + f->buf_index, pending);
+    }
+    f->buf_index = 0;
+    f->buf_size = pending;
+
+    len = f->get_buffer(f->opaque, f->buf + pending, f->buf_offset,
+                        IO_BUF_SIZE - pending);
     if (len > 0) {
-        f->buf_index = 0;
-        f->buf_size = len;
+        f->buf_size += len;
         f->buf_offset += len;
     } else if (len != -EAGAIN)
         f->has_error = 1;
commit 8a9236f1d2e91ddd31e3eeae8fe27392c07324a9
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Fri Oct 14 11:18:09 2011 -0300

    runstate: Allow user to migrate twice
    
    It should be a matter of allowing the transition POSTMIGRATE ->
    FINISH_MIGRATE, but it turns out that the VM won't do the
    transition the second time because it's already stopped.
    
    So this commit also adds vm_stop_force_state() which performs
    the transition even if the VM is already stopped.
    
    While there also allow other states to migrate.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/cpus.c b/cpus.c
index 8978779..5f5b763 100644
--- a/cpus.c
+++ b/cpus.c
@@ -887,6 +887,17 @@ void vm_stop(RunState state)
     do_vm_stop(state);
 }
 
+/* does a state transition even if the VM is already stopped,
+   current state is forgotten forever */
+void vm_stop_force_state(RunState state)
+{
+    if (runstate_is_running()) {
+        vm_stop(state);
+    } else {
+        runstate_set(state);
+    }
+}
+
 static int tcg_cpu_exec(CPUState *env)
 {
     int ret;
diff --git a/migration.c b/migration.c
index 77a51ad..62b74a6 100644
--- a/migration.c
+++ b/migration.c
@@ -375,7 +375,7 @@ void migrate_fd_put_ready(void *opaque)
         int old_vm_running = runstate_is_running();
 
         DPRINTF("done iterating\n");
-        vm_stop(RUN_STATE_FINISH_MIGRATE);
+        vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
 
         if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
             if (old_vm_running) {
diff --git a/sysemu.h b/sysemu.h
index a889d90..7d288f8 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -35,6 +35,7 @@ void vm_state_notify(int running, RunState state);
 
 void vm_start(void);
 void vm_stop(RunState state);
+void vm_stop_force_state(RunState state);
 
 void qemu_system_reset_request(void);
 void qemu_system_shutdown_request(void);
diff --git a/vl.c b/vl.c
index 3e5fdf5..fff2b4c 100644
--- a/vl.c
+++ b/vl.c
@@ -337,17 +337,20 @@ static const RunStateTransition runstate_transitions_def[] = {
     { RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
 
     { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
+    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE },
 
     { RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
+    { RUN_STATE_IO_ERROR, RUN_STATE_FINISH_MIGRATE },
 
     { RUN_STATE_PAUSED, RUN_STATE_RUNNING },
-    { RUN_STATE_PAUSED, RUN_STATE_POSTMIGRATE },
+    { RUN_STATE_PAUSED, RUN_STATE_FINISH_MIGRATE },
 
     { RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
+    { RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE },
 
     { RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
+    { RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE },
     { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
-    { RUN_STATE_PRELAUNCH, RUN_STATE_POSTMIGRATE },
 
     { RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
     { RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
@@ -367,8 +370,10 @@ static const RunStateTransition runstate_transitions_def[] = {
     { RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
 
     { RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
+    { RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE },
 
     { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
+    { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
 
     { RUN_STATE_MAX, RUN_STATE_MAX },
 };
commit c370f09dba0f0d92e0e8127e9e444f58e9332448
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu Oct 13 11:36:40 2011 -0300

    savevm: qemu_savevm_state(): Drop stop VM logic
    
    qemu_savevm_state() has some logic to stop the VM and to (or not to)
    resume it. But this seems to be a big noop, as qemu_savevm_state()
    is only called by do_savevm() when the VM is already stopped.
    
    So, let's drop qemu_savevm_state()'s stop VM logic.
    
    Reviewed-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Reviewed-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/savevm.c b/savevm.c
index bf4d0e7..abb4a60 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1599,12 +1599,8 @@ void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f)
 
 static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
 {
-    int saved_vm_running;
     int ret;
 
-    saved_vm_running = runstate_is_running();
-    vm_stop(RUN_STATE_SAVE_VM);
-
     if (qemu_savevm_state_blocked(mon)) {
         ret = -EINVAL;
         goto out;
@@ -1626,9 +1622,6 @@ out:
     if (qemu_file_has_error(f))
         ret = -EIO;
 
-    if (!ret && saved_vm_running)
-        vm_start();
-
     return ret;
 }
 
commit ee21cb5f1db20ae449d2b59130fd6b7bdc8a6e4b
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu Oct 13 14:39:59 2011 -0300

    runstate: Allow to transition from paused to postmigrate
    
    The user may already have paused the VM before starting the
    migration process. If s/he does that, then the state will be
    'paused' when we finish the migration process. In that case
    we want to transition from 'paused' to 'postmigrate' as the
    latter is now the real reason why the VM is stopped.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/vl.c b/vl.c
index 2a634a7..3e5fdf5 100644
--- a/vl.c
+++ b/vl.c
@@ -341,6 +341,7 @@ static const RunStateTransition runstate_transitions_def[] = {
     { RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
 
     { RUN_STATE_PAUSED, RUN_STATE_RUNNING },
+    { RUN_STATE_PAUSED, RUN_STATE_POSTMIGRATE },
 
     { RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
 
commit 207c5cd20c15244b7747cacf45b8dc1fd27deaa4
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu Oct 13 10:59:07 2011 -0300

    runstate: Print state transition when invalid
    
    Makes it easier to debug.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/vl.c b/vl.c
index 2dce3ae..2a634a7 100644
--- a/vl.c
+++ b/vl.c
@@ -393,9 +393,12 @@ void runstate_init(void)
 /* This function will abort() on invalid state transitions */
 void runstate_set(RunState new_state)
 {
-    if (new_state >= RUN_STATE_MAX ||
-        !runstate_valid_transitions[current_run_state][new_state]) {
-        fprintf(stderr, "invalid runstate transition\n");
+    assert(new_state < RUN_STATE_MAX);
+
+    if (!runstate_valid_transitions[current_run_state][new_state]) {
+        fprintf(stderr, "ERROR: invalid runstate transition: '%s' -> '%s'\n",
+                RunState_lookup[current_run_state],
+                RunState_lookup[new_state]);
         abort();
     }
 
commit 7f3850c2629d197fa339ff877824d91bf77f3a49
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Oct 10 17:30:08 2011 -0300

    QMP: Fix blockdev-snapshot-sync doc example
    
    Fix wrong command name.
    
    Reported-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qmp-commands.hx b/qmp-commands.hx
index 9c11e87..4328e8b 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -710,10 +710,10 @@ Arguments:
 
 Example:
 
--> { "execute": "blockdev-snapshot", "arguments": { "device": "ide-hd0",
-                                                    "snapshot-file":
-                                                    "/some/place/my-image",
-                                                    "format": "qcow2" } }
+-> { "execute": "blockdev-snapshot-sync", "arguments": { "device": "ide-hd0",
+                                                         "snapshot-file":
+                                                        "/some/place/my-image",
+                                                        "format": "qcow2" } }
 <- { "return": {} }
 
 EQMP
commit d08151bf7c022cec3e488d72ed9c429b04979f40
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Oct 5 18:26:24 2011 +0200

    tcx: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/tcx.c b/hw/tcx.c
index 309600d..cd24100 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -40,7 +40,15 @@ typedef struct TCXState {
     DisplayState *ds;
     uint8_t *vram;
     uint32_t *vram24, *cplane;
-    ram_addr_t vram_offset, vram24_offset, cplane_offset;
+    MemoryRegion vram_mem;
+    MemoryRegion vram_8bit;
+    MemoryRegion vram_24bit;
+    MemoryRegion vram_cplane;
+    MemoryRegion dac;
+    MemoryRegion tec;
+    MemoryRegion thc24;
+    MemoryRegion thc8;
+    ram_addr_t vram24_offset, cplane_offset;
     uint32_t vram_size;
     uint32_t palette[256];
     uint8_t r[256], g[256], b[256];
@@ -56,7 +64,7 @@ static void tcx_set_dirty(TCXState *s)
     unsigned int i;
 
     for (i = 0; i < MAXX * MAXY; i += TARGET_PAGE_SIZE) {
-        cpu_physical_memory_set_dirty(s->vram_offset + i);
+        memory_region_set_dirty(&s->vram_mem, i);
     }
 }
 
@@ -65,8 +73,8 @@ static void tcx24_set_dirty(TCXState *s)
     unsigned int i;
 
     for (i = 0; i < MAXX * MAXY * 4; i += TARGET_PAGE_SIZE) {
-        cpu_physical_memory_set_dirty(s->vram24_offset + i);
-        cpu_physical_memory_set_dirty(s->cplane_offset + i);
+        memory_region_set_dirty(&s->vram_mem, s->vram24_offset + i);
+        memory_region_set_dirty(&s->vram_mem, s->cplane_offset + i);
     }
 }
 
@@ -174,16 +182,18 @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
     }
 }
 
-static inline int check_dirty(ram_addr_t page, ram_addr_t page24,
+static inline int check_dirty(TCXState *s, ram_addr_t page, ram_addr_t page24,
                               ram_addr_t cpage)
 {
     int ret;
     unsigned int off;
 
-    ret = cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG);
+    ret = memory_region_get_dirty(&s->vram_mem, page, DIRTY_MEMORY_VGA);
     for (off = 0; off < TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
-        ret |= cpu_physical_memory_get_dirty(page24 + off, VGA_DIRTY_FLAG);
-        ret |= cpu_physical_memory_get_dirty(cpage + off, VGA_DIRTY_FLAG);
+        ret |= memory_region_get_dirty(&s->vram_mem, page24 + off,
+                                       DIRTY_MEMORY_VGA);
+        ret |= memory_region_get_dirty(&s->vram_mem, cpage + off,
+                                       DIRTY_MEMORY_VGA);
     }
     return ret;
 }
@@ -192,16 +202,17 @@ static inline void reset_dirty(TCXState *ts, ram_addr_t page_min,
                                ram_addr_t page_max, ram_addr_t page24,
                               ram_addr_t cpage)
 {
-    cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
-                                    VGA_DIRTY_FLAG);
-    page_min -= ts->vram_offset;
-    page_max -= ts->vram_offset;
-    cpu_physical_memory_reset_dirty(page24 + page_min * 4,
-                                    page24 + page_max * 4 + TARGET_PAGE_SIZE,
-                                    VGA_DIRTY_FLAG);
-    cpu_physical_memory_reset_dirty(cpage + page_min * 4,
-                                    cpage + page_max * 4 + TARGET_PAGE_SIZE,
-                                    VGA_DIRTY_FLAG);
+    memory_region_reset_dirty(&ts->vram_mem,
+                              page_min, page_max + TARGET_PAGE_SIZE,
+                              DIRTY_MEMORY_VGA);
+    memory_region_reset_dirty(&ts->vram_mem,
+                              page24 + page_min * 4,
+                              page24 + page_max * 4 + TARGET_PAGE_SIZE,
+                              DIRTY_MEMORY_VGA);
+    memory_region_reset_dirty(&ts->vram_mem,
+                              cpage + page_min * 4,
+                              cpage + page_max * 4 + TARGET_PAGE_SIZE,
+                              DIRTY_MEMORY_VGA);
 }
 
 /* Fixed line length 1024 allows us to do nice tricks not possible on
@@ -216,7 +227,7 @@ static void tcx_update_display(void *opaque)
 
     if (ds_get_bits_per_pixel(ts->ds) == 0)
         return;
-    page = ts->vram_offset;
+    page = 0;
     y_start = -1;
     page_min = -1;
     page_max = 0;
@@ -242,7 +253,7 @@ static void tcx_update_display(void *opaque)
     }
 
     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
-        if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
+        if (memory_region_get_dirty(&ts->vram_mem, page, DIRTY_MEMORY_VGA)) {
             if (y_start < 0)
                 y_start = y;
             if (page < page_min)
@@ -279,8 +290,9 @@ static void tcx_update_display(void *opaque)
     }
     /* reset modified pages */
     if (page_max >= page_min) {
-        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
-                                        VGA_DIRTY_FLAG);
+        memory_region_reset_dirty(&ts->vram_mem,
+                                  page_min, page_max + TARGET_PAGE_SIZE,
+                                  DIRTY_MEMORY_VGA);
     }
 }
 
@@ -294,7 +306,7 @@ static void tcx24_update_display(void *opaque)
 
     if (ds_get_bits_per_pixel(ts->ds) != 32)
             return;
-    page = ts->vram_offset;
+    page = 0;
     page24 = ts->vram24_offset;
     cpage = ts->cplane_offset;
     y_start = -1;
@@ -309,7 +321,7 @@ static void tcx24_update_display(void *opaque)
 
     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE,
             page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
-        if (check_dirty(page, page24, cpage)) {
+        if (check_dirty(ts, page, page24, cpage)) {
             if (y_start < 0)
                 y_start = y;
             if (page < page_min)
@@ -421,18 +433,20 @@ static void tcx_reset(DeviceState *d)
     s->r[255] = s->g[255] = s->b[255] = 255;
     update_palette_entries(s, 0, 256);
     memset(s->vram, 0, MAXX*MAXY);
-    cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset +
-                                    MAXX * MAXY * (1 + 4 + 4), VGA_DIRTY_FLAG);
+    memory_region_reset_dirty(&s->vram_mem, 0, MAXX * MAXY * (1 + 4 + 4),
+                              DIRTY_MEMORY_VGA);
     s->dac_index = 0;
     s->dac_state = 0;
 }
 
-static uint32_t tcx_dac_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t tcx_dac_readl(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     return 0;
 }
 
-static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint64_t val,
+                           unsigned size)
 {
     TCXState *s = opaque;
 
@@ -468,77 +482,77 @@ static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     return;
 }
 
-static CPUReadMemoryFunc * const tcx_dac_read[3] = {
-    NULL,
-    NULL,
-    tcx_dac_readl,
+static const MemoryRegionOps tcx_dac_ops = {
+    .read = tcx_dac_readl,
+    .write = tcx_dac_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
-static CPUWriteMemoryFunc * const tcx_dac_write[3] = {
-    NULL,
-    NULL,
-    tcx_dac_writel,
-};
-
-static uint32_t tcx_dummy_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t dummy_readl(void *opaque, target_phys_addr_t addr,
+                            unsigned size)
 {
     return 0;
 }
 
-static void tcx_dummy_writel(void *opaque, target_phys_addr_t addr,
-                             uint32_t val)
+static void dummy_writel(void *opaque, target_phys_addr_t addr,
+                         uint64_t val, unsigned size)
 {
 }
 
-static CPUReadMemoryFunc * const tcx_dummy_read[3] = {
-    NULL,
-    NULL,
-    tcx_dummy_readl,
-};
-
-static CPUWriteMemoryFunc * const tcx_dummy_write[3] = {
-    NULL,
-    NULL,
-    tcx_dummy_writel,
+static const MemoryRegionOps dummy_ops = {
+    .read = dummy_readl,
+    .write = dummy_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
 };
 
 static int tcx_init1(SysBusDevice *dev)
 {
     TCXState *s = FROM_SYSBUS(TCXState, dev);
-    int io_memory, dummy_memory;
-    ram_addr_t vram_offset;
+    ram_addr_t vram_offset = 0;
     int size;
     uint8_t *vram_base;
 
-    vram_offset = qemu_ram_alloc(NULL, "tcx.vram", s->vram_size * (1 + 4 + 4));
-    vram_base = qemu_get_ram_ptr(vram_offset);
-    s->vram_offset = vram_offset;
+    memory_region_init_ram(&s->vram_mem, NULL, "tcx.vram",
+                           s->vram_size * (1 + 4 + 4));
+    vram_base = memory_region_get_ram_ptr(&s->vram_mem);
 
     /* 8-bit plane */
     s->vram = vram_base;
     size = s->vram_size;
-    sysbus_init_mmio(dev, size, s->vram_offset);
+    memory_region_init_alias(&s->vram_8bit, "tcx.vram.8bit",
+                             &s->vram_mem, vram_offset, size);
+    sysbus_init_mmio_region(dev, &s->vram_8bit);
     vram_offset += size;
     vram_base += size;
 
     /* DAC */
-    io_memory = cpu_register_io_memory(tcx_dac_read, tcx_dac_write, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, TCX_DAC_NREGS, io_memory);
+    memory_region_init_io(&s->dac, &tcx_dac_ops, s, "tcx.dac", TCX_DAC_NREGS);
+    sysbus_init_mmio_region(dev, &s->dac);
 
     /* TEC (dummy) */
-    dummy_memory = cpu_register_io_memory(tcx_dummy_read, tcx_dummy_write,
-                                          s, DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, TCX_TEC_NREGS, dummy_memory);
+    memory_region_init_io(&s->tec, &dummy_ops, s, "tcx.tec", TCX_TEC_NREGS);
+    sysbus_init_mmio_region(dev, &s->tec);
     /* THC: NetBSD writes here even with 8-bit display: dummy */
-    sysbus_init_mmio(dev, TCX_THC_NREGS_24, dummy_memory);
+    memory_region_init_io(&s->thc24, &dummy_ops, s, "tcx.thc24",
+                          TCX_THC_NREGS_24);
+    sysbus_init_mmio_region(dev, &s->thc24);
 
     if (s->depth == 24) {
         /* 24-bit plane */
         size = s->vram_size * 4;
         s->vram24 = (uint32_t *)vram_base;
         s->vram24_offset = vram_offset;
-        sysbus_init_mmio(dev, size, vram_offset);
+        memory_region_init_alias(&s->vram_24bit, "tcx.vram.24bit",
+                                 &s->vram_mem, vram_offset, size);
+        sysbus_init_mmio_region(dev, &s->vram_24bit);
         vram_offset += size;
         vram_base += size;
 
@@ -546,14 +560,18 @@ static int tcx_init1(SysBusDevice *dev)
         size = s->vram_size * 4;
         s->cplane = (uint32_t *)vram_base;
         s->cplane_offset = vram_offset;
-        sysbus_init_mmio(dev, size, vram_offset);
+        memory_region_init_alias(&s->vram_cplane, "tcx.vram.cplane",
+                                 &s->vram_mem, vram_offset, size);
+        sysbus_init_mmio_region(dev, &s->vram_cplane);
 
         s->ds = graphic_console_init(tcx24_update_display,
                                      tcx24_invalidate_display,
                                      tcx24_screen_dump, NULL, s);
     } else {
         /* THC 8 bit (dummy) */
-        sysbus_init_mmio(dev, TCX_THC_NREGS_8, dummy_memory);
+        memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
+                              TCX_THC_NREGS_8);
+        sysbus_init_mmio_region(dev, &s->thc8);
 
         s->ds = graphic_console_init(tcx_update_display,
                                      tcx_invalidate_display,
commit fe06bd93e307c4449dc1b87af2e5eac0ebe41c3a
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 3 14:42:42 2011 +0200

    tc63963xb: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/devices.h b/hw/devices.h
index 8ac384f..1a55c1e 100644
--- a/hw/devices.h
+++ b/hw/devices.h
@@ -53,7 +53,8 @@ void retu_key_event(void *retu, int state);
 /* tc6393xb.c */
 typedef struct TC6393xbState TC6393xbState;
 #define TC6393XB_RAM	0x110000 /* amount of ram for Video and USB */
-TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq);
+TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
+                             uint32_t base, qemu_irq irq);
 void tc6393xb_gpio_out_set(TC6393xbState *s, int line,
                     qemu_irq handler);
 qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s);
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index c28005a..c144dcf 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -79,6 +79,7 @@
 #define NAND_MODE_ECC_RST   0x60
 
 struct TC6393xbState {
+    MemoryRegion iomem;
     qemu_irq irq;
     qemu_irq *sub_irqs;
     struct {
@@ -122,7 +123,7 @@ struct TC6393xbState {
     ECCState ecc;
 
     DisplayState *ds;
-    ram_addr_t vram_addr;
+    MemoryRegion vram;
     uint16_t *vram_ptr;
     uint32_t scr_width, scr_height; /* in pixels */
     qemu_irq l3v;
@@ -495,7 +496,9 @@ static void tc6393xb_update_display(void *opaque)
 }
 
 
-static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr) {
+static uint64_t tc6393xb_readb(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
+{
     TC6393xbState *s = opaque;
 
     switch (addr >> 8) {
@@ -516,7 +519,8 @@ static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr) {
     return 0;
 }
 
-static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) {
+static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr,
+                            uint64_t value, unsigned size) {
     TC6393xbState *s = opaque;
 
     switch (addr >> 8) {
@@ -532,51 +536,21 @@ static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t valu
         tc6393xb_nand_writeb(s, addr & 0xff, value);
     else
         fprintf(stderr, "tc6393xb: unhandled write at %08x: %02x\n",
-					(uint32_t) addr, value & 0xff);
-}
-
-static uint32_t tc6393xb_readw(void *opaque, target_phys_addr_t addr)
-{
-    return (tc6393xb_readb(opaque, addr) & 0xff) |
-        (tc6393xb_readb(opaque, addr + 1) << 8);
-}
-
-static uint32_t tc6393xb_readl(void *opaque, target_phys_addr_t addr)
-{
-    return (tc6393xb_readb(opaque, addr) & 0xff) |
-        ((tc6393xb_readb(opaque, addr + 1) & 0xff) << 8) |
-        ((tc6393xb_readb(opaque, addr + 2) & 0xff) << 16) |
-        ((tc6393xb_readb(opaque, addr + 3) & 0xff) << 24);
+                (uint32_t) addr, (int)value & 0xff);
 }
 
-static void tc6393xb_writew(void *opaque, target_phys_addr_t addr, uint32_t value)
+TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
 {
-    tc6393xb_writeb(opaque, addr, value);
-    tc6393xb_writeb(opaque, addr + 1, value >> 8);
-}
-
-static void tc6393xb_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-    tc6393xb_writeb(opaque, addr, value);
-    tc6393xb_writeb(opaque, addr + 1, value >> 8);
-    tc6393xb_writeb(opaque, addr + 2, value >> 16);
-    tc6393xb_writeb(opaque, addr + 3, value >> 24);
-}
-
-TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq)
-{
-    int iomemtype;
     TC6393xbState *s;
     DriveInfo *nand;
-    CPUReadMemoryFunc * const tc6393xb_readfn[] = {
-        tc6393xb_readb,
-        tc6393xb_readw,
-        tc6393xb_readl,
-    };
-    CPUWriteMemoryFunc * const tc6393xb_writefn[] = {
-        tc6393xb_writeb,
-        tc6393xb_writew,
-        tc6393xb_writel,
+    static const MemoryRegionOps tc6393xb_ops = {
+        .read = tc6393xb_readb,
+        .write = tc6393xb_writeb,
+        .endianness = DEVICE_NATIVE_ENDIAN,
+        .impl = {
+            .min_access_size = 1,
+            .max_access_size = 1,
+        },
     };
 
     s = (TC6393xbState *) g_malloc0(sizeof(TC6393xbState));
@@ -591,13 +565,12 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq)
     nand = drive_get(IF_MTD, 0, 0);
     s->flash = nand_init(nand ? nand->bdrv : NULL, NAND_MFR_TOSHIBA, 0x76);
 
-    iomemtype = cpu_register_io_memory(tc6393xb_readfn,
-                    tc6393xb_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x10000, iomemtype);
+    memory_region_init_io(&s->iomem, &tc6393xb_ops, s, "tc6393xb", 0x10000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
-    s->vram_addr = qemu_ram_alloc(NULL, "tc6393xb.vram", 0x100000);
-    s->vram_ptr = qemu_get_ram_ptr(s->vram_addr);
-    cpu_register_physical_memory(base + 0x100000, 0x100000, s->vram_addr);
+    memory_region_init_ram(&s->vram, NULL, "tc6393xb.vram", 0x100000);
+    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
+    memory_region_add_subregion(sysmem, base + 0x100000, &s->vram);
     s->scr_width = 480;
     s->scr_height = 640;
     s->ds = graphic_console_init(tc6393xb_update_display,
diff --git a/hw/tosa.c b/hw/tosa.c
index 92702d1..b992b99 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -220,7 +220,7 @@ static void tosa_init(ram_addr_t ram_size,
     cpu_register_physical_memory(0, TOSA_ROM,
                     qemu_ram_alloc(NULL, "tosa.rom", TOSA_ROM) | IO_MEM_ROM);
 
-    tmio = tc6393xb_init(0x10000000,
+    tmio = tc6393xb_init(address_space_mem, 0x10000000,
             qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_TC6393XB_INT));
 
     scp0 = sysbus_create_simple("scoop", 0x08800000, NULL);
commit 9f7adc31adc20cc19908e116af444cb3215be552
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 3 14:33:26 2011 +0200

    syborg: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/syborg.c b/hw/syborg.c
index bc200e4..248de54 100644
--- a/hw/syborg.c
+++ b/hw/syborg.c
@@ -26,6 +26,7 @@
 #include "boards.h"
 #include "arm-misc.h"
 #include "net.h"
+#include "exec-memory.h"
 
 static struct arm_boot_info syborg_binfo;
 
@@ -35,9 +36,10 @@ static void syborg_init(ram_addr_t ram_size,
                         const char *initrd_filename, const char *cpu_model)
 {
     CPUState *env;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
     qemu_irq *cpu_pic;
     qemu_irq pic[64];
-    ram_addr_t ram_addr;
     DeviceState *dev;
     int i;
 
@@ -50,8 +52,8 @@ static void syborg_init(ram_addr_t ram_size,
     }
 
     /* RAM at address zero. */
-    ram_addr = qemu_ram_alloc(NULL, "syborg.ram", ram_size);
-    cpu_register_physical_memory(0, ram_size, ram_addr | IO_MEM_RAM);
+    memory_region_init_ram(ram, NULL, "syborg.ram", ram_size);
+    memory_region_add_subregion(sysmem, 0, ram);
 
     cpu_pic = arm_pic_init_cpu(env);
     dev = sysbus_create_simple("syborg,interrupt", 0xC0000000,
commit d4edce380cd692c88031cfa5adc20251832b52ab
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 3 14:31:12 2011 +0200

    sun4u: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sun4u.c b/hw/sun4u.c
index 96fc3d0..eaaefe3 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -574,6 +574,11 @@ static void pci_ebus_register(void)
 
 device_init(pci_ebus_register);
 
+typedef struct PROMState {
+    SysBusDevice busdev;
+    MemoryRegion prom;
+} PROMState;
+
 static uint64_t translate_prom_address(void *opaque, uint64_t addr)
 {
     target_phys_addr_t *base_addr = (target_phys_addr_t *)opaque;
@@ -617,17 +622,18 @@ static void prom_init(target_phys_addr_t addr, const char *bios_name)
 
 static int prom_init1(SysBusDevice *dev)
 {
-    ram_addr_t prom_offset;
+    PROMState *s = FROM_SYSBUS(PROMState, dev);
 
-    prom_offset = qemu_ram_alloc(NULL, "sun4u.prom", PROM_SIZE_MAX);
-    sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
+    memory_region_init_ram(&s->prom, NULL, "sun4u.prom", PROM_SIZE_MAX);
+    memory_region_set_readonly(&s->prom, true);
+    sysbus_init_mmio_region(dev, &s->prom);
     return 0;
 }
 
 static SysBusDeviceInfo prom_info = {
     .init = prom_init1,
     .qdev.name  = "openprom",
-    .qdev.size  = sizeof(SysBusDevice),
+    .qdev.size  = sizeof(PROMState),
     .qdev.props = (Property[]) {
         {/* end of property list */}
     }
@@ -644,19 +650,17 @@ device_init(prom_register_devices);
 typedef struct RamDevice
 {
     SysBusDevice busdev;
+    MemoryRegion ram;
     uint64_t size;
 } RamDevice;
 
 /* System RAM */
 static int ram_init1(SysBusDevice *dev)
 {
-    ram_addr_t RAM_size, ram_offset;
     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
 
-    RAM_size = d->size;
-
-    ram_offset = qemu_ram_alloc(NULL, "sun4u.ram", RAM_size);
-    sysbus_init_mmio(dev, RAM_size, ram_offset);
+    memory_region_init_ram(&d->ram, NULL, "sun4u.ram", d->size);
+    sysbus_init_mmio_region(dev, &d->ram);
     return 0;
 }
 
commit 3150fa5010331ff080c9a3fd42f8286d22cebfbc
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 3 14:27:32 2011 +0200

    sun4m: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sun4m.c b/hw/sun4m.c
index 71bf648..314edc4 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -593,19 +593,25 @@ static void idreg_init(target_phys_addr_t addr)
     cpu_physical_memory_write_rom(addr, idreg_data, sizeof(idreg_data));
 }
 
+typedef struct IDRegState {
+    SysBusDevice busdev;
+    MemoryRegion mem;
+} IDRegState;
+
 static int idreg_init1(SysBusDevice *dev)
 {
-    ram_addr_t idreg_offset;
+    IDRegState *s = FROM_SYSBUS(IDRegState, dev);
 
-    idreg_offset = qemu_ram_alloc(NULL, "sun4m.idreg", sizeof(idreg_data));
-    sysbus_init_mmio(dev, sizeof(idreg_data), idreg_offset | IO_MEM_ROM);
+    memory_region_init_ram(&s->mem, NULL, "sun4m.idreg", sizeof(idreg_data));
+    memory_region_set_readonly(&s->mem, true);
+    sysbus_init_mmio_region(dev, &s->mem);
     return 0;
 }
 
 static SysBusDeviceInfo idreg_info = {
     .init = idreg_init1,
     .qdev.name  = "macio_idreg",
-    .qdev.size  = sizeof(SysBusDevice),
+    .qdev.size  = sizeof(IDRegState),
 };
 
 static void idreg_register_devices(void)
@@ -615,6 +621,11 @@ static void idreg_register_devices(void)
 
 device_init(idreg_register_devices);
 
+typedef struct AFXState {
+    SysBusDevice busdev;
+    MemoryRegion mem;
+} AFXState;
+
 /* SS-5 TCX AFX register */
 static void afx_init(target_phys_addr_t addr)
 {
@@ -630,17 +641,17 @@ static void afx_init(target_phys_addr_t addr)
 
 static int afx_init1(SysBusDevice *dev)
 {
-    ram_addr_t afx_offset;
+    AFXState *s = FROM_SYSBUS(AFXState, dev);
 
-    afx_offset = qemu_ram_alloc(NULL, "sun4m.afx", 4);
-    sysbus_init_mmio(dev, 4, afx_offset | IO_MEM_RAM);
+    memory_region_init_ram(&s->mem, NULL, "sun4m.afx", 4);
+    sysbus_init_mmio_region(dev, &s->mem);
     return 0;
 }
 
 static SysBusDeviceInfo afx_info = {
     .init = afx_init1,
     .qdev.name  = "tcx_afx",
-    .qdev.size  = sizeof(SysBusDevice),
+    .qdev.size  = sizeof(AFXState),
 };
 
 static void afx_register_devices(void)
@@ -650,6 +661,11 @@ static void afx_register_devices(void)
 
 device_init(afx_register_devices);
 
+typedef struct PROMState {
+    SysBusDevice busdev;
+    MemoryRegion prom;
+} PROMState;
+
 /* Boot PROM (OpenBIOS) */
 static uint64_t translate_prom_address(void *opaque, uint64_t addr)
 {
@@ -693,17 +709,18 @@ static void prom_init(target_phys_addr_t addr, const char *bios_name)
 
 static int prom_init1(SysBusDevice *dev)
 {
-    ram_addr_t prom_offset;
+    PROMState *s = FROM_SYSBUS(PROMState, dev);
 
-    prom_offset = qemu_ram_alloc(NULL, "sun4m.prom", PROM_SIZE_MAX);
-    sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
+    memory_region_init_ram(&s->prom, NULL, "sun4m.prom", PROM_SIZE_MAX);
+    memory_region_set_readonly(&s->prom, true);
+    sysbus_init_mmio_region(dev, &s->prom);
     return 0;
 }
 
 static SysBusDeviceInfo prom_info = {
     .init = prom_init1,
     .qdev.name  = "openprom",
-    .qdev.size  = sizeof(SysBusDevice),
+    .qdev.size  = sizeof(PROMState),
     .qdev.props = (Property[]) {
         {/* end of property list */}
     }
@@ -719,19 +736,17 @@ device_init(prom_register_devices);
 typedef struct RamDevice
 {
     SysBusDevice busdev;
+    MemoryRegion ram;
     uint64_t size;
 } RamDevice;
 
 /* System RAM */
 static int ram_init1(SysBusDevice *dev)
 {
-    ram_addr_t RAM_size, ram_offset;
     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
 
-    RAM_size = d->size;
-
-    ram_offset = qemu_ram_alloc(NULL, "sun4m.ram", RAM_size);
-    sysbus_init_mmio(dev, RAM_size, ram_offset);
+    memory_region_init_ram(&d->ram, NULL, "sun4m.ram", d->size);
+    sysbus_init_mmio_region(dev, &d->ram);
     return 0;
 }
 
commit eb2fefbc44d8b25ff94f697adf60752ae2864c93
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 3 14:14:20 2011 +0200

    strongarm: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/collie.c b/hw/collie.c
index a10cc1b..8dd6e4e 100644
--- a/hw/collie.c
+++ b/hw/collie.c
@@ -13,6 +13,7 @@
 #include "arm-misc.h"
 #include "flash.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 static struct arm_boot_info collie_binfo = {
     .loader_start = SA_SDCS0,
@@ -26,12 +27,13 @@ static void collie_init(ram_addr_t ram_size,
 {
     StrongARMState *s;
     DriveInfo *dinfo;
+    MemoryRegion *sysmem = get_system_memory();
 
     if (!cpu_model) {
         cpu_model = "sa1110";
     }
 
-    s = sa1110_init(collie_binfo.ram_size, cpu_model);
+    s = sa1110_init(sysmem, collie_binfo.ram_size, cpu_model);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000,
diff --git a/hw/strongarm.c b/hw/strongarm.c
index 6097ea2..a3d9080 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -68,6 +68,7 @@ static struct {
 /* Interrupt Controller */
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq    irq;
     qemu_irq    fiq;
 
@@ -109,7 +110,8 @@ static void strongarm_pic_set_irq(void *opaque, int irq, int level)
     strongarm_pic_update(s);
 }
 
-static uint32_t strongarm_pic_mem_read(void *opaque, target_phys_addr_t offset)
+static uint64_t strongarm_pic_mem_read(void *opaque, target_phys_addr_t offset,
+                                       unsigned size)
 {
     StrongARMPICState *s = opaque;
 
@@ -134,7 +136,7 @@ static uint32_t strongarm_pic_mem_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void strongarm_pic_mem_write(void *opaque, target_phys_addr_t offset,
-                uint32_t value)
+                                    uint64_t value, unsigned size)
 {
     StrongARMPICState *s = opaque;
 
@@ -156,27 +158,19 @@ static void strongarm_pic_mem_write(void *opaque, target_phys_addr_t offset,
     strongarm_pic_update(s);
 }
 
-static CPUReadMemoryFunc * const strongarm_pic_readfn[] = {
-    strongarm_pic_mem_read,
-    strongarm_pic_mem_read,
-    strongarm_pic_mem_read,
-};
-
-static CPUWriteMemoryFunc * const strongarm_pic_writefn[] = {
-    strongarm_pic_mem_write,
-    strongarm_pic_mem_write,
-    strongarm_pic_mem_write,
+static const MemoryRegionOps strongarm_pic_ops = {
+    .read = strongarm_pic_mem_read,
+    .write = strongarm_pic_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int strongarm_pic_initfn(SysBusDevice *dev)
 {
     StrongARMPICState *s = FROM_SYSBUS(StrongARMPICState, dev);
-    int iomemtype;
 
     qdev_init_gpio_in(&dev->qdev, strongarm_pic_set_irq, SA_PIC_SRCS);
-    iomemtype = cpu_register_io_memory(strongarm_pic_readfn,
-                    strongarm_pic_writefn, s, DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &strongarm_pic_ops, s, "pic", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     sysbus_init_irq(dev, &s->fiq);
 
@@ -229,6 +223,7 @@ static SysBusDeviceInfo strongarm_pic_info = {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t rttr;
     uint32_t rtsr;
     uint32_t rtar;
@@ -287,7 +282,8 @@ static inline void strongarm_rtc_hz_tick(void *opaque)
     strongarm_rtc_int_update(s);
 }
 
-static uint32_t strongarm_rtc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t strongarm_rtc_read(void *opaque, target_phys_addr_t addr,
+                                   unsigned size)
 {
     StrongARMRTCState *s = opaque;
 
@@ -309,7 +305,7 @@ static uint32_t strongarm_rtc_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void strongarm_rtc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                                uint64_t value, unsigned size)
 {
     StrongARMRTCState *s = opaque;
     uint32_t old_rtsr;
@@ -349,23 +345,16 @@ static void strongarm_rtc_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const strongarm_rtc_readfn[] = {
-    strongarm_rtc_read,
-    strongarm_rtc_read,
-    strongarm_rtc_read,
-};
-
-static CPUWriteMemoryFunc * const strongarm_rtc_writefn[] = {
-    strongarm_rtc_write,
-    strongarm_rtc_write,
-    strongarm_rtc_write,
+static const MemoryRegionOps strongarm_rtc_ops = {
+    .read = strongarm_rtc_read,
+    .write = strongarm_rtc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int strongarm_rtc_init(SysBusDevice *dev)
 {
     StrongARMRTCState *s = FROM_SYSBUS(StrongARMRTCState, dev);
     struct tm tm;
-    int iomemtype;
 
     s->rttr = 0x0;
     s->rtsr = 0;
@@ -381,9 +370,8 @@ static int strongarm_rtc_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->rtc_irq);
     sysbus_init_irq(dev, &s->rtc_hz_irq);
 
-    iomemtype = cpu_register_io_memory(strongarm_rtc_readfn,
-                    strongarm_rtc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x10000, iomemtype);
+    memory_region_init_io(&s->iomem, &strongarm_rtc_ops, s, "rtc", 0x10000);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     return 0;
 }
@@ -443,6 +431,7 @@ static SysBusDeviceInfo strongarm_rtc_sysbus_info = {
 typedef struct StrongARMGPIOInfo StrongARMGPIOInfo;
 struct StrongARMGPIOInfo {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq handler[28];
     qemu_irq irqs[11];
     qemu_irq irqX;
@@ -507,7 +496,8 @@ static void strongarm_gpio_handler_update(StrongARMGPIOInfo *s)
     s->prev_level = level;
 }
 
-static uint32_t strongarm_gpio_read(void *opaque, target_phys_addr_t offset)
+static uint64_t strongarm_gpio_read(void *opaque, target_phys_addr_t offset,
+                                    unsigned size)
 {
     StrongARMGPIOInfo *s = opaque;
 
@@ -548,8 +538,8 @@ static uint32_t strongarm_gpio_read(void *opaque, target_phys_addr_t offset)
     return 0;
 }
 
-static void strongarm_gpio_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void strongarm_gpio_write(void *opaque, target_phys_addr_t offset,
+                                 uint64_t value, unsigned size)
 {
     StrongARMGPIOInfo *s = opaque;
 
@@ -592,16 +582,10 @@ static void strongarm_gpio_write(void *opaque,
     }
 }
 
-static CPUReadMemoryFunc * const strongarm_gpio_readfn[] = {
-    strongarm_gpio_read,
-    strongarm_gpio_read,
-    strongarm_gpio_read
-};
-
-static CPUWriteMemoryFunc * const strongarm_gpio_writefn[] = {
-    strongarm_gpio_write,
-    strongarm_gpio_write,
-    strongarm_gpio_write
+static const MemoryRegionOps strongarm_gpio_ops = {
+    .read = strongarm_gpio_read,
+    .write = strongarm_gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static DeviceState *strongarm_gpio_init(target_phys_addr_t base,
@@ -623,7 +607,6 @@ static DeviceState *strongarm_gpio_init(target_phys_addr_t base,
 
 static int strongarm_gpio_initfn(SysBusDevice *dev)
 {
-    int iomemtype;
     StrongARMGPIOInfo *s;
     int i;
 
@@ -632,10 +615,9 @@ static int strongarm_gpio_initfn(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, strongarm_gpio_set, 28);
     qdev_init_gpio_out(&dev->qdev, s->handler, 28);
 
-    iomemtype = cpu_register_io_memory(strongarm_gpio_readfn,
-                    strongarm_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&s->iomem, &strongarm_gpio_ops, s, "gpio", 0x1000);
 
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    sysbus_init_mmio_region(dev, &s->iomem);
     for (i = 0; i < 11; i++) {
         sysbus_init_irq(dev, &s->irqs[i]);
     }
@@ -678,6 +660,7 @@ static SysBusDeviceInfo strongarm_gpio_info = {
 typedef struct StrongARMPPCInfo StrongARMPPCInfo;
 struct StrongARMPPCInfo {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq handler[28];
 
     uint32_t ilevel;
@@ -716,7 +699,8 @@ static void strongarm_ppc_handler_update(StrongARMPPCInfo *s)
     s->prev_level = level;
 }
 
-static uint32_t strongarm_ppc_read(void *opaque, target_phys_addr_t offset)
+static uint64_t strongarm_ppc_read(void *opaque, target_phys_addr_t offset,
+                                   unsigned size)
 {
     StrongARMPPCInfo *s = opaque;
 
@@ -745,8 +729,8 @@ static uint32_t strongarm_ppc_read(void *opaque, target_phys_addr_t offset)
     return 0;
 }
 
-static void strongarm_ppc_write(void *opaque,
-                target_phys_addr_t offset, uint32_t value)
+static void strongarm_ppc_write(void *opaque, target_phys_addr_t offset,
+                                uint64_t value, unsigned size)
 {
     StrongARMPPCInfo *s = opaque;
 
@@ -778,21 +762,14 @@ static void strongarm_ppc_write(void *opaque,
     }
 }
 
-static CPUReadMemoryFunc * const strongarm_ppc_readfn[] = {
-    strongarm_ppc_read,
-    strongarm_ppc_read,
-    strongarm_ppc_read
-};
-
-static CPUWriteMemoryFunc * const strongarm_ppc_writefn[] = {
-    strongarm_ppc_write,
-    strongarm_ppc_write,
-    strongarm_ppc_write
+static const MemoryRegionOps strongarm_ppc_ops = {
+    .read = strongarm_ppc_read,
+    .write = strongarm_ppc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int strongarm_ppc_init(SysBusDevice *dev)
 {
-    int iomemtype;
     StrongARMPPCInfo *s;
 
     s = FROM_SYSBUS(StrongARMPPCInfo, dev);
@@ -800,10 +777,9 @@ static int strongarm_ppc_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, strongarm_ppc_set, 22);
     qdev_init_gpio_out(&dev->qdev, s->handler, 22);
 
-    iomemtype = cpu_register_io_memory(strongarm_ppc_readfn,
-                    strongarm_ppc_writefn, s, DEVICE_NATIVE_ENDIAN);
+    memory_region_init_io(&s->iomem, &strongarm_ppc_ops, s, "ppc", 0x1000);
 
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     return 0;
 }
@@ -871,6 +847,7 @@ static SysBusDeviceInfo strongarm_ppc_info = {
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     CharDriverState *chr;
     qemu_irq irq;
 
@@ -1079,7 +1056,8 @@ static void strongarm_uart_tx(void *opaque)
     strongarm_uart_update_int_status(s);
 }
 
-static uint32_t strongarm_uart_read(void *opaque, target_phys_addr_t addr)
+static uint64_t strongarm_uart_read(void *opaque, target_phys_addr_t addr,
+                                    unsigned size)
 {
     StrongARMUARTState *s = opaque;
     uint16_t ret;
@@ -1121,7 +1099,7 @@ static uint32_t strongarm_uart_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void strongarm_uart_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                                 uint64_t value, unsigned size)
 {
     StrongARMUARTState *s = opaque;
 
@@ -1176,26 +1154,18 @@ static void strongarm_uart_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const strongarm_uart_readfn[] = {
-    strongarm_uart_read,
-    strongarm_uart_read,
-    strongarm_uart_read,
-};
-
-static CPUWriteMemoryFunc * const strongarm_uart_writefn[] = {
-    strongarm_uart_write,
-    strongarm_uart_write,
-    strongarm_uart_write,
+static const MemoryRegionOps strongarm_uart_ops = {
+    .read = strongarm_uart_read,
+    .write = strongarm_uart_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int strongarm_uart_init(SysBusDevice *dev)
 {
     StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
-    int iomemtype;
 
-    iomemtype = cpu_register_io_memory(strongarm_uart_readfn,
-                    strongarm_uart_writefn, s, DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x10000, iomemtype);
+    memory_region_init_io(&s->iomem, &strongarm_uart_ops, s, "uart", 0x10000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     s->rx_timeout_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_rx_to, s);
@@ -1288,6 +1258,7 @@ static SysBusDeviceInfo strongarm_uart_info = {
 /* Synchronous Serial Ports */
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq irq;
     SSIBus *bus;
 
@@ -1355,7 +1326,8 @@ static void strongarm_ssp_fifo_update(StrongARMSSPState *s)
     strongarm_ssp_int_update(s);
 }
 
-static uint32_t strongarm_ssp_read(void *opaque, target_phys_addr_t addr)
+static uint64_t strongarm_ssp_read(void *opaque, target_phys_addr_t addr,
+                                   unsigned size)
 {
     StrongARMSSPState *s = opaque;
     uint32_t retval;
@@ -1388,7 +1360,7 @@ static uint32_t strongarm_ssp_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void strongarm_ssp_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                                uint64_t value, unsigned size)
 {
     StrongARMSSPState *s = opaque;
 
@@ -1397,7 +1369,7 @@ static void strongarm_ssp_write(void *opaque, target_phys_addr_t addr,
         s->sscr[0] = value & 0xffbf;
         if ((s->sscr[0] & SSCR0_SSE) && SSCR0_DSS(value) < 4) {
             printf("%s: Wrong data size: %i bits\n", __func__,
-                            SSCR0_DSS(value));
+                   (int)SSCR0_DSS(value));
         }
         if (!(value & SSCR0_SSE)) {
             s->sssr = 0;
@@ -1452,16 +1424,10 @@ static void strongarm_ssp_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const strongarm_ssp_readfn[] = {
-    strongarm_ssp_read,
-    strongarm_ssp_read,
-    strongarm_ssp_read,
-};
-
-static CPUWriteMemoryFunc * const strongarm_ssp_writefn[] = {
-    strongarm_ssp_write,
-    strongarm_ssp_write,
-    strongarm_ssp_write,
+static const MemoryRegionOps strongarm_ssp_ops = {
+    .read = strongarm_ssp_read,
+    .write = strongarm_ssp_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int strongarm_ssp_post_load(void *opaque, int version_id)
@@ -1475,15 +1441,12 @@ static int strongarm_ssp_post_load(void *opaque, int version_id)
 
 static int strongarm_ssp_init(SysBusDevice *dev)
 {
-    int iomemtype;
     StrongARMSSPState *s = FROM_SYSBUS(StrongARMSSPState, dev);
 
     sysbus_init_irq(dev, &s->irq);
 
-    iomemtype = cpu_register_io_memory(strongarm_ssp_readfn,
-                                       strongarm_ssp_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &strongarm_ssp_ops, s, "ssp", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     s->bus = ssi_create_bus(&dev->qdev, "ssi");
     return 0;
@@ -1523,7 +1486,8 @@ static SysBusDeviceInfo strongarm_ssp_info = {
 };
 
 /* Main CPU functions */
-StrongARMState *sa1110_init(unsigned int sdram_size, const char *rev)
+StrongARMState *sa1110_init(MemoryRegion *sysmem,
+                            unsigned int sdram_size, const char *rev)
 {
     StrongARMState *s;
     qemu_irq *pic;
@@ -1547,9 +1511,8 @@ StrongARMState *sa1110_init(unsigned int sdram_size, const char *rev)
         exit(1);
     }
 
-    cpu_register_physical_memory(SA_SDCS0,
-                    sdram_size, qemu_ram_alloc(NULL, "strongarm.sdram",
-                                                sdram_size) | IO_MEM_RAM);
+    memory_region_init_ram(&s->sdram, NULL, "strongarm.sdram", sdram_size);
+    memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram);
 
     pic = arm_pic_init_cpu(s->env);
     s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000,
diff --git a/hw/strongarm.h b/hw/strongarm.h
index a81b110..684f61b 100644
--- a/hw/strongarm.h
+++ b/hw/strongarm.h
@@ -1,6 +1,8 @@
 #ifndef _STRONGARM_H
 #define _STRONGARM_H
 
+#include "memory.h"
+
 #define SA_CS0          0x00000000
 #define SA_CS1          0x08000000
 #define SA_CS2          0x10000000
@@ -52,6 +54,7 @@ enum {
 
 typedef struct {
     CPUState *env;
+    MemoryRegion sdram;
     DeviceState *pic;
     DeviceState *gpio;
     DeviceState *ppc;
@@ -59,6 +62,7 @@ typedef struct {
     SSIBus *ssp_bus;
 } StrongARMState;
 
-StrongARMState *sa1110_init(unsigned int sdram_size, const char *rev);
+StrongARMState *sa1110_init(MemoryRegion *sysmem,
+                            unsigned int sdram_size, const char *rev);
 
 #endif
commit 7cc09e6c4b51978a656ff5e6c0a5faafec2d82e6
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 3 13:03:56 2011 +0200

    spitz: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/spitz.c b/hw/spitz.c
index 6f8a94c..23f9d41 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -49,6 +49,7 @@
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     DeviceState *nand;
     uint8_t ctl;
     uint8_t manf_id;
@@ -56,7 +57,7 @@ typedef struct {
     ECCState ecc;
 } SLNANDState;
 
-static uint32_t sl_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t sl_read(void *opaque, target_phys_addr_t addr, unsigned size)
 {
     SLNANDState *s = (SLNANDState *) opaque;
     int ryby;
@@ -86,6 +87,10 @@ static uint32_t sl_readb(void *opaque, target_phys_addr_t addr)
             return s->ctl;
 
     case FLASH_FLASHIO:
+        if (size == 4) {
+            return ecc_digest(&s->ecc, nand_getio(s->nand)) |
+                (ecc_digest(&s->ecc, nand_getio(s->nand)) << 16);
+        }
         return ecc_digest(&s->ecc, nand_getio(s->nand));
 
     default:
@@ -94,19 +99,8 @@ static uint32_t sl_readb(void *opaque, target_phys_addr_t addr)
     return 0;
 }
 
-static uint32_t sl_readl(void *opaque, target_phys_addr_t addr)
-{
-    SLNANDState *s = (SLNANDState *) opaque;
-
-    if (addr == FLASH_FLASHIO)
-        return ecc_digest(&s->ecc, nand_getio(s->nand)) |
-                (ecc_digest(&s->ecc, nand_getio(s->nand)) << 16);
-
-    return sl_readb(opaque, addr);
-}
-
-static void sl_writeb(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+static void sl_write(void *opaque, target_phys_addr_t addr,
+                     uint64_t value, unsigned size)
 {
     SLNANDState *s = (SLNANDState *) opaque;
 
@@ -140,15 +134,10 @@ enum {
     FLASH_1024M,
 };
 
-static CPUReadMemoryFunc * const sl_readfn[] = {
-    sl_readb,
-    sl_readb,
-    sl_readl,
-};
-static CPUWriteMemoryFunc * const sl_writefn[] = {
-    sl_writeb,
-    sl_writeb,
-    sl_writeb,
+static const MemoryRegionOps sl_ops = {
+    .read = sl_read,
+    .write = sl_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void sl_flash_register(PXA2xxState *cpu, int size)
@@ -168,7 +157,6 @@ static void sl_flash_register(PXA2xxState *cpu, int size)
 }
 
 static int sl_nand_init(SysBusDevice *dev) {
-    int iomemtype;
     SLNANDState *s;
     DriveInfo *nand;
 
@@ -178,10 +166,8 @@ static int sl_nand_init(SysBusDevice *dev) {
     nand = drive_get(IF_MTD, 0, 0);
     s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
 
-    iomemtype = cpu_register_io_memory(sl_readfn,
-                    sl_writefn, s, DEVICE_NATIVE_ENDIAN);
-
-    sysbus_init_mmio(dev, 0x40, iomemtype);
+    memory_region_init_io(&s->iomem, &sl_ops, s, "sl", 0x40);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     return 0;
 }
@@ -898,6 +884,7 @@ static void spitz_common_init(ram_addr_t ram_size,
     PXA2xxState *cpu;
     DeviceState *scp0, *scp1 = NULL;
     MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
 
     if (!cpu_model)
         cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
@@ -907,8 +894,9 @@ static void spitz_common_init(ram_addr_t ram_size,
 
     sl_flash_register(cpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
 
-    cpu_register_physical_memory(0, SPITZ_ROM,
-                    qemu_ram_alloc(NULL, "spitz.rom", SPITZ_ROM) | IO_MEM_ROM);
+    memory_region_init_ram(rom, NULL, "spitz.rom", SPITZ_ROM);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(address_space_mem, 0, rom);
 
     /* Setup peripherals */
     spitz_keyboard_register(cpu);
commit 890c2b772da673785351cad38797b12dcd08d5fa
Author: Avi Kivity <avi at redhat.com>
Date:   Mon Oct 3 12:56:38 2011 +0200

    spapr: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/spapr.c b/hw/spapr.c
index b118975..63e5d33 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -41,6 +41,8 @@
 #include "kvm.h"
 #include "kvm_ppc.h"
 
+#include "exec-memory.h"
+
 #include <libfdt.h>
 
 #define KERNEL_LOAD_ADDR        0x00000000
@@ -324,7 +326,8 @@ static void ppc_spapr_init(ram_addr_t ram_size,
 {
     CPUState *env;
     int i;
-    ram_addr_t ram_offset;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
     uint32_t initrd_base;
     long kernel_size, initrd_size, fw_size;
     long pteg_shift = 17;
@@ -361,8 +364,8 @@ static void ppc_spapr_init(ram_addr_t ram_size,
 
     /* allocate RAM */
     spapr->ram_limit = ram_size;
-    ram_offset = qemu_ram_alloc(NULL, "ppc_spapr.ram", spapr->ram_limit);
-    cpu_register_physical_memory(0, ram_size, ram_offset);
+    memory_region_init_ram(ram, NULL, "ppc_spapr.ram", spapr->ram_limit);
+    memory_region_add_subregion(sysmem, 0, ram);
 
     /* allocate hash page table.  For now we always make this 16mb,
      * later we should probably make it scale to the size of guest
commit 25793bfafafbd124cd1ceae8de3e3bfd30b7f2d9
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Oct 2 17:56:06 2011 +0200

    sm501: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/sm501.c b/hw/sm501.c
index a7ed6fa..297bc9c 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -459,7 +459,7 @@ typedef struct SM501State {
     target_phys_addr_t base;
     uint32_t local_mem_size_index;
     uint8_t * local_mem;
-    ram_addr_t local_mem_offset;
+    MemoryRegion local_mem_region;
     uint32_t last_width;
     uint32_t last_height;
 
@@ -726,7 +726,8 @@ static void sm501_2d_operation(SM501State * s)
     }
 }
 
-static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr)
+static uint64_t sm501_system_config_read(void *opaque, target_phys_addr_t addr,
+                                         unsigned size)
 {
     SM501State * s = (SM501State *)opaque;
     uint32_t ret = 0;
@@ -778,12 +779,12 @@ static uint32_t sm501_system_config_read(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void sm501_system_config_write(void *opaque,
-				      target_phys_addr_t addr, uint32_t value)
+static void sm501_system_config_write(void *opaque, target_phys_addr_t addr,
+                                      uint64_t value, unsigned size)
 {
     SM501State * s = (SM501State *)opaque;
     SM501_DPRINTF("sm501 system config regs : write addr=%x, val=%x\n",
-		  addr, value);
+		  (uint32_t)addr, (uint32_t)value);
 
     switch(addr) {
     case SM501_SYSTEM_CONTROL:
@@ -821,21 +822,19 @@ static void sm501_system_config_write(void *opaque,
 
     default:
 	printf("sm501 system config : not implemented register write."
-	       " addr=%x, val=%x\n", (int)addr, value);
+	       " addr=%x, val=%x\n", (int)addr, (uint32_t)value);
         abort();
     }
 }
 
-static CPUReadMemoryFunc * const sm501_system_config_readfn[] = {
-    NULL,
-    NULL,
-    &sm501_system_config_read,
-};
-
-static CPUWriteMemoryFunc * const sm501_system_config_writefn[] = {
-    NULL,
-    NULL,
-    &sm501_system_config_write,
+static const MemoryRegionOps sm501_system_config_ops = {
+    .read = sm501_system_config_read,
+    .write = sm501_system_config_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static uint32_t sm501_palette_read(void *opaque, target_phys_addr_t addr)
@@ -864,7 +863,8 @@ static void sm501_palette_write(void *opaque,
     *(uint32_t*)&s->dc_palette[addr] = value;
 }
 
-static uint32_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr)
+static uint64_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
     SM501State * s = (SM501State *)opaque;
     uint32_t ret = 0;
@@ -958,13 +958,12 @@ static uint32_t sm501_disp_ctrl_read(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void sm501_disp_ctrl_write(void *opaque,
-					   target_phys_addr_t addr,
-					   uint32_t value)
+static void sm501_disp_ctrl_write(void *opaque, target_phys_addr_t addr,
+                                  uint64_t value, unsigned size)
 {
     SM501State * s = (SM501State *)opaque;
     SM501_DPRINTF("sm501 disp ctrl regs : write addr=%x, val=%x\n",
-		  addr, value);
+		  (unsigned)addr, (unsigned)value);
 
     switch(addr) {
     case SM501_DC_PANEL_CONTROL:
@@ -1059,24 +1058,23 @@ static void sm501_disp_ctrl_write(void *opaque,
 
     default:
 	printf("sm501 disp ctrl : not implemented register write."
-	       " addr=%x, val=%x\n", (int)addr, value);
+	       " addr=%x, val=%x\n", (int)addr, (unsigned)value);
         abort();
     }
 }
 
-static CPUReadMemoryFunc * const sm501_disp_ctrl_readfn[] = {
-    NULL,
-    NULL,
-    &sm501_disp_ctrl_read,
-};
-
-static CPUWriteMemoryFunc * const sm501_disp_ctrl_writefn[] = {
-    NULL,
-    NULL,
-    &sm501_disp_ctrl_write,
+static const MemoryRegionOps sm501_disp_ctrl_ops = {
+    .read = sm501_disp_ctrl_read,
+    .write = sm501_disp_ctrl_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static uint32_t sm501_2d_engine_read(void *opaque, target_phys_addr_t addr)
+static uint64_t sm501_2d_engine_read(void *opaque, target_phys_addr_t addr,
+                                     unsigned size)
 {
     SM501State * s = (SM501State *)opaque;
     uint32_t ret = 0;
@@ -1095,12 +1093,12 @@ static uint32_t sm501_2d_engine_read(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void sm501_2d_engine_write(void *opaque,
-                                  target_phys_addr_t addr, uint32_t value)
+static void sm501_2d_engine_write(void *opaque, target_phys_addr_t addr,
+                                  uint64_t value, unsigned size)
 {
     SM501State * s = (SM501State *)opaque;
     SM501_DPRINTF("sm501 2d engine regs : write addr=%x, val=%x\n",
-                  addr, value);
+                  (unsigned)addr, (unsigned)value);
 
     switch(addr) {
     case SM501_2D_SOURCE:
@@ -1148,21 +1146,19 @@ static void sm501_2d_engine_write(void *opaque,
         break;
     default:
         printf("sm501 2d engine : not implemented register write."
-               " addr=%x, val=%x\n", (int)addr, value);
+               " addr=%x, val=%x\n", (int)addr, (unsigned)value);
         abort();
     }
 }
 
-static CPUReadMemoryFunc * const sm501_2d_engine_readfn[] = {
-    NULL,
-    NULL,
-    &sm501_2d_engine_read,
-};
-
-static CPUWriteMemoryFunc * const sm501_2d_engine_writefn[] = {
-    NULL,
-    NULL,
-    &sm501_2d_engine_write,
+static const MemoryRegionOps sm501_2d_engine_ops = {
+    .read = sm501_2d_engine_read,
+    .write = sm501_2d_engine_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 /* draw line functions for all console modes */
@@ -1276,7 +1272,7 @@ static void sm501_draw_crt(SM501State * s)
     int y_start = -1;
     ram_addr_t page_min = ~0l;
     ram_addr_t page_max = 0l;
-    ram_addr_t offset = s->local_mem_offset;
+    ram_addr_t offset = 0;
 
     /* choose draw_line function */
     switch (s->dc_crt_control & 3) {
@@ -1333,7 +1329,8 @@ static void sm501_draw_crt(SM501State * s)
 
 	/* check dirty flags for each line */
 	for (page = page0; page <= page1; page += TARGET_PAGE_SIZE)
-	    if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG))
+            if (memory_region_get_dirty(&s->local_mem_region, page,
+                                        DIRTY_MEMORY_VGA))
 		update = 1;
 
 	/* draw line and change status */
@@ -1372,8 +1369,9 @@ static void sm501_draw_crt(SM501State * s)
 
     /* clear dirty flags */
     if (page_min != ~0l) {
-	cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
-					VGA_DIRTY_FLAG);
+	memory_region_reset_dirty(&s->local_mem_region,
+                                  page_min, page_max + TARGET_PAGE_SIZE,
+                                  DIRTY_MEMORY_VGA);
     }
 }
 
@@ -1390,9 +1388,9 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
 {
     SM501State * s;
     DeviceState *dev;
-    int sm501_system_config_index;
-    int sm501_disp_ctrl_index;
-    int sm501_2d_engine_index;
+    MemoryRegion *sm501_system_config = g_new(MemoryRegion, 1);
+    MemoryRegion *sm501_disp_ctrl = g_new(MemoryRegion, 1);
+    MemoryRegion *sm501_2d_engine = g_new(MemoryRegion, 1);
 
     /* allocate management data region */
     s = (SM501State *)g_malloc0(sizeof(SM501State));
@@ -1407,27 +1405,26 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
     s->dc_crt_control = 0x00010000;
 
     /* allocate local memory */
-    s->local_mem_offset = qemu_ram_alloc(NULL, "sm501.local", local_mem_bytes);
-    s->local_mem = qemu_get_ram_ptr(s->local_mem_offset);
-    cpu_register_physical_memory(base, local_mem_bytes, s->local_mem_offset);
+    memory_region_init_ram(&s->local_mem_region, NULL, "sm501.local",
+                           local_mem_bytes);
+    s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region);
+    memory_region_add_subregion(address_space_mem, base, &s->local_mem_region);
 
     /* map mmio */
-    sm501_system_config_index
-	= cpu_register_io_memory(sm501_system_config_readfn,
-				 sm501_system_config_writefn, s,
-                                 DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base + MMIO_BASE_OFFSET,
-				 0x6c, sm501_system_config_index);
-    sm501_disp_ctrl_index = cpu_register_io_memory(sm501_disp_ctrl_readfn,
-						   sm501_disp_ctrl_writefn, s,
-                                                   DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_DC,
-                                 0x1000, sm501_disp_ctrl_index);
-    sm501_2d_engine_index = cpu_register_io_memory(sm501_2d_engine_readfn,
-                                                   sm501_2d_engine_writefn, s,
-                                                   DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_2D_ENGINE,
-                                 0x54, sm501_2d_engine_index);
+    memory_region_init_io(sm501_system_config, &sm501_system_config_ops, s,
+                          "sm501-system-config", 0x6c);
+    memory_region_add_subregion(address_space_mem, base + MMIO_BASE_OFFSET,
+                                sm501_system_config);
+    memory_region_init_io(sm501_disp_ctrl, &sm501_disp_ctrl_ops, s,
+                          "sm501-disp-ctrl", 0x1000);
+    memory_region_add_subregion(address_space_mem,
+                                base + MMIO_BASE_OFFSET + SM501_DC,
+                                sm501_disp_ctrl);
+    memory_region_init_io(sm501_2d_engine, &sm501_2d_engine_ops, s,
+                          "sm501-2d-engine", 0x54);
+    memory_region_add_subregion(address_space_mem,
+                                base + MMIO_BASE_OFFSET + SM501_2D_ENGINE,
+                                sm501_2d_engine);
 
     /* bridge to usb host emulation module */
     dev = qdev_create(NULL, "sysbus-ohci");
commit ca3dbc2757f73969e601d901fa3aa4f0253be402
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Oct 2 17:06:42 2011 +0200

    s390-virtio: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 778cffe..60c66e9 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -29,6 +29,7 @@
 #include "hw/virtio.h"
 #include "hw/sysbus.h"
 #include "kvm.h"
+#include "exec-memory.h"
 
 #include "hw/s390-virtio-bus.h"
 
@@ -128,7 +129,8 @@ static void s390_init(ram_addr_t my_ram_size,
                       const char *cpu_model)
 {
     CPUState *env = NULL;
-    ram_addr_t ram_addr;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
     ram_addr_t kernel_size = 0;
     ram_addr_t initrd_offset;
     ram_addr_t initrd_size = 0;
@@ -150,8 +152,8 @@ static void s390_init(ram_addr_t my_ram_size,
     s390_bus = s390_virtio_bus_init(&my_ram_size);
 
     /* allocate RAM */
-    ram_addr = qemu_ram_alloc(NULL, "s390.ram", my_ram_size);
-    cpu_register_physical_memory(0, my_ram_size, ram_addr);
+    memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size);
+    memory_region_add_subregion(sysmem, 0, ram);
 
     /* allocate storage keys */
     storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE);
commit 35e87820d7c689c1fce3785837843fa77193fa38
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Oct 2 17:04:26 2011 +0200

    realview: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/realview.c b/hw/realview.c
index 11ffb8a..14281b0 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -18,17 +18,20 @@
 #include "boards.h"
 #include "bitbang_i2c.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define SMP_BOOT_ADDR 0xe0000000
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     bitbang_i2c_interface *bitbang;
     int out;
     int in;
 } RealViewI2CState;
 
-static uint32_t realview_i2c_read(void *opaque, target_phys_addr_t offset)
+static uint64_t realview_i2c_read(void *opaque, target_phys_addr_t offset,
+                                  unsigned size)
 {
     RealViewI2CState *s = (RealViewI2CState *)opaque;
 
@@ -41,7 +44,7 @@ static uint32_t realview_i2c_read(void *opaque, target_phys_addr_t offset)
 }
 
 static void realview_i2c_write(void *opaque, target_phys_addr_t offset,
-                               uint32_t value)
+                               uint64_t value, unsigned size)
 {
     RealViewI2CState *s = (RealViewI2CState *)opaque;
 
@@ -59,30 +62,22 @@ static void realview_i2c_write(void *opaque, target_phys_addr_t offset,
     s->in = bitbang_i2c_set(s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0);
 }
 
-static CPUReadMemoryFunc * const realview_i2c_readfn[] = {
-   realview_i2c_read,
-   realview_i2c_read,
-   realview_i2c_read
-};
-
-static CPUWriteMemoryFunc * const realview_i2c_writefn[] = {
-   realview_i2c_write,
-   realview_i2c_write,
-   realview_i2c_write
+static const MemoryRegionOps realview_i2c_ops = {
+    .read = realview_i2c_read,
+    .write = realview_i2c_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int realview_i2c_init(SysBusDevice *dev)
 {
     RealViewI2CState *s = FROM_SYSBUS(RealViewI2CState, dev);
     i2c_bus *bus;
-    int iomemtype;
 
     bus = i2c_init_bus(&dev->qdev, "i2c");
     s->bitbang = bitbang_i2c_init(bus);
-    iomemtype = cpu_register_io_memory(realview_i2c_readfn,
-                                       realview_i2c_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &realview_i2c_ops, s,
+                          "realview-i2c", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     return 0;
 }
 
@@ -125,7 +120,11 @@ static void realview_init(ram_addr_t ram_size,
                      enum realview_board_type board_type)
 {
     CPUState *env = NULL;
-    ram_addr_t ram_offset;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_hack = g_new(MemoryRegion, 1);
     DeviceState *dev, *sysctl, *gpio2;
     SysBusDevice *busdev;
     qemu_irq *irqp;
@@ -184,21 +183,21 @@ static void realview_init(ram_addr_t ram_size,
         /* Core tile RAM.  */
         low_ram_size = ram_size - 0x20000000;
         ram_size = 0x20000000;
-        ram_offset = qemu_ram_alloc(NULL, "realview.lowmem", low_ram_size);
-        cpu_register_physical_memory(0x20000000, low_ram_size,
-                                     ram_offset | IO_MEM_RAM);
+        memory_region_init_ram(ram_lo, NULL, "realview.lowmem", low_ram_size);
+        memory_region_add_subregion(sysmem, 0x20000000, ram_lo);
     }
 
-    ram_offset = qemu_ram_alloc(NULL, "realview.highmem", ram_size);
+    memory_region_init_ram(ram_hi, NULL, "realview.highmem", ram_size);
     low_ram_size = ram_size;
     if (low_ram_size > 0x10000000)
       low_ram_size = 0x10000000;
     /* SDRAM at address zero.  */
-    cpu_register_physical_memory(0, low_ram_size, ram_offset | IO_MEM_RAM);
+    memory_region_init_alias(ram_alias, "realview.alias",
+                             ram_hi, 0, low_ram_size);
+    memory_region_add_subregion(sysmem, 0, ram_alias);
     if (is_pb) {
         /* And again at a high address.  */
-        cpu_register_physical_memory(0x70000000, ram_size,
-                                     ram_offset | IO_MEM_RAM);
+        memory_region_add_subregion(sysmem, 0x70000000, ram_hi);
     } else {
         ram_size = low_ram_size;
     }
@@ -372,9 +371,8 @@ static void realview_init(ram_addr_t ram_size,
        startup code.  I guess this works on real hardware because the
        BootROM happens to be in ROM/flash or in memory that isn't clobbered
        until after Linux boots the secondary CPUs.  */
-    ram_offset = qemu_ram_alloc(NULL, "realview.hack", 0x1000);
-    cpu_register_physical_memory(SMP_BOOT_ADDR, 0x1000,
-                                 ram_offset | IO_MEM_RAM);
+    memory_region_init_ram(ram_hack, NULL, "realview.hack", 0x1000);
+    memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
 
     realview_binfo.ram_size = ram_size;
     realview_binfo.kernel_filename = kernel_filename;
commit 5dea2efb3b141b2e2defe0b01de023cbe9d4232d
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Oct 2 16:48:42 2011 +0200

    r2d: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/r2d.c b/hw/r2d.c
index 82377a0..b65fd42 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -82,6 +82,7 @@ typedef struct {
 
 /* output pin */
     qemu_irq irl;
+    MemoryRegion iomem;
 } r2d_fpga_t;
 
 enum r2d_fpga_irq {
@@ -168,31 +169,25 @@ r2d_fpga_write(void *opaque, target_phys_addr_t addr, uint32_t value)
     }
 }
 
-static CPUReadMemoryFunc * const r2d_fpga_readfn[] = {
-    r2d_fpga_read,
-    r2d_fpga_read,
-    NULL,
+static const MemoryRegionOps r2d_fpga_ops = {
+    .old_mmio = {
+        .read = { r2d_fpga_read, r2d_fpga_read, NULL, },
+        .write = { r2d_fpga_write, r2d_fpga_write, NULL, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const r2d_fpga_writefn[] = {
-    r2d_fpga_write,
-    r2d_fpga_write,
-    NULL,
-};
-
-static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl)
+static qemu_irq *r2d_fpga_init(MemoryRegion *sysmem,
+                               target_phys_addr_t base, qemu_irq irl)
 {
-    int iomemtype;
     r2d_fpga_t *s;
 
     s = g_malloc0(sizeof(r2d_fpga_t));
 
     s->irl = irl;
 
-    iomemtype = cpu_register_io_memory(r2d_fpga_readfn,
-				       r2d_fpga_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x40, iomemtype);
+    memory_region_init_io(&s->iomem, &r2d_fpga_ops, s, "r2d-fpga", 0x40);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
     return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
 }
 
@@ -232,7 +227,7 @@ static void r2d_init(ram_addr_t ram_size,
     CPUState *env;
     ResetData *reset_info;
     struct SH7750State *s;
-    ram_addr_t sdram_addr;
+    MemoryRegion *sdram = g_new(MemoryRegion, 1);
     qemu_irq *irq;
     DriveInfo *dinfo;
     int i;
@@ -252,11 +247,11 @@ static void r2d_init(ram_addr_t ram_size,
     qemu_register_reset(main_cpu_reset, reset_info);
 
     /* Allocate memory space */
-    sdram_addr = qemu_ram_alloc(NULL, "r2d.sdram", SDRAM_SIZE);
-    cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr);
+    memory_region_init_ram(sdram, NULL, "r2d.sdram", SDRAM_SIZE);
+    memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram);
     /* Register peripherals */
     s = sh7750_init(env);
-    irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
+    irq = r2d_fpga_init(address_space_mem, 0x04000000, sh7750_irl(s));
     sysbus_create_varargs("sh_pci", 0x1e200000, irq[PCI_INTA], irq[PCI_INTB],
                           irq[PCI_INTC], irq[PCI_INTD], NULL);
 
commit 2646c133b53659af37b88cf5faf801a3c0268971
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Oct 2 16:43:01 2011 +0200

    ppcr500_mpc8544ds: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 5bf8eab..51b6abd 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -229,6 +229,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
                          const char *cpu_model)
 {
     MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
     PCIBus *pci_bus;
     CPUState *env = NULL;
     uint64_t elf_entry;
@@ -291,8 +292,8 @@ static void mpc8544ds_init(ram_addr_t ram_size,
     ram_size &= ~(RAM_SIZES_ALIGN - 1);
 
     /* Register Memory */
-    cpu_register_physical_memory(0, ram_size, qemu_ram_alloc(NULL,
-                                 "mpc8544ds.ram", ram_size));
+    memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size);
+    memory_region_add_subregion(address_space_mem, 0, ram);
 
     /* MPIC */
     mpic = mpic_init(address_space_mem, MPC8544_MPIC_REGS_BASE,
commit 8b881e776a45cc1ee18f4bc8182bbc1d2aed56e8
Author: Avi Kivity <avi at redhat.com>
Date:   Thu Aug 11 14:40:58 2011 +0300

    pci: simplify memory region registration
    
    The two code paths (for ADDRESS_SPACE_IO and ADDRESS_SPACE_MEM) are
    identical.  Unify them.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index 749e8d8..e8cc1b0 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -998,17 +998,8 @@ static void pci_update_mappings(PCIDevice *d)
         }
         r->addr = new_addr;
         if (r->addr != PCI_BAR_UNMAPPED) {
-            if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
-                memory_region_add_subregion_overlap(r->address_space,
-                                                    r->addr,
-                                                    r->memory,
-                                                    1);
-            } else {
-                memory_region_add_subregion_overlap(r->address_space,
-                                                    r->addr,
-                                                    r->memory,
-                                                    1);
-            }
+            memory_region_add_subregion_overlap(r->address_space,
+                                                r->addr, r->memory, 1);
         }
     }
 }
commit adfc39eaeff3da25376f7d735ac97ee25f933dcc
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Sep 25 18:19:19 2011 +0300

    pxa2xx: convert to memory API (part II)
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pxa.h b/hw/pxa.h
index 3fb070f..7e98384 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -122,6 +122,11 @@ typedef struct {
     CPUState *env;
     DeviceState *pic;
     qemu_irq reset;
+    MemoryRegion sdram;
+    MemoryRegion internal;
+    MemoryRegion cm_iomem;
+    MemoryRegion mm_iomem;
+    MemoryRegion pm_iomem;
     DeviceState *dma;
     DeviceState *gpio;
     PXA2xxLCDState *lcd;
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 19ee094..bfc28a9 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -88,7 +88,8 @@ static PXASSPDef pxa27x_ssp[] = {
 #define PCMD0	0x80	/* Power Manager I2C Command register File 0 */
 #define PCMD31	0xfc	/* Power Manager I2C Command register File 31 */
 
-static uint32_t pxa2xx_pm_read(void *opaque, target_phys_addr_t addr)
+static uint64_t pxa2xx_pm_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     PXA2xxState *s = (PXA2xxState *) opaque;
 
@@ -107,7 +108,7 @@ static uint32_t pxa2xx_pm_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void pxa2xx_pm_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     PXA2xxState *s = (PXA2xxState *) opaque;
 
@@ -134,16 +135,10 @@ static void pxa2xx_pm_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_pm_readfn[] = {
-    pxa2xx_pm_read,
-    pxa2xx_pm_read,
-    pxa2xx_pm_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_pm_writefn[] = {
-    pxa2xx_pm_write,
-    pxa2xx_pm_write,
-    pxa2xx_pm_write,
+static const MemoryRegionOps pxa2xx_pm_ops = {
+    .read = pxa2xx_pm_read,
+    .write = pxa2xx_pm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_pxa2xx_pm = {
@@ -162,7 +157,8 @@ static const VMStateDescription vmstate_pxa2xx_pm = {
 #define OSCC	0x08	/* Oscillator Configuration register */
 #define CCSR	0x0c	/* Core Clock Status register */
 
-static uint32_t pxa2xx_cm_read(void *opaque, target_phys_addr_t addr)
+static uint64_t pxa2xx_cm_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     PXA2xxState *s = (PXA2xxState *) opaque;
 
@@ -183,7 +179,7 @@ static uint32_t pxa2xx_cm_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void pxa2xx_cm_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     PXA2xxState *s = (PXA2xxState *) opaque;
 
@@ -206,16 +202,10 @@ static void pxa2xx_cm_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_cm_readfn[] = {
-    pxa2xx_cm_read,
-    pxa2xx_cm_read,
-    pxa2xx_cm_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_cm_writefn[] = {
-    pxa2xx_cm_write,
-    pxa2xx_cm_write,
-    pxa2xx_cm_write,
+static const MemoryRegionOps pxa2xx_cm_ops = {
+    .read = pxa2xx_cm_read,
+    .write = pxa2xx_cm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_pxa2xx_cm = {
@@ -461,7 +451,8 @@ static void pxa2xx_cp14_write(void *opaque, int op2, int reg, int crm,
 #define BSCNTR3		0x60	/* Memory Buffer Strength Control register 3 */
 #define SA1110		0x64	/* SA-1110 Memory Compatibility register */
 
-static uint32_t pxa2xx_mm_read(void *opaque, target_phys_addr_t addr)
+static uint64_t pxa2xx_mm_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     PXA2xxState *s = (PXA2xxState *) opaque;
 
@@ -478,7 +469,7 @@ static uint32_t pxa2xx_mm_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void pxa2xx_mm_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     PXA2xxState *s = (PXA2xxState *) opaque;
 
@@ -495,16 +486,10 @@ static void pxa2xx_mm_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_mm_readfn[] = {
-    pxa2xx_mm_read,
-    pxa2xx_mm_read,
-    pxa2xx_mm_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_mm_writefn[] = {
-    pxa2xx_mm_write,
-    pxa2xx_mm_write,
-    pxa2xx_mm_write,
+static const MemoryRegionOps pxa2xx_mm_ops = {
+    .read = pxa2xx_mm_read,
+    .write = pxa2xx_mm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_pxa2xx_mm = {
@@ -1764,6 +1749,7 @@ static PXA2xxI2SState *pxa2xx_i2s_init(MemoryRegion *sysmem,
 
 /* PXA Fast Infra-red Communications Port */
 struct PXA2xxFIrState {
+    MemoryRegion iomem;
     qemu_irq irq;
     qemu_irq rx_dma;
     qemu_irq tx_dma;
@@ -1834,7 +1820,8 @@ static inline void pxa2xx_fir_update(PXA2xxFIrState *s)
 #define ICSR1	0x18	/* FICP Status register 1 */
 #define ICFOR	0x1c	/* FICP FIFO Occupancy Status register */
 
-static uint32_t pxa2xx_fir_read(void *opaque, target_phys_addr_t addr)
+static uint64_t pxa2xx_fir_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
 {
     PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
     uint8_t ret;
@@ -1872,9 +1859,10 @@ static uint32_t pxa2xx_fir_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void pxa2xx_fir_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                             uint64_t value64, unsigned size)
 {
     PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    uint32_t value = value64;
     uint8_t ch;
 
     switch (addr) {
@@ -1916,16 +1904,10 @@ static void pxa2xx_fir_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_fir_readfn[] = {
-    pxa2xx_fir_read,
-    pxa2xx_fir_read,
-    pxa2xx_fir_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_fir_writefn[] = {
-    pxa2xx_fir_write,
-    pxa2xx_fir_write,
-    pxa2xx_fir_write,
+static const MemoryRegionOps pxa2xx_fir_ops = {
+    .read = pxa2xx_fir_read,
+    .write = pxa2xx_fir_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int pxa2xx_fir_is_empty(void *opaque)
@@ -1999,11 +1981,11 @@ static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
+static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
+                target_phys_addr_t base,
                 qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
                 CharDriverState *chr)
 {
-    int iomemtype;
     PXA2xxFIrState *s = (PXA2xxFIrState *)
             g_malloc0(sizeof(PXA2xxFIrState));
 
@@ -2014,9 +1996,8 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
 
     pxa2xx_fir_reset(s);
 
-    iomemtype = cpu_register_io_memory(pxa2xx_fir_readfn,
-                    pxa2xx_fir_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     if (chr)
         qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
@@ -2043,7 +2024,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
                          unsigned int sdram_size, const char *revision)
 {
     PXA2xxState *s;
-    int iomemtype, i;
+    int i;
     DriveInfo *dinfo;
     s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
 
@@ -2062,12 +2043,11 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
     s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
 
     /* SDRAM & Internal Memory Storage */
-    cpu_register_physical_memory(PXA2XX_SDRAM_BASE,
-                    sdram_size, qemu_ram_alloc(NULL, "pxa270.sdram",
-                                               sdram_size) | IO_MEM_RAM);
-    cpu_register_physical_memory(PXA2XX_INTERNAL_BASE,
-                    0x40000, qemu_ram_alloc(NULL, "pxa270.internal",
-                                            0x40000) | IO_MEM_RAM);
+    memory_region_init_ram(&s->sdram, NULL, "pxa270.sdram", sdram_size);
+    memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
+    memory_region_init_ram(&s->internal, NULL, "pxa270.internal", 0x40000);
+    memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
+                                &s->internal);
 
     s->pic = pxa2xx_pic_init(0x40d00000, s->env);
 
@@ -2105,7 +2085,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
         }
     }
     if (serial_hds[i])
-        s->fir = pxa2xx_fir_init(0x40800000,
+        s->fir = pxa2xx_fir_init(address_space, 0x40800000,
                         qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
                         qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_ICP),
                         qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_ICP),
@@ -2117,9 +2097,8 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
     s->cm_base = 0x41300000;
     s->cm_regs[CCCR >> 2] = 0x02000210;	/* 416.0 MHz */
     s->clkcfg = 0x00000009;		/* Turbo mode active */
-    iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
-                    pxa2xx_cm_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
+    memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
+    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
 
     cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
@@ -2128,15 +2107,13 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
     s->mm_regs[MDMRS >> 2] = 0x00020002;
     s->mm_regs[MDREFR >> 2] = 0x03ca4000;
     s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
-    iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
-                    pxa2xx_mm_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
+    memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
+    memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
 
     s->pm_base = 0x40f00000;
-    iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
-                    pxa2xx_pm_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
+    memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
+    memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
 
     for (i = 0; pxa27x_ssp[i].io_base; i ++);
@@ -2182,7 +2159,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
 PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
 {
     PXA2xxState *s;
-    int iomemtype, i;
+    int i;
     DriveInfo *dinfo;
 
     s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
@@ -2195,12 +2172,12 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
     s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
 
     /* SDRAM & Internal Memory Storage */
-    cpu_register_physical_memory(PXA2XX_SDRAM_BASE, sdram_size,
-                    qemu_ram_alloc(NULL, "pxa255.sdram",
-                                   sdram_size) | IO_MEM_RAM);
-    cpu_register_physical_memory(PXA2XX_INTERNAL_BASE, PXA2XX_INTERNAL_SIZE,
-                    qemu_ram_alloc(NULL, "pxa255.internal",
-                                   PXA2XX_INTERNAL_SIZE) | IO_MEM_RAM);
+    memory_region_init_ram(&s->sdram, NULL, "pxa255.sdram", sdram_size);
+    memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
+    memory_region_init_ram(&s->internal, NULL, "pxa255.internal",
+                           PXA2XX_INTERNAL_SIZE);
+    memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
+                                &s->internal);
 
     s->pic = pxa2xx_pic_init(0x40d00000, s->env);
 
@@ -2237,7 +2214,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
         }
     }
     if (serial_hds[i])
-        s->fir = pxa2xx_fir_init(0x40800000,
+        s->fir = pxa2xx_fir_init(address_space, 0x40800000,
                         qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
                         qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_ICP),
                         qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_ICP),
@@ -2249,9 +2226,8 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
     s->cm_base = 0x41300000;
     s->cm_regs[CCCR >> 2] = 0x02000210;	/* 416.0 MHz */
     s->clkcfg = 0x00000009;		/* Turbo mode active */
-    iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
-                    pxa2xx_cm_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
+    memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
+    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
 
     cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
@@ -2260,15 +2236,13 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
     s->mm_regs[MDMRS >> 2] = 0x00020002;
     s->mm_regs[MDREFR >> 2] = 0x03ca4000;
     s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
-    iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
-                    pxa2xx_mm_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
+    memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
+    memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
 
     s->pm_base = 0x40f00000;
-    iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
-                    pxa2xx_pm_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
+    memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
+    memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem);
     vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
 
     for (i = 0; pxa255_ssp[i].io_base; i ++);
commit 9c843933fcee1b3ad53efca14caf6cf7e7d3e20d
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Sep 25 18:19:19 2011 +0300

    pxa2xx: convert to memory API (part I)
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/pxa.h b/hw/pxa.h
index 1204165..3fb070f 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -151,6 +151,7 @@ typedef struct {
 } PXA2xxState;
 
 struct PXA2xxI2SState {
+    MemoryRegion iomem;
     qemu_irq irq;
     qemu_irq rx_dma;
     qemu_irq tx_dma;
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 70d7c8a..19ee094 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -521,6 +521,7 @@ static const VMStateDescription vmstate_pxa2xx_mm = {
 /* Synchronous Serial Ports */
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     qemu_irq irq;
     int enable;
     SSIBus *bus;
@@ -627,7 +628,8 @@ static void pxa2xx_ssp_fifo_update(PXA2xxSSPState *s)
     pxa2xx_ssp_int_update(s);
 }
 
-static uint32_t pxa2xx_ssp_read(void *opaque, target_phys_addr_t addr)
+static uint64_t pxa2xx_ssp_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
 {
     PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
     uint32_t retval;
@@ -673,9 +675,10 @@ static uint32_t pxa2xx_ssp_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void pxa2xx_ssp_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                             uint64_t value64, unsigned size)
 {
     PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
+    uint32_t value = value64;
 
     switch (addr) {
     case SSCR0:
@@ -762,16 +765,10 @@ static void pxa2xx_ssp_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_ssp_readfn[] = {
-    pxa2xx_ssp_read,
-    pxa2xx_ssp_read,
-    pxa2xx_ssp_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_ssp_writefn[] = {
-    pxa2xx_ssp_write,
-    pxa2xx_ssp_write,
-    pxa2xx_ssp_write,
+static const MemoryRegionOps pxa2xx_ssp_ops = {
+    .read = pxa2xx_ssp_read,
+    .write = pxa2xx_ssp_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void pxa2xx_ssp_save(QEMUFile *f, void *opaque)
@@ -823,15 +820,12 @@ static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
 
 static int pxa2xx_ssp_init(SysBusDevice *dev)
 {
-    int iomemtype;
     PXA2xxSSPState *s = FROM_SYSBUS(PXA2xxSSPState, dev);
 
     sysbus_init_irq(dev, &s->irq);
 
-    iomemtype = cpu_register_io_memory(pxa2xx_ssp_readfn,
-                                       pxa2xx_ssp_writefn, s,
-                                       DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_ssp_ops, s, "pxa2xx-ssp", 0x1000);
+    sysbus_init_mmio_region(dev, &s->iomem);
     register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
                     pxa2xx_ssp_save, pxa2xx_ssp_load, s);
 
@@ -858,6 +852,7 @@ static int pxa2xx_ssp_init(SysBusDevice *dev)
 
 typedef struct {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     uint32_t rttr;
     uint32_t rtsr;
     uint32_t rtar;
@@ -1009,7 +1004,8 @@ static inline void pxa2xx_rtc_pi_tick(void *opaque)
     pxa2xx_rtc_int_update(s);
 }
 
-static uint32_t pxa2xx_rtc_read(void *opaque, target_phys_addr_t addr)
+static uint64_t pxa2xx_rtc_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
 {
     PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
 
@@ -1055,9 +1051,10 @@ static uint32_t pxa2xx_rtc_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void pxa2xx_rtc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                             uint64_t value64, unsigned size)
 {
     PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    uint32_t value = value64;
 
     switch (addr) {
     case RTTR:
@@ -1157,16 +1154,10 @@ static void pxa2xx_rtc_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_rtc_readfn[] = {
-    pxa2xx_rtc_read,
-    pxa2xx_rtc_read,
-    pxa2xx_rtc_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_rtc_writefn[] = {
-    pxa2xx_rtc_write,
-    pxa2xx_rtc_write,
-    pxa2xx_rtc_write,
+static const MemoryRegionOps pxa2xx_rtc_ops = {
+    .read = pxa2xx_rtc_read,
+    .write = pxa2xx_rtc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static int pxa2xx_rtc_init(SysBusDevice *dev)
@@ -1174,7 +1165,6 @@ static int pxa2xx_rtc_init(SysBusDevice *dev)
     PXA2xxRTCState *s = FROM_SYSBUS(PXA2xxRTCState, dev);
     struct tm tm;
     int wom;
-    int iomemtype;
 
     s->rttr = 0x7fff;
     s->rtsr = 0;
@@ -1201,9 +1191,8 @@ static int pxa2xx_rtc_init(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &s->rtc_irq);
 
-    iomemtype = cpu_register_io_memory(pxa2xx_rtc_readfn,
-                    pxa2xx_rtc_writefn, s, DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, 0x10000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_rtc_ops, s, "pxa2xx-rtc", 0x10000);
+    sysbus_init_mmio_region(dev, &s->iomem);
 
     return 0;
 }
@@ -1272,6 +1261,7 @@ typedef struct {
 
 struct PXA2xxI2CState {
     SysBusDevice busdev;
+    MemoryRegion iomem;
     PXA2xxI2CSlaveState *slave;
     i2c_bus *bus;
     qemu_irq irq;
@@ -1356,7 +1346,8 @@ static int pxa2xx_i2c_tx(i2c_slave *i2c, uint8_t data)
     return 1;
 }
 
-static uint32_t pxa2xx_i2c_read(void *opaque, target_phys_addr_t addr)
+static uint64_t pxa2xx_i2c_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
 {
     PXA2xxI2CState *s = (PXA2xxI2CState *) opaque;
 
@@ -1384,9 +1375,10 @@ static uint32_t pxa2xx_i2c_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void pxa2xx_i2c_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                             uint64_t value64, unsigned size)
 {
     PXA2xxI2CState *s = (PXA2xxI2CState *) opaque;
+    uint32_t value = value64;
     int ack;
 
     addr -= s->offset;
@@ -1453,16 +1445,10 @@ static void pxa2xx_i2c_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_i2c_readfn[] = {
-    pxa2xx_i2c_read,
-    pxa2xx_i2c_read,
-    pxa2xx_i2c_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_i2c_writefn[] = {
-    pxa2xx_i2c_write,
-    pxa2xx_i2c_write,
-    pxa2xx_i2c_write,
+static const MemoryRegionOps pxa2xx_i2c_ops = {
+    .read = pxa2xx_i2c_read,
+    .write = pxa2xx_i2c_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_pxa2xx_i2c_slave = {
@@ -1536,13 +1522,12 @@ PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base,
 static int pxa2xx_i2c_initfn(SysBusDevice *dev)
 {
     PXA2xxI2CState *s = FROM_SYSBUS(PXA2xxI2CState, dev);
-    int iomemtype;
 
     s->bus = i2c_init_bus(&dev->qdev, "i2c");
 
-    iomemtype = cpu_register_io_memory(pxa2xx_i2c_readfn,
-                    pxa2xx_i2c_writefn, s, DEVICE_NATIVE_ENDIAN);
-    sysbus_init_mmio(dev, s->region_size, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_i2c_ops, s,
+                          "pxa2xx-i2x", s->region_size);
+    sysbus_init_mmio_region(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
 
     return 0;
@@ -1621,7 +1606,8 @@ static inline void pxa2xx_i2s_update(PXA2xxI2SState *i2s)
 #define SADIV	0x60	/* Serial Audio Clock Divider register */
 #define SADR	0x80	/* Serial Audio Data register */
 
-static uint32_t pxa2xx_i2s_read(void *opaque, target_phys_addr_t addr)
+static uint64_t pxa2xx_i2s_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
 {
     PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
 
@@ -1653,7 +1639,7 @@ static uint32_t pxa2xx_i2s_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void pxa2xx_i2s_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                             uint64_t value, unsigned size)
 {
     PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
     uint32_t *sample;
@@ -1707,16 +1693,10 @@ static void pxa2xx_i2s_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const pxa2xx_i2s_readfn[] = {
-    pxa2xx_i2s_read,
-    pxa2xx_i2s_read,
-    pxa2xx_i2s_read,
-};
-
-static CPUWriteMemoryFunc * const pxa2xx_i2s_writefn[] = {
-    pxa2xx_i2s_write,
-    pxa2xx_i2s_write,
-    pxa2xx_i2s_write,
+static const MemoryRegionOps pxa2xx_i2s_ops = {
+    .read = pxa2xx_i2s_read,
+    .write = pxa2xx_i2s_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static const VMStateDescription vmstate_pxa2xx_i2s = {
@@ -1759,10 +1739,10 @@ static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx)
     pxa2xx_i2s_update(s);
 }
 
-static PXA2xxI2SState *pxa2xx_i2s_init(target_phys_addr_t base,
+static PXA2xxI2SState *pxa2xx_i2s_init(MemoryRegion *sysmem,
+                target_phys_addr_t base,
                 qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma)
 {
-    int iomemtype;
     PXA2xxI2SState *s = (PXA2xxI2SState *)
             g_malloc0(sizeof(PXA2xxI2SState));
 
@@ -1773,9 +1753,9 @@ static PXA2xxI2SState *pxa2xx_i2s_init(target_phys_addr_t base,
 
     pxa2xx_i2s_reset(s);
 
-    iomemtype = cpu_register_io_memory(pxa2xx_i2s_readfn,
-                    pxa2xx_i2s_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x100000, iomemtype);
+    memory_region_init_io(&s->iomem, &pxa2xx_i2s_ops, s,
+                          "pxa2xx-i2s", 0x100000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
 
     vmstate_register(NULL, base, &vmstate_pxa2xx_i2s, s);
 
@@ -2184,7 +2164,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
     s->i2c[1] = pxa2xx_i2c_init(0x40f00100,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
 
-    s->i2s = pxa2xx_i2s_init(0x40400000,
+    s->i2s = pxa2xx_i2s_init(address_space, 0x40400000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2S),
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_I2S),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_I2S));
@@ -2316,7 +2296,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
     s->i2c[1] = pxa2xx_i2c_init(0x40f00100,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
 
-    s->i2s = pxa2xx_i2s_init(0x40400000,
+    s->i2s = pxa2xx_i2s_init(address_space, 0x40400000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_I2S),
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_I2S),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_I2S));
commit 0c90c52fab5ea92d7f12b29bfe26a7cd75d9efcb
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Sep 25 16:57:45 2011 +0300

    ppc_prep: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 6427baa..f22d5b9 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -116,16 +116,17 @@ static uint32_t speaker_ioport_read (void *opaque, uint32_t addr)
 
 /* PCI intack register */
 /* Read-only register (?) */
-static void _PPC_intack_write (void *opaque,
-                               target_phys_addr_t addr, uint32_t value)
+static void PPC_intack_write (void *opaque, target_phys_addr_t addr,
+                              uint64_t value, unsigned size)
 {
 #if 0
-    printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", __func__, addr,
+    printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx64 "\n", __func__, addr,
            value);
 #endif
 }
 
-static inline uint32_t _PPC_intack_read(target_phys_addr_t addr)
+static uint64_t PPC_intack_read(void *opaque, target_phys_addr_t addr,
+                                unsigned size)
 {
     uint32_t retval = 0;
 
@@ -139,31 +140,10 @@ static inline uint32_t _PPC_intack_read(target_phys_addr_t addr)
     return retval;
 }
 
-static uint32_t PPC_intack_readb (void *opaque, target_phys_addr_t addr)
-{
-    return _PPC_intack_read(addr);
-}
-
-static uint32_t PPC_intack_readw (void *opaque, target_phys_addr_t addr)
-{
-    return _PPC_intack_read(addr);
-}
-
-static uint32_t PPC_intack_readl (void *opaque, target_phys_addr_t addr)
-{
-    return _PPC_intack_read(addr);
-}
-
-static CPUWriteMemoryFunc * const PPC_intack_write[] = {
-    &_PPC_intack_write,
-    &_PPC_intack_write,
-    &_PPC_intack_write,
-};
-
-static CPUReadMemoryFunc * const PPC_intack_read[] = {
-    &PPC_intack_readb,
-    &PPC_intack_readw,
-    &PPC_intack_readl,
+static const MemoryRegionOps PPC_intack_ops = {
+    .read = PPC_intack_read,
+    .write = PPC_intack_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 /* PowerPC control and status registers */
@@ -244,17 +224,14 @@ static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr)
     return retval;
 }
 
-static CPUWriteMemoryFunc * const PPC_XCSR_write[] = {
-    &PPC_XCSR_writeb,
-    &PPC_XCSR_writew,
-    &PPC_XCSR_writel,
+static const MemoryRegionOps PPC_XCSR_ops = {
+    .old_mmio = {
+        .read = { PPC_XCSR_readb, PPC_XCSR_readw, PPC_XCSR_readl, },
+        .write = { PPC_XCSR_writeb, PPC_XCSR_writew, PPC_XCSR_writel, },
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-static CPUReadMemoryFunc * const PPC_XCSR_read[] = {
-    &PPC_XCSR_readb,
-    &PPC_XCSR_readw,
-    &PPC_XCSR_readl,
-};
 #endif
 
 /* Fake super-io ports for PREP platform (Intel 82378ZB) */
@@ -503,16 +480,12 @@ static uint32_t PPC_prep_io_readl (void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static CPUWriteMemoryFunc * const PPC_prep_io_write[] = {
-    &PPC_prep_io_writeb,
-    &PPC_prep_io_writew,
-    &PPC_prep_io_writel,
-};
-
-static CPUReadMemoryFunc * const PPC_prep_io_read[] = {
-    &PPC_prep_io_readb,
-    &PPC_prep_io_readw,
-    &PPC_prep_io_readl,
+static const MemoryRegionOps PPC_prep_io_ops = {
+    .old_mmio = {
+        .read = { PPC_prep_io_readb, PPC_prep_io_readw, PPC_prep_io_readl },
+        .write = { PPC_prep_io_writeb, PPC_prep_io_writew, PPC_prep_io_writel },
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 #define NVRAM_SIZE        0x2000
@@ -534,13 +507,19 @@ static void ppc_prep_init (ram_addr_t ram_size,
                            const char *initrd_filename,
                            const char *cpu_model)
 {
+    MemoryRegion *sysmem = get_system_memory();
     CPUState *env = NULL;
     char *filename;
     nvram_t nvram;
     M48t59State *m48t59;
-    int PPC_io_memory;
+    MemoryRegion *PPC_io_memory = g_new(MemoryRegion, 1);
+    MemoryRegion *intack = g_new(MemoryRegion, 1);
+#if 0
+    MemoryRegion *xcsr = g_new(MemoryRegion, 1);
+#endif
     int linux_boot, i, nb_nics1, bios_size;
-    ram_addr_t ram_offset, bios_offset;
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
     uint32_t kernel_base, initrd_base;
     long kernel_size, initrd_size;
     PCIBus *pci_bus;
@@ -574,11 +553,11 @@ static void ppc_prep_init (ram_addr_t ram_size,
     }
 
     /* allocate RAM */
-    ram_offset = qemu_ram_alloc(NULL, "ppc_prep.ram", ram_size);
-    cpu_register_physical_memory(0, ram_size, ram_offset);
+    memory_region_init_ram(ram, NULL, "ppc_prep.ram", ram_size);
+    memory_region_add_subregion(sysmem, 0, ram);
 
     /* allocate and load BIOS */
-    bios_offset = qemu_ram_alloc(NULL, "ppc_prep.bios", BIOS_SIZE);
+    memory_region_init_ram(bios, NULL, "ppc_prep.bios", BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = BIOS_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -591,8 +570,8 @@ static void ppc_prep_init (ram_addr_t ram_size,
         target_phys_addr_t bios_addr;
         bios_size = (bios_size + 0xfff) & ~0xfff;
         bios_addr = (uint32_t)(-bios_size);
-        cpu_register_physical_memory(bios_addr, bios_size,
-                                     bios_offset | IO_MEM_ROM);
+        memory_region_set_readonly(bios, true);
+        memory_region_add_subregion(sysmem, bios_addr, bios);
         bios_size = load_image_targphys(filename, bios_addr, bios_size);
     }
     if (bios_size < 0 || bios_size > BIOS_SIZE) {
@@ -655,10 +634,9 @@ static void ppc_prep_init (ram_addr_t ram_size,
     isa_bus_irqs(i8259);
     //    pci_bus = i440fx_init();
     /* Register 8 MB of ISA IO space (needed for non-contiguous map) */
-    PPC_io_memory = cpu_register_io_memory(PPC_prep_io_read,
-                                           PPC_prep_io_write, sysctrl,
-                                           DEVICE_LITTLE_ENDIAN);
-    cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory);
+    memory_region_init_io(PPC_io_memory, &PPC_prep_io_ops, sysctrl,
+                          "ppc-io", 0x00800000);
+    memory_region_add_subregion(sysmem, 0x80000000, PPC_io_memory);
 
     /* init basic PC hardware */
     pci_vga_init(pci_bus);
@@ -713,15 +691,12 @@ static void ppc_prep_init (ram_addr_t ram_size,
     register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl);
     register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl);
     /* PCI intack location */
-    PPC_io_memory = cpu_register_io_memory(PPC_intack_read,
-                                           PPC_intack_write, NULL,
-                                           DEVICE_LITTLE_ENDIAN);
-    cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory);
+    memory_region_init_io(intack, &PPC_intack_ops, NULL, "ppc-intack", 4);
+    memory_region_add_subregion(sysmem, 0xBFFFFFF0, intack);
     /* PowerPC control and status register group */
 #if 0
-    PPC_io_memory = cpu_register_io_memory(PPC_XCSR_read, PPC_XCSR_write,
-                                           NULL, DEVICE_LITTLE_ENDIAN);
-    cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory);
+    memory_region_init_io(xcsr, &PPC_XCSR_ops, NULL, "ppc-xcsr", 0x1000);
+    memory_region_add_subregion(sysmem, 0xFEFF0000, xcsr);
 #endif
 
     if (usb_enabled) {
commit c92bb2c7257f74c9b871c5b8fa232a26243f1530
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Sep 25 16:27:52 2011 +0300

    ppc_oldworld: convert to memory API
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index ebcaafa..aac3526 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -73,11 +73,13 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
                                const char *initrd_filename,
                                const char *cpu_model)
 {
+    MemoryRegion *sysmem = get_system_memory();
     CPUState *env = NULL;
     char *filename;
     qemu_irq *pic, **heathrow_irqs;
     int linux_boot, i;
-    ram_addr_t ram_offset, bios_offset;
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
     uint32_t kernel_base, initrd_base, cmdline_base = 0;
     int32_t kernel_size, initrd_size;
     PCIBus *pci_bus;
@@ -114,15 +116,16 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
         exit(1);
     }
 
-    ram_offset = qemu_ram_alloc(NULL, "ppc_heathrow.ram", ram_size);
-    cpu_register_physical_memory(0, ram_size, ram_offset);
+    memory_region_init_ram(ram, NULL, "ppc_heathrow.ram", ram_size);
+    memory_region_add_subregion(sysmem, 0, ram);
 
     /* allocate and load BIOS */
-    bios_offset = qemu_ram_alloc(NULL, "ppc_heathrow.bios", BIOS_SIZE);
+    memory_region_init_ram(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    cpu_register_physical_memory(PROM_ADDR, BIOS_SIZE, bios_offset | IO_MEM_ROM);
+    memory_region_set_readonly(bios, true);
+    memory_region_add_subregion(sysmem, PROM_ADDR, bios);
 
     /* Load OpenBIOS (ELF) */
     if (filename) {
commit cfce6d8934243871c4dc6d0c5248b0b27a1b8d80
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Oct 16 11:53:17 2011 +0200

    i8259: Move to hw library
    
    No target-specific bits remaining, let's move it over.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index b839c8e..44d9bb9 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -220,6 +220,7 @@ hw-obj-$(CONFIG_APPLESMC) += applesmc.o
 hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o ccid-card-passthru.o
 hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
 hw-obj-$(CONFIG_USB_REDIR) += usb-redir.o
+hw-obj-$(CONFIG_I8259) += i8259.o
 
 # PPC devices
 hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
diff --git a/Makefile.target b/Makefile.target
index 3d94228..417f23e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -219,7 +219,7 @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o
 
 # Hardware support
 obj-i386-y += vga.o
-obj-i386-y += mc146818rtc.o i8259.o pc.o
+obj-i386-y += mc146818rtc.o pc.o
 obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o
 obj-i386-y += vmport.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
@@ -232,7 +232,7 @@ obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
 obj-ppc-y = ppc.o ppc_booke.o
 obj-ppc-y += vga.o
 # PREP target
-obj-ppc-y += i8259.o mc146818rtc.o
+obj-ppc-y += mc146818rtc.o
 obj-ppc-y += ppc_prep.o
 # OldWorld PowerMac
 obj-ppc-y += ppc_oldworld.o
@@ -283,7 +283,7 @@ obj-lm32-y += framebuffer.o
 
 obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 obj-mips-y += mips_addr.o mips_timer.o mips_int.o
-obj-mips-y += vga.o i8259.o
+obj-mips-y += vga.o
 obj-mips-y += jazz_led.o
 obj-mips-y += gt64xxx.o mc146818rtc.o
 obj-mips-y += cirrus_vga.o
@@ -365,7 +365,7 @@ obj-m68k-y += m68k-semi.o dummy_m68k.o
 
 obj-s390x-y = s390-virtio-bus.o s390-virtio.o
 
-obj-alpha-y = i8259.o mc146818rtc.o
+obj-alpha-y = mc146818rtc.o
 obj-alpha-y += vga.o cirrus_vga.o
 obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
 
diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak
index be86d0c..bd1dd95 100644
--- a/default-configs/alpha-softmmu.mak
+++ b/default-configs/alpha-softmmu.mak
@@ -9,3 +9,4 @@ CONFIG_IDE_CORE=y
 CONFIG_IDE_QDEV=y
 CONFIG_VMWARE_VGA=y
 CONFIG_IDE_CMD646=y
+CONFIG_I8259=y
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 55589fa..e67ebb3 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -21,3 +21,4 @@ CONFIG_PIIX_PCI=y
 CONFIG_SOUND=y
 CONFIG_HPET=y
 CONFIG_APPLESMC=y
+CONFIG_I8259=y
diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak
index 45bdefb..94a3486 100644
--- a/default-configs/mips-softmmu.mak
+++ b/default-configs/mips-softmmu.mak
@@ -27,3 +27,4 @@ CONFIG_DS1225Y=y
 CONFIG_MIPSNET=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_G364FB=y
+CONFIG_I8259=y
diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak
index d43e33c..b5d3108 100644
--- a/default-configs/mips64-softmmu.mak
+++ b/default-configs/mips64-softmmu.mak
@@ -27,3 +27,4 @@ CONFIG_DS1225Y=y
 CONFIG_MIPSNET=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_G364FB=y
+CONFIG_I8259=y
diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index f307e8d..2831f44 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -29,3 +29,4 @@ CONFIG_MIPSNET=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_FULONG=y
 CONFIG_G364FB=y
+CONFIG_I8259=y
diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak
index 1a66bc3..14c949d 100644
--- a/default-configs/mipsel-softmmu.mak
+++ b/default-configs/mipsel-softmmu.mak
@@ -27,3 +27,4 @@ CONFIG_DS1225Y=y
 CONFIG_MIPSNET=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_G364FB=y
+CONFIG_I8259=y
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 4563742..c85cdce 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -31,3 +31,4 @@ CONFIG_SOUND=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_PFLASH_CFI02=y
 CONFIG_PTIMER=y
+CONFIG_I8259=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index d5073b3..8874115 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -31,3 +31,4 @@ CONFIG_SOUND=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_PFLASH_CFI02=y
 CONFIG_PTIMER=y
+CONFIG_I8259=y
diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
index 9f0730c..5db7205 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -31,3 +31,4 @@ CONFIG_SOUND=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_PFLASH_CFI02=y
 CONFIG_PTIMER=y
+CONFIG_I8259=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 8895028..b75757e 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -21,3 +21,4 @@ CONFIG_PIIX_PCI=y
 CONFIG_SOUND=y
 CONFIG_HPET=y
 CONFIG_APPLESMC=y
+CONFIG_I8259=y
commit 661f1929d0b9ce9af530f1806cfc6136c630d405
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Oct 16 11:53:13 2011 +0200

    monitor: Restrict pic/irq_info to supporting targets
    
    This allows to drop various stubs and move the i8359 into hwlib.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/an5206.c b/hw/an5206.c
index 481ae60..3fe1f00 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -7,7 +7,6 @@
  */
 
 #include "hw.h"
-#include "pc.h"
 #include "mcf.h"
 #include "boards.h"
 #include "loader.h"
@@ -18,15 +17,6 @@
 #define AN5206_MBAR_ADDR 0x10000000
 #define AN5206_RAMBAR_ADDR 0x20000000
 
-/* Stub functions for hardware that doesn't exist.  */
-void pic_info(Monitor *mon)
-{
-}
-
-void irq_info(Monitor *mon)
-{
-}
-
 /* Board init.  */
 
 static void an5206_init(ram_addr_t ram_size,
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index 41f8d3e..a2e8a73 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -8,19 +8,8 @@
  */
 
 #include "hw.h"
-#include "pc.h"
 #include "arm-misc.h"
 
-/* Stub functions for hardware that doesn't exist.  */
-void pic_info(Monitor *mon)
-{
-}
-
-void irq_info(Monitor *mon)
-{
-}
-
-
 /* Input 0 is IRQ and input 1 is FIQ.  */
 static void arm_pic_cpu_handler(void *opaque, int irq, int level)
 {
diff --git a/hw/cris_pic_cpu.c b/hw/cris_pic_cpu.c
index 7f1e4ab..06ae484 100644
--- a/hw/cris_pic_cpu.c
+++ b/hw/cris_pic_cpu.c
@@ -24,16 +24,10 @@
 
 #include "sysbus.h"
 #include "hw.h"
-#include "pc.h"
 #include "etraxfs.h"
 
 #define D(x)
 
-void pic_info(Monitor *mon)
-{}
-void irq_info(Monitor *mon)
-{}
-
 static void cris_pic_cpu_handler(void *opaque, int irq, int level)
 {
     CPUState *env = (CPUState *)opaque;
diff --git a/hw/etraxfs.h b/hw/etraxfs.h
index 1554b0b..24e8fd8 100644
--- a/hw/etraxfs.h
+++ b/hw/etraxfs.h
@@ -22,6 +22,7 @@
  * THE SOFTWARE.
  */
 
+#include "net.h"
 #include "etraxfs_dma.h"
 
 qemu_irq *cris_pic_init_cpu(CPUState *env);
diff --git a/hw/lm32_pic.c b/hw/lm32_pic.c
index 02941a7..8dd0050 100644
--- a/hw/lm32_pic.c
+++ b/hw/lm32_pic.c
@@ -39,7 +39,7 @@ struct LM32PicState {
 typedef struct LM32PicState LM32PicState;
 
 static LM32PicState *pic;
-void pic_info(Monitor *mon)
+void lm32_do_pic_info(Monitor *mon)
 {
     if (pic == NULL) {
         return;
@@ -49,7 +49,7 @@ void pic_info(Monitor *mon)
             pic->im, pic->ip, pic->irq_state);
 }
 
-void irq_info(Monitor *mon)
+void lm32_irq_info(Monitor *mon)
 {
     int i;
     uint32_t count;
diff --git a/hw/lm32_pic.h b/hw/lm32_pic.h
index e6479b8..14456f3 100644
--- a/hw/lm32_pic.h
+++ b/hw/lm32_pic.h
@@ -8,4 +8,7 @@ uint32_t lm32_pic_get_im(DeviceState *d);
 void lm32_pic_set_ip(DeviceState *d, uint32_t ip);
 void lm32_pic_set_im(DeviceState *d, uint32_t im);
 
+void lm32_do_pic_info(Monitor *mon);
+void lm32_irq_info(Monitor *mon);
+
 #endif /* QEMU_HW_LM32_PIC_H */
diff --git a/hw/microblaze_pic_cpu.c b/hw/microblaze_pic_cpu.c
index 9ad48b4..8b5623c 100644
--- a/hw/microblaze_pic_cpu.c
+++ b/hw/microblaze_pic_cpu.c
@@ -23,16 +23,10 @@
  */
 
 #include "hw.h"
-#include "pc.h"
 #include "microblaze_pic_cpu.h"
 
 #define D(x)
 
-void pic_info(Monitor *mon)
-{}
-void irq_info(Monitor *mon)
-{}
-
 static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
 {
     CPUState *env = (CPUState *)opaque;
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index acbf026..778cffe 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -62,17 +62,6 @@
 static VirtIOS390Bus *s390_bus;
 static CPUState **ipi_states;
 
-void irq_info(Monitor *mon);
-void pic_info(Monitor *mon);
-
-void irq_info(Monitor *mon)
-{
-}
-
-void pic_info(Monitor *mon)
-{
-}
-
 CPUState *s390_cpu_addr2state(uint16_t cpu_addr)
 {
     if (cpu_addr >= smp_cpus) {
diff --git a/hw/shix.c b/hw/shix.c
index 638bf16..dbf4764 100644
--- a/hw/shix.c
+++ b/hw/shix.c
@@ -28,7 +28,6 @@
    More information in target-sh4/README.sh4
 */
 #include "hw.h"
-#include "pc.h"
 #include "sh.h"
 #include "sysemu.h"
 #include "boards.h"
@@ -37,16 +36,6 @@
 #define BIOS_FILENAME "shix_bios.bin"
 #define BIOS_ADDRESS 0xA0000000
 
-void irq_info(Monitor *mon)
-{
-    /* XXXXX */
-}
-
-void pic_info(Monitor *mon)
-{
-    /* XXXXX */
-}
-
 static void shix_init(ram_addr_t ram_size,
                const char *boot_device,
 	       const char *kernel_filename, const char *kernel_cmdline,
diff --git a/hw/sun4m.c b/hw/sun4m.c
index dcaed38..71bf648 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -216,13 +216,13 @@ static void nvram_init(M48t59State *nvram, uint8_t *macaddr,
 
 static DeviceState *slavio_intctl;
 
-void pic_info(Monitor *mon)
+void sun4m_pic_info(Monitor *mon)
 {
     if (slavio_intctl)
         slavio_pic_info(mon, slavio_intctl);
 }
 
-void irq_info(Monitor *mon)
+void sun4m_irq_info(Monitor *mon)
 {
     if (slavio_intctl)
         slavio_irq_info(mon, slavio_intctl);
diff --git a/hw/sun4m.h b/hw/sun4m.h
index ce97ee5..504c3af 100644
--- a/hw/sun4m.h
+++ b/hw/sun4m.h
@@ -30,6 +30,10 @@ void slavio_irq_info(Monitor *mon, DeviceState *dev);
 void sun4c_pic_info(Monitor *mon, void *opaque);
 void sun4c_irq_info(Monitor *mon, void *opaque);
 
+/* sun4m.c */
+void sun4m_pic_info(Monitor *mon);
+void sun4m_irq_info(Monitor *mon);
+
 /* sparc32_dma.c */
 #include "sparc32_dma.h"
 
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 88c633d..96fc3d0 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -243,14 +243,6 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
     return kernel_size;
 }
 
-void pic_info(Monitor *mon)
-{
-}
-
-void irq_info(Monitor *mon)
-{
-}
-
 void cpu_check_irqs(CPUState *env)
 {
     uint32_t pil = env->pil_in |
diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
index 93e28fd..71d5fc8 100644
--- a/hw/xtensa_pic.c
+++ b/hw/xtensa_pic.c
@@ -26,19 +26,9 @@
  */
 
 #include "hw.h"
-#include "pc.h"
 #include "qemu-log.h"
 #include "qemu-timer.h"
 
-/* Stub functions for hardware that doesn't exist.  */
-void pic_info(Monitor *mon)
-{
-}
-
-void irq_info(Monitor *mon)
-{
-}
-
 void xtensa_advance_ccount(CPUState *env, uint32_t d)
 {
     uint32_t old_ccount = env->sregs[CCOUNT];
diff --git a/monitor.c b/monitor.c
index 1a28956..ffda0fe 100644
--- a/monitor.c
+++ b/monitor.c
@@ -67,6 +67,12 @@
 #include "qmp-commands.h"
 #include "hmp.h"
 
+/* for pic/irq_info */
+#if defined(TARGET_SPARC)
+#include "hw/sun4m.h"
+#endif
+#include "hw/lm32_pic.h"
+
 //#define DEBUG
 //#define DEBUG_COMPLETION
 
@@ -2798,20 +2804,35 @@ static const mon_cmd_t info_cmds[] = {
         .help       = "show the command line history",
         .mhandler.info = do_info_history,
     },
+#if defined(TARGET_I386) || defined(TARGET_PPC) || defined(TARGET_MIPS) || \
+    defined(TARGET_LM32) || (defined(TARGET_SPARC) && !defined(TARGET_SPARC64))
     {
         .name       = "irq",
         .args_type  = "",
         .params     = "",
         .help       = "show the interrupts statistics (if available)",
+#ifdef TARGET_SPARC
+        .mhandler.info = sun4m_irq_info,
+#elif defined(TARGET_LM32)
+        .mhandler.info = lm32_irq_info,
+#else
         .mhandler.info = irq_info,
+#endif
     },
     {
         .name       = "pic",
         .args_type  = "",
         .params     = "",
         .help       = "show i8259 (PIC) state",
+#ifdef TARGET_SPARC
+        .mhandler.info = sun4m_pic_info,
+#elif defined(TARGET_LM32)
+        .mhandler.info = lm32_do_pic_info,
+#else
         .mhandler.info = pic_info,
+#endif
     },
+#endif
     {
         .name       = "pci",
         .args_type  = "",
commit 81a02f93bac79598637eb5ffa5a5e3a6f1887175
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:54 2011 +0200

    i8259: Fix coding style
    
    No functional changes.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index b4e1867..ab519de 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -67,7 +67,7 @@ struct PicState {
     MemoryRegion elcr_io;
 };
 
-#if defined(DEBUG_PIC) || defined (DEBUG_IRQ_COUNT)
+#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
 static int irq_level[16];
 #endif
 #ifdef DEBUG_IRQ_COUNT
@@ -84,11 +84,14 @@ static PicState *slave_pic;
 static int get_priority(PicState *s, int mask)
 {
     int priority;
-    if (mask == 0)
+
+    if (mask == 0) {
         return 8;
+    }
     priority = 0;
-    while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
+    while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0) {
         priority++;
+    }
     return priority;
 }
 
@@ -99,14 +102,16 @@ static int pic_get_irq(PicState *s)
 
     mask = s->irr & ~s->imr;
     priority = get_priority(s, mask);
-    if (priority == 8)
+    if (priority == 8) {
         return -1;
+    }
     /* compute current priority. If special fully nested mode on the
        master, the IRQ coming from the slave is not taken into account
        for the priority computation. */
     mask = s->isr;
-    if (s->special_mask)
+    if (s->special_mask) {
         mask &= ~s->imr;
+    }
     if (s->special_fully_nested_mode && s->master) {
         mask &= ~(1 << 2);
     }
@@ -188,14 +193,16 @@ static void pic_set_irq(void *opaque, int irq, int level)
 static void pic_intack(PicState *s, int irq)
 {
     if (s->auto_eoi) {
-        if (s->rotate_on_auto_eoi)
+        if (s->rotate_on_auto_eoi) {
             s->priority_add = (irq + 1) & 7;
+        }
     } else {
         s->isr |= (1 << irq);
     }
     /* We don't clear a level sensitive interrupt here */
-    if (!(s->elcr & (1 << irq)))
+    if (!(s->elcr & (1 << irq))) {
         s->irr &= ~(1 << irq);
+    }
     pic_update_irq(s);
 }
 
@@ -283,18 +290,22 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
             s->init_state = 1;
             s->init4 = val & 1;
             s->single_mode = val & 2;
-            if (val & 0x08)
+            if (val & 0x08) {
                 hw_error("level sensitive irq not supported");
+            }
         } else if (val & 0x08) {
-            if (val & 0x04)
+            if (val & 0x04) {
                 s->poll = 1;
-            if (val & 0x02)
+            }
+            if (val & 0x02) {
                 s->read_reg_select = val & 1;
-            if (val & 0x40)
+            }
+            if (val & 0x40) {
                 s->special_mask = (val >> 5) & 1;
+            }
         } else {
             cmd = val >> 5;
-            switch(cmd) {
+            switch (cmd) {
             case 0:
             case 4:
                 s->rotate_on_auto_eoi = cmd >> 2;
@@ -305,8 +316,9 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
                 if (priority != 8) {
                     irq = (priority + s->priority_add) & 7;
                     s->isr &= ~(1 << irq);
-                    if (cmd == 5)
+                    if (cmd == 5) {
                         s->priority_add = (irq + 1) & 7;
+                    }
                     pic_update_irq(s);
                 }
                 break;
@@ -331,7 +343,7 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
             }
         }
     } else {
-        switch(s->init_state) {
+        switch (s->init_state) {
         case 0:
             /* normal mode */
             s->imr = val;
@@ -374,10 +386,11 @@ static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr,
         s->poll = 0;
     } else {
         if (addr == 0) {
-            if (s->read_reg_select)
+            if (s->read_reg_select) {
                 ret = s->isr;
-            else
+            } else {
                 ret = s->irr;
+            }
         } else {
             ret = s->imr;
         }
@@ -410,7 +423,7 @@ static const VMStateDescription vmstate_pic = {
     .version_id = 1,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
+    .fields = (VMStateField[]) {
         VMSTATE_UINT8(last_irr, PicState),
         VMSTATE_UINT8(irr, PicState),
         VMSTATE_UINT8(imr, PicState),
@@ -474,9 +487,9 @@ void pic_info(Monitor *mon)
     int i;
     PicState *s;
 
-    if (!isa_pic)
+    if (!isa_pic) {
         return;
-
+    }
     for (i = 0; i < 2; i++) {
         s = i == 0 ? isa_pic : slave_pic;
         monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d "
@@ -498,8 +511,9 @@ void irq_info(Monitor *mon)
     monitor_printf(mon, "IRQ statistics:\n");
     for (i = 0; i < 16; i++) {
         count = irq_count[i];
-        if (count > 0)
+        if (count > 0) {
             monitor_printf(mon, "%2d: %" PRId64 "\n", i, count);
+        }
     }
 #endif
 }
commit 747c70af78f7088f182c87e683bdf847beead1e4
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:53 2011 +0200

    i8259: Convert to qdev
    
    This key cleanup step requires to move the IRQ debugging bit from
    i8259_set_irq directly to the per-PIC pic_set_irq, to pass the PIC
    parameters (I/O base, ELCR address and mask, master/slave mode) as
    qdev properties, and to interconnect the PICs with their environment via
    GPIO pins.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index df23bb8..b4e1867 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -41,6 +41,7 @@
 //#define DEBUG_IRQ_COUNT
 
 struct PicState {
+    ISADevice dev;
     uint8_t last_irr; /* edge detection */
     uint8_t irr; /* interrupt request register */
     uint8_t imr; /* interrupt mask register */
@@ -58,8 +59,10 @@ struct PicState {
     uint8_t single_mode; /* true if slave pic is not initialized */
     uint8_t elcr; /* PIIX edge/trigger selection*/
     uint8_t elcr_mask;
-    qemu_irq int_out;
-    bool master; /* reflects /SP input pin */
+    qemu_irq int_out[1];
+    uint32_t master; /* reflects /SP input pin */
+    uint32_t iobase;
+    uint32_t elcr_addr;
     MemoryRegion base_io;
     MemoryRegion elcr_io;
 };
@@ -70,6 +73,9 @@ static int irq_level[16];
 #ifdef DEBUG_IRQ_COUNT
 static uint64_t irq_count[16];
 #endif
+#ifdef DEBUG_IRQ_LATENCY
+static int64_t irq_time[16];
+#endif
 PicState *isa_pic;
 static PicState *slave_pic;
 
@@ -122,17 +128,39 @@ static void pic_update_irq(PicState *s)
     if (irq >= 0) {
         DPRINTF("pic%d: imr=%x irr=%x padd=%d\n",
                 s->master ? 0 : 1, s->imr, s->irr, s->priority_add);
-        qemu_irq_raise(s->int_out);
+        qemu_irq_raise(s->int_out[0]);
     } else {
-        qemu_irq_lower(s->int_out);
+        qemu_irq_lower(s->int_out[0]);
     }
 }
 
 /* set irq level. If an edge is detected, then the IRR is set to 1 */
-static void pic_set_irq1(PicState *s, int irq, int level)
+static void pic_set_irq(void *opaque, int irq, int level)
 {
-    int mask;
-    mask = 1 << irq;
+    PicState *s = opaque;
+    int mask = 1 << irq;
+
+#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT) || \
+    defined(DEBUG_IRQ_LATENCY)
+    int irq_index = s->master ? irq : irq + 8;
+#endif
+#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
+    if (level != irq_level[irq_index]) {
+        DPRINTF("pic_set_irq: irq=%d level=%d\n", irq_index, level);
+        irq_level[irq_index] = level;
+#ifdef DEBUG_IRQ_COUNT
+        if (level == 1) {
+            irq_count[irq_index]++;
+        }
+#endif
+    }
+#endif
+#ifdef DEBUG_IRQ_LATENCY
+    if (level) {
+        irq_time[irq_index] = qemu_get_clock_ns(vm_clock);
+    }
+#endif
+
     if (s->elcr & mask) {
         /* level triggered */
         if (level) {
@@ -156,32 +184,6 @@ static void pic_set_irq1(PicState *s, int irq, int level)
     pic_update_irq(s);
 }
 
-#ifdef DEBUG_IRQ_LATENCY
-int64_t irq_time[16];
-#endif
-
-static void i8259_set_irq(void *opaque, int irq, int level)
-{
-    PicState *s = irq <= 7 ? isa_pic : slave_pic;
-
-#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
-    if (level != irq_level[irq]) {
-        DPRINTF("i8259_set_irq: irq=%d level=%d\n", irq, level);
-        irq_level[irq] = level;
-#ifdef DEBUG_IRQ_COUNT
-	if (level == 1)
-	    irq_count[irq]++;
-#endif
-    }
-#endif
-#ifdef DEBUG_IRQ_LATENCY
-    if (level) {
-        irq_time[irq] = qemu_get_clock_ns(vm_clock);
-    }
-#endif
-    pic_set_irq1(s, irq & 7, level);
-}
-
 /* acknowledge interrupt 'irq' */
 static void pic_intack(PicState *s, int irq)
 {
@@ -258,9 +260,9 @@ static void pic_init_reset(PicState *s)
     pic_update_irq(s);
 }
 
-static void pic_reset(void *opaque)
+static void pic_reset(DeviceState *dev)
 {
-    PicState *s = opaque;
+    PicState *s = container_of(dev, PicState, dev.qdev);
 
     pic_init_reset(s);
     s->elcr = 0;
@@ -447,23 +449,24 @@ static const MemoryRegionOps pic_elcr_ioport_ops = {
     },
 };
 
-/* XXX: add generic master/slave system */
-static void pic_init(int io_addr, int elcr_addr, PicState *s, qemu_irq int_out,
-                     bool master)
+static int pic_initfn(ISADevice *dev)
 {
-    s->int_out = int_out;
-    s->master = master;
+    PicState *s = DO_UPCAST(PicState, dev, dev);
 
     memory_region_init_io(&s->base_io, &pic_base_ioport_ops, s, "pic", 2);
     memory_region_init_io(&s->elcr_io, &pic_elcr_ioport_ops, s, "elcr", 1);
 
-    isa_register_ioport(NULL, &s->base_io, io_addr);
-    if (elcr_addr >= 0) {
-        isa_register_ioport(NULL, &s->elcr_io, elcr_addr);
+    isa_register_ioport(NULL, &s->base_io, s->iobase);
+    if (s->elcr_addr != -1) {
+        isa_register_ioport(NULL, &s->elcr_io, s->elcr_addr);
     }
 
-    vmstate_register(NULL, io_addr, &vmstate_pic, s);
-    qemu_register_reset(pic_reset, s);
+    qdev_init_gpio_out(&dev->qdev, s->int_out, ARRAY_SIZE(s->int_out));
+    qdev_init_gpio_in(&dev->qdev, pic_set_irq, 8);
+
+    qdev_set_legacy_instance_id(&dev->qdev, s->iobase, 1);
+
+    return 0;
 }
 
 void pic_info(Monitor *mon)
@@ -503,20 +506,60 @@ void irq_info(Monitor *mon)
 
 qemu_irq *i8259_init(qemu_irq parent_irq)
 {
-    qemu_irq *irqs;
-    PicState *s;
+    qemu_irq *irq_set;
+    ISADevice *dev;
+    int i;
 
-    irqs = qemu_allocate_irqs(i8259_set_irq, NULL, 16);
+    irq_set = g_malloc(ISA_NUM_IRQS * sizeof(qemu_irq));
 
-    s = g_malloc0(sizeof(PicState));
-    pic_init(0x20, 0x4d0, s, parent_irq, true);
-    s->elcr_mask = 0xf8;
-    isa_pic = s;
+    dev = isa_create("isa-i8259");
+    qdev_prop_set_uint32(&dev->qdev, "iobase", 0x20);
+    qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d0);
+    qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xf8);
+    qdev_prop_set_bit(&dev->qdev, "master", true);
+    qdev_init_nofail(&dev->qdev);
 
-    s = g_malloc0(sizeof(PicState));
-    pic_init(0xa0, 0x4d1, s, irqs[2], false);
-    s->elcr_mask = 0xde;
-    slave_pic = s;
+    qdev_connect_gpio_out(&dev->qdev, 0, parent_irq);
+    for (i = 0 ; i < 8; i++) {
+        irq_set[i] = qdev_get_gpio_in(&dev->qdev, i);
+    }
+
+    isa_pic = DO_UPCAST(PicState, dev, dev);
+
+    dev = isa_create("isa-i8259");
+    qdev_prop_set_uint32(&dev->qdev, "iobase", 0xa0);
+    qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d1);
+    qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xde);
+    qdev_init_nofail(&dev->qdev);
+
+    qdev_connect_gpio_out(&dev->qdev, 0, irq_set[2]);
+    for (i = 0 ; i < 8; i++) {
+        irq_set[i + 8] = qdev_get_gpio_in(&dev->qdev, i);
+    }
+
+    slave_pic = DO_UPCAST(PicState, dev, dev);
 
-    return irqs;
+    return irq_set;
+}
+
+static ISADeviceInfo i8259_info = {
+    .qdev.name     = "isa-i8259",
+    .qdev.size     = sizeof(PicState),
+    .qdev.vmsd     = &vmstate_pic,
+    .qdev.reset    = pic_reset,
+    .qdev.no_user  = 1,
+    .init          = pic_initfn,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_HEX32("iobase", PicState, iobase,  -1),
+        DEFINE_PROP_HEX32("elcr_addr", PicState, elcr_addr,  -1),
+        DEFINE_PROP_HEX8("elcr_mask", PicState, elcr_mask,  -1),
+        DEFINE_PROP_BIT("master", PicState, master,  0, false),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void pic_register(void)
+{
+    isa_qdev_register(&i8259_info);
 }
+device_init(pic_register)
commit 6835678c259976c87df6be09360c1be85da37538
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:52 2011 +0200

    qdev: Add HEX8 property
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index e0e54aa..f0b811c 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -93,6 +93,35 @@ PropertyInfo qdev_prop_uint8 = {
     .print = print_uint8,
 };
 
+/* --- 8bit hex value --- */
+
+static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
+{
+    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
+    char *end;
+
+    *ptr = strtoul(str, &end, 16);
+    if ((*end != '\0') || (end == str)) {
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
+    return snprintf(dest, len, "0x%" PRIx8, *ptr);
+}
+
+PropertyInfo qdev_prop_hex8 = {
+    .name  = "hex8",
+    .type  = PROP_TYPE_UINT8,
+    .size  = sizeof(uint8_t),
+    .parse = parse_hex8,
+    .print = print_hex8,
+};
+
 /* --- 16bit integer --- */
 
 static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
diff --git a/hw/qdev.h b/hw/qdev.h
index 8a13ec9..aa7ae36 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -224,6 +224,7 @@ extern PropertyInfo qdev_prop_uint16;
 extern PropertyInfo qdev_prop_uint32;
 extern PropertyInfo qdev_prop_int32;
 extern PropertyInfo qdev_prop_uint64;
+extern PropertyInfo qdev_prop_hex8;
 extern PropertyInfo qdev_prop_hex32;
 extern PropertyInfo qdev_prop_hex64;
 extern PropertyInfo qdev_prop_string;
@@ -267,6 +268,8 @@ extern PropertyInfo qdev_prop_pci_devfn;
     DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
 #define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \
     DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
+#define DEFINE_PROP_HEX8(_n, _s, _f, _d)                       \
+    DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t)
 #define DEFINE_PROP_HEX32(_n, _s, _f, _d)                       \
     DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t)
 #define DEFINE_PROP_HEX64(_n, _s, _f, _d)                       \
commit c17725f4730941fc06a512ef2aa6c2e9377347ad
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:51 2011 +0200

    i8259: Eliminate PicState2
    
    Introduce a reference to the slave PIC for the few cases we need to
    access it without a proper pointer at hand and drop PicState2. We could
    even live without slave_pic if we had a better way of modeling the
    cascade bus the PICs are attached to (in addition to the ISA bus).
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index dc13b12..df23bb8 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -40,7 +40,7 @@
 //#define DEBUG_IRQ_LATENCY
 //#define DEBUG_IRQ_COUNT
 
-typedef struct PicState {
+struct PicState {
     uint8_t last_irr; /* edge detection */
     uint8_t irr; /* interrupt request register */
     uint8_t imr; /* interrupt mask register */
@@ -62,13 +62,6 @@ typedef struct PicState {
     bool master; /* reflects /SP input pin */
     MemoryRegion base_io;
     MemoryRegion elcr_io;
-} PicState;
-
-struct PicState2 {
-    /* 0 is master pic, 1 is slave pic */
-    /* XXX: better separation between the two pics */
-    PicState pics[2];
-    void *irq_request_opaque;
 };
 
 #if defined(DEBUG_PIC) || defined (DEBUG_IRQ_COUNT)
@@ -77,7 +70,8 @@ static int irq_level[16];
 #ifdef DEBUG_IRQ_COUNT
 static uint64_t irq_count[16];
 #endif
-PicState2 *isa_pic;
+PicState *isa_pic;
+static PicState *slave_pic;
 
 /* return the highest priority found in mask (highest = smallest
    number). Return 8 if no irq */
@@ -168,7 +162,7 @@ int64_t irq_time[16];
 
 static void i8259_set_irq(void *opaque, int irq, int level)
 {
-    PicState2 *s = opaque;
+    PicState *s = irq <= 7 ? isa_pic : slave_pic;
 
 #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
     if (level != irq_level[irq]) {
@@ -185,7 +179,7 @@ static void i8259_set_irq(void *opaque, int irq, int level)
         irq_time[irq] = qemu_get_clock_ns(vm_clock);
     }
 #endif
-    pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
+    pic_set_irq1(s, irq & 7, level);
 }
 
 /* acknowledge interrupt 'irq' */
@@ -203,29 +197,29 @@ static void pic_intack(PicState *s, int irq)
     pic_update_irq(s);
 }
 
-int pic_read_irq(PicState2 *s)
+int pic_read_irq(PicState *s)
 {
     int irq, irq2, intno;
 
-    irq = pic_get_irq(&s->pics[0]);
+    irq = pic_get_irq(s);
     if (irq >= 0) {
         if (irq == 2) {
-            irq2 = pic_get_irq(&s->pics[1]);
+            irq2 = pic_get_irq(slave_pic);
             if (irq2 >= 0) {
-                pic_intack(&s->pics[1], irq2);
+                pic_intack(slave_pic, irq2);
             } else {
                 /* spurious IRQ on slave controller */
                 irq2 = 7;
             }
-            intno = s->pics[1].irq_base + irq2;
+            intno = slave_pic->irq_base + irq2;
         } else {
-            intno = s->pics[0].irq_base + irq;
+            intno = s->irq_base + irq;
         }
-        pic_intack(&s->pics[0], irq);
+        pic_intack(s, irq);
     } else {
         /* spurious IRQ on host controller */
         irq = 7;
-        intno = s->pics[0].irq_base + irq;
+        intno = s->irq_base + irq;
     }
 
 #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY)
@@ -390,9 +384,9 @@ static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr,
     return ret;
 }
 
-int pic_get_output(PicState2 *s)
+int pic_get_output(PicState *s)
 {
-    return (pic_get_irq(&s->pics[0]) >= 0);
+    return (pic_get_irq(s) >= 0);
 }
 
 static void elcr_ioport_write(void *opaque, target_phys_addr_t addr,
@@ -480,8 +474,8 @@ void pic_info(Monitor *mon)
     if (!isa_pic)
         return;
 
-    for(i=0;i<2;i++) {
-        s = &isa_pic->pics[i];
+    for (i = 0; i < 2; i++) {
+        s = i == 0 ? isa_pic : slave_pic;
         monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d "
                        "irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
                        i, s->irr, s->imr, s->isr, s->priority_add,
@@ -510,14 +504,19 @@ void irq_info(Monitor *mon)
 qemu_irq *i8259_init(qemu_irq parent_irq)
 {
     qemu_irq *irqs;
-    PicState2 *s;
-
-    s = g_malloc0(sizeof(PicState2));
-    irqs = qemu_allocate_irqs(i8259_set_irq, s, 16);
-    pic_init(0x20, 0x4d0, &s->pics[0], parent_irq, true);
-    pic_init(0xa0, 0x4d1, &s->pics[1], irqs[2], false);
-    s->pics[0].elcr_mask = 0xf8;
-    s->pics[1].elcr_mask = 0xde;
+    PicState *s;
+
+    irqs = qemu_allocate_irqs(i8259_set_irq, NULL, 16);
+
+    s = g_malloc0(sizeof(PicState));
+    pic_init(0x20, 0x4d0, s, parent_irq, true);
+    s->elcr_mask = 0xf8;
     isa_pic = s;
+
+    s = g_malloc0(sizeof(PicState));
+    pic_init(0xa0, 0x4d1, s, irqs[2], false);
+    s->elcr_mask = 0xde;
+    slave_pic = s;
+
     return irqs;
 }
diff --git a/hw/pc.h b/hw/pc.h
index f0b31de..b8ad9a3 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -60,11 +60,11 @@ bool parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
 
 /* i8259.c */
 
-typedef struct PicState2 PicState2;
-extern PicState2 *isa_pic;
+typedef struct PicState PicState;
+extern PicState *isa_pic;
 qemu_irq *i8259_init(qemu_irq parent_irq);
-int pic_read_irq(PicState2 *s);
-int pic_get_output(PicState2 *s);
+int pic_read_irq(PicState *s);
+int pic_get_output(PicState *s);
 void pic_info(Monitor *mon);
 void irq_info(Monitor *mon);
 
commit 25985396423706d8fba9bd8c0e49217844700299
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:50 2011 +0200

    i8259: Replace PicState::pics_state with master flag
    
    This reflects how real PICs indentify their role (in non-buffered mode):
    Pass the state of the /SP input on pic_init and use it instead of
    pics_state to differentiate between master and slave mode.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index 8870277..dc13b12 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -59,7 +59,7 @@ typedef struct PicState {
     uint8_t elcr; /* PIIX edge/trigger selection*/
     uint8_t elcr_mask;
     qemu_irq int_out;
-    PicState2 *pics_state;
+    bool master; /* reflects /SP input pin */
     MemoryRegion base_io;
     MemoryRegion elcr_io;
 } PicState;
@@ -107,8 +107,9 @@ static int pic_get_irq(PicState *s)
     mask = s->isr;
     if (s->special_mask)
         mask &= ~s->imr;
-    if (s->special_fully_nested_mode && s == &s->pics_state->pics[0])
+    if (s->special_fully_nested_mode && s->master) {
         mask &= ~(1 << 2);
+    }
     cur_priority = get_priority(s, mask);
     if (priority < cur_priority) {
         /* higher priority found: an irq should be generated */
@@ -126,8 +127,7 @@ static void pic_update_irq(PicState *s)
     irq = pic_get_irq(s);
     if (irq >= 0) {
         DPRINTF("pic%d: imr=%x irr=%x padd=%d\n",
-                s == &s->pics_state->pics[0] ? 0 : 1, s->imr, s->irr,
-                s->priority_add);
+                s->master ? 0 : 1, s->imr, s->irr, s->priority_add);
         qemu_irq_raise(s->int_out);
     } else {
         qemu_irq_lower(s->int_out);
@@ -454,9 +454,11 @@ static const MemoryRegionOps pic_elcr_ioport_ops = {
 };
 
 /* XXX: add generic master/slave system */
-static void pic_init(int io_addr, int elcr_addr, PicState *s, qemu_irq int_out)
+static void pic_init(int io_addr, int elcr_addr, PicState *s, qemu_irq int_out,
+                     bool master)
 {
     s->int_out = int_out;
+    s->master = master;
 
     memory_region_init_io(&s->base_io, &pic_base_ioport_ops, s, "pic", 2);
     memory_region_init_io(&s->elcr_io, &pic_elcr_ioport_ops, s, "elcr", 1);
@@ -512,12 +514,10 @@ qemu_irq *i8259_init(qemu_irq parent_irq)
 
     s = g_malloc0(sizeof(PicState2));
     irqs = qemu_allocate_irqs(i8259_set_irq, s, 16);
-    pic_init(0x20, 0x4d0, &s->pics[0], parent_irq);
-    pic_init(0xa0, 0x4d1, &s->pics[1], irqs[2]);
+    pic_init(0x20, 0x4d0, &s->pics[0], parent_irq, true);
+    pic_init(0xa0, 0x4d1, &s->pics[1], irqs[2], false);
     s->pics[0].elcr_mask = 0xf8;
     s->pics[1].elcr_mask = 0xde;
-    s->pics[0].pics_state = s;
-    s->pics[1].pics_state = s;
     isa_pic = s;
     return irqs;
 }
commit 6e5580ca2b7a104fac865885e997da8b088de652
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:49 2011 +0200

    i8259: PREP: Replace pic_intack_read with pic_read_irq
    
    There is nothing in the i8259 spec that justifies the special
    pic_intack_read. At least the Linux PREP kernels configure the PICs
    properly so that pic_read_irq returns identical values, and setting
    read_reg_select in PIC0 cannot be derived from any special i8259 mode.
    
    So switch ppc_prep to pic_read_irq and drop the now unused PIC code.
    
    CC: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index 545d723..8870277 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -361,30 +361,6 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
     }
 }
 
-static uint32_t pic_poll_read(PicState *s)
-{
-    int ret;
-
-    ret = pic_get_irq(s);
-    if (ret >= 0) {
-        bool slave = (s == &isa_pic->pics[1]);
-
-        if (slave) {
-            s->pics_state->pics[0].isr &= ~(1 << 2);
-            s->pics_state->pics[0].irr &= ~(1 << 2);
-        }
-        s->irr &= ~(1 << ret);
-        s->isr &= ~(1 << ret);
-        if (slave || ret != 2) {
-            pic_update_irq(s);
-        }
-    } else {
-        ret = 0x07;
-    }
-
-    return ret;
-}
-
 static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr,
                                 unsigned size)
 {
@@ -414,21 +390,6 @@ static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr,
     return ret;
 }
 
-/* memory mapped interrupt status */
-/* XXX: may be the same than pic_read_irq() */
-uint32_t pic_intack_read(PicState2 *s)
-{
-    int ret;
-
-    ret = pic_poll_read(&s->pics[0]);
-    if (ret == 2)
-        ret = pic_poll_read(&s->pics[1]) + 8;
-    /* Prepare for ISR read */
-    s->pics[0].read_reg_select = 1;
-
-    return ret;
-}
-
 int pic_get_output(PicState2 *s)
 {
     return (pic_get_irq(&s->pics[0]) >= 0);
diff --git a/hw/pc.h b/hw/pc.h
index 5d20d58..f0b31de 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -65,7 +65,6 @@ extern PicState2 *isa_pic;
 qemu_irq *i8259_init(qemu_irq parent_irq);
 int pic_read_irq(PicState2 *s);
 int pic_get_output(PicState2 *s);
-uint32_t pic_intack_read(PicState2 *s);
 void pic_info(Monitor *mon);
 void irq_info(Monitor *mon);
 
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index d26049b..6427baa 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -130,7 +130,7 @@ static inline uint32_t _PPC_intack_read(target_phys_addr_t addr)
     uint32_t retval = 0;
 
     if ((addr & 0xf) == 0)
-        retval = pic_intack_read(isa_pic);
+        retval = pic_read_irq(isa_pic);
 #if 0
     printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
            retval);
commit fc1a5e0a246848c5bba271d39882f8d7b15da682
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:48 2011 +0200

    i8259: Clean up pic_ioport_read
    
    Drop redundant local address variable.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index 31962c0..545d723 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -385,11 +385,10 @@ static uint32_t pic_poll_read(PicState *s)
     return ret;
 }
 
-static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr1,
+static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr,
                                 unsigned size)
 {
     PicState *s = opaque;
-    unsigned int addr = addr1;
     int ret;
 
     if (s->poll) {
commit 8d484caa84dbaca5597cfbbf657ebdcd8f06b0c3
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:47 2011 +0200

    i8259: Fix poll command
    
    This was probably never used so far: According to the spec, polling
    means ack'ing the pending IRQ and setting its corresponding bit in isr.
    Moreover, we have to signal a pending IRQ via bit 7 of the returned
    value, and we must not return a spurious IRQ if none is pending.
    
    This implements the poll command without the help of pic_poll_read which
    is left untouched as pic_intack_read is still using it.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index bb257e6..31962c0 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -393,7 +393,13 @@ static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr1,
     int ret;
 
     if (s->poll) {
-        ret = pic_poll_read(s);
+        ret = pic_get_irq(s);
+        if (ret >= 0) {
+            pic_intack(s, ret);
+            ret |= 0x80;
+        } else {
+            ret = 0;
+        }
         s->poll = 0;
     } else {
         if (addr == 0) {
commit b76750c1ab50e23ef3ebc8cb6018dda41f174d84
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:46 2011 +0200

    i8259: Switch to per-PIC IRQ update
    
    This converts pic_update_irq to work against a single PIC instead of the
    complete cascade. Along this change, the required update after
    pic_set_irq1 is now moved into that function.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index d18fc62..bb257e6 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -118,39 +118,19 @@ static int pic_get_irq(PicState *s)
     }
 }
 
-static void pic_set_irq1(PicState *s, int irq, int level);
-
-/* raise irq to CPU if necessary. must be called every time the active
-   irq may change */
-static void pic_update_irq(PicState2 *s)
+/* Update INT output. Must be called every time the output may have changed. */
+static void pic_update_irq(PicState *s)
 {
-    int irq2, irq;
-
-    /* first look at slave pic */
-    irq2 = pic_get_irq(&s->pics[1]);
-    if (irq2 >= 0) {
-        /* if irq request by slave pic, signal master PIC */
-        pic_set_irq1(&s->pics[0], 2, 1);
-        pic_set_irq1(&s->pics[0], 2, 0);
-    }
-    /* look at requested irq */
-    irq = pic_get_irq(&s->pics[0]);
-    if (irq >= 0) {
-#if defined(DEBUG_PIC)
-        {
-            int i;
-            for(i = 0; i < 2; i++) {
-                printf("pic%d: imr=%x irr=%x padd=%d\n",
-                       i, s->pics[i].imr, s->pics[i].irr,
-                       s->pics[i].priority_add);
+    int irq;
 
-            }
-        }
-        printf("pic: cpu_interrupt\n");
-#endif
-        qemu_irq_raise(s->pics[0].int_out);
+    irq = pic_get_irq(s);
+    if (irq >= 0) {
+        DPRINTF("pic%d: imr=%x irr=%x padd=%d\n",
+                s == &s->pics_state->pics[0] ? 0 : 1, s->imr, s->irr,
+                s->priority_add);
+        qemu_irq_raise(s->int_out);
     } else {
-        qemu_irq_lower(s->pics[0].int_out);
+        qemu_irq_lower(s->int_out);
     }
 }
 
@@ -179,6 +159,7 @@ static void pic_set_irq1(PicState *s, int irq, int level)
             s->last_irr &= ~mask;
         }
     }
+    pic_update_irq(s);
 }
 
 #ifdef DEBUG_IRQ_LATENCY
@@ -205,7 +186,6 @@ static void i8259_set_irq(void *opaque, int irq, int level)
     }
 #endif
     pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
-    pic_update_irq(s);
 }
 
 /* acknowledge interrupt 'irq' */
@@ -220,6 +200,7 @@ static void pic_intack(PicState *s, int irq)
     /* We don't clear a level sensitive interrupt here */
     if (!(s->elcr & (1 << irq)))
         s->irr &= ~(1 << irq);
+    pic_update_irq(s);
 }
 
 int pic_read_irq(PicState2 *s)
@@ -246,7 +227,6 @@ int pic_read_irq(PicState2 *s)
         irq = 7;
         intno = s->pics[0].irq_base + irq;
     }
-    pic_update_irq(s);
 
 #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY)
     if (irq == 2) {
@@ -281,7 +261,7 @@ static void pic_init_reset(PicState *s)
     s->init4 = 0;
     s->single_mode = 0;
     /* Note: ELCR is not reset */
-    pic_update_irq(s->pics_state);
+    pic_update_irq(s);
 }
 
 static void pic_reset(void *opaque)
@@ -331,23 +311,23 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
                     s->isr &= ~(1 << irq);
                     if (cmd == 5)
                         s->priority_add = (irq + 1) & 7;
-                    pic_update_irq(s->pics_state);
+                    pic_update_irq(s);
                 }
                 break;
             case 3:
                 irq = val & 7;
                 s->isr &= ~(1 << irq);
-                pic_update_irq(s->pics_state);
+                pic_update_irq(s);
                 break;
             case 6:
                 s->priority_add = (val + 1) & 7;
-                pic_update_irq(s->pics_state);
+                pic_update_irq(s);
                 break;
             case 7:
                 irq = val & 7;
                 s->isr &= ~(1 << irq);
                 s->priority_add = (irq + 1) & 7;
-                pic_update_irq(s->pics_state);
+                pic_update_irq(s);
                 break;
             default:
                 /* no operation */
@@ -359,7 +339,7 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
         case 0:
             /* normal mode */
             s->imr = val;
-            pic_update_irq(s->pics_state);
+            pic_update_irq(s);
             break;
         case 1:
             s->irq_base = val & 0xf8;
@@ -395,8 +375,9 @@ static uint32_t pic_poll_read(PicState *s)
         }
         s->irr &= ~(1 << ret);
         s->isr &= ~(1 << ret);
-        if (slave || ret != 2)
-            pic_update_irq(s->pics_state);
+        if (slave || ret != 2) {
+            pic_update_irq(s);
+        }
     } else {
         ret = 0x07;
     }
commit 86fbf97ceb4a9c46a609dd4ae053ba4262b68fe8
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:45 2011 +0200

    i8259: Clear ELCR on reset
    
    The ELCR is actually part of the chipset but we model it here for
    simplicity reasons. The PIIX3 clears the ELCR on reset, which was once
    broken by 4dbe19e181. Fix this by splitting up pic_init_reset from
    pic_reset and clearing the register in the latter.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index 3498c6b..d18fc62 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -263,10 +263,8 @@ int pic_read_irq(PicState2 *s)
     return intno;
 }
 
-static void pic_reset(void *opaque)
+static void pic_init_reset(PicState *s)
 {
-    PicState *s = opaque;
-
     s->last_irr = 0;
     s->irr = 0;
     s->imr = 0;
@@ -286,6 +284,14 @@ static void pic_reset(void *opaque)
     pic_update_irq(s->pics_state);
 }
 
+static void pic_reset(void *opaque)
+{
+    PicState *s = opaque;
+
+    pic_init_reset(s);
+    s->elcr = 0;
+}
+
 static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
                              uint64_t val64, unsigned size)
 {
@@ -297,8 +303,7 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
     DPRINTF("write: addr=0x%02x val=0x%02x\n", addr, val);
     if (addr == 0) {
         if (val & 0x10) {
-            /* init */
-            pic_reset(s);
+            pic_init_reset(s);
             s->init_state = 1;
             s->init4 = val & 1;
             s->single_mode = val & 2;
commit 51d9e939b8120d76feb096aeff04368683784541
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:44 2011 +0200

    i8259: Update IRQ state after reset
    
    MIPS and PPC users of the i8259 output signal expect us to report state
    updates also after reset. As no consumer (including the master PIC) can
    misinterpret the deassert as an activation event, it is safe to simply
    update the IRQ state after reset.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index b7a011f..3498c6b 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -283,6 +283,7 @@ static void pic_reset(void *opaque)
     s->init4 = 0;
     s->single_mode = 0;
     /* Note: ELCR is not reset */
+    pic_update_irq(s->pics_state);
 }
 
 static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
@@ -298,8 +299,6 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
         if (val & 0x10) {
             /* init */
             pic_reset(s);
-            /* deassert a pending interrupt */
-            qemu_irq_lower(s->pics_state->pics[0].int_out);
             s->init_state = 1;
             s->init4 = val & 1;
             s->single_mode = val & 2;
commit 78ef2b6989fb20eb7eee3a5cef66655ea1d19175
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:43 2011 +0200

    i8259: Reorder intack in pic_read_irq
    
    As we want to move the IRQ update to pic_intack, ordering matters: the
    slave ack must be executed before the master ack to avoid missing
    further pending slave IRQs.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index cddd3c7..b7a011f 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -228,7 +228,6 @@ int pic_read_irq(PicState2 *s)
 
     irq = pic_get_irq(&s->pics[0]);
     if (irq >= 0) {
-        pic_intack(&s->pics[0], irq);
         if (irq == 2) {
             irq2 = pic_get_irq(&s->pics[1]);
             if (irq2 >= 0) {
@@ -238,12 +237,10 @@ int pic_read_irq(PicState2 *s)
                 irq2 = 7;
             }
             intno = s->pics[1].irq_base + irq2;
-#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY)
-            irq = irq2 + 8;
-#endif
         } else {
             intno = s->pics[0].irq_base + irq;
         }
+        pic_intack(&s->pics[0], irq);
     } else {
         /* spurious IRQ on host controller */
         irq = 7;
@@ -251,6 +248,11 @@ int pic_read_irq(PicState2 *s)
     }
     pic_update_irq(s);
 
+#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY)
+    if (irq == 2) {
+        irq = irq2 + 8;
+    }
+#endif
 #ifdef DEBUG_IRQ_LATENCY
     printf("IRQ%d latency=%0.3fus\n",
            irq,
commit afdb06f84920c4949da904b045cdd105caf2579c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:42 2011 +0200

    i8259: Do not update IRQ output after spurious pic_poll_read
    
    If pic_poll_read finds no pending IRQ and return a spurious one instead,
    no PIC state is changed, thus we do not need to call pic_update_irq.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index 65123bd..cddd3c7 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -393,7 +393,6 @@ static uint32_t pic_poll_read(PicState *s)
             pic_update_irq(s->pics_state);
     } else {
         ret = 0x07;
-        pic_update_irq(s->pics_state);
     }
 
     return ret;
commit 2e2b22749985f81f33f79c5cab8994ea45bb9a2b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:41 2011 +0200

    i8239: Introduce per-PIC output interrupt
    
    As a first step towards more generic master-slave support, remove
    parent_irq in favor of a per-PIC output interrupt line. The slave's
    line is attached to IRQ2 of the master, but it remains unused for now.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index de2d5ca..65123bd 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -58,6 +58,7 @@ typedef struct PicState {
     uint8_t single_mode; /* true if slave pic is not initialized */
     uint8_t elcr; /* PIIX edge/trigger selection*/
     uint8_t elcr_mask;
+    qemu_irq int_out;
     PicState2 *pics_state;
     MemoryRegion base_io;
     MemoryRegion elcr_io;
@@ -67,7 +68,6 @@ struct PicState2 {
     /* 0 is master pic, 1 is slave pic */
     /* XXX: better separation between the two pics */
     PicState pics[2];
-    qemu_irq parent_irq;
     void *irq_request_opaque;
 };
 
@@ -148,9 +148,9 @@ static void pic_update_irq(PicState2 *s)
         }
         printf("pic: cpu_interrupt\n");
 #endif
-        qemu_irq_raise(s->parent_irq);
+        qemu_irq_raise(s->pics[0].int_out);
     } else {
-        qemu_irq_lower(s->parent_irq);
+        qemu_irq_lower(s->pics[0].int_out);
     }
 }
 
@@ -297,7 +297,7 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64,
             /* init */
             pic_reset(s);
             /* deassert a pending interrupt */
-            qemu_irq_lower(s->pics_state->parent_irq);
+            qemu_irq_lower(s->pics_state->pics[0].int_out);
             s->init_state = 1;
             s->init4 = val & 1;
             s->single_mode = val & 2;
@@ -502,8 +502,10 @@ static const MemoryRegionOps pic_elcr_ioport_ops = {
 };
 
 /* XXX: add generic master/slave system */
-static void pic_init1(int io_addr, int elcr_addr, PicState *s)
+static void pic_init(int io_addr, int elcr_addr, PicState *s, qemu_irq int_out)
 {
+    s->int_out = int_out;
+
     memory_region_init_io(&s->base_io, &pic_base_ioport_ops, s, "pic", 2);
     memory_region_init_io(&s->elcr_io, &pic_elcr_ioport_ops, s, "elcr", 1);
 
@@ -553,16 +555,17 @@ void irq_info(Monitor *mon)
 
 qemu_irq *i8259_init(qemu_irq parent_irq)
 {
+    qemu_irq *irqs;
     PicState2 *s;
 
     s = g_malloc0(sizeof(PicState2));
-    pic_init1(0x20, 0x4d0, &s->pics[0]);
-    pic_init1(0xa0, 0x4d1, &s->pics[1]);
+    irqs = qemu_allocate_irqs(i8259_set_irq, s, 16);
+    pic_init(0x20, 0x4d0, &s->pics[0], parent_irq);
+    pic_init(0xa0, 0x4d1, &s->pics[1], irqs[2]);
     s->pics[0].elcr_mask = 0xf8;
     s->pics[1].elcr_mask = 0xde;
-    s->parent_irq = parent_irq;
     s->pics[0].pics_state = s;
     s->pics[1].pics_state = s;
     isa_pic = s;
-    return qemu_allocate_irqs(i8259_set_irq, s, 16);
+    return irqs;
 }
commit 620260174abdbfaba6dbe17098c91a7d164249d3
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:40 2011 +0200

    i8259: Move pic_set_irq1 after pic_update_irq
    
    We are about to call the latter from the former. No functional changes.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index f1d58ba..de2d5ca 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -79,32 +79,6 @@ static uint64_t irq_count[16];
 #endif
 PicState2 *isa_pic;
 
-/* set irq level. If an edge is detected, then the IRR is set to 1 */
-static void pic_set_irq1(PicState *s, int irq, int level)
-{
-    int mask;
-    mask = 1 << irq;
-    if (s->elcr & mask) {
-        /* level triggered */
-        if (level) {
-            s->irr |= mask;
-            s->last_irr |= mask;
-        } else {
-            s->irr &= ~mask;
-            s->last_irr &= ~mask;
-        }
-    } else {
-        /* edge triggered */
-        if (level) {
-            if ((s->last_irr & mask) == 0)
-                s->irr |= mask;
-            s->last_irr |= mask;
-        } else {
-            s->last_irr &= ~mask;
-        }
-    }
-}
-
 /* return the highest priority found in mask (highest = smallest
    number). Return 8 if no irq */
 static int get_priority(PicState *s, int mask)
@@ -144,6 +118,8 @@ static int pic_get_irq(PicState *s)
     }
 }
 
+static void pic_set_irq1(PicState *s, int irq, int level);
+
 /* raise irq to CPU if necessary. must be called every time the active
    irq may change */
 static void pic_update_irq(PicState2 *s)
@@ -178,6 +154,33 @@ static void pic_update_irq(PicState2 *s)
     }
 }
 
+/* set irq level. If an edge is detected, then the IRR is set to 1 */
+static void pic_set_irq1(PicState *s, int irq, int level)
+{
+    int mask;
+    mask = 1 << irq;
+    if (s->elcr & mask) {
+        /* level triggered */
+        if (level) {
+            s->irr |= mask;
+            s->last_irr |= mask;
+        } else {
+            s->irr &= ~mask;
+            s->last_irr &= ~mask;
+        }
+    } else {
+        /* edge triggered */
+        if (level) {
+            if ((s->last_irr & mask) == 0) {
+                s->irr |= mask;
+            }
+            s->last_irr |= mask;
+        } else {
+            s->last_irr &= ~mask;
+        }
+    }
+}
+
 #ifdef DEBUG_IRQ_LATENCY
 int64_t irq_time[16];
 #endif
commit ef5e1ae2c120419f60d1a552998b1a8384cc2287
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:39 2011 +0200

    i8259: Drop obsolete prototypes
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.h b/hw/pc.h
index d133dc0..5d20d58 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -62,8 +62,6 @@ bool parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
 
 typedef struct PicState2 PicState2;
 extern PicState2 *isa_pic;
-void pic_set_irq(int irq, int level);
-void pic_set_irq_new(void *opaque, int irq, int level);
 qemu_irq *i8259_init(qemu_irq parent_irq);
 int pic_read_irq(PicState2 *s);
 int pic_get_output(PicState2 *s);
commit 5dcd35e276888ac556ec594640376e6318c82e3a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:38 2011 +0200

    i8259: Remove premature inline function attributes
    
    The compiler is smarter in choosing the right optimization.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/i8259.c b/hw/i8259.c
index 6006123..f1d58ba 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -80,7 +80,7 @@ static uint64_t irq_count[16];
 PicState2 *isa_pic;
 
 /* set irq level. If an edge is detected, then the IRR is set to 1 */
-static inline void pic_set_irq1(PicState *s, int irq, int level)
+static void pic_set_irq1(PicState *s, int irq, int level)
 {
     int mask;
     mask = 1 << irq;
@@ -107,7 +107,7 @@ static inline void pic_set_irq1(PicState *s, int irq, int level)
 
 /* return the highest priority found in mask (highest = smallest
    number). Return 8 if no irq */
-static inline int get_priority(PicState *s, int mask)
+static int get_priority(PicState *s, int mask)
 {
     int priority;
     if (mask == 0)
@@ -206,7 +206,7 @@ static void i8259_set_irq(void *opaque, int irq, int level)
 }
 
 /* acknowledge interrupt 'irq' */
-static inline void pic_intack(PicState *s, int irq)
+static void pic_intack(PicState *s, int irq)
 {
     if (s->auto_eoi) {
         if (s->rotate_on_auto_eoi)
commit d96e1737696974efb4566741e75a1f99920f262b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:37 2011 +0200

    pc: Fix and clean up PIC-to-APIC IRQ path
    
    The master PIC is connected to the LINTIN0 of the APICs. As the APIC
    currently does not track the state of that line, we have to ask the PIC
    to reinject its IRQ after the CPU picked up an event from the APIC.
    
    This introduces pic_get_output to read the master PIC IRQ line state
    without changing it. The APIC uses this function to decide if a PIC IRQ
    should be reinjected on apic_update_irq. This reflects better how the
    real hardware works.
    
    The patch fixes some failures of the kvm unit tests apic and eventinj by
    allowing to enable the proper CPU IRQ deassertion when the guest masks
    some pending IRQs at PIC level.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/apic.c b/hw/apic.c
index d8f56c8..8289eef 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -23,6 +23,7 @@
 #include "host-utils.h"
 #include "sysbus.h"
 #include "trace.h"
+#include "pc.h"
 
 /* APIC Local Vector Table */
 #define APIC_LVT_TIMER   0
@@ -399,6 +400,9 @@ static void apic_update_irq(APICState *s)
     }
     if (apic_irq_pending(s) > 0) {
         cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+    } else if (apic_accept_pic_intr(&s->busdev.qdev) &&
+               pic_get_output(isa_pic)) {
+        apic_deliver_pic_intr(&s->busdev.qdev, 1);
     }
 }
 
diff --git a/hw/i8259.c b/hw/i8259.c
index e5323ff..6006123 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -146,8 +146,7 @@ static int pic_get_irq(PicState *s)
 
 /* raise irq to CPU if necessary. must be called every time the active
    irq may change */
-/* XXX: should not export it, but it is needed for an APIC kludge */
-void pic_update_irq(PicState2 *s)
+static void pic_update_irq(PicState2 *s)
 {
     int irq2, irq;
 
@@ -174,14 +173,9 @@ void pic_update_irq(PicState2 *s)
         printf("pic: cpu_interrupt\n");
 #endif
         qemu_irq_raise(s->parent_irq);
-    }
-
-/* all targets should do this rather than acking the IRQ in the cpu */
-#if defined(TARGET_MIPS) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
-    else {
+    } else {
         qemu_irq_lower(s->parent_irq);
     }
-#endif
 }
 
 #ifdef DEBUG_IRQ_LATENCY
@@ -441,6 +435,11 @@ uint32_t pic_intack_read(PicState2 *s)
     return ret;
 }
 
+int pic_get_output(PicState2 *s)
+{
+    return (pic_get_irq(&s->pics[0]) >= 0);
+}
+
 static void elcr_ioport_write(void *opaque, target_phys_addr_t addr,
                               uint64_t val, unsigned size)
 {
diff --git a/hw/pc.c b/hw/pc.c
index 9b68695..f0802b7 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -155,9 +155,6 @@ int cpu_get_pic_interrupt(CPUState *env)
 
     intno = apic_get_interrupt(env->apic_state);
     if (intno >= 0) {
-        /* set irq request if a PIC irq is still pending */
-        /* XXX: improve that */
-        pic_update_irq(isa_pic);
         return intno;
     }
     /* read the irq from the PIC */
diff --git a/hw/pc.h b/hw/pc.h
index 72f8c7c..d133dc0 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -66,7 +66,7 @@ void pic_set_irq(int irq, int level);
 void pic_set_irq_new(void *opaque, int irq, int level);
 qemu_irq *i8259_init(qemu_irq parent_irq);
 int pic_read_irq(PicState2 *s);
-void pic_update_irq(PicState2 *s);
+int pic_get_output(PicState2 *s);
 uint32_t pic_intack_read(PicState2 *s);
 void pic_info(Monitor *mon);
 void irq_info(Monitor *mon);
commit 43a0db3537583b269083c8ec20dbe3388510ae54
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:36 2011 +0200

    pc: Convert GSIState::i8259_irq into array
    
    Will be required when we no longer let i8259_init allocate the PIC IRQs
    but convert that chips to qdev.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.h b/hw/pc.h
index 558d9a5..72f8c7c 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -76,7 +76,7 @@ void irq_info(Monitor *mon);
 #define GSI_NUM_PINS IOAPIC_NUM_PINS
 
 typedef struct GSIState {
-    qemu_irq *i8259_irq;
+    qemu_irq i8259_irq[ISA_NUM_IRQS];
     qemu_irq ioapic_irq[IOAPIC_NUM_PINS];
 } GSIState;
 
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index e6e280c..c89042f 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -158,7 +158,9 @@ static void pc_init1(MemoryRegion *system_memory,
         i8259 = xen_interrupt_controller_init();
     }
 
-    gsi_state->i8259_irq = i8259;
+    for (i = 0; i < ISA_NUM_IRQS; i++) {
+        gsi_state->i8259_irq[i] = i8259[i];
+    }
     if (pci_enabled) {
         ioapic_init(gsi_state);
     }
commit b881fbe9f7a60ceaef20b7a234c49473d009bf4d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:35 2011 +0200

    pc: Generalize ISA IRQs to GSIs
    
    The ISA bus IRQ range is 0..15. What isa_irq_handler and IsaIrqState are
    actually dealing with are the Global System Interrupts. Refactor the
    code to clarify this.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/ioapic.h b/hw/ioapic.h
index cb2642a..86e63da 100644
--- a/hw/ioapic.h
+++ b/hw/ioapic.h
@@ -17,4 +17,11 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifndef HW_IOAPIC_H
+#define HW_IOAPIC_H
+
+#define IOAPIC_NUM_PINS 24
+
 void ioapic_eoi_broadcast(int vector);
+
+#endif /* !HW_IOAPIC_H */
diff --git a/hw/isa.h b/hw/isa.h
index d3cae35..5eb9c78 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -7,6 +7,8 @@
 #include "memory.h"
 #include "qdev.h"
 
+#define ISA_NUM_IRQS 16
+
 typedef struct ISABus ISABus;
 typedef struct ISADevice ISADevice;
 typedef struct ISADeviceInfo ISADeviceInfo;
diff --git a/hw/pc.c b/hw/pc.c
index ff081d9..9b68695 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -88,15 +88,15 @@ struct e820_table {
 static struct e820_table e820_table;
 struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
 
-void isa_irq_handler(void *opaque, int n, int level)
+void gsi_handler(void *opaque, int n, int level)
 {
-    IsaIrqState *isa = (IsaIrqState *)opaque;
+    GSIState *s = opaque;
 
-    DPRINTF("isa_irqs: %s irq %d\n", level? "raise" : "lower", n);
-    if (n < 16) {
-        qemu_set_irq(isa->i8259[n], level);
+    DPRINTF("pc: %s GSI %d\n", level ? "raising" : "lowering", n);
+    if (n < ISA_NUM_IRQS) {
+        qemu_set_irq(s->i8259_irq[n], level);
     }
-    qemu_set_irq(isa->ioapic[n], level);
+    qemu_set_irq(s->ioapic_irq[n], level);
 }
 
 static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
@@ -1125,7 +1125,7 @@ static void cpu_request_exit(void *opaque, int irq, int level)
     }
 }
 
-void pc_basic_device_init(qemu_irq *isa_irq,
+void pc_basic_device_init(qemu_irq *gsi,
                           ISADevice **rtc_state,
                           bool no_vmport)
 {
@@ -1144,8 +1144,8 @@ void pc_basic_device_init(qemu_irq *isa_irq,
         DeviceState *hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
 
         if (hpet) {
-            for (i = 0; i < 24; i++) {
-                sysbus_connect_irq(sysbus_from_qdev(hpet), i, isa_irq[i]);
+            for (i = 0; i < GSI_NUM_PINS; i++) {
+                sysbus_connect_irq(sysbus_from_qdev(hpet), i, gsi[i]);
             }
             rtc_irq = qdev_get_gpio_in(hpet, 0);
         }
diff --git a/hw/pc.h b/hw/pc.h
index f3e21b6..558d9a5 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -8,6 +8,7 @@
 #include "fdc.h"
 #include "net.h"
 #include "memory.h"
+#include "ioapic.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -70,15 +71,16 @@ uint32_t pic_intack_read(PicState2 *s);
 void pic_info(Monitor *mon);
 void irq_info(Monitor *mon);
 
-/* ISA */
-#define IOAPIC_NUM_PINS 0x18
+/* Global System Interrupts */
 
-typedef struct isa_irq_state {
-    qemu_irq *i8259;
-    qemu_irq ioapic[IOAPIC_NUM_PINS];
-} IsaIrqState;
+#define GSI_NUM_PINS IOAPIC_NUM_PINS
 
-void isa_irq_handler(void *opaque, int n, int level);
+typedef struct GSIState {
+    qemu_irq *i8259_irq;
+    qemu_irq ioapic_irq[IOAPIC_NUM_PINS];
+} GSIState;
+
+void gsi_handler(void *opaque, int n, int level);
 
 /* i8254.c */
 
@@ -141,7 +143,7 @@ void pc_memory_init(MemoryRegion *system_memory,
                     MemoryRegion **ram_memory);
 qemu_irq *pc_allocate_cpu_irq(void);
 void pc_vga_init(PCIBus *pci_bus);
-void pc_basic_device_init(qemu_irq *isa_irq,
+void pc_basic_device_init(qemu_irq *gsi,
                           ISADevice **rtc_state,
                           bool no_vmport);
 void pc_init_ne2k_isa(NICInfo *nd);
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index ce1c87f..e6e280c 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -53,7 +53,7 @@ static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
 static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
 static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
 
-static void ioapic_init(IsaIrqState *isa_irq_state)
+static void ioapic_init(GSIState *gsi_state)
 {
     DeviceState *dev;
     SysBusDevice *d;
@@ -65,7 +65,7 @@ static void ioapic_init(IsaIrqState *isa_irq_state)
     sysbus_mmio_map(d, 0, 0xfec00000);
 
     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
-        isa_irq_state->ioapic[i] = qdev_get_gpio_in(dev, i);
+        gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
     }
 }
 
@@ -87,11 +87,11 @@ static void pc_init1(MemoryRegion *system_memory,
     PCII440FXState *i440fx_state;
     int piix3_devfn = -1;
     qemu_irq *cpu_irq;
-    qemu_irq *isa_irq;
+    qemu_irq *gsi;
     qemu_irq *i8259;
     qemu_irq *cmos_s3;
     qemu_irq *smi_irq;
-    IsaIrqState *isa_irq_state;
+    GSIState *gsi_state;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BusState *idebus[MAX_IDE_BUS];
     ISADevice *rtc_state;
@@ -130,11 +130,11 @@ static void pc_init1(MemoryRegion *system_memory,
                        pci_enabled ? rom_memory : system_memory, &ram_memory);
     }
 
-    isa_irq_state = g_malloc0(sizeof(*isa_irq_state));
-    isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
+    gsi_state = g_malloc0(sizeof(*gsi_state));
+    gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
 
     if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq,
+        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, gsi,
                               system_memory, system_io, ram_size,
                               below_4g_mem_size,
                               0x100000000ULL - below_4g_mem_size,
@@ -149,7 +149,7 @@ static void pc_init1(MemoryRegion *system_memory,
         isa_bus_new(NULL, system_io);
         no_hpet = 1;
     }
-    isa_bus_irqs(isa_irq);
+    isa_bus_irqs(gsi);
 
     if (!xen_enabled()) {
         cpu_irq = pc_allocate_cpu_irq();
@@ -158,12 +158,12 @@ static void pc_init1(MemoryRegion *system_memory,
         i8259 = xen_interrupt_controller_init();
     }
 
-    isa_irq_state->i8259 = i8259;
+    gsi_state->i8259_irq = i8259;
     if (pci_enabled) {
-        ioapic_init(isa_irq_state);
+        ioapic_init(gsi_state);
     }
 
-    pc_register_ferr_irq(isa_get_irq(13));
+    pc_register_ferr_irq(gsi[13]);
 
     pc_vga_init(pci_enabled? pci_bus: NULL);
 
@@ -172,7 +172,7 @@ static void pc_init1(MemoryRegion *system_memory,
     }
 
     /* init basic PC hardware */
-    pc_basic_device_init(isa_irq, &rtc_state, xen_enabled());
+    pc_basic_device_init(gsi, &rtc_state, xen_enabled());
 
     for(i = 0; i < nb_nics; i++) {
         NICInfo *nd = &nd_table[i];
@@ -202,7 +202,7 @@ static void pc_init1(MemoryRegion *system_memory,
         }
     }
 
-    audio_init(isa_irq, pci_enabled ? pci_bus : NULL);
+    audio_init(gsi, pci_enabled ? pci_bus : NULL);
 
     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
                  idebus[0], idebus[1], rtc_state);
@@ -222,7 +222,7 @@ static void pc_init1(MemoryRegion *system_memory,
         smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
         /* TODO: Populate SPD eeprom data.  */
         smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
-                              isa_get_irq(9), *cmos_s3, *smi_irq,
+                              gsi[9], *cmos_s3, *smi_irq,
                               kvm_enabled());
         smbus_eeprom_init(smbus, 8, NULL, 0);
     }
commit 2e9947d2eaf1e9cbeb22ff15064bc70e7c9afe1e
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Oct 7 09:19:34 2011 +0200

    pc: Drop useless test from isa_irq_handler
    
    IsaIrqState::ioapic is always non-NULL. Probably, the concrete
    qemu_irq was supposed to be tested, but that's already done by
    qemu_set_irq.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index ded4758..ff081d9 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -96,9 +96,8 @@ void isa_irq_handler(void *opaque, int n, int level)
     if (n < 16) {
         qemu_set_irq(isa->i8259[n], level);
     }
-    if (isa->ioapic)
-        qemu_set_irq(isa->ioapic[n], level);
-};
+    qemu_set_irq(isa->ioapic[n], level);
+}
 
 static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
 {
commit 0200db650e6386d44ba2a707d9f22ddf72681cf7
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Oct 16 02:56:46 2011 +0400

    target-xtensa: add Avnet LX60/LX110/LX200 boards
    
    These boards carry similar hardware: SDRAM (48M for LX110, 64M for LX60,
    96M for LX200), 16 Mbyte FLASH, FPGA, 10/100 Mbps Ethernet PHY and 16550
    UART. FPGA may be loaded with almost any Tensilica processor. It is also
    used to implement Ethernet MAC, e.g. OpenCores 10/100 Mbps Ethernet MAC
    and LED/DIP switches access.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 752221c..3d94228 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -371,6 +371,7 @@ obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
 
 obj-xtensa-y += xtensa_pic.o
 obj-xtensa-y += xtensa_sim.o
+obj-xtensa-y += xtensa_lx60.o
 obj-xtensa-y += xtensa-semi.o
 obj-xtensa-y += core-dc232b.o
 obj-xtensa-y += core-fsf.o
diff --git a/default-configs/xtensa-softmmu.mak b/default-configs/xtensa-softmmu.mak
index e5faa09..7f0df34 100644
--- a/default-configs/xtensa-softmmu.mak
+++ b/default-configs/xtensa-softmmu.mak
@@ -1 +1,4 @@
 # Default configuration for Xtensa
+
+CONFIG_SERIAL=y
+CONFIG_OPENCORES_ETH=y
diff --git a/default-configs/xtensaeb-softmmu.mak b/default-configs/xtensaeb-softmmu.mak
index e5faa09..7f0df34 100644
--- a/default-configs/xtensaeb-softmmu.mak
+++ b/default-configs/xtensaeb-softmmu.mak
@@ -1 +1,4 @@
 # Default configuration for Xtensa
+
+CONFIG_SERIAL=y
+CONFIG_OPENCORES_ETH=y
diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
new file mode 100644
index 0000000..3cebca1
--- /dev/null
+++ b/hw/xtensa_lx60.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sysemu.h"
+#include "boards.h"
+#include "loader.h"
+#include "elf.h"
+#include "memory.h"
+#include "exec-memory.h"
+#include "pc.h"
+#include "sysbus.h"
+
+typedef struct Lx60FpgaState {
+    MemoryRegion iomem;
+    uint32_t leds;
+    uint32_t switches;
+} Lx60FpgaState;
+
+static void lx60_fpga_reset(void *opaque)
+{
+    Lx60FpgaState *s = opaque;
+
+    s->leds = 0;
+    s->switches = 0;
+}
+
+static uint64_t lx60_fpga_read(void *opaque, target_phys_addr_t addr,
+        unsigned size)
+{
+    Lx60FpgaState *s = opaque;
+
+    switch (addr) {
+    case 0x0: /*build date code*/
+        return 0x27092011;
+
+    case 0x4: /*processor clock frequency, Hz*/
+        return 10000000;
+
+    case 0x8: /*LEDs (off = 0, on = 1)*/
+        return s->leds;
+
+    case 0xc: /*DIP switches (off = 0, on = 1)*/
+        return s->switches;
+    }
+    return 0;
+}
+
+static void lx60_fpga_write(void *opaque, target_phys_addr_t addr,
+        uint64_t val, unsigned size)
+{
+    Lx60FpgaState *s = opaque;
+
+    switch (addr) {
+    case 0x8: /*LEDs (off = 0, on = 1)*/
+        s->leds = val;
+        break;
+
+    case 0x10: /*board reset*/
+        if (val == 0xdead) {
+            qemu_system_reset_request();
+        }
+        break;
+    }
+}
+
+static const MemoryRegionOps lx60_fpga_ops = {
+    .read = lx60_fpga_read,
+    .write = lx60_fpga_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space,
+        target_phys_addr_t base)
+{
+    Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState));
+
+    memory_region_init_io(&s->iomem, &lx60_fpga_ops, s,
+            "lx60-fpga", 0x10000);
+    memory_region_add_subregion(address_space, base, &s->iomem);
+    lx60_fpga_reset(s);
+    qemu_register_reset(lx60_fpga_reset, s);
+    return s;
+}
+
+static void lx60_net_init(MemoryRegion *address_space,
+        target_phys_addr_t base,
+        target_phys_addr_t descriptors,
+        target_phys_addr_t buffers,
+        qemu_irq irq, NICInfo *nd)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    MemoryRegion *ram;
+
+    dev = qdev_create(NULL, "open_eth");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+
+    s = sysbus_from_qdev(dev);
+    sysbus_connect_irq(s, 0, irq);
+    memory_region_add_subregion(address_space, base,
+            sysbus_mmio_get_region(s, 0));
+    memory_region_add_subregion(address_space, descriptors,
+            sysbus_mmio_get_region(s, 1));
+
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, NULL, "open_eth.ram", 16384);
+    memory_region_add_subregion(address_space, buffers, ram);
+}
+
+static uint64_t translate_phys_addr(void *env, uint64_t addr)
+{
+    return cpu_get_phys_page_debug(env, addr);
+}
+
+static void lx60_reset(void *env)
+{
+    cpu_reset(env);
+}
+
+static void lx60_init(ram_addr_t ram_size,
+        const char *boot_device,
+        const char *kernel_filename, const char *kernel_cmdline,
+        const char *initrd_filename, const char *cpu_model)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    int be = 1;
+#else
+    int be = 0;
+#endif
+    MemoryRegion *system_memory = get_system_memory();
+    CPUState *env = NULL;
+    MemoryRegion *ram, *rom, *system_io;
+    int n;
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        env->sregs[PRID] = n;
+        qemu_register_reset(lx60_reset, env);
+        /* Need MMU initialized prior to ELF loading,
+         * so that ELF gets loaded into virtual addresses
+         */
+        cpu_reset(env);
+    }
+
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size);
+    memory_region_add_subregion(system_memory, 0, ram);
+
+    rom = g_malloc(sizeof(*rom));
+    memory_region_init_ram(rom, NULL, "xtensa.rom", 0x1000);
+    memory_region_add_subregion(system_memory, 0xfe000000, rom);
+
+    system_io = g_malloc(sizeof(*system_io));
+    memory_region_init(system_io, "system.io", 224 * 1024 * 1024);
+    memory_region_add_subregion(system_memory, 0xf0000000, system_io);
+    lx60_fpga_init(system_io, 0x0d020000);
+    if (nd_table[0].vlan) {
+        lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000,
+                xtensa_get_extint(env, 1), nd_table);
+    }
+
+    if (!serial_hds[0]) {
+        serial_hds[0] = qemu_chr_new("serial0", "null", NULL);
+    }
+
+    serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0),
+            115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+
+    if (kernel_filename) {
+        uint64_t elf_entry;
+        uint64_t elf_lowaddr;
+        int success = load_elf(kernel_filename, translate_phys_addr, env,
+                &elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0);
+        if (success > 0) {
+            env->pc = elf_entry;
+        }
+    }
+}
+
+static void xtensa_lx60_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    if (!cpu_model) {
+        cpu_model = "dc232b";
+    }
+    lx60_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
+            initrd_filename, cpu_model);
+}
+
+static QEMUMachine xtensa_lx60_machine = {
+    .name = "lx60",
+    .desc = "lx60 EVB (dc232b)",
+    .init = xtensa_lx60_init,
+    .max_cpus = 4,
+};
+
+static void xtensa_lx60_machine_init(void)
+{
+    qemu_register_machine(&xtensa_lx60_machine);
+}
+
+machine_init(xtensa_lx60_machine_init);
commit 342407fd958f8f5546527e6fecaa501700fb03e5
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Oct 16 02:56:45 2011 +0400

    hw: add OpenCores 10/100 Mbps Ethernet controller
    
    This is OpenCores Ethernet MAC + subset of National Semiconductors
    DP83838C PHY.
    OpenCores Ethernet MAC project: http://opencores.org/project,ethmac
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 6424efd..b839c8e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -258,6 +258,7 @@ hw-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
 hw-obj-$(CONFIG_SMC91C111) += smc91c111.o
 hw-obj-$(CONFIG_LAN9118) += lan9118.o
 hw-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o
+hw-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o
 
 # IDE
 hw-obj-$(CONFIG_IDE_CORE) += ide/core.o ide/atapi.o
diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c
new file mode 100644
index 0000000..64b616e
--- /dev/null
+++ b/hw/opencores_eth.c
@@ -0,0 +1,728 @@
+/*
+ * OpenCores Ethernet MAC 10/100 + subset of
+ * National Semiconductors DP83848C 10/100 PHY
+ *
+ * http://opencores.org/svnget,ethmac?file=%2Ftrunk%2F%2Fdoc%2Feth_speci.pdf
+ * http://cache.national.com/ds/DP/DP83848C.pdf
+ *
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "hw.h"
+#include "sysbus.h"
+#include "net.h"
+#include "sysemu.h"
+#include "trace.h"
+
+/* RECSMALL is not used because it breaks tap networking in linux:
+ * incoming ARP responses are too short
+ */
+#undef USE_RECSMALL
+
+#define GET_FIELD(v, field) (((v) & (field)) >> (field ## _LBN))
+#define GET_REGBIT(s, reg, field) ((s)->regs[reg] & (reg ## _ ## field))
+#define GET_REGFIELD(s, reg, field) \
+    GET_FIELD((s)->regs[reg], reg ## _ ## field)
+
+#define SET_FIELD(v, field, data) \
+    ((v) = (((v) & ~(field)) | (((data) << (field ## _LBN)) & (field))))
+#define SET_REGFIELD(s, reg, field, data) \
+    SET_FIELD((s)->regs[reg], reg ## _ ## field, data)
+
+/* PHY MII registers */
+enum {
+    MII_BMCR,
+    MII_BMSR,
+    MII_PHYIDR1,
+    MII_PHYIDR2,
+    MII_ANAR,
+    MII_ANLPAR,
+    MII_REG_MAX = 16,
+};
+
+typedef struct Mii {
+    uint16_t regs[MII_REG_MAX];
+    bool link_ok;
+} Mii;
+
+static void mii_set_link(Mii *s, bool link_ok)
+{
+    if (link_ok) {
+        s->regs[MII_BMSR] |= 0x4;
+        s->regs[MII_ANLPAR] |= 0x01e1;
+    } else {
+        s->regs[MII_BMSR] &= ~0x4;
+        s->regs[MII_ANLPAR] &= 0x01ff;
+    }
+    s->link_ok = link_ok;
+}
+
+static void mii_reset(Mii *s)
+{
+    memset(s->regs, 0, sizeof(s->regs));
+    s->regs[MII_BMCR] = 0x1000;
+    s->regs[MII_BMSR] = 0x7848; /* no ext regs */
+    s->regs[MII_PHYIDR1] = 0x2000;
+    s->regs[MII_PHYIDR2] = 0x5c90;
+    s->regs[MII_ANAR] = 0x01e1;
+    mii_set_link(s, s->link_ok);
+}
+
+static void mii_ro(Mii *s, uint16_t v)
+{
+}
+
+static void mii_write_bmcr(Mii *s, uint16_t v)
+{
+    if (v & 0x8000) {
+        mii_reset(s);
+    } else {
+        s->regs[MII_BMCR] = v;
+    }
+}
+
+static void mii_write_host(Mii *s, unsigned idx, uint16_t v)
+{
+    static void (*reg_write[MII_REG_MAX])(Mii *s, uint16_t v) = {
+        [MII_BMCR] = mii_write_bmcr,
+        [MII_BMSR] = mii_ro,
+        [MII_PHYIDR1] = mii_ro,
+        [MII_PHYIDR2] = mii_ro,
+    };
+
+    if (idx < MII_REG_MAX) {
+        trace_open_eth_mii_write(idx, v);
+        if (reg_write[idx]) {
+            reg_write[idx](s, v);
+        } else {
+            s->regs[idx] = v;
+        }
+    }
+}
+
+static uint16_t mii_read_host(Mii *s, unsigned idx)
+{
+    trace_open_eth_mii_read(idx, s->regs[idx]);
+    return s->regs[idx];
+}
+
+/* OpenCores Ethernet registers */
+enum {
+    MODER,
+    INT_SOURCE,
+    INT_MASK,
+    IPGT,
+    IPGR1,
+    IPGR2,
+    PACKETLEN,
+    COLLCONF,
+    TX_BD_NUM,
+    CTRLMODER,
+    MIIMODER,
+    MIICOMMAND,
+    MIIADDRESS,
+    MIITX_DATA,
+    MIIRX_DATA,
+    MIISTATUS,
+    MAC_ADDR0,
+    MAC_ADDR1,
+    HASH0,
+    HASH1,
+    TXCTRL,
+    REG_MAX,
+};
+
+enum {
+    MODER_RECSMALL = 0x10000,
+    MODER_PAD = 0x8000,
+    MODER_HUGEN = 0x4000,
+    MODER_RST = 0x800,
+    MODER_LOOPBCK = 0x80,
+    MODER_PRO = 0x20,
+    MODER_IAM = 0x10,
+    MODER_BRO = 0x8,
+    MODER_TXEN = 0x2,
+    MODER_RXEN = 0x1,
+};
+
+enum {
+    INT_SOURCE_RXB = 0x4,
+    INT_SOURCE_TXB = 0x1,
+};
+
+enum {
+    PACKETLEN_MINFL = 0xffff0000,
+    PACKETLEN_MINFL_LBN = 16,
+    PACKETLEN_MAXFL = 0xffff,
+    PACKETLEN_MAXFL_LBN = 0,
+};
+
+enum {
+    MIICOMMAND_WCTRLDATA = 0x4,
+    MIICOMMAND_RSTAT = 0x2,
+    MIICOMMAND_SCANSTAT = 0x1,
+};
+
+enum {
+    MIIADDRESS_RGAD = 0x1f00,
+    MIIADDRESS_RGAD_LBN = 8,
+    MIIADDRESS_FIAD = 0x1f,
+    MIIADDRESS_FIAD_LBN = 0,
+};
+
+enum {
+    MIITX_DATA_CTRLDATA = 0xffff,
+    MIITX_DATA_CTRLDATA_LBN = 0,
+};
+
+enum {
+    MIIRX_DATA_PRSD = 0xffff,
+    MIIRX_DATA_PRSD_LBN = 0,
+};
+
+enum {
+    MIISTATUS_LINKFAIL = 0x1,
+    MIISTATUS_LINKFAIL_LBN = 0,
+};
+
+enum {
+    MAC_ADDR0_BYTE2 = 0xff000000,
+    MAC_ADDR0_BYTE2_LBN = 24,
+    MAC_ADDR0_BYTE3 = 0xff0000,
+    MAC_ADDR0_BYTE3_LBN = 16,
+    MAC_ADDR0_BYTE4 = 0xff00,
+    MAC_ADDR0_BYTE4_LBN = 8,
+    MAC_ADDR0_BYTE5 = 0xff,
+    MAC_ADDR0_BYTE5_LBN = 0,
+};
+
+enum {
+    MAC_ADDR1_BYTE0 = 0xff00,
+    MAC_ADDR1_BYTE0_LBN = 8,
+    MAC_ADDR1_BYTE1 = 0xff,
+    MAC_ADDR1_BYTE1_LBN = 0,
+};
+
+enum {
+    TXD_LEN = 0xffff0000,
+    TXD_LEN_LBN = 16,
+    TXD_RD = 0x8000,
+    TXD_IRQ = 0x4000,
+    TXD_WR = 0x2000,
+    TXD_PAD = 0x1000,
+    TXD_CRC = 0x800,
+    TXD_UR = 0x100,
+    TXD_RTRY = 0xf0,
+    TXD_RTRY_LBN = 4,
+    TXD_RL = 0x8,
+    TXD_LC = 0x4,
+    TXD_DF = 0x2,
+    TXD_CS = 0x1,
+};
+
+enum {
+    RXD_LEN = 0xffff0000,
+    RXD_LEN_LBN = 16,
+    RXD_E = 0x8000,
+    RXD_IRQ = 0x4000,
+    RXD_WRAP = 0x2000,
+    RXD_CF = 0x100,
+    RXD_M = 0x80,
+    RXD_OR = 0x40,
+    RXD_IS = 0x20,
+    RXD_DN = 0x10,
+    RXD_TL = 0x8,
+    RXD_SF = 0x4,
+    RXD_CRC = 0x2,
+    RXD_LC = 0x1,
+};
+
+typedef struct desc {
+    uint32_t len_flags;
+    uint32_t buf_ptr;
+} desc;
+
+#define DEFAULT_PHY 1
+
+typedef struct OpenEthState {
+    SysBusDevice dev;
+    NICState *nic;
+    NICConf conf;
+    MemoryRegion reg_io;
+    MemoryRegion desc_io;
+    qemu_irq irq;
+
+    Mii mii;
+    uint32_t regs[REG_MAX];
+    unsigned tx_desc;
+    unsigned rx_desc;
+    desc desc[128];
+} OpenEthState;
+
+static desc *rx_desc(OpenEthState *s)
+{
+    return s->desc + s->rx_desc;
+}
+
+static desc *tx_desc(OpenEthState *s)
+{
+    return s->desc + s->tx_desc;
+}
+
+static void open_eth_update_irq(OpenEthState *s,
+        uint32_t old, uint32_t new)
+{
+    if (!old != !new) {
+        trace_open_eth_update_irq(new);
+        qemu_set_irq(s->irq, new);
+    }
+}
+
+static void open_eth_int_source_write(OpenEthState *s,
+        uint32_t val)
+{
+    uint32_t old_val = s->regs[INT_SOURCE];
+
+    s->regs[INT_SOURCE] = val;
+    open_eth_update_irq(s, old_val & s->regs[INT_MASK],
+            s->regs[INT_SOURCE] & s->regs[INT_MASK]);
+}
+
+static void open_eth_set_link_status(VLANClientState *nc)
+{
+    OpenEthState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    if (GET_REGBIT(s, MIICOMMAND, SCANSTAT)) {
+        SET_REGFIELD(s, MIISTATUS, LINKFAIL, nc->link_down);
+    }
+    mii_set_link(&s->mii, !nc->link_down);
+}
+
+static void open_eth_reset(void *opaque)
+{
+    OpenEthState *s = opaque;
+
+    memset(s->regs, 0, sizeof(s->regs));
+    s->regs[MODER] = 0xa000;
+    s->regs[IPGT] = 0x12;
+    s->regs[IPGR1] = 0xc;
+    s->regs[IPGR2] = 0x12;
+    s->regs[PACKETLEN] = 0x400600;
+    s->regs[COLLCONF] = 0xf003f;
+    s->regs[TX_BD_NUM] = 0x40;
+    s->regs[MIIMODER] = 0x64;
+
+    s->tx_desc = 0;
+    s->rx_desc = 0x40;
+
+    mii_reset(&s->mii);
+    open_eth_set_link_status(&s->nic->nc);
+}
+
+static int open_eth_can_receive(VLANClientState *nc)
+{
+    OpenEthState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    return GET_REGBIT(s, MODER, RXEN) &&
+        (s->regs[TX_BD_NUM] < 0x80) &&
+        (rx_desc(s)->len_flags & RXD_E);
+}
+
+#define POLYNOMIAL 0x04c11db6
+
+/* From FreeBSD */
+/* XXX: optimize */
+static unsigned compute_mcast_idx(const uint8_t *ep)
+{
+    uint32_t crc;
+    int carry, i, j;
+    uint8_t b;
+
+    crc = 0xffffffff;
+    for (i = 0; i < 6; i++) {
+        b = *ep++;
+        for (j = 0; j < 8; j++) {
+            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
+            crc <<= 1;
+            b >>= 1;
+            if (carry) {
+                crc = ((crc ^ POLYNOMIAL) | carry);
+            }
+        }
+    }
+    return crc >> 26;
+}
+
+static ssize_t open_eth_receive(VLANClientState *nc,
+        const uint8_t *buf, size_t size)
+{
+    OpenEthState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    size_t maxfl = GET_REGFIELD(s, PACKETLEN, MAXFL);
+    size_t minfl = GET_REGFIELD(s, PACKETLEN, MINFL);
+    bool miss = true;
+
+    trace_open_eth_receive((unsigned)size);
+
+    if (size >= 6) {
+        static const uint8_t bcast_addr[] = {
+            0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+        };
+        if (memcmp(buf, bcast_addr, sizeof(bcast_addr)) == 0) {
+            miss = GET_REGBIT(s, MODER, BRO);
+        } else if ((buf[0] & 0x1) || GET_REGBIT(s, MODER, IAM)) {
+            unsigned mcast_idx = compute_mcast_idx(buf);
+            miss = !(s->regs[HASH0 + mcast_idx / 32] &
+                    (1 << (mcast_idx % 32)));
+            trace_open_eth_receive_mcast(
+                    mcast_idx, s->regs[HASH0], s->regs[HASH1]);
+        } else {
+            miss = GET_REGFIELD(s, MAC_ADDR1, BYTE0) != buf[0] ||
+                GET_REGFIELD(s, MAC_ADDR1, BYTE1) != buf[1] ||
+                GET_REGFIELD(s, MAC_ADDR0, BYTE2) != buf[2] ||
+                GET_REGFIELD(s, MAC_ADDR0, BYTE3) != buf[3] ||
+                GET_REGFIELD(s, MAC_ADDR0, BYTE4) != buf[4] ||
+                GET_REGFIELD(s, MAC_ADDR0, BYTE5) != buf[5];
+        }
+    }
+
+    if (miss && !GET_REGBIT(s, MODER, PRO)) {
+        trace_open_eth_receive_reject();
+        return size;
+    }
+
+#ifdef USE_RECSMALL
+    if (GET_REGBIT(s, MODER, RECSMALL) || size >= minfl) {
+#else
+    {
+#endif
+        desc *desc = rx_desc(s);
+        size_t copy_size = GET_REGBIT(s, MODER, HUGEN) ? 65536 : maxfl;
+
+        desc->len_flags &= ~(RXD_CF | RXD_M | RXD_OR |
+                RXD_IS | RXD_DN | RXD_TL | RXD_SF | RXD_CRC | RXD_LC);
+
+        if (copy_size > size) {
+            copy_size = size;
+        }
+        if (miss) {
+            desc->len_flags |= RXD_M;
+        }
+        if (size > maxfl) {
+            desc->len_flags |= RXD_TL;
+        }
+#ifdef USE_RECSMALL
+        if (size < minfl) {
+            desc->len_flags |= RXD_SF;
+        }
+#endif
+
+        cpu_physical_memory_write(desc->buf_ptr, buf, copy_size);
+
+        if (GET_REGBIT(s, MODER, PAD) && copy_size < minfl) {
+            static const uint8_t zero[65536] = {0};
+
+            cpu_physical_memory_write(desc->buf_ptr + copy_size,
+                    zero, minfl - copy_size);
+            copy_size = minfl;
+        }
+
+        SET_FIELD(desc->len_flags, RXD_LEN, copy_size);
+
+        if ((desc->len_flags & RXD_WRAP) || s->rx_desc == 0x7f) {
+            s->rx_desc = s->regs[TX_BD_NUM];
+        } else {
+            ++s->rx_desc;
+        }
+        desc->len_flags &= ~RXD_E;
+
+        trace_open_eth_receive_desc(desc->buf_ptr, desc->len_flags);
+
+        if (desc->len_flags & RXD_IRQ) {
+            open_eth_int_source_write(s,
+                    s->regs[INT_SOURCE] | INT_SOURCE_RXB);
+        }
+    }
+    return size;
+}
+
+static void open_eth_cleanup(VLANClientState *nc)
+{
+}
+
+static NetClientInfo net_open_eth_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = open_eth_can_receive,
+    .receive = open_eth_receive,
+    .cleanup = open_eth_cleanup,
+    .link_status_changed = open_eth_set_link_status,
+};
+
+static void open_eth_start_xmit(OpenEthState *s, desc *tx)
+{
+    uint8_t buf[65536];
+    unsigned len = GET_FIELD(tx->len_flags, TXD_LEN);
+    unsigned tx_len = len;
+
+    if ((tx->len_flags & TXD_PAD) &&
+            tx_len < GET_REGFIELD(s, PACKETLEN, MINFL)) {
+        tx_len = GET_REGFIELD(s, PACKETLEN, MINFL);
+    }
+    if (!GET_REGBIT(s, MODER, HUGEN) &&
+            tx_len > GET_REGFIELD(s, PACKETLEN, MAXFL)) {
+        tx_len = GET_REGFIELD(s, PACKETLEN, MAXFL);
+    }
+
+    trace_open_eth_start_xmit(tx->buf_ptr, len, tx_len);
+
+    if (len > tx_len) {
+        len = tx_len;
+    }
+    cpu_physical_memory_read(tx->buf_ptr, buf, len);
+    if (tx_len > len) {
+        memset(buf + len, 0, tx_len - len);
+    }
+    qemu_send_packet(&s->nic->nc, buf, tx_len);
+
+    if (tx->len_flags & TXD_WR) {
+        s->tx_desc = 0;
+    } else {
+        ++s->tx_desc;
+        if (s->tx_desc >= s->regs[TX_BD_NUM]) {
+            s->tx_desc = 0;
+        }
+    }
+    tx->len_flags &= ~(TXD_RD | TXD_UR |
+            TXD_RTRY | TXD_RL | TXD_LC | TXD_DF | TXD_CS);
+    if (tx->len_flags & TXD_IRQ) {
+        open_eth_int_source_write(s, s->regs[INT_SOURCE] | INT_SOURCE_TXB);
+    }
+
+}
+
+static void open_eth_check_start_xmit(OpenEthState *s)
+{
+    desc *tx = tx_desc(s);
+    if (GET_REGBIT(s, MODER, TXEN) && s->regs[TX_BD_NUM] > 0 &&
+            (tx->len_flags & TXD_RD) &&
+            GET_FIELD(tx->len_flags, TXD_LEN) > 4) {
+        open_eth_start_xmit(s, tx);
+    }
+}
+
+static uint64_t open_eth_reg_read(void *opaque,
+        target_phys_addr_t addr, unsigned int size)
+{
+    static uint32_t (*reg_read[REG_MAX])(OpenEthState *s) = {
+    };
+    OpenEthState *s = opaque;
+    unsigned idx = addr / 4;
+    uint64_t v = 0;
+
+    if (idx < REG_MAX) {
+        if (reg_read[idx]) {
+            v = reg_read[idx](s);
+        } else {
+            v = s->regs[idx];
+        }
+    }
+    trace_open_eth_reg_read((uint32_t)addr, (uint32_t)v);
+    return v;
+}
+
+static void open_eth_ro(OpenEthState *s, uint32_t val)
+{
+}
+
+static void open_eth_moder_host_write(OpenEthState *s, uint32_t val)
+{
+    uint32_t set = val & ~s->regs[MODER];
+
+    if (set & MODER_RST) {
+        open_eth_reset(s);
+    }
+
+    s->regs[MODER] = val;
+
+    if (set & MODER_RXEN) {
+        s->rx_desc = s->regs[TX_BD_NUM];
+    }
+    if (set & MODER_TXEN) {
+        s->tx_desc = 0;
+        open_eth_check_start_xmit(s);
+    }
+}
+
+static void open_eth_int_source_host_write(OpenEthState *s, uint32_t val)
+{
+    uint32_t old = s->regs[INT_SOURCE];
+
+    s->regs[INT_SOURCE] &= ~val;
+    open_eth_update_irq(s, old & s->regs[INT_MASK],
+            s->regs[INT_SOURCE] & s->regs[INT_MASK]);
+}
+
+static void open_eth_int_mask_host_write(OpenEthState *s, uint32_t val)
+{
+    uint32_t old = s->regs[INT_MASK];
+
+    s->regs[INT_MASK] = val;
+    open_eth_update_irq(s, s->regs[INT_SOURCE] & old,
+            s->regs[INT_SOURCE] & s->regs[INT_MASK]);
+}
+
+static void open_eth_mii_command_host_write(OpenEthState *s, uint32_t val)
+{
+    unsigned fiad = GET_REGFIELD(s, MIIADDRESS, FIAD);
+    unsigned rgad = GET_REGFIELD(s, MIIADDRESS, RGAD);
+
+    if (val & MIICOMMAND_WCTRLDATA) {
+        if (fiad == DEFAULT_PHY) {
+            mii_write_host(&s->mii, rgad,
+                    GET_REGFIELD(s, MIITX_DATA, CTRLDATA));
+        }
+    }
+    if (val & MIICOMMAND_RSTAT) {
+        if (fiad == DEFAULT_PHY) {
+            SET_REGFIELD(s, MIIRX_DATA, PRSD,
+                    mii_read_host(&s->mii, rgad));
+        } else {
+            s->regs[MIIRX_DATA] = 0xffff;
+        }
+        SET_REGFIELD(s, MIISTATUS, LINKFAIL, s->nic->nc.link_down);
+    }
+}
+
+static void open_eth_mii_tx_host_write(OpenEthState *s, uint32_t val)
+{
+    SET_REGFIELD(s, MIITX_DATA, CTRLDATA, val);
+    if (GET_REGFIELD(s, MIIADDRESS, FIAD) == DEFAULT_PHY) {
+        mii_write_host(&s->mii, GET_REGFIELD(s, MIIADDRESS, RGAD),
+                GET_REGFIELD(s, MIITX_DATA, CTRLDATA));
+    }
+}
+
+static void open_eth_reg_write(void *opaque,
+        target_phys_addr_t addr, uint64_t val, unsigned int size)
+{
+    static void (*reg_write[REG_MAX])(OpenEthState *s, uint32_t val) = {
+        [MODER] = open_eth_moder_host_write,
+        [INT_SOURCE] = open_eth_int_source_host_write,
+        [INT_MASK] = open_eth_int_mask_host_write,
+        [MIICOMMAND] = open_eth_mii_command_host_write,
+        [MIITX_DATA] = open_eth_mii_tx_host_write,
+        [MIISTATUS] = open_eth_ro,
+    };
+    OpenEthState *s = opaque;
+    unsigned idx = addr / 4;
+
+    if (idx < REG_MAX) {
+        trace_open_eth_reg_write((uint32_t)addr, (uint32_t)val);
+        if (reg_write[idx]) {
+            reg_write[idx](s, val);
+        } else {
+            s->regs[idx] = val;
+        }
+    }
+}
+
+static uint64_t open_eth_desc_read(void *opaque,
+        target_phys_addr_t addr, unsigned int size)
+{
+    OpenEthState *s = opaque;
+    uint64_t v = 0;
+
+    addr &= 0x3ff;
+    memcpy(&v, (uint8_t *)s->desc + addr, size);
+    trace_open_eth_desc_read((uint32_t)addr, (uint32_t)v);
+    return v;
+}
+
+static void open_eth_desc_write(void *opaque,
+        target_phys_addr_t addr, uint64_t val, unsigned int size)
+{
+    OpenEthState *s = opaque;
+
+    addr &= 0x3ff;
+    trace_open_eth_desc_write((uint32_t)addr, (uint32_t)val);
+    memcpy((uint8_t *)s->desc + addr, &val, size);
+    open_eth_check_start_xmit(s);
+}
+
+
+static MemoryRegionOps open_eth_reg_ops = {
+    .read = open_eth_reg_read,
+    .write = open_eth_reg_write,
+};
+
+static MemoryRegionOps open_eth_desc_ops = {
+    .read = open_eth_desc_read,
+    .write = open_eth_desc_write,
+};
+
+static int sysbus_open_eth_init(SysBusDevice *dev)
+{
+    OpenEthState *s = DO_UPCAST(OpenEthState, dev, dev);
+
+    memory_region_init_io(&s->reg_io, &open_eth_reg_ops, s,
+            "open_eth.regs", 0x54);
+    sysbus_init_mmio_region(dev, &s->reg_io);
+
+    memory_region_init_io(&s->desc_io, &open_eth_desc_ops, s,
+            "open_eth.desc", 0x400);
+    sysbus_init_mmio_region(dev, &s->desc_io);
+
+    sysbus_init_irq(dev, &s->irq);
+
+    s->nic = qemu_new_nic(&net_open_eth_info, &s->conf,
+                          s->dev.qdev.info->name, s->dev.qdev.id, s);
+    return 0;
+}
+
+static void qdev_open_eth_reset(DeviceState *dev)
+{
+    OpenEthState *d = DO_UPCAST(OpenEthState, dev.qdev, dev);
+    open_eth_reset(d);
+}
+
+static SysBusDeviceInfo open_eth_info = {
+    .qdev.name  = "open_eth",
+    .qdev.desc  = "Opencores 10/100 Mbit Ethernet",
+    .qdev.size  = sizeof(OpenEthState),
+    .qdev.reset = qdev_open_eth_reset,
+    .init       = sysbus_open_eth_init,
+    .qdev.props = (Property[]) {
+        DEFINE_NIC_PROPERTIES(OpenEthState, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void open_eth_register_devices(void)
+{
+    sysbus_register_withprop(&open_eth_info);
+}
+
+device_init(open_eth_register_devices)
diff --git a/trace-events b/trace-events
index 63d8c8e..a06c6c5 100644
--- a/trace-events
+++ b/trace-events
@@ -538,3 +538,17 @@ esp_mem_writeb_cmd_ensel(uint32_t val) "Enable selection (%2.2x)"
 # monitor.c
 handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\""
 monitor_protocol_emitter(void *mon) "mon %p"
+
+# hw/opencores_eth.c
+open_eth_mii_write(unsigned idx, uint16_t v) "MII[%02x] <- %04x"
+open_eth_mii_read(unsigned idx, uint16_t v) "MII[%02x] -> %04x"
+open_eth_update_irq(uint32_t v) "IRQ <- %x"
+open_eth_receive(unsigned len) "RX: len: %u"
+open_eth_receive_mcast(unsigned idx, uint32_t h0, uint32_t h1) "MCAST: idx = %u, hash: %08x:%08x"
+open_eth_receive_reject(void) "RX: rejected"
+open_eth_receive_desc(uint32_t addr, uint32_t len_flags) "RX: %08x, len_flags: %08x"
+open_eth_start_xmit(uint32_t addr, unsigned len, unsigned tx_len) "TX: %08x, len: %u, tx_len: %u"
+open_eth_reg_read(uint32_t addr, uint32_t v) "MAC[%02x] -> %08x"
+open_eth_reg_write(uint32_t addr, uint32_t v) "MAC[%02x] <- %08x"
+open_eth_desc_read(uint32_t addr, uint32_t v) "DESC[%04x] -> %08x"
+open_eth_desc_write(uint32_t addr, uint32_t v) "DESC[%04x] <- %08x"
commit 5e4085737400ffa3db09f1dc22569b167f9e2675
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Oct 16 02:56:07 2011 +0400

    target-xtensa: rename dc232b board to sim
    
    This is to get aligned with the linux name for this machine.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 9991d88..752221c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -370,7 +370,7 @@ obj-alpha-y += vga.o cirrus_vga.o
 obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
 
 obj-xtensa-y += xtensa_pic.o
-obj-xtensa-y += xtensa_dc232b.o
+obj-xtensa-y += xtensa_sim.o
 obj-xtensa-y += xtensa-semi.o
 obj-xtensa-y += core-dc232b.o
 obj-xtensa-y += core-fsf.o
diff --git a/hw/xtensa_dc232b.c b/hw/xtensa_dc232b.c
deleted file mode 100644
index 015d6aa..0000000
--- a/hw/xtensa_dc232b.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the Open Source and Linux Lab nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "sysemu.h"
-#include "boards.h"
-#include "loader.h"
-#include "elf.h"
-#include "memory.h"
-#include "exec-memory.h"
-
-static uint64_t translate_phys_addr(void *env, uint64_t addr)
-{
-    return cpu_get_phys_page_debug(env, addr);
-}
-
-static void dc232b_reset(void *env)
-{
-    cpu_reset(env);
-}
-
-static void dc232b_init(ram_addr_t ram_size,
-        const char *boot_device,
-        const char *kernel_filename, const char *kernel_cmdline,
-        const char *initrd_filename, const char *cpu_model)
-{
-    CPUState *env = NULL;
-    MemoryRegion *ram, *rom;
-    int n;
-
-    for (n = 0; n < smp_cpus; n++) {
-        env = cpu_init(cpu_model);
-        if (!env) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        env->sregs[PRID] = n;
-        qemu_register_reset(dc232b_reset, env);
-        /* Need MMU initialized prior to ELF loading,
-         * so that ELF gets loaded into virtual addresses
-         */
-        dc232b_reset(env);
-    }
-
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size);
-    memory_region_add_subregion(get_system_memory(), 0, ram);
-
-    rom = g_malloc(sizeof(*rom));
-    memory_region_init_ram(rom, NULL, "xtensa.rom", 0x1000);
-    memory_region_add_subregion(get_system_memory(), 0xfe000000, rom);
-
-    if (kernel_filename) {
-        uint64_t elf_entry;
-        uint64_t elf_lowaddr;
-#ifdef TARGET_WORDS_BIGENDIAN
-        int success = load_elf(kernel_filename, translate_phys_addr, env,
-                &elf_entry, &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
-#else
-        int success = load_elf(kernel_filename, translate_phys_addr, env,
-                &elf_entry, &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
-#endif
-        if (success > 0) {
-            env->pc = elf_entry;
-        }
-    }
-}
-
-static void xtensa_dc232b_init(ram_addr_t ram_size,
-                     const char *boot_device,
-                     const char *kernel_filename, const char *kernel_cmdline,
-                     const char *initrd_filename, const char *cpu_model)
-{
-    if (!cpu_model) {
-        cpu_model = "dc232b";
-    }
-    dc232b_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
-            initrd_filename, cpu_model);
-}
-
-static QEMUMachine xtensa_dc232b_machine = {
-    .name = "dc232b",
-    .desc = "Diamond 232L Standard Core Rev.B (LE) (dc232b)",
-    .init = xtensa_dc232b_init,
-    .max_cpus = 4,
-};
-
-static void xtensa_dc232b_machine_init(void)
-{
-    qemu_register_machine(&xtensa_dc232b_machine);
-}
-
-machine_init(xtensa_dc232b_machine_init);
diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c
new file mode 100644
index 0000000..a94e4e5
--- /dev/null
+++ b/hw/xtensa_sim.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sysemu.h"
+#include "boards.h"
+#include "loader.h"
+#include "elf.h"
+#include "memory.h"
+#include "exec-memory.h"
+
+static uint64_t translate_phys_addr(void *env, uint64_t addr)
+{
+    return cpu_get_phys_page_debug(env, addr);
+}
+
+static void sim_reset(void *env)
+{
+    cpu_reset(env);
+}
+
+static void sim_init(ram_addr_t ram_size,
+        const char *boot_device,
+        const char *kernel_filename, const char *kernel_cmdline,
+        const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env = NULL;
+    MemoryRegion *ram, *rom;
+    int n;
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        env->sregs[PRID] = n;
+        qemu_register_reset(sim_reset, env);
+        /* Need MMU initialized prior to ELF loading,
+         * so that ELF gets loaded into virtual addresses
+         */
+        sim_reset(env);
+    }
+
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size);
+    memory_region_add_subregion(get_system_memory(), 0, ram);
+
+    rom = g_malloc(sizeof(*rom));
+    memory_region_init_ram(rom, NULL, "xtensa.rom", 0x1000);
+    memory_region_add_subregion(get_system_memory(), 0xfe000000, rom);
+
+    if (kernel_filename) {
+        uint64_t elf_entry;
+        uint64_t elf_lowaddr;
+#ifdef TARGET_WORDS_BIGENDIAN
+        int success = load_elf(kernel_filename, translate_phys_addr, env,
+                &elf_entry, &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
+#else
+        int success = load_elf(kernel_filename, translate_phys_addr, env,
+                &elf_entry, &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
+#endif
+        if (success > 0) {
+            env->pc = elf_entry;
+        }
+    }
+}
+
+static void xtensa_sim_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    if (!cpu_model) {
+        cpu_model = "dc232b";
+    }
+    sim_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
+            initrd_filename, cpu_model);
+}
+
+static QEMUMachine xtensa_sim_machine = {
+    .name = "sim",
+    .desc = "sim machine (dc232b)",
+    .init = xtensa_sim_init,
+    .max_cpus = 4,
+};
+
+static void xtensa_sim_machine_init(void)
+{
+    qemu_register_machine(&xtensa_sim_machine);
+}
+
+machine_init(xtensa_sim_machine_init);
diff --git a/tests/xtensa/Makefile b/tests/xtensa/Makefile
index 15d39da..8713af1 100644
--- a/tests/xtensa/Makefile
+++ b/tests/xtensa/Makefile
@@ -4,7 +4,7 @@ CROSS=xtensa-dc232b-elf-
 
 ifndef XT
 SIM = qemu-system-xtensa
-SIMFLAGS = -M dc232b -nographic -semihosting $(EXTFLAGS) -kernel
+SIMFLAGS = -M sim -cpu dc232b -nographic -semihosting $(EXTFLAGS) -kernel
 SIMDEBUG = -s -S
 else
 SIM = xt-run
commit 935f7a2b428f71a40e985f09955bccaaf09518fa
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Oct 16 02:56:06 2011 +0400

    target-xtensa: add fsf core
    
    This is FSF big endian core implemented through linux overlay.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 95d51ae..9991d88 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -373,6 +373,7 @@ obj-xtensa-y += xtensa_pic.o
 obj-xtensa-y += xtensa_dc232b.o
 obj-xtensa-y += xtensa-semi.o
 obj-xtensa-y += core-dc232b.o
+obj-xtensa-y += core-fsf.o
 
 main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
diff --git a/target-xtensa/core-fsf.c b/target-xtensa/core-fsf.c
new file mode 100644
index 0000000..7650462
--- /dev/null
+++ b/target-xtensa/core-fsf.c
@@ -0,0 +1,22 @@
+#include "cpu.h"
+#include "exec-all.h"
+#include "gdbstub.h"
+#include "qemu-common.h"
+#include "host-utils.h"
+
+#include "core-fsf/core-isa.h"
+#include "overlay_tool.h"
+
+static const XtensaConfig fsf = {
+    .name = "fsf",
+    .options = XTENSA_OPTIONS,
+    /* GDB for this core is not supported currently */
+    .nareg = XCHAL_NUM_AREGS,
+    .ndepc = 1,
+    EXCEPTIONS_SECTION,
+    INTERRUPTS_SECTION,
+    TLB_SECTION,
+    .clock_freq_khz = 10000,
+};
+
+REGISTER_CORE(fsf)
diff --git a/target-xtensa/core-fsf/core-isa.h b/target-xtensa/core-fsf/core-isa.h
new file mode 100644
index 0000000..b519d6c
--- /dev/null
+++ b/target-xtensa/core-fsf/core-isa.h
@@ -0,0 +1,361 @@
+/*
+ * Xtensa processor core configuration information.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999-2006 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CORE_H
+#define _XTENSA_CORE_H
+
+
+/****************************************************************************
+            Parameters Useful for Any Code, USER or PRIVILEGED
+ ****************************************************************************/
+
+/*
+ *  Note:  Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is
+ *  configured, and a value of 0 otherwise.  These macros are always defined.
+ */
+
+
+/*----------------------------------------------------------------------
+                                ISA
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_BE                   1       /* big-endian byte ordering */
+#define XCHAL_HAVE_WINDOWED             1       /* windowed registers option */
+#define XCHAL_NUM_AREGS                 64      /* num of physical addr regs */
+#define XCHAL_NUM_AREGS_LOG2            6       /* log2(XCHAL_NUM_AREGS) */
+#define XCHAL_MAX_INSTRUCTION_SIZE      3       /* max instr bytes (3..8) */
+#define XCHAL_HAVE_DEBUG                1       /* debug option */
+#define XCHAL_HAVE_DENSITY              1       /* 16-bit instructions */
+#define XCHAL_HAVE_LOOPS                1       /* zero-overhead loops */
+#define XCHAL_HAVE_NSA                  1       /* NSA/NSAU instructions */
+#define XCHAL_HAVE_MINMAX               0       /* MIN/MAX instructions */
+#define XCHAL_HAVE_SEXT                 0       /* SEXT instruction */
+#define XCHAL_HAVE_CLAMPS               0       /* CLAMPS instruction */
+#define XCHAL_HAVE_MUL16                0       /* MUL16S/MUL16U instructions */
+#define XCHAL_HAVE_MUL32                0       /* MULL instruction */
+#define XCHAL_HAVE_MUL32_HIGH           0       /* MULUH/MULSH instructions */
+#define XCHAL_HAVE_L32R                 1       /* L32R instruction */
+#define XCHAL_HAVE_ABSOLUTE_LITERALS    1       /* non-PC-rel (extended) L32R */
+#define XCHAL_HAVE_CONST16              0       /* CONST16 instruction */
+#define XCHAL_HAVE_ADDX                 1       /* ADDX#/SUBX# instructions */
+#define XCHAL_HAVE_WIDE_BRANCHES        0       /* B*.W18 or B*.W15 instr's */
+#define XCHAL_HAVE_PREDICTED_BRANCHES   0       /* B[EQ/EQZ/NE/NEZ]T instr's */
+#define XCHAL_HAVE_CALL4AND12           1       /* (obsolete option) */
+#define XCHAL_HAVE_ABS                  1       /* ABS instruction */
+/*#define XCHAL_HAVE_POPC               0*/     /* POPC instruction */
+/*#define XCHAL_HAVE_CRC                0*/     /* CRC instruction */
+#define XCHAL_HAVE_RELEASE_SYNC         0       /* L32AI/S32RI instructions */
+#define XCHAL_HAVE_S32C1I               0       /* S32C1I instruction */
+#define XCHAL_HAVE_SPECULATION          0       /* speculation */
+#define XCHAL_HAVE_FULL_RESET           1       /* all regs/state reset */
+#define XCHAL_NUM_CONTEXTS              1       /* */
+#define XCHAL_NUM_MISC_REGS             2       /* num of scratch regs (0..4) */
+#define XCHAL_HAVE_TAP_MASTER           0       /* JTAG TAP control instr's */
+#define XCHAL_HAVE_PRID                 1       /* processor ID register */
+#define XCHAL_HAVE_THREADPTR            1       /* THREADPTR register */
+#define XCHAL_HAVE_BOOLEANS             0       /* boolean registers */
+#define XCHAL_HAVE_CP                   0       /* CPENABLE reg (coprocessor) */
+#define XCHAL_CP_MAXCFG                 0       /* max allowed cp id plus one */
+#define XCHAL_HAVE_MAC16                0       /* MAC16 package */
+#define XCHAL_HAVE_VECTORFPU2005        0       /* vector floating-point pkg */
+#define XCHAL_HAVE_FP                   0       /* floating point pkg */
+#define XCHAL_HAVE_VECTRA1              0       /* Vectra I  pkg */
+#define XCHAL_HAVE_VECTRALX             0       /* Vectra LX pkg */
+#define XCHAL_HAVE_HIFI2                0       /* HiFi2 Audio Engine pkg */
+
+
+/*----------------------------------------------------------------------
+                                MISC
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_WRITEBUFFER_ENTRIES   4       /* size of write buffer */
+#define XCHAL_INST_FETCH_WIDTH          4       /* instr-fetch width in bytes */
+#define XCHAL_DATA_WIDTH                4       /* data width in bytes */
+/*  In T1050, applies to selected core load and store instructions (see ISA): */
+#define XCHAL_UNALIGNED_LOAD_EXCEPTION  1       /* unaligned loads cause exc. */
+#define XCHAL_UNALIGNED_STORE_EXCEPTION 1       /* unaligned stores cause exc.*/
+
+#define XCHAL_SW_VERSION                800002  /* sw version of this header */
+
+#define XCHAL_CORE_ID                   "fsf"   /* alphanum core name
+                                                   (CoreID) set in the Xtensa
+                                                   Processor Generator */
+
+#define XCHAL_CORE_DESCRIPTION          "fsf standard core"
+#define XCHAL_BUILD_UNIQUE_ID           0x00006700      /* 22-bit sw build ID */
+
+/*
+ *  These definitions describe the hardware targeted by this software.
+ */
+#define XCHAL_HW_CONFIGID0              0xC103C3FF      /* ConfigID hi 32 bits*/
+#define XCHAL_HW_CONFIGID1              0x0C006700      /* ConfigID lo 32 bits*/
+#define XCHAL_HW_VERSION_NAME           "LX2.0.0"       /* full version name */
+#define XCHAL_HW_VERSION_MAJOR          2200    /* major ver# of targeted hw */
+#define XCHAL_HW_VERSION_MINOR          0       /* minor ver# of targeted hw */
+#define XTHAL_HW_REL_LX2                1
+#define XTHAL_HW_REL_LX2_0              1
+#define XTHAL_HW_REL_LX2_0_0            1
+#define XCHAL_HW_CONFIGID_RELIABLE      1
+/*  If software targets a *range* of hardware versions, these are the bounds: */
+#define XCHAL_HW_MIN_VERSION_MAJOR      2200    /* major v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION_MINOR      0       /* minor v of earliest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MAJOR      2200    /* major v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MINOR      0       /* minor v of latest tgt hw */
+
+
+/*----------------------------------------------------------------------
+                                CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_ICACHE_LINESIZE           16      /* I-cache line size in bytes */
+#define XCHAL_DCACHE_LINESIZE           16      /* D-cache line size in bytes */
+#define XCHAL_ICACHE_LINEWIDTH          4       /* log2(I line size in bytes) */
+#define XCHAL_DCACHE_LINEWIDTH          4       /* log2(D line size in bytes) */
+
+#define XCHAL_ICACHE_SIZE               8192    /* I-cache size in bytes or 0 */
+#define XCHAL_DCACHE_SIZE               8192    /* D-cache size in bytes or 0 */
+
+#define XCHAL_DCACHE_IS_WRITEBACK       0       /* writeback feature */
+
+
+
+
+/****************************************************************************
+    Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code
+ ****************************************************************************/
+
+
+#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY
+
+/*----------------------------------------------------------------------
+                                CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_PIF                  1       /* any outbound PIF present */
+
+/*  If present, cache size in bytes == (ways * 2^(linewidth + setwidth)).  */
+
+/*  Number of cache sets in log2(lines per way):  */
+#define XCHAL_ICACHE_SETWIDTH           8
+#define XCHAL_DCACHE_SETWIDTH           8
+
+/*  Cache set associativity (number of ways):  */
+#define XCHAL_ICACHE_WAYS               2
+#define XCHAL_DCACHE_WAYS               2
+
+/*  Cache features:  */
+#define XCHAL_ICACHE_LINE_LOCKABLE      0
+#define XCHAL_DCACHE_LINE_LOCKABLE      0
+#define XCHAL_ICACHE_ECC_PARITY         0
+#define XCHAL_DCACHE_ECC_PARITY         0
+
+/*  Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits):  */
+#define XCHAL_CA_BITS                   4
+
+
+/*----------------------------------------------------------------------
+                        INTERNAL I/D RAM/ROMs and XLMI
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_INSTROM               0       /* number of core instr. ROMs */
+#define XCHAL_NUM_INSTRAM               0       /* number of core instr. RAMs */
+#define XCHAL_NUM_DATAROM               0       /* number of core data ROMs */
+#define XCHAL_NUM_DATARAM               0       /* number of core data RAMs */
+#define XCHAL_NUM_URAM                  0       /* number of core unified RAMs*/
+#define XCHAL_NUM_XLMI                  0       /* number of core XLMI ports */
+
+
+/*----------------------------------------------------------------------
+                        INTERRUPTS and TIMERS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_INTERRUPTS           1       /* interrupt option */
+#define XCHAL_HAVE_HIGHPRI_INTERRUPTS   1       /* med/high-pri. interrupts */
+#define XCHAL_HAVE_NMI                  0       /* non-maskable interrupt */
+#define XCHAL_HAVE_CCOUNT               1       /* CCOUNT reg. (timer option) */
+#define XCHAL_NUM_TIMERS                3       /* number of CCOMPAREn regs */
+#define XCHAL_NUM_INTERRUPTS            17      /* number of interrupts */
+#define XCHAL_NUM_INTERRUPTS_LOG2       5       /* ceil(log2(NUM_INTERRUPTS)) */
+#define XCHAL_NUM_EXTINTERRUPTS         10      /* num of external interrupts */
+#define XCHAL_NUM_INTLEVELS             4       /* number of interrupt levels
+                                                   (not including level zero) */
+#define XCHAL_EXCM_LEVEL                1       /* level masked by PS.EXCM */
+        /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */
+
+/*  Masks of interrupts at each interrupt level:  */
+#define XCHAL_INTLEVEL1_MASK            0x000064F9
+#define XCHAL_INTLEVEL2_MASK            0x00008902
+#define XCHAL_INTLEVEL3_MASK            0x00011204
+#define XCHAL_INTLEVEL4_MASK            0x00000000
+#define XCHAL_INTLEVEL5_MASK            0x00000000
+#define XCHAL_INTLEVEL6_MASK            0x00000000
+#define XCHAL_INTLEVEL7_MASK            0x00000000
+
+/*  Masks of interrupts at each range 1..n of interrupt levels:  */
+#define XCHAL_INTLEVEL1_ANDBELOW_MASK   0x000064F9
+#define XCHAL_INTLEVEL2_ANDBELOW_MASK   0x0000EDFB
+#define XCHAL_INTLEVEL3_ANDBELOW_MASK   0x0001FFFF
+#define XCHAL_INTLEVEL4_ANDBELOW_MASK   0x0001FFFF
+#define XCHAL_INTLEVEL5_ANDBELOW_MASK   0x0001FFFF
+#define XCHAL_INTLEVEL6_ANDBELOW_MASK   0x0001FFFF
+#define XCHAL_INTLEVEL7_ANDBELOW_MASK   0x0001FFFF
+
+/*  Level of each interrupt:  */
+#define XCHAL_INT0_LEVEL                1
+#define XCHAL_INT1_LEVEL                2
+#define XCHAL_INT2_LEVEL                3
+#define XCHAL_INT3_LEVEL                1
+#define XCHAL_INT4_LEVEL                1
+#define XCHAL_INT5_LEVEL                1
+#define XCHAL_INT6_LEVEL                1
+#define XCHAL_INT7_LEVEL                1
+#define XCHAL_INT8_LEVEL                2
+#define XCHAL_INT9_LEVEL                3
+#define XCHAL_INT10_LEVEL               1
+#define XCHAL_INT11_LEVEL               2
+#define XCHAL_INT12_LEVEL               3
+#define XCHAL_INT13_LEVEL               1
+#define XCHAL_INT14_LEVEL               1
+#define XCHAL_INT15_LEVEL               2
+#define XCHAL_INT16_LEVEL               3
+#define XCHAL_DEBUGLEVEL                4       /* debug interrupt level */
+#define XCHAL_HAVE_DEBUG_EXTERN_INT     0       /* OCD external db interrupt */
+
+/*  Type of each interrupt:  */
+#define XCHAL_INT0_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT1_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT2_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT3_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT4_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT5_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT6_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT7_TYPE         XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT8_TYPE         XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT9_TYPE         XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT10_TYPE        XTHAL_INTTYPE_TIMER
+#define XCHAL_INT11_TYPE        XTHAL_INTTYPE_TIMER
+#define XCHAL_INT12_TYPE        XTHAL_INTTYPE_TIMER
+#define XCHAL_INT13_TYPE        XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT14_TYPE        XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT15_TYPE        XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT16_TYPE        XTHAL_INTTYPE_SOFTWARE
+
+/*  Masks of interrupts for each type of interrupt:  */
+#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFE0000
+#define XCHAL_INTTYPE_MASK_SOFTWARE     0x0001E000
+#define XCHAL_INTTYPE_MASK_EXTERN_EDGE  0x00000380
+#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0000007F
+#define XCHAL_INTTYPE_MASK_TIMER        0x00001C00
+#define XCHAL_INTTYPE_MASK_NMI          0x00000000
+#define XCHAL_INTTYPE_MASK_WRITE_ERROR  0x00000000
+
+/*  Interrupt numbers assigned to specific interrupt sources:  */
+#define XCHAL_TIMER0_INTERRUPT          10      /* CCOMPARE0 */
+#define XCHAL_TIMER1_INTERRUPT          11      /* CCOMPARE1 */
+#define XCHAL_TIMER2_INTERRUPT          12      /* CCOMPARE2 */
+#define XCHAL_TIMER3_INTERRUPT          XTHAL_TIMER_UNCONFIGURED
+
+/*  Interrupt numbers for levels at which only one interrupt is configured:  */
+/*  (There are many interrupts each at level(s) 1, 2, 3.)  */
+
+
+/*
+ *  External interrupt vectors/levels.
+ *  These macros describe how Xtensa processor interrupt numbers
+ *  (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
+ *  map to external BInterrupt<n> pins, for those interrupts
+ *  configured as external (level-triggered, edge-triggered, or NMI).
+ *  See the Xtensa processor databook for more details.
+ */
+
+/*  Core interrupt numbers mapped to each EXTERNAL interrupt number:  */
+#define XCHAL_EXTINT0_NUM               0       /* (intlevel 1) */
+#define XCHAL_EXTINT1_NUM               1       /* (intlevel 2) */
+#define XCHAL_EXTINT2_NUM               2       /* (intlevel 3) */
+#define XCHAL_EXTINT3_NUM               3       /* (intlevel 1) */
+#define XCHAL_EXTINT4_NUM               4       /* (intlevel 1) */
+#define XCHAL_EXTINT5_NUM               5       /* (intlevel 1) */
+#define XCHAL_EXTINT6_NUM               6       /* (intlevel 1) */
+#define XCHAL_EXTINT7_NUM               7       /* (intlevel 1) */
+#define XCHAL_EXTINT8_NUM               8       /* (intlevel 2) */
+#define XCHAL_EXTINT9_NUM               9       /* (intlevel 3) */
+
+
+/*----------------------------------------------------------------------
+                        EXCEPTIONS and VECTORS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_XEA_VERSION               2       /* Xtensa Exception Architecture
+                                                   number: 1 == XEA1 (old)
+                                                           2 == XEA2 (new)
+                                                           0 == XEAX (extern) */
+#define XCHAL_HAVE_XEA1                 0       /* Exception Architecture 1 */
+#define XCHAL_HAVE_XEA2                 1       /* Exception Architecture 2 */
+#define XCHAL_HAVE_XEAX                 0       /* External Exception Arch. */
+#define XCHAL_HAVE_EXCEPTIONS           1       /* exception option */
+#define XCHAL_HAVE_MEM_ECC_PARITY       0       /* local memory ECC/parity */
+
+#define XCHAL_RESET_VECTOR_VADDR        0xFE000020
+#define XCHAL_RESET_VECTOR_PADDR        0xFE000020
+#define XCHAL_USER_VECTOR_VADDR         0xD0000220
+#define XCHAL_USER_VECTOR_PADDR         0x00000220
+#define XCHAL_KERNEL_VECTOR_VADDR       0xD0000200
+#define XCHAL_KERNEL_VECTOR_PADDR       0x00000200
+#define XCHAL_DOUBLEEXC_VECTOR_VADDR    0xD0000290
+#define XCHAL_DOUBLEEXC_VECTOR_PADDR    0x00000290
+#define XCHAL_WINDOW_VECTORS_VADDR      0xD0000000
+#define XCHAL_WINDOW_VECTORS_PADDR      0x00000000
+#define XCHAL_INTLEVEL2_VECTOR_VADDR    0xD0000240
+#define XCHAL_INTLEVEL2_VECTOR_PADDR    0x00000240
+#define XCHAL_INTLEVEL3_VECTOR_VADDR    0xD0000250
+#define XCHAL_INTLEVEL3_VECTOR_PADDR    0x00000250
+#define XCHAL_INTLEVEL4_VECTOR_VADDR    0xFE000520
+#define XCHAL_INTLEVEL4_VECTOR_PADDR    0xFE000520
+#define XCHAL_DEBUG_VECTOR_VADDR        XCHAL_INTLEVEL4_VECTOR_VADDR
+#define XCHAL_DEBUG_VECTOR_PADDR        XCHAL_INTLEVEL4_VECTOR_PADDR
+
+
+/*----------------------------------------------------------------------
+                                DEBUG
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_OCD                  1       /* OnChipDebug option */
+#define XCHAL_NUM_IBREAK                2       /* number of IBREAKn regs */
+#define XCHAL_NUM_DBREAK                2       /* number of DBREAKn regs */
+#define XCHAL_HAVE_OCD_DIR_ARRAY        1       /* faster OCD option */
+
+
+/*----------------------------------------------------------------------
+                                MMU
+  ----------------------------------------------------------------------*/
+
+/*  See <xtensa/config/core-matmap.h> header file for more details.  */
+
+#define XCHAL_HAVE_TLBS                 1       /* inverse of HAVE_CACHEATTR */
+#define XCHAL_HAVE_SPANNING_WAY         0       /* one way maps I+D 4GB vaddr */
+#define XCHAL_HAVE_IDENTITY_MAP         0       /* vaddr == paddr always */
+#define XCHAL_HAVE_CACHEATTR            0       /* CACHEATTR register present */
+#define XCHAL_HAVE_MIMIC_CACHEATTR      0       /* region protection */
+#define XCHAL_HAVE_XLT_CACHEATTR        0       /* region prot. w/translation */
+#define XCHAL_HAVE_PTP_MMU              1       /* full MMU (with page table
+                                                   [autorefill] and protection)
+                                                   usable for an MMU-based OS */
+/*  If none of the above last 4 are set, it's a custom TLB configuration.  */
+#define XCHAL_ITLB_ARF_ENTRIES_LOG2     2       /* log2(autorefill way size) */
+#define XCHAL_DTLB_ARF_ENTRIES_LOG2     2       /* log2(autorefill way size) */
+
+#define XCHAL_MMU_ASID_BITS             8       /* number of bits in ASIDs */
+#define XCHAL_MMU_RINGS                 4       /* number of rings (1..4) */
+#define XCHAL_MMU_RING_BITS             2       /* num of bits in RING field */
+
+#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */
+
+
+#endif /* _XTENSA_CORE_CONFIGURATION_H */
commit 53add759be1a39063cfc52ca2a6d0fcdd1091697
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Oct 16 02:56:05 2011 +0400

    target-xtensa: add dc232b core
    
    This is Diamond 232L Standard Core Rev.B (LE), implemented through
    linux/gdb overlay.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index 04369b1..95d51ae 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -372,6 +372,7 @@ obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
 obj-xtensa-y += xtensa_pic.o
 obj-xtensa-y += xtensa_dc232b.o
 obj-xtensa-y += xtensa-semi.o
+obj-xtensa-y += core-dc232b.o
 
 main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
diff --git a/target-xtensa/core-dc232b.c b/target-xtensa/core-dc232b.c
new file mode 100644
index 0000000..4d9bd55
--- /dev/null
+++ b/target-xtensa/core-dc232b.c
@@ -0,0 +1,28 @@
+#include "cpu.h"
+#include "exec-all.h"
+#include "gdbstub.h"
+#include "qemu-common.h"
+#include "host-utils.h"
+
+#include "core-dc232b/core-isa.h"
+#include "overlay_tool.h"
+
+static const XtensaConfig dc232b = {
+    .name = "dc232b",
+    .options = XTENSA_OPTIONS,
+    .gdb_regmap = {
+        .num_regs = 120,
+        .num_core_regs = 52,
+        .reg = {
+#include "core-dc232b/gdb-config.c"
+        }
+    },
+    .nareg = XCHAL_NUM_AREGS,
+    .ndepc = 1,
+    EXCEPTIONS_SECTION,
+    INTERRUPTS_SECTION,
+    TLB_SECTION,
+    .clock_freq_khz = 10000,
+};
+
+REGISTER_CORE(dc232b)
diff --git a/target-xtensa/core-dc232b/core-isa.h b/target-xtensa/core-dc232b/core-isa.h
new file mode 100644
index 0000000..69f1065
--- /dev/null
+++ b/target-xtensa/core-dc232b/core-isa.h
@@ -0,0 +1,423 @@
+/*
+ * Xtensa processor core configuration information.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1999-2007 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CORE_CONFIGURATION_H
+#define _XTENSA_CORE_CONFIGURATION_H
+
+
+/****************************************************************************
+            Parameters Useful for Any Code, USER or PRIVILEGED
+ ****************************************************************************/
+
+/*
+ *  Note:  Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is
+ *  configured, and a value of 0 otherwise.  These macros are always defined.
+ */
+
+
+/*----------------------------------------------------------------------
+                                ISA
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_BE                   0       /* big-endian byte ordering */
+#define XCHAL_HAVE_WINDOWED             1       /* windowed registers option */
+#define XCHAL_NUM_AREGS                 32      /* num of physical addr regs */
+#define XCHAL_NUM_AREGS_LOG2            5       /* log2(XCHAL_NUM_AREGS) */
+#define XCHAL_MAX_INSTRUCTION_SIZE      3       /* max instr bytes (3..8) */
+#define XCHAL_HAVE_DEBUG                1       /* debug option */
+#define XCHAL_HAVE_DENSITY              1       /* 16-bit instructions */
+#define XCHAL_HAVE_LOOPS                1       /* zero-overhead loops */
+#define XCHAL_HAVE_NSA                  1       /* NSA/NSAU instructions */
+#define XCHAL_HAVE_MINMAX               1       /* MIN/MAX instructions */
+#define XCHAL_HAVE_SEXT                 1       /* SEXT instruction */
+#define XCHAL_HAVE_CLAMPS               1       /* CLAMPS instruction */
+#define XCHAL_HAVE_MUL16                1       /* MUL16S/MUL16U instructions */
+#define XCHAL_HAVE_MUL32                1       /* MULL instruction */
+#define XCHAL_HAVE_MUL32_HIGH           0       /* MULUH/MULSH instructions */
+#define XCHAL_HAVE_DIV32                1       /* QUOS/QUOU/REMS/REMU insns */
+#define XCHAL_HAVE_L32R                 1       /* L32R instruction */
+#define XCHAL_HAVE_ABSOLUTE_LITERALS    1       /* non-PC-rel (extended) L32R */
+#define XCHAL_HAVE_CONST16              0       /* CONST16 instruction */
+#define XCHAL_HAVE_ADDX                 1       /* ADDX#/SUBX# instructions */
+#define XCHAL_HAVE_WIDE_BRANCHES        0       /* B*.W18 or B*.W15 instr's */
+#define XCHAL_HAVE_PREDICTED_BRANCHES   0       /* B[EQ/EQZ/NE/NEZ]T instr's */
+#define XCHAL_HAVE_CALL4AND12           1       /* (obsolete option) */
+#define XCHAL_HAVE_ABS                  1       /* ABS instruction */
+/*#define XCHAL_HAVE_POPC               0*/     /* POPC instruction */
+/*#define XCHAL_HAVE_CRC                0*/     /* CRC instruction */
+#define XCHAL_HAVE_RELEASE_SYNC         1       /* L32AI/S32RI instructions */
+#define XCHAL_HAVE_S32C1I               1       /* S32C1I instruction */
+#define XCHAL_HAVE_SPECULATION          0       /* speculation */
+#define XCHAL_HAVE_FULL_RESET           1       /* all regs/state reset */
+#define XCHAL_NUM_CONTEXTS              1       /* */
+#define XCHAL_NUM_MISC_REGS             2       /* num of scratch regs (0..4) */
+#define XCHAL_HAVE_TAP_MASTER           0       /* JTAG TAP control instr's */
+#define XCHAL_HAVE_PRID                 1       /* processor ID register */
+#define XCHAL_HAVE_THREADPTR            1       /* THREADPTR register */
+#define XCHAL_HAVE_BOOLEANS             0       /* boolean registers */
+#define XCHAL_HAVE_CP                   1       /* CPENABLE reg (coprocessor) */
+#define XCHAL_CP_MAXCFG                 8       /* max allowed cp id plus one */
+#define XCHAL_HAVE_MAC16                1       /* MAC16 package */
+#define XCHAL_HAVE_VECTORFPU2005        0       /* vector floating-point pkg */
+#define XCHAL_HAVE_FP                   0       /* floating point pkg */
+#define XCHAL_HAVE_VECTRA1              0       /* Vectra I  pkg */
+#define XCHAL_HAVE_VECTRALX             0       /* Vectra LX pkg */
+#define XCHAL_HAVE_HIFI2                0       /* HiFi2 Audio Engine pkg */
+
+
+/*----------------------------------------------------------------------
+                                MISC
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_WRITEBUFFER_ENTRIES   8       /* size of write buffer */
+#define XCHAL_INST_FETCH_WIDTH          4       /* instr-fetch width in bytes */
+#define XCHAL_DATA_WIDTH                4       /* data width in bytes */
+/*  In T1050, applies to selected core load and store instructions (see ISA): */
+#define XCHAL_UNALIGNED_LOAD_EXCEPTION  1       /* unaligned loads cause exc. */
+#define XCHAL_UNALIGNED_STORE_EXCEPTION 1       /* unaligned stores cause exc.*/
+
+#define XCHAL_SW_VERSION                701001  /* sw version of this header */
+
+#define XCHAL_CORE_ID                   "dc232b"        /* alphanum core name
+                                                   (CoreID) set in the Xtensa
+                                                   Processor Generator */
+
+#define XCHAL_CORE_DESCRIPTION          "Diamond 232L Standard Core Rev.B (LE)"
+#define XCHAL_BUILD_UNIQUE_ID           0x0000BEEF      /* 22-bit sw build ID */
+
+/*
+ *  These definitions describe the hardware targeted by this software.
+ */
+#define XCHAL_HW_CONFIGID0              0xC56307FE      /* ConfigID hi 32 bits*/
+#define XCHAL_HW_CONFIGID1              0x0D40BEEF      /* ConfigID lo 32 bits*/
+#define XCHAL_HW_VERSION_NAME           "LX2.1.1"       /* full version name */
+#define XCHAL_HW_VERSION_MAJOR          2210    /* major ver# of targeted hw */
+#define XCHAL_HW_VERSION_MINOR          1       /* minor ver# of targeted hw */
+#define XCHAL_HW_VERSION                221001  /* major*100+minor */
+#define XCHAL_HW_REL_LX2                1
+#define XCHAL_HW_REL_LX2_1              1
+#define XCHAL_HW_REL_LX2_1_1            1
+#define XCHAL_HW_CONFIGID_RELIABLE      1
+/*  If software targets a *range* of hardware versions, these are the bounds: */
+#define XCHAL_HW_MIN_VERSION_MAJOR      2210    /* major v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION_MINOR      1       /* minor v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION            221001  /* earliest targeted hw */
+#define XCHAL_HW_MAX_VERSION_MAJOR      2210    /* major v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MINOR      1       /* minor v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION            221001  /* latest targeted hw */
+
+
+/*----------------------------------------------------------------------
+                                CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_ICACHE_LINESIZE           32      /* I-cache line size in bytes */
+#define XCHAL_DCACHE_LINESIZE           32      /* D-cache line size in bytes */
+#define XCHAL_ICACHE_LINEWIDTH          5       /* log2(I line size in bytes) */
+#define XCHAL_DCACHE_LINEWIDTH          5       /* log2(D line size in bytes) */
+
+#define XCHAL_ICACHE_SIZE               16384   /* I-cache size in bytes or 0 */
+#define XCHAL_DCACHE_SIZE               16384   /* D-cache size in bytes or 0 */
+
+#define XCHAL_DCACHE_IS_WRITEBACK       1       /* writeback feature */
+
+
+
+
+/****************************************************************************
+    Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code
+ ****************************************************************************/
+
+
+#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY
+
+/*----------------------------------------------------------------------
+                                CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_PIF                  1       /* any outbound PIF present */
+
+/*  If present, cache size in bytes == (ways * 2^(linewidth + setwidth)).  */
+
+/*  Number of cache sets in log2(lines per way):  */
+#define XCHAL_ICACHE_SETWIDTH           7
+#define XCHAL_DCACHE_SETWIDTH           7
+
+/*  Cache set associativity (number of ways):  */
+#define XCHAL_ICACHE_WAYS               4
+#define XCHAL_DCACHE_WAYS               4
+
+/*  Cache features:  */
+#define XCHAL_ICACHE_LINE_LOCKABLE      1
+#define XCHAL_DCACHE_LINE_LOCKABLE      1
+#define XCHAL_ICACHE_ECC_PARITY         0
+#define XCHAL_DCACHE_ECC_PARITY         0
+
+/*  Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits):  */
+#define XCHAL_CA_BITS                   4
+
+
+/*----------------------------------------------------------------------
+                        INTERNAL I/D RAM/ROMs and XLMI
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_INSTROM               0       /* number of core instr. ROMs */
+#define XCHAL_NUM_INSTRAM               0       /* number of core instr. RAMs */
+#define XCHAL_NUM_DATAROM               0       /* number of core data ROMs */
+#define XCHAL_NUM_DATARAM               0       /* number of core data RAMs */
+#define XCHAL_NUM_URAM                  0       /* number of core unified RAMs*/
+#define XCHAL_NUM_XLMI                  0       /* number of core XLMI ports */
+
+
+/*----------------------------------------------------------------------
+                        INTERRUPTS and TIMERS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_INTERRUPTS           1       /* interrupt option */
+#define XCHAL_HAVE_HIGHPRI_INTERRUPTS   1       /* med/high-pri. interrupts */
+#define XCHAL_HAVE_NMI                  1       /* non-maskable interrupt */
+#define XCHAL_HAVE_CCOUNT               1       /* CCOUNT reg. (timer option) */
+#define XCHAL_NUM_TIMERS                3       /* number of CCOMPAREn regs */
+#define XCHAL_NUM_INTERRUPTS            22      /* number of interrupts */
+#define XCHAL_NUM_INTERRUPTS_LOG2       5       /* ceil(log2(NUM_INTERRUPTS)) */
+#define XCHAL_NUM_EXTINTERRUPTS         17      /* num of external interrupts */
+#define XCHAL_NUM_INTLEVELS             6       /* number of interrupt levels
+                                                   (not including level zero) */
+#define XCHAL_EXCM_LEVEL                3       /* level masked by PS.EXCM */
+        /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */
+
+/*  Masks of interrupts at each interrupt level:  */
+#define XCHAL_INTLEVEL1_MASK            0x001F80FF
+#define XCHAL_INTLEVEL2_MASK            0x00000100
+#define XCHAL_INTLEVEL3_MASK            0x00200E00
+#define XCHAL_INTLEVEL4_MASK            0x00001000
+#define XCHAL_INTLEVEL5_MASK            0x00002000
+#define XCHAL_INTLEVEL6_MASK            0x00000000
+#define XCHAL_INTLEVEL7_MASK            0x00004000
+
+/*  Masks of interrupts at each range 1..n of interrupt levels:  */
+#define XCHAL_INTLEVEL1_ANDBELOW_MASK   0x001F80FF
+#define XCHAL_INTLEVEL2_ANDBELOW_MASK   0x001F81FF
+#define XCHAL_INTLEVEL3_ANDBELOW_MASK   0x003F8FFF
+#define XCHAL_INTLEVEL4_ANDBELOW_MASK   0x003F9FFF
+#define XCHAL_INTLEVEL5_ANDBELOW_MASK   0x003FBFFF
+#define XCHAL_INTLEVEL6_ANDBELOW_MASK   0x003FBFFF
+#define XCHAL_INTLEVEL7_ANDBELOW_MASK   0x003FFFFF
+
+/*  Level of each interrupt:  */
+#define XCHAL_INT0_LEVEL                1
+#define XCHAL_INT1_LEVEL                1
+#define XCHAL_INT2_LEVEL                1
+#define XCHAL_INT3_LEVEL                1
+#define XCHAL_INT4_LEVEL                1
+#define XCHAL_INT5_LEVEL                1
+#define XCHAL_INT6_LEVEL                1
+#define XCHAL_INT7_LEVEL                1
+#define XCHAL_INT8_LEVEL                2
+#define XCHAL_INT9_LEVEL                3
+#define XCHAL_INT10_LEVEL               3
+#define XCHAL_INT11_LEVEL               3
+#define XCHAL_INT12_LEVEL               4
+#define XCHAL_INT13_LEVEL               5
+#define XCHAL_INT14_LEVEL               7
+#define XCHAL_INT15_LEVEL               1
+#define XCHAL_INT16_LEVEL               1
+#define XCHAL_INT17_LEVEL               1
+#define XCHAL_INT18_LEVEL               1
+#define XCHAL_INT19_LEVEL               1
+#define XCHAL_INT20_LEVEL               1
+#define XCHAL_INT21_LEVEL               3
+#define XCHAL_DEBUGLEVEL                6       /* debug interrupt level */
+#define XCHAL_HAVE_DEBUG_EXTERN_INT     1       /* OCD external db interrupt */
+#define XCHAL_NMILEVEL                  7       /* NMI "level" (for use with
+                                                   EXCSAVE/EPS/EPC_n, RFI n) */
+
+/*  Type of each interrupt:  */
+#define XCHAL_INT0_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT1_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT2_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT3_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT4_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT5_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT6_TYPE         XTHAL_INTTYPE_TIMER
+#define XCHAL_INT7_TYPE         XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT8_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT9_TYPE         XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT10_TYPE        XTHAL_INTTYPE_TIMER
+#define XCHAL_INT11_TYPE        XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT12_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT13_TYPE        XTHAL_INTTYPE_TIMER
+#define XCHAL_INT14_TYPE        XTHAL_INTTYPE_NMI
+#define XCHAL_INT15_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT16_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT17_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT18_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT19_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT20_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT21_TYPE        XTHAL_INTTYPE_EXTERN_EDGE
+
+/*  Masks of interrupts for each type of interrupt:  */
+#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFC00000
+#define XCHAL_INTTYPE_MASK_SOFTWARE     0x00000880
+#define XCHAL_INTTYPE_MASK_EXTERN_EDGE  0x003F8000
+#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0000133F
+#define XCHAL_INTTYPE_MASK_TIMER        0x00002440
+#define XCHAL_INTTYPE_MASK_NMI          0x00004000
+#define XCHAL_INTTYPE_MASK_WRITE_ERROR  0x00000000
+
+/*  Interrupt numbers assigned to specific interrupt sources:  */
+#define XCHAL_TIMER0_INTERRUPT          6       /* CCOMPARE0 */
+#define XCHAL_TIMER1_INTERRUPT          10      /* CCOMPARE1 */
+#define XCHAL_TIMER2_INTERRUPT          13      /* CCOMPARE2 */
+#define XCHAL_TIMER3_INTERRUPT          XTHAL_TIMER_UNCONFIGURED
+#define XCHAL_NMI_INTERRUPT             14      /* non-maskable interrupt */
+
+/*  Interrupt numbers for levels at which only one interrupt is configured:  */
+#define XCHAL_INTLEVEL2_NUM             8
+#define XCHAL_INTLEVEL4_NUM             12
+#define XCHAL_INTLEVEL5_NUM             13
+#define XCHAL_INTLEVEL7_NUM             14
+/*  (There are many interrupts each at level(s) 1, 3.)  */
+
+
+/*
+ *  External interrupt vectors/levels.
+ *  These macros describe how Xtensa processor interrupt numbers
+ *  (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
+ *  map to external BInterrupt<n> pins, for those interrupts
+ *  configured as external (level-triggered, edge-triggered, or NMI).
+ *  See the Xtensa processor databook for more details.
+ */
+
+/*  Core interrupt numbers mapped to each EXTERNAL interrupt number:  */
+#define XCHAL_EXTINT0_NUM               0       /* (intlevel 1) */
+#define XCHAL_EXTINT1_NUM               1       /* (intlevel 1) */
+#define XCHAL_EXTINT2_NUM               2       /* (intlevel 1) */
+#define XCHAL_EXTINT3_NUM               3       /* (intlevel 1) */
+#define XCHAL_EXTINT4_NUM               4       /* (intlevel 1) */
+#define XCHAL_EXTINT5_NUM               5       /* (intlevel 1) */
+#define XCHAL_EXTINT6_NUM               8       /* (intlevel 2) */
+#define XCHAL_EXTINT7_NUM               9       /* (intlevel 3) */
+#define XCHAL_EXTINT8_NUM               12      /* (intlevel 4) */
+#define XCHAL_EXTINT9_NUM               14      /* (intlevel 7) */
+#define XCHAL_EXTINT10_NUM              15      /* (intlevel 1) */
+#define XCHAL_EXTINT11_NUM              16      /* (intlevel 1) */
+#define XCHAL_EXTINT12_NUM              17      /* (intlevel 1) */
+#define XCHAL_EXTINT13_NUM              18      /* (intlevel 1) */
+#define XCHAL_EXTINT14_NUM              19      /* (intlevel 1) */
+#define XCHAL_EXTINT15_NUM              20      /* (intlevel 1) */
+#define XCHAL_EXTINT16_NUM              21      /* (intlevel 3) */
+
+
+/*----------------------------------------------------------------------
+                        EXCEPTIONS and VECTORS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_XEA_VERSION               2       /* Xtensa Exception Architecture
+                                                   number: 1 == XEA1 (old)
+                                                           2 == XEA2 (new)
+                                                           0 == XEAX (extern) */
+#define XCHAL_HAVE_XEA1                 0       /* Exception Architecture 1 */
+#define XCHAL_HAVE_XEA2                 1       /* Exception Architecture 2 */
+#define XCHAL_HAVE_XEAX                 0       /* External Exception Arch. */
+#define XCHAL_HAVE_EXCEPTIONS           1       /* exception option */
+#define XCHAL_HAVE_MEM_ECC_PARITY       0       /* local memory ECC/parity */
+#define XCHAL_HAVE_VECTOR_SELECT        1       /* relocatable vectors */
+#define XCHAL_HAVE_VECBASE              1       /* relocatable vectors */
+#define XCHAL_VECBASE_RESET_VADDR       0xD0000000  /* VECBASE reset value */
+#define XCHAL_VECBASE_RESET_PADDR       0x00000000
+#define XCHAL_RESET_VECBASE_OVERLAP     0
+
+#define XCHAL_RESET_VECTOR0_VADDR       0xFE000000
+#define XCHAL_RESET_VECTOR0_PADDR       0xFE000000
+#define XCHAL_RESET_VECTOR1_VADDR       0xD8000500
+#define XCHAL_RESET_VECTOR1_PADDR       0x00000500
+#define XCHAL_RESET_VECTOR_VADDR        0xFE000000
+#define XCHAL_RESET_VECTOR_PADDR        0xFE000000
+#define XCHAL_USER_VECOFS               0x00000340
+#define XCHAL_USER_VECTOR_VADDR         0xD0000340
+#define XCHAL_USER_VECTOR_PADDR         0x00000340
+#define XCHAL_KERNEL_VECOFS             0x00000300
+#define XCHAL_KERNEL_VECTOR_VADDR       0xD0000300
+#define XCHAL_KERNEL_VECTOR_PADDR       0x00000300
+#define XCHAL_DOUBLEEXC_VECOFS          0x000003C0
+#define XCHAL_DOUBLEEXC_VECTOR_VADDR    0xD00003C0
+#define XCHAL_DOUBLEEXC_VECTOR_PADDR    0x000003C0
+#define XCHAL_WINDOW_OF4_VECOFS         0x00000000
+#define XCHAL_WINDOW_UF4_VECOFS         0x00000040
+#define XCHAL_WINDOW_OF8_VECOFS         0x00000080
+#define XCHAL_WINDOW_UF8_VECOFS         0x000000C0
+#define XCHAL_WINDOW_OF12_VECOFS        0x00000100
+#define XCHAL_WINDOW_UF12_VECOFS        0x00000140
+#define XCHAL_WINDOW_VECTORS_VADDR      0xD0000000
+#define XCHAL_WINDOW_VECTORS_PADDR      0x00000000
+#define XCHAL_INTLEVEL2_VECOFS          0x00000180
+#define XCHAL_INTLEVEL2_VECTOR_VADDR    0xD0000180
+#define XCHAL_INTLEVEL2_VECTOR_PADDR    0x00000180
+#define XCHAL_INTLEVEL3_VECOFS          0x000001C0
+#define XCHAL_INTLEVEL3_VECTOR_VADDR    0xD00001C0
+#define XCHAL_INTLEVEL3_VECTOR_PADDR    0x000001C0
+#define XCHAL_INTLEVEL4_VECOFS          0x00000200
+#define XCHAL_INTLEVEL4_VECTOR_VADDR    0xD0000200
+#define XCHAL_INTLEVEL4_VECTOR_PADDR    0x00000200
+#define XCHAL_INTLEVEL5_VECOFS          0x00000240
+#define XCHAL_INTLEVEL5_VECTOR_VADDR    0xD0000240
+#define XCHAL_INTLEVEL5_VECTOR_PADDR    0x00000240
+#define XCHAL_INTLEVEL6_VECOFS          0x00000280
+#define XCHAL_INTLEVEL6_VECTOR_VADDR    0xD0000280
+#define XCHAL_INTLEVEL6_VECTOR_PADDR    0x00000280
+#define XCHAL_DEBUG_VECOFS              XCHAL_INTLEVEL6_VECOFS
+#define XCHAL_DEBUG_VECTOR_VADDR        XCHAL_INTLEVEL6_VECTOR_VADDR
+#define XCHAL_DEBUG_VECTOR_PADDR        XCHAL_INTLEVEL6_VECTOR_PADDR
+#define XCHAL_NMI_VECOFS                0x000002C0
+#define XCHAL_NMI_VECTOR_VADDR          0xD00002C0
+#define XCHAL_NMI_VECTOR_PADDR          0x000002C0
+#define XCHAL_INTLEVEL7_VECOFS          XCHAL_NMI_VECOFS
+#define XCHAL_INTLEVEL7_VECTOR_VADDR    XCHAL_NMI_VECTOR_VADDR
+#define XCHAL_INTLEVEL7_VECTOR_PADDR    XCHAL_NMI_VECTOR_PADDR
+
+
+/*----------------------------------------------------------------------
+                                DEBUG
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_OCD                  1       /* OnChipDebug option */
+#define XCHAL_NUM_IBREAK                2       /* number of IBREAKn regs */
+#define XCHAL_NUM_DBREAK                2       /* number of DBREAKn regs */
+#define XCHAL_HAVE_OCD_DIR_ARRAY        1       /* faster OCD option */
+
+
+/*----------------------------------------------------------------------
+                                MMU
+  ----------------------------------------------------------------------*/
+
+/*  See core-matmap.h header file for more details.  */
+
+#define XCHAL_HAVE_TLBS                 1       /* inverse of HAVE_CACHEATTR */
+#define XCHAL_HAVE_SPANNING_WAY         0       /* one way maps I+D 4GB vaddr */
+#define XCHAL_HAVE_IDENTITY_MAP         0       /* vaddr == paddr always */
+#define XCHAL_HAVE_CACHEATTR            0       /* CACHEATTR register present */
+#define XCHAL_HAVE_MIMIC_CACHEATTR      0       /* region protection */
+#define XCHAL_HAVE_XLT_CACHEATTR        0       /* region prot. w/translation */
+#define XCHAL_HAVE_PTP_MMU              1       /* full MMU (with page table
+                                                   [autorefill] and protection)
+                                                   usable for an MMU-based OS */
+/*  If none of the above last 4 are set, it's a custom TLB configuration.  */
+#define XCHAL_ITLB_ARF_ENTRIES_LOG2     2       /* log2(autorefill way size) */
+#define XCHAL_DTLB_ARF_ENTRIES_LOG2     2       /* log2(autorefill way size) */
+
+#define XCHAL_MMU_ASID_BITS             8       /* number of bits in ASIDs */
+#define XCHAL_MMU_RINGS                 4       /* number of rings (1..4) */
+#define XCHAL_MMU_RING_BITS             2       /* num of bits in RING field */
+
+#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */
+
+
+#endif /* _XTENSA_CORE_CONFIGURATION_H */
diff --git a/target-xtensa/core-dc232b/gdb-config.c b/target-xtensa/core-dc232b/gdb-config.c
new file mode 100644
index 0000000..13aba5e
--- /dev/null
+++ b/target-xtensa/core-dc232b/gdb-config.c
@@ -0,0 +1,261 @@
+/* Configuration for the Xtensa architecture for GDB, the GNU debugger.
+
+   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+  XTREG(0,   0, 32, 4, 4, 0x0020, 0x0006, -2, 9, 0x0100, pc,
+          0, 0, 0, 0, 0, 0)
+  XTREG(1,   4, 32, 4, 4, 0x0100, 0x0006, -2, 1, 0x0002, ar0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(2,   8, 32, 4, 4, 0x0101, 0x0006, -2, 1, 0x0002, ar1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(3,  12, 32, 4, 4, 0x0102, 0x0006, -2, 1, 0x0002, ar2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(4,  16, 32, 4, 4, 0x0103, 0x0006, -2, 1, 0x0002, ar3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(5,  20, 32, 4, 4, 0x0104, 0x0006, -2, 1, 0x0002, ar4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(6,  24, 32, 4, 4, 0x0105, 0x0006, -2, 1, 0x0002, ar5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(7,  28, 32, 4, 4, 0x0106, 0x0006, -2, 1, 0x0002, ar6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(8,  32, 32, 4, 4, 0x0107, 0x0006, -2, 1, 0x0002, ar7,
+          0, 0, 0, 0, 0, 0)
+  XTREG(9,  36, 32, 4, 4, 0x0108, 0x0006, -2, 1, 0x0002, ar8,
+          0, 0, 0, 0, 0, 0)
+  XTREG(10,  40, 32, 4, 4, 0x0109, 0x0006, -2, 1, 0x0002, ar9,
+          0, 0, 0, 0, 0, 0)
+  XTREG(11,  44, 32, 4, 4, 0x010a, 0x0006, -2, 1, 0x0002, ar10,
+          0, 0, 0, 0, 0, 0)
+  XTREG(12,  48, 32, 4, 4, 0x010b, 0x0006, -2, 1, 0x0002, ar11,
+          0, 0, 0, 0, 0, 0)
+  XTREG(13,  52, 32, 4, 4, 0x010c, 0x0006, -2, 1, 0x0002, ar12,
+          0, 0, 0, 0, 0, 0)
+  XTREG(14,  56, 32, 4, 4, 0x010d, 0x0006, -2, 1, 0x0002, ar13,
+          0, 0, 0, 0, 0, 0)
+  XTREG(15,  60, 32, 4, 4, 0x010e, 0x0006, -2, 1, 0x0002, ar14,
+          0, 0, 0, 0, 0, 0)
+  XTREG(16,  64, 32, 4, 4, 0x010f, 0x0006, -2, 1, 0x0002, ar15,
+          0, 0, 0, 0, 0, 0)
+  XTREG(17,  68, 32, 4, 4, 0x0110, 0x0006, -2, 1, 0x0002, ar16,
+          0, 0, 0, 0, 0, 0)
+  XTREG(18,  72, 32, 4, 4, 0x0111, 0x0006, -2, 1, 0x0002, ar17,
+          0, 0, 0, 0, 0, 0)
+  XTREG(19,  76, 32, 4, 4, 0x0112, 0x0006, -2, 1, 0x0002, ar18,
+          0, 0, 0, 0, 0, 0)
+  XTREG(20,  80, 32, 4, 4, 0x0113, 0x0006, -2, 1, 0x0002, ar19,
+          0, 0, 0, 0, 0, 0)
+  XTREG(21,  84, 32, 4, 4, 0x0114, 0x0006, -2, 1, 0x0002, ar20,
+          0, 0, 0, 0, 0, 0)
+  XTREG(22,  88, 32, 4, 4, 0x0115, 0x0006, -2, 1, 0x0002, ar21,
+          0, 0, 0, 0, 0, 0)
+  XTREG(23,  92, 32, 4, 4, 0x0116, 0x0006, -2, 1, 0x0002, ar22,
+          0, 0, 0, 0, 0, 0)
+  XTREG(24,  96, 32, 4, 4, 0x0117, 0x0006, -2, 1, 0x0002, ar23,
+          0, 0, 0, 0, 0, 0)
+  XTREG(25, 100, 32, 4, 4, 0x0118, 0x0006, -2, 1, 0x0002, ar24,
+          0, 0, 0, 0, 0, 0)
+  XTREG(26, 104, 32, 4, 4, 0x0119, 0x0006, -2, 1, 0x0002, ar25,
+          0, 0, 0, 0, 0, 0)
+  XTREG(27, 108, 32, 4, 4, 0x011a, 0x0006, -2, 1, 0x0002, ar26,
+          0, 0, 0, 0, 0, 0)
+  XTREG(28, 112, 32, 4, 4, 0x011b, 0x0006, -2, 1, 0x0002, ar27,
+          0, 0, 0, 0, 0, 0)
+  XTREG(29, 116, 32, 4, 4, 0x011c, 0x0006, -2, 1, 0x0002, ar28,
+          0, 0, 0, 0, 0, 0)
+  XTREG(30, 120, 32, 4, 4, 0x011d, 0x0006, -2, 1, 0x0002, ar29,
+          0, 0, 0, 0, 0, 0)
+  XTREG(31, 124, 32, 4, 4, 0x011e, 0x0006, -2, 1, 0x0002, ar30,
+          0, 0, 0, 0, 0, 0)
+  XTREG(32, 128, 32, 4, 4, 0x011f, 0x0006, -2, 1, 0x0002, ar31,
+          0, 0, 0, 0, 0, 0)
+  XTREG(33, 132, 32, 4, 4, 0x0200, 0x0006, -2, 2, 0x1100, lbeg,
+          0, 0, 0, 0, 0, 0)
+  XTREG(34, 136, 32, 4, 4, 0x0201, 0x0006, -2, 2, 0x1100, lend,
+          0, 0, 0, 0, 0, 0)
+  XTREG(35, 140, 32, 4, 4, 0x0202, 0x0006, -2, 2, 0x1100, lcount,
+          0, 0, 0, 0, 0, 0)
+  XTREG(36, 144,  6, 4, 4, 0x0203, 0x0006, -2, 2, 0x1100, sar,
+          0, 0, 0, 0, 0, 0)
+  XTREG(37, 148, 32, 4, 4, 0x0205, 0x0006, -2, 2, 0x1100, litbase,
+          0, 0, 0, 0, 0, 0)
+  XTREG(38, 152,  3, 4, 4, 0x0248, 0x0006, -2, 2, 0x1002, windowbase,
+          0, 0, 0, 0, 0, 0)
+  XTREG(39, 156,  8, 4, 4, 0x0249, 0x0006, -2, 2, 0x1002, windowstart,
+          0, 0, 0, 0, 0, 0)
+  XTREG(40, 160, 32, 4, 4, 0x02b0, 0x0002, -2, 2, 0x1000, sr176,
+          0, 0, 0, 0, 0, 0)
+  XTREG(41, 164, 32, 4, 4, 0x02d0, 0x0002, -2, 2, 0x1000, sr208,
+          0, 0, 0, 0, 0, 0)
+  XTREG(42, 168, 19, 4, 4, 0x02e6, 0x0006, -2, 2, 0x1100, ps,
+          0, 0, 0, 0, 0, 0)
+  XTREG(43, 172, 32, 4, 4, 0x03e7, 0x0006, -2, 3, 0x0110, threadptr,
+          0, 0, 0, 0, 0, 0)
+  XTREG(44, 176, 32, 4, 4, 0x020c, 0x0006, -1, 2, 0x1100, scompare1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(45, 180, 32, 4, 4, 0x0210, 0x0006, -1, 2, 0x1100, acclo,
+          0, 0, 0, 0, 0, 0)
+  XTREG(46, 184,  8, 4, 4, 0x0211, 0x0006, -1, 2, 0x1100, acchi,
+          0, 0, 0, 0, 0, 0)
+  XTREG(47, 188, 32, 4, 4, 0x0220, 0x0006, -1, 2, 0x1100, m0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(48, 192, 32, 4, 4, 0x0221, 0x0006, -1, 2, 0x1100, m1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(49, 196, 32, 4, 4, 0x0222, 0x0006, -1, 2, 0x1100, m2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(50, 200, 32, 4, 4, 0x0223, 0x0006, -1, 2, 0x1100, m3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(51, 204, 32, 4, 4, 0x03e6, 0x000e, -1, 3, 0x0110, expstate,
+          0, 0, 0, 0, 0, 0)
+  XTREG(52, 208, 32, 4, 4, 0x0253, 0x0007, -2, 2, 0x1000, ptevaddr,
+          0, 0, 0, 0, 0, 0)
+  XTREG(53, 212, 32, 4, 4, 0x0259, 0x000d, -2, 2, 0x1000, mmid,
+          0, 0, 0, 0, 0, 0)
+  XTREG(54, 216, 32, 4, 4, 0x025a, 0x0007, -2, 2, 0x1000, rasid,
+          0, 0, 0, 0, 0, 0)
+  XTREG(55, 220, 18, 4, 4, 0x025b, 0x0007, -2, 2, 0x1000, itlbcfg,
+          0, 0, 0, 0, 0, 0)
+  XTREG(56, 224, 18, 4, 4, 0x025c, 0x0007, -2, 2, 0x1000, dtlbcfg,
+          0, 0, 0, 0, 0, 0)
+  XTREG(57, 228,  2, 4, 4, 0x0260, 0x0007, -2, 2, 0x1000, ibreakenable,
+          0, 0, 0, 0, 0, 0)
+  XTREG(58, 232, 32, 4, 4, 0x0268, 0x0007, -2, 2, 0x1000, ddr,
+          0, 0, 0, 0, 0, 0)
+  XTREG(59, 236, 32, 4, 4, 0x0280, 0x0007, -2, 2, 0x1000, ibreaka0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(60, 240, 32, 4, 4, 0x0281, 0x0007, -2, 2, 0x1000, ibreaka1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(61, 244, 32, 4, 4, 0x0290, 0x0007, -2, 2, 0x1000, dbreaka0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(62, 248, 32, 4, 4, 0x0291, 0x0007, -2, 2, 0x1000, dbreaka1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(63, 252, 32, 4, 4, 0x02a0, 0x0007, -2, 2, 0x1000, dbreakc0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(64, 256, 32, 4, 4, 0x02a1, 0x0007, -2, 2, 0x1000, dbreakc1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(65, 260, 32, 4, 4, 0x02b1, 0x0007, -2, 2, 0x1000, epc1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(66, 264, 32, 4, 4, 0x02b2, 0x0007, -2, 2, 0x1000, epc2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(67, 268, 32, 4, 4, 0x02b3, 0x0007, -2, 2, 0x1000, epc3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(68, 272, 32, 4, 4, 0x02b4, 0x0007, -2, 2, 0x1000, epc4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(69, 276, 32, 4, 4, 0x02b5, 0x0007, -2, 2, 0x1000, epc5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(70, 280, 32, 4, 4, 0x02b6, 0x0007, -2, 2, 0x1000, epc6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(71, 284, 32, 4, 4, 0x02b7, 0x0007, -2, 2, 0x1000, epc7,
+          0, 0, 0, 0, 0, 0)
+  XTREG(72, 288, 32, 4, 4, 0x02c0, 0x0007, -2, 2, 0x1000, depc,
+          0, 0, 0, 0, 0, 0)
+  XTREG(73, 292, 19, 4, 4, 0x02c2, 0x0007, -2, 2, 0x1000, eps2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(74, 296, 19, 4, 4, 0x02c3, 0x0007, -2, 2, 0x1000, eps3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(75, 300, 19, 4, 4, 0x02c4, 0x0007, -2, 2, 0x1000, eps4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(76, 304, 19, 4, 4, 0x02c5, 0x0007, -2, 2, 0x1000, eps5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(77, 308, 19, 4, 4, 0x02c6, 0x0007, -2, 2, 0x1000, eps6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(78, 312, 19, 4, 4, 0x02c7, 0x0007, -2, 2, 0x1000, eps7,
+          0, 0, 0, 0, 0, 0)
+  XTREG(79, 316, 32, 4, 4, 0x02d1, 0x0007, -2, 2, 0x1000, excsave1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(80, 320, 32, 4, 4, 0x02d2, 0x0007, -2, 2, 0x1000, excsave2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(81, 324, 32, 4, 4, 0x02d3, 0x0007, -2, 2, 0x1000, excsave3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(82, 328, 32, 4, 4, 0x02d4, 0x0007, -2, 2, 0x1000, excsave4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(83, 332, 32, 4, 4, 0x02d5, 0x0007, -2, 2, 0x1000, excsave5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(84, 336, 32, 4, 4, 0x02d6, 0x0007, -2, 2, 0x1000, excsave6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(85, 340, 32, 4, 4, 0x02d7, 0x0007, -2, 2, 0x1000, excsave7,
+          0, 0, 0, 0, 0, 0)
+  XTREG(86, 344,  8, 4, 4, 0x02e0, 0x0007, -2, 2, 0x1000, cpenable,
+          0, 0, 0, 0, 0, 0)
+  XTREG(87, 348, 22, 4, 4, 0x02e2, 0x000b, -2, 2, 0x1000, interrupt,
+          0, 0, 0, 0, 0, 0)
+  XTREG(88, 352, 22, 4, 4, 0x02e2, 0x000d, -2, 2, 0x1000, intset,
+          0, 0, 0, 0, 0, 0)
+  XTREG(89, 356, 22, 4, 4, 0x02e3, 0x000d, -2, 2, 0x1000, intclear,
+          0, 0, 0, 0, 0, 0)
+  XTREG(90, 360, 22, 4, 4, 0x02e4, 0x0007, -2, 2, 0x1000, intenable,
+          0, 0, 0, 0, 0, 0)
+  XTREG(91, 364, 32, 4, 4, 0x02e7, 0x0007, -2, 2, 0x1000, vecbase,
+          0, 0, 0, 0, 0, 0)
+  XTREG(92, 368,  6, 4, 4, 0x02e8, 0x0007, -2, 2, 0x1000, exccause,
+          0, 0, 0, 0, 0, 0)
+  XTREG(93, 372, 12, 4, 4, 0x02e9, 0x0003, -2, 2, 0x1000, debugcause,
+          0, 0, 0, 0, 0, 0)
+  XTREG(94, 376, 32, 4, 4, 0x02ea, 0x000f, -2, 2, 0x1000, ccount,
+          0, 0, 0, 0, 0, 0)
+  XTREG(95, 380, 32, 4, 4, 0x02eb, 0x0003, -2, 2, 0x1000, prid,
+          0, 0, 0, 0, 0, 0)
+  XTREG(96, 384, 32, 4, 4, 0x02ec, 0x000f, -2, 2, 0x1000, icount,
+          0, 0, 0, 0, 0, 0)
+  XTREG(97, 388,  4, 4, 4, 0x02ed, 0x0007, -2, 2, 0x1000, icountlevel,
+          0, 0, 0, 0, 0, 0)
+  XTREG(98, 392, 32, 4, 4, 0x02ee, 0x0007, -2, 2, 0x1000, excvaddr,
+          0, 0, 0, 0, 0, 0)
+  XTREG(99, 396, 32, 4, 4, 0x02f0, 0x000f, -2, 2, 0x1000, ccompare0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(100, 400, 32, 4, 4, 0x02f1, 0x000f, -2, 2, 0x1000, ccompare1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(101, 404, 32, 4, 4, 0x02f2, 0x000f, -2, 2, 0x1000, ccompare2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(102, 408, 32, 4, 4, 0x02f4, 0x0007, -2, 2, 0x1000, misc0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(103, 412, 32, 4, 4, 0x02f5, 0x0007, -2, 2, 0x1000, misc1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(104, 416, 32, 4, 4, 0x0000, 0x0006, -2, 8, 0x0100, a0,
+          0, 0, 0, 0, 0, 0)
+  XTREG(105, 420, 32, 4, 4, 0x0001, 0x0006, -2, 8, 0x0100, a1,
+          0, 0, 0, 0, 0, 0)
+  XTREG(106, 424, 32, 4, 4, 0x0002, 0x0006, -2, 8, 0x0100, a2,
+          0, 0, 0, 0, 0, 0)
+  XTREG(107, 428, 32, 4, 4, 0x0003, 0x0006, -2, 8, 0x0100, a3,
+          0, 0, 0, 0, 0, 0)
+  XTREG(108, 432, 32, 4, 4, 0x0004, 0x0006, -2, 8, 0x0100, a4,
+          0, 0, 0, 0, 0, 0)
+  XTREG(109, 436, 32, 4, 4, 0x0005, 0x0006, -2, 8, 0x0100, a5,
+          0, 0, 0, 0, 0, 0)
+  XTREG(110, 440, 32, 4, 4, 0x0006, 0x0006, -2, 8, 0x0100, a6,
+          0, 0, 0, 0, 0, 0)
+  XTREG(111, 444, 32, 4, 4, 0x0007, 0x0006, -2, 8, 0x0100, a7,
+          0, 0, 0, 0, 0, 0)
+  XTREG(112, 448, 32, 4, 4, 0x0008, 0x0006, -2, 8, 0x0100, a8,
+          0, 0, 0, 0, 0, 0)
+  XTREG(113, 452, 32, 4, 4, 0x0009, 0x0006, -2, 8, 0x0100, a9,
+          0, 0, 0, 0, 0, 0)
+  XTREG(114, 456, 32, 4, 4, 0x000a, 0x0006, -2, 8, 0x0100, a10,
+          0, 0, 0, 0, 0, 0)
+  XTREG(115, 460, 32, 4, 4, 0x000b, 0x0006, -2, 8, 0x0100, a11,
+          0, 0, 0, 0, 0, 0)
+  XTREG(116, 464, 32, 4, 4, 0x000c, 0x0006, -2, 8, 0x0100, a12,
+          0, 0, 0, 0, 0, 0)
+  XTREG(117, 468, 32, 4, 4, 0x000d, 0x0006, -2, 8, 0x0100, a13,
+          0, 0, 0, 0, 0, 0)
+  XTREG(118, 472, 32, 4, 4, 0x000e, 0x0006, -2, 8, 0x0100, a14,
+          0, 0, 0, 0, 0, 0)
+  XTREG(119, 476, 32, 4, 4, 0x000f, 0x0006, -2, 8, 0x0100, a15,
+          0, 0, 0, 0, 0, 0)
commit ac8b7db4934fcf38b49c4024feb7d5f0e1311e23
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Oct 16 02:56:04 2011 +0400

    target-xtensa: extract core configuration from overlay
    
    Introduce overlay_tool.h that defines core configuration blocks from
    data available in the linux architecture variant overlay.
    
    Overlay data is automatically generated in the core configuration
    process by Tensilica tools and can be directly converted to qemu xtensa
    core description by overlay_tool.h
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 9d36c1b..0db83a6 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -285,6 +285,11 @@ typedef struct XtensaConfig {
     xtensa_tlb dtlb;
 } XtensaConfig;
 
+typedef struct XtensaConfigList {
+    const XtensaConfig *config;
+    struct XtensaConfigList *next;
+} XtensaConfigList;
+
 typedef struct CPUXtensaState {
     const XtensaConfig *config;
     uint32_t regs[16];
@@ -317,6 +322,7 @@ typedef struct CPUXtensaState {
 CPUXtensaState *cpu_xtensa_init(const char *cpu_model);
 void xtensa_translate_init(void);
 int cpu_xtensa_exec(CPUXtensaState *s);
+void xtensa_register_core(XtensaConfigList *node);
 void do_interrupt(CPUXtensaState *s);
 void check_interrupts(CPUXtensaState *s);
 void xtensa_irq_init(CPUState *env);
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index f8b2b78..fc85815 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -34,12 +34,6 @@
 #include "hw/loader.h"
 #endif
 
-#define XTREG(idx, ofs, bi, sz, al, no, flags, cp, typ, grp, name, \
-        a1, a2, a3, a4, a5, a6) \
-    { .targno = (no), .type = (typ), .group = (grp) },
-
-static const XtensaConfig core_config[0];
-
 static void reset_mmu(CPUState *env);
 
 void cpu_reset(CPUXtensaState *env)
@@ -55,17 +49,24 @@ void cpu_reset(CPUXtensaState *env)
     reset_mmu(env);
 }
 
+static struct XtensaConfigList *xtensa_cores;
+
+void xtensa_register_core(XtensaConfigList *node)
+{
+    node->next = xtensa_cores;
+    xtensa_cores = node;
+}
 
 CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
 {
     static int tcg_inited;
     CPUXtensaState *env;
     const XtensaConfig *config = NULL;
-    int i;
+    XtensaConfigList *core = xtensa_cores;
 
-    for (i = 0; i < ARRAY_SIZE(core_config); ++i)
-        if (strcmp(core_config[i].name, cpu_model) == 0) {
-            config = core_config + i;
+    for (; core; core = core->next)
+        if (strcmp(core->config->name, cpu_model) == 0) {
+            config = core->config;
             break;
         }
 
@@ -90,10 +91,10 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
 
 void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf)
 {
-    int i;
+    XtensaConfigList *core = xtensa_cores;
     cpu_fprintf(f, "Available CPUs:\n");
-    for (i = 0; i < ARRAY_SIZE(core_config); ++i) {
-        cpu_fprintf(f, "  %s\n", core_config[i].name);
+    for (; core; core = core->next) {
+        cpu_fprintf(f, "  %s\n", core->config->name);
     }
 }
 
diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h
new file mode 100644
index 0000000..060e8e5
--- /dev/null
+++ b/target-xtensa/overlay_tool.h
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define XTREG(idx, ofs, bi, sz, al, no, flags, cp, typ, grp, name, \
+        a1, a2, a3, a4, a5, a6) \
+    { .targno = (no), .type = (typ), .group = (grp) },
+
+#ifndef XCHAL_HAVE_DIV32
+#define XCHAL_HAVE_DIV32 0
+#endif
+
+#ifndef XCHAL_UNALIGNED_LOAD_HW
+#define XCHAL_UNALIGNED_LOAD_HW 0
+#endif
+
+#ifndef XCHAL_HAVE_VECBASE
+#define XCHAL_HAVE_VECBASE 0
+#define XCHAL_VECBASE_RESET_VADDR 0
+#endif
+
+#define XCHAL_OPTION(xchal, qemu) ((xchal) ? XTENSA_OPTION_BIT(qemu) : 0)
+
+#define XTENSA_OPTIONS ( \
+    XCHAL_OPTION(XCHAL_HAVE_DENSITY, XTENSA_OPTION_CODE_DENSITY) | \
+    XCHAL_OPTION(XCHAL_HAVE_LOOPS, XTENSA_OPTION_LOOP) | \
+    XCHAL_OPTION(XCHAL_HAVE_ABSOLUTE_LITERALS, XTENSA_OPTION_EXTENDED_L32R) | \
+    XCHAL_OPTION(XCHAL_HAVE_MUL16, XTENSA_OPTION_16_BIT_IMUL) | \
+    XCHAL_OPTION(XCHAL_HAVE_MUL32, XTENSA_OPTION_32_BIT_IMUL) | \
+    XCHAL_OPTION(XCHAL_HAVE_MUL32_HIGH, XTENSA_OPTION_32_BIT_IMUL_HIGH) | \
+    XCHAL_OPTION(XCHAL_HAVE_DIV32, XTENSA_OPTION_32_BIT_IDIV) | \
+    XCHAL_OPTION(XCHAL_HAVE_MAC16, XTENSA_OPTION_MAC16) | \
+    XCHAL_OPTION(XCHAL_HAVE_NSA, XTENSA_OPTION_MISC_OP_NSA) | \
+    XCHAL_OPTION(XCHAL_HAVE_MINMAX, XTENSA_OPTION_MISC_OP_MINMAX) | \
+    XCHAL_OPTION(XCHAL_HAVE_SEXT, XTENSA_OPTION_MISC_OP_SEXT) | \
+    XCHAL_OPTION(XCHAL_HAVE_CLAMPS, XTENSA_OPTION_MISC_OP_CLAMPS) | \
+    XCHAL_OPTION(XCHAL_HAVE_CP, XTENSA_OPTION_COPROCESSOR) | \
+    XCHAL_OPTION(XCHAL_HAVE_FP, XTENSA_OPTION_FP_COPROCESSOR) | \
+    XCHAL_OPTION(XCHAL_HAVE_RELEASE_SYNC, XTENSA_OPTION_MP_SYNCHRO) | \
+    XCHAL_OPTION(XCHAL_HAVE_S32C1I, XTENSA_OPTION_CONDITIONAL_STORE) | \
+    /* Interrupts and exceptions */ \
+    XCHAL_OPTION(XCHAL_HAVE_EXCEPTIONS, XTENSA_OPTION_EXCEPTION) | \
+    XCHAL_OPTION(XCHAL_HAVE_VECBASE, XTENSA_OPTION_RELOCATABLE_VECTOR) | \
+    XCHAL_OPTION(XCHAL_UNALIGNED_LOAD_EXCEPTION, \
+        XTENSA_OPTION_UNALIGNED_EXCEPTION) | \
+    XCHAL_OPTION(XCHAL_HAVE_INTERRUPTS, XTENSA_OPTION_INTERRUPT) | \
+    XCHAL_OPTION(XCHAL_HAVE_HIGHPRI_INTERRUPTS, \
+        XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT) | \
+    XCHAL_OPTION(XCHAL_HAVE_CCOUNT, XTENSA_OPTION_TIMER_INTERRUPT) | \
+    /* Local memory, TODO */ \
+    XCHAL_OPTION(XCHAL_UNALIGNED_LOAD_HW, XTENSA_OPTION_HW_ALIGNMENT) | \
+    /* Memory protection and translation */ \
+    XCHAL_OPTION(XCHAL_HAVE_MIMIC_CACHEATTR, \
+            XTENSA_OPTION_REGION_PROTECTION) | \
+    XCHAL_OPTION(XCHAL_HAVE_XLT_CACHEATTR, \
+            XTENSA_OPTION_REGION_TRANSLATION) | \
+    XCHAL_OPTION(XCHAL_HAVE_PTP_MMU, XTENSA_OPTION_MMU) | \
+    /* Other, TODO */ \
+    XCHAL_OPTION(XCHAL_HAVE_WINDOWED, XTENSA_OPTION_WINDOWED_REGISTER) | \
+    XCHAL_OPTION(XCHAL_HAVE_DEBUG, XTENSA_OPTION_DEBUG))
+
+#ifndef XCHAL_WINDOW_OF4_VECOFS
+#define XCHAL_WINDOW_OF4_VECOFS         0x00000000
+#define XCHAL_WINDOW_UF4_VECOFS         0x00000040
+#define XCHAL_WINDOW_OF8_VECOFS         0x00000080
+#define XCHAL_WINDOW_UF8_VECOFS         0x000000C0
+#define XCHAL_WINDOW_OF12_VECOFS        0x00000100
+#define XCHAL_WINDOW_UF12_VECOFS        0x00000140
+#endif
+
+#define EXCEPTION_VECTORS { \
+        [EXC_RESET] = XCHAL_RESET_VECTOR_VADDR, \
+        [EXC_WINDOW_OVERFLOW4] = XCHAL_WINDOW_OF4_VECOFS + \
+            XCHAL_WINDOW_VECTORS_VADDR, \
+        [EXC_WINDOW_UNDERFLOW4] = XCHAL_WINDOW_UF4_VECOFS + \
+            XCHAL_WINDOW_VECTORS_VADDR, \
+        [EXC_WINDOW_OVERFLOW8] = XCHAL_WINDOW_OF8_VECOFS + \
+            XCHAL_WINDOW_VECTORS_VADDR, \
+        [EXC_WINDOW_UNDERFLOW8] = XCHAL_WINDOW_UF8_VECOFS + \
+            XCHAL_WINDOW_VECTORS_VADDR, \
+        [EXC_WINDOW_OVERFLOW12] = XCHAL_WINDOW_OF12_VECOFS + \
+            XCHAL_WINDOW_VECTORS_VADDR, \
+        [EXC_WINDOW_UNDERFLOW12] = XCHAL_WINDOW_UF12_VECOFS + \
+            XCHAL_WINDOW_VECTORS_VADDR, \
+        [EXC_KERNEL] = XCHAL_KERNEL_VECTOR_VADDR, \
+        [EXC_USER] = XCHAL_USER_VECTOR_VADDR, \
+        [EXC_DOUBLE] = XCHAL_DOUBLEEXC_VECTOR_VADDR, \
+    }
+
+#define INTERRUPT_VECTORS { \
+        0, \
+        0, \
+        XCHAL_INTLEVEL2_VECTOR_VADDR, \
+        XCHAL_INTLEVEL3_VECTOR_VADDR, \
+        XCHAL_INTLEVEL4_VECTOR_VADDR, \
+        XCHAL_INTLEVEL5_VECTOR_VADDR, \
+        XCHAL_INTLEVEL6_VECTOR_VADDR, \
+        XCHAL_INTLEVEL7_VECTOR_VADDR, \
+    }
+
+#define LEVEL_MASKS { \
+        [1] = XCHAL_INTLEVEL1_MASK, \
+        [2] = XCHAL_INTLEVEL2_MASK, \
+        [3] = XCHAL_INTLEVEL3_MASK, \
+        [4] = XCHAL_INTLEVEL4_MASK, \
+        [5] = XCHAL_INTLEVEL5_MASK, \
+        [6] = XCHAL_INTLEVEL6_MASK, \
+        [7] = XCHAL_INTLEVEL7_MASK, \
+    }
+
+#define INTTYPE_MASKS { \
+        [INTTYPE_EDGE] = XCHAL_INTTYPE_MASK_EXTERN_EDGE, \
+        [INTTYPE_NMI] = XCHAL_INTTYPE_MASK_NMI, \
+        [INTTYPE_SOFTWARE] = XCHAL_INTTYPE_MASK_SOFTWARE, \
+    }
+
+#define XTHAL_INTTYPE_EXTERN_LEVEL INTTYPE_LEVEL
+#define XTHAL_INTTYPE_EXTERN_EDGE INTTYPE_EDGE
+#define XTHAL_INTTYPE_NMI INTTYPE_NMI
+#define XTHAL_INTTYPE_SOFTWARE INTTYPE_SOFTWARE
+#define XTHAL_INTTYPE_TIMER INTTYPE_TIMER
+#define XTHAL_INTTYPE_TBD1 INTTYPE_DEBUG
+#define XTHAL_INTTYPE_TBD2 INTTYPE_WRITE_ERR
+#define XTHAL_INTTYPE_WRITE_ERROR INTTYPE_WRITE_ERR
+
+
+#define INTERRUPT(i) { \
+        .level = XCHAL_INT ## i ## _LEVEL, \
+        .inttype = XCHAL_INT ## i ## _TYPE, \
+    }
+
+#define INTERRUPTS { \
+        [0] = INTERRUPT(0), \
+        [1] = INTERRUPT(1), \
+        [2] = INTERRUPT(2), \
+        [3] = INTERRUPT(3), \
+        [4] = INTERRUPT(4), \
+        [5] = INTERRUPT(5), \
+        [6] = INTERRUPT(6), \
+        [7] = INTERRUPT(7), \
+        [8] = INTERRUPT(8), \
+        [9] = INTERRUPT(9), \
+        [10] = INTERRUPT(10), \
+        [11] = INTERRUPT(11), \
+        [12] = INTERRUPT(12), \
+        [13] = INTERRUPT(13), \
+        [14] = INTERRUPT(14), \
+        [15] = INTERRUPT(15), \
+        [16] = INTERRUPT(16), \
+        [17] = INTERRUPT(17), \
+        [18] = INTERRUPT(18), \
+        [19] = INTERRUPT(19), \
+        [20] = INTERRUPT(20), \
+        [21] = INTERRUPT(21), \
+        [22] = INTERRUPT(22), \
+        [23] = INTERRUPT(23), \
+        [24] = INTERRUPT(24), \
+        [25] = INTERRUPT(25), \
+        [26] = INTERRUPT(26), \
+        [27] = INTERRUPT(27), \
+        [28] = INTERRUPT(28), \
+        [29] = INTERRUPT(29), \
+        [30] = INTERRUPT(30), \
+        [31] = INTERRUPT(31), \
+    }
+
+#define TIMERINTS { \
+        [0] = XCHAL_TIMER0_INTERRUPT, \
+        [1] = XCHAL_TIMER1_INTERRUPT, \
+        [2] = XCHAL_TIMER2_INTERRUPT, \
+    }
+
+#define EXTINTS { \
+        [0] = XCHAL_EXTINT0_NUM, \
+        [1] = XCHAL_EXTINT1_NUM, \
+        [2] = XCHAL_EXTINT2_NUM, \
+        [3] = XCHAL_EXTINT3_NUM, \
+        [4] = XCHAL_EXTINT4_NUM, \
+        [5] = XCHAL_EXTINT5_NUM, \
+        [6] = XCHAL_EXTINT6_NUM, \
+        [7] = XCHAL_EXTINT7_NUM, \
+        [8] = XCHAL_EXTINT8_NUM, \
+        [9] = XCHAL_EXTINT9_NUM, \
+        [10] = XCHAL_EXTINT10_NUM, \
+        [11] = XCHAL_EXTINT11_NUM, \
+        [12] = XCHAL_EXTINT12_NUM, \
+        [13] = XCHAL_EXTINT13_NUM, \
+        [14] = XCHAL_EXTINT14_NUM, \
+        [15] = XCHAL_EXTINT15_NUM, \
+        [16] = XCHAL_EXTINT16_NUM, \
+        [17] = XCHAL_EXTINT17_NUM, \
+        [18] = XCHAL_EXTINT18_NUM, \
+        [19] = XCHAL_EXTINT19_NUM, \
+        [20] = XCHAL_EXTINT20_NUM, \
+        [21] = XCHAL_EXTINT21_NUM, \
+        [22] = XCHAL_EXTINT22_NUM, \
+        [23] = XCHAL_EXTINT23_NUM, \
+        [24] = XCHAL_EXTINT24_NUM, \
+        [25] = XCHAL_EXTINT25_NUM, \
+        [26] = XCHAL_EXTINT26_NUM, \
+        [27] = XCHAL_EXTINT27_NUM, \
+        [28] = XCHAL_EXTINT28_NUM, \
+        [29] = XCHAL_EXTINT29_NUM, \
+        [30] = XCHAL_EXTINT30_NUM, \
+        [31] = XCHAL_EXTINT31_NUM, \
+    }
+
+#define EXCEPTIONS_SECTION \
+    .excm_level = XCHAL_EXCM_LEVEL, \
+    .vecbase = XCHAL_VECBASE_RESET_VADDR, \
+    .exception_vector = EXCEPTION_VECTORS
+
+#define INTERRUPTS_SECTION \
+    .ninterrupt = XCHAL_NUM_INTERRUPTS, \
+    .nlevel = XCHAL_NUM_INTLEVELS, \
+    .interrupt_vector = INTERRUPT_VECTORS, \
+    .level_mask = LEVEL_MASKS, \
+    .inttype_mask = INTTYPE_MASKS, \
+    .interrupt = INTERRUPTS, \
+    .nccompare = XCHAL_NUM_TIMERS, \
+    .timerint = TIMERINTS, \
+    .nextint = XCHAL_NUM_EXTINTERRUPTS, \
+    .extint = EXTINTS
+
+#define TLB_TEMPLATE(ways, refill_way_size, way56) { \
+        .nways = ways, \
+        .way_size = { \
+            (refill_way_size), (refill_way_size), \
+            (refill_way_size), (refill_way_size), \
+            4, 2, 2, 1, 1, 1, \
+        }, \
+        .varway56 = (way56), \
+        .nrefillentries = (refill_way_size) * 4, \
+    }
+
+#define ITLB(varway56) \
+    TLB_TEMPLATE(7, 1 << XCHAL_ITLB_ARF_ENTRIES_LOG2, varway56)
+
+#define DTLB(varway56) \
+    TLB_TEMPLATE(10, 1 << XCHAL_DTLB_ARF_ENTRIES_LOG2, varway56)
+
+#if XCHAL_HAVE_PTP_MMU
+#define TLB_SECTION \
+    .itlb = ITLB(XCHAL_HAVE_SPANNING_WAY), \
+    .dtlb = DTLB(XCHAL_HAVE_SPANNING_WAY)
+#else
+#endif
+
+#if (defined(TARGET_WORDS_BIGENDIAN) != 0) == (XCHAL_HAVE_BE != 0)
+#define REGISTER_CORE(core) \
+    static void __attribute__((constructor)) register_core(void) \
+    { \
+        static XtensaConfigList node = { \
+            .config = &core, \
+        }; \
+        xtensa_register_core(&node); \
+    }
+#else
+#define REGISTER_CORE(core)
+#endif
+
+
+#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI + 1 <= 2
+#define XCHAL_INTLEVEL2_VECTOR_VADDR 0
+#endif
+#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI + 1 <= 3
+#define XCHAL_INTLEVEL3_VECTOR_VADDR 0
+#endif
+#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI + 1 <= 4
+#define XCHAL_INTLEVEL4_VECTOR_VADDR 0
+#endif
+#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI + 1 <= 5
+#define XCHAL_INTLEVEL5_VECTOR_VADDR 0
+#endif
+#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI + 1 <= 6
+#define XCHAL_INTLEVEL6_VECTOR_VADDR 0
+#endif
+#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI + 1 <= 7
+#define XCHAL_INTLEVEL7_VECTOR_VADDR 0
+#endif
+
+
+#if XCHAL_NUM_INTERRUPTS <= 0
+#define XCHAL_INT0_LEVEL 0
+#define XCHAL_INT0_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 1
+#define XCHAL_INT1_LEVEL 0
+#define XCHAL_INT1_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 2
+#define XCHAL_INT2_LEVEL 0
+#define XCHAL_INT2_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 3
+#define XCHAL_INT3_LEVEL 0
+#define XCHAL_INT3_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 4
+#define XCHAL_INT4_LEVEL 0
+#define XCHAL_INT4_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 5
+#define XCHAL_INT5_LEVEL 0
+#define XCHAL_INT5_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 6
+#define XCHAL_INT6_LEVEL 0
+#define XCHAL_INT6_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 7
+#define XCHAL_INT7_LEVEL 0
+#define XCHAL_INT7_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 8
+#define XCHAL_INT8_LEVEL 0
+#define XCHAL_INT8_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 9
+#define XCHAL_INT9_LEVEL 0
+#define XCHAL_INT9_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 10
+#define XCHAL_INT10_LEVEL 0
+#define XCHAL_INT10_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 11
+#define XCHAL_INT11_LEVEL 0
+#define XCHAL_INT11_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 12
+#define XCHAL_INT12_LEVEL 0
+#define XCHAL_INT12_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 13
+#define XCHAL_INT13_LEVEL 0
+#define XCHAL_INT13_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 14
+#define XCHAL_INT14_LEVEL 0
+#define XCHAL_INT14_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 15
+#define XCHAL_INT15_LEVEL 0
+#define XCHAL_INT15_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 16
+#define XCHAL_INT16_LEVEL 0
+#define XCHAL_INT16_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 17
+#define XCHAL_INT17_LEVEL 0
+#define XCHAL_INT17_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 18
+#define XCHAL_INT18_LEVEL 0
+#define XCHAL_INT18_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 19
+#define XCHAL_INT19_LEVEL 0
+#define XCHAL_INT19_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 20
+#define XCHAL_INT20_LEVEL 0
+#define XCHAL_INT20_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 21
+#define XCHAL_INT21_LEVEL 0
+#define XCHAL_INT21_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 22
+#define XCHAL_INT22_LEVEL 0
+#define XCHAL_INT22_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 23
+#define XCHAL_INT23_LEVEL 0
+#define XCHAL_INT23_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 24
+#define XCHAL_INT24_LEVEL 0
+#define XCHAL_INT24_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 25
+#define XCHAL_INT25_LEVEL 0
+#define XCHAL_INT25_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 26
+#define XCHAL_INT26_LEVEL 0
+#define XCHAL_INT26_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 27
+#define XCHAL_INT27_LEVEL 0
+#define XCHAL_INT27_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 28
+#define XCHAL_INT28_LEVEL 0
+#define XCHAL_INT28_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 29
+#define XCHAL_INT29_LEVEL 0
+#define XCHAL_INT29_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 30
+#define XCHAL_INT30_LEVEL 0
+#define XCHAL_INT30_TYPE 0
+#endif
+#if XCHAL_NUM_INTERRUPTS <= 31
+#define XCHAL_INT31_LEVEL 0
+#define XCHAL_INT31_TYPE 0
+#endif
+
+
+#if XCHAL_NUM_EXTINTERRUPTS <= 0
+#define XCHAL_EXTINT0_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 1
+#define XCHAL_EXTINT1_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 2
+#define XCHAL_EXTINT2_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 3
+#define XCHAL_EXTINT3_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 4
+#define XCHAL_EXTINT4_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 5
+#define XCHAL_EXTINT5_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 6
+#define XCHAL_EXTINT6_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 7
+#define XCHAL_EXTINT7_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 8
+#define XCHAL_EXTINT8_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 9
+#define XCHAL_EXTINT9_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 10
+#define XCHAL_EXTINT10_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 11
+#define XCHAL_EXTINT11_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 12
+#define XCHAL_EXTINT12_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 13
+#define XCHAL_EXTINT13_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 14
+#define XCHAL_EXTINT14_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 15
+#define XCHAL_EXTINT15_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 16
+#define XCHAL_EXTINT16_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 17
+#define XCHAL_EXTINT17_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 18
+#define XCHAL_EXTINT18_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 19
+#define XCHAL_EXTINT19_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 20
+#define XCHAL_EXTINT20_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 21
+#define XCHAL_EXTINT21_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 22
+#define XCHAL_EXTINT22_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 23
+#define XCHAL_EXTINT23_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 24
+#define XCHAL_EXTINT24_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 25
+#define XCHAL_EXTINT25_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 26
+#define XCHAL_EXTINT26_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 27
+#define XCHAL_EXTINT27_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 28
+#define XCHAL_EXTINT28_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 29
+#define XCHAL_EXTINT29_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 30
+#define XCHAL_EXTINT30_NUM 0
+#endif
+#if XCHAL_NUM_EXTINTERRUPTS <= 31
+#define XCHAL_EXTINT31_NUM 0
+#endif
+
+
+#define XTHAL_TIMER_UNCONFIGURED 0
commit b8929a549f3e97b6cc2dfd22ba83612a1bb625ec
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Oct 16 02:56:03 2011 +0400

    target-xtensa: implement external interrupt mapping
    
    Xtensa cores may have different mapping of external interrupt pins to
    internal IRQ numers. Implement API to acquire core IRQ by its external
    interrupt number.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
index e5085ea..93e28fd 100644
--- a/hw/xtensa_pic.c
+++ b/hw/xtensa_pic.c
@@ -157,3 +157,15 @@ void xtensa_irq_init(CPUState *env)
             qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, env);
     }
 }
+
+void *xtensa_get_extint(CPUState *env, unsigned extint)
+{
+    if (extint < env->config->nextint) {
+        unsigned irq = env->config->extint[extint];
+        return env->irq_inputs[irq];
+    } else {
+        qemu_log("%s: trying to acquire invalid external interrupt %d\n",
+                __func__, extint);
+        return NULL;
+    }
+}
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index df168d5..9d36c1b 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -277,6 +277,8 @@ typedef struct XtensaConfig {
     } interrupt[MAX_NINTERRUPT];
     unsigned nccompare;
     uint32_t timerint[MAX_NCCOMPARE];
+    unsigned nextint;
+    unsigned extint[MAX_NINTERRUPT];
     uint32_t clock_freq_khz;
 
     xtensa_tlb itlb;
@@ -318,6 +320,7 @@ int cpu_xtensa_exec(CPUXtensaState *s);
 void do_interrupt(CPUXtensaState *s);
 void check_interrupts(CPUXtensaState *s);
 void xtensa_irq_init(CPUState *env);
+void *xtensa_get_extint(CPUState *env, unsigned extint);
 void xtensa_advance_ccount(CPUState *env, uint32_t d);
 void xtensa_timer_irq(CPUState *env, uint32_t id, uint32_t active);
 void xtensa_rearm_ccompare_timer(CPUState *env);
commit 63f95e4c652fd35df7e048574dcb468b404a6f4e
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Sun Oct 16 02:56:02 2011 +0400

    target-xtensa: remove hand-written xtensa cores implementations
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index c22b3cb..04369b1 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -370,7 +370,6 @@ obj-alpha-y += vga.o cirrus_vga.o
 obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
 
 obj-xtensa-y += xtensa_pic.o
-obj-xtensa-y += xtensa_sample.o
 obj-xtensa-y += xtensa_dc232b.o
 obj-xtensa-y += xtensa-semi.o
 
diff --git a/hw/xtensa_sample.c b/hw/xtensa_sample.c
deleted file mode 100644
index 31a6f70..0000000
--- a/hw/xtensa_sample.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the Open Source and Linux Lab nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "sysemu.h"
-#include "boards.h"
-#include "loader.h"
-#include "elf.h"
-#include "memory.h"
-#include "exec-memory.h"
-
-static void xtensa_sample_reset(void *env)
-{
-    cpu_reset(env);
-}
-
-static void xtensa_init(ram_addr_t ram_size,
-        const char *boot_device,
-        const char *kernel_filename, const char *kernel_cmdline,
-        const char *initrd_filename, const char *cpu_model)
-{
-    CPUState *env = NULL;
-    MemoryRegion *ram;
-    const size_t dram_size = 0x10000;
-    const size_t iram_size = 0x20000;
-    int n;
-
-    for (n = 0; n < smp_cpus; n++) {
-        env = cpu_init(cpu_model);
-        if (!env) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        qemu_register_reset(xtensa_sample_reset, env);
-        env->sregs[PRID] = n;
-    }
-
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, NULL, "xtensa.ram",
-            dram_size + iram_size + ram_size);
-    memory_region_add_subregion(get_system_memory(),
-            0x60000000 - dram_size - iram_size, ram);
-
-    if (kernel_filename) {
-        uint64_t elf_entry;
-        uint64_t elf_lowaddr;
-#ifdef TARGET_WORDS_BIGENDIAN
-        int success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
-#else
-        int success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
-#endif
-        if (success > 0) {
-            env->pc = elf_entry;
-        }
-    }
-}
-
-static void xtensa_sample_init(ram_addr_t ram_size,
-                     const char *boot_device,
-                     const char *kernel_filename, const char *kernel_cmdline,
-                     const char *initrd_filename, const char *cpu_model)
-{
-    if (!cpu_model) {
-        cpu_model = "sample-xtensa-core";
-    }
-    xtensa_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
-                  initrd_filename, cpu_model);
-}
-
-static QEMUMachine xtensa_sample_machine = {
-    .name = "sample-xtensa-machine",
-    .desc = "Sample Xtensa machine (sample Xtensa core)",
-    .init = xtensa_sample_init,
-    .max_cpus = 4,
-};
-
-static void xtensa_sample_machine_init(void)
-{
-    qemu_register_machine(&xtensa_sample_machine);
-}
-
-machine_init(xtensa_sample_machine_init);
diff --git a/target-xtensa/gdb-config-dc232b.c b/target-xtensa/gdb-config-dc232b.c