[Spice-commits] 92 commits - .exrc MAINTAINERS QMP/qmp-shell VERSION configure console.c console.h error.h hmp-commands.hx hmp.c hmp.h hw/blizzard.c hw/elf_ops.h hw/g364fb.c hw/kvm hw/lan9118.c hw/mc146818rtc.c hw/mc146818rtc_regs.h hw/mcf5206.c hw/musicpal.c hw/omap_lcdc.c hw/pci.c hw/pcie.h hw/pcie_aer.c hw/pl110.c hw/pl110_template.h hw/qdev-monitor.c hw/qxl.c hw/qxl.h hw/tcx.c hw/vga.c hw/vga_int.h hw/vhost.c hw/vhost.h hw/vhost_net.c hw/virtio-pci.c hw/vmware_vga.c hw/wm8750.c input.c kvm-all.c kvm-stub.c kvm.h monitor.c monitor.h net.c net.h net/socket.c net/tap.c qapi-schema.json qemu-char.c qemu-config.c qemu-options.hx qmp-commands.hx qobject.h scripts/checkpatch.pl scripts/qapi-types.py scripts/qapi-visit.py target-arm/helper.c target-cris/translate.c target-i386/kvm.c target-i386/kvm_i386.h target-mips/cpu.h target-mips/op_helper.c target-mips/translate.c target-s390x/Makefile.objs target-s390x/cc_helper.c target-s390x/cpu.h target-s390x/fpu_helper.c target-s390x/helper.c target-s390x/helper.h target-s390x/int_helper.c target-s390x/mem_helper.c target-s390x/misc_helper.c target-s390x/op_helper.c target-s390x/translate.c target-sparc/fop_helper.c target-xtensa/xtensa-semi.c tcg/s390 trace-events ui/spice-core.c ui/spice-display.c ui/spice-display.h vmstate.h

Gerd Hoffmann kraxel at kemper.freedesktop.org
Tue Sep 11 01:49:20 PDT 2012


 .exrc                       |    7 
 MAINTAINERS                 |    6 
 QMP/qmp-shell               |   46 
 VERSION                     |    2 
 configure                   |   60 
 console.c                   |    7 
 console.h                   |   10 
 error.h                     |    6 
 hmp-commands.hx             |   13 
 hmp.c                       |   66 
 hmp.h                       |    2 
 hw/blizzard.c               |    4 
 hw/elf_ops.h                |   11 
 hw/g364fb.c                 |   55 
 hw/kvm/Makefile.objs        |    2 
 hw/kvm/pci-assign.c         | 1915 +++++++++++++++++++++++++++
 hw/lan9118.c                |    2 
 hw/mc146818rtc.c            |  520 +++++--
 hw/mc146818rtc_regs.h       |    1 
 hw/mcf5206.c                |   12 
 hw/musicpal.c               |    4 
 hw/omap_lcdc.c              |   66 
 hw/pci.c                    |    2 
 hw/pcie.h                   |    1 
 hw/pcie_aer.c               |    5 
 hw/pl110.c                  |   30 
 hw/pl110_template.h         |   22 
 hw/qdev-monitor.c           |    1 
 hw/qxl.c                    |  182 ++
 hw/qxl.h                    |   10 
 hw/tcx.c                    |   97 +
 hw/vga.c                    |   38 
 hw/vga_int.h                |    3 
 hw/vhost.c                  |    5 
 hw/vhost.h                  |    3 
 hw/vhost_net.c              |    2 
 hw/virtio-pci.c             |    4 
 hw/vmware_vga.c             |    7 
 hw/wm8750.c                 |    4 
 input.c                     |  251 +++
 kvm-all.c                   |   75 -
 kvm-stub.c                  |   14 
 kvm.h                       |    8 
 monitor.c                   |  270 ---
 monitor.h                   |    2 
 net.c                       |   18 
 net.h                       |    2 
 net/socket.c                |    2 
 net/tap.c                   |    4 
 qapi-schema.json            |   64 
 qemu-char.c                 |    4 
 qemu-config.c               |    3 
 qemu-options.hx             |   21 
 qmp-commands.hx             |   33 
 qobject.h                   |    2 
 scripts/checkpatch.pl       |   68 
 scripts/qapi-types.py       |   16 
 scripts/qapi-visit.py       |   16 
 target-arm/helper.c         |    4 
 target-cris/translate.c     |    2 
 target-i386/kvm.c           |  141 ++
 target-i386/kvm_i386.h      |   22 
 target-mips/cpu.h           |   49 
 target-mips/op_helper.c     |   49 
 target-mips/translate.c     |   16 
 target-s390x/Makefile.objs  |    5 
 target-s390x/cc_helper.c    |  550 ++++++++
 target-s390x/cpu.h          |    9 
 target-s390x/fpu_helper.c   |  843 ++++++++++++
 target-s390x/helper.c       |  102 -
 target-s390x/helper.h       |  250 +--
 target-s390x/int_helper.c   |  201 ++
 target-s390x/mem_helper.c   | 1203 +++++++++++++++++
 target-s390x/misc_helper.c  |  430 ++++++
 target-s390x/op_helper.c    | 3019 --------------------------------------------
 target-s390x/translate.c    |  233 +--
 target-sparc/fop_helper.c   |   67 
 target-xtensa/xtensa-semi.c |  112 +
 tcg/s390/tcg-target.c       |   14 
 trace-events                |    1 
 ui/spice-core.c             |   41 
 ui/spice-display.c          |   37 
 ui/spice-display.h          |   13 
 vmstate.h                   |    5 
 84 files changed, 7386 insertions(+), 4138 deletions(-)

New commits:
commit 4b1c11fd20e8901f04a2d9c225cd10fc05a762ff
Author: Daniel P. Berrange <berrange at redhat.com>
Date:   Mon Sep 10 12:26:29 2012 +0100

    Add ability to force enable/disable of tools build
    
    The qemu-img, qemu-nbd and qemu-io tools are built conditionally
    based on whether any softmmu target is enabled. These are useful
    self-contained tools which can be used in many other scenarios.
    Add new --enable-tools/--disable-tools args to configure to allow
    the user to explicitly turn on / off their build. The default
    behaviour is now to build these tools are all times, regardless
    of whether any softmmu target is enabled
    
    Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 76289bc..30be784 100755
--- a/configure
+++ b/configure
@@ -217,6 +217,7 @@ usb_redir=""
 opengl=""
 zlib="yes"
 guest_agent="yes"
+want_tools="yes"
 libiscsi=""
 coroutine=""
 seccomp=""
@@ -868,6 +869,10 @@ for opt do
   ;;
   --disable-guest-agent) guest_agent="no"
   ;;
+  --enable-tools) want_tools="yes"
+  ;;
+  --disable-tools) want_tools="no"
+  ;;
   --enable-seccomp) seccomp="yes"
   ;;
   --disable-seccomp) seccomp="no"
@@ -3043,9 +3048,14 @@ fi
 qemu_confdir=$sysconfdir$confsuffix
 qemu_datadir=$datadir$confsuffix
 
-tools=
-if test "$softmmu" = yes ; then
+tools=""
+if test "$want_tools" = "yes" ; then
   tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
+  if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
+    tools="qemu-nbd\$(EXESUF) $tools"
+  fi
+fi
+if test "$softmmu" = yes ; then
   if test "$virtfs" != no ; then
     if test "$cap" = yes && test "$linux" = yes && test "$attr" = yes ; then
       virtfs=yes
@@ -3059,14 +3069,13 @@ if test "$softmmu" = yes ; then
     fi
   fi
   if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
-      tools="qemu-nbd\$(EXESUF) $tools"
     if [ "$guest_agent" = "yes" ]; then
       tools="qemu-ga\$(EXESUF) $tools"
     fi
   fi
-fi
-if test "$smartcard_nss" = "yes" ; then
-  tools="vscclient\$(EXESUF) $tools"
+  if test "$smartcard_nss" = "yes" ; then
+    tools="vscclient\$(EXESUF) $tools"
+  fi
 fi
 
 # Mac OS X ships with a broken assembler
commit 66d5499b3754b83c09487259c08fe2ce73188a59
Author: Daniel P. Berrange <berrange at redhat.com>
Date:   Mon Sep 10 12:27:21 2012 +0100

    Add ability to disable build of all targets
    
    Allow passing of '--target-list=' to configure to request that
    all targets are to be disabled. This allows for doing a very
    fast tools-only build of things like qemu-img, qemu-io, qemu-nbd.
    
    Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 2e4a3b0..76289bc 100755
--- a/configure
+++ b/configure
@@ -127,7 +127,7 @@ cc_i386=i386-pc-linux-gnu-gcc
 libs_qga=""
 debug_info="yes"
 
-target_list=""
+target_list="DEFAULT"
 
 # Default value for a variable defining feature "foo".
 #  * foo="no"  feature will only be used if --enable-foo arg is given
@@ -1317,15 +1317,10 @@ if ! "$python" -c 'import sys; sys.exit(sys.version_info < (2,4) or sys.version_
   exit 1
 fi
 
-if test -z "$target_list" ; then
-    target_list="$default_target_list"
-else
-    target_list=`echo "$target_list" | sed -e 's/,/ /g'`
-fi
-if test -z "$target_list" ; then
-    echo "No targets enabled"
-    exit 1
+if test "$target_list" = "DEFAULT" ; then
+    target_list=`echo "$default_target_list" | sed -e 's/,/ /g'`
 fi
+
 # see if system emulation was really requested
 case " $target_list " in
   *"-softmmu "*) softmmu=yes
commit 89166459065353c6a49456794f840ffe57016020
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Aug 2 18:04:13 2012 +0200

    RTC: Remove the current_tm field
    
    This is not used anymore and only written to.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index a609f72..d63554f 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -61,7 +61,6 @@ typedef struct RTCState {
     MemoryRegion io;
     uint8_t cmos_data[128];
     uint8_t cmos_index;
-    struct tm current_tm;
     int32_t base_year;
     uint64_t base_rtc;
     uint64_t last_update;
@@ -524,7 +523,6 @@ static void rtc_set_time(RTCState *s)
     struct tm tm;
 
     rtc_get_time(s, &tm);
-    s->current_tm = tm;
     s->base_rtc = mktimegm(&tm);
     s->last_update = qemu_get_clock_ns(rtc_clock);
 
@@ -566,7 +564,6 @@ static void rtc_update_time(RTCState *s)
     guest_sec = guest_nsec / NSEC_PER_SEC;
     gmtime_r(&guest_sec, &ret);
     rtc_set_cmos(s, &ret);
-    s->current_tm = ret;
 }
 
 static int update_in_progress(RTCState *s)
@@ -682,7 +679,6 @@ static void rtc_set_date_from_host(ISADevice *dev)
 
     /* set the CMOS date */
     rtc_set_cmos(s, &tm);
-    s->current_tm = tm;
 
     val = rtc_to_bcd(s, (tm.tm_year / 100) + 19);
     rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val);
@@ -718,13 +714,7 @@ static const VMStateDescription vmstate_rtc = {
     .fields      = (VMStateField []) {
         VMSTATE_BUFFER(cmos_data, RTCState),
         VMSTATE_UINT8(cmos_index, RTCState),
-        VMSTATE_INT32(current_tm.tm_sec, RTCState),
-        VMSTATE_INT32(current_tm.tm_min, RTCState),
-        VMSTATE_INT32(current_tm.tm_hour, RTCState),
-        VMSTATE_INT32(current_tm.tm_wday, RTCState),
-        VMSTATE_INT32(current_tm.tm_mday, RTCState),
-        VMSTATE_INT32(current_tm.tm_mon, RTCState),
-        VMSTATE_INT32(current_tm.tm_year, RTCState),
+        VMSTATE_UNUSED(7*4),
         VMSTATE_TIMER(periodic_timer, RTCState),
         VMSTATE_INT64(next_periodic_time, RTCState),
         VMSTATE_UNUSED(3*8),
commit e2826cf4a8c89d64cdf8304f861910293f046aa8
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Aug 2 18:04:12 2012 +0200

    RTC: Get and set time without going through s->current_tm
    
    This patch makes rtc_set_time and rtc_set_cmos work without reading
    s->current_tm.  In the case of rtc_set_time I introduce a new
    function that retrieves the time and stores into a given struct tm
    (not hard-coded to s->current_tm).  In the case of rtc_set_cmos, the
    current time is similarly taken from a struct tm rather than
    s->current_tm.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 9d530a8..a609f72 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -86,7 +86,7 @@ typedef struct RTCState {
 
 static void rtc_set_time(RTCState *s);
 static void rtc_update_time(RTCState *s);
-static void rtc_set_cmos(RTCState *s);
+static void rtc_set_cmos(RTCState *s, const struct tm *tm);
 static inline int rtc_from_bcd(RTCState *s, int a);
 static uint64_t get_next_alarm(RTCState *s);
 
@@ -502,10 +502,8 @@ static inline int rtc_from_bcd(RTCState *s, int a)
     }
 }
 
-static void rtc_set_time(RTCState *s)
+static void rtc_get_time(RTCState *s, struct tm *tm)
 {
-    struct tm *tm = &s->current_tm;
-
     tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
     tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
     tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
@@ -519,16 +517,22 @@ static void rtc_set_time(RTCState *s)
     tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
     tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
     tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900;
+}
+
+static void rtc_set_time(RTCState *s)
+{
+    struct tm tm;
 
-    s->base_rtc = mktimegm(tm);
+    rtc_get_time(s, &tm);
+    s->current_tm = tm;
+    s->base_rtc = mktimegm(&tm);
     s->last_update = qemu_get_clock_ns(rtc_clock);
 
-    rtc_change_mon_event(tm);
+    rtc_change_mon_event(&tm);
 }
 
-static void rtc_set_cmos(RTCState *s)
+static void rtc_set_cmos(RTCState *s, const struct tm *tm)
 {
-    const struct tm *tm = &s->current_tm;
     int year;
 
     s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec);
@@ -561,8 +565,8 @@ static void rtc_update_time(RTCState *s)
     guest_nsec = get_guest_rtc_ns(s);
     guest_sec = guest_nsec / NSEC_PER_SEC;
     gmtime_r(&guest_sec, &ret);
+    rtc_set_cmos(s, &ret);
     s->current_tm = ret;
-    rtc_set_cmos(s);
 }
 
 static int update_in_progress(RTCState *s)
@@ -677,8 +681,8 @@ static void rtc_set_date_from_host(ISADevice *dev)
     s->offset = 0;
 
     /* set the CMOS date */
+    rtc_set_cmos(s, &tm);
     s->current_tm = tm;
-    rtc_set_cmos(s);
 
     val = rtc_to_bcd(s, (tm.tm_year / 100) + 19);
     rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val);
@@ -789,15 +793,17 @@ static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
 {
     ISADevice *isa = ISA_DEVICE(obj);
     RTCState *s = DO_UPCAST(RTCState, dev, isa);
+    struct tm current_tm;
 
     rtc_update_time(s);
+    rtc_get_time(s, &current_tm);
     visit_start_struct(v, NULL, "struct tm", name, 0, errp);
-    visit_type_int32(v, &s->current_tm.tm_year, "tm_year", errp);
-    visit_type_int32(v, &s->current_tm.tm_mon, "tm_mon", errp);
-    visit_type_int32(v, &s->current_tm.tm_mday, "tm_mday", errp);
-    visit_type_int32(v, &s->current_tm.tm_hour, "tm_hour", errp);
-    visit_type_int32(v, &s->current_tm.tm_min, "tm_min", errp);
-    visit_type_int32(v, &s->current_tm.tm_sec, "tm_sec", errp);
+    visit_type_int32(v, &current_tm.tm_year, "tm_year", errp);
+    visit_type_int32(v, &current_tm.tm_mon, "tm_mon", errp);
+    visit_type_int32(v, &current_tm.tm_mday, "tm_mday", errp);
+    visit_type_int32(v, &current_tm.tm_hour, "tm_hour", errp);
+    visit_type_int32(v, &current_tm.tm_min, "tm_min", errp);
+    visit_type_int32(v, &current_tm.tm_sec, "tm_sec", errp);
     visit_end_struct(v, errp);
 }
 
commit 00cf57747db98c6a9e4219cea39ac3113dde6993
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Aug 2 18:04:11 2012 +0200

    RTC: Do not fire timer periodically to catch next alarm
    
    This patch limits further the usage of a periodic timer.  It computes the
    time of the next alarm, and uses it to skip all intermediate occurrences
    of the timer.
    
    Cc: Yang Zhang <yang.z.zhang at intel.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index cb65c4f..9d530a8 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -46,6 +46,11 @@
 #endif
 
 #define NSEC_PER_SEC    1000000000LL
+#define SEC_PER_MIN     60
+#define MIN_PER_HOUR    60
+#define SEC_PER_HOUR    3600
+#define HOUR_PER_DAY    24
+#define SEC_PER_DAY     86400
 
 #define RTC_REINJECT_ON_ACK_COUNT 20
 #define RTC_CLOCK_RATE            32768
@@ -69,6 +74,7 @@ typedef struct RTCState {
     int64_t next_periodic_time;
     /* update-ended timer */
     QEMUTimer *update_timer;
+    uint64_t next_alarm_time;
     uint16_t irq_reinject_on_ack_count;
     uint32_t irq_coalesced;
     uint32_t period;
@@ -82,6 +88,7 @@ static void rtc_set_time(RTCState *s);
 static void rtc_update_time(RTCState *s);
 static void rtc_set_cmos(RTCState *s);
 static inline int rtc_from_bcd(RTCState *s, int a);
+static uint64_t get_next_alarm(RTCState *s);
 
 static inline bool rtc_running(RTCState *s)
 {
@@ -204,6 +211,7 @@ static void check_update_timer(RTCState *s)
 {
     uint64_t next_update_time;
     uint64_t guest_nsec;
+    int next_alarm_sec;
 
     /* From the data sheet: "Holding the dividers in reset prevents
      * interrupts from operating, while setting the SET bit allows"
@@ -226,9 +234,21 @@ static void check_update_timer(RTCState *s)
     }
 
     guest_nsec = get_guest_rtc_ns(s) % NSEC_PER_SEC;
-    /* reprogram to next second */
+    /* if UF is clear, reprogram to next second */
     next_update_time = qemu_get_clock_ns(rtc_clock)
         + NSEC_PER_SEC - guest_nsec;
+
+    /* Compute time of next alarm.  One second is already accounted
+     * for in next_update_time.
+     */
+    next_alarm_sec = get_next_alarm(s);
+    s->next_alarm_time = next_update_time + (next_alarm_sec - 1) * NSEC_PER_SEC;
+
+    if (s->cmos_data[RTC_REG_C] & REG_C_UF) {
+        /* UF is set, but AF is clear.  Program the timer to target
+         * the alarm time.  */
+        next_update_time = s->next_alarm_time;
+    }
     if (next_update_time != qemu_timer_expire_time_ns(s->update_timer)) {
         qemu_mod_timer(s->update_timer, next_update_time);
     }
@@ -245,31 +265,95 @@ static inline uint8_t convert_hour(RTCState *s, uint8_t hour)
     return hour;
 }
 
-static uint32_t check_alarm(RTCState *s)
+static uint64_t get_next_alarm(RTCState *s)
 {
-    uint8_t alarm_hour, alarm_min, alarm_sec;
-    uint8_t cur_hour, cur_min, cur_sec;
+    int32_t alarm_sec, alarm_min, alarm_hour, cur_hour, cur_min, cur_sec;
+    int32_t hour, min, sec;
+
+    rtc_update_time(s);
 
     alarm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]);
     alarm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]);
     alarm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]);
-    alarm_hour = convert_hour(s, alarm_hour);
+    alarm_hour = alarm_hour == -1 ? -1 : convert_hour(s, alarm_hour);
 
     cur_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
     cur_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
     cur_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS]);
     cur_hour = convert_hour(s, cur_hour);
 
-    if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0
-                || alarm_sec == cur_sec) &&
-            ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0
-             || alarm_min == cur_min) &&
-            ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0
-             || alarm_hour == cur_hour)) {
-        return 1;
+    if (alarm_hour == -1) {
+        alarm_hour = cur_hour;
+        if (alarm_min == -1) {
+            alarm_min = cur_min;
+            if (alarm_sec == -1) {
+                alarm_sec = cur_sec + 1;
+            } else if (cur_sec > alarm_sec) {
+                alarm_min++;
+            }
+        } else if (cur_min == alarm_min) {
+            if (alarm_sec == -1) {
+                alarm_sec = cur_sec + 1;
+            } else {
+                if (cur_sec > alarm_sec) {
+                    alarm_hour++;
+                }
+            }
+            if (alarm_sec == SEC_PER_MIN) {
+                /* wrap to next hour, minutes is not in don't care mode */
+                alarm_sec = 0;
+                alarm_hour++;
+            }
+        } else if (cur_min > alarm_min) {
+            alarm_hour++;
+        }
+    } else if (cur_hour == alarm_hour) {
+        if (alarm_min == -1) {
+            alarm_min = cur_min;
+            if (alarm_sec == -1) {
+                alarm_sec = cur_sec + 1;
+            } else if (cur_sec > alarm_sec) {
+                alarm_min++;
+            }
+
+            if (alarm_sec == SEC_PER_MIN) {
+                alarm_sec = 0;
+                alarm_min++;
+            }
+            /* wrap to next day, hour is not in don't care mode */
+            alarm_min %= MIN_PER_HOUR;
+        } else if (cur_min == alarm_min) {
+            if (alarm_sec == -1) {
+                alarm_sec = cur_sec + 1;
+            }
+            /* wrap to next day, hours+minutes not in don't care mode */
+            alarm_sec %= SEC_PER_MIN;
+        }
     }
-    return 0;
 
+    /* values that are still don't care fire at the next min/sec */
+    if (alarm_min == -1) {
+        alarm_min = 0;
+    }
+    if (alarm_sec == -1) {
+        alarm_sec = 0;
+    }
+
+    /* keep values in range */
+    if (alarm_sec == SEC_PER_MIN) {
+        alarm_sec = 0;
+        alarm_min++;
+    }
+    if (alarm_min == MIN_PER_HOUR) {
+        alarm_min = 0;
+        alarm_hour++;
+    }
+    alarm_hour %= HOUR_PER_DAY;
+
+    hour = alarm_hour - cur_hour;
+    min = hour * MIN_PER_HOUR + alarm_min - cur_min;
+    sec = min * SEC_PER_MIN + alarm_sec - cur_sec;
+    return sec <= 0 ? sec + SEC_PER_DAY : sec;
 }
 
 static void rtc_update_timer(void *opaque)
@@ -284,12 +368,13 @@ static void rtc_update_timer(void *opaque)
     rtc_update_time(s);
     s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
 
-    if (check_alarm(s)) {
+    if (qemu_get_clock_ns(rtc_clock) >= s->next_alarm_time) {
         irqs |= REG_C_AF;
         if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
             qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC);
         }
     }
+
     new_irqs = irqs & ~s->cmos_data[RTC_REG_C];
     s->cmos_data[RTC_REG_C] |= irqs;
     if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) {
@@ -407,6 +492,9 @@ static inline int rtc_to_bcd(RTCState *s, int a)
 
 static inline int rtc_from_bcd(RTCState *s, int a)
 {
+    if ((a & 0xc0) == 0xc0) {
+        return -1;
+    }
     if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
         return a;
     } else {
@@ -642,6 +730,7 @@ static const VMStateDescription vmstate_rtc = {
         VMSTATE_UINT64_V(last_update, RTCState, 3),
         VMSTATE_INT64_V(offset, RTCState, 3),
         VMSTATE_TIMER_V(update_timer, RTCState, 3),
+        VMSTATE_UINT64_V(next_alarm_time, RTCState, 3),
         VMSTATE_END_OF_LIST()
     }
 };
commit 41a9b8b24d59acec462b0d8e0d2a7ffce6031d55
Author: Yang Zhang <yang.z.zhang at intel.com>
Date:   Thu Aug 2 18:04:10 2012 +0200

    RTC: Add divider reset support
    
    The first update cycle begins one-half seconds after divider
    reset is removed.  This feature is useful for testing.
    
    Signed-off-by: Yang Zhang <yang.z.zhang at intel.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 54c98a5..cb65c4f 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -83,6 +83,12 @@ static void rtc_update_time(RTCState *s);
 static void rtc_set_cmos(RTCState *s);
 static inline int rtc_from_bcd(RTCState *s, int a);
 
+static inline bool rtc_running(RTCState *s)
+{
+    return (!(s->cmos_data[RTC_REG_B] & REG_B_SET) &&
+            (s->cmos_data[RTC_REG_A] & 0x70) <= 0x20);
+}
+
 static uint64_t get_guest_rtc_ns(RTCState *s)
 {
     uint64_t guest_rtc;
@@ -199,11 +205,15 @@ static void check_update_timer(RTCState *s)
     uint64_t next_update_time;
     uint64_t guest_nsec;
 
-    /* From the data sheet: setting the SET bit does not prevent
-     * interrupts from occurring!  However, it will prevent an
-     * alarm interrupt from occurring, because the time of day is
-     * not updated.
+    /* From the data sheet: "Holding the dividers in reset prevents
+     * interrupts from operating, while setting the SET bit allows"
+     * them to occur.  However, it will prevent an alarm interrupt
+     * from occurring, because the time of day is not updated.
      */
+    if ((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) {
+        qemu_del_timer(s->update_timer);
+        return;
+    }
     if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
         (s->cmos_data[RTC_REG_B] & REG_B_SET)) {
         qemu_del_timer(s->update_timer);
@@ -268,6 +278,8 @@ static void rtc_update_timer(void *opaque)
     int32_t irqs = REG_C_UF;
     int32_t new_irqs;
 
+    assert((s->cmos_data[RTC_REG_A] & 0x60) != 0x60);
+
     /* UIP might have been latched, update time and clear it.  */
     rtc_update_time(s);
     s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
@@ -312,12 +324,31 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
         case RTC_YEAR:
             s->cmos_data[s->cmos_index] = data;
             /* if in set mode, do not update the time */
-            if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+            if (rtc_running(s)) {
                 rtc_set_time(s);
                 check_update_timer(s);
             }
             break;
         case RTC_REG_A:
+            if ((data & 0x60) == 0x60) {
+                if (rtc_running(s)) {
+                    rtc_update_time(s);
+                }
+                /* What happens to UIP when divider reset is enabled is
+                 * unclear from the datasheet.  Shouldn't matter much
+                 * though.
+                 */
+                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
+            } else if (((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) &&
+                    (data & 0x70)  <= 0x20) {
+                /* when the divider reset is removed, the first update cycle
+                 * begins one-half second later*/
+                if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+                    s->offset = 500000000;
+                    rtc_set_time(s);
+                }
+                s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
+            }
             /* UIP bit is read only */
             s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
                 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
@@ -327,7 +358,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
         case RTC_REG_B:
             if (data & REG_B_SET) {
                 /* update cmos to when the rtc was stopping */
-                if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+                if (rtc_running(s)) {
                     rtc_update_time(s);
                 }
                 /* set mode: reset UIP mode */
@@ -335,7 +366,8 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
                 data &= ~REG_B_UIE;
             } else {
                 /* if disabling set mode, update the time */
-                if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
+                if ((s->cmos_data[RTC_REG_B] & REG_B_SET) &&
+                    (s->cmos_data[RTC_REG_A] & 0x70) <= 0x20) {
                     s->offset = get_guest_rtc_ns(s) % NSEC_PER_SEC;
                     rtc_set_time(s);
                 }
@@ -449,7 +481,7 @@ static int update_in_progress(RTCState *s)
 {
     int64_t guest_nsec;
 
-    if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
+    if (!rtc_running(s)) {
         return 0;
     }
     if (qemu_timer_pending(s->update_timer)) {
@@ -486,7 +518,7 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
         case RTC_YEAR:
             /* if not in set mode, calibrate cmos before
              * reading*/
-            if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+            if (rtc_running(s)) {
                 rtc_update_time(s);
             }
             ret = s->cmos_data[s->cmos_index];
commit 56038ef6234e5fb3d01bad1f6df37c2ccab82af9
Author: Yang Zhang <yang.z.zhang at intel.com>
Date:   Thu Aug 2 18:04:09 2012 +0200

    RTC: Update the RTC clock only when reading it
    
    Calculate guest RTC based on the time of the last update, instead of
    using timers.  The formula is
    
        (base_rtc + guest_time_now - guest_time_last_update + offset)
    
    Base_rtc is the RTC value when the RTC was last updated.
    Guest_time_now is the guest time when the access happens.
    Guest_time_last_update was the guest time when the RTC was last updated.
    Offset is used when divider reset happens or the set bit is toggled.
    
    The timer is kept in order to signal interrupts, but it only needs to
    run when either UF or AF is cleared.  When the bits are both set, the
    timer does not run.
    
    UIP is now synthesized when reading register A.  If the timer is not set,
    or if there is more than one second before it (as is the case at the
    end of this series), the leading edge of UIP is computed and the rising
    edge occurs 220us later.  If the update timer occurs within one second,
    however, the rising edge of the AF and UF bits should coincide withe
    the falling edge of UIP.  We do not know exactly when this will happen
    because there could be delays in the servicing of the timer.  Hence, in
    this case reading register A only computes for the rising edge of UIP,
    and latches the bit until the timer is fired and clears it.
    
    Signed-off-by: Yang Zhang <yang.z.zhang at intel.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index b41eb4b..54c98a5 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -45,8 +45,11 @@
 # define DPRINTF_C(format, ...)      do { } while (0)
 #endif
 
+#define NSEC_PER_SEC    1000000000LL
+
 #define RTC_REINJECT_ON_ACK_COUNT 20
 #define RTC_CLOCK_RATE            32768
+#define UIP_HOLD_LENGTH           (8 * NSEC_PER_SEC / 32768)
 
 typedef struct RTCState {
     ISADevice dev;
@@ -55,27 +58,40 @@ typedef struct RTCState {
     uint8_t cmos_index;
     struct tm current_tm;
     int32_t base_year;
+    uint64_t base_rtc;
+    uint64_t last_update;
+    int64_t offset;
     qemu_irq irq;
     qemu_irq sqw_irq;
     int it_shift;
     /* periodic timer */
     QEMUTimer *periodic_timer;
     int64_t next_periodic_time;
-    /* second update */
-    int64_t next_second_time;
+    /* update-ended timer */
+    QEMUTimer *update_timer;
     uint16_t irq_reinject_on_ack_count;
     uint32_t irq_coalesced;
     uint32_t period;
     QEMUTimer *coalesced_timer;
-    QEMUTimer *second_timer;
-    QEMUTimer *second_timer2;
     Notifier clock_reset_notifier;
     LostTickPolicy lost_tick_policy;
     Notifier suspend_notifier;
 } RTCState;
 
 static void rtc_set_time(RTCState *s);
-static void rtc_copy_date(RTCState *s);
+static void rtc_update_time(RTCState *s);
+static void rtc_set_cmos(RTCState *s);
+static inline int rtc_from_bcd(RTCState *s, int a);
+
+static uint64_t get_guest_rtc_ns(RTCState *s)
+{
+    uint64_t guest_rtc;
+    uint64_t guest_clock = qemu_get_clock_ns(rtc_clock);
+
+    guest_rtc = s->base_rtc * NSEC_PER_SEC
+                 + guest_clock - s->last_update + s->offset;
+    return guest_rtc;
+}
 
 #ifdef TARGET_I386
 static void rtc_coalesced_timer_update(RTCState *s)
@@ -111,6 +127,7 @@ static void rtc_coalesced_timer(void *opaque)
 }
 #endif
 
+/* handle periodic timer */
 static void periodic_timer_update(RTCState *s, int64_t current_time)
 {
     int period_code, period;
@@ -176,6 +193,100 @@ static void rtc_periodic_timer(void *opaque)
     }
 }
 
+/* handle update-ended timer */
+static void check_update_timer(RTCState *s)
+{
+    uint64_t next_update_time;
+    uint64_t guest_nsec;
+
+    /* From the data sheet: setting the SET bit does not prevent
+     * interrupts from occurring!  However, it will prevent an
+     * alarm interrupt from occurring, because the time of day is
+     * not updated.
+     */
+    if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
+        (s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+        qemu_del_timer(s->update_timer);
+        return;
+    }
+    if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
+        (s->cmos_data[RTC_REG_C] & REG_C_AF)) {
+        qemu_del_timer(s->update_timer);
+        return;
+    }
+
+    guest_nsec = get_guest_rtc_ns(s) % NSEC_PER_SEC;
+    /* reprogram to next second */
+    next_update_time = qemu_get_clock_ns(rtc_clock)
+        + NSEC_PER_SEC - guest_nsec;
+    if (next_update_time != qemu_timer_expire_time_ns(s->update_timer)) {
+        qemu_mod_timer(s->update_timer, next_update_time);
+    }
+}
+
+static inline uint8_t convert_hour(RTCState *s, uint8_t hour)
+{
+    if (!(s->cmos_data[RTC_REG_B] & REG_B_24H)) {
+        hour %= 12;
+        if (s->cmos_data[RTC_HOURS] & 0x80) {
+            hour += 12;
+        }
+    }
+    return hour;
+}
+
+static uint32_t check_alarm(RTCState *s)
+{
+    uint8_t alarm_hour, alarm_min, alarm_sec;
+    uint8_t cur_hour, cur_min, cur_sec;
+
+    alarm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]);
+    alarm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]);
+    alarm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]);
+    alarm_hour = convert_hour(s, alarm_hour);
+
+    cur_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
+    cur_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
+    cur_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS]);
+    cur_hour = convert_hour(s, cur_hour);
+
+    if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0
+                || alarm_sec == cur_sec) &&
+            ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0
+             || alarm_min == cur_min) &&
+            ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0
+             || alarm_hour == cur_hour)) {
+        return 1;
+    }
+    return 0;
+
+}
+
+static void rtc_update_timer(void *opaque)
+{
+    RTCState *s = opaque;
+    int32_t irqs = REG_C_UF;
+    int32_t new_irqs;
+
+    /* UIP might have been latched, update time and clear it.  */
+    rtc_update_time(s);
+    s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
+
+    if (check_alarm(s)) {
+        irqs |= REG_C_AF;
+        if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
+            qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC);
+        }
+    }
+    new_irqs = irqs & ~s->cmos_data[RTC_REG_C];
+    s->cmos_data[RTC_REG_C] |= irqs;
+    if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) {
+        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
+        qemu_irq_raise(s->irq);
+    }
+    check_update_timer(s);
+}
+
 static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
 {
     RTCState *s = opaque;
@@ -190,6 +301,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
         case RTC_MINUTES_ALARM:
         case RTC_HOURS_ALARM:
             s->cmos_data[s->cmos_index] = data;
+            check_update_timer(s);
             break;
         case RTC_SECONDS:
         case RTC_MINUTES:
@@ -202,6 +314,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
             /* if in set mode, do not update the time */
             if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
                 rtc_set_time(s);
+                check_update_timer(s);
             }
             break;
         case RTC_REG_A:
@@ -209,15 +322,21 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
             s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
                 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
             periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
+            check_update_timer(s);
             break;
         case RTC_REG_B:
             if (data & REG_B_SET) {
+                /* update cmos to when the rtc was stopping */
+                if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+                    rtc_update_time(s);
+                }
                 /* set mode: reset UIP mode */
                 s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
                 data &= ~REG_B_UIE;
             } else {
                 /* if disabling set mode, update the time */
                 if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
+                    s->offset = get_guest_rtc_ns(s) % NSEC_PER_SEC;
                     rtc_set_time(s);
                 }
             }
@@ -232,6 +351,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
             }
             s->cmos_data[RTC_REG_B] = data;
             periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
+            check_update_timer(s);
             break;
         case RTC_REG_C:
         case RTC_REG_D:
@@ -280,10 +400,13 @@ static void rtc_set_time(RTCState *s)
     tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
     tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900;
 
+    s->base_rtc = mktimegm(tm);
+    s->last_update = qemu_get_clock_ns(rtc_clock);
+
     rtc_change_mon_event(tm);
 }
 
-static void rtc_copy_date(RTCState *s)
+static void rtc_set_cmos(RTCState *s)
 {
     const struct tm *tm = &s->current_tm;
     int year;
@@ -309,122 +432,41 @@ static void rtc_copy_date(RTCState *s)
     s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year);
 }
 
-/* month is between 0 and 11. */
-static int get_days_in_month(int month, int year)
+static void rtc_update_time(RTCState *s)
 {
-    static const int days_tab[12] = {
-        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-    };
-    int d;
-    if ((unsigned )month >= 12)
-        return 31;
-    d = days_tab[month];
-    if (month == 1) {
-        if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
-            d++;
-    }
-    return d;
+    struct tm ret;
+    time_t guest_sec;
+    int64_t guest_nsec;
+
+    guest_nsec = get_guest_rtc_ns(s);
+    guest_sec = guest_nsec / NSEC_PER_SEC;
+    gmtime_r(&guest_sec, &ret);
+    s->current_tm = ret;
+    rtc_set_cmos(s);
 }
 
-/* update 'tm' to the next second */
-static void rtc_next_second(struct tm *tm)
+static int update_in_progress(RTCState *s)
 {
-    int days_in_month;
-
-    tm->tm_sec++;
-    if ((unsigned)tm->tm_sec >= 60) {
-        tm->tm_sec = 0;
-        tm->tm_min++;
-        if ((unsigned)tm->tm_min >= 60) {
-            tm->tm_min = 0;
-            tm->tm_hour++;
-            if ((unsigned)tm->tm_hour >= 24) {
-                tm->tm_hour = 0;
-                /* next day */
-                tm->tm_wday++;
-                if ((unsigned)tm->tm_wday >= 7)
-                    tm->tm_wday = 0;
-                days_in_month = get_days_in_month(tm->tm_mon,
-                                                  tm->tm_year + 1900);
-                tm->tm_mday++;
-                if (tm->tm_mday < 1) {
-                    tm->tm_mday = 1;
-                } else if (tm->tm_mday > days_in_month) {
-                    tm->tm_mday = 1;
-                    tm->tm_mon++;
-                    if (tm->tm_mon >= 12) {
-                        tm->tm_mon = 0;
-                        tm->tm_year++;
-                    }
-                }
-            }
-        }
-    }
-}
-
-
-static void rtc_update_second(void *opaque)
-{
-    RTCState *s = opaque;
-    int64_t delay;
-
-    /* if the oscillator is not in normal operation, we do not update */
-    if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
-        s->next_second_time += get_ticks_per_sec();
-        qemu_mod_timer(s->second_timer, s->next_second_time);
-    } else {
-        rtc_next_second(&s->current_tm);
+    int64_t guest_nsec;
 
-        if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
-            /* update in progress bit */
-            s->cmos_data[RTC_REG_A] |= REG_A_UIP;
-        }
-        /* should be 244 us = 8 / RTC_CLOCK_RATE seconds, but currently the
-           timers do not have the necessary resolution. */
-        delay = (get_ticks_per_sec() * 1) / 100;
-        if (delay < 1)
-            delay = 1;
-        qemu_mod_timer(s->second_timer2,
-                       s->next_second_time + delay);
+    if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
+        return 0;
     }
-}
-
-static void rtc_update_second2(void *opaque)
-{
-    RTCState *s = opaque;
-
-    if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
-        rtc_copy_date(s);
-    }
-
-    /* check alarm */
-    if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
-         rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]) == s->current_tm.tm_sec) &&
-        ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
-         rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]) == s->current_tm.tm_min) &&
-        ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
-         rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]) == s->current_tm.tm_hour)) {
-
-        s->cmos_data[RTC_REG_C] |= REG_C_AF;
-        if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
-            qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC);
-            qemu_irq_raise(s->irq);
-            s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
+    if (qemu_timer_pending(s->update_timer)) {
+        int64_t next_update_time = qemu_timer_expire_time_ns(s->update_timer);
+        /* Latch UIP until the timer expires.  */
+        if (qemu_get_clock_ns(rtc_clock) >= (next_update_time - UIP_HOLD_LENGTH)) {
+            s->cmos_data[RTC_REG_A] |= REG_A_UIP;
+            return 1;
         }
     }
 
-    /* update ended interrupt */
-    s->cmos_data[RTC_REG_C] |= REG_C_UF;
-    if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
-        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
-        qemu_irq_raise(s->irq);
+    guest_nsec = get_guest_rtc_ns(s);
+    /* UIP bit will be set at last 244us of every second. */
+    if ((guest_nsec % NSEC_PER_SEC) >= (NSEC_PER_SEC - UIP_HOLD_LENGTH)) {
+        return 1;
     }
-
-    /* clear update in progress bit */
-    s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
-
-    s->next_second_time += get_ticks_per_sec();
-    qemu_mod_timer(s->second_timer, s->next_second_time);
+    return 0;
 }
 
 static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
@@ -442,15 +484,28 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
         case RTC_DAY_OF_MONTH:
         case RTC_MONTH:
         case RTC_YEAR:
+            /* if not in set mode, calibrate cmos before
+             * reading*/
+            if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+                rtc_update_time(s);
+            }
             ret = s->cmos_data[s->cmos_index];
             break;
         case RTC_REG_A:
+            if (update_in_progress(s)) {
+                s->cmos_data[s->cmos_index] |= REG_A_UIP;
+            } else {
+                s->cmos_data[s->cmos_index] &= ~REG_A_UIP;
+            }
             ret = s->cmos_data[s->cmos_index];
             break;
         case RTC_REG_C:
             ret = s->cmos_data[s->cmos_index];
             qemu_irq_lower(s->irq);
             s->cmos_data[RTC_REG_C] = 0x00;
+            if (ret & (REG_C_UF | REG_C_AF)) {
+                check_update_timer(s);
+            }
 #ifdef TARGET_I386
             if(s->irq_coalesced &&
                     (s->cmos_data[RTC_REG_B] & REG_B_PIE) &&
@@ -485,13 +540,6 @@ void rtc_set_memory(ISADevice *dev, int addr, int val)
         s->cmos_data[addr] = val;
 }
 
-void rtc_set_date(ISADevice *dev, const struct tm *tm)
-{
-    RTCState *s = DO_UPCAST(RTCState, dev, dev);
-    s->current_tm = *tm;
-    rtc_copy_date(s);
-}
-
 /* PC cmos mappings */
 #define REG_IBM_CENTURY_BYTE        0x32
 #define REG_IBM_PS2_CENTURY_BYTE    0x37
@@ -502,9 +550,15 @@ static void rtc_set_date_from_host(ISADevice *dev)
     struct tm tm;
     int val;
 
-    /* set the CMOS date */
     qemu_get_timedate(&tm, 0);
-    rtc_set_date(dev, &tm);
+
+    s->base_rtc = mktimegm(&tm);
+    s->last_update = qemu_get_clock_ns(rtc_clock);
+    s->offset = 0;
+
+    /* set the CMOS date */
+    s->current_tm = tm;
+    rtc_set_cmos(s);
 
     val = rtc_to_bcd(s, (tm.tm_year / 100) + 19);
     rtc_set_memory(dev, REG_IBM_CENTURY_BYTE, val);
@@ -513,9 +567,15 @@ static void rtc_set_date_from_host(ISADevice *dev)
 
 static int rtc_post_load(void *opaque, int version_id)
 {
-#ifdef TARGET_I386
     RTCState *s = opaque;
 
+    if (version_id <= 2) {
+        rtc_set_time(s);
+        s->offset = 0;
+        check_update_timer(s);
+    }
+
+#ifdef TARGET_I386
     if (version_id >= 2) {
         if (s->lost_tick_policy == LOST_TICK_SLEW) {
             rtc_coalesced_timer_update(s);
@@ -527,7 +587,7 @@ static int rtc_post_load(void *opaque, int version_id)
 
 static const VMStateDescription vmstate_rtc = {
     .name = "mc146818rtc",
-    .version_id = 2,
+    .version_id = 3,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .post_load = rtc_post_load,
@@ -543,11 +603,13 @@ static const VMStateDescription vmstate_rtc = {
         VMSTATE_INT32(current_tm.tm_year, RTCState),
         VMSTATE_TIMER(periodic_timer, RTCState),
         VMSTATE_INT64(next_periodic_time, RTCState),
-        VMSTATE_INT64(next_second_time, RTCState),
-        VMSTATE_TIMER(second_timer, RTCState),
-        VMSTATE_TIMER(second_timer2, RTCState),
+        VMSTATE_UNUSED(3*8),
         VMSTATE_UINT32_V(irq_coalesced, RTCState, 2),
         VMSTATE_UINT32_V(period, RTCState, 2),
+        VMSTATE_UINT64_V(base_rtc, RTCState, 3),
+        VMSTATE_UINT64_V(last_update, RTCState, 3),
+        VMSTATE_INT64_V(offset, RTCState, 3),
+        VMSTATE_TIMER_V(update_timer, RTCState, 3),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -558,9 +620,8 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
     int64_t now = *(int64_t *)data;
 
     rtc_set_date_from_host(&s->dev);
-    s->next_second_time = now + (get_ticks_per_sec() * 99) / 100;
-    qemu_mod_timer(s->second_timer2, s->next_second_time);
     periodic_timer_update(s, now);
+    check_update_timer(s);
 #ifdef TARGET_I386
     if (s->lost_tick_policy == LOST_TICK_SLEW) {
         rtc_coalesced_timer_update(s);
@@ -582,6 +643,7 @@ static void rtc_reset(void *opaque)
 
     s->cmos_data[RTC_REG_B] &= ~(REG_B_PIE | REG_B_AIE | REG_B_SQWE);
     s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF);
+    check_update_timer(s);
 
     qemu_irq_lower(s->irq);
 
@@ -607,6 +669,7 @@ static void rtc_get_date(Object *obj, Visitor *v, void *opaque,
     ISADevice *isa = ISA_DEVICE(obj);
     RTCState *s = DO_UPCAST(RTCState, dev, isa);
 
+    rtc_update_time(s);
     visit_start_struct(v, NULL, "struct tm", name, 0, errp);
     visit_type_int32(v, &s->current_tm.tm_year, "tm_year", errp);
     visit_type_int32(v, &s->current_tm.tm_mon, "tm_mon", errp);
@@ -643,8 +706,8 @@ static int rtc_initfn(ISADevice *dev)
 #endif
 
     s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s);
-    s->second_timer = qemu_new_timer_ns(rtc_clock, rtc_update_second, s);
-    s->second_timer2 = qemu_new_timer_ns(rtc_clock, rtc_update_second2, s);
+    s->update_timer = qemu_new_timer_ns(rtc_clock, rtc_update_timer, s);
+    check_update_timer(s);
 
     s->clock_reset_notifier.notify = rtc_notify_clock_reset;
     qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier);
@@ -652,14 +715,10 @@ static int rtc_initfn(ISADevice *dev)
     s->suspend_notifier.notify = rtc_notify_suspend;
     qemu_register_suspend_notifier(&s->suspend_notifier);
 
-    s->next_second_time =
-        qemu_get_clock_ns(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
-    qemu_mod_timer(s->second_timer2, s->next_second_time);
-
     memory_region_init_io(&s->io, &cmos_ops, s, "rtc", 2);
     isa_register_ioport(dev, &s->io, base);
 
-    qdev_set_legacy_instance_id(&dev->qdev, base, 2);
+    qdev_set_legacy_instance_id(&dev->qdev, base, 3);
     qemu_register_reset(rtc_reset, s);
 
     object_property_add(OBJECT(s), "date", "struct tm",
commit 0281518a1c7dd3577dea9ccc78869ecff954589c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Aug 2 18:04:08 2012 +0200

    vmstate: add VMSTATE_TIMER_V
    
    Also, for consistency with other occurrences, implement VMSTATE_TIMER
    as a special case of VMSTATE_TIMER_V rather than VMSTATE_TIMER_TEST.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vmstate.h b/vmstate.h
index 5bd2b76..c9c320e 100644
--- a/vmstate.h
+++ b/vmstate.h
@@ -503,8 +503,11 @@ extern const VMStateInfo vmstate_info_unused_buffer;
 #define VMSTATE_TIMER_TEST(_f, _s, _test)                             \
     VMSTATE_POINTER_TEST(_f, _s, _test, vmstate_info_timer, QEMUTimer *)
 
+#define VMSTATE_TIMER_V(_f, _s, _v)                                   \
+    VMSTATE_POINTER(_f, _s, _v, vmstate_info_timer, QEMUTimer *)
+
 #define VMSTATE_TIMER(_f, _s)                                         \
-    VMSTATE_TIMER_TEST(_f, _s, NULL)
+    VMSTATE_TIMER_V(_f, _s, 0)
 
 #define VMSTATE_TIMER_ARRAY(_f, _s, _n)                              \
     VMSTATE_ARRAY_OF_POINTER(_f, _s, _n, 0, vmstate_info_timer, QEMUTimer *)
commit 9324cc50c6b5df0998d46e8fca76e35f00ced6c3
Author: Yang Zhang <yang.z.zhang at intel.com>
Date:   Thu Aug 2 18:04:07 2012 +0200

    RTC: Update interrupt state when interrupts are masked/unmasked
    
    If an interrupt flag is already set when the interrupt becomes enabled,
    raise an interrupt immediately, and vice versa if interrupts become
    disabled.
    
    Signed-off-by: Yang Zhang <yang.z.zhang at intel.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 175ddac..b41eb4b 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -221,6 +221,15 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
                     rtc_set_time(s);
                 }
             }
+            /* if an interrupt flag is already set when the interrupt
+             * becomes enabled, raise an interrupt immediately.  */
+            if (data & s->cmos_data[RTC_REG_C] & REG_C_MASK) {
+                s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
+                qemu_irq_raise(s->irq);
+            } else {
+                s->cmos_data[RTC_REG_C] &= ~REG_C_IRQF;
+                qemu_irq_lower(s->irq);
+            }
             s->cmos_data[RTC_REG_B] = data;
             periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
             break;
diff --git a/hw/mc146818rtc_regs.h b/hw/mc146818rtc_regs.h
index 3ab3770..fc10076 100644
--- a/hw/mc146818rtc_regs.h
+++ b/hw/mc146818rtc_regs.h
@@ -58,5 +58,6 @@
 #define REG_C_IRQF 0x80
 #define REG_C_PF   0x40
 #define REG_C_AF   0x20
+#define REG_C_MASK 0x70
 
 #endif
commit e46deabaa58b78397aeef2b04147aeecf5933794
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Aug 2 18:04:06 2012 +0200

    RTC: introduce RTC_CLOCK_RATE
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index b99f4d3..175ddac 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -46,6 +46,7 @@
 #endif
 
 #define RTC_REINJECT_ON_ACK_COUNT 20
+#define RTC_CLOCK_RATE            32768
 
 typedef struct RTCState {
     ISADevice dev;
@@ -85,7 +86,7 @@ static void rtc_coalesced_timer_update(RTCState *s)
         /* divide each RTC interval to 2 - 8 smaller intervals */
         int c = MIN(s->irq_coalesced, 7) + 1; 
         int64_t next_clock = qemu_get_clock_ns(rtc_clock) +
-            muldiv64(s->period / c, get_ticks_per_sec(), 32768);
+            muldiv64(s->period / c, get_ticks_per_sec(), RTC_CLOCK_RATE);
         qemu_mod_timer(s->coalesced_timer, next_clock);
     }
 }
@@ -131,10 +132,10 @@ static void periodic_timer_update(RTCState *s, int64_t current_time)
         s->period = period;
 #endif
         /* compute 32 khz clock */
-        cur_clock = muldiv64(current_time, 32768, get_ticks_per_sec());
+        cur_clock = muldiv64(current_time, RTC_CLOCK_RATE, get_ticks_per_sec());
         next_irq_clock = (cur_clock & ~(period - 1)) + period;
         s->next_periodic_time =
-            muldiv64(next_irq_clock, get_ticks_per_sec(), 32768) + 1;
+            muldiv64(next_irq_clock, get_ticks_per_sec(), RTC_CLOCK_RATE) + 1;
         qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
     } else {
 #ifdef TARGET_I386
@@ -369,7 +370,7 @@ static void rtc_update_second(void *opaque)
             /* update in progress bit */
             s->cmos_data[RTC_REG_A] |= REG_A_UIP;
         }
-        /* should be 244 us = 8 / 32768 seconds, but currently the
+        /* should be 244 us = 8 / RTC_CLOCK_RATE seconds, but currently the
            timers do not have the necessary resolution. */
         delay = (get_ticks_per_sec() * 1) / 100;
         if (delay < 1)
commit c4c18e246f968f18dc656afa3e8de7cf6b9752e8
Author: Yang Zhang <yang.z.zhang at intel.com>
Date:   Thu Aug 2 18:04:05 2012 +0200

    RTC: Rename rtc_timer_update
    
    Signed-off-by: Yang Zhang <yang.z.zhang at intel.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 6e5b2f0..b99f4d3 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -110,7 +110,7 @@ static void rtc_coalesced_timer(void *opaque)
 }
 #endif
 
-static void rtc_timer_update(RTCState *s, int64_t current_time)
+static void periodic_timer_update(RTCState *s, int64_t current_time)
 {
     int period_code, period;
     int64_t cur_clock, next_irq_clock;
@@ -148,7 +148,7 @@ static void rtc_periodic_timer(void *opaque)
 {
     RTCState *s = opaque;
 
-    rtc_timer_update(s, s->next_periodic_time);
+    periodic_timer_update(s, s->next_periodic_time);
     s->cmos_data[RTC_REG_C] |= REG_C_PF;
     if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
         s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
@@ -207,7 +207,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
             /* UIP bit is read only */
             s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
                 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
-            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
+            periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
             break;
         case RTC_REG_B:
             if (data & REG_B_SET) {
@@ -221,7 +221,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
                 }
             }
             s->cmos_data[RTC_REG_B] = data;
-            rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
+            periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
             break;
         case RTC_REG_C:
         case RTC_REG_D:
@@ -550,7 +550,7 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data)
     rtc_set_date_from_host(&s->dev);
     s->next_second_time = now + (get_ticks_per_sec() * 99) / 100;
     qemu_mod_timer(s->second_timer2, s->next_second_time);
-    rtc_timer_update(s, now);
+    periodic_timer_update(s, now);
 #ifdef TARGET_I386
     if (s->lost_tick_policy == LOST_TICK_SLEW) {
         rtc_coalesced_timer_update(s);
commit bedc572eae6e250070495116f0db72607826aee5
Author: Yang Zhang <yang.z.zhang at intel.com>
Date:   Thu Aug 2 18:04:04 2012 +0200

    RTC: Remove the logic to update time format when DM bit changed
    
    Changing the DM (binary/BCD) and 24/12 control bit doesn't affect the internal
    registers. It only indicates what format is used for those registers.
    
    Signed-off-by: Yang Zhang <yang.z.zhang at intel.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 3777f85..6e5b2f0 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -220,15 +220,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
                     rtc_set_time(s);
                 }
             }
-            if (((s->cmos_data[RTC_REG_B] ^ data) & (REG_B_DM | REG_B_24H)) &&
-                !(data & REG_B_SET)) {
-                /* If the time format has changed and not in set mode,
-                   update the registers immediately. */
-                s->cmos_data[RTC_REG_B] = data;
-                rtc_copy_date(s);
-            } else {
-                s->cmos_data[RTC_REG_B] = data;
-            }
+            s->cmos_data[RTC_REG_B] = data;
             rtc_timer_update(s, qemu_get_clock_ns(rtc_clock));
             break;
         case RTC_REG_C:
commit 6a38e0dc369e6bdc3b3ac4a965a34990c4980b66
Merge: 14df77a... c3ebd3b...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Sep 10 12:51:44 2012 -0500

    Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
    
    * qemu-kvm/uq/master:
      kvm: i386: Add classic PCI device assignment
      kvm: i386: Add services required for PCI device assignment
      kvm: Introduce kvm_has_intx_set_mask
      kvm: Introduce kvm_irqchip_update_msi_route
      kvm: Clean up irqfd API
      qemu: Use valgrind annotations to mark kvm guest memory as defined

commit 14df77a609e39403c3ec814bae63bec0fb4d24d2
Merge: 455aa1e... 1241ed9...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Sep 10 12:48:43 2012 -0500

    Merge remote-tracking branch 'mst/tags/for_anthony' into staging
    
    * mst/tags/for_anthony:
      vhost: Pass device path to vhost_dev_init()
      monitor: Rename+move net_handle_fd_param -> monitor_handle_fd_param
      pcie_aer: clear cmask for Advanced Error Interrupt Message Number
      pcie: drop version_id field for live migration
      qemu: add .exrc

commit 455aa1e0818653c41fd794435b982426ce21ba2f
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Sep 5 13:52:49 2012 -0500

    socket: don't attempt to reconnect a TCP socket in server mode
    
    Commit c3767ed0eb5d0bb25fe409ae5dec06e3411ff1b6 introduced a possible SEGV when
    using a socket chardev with server=on because it assumes that all TCP sockets
    are in client mode.
    
    This patch adds a check to only reconnect when in client mode.
    
    Cc: Lei Li <lilei at linux.vnet.ibm.com>
    Reported-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 398baf1..767da93 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2148,10 +2148,12 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
     TCPCharDriver *s = chr->opaque;
     if (s->connected) {
         return send_all(s->fd, buf, len);
-    } else {
+    } else if (s->listen_fd == -1) {
         /* (Re-)connect for unconnected writing */
         tcp_chr_connect(chr);
         return 0;
+    } else {
+        return len;
     }
 }
 
commit 8bf188aa18ef7a8355d9edbd43871d590468c4ed
Author: Michael Tokarev <mjt at tls.msk.ru>
Date:   Thu Jun 7 01:11:00 2012 +0400

    use --libexecdir instead of ignoring it first and reinventing it later
    
    Commit 7b93fadf3a38d1ed65ea5536a52efc2772c6e3b8 "Add basic version
    of bridge helper" put the bridge helper executable into a fixed
    ${prefix}/libexec/ location, instead of using ${libexecdir} for
    this.  At the same time, --libexecdir is being happily ignored
    by ./configure.  Even more, the same patch sets unused $libexecdir
    variable in the generated config-host.mak, and uses fixed string
    (\${prefix}/libexecdir) for the bridge helper binary.
    
    Fix this braindamage by introducing $libexecdir variable, using
    it for the bridge helper binary, and recognizing --libexecdir.
    
    This patch is applicable to stable-1.1.
    
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
    Cc: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Cc: Richa Marwaha <rmarwah at linux.vnet.ibm.com>
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index f4de245..fa64d5d 100755
--- a/configure
+++ b/configure
@@ -183,6 +183,7 @@ datadir="\${prefix}/share"
 qemu_docdir="\${prefix}/share/doc/qemu"
 bindir="\${prefix}/bin"
 libdir="\${prefix}/lib"
+libexecdir="\${prefix}/libexec"
 includedir="\${prefix}/include"
 sysconfdir="\${prefix}/etc"
 confsuffix="/qemu"
@@ -633,6 +634,8 @@ for opt do
   ;;
   --libdir=*) libdir="$optarg"
   ;;
+  --libexecdir=*) libexecdir="$optarg"
+  ;;
   --includedir=*) includedir="$optarg"
   ;;
   --datadir=*) datadir="$optarg"
@@ -643,7 +646,7 @@ for opt do
   ;;
   --sysconfdir=*) sysconfdir="$optarg"
   ;;
-  --sbindir=*|--libexecdir=*|--sharedstatedir=*|--localstatedir=*|\
+  --sbindir=*|--sharedstatedir=*|--localstatedir=*|\
   --oldincludedir=*|--datarootdir=*|--infodir=*|--localedir=*|\
   --htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*)
     # These switches are silently ignored, for compatibility with
@@ -3085,6 +3088,7 @@ echo "Install prefix    $prefix"
 echo "BIOS directory    `eval echo $qemu_datadir`"
 echo "binary directory  `eval echo $bindir`"
 echo "library directory `eval echo $libdir`"
+echo "libexec directory `eval echo $libexecdir`"
 echo "include directory `eval echo $includedir`"
 echo "config directory  `eval echo $sysconfdir`"
 if test "$mingw32" = "no" ; then
@@ -3188,14 +3192,14 @@ echo all: >> $config_host_mak
 echo "prefix=$prefix" >> $config_host_mak
 echo "bindir=$bindir" >> $config_host_mak
 echo "libdir=$libdir" >> $config_host_mak
+echo "libexecdir=$libexecdir" >> $config_host_mak
 echo "includedir=$includedir" >> $config_host_mak
 echo "mandir=$mandir" >> $config_host_mak
 echo "sysconfdir=$sysconfdir" >> $config_host_mak
 echo "qemu_confdir=$qemu_confdir" >> $config_host_mak
 echo "qemu_datadir=$qemu_datadir" >> $config_host_mak
 echo "qemu_docdir=$qemu_docdir" >> $config_host_mak
-echo "libexecdir=\${prefix}/libexec" >> $config_host_mak
-echo "CONFIG_QEMU_HELPERDIR=\"$prefix/libexec\"" >> $config_host_mak
+echo "CONFIG_QEMU_HELPERDIR=\"$libexecdir\"" >> $config_host_mak
 
 echo "ARCH=$ARCH" >> $config_host_mak
 if test "$debug_tcg" = "yes" ; then
commit 69fc255350af9e8e39e29b4d6a84d44f0a55ebf2
Merge: e22b1e9... 265db73...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Sep 10 15:32:11 2012 +0200

    Merge branch 'spice.v59' of git://anongit.freedesktop.org/spice/qemu
    
    * 'spice.v59' of git://anongit.freedesktop.org/spice/qemu:
      Remove #ifdef QXL_COMMAND_FLAG_COMPAT_16BPP
      qxl: Add set_client_capabilities() interface to QXLInterface
      spice: make number of surfaces runtime-configurable.
      configure: print spice-protocol and spice-server versions
      qxl: add QXL_IO_MONITORS_CONFIG_ASYNC
      qxl: disallow unknown revisions
      qxl/update_area_io: guest_bug on invalid parameters
      spice: increase the verbosity of spice section in "qemu --help"
      spice: adding seamless-migration option to the command line
      spice: add 'migrated' flag to spice info
      spice migration: add QEVENT_SPICE_MIGRATE_COMPLETED
      spice: notify on vm state change only via spice_server_vm_start/stop
      spice: notify spice server on vm start/stop
      spice: abort on invalid streaming cmdline params

commit e22b1e9907833d72f4a959b34c5eefc3533c7711
Merge: a32354e... 0ab6b63...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Sep 10 15:04:36 2012 +0200

    Merge branch 'queue/qmp' of git://repo.or.cz/qemu/qmp-unstable
    
    * 'queue/qmp' of git://repo.or.cz/qemu/qmp-unstable:
      tcx: tcx_screen_dump(): add error handling
      tcx: tcx24_screen_dump(): add error handling
      g364fb: g364fb_screen_dump(): add error handling
      omap_lcdc: omap_ppm_save(): add error handling
      omap_lcdc: rename ppm_save() to omap_ppm_save()
      vga: ppm_save(): add error handling
      qapi: convert screendump
      console: vga_hw_screen_dump_ptr: take Error argument
      error: add error_setg()
      json-parser: Fix potential NULL pointer segfault
      qapi: Fix potential NULL pointer segfault
      qapi: convert sendkey
      monitor: move key_defs[] table and introduce two help functions
      qapi: add the QKeyCode enum
      qapi: generate list struct and visit_list for enum
      hmp: rename arguments
      monitor: rename keyname '<' to 'less'
      fix doc of using raw values with sendkey
      Add support for pretty-printing response in qmp-shell

commit a32354e206895400d17c3de9a8df1de96d3df289
Author: Stefan Weil <sw at weilnetz.de>
Date:   Tue Sep 4 19:37:39 2012 +0200

    hw/mcf5206: Fix buffer overflow for MBAR read / write
    
    Report from smatch:
    
    mcf5206.c:384 m5206_mbar_readb(7) error: buffer overflow 'm5206_mbar_width' 128 <= 128
    mcf5206.c:403 m5206_mbar_readw(8) error: buffer overflow 'm5206_mbar_width' 128 <= 128
    mcf5206.c:427 m5206_mbar_readl(8) error: buffer overflow 'm5206_mbar_width' 128 <= 128
    mcf5206.c:451 m5206_mbar_writeb(9) error: buffer overflow 'm5206_mbar_width' 128 <= 128
    mcf5206.c:475 m5206_mbar_writew(9) error: buffer overflow 'm5206_mbar_width' 128 <= 128
    mcf5206.c:503 m5206_mbar_writel(9) error: buffer overflow 'm5206_mbar_width' 128 <= 128
    
    m5206_mbar_width has 0x80 elements and supports 0 <= offset < 0x200.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/mcf5206.c b/hw/mcf5206.c
index 539b391..27753e2 100644
--- a/hw/mcf5206.c
+++ b/hw/mcf5206.c
@@ -378,7 +378,7 @@ static uint32_t m5206_mbar_readb(void *opaque, target_phys_addr_t offset)
 {
     m5206_mbar_state *s = (m5206_mbar_state *)opaque;
     offset &= 0x3ff;
-    if (offset > 0x200) {
+    if (offset >= 0x200) {
         hw_error("Bad MBAR read offset 0x%x", (int)offset);
     }
     if (m5206_mbar_width[offset >> 2] > 1) {
@@ -397,7 +397,7 @@ static uint32_t m5206_mbar_readw(void *opaque, target_phys_addr_t offset)
     m5206_mbar_state *s = (m5206_mbar_state *)opaque;
     int width;
     offset &= 0x3ff;
-    if (offset > 0x200) {
+    if (offset >= 0x200) {
         hw_error("Bad MBAR read offset 0x%x", (int)offset);
     }
     width = m5206_mbar_width[offset >> 2];
@@ -421,7 +421,7 @@ static uint32_t m5206_mbar_readl(void *opaque, target_phys_addr_t offset)
     m5206_mbar_state *s = (m5206_mbar_state *)opaque;
     int width;
     offset &= 0x3ff;
-    if (offset > 0x200) {
+    if (offset >= 0x200) {
         hw_error("Bad MBAR read offset 0x%x", (int)offset);
     }
     width = m5206_mbar_width[offset >> 2];
@@ -445,7 +445,7 @@ static void m5206_mbar_writeb(void *opaque, target_phys_addr_t offset,
     m5206_mbar_state *s = (m5206_mbar_state *)opaque;
     int width;
     offset &= 0x3ff;
-    if (offset > 0x200) {
+    if (offset >= 0x200) {
         hw_error("Bad MBAR write offset 0x%x", (int)offset);
     }
     width = m5206_mbar_width[offset >> 2];
@@ -469,7 +469,7 @@ static void m5206_mbar_writew(void *opaque, target_phys_addr_t offset,
     m5206_mbar_state *s = (m5206_mbar_state *)opaque;
     int width;
     offset &= 0x3ff;
-    if (offset > 0x200) {
+    if (offset >= 0x200) {
         hw_error("Bad MBAR write offset 0x%x", (int)offset);
     }
     width = m5206_mbar_width[offset >> 2];
@@ -497,7 +497,7 @@ static void m5206_mbar_writel(void *opaque, target_phys_addr_t offset,
     m5206_mbar_state *s = (m5206_mbar_state *)opaque;
     int width;
     offset &= 0x3ff;
-    if (offset > 0x200) {
+    if (offset >= 0x200) {
         hw_error("Bad MBAR write offset 0x%x", (int)offset);
     }
     width = m5206_mbar_width[offset >> 2];
commit 599d64f6dc10f267a45e7abebfcafd8e7626585b
Author: Stefan Weil <sw at weilnetz.de>
Date:   Tue Sep 4 07:35:57 2012 +0200

    target-arm: Fix potential buffer overflow
    
    Report from smatch:
    
    target-arm/helper.c:651 arm946_prbs_read(6) error:
     buffer overflow 'env->cp15.c6_region' 8 <= 8
    target-arm/helper.c:661 arm946_prbs_write(6) error:
     buffer overflow 'env->cp15.c6_region' 8 <= 8
    
    c7_region is an array with 8 elements, so the index must be less than 8.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index dceaa95..e27df96 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -645,7 +645,7 @@ static int pmsav5_insn_ap_read(CPUARMState *env, const ARMCPRegInfo *ri,
 static int arm946_prbs_read(CPUARMState *env, const ARMCPRegInfo *ri,
                             uint64_t *value)
 {
-    if (ri->crm > 8) {
+    if (ri->crm >= 8) {
         return EXCP_UDEF;
     }
     *value = env->cp15.c6_region[ri->crm];
@@ -655,7 +655,7 @@ static int arm946_prbs_read(CPUARMState *env, const ARMCPRegInfo *ri,
 static int arm946_prbs_write(CPUARMState *env, const ARMCPRegInfo *ri,
                              uint64_t value)
 {
-    if (ri->crm > 8) {
+    if (ri->crm >= 8) {
         return EXCP_UDEF;
     }
     env->cp15.c6_region[ri->crm] = value;
commit 149eeb5fe57b853081e8059575d91b8a58a4f96c
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Sep 3 22:56:00 2012 +0200

    hw/wm8750: Fix potential buffer overflow
    
    Report from smatch:
    
    hw/wm8750.c:369 wm8750_tx(12) error: buffer overflow 's->i2c_data' 2 <= 2
    
    It looks like the preprocessor statements were simply misplaced.
    
    Replace also __FUNCTION__ by __func__ to please checkpatch.pl.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/wm8750.c b/hw/wm8750.c
index 11bcec3..44f138f 100644
--- a/hw/wm8750.c
+++ b/hw/wm8750.c
@@ -361,10 +361,10 @@ static int wm8750_tx(I2CSlave *i2c, uint8_t data)
     uint16_t value;
 
     if (s->i2c_len >= 2) {
-        printf("%s: long message (%i bytes)\n", __FUNCTION__, s->i2c_len);
 #ifdef VERBOSE
-        return 1;
+        printf("%s: long message (%i bytes)\n", __func__, s->i2c_len);
 #endif
+        return 1;
     }
     s->i2c_data[s->i2c_len ++] = data;
     if (s->i2c_len != 2)
commit c3ebd3ba786e1be5449527e47001eded6b59322b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu Aug 30 20:30:00 2012 +0200

    kvm: i386: Add classic PCI device assignment
    
    This adds PCI device assignment for i386 targets using the classic KVM
    interfaces. This version is 100% identical to what is being maintained
    in qemu-kvm for several years and is supported by libvirt as well. It is
    expected to remain relevant for another couple of years until kernels
    without full-features and performance-wise equivalent VFIO support are
    obsolete.
    
    A refactoring to-do that should be done in-tree is to model MSI and
    MSI-X support via the generic PCI layer, similar to what VFIO is already
    doing for MSI-X. This should improve the correctness and clean up the
    code from duplicate logic.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Acked-by: Acked-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/kvm/Makefile.objs b/hw/kvm/Makefile.objs
index 226497a..f620d7f 100644
--- a/hw/kvm/Makefile.objs
+++ b/hw/kvm/Makefile.objs
@@ -1 +1 @@
-obj-$(CONFIG_KVM) += clock.o apic.o i8259.o ioapic.o i8254.o
+obj-$(CONFIG_KVM) += clock.o apic.o i8259.o ioapic.o i8254.o pci-assign.o
diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c
new file mode 100644
index 0000000..05b93d9
--- /dev/null
+++ b/hw/kvm/pci-assign.c
@@ -0,0 +1,1915 @@
+/*
+ * Copyright (c) 2007, Neocleus Corporation.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ *
+ *  Assign a PCI device from the host to a guest VM.
+ *
+ *  This implementation uses the classic device assignment interface of KVM
+ *  and is only available on x86 hosts. It is expected to be obsoleted by VFIO
+ *  based device assignment.
+ *
+ *  Adapted for KVM (qemu-kvm) by Qumranet. QEMU version was based on qemu-kvm
+ *  revision 4144fe9d48. See its repository for the history.
+ *
+ *  Copyright (c) 2007, Neocleus, Alex Novik (alex at neocleus.com)
+ *  Copyright (c) 2007, Neocleus, Guy Zana (guy at neocleus.com)
+ *  Copyright (C) 2008, Qumranet, Amit Shah (amit.shah at qumranet.com)
+ *  Copyright (C) 2008, Red Hat, Amit Shah (amit.shah at redhat.com)
+ *  Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli at il.ibm.com)
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/io.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "qemu-error.h"
+#include "console.h"
+#include "hw/loader.h"
+#include "monitor.h"
+#include "range.h"
+#include "sysemu.h"
+#include "hw/pci.h"
+#include "hw/msi.h"
+#include "kvm_i386.h"
+
+#define MSIX_PAGE_SIZE 0x1000
+
+/* From linux/ioport.h */
+#define IORESOURCE_IO       0x00000100  /* Resource type */
+#define IORESOURCE_MEM      0x00000200
+#define IORESOURCE_IRQ      0x00000400
+#define IORESOURCE_DMA      0x00000800
+#define IORESOURCE_PREFETCH 0x00002000  /* No side effects */
+
+//#define DEVICE_ASSIGNMENT_DEBUG
+
+#ifdef DEVICE_ASSIGNMENT_DEBUG
+#define DEBUG(fmt, ...)                                       \
+    do {                                                      \
+        fprintf(stderr, "%s: " fmt, __func__ , __VA_ARGS__);  \
+    } while (0)
+#else
+#define DEBUG(fmt, ...)
+#endif
+
+typedef struct PCIRegion {
+    int type;           /* Memory or port I/O */
+    int valid;
+    uint64_t base_addr;
+    uint64_t size;    /* size of the region */
+    int resource_fd;
+} PCIRegion;
+
+typedef struct PCIDevRegions {
+    uint8_t bus, dev, func; /* Bus inside domain, device and function */
+    int irq;                /* IRQ number */
+    uint16_t region_number; /* number of active regions */
+
+    /* Port I/O or MMIO Regions */
+    PCIRegion regions[PCI_NUM_REGIONS - 1];
+    int config_fd;
+} PCIDevRegions;
+
+typedef struct AssignedDevRegion {
+    MemoryRegion container;
+    MemoryRegion real_iomem;
+    union {
+        uint8_t *r_virtbase; /* mmapped access address for memory regions */
+        uint32_t r_baseport; /* the base guest port for I/O regions */
+    } u;
+    pcibus_t e_size;    /* emulated size of region in bytes */
+    pcibus_t r_size;    /* real size of region in bytes */
+    PCIRegion *region;
+} AssignedDevRegion;
+
+#define ASSIGNED_DEVICE_PREFER_MSI_BIT  0
+#define ASSIGNED_DEVICE_SHARE_INTX_BIT  1
+
+#define ASSIGNED_DEVICE_PREFER_MSI_MASK (1 << ASSIGNED_DEVICE_PREFER_MSI_BIT)
+#define ASSIGNED_DEVICE_SHARE_INTX_MASK (1 << ASSIGNED_DEVICE_SHARE_INTX_BIT)
+
+typedef struct MSIXTableEntry {
+    uint32_t addr_lo;
+    uint32_t addr_hi;
+    uint32_t data;
+    uint32_t ctrl;
+} MSIXTableEntry;
+
+typedef enum AssignedIRQType {
+    ASSIGNED_IRQ_NONE = 0,
+    ASSIGNED_IRQ_INTX_HOST_INTX,
+    ASSIGNED_IRQ_INTX_HOST_MSI,
+    ASSIGNED_IRQ_MSI,
+    ASSIGNED_IRQ_MSIX
+} AssignedIRQType;
+
+typedef struct AssignedDevice {
+    PCIDevice dev;
+    PCIHostDeviceAddress host;
+    uint32_t dev_id;
+    uint32_t features;
+    int intpin;
+    AssignedDevRegion v_addrs[PCI_NUM_REGIONS - 1];
+    PCIDevRegions real_device;
+    PCIINTxRoute intx_route;
+    AssignedIRQType assigned_irq_type;
+    struct {
+#define ASSIGNED_DEVICE_CAP_MSI (1 << 0)
+#define ASSIGNED_DEVICE_CAP_MSIX (1 << 1)
+        uint32_t available;
+#define ASSIGNED_DEVICE_MSI_ENABLED (1 << 0)
+#define ASSIGNED_DEVICE_MSIX_ENABLED (1 << 1)
+#define ASSIGNED_DEVICE_MSIX_MASKED (1 << 2)
+        uint32_t state;
+    } cap;
+    uint8_t emulate_config_read[PCI_CONFIG_SPACE_SIZE];
+    uint8_t emulate_config_write[PCI_CONFIG_SPACE_SIZE];
+    int msi_virq_nr;
+    int *msi_virq;
+    MSIXTableEntry *msix_table;
+    target_phys_addr_t msix_table_addr;
+    uint16_t msix_max;
+    MemoryRegion mmio;
+    char *configfd_name;
+    int32_t bootindex;
+} AssignedDevice;
+
+static void assigned_dev_update_irq_routing(PCIDevice *dev);
+
+static void assigned_dev_load_option_rom(AssignedDevice *dev);
+
+static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev);
+
+static uint64_t assigned_dev_ioport_rw(AssignedDevRegion *dev_region,
+                                       target_phys_addr_t addr, int size,
+                                       uint64_t *data)
+{
+    uint64_t val = 0;
+    int fd = dev_region->region->resource_fd;
+
+    if (fd >= 0) {
+        if (data) {
+            DEBUG("pwrite data=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx
+                  ", addr="TARGET_FMT_plx"\n", *data, size, addr, addr);
+            if (pwrite(fd, data, size, addr) != size) {
+                error_report("%s - pwrite failed %s",
+                             __func__, strerror(errno));
+            }
+        } else {
+            if (pread(fd, &val, size, addr) != size) {
+                error_report("%s - pread failed %s",
+                             __func__, strerror(errno));
+                val = (1UL << (size * 8)) - 1;
+            }
+            DEBUG("pread val=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx
+                  ", addr=" TARGET_FMT_plx "\n", val, size, addr, addr);
+        }
+    } else {
+        uint32_t port = addr + dev_region->u.r_baseport;
+
+        if (data) {
+            DEBUG("out data=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx
+                  ", host=%x\n", *data, size, addr, port);
+            switch (size) {
+            case 1:
+                outb(*data, port);
+                break;
+            case 2:
+                outw(*data, port);
+                break;
+            case 4:
+                outl(*data, port);
+                break;
+            }
+        } else {
+            switch (size) {
+            case 1:
+                val = inb(port);
+                break;
+            case 2:
+                val = inw(port);
+                break;
+            case 4:
+                val = inl(port);
+                break;
+            }
+            DEBUG("in data=%" PRIx64 ", size=%d, e_phys=" TARGET_FMT_plx
+                  ", host=%x\n", val, size, addr, port);
+        }
+    }
+    return val;
+}
+
+static void assigned_dev_ioport_write(void *opaque, target_phys_addr_t addr,
+                                      uint64_t data, unsigned size)
+{
+    assigned_dev_ioport_rw(opaque, addr, size, &data);
+}
+
+static uint64_t assigned_dev_ioport_read(void *opaque,
+                                         target_phys_addr_t addr, unsigned size)
+{
+    return assigned_dev_ioport_rw(opaque, addr, size, NULL);
+}
+
+static uint32_t slow_bar_readb(void *opaque, target_phys_addr_t addr)
+{
+    AssignedDevRegion *d = opaque;
+    uint8_t *in = d->u.r_virtbase + addr;
+    uint32_t r;
+
+    r = *in;
+    DEBUG("slow_bar_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r);
+
+    return r;
+}
+
+static uint32_t slow_bar_readw(void *opaque, target_phys_addr_t addr)
+{
+    AssignedDevRegion *d = opaque;
+    uint16_t *in = (uint16_t *)(d->u.r_virtbase + addr);
+    uint32_t r;
+
+    r = *in;
+    DEBUG("slow_bar_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r);
+
+    return r;
+}
+
+static uint32_t slow_bar_readl(void *opaque, target_phys_addr_t addr)
+{
+    AssignedDevRegion *d = opaque;
+    uint32_t *in = (uint32_t *)(d->u.r_virtbase + addr);
+    uint32_t r;
+
+    r = *in;
+    DEBUG("slow_bar_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r);
+
+    return r;
+}
+
+static void slow_bar_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    AssignedDevRegion *d = opaque;
+    uint8_t *out = d->u.r_virtbase + addr;
+
+    DEBUG("slow_bar_writeb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr, val);
+    *out = val;
+}
+
+static void slow_bar_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    AssignedDevRegion *d = opaque;
+    uint16_t *out = (uint16_t *)(d->u.r_virtbase + addr);
+
+    DEBUG("slow_bar_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr, val);
+    *out = val;
+}
+
+static void slow_bar_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    AssignedDevRegion *d = opaque;
+    uint32_t *out = (uint32_t *)(d->u.r_virtbase + addr);
+
+    DEBUG("slow_bar_writel addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, val);
+    *out = val;
+}
+
+static const MemoryRegionOps slow_bar_ops = {
+    .old_mmio = {
+        .read = { slow_bar_readb, slow_bar_readw, slow_bar_readl, },
+        .write = { slow_bar_writeb, slow_bar_writew, slow_bar_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void assigned_dev_iomem_setup(PCIDevice *pci_dev, int region_num,
+                                     pcibus_t e_size)
+{
+    AssignedDevice *r_dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+    AssignedDevRegion *region = &r_dev->v_addrs[region_num];
+    PCIRegion *real_region = &r_dev->real_device.regions[region_num];
+
+    if (e_size > 0) {
+        memory_region_init(&region->container, "assigned-dev-container",
+                           e_size);
+        memory_region_add_subregion(&region->container, 0, &region->real_iomem);
+
+        /* deal with MSI-X MMIO page */
+        if (real_region->base_addr <= r_dev->msix_table_addr &&
+                real_region->base_addr + real_region->size >
+                r_dev->msix_table_addr) {
+            uint64_t offset = r_dev->msix_table_addr - real_region->base_addr;
+
+            memory_region_add_subregion_overlap(&region->container,
+                                                offset,
+                                                &r_dev->mmio,
+                                                1);
+        }
+    }
+}
+
+static const MemoryRegionOps assigned_dev_ioport_ops = {
+    .read = assigned_dev_ioport_read,
+    .write = assigned_dev_ioport_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void assigned_dev_ioport_setup(PCIDevice *pci_dev, int region_num,
+                                      pcibus_t size)
+{
+    AssignedDevice *r_dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+    AssignedDevRegion *region = &r_dev->v_addrs[region_num];
+
+    region->e_size = size;
+    memory_region_init(&region->container, "assigned-dev-container", size);
+    memory_region_init_io(&region->real_iomem, &assigned_dev_ioport_ops,
+                          r_dev->v_addrs + region_num,
+                          "assigned-dev-iomem", size);
+    memory_region_add_subregion(&region->container, 0, &region->real_iomem);
+}
+
+static uint32_t assigned_dev_pci_read(PCIDevice *d, int pos, int len)
+{
+    AssignedDevice *pci_dev = DO_UPCAST(AssignedDevice, dev, d);
+    uint32_t val;
+    ssize_t ret;
+    int fd = pci_dev->real_device.config_fd;
+
+again:
+    ret = pread(fd, &val, len, pos);
+    if (ret != len) {
+        if ((ret < 0) && (errno == EINTR || errno == EAGAIN)) {
+            goto again;
+        }
+
+        hw_error("pci read failed, ret = %zd errno = %d\n", ret, errno);
+    }
+
+    return val;
+}
+
+static uint8_t assigned_dev_pci_read_byte(PCIDevice *d, int pos)
+{
+    return (uint8_t)assigned_dev_pci_read(d, pos, 1);
+}
+
+static void assigned_dev_pci_write(PCIDevice *d, int pos, uint32_t val, int len)
+{
+    AssignedDevice *pci_dev = DO_UPCAST(AssignedDevice, dev, d);
+    ssize_t ret;
+    int fd = pci_dev->real_device.config_fd;
+
+again:
+    ret = pwrite(fd, &val, len, pos);
+    if (ret != len) {
+        if ((ret < 0) && (errno == EINTR || errno == EAGAIN)) {
+            goto again;
+        }
+
+        hw_error("pci write failed, ret = %zd errno = %d\n", ret, errno);
+    }
+}
+
+static void assigned_dev_emulate_config_read(AssignedDevice *dev,
+                                             uint32_t offset, uint32_t len)
+{
+    memset(dev->emulate_config_read + offset, 0xff, len);
+}
+
+static void assigned_dev_direct_config_read(AssignedDevice *dev,
+                                            uint32_t offset, uint32_t len)
+{
+    memset(dev->emulate_config_read + offset, 0, len);
+}
+
+static void assigned_dev_direct_config_write(AssignedDevice *dev,
+                                             uint32_t offset, uint32_t len)
+{
+    memset(dev->emulate_config_write + offset, 0, len);
+}
+
+static uint8_t pci_find_cap_offset(PCIDevice *d, uint8_t cap, uint8_t start)
+{
+    int id;
+    int max_cap = 48;
+    int pos = start ? start : PCI_CAPABILITY_LIST;
+    int status;
+
+    status = assigned_dev_pci_read_byte(d, PCI_STATUS);
+    if ((status & PCI_STATUS_CAP_LIST) == 0) {
+        return 0;
+    }
+
+    while (max_cap--) {
+        pos = assigned_dev_pci_read_byte(d, pos);
+        if (pos < 0x40) {
+            break;
+        }
+
+        pos &= ~3;
+        id = assigned_dev_pci_read_byte(d, pos + PCI_CAP_LIST_ID);
+
+        if (id == 0xff) {
+            break;
+        }
+        if (id == cap) {
+            return pos;
+        }
+
+        pos += PCI_CAP_LIST_NEXT;
+    }
+    return 0;
+}
+
+static int assigned_dev_register_regions(PCIRegion *io_regions,
+                                         unsigned long regions_num,
+                                         AssignedDevice *pci_dev)
+{
+    uint32_t i;
+    PCIRegion *cur_region = io_regions;
+
+    for (i = 0; i < regions_num; i++, cur_region++) {
+        if (!cur_region->valid) {
+            continue;
+        }
+
+        /* handle memory io regions */
+        if (cur_region->type & IORESOURCE_MEM) {
+            int t = cur_region->type & IORESOURCE_PREFETCH
+                ? PCI_BASE_ADDRESS_MEM_PREFETCH
+                : PCI_BASE_ADDRESS_SPACE_MEMORY;
+
+            /* map physical memory */
+            pci_dev->v_addrs[i].u.r_virtbase = mmap(NULL, cur_region->size,
+                                                    PROT_WRITE | PROT_READ,
+                                                    MAP_SHARED,
+                                                    cur_region->resource_fd,
+                                                    (off_t)0);
+
+            if (pci_dev->v_addrs[i].u.r_virtbase == MAP_FAILED) {
+                pci_dev->v_addrs[i].u.r_virtbase = NULL;
+                error_report("%s: Error: Couldn't mmap 0x%" PRIx64 "!",
+                             __func__, cur_region->base_addr);
+                return -1;
+            }
+
+            pci_dev->v_addrs[i].r_size = cur_region->size;
+            pci_dev->v_addrs[i].e_size = 0;
+
+            /* add offset */
+            pci_dev->v_addrs[i].u.r_virtbase +=
+                (cur_region->base_addr & 0xFFF);
+
+            if (cur_region->size & 0xFFF) {
+                error_report("PCI region %d at address 0x%" PRIx64 " has "
+                             "size 0x%" PRIx64 ", which is not a multiple of "
+                             "4K.  You might experience some performance hit "
+                             "due to that.",
+                             i, cur_region->base_addr, cur_region->size);
+                memory_region_init_io(&pci_dev->v_addrs[i].real_iomem,
+                                      &slow_bar_ops, &pci_dev->v_addrs[i],
+                                      "assigned-dev-slow-bar",
+                                      cur_region->size);
+            } else {
+                void *virtbase = pci_dev->v_addrs[i].u.r_virtbase;
+                char name[32];
+                snprintf(name, sizeof(name), "%s.bar%d",
+                         object_get_typename(OBJECT(pci_dev)), i);
+                memory_region_init_ram_ptr(&pci_dev->v_addrs[i].real_iomem,
+                                           name, cur_region->size,
+                                           virtbase);
+                vmstate_register_ram(&pci_dev->v_addrs[i].real_iomem,
+                                     &pci_dev->dev.qdev);
+            }
+
+            assigned_dev_iomem_setup(&pci_dev->dev, i, cur_region->size);
+            pci_register_bar((PCIDevice *) pci_dev, i, t,
+                             &pci_dev->v_addrs[i].container);
+            continue;
+        } else {
+            /* handle port io regions */
+            uint32_t val;
+            int ret;
+
+            /* Test kernel support for ioport resource read/write.  Old
+             * kernels return EIO.  New kernels only allow 1/2/4 byte reads
+             * so should return EINVAL for a 3 byte read */
+            ret = pread(pci_dev->v_addrs[i].region->resource_fd, &val, 3, 0);
+            if (ret >= 0) {
+                error_report("Unexpected return from I/O port read: %d", ret);
+                abort();
+            } else if (errno != EINVAL) {
+                error_report("Kernel doesn't support ioport resource "
+                             "access, hiding this region.");
+                close(pci_dev->v_addrs[i].region->resource_fd);
+                cur_region->valid = 0;
+                continue;
+            }
+
+            pci_dev->v_addrs[i].u.r_baseport = cur_region->base_addr;
+            pci_dev->v_addrs[i].r_size = cur_region->size;
+            pci_dev->v_addrs[i].e_size = 0;
+
+            assigned_dev_ioport_setup(&pci_dev->dev, i, cur_region->size);
+            pci_register_bar((PCIDevice *) pci_dev, i,
+                             PCI_BASE_ADDRESS_SPACE_IO,
+                             &pci_dev->v_addrs[i].container);
+        }
+    }
+
+    /* success */
+    return 0;
+}
+
+static int get_real_id(const char *devpath, const char *idname, uint16_t *val)
+{
+    FILE *f;
+    char name[128];
+    long id;
+
+    snprintf(name, sizeof(name), "%s%s", devpath, idname);
+    f = fopen(name, "r");
+    if (f == NULL) {
+        error_report("%s: %s: %m", __func__, name);
+        return -1;
+    }
+    if (fscanf(f, "%li\n", &id) == 1) {
+        *val = id;
+    } else {
+        return -1;
+    }
+    fclose(f);
+
+    return 0;
+}
+
+static int get_real_vendor_id(const char *devpath, uint16_t *val)
+{
+    return get_real_id(devpath, "vendor", val);
+}
+
+static int get_real_device_id(const char *devpath, uint16_t *val)
+{
+    return get_real_id(devpath, "device", val);
+}
+
+static int get_real_device(AssignedDevice *pci_dev, uint16_t r_seg,
+                           uint8_t r_bus, uint8_t r_dev, uint8_t r_func)
+{
+    char dir[128], name[128];
+    int fd, r = 0, v;
+    FILE *f;
+    uint64_t start, end, size, flags;
+    uint16_t id;
+    PCIRegion *rp;
+    PCIDevRegions *dev = &pci_dev->real_device;
+
+    dev->region_number = 0;
+
+    snprintf(dir, sizeof(dir), "/sys/bus/pci/devices/%04x:%02x:%02x.%x/",
+             r_seg, r_bus, r_dev, r_func);
+
+    snprintf(name, sizeof(name), "%sconfig", dir);
+
+    if (pci_dev->configfd_name && *pci_dev->configfd_name) {
+        if (qemu_isdigit(pci_dev->configfd_name[0])) {
+            dev->config_fd = strtol(pci_dev->configfd_name, NULL, 0);
+        } else {
+            dev->config_fd = monitor_get_fd(cur_mon, pci_dev->configfd_name);
+            if (dev->config_fd < 0) {
+                error_report("%s: (%s) unkown", __func__,
+                             pci_dev->configfd_name);
+                return 1;
+            }
+        }
+    } else {
+        dev->config_fd = open(name, O_RDWR);
+
+        if (dev->config_fd == -1) {
+            error_report("%s: %s: %m", __func__, name);
+            return 1;
+        }
+    }
+again:
+    r = read(dev->config_fd, pci_dev->dev.config,
+             pci_config_size(&pci_dev->dev));
+    if (r < 0) {
+        if (errno == EINTR || errno == EAGAIN) {
+            goto again;
+        }
+        error_report("%s: read failed, errno = %d", __func__, errno);
+    }
+
+    /* Restore or clear multifunction, this is always controlled by qemu */
+    if (pci_dev->dev.cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
+        pci_dev->dev.config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
+    } else {
+        pci_dev->dev.config[PCI_HEADER_TYPE] &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;
+    }
+
+    /* Clear host resource mapping info.  If we choose not to register a
+     * BAR, such as might be the case with the option ROM, we can get
+     * confusing, unwritable, residual addresses from the host here. */
+    memset(&pci_dev->dev.config[PCI_BASE_ADDRESS_0], 0, 24);
+    memset(&pci_dev->dev.config[PCI_ROM_ADDRESS], 0, 4);
+
+    snprintf(name, sizeof(name), "%sresource", dir);
+
+    f = fopen(name, "r");
+    if (f == NULL) {
+        error_report("%s: %s: %m", __func__, name);
+        return 1;
+    }
+
+    for (r = 0; r < PCI_ROM_SLOT; r++) {
+        if (fscanf(f, "%" SCNi64 " %" SCNi64 " %" SCNi64 "\n",
+                   &start, &end, &flags) != 3) {
+            break;
+        }
+
+        rp = dev->regions + r;
+        rp->valid = 0;
+        rp->resource_fd = -1;
+        size = end - start + 1;
+        flags &= IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH;
+        if (size == 0 || (flags & ~IORESOURCE_PREFETCH) == 0) {
+            continue;
+        }
+        if (flags & IORESOURCE_MEM) {
+            flags &= ~IORESOURCE_IO;
+        } else {
+            flags &= ~IORESOURCE_PREFETCH;
+        }
+        snprintf(name, sizeof(name), "%sresource%d", dir, r);
+        fd = open(name, O_RDWR);
+        if (fd == -1) {
+            continue;
+        }
+        rp->resource_fd = fd;
+
+        rp->type = flags;
+        rp->valid = 1;
+        rp->base_addr = start;
+        rp->size = size;
+        pci_dev->v_addrs[r].region = rp;
+        DEBUG("region %d size %" PRIu64 " start 0x%" PRIx64
+              " type %d resource_fd %d\n",
+              r, rp->size, start, rp->type, rp->resource_fd);
+    }
+
+    fclose(f);
+
+    /* read and fill vendor ID */
+    v = get_real_vendor_id(dir, &id);
+    if (v) {
+        return 1;
+    }
+    pci_dev->dev.config[0] = id & 0xff;
+    pci_dev->dev.config[1] = (id & 0xff00) >> 8;
+
+    /* read and fill device ID */
+    v = get_real_device_id(dir, &id);
+    if (v) {
+        return 1;
+    }
+    pci_dev->dev.config[2] = id & 0xff;
+    pci_dev->dev.config[3] = (id & 0xff00) >> 8;
+
+    pci_word_test_and_clear_mask(pci_dev->emulate_config_write + PCI_COMMAND,
+                                 PCI_COMMAND_MASTER | PCI_COMMAND_INTX_DISABLE);
+
+    dev->region_number = r;
+    return 0;
+}
+
+static void free_msi_virqs(AssignedDevice *dev)
+{
+    int i;
+
+    for (i = 0; i < dev->msi_virq_nr; i++) {
+        if (dev->msi_virq[i] >= 0) {
+            kvm_irqchip_release_virq(kvm_state, dev->msi_virq[i]);
+            dev->msi_virq[i] = -1;
+        }
+    }
+    g_free(dev->msi_virq);
+    dev->msi_virq = NULL;
+    dev->msi_virq_nr = 0;
+}
+
+static void free_assigned_device(AssignedDevice *dev)
+{
+    int i;
+
+    if (dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) {
+        assigned_dev_unregister_msix_mmio(dev);
+    }
+    for (i = 0; i < dev->real_device.region_number; i++) {
+        PCIRegion *pci_region = &dev->real_device.regions[i];
+        AssignedDevRegion *region = &dev->v_addrs[i];
+
+        if (!pci_region->valid) {
+            continue;
+        }
+        if (pci_region->type & IORESOURCE_IO) {
+            if (region->u.r_baseport) {
+                memory_region_del_subregion(&region->container,
+                                            &region->real_iomem);
+                memory_region_destroy(&region->real_iomem);
+                memory_region_destroy(&region->container);
+            }
+        } else if (pci_region->type & IORESOURCE_MEM) {
+            if (region->u.r_virtbase) {
+                memory_region_del_subregion(&region->container,
+                                            &region->real_iomem);
+
+                /* Remove MSI-X table subregion */
+                if (pci_region->base_addr <= dev->msix_table_addr &&
+                    pci_region->base_addr + pci_region->size >
+                    dev->msix_table_addr) {
+                    memory_region_del_subregion(&region->container,
+                                                &dev->mmio);
+                }
+
+                memory_region_destroy(&region->real_iomem);
+                memory_region_destroy(&region->container);
+                if (munmap(region->u.r_virtbase,
+                           (pci_region->size + 0xFFF) & 0xFFFFF000)) {
+                    error_report("Failed to unmap assigned device region: %s",
+                                 strerror(errno));
+                }
+            }
+        }
+        if (pci_region->resource_fd >= 0) {
+            close(pci_region->resource_fd);
+        }
+    }
+
+    if (dev->real_device.config_fd >= 0) {
+        close(dev->real_device.config_fd);
+    }
+
+    free_msi_virqs(dev);
+}
+
+static void assign_failed_examine(AssignedDevice *dev)
+{
+    char name[PATH_MAX], dir[PATH_MAX], driver[PATH_MAX] = {}, *ns;
+    uint16_t vendor_id, device_id;
+    int r;
+
+    snprintf(dir, sizeof(dir), "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/",
+            dev->host.domain, dev->host.bus, dev->host.slot,
+            dev->host.function);
+
+    snprintf(name, sizeof(name), "%sdriver", dir);
+
+    r = readlink(name, driver, sizeof(driver));
+    if ((r <= 0) || r >= sizeof(driver)) {
+        goto fail;
+    }
+
+    ns = strrchr(driver, '/');
+    if (!ns) {
+        goto fail;
+    }
+
+    ns++;
+
+    if (get_real_vendor_id(dir, &vendor_id) ||
+        get_real_device_id(dir, &device_id)) {
+        goto fail;
+    }
+
+    error_report("*** The driver '%s' is occupying your device "
+                 "%04x:%02x:%02x.%x.",
+                 ns, dev->host.domain, dev->host.bus, dev->host.slot,
+                 dev->host.function);
+    error_report("***");
+    error_report("*** You can try the following commands to free it:");
+    error_report("***");
+    error_report("*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub/"
+                 "new_id", vendor_id, device_id);
+    error_report("*** $ echo \"%04x:%02x:%02x.%x\" > /sys/bus/pci/drivers/"
+                 "%s/unbind",
+                 dev->host.domain, dev->host.bus, dev->host.slot,
+                 dev->host.function, ns);
+    error_report("*** $ echo \"%04x:%02x:%02x.%x\" > /sys/bus/pci/drivers/"
+                 "pci-stub/bind",
+                 dev->host.domain, dev->host.bus, dev->host.slot,
+                 dev->host.function);
+    error_report("*** $ echo \"%04x %04x\" > /sys/bus/pci/drivers/pci-stub"
+                 "/remove_id", vendor_id, device_id);
+    error_report("***");
+
+    return;
+
+fail:
+    error_report("Couldn't find out why.");
+}
+
+static int assign_device(AssignedDevice *dev)
+{
+    uint32_t flags = KVM_DEV_ASSIGN_ENABLE_IOMMU;
+    int r;
+
+    /* Only pass non-zero PCI segment to capable module */
+    if (!kvm_check_extension(kvm_state, KVM_CAP_PCI_SEGMENT) &&
+        dev->host.domain) {
+        error_report("Can't assign device inside non-zero PCI segment "
+                     "as this KVM module doesn't support it.");
+        return -ENODEV;
+    }
+
+    if (!kvm_check_extension(kvm_state, KVM_CAP_IOMMU)) {
+        error_report("No IOMMU found.  Unable to assign device \"%s\"",
+                     dev->dev.qdev.id);
+        return -ENODEV;
+    }
+
+    if (dev->features & ASSIGNED_DEVICE_SHARE_INTX_MASK &&
+        kvm_has_intx_set_mask()) {
+        flags |= KVM_DEV_ASSIGN_PCI_2_3;
+    }
+
+    r = kvm_device_pci_assign(kvm_state, &dev->host, flags, &dev->dev_id);
+    if (r < 0) {
+        error_report("Failed to assign device \"%s\" : %s",
+                     dev->dev.qdev.id, strerror(-r));
+
+        switch (r) {
+        case -EBUSY:
+            assign_failed_examine(dev);
+            break;
+        default:
+            break;
+        }
+    }
+    return r;
+}
+
+static bool check_irqchip_in_kernel(void)
+{
+    if (kvm_irqchip_in_kernel()) {
+        return true;
+    }
+    error_report("pci-assign: error: requires KVM with in-kernel irqchip "
+                 "enabled");
+    return false;
+}
+
+static int assign_intx(AssignedDevice *dev)
+{
+    AssignedIRQType new_type;
+    PCIINTxRoute intx_route;
+    bool intx_host_msi;
+    int r;
+
+    /* Interrupt PIN 0 means don't use INTx */
+    if (assigned_dev_pci_read_byte(&dev->dev, PCI_INTERRUPT_PIN) == 0) {
+        pci_device_set_intx_routing_notifier(&dev->dev, NULL);
+        return 0;
+    }
+
+    if (!check_irqchip_in_kernel()) {
+        return -ENOTSUP;
+    }
+
+    pci_device_set_intx_routing_notifier(&dev->dev,
+                                         assigned_dev_update_irq_routing);
+
+    intx_route = pci_device_route_intx_to_irq(&dev->dev, dev->intpin);
+    assert(intx_route.mode != PCI_INTX_INVERTED);
+
+    if (dev->intx_route.mode == intx_route.mode &&
+        dev->intx_route.irq == intx_route.irq) {
+        return 0;
+    }
+
+    switch (dev->assigned_irq_type) {
+    case ASSIGNED_IRQ_INTX_HOST_INTX:
+    case ASSIGNED_IRQ_INTX_HOST_MSI:
+        intx_host_msi = dev->assigned_irq_type == ASSIGNED_IRQ_INTX_HOST_MSI;
+        r = kvm_device_intx_deassign(kvm_state, dev->dev_id, intx_host_msi);
+        break;
+    case ASSIGNED_IRQ_MSI:
+        r = kvm_device_msi_deassign(kvm_state, dev->dev_id);
+        break;
+    case ASSIGNED_IRQ_MSIX:
+        r = kvm_device_msix_deassign(kvm_state, dev->dev_id);
+        break;
+    default:
+        r = 0;
+        break;
+    }
+    if (r) {
+        perror("assign_intx: deassignment of previous interrupt failed");
+    }
+    dev->assigned_irq_type = ASSIGNED_IRQ_NONE;
+
+    if (intx_route.mode == PCI_INTX_DISABLED) {
+        dev->intx_route = intx_route;
+        return 0;
+    }
+
+retry:
+    if (dev->features & ASSIGNED_DEVICE_PREFER_MSI_MASK &&
+        dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) {
+        intx_host_msi = true;
+        new_type = ASSIGNED_IRQ_INTX_HOST_MSI;
+    } else {
+        intx_host_msi = false;
+        new_type = ASSIGNED_IRQ_INTX_HOST_INTX;
+    }
+
+    r = kvm_device_intx_assign(kvm_state, dev->dev_id, intx_host_msi,
+                               intx_route.irq);
+    if (r < 0) {
+        if (r == -EIO && !(dev->features & ASSIGNED_DEVICE_PREFER_MSI_MASK) &&
+            dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) {
+            /* Retry with host-side MSI. There might be an IRQ conflict and
+             * either the kernel or the device doesn't support sharing. */
+            error_report("Host-side INTx sharing not supported, "
+                         "using MSI instead.\n"
+                         "Some devices do not to work properly in this mode.");
+            dev->features |= ASSIGNED_DEVICE_PREFER_MSI_MASK;
+            goto retry;
+        }
+        error_report("Failed to assign irq for \"%s\": %s",
+                     dev->dev.qdev.id, strerror(-r));
+        error_report("Perhaps you are assigning a device "
+                     "that shares an IRQ with another device?");
+        return r;
+    }
+
+    dev->intx_route = intx_route;
+    dev->assigned_irq_type = new_type;
+    return r;
+}
+
+static void deassign_device(AssignedDevice *dev)
+{
+    int r;
+
+    r = kvm_device_pci_deassign(kvm_state, dev->dev_id);
+    assert(r == 0);
+}
+
+/* The pci config space got updated. Check if irq numbers have changed
+ * for our devices
+ */
+static void assigned_dev_update_irq_routing(PCIDevice *dev)
+{
+    AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, dev);
+    Error *err = NULL;
+    int r;
+
+    r = assign_intx(assigned_dev);
+    if (r < 0) {
+        qdev_unplug(&dev->qdev, &err);
+        assert(!err);
+    }
+}
+
+static void assigned_dev_update_msi(PCIDevice *pci_dev)
+{
+    AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+    uint8_t ctrl_byte = pci_get_byte(pci_dev->config + pci_dev->msi_cap +
+                                     PCI_MSI_FLAGS);
+    int r;
+
+    /* Some guests gratuitously disable MSI even if they're not using it,
+     * try to catch this by only deassigning irqs if the guest is using
+     * MSI or intends to start. */
+    if (assigned_dev->assigned_irq_type == ASSIGNED_IRQ_MSI ||
+        (ctrl_byte & PCI_MSI_FLAGS_ENABLE)) {
+        r = kvm_device_msi_deassign(kvm_state, assigned_dev->dev_id);
+        /* -ENXIO means no assigned irq */
+        if (r && r != -ENXIO) {
+            perror("assigned_dev_update_msi: deassign irq");
+        }
+
+        free_msi_virqs(assigned_dev);
+
+        assigned_dev->assigned_irq_type = ASSIGNED_IRQ_NONE;
+        pci_device_set_intx_routing_notifier(pci_dev, NULL);
+    }
+
+    if (ctrl_byte & PCI_MSI_FLAGS_ENABLE) {
+        uint8_t *pos = pci_dev->config + pci_dev->msi_cap;
+        MSIMessage msg;
+        int virq;
+
+        msg.address = pci_get_long(pos + PCI_MSI_ADDRESS_LO);
+        msg.data = pci_get_word(pos + PCI_MSI_DATA_32);
+        virq = kvm_irqchip_add_msi_route(kvm_state, msg);
+        if (virq < 0) {
+            perror("assigned_dev_update_msi: kvm_irqchip_add_msi_route");
+            return;
+        }
+
+        assigned_dev->msi_virq = g_malloc(sizeof(*assigned_dev->msi_virq));
+        assigned_dev->msi_virq_nr = 1;
+        assigned_dev->msi_virq[0] = virq;
+        if (kvm_device_msi_assign(kvm_state, assigned_dev->dev_id, virq) < 0) {
+            perror("assigned_dev_update_msi: kvm_device_msi_assign");
+        }
+
+        assigned_dev->intx_route.mode = PCI_INTX_DISABLED;
+        assigned_dev->intx_route.irq = -1;
+        assigned_dev->assigned_irq_type = ASSIGNED_IRQ_MSI;
+    } else {
+        assign_intx(assigned_dev);
+    }
+}
+
+static bool assigned_dev_msix_masked(MSIXTableEntry *entry)
+{
+    return (entry->ctrl & cpu_to_le32(0x1)) != 0;
+}
+
+static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev)
+{
+    AssignedDevice *adev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+    uint16_t entries_nr = 0;
+    int i, r = 0;
+    MSIXTableEntry *entry = adev->msix_table;
+    MSIMessage msg;
+
+    /* Get the usable entry number for allocating */
+    for (i = 0; i < adev->msix_max; i++, entry++) {
+        if (assigned_dev_msix_masked(entry)) {
+            continue;
+        }
+        entries_nr++;
+    }
+
+    DEBUG("MSI-X entries: %d\n", entries_nr);
+
+    /* It's valid to enable MSI-X with all entries masked */
+    if (!entries_nr) {
+        return 0;
+    }
+
+    r = kvm_device_msix_init_vectors(kvm_state, adev->dev_id, entries_nr);
+    if (r != 0) {
+        error_report("fail to set MSI-X entry number for MSIX! %s",
+                     strerror(-r));
+        return r;
+    }
+
+    free_msi_virqs(adev);
+
+    adev->msi_virq_nr = adev->msix_max;
+    adev->msi_virq = g_malloc(adev->msix_max * sizeof(*adev->msi_virq));
+
+    entry = adev->msix_table;
+    for (i = 0; i < adev->msix_max; i++, entry++) {
+        adev->msi_virq[i] = -1;
+
+        if (assigned_dev_msix_masked(entry)) {
+            continue;
+        }
+
+        msg.address = entry->addr_lo | ((uint64_t)entry->addr_hi << 32);
+        msg.data = entry->data;
+        r = kvm_irqchip_add_msi_route(kvm_state, msg);
+        if (r < 0) {
+            return r;
+        }
+        adev->msi_virq[i] = r;
+
+        DEBUG("MSI-X vector %d, gsi %d, addr %08x_%08x, data %08x\n", i,
+              r, entry->addr_hi, entry->addr_lo, entry->data);
+
+        r = kvm_device_msix_set_vector(kvm_state, adev->dev_id, i,
+                                       adev->msi_virq[i]);
+        if (r) {
+            error_report("fail to set MSI-X entry! %s", strerror(-r));
+            break;
+        }
+    }
+
+    return r;
+}
+
+static void assigned_dev_update_msix(PCIDevice *pci_dev)
+{
+    AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+    uint16_t ctrl_word = pci_get_word(pci_dev->config + pci_dev->msix_cap +
+                                      PCI_MSIX_FLAGS);
+    int r;
+
+    /* Some guests gratuitously disable MSIX even if they're not using it,
+     * try to catch this by only deassigning irqs if the guest is using
+     * MSIX or intends to start. */
+    if ((assigned_dev->assigned_irq_type == ASSIGNED_IRQ_MSIX) ||
+        (ctrl_word & PCI_MSIX_FLAGS_ENABLE)) {
+        r = kvm_device_msix_deassign(kvm_state, assigned_dev->dev_id);
+        /* -ENXIO means no assigned irq */
+        if (r && r != -ENXIO) {
+            perror("assigned_dev_update_msix: deassign irq");
+        }
+
+        free_msi_virqs(assigned_dev);
+
+        assigned_dev->assigned_irq_type = ASSIGNED_IRQ_NONE;
+        pci_device_set_intx_routing_notifier(pci_dev, NULL);
+    }
+
+    if (ctrl_word & PCI_MSIX_FLAGS_ENABLE) {
+        if (assigned_dev_update_msix_mmio(pci_dev) < 0) {
+            perror("assigned_dev_update_msix_mmio");
+            return;
+        }
+
+        if (assigned_dev->msi_virq_nr > 0) {
+            if (kvm_device_msix_assign(kvm_state, assigned_dev->dev_id) < 0) {
+                perror("assigned_dev_enable_msix: assign irq");
+                return;
+            }
+        }
+        assigned_dev->intx_route.mode = PCI_INTX_DISABLED;
+        assigned_dev->intx_route.irq = -1;
+        assigned_dev->assigned_irq_type = ASSIGNED_IRQ_MSIX;
+    } else {
+        assign_intx(assigned_dev);
+    }
+}
+
+static uint32_t assigned_dev_pci_read_config(PCIDevice *pci_dev,
+                                             uint32_t address, int len)
+{
+    AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+    uint32_t virt_val = pci_default_read_config(pci_dev, address, len);
+    uint32_t real_val, emulate_mask, full_emulation_mask;
+
+    emulate_mask = 0;
+    memcpy(&emulate_mask, assigned_dev->emulate_config_read + address, len);
+    emulate_mask = le32_to_cpu(emulate_mask);
+
+    full_emulation_mask = 0xffffffff >> (32 - len * 8);
+
+    if (emulate_mask != full_emulation_mask) {
+        real_val = assigned_dev_pci_read(pci_dev, address, len);
+        return (virt_val & emulate_mask) | (real_val & ~emulate_mask);
+    } else {
+        return virt_val;
+    }
+}
+
+static void assigned_dev_pci_write_config(PCIDevice *pci_dev, uint32_t address,
+                                          uint32_t val, int len)
+{
+    AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+    uint16_t old_cmd = pci_get_word(pci_dev->config + PCI_COMMAND);
+    uint32_t emulate_mask, full_emulation_mask;
+    int ret;
+
+    pci_default_write_config(pci_dev, address, val, len);
+
+    if (kvm_has_intx_set_mask() &&
+        range_covers_byte(address, len, PCI_COMMAND + 1)) {
+        bool intx_masked = (pci_get_word(pci_dev->config + PCI_COMMAND) &
+                            PCI_COMMAND_INTX_DISABLE);
+
+        if (intx_masked != !!(old_cmd & PCI_COMMAND_INTX_DISABLE)) {
+            ret = kvm_device_intx_set_mask(kvm_state, assigned_dev->dev_id,
+                                           intx_masked);
+            if (ret) {
+                perror("assigned_dev_pci_write_config: set intx mask");
+            }
+        }
+    }
+    if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) {
+        if (range_covers_byte(address, len,
+                              pci_dev->msi_cap + PCI_MSI_FLAGS)) {
+            assigned_dev_update_msi(pci_dev);
+        }
+    }
+    if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) {
+        if (range_covers_byte(address, len,
+                              pci_dev->msix_cap + PCI_MSIX_FLAGS + 1)) {
+            assigned_dev_update_msix(pci_dev);
+        }
+    }
+
+    emulate_mask = 0;
+    memcpy(&emulate_mask, assigned_dev->emulate_config_write + address, len);
+    emulate_mask = le32_to_cpu(emulate_mask);
+
+    full_emulation_mask = 0xffffffff >> (32 - len * 8);
+
+    if (emulate_mask != full_emulation_mask) {
+        if (emulate_mask) {
+            val &= ~emulate_mask;
+            val |= assigned_dev_pci_read(pci_dev, address, len) & emulate_mask;
+        }
+        assigned_dev_pci_write(pci_dev, address, val, len);
+    }
+}
+
+static void assigned_dev_setup_cap_read(AssignedDevice *dev, uint32_t offset,
+                                        uint32_t len)
+{
+    assigned_dev_direct_config_read(dev, offset, len);
+    assigned_dev_emulate_config_read(dev, offset + PCI_CAP_LIST_NEXT, 1);
+}
+
+static int assigned_device_pci_cap_init(PCIDevice *pci_dev)
+{
+    AssignedDevice *dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+    PCIRegion *pci_region = dev->real_device.regions;
+    int ret, pos;
+
+    /* Clear initial capabilities pointer and status copied from hw */
+    pci_set_byte(pci_dev->config + PCI_CAPABILITY_LIST, 0);
+    pci_set_word(pci_dev->config + PCI_STATUS,
+                 pci_get_word(pci_dev->config + PCI_STATUS) &
+                 ~PCI_STATUS_CAP_LIST);
+
+    /* Expose MSI capability
+     * MSI capability is the 1st capability in capability config */
+    pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_MSI, 0);
+    if (pos != 0 && kvm_check_extension(kvm_state, KVM_CAP_ASSIGN_DEV_IRQ)) {
+        if (!check_irqchip_in_kernel()) {
+            return -ENOTSUP;
+        }
+        dev->cap.available |= ASSIGNED_DEVICE_CAP_MSI;
+        /* Only 32-bit/no-mask currently supported */
+        ret = pci_add_capability(pci_dev, PCI_CAP_ID_MSI, pos, 10);
+        if (ret < 0) {
+            return ret;
+        }
+        pci_dev->msi_cap = pos;
+
+        pci_set_word(pci_dev->config + pos + PCI_MSI_FLAGS,
+                     pci_get_word(pci_dev->config + pos + PCI_MSI_FLAGS) &
+                     PCI_MSI_FLAGS_QMASK);
+        pci_set_long(pci_dev->config + pos + PCI_MSI_ADDRESS_LO, 0);
+        pci_set_word(pci_dev->config + pos + PCI_MSI_DATA_32, 0);
+
+        /* Set writable fields */
+        pci_set_word(pci_dev->wmask + pos + PCI_MSI_FLAGS,
+                     PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
+        pci_set_long(pci_dev->wmask + pos + PCI_MSI_ADDRESS_LO, 0xfffffffc);
+        pci_set_word(pci_dev->wmask + pos + PCI_MSI_DATA_32, 0xffff);
+    }
+    /* Expose MSI-X capability */
+    pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_MSIX, 0);
+    if (pos != 0 && kvm_device_msix_supported(kvm_state)) {
+        int bar_nr;
+        uint32_t msix_table_entry;
+
+        if (!check_irqchip_in_kernel()) {
+            return -ENOTSUP;
+        }
+        dev->cap.available |= ASSIGNED_DEVICE_CAP_MSIX;
+        ret = pci_add_capability(pci_dev, PCI_CAP_ID_MSIX, pos, 12);
+        if (ret < 0) {
+            return ret;
+        }
+        pci_dev->msix_cap = pos;
+
+        pci_set_word(pci_dev->config + pos + PCI_MSIX_FLAGS,
+                     pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS) &
+                     PCI_MSIX_FLAGS_QSIZE);
+
+        /* Only enable and function mask bits are writable */
+        pci_set_word(pci_dev->wmask + pos + PCI_MSIX_FLAGS,
+                     PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL);
+
+        msix_table_entry = pci_get_long(pci_dev->config + pos + PCI_MSIX_TABLE);
+        bar_nr = msix_table_entry & PCI_MSIX_FLAGS_BIRMASK;
+        msix_table_entry &= ~PCI_MSIX_FLAGS_BIRMASK;
+        dev->msix_table_addr = pci_region[bar_nr].base_addr + msix_table_entry;
+        dev->msix_max = pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS);
+        dev->msix_max &= PCI_MSIX_FLAGS_QSIZE;
+        dev->msix_max += 1;
+    }
+
+    /* Minimal PM support, nothing writable, device appears to NAK changes */
+    pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_PM, 0);
+    if (pos) {
+        uint16_t pmc;
+
+        ret = pci_add_capability(pci_dev, PCI_CAP_ID_PM, pos, PCI_PM_SIZEOF);
+        if (ret < 0) {
+            return ret;
+        }
+
+        assigned_dev_setup_cap_read(dev, pos, PCI_PM_SIZEOF);
+
+        pmc = pci_get_word(pci_dev->config + pos + PCI_CAP_FLAGS);
+        pmc &= (PCI_PM_CAP_VER_MASK | PCI_PM_CAP_DSI);
+        pci_set_word(pci_dev->config + pos + PCI_CAP_FLAGS, pmc);
+
+        /* assign_device will bring the device up to D0, so we don't need
+         * to worry about doing that ourselves here. */
+        pci_set_word(pci_dev->config + pos + PCI_PM_CTRL,
+                     PCI_PM_CTRL_NO_SOFT_RESET);
+
+        pci_set_byte(pci_dev->config + pos + PCI_PM_PPB_EXTENSIONS, 0);
+        pci_set_byte(pci_dev->config + pos + PCI_PM_DATA_REGISTER, 0);
+    }
+
+    pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_EXP, 0);
+    if (pos) {
+        uint8_t version, size = 0;
+        uint16_t type, devctl, lnksta;
+        uint32_t devcap, lnkcap;
+
+        version = pci_get_byte(pci_dev->config + pos + PCI_EXP_FLAGS);
+        version &= PCI_EXP_FLAGS_VERS;
+        if (version == 1) {
+            size = 0x14;
+        } else if (version == 2) {
+            /*
+             * Check for non-std size, accept reduced size to 0x34,
+             * which is what bcm5761 implemented, violating the
+             * PCIe v3.0 spec that regs should exist and be read as 0,
+             * not optionally provided and shorten the struct size.
+             */
+            size = MIN(0x3c, PCI_CONFIG_SPACE_SIZE - pos);
+            if (size < 0x34) {
+                error_report("%s: Invalid size PCIe cap-id 0x%x",
+                             __func__, PCI_CAP_ID_EXP);
+                return -EINVAL;
+            } else if (size != 0x3c) {
+                error_report("WARNING, %s: PCIe cap-id 0x%x has "
+                             "non-standard size 0x%x; std size should be 0x3c",
+                             __func__, PCI_CAP_ID_EXP, size);
+            }
+        } else if (version == 0) {
+            uint16_t vid, did;
+            vid = pci_get_word(pci_dev->config + PCI_VENDOR_ID);
+            did = pci_get_word(pci_dev->config + PCI_DEVICE_ID);
+            if (vid == PCI_VENDOR_ID_INTEL && did == 0x10ed) {
+                /*
+                 * quirk for Intel 82599 VF with invalid PCIe capability
+                 * version, should really be version 2 (same as PF)
+                 */
+                size = 0x3c;
+            }
+        }
+
+        if (size == 0) {
+            error_report("%s: Unsupported PCI express capability version %d",
+                         __func__, version);
+            return -EINVAL;
+        }
+
+        ret = pci_add_capability(pci_dev, PCI_CAP_ID_EXP, pos, size);
+        if (ret < 0) {
+            return ret;
+        }
+
+        assigned_dev_setup_cap_read(dev, pos, size);
+
+        type = pci_get_word(pci_dev->config + pos + PCI_EXP_FLAGS);
+        type = (type & PCI_EXP_FLAGS_TYPE) >> 4;
+        if (type != PCI_EXP_TYPE_ENDPOINT &&
+            type != PCI_EXP_TYPE_LEG_END && type != PCI_EXP_TYPE_RC_END) {
+            error_report("Device assignment only supports endpoint assignment,"
+                         " device type %d", type);
+            return -EINVAL;
+        }
+
+        /* capabilities, pass existing read-only copy
+         * PCI_EXP_FLAGS_IRQ: updated by hardware, should be direct read */
+
+        /* device capabilities: hide FLR */
+        devcap = pci_get_long(pci_dev->config + pos + PCI_EXP_DEVCAP);
+        devcap &= ~PCI_EXP_DEVCAP_FLR;
+        pci_set_long(pci_dev->config + pos + PCI_EXP_DEVCAP, devcap);
+
+        /* device control: clear all error reporting enable bits, leaving
+         *                 only a few host values.  Note, these are
+         *                 all writable, but not passed to hw.
+         */
+        devctl = pci_get_word(pci_dev->config + pos + PCI_EXP_DEVCTL);
+        devctl = (devctl & (PCI_EXP_DEVCTL_READRQ | PCI_EXP_DEVCTL_PAYLOAD)) |
+                  PCI_EXP_DEVCTL_RELAX_EN | PCI_EXP_DEVCTL_NOSNOOP_EN;
+        pci_set_word(pci_dev->config + pos + PCI_EXP_DEVCTL, devctl);
+        devctl = PCI_EXP_DEVCTL_BCR_FLR | PCI_EXP_DEVCTL_AUX_PME;
+        pci_set_word(pci_dev->wmask + pos + PCI_EXP_DEVCTL, ~devctl);
+
+        /* Clear device status */
+        pci_set_word(pci_dev->config + pos + PCI_EXP_DEVSTA, 0);
+
+        /* Link capabilities, expose links and latencues, clear reporting */
+        lnkcap = pci_get_long(pci_dev->config + pos + PCI_EXP_LNKCAP);
+        lnkcap &= (PCI_EXP_LNKCAP_SLS | PCI_EXP_LNKCAP_MLW |
+                   PCI_EXP_LNKCAP_ASPMS | PCI_EXP_LNKCAP_L0SEL |
+                   PCI_EXP_LNKCAP_L1EL);
+        pci_set_long(pci_dev->config + pos + PCI_EXP_LNKCAP, lnkcap);
+
+        /* Link control, pass existing read-only copy.  Should be writable? */
+
+        /* Link status, only expose current speed and width */
+        lnksta = pci_get_word(pci_dev->config + pos + PCI_EXP_LNKSTA);
+        lnksta &= (PCI_EXP_LNKSTA_CLS | PCI_EXP_LNKSTA_NLW);
+        pci_set_word(pci_dev->config + pos + PCI_EXP_LNKSTA, lnksta);
+
+        if (version >= 2) {
+            /* Slot capabilities, control, status - not needed for endpoints */
+            pci_set_long(pci_dev->config + pos + PCI_EXP_SLTCAP, 0);
+            pci_set_word(pci_dev->config + pos + PCI_EXP_SLTCTL, 0);
+            pci_set_word(pci_dev->config + pos + PCI_EXP_SLTSTA, 0);
+
+            /* Root control, capabilities, status - not needed for endpoints */
+            pci_set_word(pci_dev->config + pos + PCI_EXP_RTCTL, 0);
+            pci_set_word(pci_dev->config + pos + PCI_EXP_RTCAP, 0);
+            pci_set_long(pci_dev->config + pos + PCI_EXP_RTSTA, 0);
+
+            /* Device capabilities/control 2, pass existing read-only copy */
+            /* Link control 2, pass existing read-only copy */
+        }
+    }
+
+    pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_PCIX, 0);
+    if (pos) {
+        uint16_t cmd;
+        uint32_t status;
+
+        /* Only expose the minimum, 8 byte capability */
+        ret = pci_add_capability(pci_dev, PCI_CAP_ID_PCIX, pos, 8);
+        if (ret < 0) {
+            return ret;
+        }
+
+        assigned_dev_setup_cap_read(dev, pos, 8);
+
+        /* Command register, clear upper bits, including extended modes */
+        cmd = pci_get_word(pci_dev->config + pos + PCI_X_CMD);
+        cmd &= (PCI_X_CMD_DPERR_E | PCI_X_CMD_ERO | PCI_X_CMD_MAX_READ |
+                PCI_X_CMD_MAX_SPLIT);
+        pci_set_word(pci_dev->config + pos + PCI_X_CMD, cmd);
+
+        /* Status register, update with emulated PCI bus location, clear
+         * error bits, leave the rest. */
+        status = pci_get_long(pci_dev->config + pos + PCI_X_STATUS);
+        status &= ~(PCI_X_STATUS_BUS | PCI_X_STATUS_DEVFN);
+        status |= (pci_bus_num(pci_dev->bus) << 8) | pci_dev->devfn;
+        status &= ~(PCI_X_STATUS_SPL_DISC | PCI_X_STATUS_UNX_SPL |
+                    PCI_X_STATUS_SPL_ERR);
+        pci_set_long(pci_dev->config + pos + PCI_X_STATUS, status);
+    }
+
+    pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_VPD, 0);
+    if (pos) {
+        /* Direct R/W passthrough */
+        ret = pci_add_capability(pci_dev, PCI_CAP_ID_VPD, pos, 8);
+        if (ret < 0) {
+            return ret;
+        }
+
+        assigned_dev_setup_cap_read(dev, pos, 8);
+
+        /* direct write for cap content */
+        assigned_dev_direct_config_write(dev, pos + 2, 6);
+    }
+
+    /* Devices can have multiple vendor capabilities, get them all */
+    for (pos = 0; (pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_VNDR, pos));
+        pos += PCI_CAP_LIST_NEXT) {
+        uint8_t len = pci_get_byte(pci_dev->config + pos + PCI_CAP_FLAGS);
+        /* Direct R/W passthrough */
+        ret = pci_add_capability(pci_dev, PCI_CAP_ID_VNDR, pos, len);
+        if (ret < 0) {
+            return ret;
+        }
+
+        assigned_dev_setup_cap_read(dev, pos, len);
+
+        /* direct write for cap content */
+        assigned_dev_direct_config_write(dev, pos + 2, len - 2);
+    }
+
+    /* If real and virtual capability list status bits differ, virtualize the
+     * access. */
+    if ((pci_get_word(pci_dev->config + PCI_STATUS) & PCI_STATUS_CAP_LIST) !=
+        (assigned_dev_pci_read_byte(pci_dev, PCI_STATUS) &
+         PCI_STATUS_CAP_LIST)) {
+        dev->emulate_config_read[PCI_STATUS] |= PCI_STATUS_CAP_LIST;
+    }
+
+    return 0;
+}
+
+static uint64_t
+assigned_dev_msix_mmio_read(void *opaque, target_phys_addr_t addr,
+                            unsigned size)
+{
+    AssignedDevice *adev = opaque;
+    uint64_t val;
+
+    memcpy(&val, (void *)((uint8_t *)adev->msix_table + addr), size);
+
+    return val;
+}
+
+static void assigned_dev_msix_mmio_write(void *opaque, target_phys_addr_t addr,
+                                         uint64_t val, unsigned size)
+{
+    AssignedDevice *adev = opaque;
+    PCIDevice *pdev = &adev->dev;
+    uint16_t ctrl;
+    MSIXTableEntry orig;
+    int i = addr >> 4;
+
+    if (i >= adev->msix_max) {
+        return; /* Drop write */
+    }
+
+    ctrl = pci_get_word(pdev->config + pdev->msix_cap + PCI_MSIX_FLAGS);
+
+    DEBUG("write to MSI-X table offset 0x%lx, val 0x%lx\n", addr, val);
+
+    if (ctrl & PCI_MSIX_FLAGS_ENABLE) {
+        orig = adev->msix_table[i];
+    }
+
+    memcpy((uint8_t *)adev->msix_table + addr, &val, size);
+
+    if (ctrl & PCI_MSIX_FLAGS_ENABLE) {
+        MSIXTableEntry *entry = &adev->msix_table[i];
+
+        if (!assigned_dev_msix_masked(&orig) &&
+            assigned_dev_msix_masked(entry)) {
+            /*
+             * Vector masked, disable it
+             *
+             * XXX It's not clear if we can or should actually attempt
+             * to mask or disable the interrupt.  KVM doesn't have
+             * support for pending bits and kvm_assign_set_msix_entry
+             * doesn't modify the device hardware mask.  Interrupts
+             * while masked are simply not injected to the guest, so
+             * are lost.  Can we get away with always injecting an
+             * interrupt on unmask?
+             */
+        } else if (assigned_dev_msix_masked(&orig) &&
+                   !assigned_dev_msix_masked(entry)) {
+            /* Vector unmasked */
+            if (i >= adev->msi_virq_nr || adev->msi_virq[i] < 0) {
+                /* Previously unassigned vector, start from scratch */
+                assigned_dev_update_msix(pdev);
+                return;
+            } else {
+                /* Update an existing, previously masked vector */
+                MSIMessage msg;
+                int ret;
+
+                msg.address = entry->addr_lo |
+                    ((uint64_t)entry->addr_hi << 32);
+                msg.data = entry->data;
+
+                ret = kvm_irqchip_update_msi_route(kvm_state,
+                                                   adev->msi_virq[i], msg);
+                if (ret) {
+                    error_report("Error updating irq routing entry (%d)", ret);
+                }
+            }
+        }
+    }
+}
+
+static const MemoryRegionOps assigned_dev_msix_mmio_ops = {
+    .read = assigned_dev_msix_mmio_read,
+    .write = assigned_dev_msix_mmio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 8,
+    },
+};
+
+static void assigned_dev_msix_reset(AssignedDevice *dev)
+{
+    MSIXTableEntry *entry;
+    int i;
+
+    if (!dev->msix_table) {
+        return;
+    }
+
+    memset(dev->msix_table, 0, MSIX_PAGE_SIZE);
+
+    for (i = 0, entry = dev->msix_table; i < dev->msix_max; i++, entry++) {
+        entry->ctrl = cpu_to_le32(0x1); /* Masked */
+    }
+}
+
+static int assigned_dev_register_msix_mmio(AssignedDevice *dev)
+{
+    dev->msix_table = mmap(NULL, MSIX_PAGE_SIZE, PROT_READ|PROT_WRITE,
+                           MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
+    if (dev->msix_table == MAP_FAILED) {
+        error_report("fail allocate msix_table! %s", strerror(errno));
+        return -EFAULT;
+    }
+
+    assigned_dev_msix_reset(dev);
+
+    memory_region_init_io(&dev->mmio, &assigned_dev_msix_mmio_ops, dev,
+                          "assigned-dev-msix", MSIX_PAGE_SIZE);
+    return 0;
+}
+
+static void assigned_dev_unregister_msix_mmio(AssignedDevice *dev)
+{
+    if (!dev->msix_table) {
+        return;
+    }
+
+    memory_region_destroy(&dev->mmio);
+
+    if (munmap(dev->msix_table, MSIX_PAGE_SIZE) == -1) {
+        error_report("error unmapping msix_table! %s", strerror(errno));
+    }
+    dev->msix_table = NULL;
+}
+
+static const VMStateDescription vmstate_assigned_device = {
+    .name = "pci-assign",
+    .unmigratable = 1,
+};
+
+static void reset_assigned_device(DeviceState *dev)
+{
+    PCIDevice *pci_dev = DO_UPCAST(PCIDevice, qdev, dev);
+    AssignedDevice *adev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+    char reset_file[64];
+    const char reset[] = "1";
+    int fd, ret;
+
+    /*
+     * If a guest is reset without being shutdown, MSI/MSI-X can still
+     * be running.  We want to return the device to a known state on
+     * reset, so disable those here.  We especially do not want MSI-X
+     * enabled since it lives in MMIO space, which is about to get
+     * disabled.
+     */
+    if (adev->assigned_irq_type == ASSIGNED_IRQ_MSIX) {
+        uint16_t ctrl = pci_get_word(pci_dev->config +
+                                     pci_dev->msix_cap + PCI_MSIX_FLAGS);
+
+        pci_set_word(pci_dev->config + pci_dev->msix_cap + PCI_MSIX_FLAGS,
+                     ctrl & ~PCI_MSIX_FLAGS_ENABLE);
+        assigned_dev_update_msix(pci_dev);
+    } else if (adev->assigned_irq_type == ASSIGNED_IRQ_MSI) {
+        uint8_t ctrl = pci_get_byte(pci_dev->config +
+                                    pci_dev->msi_cap + PCI_MSI_FLAGS);
+
+        pci_set_byte(pci_dev->config + pci_dev->msi_cap + PCI_MSI_FLAGS,
+                     ctrl & ~PCI_MSI_FLAGS_ENABLE);
+        assigned_dev_update_msi(pci_dev);
+    }
+
+    snprintf(reset_file, sizeof(reset_file),
+             "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/reset",
+             adev->host.domain, adev->host.bus, adev->host.slot,
+             adev->host.function);
+
+    /*
+     * Issue a device reset via pci-sysfs.  Note that we use write(2) here
+     * and ignore the return value because some kernels have a bug that
+     * returns 0 rather than bytes written on success, sending us into an
+     * infinite retry loop using other write mechanisms.
+     */
+    fd = open(reset_file, O_WRONLY);
+    if (fd != -1) {
+        ret = write(fd, reset, strlen(reset));
+        (void)ret;
+        close(fd);
+    }
+
+    /*
+     * When a 0 is written to the bus master register, the device is logically
+     * disconnected from the PCI bus. This avoids further DMA transfers.
+     */
+    assigned_dev_pci_write_config(pci_dev, PCI_COMMAND, 0, 1);
+}
+
+static int assigned_initfn(struct PCIDevice *pci_dev)
+{
+    AssignedDevice *dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+    uint8_t e_intx;
+    int r;
+
+    if (!kvm_enabled()) {
+        error_report("pci-assign: error: requires KVM support");
+        return -1;
+    }
+
+    if (!dev->host.domain && !dev->host.bus && !dev->host.slot &&
+        !dev->host.function) {
+        error_report("pci-assign: error: no host device specified");
+        return -1;
+    }
+
+    /*
+     * Set up basic config space access control. Will be further refined during
+     * device initialization.
+     */
+    assigned_dev_emulate_config_read(dev, 0, PCI_CONFIG_SPACE_SIZE);
+    assigned_dev_direct_config_read(dev, PCI_STATUS, 2);
+    assigned_dev_direct_config_read(dev, PCI_REVISION_ID, 1);
+    assigned_dev_direct_config_read(dev, PCI_CLASS_PROG, 3);
+    assigned_dev_direct_config_read(dev, PCI_CACHE_LINE_SIZE, 1);
+    assigned_dev_direct_config_read(dev, PCI_LATENCY_TIMER, 1);
+    assigned_dev_direct_config_read(dev, PCI_BIST, 1);
+    assigned_dev_direct_config_read(dev, PCI_CARDBUS_CIS, 4);
+    assigned_dev_direct_config_read(dev, PCI_SUBSYSTEM_VENDOR_ID, 2);
+    assigned_dev_direct_config_read(dev, PCI_SUBSYSTEM_ID, 2);
+    assigned_dev_direct_config_read(dev, PCI_CAPABILITY_LIST + 1, 7);
+    assigned_dev_direct_config_read(dev, PCI_MIN_GNT, 1);
+    assigned_dev_direct_config_read(dev, PCI_MAX_LAT, 1);
+    memcpy(dev->emulate_config_write, dev->emulate_config_read,
+           sizeof(dev->emulate_config_read));
+
+    if (get_real_device(dev, dev->host.domain, dev->host.bus,
+                        dev->host.slot, dev->host.function)) {
+        error_report("pci-assign: Error: Couldn't get real device (%s)!",
+                     dev->dev.qdev.id);
+        goto out;
+    }
+
+    if (assigned_device_pci_cap_init(pci_dev) < 0) {
+        goto out;
+    }
+
+    /* intercept MSI-X entry page in the MMIO */
+    if (dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) {
+        if (assigned_dev_register_msix_mmio(dev)) {
+            goto out;
+        }
+    }
+
+    /* handle real device's MMIO/PIO BARs */
+    if (assigned_dev_register_regions(dev->real_device.regions,
+                                      dev->real_device.region_number,
+                                      dev)) {
+        goto out;
+    }
+
+    /* handle interrupt routing */
+    e_intx = dev->dev.config[PCI_INTERRUPT_PIN] - 1;
+    dev->intpin = e_intx;
+    dev->intx_route.mode = PCI_INTX_DISABLED;
+    dev->intx_route.irq = -1;
+
+    /* assign device to guest */
+    r = assign_device(dev);
+    if (r < 0) {
+        goto out;
+    }
+
+    /* assign legacy INTx to the device */
+    r = assign_intx(dev);
+    if (r < 0) {
+        goto assigned_out;
+    }
+
+    assigned_dev_load_option_rom(dev);
+
+    add_boot_device_path(dev->bootindex, &pci_dev->qdev, NULL);
+
+    return 0;
+
+assigned_out:
+    deassign_device(dev);
+out:
+    free_assigned_device(dev);
+    return -1;
+}
+
+static void assigned_exitfn(struct PCIDevice *pci_dev)
+{
+    AssignedDevice *dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+
+    deassign_device(dev);
+    free_assigned_device(dev);
+}
+
+static Property assigned_dev_properties[] = {
+    DEFINE_PROP_PCI_HOST_DEVADDR("host", AssignedDevice, host),
+    DEFINE_PROP_BIT("prefer_msi", AssignedDevice, features,
+                    ASSIGNED_DEVICE_PREFER_MSI_BIT, false),
+    DEFINE_PROP_BIT("share_intx", AssignedDevice, features,
+                    ASSIGNED_DEVICE_SHARE_INTX_BIT, true),
+    DEFINE_PROP_INT32("bootindex", AssignedDevice, bootindex, -1),
+    DEFINE_PROP_STRING("configfd", AssignedDevice, configfd_name),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void assign_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init         = assigned_initfn;
+    k->exit         = assigned_exitfn;
+    k->config_read  = assigned_dev_pci_read_config;
+    k->config_write = assigned_dev_pci_write_config;
+    dc->props       = assigned_dev_properties;
+    dc->vmsd        = &vmstate_assigned_device;
+    dc->reset       = reset_assigned_device;
+    dc->desc        = "KVM-based PCI passthrough";
+}
+
+static const TypeInfo assign_info = {
+    .name               = "kvm-pci-assign",
+    .parent             = TYPE_PCI_DEVICE,
+    .instance_size      = sizeof(AssignedDevice),
+    .class_init         = assign_class_init,
+};
+
+static void assign_register_types(void)
+{
+    type_register_static(&assign_info);
+}
+
+type_init(assign_register_types)
+
+/*
+ * Scan the assigned devices for the devices that have an option ROM, and then
+ * load the corresponding ROM data to RAM. If an error occurs while loading an
+ * option ROM, we just ignore that option ROM and continue with the next one.
+ */
+static void assigned_dev_load_option_rom(AssignedDevice *dev)
+{
+    char name[32], rom_file[64];
+    FILE *fp;
+    uint8_t val;
+    struct stat st;
+    void *ptr;
+
+    /* If loading ROM from file, pci handles it */
+    if (dev->dev.romfile || !dev->dev.rom_bar) {
+        return;
+    }
+
+    snprintf(rom_file, sizeof(rom_file),
+             "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/rom",
+             dev->host.domain, dev->host.bus, dev->host.slot,
+             dev->host.function);
+
+    if (stat(rom_file, &st)) {
+        return;
+    }
+
+    if (access(rom_file, F_OK)) {
+        error_report("pci-assign: Insufficient privileges for %s", rom_file);
+        return;
+    }
+
+    /* Write "1" to the ROM file to enable it */
+    fp = fopen(rom_file, "r+");
+    if (fp == NULL) {
+        return;
+    }
+    val = 1;
+    if (fwrite(&val, 1, 1, fp) != 1) {
+        goto close_rom;
+    }
+    fseek(fp, 0, SEEK_SET);
+
+    snprintf(name, sizeof(name), "%s.rom",
+            object_get_typename(OBJECT(dev)));
+    memory_region_init_ram(&dev->dev.rom, name, st.st_size);
+    vmstate_register_ram(&dev->dev.rom, &dev->dev.qdev);
+    ptr = memory_region_get_ram_ptr(&dev->dev.rom);
+    memset(ptr, 0xff, st.st_size);
+
+    if (!fread(ptr, 1, st.st_size, fp)) {
+        error_report("pci-assign: Cannot read from host %s\n"
+                     "\tDevice option ROM contents are probably invalid "
+                     "(check dmesg).\n\tSkip option ROM probe with rombar=0, "
+                     "or load from file with romfile=", rom_file);
+        memory_region_destroy(&dev->dev.rom);
+        goto close_rom;
+    }
+
+    pci_register_bar(&dev->dev, PCI_ROM_SLOT, 0, &dev->dev.rom);
+    dev->dev.has_rom = true;
+close_rom:
+    /* Write "0" to disable ROM */
+    fseek(fp, 0, SEEK_SET);
+    val = 0;
+    if (!fwrite(&val, 1, 1, fp)) {
+        DEBUG("%s\n", "Failed to disable pci-sysfs rom file");
+    }
+    fclose(fp);
+}
diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index 33b7f79..479eecd 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -44,6 +44,7 @@ static const QDevAlias qdev_alias_table[] = {
     { "virtio-serial-s390", "virtio-serial", QEMU_ARCH_S390X },
     { "lsi53c895a", "lsi" },
     { "ich9-ahci", "ahci" },
+    { "kvm-pci-assign", "pci-assign" },
     { }
 };
 
commit b139bd300f4f579c526d153efa4960c380e2b6e3
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Aug 27 08:28:40 2012 +0200

    kvm: i386: Add services required for PCI device assignment
    
    These helpers abstract the interaction of upcoming pci-assign with the
    KVM kernel services. Put them under i386 only as other archs will
    implement device pass-through via VFIO and not this classic interface.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Acked-by: Acked-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index ffc294e..6790180 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -31,6 +31,7 @@
 #include "hw/apic.h"
 #include "ioport.h"
 #include "hyperv.h"
+#include "hw/pci.h"
 
 //#define DEBUG_KVM
 
@@ -2068,3 +2069,143 @@ void kvm_arch_init_irq_routing(KVMState *s)
     kvm_msi_via_irqfd_allowed = true;
     kvm_gsi_routing_allowed = true;
 }
+
+/* Classic KVM device assignment interface. Will remain x86 only. */
+int kvm_device_pci_assign(KVMState *s, PCIHostDeviceAddress *dev_addr,
+                          uint32_t flags, uint32_t *dev_id)
+{
+    struct kvm_assigned_pci_dev dev_data = {
+        .segnr = dev_addr->domain,
+        .busnr = dev_addr->bus,
+        .devfn = PCI_DEVFN(dev_addr->slot, dev_addr->function),
+        .flags = flags,
+    };
+    int ret;
+
+    dev_data.assigned_dev_id =
+        (dev_addr->domain << 16) | (dev_addr->bus << 8) | dev_data.devfn;
+
+    ret = kvm_vm_ioctl(s, KVM_ASSIGN_PCI_DEVICE, &dev_data);
+    if (ret < 0) {
+        return ret;
+    }
+
+    *dev_id = dev_data.assigned_dev_id;
+
+    return 0;
+}
+
+int kvm_device_pci_deassign(KVMState *s, uint32_t dev_id)
+{
+    struct kvm_assigned_pci_dev dev_data = {
+        .assigned_dev_id = dev_id,
+    };
+
+    return kvm_vm_ioctl(s, KVM_DEASSIGN_PCI_DEVICE, &dev_data);
+}
+
+static int kvm_assign_irq_internal(KVMState *s, uint32_t dev_id,
+                                   uint32_t irq_type, uint32_t guest_irq)
+{
+    struct kvm_assigned_irq assigned_irq = {
+        .assigned_dev_id = dev_id,
+        .guest_irq = guest_irq,
+        .flags = irq_type,
+    };
+
+    if (kvm_check_extension(s, KVM_CAP_ASSIGN_DEV_IRQ)) {
+        return kvm_vm_ioctl(s, KVM_ASSIGN_DEV_IRQ, &assigned_irq);
+    } else {
+        return kvm_vm_ioctl(s, KVM_ASSIGN_IRQ, &assigned_irq);
+    }
+}
+
+int kvm_device_intx_assign(KVMState *s, uint32_t dev_id, bool use_host_msi,
+                           uint32_t guest_irq)
+{
+    uint32_t irq_type = KVM_DEV_IRQ_GUEST_INTX |
+        (use_host_msi ? KVM_DEV_IRQ_HOST_MSI : KVM_DEV_IRQ_HOST_INTX);
+
+    return kvm_assign_irq_internal(s, dev_id, irq_type, guest_irq);
+}
+
+int kvm_device_intx_set_mask(KVMState *s, uint32_t dev_id, bool masked)
+{
+    struct kvm_assigned_pci_dev dev_data = {
+        .assigned_dev_id = dev_id,
+        .flags = masked ? KVM_DEV_ASSIGN_MASK_INTX : 0,
+    };
+
+    return kvm_vm_ioctl(s, KVM_ASSIGN_SET_INTX_MASK, &dev_data);
+}
+
+static int kvm_deassign_irq_internal(KVMState *s, uint32_t dev_id,
+                                     uint32_t type)
+{
+    struct kvm_assigned_irq assigned_irq = {
+        .assigned_dev_id = dev_id,
+        .flags = type,
+    };
+
+    return kvm_vm_ioctl(s, KVM_DEASSIGN_DEV_IRQ, &assigned_irq);
+}
+
+int kvm_device_intx_deassign(KVMState *s, uint32_t dev_id, bool use_host_msi)
+{
+    return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_INTX |
+        (use_host_msi ? KVM_DEV_IRQ_HOST_MSI : KVM_DEV_IRQ_HOST_INTX));
+}
+
+int kvm_device_msi_assign(KVMState *s, uint32_t dev_id, int virq)
+{
+    return kvm_assign_irq_internal(s, dev_id, KVM_DEV_IRQ_HOST_MSI |
+                                              KVM_DEV_IRQ_GUEST_MSI, virq);
+}
+
+int kvm_device_msi_deassign(KVMState *s, uint32_t dev_id)
+{
+    return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSI |
+                                                KVM_DEV_IRQ_HOST_MSI);
+}
+
+bool kvm_device_msix_supported(KVMState *s)
+{
+    /* The kernel lacks a corresponding KVM_CAP, so we probe by calling
+     * KVM_ASSIGN_SET_MSIX_NR with an invalid parameter. */
+    return kvm_vm_ioctl(s, KVM_ASSIGN_SET_MSIX_NR, NULL) == -EFAULT;
+}
+
+int kvm_device_msix_init_vectors(KVMState *s, uint32_t dev_id,
+                                 uint32_t nr_vectors)
+{
+    struct kvm_assigned_msix_nr msix_nr = {
+        .assigned_dev_id = dev_id,
+        .entry_nr = nr_vectors,
+    };
+
+    return kvm_vm_ioctl(s, KVM_ASSIGN_SET_MSIX_NR, &msix_nr);
+}
+
+int kvm_device_msix_set_vector(KVMState *s, uint32_t dev_id, uint32_t vector,
+                               int virq)
+{
+    struct kvm_assigned_msix_entry msix_entry = {
+        .assigned_dev_id = dev_id,
+        .gsi = virq,
+        .entry = vector,
+    };
+
+    return kvm_vm_ioctl(s, KVM_ASSIGN_SET_MSIX_ENTRY, &msix_entry);
+}
+
+int kvm_device_msix_assign(KVMState *s, uint32_t dev_id)
+{
+    return kvm_assign_irq_internal(s, dev_id, KVM_DEV_IRQ_HOST_MSIX |
+                                              KVM_DEV_IRQ_GUEST_MSIX, 0);
+}
+
+int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id)
+{
+    return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSIX |
+                                                KVM_DEV_IRQ_HOST_MSIX);
+}
diff --git a/target-i386/kvm_i386.h b/target-i386/kvm_i386.h
index b82bbf4..f6ab82f 100644
--- a/target-i386/kvm_i386.h
+++ b/target-i386/kvm_i386.h
@@ -11,6 +11,28 @@
 #ifndef QEMU_KVM_I386_H
 #define QEMU_KVM_I386_H
 
+#include "kvm.h"
+
 bool kvm_allows_irq0_override(void);
 
+int kvm_device_pci_assign(KVMState *s, PCIHostDeviceAddress *dev_addr,
+                          uint32_t flags, uint32_t *dev_id);
+int kvm_device_pci_deassign(KVMState *s, uint32_t dev_id);
+
+int kvm_device_intx_assign(KVMState *s, uint32_t dev_id,
+                           bool use_host_msi, uint32_t guest_irq);
+int kvm_device_intx_set_mask(KVMState *s, uint32_t dev_id, bool masked);
+int kvm_device_intx_deassign(KVMState *s, uint32_t dev_id, bool use_host_msi);
+
+int kvm_device_msi_assign(KVMState *s, uint32_t dev_id, int virq);
+int kvm_device_msi_deassign(KVMState *s, uint32_t dev_id);
+
+bool kvm_device_msix_supported(KVMState *s);
+int kvm_device_msix_init_vectors(KVMState *s, uint32_t dev_id,
+                                 uint32_t nr_vectors);
+int kvm_device_msix_set_vector(KVMState *s, uint32_t dev_id, uint32_t vector,
+                               int virq);
+int kvm_device_msix_assign(KVMState *s, uint32_t dev_id);
+int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id);
+
 #endif
commit 3ab73842446a9f2d9d78b23daa43ff382679eece
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Aug 27 08:28:39 2012 +0200

    kvm: Introduce kvm_has_intx_set_mask
    
    Will be used by PCI device assignment code.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Acked-by: Acked-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index e2abfb9..39cff55 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -88,6 +88,7 @@ struct KVMState
     int pit_state2;
     int xsave, xcrs;
     int many_ioeventfds;
+    int intx_set_mask;
     /* The man page (and posix) say ioctl numbers are signed int, but
      * they're not.  Linux, glibc and *BSD all treat ioctl numbers as
      * unsigned, and treating them as signed here can break things */
@@ -1386,6 +1387,8 @@ int kvm_init(void)
     s->direct_msi = (kvm_check_extension(s, KVM_CAP_SIGNAL_MSI) > 0);
 #endif
 
+    s->intx_set_mask = kvm_check_extension(s, KVM_CAP_PCI_2_3);
+
     ret = kvm_arch_init(s);
     if (ret < 0) {
         goto err;
@@ -1740,6 +1743,11 @@ int kvm_has_gsi_routing(void)
 #endif
 }
 
+int kvm_has_intx_set_mask(void)
+{
+    return kvm_state->intx_set_mask;
+}
+
 void *kvm_vmalloc(ram_addr_t size)
 {
 #ifdef TARGET_S390X
diff --git a/kvm.h b/kvm.h
index 5cefe3a..dea2998 100644
--- a/kvm.h
+++ b/kvm.h
@@ -117,6 +117,7 @@ int kvm_has_xcrs(void);
 int kvm_has_pit_state2(void);
 int kvm_has_many_ioeventfds(void);
 int kvm_has_gsi_routing(void);
+int kvm_has_intx_set_mask(void);
 
 #ifdef NEED_CPU_H
 int kvm_init_vcpu(CPUArchState *env);
commit cc57407e966e8467f9742e7a4ad47567b5951122
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Aug 27 08:28:38 2012 +0200

    kvm: Introduce kvm_irqchip_update_msi_route
    
    This service allows to update an MSI route without releasing/reacquiring
    the associated VIRQ. Will be used by PCI device assignment, later on
    likely also by virtio/vhost and VFIO.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Acked-by: Acked-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index f96be21..e2abfb9 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -963,6 +963,30 @@ static void kvm_add_routing_entry(KVMState *s,
     kvm_irqchip_commit_routes(s);
 }
 
+static int kvm_update_routing_entry(KVMState *s,
+                                    struct kvm_irq_routing_entry *new_entry)
+{
+    struct kvm_irq_routing_entry *entry;
+    int n;
+
+    for (n = 0; n < s->irq_routes->nr; n++) {
+        entry = &s->irq_routes->entries[n];
+        if (entry->gsi != new_entry->gsi) {
+            continue;
+        }
+
+        entry->type = new_entry->type;
+        entry->flags = new_entry->flags;
+        entry->u = new_entry->u;
+
+        kvm_irqchip_commit_routes(s);
+
+        return 0;
+    }
+
+    return -ESRCH;
+}
+
 void kvm_irqchip_add_irq_route(KVMState *s, int irq, int irqchip, int pin)
 {
     struct kvm_irq_routing_entry e;
@@ -1125,6 +1149,24 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
     return virq;
 }
 
+int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
+{
+    struct kvm_irq_routing_entry kroute;
+
+    if (!kvm_irqchip_in_kernel()) {
+        return -ENOSYS;
+    }
+
+    kroute.gsi = virq;
+    kroute.type = KVM_IRQ_ROUTING_MSI;
+    kroute.flags = 0;
+    kroute.u.msi.address_lo = (uint32_t)msg.address;
+    kroute.u.msi.address_hi = msg.address >> 32;
+    kroute.u.msi.data = msg.data;
+
+    return kvm_update_routing_entry(s, &kroute);
+}
+
 static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
 {
     struct kvm_irqfd irqfd = {
diff --git a/kvm.h b/kvm.h
index 37d1f81..5cefe3a 100644
--- a/kvm.h
+++ b/kvm.h
@@ -270,6 +270,7 @@ int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign,
 int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign);
 
 int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
+int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
 void kvm_irqchip_release_virq(KVMState *s, int virq);
 
 int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
commit 6845df48cec9cc6833429942b3ceed333a791119
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Sep 8 03:45:43 2012 +0000

    tcg/s390: fix ld/st with CONFIG_TCG_PASS_AREG0
    
    The load/store slow path has been broken in e141ab52d:
    - We need to move 4 registers for store functions and 3 registers for
      load functions and not the reverse.
    - According to the s390x calling convention the arguments of a function
      should be zero extended. This means that the register shift should be
      done with TCG_TYPE_I64 to ensure the higher word is correctly zero
      extended when needed.
    
    I am aware that CONFIG_TCG_PASS_AREG0 is being removed and thus that
    this patch can be improved, but doing so means it can also be applied to
    the 1.1 and 1.2 stable branches.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 04662c1..99b5339 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -1509,11 +1509,13 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R4, mem_index);
 #ifdef CONFIG_TCG_PASS_AREG0
         /* XXX/FIXME: suboptimal */
-        tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
+        tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3],
+                    tcg_target_call_iarg_regs[2]);
+        tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
                     tcg_target_call_iarg_regs[1]);
-        tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+        tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1],
                     tcg_target_call_iarg_regs[0]);
-        tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+        tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0],
                     TCG_AREG0);
 #endif
         tgen_calli(s, (tcg_target_ulong)qemu_st_helpers[s_bits]);
@@ -1521,13 +1523,11 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
         tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index);
 #ifdef CONFIG_TCG_PASS_AREG0
         /* XXX/FIXME: suboptimal */
-        tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
-                    tcg_target_call_iarg_regs[2]);
         tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
                     tcg_target_call_iarg_regs[1]);
-        tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+        tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1],
                     tcg_target_call_iarg_regs[0]);
-        tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
+        tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0],
                     TCG_AREG0);
 #endif
         tgen_calli(s, (tcg_target_ulong)qemu_ld_helpers[s_bits]);
commit 19b0516fb4fd22b08c6ee42ea4162aaf3b9c8ee1
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 2 07:33:40 2012 +0000

    target-s390x: switch to AREG0 free mode
    
    Add an explicit CPUState parameter instead of relying on AREG0.
    
    Remove temporary wrappers and switch to AREG0 free mode.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    [agraf: fix conflicts]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/configure b/configure
index d97fd81..a88a465 100755
--- a/configure
+++ b/configure
@@ -3829,7 +3829,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile"
 
 
 case "$target_arch2" in
-  alpha | i386 | or32 | sparc* | x86_64 | xtensa* | ppc*)
+  alpha | i386 | or32 | s390x | sparc* | x86_64 | xtensa* | ppc*)
     echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
   ;;
 esac
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 156d946..e728abf 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -2,5 +2,3 @@ obj-y += translate.o helper.o cpu.o interrupt.o
 obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
-
-$(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 9b7a2e3..ed81af3 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -1008,14 +1008,4 @@ uint32_t set_cc_nz_f64(float64 v);
 /* misc_helper.c */
 void program_interrupt(CPUS390XState *env, uint32_t code, int ilc);
 
-/* temporary wrappers */
-uint32_t cpu_ldub_data(CPUS390XState *env, target_ulong ptr);
-uint32_t cpu_lduw_data(CPUS390XState *env, target_ulong ptr);
-uint32_t cpu_ldl_data(CPUS390XState *env, target_ulong ptr);
-uint64_t cpu_ldq_data(CPUS390XState *env, target_ulong ptr);
-
-void cpu_stb_data(CPUS390XState *env, target_ulong ptr, uint32_t data);
-void cpu_stw_data(CPUS390XState *env, target_ulong ptr, uint32_t data);
-void cpu_stl_data(CPUS390XState *env, target_ulong ptr, uint32_t data);
-void cpu_stq_data(CPUS390XState *env, target_ulong ptr, uint64_t data);
 #endif
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index e235419..ee9420d 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -21,8 +21,7 @@
 #include "cpu.h"
 #include "helper.h"
 
-/* temporarily disabled due to wrapper use */
-#if 0 && !defined(CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
 #include "softmmu_exec.h"
 #endif
 
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index d98e6d9..a5741ec 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -499,14 +499,14 @@ static void do_program_interrupt(CPUS390XState *env)
 
     switch (ilc) {
     case ILC_LATER:
-        ilc = get_ilc(ldub_code(env->psw.addr));
+        ilc = get_ilc(cpu_ldub_code(env, env->psw.addr));
         break;
     case ILC_LATER_INC:
-        ilc = get_ilc(ldub_code(env->psw.addr));
+        ilc = get_ilc(cpu_ldub_code(env, env->psw.addr));
         env->psw.addr += ilc * 2;
         break;
     case ILC_LATER_INC_2:
-        ilc = get_ilc(ldub_code(env->psw.addr)) * 2;
+        ilc = get_ilc(cpu_ldub_code(env, env->psw.addr)) * 2;
         env->psw.addr += ilc;
         break;
     }
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index f4e0b37..5419f37 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -1,17 +1,17 @@
 #include "def-helper.h"
 
 DEF_HELPER_2(exception, void, env, i32)
-DEF_HELPER_3(nc, i32, i32, i64, i64)
-DEF_HELPER_3(oc, i32, i32, i64, i64)
-DEF_HELPER_3(xc, i32, i32, i64, i64)
-DEF_HELPER_3(mvc, void, i32, i64, i64)
-DEF_HELPER_3(clc, i32, i32, i64, i64)
-DEF_HELPER_2(mvcl, i32, i32, i32)
+DEF_HELPER_4(nc, i32, env, i32, i64, i64)
+DEF_HELPER_4(oc, i32, env, i32, i64, i64)
+DEF_HELPER_4(xc, i32, env, i32, i64, i64)
+DEF_HELPER_4(mvc, void, env, i32, i64, i64)
+DEF_HELPER_4(clc, i32, env, i32, i64, i64)
+DEF_HELPER_3(mvcl, i32, env, i32, i32)
 DEF_HELPER_FLAGS_1(set_cc_comp_s32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32)
 DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64)
 DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32)
-DEF_HELPER_3(clm, i32, i32, i32, i64)
-DEF_HELPER_3(stcm, void, i32, i32, i64)
+DEF_HELPER_4(clm, i32, env, i32, i32, i64)
+DEF_HELPER_4(stcm, void, env, i32, i32, i64)
 DEF_HELPER_3(mlg, void, env, i32, i64)
 DEF_HELPER_3(dlg, void, env, i32, i64)
 DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64)
@@ -22,27 +22,27 @@ DEF_HELPER_FLAGS_3(set_cc_sub64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s6
 DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32)
 DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
-DEF_HELPER_3(srst, i32, i32, i32, i32)
-DEF_HELPER_3(clst, i32, i32, i32, i32)
-DEF_HELPER_3(mvpg, void, i64, i64, i64)
-DEF_HELPER_3(mvst, void, i32, i32, i32)
-DEF_HELPER_3(csg, i32, i32, i64, i32)
-DEF_HELPER_3(cdsg, i32, i32, i64, i32)
-DEF_HELPER_3(cs, i32, i32, i64, i32)
-DEF_HELPER_4(ex, i32, i32, i64, i64, i64)
+DEF_HELPER_4(srst, i32, env, i32, i32, i32)
+DEF_HELPER_4(clst, i32, env, i32, i32, i32)
+DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
+DEF_HELPER_4(mvst, void, env, i32, i32, i32)
+DEF_HELPER_4(csg, i32, env, i32, i64, i32)
+DEF_HELPER_4(cdsg, i32, env, i32, i64, i32)
+DEF_HELPER_4(cs, i32, env, i32, i64, i32)
+DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32)
 DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_PURE|TCG_CALL_CONST, s32, s32)
 DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_PURE|TCG_CALL_CONST, i64, s64)
 DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64)
-DEF_HELPER_3(stcmh, void, i32, i64, i32)
-DEF_HELPER_3(icmh, i32, i32, i64, i32)
+DEF_HELPER_4(stcmh, void, env, i32, i64, i32)
+DEF_HELPER_4(icmh, i32, env, i32, i64, i32)
 DEF_HELPER_3(ipm, void, env, i32, i32)
 DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
 DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
-DEF_HELPER_3(stam, void, i32, i64, i32)
-DEF_HELPER_3(lam, void, i32, i64, i32)
-DEF_HELPER_3(mvcle, i32, i32, i64, i32)
-DEF_HELPER_3(clcle, i32, i32, i64, i32)
+DEF_HELPER_4(stam, void, env, i32, i64, i32)
+DEF_HELPER_4(lam, void, env, i32, i64, i32)
+DEF_HELPER_4(mvcle, i32, env, i32, i64, i32)
+DEF_HELPER_4(clcle, i32, env, i32, i64, i32)
 DEF_HELPER_4(slb, i32, env, i32, i32, i32)
 DEF_HELPER_5(slbg, i32, env, i32, i32, i64, i64)
 DEF_HELPER_3(cefbr, void, env, i32, s32)
@@ -110,8 +110,8 @@ DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64)
 DEF_HELPER_3(flogr, i32, env, i32, i64)
 DEF_HELPER_3(sqdbr, void, env, i32, i32)
 DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32)
-DEF_HELPER_3(unpk, void, i32, i64, i64)
-DEF_HELPER_3(tr, void, i32, i64, i64)
+DEF_HELPER_4(unpk, void, env, i32, i64, i64)
+DEF_HELPER_4(tr, void, env, i32, i64, i64)
 
 DEF_HELPER_3(servc, i32, env, i32, i64)
 DEF_HELPER_4(diag, i64, env, i32, i64, i64)
@@ -127,24 +127,24 @@ DEF_HELPER_FLAGS_2(stckc, TCG_CALL_CONST, void, env, i64)
 DEF_HELPER_FLAGS_2(spt, TCG_CALL_CONST, void, env, i64)
 DEF_HELPER_FLAGS_2(stpt, TCG_CALL_CONST, void, env, i64)
 DEF_HELPER_4(stsi, i32, env, i64, i32, i32)
-DEF_HELPER_3(lctl, void, i32, i64, i32)
-DEF_HELPER_3(lctlg, void, i32, i64, i32)
-DEF_HELPER_3(stctl, void, i32, i64, i32)
-DEF_HELPER_3(stctg, void, i32, i64, i32)
+DEF_HELPER_4(lctl, void, env, i32, i64, i32)
+DEF_HELPER_4(lctlg, void, env, i32, i64, i32)
+DEF_HELPER_4(stctl, void, env, i32, i64, i32)
+DEF_HELPER_4(stctg, void, env, i32, i64, i32)
 DEF_HELPER_FLAGS_2(tprot, TCG_CALL_CONST, i32, i64, i64)
-DEF_HELPER_FLAGS_1(iske, TCG_CALL_PURE|TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_2(sske, TCG_CALL_CONST, void, i32, i64)
-DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_CONST, i32, i32, i64)
-DEF_HELPER_2(csp, i32, i32, i32)
-DEF_HELPER_3(mvcs, i32, i64, i64, i64)
-DEF_HELPER_3(mvcp, i32, i64, i64, i64)
+DEF_HELPER_FLAGS_2(iske, TCG_CALL_PURE|TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_3(sske, TCG_CALL_CONST, void, env, i32, i64)
+DEF_HELPER_FLAGS_3(rrbe, TCG_CALL_CONST, i32, env, i32, i64)
+DEF_HELPER_3(csp, i32, env, i32, i32)
+DEF_HELPER_4(mvcs, i32, env, i64, i64, i64)
+DEF_HELPER_4(mvcp, i32, env, i64, i64, i64)
 DEF_HELPER_4(sigp, i32, env, i64, i32, i64)
 DEF_HELPER_2(sacf, void, env, i64)
-DEF_HELPER_FLAGS_2(ipte, TCG_CALL_CONST, void, i64, i64)
-DEF_HELPER_FLAGS_0(ptlb, TCG_CALL_CONST, void)
-DEF_HELPER_2(lra, i32, i64, i32)
-DEF_HELPER_2(stura, void, i64, i32)
-DEF_HELPER_2(cksm, void, i32, i32)
+DEF_HELPER_FLAGS_3(ipte, TCG_CALL_CONST, void, env, i64, i64)
+DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_CONST, void, env)
+DEF_HELPER_3(lra, i32, env, i64, i32)
+DEF_HELPER_3(stura, void, env, i64, i32)
+DEF_HELPER_3(cksm, void, env, i32, i32)
 
 DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
                    i32, env, i32, i64, i64, i64)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 52f2602..b21b37c 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -19,7 +19,6 @@
  */
 
 #include "cpu.h"
-#include "dyngen-exec.h"
 #include "helper.h"
 
 /*****************************************************************************/
@@ -45,15 +44,12 @@
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
-void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUS390XState *env, target_ulong addr, int is_write, int mmu_idx,
               uintptr_t retaddr)
 {
     TranslationBlock *tb;
-    CPUS390XState *saved_env;
     int ret;
 
-    saved_env = env;
-    env = env1;
     ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx);
     if (unlikely(ret != 0)) {
         if (likely(retaddr)) {
@@ -67,7 +63,6 @@ void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx,
         }
         cpu_loop_exit(env);
     }
-    env = saved_env;
 }
 
 #endif
@@ -90,7 +85,7 @@ static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest,
     int flags;
 
     if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
-        stb(dest, byte);
+        cpu_stb_data(env, dest, byte);
         cpu_abort(env, "should never reach here");
     }
     dest_phys |= dest & ~TARGET_PAGE_MASK;
@@ -114,13 +109,13 @@ static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest,
     int flags;
 
     if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
-        stb(dest, 0);
+        cpu_stb_data(env, dest, 0);
         cpu_abort(env, "should never reach here");
     }
     dest_phys |= dest & ~TARGET_PAGE_MASK;
 
     if (mmu_translate(env, src, 0, asc, &src_phys, &flags)) {
-        ldub(src);
+        cpu_ldub_data(env, src);
         cpu_abort(env, "should never reach here");
     }
     src_phys |= src & ~TARGET_PAGE_MASK;
@@ -136,7 +131,8 @@ static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest,
 #endif
 
 /* and on array */
-uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src)
+uint32_t HELPER(nc)(CPUS390XState *env, uint32_t l, uint64_t dest,
+                    uint64_t src)
 {
     int i;
     unsigned char x;
@@ -145,17 +141,18 @@ uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src)
     HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
                __func__, l, dest, src);
     for (i = 0; i <= l; i++) {
-        x = ldub(dest + i) & ldub(src + i);
+        x = cpu_ldub_data(env, dest + i) & cpu_ldub_data(env, src + i);
         if (x) {
             cc = 1;
         }
-        stb(dest + i, x);
+        cpu_stb_data(env, dest + i, x);
     }
     return cc;
 }
 
 /* xor on array */
-uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src)
+uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, uint64_t dest,
+                    uint64_t src)
 {
     int i;
     unsigned char x;
@@ -179,17 +176,18 @@ uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src)
 #endif
 
     for (i = 0; i <= l; i++) {
-        x = ldub(dest + i) ^ ldub(src + i);
+        x = cpu_ldub_data(env, dest + i) ^ cpu_ldub_data(env, src + i);
         if (x) {
             cc = 1;
         }
-        stb(dest + i, x);
+        cpu_stb_data(env, dest + i, x);
     }
     return cc;
 }
 
 /* or on array */
-uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src)
+uint32_t HELPER(oc)(CPUS390XState *env, uint32_t l, uint64_t dest,
+                    uint64_t src)
 {
     int i;
     unsigned char x;
@@ -198,17 +196,17 @@ uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src)
     HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
                __func__, l, dest, src);
     for (i = 0; i <= l; i++) {
-        x = ldub(dest + i) | ldub(src + i);
+        x = cpu_ldub_data(env, dest + i) | cpu_ldub_data(env, src + i);
         if (x) {
             cc = 1;
         }
-        stb(dest + i, x);
+        cpu_stb_data(env, dest + i, x);
     }
     return cc;
 }
 
 /* memmove */
-void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src)
+void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 {
     int i = 0;
     int x = 0;
@@ -222,7 +220,7 @@ void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src)
         (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) &&
         (dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) {
         if (dest == (src + 1)) {
-            mvc_fast_memset(env, l + 1, dest, ldub(src));
+            mvc_fast_memset(env, l + 1, dest, cpu_ldub_data(env, src));
             return;
         } else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
             mvc_fast_memmove(env, l + 1, dest, src);
@@ -231,7 +229,7 @@ void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src)
     }
 #else
     if (dest == (src + 1)) {
-        memset(g2h(dest), ldub(src), l + 1);
+        memset(g2h(dest), cpu_ldub_data(env, src), l + 1);
         return;
     } else {
         memmove(g2h(dest), g2h(src), l + 1);
@@ -242,19 +240,19 @@ void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src)
     /* handle the parts that fit into 8-byte loads/stores */
     if (dest != (src + 1)) {
         for (i = 0; i < l_64; i++) {
-            stq(dest + x, ldq(src + x));
+            cpu_stq_data(env, dest + x, cpu_ldq_data(env, src + x));
             x += 8;
         }
     }
 
     /* slow version crossing pages with byte accesses */
     for (i = x; i <= l; i++) {
-        stb(dest + i, ldub(src + i));
+        cpu_stb_data(env, dest + i, cpu_ldub_data(env, src + i));
     }
 }
 
 /* compare unsigned byte arrays */
-uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2)
+uint32_t HELPER(clc)(CPUS390XState *env, uint32_t l, uint64_t s1, uint64_t s2)
 {
     int i;
     unsigned char x, y;
@@ -263,8 +261,8 @@ uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2)
     HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n",
                __func__, l, s1, s2);
     for (i = 0; i <= l; i++) {
-        x = ldub(s1 + i);
-        y = ldub(s2 + i);
+        x = cpu_ldub_data(env, s1 + i);
+        y = cpu_ldub_data(env, s2 + i);
         HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y);
         if (x < y) {
             cc = 1;
@@ -281,7 +279,8 @@ uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2)
 }
 
 /* compare logical under mask */
-uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr)
+uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
+                     uint64_t addr)
 {
     uint8_t r, d;
     uint32_t cc;
@@ -291,7 +290,7 @@ uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr)
     cc = 0;
     while (mask) {
         if (mask & 8) {
-            d = ldub(addr);
+            d = cpu_ldub_data(env, addr);
             r = (r1 & 0xff000000UL) >> 24;
             HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d,
                        addr);
@@ -312,7 +311,8 @@ uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr)
 }
 
 /* store character under mask */
-void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr)
+void HELPER(stcm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
+                  uint64_t addr)
 {
     uint8_t r;
 
@@ -321,7 +321,7 @@ void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr)
     while (mask) {
         if (mask & 8) {
             r = (r1 & 0xff000000UL) >> 24;
-            stb(addr, r);
+            cpu_stb_data(env, addr, r);
             HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr);
             addr++;
         }
@@ -331,7 +331,7 @@ void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr)
     HELPER_LOG("\n");
 }
 
-static inline uint64_t get_address(int x2, int b2, int d2)
+static inline uint64_t get_address(CPUS390XState *env, int x2, int b2, int d2)
 {
     uint64_t r = d2;
 
@@ -351,7 +351,7 @@ static inline uint64_t get_address(int x2, int b2, int d2)
     return r;
 }
 
-static inline uint64_t get_address_31fix(int reg)
+static inline uint64_t get_address_31fix(CPUS390XState *env, int reg)
 {
     uint64_t r = env->regs[reg];
 
@@ -364,18 +364,18 @@ static inline uint64_t get_address_31fix(int reg)
 }
 
 /* search string (c is byte to search, r2 is string, r1 end of string) */
-uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2)
+uint32_t HELPER(srst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
 {
     uint64_t i;
     uint32_t cc = 2;
-    uint64_t str = get_address_31fix(r2);
-    uint64_t end = get_address_31fix(r1);
+    uint64_t str = get_address_31fix(env, r2);
+    uint64_t end = get_address_31fix(env, r1);
 
     HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __func__,
                c, env->regs[r1], env->regs[r2]);
 
     for (i = str; i != end; i++) {
-        if (ldub(i) == c) {
+        if (cpu_ldub_data(env, i) == c) {
             env->regs[r1] = i;
             cc = 1;
             break;
@@ -386,10 +386,10 @@ uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2)
 }
 
 /* unsigned string compare (c is string terminator) */
-uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2)
+uint32_t HELPER(clst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
 {
-    uint64_t s1 = get_address_31fix(r1);
-    uint64_t s2 = get_address_31fix(r2);
+    uint64_t s1 = get_address_31fix(env, r1);
+    uint64_t s2 = get_address_31fix(env, r2);
     uint8_t v1, v2;
     uint32_t cc;
 
@@ -401,8 +401,8 @@ uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2)
     }
 #endif
     for (;;) {
-        v1 = ldub(s1);
-        v2 = ldub(s2);
+        v1 = cpu_ldub_data(env, s1);
+        v2 = cpu_ldub_data(env, s2);
         if ((v1 == c || v2 == c) || (v1 != v2)) {
             break;
         }
@@ -422,14 +422,14 @@ uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2)
 }
 
 /* move page */
-void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2)
+void HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2)
 {
     /* XXX missing r0 handling */
 #ifdef CONFIG_USER_ONLY
     int i;
 
     for (i = 0; i < TARGET_PAGE_SIZE; i++) {
-        stb(r1 + i, ldub(r2 + i));
+        cpu_stb_data(env, r1 + i, cpu_ldub_data(env, r2 + i));
     }
 #else
     mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2);
@@ -437,10 +437,10 @@ void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2)
 }
 
 /* string copy (c is string terminator) */
-void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2)
+void HELPER(mvst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
 {
-    uint64_t dest = get_address_31fix(r1);
-    uint64_t src = get_address_31fix(r2);
+    uint64_t dest = get_address_31fix(env, r1);
+    uint64_t src = get_address_31fix(env, r2);
     uint8_t v;
 
     c = c & 0xff;
@@ -451,8 +451,8 @@ void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2)
     }
 #endif
     for (;;) {
-        v = ldub(src);
-        stb(dest, v);
+        v = cpu_ldub_data(env, src);
+        cpu_stb_data(env, dest, v);
         if (v == c) {
             break;
         }
@@ -463,15 +463,15 @@ void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2)
 }
 
 /* compare and swap 64-bit */
-uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3)
+uint32_t HELPER(csg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 {
     /* FIXME: locking? */
     uint32_t cc;
-    uint64_t v2 = ldq(a2);
+    uint64_t v2 = cpu_ldq_data(env, a2);
 
     if (env->regs[r1] == v2) {
         cc = 0;
-        stq(a2, env->regs[r3]);
+        cpu_stq_data(env, a2, env->regs[r3]);
     } else {
         cc = 1;
         env->regs[r1] = v2;
@@ -480,19 +480,19 @@ uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3)
 }
 
 /* compare double and swap 64-bit */
-uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3)
+uint32_t HELPER(cdsg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 {
     /* FIXME: locking? */
     uint32_t cc;
-    uint64_t v2_hi = ldq(a2);
-    uint64_t v2_lo = ldq(a2 + 8);
+    uint64_t v2_hi = cpu_ldq_data(env, a2);
+    uint64_t v2_lo = cpu_ldq_data(env, a2 + 8);
     uint64_t v1_hi = env->regs[r1];
     uint64_t v1_lo = env->regs[r1 + 1];
 
     if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) {
         cc = 0;
-        stq(a2, env->regs[r3]);
-        stq(a2 + 8, env->regs[r3 + 1]);
+        cpu_stq_data(env, a2, env->regs[r3]);
+        cpu_stq_data(env, a2 + 8, env->regs[r3 + 1]);
     } else {
         cc = 1;
         env->regs[r1] = v2_hi;
@@ -503,16 +503,16 @@ uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3)
 }
 
 /* compare and swap 32-bit */
-uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3)
+uint32_t HELPER(cs)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 {
     /* FIXME: locking? */
     uint32_t cc;
-    uint32_t v2 = ldl(a2);
+    uint32_t v2 = cpu_ldl_data(env, a2);
 
     HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __func__, r1, a2, r3);
     if (((uint32_t)env->regs[r1]) == v2) {
         cc = 0;
-        stl(a2, (uint32_t)env->regs[r3]);
+        cpu_stl_data(env, a2, (uint32_t)env->regs[r3]);
     } else {
         cc = 1;
         env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2;
@@ -520,7 +520,8 @@ uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3)
     return cc;
 }
 
-static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask)
+static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address,
+                           uint32_t mask)
 {
     int pos = 24; /* top of the lower half of r1 */
     uint64_t rmask = 0xff000000ULL;
@@ -531,7 +532,7 @@ static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask)
     while (mask) {
         if (mask & 8) {
             env->regs[r1] &= ~rmask;
-            val = ldub(address);
+            val = cpu_ldub_data(env, address);
             if ((val & 0x80) && !ccd) {
                 cc = 1;
             }
@@ -557,9 +558,10 @@ static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask)
    in other words: tricky...
    currently implemented by interpreting the cases it is most commonly used in
 */
-uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
+uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1,
+                    uint64_t addr, uint64_t ret)
 {
-    uint16_t insn = lduw_code(addr);
+    uint16_t insn = cpu_lduw_code(env, addr);
 
     HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr,
                insn);
@@ -567,23 +569,27 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
         uint32_t l, insn2, b1, b2, d1, d2;
 
         l = v1 & 0xff;
-        insn2 = ldl_code(addr + 2);
+        insn2 = cpu_ldl_code(env, addr + 2);
         b1 = (insn2 >> 28) & 0xf;
         b2 = (insn2 >> 12) & 0xf;
         d1 = (insn2 >> 16) & 0xfff;
         d2 = insn2 & 0xfff;
         switch (insn & 0xf00) {
         case 0x200:
-            helper_mvc(l, get_address(0, b1, d1), get_address(0, b2, d2));
+            helper_mvc(env, l, get_address(env, 0, b1, d1),
+                       get_address(env, 0, b2, d2));
             break;
         case 0x500:
-            cc = helper_clc(l, get_address(0, b1, d1), get_address(0, b2, d2));
+            cc = helper_clc(env, l, get_address(env, 0, b1, d1),
+                            get_address(env, 0, b2, d2));
             break;
         case 0x700:
-            cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2));
+            cc = helper_xc(env, l, get_address(env, 0, b1, d1),
+                           get_address(env, 0, b2, d2));
             break;
         case 0xc00:
-            helper_tr(l, get_address(0, b1, d1), get_address(0, b2, d2));
+            helper_tr(env, l, get_address(env, 0, b1, d1),
+                      get_address(env, 0, b2, d2));
             break;
         default:
             goto abort;
@@ -599,12 +605,12 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
     } else if ((insn & 0xff00) == 0xbf00) {
         uint32_t insn2, r1, r3, b2, d2;
 
-        insn2 = ldl_code(addr + 2);
+        insn2 = cpu_ldl_code(env, addr + 2);
         r1 = (insn2 >> 20) & 0xf;
         r3 = (insn2 >> 16) & 0xf;
         b2 = (insn2 >> 12) & 0xf;
         d2 = insn2 & 0xfff;
-        cc = helper_icm(r1, get_address(0, b2, d2), r3);
+        cc = helper_icm(env, r1, get_address(env, 0, b2, d2), r3);
     } else {
     abort:
         cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n",
@@ -614,13 +620,14 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
 }
 
 /* store character under mask high operates on the upper half of r1 */
-void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask)
+void HELPER(stcmh)(CPUS390XState *env, uint32_t r1, uint64_t address,
+                   uint32_t mask)
 {
     int pos = 56; /* top of the upper half of r1 */
 
     while (mask) {
         if (mask & 8) {
-            stb(address, (env->regs[r1] >> pos) & 0xff);
+            cpu_stb_data(env, address, (env->regs[r1] >> pos) & 0xff);
             address++;
         }
         mask = (mask << 1) & 0xf;
@@ -630,7 +637,8 @@ void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask)
 
 /* insert character under mask high; same as icm, but operates on the
    upper half of r1 */
-uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask)
+uint32_t HELPER(icmh)(CPUS390XState *env, uint32_t r1, uint64_t address,
+                      uint32_t mask)
 {
     int pos = 56; /* top of the upper half of r1 */
     uint64_t rmask = 0xff00000000000000ULL;
@@ -641,7 +649,7 @@ uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask)
     while (mask) {
         if (mask & 8) {
             env->regs[r1] &= ~rmask;
-            val = ldub(address);
+            val = cpu_ldub_data(env, address);
             if ((val & 0x80) && !ccd) {
                 cc = 1;
             }
@@ -661,12 +669,12 @@ uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask)
 }
 
 /* load access registers r1 to r3 from memory at a2 */
-void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3)
+void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 {
     int i;
 
     for (i = r1;; i = (i + 1) % 16) {
-        env->aregs[i] = ldl(a2);
+        env->aregs[i] = cpu_ldl_data(env, a2);
         a2 += 4;
 
         if (i == r3) {
@@ -676,12 +684,12 @@ void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3)
 }
 
 /* store access registers r1 to r3 in memory at a2 */
-void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3)
+void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 {
     int i;
 
     for (i = r1;; i = (i + 1) % 16) {
-        stl(a2, env->aregs[i]);
+        cpu_stl_data(env, a2, env->aregs[i]);
         a2 += 4;
 
         if (i == r3) {
@@ -691,12 +699,12 @@ void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3)
 }
 
 /* move long */
-uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2)
+uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2)
 {
     uint64_t destlen = env->regs[r1 + 1] & 0xffffff;
-    uint64_t dest = get_address_31fix(r1);
+    uint64_t dest = get_address_31fix(env, r1);
     uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
-    uint64_t src = get_address_31fix(r2);
+    uint64_t src = get_address_31fix(env, r2);
     uint8_t pad = src >> 24;
     uint8_t v;
     uint32_t cc;
@@ -714,12 +722,12 @@ uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2)
     }
 
     for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
-        v = ldub(src);
-        stb(dest, v);
+        v = cpu_ldub_data(env, src);
+        cpu_stb_data(env, dest, v);
     }
 
     for (; destlen; dest++, destlen--) {
-        stb(dest, pad);
+        cpu_stb_data(env, dest, pad);
     }
 
     env->regs[r1 + 1] = destlen;
@@ -732,7 +740,8 @@ uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2)
 }
 
 /* move long extended another memcopy insn with more bells and whistles */
-uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3)
+uint32_t HELPER(mvcle)(CPUS390XState *env, uint32_t r1, uint64_t a2,
+                       uint32_t r3)
 {
     uint64_t destlen = env->regs[r1 + 1];
     uint64_t dest = env->regs[r1];
@@ -762,12 +771,12 @@ uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3)
     }
 
     for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
-        v = ldub(src);
-        stb(dest, v);
+        v = cpu_ldub_data(env, src);
+        cpu_stb_data(env, dest, v);
     }
 
     for (; destlen; dest++, destlen--) {
-        stb(dest, pad);
+        cpu_stb_data(env, dest, pad);
     }
 
     env->regs[r1 + 1] = destlen;
@@ -781,12 +790,13 @@ uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3)
 }
 
 /* compare logical long extended memcompare insn with padding */
-uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3)
+uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2,
+                       uint32_t r3)
 {
     uint64_t destlen = env->regs[r1 + 1];
-    uint64_t dest = get_address_31fix(r1);
+    uint64_t dest = get_address_31fix(env, r1);
     uint64_t srclen = env->regs[r3 + 1];
-    uint64_t src = get_address_31fix(r3);
+    uint64_t src = get_address_31fix(env, r3);
     uint8_t pad = a2 & 0xff;
     uint8_t v1 = 0, v2 = 0;
     uint32_t cc = 0;
@@ -800,8 +810,8 @@ uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3)
     }
 
     for (; destlen || srclen; src++, dest++, destlen--, srclen--) {
-        v1 = srclen ? ldub(src) : pad;
-        v2 = destlen ? ldub(dest) : pad;
+        v1 = srclen ? cpu_ldub_data(env, src) : pad;
+        v2 = destlen ? cpu_ldub_data(env, dest) : pad;
         if (v1 != v2) {
             cc = (v1 < v2) ? 1 : 2;
             break;
@@ -818,14 +828,14 @@ uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3)
 }
 
 /* checksum */
-void HELPER(cksm)(uint32_t r1, uint32_t r2)
+void HELPER(cksm)(CPUS390XState *env, uint32_t r1, uint32_t r2)
 {
-    uint64_t src = get_address_31fix(r2);
+    uint64_t src = get_address_31fix(env, r2);
     uint64_t src_len = env->regs[(r2 + 1) & 15];
     uint64_t cksm = (uint32_t)env->regs[r1];
 
     while (src_len >= 4) {
-        cksm += ldl(src);
+        cksm += cpu_ldl_data(env, src);
 
         /* move to next word */
         src_len -= 4;
@@ -836,14 +846,14 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2)
     case 0:
         break;
     case 1:
-        cksm += ldub(src) << 24;
+        cksm += cpu_ldub_data(env, src) << 24;
         break;
     case 2:
-        cksm += lduw(src) << 16;
+        cksm += cpu_lduw_data(env, src) << 16;
         break;
     case 3:
-        cksm += lduw(src) << 16;
-        cksm += ldub(src + 2) << 8;
+        cksm += cpu_lduw_data(env, src) << 16;
+        cksm += cpu_ldub_data(env, src + 2) << 8;
         break;
     }
 
@@ -856,7 +866,8 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2)
         ((uint32_t)cksm + (cksm >> 32));
 }
 
-void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
+void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest,
+                  uint64_t src)
 {
     int len_dest = len >> 4;
     int len_src = len & 0xf;
@@ -867,8 +878,8 @@ void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
     src += len_src;
 
     /* last byte is special, it only flips the nibbles */
-    b = ldub(src);
-    stb(dest, (b << 4) | (b >> 4));
+    b = cpu_ldub_data(env, src);
+    cpu_stb_data(env, dest, (b << 4) | (b >> 4));
     src--;
     len_src--;
 
@@ -878,7 +889,7 @@ void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
         uint8_t cur_byte = 0;
 
         if (len_src > 0) {
-            cur_byte = ldub(src);
+            cur_byte = cpu_ldub_data(env, src);
         }
 
         len_dest--;
@@ -897,30 +908,31 @@ void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
         /* zone bits */
         cur_byte |= 0xf0;
 
-        stb(dest, cur_byte);
+        cpu_stb_data(env, dest, cur_byte);
     }
 }
 
-void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans)
+void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array,
+                uint64_t trans)
 {
     int i;
 
     for (i = 0; i <= len; i++) {
-        uint8_t byte = ldub(array + i);
-        uint8_t new_byte = ldub(trans + byte);
+        uint8_t byte = cpu_ldub_data(env, array + i);
+        uint8_t new_byte = cpu_ldub_data(env, trans + byte);
 
-        stb(array + i, new_byte);
+        cpu_stb_data(env, array + i, new_byte);
     }
 }
 
 #if !defined(CONFIG_USER_ONLY)
-void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3)
+void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 {
     int i;
     uint64_t src = a2;
 
     for (i = r1;; i = (i + 1) % 16) {
-        env->cregs[i] = ldq(src);
+        env->cregs[i] = cpu_ldq_data(env, src);
         HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n",
                    i, src, env->cregs[i]);
         src += sizeof(uint64_t);
@@ -933,13 +945,14 @@ void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3)
     tlb_flush(env, 1);
 }
 
-void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3)
+void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 {
     int i;
     uint64_t src = a2;
 
     for (i = r1;; i = (i + 1) % 16) {
-        env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | ldl(src);
+        env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) |
+            cpu_ldl_data(env, src);
         src += sizeof(uint32_t);
 
         if (i == r3) {
@@ -950,13 +963,13 @@ void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3)
     tlb_flush(env, 1);
 }
 
-void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3)
+void HELPER(stctg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 {
     int i;
     uint64_t dest = a2;
 
     for (i = r1;; i = (i + 1) % 16) {
-        stq(dest, env->cregs[i]);
+        cpu_stq_data(env, dest, env->cregs[i]);
         dest += sizeof(uint64_t);
 
         if (i == r3) {
@@ -965,13 +978,13 @@ void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3)
     }
 }
 
-void HELPER(stctl)(uint32_t r1, uint64_t a2, uint32_t r3)
+void HELPER(stctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 {
     int i;
     uint64_t dest = a2;
 
     for (i = r1;; i = (i + 1) % 16) {
-        stl(dest, env->cregs[i]);
+        cpu_stl_data(env, dest, env->cregs[i]);
         dest += sizeof(uint32_t);
 
         if (i == r3) {
@@ -988,9 +1001,9 @@ uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2)
 }
 
 /* insert storage key extended */
-uint64_t HELPER(iske)(uint64_t r2)
+uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2)
 {
-    uint64_t addr = get_address(0, 0, r2);
+    uint64_t addr = get_address(env, 0, 0, r2);
 
     if (addr > ram_size) {
         return 0;
@@ -1000,9 +1013,9 @@ uint64_t HELPER(iske)(uint64_t r2)
 }
 
 /* set storage key extended */
-void HELPER(sske)(uint32_t r1, uint64_t r2)
+void HELPER(sske)(CPUS390XState *env, uint32_t r1, uint64_t r2)
 {
-    uint64_t addr = get_address(0, 0, r2);
+    uint64_t addr = get_address(env, 0, 0, r2);
 
     if (addr > ram_size) {
         return;
@@ -1012,7 +1025,7 @@ void HELPER(sske)(uint32_t r1, uint64_t r2)
 }
 
 /* reset reference bit extended */
-uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
+uint32_t HELPER(rrbe)(CPUS390XState *env, uint32_t r1, uint64_t r2)
 {
     uint8_t re;
     uint8_t key;
@@ -1038,15 +1051,15 @@ uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
 }
 
 /* compare and swap and purge */
-uint32_t HELPER(csp)(uint32_t r1, uint32_t r2)
+uint32_t HELPER(csp)(CPUS390XState *env, uint32_t r1, uint32_t r2)
 {
     uint32_t cc;
     uint32_t o1 = env->regs[r1];
-    uint64_t a2 = get_address_31fix(r2) & ~3ULL;
-    uint32_t o2 = ldl(a2);
+    uint64_t a2 = get_address_31fix(env, r2) & ~3ULL;
+    uint32_t o2 = cpu_ldl_data(env, a2);
 
     if (o1 == o2) {
-        stl(a2, env->regs[(r1 + 1) & 15]);
+        cpu_stl_data(env, a2, env->regs[(r1 + 1) & 15]);
         if (env->regs[r2] & 0x3) {
             /* flush TLB / ALB */
             tlb_flush(env, 1);
@@ -1060,8 +1073,8 @@ uint32_t HELPER(csp)(uint32_t r1, uint32_t r2)
     return cc;
 }
 
-static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2,
-                        uint64_t mode2)
+static uint32_t mvc_asc(CPUS390XState *env, int64_t l, uint64_t a1,
+                        uint64_t mode1, uint64_t a2, uint64_t mode2)
 {
     target_ulong src, dest;
     int flags, cc = 0, i;
@@ -1089,7 +1102,7 @@ static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2,
         /* XXX be more clever */
         if ((((dest + i) & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) ||
             (((src + i) & TARGET_PAGE_MASK) != (src & TARGET_PAGE_MASK))) {
-            mvc_asc(l - i, a1 + i, mode1, a2 + i, mode2);
+            mvc_asc(env, l - i, a1 + i, mode1, a2 + i, mode2);
             break;
         }
         stb_phys(dest + i, ldub_phys(src + i));
@@ -1098,24 +1111,24 @@ static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2,
     return cc;
 }
 
-uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2)
+uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2)
 {
     HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
                __func__, l, a1, a2);
 
-    return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY);
+    return mvc_asc(env, l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY);
 }
 
-uint32_t HELPER(mvcp)(uint64_t l, uint64_t a1, uint64_t a2)
+uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2)
 {
     HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
                __func__, l, a1, a2);
 
-    return mvc_asc(l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY);
+    return mvc_asc(env, l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY);
 }
 
 /* invalidate pte */
-void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
+void HELPER(ipte)(CPUS390XState *env, uint64_t pte_addr, uint64_t vaddr)
 {
     uint64_t page = vaddr & TARGET_PAGE_MASK;
     uint64_t pte = 0;
@@ -1141,19 +1154,19 @@ void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
 }
 
 /* flush local tlb */
-void HELPER(ptlb)(void)
+void HELPER(ptlb)(CPUS390XState *env)
 {
     tlb_flush(env, 1);
 }
 
 /* store using real address */
-void HELPER(stura)(uint64_t addr, uint32_t v1)
+void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint32_t v1)
 {
-    stw_phys(get_address(0, 0, addr), v1);
+    stw_phys(get_address(env, 0, 0, addr), v1);
 }
 
 /* load real address */
-uint32_t HELPER(lra)(uint64_t addr, uint32_t r1)
+uint32_t HELPER(lra)(CPUS390XState *env, uint64_t addr, uint32_t r1)
 {
     uint32_t cc = 0;
     int old_exc = env->exception_index;
@@ -1188,52 +1201,3 @@ uint32_t HELPER(lra)(uint64_t addr, uint32_t r1)
 }
 
 #endif
-
-/* temporary wrappers */
-#if defined(CONFIG_USER_ONLY)
-#define ldub_data(addr) ldub_raw(addr)
-#define lduw_data(addr) lduw_raw(addr)
-#define ldl_data(addr) ldl_raw(addr)
-#define ldq_data(addr) ldq_raw(addr)
-
-#define stb_data(addr, data) stb_raw(addr, data)
-#define stw_data(addr, data) stw_raw(addr, data)
-#define stl_data(addr, data) stl_raw(addr, data)
-#define stq_data(addr, data) stq_raw(addr, data)
-#endif
-
-#define WRAP_LD(rettype, fn)                                    \
-    rettype cpu_ ## fn(CPUS390XState *env1, target_ulong addr)  \
-    {                                                           \
-        CPUS390XState *saved_env;                               \
-        rettype ret;                                            \
-                                                                \
-        saved_env = env;                                        \
-        env = env1;                                             \
-        ret = fn(addr);                                         \
-        env = saved_env;                                        \
-        return ret;                                             \
-    }
-
-WRAP_LD(uint32_t, ldub_data)
-WRAP_LD(uint32_t, lduw_data)
-WRAP_LD(uint32_t, ldl_data)
-WRAP_LD(uint64_t, ldq_data)
-#undef WRAP_LD
-
-#define WRAP_ST(datatype, fn)                                           \
-    void cpu_ ## fn(CPUS390XState *env1, target_ulong addr, datatype val) \
-    {                                                                   \
-        CPUS390XState *saved_env;                                       \
-                                                                        \
-        saved_env = env;                                                \
-        env = env1;                                                     \
-        fn(addr, val);                                                  \
-        env = saved_env;                                                \
-    }
-
-WRAP_ST(uint32_t, stb_data)
-WRAP_ST(uint32_t, stw_data)
-WRAP_ST(uint32_t, stl_data)
-WRAP_ST(uint64_t, stq_data)
-#undef WRAP_ST
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index ced26c6..2938ac9 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -31,10 +31,7 @@
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
-/* temporarily disabled due to wrapper use */
-#if 0
 #include "softmmu_exec.h"
-#endif
 #include "sysemu.h"
 #endif
 
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0c61e63..66119cd 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -276,19 +276,19 @@ static inline void potential_page_fault(DisasContext *s)
 
 static inline uint64_t ld_code2(uint64_t pc)
 {
-    return (uint64_t)lduw_code(pc);
+    return (uint64_t)cpu_lduw_code(cpu_single_env, pc);
 }
 
 static inline uint64_t ld_code4(uint64_t pc)
 {
-    return (uint64_t)ldl_code(pc);
+    return (uint64_t)cpu_ldl_code(cpu_single_env, pc);
 }
 
 static inline uint64_t ld_code6(uint64_t pc)
 {
     uint64_t opc;
-    opc = (uint64_t)lduw_code(pc) << 32;
-    opc |= (uint64_t)(uint32_t)ldl_code(pc+2);
+    opc = (uint64_t)cpu_lduw_code(cpu_single_env, pc) << 32;
+    opc |= (uint64_t)(uint32_t)cpu_ldl_code(cpu_single_env, pc + 2);
     return opc;
 }
 
@@ -1263,7 +1263,7 @@ static void gen_op_mvc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
         /* Fall back to helper */
         vl = tcg_const_i32(l);
         potential_page_fault(s);
-        gen_helper_mvc(vl, s1, s2);
+        gen_helper_mvc(cpu_env, vl, s1, s2);
         tcg_temp_free_i32(vl);
         return;
     }
@@ -1455,7 +1455,7 @@ static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
 
     potential_page_fault(s);
     vl = tcg_const_i32(l);
-    gen_helper_clc(cc_op, vl, s1, s2);
+    gen_helper_clc(cc_op, cpu_env, vl, s1, s2);
     tcg_temp_free_i32(vl);
     set_cc_static(s);
 }
@@ -2094,7 +2094,7 @@ do_mh:
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_stcmh(tmp32_1, tmp, tmp32_2);
+        gen_helper_stcmh(cpu_env, tmp32_1, tmp, tmp32_2);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -2107,7 +2107,7 @@ do_mh:
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_lctlg(tmp32_1, tmp, tmp32_2);
+        gen_helper_lctlg(cpu_env, tmp32_1, tmp, tmp32_2);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -2119,7 +2119,7 @@ do_mh:
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_stctg(tmp32_1, tmp, tmp32_2);
+        gen_helper_stctg(cpu_env, tmp32_1, tmp, tmp32_2);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -2131,7 +2131,7 @@ do_mh:
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
         /* XXX rewrite in tcg */
-        gen_helper_csg(cc_op, tmp32_1, tmp, tmp32_2);
+        gen_helper_csg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
@@ -2143,7 +2143,7 @@ do_mh:
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
         /* XXX rewrite in tcg */
-        gen_helper_cdsg(cc_op, tmp32_1, tmp, tmp32_2);
+        gen_helper_cdsg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
@@ -2183,7 +2183,7 @@ do_mh:
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
         /* XXX split CC calculation out */
-        gen_helper_icmh(cc_op, tmp32_1, tmp, tmp32_2);
+        gen_helper_icmh(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
@@ -2635,7 +2635,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r2);
         potential_page_fault(s);
-        gen_helper_cksm(tmp32_1, tmp32_2);
+        gen_helper_cksm(cpu_env, tmp32_1, tmp32_2);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         gen_op_movi_cc(s, 0);
@@ -2664,7 +2664,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         tmp2 = load_reg(r1);
         tmp3 = load_reg(r2);
         potential_page_fault(s);
-        gen_helper_mvpg(tmp, tmp2, tmp3);
+        gen_helper_mvpg(cpu_env, tmp, tmp2, tmp3);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i64(tmp3);
@@ -2676,7 +2676,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         tmp32_2 = tcg_const_i32(r1);
         tmp32_3 = tcg_const_i32(r2);
         potential_page_fault(s);
-        gen_helper_mvst(tmp32_1, tmp32_2, tmp32_3);
+        gen_helper_mvst(cpu_env, tmp32_1, tmp32_2, tmp32_3);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         tcg_temp_free_i32(tmp32_3);
@@ -2687,7 +2687,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         tmp32_2 = tcg_const_i32(r1);
         tmp32_3 = tcg_const_i32(r2);
         potential_page_fault(s);
-        gen_helper_clst(cc_op, tmp32_1, tmp32_2, tmp32_3);
+        gen_helper_clst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
         set_cc_static(s);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -2698,7 +2698,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         tmp32_2 = tcg_const_i32(r1);
         tmp32_3 = tcg_const_i32(r2);
         potential_page_fault(s);
-        gen_helper_srst(cc_op, tmp32_1, tmp32_2, tmp32_3);
+        gen_helper_srst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
         set_cc_static(s);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -2785,7 +2785,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
     case 0x0d: /* PTLB                [S] */
         /* Purge TLB */
         check_privileged(s, ilc);
-        gen_helper_ptlb();
+        gen_helper_ptlb(cpu_env);
         break;
     case 0x10: /* SPX      D2(B2)     [S] */
         /* Set Prefix Register */
@@ -2828,7 +2828,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         r2 = insn & 0xf;
         tmp = load_reg(r1);
         tmp2 = load_reg(r2);
-        gen_helper_ipte(tmp, tmp2);
+        gen_helper_ipte(cpu_env, tmp, tmp2);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
@@ -2839,7 +2839,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         r2 = insn & 0xf;
         tmp = load_reg(r2);
         tmp2 = tcg_temp_new_i64();
-        gen_helper_iske(tmp2, tmp);
+        gen_helper_iske(tmp2, cpu_env, tmp);
         store_reg(r1, tmp2);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
@@ -2851,7 +2851,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         r2 = insn & 0xf;
         tmp32_1 = load_reg32(r1);
         tmp = load_reg(r2);
-        gen_helper_rrbe(cc_op, tmp32_1, tmp);
+        gen_helper_rrbe(cc_op, cpu_env, tmp32_1, tmp);
         set_cc_static(s);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp);
@@ -2863,7 +2863,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         r2 = insn & 0xf;
         tmp32_1 = load_reg32(r1);
         tmp = load_reg(r2);
-        gen_helper_sske(tmp32_1, tmp);
+        gen_helper_sske(cpu_env, tmp32_1, tmp);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp);
         break;
@@ -2880,7 +2880,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         tmp32_1 = load_reg32(r1);
         tmp = load_reg(r2);
         potential_page_fault(s);
-        gen_helper_stura(tmp, tmp32_1);
+        gen_helper_stura(cpu_env, tmp, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp);
         break;
@@ -2891,7 +2891,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         r2 = insn & 0xf;
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r2);
-        gen_helper_csp(cc_op, tmp32_1, tmp32_2);
+        gen_helper_csp(cc_op, cpu_env, tmp32_1, tmp32_2);
         set_cc_static(s);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -3865,7 +3865,7 @@ static void disas_s390_insn(DisasContext *s)
     int ilc;
     int l1;
 
-    opc = ldub_code(s->pc);
+    opc = cpu_ldub_code(cpu_single_env, s->pc);
     LOG_DISAS("opc 0x%x\n", opc);
 
     ilc = get_ilc(opc);
@@ -3951,7 +3951,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r2);
         potential_page_fault(s);
-        gen_helper_mvcl(cc_op, tmp32_1, tmp32_2);
+        gen_helper_mvcl(cc_op, cpu_env, tmp32_1, tmp32_2);
         set_cc_static(s);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -4165,7 +4165,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp3 = tcg_const_i64(s->pc + 4);
         update_psw_addr(s);
         gen_op_calc_cc(s);
-        gen_helper_ex(cc_op, cc_op, tmp2, tmp, tmp3);
+        gen_helper_ex(cc_op, cpu_env, cc_op, tmp2, tmp, tmp3);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
@@ -4694,7 +4694,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_lam(tmp32_1, tmp, tmp32_2);
+        gen_helper_lam(cpu_env, tmp32_1, tmp, tmp32_2);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -4706,7 +4706,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_stam(tmp32_1, tmp, tmp32_2);
+        gen_helper_stam(cpu_env, tmp32_1, tmp, tmp32_2);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -4732,7 +4732,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_mvcle(cc_op, tmp32_1, tmp, tmp32_2);
+        gen_helper_mvcle(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
@@ -4745,7 +4745,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_clcle(cc_op, tmp32_1, tmp, tmp32_2);
+        gen_helper_clcle(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
@@ -4789,7 +4789,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
         tmp32_1 = tcg_const_i32(r1);
         potential_page_fault(s);
-        gen_helper_lra(cc_op, tmp, tmp32_1);
+        gen_helper_lra(cc_op, cpu_env, tmp, tmp32_1);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
@@ -4835,7 +4835,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_stctl(tmp32_1, tmp, tmp32_2);
+        gen_helper_stctl(cpu_env, tmp32_1, tmp, tmp32_2);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -4849,7 +4849,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_lctl(tmp32_1, tmp, tmp32_2);
+        gen_helper_lctl(cpu_env, tmp32_1, tmp, tmp32_2);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -4869,7 +4869,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_cs(cc_op, tmp32_1, tmp, tmp32_2);
+        gen_helper_cs(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
@@ -4882,7 +4882,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_1 = load_reg32(r1);
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_clm(cc_op, tmp32_1, tmp32_2, tmp);
+        gen_helper_clm(cc_op, cpu_env, tmp32_1, tmp32_2, tmp);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
@@ -4895,7 +4895,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_1 = load_reg32(r1);
         tmp32_2 = tcg_const_i32(r3);
         potential_page_fault(s);
-        gen_helper_stcm(tmp32_1, tmp32_2, tmp);
+        gen_helper_stcm(cpu_env, tmp32_1, tmp32_2, tmp);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -4992,7 +4992,7 @@ static void disas_s390_insn(DisasContext *s)
             break;
         case 0xd4:
             potential_page_fault(s);
-            gen_helper_nc(cc_op, vl, tmp, tmp2);
+            gen_helper_nc(cc_op, cpu_env, vl, tmp, tmp2);
             set_cc_static(s);
             break;
         case 0xd5:
@@ -5000,22 +5000,22 @@ static void disas_s390_insn(DisasContext *s)
             break;
         case 0xd6:
             potential_page_fault(s);
-            gen_helper_oc(cc_op, vl, tmp, tmp2);
+            gen_helper_oc(cc_op, cpu_env, vl, tmp, tmp2);
             set_cc_static(s);
             break;
         case 0xd7:
             potential_page_fault(s);
-            gen_helper_xc(cc_op, vl, tmp, tmp2);
+            gen_helper_xc(cc_op, cpu_env, vl, tmp, tmp2);
             set_cc_static(s);
             break;
         case 0xdc:
             potential_page_fault(s);
-            gen_helper_tr(vl, tmp, tmp2);
+            gen_helper_tr(cpu_env, vl, tmp, tmp2);
             set_cc_static(s);
             break;
         case 0xf3:
             potential_page_fault(s);
-            gen_helper_unpk(vl, tmp, tmp2);
+            gen_helper_unpk(cpu_env, vl, tmp, tmp2);
             break;
         default:
             tcg_abort();
@@ -5040,9 +5040,9 @@ static void disas_s390_insn(DisasContext *s)
         tmp2 = get_address(s, 0, b1, d1);
         tmp3 = get_address(s, 0, b2, d2);
         if (opc == 0xda) {
-            gen_helper_mvcp(cc_op, tmp, tmp2, tmp3);
+            gen_helper_mvcp(cc_op, cpu_env, tmp, tmp2, tmp3);
         } else {
-            gen_helper_mvcs(cc_op, tmp, tmp2, tmp3);
+            gen_helper_mvcs(cc_op, cpu_env, tmp, tmp2, tmp3);
         }
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
commit 089f5c06926105a35df461003ae32b7387ed4236
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 2 07:33:39 2012 +0000

    target-s390x: avoid AREG0 for misc helpers
    
    Make misc helpers take a parameter for CPUState instead
    of relying on global env.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    [agraf: fix conflict]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 736cf33..156d946 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -4,4 +4,3 @@ obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
 
 $(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
-$(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 876b88e..f4e0b37 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -1,6 +1,6 @@
 #include "def-helper.h"
 
-DEF_HELPER_1(exception, void, i32)
+DEF_HELPER_2(exception, void, env, i32)
 DEF_HELPER_3(nc, i32, i32, i64, i64)
 DEF_HELPER_3(oc, i32, i32, i64, i64)
 DEF_HELPER_3(xc, i32, i32, i64, i64)
@@ -113,20 +113,20 @@ DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32)
 DEF_HELPER_3(unpk, void, i32, i64, i64)
 DEF_HELPER_3(tr, void, i32, i64, i64)
 
-DEF_HELPER_2(servc, i32, i32, i64)
-DEF_HELPER_3(diag, i64, i32, i64, i64)
+DEF_HELPER_3(servc, i32, env, i32, i64)
+DEF_HELPER_4(diag, i64, env, i32, i64, i64)
 DEF_HELPER_3(load_psw, void, env, i64, i64)
 DEF_HELPER_1(program_interrupt, void, i32)
-DEF_HELPER_FLAGS_1(stidp, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(spx, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_2(stidp, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_FLAGS_2(spx, TCG_CALL_CONST, void, env, i64)
 DEF_HELPER_FLAGS_1(sck, TCG_CALL_CONST, i32, i64)
-DEF_HELPER_1(stck, i32, i64)
-DEF_HELPER_1(stcke, i32, i64)
-DEF_HELPER_FLAGS_1(sckc, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(stckc, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(spt, TCG_CALL_CONST, void, i64)
-DEF_HELPER_FLAGS_1(stpt, TCG_CALL_CONST, void, i64)
-DEF_HELPER_3(stsi, i32, i64, i32, i32)
+DEF_HELPER_2(stck, i32, env, i64)
+DEF_HELPER_2(stcke, i32, env, i64)
+DEF_HELPER_FLAGS_2(sckc, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_FLAGS_2(stckc, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_FLAGS_2(spt, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_FLAGS_2(stpt, TCG_CALL_CONST, void, env, i64)
+DEF_HELPER_4(stsi, i32, env, i64, i32, i32)
 DEF_HELPER_3(lctl, void, i32, i64, i32)
 DEF_HELPER_3(lctlg, void, i32, i64, i32)
 DEF_HELPER_3(stctl, void, i32, i64, i32)
@@ -138,7 +138,7 @@ DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_CONST, i32, i32, i64)
 DEF_HELPER_2(csp, i32, i32, i32)
 DEF_HELPER_3(mvcs, i32, i64, i64, i64)
 DEF_HELPER_3(mvcp, i32, i64, i64, i64)
-DEF_HELPER_3(sigp, i32, i64, i32, i64)
+DEF_HELPER_4(sigp, i32, env, i64, i32, i64)
 DEF_HELPER_2(sacf, void, env, i64)
 DEF_HELPER_FLAGS_2(ipte, TCG_CALL_CONST, void, i64, i64)
 DEF_HELPER_FLAGS_0(ptlb, TCG_CALL_CONST, void)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 3f8b3ba..52f2602 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -595,7 +595,7 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
         env->psw.addr = ret - 4;
         env->int_svc_code = (insn | v1) & 0xff;
         env->int_svc_ilc = 4;
-        helper_exception(EXCP_SVC);
+        helper_exception(env, EXCP_SVC);
     } else if ((insn & 0xff00) == 0xbf00) {
         uint32_t insn2, r1, r3, b2, d2;
 
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 1d5137f..ced26c6 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -21,7 +21,6 @@
 #include "cpu.h"
 #include "memory.h"
 #include "cputlb.h"
-#include "dyngen-exec.h"
 #include "host-utils.h"
 #include "helper.h"
 #include <string.h>
@@ -32,7 +31,10 @@
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
+/* temporarily disabled due to wrapper use */
+#if 0
 #include "softmmu_exec.h"
+#endif
 #include "sysemu.h"
 #endif
 
@@ -44,7 +46,7 @@
 #endif
 
 /* raise an exception */
-void HELPER(exception)(uint32_t excp)
+void HELPER(exception)(CPUS390XState *env, uint32_t excp)
 {
     HELPER_LOG("%s: exception %d\n", __func__, excp);
     env->exception_index = excp;
@@ -112,7 +114,7 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
 }
 
 /* SCLP service call */
-uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
+uint32_t HELPER(servc)(CPUS390XState *env, uint32_t r1, uint64_t r2)
 {
     int r;
 
@@ -125,7 +127,8 @@ uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
 }
 
 /* DIAG */
-uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
+uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem,
+                      uint64_t code)
 {
     uint64_t r;
 
@@ -155,17 +158,17 @@ uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
 }
 
 /* Store CPU ID */
-void HELPER(stidp)(uint64_t a1)
+void HELPER(stidp)(CPUS390XState *env, uint64_t a1)
 {
-    stq(a1, env->cpu_num);
+    cpu_stq_data(env, a1, env->cpu_num);
 }
 
 /* Set Prefix */
-void HELPER(spx)(uint64_t a1)
+void HELPER(spx)(CPUS390XState *env, uint64_t a1)
 {
     uint32_t prefix;
 
-    prefix = ldl(a1);
+    prefix = cpu_ldl_data(env, a1);
     env->psa = prefix & 0xfffff000;
     qemu_log("prefix: %#x\n", prefix);
     tlb_flush_page(env, 0);
@@ -191,31 +194,31 @@ static inline uint64_t clock_value(CPUS390XState *env)
 }
 
 /* Store Clock */
-uint32_t HELPER(stck)(uint64_t a1)
+uint32_t HELPER(stck)(CPUS390XState *env, uint64_t a1)
 {
-    stq(a1, clock_value(env));
+    cpu_stq_data(env, a1, clock_value(env));
 
     return 0;
 }
 
 /* Store Clock Extended */
-uint32_t HELPER(stcke)(uint64_t a1)
+uint32_t HELPER(stcke)(CPUS390XState *env, uint64_t a1)
 {
-    stb(a1, 0);
+    cpu_stb_data(env, a1, 0);
     /* basically the same value as stck */
-    stq(a1 + 1, clock_value(env) | env->cpu_num);
+    cpu_stq_data(env, a1 + 1, clock_value(env) | env->cpu_num);
     /* more fine grained than stck */
-    stq(a1 + 9, 0);
+    cpu_stq_data(env, a1 + 9, 0);
     /* XXX programmable fields */
-    stw(a1 + 17, 0);
+    cpu_stw_data(env, a1 + 17, 0);
 
     return 0;
 }
 
 /* Set Clock Comparator */
-void HELPER(sckc)(uint64_t a1)
+void HELPER(sckc)(CPUS390XState *env, uint64_t a1)
 {
-    uint64_t time = ldq(a1);
+    uint64_t time = cpu_ldq_data(env, a1);
 
     if (time == -1ULL) {
         return;
@@ -230,16 +233,16 @@ void HELPER(sckc)(uint64_t a1)
 }
 
 /* Store Clock Comparator */
-void HELPER(stckc)(uint64_t a1)
+void HELPER(stckc)(CPUS390XState *env, uint64_t a1)
 {
     /* XXX implement */
-    stq(a1, 0);
+    cpu_stq_data(env, a1, 0);
 }
 
 /* Set CPU Timer */
-void HELPER(spt)(uint64_t a1)
+void HELPER(spt)(CPUS390XState *env, uint64_t a1)
 {
-    uint64_t time = ldq(a1);
+    uint64_t time = cpu_ldq_data(env, a1);
 
     if (time == -1ULL) {
         return;
@@ -252,14 +255,15 @@ void HELPER(spt)(uint64_t a1)
 }
 
 /* Store CPU Timer */
-void HELPER(stpt)(uint64_t a1)
+void HELPER(stpt)(CPUS390XState *env, uint64_t a1)
 {
     /* XXX implement */
-    stq(a1, 0);
+    cpu_stq_data(env, a1, 0);
 }
 
 /* Store System Information */
-uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
+uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, uint32_t r0,
+                      uint32_t r1)
 {
     int cc = 0;
     int sel1, sel2;
@@ -384,7 +388,8 @@ uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
     return cc;
 }
 
-uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
+uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1,
+                      uint64_t cpu_addr)
 {
     int cc = 0;
 
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1d87272..0c61e63 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -312,7 +312,7 @@ static inline void gen_debug(DisasContext *s)
     TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
     update_psw_addr(s);
     gen_op_calc_cc(s);
-    gen_helper_exception(tmp);
+    gen_helper_exception(cpu_env, tmp);
     tcg_temp_free_i32(tmp);
     s->is_jmp = DISAS_EXCP;
 }
@@ -324,7 +324,7 @@ static void gen_illegal_opcode(DisasContext *s, int ilc)
     TCGv_i32 tmp = tcg_const_i32(EXCP_SPEC);
     update_psw_addr(s);
     gen_op_calc_cc(s);
-    gen_helper_exception(tmp);
+    gen_helper_exception(cpu_env, tmp);
     tcg_temp_free_i32(tmp);
     s->is_jmp = DISAS_EXCP;
 }
@@ -377,7 +377,7 @@ static void gen_program_exception(DisasContext *s, int ilc, int code)
 
     /* trigger exception */
     tmp = tcg_const_i32(EXCP_PGM);
-    gen_helper_exception(tmp);
+    gen_helper_exception(cpu_env, tmp);
     tcg_temp_free_i32(tmp);
 
     /* end TB here */
@@ -2712,7 +2712,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
-        gen_helper_stidp(tmp);
+        gen_helper_stidp(cpu_env, tmp);
         tcg_temp_free_i64(tmp);
         break;
     case 0x04: /* SCK       D2(B2)     [S] */
@@ -2730,7 +2730,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
-        gen_helper_stck(cc_op, tmp);
+        gen_helper_stck(cc_op, cpu_env, tmp);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         break;
@@ -2740,7 +2740,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
-        gen_helper_sckc(tmp);
+        gen_helper_sckc(cpu_env, tmp);
         tcg_temp_free_i64(tmp);
         break;
     case 0x07: /* STCKC    D2(B2)     [S] */
@@ -2749,7 +2749,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
-        gen_helper_stckc(tmp);
+        gen_helper_stckc(cpu_env, tmp);
         tcg_temp_free_i64(tmp);
         break;
     case 0x08: /* SPT      D2(B2)     [S] */
@@ -2758,7 +2758,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
-        gen_helper_spt(tmp);
+        gen_helper_spt(cpu_env, tmp);
         tcg_temp_free_i64(tmp);
         break;
     case 0x09: /* STPT     D2(B2)     [S] */
@@ -2767,7 +2767,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
-        gen_helper_stpt(tmp);
+        gen_helper_stpt(cpu_env, tmp);
         tcg_temp_free_i64(tmp);
         break;
     case 0x0a: /* SPKA     D2(B2)     [S] */
@@ -2793,7 +2793,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
-        gen_helper_spx(tmp);
+        gen_helper_spx(cpu_env, tmp);
         tcg_temp_free_i64(tmp);
         break;
     case 0x11: /* STPX     D2(B2)     [S] */
@@ -2906,7 +2906,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
-        gen_helper_stcke(cc_op, tmp);
+        gen_helper_stcke(cc_op, cpu_env, tmp);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         break;
@@ -2930,7 +2930,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         tmp32_1 = load_reg32(0);
         tmp32_2 = load_reg32(1);
         potential_page_fault(s);
-        gen_helper_stsi(cc_op, tmp, tmp32_1, tmp32_2);
+        gen_helper_stsi(cc_op, cpu_env, tmp, tmp32_1, tmp32_2);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
@@ -2980,7 +2980,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         potential_page_fault(s);
         tmp32_1 = load_reg32(r2);
         tmp = load_reg(r1);
-        gen_helper_servc(cc_op, tmp32_1, tmp);
+        gen_helper_servc(cc_op, cpu_env, tmp32_1, tmp);
         set_cc_static(s);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp);
@@ -3926,7 +3926,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_3 = tcg_const_i32(EXCP_SVC);
         tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, int_svc_code));
         tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilc));
-        gen_helper_exception(tmp32_3);
+        gen_helper_exception(cpu_env, tmp32_3);
         s->is_jmp = DISAS_EXCP;
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -4543,7 +4543,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp32_1 = tcg_const_i32(insn & 0xfff);
         tmp2 = load_reg(2);
         tmp3 = load_reg(1);
-        gen_helper_diag(tmp2, tmp32_1, tmp2, tmp3);
+        gen_helper_diag(tmp2, cpu_env, tmp32_1, tmp2, tmp3);
         store_reg(2, tmp2);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp2);
@@ -4777,7 +4777,7 @@ static void disas_s390_insn(DisasContext *s)
         tmp2 = load_reg(r3);
         tmp32_1 = tcg_const_i32(r1);
         potential_page_fault(s);
-        gen_helper_sigp(cc_op, tmp, tmp32_1, tmp2);
+        gen_helper_sigp(cc_op, cpu_env, tmp, tmp32_1, tmp2);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
commit 932385a367b2c67f1ea7148dcafb013db188cd23
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 2 07:33:38 2012 +0000

    target-s390x: avoid AREG0 for condition code helpers
    
    Make condition code helpers take a parameter for CPUState instead
    of relying on global env.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 7b2c5c1..736cf33 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -3,6 +3,5 @@ obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
 
-$(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 9c3a2c4..19ef145 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -19,7 +19,6 @@
  */
 
 #include "cpu.h"
-#include "dyngen-exec.h"
 #include "helper.h"
 
 /* #define DEBUG_HELPER */
@@ -500,14 +499,14 @@ uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
     return do_calc_cc(env, cc_op, src, dst, vr);
 }
 
-uint32_t HELPER(calc_cc)(uint32_t cc_op, uint64_t src, uint64_t dst,
-                         uint64_t vr)
+uint32_t HELPER(calc_cc)(CPUS390XState *env, uint32_t cc_op, uint64_t src,
+                         uint64_t dst, uint64_t vr)
 {
     return do_calc_cc(env, cc_op, src, dst, vr);
 }
 
 /* insert psw mask and condition code into r1 */
-void HELPER(ipm)(uint32_t cc, uint32_t r1)
+void HELPER(ipm)(CPUS390XState *env, uint32_t cc, uint32_t r1)
 {
     uint64_t r = env->regs[r1];
 
@@ -519,13 +518,13 @@ void HELPER(ipm)(uint32_t cc, uint32_t r1)
 }
 
 #ifndef CONFIG_USER_ONLY
-void HELPER(load_psw)(uint64_t mask, uint64_t addr)
+void HELPER(load_psw)(CPUS390XState *env, uint64_t mask, uint64_t addr)
 {
     load_psw(env, mask, addr);
     cpu_loop_exit(env);
 }
 
-void HELPER(sacf)(uint64_t a1)
+void HELPER(sacf)(CPUS390XState *env, uint64_t a1)
 {
     HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1);
 
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index c03cd59..876b88e 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -36,7 +36,7 @@ DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_PURE|TCG_CALL_CONST, i64, s64)
 DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64)
 DEF_HELPER_3(stcmh, void, i32, i64, i32)
 DEF_HELPER_3(icmh, i32, i32, i64, i32)
-DEF_HELPER_2(ipm, void, i32, i32)
+DEF_HELPER_3(ipm, void, env, i32, i32)
 DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32)
 DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
 DEF_HELPER_3(stam, void, i32, i64, i32)
@@ -115,7 +115,7 @@ DEF_HELPER_3(tr, void, i32, i64, i64)
 
 DEF_HELPER_2(servc, i32, i32, i64)
 DEF_HELPER_3(diag, i64, i32, i64, i64)
-DEF_HELPER_2(load_psw, void, i64, i64)
+DEF_HELPER_3(load_psw, void, env, i64, i64)
 DEF_HELPER_1(program_interrupt, void, i32)
 DEF_HELPER_FLAGS_1(stidp, TCG_CALL_CONST, void, i64)
 DEF_HELPER_FLAGS_1(spx, TCG_CALL_CONST, void, i64)
@@ -139,14 +139,14 @@ DEF_HELPER_2(csp, i32, i32, i32)
 DEF_HELPER_3(mvcs, i32, i64, i64, i64)
 DEF_HELPER_3(mvcp, i32, i64, i64, i64)
 DEF_HELPER_3(sigp, i32, i64, i32, i64)
-DEF_HELPER_1(sacf, void, i64)
+DEF_HELPER_2(sacf, void, env, i64)
 DEF_HELPER_FLAGS_2(ipte, TCG_CALL_CONST, void, i64, i64)
 DEF_HELPER_FLAGS_0(ptlb, TCG_CALL_CONST, void)
 DEF_HELPER_2(lra, i32, i64, i32)
 DEF_HELPER_2(stura, void, i64, i32)
 DEF_HELPER_2(cksm, void, i32, i32)
 
-DEF_HELPER_FLAGS_4(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
-                   i32, i32, i64, i64, i64)
+DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
+                   i32, env, i32, i64, i64, i64)
 
 #include "def-helper.h"
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2a61e92..1d87272 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -722,7 +722,7 @@ static void gen_op_calc_cc(DisasContext *s)
     case CC_OP_NZ_F32:
     case CC_OP_NZ_F64:
         /* 1 argument */
-        gen_helper_calc_cc(cc_op, local_cc_op, dummy, cc_dst, dummy);
+        gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
         break;
     case CC_OP_ICM:
     case CC_OP_LTGT_32:
@@ -735,7 +735,7 @@ static void gen_op_calc_cc(DisasContext *s)
     case CC_OP_LTGT_F64:
     case CC_OP_SLAG:
         /* 2 arguments */
-        gen_helper_calc_cc(cc_op, local_cc_op, cc_src, cc_dst, dummy);
+        gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
         break;
     case CC_OP_ADD_64:
     case CC_OP_ADDU_64:
@@ -746,11 +746,11 @@ static void gen_op_calc_cc(DisasContext *s)
     case CC_OP_SUB_32:
     case CC_OP_SUBU_32:
         /* 3 arguments */
-        gen_helper_calc_cc(cc_op, local_cc_op, cc_src, cc_dst, cc_vr);
+        gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, cc_vr);
         break;
     case CC_OP_DYNAMIC:
         /* unknown operation - assume 3 arguments and cc_op in env */
-        gen_helper_calc_cc(cc_op, cc_op, cc_src, cc_dst, cc_vr);
+        gen_helper_calc_cc(cc_op, cpu_env, cc_op, cc_src, cc_dst, cc_vr);
         break;
     default:
         tcg_abort();
@@ -2628,7 +2628,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
     case 0x22: /* IPM    R1               [RRE] */
         tmp32_1 = tcg_const_i32(r1);
         gen_op_calc_cc(s);
-        gen_helper_ipm(cc_op, tmp32_1);
+        gen_helper_ipm(cpu_env, cc_op, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
     case 0x41: /* CKSM    R1,R2     [RRE] */
@@ -2916,7 +2916,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
-        gen_helper_sacf(tmp);
+        gen_helper_sacf(cpu_env, tmp);
         tcg_temp_free_i64(tmp);
         /* addressing mode has changed, so end the block */
         s->pc += ilc * 2;
@@ -2967,7 +2967,7 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
         tcg_gen_addi_i64(tmp, tmp, 8);
         tcg_gen_qemu_ld64(tmp3, tmp, get_mem_index(s));
-        gen_helper_load_psw(tmp2, tmp3);
+        gen_helper_load_psw(cpu_env, tmp2, tmp3);
         /* we need to keep cc_op intact */
         s->is_jmp = DISAS_JUMP;
         tcg_temp_free_i64(tmp);
@@ -4527,7 +4527,7 @@ static void disas_s390_insn(DisasContext *s)
         tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
         tcg_gen_addi_i64(tmp, tmp, 4);
         tcg_gen_qemu_ld32u(tmp3, tmp, get_mem_index(s));
-        gen_helper_load_psw(tmp2, tmp3);
+        gen_helper_load_psw(cpu_env, tmp2, tmp3);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i64(tmp3);
commit 4fda26a7b0d6ffbb4055ab8b756cd94647f5fd22
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 2 07:33:37 2012 +0000

    target-s390x: avoid AREG0 for integer helpers
    
    Make integer helpers take a parameter for CPUState instead
    of relying on global env.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 7d965e9..7b2c5c1 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -3,7 +3,6 @@ obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
 
-$(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index af98773..c03cd59 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -12,8 +12,8 @@ DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64)
 DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32)
 DEF_HELPER_3(clm, i32, i32, i32, i64)
 DEF_HELPER_3(stcm, void, i32, i32, i64)
-DEF_HELPER_2(mlg, void, i32, i64)
-DEF_HELPER_2(dlg, void, i32, i64)
+DEF_HELPER_3(mlg, void, env, i32, i64)
+DEF_HELPER_3(dlg, void, env, i32, i64)
 DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64)
 DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32)
@@ -43,8 +43,8 @@ DEF_HELPER_3(stam, void, i32, i64, i32)
 DEF_HELPER_3(lam, void, i32, i64, i32)
 DEF_HELPER_3(mvcle, i32, i32, i64, i32)
 DEF_HELPER_3(clcle, i32, i32, i64, i32)
-DEF_HELPER_3(slb, i32, i32, i32, i32)
-DEF_HELPER_4(slbg, i32, i32, i32, i64, i64)
+DEF_HELPER_4(slb, i32, env, i32, i32, i32)
+DEF_HELPER_5(slbg, i32, env, i32, i32, i64, i64)
 DEF_HELPER_3(cefbr, void, env, i32, s32)
 DEF_HELPER_3(cdfbr, void, env, i32, s32)
 DEF_HELPER_3(cxfbr, void, env, i32, s32)
@@ -107,7 +107,7 @@ DEF_HELPER_3(lxdb, void, env, i32, i64)
 DEF_HELPER_FLAGS_3(tceb, TCG_CALL_PURE, i32, env, i32, i64)
 DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_PURE, i32, env, i32, i64)
 DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64)
-DEF_HELPER_2(flogr, i32, i32, i64)
+DEF_HELPER_3(flogr, i32, env, i32, i64)
 DEF_HELPER_3(sqdbr, void, env, i32, i32)
 DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32)
 DEF_HELPER_3(unpk, void, i32, i64, i64)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index e2eeb07..f202a7e 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -19,7 +19,6 @@
  */
 
 #include "cpu.h"
-#include "dyngen-exec.h"
 #include "host-utils.h"
 #include "helper.h"
 
@@ -31,7 +30,7 @@
 #endif
 
 /* 64/64 -> 128 unsigned multiplication */
-void HELPER(mlg)(uint32_t r1, uint64_t v2)
+void HELPER(mlg)(CPUS390XState *env, uint32_t r1, uint64_t v2)
 {
 #if HOST_LONG_BITS == 64 && defined(__GNUC__)
     /* assuming 64-bit hosts have __uint128_t */
@@ -46,7 +45,7 @@ void HELPER(mlg)(uint32_t r1, uint64_t v2)
 }
 
 /* 128 -> 64/64 unsigned division */
-void HELPER(dlg)(uint32_t r1, uint64_t v2)
+void HELPER(dlg)(CPUS390XState *env, uint32_t r1, uint64_t v2)
 {
     uint64_t divisor = v2;
 
@@ -129,7 +128,7 @@ uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
 }
 
 /* subtract unsigned v2 from v1 with borrow */
-uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
+uint32_t HELPER(slb)(CPUS390XState *env, uint32_t cc, uint32_t r1, uint32_t v2)
 {
     uint32_t v1 = env->regs[r1];
     uint32_t res = v1 + (~v2) + (cc >> 1);
@@ -144,7 +143,8 @@ uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
 }
 
 /* subtract unsigned v2 from v1 with borrow */
-uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
+uint32_t HELPER(slbg)(CPUS390XState *env, uint32_t cc, uint32_t r1,
+                      uint64_t v1, uint64_t v2)
 {
     uint64_t res = v1 + (~v2) + (cc >> 1);
 
@@ -158,7 +158,7 @@ uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
 }
 
 /* find leftmost one */
-uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
+uint32_t HELPER(flogr)(CPUS390XState *env, uint32_t r1, uint64_t v2)
 {
     uint64_t res = 0;
     uint64_t ov2 = v2;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b1f2071..2a61e92 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1803,7 +1803,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
         tmp2 = tcg_temp_new_i64();
         tmp32_1 = tcg_const_i32(r1);
         tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-        gen_helper_mlg(tmp32_1, tmp2);
+        gen_helper_mlg(cpu_env, tmp32_1, tmp2);
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
@@ -1811,7 +1811,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
         tmp2 = tcg_temp_new_i64();
         tmp32_1 = tcg_const_i32(r1);
         tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-        gen_helper_dlg(tmp32_1, tmp2);
+        gen_helper_dlg(cpu_env, tmp32_1, tmp2);
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
@@ -1837,7 +1837,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
         tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
         /* XXX possible optimization point */
         gen_op_calc_cc(s);
-        gen_helper_slbg(cc_op, cc_op, tmp32_1, regs[r1], tmp2);
+        gen_helper_slbg(cc_op, cpu_env, cc_op, tmp32_1, regs[r1], tmp2);
         set_cc_static(s);
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
@@ -1917,7 +1917,7 @@ static void disas_e3(DisasContext* s, int op, int r1, int x2, int b2, int d2)
         tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
         /* XXX possible optimization point */
         gen_op_calc_cc(s);
-        gen_helper_slb(cc_op, cc_op, tmp32_1, tmp32_2);
+        gen_helper_slb(cc_op, cpu_env, cc_op, tmp32_1, tmp32_2);
         set_cc_static(s);
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
@@ -3535,7 +3535,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
     case 0x83: /* FLOGR R1,R2 [RRE] */
         tmp = load_reg(r2);
         tmp32_1 = tcg_const_i32(r1);
-        gen_helper_flogr(cc_op, tmp32_1, tmp);
+        gen_helper_flogr(cc_op, cpu_env, tmp32_1, tmp);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
@@ -3555,7 +3555,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
     case 0x87: /* DLGR      R1,R2     [RRE] */
         tmp32_1 = tcg_const_i32(r1);
         tmp = load_reg(r2);
-        gen_helper_dlg(tmp32_1, tmp);
+        gen_helper_dlg(cpu_env, tmp32_1, tmp);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         break;
@@ -3580,7 +3580,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
         tmp2 = load_reg(r2);
         tmp32_1 = tcg_const_i32(r1);
         gen_op_calc_cc(s);
-        gen_helper_slbg(cc_op, cc_op, tmp32_1, tmp, tmp2);
+        gen_helper_slbg(cc_op, cpu_env, cc_op, tmp32_1, tmp, tmp2);
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
@@ -3647,7 +3647,7 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2)
         tmp32_1 = load_reg32(r2);
         tmp32_2 = tcg_const_i32(r1);
         gen_op_calc_cc(s);
-        gen_helper_slb(cc_op, cc_op, tmp32_2, tmp32_1);
+        gen_helper_slb(cc_op, cpu_env, cc_op, tmp32_2, tmp32_1);
         set_cc_static(s);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
commit 449c0d70b6d5692bafd8b028e2a8a4e0ed7076fe
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 2 07:33:36 2012 +0000

    target-s390x: avoid AREG0 for FPU helpers
    
    Make FPU helpers take a parameter for CPUState instead
    of relying on global env.
    
    Introduce temporary wrappers for FPU load and store ops.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index a87d26f..7d965e9 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -4,7 +4,6 @@ obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
 
 $(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
-$(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 2ac1659..9c3a2c4 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -473,10 +473,10 @@ static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
         break;
 
     case CC_OP_LTGT_F32:
-        r = set_cc_f32(src, dst);
+        r = set_cc_f32(env, src, dst);
         break;
     case CC_OP_LTGT_F64:
-        r = set_cc_f64(src, dst);
+        r = set_cc_f64(env, src, dst);
         break;
     case CC_OP_NZ_F32:
         r = set_cc_nz_f32(dst);
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 0ccb551..9b7a2e3 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -1000,12 +1000,22 @@ static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb)
 }
 
 /* fpu_helper.c */
-uint32_t set_cc_f32(float32 v1, float32 v2);
-uint32_t set_cc_f64(float64 v1, float64 v2);
+uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2);
+uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2);
 uint32_t set_cc_nz_f32(float32 v);
 uint32_t set_cc_nz_f64(float64 v);
 
 /* misc_helper.c */
 void program_interrupt(CPUS390XState *env, uint32_t code, int ilc);
 
+/* temporary wrappers */
+uint32_t cpu_ldub_data(CPUS390XState *env, target_ulong ptr);
+uint32_t cpu_lduw_data(CPUS390XState *env, target_ulong ptr);
+uint32_t cpu_ldl_data(CPUS390XState *env, target_ulong ptr);
+uint64_t cpu_ldq_data(CPUS390XState *env, target_ulong ptr);
+
+void cpu_stb_data(CPUS390XState *env, target_ulong ptr, uint32_t data);
+void cpu_stw_data(CPUS390XState *env, target_ulong ptr, uint32_t data);
+void cpu_stl_data(CPUS390XState *env, target_ulong ptr, uint32_t data);
+void cpu_stq_data(CPUS390XState *env, target_ulong ptr, uint64_t data);
 #endif
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 1389052..e235419 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -19,10 +19,10 @@
  */
 
 #include "cpu.h"
-#include "dyngen-exec.h"
 #include "helper.h"
 
-#if !defined(CONFIG_USER_ONLY)
+/* temporarily disabled due to wrapper use */
+#if 0 && !defined(CONFIG_USER_ONLY)
 #include "softmmu_exec.h"
 #endif
 
@@ -33,7 +33,7 @@
 #define HELPER_LOG(x...)
 #endif
 
-static inline int float_comp_to_cc(int float_compare)
+static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
 {
     switch (float_compare) {
     case float_relation_equal:
@@ -50,14 +50,16 @@ static inline int float_comp_to_cc(int float_compare)
 }
 
 /* condition codes for binary FP ops */
-uint32_t set_cc_f32(float32 v1, float32 v2)
+uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2)
 {
-    return float_comp_to_cc(float32_compare_quiet(v1, v2, &env->fpu_status));
+    return float_comp_to_cc(env, float32_compare_quiet(v1, v2,
+                                                       &env->fpu_status));
 }
 
-uint32_t set_cc_f64(float64 v1, float64 v2)
+uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2)
 {
-    return float_comp_to_cc(float64_compare_quiet(v1, v2, &env->fpu_status));
+    return float_comp_to_cc(env, float64_compare_quiet(v1, v2,
+                                                       &env->fpu_status));
 }
 
 /* condition codes for unary FP ops */
@@ -101,14 +103,14 @@ static uint32_t set_cc_nz_f128(float128 v)
 }
 
 /* convert 32-bit int to 64-bit float */
-void HELPER(cdfbr)(uint32_t f1, int32_t v2)
+void HELPER(cdfbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
 {
     HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1);
     env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status);
 }
 
 /* convert 32-bit int to 128-bit float */
-void HELPER(cxfbr)(uint32_t f1, int32_t v2)
+void HELPER(cxfbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
 {
     CPU_QuadU v1;
 
@@ -118,21 +120,21 @@ void HELPER(cxfbr)(uint32_t f1, int32_t v2)
 }
 
 /* convert 64-bit int to 32-bit float */
-void HELPER(cegbr)(uint32_t f1, int64_t v2)
+void HELPER(cegbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
 {
     HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
     env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status);
 }
 
 /* convert 64-bit int to 64-bit float */
-void HELPER(cdgbr)(uint32_t f1, int64_t v2)
+void HELPER(cdgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
 {
     HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
     env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status);
 }
 
 /* convert 64-bit int to 128-bit float */
-void HELPER(cxgbr)(uint32_t f1, int64_t v2)
+void HELPER(cxgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
 {
     CPU_QuadU x1;
 
@@ -144,7 +146,7 @@ void HELPER(cxgbr)(uint32_t f1, int64_t v2)
 }
 
 /* convert 32-bit int to 32-bit float */
-void HELPER(cefbr)(uint32_t f1, int32_t v2)
+void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
 {
     env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
     HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2,
@@ -152,7 +154,7 @@ void HELPER(cefbr)(uint32_t f1, int32_t v2)
 }
 
 /* 32-bit FP addition RR */
-uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(aebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
                                          env->fregs[f2].l.upper,
@@ -164,7 +166,7 @@ uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2)
 }
 
 /* 64-bit FP addition RR */
-uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(adbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d,
                                    &env->fpu_status);
@@ -175,7 +177,7 @@ uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2)
 }
 
 /* 32-bit FP subtraction RR */
-uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(sebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
                                          env->fregs[f2].l.upper,
@@ -187,7 +189,7 @@ uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2)
 }
 
 /* 64-bit FP subtraction RR */
-uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(sdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
                                    &env->fpu_status);
@@ -198,7 +200,7 @@ uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2)
 }
 
 /* 32-bit FP division RR */
-void HELPER(debr)(uint32_t f1, uint32_t f2)
+void HELPER(debr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper,
                                          env->fregs[f2].l.upper,
@@ -206,7 +208,7 @@ void HELPER(debr)(uint32_t f1, uint32_t f2)
 }
 
 /* 128-bit FP division RR */
-void HELPER(dxbr)(uint32_t f1, uint32_t f2)
+void HELPER(dxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     CPU_QuadU v1;
     CPU_QuadU v2;
@@ -222,14 +224,14 @@ void HELPER(dxbr)(uint32_t f1, uint32_t f2)
 }
 
 /* 64-bit FP multiplication RR */
-void HELPER(mdbr)(uint32_t f1, uint32_t f2)
+void HELPER(mdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d,
                                    &env->fpu_status);
 }
 
 /* 128-bit FP multiplication RR */
-void HELPER(mxbr)(uint32_t f1, uint32_t f2)
+void HELPER(mxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     CPU_QuadU v1;
     CPU_QuadU v2;
@@ -245,14 +247,14 @@ void HELPER(mxbr)(uint32_t f1, uint32_t f2)
 }
 
 /* convert 32-bit float to 64-bit float */
-void HELPER(ldebr)(uint32_t r1, uint32_t r2)
+void HELPER(ldebr)(CPUS390XState *env, uint32_t r1, uint32_t r2)
 {
     env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper,
                                           &env->fpu_status);
 }
 
 /* convert 128-bit float to 64-bit float */
-void HELPER(ldxbr)(uint32_t f1, uint32_t f2)
+void HELPER(ldxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     CPU_QuadU x2;
 
@@ -263,7 +265,7 @@ void HELPER(ldxbr)(uint32_t f1, uint32_t f2)
 }
 
 /* convert 64-bit float to 128-bit float */
-void HELPER(lxdbr)(uint32_t f1, uint32_t f2)
+void HELPER(lxdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     CPU_QuadU res;
 
@@ -273,7 +275,7 @@ void HELPER(lxdbr)(uint32_t f1, uint32_t f2)
 }
 
 /* convert 64-bit float to 32-bit float */
-void HELPER(ledbr)(uint32_t f1, uint32_t f2)
+void HELPER(ledbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     float64 d2 = env->fregs[f2].d;
 
@@ -281,7 +283,7 @@ void HELPER(ledbr)(uint32_t f1, uint32_t f2)
 }
 
 /* convert 128-bit float to 32-bit float */
-void HELPER(lexbr)(uint32_t f1, uint32_t f2)
+void HELPER(lexbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     CPU_QuadU x2;
 
@@ -292,7 +294,7 @@ void HELPER(lexbr)(uint32_t f1, uint32_t f2)
 }
 
 /* absolute value of 32-bit float */
-uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(lpebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     float32 v1;
     float32 v2 = env->fregs[f2].d;
@@ -303,7 +305,7 @@ uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2)
 }
 
 /* absolute value of 64-bit float */
-uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(lpdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     float64 v1;
     float64 v2 = env->fregs[f2].d;
@@ -314,7 +316,7 @@ uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2)
 }
 
 /* absolute value of 128-bit float */
-uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(lpxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     CPU_QuadU v1;
     CPU_QuadU v2;
@@ -328,21 +330,21 @@ uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2)
 }
 
 /* load and test 64-bit float */
-uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(ltdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].d = env->fregs[f2].d;
     return set_cc_nz_f64(env->fregs[f1].d);
 }
 
 /* load and test 32-bit float */
-uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(ltebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].l.upper = env->fregs[f2].l.upper;
     return set_cc_nz_f32(env->fregs[f1].l.upper);
 }
 
 /* load and test 128-bit float */
-uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(ltxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     CPU_QuadU x;
 
@@ -354,7 +356,7 @@ uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2)
 }
 
 /* load complement of 32-bit float */
-uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(lcebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper);
 
@@ -362,7 +364,7 @@ uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2)
 }
 
 /* load complement of 64-bit float */
-uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(lcdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].d = float64_chs(env->fregs[f2].d);
 
@@ -370,7 +372,7 @@ uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2)
 }
 
 /* load complement of 128-bit float */
-uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     CPU_QuadU x1, x2;
 
@@ -383,7 +385,7 @@ uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2)
 }
 
 /* 32-bit FP addition RM */
-void HELPER(aeb)(uint32_t f1, uint32_t val)
+void HELPER(aeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
 {
     float32 v1 = env->fregs[f1].l.upper;
     CPU_FloatU v2;
@@ -395,7 +397,7 @@ void HELPER(aeb)(uint32_t f1, uint32_t val)
 }
 
 /* 32-bit FP division RM */
-void HELPER(deb)(uint32_t f1, uint32_t val)
+void HELPER(deb)(CPUS390XState *env, uint32_t f1, uint32_t val)
 {
     float32 v1 = env->fregs[f1].l.upper;
     CPU_FloatU v2;
@@ -407,7 +409,7 @@ void HELPER(deb)(uint32_t f1, uint32_t val)
 }
 
 /* 32-bit FP multiplication RM */
-void HELPER(meeb)(uint32_t f1, uint32_t val)
+void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
 {
     float32 v1 = env->fregs[f1].l.upper;
     CPU_FloatU v2;
@@ -419,29 +421,29 @@ void HELPER(meeb)(uint32_t f1, uint32_t val)
 }
 
 /* 32-bit FP compare RR */
-uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(cebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     float32 v1 = env->fregs[f1].l.upper;
     float32 v2 = env->fregs[f2].l.upper;
 
     HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__,
                v1, f1, v2);
-    return set_cc_f32(v1, v2);
+    return set_cc_f32(env, v1, v2);
 }
 
 /* 64-bit FP compare RR */
-uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(cdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     float64 v1 = env->fregs[f1].d;
     float64 v2 = env->fregs[f2].d;
 
     HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__,
                v1, f1, v2);
-    return set_cc_f64(v1, v2);
+    return set_cc_f64(env, v1, v2);
 }
 
 /* 128-bit FP compare RR */
-uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(cxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     CPU_QuadU v1;
     CPU_QuadU v2;
@@ -451,29 +453,29 @@ uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2)
     v2.ll.upper = env->fregs[f2].ll;
     v2.ll.lower = env->fregs[f2 + 2].ll;
 
-    return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q,
+    return float_comp_to_cc(env, float128_compare_quiet(v1.q, v2.q,
                                                    &env->fpu_status));
 }
 
 /* 64-bit FP compare RM */
-uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2)
+uint32_t HELPER(cdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
 {
     float64 v1 = env->fregs[f1].d;
     CPU_DoubleU v2;
 
-    v2.ll = ldq(a2);
+    v2.ll = cpu_ldq_data(env, a2);
     HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1,
                f1, v2.d);
-    return set_cc_f64(v1, v2.d);
+    return set_cc_f64(env, v1, v2.d);
 }
 
 /* 64-bit FP addition RM */
-uint32_t HELPER(adb)(uint32_t f1, uint64_t a2)
+uint32_t HELPER(adb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
 {
     float64 v1 = env->fregs[f1].d;
     CPU_DoubleU v2;
 
-    v2.ll = ldq(a2);
+    v2.ll = cpu_ldq_data(env, a2);
     HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__,
                v1, f1, v2.d);
     env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
@@ -481,7 +483,7 @@ uint32_t HELPER(adb)(uint32_t f1, uint64_t a2)
 }
 
 /* 32-bit FP subtraction RM */
-void HELPER(seb)(uint32_t f1, uint32_t val)
+void HELPER(seb)(CPUS390XState *env, uint32_t f1, uint32_t val)
 {
     float32 v1 = env->fregs[f1].l.upper;
     CPU_FloatU v2;
@@ -491,41 +493,41 @@ void HELPER(seb)(uint32_t f1, uint32_t val)
 }
 
 /* 64-bit FP subtraction RM */
-uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2)
+uint32_t HELPER(sdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
 {
     float64 v1 = env->fregs[f1].d;
     CPU_DoubleU v2;
 
-    v2.ll = ldq(a2);
+    v2.ll = cpu_ldq_data(env, a2);
     env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status);
     return set_cc_nz_f64(v1);
 }
 
 /* 64-bit FP multiplication RM */
-void HELPER(mdb)(uint32_t f1, uint64_t a2)
+void HELPER(mdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
 {
     float64 v1 = env->fregs[f1].d;
     CPU_DoubleU v2;
 
-    v2.ll = ldq(a2);
+    v2.ll = cpu_ldq_data(env, a2);
     HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__,
                v1, f1, v2.d);
     env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
 }
 
 /* 64-bit FP division RM */
-void HELPER(ddb)(uint32_t f1, uint64_t a2)
+void HELPER(ddb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
 {
     float64 v1 = env->fregs[f1].d;
     CPU_DoubleU v2;
 
-    v2.ll = ldq(a2);
+    v2.ll = cpu_ldq_data(env, a2);
     HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__,
                v1, f1, v2.d);
     env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
 }
 
-static void set_round_mode(int m3)
+static void set_round_mode(CPUS390XState *env, int m3)
 {
     switch (m3) {
     case 0:
@@ -553,33 +555,36 @@ static void set_round_mode(int m3)
 }
 
 /* convert 32-bit float to 64-bit int */
-uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3)
+uint32_t HELPER(cgebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
+                       uint32_t m3)
 {
     float32 v2 = env->fregs[f2].l.upper;
 
-    set_round_mode(m3);
+    set_round_mode(env, m3);
     env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
     return set_cc_nz_f32(v2);
 }
 
 /* convert 64-bit float to 64-bit int */
-uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
+uint32_t HELPER(cgdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
+                       uint32_t m3)
 {
     float64 v2 = env->fregs[f2].d;
 
-    set_round_mode(m3);
+    set_round_mode(env, m3);
     env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
     return set_cc_nz_f64(v2);
 }
 
 /* convert 128-bit float to 64-bit int */
-uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
+uint32_t HELPER(cgxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
+                       uint32_t m3)
 {
     CPU_QuadU v2;
 
     v2.ll.upper = env->fregs[f2].ll;
     v2.ll.lower = env->fregs[f2 + 2].ll;
-    set_round_mode(m3);
+    set_round_mode(env, m3);
     env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status);
     if (float128_is_any_nan(v2.q)) {
         return 3;
@@ -593,29 +598,32 @@ uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
 }
 
 /* convert 32-bit float to 32-bit int */
-uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3)
+uint32_t HELPER(cfebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
+                       uint32_t m3)
 {
     float32 v2 = env->fregs[f2].l.upper;
 
-    set_round_mode(m3);
+    set_round_mode(env, m3);
     env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
         float32_to_int32(v2, &env->fpu_status);
     return set_cc_nz_f32(v2);
 }
 
 /* convert 64-bit float to 32-bit int */
-uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
+uint32_t HELPER(cfdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
+                       uint32_t m3)
 {
     float64 v2 = env->fregs[f2].d;
 
-    set_round_mode(m3);
+    set_round_mode(env, m3);
     env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
         float64_to_int32(v2, &env->fpu_status);
     return set_cc_nz_f64(v2);
 }
 
 /* convert 128-bit float to 32-bit int */
-uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
+uint32_t HELPER(cfxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
+                       uint32_t m3)
 {
     CPU_QuadU v2;
 
@@ -627,19 +635,19 @@ uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
 }
 
 /* load 32-bit FP zero */
-void HELPER(lzer)(uint32_t f1)
+void HELPER(lzer)(CPUS390XState *env, uint32_t f1)
 {
     env->fregs[f1].l.upper = float32_zero;
 }
 
 /* load 64-bit FP zero */
-void HELPER(lzdr)(uint32_t f1)
+void HELPER(lzdr)(CPUS390XState *env, uint32_t f1)
 {
     env->fregs[f1].d = float64_zero;
 }
 
 /* load 128-bit FP zero */
-void HELPER(lzxr)(uint32_t f1)
+void HELPER(lzxr)(CPUS390XState *env, uint32_t f1)
 {
     CPU_QuadU x;
 
@@ -649,7 +657,7 @@ void HELPER(lzxr)(uint32_t f1)
 }
 
 /* 128-bit FP subtraction RR */
-uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(sxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     CPU_QuadU v1;
     CPU_QuadU v2;
@@ -666,7 +674,7 @@ uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2)
 }
 
 /* 128-bit FP addition RR */
-uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2)
+uint32_t HELPER(axbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     CPU_QuadU v1;
     CPU_QuadU v2;
@@ -683,7 +691,7 @@ uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2)
 }
 
 /* 32-bit FP multiplication RR */
-void HELPER(meebr)(uint32_t f1, uint32_t f2)
+void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper,
                                          env->fregs[f2].l.upper,
@@ -691,19 +699,19 @@ void HELPER(meebr)(uint32_t f1, uint32_t f2)
 }
 
 /* 64-bit FP division RR */
-void HELPER(ddbr)(uint32_t f1, uint32_t f2)
+void HELPER(ddbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d,
                                    &env->fpu_status);
 }
 
 /* 64-bit FP multiply and add RM */
-void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3)
+void HELPER(madb)(CPUS390XState *env, uint32_t f1, uint64_t a2, uint32_t f3)
 {
     CPU_DoubleU v2;
 
     HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3);
-    v2.ll = ldq(a2);
+    v2.ll = cpu_ldq_data(env, a2);
     env->fregs[f1].d = float64_add(env->fregs[f1].d,
                                    float64_mul(v2.d, env->fregs[f3].d,
                                                &env->fpu_status),
@@ -711,7 +719,7 @@ void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3)
 }
 
 /* 64-bit FP multiply and add RR */
-void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2)
+void HELPER(madbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
 {
     HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
     env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d,
@@ -721,7 +729,7 @@ void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2)
 }
 
 /* 64-bit FP multiply and subtract RR */
-void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2)
+void HELPER(msdbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
 {
     HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
     env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d,
@@ -731,7 +739,7 @@ void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2)
 }
 
 /* 32-bit FP multiply and add RR */
-void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2)
+void HELPER(maebr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
 {
     env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
                                          float32_mul(env->fregs[f2].l.upper,
@@ -741,29 +749,29 @@ void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2)
 }
 
 /* convert 32-bit float to 64-bit float */
-void HELPER(ldeb)(uint32_t f1, uint64_t a2)
+void HELPER(ldeb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
 {
     uint32_t v2;
 
-    v2 = ldl(a2);
+    v2 = cpu_ldl_data(env, a2);
     env->fregs[f1].d = float32_to_float64(v2,
                                           &env->fpu_status);
 }
 
 /* convert 64-bit float to 128-bit float */
-void HELPER(lxdb)(uint32_t f1, uint64_t a2)
+void HELPER(lxdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
 {
     CPU_DoubleU v2;
     CPU_QuadU v1;
 
-    v2.ll = ldq(a2);
+    v2.ll = cpu_ldq_data(env, a2);
     v1.q = float64_to_float128(v2.d, &env->fpu_status);
     env->fregs[f1].ll = v1.ll.upper;
     env->fregs[f1 + 2].ll = v1.ll.lower;
 }
 
 /* test data class 32-bit */
-uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2)
+uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
 {
     float32 v1 = env->fregs[f1].l.upper;
     int neg = float32_is_neg(v1);
@@ -785,7 +793,7 @@ uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2)
 }
 
 /* test data class 64-bit */
-uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2)
+uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
 {
     float64 v1 = env->fregs[f1].d;
     int neg = float64_is_neg(v1);
@@ -806,7 +814,7 @@ uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2)
 }
 
 /* test data class 128-bit */
-uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2)
+uint32_t HELPER(tcxb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
 {
     CPU_QuadU v1;
     uint32_t cc = 0;
@@ -830,7 +838,7 @@ uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2)
 }
 
 /* square root 64-bit RR */
-void HELPER(sqdbr)(uint32_t f1, uint32_t f2)
+void HELPER(sqdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
 }
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 01c8d0e..af98773 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -45,70 +45,70 @@ DEF_HELPER_3(mvcle, i32, i32, i64, i32)
 DEF_HELPER_3(clcle, i32, i32, i64, i32)
 DEF_HELPER_3(slb, i32, i32, i32, i32)
 DEF_HELPER_4(slbg, i32, i32, i32, i64, i64)
-DEF_HELPER_2(cefbr, void, i32, s32)
-DEF_HELPER_2(cdfbr, void, i32, s32)
-DEF_HELPER_2(cxfbr, void, i32, s32)
-DEF_HELPER_2(cegbr, void, i32, s64)
-DEF_HELPER_2(cdgbr, void, i32, s64)
-DEF_HELPER_2(cxgbr, void, i32, s64)
-DEF_HELPER_2(adbr, i32, i32, i32)
-DEF_HELPER_2(aebr, i32, i32, i32)
-DEF_HELPER_2(sebr, i32, i32, i32)
-DEF_HELPER_2(sdbr, i32, i32, i32)
-DEF_HELPER_2(debr, void, i32, i32)
-DEF_HELPER_2(dxbr, void, i32, i32)
-DEF_HELPER_2(mdbr, void, i32, i32)
-DEF_HELPER_2(mxbr, void, i32, i32)
-DEF_HELPER_2(ldebr, void, i32, i32)
-DEF_HELPER_2(ldxbr, void, i32, i32)
-DEF_HELPER_2(lxdbr, void, i32, i32)
-DEF_HELPER_2(ledbr, void, i32, i32)
-DEF_HELPER_2(lexbr, void, i32, i32)
-DEF_HELPER_2(lpebr, i32, i32, i32)
-DEF_HELPER_2(lpdbr, i32, i32, i32)
-DEF_HELPER_2(lpxbr, i32, i32, i32)
-DEF_HELPER_2(ltebr, i32, i32, i32)
-DEF_HELPER_2(ltdbr, i32, i32, i32)
-DEF_HELPER_2(ltxbr, i32, i32, i32)
-DEF_HELPER_2(lcebr, i32, i32, i32)
-DEF_HELPER_2(lcdbr, i32, i32, i32)
-DEF_HELPER_2(lcxbr, i32, i32, i32)
-DEF_HELPER_2(aeb, void, i32, i32)
-DEF_HELPER_2(deb, void, i32, i32)
-DEF_HELPER_2(meeb, void, i32, i32)
-DEF_HELPER_2(cdb, i32, i32, i64)
-DEF_HELPER_2(adb, i32, i32, i64)
-DEF_HELPER_2(seb, void, i32, i32)
-DEF_HELPER_2(sdb, i32, i32, i64)
-DEF_HELPER_2(mdb, void, i32, i64)
-DEF_HELPER_2(ddb, void, i32, i64)
-DEF_HELPER_FLAGS_2(cebr, TCG_CALL_PURE, i32, i32, i32)
-DEF_HELPER_FLAGS_2(cdbr, TCG_CALL_PURE, i32, i32, i32)
-DEF_HELPER_FLAGS_2(cxbr, TCG_CALL_PURE, i32, i32, i32)
-DEF_HELPER_3(cgebr, i32, i32, i32, i32)
-DEF_HELPER_3(cgdbr, i32, i32, i32, i32)
-DEF_HELPER_3(cgxbr, i32, i32, i32, i32)
-DEF_HELPER_1(lzer, void, i32)
-DEF_HELPER_1(lzdr, void, i32)
-DEF_HELPER_1(lzxr, void, i32)
-DEF_HELPER_3(cfebr, i32, i32, i32, i32)
-DEF_HELPER_3(cfdbr, i32, i32, i32, i32)
-DEF_HELPER_3(cfxbr, i32, i32, i32, i32)
-DEF_HELPER_2(axbr, i32, i32, i32)
-DEF_HELPER_2(sxbr, i32, i32, i32)
-DEF_HELPER_2(meebr, void, i32, i32)
-DEF_HELPER_2(ddbr, void, i32, i32)
-DEF_HELPER_3(madb, void, i32, i64, i32)
-DEF_HELPER_3(maebr, void, i32, i32, i32)
-DEF_HELPER_3(madbr, void, i32, i32, i32)
-DEF_HELPER_3(msdbr, void, i32, i32, i32)
-DEF_HELPER_2(ldeb, void, i32, i64)
-DEF_HELPER_2(lxdb, void, i32, i64)
-DEF_HELPER_FLAGS_2(tceb, TCG_CALL_PURE, i32, i32, i64)
-DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_PURE, i32, i32, i64)
-DEF_HELPER_FLAGS_2(tcxb, TCG_CALL_PURE, i32, i32, i64)
+DEF_HELPER_3(cefbr, void, env, i32, s32)
+DEF_HELPER_3(cdfbr, void, env, i32, s32)
+DEF_HELPER_3(cxfbr, void, env, i32, s32)
+DEF_HELPER_3(cegbr, void, env, i32, s64)
+DEF_HELPER_3(cdgbr, void, env, i32, s64)
+DEF_HELPER_3(cxgbr, void, env, i32, s64)
+DEF_HELPER_3(adbr, i32, env, i32, i32)
+DEF_HELPER_3(aebr, i32, env, i32, i32)
+DEF_HELPER_3(sebr, i32, env, i32, i32)
+DEF_HELPER_3(sdbr, i32, env, i32, i32)
+DEF_HELPER_3(debr, void, env, i32, i32)
+DEF_HELPER_3(dxbr, void, env, i32, i32)
+DEF_HELPER_3(mdbr, void, env, i32, i32)
+DEF_HELPER_3(mxbr, void, env, i32, i32)
+DEF_HELPER_3(ldebr, void, env, i32, i32)
+DEF_HELPER_3(ldxbr, void, env, i32, i32)
+DEF_HELPER_3(lxdbr, void, env, i32, i32)
+DEF_HELPER_3(ledbr, void, env, i32, i32)
+DEF_HELPER_3(lexbr, void, env, i32, i32)
+DEF_HELPER_3(lpebr, i32, env, i32, i32)
+DEF_HELPER_3(lpdbr, i32, env, i32, i32)
+DEF_HELPER_3(lpxbr, i32, env, i32, i32)
+DEF_HELPER_3(ltebr, i32, env, i32, i32)
+DEF_HELPER_3(ltdbr, i32, env, i32, i32)
+DEF_HELPER_3(ltxbr, i32, env, i32, i32)
+DEF_HELPER_3(lcebr, i32, env, i32, i32)
+DEF_HELPER_3(lcdbr, i32, env, i32, i32)
+DEF_HELPER_3(lcxbr, i32, env, i32, i32)
+DEF_HELPER_3(aeb, void, env, i32, i32)
+DEF_HELPER_3(deb, void, env, i32, i32)
+DEF_HELPER_3(meeb, void, env, i32, i32)
+DEF_HELPER_3(cdb, i32, env, i32, i64)
+DEF_HELPER_3(adb, i32, env, i32, i64)
+DEF_HELPER_3(seb, void, env, i32, i32)
+DEF_HELPER_3(sdb, i32, env, i32, i64)
+DEF_HELPER_3(mdb, void, env, i32, i64)
+DEF_HELPER_3(ddb, void, env, i32, i64)
+DEF_HELPER_FLAGS_3(cebr, TCG_CALL_PURE, i32, env, i32, i32)
+DEF_HELPER_FLAGS_3(cdbr, TCG_CALL_PURE, i32, env, i32, i32)
+DEF_HELPER_FLAGS_3(cxbr, TCG_CALL_PURE, i32, env, i32, i32)
+DEF_HELPER_4(cgebr, i32, env, i32, i32, i32)
+DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32)
+DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32)
+DEF_HELPER_2(lzer, void, env, i32)
+DEF_HELPER_2(lzdr, void, env, i32)
+DEF_HELPER_2(lzxr, void, env, i32)
+DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
+DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
+DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
+DEF_HELPER_3(axbr, i32, env, i32, i32)
+DEF_HELPER_3(sxbr, i32, env, i32, i32)
+DEF_HELPER_3(meebr, void, env, i32, i32)
+DEF_HELPER_3(ddbr, void, env, i32, i32)
+DEF_HELPER_4(madb, void, env, i32, i64, i32)
+DEF_HELPER_4(maebr, void, env, i32, i32, i32)
+DEF_HELPER_4(madbr, void, env, i32, i32, i32)
+DEF_HELPER_4(msdbr, void, env, i32, i32, i32)
+DEF_HELPER_3(ldeb, void, env, i32, i64)
+DEF_HELPER_3(lxdb, void, env, i32, i64)
+DEF_HELPER_FLAGS_3(tceb, TCG_CALL_PURE, i32, env, i32, i64)
+DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_PURE, i32, env, i32, i64)
+DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64)
 DEF_HELPER_2(flogr, i32, i32, i64)
-DEF_HELPER_2(sqdbr, void, i32, i32)
+DEF_HELPER_3(sqdbr, void, env, i32, i32)
 DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32)
 DEF_HELPER_3(unpk, void, i32, i64, i64)
 DEF_HELPER_3(tr, void, i32, i64, i64)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index ba05e65..3f8b3ba 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -1188,3 +1188,52 @@ uint32_t HELPER(lra)(uint64_t addr, uint32_t r1)
 }
 
 #endif
+
+/* temporary wrappers */
+#if defined(CONFIG_USER_ONLY)
+#define ldub_data(addr) ldub_raw(addr)
+#define lduw_data(addr) lduw_raw(addr)
+#define ldl_data(addr) ldl_raw(addr)
+#define ldq_data(addr) ldq_raw(addr)
+
+#define stb_data(addr, data) stb_raw(addr, data)
+#define stw_data(addr, data) stw_raw(addr, data)
+#define stl_data(addr, data) stl_raw(addr, data)
+#define stq_data(addr, data) stq_raw(addr, data)
+#endif
+
+#define WRAP_LD(rettype, fn)                                    \
+    rettype cpu_ ## fn(CPUS390XState *env1, target_ulong addr)  \
+    {                                                           \
+        CPUS390XState *saved_env;                               \
+        rettype ret;                                            \
+                                                                \
+        saved_env = env;                                        \
+        env = env1;                                             \
+        ret = fn(addr);                                         \
+        env = saved_env;                                        \
+        return ret;                                             \
+    }
+
+WRAP_LD(uint32_t, ldub_data)
+WRAP_LD(uint32_t, lduw_data)
+WRAP_LD(uint32_t, ldl_data)
+WRAP_LD(uint64_t, ldq_data)
+#undef WRAP_LD
+
+#define WRAP_ST(datatype, fn)                                           \
+    void cpu_ ## fn(CPUS390XState *env1, target_ulong addr, datatype val) \
+    {                                                                   \
+        CPUS390XState *saved_env;                                       \
+                                                                        \
+        saved_env = env;                                                \
+        env = env1;                                                     \
+        fn(addr, val);                                                  \
+        env = saved_env;                                                \
+    }
+
+WRAP_ST(uint32_t, stb_data)
+WRAP_ST(uint32_t, stw_data)
+WRAP_ST(uint32_t, stl_data)
+WRAP_ST(uint64_t, stq_data)
+#undef WRAP_ST
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c370df3..b1f2071 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2206,11 +2206,11 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
     switch (op) {
     case 0x4: /* LDEB R1,D2(X2,B2) [RXE] */
         potential_page_fault(s);
-        gen_helper_ldeb(tmp_r1, addr);
+        gen_helper_ldeb(cpu_env, tmp_r1, addr);
         break;
     case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */
         potential_page_fault(s);
-        gen_helper_lxdb(tmp_r1, addr);
+        gen_helper_lxdb(cpu_env, tmp_r1, addr);
         break;
     case 0x9: /* CEB    R1,D2(X2,B2)       [RXE] */
         tmp = tcg_temp_new_i64();
@@ -2225,7 +2225,7 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
         tmp32 = tcg_temp_new_i32();
         tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
         tcg_gen_trunc_i64_i32(tmp32, tmp);
-        gen_helper_aeb(tmp_r1, tmp32);
+        gen_helper_aeb(cpu_env, tmp_r1, tmp32);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32);
 
@@ -2238,7 +2238,7 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
         tmp32 = tcg_temp_new_i32();
         tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
         tcg_gen_trunc_i64_i32(tmp32, tmp);
-        gen_helper_seb(tmp_r1, tmp32);
+        gen_helper_seb(cpu_env, tmp_r1, tmp32);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32);
 
@@ -2251,23 +2251,23 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
         tmp32 = tcg_temp_new_i32();
         tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
         tcg_gen_trunc_i64_i32(tmp32, tmp);
-        gen_helper_deb(tmp_r1, tmp32);
+        gen_helper_deb(cpu_env, tmp_r1, tmp32);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32);
         break;
     case 0x10: /* TCEB   R1,D2(X2,B2)       [RXE] */
         potential_page_fault(s);
-        gen_helper_tceb(cc_op, tmp_r1, addr);
+        gen_helper_tceb(cc_op, cpu_env, tmp_r1, addr);
         set_cc_static(s);
         break;
     case 0x11: /* TCDB   R1,D2(X2,B2)       [RXE] */
         potential_page_fault(s);
-        gen_helper_tcdb(cc_op, tmp_r1, addr);
+        gen_helper_tcdb(cc_op, cpu_env, tmp_r1, addr);
         set_cc_static(s);
         break;
     case 0x12: /* TCXB   R1,D2(X2,B2)       [RXE] */
         potential_page_fault(s);
-        gen_helper_tcxb(cc_op, tmp_r1, addr);
+        gen_helper_tcxb(cc_op, cpu_env, tmp_r1, addr);
         set_cc_static(s);
         break;
     case 0x17: /* MEEB   R1,D2(X2,B2)       [RXE] */
@@ -2275,38 +2275,38 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
         tmp32 = tcg_temp_new_i32();
         tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
         tcg_gen_trunc_i64_i32(tmp32, tmp);
-        gen_helper_meeb(tmp_r1, tmp32);
+        gen_helper_meeb(cpu_env, tmp_r1, tmp32);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32);
         break;
     case 0x19: /* CDB    R1,D2(X2,B2)       [RXE] */
         potential_page_fault(s);
-        gen_helper_cdb(cc_op, tmp_r1, addr);
+        gen_helper_cdb(cc_op, cpu_env, tmp_r1, addr);
         set_cc_static(s);
         break;
     case 0x1a: /* ADB    R1,D2(X2,B2)       [RXE] */
         potential_page_fault(s);
-        gen_helper_adb(cc_op, tmp_r1, addr);
+        gen_helper_adb(cc_op, cpu_env, tmp_r1, addr);
         set_cc_static(s);
         break;
     case 0x1b: /* SDB    R1,D2(X2,B2)       [RXE] */
         potential_page_fault(s);
-        gen_helper_sdb(cc_op, tmp_r1, addr);
+        gen_helper_sdb(cc_op, cpu_env, tmp_r1, addr);
         set_cc_static(s);
         break;
     case 0x1c: /* MDB    R1,D2(X2,B2)       [RXE] */
         potential_page_fault(s);
-        gen_helper_mdb(tmp_r1, addr);
+        gen_helper_mdb(cpu_env, tmp_r1, addr);
         break;
     case 0x1d: /* DDB    R1,D2(X2,B2)       [RXE] */
         potential_page_fault(s);
-        gen_helper_ddb(tmp_r1, addr);
+        gen_helper_ddb(cpu_env, tmp_r1, addr);
         break;
     case 0x1e: /* MADB  R1,R3,D2(X2,B2) [RXF] */
         /* for RXF insns, r1 is R3 and r1b is R1 */
         tmp32 = tcg_const_i32(r1b);
         potential_page_fault(s);
-        gen_helper_madb(tmp32, addr, tmp_r1);
+        gen_helper_madb(cpu_env, tmp32, addr, tmp_r1);
         tcg_temp_free_i32(tmp32);
         break;
     default:
@@ -3001,14 +3001,14 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
 #define FP_HELPER(i) \
     tmp32_1 = tcg_const_i32(r1); \
     tmp32_2 = tcg_const_i32(r2); \
-    gen_helper_ ## i (tmp32_1, tmp32_2); \
+    gen_helper_ ## i(cpu_env, tmp32_1, tmp32_2); \
     tcg_temp_free_i32(tmp32_1); \
     tcg_temp_free_i32(tmp32_2);
 
 #define FP_HELPER_CC(i) \
     tmp32_1 = tcg_const_i32(r1); \
     tmp32_2 = tcg_const_i32(r2); \
-    gen_helper_ ## i (cc_op, tmp32_1, tmp32_2); \
+    gen_helper_ ## i(cc_op, cpu_env, tmp32_1, tmp32_2); \
     set_cc_static(s); \
     tcg_temp_free_i32(tmp32_1); \
     tcg_temp_free_i32(tmp32_2);
@@ -3080,13 +3080,13 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
         tmp32_3 = tcg_const_i32(r1);
         switch (op) {
         case 0xe:
-            gen_helper_maebr(tmp32_1, tmp32_3, tmp32_2);
+            gen_helper_maebr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
             break;
         case 0x1e:
-            gen_helper_madbr(tmp32_1, tmp32_3, tmp32_2);
+            gen_helper_madbr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
             break;
         case 0x1f:
-            gen_helper_msdbr(tmp32_1, tmp32_3, tmp32_2);
+            gen_helper_msdbr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
             break;
         default:
             tcg_abort();
@@ -3138,17 +3138,17 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
         break;
     case 0x74: /* LZER        R1                [RRE] */
         tmp32_1 = tcg_const_i32(r1);
-        gen_helper_lzer(tmp32_1);
+        gen_helper_lzer(cpu_env, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
     case 0x75: /* LZDR        R1                [RRE] */
         tmp32_1 = tcg_const_i32(r1);
-        gen_helper_lzdr(tmp32_1);
+        gen_helper_lzdr(cpu_env, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
     case 0x76: /* LZXR        R1                [RRE] */
         tmp32_1 = tcg_const_i32(r1);
-        gen_helper_lzxr(tmp32_1);
+        gen_helper_lzxr(cpu_env, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
     case 0x84: /* SFPC        R1                [RRE] */
@@ -3169,13 +3169,13 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
         tmp32_2 = load_reg32(r2);
         switch (op) {
         case 0x94:
-            gen_helper_cefbr(tmp32_1, tmp32_2);
+            gen_helper_cefbr(cpu_env, tmp32_1, tmp32_2);
             break;
         case 0x95:
-            gen_helper_cdfbr(tmp32_1, tmp32_2);
+            gen_helper_cdfbr(cpu_env, tmp32_1, tmp32_2);
             break;
         case 0x96:
-            gen_helper_cxfbr(tmp32_1, tmp32_2);
+            gen_helper_cxfbr(cpu_env, tmp32_1, tmp32_2);
             break;
         default:
             tcg_abort();
@@ -3191,13 +3191,13 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
         tmp32_3 = tcg_const_i32(m3);
         switch (op) {
         case 0x98:
-            gen_helper_cfebr(cc_op, tmp32_1, tmp32_2, tmp32_3);
+            gen_helper_cfebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
             break;
         case 0x99:
-            gen_helper_cfdbr(cc_op, tmp32_1, tmp32_2, tmp32_3);
+            gen_helper_cfdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
             break;
         case 0x9a:
-            gen_helper_cfxbr(cc_op, tmp32_1, tmp32_2, tmp32_3);
+            gen_helper_cfxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
             break;
         default:
             tcg_abort();
@@ -3213,10 +3213,10 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
         tmp = load_reg(r2);
         switch (op) {
         case 0xa4:
-            gen_helper_cegbr(tmp32_1, tmp);
+            gen_helper_cegbr(cpu_env, tmp32_1, tmp);
             break;
         case 0xa5:
-            gen_helper_cdgbr(tmp32_1, tmp);
+            gen_helper_cdgbr(cpu_env, tmp32_1, tmp);
             break;
         default:
             tcg_abort();
@@ -3227,7 +3227,7 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
     case 0xa6: /* CXGBR       R1,R2             [RRE] */
         tmp32_1 = tcg_const_i32(r1);
         tmp = load_reg(r2);
-        gen_helper_cxgbr(tmp32_1, tmp);
+        gen_helper_cxgbr(cpu_env, tmp32_1, tmp);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp);
         break;
@@ -3235,7 +3235,7 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r2);
         tmp32_3 = tcg_const_i32(m3);
-        gen_helper_cgebr(cc_op, tmp32_1, tmp32_2, tmp32_3);
+        gen_helper_cgebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
         set_cc_static(s);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -3245,7 +3245,7 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r2);
         tmp32_3 = tcg_const_i32(m3);
-        gen_helper_cgdbr(cc_op, tmp32_1, tmp32_2, tmp32_3);
+        gen_helper_cgdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
         set_cc_static(s);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
@@ -3255,7 +3255,7 @@ static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r2);
         tmp32_3 = tcg_const_i32(m3);
-        gen_helper_cgxbr(cc_op, tmp32_1, tmp32_2, tmp32_3);
+        gen_helper_cgxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
         set_cc_static(s);
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
commit aea1e885b2b59cf93d0db9356fd5bb6cb1780f01
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 2 07:33:35 2012 +0000

    target-s390x: rename op_helper.c to misc_helper.c
    
    Now op_helper.c contains miscellaneous helpers, rename
    it to misc_helper.c.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    [agraf: fix conflict]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index b9b3061..a87d26f 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -1,10 +1,10 @@
-obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o
-obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o
+obj-y += translate.o helper.o cpu.o interrupt.o
+obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
 
-$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+$(obj)/misc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 97fde5e..0ccb551 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -1005,7 +1005,7 @@ uint32_t set_cc_f64(float64 v1, float64 v2);
 uint32_t set_cc_nz_f32(float32 v);
 uint32_t set_cc_nz_f64(float64 v);
 
-/* op_helper.c */
+/* misc_helper.c */
 void program_interrupt(CPUS390XState *env, uint32_t code, int ilc);
 
 #endif
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
new file mode 100644
index 0000000..1d5137f
--- /dev/null
+++ b/target-s390x/misc_helper.c
@@ -0,0 +1,428 @@
+/*
+ *  S/390 misc helper routines
+ *
+ *  Copyright (c) 2009 Ulrich Hecht
+ *  Copyright (c) 2009 Alexander Graf
+ *
+ * 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 "memory.h"
+#include "cputlb.h"
+#include "dyngen-exec.h"
+#include "host-utils.h"
+#include "helper.h"
+#include <string.h>
+#include "kvm.h"
+#include "qemu-timer.h"
+#ifdef CONFIG_KVM
+#include <linux/kvm.h>
+#endif
+
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#include "sysemu.h"
+#endif
+
+/* #define DEBUG_HELPER */
+#ifdef DEBUG_HELPER
+#define HELPER_LOG(x...) qemu_log(x)
+#else
+#define HELPER_LOG(x...)
+#endif
+
+/* raise an exception */
+void HELPER(exception)(uint32_t excp)
+{
+    HELPER_LOG("%s: exception %d\n", __func__, excp);
+    env->exception_index = excp;
+    cpu_loop_exit(env);
+}
+
+#ifndef CONFIG_USER_ONLY
+void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
+{
+    qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr);
+
+    if (kvm_enabled()) {
+#ifdef CONFIG_KVM
+        kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
+#endif
+    } else {
+        env->int_pgm_code = code;
+        env->int_pgm_ilc = ilc;
+        env->exception_index = EXCP_PGM;
+        cpu_loop_exit(env);
+    }
+}
+
+/*
+ * ret < 0 indicates program check, ret = 0, 1, 2, 3 -> cc
+ */
+int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
+{
+    int r = 0;
+    int shift = 0;
+
+#ifdef DEBUG_HELPER
+    printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code);
+#endif
+
+    /* basic checks */
+    if (!memory_region_is_ram(phys_page_find(sccb >> TARGET_PAGE_BITS)->mr)) {
+        return -PGM_ADDRESSING;
+    }
+    if (sccb & ~0x7ffffff8ul) {
+        return -PGM_SPECIFICATION;
+    }
+
+    switch (code) {
+    case SCLP_CMDW_READ_SCP_INFO:
+    case SCLP_CMDW_READ_SCP_INFO_FORCED:
+        while ((ram_size >> (20 + shift)) > 65535) {
+            shift++;
+        }
+        stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift));
+        stb_phys(sccb + SCP_INCREMENT, 1 << shift);
+        stw_phys(sccb + SCP_RESPONSE_CODE, 0x10);
+
+        s390_sclp_extint(sccb & ~3);
+        break;
+    default:
+#ifdef DEBUG_HELPER
+        printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
+#endif
+        r = 3;
+        break;
+    }
+
+    return r;
+}
+
+/* SCLP service call */
+uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
+{
+    int r;
+
+    r = sclp_service_call(env, r1, r2);
+    if (r < 0) {
+        program_interrupt(env, -r, 4);
+        return 0;
+    }
+    return r;
+}
+
+/* DIAG */
+uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
+{
+    uint64_t r;
+
+    switch (num) {
+    case 0x500:
+        /* KVM hypercall */
+        r = s390_virtio_hypercall(env, mem, code);
+        break;
+    case 0x44:
+        /* yield */
+        r = 0;
+        break;
+    case 0x308:
+        /* ipl */
+        r = 0;
+        break;
+    default:
+        r = -1;
+        break;
+    }
+
+    if (r) {
+        program_interrupt(env, PGM_OPERATION, ILC_LATER_INC);
+    }
+
+    return r;
+}
+
+/* Store CPU ID */
+void HELPER(stidp)(uint64_t a1)
+{
+    stq(a1, env->cpu_num);
+}
+
+/* Set Prefix */
+void HELPER(spx)(uint64_t a1)
+{
+    uint32_t prefix;
+
+    prefix = ldl(a1);
+    env->psa = prefix & 0xfffff000;
+    qemu_log("prefix: %#x\n", prefix);
+    tlb_flush_page(env, 0);
+    tlb_flush_page(env, TARGET_PAGE_SIZE);
+}
+
+/* Set Clock */
+uint32_t HELPER(sck)(uint64_t a1)
+{
+    /* XXX not implemented - is it necessary? */
+
+    return 0;
+}
+
+static inline uint64_t clock_value(CPUS390XState *env)
+{
+    uint64_t time;
+
+    time = env->tod_offset +
+        time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
+
+    return time;
+}
+
+/* Store Clock */
+uint32_t HELPER(stck)(uint64_t a1)
+{
+    stq(a1, clock_value(env));
+
+    return 0;
+}
+
+/* Store Clock Extended */
+uint32_t HELPER(stcke)(uint64_t a1)
+{
+    stb(a1, 0);
+    /* basically the same value as stck */
+    stq(a1 + 1, clock_value(env) | env->cpu_num);
+    /* more fine grained than stck */
+    stq(a1 + 9, 0);
+    /* XXX programmable fields */
+    stw(a1 + 17, 0);
+
+    return 0;
+}
+
+/* Set Clock Comparator */
+void HELPER(sckc)(uint64_t a1)
+{
+    uint64_t time = ldq(a1);
+
+    if (time == -1ULL) {
+        return;
+    }
+
+    /* difference between now and then */
+    time -= clock_value(env);
+    /* nanoseconds */
+    time = (time * 125) >> 9;
+
+    qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time);
+}
+
+/* Store Clock Comparator */
+void HELPER(stckc)(uint64_t a1)
+{
+    /* XXX implement */
+    stq(a1, 0);
+}
+
+/* Set CPU Timer */
+void HELPER(spt)(uint64_t a1)
+{
+    uint64_t time = ldq(a1);
+
+    if (time == -1ULL) {
+        return;
+    }
+
+    /* nanoseconds */
+    time = (time * 125) >> 9;
+
+    qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time);
+}
+
+/* Store CPU Timer */
+void HELPER(stpt)(uint64_t a1)
+{
+    /* XXX implement */
+    stq(a1, 0);
+}
+
+/* Store System Information */
+uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
+{
+    int cc = 0;
+    int sel1, sel2;
+
+    if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 &&
+        ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) {
+        /* valid function code, invalid reserved bits */
+        program_interrupt(env, PGM_SPECIFICATION, 2);
+    }
+
+    sel1 = r0 & STSI_R0_SEL1_MASK;
+    sel2 = r1 & STSI_R1_SEL2_MASK;
+
+    /* XXX: spec exception if sysib is not 4k-aligned */
+
+    switch (r0 & STSI_LEVEL_MASK) {
+    case STSI_LEVEL_1:
+        if ((sel1 == 1) && (sel2 == 1)) {
+            /* Basic Machine Configuration */
+            struct sysib_111 sysib;
+
+            memset(&sysib, 0, sizeof(sysib));
+            ebcdic_put(sysib.manuf, "QEMU            ", 16);
+            /* same as machine type number in STORE CPU ID */
+            ebcdic_put(sysib.type, "QEMU", 4);
+            /* same as model number in STORE CPU ID */
+            ebcdic_put(sysib.model, "QEMU            ", 16);
+            ebcdic_put(sysib.sequence, "QEMU            ", 16);
+            ebcdic_put(sysib.plant, "QEMU", 4);
+            cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+        } else if ((sel1 == 2) && (sel2 == 1)) {
+            /* Basic Machine CPU */
+            struct sysib_121 sysib;
+
+            memset(&sysib, 0, sizeof(sysib));
+            /* XXX make different for different CPUs? */
+            ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
+            ebcdic_put(sysib.plant, "QEMU", 4);
+            stw_p(&sysib.cpu_addr, env->cpu_num);
+            cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+        } else if ((sel1 == 2) && (sel2 == 2)) {
+            /* Basic Machine CPUs */
+            struct sysib_122 sysib;
+
+            memset(&sysib, 0, sizeof(sysib));
+            stl_p(&sysib.capability, 0x443afc29);
+            /* XXX change when SMP comes */
+            stw_p(&sysib.total_cpus, 1);
+            stw_p(&sysib.active_cpus, 1);
+            stw_p(&sysib.standby_cpus, 0);
+            stw_p(&sysib.reserved_cpus, 0);
+            cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+        } else {
+            cc = 3;
+        }
+        break;
+    case STSI_LEVEL_2:
+        {
+            if ((sel1 == 2) && (sel2 == 1)) {
+                /* LPAR CPU */
+                struct sysib_221 sysib;
+
+                memset(&sysib, 0, sizeof(sysib));
+                /* XXX make different for different CPUs? */
+                ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
+                ebcdic_put(sysib.plant, "QEMU", 4);
+                stw_p(&sysib.cpu_addr, env->cpu_num);
+                stw_p(&sysib.cpu_id, 0);
+                cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+            } else if ((sel1 == 2) && (sel2 == 2)) {
+                /* LPAR CPUs */
+                struct sysib_222 sysib;
+
+                memset(&sysib, 0, sizeof(sysib));
+                stw_p(&sysib.lpar_num, 0);
+                sysib.lcpuc = 0;
+                /* XXX change when SMP comes */
+                stw_p(&sysib.total_cpus, 1);
+                stw_p(&sysib.conf_cpus, 1);
+                stw_p(&sysib.standby_cpus, 0);
+                stw_p(&sysib.reserved_cpus, 0);
+                ebcdic_put(sysib.name, "QEMU    ", 8);
+                stl_p(&sysib.caf, 1000);
+                stw_p(&sysib.dedicated_cpus, 0);
+                stw_p(&sysib.shared_cpus, 0);
+                cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+            } else {
+                cc = 3;
+            }
+            break;
+        }
+    case STSI_LEVEL_3:
+        {
+            if ((sel1 == 2) && (sel2 == 2)) {
+                /* VM CPUs */
+                struct sysib_322 sysib;
+
+                memset(&sysib, 0, sizeof(sysib));
+                sysib.count = 1;
+                /* XXX change when SMP comes */
+                stw_p(&sysib.vm[0].total_cpus, 1);
+                stw_p(&sysib.vm[0].conf_cpus, 1);
+                stw_p(&sysib.vm[0].standby_cpus, 0);
+                stw_p(&sysib.vm[0].reserved_cpus, 0);
+                ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
+                stl_p(&sysib.vm[0].caf, 1000);
+                ebcdic_put(sysib.vm[0].cpi, "KVM/Linux       ", 16);
+                cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+            } else {
+                cc = 3;
+            }
+            break;
+        }
+    case STSI_LEVEL_CURRENT:
+        env->regs[0] = STSI_LEVEL_3;
+        break;
+    default:
+        cc = 3;
+        break;
+    }
+
+    return cc;
+}
+
+uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
+{
+    int cc = 0;
+
+    HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
+               __func__, order_code, r1, cpu_addr);
+
+    /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register"
+       as parameter (input). Status (output) is always R1. */
+
+    switch (order_code) {
+    case SIGP_SET_ARCH:
+        /* switch arch */
+        break;
+    case SIGP_SENSE:
+        /* enumerate CPU status */
+        if (cpu_addr) {
+            /* XXX implement when SMP comes */
+            return 3;
+        }
+        env->regs[r1] &= 0xffffffff00000000ULL;
+        cc = 1;
+        break;
+#if !defined(CONFIG_USER_ONLY)
+    case SIGP_RESTART:
+        qemu_system_reset_request();
+        cpu_loop_exit(env);
+        break;
+    case SIGP_STOP:
+        qemu_system_shutdown_request();
+        cpu_loop_exit(env);
+        break;
+#endif
+    default:
+        /* unknown sigp */
+        fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
+        cc = 3;
+    }
+
+    return cc;
+}
+#endif
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
deleted file mode 100644
index bb8dbf5..0000000
--- a/target-s390x/op_helper.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- *  S/390 helper routines
- *
- *  Copyright (c) 2009 Ulrich Hecht
- *  Copyright (c) 2009 Alexander Graf
- *
- * 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 "memory.h"
-#include "cputlb.h"
-#include "dyngen-exec.h"
-#include "host-utils.h"
-#include "helper.h"
-#include <string.h>
-#include "kvm.h"
-#include "qemu-timer.h"
-#ifdef CONFIG_KVM
-#include <linux/kvm.h>
-#endif
-
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#include "sysemu.h"
-#endif
-
-/* #define DEBUG_HELPER */
-#ifdef DEBUG_HELPER
-#define HELPER_LOG(x...) qemu_log(x)
-#else
-#define HELPER_LOG(x...)
-#endif
-
-/* raise an exception */
-void HELPER(exception)(uint32_t excp)
-{
-    HELPER_LOG("%s: exception %d\n", __func__, excp);
-    env->exception_index = excp;
-    cpu_loop_exit(env);
-}
-
-#ifndef CONFIG_USER_ONLY
-void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
-{
-    qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr);
-
-    if (kvm_enabled()) {
-#ifdef CONFIG_KVM
-        kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
-#endif
-    } else {
-        env->int_pgm_code = code;
-        env->int_pgm_ilc = ilc;
-        env->exception_index = EXCP_PGM;
-        cpu_loop_exit(env);
-    }
-}
-
-/*
- * ret < 0 indicates program check, ret = 0, 1, 2, 3 -> cc
- */
-int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
-{
-    int r = 0;
-    int shift = 0;
-
-#ifdef DEBUG_HELPER
-    printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code);
-#endif
-
-    /* basic checks */
-    if (!memory_region_is_ram(phys_page_find(sccb >> TARGET_PAGE_BITS)->mr)) {
-        return -PGM_ADDRESSING;
-    }
-    if (sccb & ~0x7ffffff8ul) {
-        return -PGM_SPECIFICATION;
-    }
-
-    switch (code) {
-    case SCLP_CMDW_READ_SCP_INFO:
-    case SCLP_CMDW_READ_SCP_INFO_FORCED:
-        while ((ram_size >> (20 + shift)) > 65535) {
-            shift++;
-        }
-        stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift));
-        stb_phys(sccb + SCP_INCREMENT, 1 << shift);
-        stw_phys(sccb + SCP_RESPONSE_CODE, 0x10);
-
-        s390_sclp_extint(sccb & ~3);
-        break;
-    default:
-#ifdef DEBUG_HELPER
-        printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
-#endif
-        r = 3;
-        break;
-    }
-
-    return r;
-}
-
-/* SCLP service call */
-uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
-{
-    int r;
-
-    r = sclp_service_call(env, r1, r2);
-    if (r < 0) {
-        program_interrupt(env, -r, 4);
-        return 0;
-    }
-    return r;
-}
-
-/* DIAG */
-uint64_t HELPER(diag)(uint32_t num, uint64_t mem, uint64_t code)
-{
-    uint64_t r;
-
-    switch (num) {
-    case 0x500:
-        /* KVM hypercall */
-        r = s390_virtio_hypercall(env, mem, code);
-        break;
-    case 0x44:
-        /* yield */
-        r = 0;
-        break;
-    case 0x308:
-        /* ipl */
-        r = 0;
-        break;
-    default:
-        r = -1;
-        break;
-    }
-
-    if (r) {
-        program_interrupt(env, PGM_OPERATION, ILC_LATER_INC);
-    }
-
-    return r;
-}
-
-/* Store CPU ID */
-void HELPER(stidp)(uint64_t a1)
-{
-    stq(a1, env->cpu_num);
-}
-
-/* Set Prefix */
-void HELPER(spx)(uint64_t a1)
-{
-    uint32_t prefix;
-
-    prefix = ldl(a1);
-    env->psa = prefix & 0xfffff000;
-    qemu_log("prefix: %#x\n", prefix);
-    tlb_flush_page(env, 0);
-    tlb_flush_page(env, TARGET_PAGE_SIZE);
-}
-
-/* Set Clock */
-uint32_t HELPER(sck)(uint64_t a1)
-{
-    /* XXX not implemented - is it necessary? */
-
-    return 0;
-}
-
-static inline uint64_t clock_value(CPUS390XState *env)
-{
-    uint64_t time;
-
-    time = env->tod_offset +
-        time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
-
-    return time;
-}
-
-/* Store Clock */
-uint32_t HELPER(stck)(uint64_t a1)
-{
-    stq(a1, clock_value(env));
-
-    return 0;
-}
-
-/* Store Clock Extended */
-uint32_t HELPER(stcke)(uint64_t a1)
-{
-    stb(a1, 0);
-    /* basically the same value as stck */
-    stq(a1 + 1, clock_value(env) | env->cpu_num);
-    /* more fine grained than stck */
-    stq(a1 + 9, 0);
-    /* XXX programmable fields */
-    stw(a1 + 17, 0);
-
-    return 0;
-}
-
-/* Set Clock Comparator */
-void HELPER(sckc)(uint64_t a1)
-{
-    uint64_t time = ldq(a1);
-
-    if (time == -1ULL) {
-        return;
-    }
-
-    /* difference between now and then */
-    time -= clock_value(env);
-    /* nanoseconds */
-    time = (time * 125) >> 9;
-
-    qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time);
-}
-
-/* Store Clock Comparator */
-void HELPER(stckc)(uint64_t a1)
-{
-    /* XXX implement */
-    stq(a1, 0);
-}
-
-/* Set CPU Timer */
-void HELPER(spt)(uint64_t a1)
-{
-    uint64_t time = ldq(a1);
-
-    if (time == -1ULL) {
-        return;
-    }
-
-    /* nanoseconds */
-    time = (time * 125) >> 9;
-
-    qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time);
-}
-
-/* Store CPU Timer */
-void HELPER(stpt)(uint64_t a1)
-{
-    /* XXX implement */
-    stq(a1, 0);
-}
-
-/* Store System Information */
-uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
-{
-    int cc = 0;
-    int sel1, sel2;
-
-    if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 &&
-        ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) {
-        /* valid function code, invalid reserved bits */
-        program_interrupt(env, PGM_SPECIFICATION, 2);
-    }
-
-    sel1 = r0 & STSI_R0_SEL1_MASK;
-    sel2 = r1 & STSI_R1_SEL2_MASK;
-
-    /* XXX: spec exception if sysib is not 4k-aligned */
-
-    switch (r0 & STSI_LEVEL_MASK) {
-    case STSI_LEVEL_1:
-        if ((sel1 == 1) && (sel2 == 1)) {
-            /* Basic Machine Configuration */
-            struct sysib_111 sysib;
-
-            memset(&sysib, 0, sizeof(sysib));
-            ebcdic_put(sysib.manuf, "QEMU            ", 16);
-            /* same as machine type number in STORE CPU ID */
-            ebcdic_put(sysib.type, "QEMU", 4);
-            /* same as model number in STORE CPU ID */
-            ebcdic_put(sysib.model, "QEMU            ", 16);
-            ebcdic_put(sysib.sequence, "QEMU            ", 16);
-            ebcdic_put(sysib.plant, "QEMU", 4);
-            cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
-        } else if ((sel1 == 2) && (sel2 == 1)) {
-            /* Basic Machine CPU */
-            struct sysib_121 sysib;
-
-            memset(&sysib, 0, sizeof(sysib));
-            /* XXX make different for different CPUs? */
-            ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
-            ebcdic_put(sysib.plant, "QEMU", 4);
-            stw_p(&sysib.cpu_addr, env->cpu_num);
-            cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
-        } else if ((sel1 == 2) && (sel2 == 2)) {
-            /* Basic Machine CPUs */
-            struct sysib_122 sysib;
-
-            memset(&sysib, 0, sizeof(sysib));
-            stl_p(&sysib.capability, 0x443afc29);
-            /* XXX change when SMP comes */
-            stw_p(&sysib.total_cpus, 1);
-            stw_p(&sysib.active_cpus, 1);
-            stw_p(&sysib.standby_cpus, 0);
-            stw_p(&sysib.reserved_cpus, 0);
-            cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
-        } else {
-            cc = 3;
-        }
-        break;
-    case STSI_LEVEL_2:
-        {
-            if ((sel1 == 2) && (sel2 == 1)) {
-                /* LPAR CPU */
-                struct sysib_221 sysib;
-
-                memset(&sysib, 0, sizeof(sysib));
-                /* XXX make different for different CPUs? */
-                ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
-                ebcdic_put(sysib.plant, "QEMU", 4);
-                stw_p(&sysib.cpu_addr, env->cpu_num);
-                stw_p(&sysib.cpu_id, 0);
-                cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
-            } else if ((sel1 == 2) && (sel2 == 2)) {
-                /* LPAR CPUs */
-                struct sysib_222 sysib;
-
-                memset(&sysib, 0, sizeof(sysib));
-                stw_p(&sysib.lpar_num, 0);
-                sysib.lcpuc = 0;
-                /* XXX change when SMP comes */
-                stw_p(&sysib.total_cpus, 1);
-                stw_p(&sysib.conf_cpus, 1);
-                stw_p(&sysib.standby_cpus, 0);
-                stw_p(&sysib.reserved_cpus, 0);
-                ebcdic_put(sysib.name, "QEMU    ", 8);
-                stl_p(&sysib.caf, 1000);
-                stw_p(&sysib.dedicated_cpus, 0);
-                stw_p(&sysib.shared_cpus, 0);
-                cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
-            } else {
-                cc = 3;
-            }
-            break;
-        }
-    case STSI_LEVEL_3:
-        {
-            if ((sel1 == 2) && (sel2 == 2)) {
-                /* VM CPUs */
-                struct sysib_322 sysib;
-
-                memset(&sysib, 0, sizeof(sysib));
-                sysib.count = 1;
-                /* XXX change when SMP comes */
-                stw_p(&sysib.vm[0].total_cpus, 1);
-                stw_p(&sysib.vm[0].conf_cpus, 1);
-                stw_p(&sysib.vm[0].standby_cpus, 0);
-                stw_p(&sysib.vm[0].reserved_cpus, 0);
-                ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
-                stl_p(&sysib.vm[0].caf, 1000);
-                ebcdic_put(sysib.vm[0].cpi, "KVM/Linux       ", 16);
-                cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
-            } else {
-                cc = 3;
-            }
-            break;
-        }
-    case STSI_LEVEL_CURRENT:
-        env->regs[0] = STSI_LEVEL_3;
-        break;
-    default:
-        cc = 3;
-        break;
-    }
-
-    return cc;
-}
-
-uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
-{
-    int cc = 0;
-
-    HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
-               __func__, order_code, r1, cpu_addr);
-
-    /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register"
-       as parameter (input). Status (output) is always R1. */
-
-    switch (order_code) {
-    case SIGP_SET_ARCH:
-        /* switch arch */
-        break;
-    case SIGP_SENSE:
-        /* enumerate CPU status */
-        if (cpu_addr) {
-            /* XXX implement when SMP comes */
-            return 3;
-        }
-        env->regs[r1] &= 0xffffffff00000000ULL;
-        cc = 1;
-        break;
-#if !defined(CONFIG_USER_ONLY)
-    case SIGP_RESTART:
-        qemu_system_reset_request();
-        cpu_loop_exit(env);
-        break;
-    case SIGP_STOP:
-        qemu_system_shutdown_request();
-        cpu_loop_exit(env);
-        break;
-#endif
-    default:
-        /* unknown sigp */
-        fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
-        cc = 3;
-    }
-
-    return cc;
-}
-#endif
commit 8ef7f78e190b3a34e167a31c9a8e43c813c7ff78
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 2 07:33:34 2012 +0000

    target-s390x: split memory access helpers
    
    Move memory access helpers to mem_helper.c.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    [agraf: fold softmmu include ifdefs together]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index e8f66e9..b9b3061 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -1,5 +1,5 @@
 obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o
-obj-y += int_helper.o fpu_helper.o cc_helper.o
+obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
 
@@ -7,3 +7,4 @@ $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+$(obj)/mem_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
new file mode 100644
index 0000000..ba05e65
--- /dev/null
+++ b/target-s390x/mem_helper.c
@@ -0,0 +1,1190 @@
+/*
+ *  S/390 memory access helper routines
+ *
+ *  Copyright (c) 2009 Ulrich Hecht
+ *  Copyright (c) 2009 Alexander Graf
+ *
+ * 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"
+
+/*****************************************************************************/
+/* Softmmu support */
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+
+#define MMUSUFFIX _mmu
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+
+/* try to fill the TLB and return an exception if error. If retaddr is
+   NULL, it means that the function was called in C code (i.e. not
+   from generated code or from helper.c) */
+/* XXX: fix it to restore all registers */
+void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx,
+              uintptr_t retaddr)
+{
+    TranslationBlock *tb;
+    CPUS390XState *saved_env;
+    int ret;
+
+    saved_env = env;
+    env = env1;
+    ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx);
+    if (unlikely(ret != 0)) {
+        if (likely(retaddr)) {
+            /* now we have a real cpu fault */
+            tb = tb_find_pc(retaddr);
+            if (likely(tb)) {
+                /* the PC is inside the translated code. It means that we have
+                   a virtual CPU fault */
+                cpu_restore_state(tb, env, retaddr);
+            }
+        }
+        cpu_loop_exit(env);
+    }
+    env = saved_env;
+}
+
+#endif
+
+/* #define DEBUG_HELPER */
+#ifdef DEBUG_HELPER
+#define HELPER_LOG(x...) qemu_log(x)
+#else
+#define HELPER_LOG(x...)
+#endif
+
+#ifndef CONFIG_USER_ONLY
+static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest,
+                            uint8_t byte)
+{
+    target_phys_addr_t dest_phys;
+    target_phys_addr_t len = l;
+    void *dest_p;
+    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
+    int flags;
+
+    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
+        stb(dest, byte);
+        cpu_abort(env, "should never reach here");
+    }
+    dest_phys |= dest & ~TARGET_PAGE_MASK;
+
+    dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
+
+    memset(dest_p, byte, len);
+
+    cpu_physical_memory_unmap(dest_p, 1, len, len);
+}
+
+static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest,
+                             uint64_t src)
+{
+    target_phys_addr_t dest_phys;
+    target_phys_addr_t src_phys;
+    target_phys_addr_t len = l;
+    void *dest_p;
+    void *src_p;
+    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
+    int flags;
+
+    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
+        stb(dest, 0);
+        cpu_abort(env, "should never reach here");
+    }
+    dest_phys |= dest & ~TARGET_PAGE_MASK;
+
+    if (mmu_translate(env, src, 0, asc, &src_phys, &flags)) {
+        ldub(src);
+        cpu_abort(env, "should never reach here");
+    }
+    src_phys |= src & ~TARGET_PAGE_MASK;
+
+    dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
+    src_p = cpu_physical_memory_map(src_phys, &len, 0);
+
+    memmove(dest_p, src_p, len);
+
+    cpu_physical_memory_unmap(dest_p, 1, len, len);
+    cpu_physical_memory_unmap(src_p, 0, len, len);
+}
+#endif
+
+/* and on array */
+uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src)
+{
+    int i;
+    unsigned char x;
+    uint32_t cc = 0;
+
+    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
+               __func__, l, dest, src);
+    for (i = 0; i <= l; i++) {
+        x = ldub(dest + i) & ldub(src + i);
+        if (x) {
+            cc = 1;
+        }
+        stb(dest + i, x);
+    }
+    return cc;
+}
+
+/* xor on array */
+uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src)
+{
+    int i;
+    unsigned char x;
+    uint32_t cc = 0;
+
+    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
+               __func__, l, dest, src);
+
+#ifndef CONFIG_USER_ONLY
+    /* xor with itself is the same as memset(0) */
+    if ((l > 32) && (src == dest) &&
+        (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK)) {
+        mvc_fast_memset(env, l + 1, dest, 0);
+        return 0;
+    }
+#else
+    if (src == dest) {
+        memset(g2h(dest), 0, l + 1);
+        return 0;
+    }
+#endif
+
+    for (i = 0; i <= l; i++) {
+        x = ldub(dest + i) ^ ldub(src + i);
+        if (x) {
+            cc = 1;
+        }
+        stb(dest + i, x);
+    }
+    return cc;
+}
+
+/* or on array */
+uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src)
+{
+    int i;
+    unsigned char x;
+    uint32_t cc = 0;
+
+    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
+               __func__, l, dest, src);
+    for (i = 0; i <= l; i++) {
+        x = ldub(dest + i) | ldub(src + i);
+        if (x) {
+            cc = 1;
+        }
+        stb(dest + i, x);
+    }
+    return cc;
+}
+
+/* memmove */
+void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src)
+{
+    int i = 0;
+    int x = 0;
+    uint32_t l_64 = (l + 1) / 8;
+
+    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
+               __func__, l, dest, src);
+
+#ifndef CONFIG_USER_ONLY
+    if ((l > 32) &&
+        (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) &&
+        (dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) {
+        if (dest == (src + 1)) {
+            mvc_fast_memset(env, l + 1, dest, ldub(src));
+            return;
+        } else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
+            mvc_fast_memmove(env, l + 1, dest, src);
+            return;
+        }
+    }
+#else
+    if (dest == (src + 1)) {
+        memset(g2h(dest), ldub(src), l + 1);
+        return;
+    } else {
+        memmove(g2h(dest), g2h(src), l + 1);
+        return;
+    }
+#endif
+
+    /* handle the parts that fit into 8-byte loads/stores */
+    if (dest != (src + 1)) {
+        for (i = 0; i < l_64; i++) {
+            stq(dest + x, ldq(src + x));
+            x += 8;
+        }
+    }
+
+    /* slow version crossing pages with byte accesses */
+    for (i = x; i <= l; i++) {
+        stb(dest + i, ldub(src + i));
+    }
+}
+
+/* compare unsigned byte arrays */
+uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2)
+{
+    int i;
+    unsigned char x, y;
+    uint32_t cc;
+
+    HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n",
+               __func__, l, s1, s2);
+    for (i = 0; i <= l; i++) {
+        x = ldub(s1 + i);
+        y = ldub(s2 + i);
+        HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y);
+        if (x < y) {
+            cc = 1;
+            goto done;
+        } else if (x > y) {
+            cc = 2;
+            goto done;
+        }
+    }
+    cc = 0;
+ done:
+    HELPER_LOG("\n");
+    return cc;
+}
+
+/* compare logical under mask */
+uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr)
+{
+    uint8_t r, d;
+    uint32_t cc;
+
+    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1,
+               mask, addr);
+    cc = 0;
+    while (mask) {
+        if (mask & 8) {
+            d = ldub(addr);
+            r = (r1 & 0xff000000UL) >> 24;
+            HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d,
+                       addr);
+            if (r < d) {
+                cc = 1;
+                break;
+            } else if (r > d) {
+                cc = 2;
+                break;
+            }
+            addr++;
+        }
+        mask = (mask << 1) & 0xf;
+        r1 <<= 8;
+    }
+    HELPER_LOG("\n");
+    return cc;
+}
+
+/* store character under mask */
+void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr)
+{
+    uint8_t r;
+
+    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __func__, r1, mask,
+               addr);
+    while (mask) {
+        if (mask & 8) {
+            r = (r1 & 0xff000000UL) >> 24;
+            stb(addr, r);
+            HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr);
+            addr++;
+        }
+        mask = (mask << 1) & 0xf;
+        r1 <<= 8;
+    }
+    HELPER_LOG("\n");
+}
+
+static inline uint64_t get_address(int x2, int b2, int d2)
+{
+    uint64_t r = d2;
+
+    if (x2) {
+        r += env->regs[x2];
+    }
+
+    if (b2) {
+        r += env->regs[b2];
+    }
+
+    /* 31-Bit mode */
+    if (!(env->psw.mask & PSW_MASK_64)) {
+        r &= 0x7fffffff;
+    }
+
+    return r;
+}
+
+static inline uint64_t get_address_31fix(int reg)
+{
+    uint64_t r = env->regs[reg];
+
+    /* 31-Bit mode */
+    if (!(env->psw.mask & PSW_MASK_64)) {
+        r &= 0x7fffffff;
+    }
+
+    return r;
+}
+
+/* search string (c is byte to search, r2 is string, r1 end of string) */
+uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2)
+{
+    uint64_t i;
+    uint32_t cc = 2;
+    uint64_t str = get_address_31fix(r2);
+    uint64_t end = get_address_31fix(r1);
+
+    HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __func__,
+               c, env->regs[r1], env->regs[r2]);
+
+    for (i = str; i != end; i++) {
+        if (ldub(i) == c) {
+            env->regs[r1] = i;
+            cc = 1;
+            break;
+        }
+    }
+
+    return cc;
+}
+
+/* unsigned string compare (c is string terminator) */
+uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2)
+{
+    uint64_t s1 = get_address_31fix(r1);
+    uint64_t s2 = get_address_31fix(r2);
+    uint8_t v1, v2;
+    uint32_t cc;
+
+    c = c & 0xff;
+#ifdef CONFIG_USER_ONLY
+    if (!c) {
+        HELPER_LOG("%s: comparing '%s' and '%s'\n",
+                   __func__, (char *)g2h(s1), (char *)g2h(s2));
+    }
+#endif
+    for (;;) {
+        v1 = ldub(s1);
+        v2 = ldub(s2);
+        if ((v1 == c || v2 == c) || (v1 != v2)) {
+            break;
+        }
+        s1++;
+        s2++;
+    }
+
+    if (v1 == v2) {
+        cc = 0;
+    } else {
+        cc = (v1 < v2) ? 1 : 2;
+        /* FIXME: 31-bit mode! */
+        env->regs[r1] = s1;
+        env->regs[r2] = s2;
+    }
+    return cc;
+}
+
+/* move page */
+void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2)
+{
+    /* XXX missing r0 handling */
+#ifdef CONFIG_USER_ONLY
+    int i;
+
+    for (i = 0; i < TARGET_PAGE_SIZE; i++) {
+        stb(r1 + i, ldub(r2 + i));
+    }
+#else
+    mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2);
+#endif
+}
+
+/* string copy (c is string terminator) */
+void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2)
+{
+    uint64_t dest = get_address_31fix(r1);
+    uint64_t src = get_address_31fix(r2);
+    uint8_t v;
+
+    c = c & 0xff;
+#ifdef CONFIG_USER_ONLY
+    if (!c) {
+        HELPER_LOG("%s: copy '%s' to 0x%lx\n", __func__, (char *)g2h(src),
+                   dest);
+    }
+#endif
+    for (;;) {
+        v = ldub(src);
+        stb(dest, v);
+        if (v == c) {
+            break;
+        }
+        src++;
+        dest++;
+    }
+    env->regs[r1] = dest; /* FIXME: 31-bit mode! */
+}
+
+/* compare and swap 64-bit */
+uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    /* FIXME: locking? */
+    uint32_t cc;
+    uint64_t v2 = ldq(a2);
+
+    if (env->regs[r1] == v2) {
+        cc = 0;
+        stq(a2, env->regs[r3]);
+    } else {
+        cc = 1;
+        env->regs[r1] = v2;
+    }
+    return cc;
+}
+
+/* compare double and swap 64-bit */
+uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    /* FIXME: locking? */
+    uint32_t cc;
+    uint64_t v2_hi = ldq(a2);
+    uint64_t v2_lo = ldq(a2 + 8);
+    uint64_t v1_hi = env->regs[r1];
+    uint64_t v1_lo = env->regs[r1 + 1];
+
+    if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) {
+        cc = 0;
+        stq(a2, env->regs[r3]);
+        stq(a2 + 8, env->regs[r3 + 1]);
+    } else {
+        cc = 1;
+        env->regs[r1] = v2_hi;
+        env->regs[r1 + 1] = v2_lo;
+    }
+
+    return cc;
+}
+
+/* compare and swap 32-bit */
+uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    /* FIXME: locking? */
+    uint32_t cc;
+    uint32_t v2 = ldl(a2);
+
+    HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __func__, r1, a2, r3);
+    if (((uint32_t)env->regs[r1]) == v2) {
+        cc = 0;
+        stl(a2, (uint32_t)env->regs[r3]);
+    } else {
+        cc = 1;
+        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2;
+    }
+    return cc;
+}
+
+static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask)
+{
+    int pos = 24; /* top of the lower half of r1 */
+    uint64_t rmask = 0xff000000ULL;
+    uint8_t val = 0;
+    int ccd = 0;
+    uint32_t cc = 0;
+
+    while (mask) {
+        if (mask & 8) {
+            env->regs[r1] &= ~rmask;
+            val = ldub(address);
+            if ((val & 0x80) && !ccd) {
+                cc = 1;
+            }
+            ccd = 1;
+            if (val && cc == 0) {
+                cc = 2;
+            }
+            env->regs[r1] |= (uint64_t)val << pos;
+            address++;
+        }
+        mask = (mask << 1) & 0xf;
+        pos -= 8;
+        rmask >>= 8;
+    }
+
+    return cc;
+}
+
+/* execute instruction
+   this instruction executes an insn modified with the contents of r1
+   it does not change the executed instruction in memory
+   it does not change the program counter
+   in other words: tricky...
+   currently implemented by interpreting the cases it is most commonly used in
+*/
+uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
+{
+    uint16_t insn = lduw_code(addr);
+
+    HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr,
+               insn);
+    if ((insn & 0xf0ff) == 0xd000) {
+        uint32_t l, insn2, b1, b2, d1, d2;
+
+        l = v1 & 0xff;
+        insn2 = ldl_code(addr + 2);
+        b1 = (insn2 >> 28) & 0xf;
+        b2 = (insn2 >> 12) & 0xf;
+        d1 = (insn2 >> 16) & 0xfff;
+        d2 = insn2 & 0xfff;
+        switch (insn & 0xf00) {
+        case 0x200:
+            helper_mvc(l, get_address(0, b1, d1), get_address(0, b2, d2));
+            break;
+        case 0x500:
+            cc = helper_clc(l, get_address(0, b1, d1), get_address(0, b2, d2));
+            break;
+        case 0x700:
+            cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2));
+            break;
+        case 0xc00:
+            helper_tr(l, get_address(0, b1, d1), get_address(0, b2, d2));
+            break;
+        default:
+            goto abort;
+            break;
+        }
+    } else if ((insn & 0xff00) == 0x0a00) {
+        /* supervisor call */
+        HELPER_LOG("%s: svc %ld via execute\n", __func__, (insn | v1) & 0xff);
+        env->psw.addr = ret - 4;
+        env->int_svc_code = (insn | v1) & 0xff;
+        env->int_svc_ilc = 4;
+        helper_exception(EXCP_SVC);
+    } else if ((insn & 0xff00) == 0xbf00) {
+        uint32_t insn2, r1, r3, b2, d2;
+
+        insn2 = ldl_code(addr + 2);
+        r1 = (insn2 >> 20) & 0xf;
+        r3 = (insn2 >> 16) & 0xf;
+        b2 = (insn2 >> 12) & 0xf;
+        d2 = insn2 & 0xfff;
+        cc = helper_icm(r1, get_address(0, b2, d2), r3);
+    } else {
+    abort:
+        cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n",
+                  insn);
+    }
+    return cc;
+}
+
+/* store character under mask high operates on the upper half of r1 */
+void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask)
+{
+    int pos = 56; /* top of the upper half of r1 */
+
+    while (mask) {
+        if (mask & 8) {
+            stb(address, (env->regs[r1] >> pos) & 0xff);
+            address++;
+        }
+        mask = (mask << 1) & 0xf;
+        pos -= 8;
+    }
+}
+
+/* insert character under mask high; same as icm, but operates on the
+   upper half of r1 */
+uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask)
+{
+    int pos = 56; /* top of the upper half of r1 */
+    uint64_t rmask = 0xff00000000000000ULL;
+    uint8_t val = 0;
+    int ccd = 0;
+    uint32_t cc = 0;
+
+    while (mask) {
+        if (mask & 8) {
+            env->regs[r1] &= ~rmask;
+            val = ldub(address);
+            if ((val & 0x80) && !ccd) {
+                cc = 1;
+            }
+            ccd = 1;
+            if (val && cc == 0) {
+                cc = 2;
+            }
+            env->regs[r1] |= (uint64_t)val << pos;
+            address++;
+        }
+        mask = (mask << 1) & 0xf;
+        pos -= 8;
+        rmask >>= 8;
+    }
+
+    return cc;
+}
+
+/* load access registers r1 to r3 from memory at a2 */
+void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    int i;
+
+    for (i = r1;; i = (i + 1) % 16) {
+        env->aregs[i] = ldl(a2);
+        a2 += 4;
+
+        if (i == r3) {
+            break;
+        }
+    }
+}
+
+/* store access registers r1 to r3 in memory at a2 */
+void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    int i;
+
+    for (i = r1;; i = (i + 1) % 16) {
+        stl(a2, env->aregs[i]);
+        a2 += 4;
+
+        if (i == r3) {
+            break;
+        }
+    }
+}
+
+/* move long */
+uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2)
+{
+    uint64_t destlen = env->regs[r1 + 1] & 0xffffff;
+    uint64_t dest = get_address_31fix(r1);
+    uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
+    uint64_t src = get_address_31fix(r2);
+    uint8_t pad = src >> 24;
+    uint8_t v;
+    uint32_t cc;
+
+    if (destlen == srclen) {
+        cc = 0;
+    } else if (destlen < srclen) {
+        cc = 1;
+    } else {
+        cc = 2;
+    }
+
+    if (srclen > destlen) {
+        srclen = destlen;
+    }
+
+    for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
+        v = ldub(src);
+        stb(dest, v);
+    }
+
+    for (; destlen; dest++, destlen--) {
+        stb(dest, pad);
+    }
+
+    env->regs[r1 + 1] = destlen;
+    /* can't use srclen here, we trunc'ed it */
+    env->regs[r2 + 1] -= src - env->regs[r2];
+    env->regs[r1] = dest;
+    env->regs[r2] = src;
+
+    return cc;
+}
+
+/* move long extended another memcopy insn with more bells and whistles */
+uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    uint64_t destlen = env->regs[r1 + 1];
+    uint64_t dest = env->regs[r1];
+    uint64_t srclen = env->regs[r3 + 1];
+    uint64_t src = env->regs[r3];
+    uint8_t pad = a2 & 0xff;
+    uint8_t v;
+    uint32_t cc;
+
+    if (!(env->psw.mask & PSW_MASK_64)) {
+        destlen = (uint32_t)destlen;
+        srclen = (uint32_t)srclen;
+        dest &= 0x7fffffff;
+        src &= 0x7fffffff;
+    }
+
+    if (destlen == srclen) {
+        cc = 0;
+    } else if (destlen < srclen) {
+        cc = 1;
+    } else {
+        cc = 2;
+    }
+
+    if (srclen > destlen) {
+        srclen = destlen;
+    }
+
+    for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
+        v = ldub(src);
+        stb(dest, v);
+    }
+
+    for (; destlen; dest++, destlen--) {
+        stb(dest, pad);
+    }
+
+    env->regs[r1 + 1] = destlen;
+    /* can't use srclen here, we trunc'ed it */
+    /* FIXME: 31-bit mode! */
+    env->regs[r3 + 1] -= src - env->regs[r3];
+    env->regs[r1] = dest;
+    env->regs[r3] = src;
+
+    return cc;
+}
+
+/* compare logical long extended memcompare insn with padding */
+uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    uint64_t destlen = env->regs[r1 + 1];
+    uint64_t dest = get_address_31fix(r1);
+    uint64_t srclen = env->regs[r3 + 1];
+    uint64_t src = get_address_31fix(r3);
+    uint8_t pad = a2 & 0xff;
+    uint8_t v1 = 0, v2 = 0;
+    uint32_t cc = 0;
+
+    if (!(destlen || srclen)) {
+        return cc;
+    }
+
+    if (srclen > destlen) {
+        srclen = destlen;
+    }
+
+    for (; destlen || srclen; src++, dest++, destlen--, srclen--) {
+        v1 = srclen ? ldub(src) : pad;
+        v2 = destlen ? ldub(dest) : pad;
+        if (v1 != v2) {
+            cc = (v1 < v2) ? 1 : 2;
+            break;
+        }
+    }
+
+    env->regs[r1 + 1] = destlen;
+    /* can't use srclen here, we trunc'ed it */
+    env->regs[r3 + 1] -= src - env->regs[r3];
+    env->regs[r1] = dest;
+    env->regs[r3] = src;
+
+    return cc;
+}
+
+/* checksum */
+void HELPER(cksm)(uint32_t r1, uint32_t r2)
+{
+    uint64_t src = get_address_31fix(r2);
+    uint64_t src_len = env->regs[(r2 + 1) & 15];
+    uint64_t cksm = (uint32_t)env->regs[r1];
+
+    while (src_len >= 4) {
+        cksm += ldl(src);
+
+        /* move to next word */
+        src_len -= 4;
+        src += 4;
+    }
+
+    switch (src_len) {
+    case 0:
+        break;
+    case 1:
+        cksm += ldub(src) << 24;
+        break;
+    case 2:
+        cksm += lduw(src) << 16;
+        break;
+    case 3:
+        cksm += lduw(src) << 16;
+        cksm += ldub(src + 2) << 8;
+        break;
+    }
+
+    /* indicate we've processed everything */
+    env->regs[r2] = src + src_len;
+    env->regs[(r2 + 1) & 15] = 0;
+
+    /* store result */
+    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
+        ((uint32_t)cksm + (cksm >> 32));
+}
+
+void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
+{
+    int len_dest = len >> 4;
+    int len_src = len & 0xf;
+    uint8_t b;
+    int second_nibble = 0;
+
+    dest += len_dest;
+    src += len_src;
+
+    /* last byte is special, it only flips the nibbles */
+    b = ldub(src);
+    stb(dest, (b << 4) | (b >> 4));
+    src--;
+    len_src--;
+
+    /* now pad every nibble with 0xf0 */
+
+    while (len_dest > 0) {
+        uint8_t cur_byte = 0;
+
+        if (len_src > 0) {
+            cur_byte = ldub(src);
+        }
+
+        len_dest--;
+        dest--;
+
+        /* only advance one nibble at a time */
+        if (second_nibble) {
+            cur_byte >>= 4;
+            len_src--;
+            src--;
+        }
+        second_nibble = !second_nibble;
+
+        /* digit */
+        cur_byte = (cur_byte & 0xf);
+        /* zone bits */
+        cur_byte |= 0xf0;
+
+        stb(dest, cur_byte);
+    }
+}
+
+void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans)
+{
+    int i;
+
+    for (i = 0; i <= len; i++) {
+        uint8_t byte = ldub(array + i);
+        uint8_t new_byte = ldub(trans + byte);
+
+        stb(array + i, new_byte);
+    }
+}
+
+#if !defined(CONFIG_USER_ONLY)
+void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    int i;
+    uint64_t src = a2;
+
+    for (i = r1;; i = (i + 1) % 16) {
+        env->cregs[i] = ldq(src);
+        HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n",
+                   i, src, env->cregs[i]);
+        src += sizeof(uint64_t);
+
+        if (i == r3) {
+            break;
+        }
+    }
+
+    tlb_flush(env, 1);
+}
+
+void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    int i;
+    uint64_t src = a2;
+
+    for (i = r1;; i = (i + 1) % 16) {
+        env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | ldl(src);
+        src += sizeof(uint32_t);
+
+        if (i == r3) {
+            break;
+        }
+    }
+
+    tlb_flush(env, 1);
+}
+
+void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    int i;
+    uint64_t dest = a2;
+
+    for (i = r1;; i = (i + 1) % 16) {
+        stq(dest, env->cregs[i]);
+        dest += sizeof(uint64_t);
+
+        if (i == r3) {
+            break;
+        }
+    }
+}
+
+void HELPER(stctl)(uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    int i;
+    uint64_t dest = a2;
+
+    for (i = r1;; i = (i + 1) % 16) {
+        stl(dest, env->cregs[i]);
+        dest += sizeof(uint32_t);
+
+        if (i == r3) {
+            break;
+        }
+    }
+}
+
+uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2)
+{
+    /* XXX implement */
+
+    return 0;
+}
+
+/* insert storage key extended */
+uint64_t HELPER(iske)(uint64_t r2)
+{
+    uint64_t addr = get_address(0, 0, r2);
+
+    if (addr > ram_size) {
+        return 0;
+    }
+
+    return env->storage_keys[addr / TARGET_PAGE_SIZE];
+}
+
+/* set storage key extended */
+void HELPER(sske)(uint32_t r1, uint64_t r2)
+{
+    uint64_t addr = get_address(0, 0, r2);
+
+    if (addr > ram_size) {
+        return;
+    }
+
+    env->storage_keys[addr / TARGET_PAGE_SIZE] = r1;
+}
+
+/* reset reference bit extended */
+uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
+{
+    uint8_t re;
+    uint8_t key;
+
+    if (r2 > ram_size) {
+        return 0;
+    }
+
+    key = env->storage_keys[r2 / TARGET_PAGE_SIZE];
+    re = key & (SK_R | SK_C);
+    env->storage_keys[r2 / TARGET_PAGE_SIZE] = (key & ~SK_R);
+
+    /*
+     * cc
+     *
+     * 0  Reference bit zero; change bit zero
+     * 1  Reference bit zero; change bit one
+     * 2  Reference bit one; change bit zero
+     * 3  Reference bit one; change bit one
+     */
+
+    return re >> 1;
+}
+
+/* compare and swap and purge */
+uint32_t HELPER(csp)(uint32_t r1, uint32_t r2)
+{
+    uint32_t cc;
+    uint32_t o1 = env->regs[r1];
+    uint64_t a2 = get_address_31fix(r2) & ~3ULL;
+    uint32_t o2 = ldl(a2);
+
+    if (o1 == o2) {
+        stl(a2, env->regs[(r1 + 1) & 15]);
+        if (env->regs[r2] & 0x3) {
+            /* flush TLB / ALB */
+            tlb_flush(env, 1);
+        }
+        cc = 0;
+    } else {
+        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | o2;
+        cc = 1;
+    }
+
+    return cc;
+}
+
+static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2,
+                        uint64_t mode2)
+{
+    target_ulong src, dest;
+    int flags, cc = 0, i;
+
+    if (!l) {
+        return 0;
+    } else if (l > 256) {
+        /* max 256 */
+        l = 256;
+        cc = 3;
+    }
+
+    if (mmu_translate(env, a1 & TARGET_PAGE_MASK, 1, mode1, &dest, &flags)) {
+        cpu_loop_exit(env);
+    }
+    dest |= a1 & ~TARGET_PAGE_MASK;
+
+    if (mmu_translate(env, a2 & TARGET_PAGE_MASK, 0, mode2, &src, &flags)) {
+        cpu_loop_exit(env);
+    }
+    src |= a2 & ~TARGET_PAGE_MASK;
+
+    /* XXX replace w/ memcpy */
+    for (i = 0; i < l; i++) {
+        /* XXX be more clever */
+        if ((((dest + i) & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) ||
+            (((src + i) & TARGET_PAGE_MASK) != (src & TARGET_PAGE_MASK))) {
+            mvc_asc(l - i, a1 + i, mode1, a2 + i, mode2);
+            break;
+        }
+        stb_phys(dest + i, ldub_phys(src + i));
+    }
+
+    return cc;
+}
+
+uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2)
+{
+    HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
+               __func__, l, a1, a2);
+
+    return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY);
+}
+
+uint32_t HELPER(mvcp)(uint64_t l, uint64_t a1, uint64_t a2)
+{
+    HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
+               __func__, l, a1, a2);
+
+    return mvc_asc(l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY);
+}
+
+/* invalidate pte */
+void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
+{
+    uint64_t page = vaddr & TARGET_PAGE_MASK;
+    uint64_t pte = 0;
+
+    /* XXX broadcast to other CPUs */
+
+    /* XXX Linux is nice enough to give us the exact pte address.
+       According to spec we'd have to find it out ourselves */
+    /* XXX Linux is fine with overwriting the pte, the spec requires
+       us to only set the invalid bit */
+    stq_phys(pte_addr, pte | _PAGE_INVALID);
+
+    /* XXX we exploit the fact that Linux passes the exact virtual
+       address here - it's not obliged to! */
+    tlb_flush_page(env, page);
+
+    /* XXX 31-bit hack */
+    if (page & 0x80000000) {
+        tlb_flush_page(env, page & ~0x80000000);
+    } else {
+        tlb_flush_page(env, page | 0x80000000);
+    }
+}
+
+/* flush local tlb */
+void HELPER(ptlb)(void)
+{
+    tlb_flush(env, 1);
+}
+
+/* store using real address */
+void HELPER(stura)(uint64_t addr, uint32_t v1)
+{
+    stw_phys(get_address(0, 0, addr), v1);
+}
+
+/* load real address */
+uint32_t HELPER(lra)(uint64_t addr, uint32_t r1)
+{
+    uint32_t cc = 0;
+    int old_exc = env->exception_index;
+    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
+    uint64_t ret;
+    int flags;
+
+    /* XXX incomplete - has more corner cases */
+    if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) {
+        program_interrupt(env, PGM_SPECIAL_OP, 2);
+    }
+
+    env->exception_index = old_exc;
+    if (mmu_translate(env, addr, 0, asc, &ret, &flags)) {
+        cc = 3;
+    }
+    if (env->exception_index == EXCP_PGM) {
+        ret = env->int_pgm_code | 0x80000000;
+    } else {
+        ret |= addr & ~TARGET_PAGE_MASK;
+    }
+    env->exception_index = old_exc;
+
+    if (!(env->psw.mask & PSW_MASK_64)) {
+        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
+            (ret & 0xffffffffULL);
+    } else {
+        env->regs[r1] = ret;
+    }
+
+    return cc;
+}
+
+#endif
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 3b8b997..bb8dbf5 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -32,57 +32,8 @@
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
-#include "sysemu.h"
-#endif
-
-/*****************************************************************************/
-/* Softmmu support */
-#if !defined(CONFIG_USER_ONLY)
 #include "softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "softmmu_template.h"
-
-#define SHIFT 1
-#include "softmmu_template.h"
-
-#define SHIFT 2
-#include "softmmu_template.h"
-
-#define SHIFT 3
-#include "softmmu_template.h"
-
-/* try to fill the TLB and return an exception if error. If retaddr is
-   NULL, it means that the function was called in C code (i.e. not
-   from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx,
-              uintptr_t retaddr)
-{
-    TranslationBlock *tb;
-    CPUS390XState *saved_env;
-    int ret;
-
-    saved_env = env;
-    env = env1;
-    ret = cpu_s390x_handle_mmu_fault(env, addr, is_write, mmu_idx);
-    if (unlikely(ret != 0)) {
-        if (likely(retaddr)) {
-            /* now we have a real cpu fault */
-            tb = tb_find_pc(retaddr);
-            if (likely(tb)) {
-                /* the PC is inside the translated code. It means that we have
-                   a virtual CPU fault */
-                cpu_restore_state(tb, env, retaddr);
-            }
-        }
-        cpu_loop_exit(env);
-    }
-    env = saved_env;
-}
-
+#include "sysemu.h"
 #endif
 
 /* #define DEBUG_HELPER */
@@ -101,840 +52,6 @@ void HELPER(exception)(uint32_t excp)
 }
 
 #ifndef CONFIG_USER_ONLY
-static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest,
-                            uint8_t byte)
-{
-    target_phys_addr_t dest_phys;
-    target_phys_addr_t len = l;
-    void *dest_p;
-    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
-    int flags;
-
-    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
-        stb(dest, byte);
-        cpu_abort(env, "should never reach here");
-    }
-    dest_phys |= dest & ~TARGET_PAGE_MASK;
-
-    dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
-
-    memset(dest_p, byte, len);
-
-    cpu_physical_memory_unmap(dest_p, 1, len, len);
-}
-
-static void mvc_fast_memmove(CPUS390XState *env, uint32_t l, uint64_t dest,
-                             uint64_t src)
-{
-    target_phys_addr_t dest_phys;
-    target_phys_addr_t src_phys;
-    target_phys_addr_t len = l;
-    void *dest_p;
-    void *src_p;
-    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
-    int flags;
-
-    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {
-        stb(dest, 0);
-        cpu_abort(env, "should never reach here");
-    }
-    dest_phys |= dest & ~TARGET_PAGE_MASK;
-
-    if (mmu_translate(env, src, 0, asc, &src_phys, &flags)) {
-        ldub(src);
-        cpu_abort(env, "should never reach here");
-    }
-    src_phys |= src & ~TARGET_PAGE_MASK;
-
-    dest_p = cpu_physical_memory_map(dest_phys, &len, 1);
-    src_p = cpu_physical_memory_map(src_phys, &len, 0);
-
-    memmove(dest_p, src_p, len);
-
-    cpu_physical_memory_unmap(dest_p, 1, len, len);
-    cpu_physical_memory_unmap(src_p, 0, len, len);
-}
-#endif
-
-/* and on array */
-uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src)
-{
-    int i;
-    unsigned char x;
-    uint32_t cc = 0;
-
-    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
-               __func__, l, dest, src);
-    for (i = 0; i <= l; i++) {
-        x = ldub(dest + i) & ldub(src + i);
-        if (x) {
-            cc = 1;
-        }
-        stb(dest + i, x);
-    }
-    return cc;
-}
-
-/* xor on array */
-uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src)
-{
-    int i;
-    unsigned char x;
-    uint32_t cc = 0;
-
-    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
-               __func__, l, dest, src);
-
-#ifndef CONFIG_USER_ONLY
-    /* xor with itself is the same as memset(0) */
-    if ((l > 32) && (src == dest) &&
-        (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK)) {
-        mvc_fast_memset(env, l + 1, dest, 0);
-        return 0;
-    }
-#else
-    if (src == dest) {
-        memset(g2h(dest), 0, l + 1);
-        return 0;
-    }
-#endif
-
-    for (i = 0; i <= l; i++) {
-        x = ldub(dest + i) ^ ldub(src + i);
-        if (x) {
-            cc = 1;
-        }
-        stb(dest + i, x);
-    }
-    return cc;
-}
-
-/* or on array */
-uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src)
-{
-    int i;
-    unsigned char x;
-    uint32_t cc = 0;
-
-    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
-               __func__, l, dest, src);
-    for (i = 0; i <= l; i++) {
-        x = ldub(dest + i) | ldub(src + i);
-        if (x) {
-            cc = 1;
-        }
-        stb(dest + i, x);
-    }
-    return cc;
-}
-
-/* memmove */
-void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src)
-{
-    int i = 0;
-    int x = 0;
-    uint32_t l_64 = (l + 1) / 8;
-
-    HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
-               __func__, l, dest, src);
-
-#ifndef CONFIG_USER_ONLY
-    if ((l > 32) &&
-        (src & TARGET_PAGE_MASK) == ((src + l) & TARGET_PAGE_MASK) &&
-        (dest & TARGET_PAGE_MASK) == ((dest + l) & TARGET_PAGE_MASK)) {
-        if (dest == (src + 1)) {
-            mvc_fast_memset(env, l + 1, dest, ldub(src));
-            return;
-        } else if ((src & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
-            mvc_fast_memmove(env, l + 1, dest, src);
-            return;
-        }
-    }
-#else
-    if (dest == (src + 1)) {
-        memset(g2h(dest), ldub(src), l + 1);
-        return;
-    } else {
-        memmove(g2h(dest), g2h(src), l + 1);
-        return;
-    }
-#endif
-
-    /* handle the parts that fit into 8-byte loads/stores */
-    if (dest != (src + 1)) {
-        for (i = 0; i < l_64; i++) {
-            stq(dest + x, ldq(src + x));
-            x += 8;
-        }
-    }
-
-    /* slow version crossing pages with byte accesses */
-    for (i = x; i <= l; i++) {
-        stb(dest + i, ldub(src + i));
-    }
-}
-
-/* compare unsigned byte arrays */
-uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2)
-{
-    int i;
-    unsigned char x, y;
-    uint32_t cc;
-
-    HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n",
-               __func__, l, s1, s2);
-    for (i = 0; i <= l; i++) {
-        x = ldub(s1 + i);
-        y = ldub(s2 + i);
-        HELPER_LOG("%02x (%c)/%02x (%c) ", x, x, y, y);
-        if (x < y) {
-            cc = 1;
-            goto done;
-        } else if (x > y) {
-            cc = 2;
-            goto done;
-        }
-    }
-    cc = 0;
- done:
-    HELPER_LOG("\n");
-    return cc;
-}
-
-/* compare logical under mask */
-uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr)
-{
-    uint8_t r, d;
-    uint32_t cc;
-
-    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1,
-               mask, addr);
-    cc = 0;
-    while (mask) {
-        if (mask & 8) {
-            d = ldub(addr);
-            r = (r1 & 0xff000000UL) >> 24;
-            HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d,
-                       addr);
-            if (r < d) {
-                cc = 1;
-                break;
-            } else if (r > d) {
-                cc = 2;
-                break;
-            }
-            addr++;
-        }
-        mask = (mask << 1) & 0xf;
-        r1 <<= 8;
-    }
-    HELPER_LOG("\n");
-    return cc;
-}
-
-/* store character under mask */
-void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr)
-{
-    uint8_t r;
-
-    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __func__, r1, mask,
-               addr);
-    while (mask) {
-        if (mask & 8) {
-            r = (r1 & 0xff000000UL) >> 24;
-            stb(addr, r);
-            HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr);
-            addr++;
-        }
-        mask = (mask << 1) & 0xf;
-        r1 <<= 8;
-    }
-    HELPER_LOG("\n");
-}
-
-static inline uint64_t get_address(int x2, int b2, int d2)
-{
-    uint64_t r = d2;
-
-    if (x2) {
-        r += env->regs[x2];
-    }
-
-    if (b2) {
-        r += env->regs[b2];
-    }
-
-    /* 31-Bit mode */
-    if (!(env->psw.mask & PSW_MASK_64)) {
-        r &= 0x7fffffff;
-    }
-
-    return r;
-}
-
-static inline uint64_t get_address_31fix(int reg)
-{
-    uint64_t r = env->regs[reg];
-
-    /* 31-Bit mode */
-    if (!(env->psw.mask & PSW_MASK_64)) {
-        r &= 0x7fffffff;
-    }
-
-    return r;
-}
-
-/* search string (c is byte to search, r2 is string, r1 end of string) */
-uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2)
-{
-    uint64_t i;
-    uint32_t cc = 2;
-    uint64_t str = get_address_31fix(r2);
-    uint64_t end = get_address_31fix(r1);
-
-    HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __func__,
-               c, env->regs[r1], env->regs[r2]);
-
-    for (i = str; i != end; i++) {
-        if (ldub(i) == c) {
-            env->regs[r1] = i;
-            cc = 1;
-            break;
-        }
-    }
-
-    return cc;
-}
-
-/* unsigned string compare (c is string terminator) */
-uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2)
-{
-    uint64_t s1 = get_address_31fix(r1);
-    uint64_t s2 = get_address_31fix(r2);
-    uint8_t v1, v2;
-    uint32_t cc;
-
-    c = c & 0xff;
-#ifdef CONFIG_USER_ONLY
-    if (!c) {
-        HELPER_LOG("%s: comparing '%s' and '%s'\n",
-                   __func__, (char *)g2h(s1), (char *)g2h(s2));
-    }
-#endif
-    for (;;) {
-        v1 = ldub(s1);
-        v2 = ldub(s2);
-        if ((v1 == c || v2 == c) || (v1 != v2)) {
-            break;
-        }
-        s1++;
-        s2++;
-    }
-
-    if (v1 == v2) {
-        cc = 0;
-    } else {
-        cc = (v1 < v2) ? 1 : 2;
-        /* FIXME: 31-bit mode! */
-        env->regs[r1] = s1;
-        env->regs[r2] = s2;
-    }
-    return cc;
-}
-
-/* move page */
-void HELPER(mvpg)(uint64_t r0, uint64_t r1, uint64_t r2)
-{
-    /* XXX missing r0 handling */
-#ifdef CONFIG_USER_ONLY
-    int i;
-
-    for (i = 0; i < TARGET_PAGE_SIZE; i++) {
-        stb(r1 + i, ldub(r2 + i));
-    }
-#else
-    mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2);
-#endif
-}
-
-/* string copy (c is string terminator) */
-void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2)
-{
-    uint64_t dest = get_address_31fix(r1);
-    uint64_t src = get_address_31fix(r2);
-    uint8_t v;
-
-    c = c & 0xff;
-#ifdef CONFIG_USER_ONLY
-    if (!c) {
-        HELPER_LOG("%s: copy '%s' to 0x%lx\n", __func__, (char *)g2h(src),
-                   dest);
-    }
-#endif
-    for (;;) {
-        v = ldub(src);
-        stb(dest, v);
-        if (v == c) {
-            break;
-        }
-        src++;
-        dest++;
-    }
-    env->regs[r1] = dest; /* FIXME: 31-bit mode! */
-}
-
-/* compare and swap 64-bit */
-uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3)
-{
-    /* FIXME: locking? */
-    uint32_t cc;
-    uint64_t v2 = ldq(a2);
-
-    if (env->regs[r1] == v2) {
-        cc = 0;
-        stq(a2, env->regs[r3]);
-    } else {
-        cc = 1;
-        env->regs[r1] = v2;
-    }
-    return cc;
-}
-
-/* compare double and swap 64-bit */
-uint32_t HELPER(cdsg)(uint32_t r1, uint64_t a2, uint32_t r3)
-{
-    /* FIXME: locking? */
-    uint32_t cc;
-    uint64_t v2_hi = ldq(a2);
-    uint64_t v2_lo = ldq(a2 + 8);
-    uint64_t v1_hi = env->regs[r1];
-    uint64_t v1_lo = env->regs[r1 + 1];
-
-    if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) {
-        cc = 0;
-        stq(a2, env->regs[r3]);
-        stq(a2 + 8, env->regs[r3 + 1]);
-    } else {
-        cc = 1;
-        env->regs[r1] = v2_hi;
-        env->regs[r1 + 1] = v2_lo;
-    }
-
-    return cc;
-}
-
-/* compare and swap 32-bit */
-uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3)
-{
-    /* FIXME: locking? */
-    uint32_t cc;
-    uint32_t v2 = ldl(a2);
-
-    HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __func__, r1, a2, r3);
-    if (((uint32_t)env->regs[r1]) == v2) {
-        cc = 0;
-        stl(a2, (uint32_t)env->regs[r3]);
-    } else {
-        cc = 1;
-        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2;
-    }
-    return cc;
-}
-
-static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask)
-{
-    int pos = 24; /* top of the lower half of r1 */
-    uint64_t rmask = 0xff000000ULL;
-    uint8_t val = 0;
-    int ccd = 0;
-    uint32_t cc = 0;
-
-    while (mask) {
-        if (mask & 8) {
-            env->regs[r1] &= ~rmask;
-            val = ldub(address);
-            if ((val & 0x80) && !ccd) {
-                cc = 1;
-            }
-            ccd = 1;
-            if (val && cc == 0) {
-                cc = 2;
-            }
-            env->regs[r1] |= (uint64_t)val << pos;
-            address++;
-        }
-        mask = (mask << 1) & 0xf;
-        pos -= 8;
-        rmask >>= 8;
-    }
-
-    return cc;
-}
-
-/* execute instruction
-   this instruction executes an insn modified with the contents of r1
-   it does not change the executed instruction in memory
-   it does not change the program counter
-   in other words: tricky...
-   currently implemented by interpreting the cases it is most commonly used in
-*/
-uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
-{
-    uint16_t insn = lduw_code(addr);
-
-    HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr,
-               insn);
-    if ((insn & 0xf0ff) == 0xd000) {
-        uint32_t l, insn2, b1, b2, d1, d2;
-
-        l = v1 & 0xff;
-        insn2 = ldl_code(addr + 2);
-        b1 = (insn2 >> 28) & 0xf;
-        b2 = (insn2 >> 12) & 0xf;
-        d1 = (insn2 >> 16) & 0xfff;
-        d2 = insn2 & 0xfff;
-        switch (insn & 0xf00) {
-        case 0x200:
-            helper_mvc(l, get_address(0, b1, d1), get_address(0, b2, d2));
-            break;
-        case 0x500:
-            cc = helper_clc(l, get_address(0, b1, d1), get_address(0, b2, d2));
-            break;
-        case 0x700:
-            cc = helper_xc(l, get_address(0, b1, d1), get_address(0, b2, d2));
-            break;
-        case 0xc00:
-            helper_tr(l, get_address(0, b1, d1), get_address(0, b2, d2));
-            break;
-        default:
-            goto abort;
-            break;
-        }
-    } else if ((insn & 0xff00) == 0x0a00) {
-        /* supervisor call */
-        HELPER_LOG("%s: svc %ld via execute\n", __func__, (insn | v1) & 0xff);
-        env->psw.addr = ret - 4;
-        env->int_svc_code = (insn | v1) & 0xff;
-        env->int_svc_ilc = 4;
-        helper_exception(EXCP_SVC);
-    } else if ((insn & 0xff00) == 0xbf00) {
-        uint32_t insn2, r1, r3, b2, d2;
-
-        insn2 = ldl_code(addr + 2);
-        r1 = (insn2 >> 20) & 0xf;
-        r3 = (insn2 >> 16) & 0xf;
-        b2 = (insn2 >> 12) & 0xf;
-        d2 = insn2 & 0xfff;
-        cc = helper_icm(r1, get_address(0, b2, d2), r3);
-    } else {
-    abort:
-        cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n",
-                  insn);
-    }
-    return cc;
-}
-
-/* store character under mask high operates on the upper half of r1 */
-void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask)
-{
-    int pos = 56; /* top of the upper half of r1 */
-
-    while (mask) {
-        if (mask & 8) {
-            stb(address, (env->regs[r1] >> pos) & 0xff);
-            address++;
-        }
-        mask = (mask << 1) & 0xf;
-        pos -= 8;
-    }
-}
-
-/* insert character under mask high; same as icm, but operates on the
-   upper half of r1 */
-uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask)
-{
-    int pos = 56; /* top of the upper half of r1 */
-    uint64_t rmask = 0xff00000000000000ULL;
-    uint8_t val = 0;
-    int ccd = 0;
-    uint32_t cc = 0;
-
-    while (mask) {
-        if (mask & 8) {
-            env->regs[r1] &= ~rmask;
-            val = ldub(address);
-            if ((val & 0x80) && !ccd) {
-                cc = 1;
-            }
-            ccd = 1;
-            if (val && cc == 0) {
-                cc = 2;
-            }
-            env->regs[r1] |= (uint64_t)val << pos;
-            address++;
-        }
-        mask = (mask << 1) & 0xf;
-        pos -= 8;
-        rmask >>= 8;
-    }
-
-    return cc;
-}
-
-/* load access registers r1 to r3 from memory at a2 */
-void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3)
-{
-    int i;
-
-    for (i = r1;; i = (i + 1) % 16) {
-        env->aregs[i] = ldl(a2);
-        a2 += 4;
-
-        if (i == r3) {
-            break;
-        }
-    }
-}
-
-/* store access registers r1 to r3 in memory at a2 */
-void HELPER(stam)(uint32_t r1, uint64_t a2, uint32_t r3)
-{
-    int i;
-
-    for (i = r1;; i = (i + 1) % 16) {
-        stl(a2, env->aregs[i]);
-        a2 += 4;
-
-        if (i == r3) {
-            break;
-        }
-    }
-}
-
-/* move long */
-uint32_t HELPER(mvcl)(uint32_t r1, uint32_t r2)
-{
-    uint64_t destlen = env->regs[r1 + 1] & 0xffffff;
-    uint64_t dest = get_address_31fix(r1);
-    uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
-    uint64_t src = get_address_31fix(r2);
-    uint8_t pad = src >> 24;
-    uint8_t v;
-    uint32_t cc;
-
-    if (destlen == srclen) {
-        cc = 0;
-    } else if (destlen < srclen) {
-        cc = 1;
-    } else {
-        cc = 2;
-    }
-
-    if (srclen > destlen) {
-        srclen = destlen;
-    }
-
-    for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
-        v = ldub(src);
-        stb(dest, v);
-    }
-
-    for (; destlen; dest++, destlen--) {
-        stb(dest, pad);
-    }
-
-    env->regs[r1 + 1] = destlen;
-    /* can't use srclen here, we trunc'ed it */
-    env->regs[r2 + 1] -= src - env->regs[r2];
-    env->regs[r1] = dest;
-    env->regs[r2] = src;
-
-    return cc;
-}
-
-/* move long extended another memcopy insn with more bells and whistles */
-uint32_t HELPER(mvcle)(uint32_t r1, uint64_t a2, uint32_t r3)
-{
-    uint64_t destlen = env->regs[r1 + 1];
-    uint64_t dest = env->regs[r1];
-    uint64_t srclen = env->regs[r3 + 1];
-    uint64_t src = env->regs[r3];
-    uint8_t pad = a2 & 0xff;
-    uint8_t v;
-    uint32_t cc;
-
-    if (!(env->psw.mask & PSW_MASK_64)) {
-        destlen = (uint32_t)destlen;
-        srclen = (uint32_t)srclen;
-        dest &= 0x7fffffff;
-        src &= 0x7fffffff;
-    }
-
-    if (destlen == srclen) {
-        cc = 0;
-    } else if (destlen < srclen) {
-        cc = 1;
-    } else {
-        cc = 2;
-    }
-
-    if (srclen > destlen) {
-        srclen = destlen;
-    }
-
-    for (; destlen && srclen; src++, dest++, destlen--, srclen--) {
-        v = ldub(src);
-        stb(dest, v);
-    }
-
-    for (; destlen; dest++, destlen--) {
-        stb(dest, pad);
-    }
-
-    env->regs[r1 + 1] = destlen;
-    /* can't use srclen here, we trunc'ed it */
-    /* FIXME: 31-bit mode! */
-    env->regs[r3 + 1] -= src - env->regs[r3];
-    env->regs[r1] = dest;
-    env->regs[r3] = src;
-
-    return cc;
-}
-
-/* compare logical long extended memcompare insn with padding */
-uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3)
-{
-    uint64_t destlen = env->regs[r1 + 1];
-    uint64_t dest = get_address_31fix(r1);
-    uint64_t srclen = env->regs[r3 + 1];
-    uint64_t src = get_address_31fix(r3);
-    uint8_t pad = a2 & 0xff;
-    uint8_t v1 = 0, v2 = 0;
-    uint32_t cc = 0;
-
-    if (!(destlen || srclen)) {
-        return cc;
-    }
-
-    if (srclen > destlen) {
-        srclen = destlen;
-    }
-
-    for (; destlen || srclen; src++, dest++, destlen--, srclen--) {
-        v1 = srclen ? ldub(src) : pad;
-        v2 = destlen ? ldub(dest) : pad;
-        if (v1 != v2) {
-            cc = (v1 < v2) ? 1 : 2;
-            break;
-        }
-    }
-
-    env->regs[r1 + 1] = destlen;
-    /* can't use srclen here, we trunc'ed it */
-    env->regs[r3 + 1] -= src - env->regs[r3];
-    env->regs[r1] = dest;
-    env->regs[r3] = src;
-
-    return cc;
-}
-
-/* checksum */
-void HELPER(cksm)(uint32_t r1, uint32_t r2)
-{
-    uint64_t src = get_address_31fix(r2);
-    uint64_t src_len = env->regs[(r2 + 1) & 15];
-    uint64_t cksm = (uint32_t)env->regs[r1];
-
-    while (src_len >= 4) {
-        cksm += ldl(src);
-
-        /* move to next word */
-        src_len -= 4;
-        src += 4;
-    }
-
-    switch (src_len) {
-    case 0:
-        break;
-    case 1:
-        cksm += ldub(src) << 24;
-        break;
-    case 2:
-        cksm += lduw(src) << 16;
-        break;
-    case 3:
-        cksm += lduw(src) << 16;
-        cksm += ldub(src + 2) << 8;
-        break;
-    }
-
-    /* indicate we've processed everything */
-    env->regs[r2] = src + src_len;
-    env->regs[(r2 + 1) & 15] = 0;
-
-    /* store result */
-    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-        ((uint32_t)cksm + (cksm >> 32));
-}
-
-void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
-{
-    int len_dest = len >> 4;
-    int len_src = len & 0xf;
-    uint8_t b;
-    int second_nibble = 0;
-
-    dest += len_dest;
-    src += len_src;
-
-    /* last byte is special, it only flips the nibbles */
-    b = ldub(src);
-    stb(dest, (b << 4) | (b >> 4));
-    src--;
-    len_src--;
-
-    /* now pad every nibble with 0xf0 */
-
-    while (len_dest > 0) {
-        uint8_t cur_byte = 0;
-
-        if (len_src > 0) {
-            cur_byte = ldub(src);
-        }
-
-        len_dest--;
-        dest--;
-
-        /* only advance one nibble at a time */
-        if (second_nibble) {
-            cur_byte >>= 4;
-            len_src--;
-            src--;
-        }
-        second_nibble = !second_nibble;
-
-        /* digit */
-        cur_byte = (cur_byte & 0xf);
-        /* zone bits */
-        cur_byte |= 0xf0;
-
-        stb(dest, cur_byte);
-    }
-}
-
-void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans)
-{
-    int i;
-
-    for (i = 0; i <= len; i++) {
-        uint8_t byte = ldub(array + i);
-        uint8_t new_byte = ldub(trans + byte);
-
-        stb(array + i, new_byte);
-    }
-}
-
-#ifndef CONFIG_USER_ONLY
 void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
 {
     qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr);
@@ -1267,206 +384,6 @@ uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
     return cc;
 }
 
-void HELPER(lctlg)(uint32_t r1, uint64_t a2, uint32_t r3)
-{
-    int i;
-    uint64_t src = a2;
-
-    for (i = r1;; i = (i + 1) % 16) {
-        env->cregs[i] = ldq(src);
-        HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n",
-                   i, src, env->cregs[i]);
-        src += sizeof(uint64_t);
-
-        if (i == r3) {
-            break;
-        }
-    }
-
-    tlb_flush(env, 1);
-}
-
-void HELPER(lctl)(uint32_t r1, uint64_t a2, uint32_t r3)
-{
-    int i;
-    uint64_t src = a2;
-
-    for (i = r1;; i = (i + 1) % 16) {
-        env->cregs[i] = (env->cregs[i] & 0xFFFFFFFF00000000ULL) | ldl(src);
-        src += sizeof(uint32_t);
-
-        if (i == r3) {
-            break;
-        }
-    }
-
-    tlb_flush(env, 1);
-}
-
-void HELPER(stctg)(uint32_t r1, uint64_t a2, uint32_t r3)
-{
-    int i;
-    uint64_t dest = a2;
-
-    for (i = r1;; i = (i + 1) % 16) {
-        stq(dest, env->cregs[i]);
-        dest += sizeof(uint64_t);
-
-        if (i == r3) {
-            break;
-        }
-    }
-}
-
-void HELPER(stctl)(uint32_t r1, uint64_t a2, uint32_t r3)
-{
-    int i;
-    uint64_t dest = a2;
-
-    for (i = r1;; i = (i + 1) % 16) {
-        stl(dest, env->cregs[i]);
-        dest += sizeof(uint32_t);
-
-        if (i == r3) {
-            break;
-        }
-    }
-}
-
-uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2)
-{
-    /* XXX implement */
-
-    return 0;
-}
-
-/* insert storage key extended */
-uint64_t HELPER(iske)(uint64_t r2)
-{
-    uint64_t addr = get_address(0, 0, r2);
-
-    if (addr > ram_size) {
-        return 0;
-    }
-
-    return env->storage_keys[addr / TARGET_PAGE_SIZE];
-}
-
-/* set storage key extended */
-void HELPER(sske)(uint32_t r1, uint64_t r2)
-{
-    uint64_t addr = get_address(0, 0, r2);
-
-    if (addr > ram_size) {
-        return;
-    }
-
-    env->storage_keys[addr / TARGET_PAGE_SIZE] = r1;
-}
-
-/* reset reference bit extended */
-uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
-{
-    uint8_t re;
-    uint8_t key;
-
-    if (r2 > ram_size) {
-        return 0;
-    }
-
-    key = env->storage_keys[r2 / TARGET_PAGE_SIZE];
-    re = key & (SK_R | SK_C);
-    env->storage_keys[r2 / TARGET_PAGE_SIZE] = (key & ~SK_R);
-
-    /*
-     * cc
-     *
-     * 0  Reference bit zero; change bit zero
-     * 1  Reference bit zero; change bit one
-     * 2  Reference bit one; change bit zero
-     * 3  Reference bit one; change bit one
-     */
-
-    return re >> 1;
-}
-
-/* compare and swap and purge */
-uint32_t HELPER(csp)(uint32_t r1, uint32_t r2)
-{
-    uint32_t cc;
-    uint32_t o1 = env->regs[r1];
-    uint64_t a2 = get_address_31fix(r2) & ~3ULL;
-    uint32_t o2 = ldl(a2);
-
-    if (o1 == o2) {
-        stl(a2, env->regs[(r1 + 1) & 15]);
-        if (env->regs[r2] & 0x3) {
-            /* flush TLB / ALB */
-            tlb_flush(env, 1);
-        }
-        cc = 0;
-    } else {
-        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | o2;
-        cc = 1;
-    }
-
-    return cc;
-}
-
-static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2,
-                        uint64_t mode2)
-{
-    target_ulong src, dest;
-    int flags, cc = 0, i;
-
-    if (!l) {
-        return 0;
-    } else if (l > 256) {
-        /* max 256 */
-        l = 256;
-        cc = 3;
-    }
-
-    if (mmu_translate(env, a1 & TARGET_PAGE_MASK, 1, mode1, &dest, &flags)) {
-        cpu_loop_exit(env);
-    }
-    dest |= a1 & ~TARGET_PAGE_MASK;
-
-    if (mmu_translate(env, a2 & TARGET_PAGE_MASK, 0, mode2, &src, &flags)) {
-        cpu_loop_exit(env);
-    }
-    src |= a2 & ~TARGET_PAGE_MASK;
-
-    /* XXX replace w/ memcpy */
-    for (i = 0; i < l; i++) {
-        /* XXX be more clever */
-        if ((((dest + i) & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) ||
-            (((src + i) & TARGET_PAGE_MASK) != (src & TARGET_PAGE_MASK))) {
-            mvc_asc(l - i, a1 + i, mode1, a2 + i, mode2);
-            break;
-        }
-        stb_phys(dest + i, ldub_phys(src + i));
-    }
-
-    return cc;
-}
-
-uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2)
-{
-    HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
-               __func__, l, a1, a2);
-
-    return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY);
-}
-
-uint32_t HELPER(mvcp)(uint64_t l, uint64_t a1, uint64_t a2)
-{
-    HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
-               __func__, l, a1, a2);
-
-    return mvc_asc(l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY);
-}
-
 uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
 {
     int cc = 0;
@@ -1508,78 +425,4 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
 
     return cc;
 }
-
-/* invalidate pte */
-void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
-{
-    uint64_t page = vaddr & TARGET_PAGE_MASK;
-    uint64_t pte = 0;
-
-    /* XXX broadcast to other CPUs */
-
-    /* XXX Linux is nice enough to give us the exact pte address.
-       According to spec we'd have to find it out ourselves */
-    /* XXX Linux is fine with overwriting the pte, the spec requires
-       us to only set the invalid bit */
-    stq_phys(pte_addr, pte | _PAGE_INVALID);
-
-    /* XXX we exploit the fact that Linux passes the exact virtual
-       address here - it's not obliged to! */
-    tlb_flush_page(env, page);
-
-    /* XXX 31-bit hack */
-    if (page & 0x80000000) {
-        tlb_flush_page(env, page & ~0x80000000);
-    } else {
-        tlb_flush_page(env, page | 0x80000000);
-    }
-}
-
-/* flush local tlb */
-void HELPER(ptlb)(void)
-{
-    tlb_flush(env, 1);
-}
-
-/* store using real address */
-void HELPER(stura)(uint64_t addr, uint32_t v1)
-{
-    stw_phys(get_address(0, 0, addr), v1);
-}
-
-/* load real address */
-uint32_t HELPER(lra)(uint64_t addr, uint32_t r1)
-{
-    uint32_t cc = 0;
-    int old_exc = env->exception_index;
-    uint64_t asc = env->psw.mask & PSW_MASK_ASC;
-    uint64_t ret;
-    int flags;
-
-    /* XXX incomplete - has more corner cases */
-    if (!(env->psw.mask & PSW_MASK_64) && (addr >> 32)) {
-        program_interrupt(env, PGM_SPECIAL_OP, 2);
-    }
-
-    env->exception_index = old_exc;
-    if (mmu_translate(env, addr, 0, asc, &ret, &flags)) {
-        cc = 3;
-    }
-    if (env->exception_index == EXCP_PGM) {
-        ret = env->int_pgm_code | 0x80000000;
-    } else {
-        ret |= addr & ~TARGET_PAGE_MASK;
-    }
-    env->exception_index = old_exc;
-
-    if (!(env->psw.mask & PSW_MASK_64)) {
-        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-            (ret & 0xffffffffULL);
-    } else {
-        env->regs[r1] = ret;
-    }
-
-    return cc;
-}
-
 #endif
commit fc8d72c2d34afd6789e8c4374d275a5f69c603f1
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 2 07:33:33 2012 +0000

    target-s390x: split integer helpers
    
    Move integer helpers to int_helper.c.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index f9437d6..e8f66e9 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -1,8 +1,9 @@
 obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o
-obj-y += fpu_helper.o cc_helper.o
+obj-y += int_helper.o fpu_helper.o cc_helper.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+$(obj)/int_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
new file mode 100644
index 0000000..e2eeb07
--- /dev/null
+++ b/target-s390x/int_helper.c
@@ -0,0 +1,201 @@
+/*
+ *  S/390 integer helper routines
+ *
+ *  Copyright (c) 2009 Ulrich Hecht
+ *  Copyright (c) 2009 Alexander Graf
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "dyngen-exec.h"
+#include "host-utils.h"
+#include "helper.h"
+
+/* #define DEBUG_HELPER */
+#ifdef DEBUG_HELPER
+#define HELPER_LOG(x...) qemu_log(x)
+#else
+#define HELPER_LOG(x...)
+#endif
+
+/* 64/64 -> 128 unsigned multiplication */
+void HELPER(mlg)(uint32_t r1, uint64_t v2)
+{
+#if HOST_LONG_BITS == 64 && defined(__GNUC__)
+    /* assuming 64-bit hosts have __uint128_t */
+    __uint128_t res = (__uint128_t)env->regs[r1 + 1];
+
+    res *= (__uint128_t)v2;
+    env->regs[r1] = (uint64_t)(res >> 64);
+    env->regs[r1 + 1] = (uint64_t)res;
+#else
+    mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2);
+#endif
+}
+
+/* 128 -> 64/64 unsigned division */
+void HELPER(dlg)(uint32_t r1, uint64_t v2)
+{
+    uint64_t divisor = v2;
+
+    if (!env->regs[r1]) {
+        /* 64 -> 64/64 case */
+        env->regs[r1] = env->regs[r1 + 1] % divisor;
+        env->regs[r1 + 1] = env->regs[r1 + 1] / divisor;
+        return;
+    } else {
+#if HOST_LONG_BITS == 64 && defined(__GNUC__)
+        /* assuming 64-bit hosts have __uint128_t */
+        __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) |
+            (env->regs[r1 + 1]);
+        __uint128_t quotient = dividend / divisor;
+        __uint128_t remainder = dividend % divisor;
+
+        env->regs[r1 + 1] = quotient;
+        env->regs[r1] = remainder;
+#else
+        /* 32-bit hosts would need special wrapper functionality - just abort if
+           we encounter such a case; it's very unlikely anyways. */
+        cpu_abort(env, "128 -> 64/64 division not implemented\n");
+#endif
+    }
+}
+
+/* absolute value 32-bit */
+uint32_t HELPER(abs_i32)(int32_t val)
+{
+    if (val < 0) {
+        return -val;
+    } else {
+        return val;
+    }
+}
+
+/* negative absolute value 32-bit */
+int32_t HELPER(nabs_i32)(int32_t val)
+{
+    if (val < 0) {
+        return val;
+    } else {
+        return -val;
+    }
+}
+
+/* absolute value 64-bit */
+uint64_t HELPER(abs_i64)(int64_t val)
+{
+    HELPER_LOG("%s: val 0x%" PRIx64 "\n", __func__, val);
+
+    if (val < 0) {
+        return -val;
+    } else {
+        return val;
+    }
+}
+
+/* negative absolute value 64-bit */
+int64_t HELPER(nabs_i64)(int64_t val)
+{
+    if (val < 0) {
+        return val;
+    } else {
+        return -val;
+    }
+}
+
+/* add with carry 32-bit unsigned */
+uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
+{
+    uint32_t res;
+
+    res = v1 + v2;
+    if (cc & 2) {
+        res++;
+    }
+
+    return res;
+}
+
+/* subtract unsigned v2 from v1 with borrow */
+uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
+{
+    uint32_t v1 = env->regs[r1];
+    uint32_t res = v1 + (~v2) + (cc >> 1);
+
+    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res;
+    if (cc & 2) {
+        /* borrow */
+        return v1 ? 1 : 0;
+    } else {
+        return v1 ? 3 : 2;
+    }
+}
+
+/* subtract unsigned v2 from v1 with borrow */
+uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
+{
+    uint64_t res = v1 + (~v2) + (cc >> 1);
+
+    env->regs[r1] = res;
+    if (cc & 2) {
+        /* borrow */
+        return v1 ? 1 : 0;
+    } else {
+        return v1 ? 3 : 2;
+    }
+}
+
+/* find leftmost one */
+uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
+{
+    uint64_t res = 0;
+    uint64_t ov2 = v2;
+
+    while (!(v2 & 0x8000000000000000ULL) && v2) {
+        v2 <<= 1;
+        res++;
+    }
+
+    if (!v2) {
+        env->regs[r1] = 64;
+        env->regs[r1 + 1] = 0;
+        return 0;
+    } else {
+        env->regs[r1] = res;
+        env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res);
+        return 2;
+    }
+}
+
+uint64_t HELPER(cvd)(int32_t bin)
+{
+    /* positive 0 */
+    uint64_t dec = 0x0c;
+    int shift = 4;
+
+    if (bin < 0) {
+        bin = -bin;
+        dec = 0x0d;
+    }
+
+    for (shift = 4; (shift < 64) && bin; shift += 4) {
+        int current_number = bin % 10;
+
+        dec |= (current_number) << shift;
+        bin /= 10;
+    }
+
+    return dec;
+}
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index eced890..3b8b997 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -352,49 +352,6 @@ void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr)
     HELPER_LOG("\n");
 }
 
-/* 64/64 -> 128 unsigned multiplication */
-void HELPER(mlg)(uint32_t r1, uint64_t v2)
-{
-#if HOST_LONG_BITS == 64 && defined(__GNUC__)
-    /* assuming 64-bit hosts have __uint128_t */
-    __uint128_t res = (__uint128_t)env->regs[r1 + 1];
-
-    res *= (__uint128_t)v2;
-    env->regs[r1] = (uint64_t)(res >> 64);
-    env->regs[r1 + 1] = (uint64_t)res;
-#else
-    mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2);
-#endif
-}
-
-/* 128 -> 64/64 unsigned division */
-void HELPER(dlg)(uint32_t r1, uint64_t v2)
-{
-    uint64_t divisor = v2;
-
-    if (!env->regs[r1]) {
-        /* 64 -> 64/64 case */
-        env->regs[r1] = env->regs[r1 + 1] % divisor;
-        env->regs[r1 + 1] = env->regs[r1 + 1] / divisor;
-        return;
-    } else {
-#if HOST_LONG_BITS == 64 && defined(__GNUC__)
-        /* assuming 64-bit hosts have __uint128_t */
-        __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) |
-            (env->regs[r1 + 1]);
-        __uint128_t quotient = dividend / divisor;
-        __uint128_t remainder = dividend % divisor;
-
-        env->regs[r1 + 1] = quotient;
-        env->regs[r1] = remainder;
-#else
-        /* 32-bit hosts would need special wrapper functionality - just abort if
-           we encounter such a case; it's very unlikely anyways. */
-        cpu_abort(env, "128 -> 64/64 division not implemented\n");
-#endif
-    }
-}
-
 static inline uint64_t get_address(int x2, int b2, int d2)
 {
     uint64_t r = d2;
@@ -677,61 +634,6 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
     return cc;
 }
 
-/* absolute value 32-bit */
-uint32_t HELPER(abs_i32)(int32_t val)
-{
-    if (val < 0) {
-        return -val;
-    } else {
-        return val;
-    }
-}
-
-/* negative absolute value 32-bit */
-int32_t HELPER(nabs_i32)(int32_t val)
-{
-    if (val < 0) {
-        return val;
-    } else {
-        return -val;
-    }
-}
-
-/* absolute value 64-bit */
-uint64_t HELPER(abs_i64)(int64_t val)
-{
-    HELPER_LOG("%s: val 0x%" PRIx64 "\n", __func__, val);
-
-    if (val < 0) {
-        return -val;
-    } else {
-        return val;
-    }
-}
-
-/* negative absolute value 64-bit */
-int64_t HELPER(nabs_i64)(int64_t val)
-{
-    if (val < 0) {
-        return val;
-    } else {
-        return -val;
-    }
-}
-
-/* add with carry 32-bit unsigned */
-uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
-{
-    uint32_t res;
-
-    res = v1 + v2;
-    if (cc & 2) {
-        res++;
-    }
-
-    return res;
-}
-
 /* store character under mask high operates on the upper half of r1 */
 void HELPER(stcmh)(uint32_t r1, uint64_t address, uint32_t mask)
 {
@@ -936,57 +838,6 @@ uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3)
     return cc;
 }
 
-/* subtract unsigned v2 from v1 with borrow */
-uint32_t HELPER(slb)(uint32_t cc, uint32_t r1, uint32_t v2)
-{
-    uint32_t v1 = env->regs[r1];
-    uint32_t res = v1 + (~v2) + (cc >> 1);
-
-    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res;
-    if (cc & 2) {
-        /* borrow */
-        return v1 ? 1 : 0;
-    } else {
-        return v1 ? 3 : 2;
-    }
-}
-
-/* subtract unsigned v2 from v1 with borrow */
-uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
-{
-    uint64_t res = v1 + (~v2) + (cc >> 1);
-
-    env->regs[r1] = res;
-    if (cc & 2) {
-        /* borrow */
-        return v1 ? 1 : 0;
-    } else {
-        return v1 ? 3 : 2;
-    }
-}
-
-/* find leftmost one */
-uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
-{
-    uint64_t res = 0;
-    uint64_t ov2 = v2;
-
-    while (!(v2 & 0x8000000000000000ULL) && v2) {
-        v2 <<= 1;
-        res++;
-    }
-
-    if (!v2) {
-        env->regs[r1] = 64;
-        env->regs[r1 + 1] = 0;
-        return 0;
-    } else {
-        env->regs[r1] = res;
-        env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res);
-        return 2;
-    }
-}
-
 /* checksum */
 void HELPER(cksm)(uint32_t r1, uint32_t r2)
 {
@@ -1026,27 +877,6 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2)
         ((uint32_t)cksm + (cksm >> 32));
 }
 
-uint64_t HELPER(cvd)(int32_t bin)
-{
-    /* positive 0 */
-    uint64_t dec = 0x0c;
-    int shift = 4;
-
-    if (bin < 0) {
-        bin = -bin;
-        dec = 0x0d;
-    }
-
-    for (shift = 4; (shift < 64) && bin; shift += 4) {
-        int current_number = bin % 10;
-
-        dec |= (current_number) << shift;
-        bin /= 10;
-    }
-
-    return dec;
-}
-
 void HELPER(unpk)(uint32_t len, uint64_t dest, uint64_t src)
 {
     int len_dest = len >> 4;
commit a78b0504e8d5487fca77b6b0cd8d3c98b9bace8c
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 2 07:33:32 2012 +0000

    target-s390x: split condition code helpers
    
    Move condition code helpers to cc_helper.c.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 23b3bd9..f9437d6 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -1,7 +1,8 @@
 obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o
-obj-y += fpu_helper.o
+obj-y += fpu_helper.o cc_helper.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 $(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+$(obj)/cc_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
new file mode 100644
index 0000000..2ac1659
--- /dev/null
+++ b/target-s390x/cc_helper.c
@@ -0,0 +1,551 @@
+/*
+ *  S/390 condition code helper routines
+ *
+ *  Copyright (c) 2009 Ulrich Hecht
+ *  Copyright (c) 2009 Alexander Graf
+ *
+ * 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_HELPER */
+#ifdef DEBUG_HELPER
+#define HELPER_LOG(x...) qemu_log(x)
+#else
+#define HELPER_LOG(x...)
+#endif
+
+static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src,
+                                       int32_t dst)
+{
+    if (src == dst) {
+        return 0;
+    } else if (src < dst) {
+        return 1;
+    } else {
+        return 2;
+    }
+}
+
+static inline uint32_t cc_calc_ltgt0_32(CPUS390XState *env, int32_t dst)
+{
+    return cc_calc_ltgt_32(env, dst, 0);
+}
+
+static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src,
+                                       int64_t dst)
+{
+    if (src == dst) {
+        return 0;
+    } else if (src < dst) {
+        return 1;
+    } else {
+        return 2;
+    }
+}
+
+static inline uint32_t cc_calc_ltgt0_64(CPUS390XState *env, int64_t dst)
+{
+    return cc_calc_ltgt_64(env, dst, 0);
+}
+
+static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src,
+                                         uint32_t dst)
+{
+    if (src == dst) {
+        return 0;
+    } else if (src < dst) {
+        return 1;
+    } else {
+        return 2;
+    }
+}
+
+static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
+                                         uint64_t dst)
+{
+    if (src == dst) {
+        return 0;
+    } else if (src < dst) {
+        return 1;
+    } else {
+        return 2;
+    }
+}
+
+static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val,
+                                     uint32_t mask)
+{
+    uint16_t r = val & mask;
+
+    HELPER_LOG("%s: val 0x%x mask 0x%x\n", __func__, val, mask);
+    if (r == 0 || mask == 0) {
+        return 0;
+    } else if (r == mask) {
+        return 3;
+    } else {
+        return 1;
+    }
+}
+
+/* set condition code for test under mask */
+static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val,
+                                     uint32_t mask)
+{
+    uint16_t r = val & mask;
+
+    HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __func__, val, mask, r);
+    if (r == 0 || mask == 0) {
+        return 0;
+    } else if (r == mask) {
+        return 3;
+    } else {
+        while (!(mask & 0x8000)) {
+            mask <<= 1;
+            val <<= 1;
+        }
+        if (val & 0x8000) {
+            return 2;
+        } else {
+            return 1;
+        }
+    }
+}
+
+static inline uint32_t cc_calc_nz(CPUS390XState *env, uint64_t dst)
+{
+    return !!dst;
+}
+
+static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1,
+                                      int64_t a2, int64_t ar)
+{
+    if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
+        return 3; /* overflow */
+    } else {
+        if (ar < 0) {
+            return 1;
+        } else if (ar > 0) {
+            return 2;
+        } else {
+            return 0;
+        }
+    }
+}
+
+static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1,
+                                       uint64_t a2, uint64_t ar)
+{
+    if (ar == 0) {
+        if (a1) {
+            return 2;
+        } else {
+            return 0;
+        }
+    } else {
+        if (ar < a1 || ar < a2) {
+            return 3;
+        } else {
+            return 1;
+        }
+    }
+}
+
+static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1,
+                                      int64_t a2, int64_t ar)
+{
+    if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
+        return 3; /* overflow */
+    } else {
+        if (ar < 0) {
+            return 1;
+        } else if (ar > 0) {
+            return 2;
+        } else {
+            return 0;
+        }
+    }
+}
+
+static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1,
+                                       uint64_t a2, uint64_t ar)
+{
+    if (ar == 0) {
+        return 2;
+    } else {
+        if (a2 > a1) {
+            return 1;
+        } else {
+            return 3;
+        }
+    }
+}
+
+static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
+{
+    if ((uint64_t)dst == 0x8000000000000000ULL) {
+        return 3;
+    } else if (dst) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+static inline uint32_t cc_calc_nabs_64(CPUS390XState *env, int64_t dst)
+{
+    return !!dst;
+}
+
+static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst)
+{
+    if ((uint64_t)dst == 0x8000000000000000ULL) {
+        return 3;
+    } else if (dst < 0) {
+        return 1;
+    } else if (dst > 0) {
+        return 2;
+    } else {
+        return 0;
+    }
+}
+
+
+static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1,
+                                      int32_t a2, int32_t ar)
+{
+    if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
+        return 3; /* overflow */
+    } else {
+        if (ar < 0) {
+            return 1;
+        } else if (ar > 0) {
+            return 2;
+        } else {
+            return 0;
+        }
+    }
+}
+
+static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1,
+                                       uint32_t a2, uint32_t ar)
+{
+    if (ar == 0) {
+        if (a1) {
+            return 2;
+        } else {
+            return 0;
+        }
+    } else {
+        if (ar < a1 || ar < a2) {
+            return 3;
+        } else {
+            return 1;
+        }
+    }
+}
+
+static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1,
+                                      int32_t a2, int32_t ar)
+{
+    if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
+        return 3; /* overflow */
+    } else {
+        if (ar < 0) {
+            return 1;
+        } else if (ar > 0) {
+            return 2;
+        } else {
+            return 0;
+        }
+    }
+}
+
+static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1,
+                                       uint32_t a2, uint32_t ar)
+{
+    if (ar == 0) {
+        return 2;
+    } else {
+        if (a2 > a1) {
+            return 1;
+        } else {
+            return 3;
+        }
+    }
+}
+
+static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
+{
+    if ((uint32_t)dst == 0x80000000UL) {
+        return 3;
+    } else if (dst) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+static inline uint32_t cc_calc_nabs_32(CPUS390XState *env, int32_t dst)
+{
+    return !!dst;
+}
+
+static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst)
+{
+    if ((uint32_t)dst == 0x80000000UL) {
+        return 3;
+    } else if (dst < 0) {
+        return 1;
+    } else if (dst > 0) {
+        return 2;
+    } else {
+        return 0;
+    }
+}
+
+/* calculate condition code for insert character under mask insn */
+static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask,
+                                      uint32_t val)
+{
+    uint32_t cc;
+
+    HELPER_LOG("%s: mask 0x%x val %d\n", __func__, mask, val);
+    if (mask == 0xf) {
+        if (!val) {
+            return 0;
+        } else if (val & 0x80000000) {
+            return 1;
+        } else {
+            return 2;
+        }
+    }
+
+    if (!val || !mask) {
+        cc = 0;
+    } else {
+        while (mask != 1) {
+            mask >>= 1;
+            val >>= 8;
+        }
+        if (val & 0x80) {
+            cc = 1;
+        } else {
+            cc = 2;
+        }
+    }
+    return cc;
+}
+
+static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src,
+                                    uint64_t shift)
+{
+    uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
+    uint64_t match, r;
+
+    /* check if the sign bit stays the same */
+    if (src & (1ULL << 63)) {
+        match = mask;
+    } else {
+        match = 0;
+    }
+
+    if ((src & mask) != match) {
+        /* overflow */
+        return 3;
+    }
+
+    r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63));
+
+    if ((int64_t)r == 0) {
+        return 0;
+    } else if ((int64_t)r < 0) {
+        return 1;
+    }
+
+    return 2;
+}
+
+
+static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
+                                  uint64_t src, uint64_t dst, uint64_t vr)
+{
+    uint32_t r = 0;
+
+    switch (cc_op) {
+    case CC_OP_CONST0:
+    case CC_OP_CONST1:
+    case CC_OP_CONST2:
+    case CC_OP_CONST3:
+        /* cc_op value _is_ cc */
+        r = cc_op;
+        break;
+    case CC_OP_LTGT0_32:
+        r = cc_calc_ltgt0_32(env, dst);
+        break;
+    case CC_OP_LTGT0_64:
+        r =  cc_calc_ltgt0_64(env, dst);
+        break;
+    case CC_OP_LTGT_32:
+        r =  cc_calc_ltgt_32(env, src, dst);
+        break;
+    case CC_OP_LTGT_64:
+        r =  cc_calc_ltgt_64(env, src, dst);
+        break;
+    case CC_OP_LTUGTU_32:
+        r =  cc_calc_ltugtu_32(env, src, dst);
+        break;
+    case CC_OP_LTUGTU_64:
+        r =  cc_calc_ltugtu_64(env, src, dst);
+        break;
+    case CC_OP_TM_32:
+        r =  cc_calc_tm_32(env, src, dst);
+        break;
+    case CC_OP_TM_64:
+        r =  cc_calc_tm_64(env, src, dst);
+        break;
+    case CC_OP_NZ:
+        r =  cc_calc_nz(env, dst);
+        break;
+    case CC_OP_ADD_64:
+        r =  cc_calc_add_64(env, src, dst, vr);
+        break;
+    case CC_OP_ADDU_64:
+        r =  cc_calc_addu_64(env, src, dst, vr);
+        break;
+    case CC_OP_SUB_64:
+        r =  cc_calc_sub_64(env, src, dst, vr);
+        break;
+    case CC_OP_SUBU_64:
+        r =  cc_calc_subu_64(env, src, dst, vr);
+        break;
+    case CC_OP_ABS_64:
+        r =  cc_calc_abs_64(env, dst);
+        break;
+    case CC_OP_NABS_64:
+        r =  cc_calc_nabs_64(env, dst);
+        break;
+    case CC_OP_COMP_64:
+        r =  cc_calc_comp_64(env, dst);
+        break;
+
+    case CC_OP_ADD_32:
+        r =  cc_calc_add_32(env, src, dst, vr);
+        break;
+    case CC_OP_ADDU_32:
+        r =  cc_calc_addu_32(env, src, dst, vr);
+        break;
+    case CC_OP_SUB_32:
+        r =  cc_calc_sub_32(env, src, dst, vr);
+        break;
+    case CC_OP_SUBU_32:
+        r =  cc_calc_subu_32(env, src, dst, vr);
+        break;
+    case CC_OP_ABS_32:
+        r =  cc_calc_abs_64(env, dst);
+        break;
+    case CC_OP_NABS_32:
+        r =  cc_calc_nabs_64(env, dst);
+        break;
+    case CC_OP_COMP_32:
+        r =  cc_calc_comp_32(env, dst);
+        break;
+
+    case CC_OP_ICM:
+        r =  cc_calc_icm_32(env, src, dst);
+        break;
+    case CC_OP_SLAG:
+        r =  cc_calc_slag(env, src, dst);
+        break;
+
+    case CC_OP_LTGT_F32:
+        r = set_cc_f32(src, dst);
+        break;
+    case CC_OP_LTGT_F64:
+        r = set_cc_f64(src, dst);
+        break;
+    case CC_OP_NZ_F32:
+        r = set_cc_nz_f32(dst);
+        break;
+    case CC_OP_NZ_F64:
+        r = set_cc_nz_f64(dst);
+        break;
+
+    default:
+        cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op));
+    }
+
+    HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __func__,
+               cc_name(cc_op), src, dst, vr, r);
+    return r;
+}
+
+uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
+                 uint64_t vr)
+{
+    return do_calc_cc(env, cc_op, src, dst, vr);
+}
+
+uint32_t HELPER(calc_cc)(uint32_t cc_op, uint64_t src, uint64_t dst,
+                         uint64_t vr)
+{
+    return do_calc_cc(env, cc_op, src, dst, vr);
+}
+
+/* insert psw mask and condition code into r1 */
+void HELPER(ipm)(uint32_t cc, uint32_t r1)
+{
+    uint64_t r = env->regs[r1];
+
+    r &= 0xffffffff00ffffffULL;
+    r |= (cc << 28) | ((env->psw.mask >> 40) & 0xf);
+    env->regs[r1] = r;
+    HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __func__,
+               cc, env->psw.mask, r);
+}
+
+#ifndef CONFIG_USER_ONLY
+void HELPER(load_psw)(uint64_t mask, uint64_t addr)
+{
+    load_psw(env, mask, addr);
+    cpu_loop_exit(env);
+}
+
+void HELPER(sacf)(uint64_t a1)
+{
+    HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1);
+
+    switch (a1 & 0xf00) {
+    case 0x000:
+        env->psw.mask &= ~PSW_MASK_ASC;
+        env->psw.mask |= PSW_ASC_PRIMARY;
+        break;
+    case 0x100:
+        env->psw.mask &= ~PSW_MASK_ASC;
+        env->psw.mask |= PSW_ASC_SECONDARY;
+        break;
+    case 0x300:
+        env->psw.mask &= ~PSW_MASK_ASC;
+        env->psw.mask |= PSW_ASC_HOME;
+        break;
+    default:
+        qemu_log("unknown sacf mode: %" PRIx64 "\n", a1);
+        program_interrupt(env, PGM_SPECIFICATION, 2);
+        break;
+    }
+}
+#endif
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index b4620c5..97fde5e 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -1005,4 +1005,7 @@ uint32_t set_cc_f64(float64 v1, float64 v2);
 uint32_t set_cc_nz_f32(float32 v);
 uint32_t set_cc_nz_f64(float64 v);
 
+/* op_helper.c */
+void program_interrupt(CPUS390XState *env, uint32_t code, int ilc);
+
 #endif
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 270bf14..eced890 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -779,18 +779,6 @@ uint32_t HELPER(icmh)(uint32_t r1, uint64_t address, uint32_t mask)
     return cc;
 }
 
-/* insert psw mask and condition code into r1 */
-void HELPER(ipm)(uint32_t cc, uint32_t r1)
-{
-    uint64_t r = env->regs[r1];
-
-    r &= 0xffffffff00ffffffULL;
-    r |= (cc << 28) | ((env->psw.mask >> 40) & 0xf);
-    env->regs[r1] = r;
-    HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __func__,
-               cc, env->psw.mask, r);
-}
-
 /* load access registers r1 to r3 from memory at a2 */
 void HELPER(lam)(uint32_t r1, uint64_t a2, uint32_t r3)
 {
@@ -1038,483 +1026,6 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2)
         ((uint32_t)cksm + (cksm >> 32));
 }
 
-static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src,
-                                       int32_t dst)
-{
-    if (src == dst) {
-        return 0;
-    } else if (src < dst) {
-        return 1;
-    } else {
-        return 2;
-    }
-}
-
-static inline uint32_t cc_calc_ltgt0_32(CPUS390XState *env, int32_t dst)
-{
-    return cc_calc_ltgt_32(env, dst, 0);
-}
-
-static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src,
-                                       int64_t dst)
-{
-    if (src == dst) {
-        return 0;
-    } else if (src < dst) {
-        return 1;
-    } else {
-        return 2;
-    }
-}
-
-static inline uint32_t cc_calc_ltgt0_64(CPUS390XState *env, int64_t dst)
-{
-    return cc_calc_ltgt_64(env, dst, 0);
-}
-
-static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src,
-                                         uint32_t dst)
-{
-    if (src == dst) {
-        return 0;
-    } else if (src < dst) {
-        return 1;
-    } else {
-        return 2;
-    }
-}
-
-static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
-                                         uint64_t dst)
-{
-    if (src == dst) {
-        return 0;
-    } else if (src < dst) {
-        return 1;
-    } else {
-        return 2;
-    }
-}
-
-static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val,
-                                     uint32_t mask)
-{
-    uint16_t r = val & mask;
-
-    HELPER_LOG("%s: val 0x%x mask 0x%x\n", __func__, val, mask);
-    if (r == 0 || mask == 0) {
-        return 0;
-    } else if (r == mask) {
-        return 3;
-    } else {
-        return 1;
-    }
-}
-
-/* set condition code for test under mask */
-static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val,
-                                     uint32_t mask)
-{
-    uint16_t r = val & mask;
-
-    HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __func__, val, mask, r);
-    if (r == 0 || mask == 0) {
-        return 0;
-    } else if (r == mask) {
-        return 3;
-    } else {
-        while (!(mask & 0x8000)) {
-            mask <<= 1;
-            val <<= 1;
-        }
-        if (val & 0x8000) {
-            return 2;
-        } else {
-            return 1;
-        }
-    }
-}
-
-static inline uint32_t cc_calc_nz(CPUS390XState *env, uint64_t dst)
-{
-    return !!dst;
-}
-
-static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1,
-                                      int64_t a2, int64_t ar)
-{
-    if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
-        return 3; /* overflow */
-    } else {
-        if (ar < 0) {
-            return 1;
-        } else if (ar > 0) {
-            return 2;
-        } else {
-            return 0;
-        }
-    }
-}
-
-static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1,
-                                       uint64_t a2, uint64_t ar)
-{
-    if (ar == 0) {
-        if (a1) {
-            return 2;
-        } else {
-            return 0;
-        }
-    } else {
-        if (ar < a1 || ar < a2) {
-            return 3;
-        } else {
-            return 1;
-        }
-    }
-}
-
-static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1,
-                                      int64_t a2, int64_t ar)
-{
-    if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
-        return 3; /* overflow */
-    } else {
-        if (ar < 0) {
-            return 1;
-        } else if (ar > 0) {
-            return 2;
-        } else {
-            return 0;
-        }
-    }
-}
-
-static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1,
-                                       uint64_t a2, uint64_t ar)
-{
-    if (ar == 0) {
-        return 2;
-    } else {
-        if (a2 > a1) {
-            return 1;
-        } else {
-            return 3;
-        }
-    }
-}
-
-static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
-{
-    if ((uint64_t)dst == 0x8000000000000000ULL) {
-        return 3;
-    } else if (dst) {
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
-static inline uint32_t cc_calc_nabs_64(CPUS390XState *env, int64_t dst)
-{
-    return !!dst;
-}
-
-static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst)
-{
-    if ((uint64_t)dst == 0x8000000000000000ULL) {
-        return 3;
-    } else if (dst < 0) {
-        return 1;
-    } else if (dst > 0) {
-        return 2;
-    } else {
-        return 0;
-    }
-}
-
-
-static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1,
-                                      int32_t a2, int32_t ar)
-{
-    if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
-        return 3; /* overflow */
-    } else {
-        if (ar < 0) {
-            return 1;
-        } else if (ar > 0) {
-            return 2;
-        } else {
-            return 0;
-        }
-    }
-}
-
-static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1,
-                                       uint32_t a2, uint32_t ar)
-{
-    if (ar == 0) {
-        if (a1) {
-            return 2;
-        } else {
-            return 0;
-        }
-    } else {
-        if (ar < a1 || ar < a2) {
-            return 3;
-        } else {
-            return 1;
-        }
-    }
-}
-
-static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1,
-                                      int32_t a2, int32_t ar)
-{
-    if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
-        return 3; /* overflow */
-    } else {
-        if (ar < 0) {
-            return 1;
-        } else if (ar > 0) {
-            return 2;
-        } else {
-            return 0;
-        }
-    }
-}
-
-static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1,
-                                       uint32_t a2, uint32_t ar)
-{
-    if (ar == 0) {
-        return 2;
-    } else {
-        if (a2 > a1) {
-            return 1;
-        } else {
-            return 3;
-        }
-    }
-}
-
-static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
-{
-    if ((uint32_t)dst == 0x80000000UL) {
-        return 3;
-    } else if (dst) {
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
-static inline uint32_t cc_calc_nabs_32(CPUS390XState *env, int32_t dst)
-{
-    return !!dst;
-}
-
-static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst)
-{
-    if ((uint32_t)dst == 0x80000000UL) {
-        return 3;
-    } else if (dst < 0) {
-        return 1;
-    } else if (dst > 0) {
-        return 2;
-    } else {
-        return 0;
-    }
-}
-
-/* calculate condition code for insert character under mask insn */
-static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask,
-                                      uint32_t val)
-{
-    uint32_t cc;
-
-    HELPER_LOG("%s: mask 0x%x val %d\n", __func__, mask, val);
-    if (mask == 0xf) {
-        if (!val) {
-            return 0;
-        } else if (val & 0x80000000) {
-            return 1;
-        } else {
-            return 2;
-        }
-    }
-
-    if (!val || !mask) {
-        cc = 0;
-    } else {
-        while (mask != 1) {
-            mask >>= 1;
-            val >>= 8;
-        }
-        if (val & 0x80) {
-            cc = 1;
-        } else {
-            cc = 2;
-        }
-    }
-    return cc;
-}
-
-static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src,
-                                    uint64_t shift)
-{
-    uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
-    uint64_t match, r;
-
-    /* check if the sign bit stays the same */
-    if (src & (1ULL << 63)) {
-        match = mask;
-    } else {
-        match = 0;
-    }
-
-    if ((src & mask) != match) {
-        /* overflow */
-        return 3;
-    }
-
-    r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63));
-
-    if ((int64_t)r == 0) {
-        return 0;
-    } else if ((int64_t)r < 0) {
-        return 1;
-    }
-
-    return 2;
-}
-
-
-static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
-                                  uint64_t src, uint64_t dst, uint64_t vr)
-{
-    uint32_t r = 0;
-
-    switch (cc_op) {
-    case CC_OP_CONST0:
-    case CC_OP_CONST1:
-    case CC_OP_CONST2:
-    case CC_OP_CONST3:
-        /* cc_op value _is_ cc */
-        r = cc_op;
-        break;
-    case CC_OP_LTGT0_32:
-        r = cc_calc_ltgt0_32(env, dst);
-        break;
-    case CC_OP_LTGT0_64:
-        r =  cc_calc_ltgt0_64(env, dst);
-        break;
-    case CC_OP_LTGT_32:
-        r =  cc_calc_ltgt_32(env, src, dst);
-        break;
-    case CC_OP_LTGT_64:
-        r =  cc_calc_ltgt_64(env, src, dst);
-        break;
-    case CC_OP_LTUGTU_32:
-        r =  cc_calc_ltugtu_32(env, src, dst);
-        break;
-    case CC_OP_LTUGTU_64:
-        r =  cc_calc_ltugtu_64(env, src, dst);
-        break;
-    case CC_OP_TM_32:
-        r =  cc_calc_tm_32(env, src, dst);
-        break;
-    case CC_OP_TM_64:
-        r =  cc_calc_tm_64(env, src, dst);
-        break;
-    case CC_OP_NZ:
-        r =  cc_calc_nz(env, dst);
-        break;
-    case CC_OP_ADD_64:
-        r =  cc_calc_add_64(env, src, dst, vr);
-        break;
-    case CC_OP_ADDU_64:
-        r =  cc_calc_addu_64(env, src, dst, vr);
-        break;
-    case CC_OP_SUB_64:
-        r =  cc_calc_sub_64(env, src, dst, vr);
-        break;
-    case CC_OP_SUBU_64:
-        r =  cc_calc_subu_64(env, src, dst, vr);
-        break;
-    case CC_OP_ABS_64:
-        r =  cc_calc_abs_64(env, dst);
-        break;
-    case CC_OP_NABS_64:
-        r =  cc_calc_nabs_64(env, dst);
-        break;
-    case CC_OP_COMP_64:
-        r =  cc_calc_comp_64(env, dst);
-        break;
-
-    case CC_OP_ADD_32:
-        r =  cc_calc_add_32(env, src, dst, vr);
-        break;
-    case CC_OP_ADDU_32:
-        r =  cc_calc_addu_32(env, src, dst, vr);
-        break;
-    case CC_OP_SUB_32:
-        r =  cc_calc_sub_32(env, src, dst, vr);
-        break;
-    case CC_OP_SUBU_32:
-        r =  cc_calc_subu_32(env, src, dst, vr);
-        break;
-    case CC_OP_ABS_32:
-        r =  cc_calc_abs_64(env, dst);
-        break;
-    case CC_OP_NABS_32:
-        r =  cc_calc_nabs_64(env, dst);
-        break;
-    case CC_OP_COMP_32:
-        r =  cc_calc_comp_32(env, dst);
-        break;
-
-    case CC_OP_ICM:
-        r =  cc_calc_icm_32(env, src, dst);
-        break;
-    case CC_OP_SLAG:
-        r =  cc_calc_slag(env, src, dst);
-        break;
-
-    case CC_OP_LTGT_F32:
-        r = set_cc_f32(src, dst);
-        break;
-    case CC_OP_LTGT_F64:
-        r = set_cc_f64(src, dst);
-        break;
-    case CC_OP_NZ_F32:
-        r = set_cc_nz_f32(dst);
-        break;
-    case CC_OP_NZ_F64:
-        r = set_cc_nz_f64(dst);
-        break;
-
-    default:
-        cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op));
-    }
-
-    HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __func__,
-               cc_name(cc_op), src, dst, vr, r);
-    return r;
-}
-
-uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
-                 uint64_t vr)
-{
-    return do_calc_cc(env, cc_op, src, dst, vr);
-}
-
-uint32_t HELPER(calc_cc)(uint32_t cc_op, uint64_t src, uint64_t dst,
-                         uint64_t vr)
-{
-    return do_calc_cc(env, cc_op, src, dst, vr);
-}
-
 uint64_t HELPER(cvd)(int32_t bin)
 {
     /* positive 0 */
@@ -1594,14 +1105,7 @@ void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans)
 }
 
 #ifndef CONFIG_USER_ONLY
-
-void HELPER(load_psw)(uint64_t mask, uint64_t addr)
-{
-    load_psw(env, mask, addr);
-    cpu_loop_exit(env);
-}
-
-static void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
+void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
 {
     qemu_log("program interrupt at %#" PRIx64 "\n", env->psw.addr);
 
@@ -2175,30 +1679,6 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
     return cc;
 }
 
-void HELPER(sacf)(uint64_t a1)
-{
-    HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1);
-
-    switch (a1 & 0xf00) {
-    case 0x000:
-        env->psw.mask &= ~PSW_MASK_ASC;
-        env->psw.mask |= PSW_ASC_PRIMARY;
-        break;
-    case 0x100:
-        env->psw.mask &= ~PSW_MASK_ASC;
-        env->psw.mask |= PSW_ASC_SECONDARY;
-        break;
-    case 0x300:
-        env->psw.mask &= ~PSW_MASK_ASC;
-        env->psw.mask |= PSW_ASC_HOME;
-        break;
-    default:
-        qemu_log("unknown sacf mode: %" PRIx64 "\n", a1);
-        program_interrupt(env, PGM_SPECIFICATION, 2);
-        break;
-    }
-}
-
 /* invalidate pte */
 void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
 {
commit e72ca652aa08e3d07c59349f239ba596f27c97af
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 2 07:33:31 2012 +0000

    target-s390x: split FPU ops
    
    Move floating point instructions to fpu_helper.c.
    
    While exporting some condition code helpers,
    avoid duplicate identifier conflict with translate.c.
    
    Remove unused set_cc_nz_f64() in translate.c.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 80be3bb..23b3bd9 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -1,5 +1,7 @@
 obj-y += translate.o op_helper.o helper.o cpu.o interrupt.o
+obj-y += fpu_helper.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
 
 $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+$(obj)/fpu_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 18ac6e3..b4620c5 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -999,4 +999,10 @@ static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb)
     env->psw.addr = tb->pc;
 }
 
+/* fpu_helper.c */
+uint32_t set_cc_f32(float32 v1, float32 v2);
+uint32_t set_cc_f64(float64 v1, float64 v2);
+uint32_t set_cc_nz_f32(float32 v);
+uint32_t set_cc_nz_f64(float64 v);
+
 #endif
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
new file mode 100644
index 0000000..1389052
--- /dev/null
+++ b/target-s390x/fpu_helper.c
@@ -0,0 +1,836 @@
+/*
+ *  S/390 FPU helper routines
+ *
+ *  Copyright (c) 2009 Ulrich Hecht
+ *  Copyright (c) 2009 Alexander Graf
+ *
+ * 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"
+
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif
+
+/* #define DEBUG_HELPER */
+#ifdef DEBUG_HELPER
+#define HELPER_LOG(x...) qemu_log(x)
+#else
+#define HELPER_LOG(x...)
+#endif
+
+static inline int float_comp_to_cc(int float_compare)
+{
+    switch (float_compare) {
+    case float_relation_equal:
+        return 0;
+    case float_relation_less:
+        return 1;
+    case float_relation_greater:
+        return 2;
+    case float_relation_unordered:
+        return 3;
+    default:
+        cpu_abort(env, "unknown return value for float compare\n");
+    }
+}
+
+/* condition codes for binary FP ops */
+uint32_t set_cc_f32(float32 v1, float32 v2)
+{
+    return float_comp_to_cc(float32_compare_quiet(v1, v2, &env->fpu_status));
+}
+
+uint32_t set_cc_f64(float64 v1, float64 v2)
+{
+    return float_comp_to_cc(float64_compare_quiet(v1, v2, &env->fpu_status));
+}
+
+/* condition codes for unary FP ops */
+uint32_t set_cc_nz_f32(float32 v)
+{
+    if (float32_is_any_nan(v)) {
+        return 3;
+    } else if (float32_is_zero(v)) {
+        return 0;
+    } else if (float32_is_neg(v)) {
+        return 1;
+    } else {
+        return 2;
+    }
+}
+
+uint32_t set_cc_nz_f64(float64 v)
+{
+    if (float64_is_any_nan(v)) {
+        return 3;
+    } else if (float64_is_zero(v)) {
+        return 0;
+    } else if (float64_is_neg(v)) {
+        return 1;
+    } else {
+        return 2;
+    }
+}
+
+static uint32_t set_cc_nz_f128(float128 v)
+{
+    if (float128_is_any_nan(v)) {
+        return 3;
+    } else if (float128_is_zero(v)) {
+        return 0;
+    } else if (float128_is_neg(v)) {
+        return 1;
+    } else {
+        return 2;
+    }
+}
+
+/* convert 32-bit int to 64-bit float */
+void HELPER(cdfbr)(uint32_t f1, int32_t v2)
+{
+    HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1);
+    env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status);
+}
+
+/* convert 32-bit int to 128-bit float */
+void HELPER(cxfbr)(uint32_t f1, int32_t v2)
+{
+    CPU_QuadU v1;
+
+    v1.q = int32_to_float128(v2, &env->fpu_status);
+    env->fregs[f1].ll = v1.ll.upper;
+    env->fregs[f1 + 2].ll = v1.ll.lower;
+}
+
+/* convert 64-bit int to 32-bit float */
+void HELPER(cegbr)(uint32_t f1, int64_t v2)
+{
+    HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
+    env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status);
+}
+
+/* convert 64-bit int to 64-bit float */
+void HELPER(cdgbr)(uint32_t f1, int64_t v2)
+{
+    HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
+    env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status);
+}
+
+/* convert 64-bit int to 128-bit float */
+void HELPER(cxgbr)(uint32_t f1, int64_t v2)
+{
+    CPU_QuadU x1;
+
+    x1.q = int64_to_float128(v2, &env->fpu_status);
+    HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__, v2,
+               x1.ll.upper, x1.ll.lower);
+    env->fregs[f1].ll = x1.ll.upper;
+    env->fregs[f1 + 2].ll = x1.ll.lower;
+}
+
+/* convert 32-bit int to 32-bit float */
+void HELPER(cefbr)(uint32_t f1, int32_t v2)
+{
+    env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
+    HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2,
+               env->fregs[f1].l.upper, f1);
+}
+
+/* 32-bit FP addition RR */
+uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
+                                         env->fregs[f2].l.upper,
+                                         &env->fpu_status);
+    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
+               env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
+
+    return set_cc_nz_f32(env->fregs[f1].l.upper);
+}
+
+/* 64-bit FP addition RR */
+uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d,
+                                   &env->fpu_status);
+    HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__,
+               env->fregs[f2].d, env->fregs[f1].d, f1);
+
+    return set_cc_nz_f64(env->fregs[f1].d);
+}
+
+/* 32-bit FP subtraction RR */
+uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
+                                         env->fregs[f2].l.upper,
+                                         &env->fpu_status);
+    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
+               env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
+
+    return set_cc_nz_f32(env->fregs[f1].l.upper);
+}
+
+/* 64-bit FP subtraction RR */
+uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
+                                   &env->fpu_status);
+    HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
+               __func__, env->fregs[f2].d, env->fregs[f1].d, f1);
+
+    return set_cc_nz_f64(env->fregs[f1].d);
+}
+
+/* 32-bit FP division RR */
+void HELPER(debr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper,
+                                         env->fregs[f2].l.upper,
+                                         &env->fpu_status);
+}
+
+/* 128-bit FP division RR */
+void HELPER(dxbr)(uint32_t f1, uint32_t f2)
+{
+    CPU_QuadU v1;
+    CPU_QuadU v2;
+    CPU_QuadU res;
+
+    v1.ll.upper = env->fregs[f1].ll;
+    v1.ll.lower = env->fregs[f1 + 2].ll;
+    v2.ll.upper = env->fregs[f2].ll;
+    v2.ll.lower = env->fregs[f2 + 2].ll;
+    res.q = float128_div(v1.q, v2.q, &env->fpu_status);
+    env->fregs[f1].ll = res.ll.upper;
+    env->fregs[f1 + 2].ll = res.ll.lower;
+}
+
+/* 64-bit FP multiplication RR */
+void HELPER(mdbr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d,
+                                   &env->fpu_status);
+}
+
+/* 128-bit FP multiplication RR */
+void HELPER(mxbr)(uint32_t f1, uint32_t f2)
+{
+    CPU_QuadU v1;
+    CPU_QuadU v2;
+    CPU_QuadU res;
+
+    v1.ll.upper = env->fregs[f1].ll;
+    v1.ll.lower = env->fregs[f1 + 2].ll;
+    v2.ll.upper = env->fregs[f2].ll;
+    v2.ll.lower = env->fregs[f2 + 2].ll;
+    res.q = float128_mul(v1.q, v2.q, &env->fpu_status);
+    env->fregs[f1].ll = res.ll.upper;
+    env->fregs[f1 + 2].ll = res.ll.lower;
+}
+
+/* convert 32-bit float to 64-bit float */
+void HELPER(ldebr)(uint32_t r1, uint32_t r2)
+{
+    env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper,
+                                          &env->fpu_status);
+}
+
+/* convert 128-bit float to 64-bit float */
+void HELPER(ldxbr)(uint32_t f1, uint32_t f2)
+{
+    CPU_QuadU x2;
+
+    x2.ll.upper = env->fregs[f2].ll;
+    x2.ll.lower = env->fregs[f2 + 2].ll;
+    env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status);
+    HELPER_LOG("%s: to 0x%ld\n", __func__, env->fregs[f1].d);
+}
+
+/* convert 64-bit float to 128-bit float */
+void HELPER(lxdbr)(uint32_t f1, uint32_t f2)
+{
+    CPU_QuadU res;
+
+    res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status);
+    env->fregs[f1].ll = res.ll.upper;
+    env->fregs[f1 + 2].ll = res.ll.lower;
+}
+
+/* convert 64-bit float to 32-bit float */
+void HELPER(ledbr)(uint32_t f1, uint32_t f2)
+{
+    float64 d2 = env->fregs[f2].d;
+
+    env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status);
+}
+
+/* convert 128-bit float to 32-bit float */
+void HELPER(lexbr)(uint32_t f1, uint32_t f2)
+{
+    CPU_QuadU x2;
+
+    x2.ll.upper = env->fregs[f2].ll;
+    x2.ll.lower = env->fregs[f2 + 2].ll;
+    env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status);
+    HELPER_LOG("%s: to 0x%d\n", __func__, env->fregs[f1].l.upper);
+}
+
+/* absolute value of 32-bit float */
+uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2)
+{
+    float32 v1;
+    float32 v2 = env->fregs[f2].d;
+
+    v1 = float32_abs(v2);
+    env->fregs[f1].d = v1;
+    return set_cc_nz_f32(v1);
+}
+
+/* absolute value of 64-bit float */
+uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2)
+{
+    float64 v1;
+    float64 v2 = env->fregs[f2].d;
+
+    v1 = float64_abs(v2);
+    env->fregs[f1].d = v1;
+    return set_cc_nz_f64(v1);
+}
+
+/* absolute value of 128-bit float */
+uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2)
+{
+    CPU_QuadU v1;
+    CPU_QuadU v2;
+
+    v2.ll.upper = env->fregs[f2].ll;
+    v2.ll.lower = env->fregs[f2 + 2].ll;
+    v1.q = float128_abs(v2.q);
+    env->fregs[f1].ll = v1.ll.upper;
+    env->fregs[f1 + 2].ll = v1.ll.lower;
+    return set_cc_nz_f128(v1.q);
+}
+
+/* load and test 64-bit float */
+uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].d = env->fregs[f2].d;
+    return set_cc_nz_f64(env->fregs[f1].d);
+}
+
+/* load and test 32-bit float */
+uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].l.upper = env->fregs[f2].l.upper;
+    return set_cc_nz_f32(env->fregs[f1].l.upper);
+}
+
+/* load and test 128-bit float */
+uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2)
+{
+    CPU_QuadU x;
+
+    x.ll.upper = env->fregs[f2].ll;
+    x.ll.lower = env->fregs[f2 + 2].ll;
+    env->fregs[f1].ll = x.ll.upper;
+    env->fregs[f1 + 2].ll = x.ll.lower;
+    return set_cc_nz_f128(x.q);
+}
+
+/* load complement of 32-bit float */
+uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper);
+
+    return set_cc_nz_f32(env->fregs[f1].l.upper);
+}
+
+/* load complement of 64-bit float */
+uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].d = float64_chs(env->fregs[f2].d);
+
+    return set_cc_nz_f64(env->fregs[f1].d);
+}
+
+/* load complement of 128-bit float */
+uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2)
+{
+    CPU_QuadU x1, x2;
+
+    x2.ll.upper = env->fregs[f2].ll;
+    x2.ll.lower = env->fregs[f2 + 2].ll;
+    x1.q = float128_chs(x2.q);
+    env->fregs[f1].ll = x1.ll.upper;
+    env->fregs[f1 + 2].ll = x1.ll.lower;
+    return set_cc_nz_f128(x1.q);
+}
+
+/* 32-bit FP addition RM */
+void HELPER(aeb)(uint32_t f1, uint32_t val)
+{
+    float32 v1 = env->fregs[f1].l.upper;
+    CPU_FloatU v2;
+
+    v2.l = val;
+    HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__,
+               v1, f1, v2.f);
+    env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status);
+}
+
+/* 32-bit FP division RM */
+void HELPER(deb)(uint32_t f1, uint32_t val)
+{
+    float32 v1 = env->fregs[f1].l.upper;
+    CPU_FloatU v2;
+
+    v2.l = val;
+    HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__,
+               v1, f1, v2.f);
+    env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status);
+}
+
+/* 32-bit FP multiplication RM */
+void HELPER(meeb)(uint32_t f1, uint32_t val)
+{
+    float32 v1 = env->fregs[f1].l.upper;
+    CPU_FloatU v2;
+
+    v2.l = val;
+    HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__,
+               v1, f1, v2.f);
+    env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
+}
+
+/* 32-bit FP compare RR */
+uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2)
+{
+    float32 v1 = env->fregs[f1].l.upper;
+    float32 v2 = env->fregs[f2].l.upper;
+
+    HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__,
+               v1, f1, v2);
+    return set_cc_f32(v1, v2);
+}
+
+/* 64-bit FP compare RR */
+uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2)
+{
+    float64 v1 = env->fregs[f1].d;
+    float64 v2 = env->fregs[f2].d;
+
+    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__,
+               v1, f1, v2);
+    return set_cc_f64(v1, v2);
+}
+
+/* 128-bit FP compare RR */
+uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2)
+{
+    CPU_QuadU v1;
+    CPU_QuadU v2;
+
+    v1.ll.upper = env->fregs[f1].ll;
+    v1.ll.lower = env->fregs[f1 + 2].ll;
+    v2.ll.upper = env->fregs[f2].ll;
+    v2.ll.lower = env->fregs[f2 + 2].ll;
+
+    return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q,
+                                                   &env->fpu_status));
+}
+
+/* 64-bit FP compare RM */
+uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2)
+{
+    float64 v1 = env->fregs[f1].d;
+    CPU_DoubleU v2;
+
+    v2.ll = ldq(a2);
+    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1,
+               f1, v2.d);
+    return set_cc_f64(v1, v2.d);
+}
+
+/* 64-bit FP addition RM */
+uint32_t HELPER(adb)(uint32_t f1, uint64_t a2)
+{
+    float64 v1 = env->fregs[f1].d;
+    CPU_DoubleU v2;
+
+    v2.ll = ldq(a2);
+    HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__,
+               v1, f1, v2.d);
+    env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
+    return set_cc_nz_f64(v1);
+}
+
+/* 32-bit FP subtraction RM */
+void HELPER(seb)(uint32_t f1, uint32_t val)
+{
+    float32 v1 = env->fregs[f1].l.upper;
+    CPU_FloatU v2;
+
+    v2.l = val;
+    env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status);
+}
+
+/* 64-bit FP subtraction RM */
+uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2)
+{
+    float64 v1 = env->fregs[f1].d;
+    CPU_DoubleU v2;
+
+    v2.ll = ldq(a2);
+    env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status);
+    return set_cc_nz_f64(v1);
+}
+
+/* 64-bit FP multiplication RM */
+void HELPER(mdb)(uint32_t f1, uint64_t a2)
+{
+    float64 v1 = env->fregs[f1].d;
+    CPU_DoubleU v2;
+
+    v2.ll = ldq(a2);
+    HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__,
+               v1, f1, v2.d);
+    env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
+}
+
+/* 64-bit FP division RM */
+void HELPER(ddb)(uint32_t f1, uint64_t a2)
+{
+    float64 v1 = env->fregs[f1].d;
+    CPU_DoubleU v2;
+
+    v2.ll = ldq(a2);
+    HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__,
+               v1, f1, v2.d);
+    env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
+}
+
+static void set_round_mode(int m3)
+{
+    switch (m3) {
+    case 0:
+        /* current mode */
+        break;
+    case 1:
+        /* biased round no nearest */
+    case 4:
+        /* round to nearest */
+        set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
+        break;
+    case 5:
+        /* round to zero */
+        set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
+        break;
+    case 6:
+        /* round to +inf */
+        set_float_rounding_mode(float_round_up, &env->fpu_status);
+        break;
+    case 7:
+        /* round to -inf */
+        set_float_rounding_mode(float_round_down, &env->fpu_status);
+        break;
+    }
+}
+
+/* convert 32-bit float to 64-bit int */
+uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3)
+{
+    float32 v2 = env->fregs[f2].l.upper;
+
+    set_round_mode(m3);
+    env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
+    return set_cc_nz_f32(v2);
+}
+
+/* convert 64-bit float to 64-bit int */
+uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
+{
+    float64 v2 = env->fregs[f2].d;
+
+    set_round_mode(m3);
+    env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
+    return set_cc_nz_f64(v2);
+}
+
+/* convert 128-bit float to 64-bit int */
+uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
+{
+    CPU_QuadU v2;
+
+    v2.ll.upper = env->fregs[f2].ll;
+    v2.ll.lower = env->fregs[f2 + 2].ll;
+    set_round_mode(m3);
+    env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status);
+    if (float128_is_any_nan(v2.q)) {
+        return 3;
+    } else if (float128_is_zero(v2.q)) {
+        return 0;
+    } else if (float128_is_neg(v2.q)) {
+        return 1;
+    } else {
+        return 2;
+    }
+}
+
+/* convert 32-bit float to 32-bit int */
+uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3)
+{
+    float32 v2 = env->fregs[f2].l.upper;
+
+    set_round_mode(m3);
+    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
+        float32_to_int32(v2, &env->fpu_status);
+    return set_cc_nz_f32(v2);
+}
+
+/* convert 64-bit float to 32-bit int */
+uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
+{
+    float64 v2 = env->fregs[f2].d;
+
+    set_round_mode(m3);
+    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
+        float64_to_int32(v2, &env->fpu_status);
+    return set_cc_nz_f64(v2);
+}
+
+/* convert 128-bit float to 32-bit int */
+uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
+{
+    CPU_QuadU v2;
+
+    v2.ll.upper = env->fregs[f2].ll;
+    v2.ll.lower = env->fregs[f2 + 2].ll;
+    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
+        float128_to_int32(v2.q, &env->fpu_status);
+    return set_cc_nz_f128(v2.q);
+}
+
+/* load 32-bit FP zero */
+void HELPER(lzer)(uint32_t f1)
+{
+    env->fregs[f1].l.upper = float32_zero;
+}
+
+/* load 64-bit FP zero */
+void HELPER(lzdr)(uint32_t f1)
+{
+    env->fregs[f1].d = float64_zero;
+}
+
+/* load 128-bit FP zero */
+void HELPER(lzxr)(uint32_t f1)
+{
+    CPU_QuadU x;
+
+    x.q = float64_to_float128(float64_zero, &env->fpu_status);
+    env->fregs[f1].ll = x.ll.upper;
+    env->fregs[f1 + 1].ll = x.ll.lower;
+}
+
+/* 128-bit FP subtraction RR */
+uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2)
+{
+    CPU_QuadU v1;
+    CPU_QuadU v2;
+    CPU_QuadU res;
+
+    v1.ll.upper = env->fregs[f1].ll;
+    v1.ll.lower = env->fregs[f1 + 2].ll;
+    v2.ll.upper = env->fregs[f2].ll;
+    v2.ll.lower = env->fregs[f2 + 2].ll;
+    res.q = float128_sub(v1.q, v2.q, &env->fpu_status);
+    env->fregs[f1].ll = res.ll.upper;
+    env->fregs[f1 + 2].ll = res.ll.lower;
+    return set_cc_nz_f128(res.q);
+}
+
+/* 128-bit FP addition RR */
+uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2)
+{
+    CPU_QuadU v1;
+    CPU_QuadU v2;
+    CPU_QuadU res;
+
+    v1.ll.upper = env->fregs[f1].ll;
+    v1.ll.lower = env->fregs[f1 + 2].ll;
+    v2.ll.upper = env->fregs[f2].ll;
+    v2.ll.lower = env->fregs[f2 + 2].ll;
+    res.q = float128_add(v1.q, v2.q, &env->fpu_status);
+    env->fregs[f1].ll = res.ll.upper;
+    env->fregs[f1 + 2].ll = res.ll.lower;
+    return set_cc_nz_f128(res.q);
+}
+
+/* 32-bit FP multiplication RR */
+void HELPER(meebr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper,
+                                         env->fregs[f2].l.upper,
+                                         &env->fpu_status);
+}
+
+/* 64-bit FP division RR */
+void HELPER(ddbr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d,
+                                   &env->fpu_status);
+}
+
+/* 64-bit FP multiply and add RM */
+void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3)
+{
+    CPU_DoubleU v2;
+
+    HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3);
+    v2.ll = ldq(a2);
+    env->fregs[f1].d = float64_add(env->fregs[f1].d,
+                                   float64_mul(v2.d, env->fregs[f3].d,
+                                               &env->fpu_status),
+                                   &env->fpu_status);
+}
+
+/* 64-bit FP multiply and add RR */
+void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2)
+{
+    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
+    env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d,
+                                               env->fregs[f3].d,
+                                               &env->fpu_status),
+                                   env->fregs[f1].d, &env->fpu_status);
+}
+
+/* 64-bit FP multiply and subtract RR */
+void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2)
+{
+    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
+    env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d,
+                                               env->fregs[f3].d,
+                                               &env->fpu_status),
+                                   env->fregs[f1].d, &env->fpu_status);
+}
+
+/* 32-bit FP multiply and add RR */
+void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2)
+{
+    env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
+                                         float32_mul(env->fregs[f2].l.upper,
+                                                     env->fregs[f3].l.upper,
+                                                     &env->fpu_status),
+                                         &env->fpu_status);
+}
+
+/* convert 32-bit float to 64-bit float */
+void HELPER(ldeb)(uint32_t f1, uint64_t a2)
+{
+    uint32_t v2;
+
+    v2 = ldl(a2);
+    env->fregs[f1].d = float32_to_float64(v2,
+                                          &env->fpu_status);
+}
+
+/* convert 64-bit float to 128-bit float */
+void HELPER(lxdb)(uint32_t f1, uint64_t a2)
+{
+    CPU_DoubleU v2;
+    CPU_QuadU v1;
+
+    v2.ll = ldq(a2);
+    v1.q = float64_to_float128(v2.d, &env->fpu_status);
+    env->fregs[f1].ll = v1.ll.upper;
+    env->fregs[f1 + 2].ll = v1.ll.lower;
+}
+
+/* test data class 32-bit */
+uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2)
+{
+    float32 v1 = env->fregs[f1].l.upper;
+    int neg = float32_is_neg(v1);
+    uint32_t cc = 0;
+
+    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, (long)v1, m2, neg);
+    if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
+        (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
+        (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
+        (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
+        cc = 1;
+    } else if (m2 & (1 << (9-neg))) {
+        /* assume normalized number */
+        cc = 1;
+    }
+
+    /* FIXME: denormalized? */
+    return cc;
+}
+
+/* test data class 64-bit */
+uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2)
+{
+    float64 v1 = env->fregs[f1].d;
+    int neg = float64_is_neg(v1);
+    uint32_t cc = 0;
+
+    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg);
+    if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
+        (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
+        (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
+        (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
+        cc = 1;
+    } else if (m2 & (1 << (9-neg))) {
+        /* assume normalized number */
+        cc = 1;
+    }
+    /* FIXME: denormalized? */
+    return cc;
+}
+
+/* test data class 128-bit */
+uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2)
+{
+    CPU_QuadU v1;
+    uint32_t cc = 0;
+    int neg;
+
+    v1.ll.upper = env->fregs[f1].ll;
+    v1.ll.lower = env->fregs[f1 + 2].ll;
+
+    neg = float128_is_neg(v1.q);
+    if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) ||
+        (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) ||
+        (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) ||
+        (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) {
+        cc = 1;
+    } else if (m2 & (1 << (9-neg))) {
+        /* assume normalized number */
+        cc = 1;
+    }
+    /* FIXME: denormalized? */
+    return cc;
+}
+
+/* square root 64-bit RR */
+void HELPER(sqdbr)(uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
+}
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 195e93e..270bf14 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -977,802 +977,6 @@ uint32_t HELPER(slbg)(uint32_t cc, uint32_t r1, uint64_t v1, uint64_t v2)
     }
 }
 
-static inline int float_comp_to_cc(int float_compare)
-{
-    switch (float_compare) {
-    case float_relation_equal:
-        return 0;
-    case float_relation_less:
-        return 1;
-    case float_relation_greater:
-        return 2;
-    case float_relation_unordered:
-        return 3;
-    default:
-        cpu_abort(env, "unknown return value for float compare\n");
-    }
-}
-
-/* condition codes for binary FP ops */
-static uint32_t set_cc_f32(float32 v1, float32 v2)
-{
-    return float_comp_to_cc(float32_compare_quiet(v1, v2, &env->fpu_status));
-}
-
-static uint32_t set_cc_f64(float64 v1, float64 v2)
-{
-    return float_comp_to_cc(float64_compare_quiet(v1, v2, &env->fpu_status));
-}
-
-/* condition codes for unary FP ops */
-static uint32_t set_cc_nz_f32(float32 v)
-{
-    if (float32_is_any_nan(v)) {
-        return 3;
-    } else if (float32_is_zero(v)) {
-        return 0;
-    } else if (float32_is_neg(v)) {
-        return 1;
-    } else {
-        return 2;
-    }
-}
-
-static uint32_t set_cc_nz_f64(float64 v)
-{
-    if (float64_is_any_nan(v)) {
-        return 3;
-    } else if (float64_is_zero(v)) {
-        return 0;
-    } else if (float64_is_neg(v)) {
-        return 1;
-    } else {
-        return 2;
-    }
-}
-
-static uint32_t set_cc_nz_f128(float128 v)
-{
-    if (float128_is_any_nan(v)) {
-        return 3;
-    } else if (float128_is_zero(v)) {
-        return 0;
-    } else if (float128_is_neg(v)) {
-        return 1;
-    } else {
-        return 2;
-    }
-}
-
-/* convert 32-bit int to 64-bit float */
-void HELPER(cdfbr)(uint32_t f1, int32_t v2)
-{
-    HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1);
-    env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status);
-}
-
-/* convert 32-bit int to 128-bit float */
-void HELPER(cxfbr)(uint32_t f1, int32_t v2)
-{
-    CPU_QuadU v1;
-
-    v1.q = int32_to_float128(v2, &env->fpu_status);
-    env->fregs[f1].ll = v1.ll.upper;
-    env->fregs[f1 + 2].ll = v1.ll.lower;
-}
-
-/* convert 64-bit int to 32-bit float */
-void HELPER(cegbr)(uint32_t f1, int64_t v2)
-{
-    HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
-    env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status);
-}
-
-/* convert 64-bit int to 64-bit float */
-void HELPER(cdgbr)(uint32_t f1, int64_t v2)
-{
-    HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
-    env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status);
-}
-
-/* convert 64-bit int to 128-bit float */
-void HELPER(cxgbr)(uint32_t f1, int64_t v2)
-{
-    CPU_QuadU x1;
-
-    x1.q = int64_to_float128(v2, &env->fpu_status);
-    HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__, v2,
-               x1.ll.upper, x1.ll.lower);
-    env->fregs[f1].ll = x1.ll.upper;
-    env->fregs[f1 + 2].ll = x1.ll.lower;
-}
-
-/* convert 32-bit int to 32-bit float */
-void HELPER(cefbr)(uint32_t f1, int32_t v2)
-{
-    env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
-    HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2,
-               env->fregs[f1].l.upper, f1);
-}
-
-/* 32-bit FP addition RR */
-uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
-                                         env->fregs[f2].l.upper,
-                                         &env->fpu_status);
-    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
-               env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
-
-    return set_cc_nz_f32(env->fregs[f1].l.upper);
-}
-
-/* 64-bit FP addition RR */
-uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d,
-                                   &env->fpu_status);
-    HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__,
-               env->fregs[f2].d, env->fregs[f1].d, f1);
-
-    return set_cc_nz_f64(env->fregs[f1].d);
-}
-
-/* 32-bit FP subtraction RR */
-uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
-                                         env->fregs[f2].l.upper,
-                                         &env->fpu_status);
-    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
-               env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
-
-    return set_cc_nz_f32(env->fregs[f1].l.upper);
-}
-
-/* 64-bit FP subtraction RR */
-uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
-                                   &env->fpu_status);
-    HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
-               __func__, env->fregs[f2].d, env->fregs[f1].d, f1);
-
-    return set_cc_nz_f64(env->fregs[f1].d);
-}
-
-/* 32-bit FP division RR */
-void HELPER(debr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper,
-                                         env->fregs[f2].l.upper,
-                                         &env->fpu_status);
-}
-
-/* 128-bit FP division RR */
-void HELPER(dxbr)(uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU v1;
-    CPU_QuadU v2;
-    CPU_QuadU res;
-
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    res.q = float128_div(v1.q, v2.q, &env->fpu_status);
-    env->fregs[f1].ll = res.ll.upper;
-    env->fregs[f1 + 2].ll = res.ll.lower;
-}
-
-/* 64-bit FP multiplication RR */
-void HELPER(mdbr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d,
-                                   &env->fpu_status);
-}
-
-/* 128-bit FP multiplication RR */
-void HELPER(mxbr)(uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU v1;
-    CPU_QuadU v2;
-    CPU_QuadU res;
-
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    res.q = float128_mul(v1.q, v2.q, &env->fpu_status);
-    env->fregs[f1].ll = res.ll.upper;
-    env->fregs[f1 + 2].ll = res.ll.lower;
-}
-
-/* convert 32-bit float to 64-bit float */
-void HELPER(ldebr)(uint32_t r1, uint32_t r2)
-{
-    env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper,
-                                          &env->fpu_status);
-}
-
-/* convert 128-bit float to 64-bit float */
-void HELPER(ldxbr)(uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU x2;
-
-    x2.ll.upper = env->fregs[f2].ll;
-    x2.ll.lower = env->fregs[f2 + 2].ll;
-    env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status);
-    HELPER_LOG("%s: to 0x%ld\n", __func__, env->fregs[f1].d);
-}
-
-/* convert 64-bit float to 128-bit float */
-void HELPER(lxdbr)(uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU res;
-
-    res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status);
-    env->fregs[f1].ll = res.ll.upper;
-    env->fregs[f1 + 2].ll = res.ll.lower;
-}
-
-/* convert 64-bit float to 32-bit float */
-void HELPER(ledbr)(uint32_t f1, uint32_t f2)
-{
-    float64 d2 = env->fregs[f2].d;
-
-    env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status);
-}
-
-/* convert 128-bit float to 32-bit float */
-void HELPER(lexbr)(uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU x2;
-
-    x2.ll.upper = env->fregs[f2].ll;
-    x2.ll.lower = env->fregs[f2 + 2].ll;
-    env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status);
-    HELPER_LOG("%s: to 0x%d\n", __func__, env->fregs[f1].l.upper);
-}
-
-/* absolute value of 32-bit float */
-uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2)
-{
-    float32 v1;
-    float32 v2 = env->fregs[f2].d;
-
-    v1 = float32_abs(v2);
-    env->fregs[f1].d = v1;
-    return set_cc_nz_f32(v1);
-}
-
-/* absolute value of 64-bit float */
-uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2)
-{
-    float64 v1;
-    float64 v2 = env->fregs[f2].d;
-
-    v1 = float64_abs(v2);
-    env->fregs[f1].d = v1;
-    return set_cc_nz_f64(v1);
-}
-
-/* absolute value of 128-bit float */
-uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU v1;
-    CPU_QuadU v2;
-
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    v1.q = float128_abs(v2.q);
-    env->fregs[f1].ll = v1.ll.upper;
-    env->fregs[f1 + 2].ll = v1.ll.lower;
-    return set_cc_nz_f128(v1.q);
-}
-
-/* load and test 64-bit float */
-uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].d = env->fregs[f2].d;
-    return set_cc_nz_f64(env->fregs[f1].d);
-}
-
-/* load and test 32-bit float */
-uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].l.upper = env->fregs[f2].l.upper;
-    return set_cc_nz_f32(env->fregs[f1].l.upper);
-}
-
-/* load and test 128-bit float */
-uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU x;
-
-    x.ll.upper = env->fregs[f2].ll;
-    x.ll.lower = env->fregs[f2 + 2].ll;
-    env->fregs[f1].ll = x.ll.upper;
-    env->fregs[f1 + 2].ll = x.ll.lower;
-    return set_cc_nz_f128(x.q);
-}
-
-/* load complement of 32-bit float */
-uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper);
-
-    return set_cc_nz_f32(env->fregs[f1].l.upper);
-}
-
-/* load complement of 64-bit float */
-uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].d = float64_chs(env->fregs[f2].d);
-
-    return set_cc_nz_f64(env->fregs[f1].d);
-}
-
-/* load complement of 128-bit float */
-uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU x1, x2;
-
-    x2.ll.upper = env->fregs[f2].ll;
-    x2.ll.lower = env->fregs[f2 + 2].ll;
-    x1.q = float128_chs(x2.q);
-    env->fregs[f1].ll = x1.ll.upper;
-    env->fregs[f1 + 2].ll = x1.ll.lower;
-    return set_cc_nz_f128(x1.q);
-}
-
-/* 32-bit FP addition RM */
-void HELPER(aeb)(uint32_t f1, uint32_t val)
-{
-    float32 v1 = env->fregs[f1].l.upper;
-    CPU_FloatU v2;
-
-    v2.l = val;
-    HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__,
-               v1, f1, v2.f);
-    env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status);
-}
-
-/* 32-bit FP division RM */
-void HELPER(deb)(uint32_t f1, uint32_t val)
-{
-    float32 v1 = env->fregs[f1].l.upper;
-    CPU_FloatU v2;
-
-    v2.l = val;
-    HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__,
-               v1, f1, v2.f);
-    env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status);
-}
-
-/* 32-bit FP multiplication RM */
-void HELPER(meeb)(uint32_t f1, uint32_t val)
-{
-    float32 v1 = env->fregs[f1].l.upper;
-    CPU_FloatU v2;
-
-    v2.l = val;
-    HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__,
-               v1, f1, v2.f);
-    env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
-}
-
-/* 32-bit FP compare RR */
-uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2)
-{
-    float32 v1 = env->fregs[f1].l.upper;
-    float32 v2 = env->fregs[f2].l.upper;
-
-    HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__,
-               v1, f1, v2);
-    return set_cc_f32(v1, v2);
-}
-
-/* 64-bit FP compare RR */
-uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2)
-{
-    float64 v1 = env->fregs[f1].d;
-    float64 v2 = env->fregs[f2].d;
-
-    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__,
-               v1, f1, v2);
-    return set_cc_f64(v1, v2);
-}
-
-/* 128-bit FP compare RR */
-uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU v1;
-    CPU_QuadU v2;
-
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-
-    return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q,
-                                                   &env->fpu_status));
-}
-
-/* 64-bit FP compare RM */
-uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2)
-{
-    float64 v1 = env->fregs[f1].d;
-    CPU_DoubleU v2;
-
-    v2.ll = ldq(a2);
-    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1,
-               f1, v2.d);
-    return set_cc_f64(v1, v2.d);
-}
-
-/* 64-bit FP addition RM */
-uint32_t HELPER(adb)(uint32_t f1, uint64_t a2)
-{
-    float64 v1 = env->fregs[f1].d;
-    CPU_DoubleU v2;
-
-    v2.ll = ldq(a2);
-    HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__,
-               v1, f1, v2.d);
-    env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
-    return set_cc_nz_f64(v1);
-}
-
-/* 32-bit FP subtraction RM */
-void HELPER(seb)(uint32_t f1, uint32_t val)
-{
-    float32 v1 = env->fregs[f1].l.upper;
-    CPU_FloatU v2;
-
-    v2.l = val;
-    env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status);
-}
-
-/* 64-bit FP subtraction RM */
-uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2)
-{
-    float64 v1 = env->fregs[f1].d;
-    CPU_DoubleU v2;
-
-    v2.ll = ldq(a2);
-    env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status);
-    return set_cc_nz_f64(v1);
-}
-
-/* 64-bit FP multiplication RM */
-void HELPER(mdb)(uint32_t f1, uint64_t a2)
-{
-    float64 v1 = env->fregs[f1].d;
-    CPU_DoubleU v2;
-
-    v2.ll = ldq(a2);
-    HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__,
-               v1, f1, v2.d);
-    env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
-}
-
-/* 64-bit FP division RM */
-void HELPER(ddb)(uint32_t f1, uint64_t a2)
-{
-    float64 v1 = env->fregs[f1].d;
-    CPU_DoubleU v2;
-
-    v2.ll = ldq(a2);
-    HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__,
-               v1, f1, v2.d);
-    env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
-}
-
-static void set_round_mode(int m3)
-{
-    switch (m3) {
-    case 0:
-        /* current mode */
-        break;
-    case 1:
-        /* biased round no nearest */
-    case 4:
-        /* round to nearest */
-        set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
-        break;
-    case 5:
-        /* round to zero */
-        set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
-        break;
-    case 6:
-        /* round to +inf */
-        set_float_rounding_mode(float_round_up, &env->fpu_status);
-        break;
-    case 7:
-        /* round to -inf */
-        set_float_rounding_mode(float_round_down, &env->fpu_status);
-        break;
-    }
-}
-
-/* convert 32-bit float to 64-bit int */
-uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3)
-{
-    float32 v2 = env->fregs[f2].l.upper;
-
-    set_round_mode(m3);
-    env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
-    return set_cc_nz_f32(v2);
-}
-
-/* convert 64-bit float to 64-bit int */
-uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
-{
-    float64 v2 = env->fregs[f2].d;
-
-    set_round_mode(m3);
-    env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
-    return set_cc_nz_f64(v2);
-}
-
-/* convert 128-bit float to 64-bit int */
-uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
-{
-    CPU_QuadU v2;
-
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    set_round_mode(m3);
-    env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status);
-    if (float128_is_any_nan(v2.q)) {
-        return 3;
-    } else if (float128_is_zero(v2.q)) {
-        return 0;
-    } else if (float128_is_neg(v2.q)) {
-        return 1;
-    } else {
-        return 2;
-    }
-}
-
-/* convert 32-bit float to 32-bit int */
-uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3)
-{
-    float32 v2 = env->fregs[f2].l.upper;
-
-    set_round_mode(m3);
-    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-        float32_to_int32(v2, &env->fpu_status);
-    return set_cc_nz_f32(v2);
-}
-
-/* convert 64-bit float to 32-bit int */
-uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
-{
-    float64 v2 = env->fregs[f2].d;
-
-    set_round_mode(m3);
-    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-        float64_to_int32(v2, &env->fpu_status);
-    return set_cc_nz_f64(v2);
-}
-
-/* convert 128-bit float to 32-bit int */
-uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
-{
-    CPU_QuadU v2;
-
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-        float128_to_int32(v2.q, &env->fpu_status);
-    return set_cc_nz_f128(v2.q);
-}
-
-/* load 32-bit FP zero */
-void HELPER(lzer)(uint32_t f1)
-{
-    env->fregs[f1].l.upper = float32_zero;
-}
-
-/* load 64-bit FP zero */
-void HELPER(lzdr)(uint32_t f1)
-{
-    env->fregs[f1].d = float64_zero;
-}
-
-/* load 128-bit FP zero */
-void HELPER(lzxr)(uint32_t f1)
-{
-    CPU_QuadU x;
-
-    x.q = float64_to_float128(float64_zero, &env->fpu_status);
-    env->fregs[f1].ll = x.ll.upper;
-    env->fregs[f1 + 1].ll = x.ll.lower;
-}
-
-/* 128-bit FP subtraction RR */
-uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU v1;
-    CPU_QuadU v2;
-    CPU_QuadU res;
-
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    res.q = float128_sub(v1.q, v2.q, &env->fpu_status);
-    env->fregs[f1].ll = res.ll.upper;
-    env->fregs[f1 + 2].ll = res.ll.lower;
-    return set_cc_nz_f128(res.q);
-}
-
-/* 128-bit FP addition RR */
-uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU v1;
-    CPU_QuadU v2;
-    CPU_QuadU res;
-
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    res.q = float128_add(v1.q, v2.q, &env->fpu_status);
-    env->fregs[f1].ll = res.ll.upper;
-    env->fregs[f1 + 2].ll = res.ll.lower;
-    return set_cc_nz_f128(res.q);
-}
-
-/* 32-bit FP multiplication RR */
-void HELPER(meebr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper,
-                                         env->fregs[f2].l.upper,
-                                         &env->fpu_status);
-}
-
-/* 64-bit FP division RR */
-void HELPER(ddbr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d,
-                                   &env->fpu_status);
-}
-
-/* 64-bit FP multiply and add RM */
-void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3)
-{
-    CPU_DoubleU v2;
-
-    HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3);
-    v2.ll = ldq(a2);
-    env->fregs[f1].d = float64_add(env->fregs[f1].d,
-                                   float64_mul(v2.d, env->fregs[f3].d,
-                                               &env->fpu_status),
-                                   &env->fpu_status);
-}
-
-/* 64-bit FP multiply and add RR */
-void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2)
-{
-    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
-    env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d,
-                                               env->fregs[f3].d,
-                                               &env->fpu_status),
-                                   env->fregs[f1].d, &env->fpu_status);
-}
-
-/* 64-bit FP multiply and subtract RR */
-void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2)
-{
-    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
-    env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d,
-                                               env->fregs[f3].d,
-                                               &env->fpu_status),
-                                   env->fregs[f1].d, &env->fpu_status);
-}
-
-/* 32-bit FP multiply and add RR */
-void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2)
-{
-    env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
-                                         float32_mul(env->fregs[f2].l.upper,
-                                                     env->fregs[f3].l.upper,
-                                                     &env->fpu_status),
-                                         &env->fpu_status);
-}
-
-/* convert 32-bit float to 64-bit float */
-void HELPER(ldeb)(uint32_t f1, uint64_t a2)
-{
-    uint32_t v2;
-
-    v2 = ldl(a2);
-    env->fregs[f1].d = float32_to_float64(v2,
-                                          &env->fpu_status);
-}
-
-/* convert 64-bit float to 128-bit float */
-void HELPER(lxdb)(uint32_t f1, uint64_t a2)
-{
-    CPU_DoubleU v2;
-    CPU_QuadU v1;
-
-    v2.ll = ldq(a2);
-    v1.q = float64_to_float128(v2.d, &env->fpu_status);
-    env->fregs[f1].ll = v1.ll.upper;
-    env->fregs[f1 + 2].ll = v1.ll.lower;
-}
-
-/* test data class 32-bit */
-uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2)
-{
-    float32 v1 = env->fregs[f1].l.upper;
-    int neg = float32_is_neg(v1);
-    uint32_t cc = 0;
-
-    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, (long)v1, m2, neg);
-    if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
-        (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
-        (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
-        (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
-        cc = 1;
-    } else if (m2 & (1 << (9-neg))) {
-        /* assume normalized number */
-        cc = 1;
-    }
-
-    /* FIXME: denormalized? */
-    return cc;
-}
-
-/* test data class 64-bit */
-uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2)
-{
-    float64 v1 = env->fregs[f1].d;
-    int neg = float64_is_neg(v1);
-    uint32_t cc = 0;
-
-    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg);
-    if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
-        (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
-        (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
-        (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
-        cc = 1;
-    } else if (m2 & (1 << (9-neg))) {
-        /* assume normalized number */
-        cc = 1;
-    }
-    /* FIXME: denormalized? */
-    return cc;
-}
-
-/* test data class 128-bit */
-uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2)
-{
-    CPU_QuadU v1;
-    uint32_t cc = 0;
-    int neg;
-
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
-
-    neg = float128_is_neg(v1.q);
-    if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) ||
-        (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) ||
-        (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) ||
-        (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) {
-        cc = 1;
-    } else if (m2 & (1 << (9-neg))) {
-        /* assume normalized number */
-        cc = 1;
-    }
-    /* FIXME: denormalized? */
-    return cc;
-}
-
 /* find leftmost one */
 uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
 {
@@ -1795,12 +999,6 @@ uint32_t HELPER(flogr)(uint32_t r1, uint64_t v2)
     }
 }
 
-/* square root 64-bit RR */
-void HELPER(sqdbr)(uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
-}
-
 /* checksum */
 void HELPER(cksm)(uint32_t r1, uint32_t r2)
 {
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1c1baf5..c370df3 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -667,16 +667,11 @@ static void set_cc_cmp_f32_i64(DisasContext *s, TCGv_i32 v1, TCGv_i64 v2)
     s->cc_op = CC_OP_LTGT_F32;
 }
 
-static void set_cc_nz_f32(DisasContext *s, TCGv_i32 v1)
+static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i32 v1)
 {
     gen_op_update1_cc_i32(s, CC_OP_NZ_F32, v1);
 }
 
-static inline void set_cc_nz_f64(DisasContext *s, TCGv_i64 v1)
-{
-    gen_op_update1_cc_i64(s, CC_OP_NZ_F64, v1);
-}
-
 /* CC value is in env->cc_op */
 static inline void set_cc_static(DisasContext *s)
 {
@@ -2235,7 +2230,7 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
         tcg_temp_free_i32(tmp32);
 
         tmp32 = load_freg32(r1);
-        set_cc_nz_f32(s, tmp32);
+        gen_set_cc_nz_f32(s, tmp32);
         tcg_temp_free_i32(tmp32);
         break;
     case 0xb: /* SEB    R1,D2(X2,B2)       [RXE] */
@@ -2248,7 +2243,7 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
         tcg_temp_free_i32(tmp32);
 
         tmp32 = load_freg32(r1);
-        set_cc_nz_f32(s, tmp32);
+        gen_set_cc_nz_f32(s, tmp32);
         tcg_temp_free_i32(tmp32);
         break;
     case 0xd: /* DEB    R1,D2(X2,B2)       [RXE] */
commit 71e470886fb6092504503a5fe41092ace71c096c
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Sep 2 07:33:30 2012 +0000

    target-s390x: fix style
    
    Before splitting op_helper.c and helper.c in the next patches,
    fix style issues. No functional changes.
    
    Replace also GCC specific __FUNCTION__ with
    standard __func__.
    
    Don't init static variable (cpu_s390x_init:inited) with 0.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index d0a1180..d98e6d9 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -74,7 +74,7 @@ S390CPU *cpu_s390x_init(const char *cpu_model)
 {
     S390CPU *cpu;
     CPUS390XState *env;
-    static int inited = 0;
+    static int inited;
 
     cpu = S390_CPU(object_new(TYPE_S390_CPU));
     env = &cpu->env;
@@ -91,25 +91,27 @@ S390CPU *cpu_s390x_init(const char *cpu_model)
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUS390XState *env)
+void do_interrupt(CPUS390XState *env)
 {
     env->exception_index = -1;
 }
 
-int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw,
-                                int mmu_idx)
+int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong address,
+                               int rw, int mmu_idx)
 {
-    /* fprintf(stderr,"%s: address 0x%lx rw %d mmu_idx %d\n",
-            __FUNCTION__, address, rw, mmu_idx); */
+    /* fprintf(stderr, "%s: address 0x%lx rw %d mmu_idx %d\n",
+       __func__, address, rw, mmu_idx); */
     env->exception_index = EXCP_ADDR;
-    env->__excp_addr = address; /* FIXME: find out how this works on a real machine */
+    /* FIXME: find out how this works on a real machine */
+    env->__excp_addr = address;
     return 1;
 }
 
 #else /* !CONFIG_USER_ONLY */
 
 /* Ensure to exit the TB after this call! */
-static void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilc)
+static void trigger_pgm_exception(CPUS390XState *env, uint32_t code,
+                                  uint32_t ilc)
 {
     env->exception_index = EXCP_PGM;
     env->int_pgm_code = code;
@@ -138,19 +140,20 @@ static int trans_bits(CPUS390XState *env, uint64_t mode)
     return bits;
 }
 
-static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr, uint64_t mode)
+static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
+                               uint64_t mode)
 {
     int ilc = ILC_LATER_INC_2;
     int bits = trans_bits(env, mode) | 4;
 
-    DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __FUNCTION__, vaddr, bits);
+    DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
 
     stq_phys(env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
     trigger_pgm_exception(env, PGM_PROTECTION, ilc);
 }
 
-static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr, uint32_t type,
-                               uint64_t asc, int rw)
+static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
+                               uint32_t type, uint64_t asc, int rw)
 {
     int ilc = ILC_LATER;
     int bits = trans_bits(env, asc);
@@ -160,26 +163,26 @@ static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr, uint32_t
         ilc = 2;
     }
 
-    DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __FUNCTION__, vaddr, bits);
+    DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
 
     stq_phys(env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
     trigger_pgm_exception(env, type, ilc);
 }
 
-static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, uint64_t asc,
-                              uint64_t asce, int level, target_ulong *raddr,
-                              int *flags, int rw)
+static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
+                              uint64_t asc, uint64_t asce, int level,
+                              target_ulong *raddr, int *flags, int rw)
 {
     uint64_t offs = 0;
     uint64_t origin;
     uint64_t new_asce;
 
-    PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __FUNCTION__, asce);
+    PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, asce);
 
     if (((level != _ASCE_TYPE_SEGMENT) && (asce & _REGION_ENTRY_INV)) ||
         ((level == _ASCE_TYPE_SEGMENT) && (asce & _SEGMENT_ENTRY_INV))) {
         /* XXX different regions have different faults */
-        DPRINTF("%s: invalid region\n", __FUNCTION__);
+        DPRINTF("%s: invalid region\n", __func__);
         trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw);
         return -1;
     }
@@ -222,7 +225,7 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, uint64_t a
 
     new_asce = ldq_phys(origin + offs);
     PTE_DPRINTF("%s: 0x%" PRIx64 " + 0x%" PRIx64 " => 0x%016" PRIx64 "\n",
-                __FUNCTION__, origin, offs, new_asce);
+                __func__, origin, offs, new_asce);
 
     if (level != _ASCE_TYPE_SEGMENT) {
         /* yet another region */
@@ -232,7 +235,7 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, uint64_t a
 
     /* PTE */
     if (new_asce & _PAGE_INVALID) {
-        DPRINTF("%s: PTE=0x%" PRIx64 " invalid\n", __FUNCTION__, new_asce);
+        DPRINTF("%s: PTE=0x%" PRIx64 " invalid\n", __func__, new_asce);
         trigger_page_fault(env, vaddr, PGM_PAGE_TRANS, asc, rw);
         return -1;
     }
@@ -243,13 +246,14 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, uint64_t a
 
     *raddr = new_asce & _ASCE_ORIGIN;
 
-    PTE_DPRINTF("%s: PTE=0x%" PRIx64 "\n", __FUNCTION__, new_asce);
+    PTE_DPRINTF("%s: PTE=0x%" PRIx64 "\n", __func__, new_asce);
 
     return 0;
 }
 
-static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, uint64_t asc,
-                             target_ulong *raddr, int *flags, int rw)
+static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,
+                             uint64_t asc, target_ulong *raddr, int *flags,
+                             int rw)
 {
     uint64_t asce = 0;
     int level, new_level;
@@ -257,15 +261,15 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, uint64_t as
 
     switch (asc) {
     case PSW_ASC_PRIMARY:
-        PTE_DPRINTF("%s: asc=primary\n", __FUNCTION__);
+        PTE_DPRINTF("%s: asc=primary\n", __func__);
         asce = env->cregs[1];
         break;
     case PSW_ASC_SECONDARY:
-        PTE_DPRINTF("%s: asc=secondary\n", __FUNCTION__);
+        PTE_DPRINTF("%s: asc=secondary\n", __func__);
         asce = env->cregs[7];
         break;
     case PSW_ASC_HOME:
-        PTE_DPRINTF("%s: asc=home\n", __FUNCTION__);
+        PTE_DPRINTF("%s: asc=home\n", __func__);
         asce = env->cregs[13];
         break;
     }
@@ -276,8 +280,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, uint64_t as
     case _ASCE_TYPE_REGION2:
         if (vaddr & 0xffe0000000000000ULL) {
             DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
-                        " 0xffe0000000000000ULL\n", __FUNCTION__,
-                        vaddr);
+                    " 0xffe0000000000000ULL\n", __func__, vaddr);
             trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
             return -1;
         }
@@ -285,8 +288,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, uint64_t as
     case _ASCE_TYPE_REGION3:
         if (vaddr & 0xfffffc0000000000ULL) {
             DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
-                        " 0xfffffc0000000000ULL\n", __FUNCTION__,
-                        vaddr);
+                    " 0xfffffc0000000000ULL\n", __func__, vaddr);
             trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
             return -1;
         }
@@ -294,8 +296,7 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, uint64_t as
     case _ASCE_TYPE_SEGMENT:
         if (vaddr & 0xffffffff80000000ULL) {
             DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64
-                        " 0xffffffff80000000ULL\n", __FUNCTION__,
-                        vaddr);
+                    " 0xffffffff80000000ULL\n", __func__, vaddr);
             trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw);
             return -1;
         }
@@ -358,7 +359,7 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
         break;
     }
 
-out:
+ out:
     /* Convert real address -> absolute address */
     if (*raddr < 0x2000) {
         *raddr = *raddr + env->psa;
@@ -378,18 +379,18 @@ out:
     return r;
 }
 
-int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong _vaddr, int rw,
-                                int mmu_idx)
+int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong orig_vaddr,
+                               int rw, int mmu_idx)
 {
     uint64_t asc = env->psw.mask & PSW_MASK_ASC;
     target_ulong vaddr, raddr;
     int prot;
 
     DPRINTF("%s: address 0x%" PRIx64 " rw %d mmu_idx %d\n",
-            __FUNCTION__, _vaddr, rw, mmu_idx);
+            __func__, _vaddr, rw, mmu_idx);
 
-    _vaddr &= TARGET_PAGE_MASK;
-    vaddr = _vaddr;
+    orig_vaddr &= TARGET_PAGE_MASK;
+    vaddr = orig_vaddr;
 
     /* 31-Bit mode */
     if (!(env->psw.mask & PSW_MASK_64)) {
@@ -403,22 +404,23 @@ int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong _vaddr, int rw,
 
     /* check out of RAM access */
     if (raddr > (ram_size + virtio_size)) {
-        DPRINTF("%s: aaddr %" PRIx64 " > ram_size %" PRIx64 "\n", __FUNCTION__,
+        DPRINTF("%s: aaddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__,
                 (uint64_t)aaddr, (uint64_t)ram_size);
         trigger_pgm_exception(env, PGM_ADDRESSING, ILC_LATER);
         return 1;
     }
 
-    DPRINTF("%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n", __FUNCTION__,
+    DPRINTF("%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n", __func__,
             (uint64_t)vaddr, (uint64_t)raddr, prot);
 
-    tlb_set_page(env, _vaddr, raddr, prot,
+    tlb_set_page(env, orig_vaddr, raddr, prot,
                  mmu_idx, TARGET_PAGE_SIZE);
 
     return 0;
 }
 
-target_phys_addr_t cpu_get_phys_page_debug(CPUS390XState *env, target_ulong vaddr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUS390XState *env,
+                                           target_ulong vaddr)
 {
     target_ulong raddr;
     int prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
@@ -509,7 +511,7 @@ static void do_program_interrupt(CPUS390XState *env)
         break;
     }
 
-    qemu_log("%s: code=0x%x ilc=%d\n", __FUNCTION__, env->int_pgm_code, ilc);
+    qemu_log("%s: code=0x%x ilc=%d\n", __func__, env->int_pgm_code, ilc);
 
     lowcore = cpu_physical_memory_map(env->psa, &len, 1);
 
@@ -522,7 +524,7 @@ static void do_program_interrupt(CPUS390XState *env)
 
     cpu_physical_memory_unmap(lowcore, len, 1, len);
 
-    DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __FUNCTION__,
+    DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __func__,
             env->int_pgm_code, ilc, env->psw.mask,
             env->psw.addr);
 
@@ -565,15 +567,15 @@ static void do_ext_interrupt(CPUS390XState *env)
         env->pending_int &= ~INTERRUPT_EXT;
     }
 
-    DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __FUNCTION__,
+    DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__,
             env->psw.mask, env->psw.addr);
 
     load_psw(env, mask, addr);
 }
 
-void do_interrupt (CPUS390XState *env)
+void do_interrupt(CPUS390XState *env)
 {
-    qemu_log("%s: %d at pc=%" PRIx64 "\n", __FUNCTION__, env->exception_index,
+    qemu_log("%s: %d at pc=%" PRIx64 "\n", __func__, env->exception_index,
              env->psw.addr);
 
     s390_add_running_cpu(env);
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index abc35dd..195e93e 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -31,13 +31,13 @@
 #include <linux/kvm.h>
 #endif
 
-#if !defined (CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
 #include "sysemu.h"
 #endif
 
 /*****************************************************************************/
 /* Softmmu support */
-#if !defined (CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
 #include "softmmu_exec.h"
 
 #define MMUSUFFIX _mmu
@@ -95,7 +95,7 @@ void tlb_fill(CPUS390XState *env1, target_ulong addr, int is_write, int mmu_idx,
 /* raise an exception */
 void HELPER(exception)(uint32_t excp)
 {
-    HELPER_LOG("%s: exception %d\n", __FUNCTION__, excp);
+    HELPER_LOG("%s: exception %d\n", __func__, excp);
     env->exception_index = excp;
     cpu_loop_exit(env);
 }
@@ -164,7 +164,7 @@ uint32_t HELPER(nc)(uint32_t l, uint64_t dest, uint64_t src)
     uint32_t cc = 0;
 
     HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
-               __FUNCTION__, l, dest, src);
+               __func__, l, dest, src);
     for (i = 0; i <= l; i++) {
         x = ldub(dest + i) & ldub(src + i);
         if (x) {
@@ -183,7 +183,7 @@ uint32_t HELPER(xc)(uint32_t l, uint64_t dest, uint64_t src)
     uint32_t cc = 0;
 
     HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
-               __FUNCTION__, l, dest, src);
+               __func__, l, dest, src);
 
 #ifndef CONFIG_USER_ONLY
     /* xor with itself is the same as memset(0) */
@@ -217,7 +217,7 @@ uint32_t HELPER(oc)(uint32_t l, uint64_t dest, uint64_t src)
     uint32_t cc = 0;
 
     HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
-               __FUNCTION__, l, dest, src);
+               __func__, l, dest, src);
     for (i = 0; i <= l; i++) {
         x = ldub(dest + i) | ldub(src + i);
         if (x) {
@@ -236,7 +236,7 @@ void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src)
     uint32_t l_64 = (l + 1) / 8;
 
     HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
-               __FUNCTION__, l, dest, src);
+               __func__, l, dest, src);
 
 #ifndef CONFIG_USER_ONLY
     if ((l > 32) &&
@@ -278,10 +278,11 @@ void HELPER(mvc)(uint32_t l, uint64_t dest, uint64_t src)
 uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2)
 {
     int i;
-    unsigned char x,y;
+    unsigned char x, y;
     uint32_t cc;
+
     HELPER_LOG("%s l %d s1 %" PRIx64 " s2 %" PRIx64 "\n",
-               __FUNCTION__, l, s1, s2);
+               __func__, l, s1, s2);
     for (i = 0; i <= l; i++) {
         x = ldub(s1 + i);
         y = ldub(s2 + i);
@@ -295,7 +296,7 @@ uint32_t HELPER(clc)(uint32_t l, uint64_t s1, uint64_t s2)
         }
     }
     cc = 0;
-done:
+ done:
     HELPER_LOG("\n");
     return cc;
 }
@@ -303,9 +304,10 @@ done:
 /* compare logical under mask */
 uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr)
 {
-    uint8_t r,d;
+    uint8_t r, d;
     uint32_t cc;
-    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __FUNCTION__, r1,
+
+    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1,
                mask, addr);
     cc = 0;
     while (mask) {
@@ -313,7 +315,7 @@ uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr)
             d = ldub(addr);
             r = (r1 & 0xff000000UL) >> 24;
             HELPER_LOG("mask 0x%x %02x/%02x (0x%" PRIx64 ") ", mask, r, d,
-                        addr);
+                       addr);
             if (r < d) {
                 cc = 1;
                 break;
@@ -334,7 +336,8 @@ uint32_t HELPER(clm)(uint32_t r1, uint32_t mask, uint64_t addr)
 void HELPER(stcm)(uint32_t r1, uint32_t mask, uint64_t addr)
 {
     uint8_t r;
-    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __FUNCTION__, r1, mask,
+
+    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __func__, r1, mask,
                addr);
     while (mask) {
         if (mask & 8) {
@@ -355,6 +358,7 @@ void HELPER(mlg)(uint32_t r1, uint64_t v2)
 #if HOST_LONG_BITS == 64 && defined(__GNUC__)
     /* assuming 64-bit hosts have __uint128_t */
     __uint128_t res = (__uint128_t)env->regs[r1 + 1];
+
     res *= (__uint128_t)v2;
     env->regs[r1] = (uint64_t)(res >> 64);
     env->regs[r1 + 1] = (uint64_t)res;
@@ -370,18 +374,18 @@ void HELPER(dlg)(uint32_t r1, uint64_t v2)
 
     if (!env->regs[r1]) {
         /* 64 -> 64/64 case */
-        env->regs[r1] = env->regs[r1+1] % divisor;
-        env->regs[r1+1] = env->regs[r1+1] / divisor;
+        env->regs[r1] = env->regs[r1 + 1] % divisor;
+        env->regs[r1 + 1] = env->regs[r1 + 1] / divisor;
         return;
     } else {
-
 #if HOST_LONG_BITS == 64 && defined(__GNUC__)
         /* assuming 64-bit hosts have __uint128_t */
         __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) |
-                               (env->regs[r1+1]);
+            (env->regs[r1 + 1]);
         __uint128_t quotient = dividend / divisor;
-        env->regs[r1+1] = quotient;
         __uint128_t remainder = dividend % divisor;
+
+        env->regs[r1 + 1] = quotient;
         env->regs[r1] = remainder;
 #else
         /* 32-bit hosts would need special wrapper functionality - just abort if
@@ -431,7 +435,7 @@ uint32_t HELPER(srst)(uint32_t c, uint32_t r1, uint32_t r2)
     uint64_t str = get_address_31fix(r2);
     uint64_t end = get_address_31fix(r1);
 
-    HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __FUNCTION__,
+    HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __func__,
                c, env->regs[r1], env->regs[r2]);
 
     for (i = str; i != end; i++) {
@@ -452,11 +456,12 @@ uint32_t HELPER(clst)(uint32_t c, uint32_t r1, uint32_t r2)
     uint64_t s2 = get_address_31fix(r2);
     uint8_t v1, v2;
     uint32_t cc;
+
     c = c & 0xff;
 #ifdef CONFIG_USER_ONLY
     if (!c) {
         HELPER_LOG("%s: comparing '%s' and '%s'\n",
-                   __FUNCTION__, (char*)g2h(s1), (char*)g2h(s2));
+                   __func__, (char *)g2h(s1), (char *)g2h(s2));
     }
 #endif
     for (;;) {
@@ -501,10 +506,11 @@ void HELPER(mvst)(uint32_t c, uint32_t r1, uint32_t r2)
     uint64_t dest = get_address_31fix(r1);
     uint64_t src = get_address_31fix(r2);
     uint8_t v;
+
     c = c & 0xff;
 #ifdef CONFIG_USER_ONLY
     if (!c) {
-        HELPER_LOG("%s: copy '%s' to 0x%lx\n", __FUNCTION__, (char*)g2h(src),
+        HELPER_LOG("%s: copy '%s' to 0x%lx\n", __func__, (char *)g2h(src),
                    dest);
     }
 #endif
@@ -526,6 +532,7 @@ uint32_t HELPER(csg)(uint32_t r1, uint64_t a2, uint32_t r3)
     /* FIXME: locking? */
     uint32_t cc;
     uint64_t v2 = ldq(a2);
+
     if (env->regs[r1] == v2) {
         cc = 0;
         stq(a2, env->regs[r3]);
@@ -564,8 +571,9 @@ uint32_t HELPER(cs)(uint32_t r1, uint64_t a2, uint32_t r3)
 {
     /* FIXME: locking? */
     uint32_t cc;
-    HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __FUNCTION__, r1, a2, r3);
     uint32_t v2 = ldl(a2);
+
+    HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __func__, r1, a2, r3);
     if (((uint32_t)env->regs[r1]) == v2) {
         cc = 0;
         stl(a2, (uint32_t)env->regs[r3]);
@@ -612,14 +620,16 @@ static uint32_t helper_icm(uint32_t r1, uint64_t address, uint32_t mask)
    it does not change the program counter
    in other words: tricky...
    currently implemented by interpreting the cases it is most commonly used in
- */
+*/
 uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
 {
     uint16_t insn = lduw_code(addr);
-    HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __FUNCTION__, v1, addr,
-             insn);
+
+    HELPER_LOG("%s: v1 0x%lx addr 0x%lx insn 0x%x\n", __func__, v1, addr,
+               insn);
     if ((insn & 0xf0ff) == 0xd000) {
         uint32_t l, insn2, b1, b2, d1, d2;
+
         l = v1 & 0xff;
         insn2 = ldl_code(addr + 2);
         b1 = (insn2 >> 28) & 0xf;
@@ -645,13 +655,14 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
         }
     } else if ((insn & 0xff00) == 0x0a00) {
         /* supervisor call */
-        HELPER_LOG("%s: svc %ld via execute\n", __FUNCTION__, (insn|v1) & 0xff);
+        HELPER_LOG("%s: svc %ld via execute\n", __func__, (insn | v1) & 0xff);
         env->psw.addr = ret - 4;
-        env->int_svc_code = (insn|v1) & 0xff;
+        env->int_svc_code = (insn | v1) & 0xff;
         env->int_svc_ilc = 4;
         helper_exception(EXCP_SVC);
     } else if ((insn & 0xff00) == 0xbf00) {
         uint32_t insn2, r1, r3, b2, d2;
+
         insn2 = ldl_code(addr + 2);
         r1 = (insn2 >> 20) & 0xf;
         r3 = (insn2 >> 16) & 0xf;
@@ -659,7 +670,7 @@ uint32_t HELPER(ex)(uint32_t cc, uint64_t v1, uint64_t addr, uint64_t ret)
         d2 = insn2 & 0xfff;
         cc = helper_icm(r1, get_address(0, b2, d2), r3);
     } else {
-abort:
+    abort:
         cpu_abort(env, "EXECUTE on instruction prefix 0x%x not implemented\n",
                   insn);
     }
@@ -689,7 +700,7 @@ int32_t HELPER(nabs_i32)(int32_t val)
 /* absolute value 64-bit */
 uint64_t HELPER(abs_i64)(int64_t val)
 {
-    HELPER_LOG("%s: val 0x%" PRIx64 "\n", __FUNCTION__, val);
+    HELPER_LOG("%s: val 0x%" PRIx64 "\n", __func__, val);
 
     if (val < 0) {
         return -val;
@@ -774,9 +785,9 @@ void HELPER(ipm)(uint32_t cc, uint32_t r1)
     uint64_t r = env->regs[r1];
 
     r &= 0xffffffff00ffffffULL;
-    r |= (cc << 28) | ( (env->psw.mask >> 40) & 0xf );
+    r |= (cc << 28) | ((env->psw.mask >> 40) & 0xf);
     env->regs[r1] = r;
-    HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __FUNCTION__,
+    HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __func__,
                cc, env->psw.mask, r);
 }
 
@@ -908,7 +919,7 @@ uint32_t HELPER(clcle)(uint32_t r1, uint64_t a2, uint32_t r3)
     uint64_t srclen = env->regs[r3 + 1];
     uint64_t src = get_address_31fix(r3);
     uint8_t pad = a2 & 0xff;
-    uint8_t v1 = 0,v2 = 0;
+    uint8_t v1 = 0, v2 = 0;
     uint32_t cc = 0;
 
     if (!(destlen || srclen)) {
@@ -1036,7 +1047,7 @@ static uint32_t set_cc_nz_f128(float128 v)
 /* convert 32-bit int to 64-bit float */
 void HELPER(cdfbr)(uint32_t f1, int32_t v2)
 {
-    HELPER_LOG("%s: converting %d to f%d\n", __FUNCTION__, v2, f1);
+    HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1);
     env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status);
 }
 
@@ -1044,6 +1055,7 @@ void HELPER(cdfbr)(uint32_t f1, int32_t v2)
 void HELPER(cxfbr)(uint32_t f1, int32_t v2)
 {
     CPU_QuadU v1;
+
     v1.q = int32_to_float128(v2, &env->fpu_status);
     env->fregs[f1].ll = v1.ll.upper;
     env->fregs[f1 + 2].ll = v1.ll.lower;
@@ -1052,14 +1064,14 @@ void HELPER(cxfbr)(uint32_t f1, int32_t v2)
 /* convert 64-bit int to 32-bit float */
 void HELPER(cegbr)(uint32_t f1, int64_t v2)
 {
-    HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1);
+    HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
     env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status);
 }
 
 /* convert 64-bit int to 64-bit float */
 void HELPER(cdgbr)(uint32_t f1, int64_t v2)
 {
-    HELPER_LOG("%s: converting %ld to f%d\n", __FUNCTION__, v2, f1);
+    HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
     env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status);
 }
 
@@ -1067,8 +1079,9 @@ void HELPER(cdgbr)(uint32_t f1, int64_t v2)
 void HELPER(cxgbr)(uint32_t f1, int64_t v2)
 {
     CPU_QuadU x1;
+
     x1.q = int64_to_float128(v2, &env->fpu_status);
-    HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __FUNCTION__, v2,
+    HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__, v2,
                x1.ll.upper, x1.ll.lower);
     env->fregs[f1].ll = x1.ll.upper;
     env->fregs[f1 + 2].ll = x1.ll.lower;
@@ -1078,7 +1091,7 @@ void HELPER(cxgbr)(uint32_t f1, int64_t v2)
 void HELPER(cefbr)(uint32_t f1, int32_t v2)
 {
     env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
-    HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __FUNCTION__, v2,
+    HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2,
                env->fregs[f1].l.upper, f1);
 }
 
@@ -1088,7 +1101,7 @@ uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2)
     env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
                                          env->fregs[f2].l.upper,
                                          &env->fpu_status);
-    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__,
+    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
                env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
 
     return set_cc_nz_f32(env->fregs[f1].l.upper);
@@ -1099,7 +1112,7 @@ uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2)
 {
     env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d,
                                    &env->fpu_status);
-    HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __FUNCTION__,
+    HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__,
                env->fregs[f2].d, env->fregs[f1].d, f1);
 
     return set_cc_nz_f64(env->fregs[f1].d);
@@ -1111,7 +1124,7 @@ uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2)
     env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
                                          env->fregs[f2].l.upper,
                                          &env->fpu_status);
-    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __FUNCTION__,
+    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
                env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
 
     return set_cc_nz_f32(env->fregs[f1].l.upper);
@@ -1123,7 +1136,7 @@ uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2)
     env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
                                    &env->fpu_status);
     HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
-               __FUNCTION__, env->fregs[f2].d, env->fregs[f1].d, f1);
+               __func__, env->fregs[f2].d, env->fregs[f1].d, f1);
 
     return set_cc_nz_f64(env->fregs[f1].d);
 }
@@ -1140,12 +1153,13 @@ void HELPER(debr)(uint32_t f1, uint32_t f2)
 void HELPER(dxbr)(uint32_t f1, uint32_t f2)
 {
     CPU_QuadU v1;
+    CPU_QuadU v2;
+    CPU_QuadU res;
+
     v1.ll.upper = env->fregs[f1].ll;
     v1.ll.lower = env->fregs[f1 + 2].ll;
-    CPU_QuadU v2;
     v2.ll.upper = env->fregs[f2].ll;
     v2.ll.lower = env->fregs[f2 + 2].ll;
-    CPU_QuadU res;
     res.q = float128_div(v1.q, v2.q, &env->fpu_status);
     env->fregs[f1].ll = res.ll.upper;
     env->fregs[f1 + 2].ll = res.ll.lower;
@@ -1162,12 +1176,13 @@ void HELPER(mdbr)(uint32_t f1, uint32_t f2)
 void HELPER(mxbr)(uint32_t f1, uint32_t f2)
 {
     CPU_QuadU v1;
+    CPU_QuadU v2;
+    CPU_QuadU res;
+
     v1.ll.upper = env->fregs[f1].ll;
     v1.ll.lower = env->fregs[f1 + 2].ll;
-    CPU_QuadU v2;
     v2.ll.upper = env->fregs[f2].ll;
     v2.ll.lower = env->fregs[f2 + 2].ll;
-    CPU_QuadU res;
     res.q = float128_mul(v1.q, v2.q, &env->fpu_status);
     env->fregs[f1].ll = res.ll.upper;
     env->fregs[f1 + 2].ll = res.ll.lower;
@@ -1184,16 +1199,18 @@ void HELPER(ldebr)(uint32_t r1, uint32_t r2)
 void HELPER(ldxbr)(uint32_t f1, uint32_t f2)
 {
     CPU_QuadU x2;
+
     x2.ll.upper = env->fregs[f2].ll;
     x2.ll.lower = env->fregs[f2 + 2].ll;
     env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status);
-    HELPER_LOG("%s: to 0x%ld\n", __FUNCTION__, env->fregs[f1].d);
+    HELPER_LOG("%s: to 0x%ld\n", __func__, env->fregs[f1].d);
 }
 
 /* convert 64-bit float to 128-bit float */
 void HELPER(lxdbr)(uint32_t f1, uint32_t f2)
 {
     CPU_QuadU res;
+
     res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status);
     env->fregs[f1].ll = res.ll.upper;
     env->fregs[f1 + 2].ll = res.ll.lower;
@@ -1203,6 +1220,7 @@ void HELPER(lxdbr)(uint32_t f1, uint32_t f2)
 void HELPER(ledbr)(uint32_t f1, uint32_t f2)
 {
     float64 d2 = env->fregs[f2].d;
+
     env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status);
 }
 
@@ -1210,10 +1228,11 @@ void HELPER(ledbr)(uint32_t f1, uint32_t f2)
 void HELPER(lexbr)(uint32_t f1, uint32_t f2)
 {
     CPU_QuadU x2;
+
     x2.ll.upper = env->fregs[f2].ll;
     x2.ll.lower = env->fregs[f2 + 2].ll;
     env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status);
-    HELPER_LOG("%s: to 0x%d\n", __FUNCTION__, env->fregs[f1].l.upper);
+    HELPER_LOG("%s: to 0x%d\n", __func__, env->fregs[f1].l.upper);
 }
 
 /* absolute value of 32-bit float */
@@ -1221,6 +1240,7 @@ uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2)
 {
     float32 v1;
     float32 v2 = env->fregs[f2].d;
+
     v1 = float32_abs(v2);
     env->fregs[f1].d = v1;
     return set_cc_nz_f32(v1);
@@ -1231,6 +1251,7 @@ uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2)
 {
     float64 v1;
     float64 v2 = env->fregs[f2].d;
+
     v1 = float64_abs(v2);
     env->fregs[f1].d = v1;
     return set_cc_nz_f64(v1);
@@ -1241,6 +1262,7 @@ uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2)
 {
     CPU_QuadU v1;
     CPU_QuadU v2;
+
     v2.ll.upper = env->fregs[f2].ll;
     v2.ll.lower = env->fregs[f2 + 2].ll;
     v1.q = float128_abs(v2.q);
@@ -1267,6 +1289,7 @@ uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2)
 uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2)
 {
     CPU_QuadU x;
+
     x.ll.upper = env->fregs[f2].ll;
     x.ll.lower = env->fregs[f2 + 2].ll;
     env->fregs[f1].ll = x.ll.upper;
@@ -1294,6 +1317,7 @@ uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2)
 uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2)
 {
     CPU_QuadU x1, x2;
+
     x2.ll.upper = env->fregs[f2].ll;
     x2.ll.lower = env->fregs[f2 + 2].ll;
     x1.q = float128_chs(x2.q);
@@ -1307,8 +1331,9 @@ void HELPER(aeb)(uint32_t f1, uint32_t val)
 {
     float32 v1 = env->fregs[f1].l.upper;
     CPU_FloatU v2;
+
     v2.l = val;
-    HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __FUNCTION__,
+    HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__,
                v1, f1, v2.f);
     env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status);
 }
@@ -1318,8 +1343,9 @@ void HELPER(deb)(uint32_t f1, uint32_t val)
 {
     float32 v1 = env->fregs[f1].l.upper;
     CPU_FloatU v2;
+
     v2.l = val;
-    HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __FUNCTION__,
+    HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__,
                v1, f1, v2.f);
     env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status);
 }
@@ -1329,8 +1355,9 @@ void HELPER(meeb)(uint32_t f1, uint32_t val)
 {
     float32 v1 = env->fregs[f1].l.upper;
     CPU_FloatU v2;
+
     v2.l = val;
-    HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __FUNCTION__,
+    HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__,
                v1, f1, v2.f);
     env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
 }
@@ -1340,7 +1367,8 @@ uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2)
 {
     float32 v1 = env->fregs[f1].l.upper;
     float32 v2 = env->fregs[f2].l.upper;
-    HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __FUNCTION__,
+
+    HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__,
                v1, f1, v2);
     return set_cc_f32(v1, v2);
 }
@@ -1350,7 +1378,8 @@ uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2)
 {
     float64 v1 = env->fregs[f1].d;
     float64 v2 = env->fregs[f2].d;
-    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __FUNCTION__,
+
+    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__,
                v1, f1, v2);
     return set_cc_f64(v1, v2);
 }
@@ -1359,14 +1388,15 @@ uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2)
 uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2)
 {
     CPU_QuadU v1;
+    CPU_QuadU v2;
+
     v1.ll.upper = env->fregs[f1].ll;
     v1.ll.lower = env->fregs[f1 + 2].ll;
-    CPU_QuadU v2;
     v2.ll.upper = env->fregs[f2].ll;
     v2.ll.lower = env->fregs[f2 + 2].ll;
 
     return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q,
-                            &env->fpu_status));
+                                                   &env->fpu_status));
 }
 
 /* 64-bit FP compare RM */
@@ -1374,8 +1404,9 @@ uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2)
 {
     float64 v1 = env->fregs[f1].d;
     CPU_DoubleU v2;
+
     v2.ll = ldq(a2);
-    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __FUNCTION__, v1,
+    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1,
                f1, v2.d);
     return set_cc_f64(v1, v2.d);
 }
@@ -1385,8 +1416,9 @@ uint32_t HELPER(adb)(uint32_t f1, uint64_t a2)
 {
     float64 v1 = env->fregs[f1].d;
     CPU_DoubleU v2;
+
     v2.ll = ldq(a2);
-    HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __FUNCTION__,
+    HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__,
                v1, f1, v2.d);
     env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
     return set_cc_nz_f64(v1);
@@ -1397,6 +1429,7 @@ void HELPER(seb)(uint32_t f1, uint32_t val)
 {
     float32 v1 = env->fregs[f1].l.upper;
     CPU_FloatU v2;
+
     v2.l = val;
     env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status);
 }
@@ -1406,6 +1439,7 @@ uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2)
 {
     float64 v1 = env->fregs[f1].d;
     CPU_DoubleU v2;
+
     v2.ll = ldq(a2);
     env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status);
     return set_cc_nz_f64(v1);
@@ -1416,8 +1450,9 @@ void HELPER(mdb)(uint32_t f1, uint64_t a2)
 {
     float64 v1 = env->fregs[f1].d;
     CPU_DoubleU v2;
+
     v2.ll = ldq(a2);
-    HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __FUNCTION__,
+    HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__,
                v1, f1, v2.d);
     env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
 }
@@ -1427,8 +1462,9 @@ void HELPER(ddb)(uint32_t f1, uint64_t a2)
 {
     float64 v1 = env->fregs[f1].d;
     CPU_DoubleU v2;
+
     v2.ll = ldq(a2);
-    HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __FUNCTION__,
+    HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__,
                v1, f1, v2.d);
     env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
 }
@@ -1464,6 +1500,7 @@ static void set_round_mode(int m3)
 uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3)
 {
     float32 v2 = env->fregs[f2].l.upper;
+
     set_round_mode(m3);
     env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
     return set_cc_nz_f32(v2);
@@ -1473,6 +1510,7 @@ uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3)
 uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
 {
     float64 v2 = env->fregs[f2].d;
+
     set_round_mode(m3);
     env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
     return set_cc_nz_f64(v2);
@@ -1482,6 +1520,7 @@ uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
 uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
 {
     CPU_QuadU v2;
+
     v2.ll.upper = env->fregs[f2].ll;
     v2.ll.lower = env->fregs[f2 + 2].ll;
     set_round_mode(m3);
@@ -1501,9 +1540,10 @@ uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
 uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3)
 {
     float32 v2 = env->fregs[f2].l.upper;
+
     set_round_mode(m3);
     env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-                     float32_to_int32(v2, &env->fpu_status);
+        float32_to_int32(v2, &env->fpu_status);
     return set_cc_nz_f32(v2);
 }
 
@@ -1511,9 +1551,10 @@ uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3)
 uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
 {
     float64 v2 = env->fregs[f2].d;
+
     set_round_mode(m3);
     env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-                     float64_to_int32(v2, &env->fpu_status);
+        float64_to_int32(v2, &env->fpu_status);
     return set_cc_nz_f64(v2);
 }
 
@@ -1521,10 +1562,11 @@ uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
 uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
 {
     CPU_QuadU v2;
+
     v2.ll.upper = env->fregs[f2].ll;
     v2.ll.lower = env->fregs[f2 + 2].ll;
     env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-                     float128_to_int32(v2.q, &env->fpu_status);
+        float128_to_int32(v2.q, &env->fpu_status);
     return set_cc_nz_f128(v2.q);
 }
 
@@ -1544,6 +1586,7 @@ void HELPER(lzdr)(uint32_t f1)
 void HELPER(lzxr)(uint32_t f1)
 {
     CPU_QuadU x;
+
     x.q = float64_to_float128(float64_zero, &env->fpu_status);
     env->fregs[f1].ll = x.ll.upper;
     env->fregs[f1 + 1].ll = x.ll.lower;
@@ -1553,12 +1596,13 @@ void HELPER(lzxr)(uint32_t f1)
 uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2)
 {
     CPU_QuadU v1;
+    CPU_QuadU v2;
+    CPU_QuadU res;
+
     v1.ll.upper = env->fregs[f1].ll;
     v1.ll.lower = env->fregs[f1 + 2].ll;
-    CPU_QuadU v2;
     v2.ll.upper = env->fregs[f2].ll;
     v2.ll.lower = env->fregs[f2 + 2].ll;
-    CPU_QuadU res;
     res.q = float128_sub(v1.q, v2.q, &env->fpu_status);
     env->fregs[f1].ll = res.ll.upper;
     env->fregs[f1 + 2].ll = res.ll.lower;
@@ -1569,12 +1613,13 @@ uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2)
 uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2)
 {
     CPU_QuadU v1;
+    CPU_QuadU v2;
+    CPU_QuadU res;
+
     v1.ll.upper = env->fregs[f1].ll;
     v1.ll.lower = env->fregs[f1 + 2].ll;
-    CPU_QuadU v2;
     v2.ll.upper = env->fregs[f2].ll;
     v2.ll.lower = env->fregs[f2 + 2].ll;
-    CPU_QuadU res;
     res.q = float128_add(v1.q, v2.q, &env->fpu_status);
     env->fregs[f1].ll = res.ll.upper;
     env->fregs[f1 + 2].ll = res.ll.lower;
@@ -1599,8 +1644,9 @@ void HELPER(ddbr)(uint32_t f1, uint32_t f2)
 /* 64-bit FP multiply and add RM */
 void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3)
 {
-    HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __FUNCTION__, f1, a2, f3);
     CPU_DoubleU v2;
+
+    HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3);
     v2.ll = ldq(a2);
     env->fregs[f1].d = float64_add(env->fregs[f1].d,
                                    float64_mul(v2.d, env->fregs[f3].d,
@@ -1611,7 +1657,7 @@ void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3)
 /* 64-bit FP multiply and add RR */
 void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2)
 {
-    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3);
+    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
     env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d,
                                                env->fregs[f3].d,
                                                &env->fpu_status),
@@ -1621,7 +1667,7 @@ void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2)
 /* 64-bit FP multiply and subtract RR */
 void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2)
 {
-    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __FUNCTION__, f1, f2, f3);
+    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
     env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d,
                                                env->fregs[f3].d,
                                                &env->fpu_status),
@@ -1642,6 +1688,7 @@ void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2)
 void HELPER(ldeb)(uint32_t f1, uint64_t a2)
 {
     uint32_t v2;
+
     v2 = ldl(a2);
     env->fregs[f1].d = float32_to_float64(v2,
                                           &env->fpu_status);
@@ -1651,8 +1698,9 @@ void HELPER(ldeb)(uint32_t f1, uint64_t a2)
 void HELPER(lxdb)(uint32_t f1, uint64_t a2)
 {
     CPU_DoubleU v2;
-    v2.ll = ldq(a2);
     CPU_QuadU v1;
+
+    v2.ll = ldq(a2);
     v1.q = float64_to_float128(v2.d, &env->fpu_status);
     env->fregs[f1].ll = v1.ll.upper;
     env->fregs[f1 + 2].ll = v1.ll.lower;
@@ -1665,7 +1713,7 @@ uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2)
     int neg = float32_is_neg(v1);
     uint32_t cc = 0;
 
-    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, (long)v1, m2, neg);
+    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, (long)v1, m2, neg);
     if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
         (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
         (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
@@ -1687,7 +1735,7 @@ uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2)
     int neg = float64_is_neg(v1);
     uint32_t cc = 0;
 
-    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, v1, m2, neg);
+    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg);
     if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
         (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
         (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
@@ -1706,10 +1754,12 @@ uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2)
 {
     CPU_QuadU v1;
     uint32_t cc = 0;
+    int neg;
+
     v1.ll.upper = env->fregs[f1].ll;
     v1.ll.lower = env->fregs[f1 + 2].ll;
 
-    int neg = float128_is_neg(v1.q);
+    neg = float128_is_neg(v1.q);
     if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) ||
         (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) ||
         (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) ||
@@ -1787,7 +1837,7 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2)
 
     /* store result */
     env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-                    ((uint32_t)cksm + (cksm >> 32));
+        ((uint32_t)cksm + (cksm >> 32));
 }
 
 static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src,
@@ -1848,10 +1898,12 @@ static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
     }
 }
 
-static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t mask)
+static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val,
+                                     uint32_t mask)
 {
-    HELPER_LOG("%s: val 0x%x mask 0x%x\n", __FUNCTION__, val, mask);
     uint16_t r = val & mask;
+
+    HELPER_LOG("%s: val 0x%x mask 0x%x\n", __func__, val, mask);
     if (r == 0 || mask == 0) {
         return 0;
     } else if (r == mask) {
@@ -1862,10 +1914,12 @@ static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t
 }
 
 /* set condition code for test under mask */
-static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, uint32_t mask)
+static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val,
+                                     uint32_t mask)
 {
     uint16_t r = val & mask;
-    HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __FUNCTION__, val, mask, r);
+
+    HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __func__, val, mask, r);
     if (r == 0 || mask == 0) {
         return 0;
     } else if (r == mask) {
@@ -1888,8 +1942,8 @@ static inline uint32_t cc_calc_nz(CPUS390XState *env, uint64_t dst)
     return !!dst;
 }
 
-static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1, int64_t a2,
-                                      int64_t ar)
+static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1,
+                                      int64_t a2, int64_t ar)
 {
     if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
         return 3; /* overflow */
@@ -1904,8 +1958,8 @@ static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1, int64_t a2
     }
 }
 
-static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1, uint64_t a2,
-                                       uint64_t ar)
+static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1,
+                                       uint64_t a2, uint64_t ar)
 {
     if (ar == 0) {
         if (a1) {
@@ -1915,15 +1969,15 @@ static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1, uint64_t
         }
     } else {
         if (ar < a1 || ar < a2) {
-          return 3;
+            return 3;
         } else {
-          return 1;
+            return 1;
         }
     }
 }
 
-static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1, int64_t a2,
-                                      int64_t ar)
+static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1,
+                                      int64_t a2, int64_t ar)
 {
     if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
         return 3; /* overflow */
@@ -1938,8 +1992,8 @@ static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1, int64_t a2
     }
 }
 
-static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1, uint64_t a2,
-                                       uint64_t ar)
+static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1,
+                                       uint64_t a2, uint64_t ar)
 {
     if (ar == 0) {
         return 2;
@@ -1982,8 +2036,8 @@ static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst)
 }
 
 
-static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1, int32_t a2,
-                                      int32_t ar)
+static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1,
+                                      int32_t a2, int32_t ar)
 {
     if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
         return 3; /* overflow */
@@ -1998,26 +2052,26 @@ static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1, int32_t a2
     }
 }
 
-static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1, uint32_t a2,
-                                       uint32_t ar)
+static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1,
+                                       uint32_t a2, uint32_t ar)
 {
     if (ar == 0) {
         if (a1) {
-          return 2;
+            return 2;
         } else {
-          return 0;
+            return 0;
         }
     } else {
         if (ar < a1 || ar < a2) {
-          return 3;
+            return 3;
         } else {
-          return 1;
+            return 1;
         }
     }
 }
 
-static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1, int32_t a2,
-                                      int32_t ar)
+static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1,
+                                      int32_t a2, int32_t ar)
 {
     if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
         return 3; /* overflow */
@@ -2032,8 +2086,8 @@ static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1, int32_t a2
     }
 }
 
-static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1, uint32_t a2,
-                                       uint32_t ar)
+static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1,
+                                       uint32_t a2, uint32_t ar)
 {
     if (ar == 0) {
         return 2;
@@ -2076,11 +2130,12 @@ static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst)
 }
 
 /* calculate condition code for insert character under mask insn */
-static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask, uint32_t val)
+static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask,
+                                      uint32_t val)
 {
-    HELPER_LOG("%s: mask 0x%x val %d\n", __FUNCTION__, mask, val);
     uint32_t cc;
 
+    HELPER_LOG("%s: mask 0x%x val %d\n", __func__, mask, val);
     if (mask == 0xf) {
         if (!val) {
             return 0;
@@ -2107,7 +2162,8 @@ static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask, uint32_
     return cc;
 }
 
-static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src, uint64_t shift)
+static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src,
+                                    uint64_t shift)
 {
     uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
     uint64_t match, r;
@@ -2136,8 +2192,8 @@ static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src, uint64_t s
 }
 
 
-static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src,
-                                  uint64_t dst, uint64_t vr)
+static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
+                                  uint64_t src, uint64_t dst, uint64_t vr)
 {
     uint32_t r = 0;
 
@@ -2244,7 +2300,7 @@ static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t s
         cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op));
     }
 
-    HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __FUNCTION__,
+    HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __func__,
                cc_name(cc_op), src, dst, vr, r);
     return r;
 }
@@ -2334,6 +2390,7 @@ void HELPER(tr)(uint32_t len, uint64_t array, uint64_t trans)
     for (i = 0; i <= len; i++) {
         uint8_t byte = ldub(array + i);
         uint8_t new_byte = ldub(trans + byte);
+
         stb(array + i, new_byte);
     }
 }
@@ -2363,7 +2420,7 @@ static void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
 }
 
 /*
- * ret < 0 indicates program check, ret = 0,1,2,3 -> cc
+ * ret < 0 indicates program check, ret = 0, 1, 2, 3 -> cc
  */
 int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
 {
@@ -2382,24 +2439,24 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
         return -PGM_SPECIFICATION;
     }
 
-    switch(code) {
-        case SCLP_CMDW_READ_SCP_INFO:
-        case SCLP_CMDW_READ_SCP_INFO_FORCED:
-            while ((ram_size >> (20 + shift)) > 65535) {
-                shift++;
-            }
-            stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift));
-            stb_phys(sccb + SCP_INCREMENT, 1 << shift);
-            stw_phys(sccb + SCP_RESPONSE_CODE, 0x10);
+    switch (code) {
+    case SCLP_CMDW_READ_SCP_INFO:
+    case SCLP_CMDW_READ_SCP_INFO_FORCED:
+        while ((ram_size >> (20 + shift)) > 65535) {
+            shift++;
+        }
+        stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift));
+        stb_phys(sccb + SCP_INCREMENT, 1 << shift);
+        stw_phys(sccb + SCP_RESPONSE_CODE, 0x10);
 
-            s390_sclp_extint(sccb & ~3);
-            break;
-        default:
+        s390_sclp_extint(sccb & ~3);
+        break;
+    default:
 #ifdef DEBUG_HELPER
-            printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
+        printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
 #endif
-            r = 3;
-            break;
+        r = 3;
+        break;
     }
 
     return r;
@@ -2479,7 +2536,7 @@ static inline uint64_t clock_value(CPUS390XState *env)
     uint64_t time;
 
     time = env->tod_offset +
-           time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
+        time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
 
     return time;
 }
@@ -2503,7 +2560,6 @@ uint32_t HELPER(stcke)(uint64_t a1)
     /* XXX programmable fields */
     stw(a1 + 17, 0);
 
-
     return 0;
 }
 
@@ -2584,7 +2640,7 @@ uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
             ebcdic_put(sysib.model, "QEMU            ", 16);
             ebcdic_put(sysib.sequence, "QEMU            ", 16);
             ebcdic_put(sysib.plant, "QEMU", 4);
-            cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
+            cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
         } else if ((sel1 == 2) && (sel2 == 1)) {
             /* Basic Machine CPU */
             struct sysib_121 sysib;
@@ -2594,7 +2650,7 @@ uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
             ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
             ebcdic_put(sysib.plant, "QEMU", 4);
             stw_p(&sysib.cpu_addr, env->cpu_num);
-            cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
+            cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
         } else if ((sel1 == 2) && (sel2 == 2)) {
             /* Basic Machine CPUs */
             struct sysib_122 sysib;
@@ -2606,68 +2662,68 @@ uint32_t HELPER(stsi)(uint64_t a0, uint32_t r0, uint32_t r1)
             stw_p(&sysib.active_cpus, 1);
             stw_p(&sysib.standby_cpus, 0);
             stw_p(&sysib.reserved_cpus, 0);
-            cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
+            cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
         } else {
             cc = 3;
         }
         break;
     case STSI_LEVEL_2:
-    {
-        if ((sel1 == 2) && (sel2 == 1)) {
-            /* LPAR CPU */
-            struct sysib_221 sysib;
-
-            memset(&sysib, 0, sizeof(sysib));
-            /* XXX make different for different CPUs? */
-            ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
-            ebcdic_put(sysib.plant, "QEMU", 4);
-            stw_p(&sysib.cpu_addr, env->cpu_num);
-            stw_p(&sysib.cpu_id, 0);
-            cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
-        } else if ((sel1 == 2) && (sel2 == 2)) {
-            /* LPAR CPUs */
-            struct sysib_222 sysib;
-
-            memset(&sysib, 0, sizeof(sysib));
-            stw_p(&sysib.lpar_num, 0);
-            sysib.lcpuc = 0;
-            /* XXX change when SMP comes */
-            stw_p(&sysib.total_cpus, 1);
-            stw_p(&sysib.conf_cpus, 1);
-            stw_p(&sysib.standby_cpus, 0);
-            stw_p(&sysib.reserved_cpus, 0);
-            ebcdic_put(sysib.name, "QEMU    ", 8);
-            stl_p(&sysib.caf, 1000);
-            stw_p(&sysib.dedicated_cpus, 0);
-            stw_p(&sysib.shared_cpus, 0);
-            cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
-        } else {
-            cc = 3;
+        {
+            if ((sel1 == 2) && (sel2 == 1)) {
+                /* LPAR CPU */
+                struct sysib_221 sysib;
+
+                memset(&sysib, 0, sizeof(sysib));
+                /* XXX make different for different CPUs? */
+                ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
+                ebcdic_put(sysib.plant, "QEMU", 4);
+                stw_p(&sysib.cpu_addr, env->cpu_num);
+                stw_p(&sysib.cpu_id, 0);
+                cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+            } else if ((sel1 == 2) && (sel2 == 2)) {
+                /* LPAR CPUs */
+                struct sysib_222 sysib;
+
+                memset(&sysib, 0, sizeof(sysib));
+                stw_p(&sysib.lpar_num, 0);
+                sysib.lcpuc = 0;
+                /* XXX change when SMP comes */
+                stw_p(&sysib.total_cpus, 1);
+                stw_p(&sysib.conf_cpus, 1);
+                stw_p(&sysib.standby_cpus, 0);
+                stw_p(&sysib.reserved_cpus, 0);
+                ebcdic_put(sysib.name, "QEMU    ", 8);
+                stl_p(&sysib.caf, 1000);
+                stw_p(&sysib.dedicated_cpus, 0);
+                stw_p(&sysib.shared_cpus, 0);
+                cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+            } else {
+                cc = 3;
+            }
+            break;
         }
-        break;
-    }
     case STSI_LEVEL_3:
-    {
-        if ((sel1 == 2) && (sel2 == 2)) {
-            /* VM CPUs */
-            struct sysib_322 sysib;
-
-            memset(&sysib, 0, sizeof(sysib));
-            sysib.count = 1;
-            /* XXX change when SMP comes */
-            stw_p(&sysib.vm[0].total_cpus, 1);
-            stw_p(&sysib.vm[0].conf_cpus, 1);
-            stw_p(&sysib.vm[0].standby_cpus, 0);
-            stw_p(&sysib.vm[0].reserved_cpus, 0);
-            ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
-            stl_p(&sysib.vm[0].caf, 1000);
-            ebcdic_put(sysib.vm[0].cpi, "KVM/Linux       ", 16);
-            cpu_physical_memory_rw(a0, (uint8_t*)&sysib, sizeof(sysib), 1);
-        } else {
-            cc = 3;
+        {
+            if ((sel1 == 2) && (sel2 == 2)) {
+                /* VM CPUs */
+                struct sysib_322 sysib;
+
+                memset(&sysib, 0, sizeof(sysib));
+                sysib.count = 1;
+                /* XXX change when SMP comes */
+                stw_p(&sysib.vm[0].total_cpus, 1);
+                stw_p(&sysib.vm[0].conf_cpus, 1);
+                stw_p(&sysib.vm[0].standby_cpus, 0);
+                stw_p(&sysib.vm[0].reserved_cpus, 0);
+                ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
+                stl_p(&sysib.vm[0].caf, 1000);
+                ebcdic_put(sysib.vm[0].cpi, "KVM/Linux       ", 16);
+                cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
+            } else {
+                cc = 3;
+            }
+            break;
         }
-        break;
-    }
     case STSI_LEVEL_CURRENT:
         env->regs[0] = STSI_LEVEL_3;
         break;
@@ -2781,6 +2837,7 @@ uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
 {
     uint8_t re;
     uint8_t key;
+
     if (r2 > ram_size) {
         return 0;
     }
@@ -2865,7 +2922,7 @@ static uint32_t mvc_asc(int64_t l, uint64_t a1, uint64_t mode1, uint64_t a2,
 uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2)
 {
     HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
-               __FUNCTION__, l, a1, a2);
+               __func__, l, a1, a2);
 
     return mvc_asc(l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY);
 }
@@ -2873,7 +2930,7 @@ uint32_t HELPER(mvcs)(uint64_t l, uint64_t a1, uint64_t a2)
 uint32_t HELPER(mvcp)(uint64_t l, uint64_t a1, uint64_t a2)
 {
     HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
-               __FUNCTION__, l, a1, a2);
+               __func__, l, a1, a2);
 
     return mvc_asc(l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY);
 }
@@ -2883,9 +2940,9 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
     int cc = 0;
 
     HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
-               __FUNCTION__, order_code, r1, cpu_addr);
+               __func__, order_code, r1, cpu_addr);
 
-    /* Remember: Use "R1 or R1+1, whichever is the odd-numbered register"
+    /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register"
        as parameter (input). Status (output) is always R1. */
 
     switch (order_code) {
@@ -2901,7 +2958,7 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
         env->regs[r1] &= 0xffffffff00000000ULL;
         cc = 1;
         break;
-#if !defined (CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
     case SIGP_RESTART:
         qemu_system_reset_request();
         cpu_loop_exit(env);
@@ -2922,7 +2979,7 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
 
 void HELPER(sacf)(uint64_t a1)
 {
-    HELPER_LOG("%s: %16" PRIx64 "\n", __FUNCTION__, a1);
+    HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1);
 
     switch (a1 & 0xf00) {
     case 0x000:
@@ -2953,13 +3010,13 @@ void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
     /* XXX broadcast to other CPUs */
 
     /* XXX Linux is nice enough to give us the exact pte address.
-           According to spec we'd have to find it out ourselves */
+       According to spec we'd have to find it out ourselves */
     /* XXX Linux is fine with overwriting the pte, the spec requires
-           us to only set the invalid bit */
+       us to only set the invalid bit */
     stq_phys(pte_addr, pte | _PAGE_INVALID);
 
     /* XXX we exploit the fact that Linux passes the exact virtual
-           address here - it's not obliged to! */
+       address here - it's not obliged to! */
     tlb_flush_page(env, page);
 
     /* XXX 31-bit hack */
@@ -3008,7 +3065,8 @@ uint32_t HELPER(lra)(uint64_t addr, uint32_t r1)
     env->exception_index = old_exc;
 
     if (!(env->psw.mask & PSW_MASK_64)) {
-        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | (ret & 0xffffffffULL);
+        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
+            (ret & 0xffffffffULL);
     } else {
         env->regs[r1] = ret;
     }
commit b131c74a0e485b084ddaffc8214c8a19af492be7
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Aug 20 10:55:56 2012 +0200

    kvm: Clean up irqfd API
    
    No need to expose the fd-based interface, everyone will already be fine
    with the more handy EventNotifier variant. Rename the latter to clarify
    that we are still talking about irqfds here.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Acked-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index b3f0710..400f3c2 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -517,7 +517,7 @@ static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
     }
     irqfd->users++;
 
-    ret = kvm_irqchip_add_irq_notifier(kvm_state, n, irqfd->virq);
+    ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, irqfd->virq);
     if (ret < 0) {
         if (--irqfd->users == 0) {
             kvm_irqchip_release_virq(kvm_state, irqfd->virq);
@@ -538,7 +538,7 @@ static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy,
     VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
     int ret;
 
-    ret = kvm_irqchip_remove_irq_notifier(kvm_state, n, irqfd->virq);
+    ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, n, irqfd->virq);
     assert(ret == 0);
 
     if (--irqfd->users == 0) {
diff --git a/kvm-all.c b/kvm-all.c
index e0244b6..f96be21 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1166,24 +1166,14 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
 }
 #endif /* !KVM_CAP_IRQ_ROUTING */
 
-int kvm_irqchip_add_irqfd(KVMState *s, int fd, int virq)
+int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
 {
-    return kvm_irqchip_assign_irqfd(s, fd, virq, true);
+    return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), virq, true);
 }
 
-int kvm_irqchip_add_irq_notifier(KVMState *s, EventNotifier *n, int virq)
+int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
 {
-    return kvm_irqchip_add_irqfd(s, event_notifier_get_fd(n), virq);
-}
-
-int kvm_irqchip_remove_irqfd(KVMState *s, int fd, int virq)
-{
-    return kvm_irqchip_assign_irqfd(s, fd, virq, false);
-}
-
-int kvm_irqchip_remove_irq_notifier(KVMState *s, EventNotifier *n, int virq)
-{
-    return kvm_irqchip_remove_irqfd(s, event_notifier_get_fd(n), virq);
+    return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), virq, false);
 }
 
 static int kvm_irqchip_create(KVMState *s)
diff --git a/kvm-stub.c b/kvm-stub.c
index 94c9ea1..3c52eb5 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -141,22 +141,12 @@ void kvm_irqchip_release_virq(KVMState *s, int virq)
 {
 }
 
-int kvm_irqchip_add_irqfd(KVMState *s, int fd, int virq)
+int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
 {
     return -ENOSYS;
 }
 
-int kvm_irqchip_add_irq_notifier(KVMState *s, EventNotifier *n, int virq)
-{
-    return -ENOSYS;
-}
-
-int kvm_irqchip_remove_irqfd(KVMState *s, int fd, int virq)
-{
-    return -ENOSYS;
-}
-
-int kvm_irqchip_remove_irq_notifier(KVMState *s, EventNotifier *n, int virq)
+int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
 {
     return -ENOSYS;
 }
diff --git a/kvm.h b/kvm.h
index 5b8f588..37d1f81 100644
--- a/kvm.h
+++ b/kvm.h
@@ -272,8 +272,6 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign);
 int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
 void kvm_irqchip_release_virq(KVMState *s, int virq);
 
-int kvm_irqchip_add_irqfd(KVMState *s, int fd, int virq);
-int kvm_irqchip_remove_irqfd(KVMState *s, int fd, int virq);
-int kvm_irqchip_add_irq_notifier(KVMState *s, EventNotifier *n, int virq);
-int kvm_irqchip_remove_irq_notifier(KVMState *s, EventNotifier *n, int virq);
+int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
+int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
 #endif
commit 62fe83318d2fc5b31f473d66326910d94c1c4907
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Fri Aug 10 15:11:45 2012 +0200

    qemu: Use valgrind annotations to mark kvm guest memory as defined
    
    valgrind with kvm produces a big amount of false positives regarding
    "Conditional jump or move depends on uninitialised value(s)". This
    happens because the guest memory is allocated with qemu_vmalloc which
    boils down posix_memalign etc. This function is (correctly) considered
    by valgrind as returning undefined memory.
    
    Since valgrind is based on jitting code, it will not be able to see
    changes made by the guest to guest memory if this is done by KVM_RUN,
    thus keeping most of the guest memory undefined.
    
    Now lots of places in qemu will then use guest memory to change behaviour.
    To avoid the flood of these messages, lets declare the whole guest
    memory as defined. This will reduce the noise and allows us to see real
    problems.
    
    In the future we might want to make this conditional, since there
    is actually something that we can use those false positives for:
    These messages will point to code that depends on guest memory, so
    we can use these backtraces to actually make an audit that is focussed
    only at those code places. For normal development we dont want to
    see those messages, though.
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/configure b/configure
index d97fd81..056b356 100755
--- a/configure
+++ b/configure
@@ -2963,11 +2963,12 @@ if compile_prog "-Werror" "" ; then
 fi
 
 ########################################
-# check if we have valgrind/valgrind.h
+# check if we have valgrind/valgrind.h and valgrind/memcheck.h
 
 valgrind_h=no
 cat > $TMPC << EOF
 #include <valgrind/valgrind.h>
+#include <valgrind/memcheck.h>
 int main(void) {
   return 0;
 }
diff --git a/kvm-all.c b/kvm-all.c
index 34b02c1..e0244b6 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -39,6 +39,10 @@
 #include <sys/eventfd.h>
 #endif
 
+#ifdef CONFIG_VALGRIND_H
+#include <valgrind/memcheck.h>
+#endif
+
 /* KVM uses PAGE_SIZE in its definition of COALESCED_MMIO_MAX */
 #define PAGE_SIZE TARGET_PAGE_SIZE
 
@@ -1719,6 +1723,9 @@ void *kvm_vmalloc(ram_addr_t size)
 
 void kvm_setup_guest_memory(void *start, size_t size)
 {
+#ifdef CONFIG_VALGRIND_H
+    VALGRIND_MAKE_MEM_DEFINED(start, size);
+#endif
     if (!kvm_has_sync_mmu()) {
         int ret = qemu_madvise(start, size, QEMU_MADV_DONTFORK);
 
commit 0c267217ca9985e6d118ec8368bebd382db7a099
Author: Jan Kiszka <jan.kiszka at web.de>
Date:   Sat Sep 8 11:52:39 2012 +0200

    musicpal: Fix flash mapping
    
    The old arithmetic assumed 32 physical address bits which is no longer
    true for ARM since 3cc0cd61f4.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at web.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/musicpal.c b/hw/musicpal.c
index ad725b5..f305e21 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1583,7 +1583,7 @@ static void musicpal_init(ram_addr_t ram_size,
          * image is smaller than 32 MB.
          */
 #ifdef TARGET_WORDS_BIGENDIAN
-        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, NULL,
+        pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
                               "musicpal.flash", flash_size,
                               dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
@@ -1591,7 +1591,7 @@ static void musicpal_init(ram_addr_t ram_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
                               0x5555, 0x2AAA, 1);
 #else
-        pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, NULL,
+        pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
                               "musicpal.flash", flash_size,
                               dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
commit ce6c760c37b9a88db87c5b9b9bf39ca866e570f6
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Tue May 22 10:14:28 2012 +0200

    Add MAINTAINERS entry for leon3
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index 6d864c1..61f8b45 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -398,6 +398,12 @@ M: Blue Swirl <blauwirbel at gmail.com>
 S: Maintained
 F: hw/sun4u.c
 
+Leon3
+M: Fabien Chouteau <chouteau at adacore.com>
+S: Maintained
+F: hw/leon3.c
+F: hw/grlib*
+
 S390 Machines
 -------------
 S390 Virtio
commit 5acfc8320fdd455c3ee5c21fe7d3403dbc755372
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Sep 7 17:13:28 2012 +0200

    target-sparc: fix fcmp{s,d,q} instructions wrt exception
    
    fcmp{s,d,q} instructions are supposed to ignore quiet NaN (contrary to
    the fcmpe{s,d,q} instructions), but the current code is wrongly setting
    the NV exception in that case. Moreover the current code is duplicated:
    first the arguments are checked for NaN to generate an exception, and
    later in case the comparison is unordered (which can only happens if one
    of the argument is a NaN), the same check is done to generate an
    exception.
    
    Fix that by calling clear_float_exceptions() followed by
    check_ieee_exceptions() as for the other floating point instructions.
    Use the _compare_quiet functions for fcmp{s,d,q} and the _compare ones
    for fcmpe{s,d,q}. Simplify the flag setting by not clearing a flag that
    is set the line just below.
    
    This fix allows the math glibc testsuite to pass.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/fop_helper.c b/target-sparc/fop_helper.c
index 9c64ef8..f4b62a5 100644
--- a/target-sparc/fop_helper.c
+++ b/target-sparc/fop_helper.c
@@ -334,34 +334,28 @@ void helper_fsqrtq(CPUSPARCState *env)
 }
 
 #define GEN_FCMP(name, size, reg1, reg2, FS, E)                         \
-    void glue(helper_, name) (CPUSPARCState *env)                            \
+    void glue(helper_, name) (CPUSPARCState *env)                       \
     {                                                                   \
-        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);                    \
+        int ret;                                                        \
+        clear_float_exceptions(env);                                    \
+        if (E) {                                                        \
+            ret = glue(size, _compare)(reg1, reg2, &env->fp_status);    \
+        } else {                                                        \
+            ret = glue(size, _compare_quiet)(reg1, reg2,                \
+                                             &env->fp_status);          \
         }                                                               \
-        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
+        check_ieee_exceptions(env);                                     \
+        switch (ret) {                                                  \
         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;                                    \
-            }                                                           \
+            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_FCC1) << FS;                              \
             env->fsr |= FSR_FCC0 << FS;                                 \
             break;                                                      \
         case float_relation_greater:                                    \
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
+            env->fsr &= ~(FSR_FCC0) << FS;                              \
             env->fsr |= FSR_FCC1 << FS;                                 \
             break;                                                      \
         default:                                                        \
@@ -370,34 +364,27 @@ void helper_fsqrtq(CPUSPARCState *env)
         }                                                               \
     }
 #define GEN_FCMP_T(name, size, FS, E)                                   \
-    void glue(helper_, name)(CPUSPARCState *env, size src1, size src2)       \
+    void glue(helper_, name)(CPUSPARCState *env, size src1, size 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);                    \
+        int ret;                                                        \
+        clear_float_exceptions(env);                                    \
+        if (E) {                                                        \
+            ret = glue(size, _compare)(src1, src2, &env->fp_status);    \
+        } else {                                                        \
+            ret = glue(size, _compare_quiet)(src1, src2,                \
+                                             &env->fp_status);          \
         }                                                               \
-        switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
+        check_ieee_exceptions(env);                                     \
+        switch (ret) {                                                  \
         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;                                    \
-            }                                                           \
+            env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS;                    \
             break;                                                      \
         case float_relation_less:                                       \
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
+            env->fsr &= ~(FSR_FCC1 << FS);                              \
             env->fsr |= FSR_FCC0 << FS;                                 \
             break;                                                      \
         case float_relation_greater:                                    \
-            env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                 \
+            env->fsr &= ~(FSR_FCC0 << FS);                              \
             env->fsr |= FSR_FCC1 << FS;                                 \
             break;                                                      \
         default:                                                        \
commit c29b1bee4b025f51f02cc9f521ca19cb5f3eb432
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Thu Sep 6 04:36:46 2012 +0400

    target-xtensa: fix missing errno codes for mingw32
    
    Put the following errno value mappings under #ifdef:
    
    xtensa-semi.c: In function 'errno_h2g':
    xtensa-semi.c:113: error: 'ENOTBLK' undeclared (first use in this function)
    xtensa-semi.c:113: error: (Each undeclared identifier is reported only once
    xtensa-semi.c:113: error: for each function it appears in.)
    xtensa-semi.c:113: error: array index in initializer not of integer type
    xtensa-semi.c:113: error: (near initialization for 'guest_errno')
    xtensa-semi.c:124: error: 'ETXTBSY' undeclared (first use in this function)
    xtensa-semi.c:124: error: array index in initializer not of integer type
    xtensa-semi.c:124: error: (near initialization for 'guest_errno')
    xtensa-semi.c:134: error: 'ELOOP' undeclared (first use in this function)
    xtensa-semi.c:134: error: array index in initializer not of integer type
    xtensa-semi.c:134: error: (near initialization for 'guest_errno')
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/xtensa-semi.c b/target-xtensa/xtensa-semi.c
index e745bef..52be07a 100644
--- a/target-xtensa/xtensa-semi.c
+++ b/target-xtensa/xtensa-semi.c
@@ -110,7 +110,9 @@ static uint32_t errno_h2g(int host_errno)
         [ENOMEM]        = TARGET_ENOMEM,
         [EACCES]        = TARGET_EACCES,
         [EFAULT]        = TARGET_EFAULT,
+#ifdef ENOTBLK
         [ENOTBLK]       = TARGET_ENOTBLK,
+#endif
         [EBUSY]         = TARGET_EBUSY,
         [EEXIST]        = TARGET_EEXIST,
         [EXDEV]         = TARGET_EXDEV,
@@ -121,7 +123,9 @@ static uint32_t errno_h2g(int host_errno)
         [ENFILE]        = TARGET_ENFILE,
         [EMFILE]        = TARGET_EMFILE,
         [ENOTTY]        = TARGET_ENOTTY,
+#ifdef ETXTBSY
         [ETXTBSY]       = TARGET_ETXTBSY,
+#endif
         [EFBIG]         = TARGET_EFBIG,
         [ENOSPC]        = TARGET_ENOSPC,
         [ESPIPE]        = TARGET_ESPIPE,
@@ -131,7 +135,9 @@ static uint32_t errno_h2g(int host_errno)
         [EDOM]          = TARGET_EDOM,
         [ERANGE]        = TARGET_ERANGE,
         [ENOSYS]        = TARGET_ENOSYS,
+#ifdef ELOOP
         [ELOOP]         = TARGET_ELOOP,
+#endif
     };
 
     if (host_errno == 0) {
commit c001ed15f7bfeaa3cabde5c9cc79c4dfdb674769
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Sep 7 22:36:08 2012 +0200

    target-cris: Fix buffer overflow
    
    Report from smatch:
    
    target-cris/translate.c:3464 cpu_dump_state(32) error:
     buffer overflow 'env->sregs' 4 <= 255
    
    sregs is declared 'uint32_t sregs[4][16]', so the first index must be
    less than 4 or ARRAY_SIZE(env->sregs).
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>

diff --git a/target-cris/translate.c b/target-cris/translate.c
index 1ad9ec7..ad31877 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3458,7 +3458,7 @@ void cpu_dump_state (CPUCRISState *env, FILE *f, fprintf_function cpu_fprintf,
 	}
 	srs = env->pregs[PR_SRS];
 	cpu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
-	if (srs < 256) {
+	if (srs < ARRAY_SIZE(env->sregs)) {
 		for (i = 0; i < 16; i++) {
 			cpu_fprintf(f, "s%2.2d=%8.8x ",
 				    i, env->sregs[srs][i]);
commit 03e6e5017757645f00b2f3b4f3a257973985e455
Author: Maciej W. Rozycki <macro at codesourcery.com>
Date:   Fri Jun 8 02:04:40 2012 +0100

    MIPS/user: Fix reset CPU state initialization
    
     This change updates the CPU reset sequence to use a common piece of code
    that figures out CPU state flags, fixing the problem with MIPS_HFLAG_COP1X
    not being set where applicable that causes floating-point MADD family
    instructions (and other instructions from the MIPS IV FP subset) to trap.
    
     As compute_hflags is now shared between op_helper.c and translate.c, the
    function is now moved to a common header.  There are no changes to this
    function.
    
     The problem was seen with the 24Kf MIPS32r2 processor in user emulation.
    The new approach prevents system and user emulation from diverging -- all
    the hflags state is initialized in one place now.
    
    Signed-off-by: Maciej W. Rozycki <macro at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index ce3467f..88d92f1 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -742,4 +742,53 @@ static inline void cpu_pc_from_tb(CPUMIPSState *env, TranslationBlock *tb)
     env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
 }
 
+static inline void compute_hflags(CPUMIPSState *env)
+{
+    env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
+                     MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
+                     MIPS_HFLAG_UX);
+    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM)) {
+        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
+    }
+#if defined(TARGET_MIPS64)
+    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
+        (env->CP0_Status & (1 << CP0St_PX)) ||
+        (env->CP0_Status & (1 << CP0St_UX))) {
+        env->hflags |= MIPS_HFLAG_64;
+    }
+    if (env->CP0_Status & (1 << CP0St_UX)) {
+        env->hflags |= MIPS_HFLAG_UX;
+    }
+#endif
+    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
+        !(env->hflags & MIPS_HFLAG_KSU)) {
+        env->hflags |= MIPS_HFLAG_CP0;
+    }
+    if (env->CP0_Status & (1 << CP0St_CU1)) {
+        env->hflags |= MIPS_HFLAG_FPU;
+    }
+    if (env->CP0_Status & (1 << CP0St_FR)) {
+        env->hflags |= MIPS_HFLAG_F64;
+    }
+    if (env->insn_flags & ISA_MIPS32R2) {
+        if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
+            env->hflags |= MIPS_HFLAG_COP1X;
+        }
+    } else if (env->insn_flags & ISA_MIPS32) {
+        if (env->hflags & MIPS_HFLAG_64) {
+            env->hflags |= MIPS_HFLAG_COP1X;
+        }
+    } else if (env->insn_flags & ISA_MIPS4) {
+        /* All supported MIPS IV CPUs use the XX (CU3) to enable
+           and disable the MIPS IV extensions to the MIPS III ISA.
+           Some other MIPS IV CPUs ignore the bit, so the check here
+           would be too restrictive for them.  */
+        if (env->CP0_Status & (1 << CP0St_CU3)) {
+            env->hflags |= MIPS_HFLAG_COP1X;
+        }
+    }
+}
+
 #endif /* !defined (__MIPS_CPU_H__) */
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index e5bc93e..3d242aa 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -32,55 +32,6 @@
 static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global);
 #endif
 
-static inline void compute_hflags(CPUMIPSState *env)
-{
-    env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
-                     MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
-                     MIPS_HFLAG_UX);
-    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
-        !(env->CP0_Status & (1 << CP0St_ERL)) &&
-        !(env->hflags & MIPS_HFLAG_DM)) {
-        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
-    }
-#if defined(TARGET_MIPS64)
-    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
-        (env->CP0_Status & (1 << CP0St_PX)) ||
-        (env->CP0_Status & (1 << CP0St_UX))) {
-        env->hflags |= MIPS_HFLAG_64;
-    }
-    if (env->CP0_Status & (1 << CP0St_UX)) {
-        env->hflags |= MIPS_HFLAG_UX;
-    }
-#endif
-    if ((env->CP0_Status & (1 << CP0St_CU0)) ||
-        !(env->hflags & MIPS_HFLAG_KSU)) {
-        env->hflags |= MIPS_HFLAG_CP0;
-    }
-    if (env->CP0_Status & (1 << CP0St_CU1)) {
-        env->hflags |= MIPS_HFLAG_FPU;
-    }
-    if (env->CP0_Status & (1 << CP0St_FR)) {
-        env->hflags |= MIPS_HFLAG_F64;
-    }
-    if (env->insn_flags & ISA_MIPS32R2) {
-        if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
-            env->hflags |= MIPS_HFLAG_COP1X;
-        }
-    } else if (env->insn_flags & ISA_MIPS32) {
-        if (env->hflags & MIPS_HFLAG_64) {
-            env->hflags |= MIPS_HFLAG_COP1X;
-        }
-    } else if (env->insn_flags & ISA_MIPS4) {
-        /* All supported MIPS IV CPUs use the XX (CU3) to enable
-           and disable the MIPS IV extensions to the MIPS III ISA.
-           Some other MIPS IV CPUs ignore the bit, so the check here
-           would be too restrictive for them.  */
-        if (env->CP0_Status & (1 << CP0St_CU3)) {
-            env->hflags |= MIPS_HFLAG_COP1X;
-        }
-    }
-}
-
 /*****************************************************************************/
 /* Exceptions processing helpers */
 
diff --git a/target-mips/translate.c b/target-mips/translate.c
index b293419..a884f75 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -12787,18 +12787,13 @@ void cpu_state_reset(CPUMIPSState *env)
     env->insn_flags = env->cpu_model->insn_flags;
 
 #if defined(CONFIG_USER_ONLY)
-    env->hflags = MIPS_HFLAG_UM;
+    env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
     /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
        hardware registers.  */
     env->CP0_HWREna |= 0x0000000F;
     if (env->CP0_Config1 & (1 << CP0C1_FP)) {
-        env->hflags |= MIPS_HFLAG_FPU;
+        env->CP0_Status |= (1 << CP0St_CU1);
     }
-#ifdef TARGET_MIPS64
-    if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
-        env->hflags |= MIPS_HFLAG_F64;
-    }
-#endif
 #else
     if (env->hflags & MIPS_HFLAG_BMASK) {
         /* If the exception was raised from a delay slot,
@@ -12828,7 +12823,6 @@ void cpu_state_reset(CPUMIPSState *env)
     }
     /* Count register increments in debug mode, EJTAG version 1 */
     env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
-    env->hflags = MIPS_HFLAG_CP0;
 
     if (env->CP0_Config3 & (1 << CP0C3_MT)) {
         int i;
@@ -12856,11 +12850,7 @@ void cpu_state_reset(CPUMIPSState *env)
         }
     }
 #endif
-#if defined(TARGET_MIPS64)
-    if (env->cpu_model->insn_flags & ISA_MIPS3) {
-        env->hflags |= MIPS_HFLAG_64;
-    }
-#endif
+    compute_hflags(env);
     env->exception_index = EXCP_NONE;
 }
 
commit 449bc90e1f2e2fbafb64eb0c76d16c9352b0d2df
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sun Jun 10 23:18:44 2012 +0200

    lan9118: fix multicast filtering
    
    The lan9118 emulation tries to compute the multicast index by calling
    directly the crc32() function from zlib, but fails to get the correct
    result.
    
    Use the common compute_mcast_idx() function instead, which gives the
    correct result. This fixes IPv6 support.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/lan9118.c b/hw/lan9118.c
index ff0a50b..ceaf96f 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -500,7 +500,7 @@ static int lan9118_filter(lan9118_state *s, const uint8_t *addr)
         }
     } else {
         /* Hash matching  */
-        hash = (crc32(~0, addr, 6) >> 26);
+        hash = compute_mcast_idx(addr);
         if (hash & 0x20) {
             return (s->mac_hashh >> (hash & 0x1f)) & 1;
         } else {
commit 7e9c7ffe9fd9dfc3d0168dd584936db8144b230b
Author: Henning Schild <henning at hennsch.de>
Date:   Wed Sep 5 14:56:39 2012 +0200

    fix entry pointer for ELF kernels loaded with -kernel option
    
     Find a hopefully proper patch attached. Take it or leave it.
    
    Reviewed-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Henning Schild <henning at hennsch.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/elf_ops.h b/hw/elf_ops.h
index fa65ce2..731a983 100644
--- a/hw/elf_ops.h
+++ b/hw/elf_ops.h
@@ -269,6 +269,17 @@ static int glue(load_elf, SZ)(const char *name, int fd,
                 addr = ph->p_paddr;
             }
 
+            /* the entry pointer in the ELF header is a virtual
+             * address, if the text segments paddr and vaddr differ
+             * we need to adjust the entry */
+            if (pentry && !translate_fn &&
+                    ph->p_vaddr != ph->p_paddr &&
+                    ehdr.e_entry >= ph->p_vaddr &&
+                    ehdr.e_entry < ph->p_vaddr + ph->p_filesz &&
+                    ph->p_flags & PF_X) {
+                *pentry = ehdr.e_entry - ph->p_vaddr + ph->p_paddr;
+            }
+
             snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
             rom_add_blob_fixed(label, data, mem_size, addr);
 
commit 1241ed94c331ddd8fc8297b02b4508ead59467de
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Tue Aug 21 20:52:08 2012 +0000

    vhost: Pass device path to vhost_dev_init()
    
    The path to /dev/vhost-net is currently hardcoded in vhost_dev_init().
    This needs to be changed so that /dev/vhost-scsi can be used.  Pass in
    the device path instead of hardcoding it.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Cc: Paolo Bonzini <pbonzini at redhat.com>
    Cc: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/vhost.c b/hw/vhost.c
index 0fd8da8..d0ce5aa 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -747,14 +747,15 @@ static void vhost_eventfd_del(MemoryListener *listener,
 {
 }
 
-int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
+int vhost_dev_init(struct vhost_dev *hdev, int devfd, const char *devpath,
+                   bool force)
 {
     uint64_t features;
     int r;
     if (devfd >= 0) {
         hdev->control = devfd;
     } else {
-        hdev->control = open("/dev/vhost-net", O_RDWR);
+        hdev->control = open(devpath, O_RDWR);
         if (hdev->control < 0) {
             return -errno;
         }
diff --git a/hw/vhost.h b/hw/vhost.h
index 80e64df..0c47229 100644
--- a/hw/vhost.h
+++ b/hw/vhost.h
@@ -44,7 +44,8 @@ struct vhost_dev {
     bool force;
 };
 
-int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force);
+int vhost_dev_init(struct vhost_dev *hdev, int devfd, const char *devpath,
+                   bool force);
 void vhost_dev_cleanup(struct vhost_dev *hdev);
 bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev);
 int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
index ecaa22d..df2c4a3 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -109,7 +109,7 @@ struct vhost_net *vhost_net_init(NetClientState *backend, int devfd,
         (1 << VHOST_NET_F_VIRTIO_NET_HDR);
     net->backend = r;
 
-    r = vhost_dev_init(&net->dev, devfd, force);
+    r = vhost_dev_init(&net->dev, devfd, "/dev/vhost-net", force);
     if (r < 0) {
         goto fail;
     }
commit a96ed02fc73e23748c8b3e38880eeac91f83ab9f
Author: Nicholas Bellinger <nab at linux-iscsi.org>
Date:   Tue Aug 21 20:52:07 2012 +0000

    monitor: Rename+move net_handle_fd_param -> monitor_handle_fd_param
    
    This patch renames+moves the net_handle_fd_param() caller used to
    obtain a file descriptor from either qemu_parse_fd() (the normal case)
    or from monitor_get_fd() (migration case) into a generically prefixed
    monitor_handle_fd_param() to be used by vhost-scsi code.
    
    Also update net/[socket,tap].c consumers to use the new prefix.
    
    Reported-by: Michael S. Tsirkin <mst at redhat.com>
    Cc: Michael S. Tsirkin <mst at redhat.com>
    Cc: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Cc: Paolo Bonzini <pbonzini at redhat.com>
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Nicholas Bellinger <nab at linux-iscsi.org>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/monitor.c b/monitor.c
index b17b1bb..6b70b20 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2651,6 +2651,24 @@ int monitor_fdset_dup_fd_remove(int dup_fd)
     return monitor_fdset_dup_fd_find_remove(dup_fd, true);
 }
 
+int monitor_handle_fd_param(Monitor *mon, const char *fdname)
+{
+    int fd;
+
+    if (!qemu_isdigit(fdname[0]) && mon) {
+
+        fd = monitor_get_fd(mon, fdname);
+        if (fd == -1) {
+            error_report("No file descriptor named %s found", fdname);
+            return -1;
+        }
+    } else {
+        fd = qemu_parse_fd(fdname);
+    }
+
+    return fd;
+}
+
 /* mon_cmds and info_cmds would be sorted at runtime */
 static mon_cmd_t mon_cmds[] = {
 #include "hmp-commands.h"
diff --git a/monitor.h b/monitor.h
index 47d556b..714b9ea 100644
--- a/monitor.h
+++ b/monitor.h
@@ -66,6 +66,7 @@ int monitor_read_block_device_key(Monitor *mon, const char *device,
                                   void *opaque);
 
 int monitor_get_fd(Monitor *mon, const char *fdname);
+int monitor_handle_fd_param(Monitor *mon, const char *fdname);
 
 void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
     GCC_FMT_ATTR(2, 0);
diff --git a/net.c b/net.c
index 60043dd..e5d25d4 100644
--- a/net.c
+++ b/net.c
@@ -522,24 +522,6 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models,
     return -1;
 }
 
-int net_handle_fd_param(Monitor *mon, const char *param)
-{
-    int fd;
-
-    if (!qemu_isdigit(param[0]) && mon) {
-
-        fd = monitor_get_fd(mon, param);
-        if (fd == -1) {
-            error_report("No file descriptor named %s found", param);
-            return -1;
-        }
-    } else {
-        fd = qemu_parse_fd(param);
-    }
-
-    return fd;
-}
-
 static int net_init_nic(const NetClientOptions *opts, const char *name,
                         NetClientState *peer)
 {
diff --git a/net.h b/net.h
index 2975056..04fda1d 100644
--- a/net.h
+++ b/net.h
@@ -168,8 +168,6 @@ int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret);
 
 void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd);
 
-int net_handle_fd_param(Monitor *mon, const char *param);
-
 #define POLYNOMIAL 0x04c11db6
 unsigned compute_mcast_idx(const uint8_t *ep);
 
diff --git a/net/socket.c b/net/socket.c
index c172c24..7c602e4 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -629,7 +629,7 @@ int net_init_socket(const NetClientOptions *opts, const char *name,
     if (sock->has_fd) {
         int fd;
 
-        fd = net_handle_fd_param(cur_mon, sock->fd);
+        fd = monitor_handle_fd_param(cur_mon, sock->fd);
         if (fd == -1 || !net_socket_fd_init(peer, "socket", name, fd, 1)) {
             return -1;
         }
diff --git a/net/tap.c b/net/tap.c
index 1971525..a88ae8f 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -610,7 +610,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
             return -1;
         }
 
-        fd = net_handle_fd_param(cur_mon, tap->fd);
+        fd = monitor_handle_fd_param(cur_mon, tap->fd);
         if (fd == -1) {
             return -1;
         }
@@ -686,7 +686,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
         int vhostfd;
 
         if (tap->has_vhostfd) {
-            vhostfd = net_handle_fd_param(cur_mon, tap->vhostfd);
+            vhostfd = monitor_handle_fd_param(cur_mon, tap->vhostfd);
             if (vhostfd == -1) {
                 return -1;
             }
commit 0e180d9c8a7429c55d23d2e7855f1e490a063aaa
Author: Jason Baron <jbaron at redhat.com>
Date:   Tue Sep 4 16:22:46 2012 -0400

    pcie_aer: clear cmask for Advanced Error Interrupt Message Number
    
    The Advanced Error Interrupt Message Number (bits 31:27 of the Root
    Error Status Register) is updated when the number of msi messages assigned to a
    device changes. Migration of windows 7 on q35 chipset failed because the check
    in get_pci_config_device() fails due to cmask being set on these bits. Its valid
    to update these bits and we must restore this state across migration.
    
    Signed-off-by: Jason Baron <jbaron at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index 3b6981c..b04c164 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -738,6 +738,11 @@ void pcie_aer_root_init(PCIDevice *dev)
                  PCI_ERR_ROOT_CMD_EN_MASK);
     pci_set_long(dev->w1cmask + pos + PCI_ERR_ROOT_STATUS,
                  PCI_ERR_ROOT_STATUS_REPORT_MASK);
+    /* PCI_ERR_ROOT_IRQ is RO but devices change it using a
+     * device-specific method.
+     */
+    pci_set_long(dev->cmask + pos + PCI_ERR_ROOT_STATUS,
+                 ~PCI_ERR_ROOT_IRQ);
 }
 
 void pcie_aer_root_reset(PCIDevice *dev)
commit 1de53459272d89c52bb21b45d5d970de40fbb642
Author: Jason Baron <jbaron at redhat.com>
Date:   Wed Aug 8 14:29:12 2012 -0400

    pcie: drop version_id field for live migration
    
    While testing q35 live migration, I found that the migration would abort with
    the following error: "Unknown savevm section type 76".
    
    The error is due to this check failing in 'vmstate_load_state()':
    
        while(field->name) {
            if ((field->field_exists &&
                 field->field_exists(opaque, version_id)) ||
                (!field->field_exists &&
                 field->version_id <= version_id)) {
    
    The VMSTATE_PCIE_DEVICE() currently has a 'version_id' set to 2. However,
    'version_id' in the above check is 1. And thus we fail to load the pcie device
    field. Further the code returns to 'qemu_loadvm_state()' which produces the
    error that I saw.
    
    I'm proposing to fix this by simply dropping the 'version_id' field from
    VMSTATE_PCIE_DEVICE(). VMSTATE_PCI_DEVICE() defines no such field and further
    the vmstate_pcie_device that VMSTATE_PCI_DEVICE() refers to is already
    versioned. Thus, any versioning issues could be detected at the vmsd level.
    
    Taking a step back, I think that the 'field->version_id' should be compared
    against a saved version number for the field not the 'version_id'. Futhermore,
    once vmstate_load_state() is called recursively on another vmsd, the check of:
    
        if (version_id > vmsd->version_id) {
            return -EINVAL;
        }
    
    Will never fail since version_id is always equal to vmsd->version_id. So I'm
    wondering why we aren't storing the vmsd version id of the source in the
    migration stream?
    
    This patch also renames the 'name' field of vmstate_pcie_device from:
    PCIDevice -> PCIEDevice to differentiate it from vmstate_pci_device.
    
    Signed-off-by: Jason Baron <jbaron at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index 4d95984..f855cf3 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -439,7 +439,7 @@ const VMStateDescription vmstate_pci_device = {
 };
 
 const VMStateDescription vmstate_pcie_device = {
-    .name = "PCIDevice",
+    .name = "PCIEDevice",
     .version_id = 2,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
diff --git a/hw/pcie.h b/hw/pcie.h
index b8ab0c7..4889194 100644
--- a/hw/pcie.h
+++ b/hw/pcie.h
@@ -133,7 +133,6 @@ extern const VMStateDescription vmstate_pcie_device;
 
 #define VMSTATE_PCIE_DEVICE(_field, _state) {                        \
     .name       = (stringify(_field)),                               \
-    .version_id = 2,                                                 \
     .size       = sizeof(PCIDevice),                                 \
     .vmsd       = &vmstate_pcie_device,                              \
     .flags      = VMS_STRUCT,                                        \
commit 692e587fc61fd32d755234d187b4f082e28c3993
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Thu Jul 19 17:26:10 2012 +0300

    qemu: add .exrc
    
    I've been using this to get correct indenting with vim
    in qemu for a while, but it's a bit easier if we
    put the settings in the central place.
    Note that
    1. you still need to enable 'exrc' and 'secure'
       options in your vimrc for these settings to take effect.
    2. you can create a .vimrc file if 'exrc' is on but there's
       need to bypass this configuration.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/.exrc b/.exrc
new file mode 100644
index 0000000..37755ed
--- /dev/null
+++ b/.exrc
@@ -0,0 +1,7 @@
+"VIM settings to match QEMU coding style.  They are activated by adding the
+"following settings (without the " symbol) as last two lines in $HOME/.vimrc:
+"set secure
+"set exrc
+set expandtab
+set shiftwidth=4
+set smarttab
commit 6e4c0d1f03d6ab407509c32fab7cb4b8230f57ff
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Aug 27 12:32:36 2012 +0100

    hw/pl110: Fix spelling of 'palette'
    
    Fix the spelling of 'palette' used in various local variables,
    structure members and comments.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/pl110.c b/hw/pl110.c
index f94608c..a582640 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -55,8 +55,8 @@ typedef struct {
     enum pl110_bppmode bpp;
     int invalidate;
     uint32_t mux_ctrl;
-    uint32_t pallette[256];
-    uint32_t raw_pallette[128];
+    uint32_t palette[256];
+    uint32_t raw_palette[128];
     qemu_irq irq;
 } pl110_state;
 
@@ -79,8 +79,8 @@ static const VMStateDescription vmstate_pl110 = {
         VMSTATE_INT32(rows, pl110_state),
         VMSTATE_UINT32(bpp, pl110_state),
         VMSTATE_INT32(invalidate, pl110_state),
-        VMSTATE_UINT32_ARRAY(pallette, pl110_state, 256),
-        VMSTATE_UINT32_ARRAY(raw_pallette, pl110_state, 128),
+        VMSTATE_UINT32_ARRAY(palette, pl110_state, 256),
+        VMSTATE_UINT32_ARRAY(raw_palette, pl110_state, 128),
         VMSTATE_UINT32_V(mux_ctrl, pl110_state, 2),
         VMSTATE_END_OF_LIST()
     }
@@ -236,7 +236,7 @@ static void pl110_update_display(void *opaque)
                                s->upbase, s->cols, s->rows,
                                src_width, dest_width, 0,
                                s->invalidate,
-                               fn, s->pallette,
+                               fn, s->palette,
                                &first, &last);
     if (first >= 0) {
         dpy_update(s->ds, 0, first, s->cols, last - first + 1);
@@ -253,13 +253,13 @@ static void pl110_invalidate_display(void * opaque)
     }
 }
 
-static void pl110_update_pallette(pl110_state *s, int n)
+static void pl110_update_palette(pl110_state *s, int n)
 {
     int i;
     uint32_t raw;
     unsigned int r, g, b;
 
-    raw = s->raw_pallette[n];
+    raw = s->raw_palette[n];
     n <<= 1;
     for (i = 0; i < 2; i++) {
         r = (raw & 0x1f) << 3;
@@ -271,17 +271,17 @@ static void pl110_update_pallette(pl110_state *s, int n)
         raw >>= 6;
         switch (ds_get_bits_per_pixel(s->ds)) {
         case 8:
-            s->pallette[n] = rgb_to_pixel8(r, g, b);
+            s->palette[n] = rgb_to_pixel8(r, g, b);
             break;
         case 15:
-            s->pallette[n] = rgb_to_pixel15(r, g, b);
+            s->palette[n] = rgb_to_pixel15(r, g, b);
             break;
         case 16:
-            s->pallette[n] = rgb_to_pixel16(r, g, b);
+            s->palette[n] = rgb_to_pixel16(r, g, b);
             break;
         case 24:
         case 32:
-            s->pallette[n] = rgb_to_pixel32(r, g, b);
+            s->palette[n] = rgb_to_pixel32(r, g, b);
             break;
         }
         n++;
@@ -314,7 +314,7 @@ static uint64_t pl110_read(void *opaque, target_phys_addr_t offset,
         return idregs[s->version][(offset - 0xfe0) >> 2];
     }
     if (offset >= 0x200 && offset < 0x400) {
-        return s->raw_pallette[(offset - 0x200) >> 2];
+        return s->raw_palette[(offset - 0x200) >> 2];
     }
     switch (offset >> 2) {
     case 0: /* LCDTiming0 */
@@ -364,10 +364,10 @@ static void pl110_write(void *opaque, target_phys_addr_t offset,
        is written to.  */
     s->invalidate = 1;
     if (offset >= 0x200 && offset < 0x400) {
-        /* Pallette.  */
+        /* Palette.  */
         n = (offset - 0x200) >> 2;
-        s->raw_pallette[(offset - 0x200) >> 2] = val;
-        pl110_update_pallette(s, n);
+        s->raw_palette[(offset - 0x200) >> 2] = val;
+        pl110_update_palette(s, n);
         return;
     }
     switch (offset >> 2) {
diff --git a/hw/pl110_template.h b/hw/pl110_template.h
index 1dce32a..e738e4a 100644
--- a/hw/pl110_template.h
+++ b/hw/pl110_template.h
@@ -129,14 +129,14 @@ static drawfn glue(pl110_draw_fn_,BITS)[48] =
 
 static void glue(pl110_draw_line1_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
 {
-    uint32_t *pallette = opaque;
+    uint32_t *palette = opaque;
     uint32_t data;
     while (width > 0) {
         data = *(uint32_t *)src;
 #ifdef SWAP_PIXELS
-#define FN(x, y) COPY_PIXEL(d, pallette[(data >> (y + 7 - (x))) & 1]);
+#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 7 - (x))) & 1]);
 #else
-#define FN(x, y) COPY_PIXEL(d, pallette[(data >> ((x) + y)) & 1]);
+#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x) + y)) & 1]);
 #endif
 #ifdef SWAP_WORDS
         FN_8(24)
@@ -157,14 +157,14 @@ static void glue(pl110_draw_line1_,NAME)(void *opaque, uint8_t *d, const uint8_t
 
 static void glue(pl110_draw_line2_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
 {
-    uint32_t *pallette = opaque;
+    uint32_t *palette = opaque;
     uint32_t data;
     while (width > 0) {
         data = *(uint32_t *)src;
 #ifdef SWAP_PIXELS
-#define FN(x, y) COPY_PIXEL(d, pallette[(data >> (y + 6 - (x)*2)) & 3]);
+#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 6 - (x)*2)) & 3]);
 #else
-#define FN(x, y) COPY_PIXEL(d, pallette[(data >> ((x)*2 + y)) & 3]);
+#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*2 + y)) & 3]);
 #endif
 #ifdef SWAP_WORDS
         FN_4(0, 24)
@@ -185,14 +185,14 @@ static void glue(pl110_draw_line2_,NAME)(void *opaque, uint8_t *d, const uint8_t
 
 static void glue(pl110_draw_line4_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
 {
-    uint32_t *pallette = opaque;
+    uint32_t *palette = opaque;
     uint32_t data;
     while (width > 0) {
         data = *(uint32_t *)src;
 #ifdef SWAP_PIXELS
-#define FN(x, y) COPY_PIXEL(d, pallette[(data >> (y + 4 - (x)*4)) & 0xf]);
+#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 4 - (x)*4)) & 0xf]);
 #else
-#define FN(x, y) COPY_PIXEL(d, pallette[(data >> ((x)*4 + y)) & 0xf]);
+#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*4 + y)) & 0xf]);
 #endif
 #ifdef SWAP_WORDS
         FN_2(0, 24)
@@ -213,11 +213,11 @@ static void glue(pl110_draw_line4_,NAME)(void *opaque, uint8_t *d, const uint8_t
 
 static void glue(pl110_draw_line8_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
 {
-    uint32_t *pallette = opaque;
+    uint32_t *palette = opaque;
     uint32_t data;
     while (width > 0) {
         data = *(uint32_t *)src;
-#define FN(x) COPY_PIXEL(d, pallette[(data >> (x)) & 0xff]);
+#define FN(x) COPY_PIXEL(d, palette[(data >> (x)) & 0xff]);
 #ifdef SWAP_WORDS
         FN(24)
         FN(16)
commit d6ce52c1f183add6f60509bc3344a61104489613
Author: Max Filippov <jcmvbkbc at gmail.com>
Date:   Wed Aug 29 23:54:25 2012 +0400

    target-xtensa: convert host errno values to guest
    
    Guest errno values are taken from the newlib. Convert only those errno
    values that can be returned from used system calls.
    
    Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-xtensa/xtensa-semi.c b/target-xtensa/xtensa-semi.c
index 6d001c2..e745bef 100644
--- a/target-xtensa/xtensa-semi.c
+++ b/target-xtensa/xtensa-semi.c
@@ -54,6 +54,96 @@ enum {
     SELECT_ONE_EXCEPT = 3,
 };
 
+enum {
+    TARGET_EPERM        =  1,
+    TARGET_ENOENT       =  2,
+    TARGET_ESRCH        =  3,
+    TARGET_EINTR        =  4,
+    TARGET_EIO          =  5,
+    TARGET_ENXIO        =  6,
+    TARGET_E2BIG        =  7,
+    TARGET_ENOEXEC      =  8,
+    TARGET_EBADF        =  9,
+    TARGET_ECHILD       = 10,
+    TARGET_EAGAIN       = 11,
+    TARGET_ENOMEM       = 12,
+    TARGET_EACCES       = 13,
+    TARGET_EFAULT       = 14,
+    TARGET_ENOTBLK      = 15,
+    TARGET_EBUSY        = 16,
+    TARGET_EEXIST       = 17,
+    TARGET_EXDEV        = 18,
+    TARGET_ENODEV       = 19,
+    TARGET_ENOTDIR      = 20,
+    TARGET_EISDIR       = 21,
+    TARGET_EINVAL       = 22,
+    TARGET_ENFILE       = 23,
+    TARGET_EMFILE       = 24,
+    TARGET_ENOTTY       = 25,
+    TARGET_ETXTBSY      = 26,
+    TARGET_EFBIG        = 27,
+    TARGET_ENOSPC       = 28,
+    TARGET_ESPIPE       = 29,
+    TARGET_EROFS        = 30,
+    TARGET_EMLINK       = 31,
+    TARGET_EPIPE        = 32,
+    TARGET_EDOM         = 33,
+    TARGET_ERANGE       = 34,
+    TARGET_ENOSYS       = 88,
+    TARGET_ELOOP        = 92,
+};
+
+static uint32_t errno_h2g(int host_errno)
+{
+    static const uint32_t guest_errno[] = {
+        [EPERM]         = TARGET_EPERM,
+        [ENOENT]        = TARGET_ENOENT,
+        [ESRCH]         = TARGET_ESRCH,
+        [EINTR]         = TARGET_EINTR,
+        [EIO]           = TARGET_EIO,
+        [ENXIO]         = TARGET_ENXIO,
+        [E2BIG]         = TARGET_E2BIG,
+        [ENOEXEC]       = TARGET_ENOEXEC,
+        [EBADF]         = TARGET_EBADF,
+        [ECHILD]        = TARGET_ECHILD,
+        [EAGAIN]        = TARGET_EAGAIN,
+        [ENOMEM]        = TARGET_ENOMEM,
+        [EACCES]        = TARGET_EACCES,
+        [EFAULT]        = TARGET_EFAULT,
+        [ENOTBLK]       = TARGET_ENOTBLK,
+        [EBUSY]         = TARGET_EBUSY,
+        [EEXIST]        = TARGET_EEXIST,
+        [EXDEV]         = TARGET_EXDEV,
+        [ENODEV]        = TARGET_ENODEV,
+        [ENOTDIR]       = TARGET_ENOTDIR,
+        [EISDIR]        = TARGET_EISDIR,
+        [EINVAL]        = TARGET_EINVAL,
+        [ENFILE]        = TARGET_ENFILE,
+        [EMFILE]        = TARGET_EMFILE,
+        [ENOTTY]        = TARGET_ENOTTY,
+        [ETXTBSY]       = TARGET_ETXTBSY,
+        [EFBIG]         = TARGET_EFBIG,
+        [ENOSPC]        = TARGET_ENOSPC,
+        [ESPIPE]        = TARGET_ESPIPE,
+        [EROFS]         = TARGET_EROFS,
+        [EMLINK]        = TARGET_EMLINK,
+        [EPIPE]         = TARGET_EPIPE,
+        [EDOM]          = TARGET_EDOM,
+        [ERANGE]        = TARGET_ERANGE,
+        [ENOSYS]        = TARGET_ENOSYS,
+        [ELOOP]         = TARGET_ELOOP,
+    };
+
+    if (host_errno == 0) {
+        return 0;
+    } else if (host_errno > 0 && host_errno < ARRAY_SIZE(guest_errno) &&
+            guest_errno[host_errno]) {
+        return guest_errno[host_errno];
+    } else {
+        return TARGET_EINVAL;
+    }
+}
+
 void HELPER(simcall)(CPUXtensaState *env)
 {
     uint32_t *regs = env->regs;
@@ -87,14 +177,14 @@ void HELPER(simcall)(CPUXtensaState *env)
                     regs[2] = is_write ?
                         write(fd, buf, io_sz) :
                         read(fd, buf, io_sz);
-                    regs[3] = errno;
+                    regs[3] = errno_h2g(errno);
                     cpu_physical_memory_unmap(buf, sz, is_write, sz);
                     if (regs[2] == -1) {
                         break;
                     }
                 } else {
                     regs[2] = -1;
-                    regs[3] = EINVAL;
+                    regs[3] = TARGET_EINVAL;
                     break;
                 }
             }
@@ -117,10 +207,10 @@ void HELPER(simcall)(CPUXtensaState *env)
 
             if (rc == 0 && i < ARRAY_SIZE(name)) {
                 regs[2] = open(name, regs[4], regs[5]);
-                regs[3] = errno;
+                regs[3] = errno_h2g(errno);
             } else {
                 regs[2] = -1;
-                regs[3] = EINVAL;
+                regs[3] = TARGET_EINVAL;
             }
         }
         break;
@@ -130,13 +220,13 @@ void HELPER(simcall)(CPUXtensaState *env)
             regs[2] = regs[3] = 0;
         } else {
             regs[2] = close(regs[3]);
-            regs[3] = errno;
+            regs[3] = errno_h2g(errno);
         }
         break;
 
     case TARGET_SYS_lseek:
         regs[2] = lseek(regs[3], (off_t)(int32_t)regs[4], regs[5]);
-        regs[3] = errno;
+        regs[3] = errno_h2g(errno);
         break;
 
     case TARGET_SYS_select_one:
@@ -163,7 +253,7 @@ void HELPER(simcall)(CPUXtensaState *env)
                     rq == SELECT_ONE_WRITE  ? &fdset : NULL,
                     rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
                     target_tv ? &tv : NULL);
-            regs[3] = errno;
+            regs[3] = errno_h2g(errno);
         }
         break;
 
@@ -219,7 +309,7 @@ void HELPER(simcall)(CPUXtensaState *env)
     default:
         qemu_log("%s(%d): not implemented\n", __func__, regs[2]);
         regs[2] = -1;
-        regs[3] = ENOSYS;
+        regs[3] = TARGET_ENOSYS;
         break;
     }
 }
commit dfe7053a34353079503bf350f83cb8b6101a450d
Author: Don Slutz <Don at CloudSwitch.com>
Date:   Sun Sep 2 19:22:38 2012 -0400

    CHECKPATCH: Add warning for single else statement.
    
    For an example:
    
    WARNING: braces {} are necessary even for single statement blocks
    +    } else
    +        return env->regs[R_EAX];
    
    total: 0 errors, 1 warnings, 41 lines checked
    Signed-off-by: Don Slutz <Don at CloudSwitch.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 7ec8846..ec0aa4c 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2547,12 +2547,16 @@ sub process {
 					$line !~ /\#\s*else/) {
 			my $allowed = 0;
 
-			# Check the pre-context.
-			if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
-                            print "APW: ALLOWED: pre<$pre> line<$line>\n"
-                                if $dbg_adv_apw;
-                            $allowed = 1;
-			}
+                        # Check the pre-context.
+                        if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
+                            my $pre = $1;
+
+                            if ($line !~ /else/) {
+                                print "APW: ALLOWED: pre<$pre> line<$line>\n"
+                                    if $dbg_adv_apw;
+                                $allowed = 1;
+                            }
+                        }
 
 			my ($level, $endln, @chunks) =
 				ctx_statement_full($linenr, $realcnt, $-[0]);
commit 69402a6944f506f51efee13c9db94bd1605eb478
Author: Don Slutz <Don at CloudSwitch.com>
Date:   Sun Sep 2 19:22:37 2012 -0400

    CHECKPATCH: Add --debug adv_apw
    
    Add debug options to find this issue.  They were not listed
    in the help because the are not simple to understand the output of.
    
    Signed-off-by: Don Slutz <Don at CloudSwitch.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 8c83b56..7ec8846 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -99,6 +99,7 @@ my $dbg_type = 0;
 my $dbg_attr = 0;
 my $dbg_adv_dcs = 0;
 my $dbg_adv_checking = 0;
+my $dbg_adv_apw = 0;
 for my $key (keys %debug) {
 	## no critic
 	eval "\${dbg_$key} = '$debug{$key}';";
@@ -2488,8 +2489,11 @@ sub process {
 		if ($line =~ /(^.*)\bif\b/ && $line !~ /\#\s*if/) {
 			my ($level, $endln, @chunks) =
 				ctx_statement_full($linenr, $realcnt, 1);
-			#print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
-			#print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
+                        if ($dbg_adv_apw) {
+                            print "APW: chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
+                            print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"
+                                if $#chunks >= 1;
+                        }
 			if ($#chunks >= 0 && $level == 0) {
 				my $allowed = 0;
 				my $seen = 0;
@@ -2514,18 +2518,22 @@ sub process {
 
 					$seen++ if ($block =~ /^\s*{/);
 
-					#print "cond<$cond> block<$block> allowed<$allowed>\n";
+                                        print "APW: cond<$cond> block<$block> allowed<$allowed>\n"
+                                            if $dbg_adv_apw;
 					if (statement_lines($cond) > 1) {
-						#print "APW: ALLOWED: cond<$cond>\n";
-						$allowed = 1;
+                                            print "APW: ALLOWED: cond<$cond>\n"
+                                                if $dbg_adv_apw;
+                                            $allowed = 1;
 					}
 					if ($block =~/\b(?:if|for|while)\b/) {
-						#print "APW: ALLOWED: block<$block>\n";
-						$allowed = 1;
+                                            print "APW: ALLOWED: block<$block>\n"
+                                                if $dbg_adv_apw;
+                                            $allowed = 1;
 					}
 					if (statement_block_size($block) > 1) {
-						#print "APW: ALLOWED: lines block<$block>\n";
-						$allowed = 1;
+                                            print "APW: ALLOWED: lines block<$block>\n"
+                                                if $dbg_adv_apw;
+                                            $allowed = 1;
 					}
 				}
 				if ($seen != ($#chunks + 1)) {
@@ -2541,8 +2549,9 @@ sub process {
 
 			# Check the pre-context.
 			if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
-				#print "APW: ALLOWED: pre<$1>\n";
-				$allowed = 1;
+                            print "APW: ALLOWED: pre<$pre> line<$line>\n"
+                                if $dbg_adv_apw;
+                            $allowed = 1;
 			}
 
 			my ($level, $endln, @chunks) =
@@ -2556,16 +2565,19 @@ sub process {
 				substr($block, 0, length($cond), '');
 			}
 			if (statement_lines($cond) > 1) {
-				#print "APW: ALLOWED: cond<$cond>\n";
-				$allowed = 1;
+                            print "APW: ALLOWED: cond<$cond>\n"
+                                if $dbg_adv_apw;
+                            $allowed = 1;
 			}
 			if ($block =~/\b(?:if|for|while)\b/) {
-				#print "APW: ALLOWED: block<$block>\n";
-				$allowed = 1;
+                            print "APW: ALLOWED: block<$block>\n"
+                                if $dbg_adv_apw;
+                            $allowed = 1;
 			}
 			if (statement_block_size($block) > 1) {
-				#print "APW: ALLOWED: lines block<$block>\n";
-				$allowed = 1;
+                            print "APW: ALLOWED: lines block<$block>\n"
+                                if $dbg_adv_apw;
+                            $allowed = 1;
 			}
 			# Check the post-context.
 			if (defined $chunks[1]) {
@@ -2574,8 +2586,9 @@ sub process {
 					substr($block, 0, length($cond), '');
 				}
 				if ($block =~ /^\s*\{/) {
-					#print "APW: ALLOWED: chunk-1 block<$block>\n";
-					$allowed = 1;
+                                    print "APW: ALLOWED: chunk-1 block<$block>\n"
+                                        if $dbg_adv_apw;
+                                    $allowed = 1;
 				}
 			}
                         print "DCS: level=$level block<$block> allowed=$allowed\n"
commit 5424302e56ca587b665e3f409c4daa1bc2ff1cf7
Author: Don Slutz <Don at CloudSwitch.com>
Date:   Sun Sep 2 19:22:36 2012 -0400

    CHECKPATCH: Add --debug adv_checking
    
    Add debug options to find this issue.  They were not listed
    in the help because the are not simple to understand the output of.
    
    Signed-off-by: Don Slutz <Don at CloudSwitch.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 0b0f3f3..8c83b56 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -98,6 +98,7 @@ my $dbg_possible = 0;
 my $dbg_type = 0;
 my $dbg_attr = 0;
 my $dbg_adv_dcs = 0;
+my $dbg_adv_checking = 0;
 for my $key (keys %debug) {
 	## no critic
 	eval "\${dbg_$key} = '$debug{$key}';";
@@ -2549,7 +2550,8 @@ sub process {
 
 			# Check the condition.
 			my ($cond, $block) = @{$chunks[0]};
-			#print "CHECKING<$linenr> cond<$cond> block<$block>\n";
+                        print "CHECKING<$linenr> cond<$cond> block<$block>\n"
+                            if $dbg_adv_checking;
 			if (defined $cond) {
 				substr($block, 0, length($cond), '');
 			}
commit a99ac041e9f30dafb0afa326ddbeb8a481ba3f81
Author: Don Slutz <Don at CloudSwitch.com>
Date:   Sun Sep 2 19:22:35 2012 -0400

    CHECKPATCH: Add --debug adv_dcs
    
    Add debug options to find this issue.  They were not listed
    in the help because the are not simple to understand the output of.
    
    Signed-off-by: Don Slutz <Don at CloudSwitch.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index b98dc6c..0b0f3f3 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -97,6 +97,7 @@ my $dbg_values = 0;
 my $dbg_possible = 0;
 my $dbg_type = 0;
 my $dbg_attr = 0;
+my $dbg_adv_dcs = 0;
 for my $key (keys %debug) {
 	## no critic
 	eval "\${dbg_$key} = '$debug{$key}';";
@@ -2575,6 +2576,8 @@ sub process {
 					$allowed = 1;
 				}
 			}
+                        print "DCS: level=$level block<$block> allowed=$allowed\n"
+                            if $dbg_adv_dcs;
 			if ($level == 0 && $block !~ /^\s*\{/ && !$allowed) {
 				my $herectx = $here . "\n";;
 				my $cnt = statement_rawlines($block);
commit 0ab6b63655ba59d7c05089017acb721a44979526
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu May 24 11:33:25 2012 -0300

    tcx: tcx_screen_dump(): add error handling
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hw/tcx.c b/hw/tcx.c
index 428649e..93994d6 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -582,26 +582,49 @@ static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch,
     TCXState *s = opaque;
     FILE *f;
     uint8_t *d, *d1, v;
-    int y, x;
+    int ret, y, x;
 
     f = fopen(filename, "wb");
-    if (!f)
+    if (!f) {
+        error_setg(errp, "failed to open file '%s': %s", filename,
+                   strerror(errno));
         return;
-    fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
+    }
+    ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
+    if (ret < 0) {
+        goto write_err;
+    }
     d1 = s->vram;
     for(y = 0; y < s->height; y++) {
         d = d1;
         for(x = 0; x < s->width; x++) {
             v = *d;
-            fputc(s->r[v], f);
-            fputc(s->g[v], f);
-            fputc(s->b[v], f);
+            ret = fputc(s->r[v], f);
+            if (ret == EOF) {
+                goto write_err;
+            }
+            ret = fputc(s->g[v], f);
+            if (ret == EOF) {
+                goto write_err;
+            }
+            ret = fputc(s->b[v], f);
+            if (ret == EOF) {
+                goto write_err;
+            }
             d++;
         }
         d1 += MAXX;
     }
+
+out:
     fclose(f);
     return;
+
+write_err:
+    error_setg(errp, "failed to write to file '%s': %s", filename,
+               strerror(errno));
+    unlink(filename);
+    goto out;
 }
 
 static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
commit 537f2d2b0d4c27e21b3e610e57d6511e315d76cc
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu May 24 11:30:40 2012 -0300

    tcx: tcx24_screen_dump(): add error handling
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hw/tcx.c b/hw/tcx.c
index 74a7085..428649e 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -611,12 +611,18 @@ static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
     FILE *f;
     uint8_t *d, *d1, v;
     uint32_t *s24, *cptr, dval;
-    int y, x;
+    int ret, y, x;
 
     f = fopen(filename, "wb");
-    if (!f)
+    if (!f) {
+        error_setg(errp, "failed to open file '%s': %s", filename,
+                   strerror(errno));
         return;
-    fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
+    }
+    ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
+    if (ret < 0) {
+        goto write_err;
+    }
     d1 = s->vram;
     s24 = s->vram24;
     cptr = s->cplane;
@@ -625,20 +631,46 @@ static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
         for(x = 0; x < s->width; x++, d++, s24++) {
             if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct
                 dval = *s24 & 0x00ffffff;
-                fputc((dval >> 16) & 0xff, f);
-                fputc((dval >> 8) & 0xff, f);
-                fputc(dval & 0xff, f);
+                ret = fputc((dval >> 16) & 0xff, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc((dval >> 8) & 0xff, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc(dval & 0xff, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
             } else {
                 v = *d;
-                fputc(s->r[v], f);
-                fputc(s->g[v], f);
-                fputc(s->b[v], f);
+                ret = fputc(s->r[v], f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc(s->g[v], f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc(s->b[v], f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
             }
         }
         d1 += MAXX;
     }
+
+out:
     fclose(f);
     return;
+
+write_err:
+    error_setg(errp, "failed to write to file '%s': %s", filename,
+               strerror(errno));
+    unlink(filename);
+    goto out;
 }
 
 static Property tcx_properties[] = {
commit 61a3f955c1caca775729fc59e97fb9c97808ffca
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu May 24 11:28:17 2012 -0300

    g364fb: g364fb_screen_dump(): add error handling
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hw/g364fb.c b/hw/g364fb.c
index 498154b..059e622 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -293,7 +293,7 @@ static void g364fb_screen_dump(void *opaque, const char *filename, bool cswitch,
                                Error **errp)
 {
     G364State *s = opaque;
-    int y, x;
+    int ret, y, x;
     uint8_t index;
     uint8_t *data_buffer;
     FILE *f;
@@ -301,35 +301,63 @@ static void g364fb_screen_dump(void *opaque, const char *filename, bool cswitch,
     qemu_flush_coalesced_mmio_buffer();
 
     if (s->depth != 8) {
-        error_report("g364: unknown guest depth %d", s->depth);
+        error_setg(errp, "g364: unknown guest depth %d", s->depth);
         return;
     }
 
     f = fopen(filename, "wb");
-    if (!f)
+    if (!f) {
+        error_setg(errp, "failed to open file '%s': %s", filename,
+                   strerror(errno));
         return;
+    }
 
     if (s->ctla & CTLA_FORCE_BLANK) {
         /* blank screen */
-        fprintf(f, "P4\n%d %d\n",
-            s->width, s->height);
+        ret = fprintf(f, "P4\n%d %d\n", s->width, s->height);
+        if (ret < 0) {
+            goto write_err;
+        }
         for (y = 0; y < s->height; y++)
-            for (x = 0; x < s->width; x++)
-                fputc(0, f);
+            for (x = 0; x < s->width; x++) {
+                ret = fputc(0, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+            }
     } else {
         data_buffer = s->vram + s->top_of_screen;
-        fprintf(f, "P6\n%d %d\n%d\n",
-            s->width, s->height, 255);
+        ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
+        if (ret < 0) {
+            goto write_err;
+        }
         for (y = 0; y < s->height; y++)
             for (x = 0; x < s->width; x++, data_buffer++) {
                 index = *data_buffer;
-                fputc(s->color_palette[index][0], f);
-                fputc(s->color_palette[index][1], f);
-                fputc(s->color_palette[index][2], f);
+                ret = fputc(s->color_palette[index][0], f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc(s->color_palette[index][1], f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc(s->color_palette[index][2], f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
         }
     }
 
+out:
     fclose(f);
+    return;
+
+write_err:
+    error_setg(errp, "failed to write to file '%s': %s", filename,
+               strerror(errno));
+    unlink(filename);
+    goto out;
 }
 
 /* called for accesses to io ports */
commit d9c7ebb10042a7d29d50b47c110e5cb754293d89
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu May 24 11:24:34 2012 -0300

    omap_lcdc: omap_ppm_save(): add error handling
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index 3d6328f..e2ba108 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -224,18 +224,24 @@ static void omap_update_display(void *opaque)
     omap_lcd->invalidate = 0;
 }
 
-static int omap_ppm_save(const char *filename, uint8_t *data,
-                    int w, int h, int linesize)
+static void omap_ppm_save(const char *filename, uint8_t *data,
+                    int w, int h, int linesize, Error **errp)
 {
     FILE *f;
     uint8_t *d, *d1;
     unsigned int v;
-    int y, x, bpp;
+    int ret, y, x, bpp;
 
     f = fopen(filename, "wb");
-    if (!f)
-        return -1;
-    fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
+    if (!f) {
+        error_setg(errp, "failed to open file '%s': %s", filename,
+                   strerror(errno));
+        return;
+    }
+    ret = fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
+    if (ret < 0) {
+        goto write_err;
+    }
     d1 = data;
     bpp = linesize / w;
     for (y = 0; y < h; y ++) {
@@ -244,24 +250,49 @@ static int omap_ppm_save(const char *filename, uint8_t *data,
             v = *(uint32_t *) d;
             switch (bpp) {
             case 2:
-                fputc((v >> 8) & 0xf8, f);
-                fputc((v >> 3) & 0xfc, f);
-                fputc((v << 3) & 0xf8, f);
+                ret = fputc((v >> 8) & 0xf8, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc((v >> 3) & 0xfc, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc((v << 3) & 0xf8, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
                 break;
             case 3:
             case 4:
             default:
-                fputc((v >> 16) & 0xff, f);
-                fputc((v >> 8) & 0xff, f);
-                fputc((v) & 0xff, f);
+                ret = fputc((v >> 16) & 0xff, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc((v >> 8) & 0xff, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
+                ret = fputc((v) & 0xff, f);
+                if (ret == EOF) {
+                    goto write_err;
+                }
                 break;
             }
             d += bpp;
         }
         d1 += linesize;
     }
+out:
     fclose(f);
-    return 0;
+    return;
+
+write_err:
+    error_setg(errp, "failed to write to file '%s': %s", filename,
+               strerror(errno));
+    unlink(filename);
+    goto out;
 }
 
 static void omap_screen_dump(void *opaque, const char *filename, bool cswitch,
@@ -273,7 +304,7 @@ static void omap_screen_dump(void *opaque, const char *filename, bool cswitch,
     if (omap_lcd && ds_get_data(omap_lcd->state))
         omap_ppm_save(filename, ds_get_data(omap_lcd->state),
                     omap_lcd->width, omap_lcd->height,
-                    ds_get_linesize(omap_lcd->state));
+                    ds_get_linesize(omap_lcd->state), errp);
 }
 
 static void omap_invalidate_display(void *opaque) {
commit 8dc4cc7bb57d3f0d6a1d8ba372d9eda1494bcc64
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon May 21 15:18:58 2012 -0300

    omap_lcdc: rename ppm_save() to omap_ppm_save()
    
    Avoids confusion with the global ppm_save() defined in hw/vga.c.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index 39b78cd..3d6328f 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -224,8 +224,8 @@ static void omap_update_display(void *opaque)
     omap_lcd->invalidate = 0;
 }
 
-static int ppm_save(const char *filename, uint8_t *data,
-                int w, int h, int linesize)
+static int omap_ppm_save(const char *filename, uint8_t *data,
+                    int w, int h, int linesize)
 {
     FILE *f;
     uint8_t *d, *d1;
@@ -271,9 +271,9 @@ static void omap_screen_dump(void *opaque, const char *filename, bool cswitch,
 
     omap_update_display(opaque);
     if (omap_lcd && ds_get_data(omap_lcd->state))
-        ppm_save(filename, ds_get_data(omap_lcd->state),
-                omap_lcd->width, omap_lcd->height,
-                ds_get_linesize(omap_lcd->state));
+        omap_ppm_save(filename, ds_get_data(omap_lcd->state),
+                    omap_lcd->width, omap_lcd->height,
+                    ds_get_linesize(omap_lcd->state));
 }
 
 static void omap_invalidate_display(void *opaque) {
commit d663174dcd9623c44f3af2a46de2a55d16f15c19
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu May 24 10:42:25 2012 -0300

    vga: ppm_save(): add error handling
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hw/blizzard.c b/hw/blizzard.c
index a2b9053..d1c9d81 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -939,7 +939,7 @@ static void blizzard_screen_dump(void *opaque, const char *filename,
 
     blizzard_update_display(opaque);
     if (s && ds_get_data(s->state))
-        ppm_save(filename, s->state->surface);
+        ppm_save(filename, s->state->surface, errp);
 }
 
 #define DEPTH 8
diff --git a/hw/qxl.c b/hw/qxl.c
index 46a929d..bae5758 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1605,7 +1605,7 @@ static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch,
     case QXL_MODE_COMPAT:
     case QXL_MODE_NATIVE:
         qxl_render_update(qxl);
-        ppm_save(filename, qxl->ssd.ds->surface);
+        ppm_save(filename, qxl->ssd.ds->surface, errp);
         break;
     case QXL_MODE_VGA:
         vga->screen_dump(vga, filename, cswitch, errp);
diff --git a/hw/vga.c b/hw/vga.c
index dd703cf..80299ea 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2390,7 +2390,7 @@ void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
 /********************************************************/
 /* vga screen dump */
 
-int ppm_save(const char *filename, struct DisplaySurface *ds)
+void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp)
 {
     FILE *f;
     uint8_t *d, *d1;
@@ -2402,10 +2402,16 @@ int ppm_save(const char *filename, struct DisplaySurface *ds)
 
     trace_ppm_save(filename, ds);
     f = fopen(filename, "wb");
-    if (!f)
-        return -1;
-    fprintf(f, "P6\n%d %d\n%d\n",
-            ds->width, ds->height, 255);
+    if (!f) {
+        error_setg(errp, "failed to open file '%s': %s", filename,
+                   strerror(errno));
+        return;
+    }
+    ret = fprintf(f, "P6\n%d %d\n%d\n", ds->width, ds->height, 255);
+    if (ret < 0) {
+        linebuf = NULL;
+        goto write_err;
+    }
     linebuf = g_malloc(ds->width * 3);
     d1 = ds->data;
     for(y = 0; y < ds->height; y++) {
@@ -2426,12 +2432,24 @@ int ppm_save(const char *filename, struct DisplaySurface *ds)
             d += ds->pf.bytes_per_pixel;
         }
         d1 += ds->linesize;
+        clearerr(f);
         ret = fwrite(linebuf, 1, pbuf - linebuf, f);
         (void)ret;
+        if (ferror(f)) {
+            goto write_err;
+        }
     }
+
+out:
     g_free(linebuf);
     fclose(f);
-    return 0;
+    return;
+
+write_err:
+    error_setg(errp, "failed to write to file '%s': %s", filename,
+               strerror(errno));
+    unlink(filename);
+    goto out;
 }
 
 /* save the vga display in a PPM image even if no display is
@@ -2445,5 +2463,5 @@ static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
         vga_invalidate_display(s);
     }
     vga_hw_update();
-    ppm_save(filename, s->ds->surface);
+    ppm_save(filename, s->ds->surface, errp);
 }
diff --git a/hw/vga_int.h b/hw/vga_int.h
index 8938093..330a32f 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -23,6 +23,7 @@
  */
 
 #include <hw/hw.h>
+#include "error.h"
 #include "memory.h"
 
 #define ST01_V_RETRACE      0x08
@@ -204,7 +205,7 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val);
 uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr);
 void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val);
 void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2);
-int ppm_save(const char *filename, struct DisplaySurface *ds);
+void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp);
 
 int vga_ioport_invalid(VGACommonState *s, uint32_t addr);
 void vga_init_vbe(VGACommonState *s, MemoryRegion *address_space);
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 29750e1..b68e883 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1015,7 +1015,7 @@ static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch,
     if (s->depth == 32) {
         DisplaySurface *ds = qemu_create_displaysurface_from(s->width,
                 s->height, 32, ds_get_linesize(s->vga.ds), s->vga.vram_ptr);
-        ppm_save(filename, ds);
+        ppm_save(filename, ds, errp);
         g_free(ds);
     }
 }
commit ad39cf6d150e951e4c67c8120d495ae7e78054a6
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Thu May 24 13:48:23 2012 -0300

    qapi: convert screendump
    
    Next commits will update devices to propagate errors.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/console.c b/console.c
index 8228773..c1ed5e0 100644
--- a/console.c
+++ b/console.c
@@ -24,6 +24,7 @@
 #include "qemu-common.h"
 #include "console.h"
 #include "qemu-timer.h"
+#include "qmp-commands.h"
 
 //#define DEBUG_CONSOLE
 #define DEFAULT_BACKSCROLL 512
@@ -176,7 +177,7 @@ void vga_hw_invalidate(void)
         active_console->hw_invalidate(active_console->hw);
 }
 
-void vga_hw_screen_dump(const char *filename)
+void qmp_screendump(const char *filename, Error **errp)
 {
     TextConsole *previous_active_console;
     bool cswitch;
@@ -190,9 +191,9 @@ void vga_hw_screen_dump(const char *filename)
         console_select(0);
     }
     if (consoles[0] && consoles[0]->hw_screen_dump) {
-        consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch, NULL);
+        consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch, errp);
     } else {
-        error_report("screen dump not implemented");
+        error_setg(errp, "device doesn't support screendump\n");
     }
 
     if (cswitch) {
diff --git a/console.h b/console.h
index fd68ecc..f990684 100644
--- a/console.h
+++ b/console.h
@@ -357,7 +357,6 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update,
 
 void vga_hw_update(void);
 void vga_hw_invalidate(void);
-void vga_hw_screen_dump(const char *filename);
 void vga_hw_text_update(console_ch_t *chardata);
 
 int is_graphic_console(void);
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 5cee131..ed67e99 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -194,8 +194,7 @@ ETEXI
         .args_type  = "filename:F",
         .params     = "filename",
         .help       = "save screen into PPM image 'filename'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_screen_dump,
+        .mhandler.cmd = hmp_screen_dump,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index ba99b2f..1bdab22 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1157,3 +1157,12 @@ void hmp_send_key(Monitor *mon, const QDict *qdict)
     hmp_handle_error(mon, &err);
     qapi_free_QKeyCodeList(head);
 }
+
+void hmp_screen_dump(Monitor *mon, const QDict *qdict)
+{
+    const char *filename = qdict_get_str(qdict, "filename");
+    Error *err = NULL;
+
+    qmp_screendump(filename, &err);
+    hmp_handle_error(mon, &err);
+}
diff --git a/hmp.h b/hmp.h
index 8e7838c..48b9c59 100644
--- a/hmp.h
+++ b/hmp.h
@@ -72,5 +72,6 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict);
 void hmp_getfd(Monitor *mon, const QDict *qdict);
 void hmp_closefd(Monitor *mon, const QDict *qdict);
 void hmp_send_key(Monitor *mon, const QDict *qdict);
+void hmp_screen_dump(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/monitor.c b/monitor.c
index d73bad8..e315b27 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1016,12 +1016,6 @@ static int client_migrate_info(Monitor *mon, const QDict *qdict,
     return -1;
 }
 
-static int do_screen_dump(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    vga_hw_screen_dump(qdict_get_str(qdict, "filename"));
-    return 0;
-}
-
 static void do_logfile(Monitor *mon, const QDict *qdict)
 {
     cpu_set_log_filename(qdict_get_str(qdict, "filename"));
diff --git a/qapi-schema.json b/qapi-schema.json
index 5421382..df47fce 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2539,3 +2539,16 @@
 ##
 { 'command': 'send-key',
   'data': { 'keys': ['QKeyCode'], '*hold-time': 'int' } }
+
+##
+# @screendump:
+#
+# Write a PPM of the VGA screen to a file.
+#
+# @filename: the path of a new PPM file to store the image
+#
+# Returns: Nothing on success
+#
+# Since: 0.14.0
+##
+{ 'command': 'screendump', 'data': {'filename': 'str'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 470f08e..6e21ddb 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -146,10 +146,7 @@ EQMP
     {
         .name       = "screendump",
         .args_type  = "filename:F",
-        .params     = "filename",
-        .help       = "save screen into PPM image 'filename'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_screen_dump,
+        .mhandler.cmd_new = qmp_marshal_input_screendump,
     },
 
 SQMP
commit d7098135d4baac8141b2e76f2daa8a7f61599c72
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon May 21 16:41:37 2012 -0300

    console: vga_hw_screen_dump_ptr: take Error argument
    
    All devices that register a screen dump callback via
    graphic_console_init() are updated.
    
    The new argument is not used in this commit. Error handling will
    be added to each device individually later.
    
    This change is a preparation to convert the screendump command
    to the QAPI.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/console.c b/console.c
index 3b5cabb..8228773 100644
--- a/console.c
+++ b/console.c
@@ -190,7 +190,7 @@ void vga_hw_screen_dump(const char *filename)
         console_select(0);
     }
     if (consoles[0] && consoles[0]->hw_screen_dump) {
-        consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch);
+        consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch, NULL);
     } else {
         error_report("screen dump not implemented");
     }
diff --git a/console.h b/console.h
index c702b23..fd68ecc 100644
--- a/console.h
+++ b/console.h
@@ -7,6 +7,7 @@
 #include "monitor.h"
 #include "trace.h"
 #include "qapi-types.h"
+#include "error.h"
 
 /* keyboard/mouse support */
 
@@ -344,7 +345,8 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch)
 
 typedef void (*vga_hw_update_ptr)(void *);
 typedef void (*vga_hw_invalidate_ptr)(void *);
-typedef void (*vga_hw_screen_dump_ptr)(void *, const char *, bool cswitch);
+typedef void (*vga_hw_screen_dump_ptr)(void *, const char *, bool cswitch,
+                                       Error **errp);
 typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *);
 
 DisplayState *graphic_console_init(vga_hw_update_ptr update,
diff --git a/hw/blizzard.c b/hw/blizzard.c
index 29074c4..a2b9053 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -933,7 +933,7 @@ static void blizzard_update_display(void *opaque)
 }
 
 static void blizzard_screen_dump(void *opaque, const char *filename,
-                                 bool cswitch)
+                                 bool cswitch, Error **errp)
 {
     BlizzardState *s = (BlizzardState *) opaque;
 
diff --git a/hw/g364fb.c b/hw/g364fb.c
index 3a0b68f..498154b 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -289,7 +289,8 @@ static void g364fb_reset(G364State *s)
     g364fb_invalidate_display(s);
 }
 
-static void g364fb_screen_dump(void *opaque, const char *filename, bool cswitch)
+static void g364fb_screen_dump(void *opaque, const char *filename, bool cswitch,
+                               Error **errp)
 {
     G364State *s = opaque;
     int y, x;
diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index 4a08e9d..39b78cd 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -264,7 +264,8 @@ static int ppm_save(const char *filename, uint8_t *data,
     return 0;
 }
 
-static void omap_screen_dump(void *opaque, const char *filename, bool cswitch)
+static void omap_screen_dump(void *opaque, const char *filename, bool cswitch,
+                             Error **errp)
 {
     struct omap_lcd_panel_s *omap_lcd = opaque;
 
diff --git a/hw/qxl.c b/hw/qxl.c
index c2dd3b4..46a929d 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1595,7 +1595,8 @@ static void qxl_hw_invalidate(void *opaque)
     vga->invalidate(vga);
 }
 
-static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch)
+static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch,
+                               Error **errp)
 {
     PCIQXLDevice *qxl = opaque;
     VGACommonState *vga = &qxl->vga;
@@ -1607,7 +1608,7 @@ static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch)
         ppm_save(filename, qxl->ssd.ds->surface);
         break;
     case QXL_MODE_VGA:
-        vga->screen_dump(vga, filename, cswitch);
+        vga->screen_dump(vga, filename, cswitch, errp);
         break;
     default:
         break;
diff --git a/hw/tcx.c b/hw/tcx.c
index ac7dcb4..74a7085 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -56,8 +56,10 @@ typedef struct TCXState {
     uint8_t dac_index, dac_state;
 } TCXState;
 
-static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch);
-static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch);
+static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch,
+                            Error **errp);
+static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
+                            Error **errp);
 
 static void tcx_set_dirty(TCXState *s)
 {
@@ -574,7 +576,8 @@ static int tcx_init1(SysBusDevice *dev)
     return 0;
 }
 
-static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch)
+static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch,
+                            Error **errp)
 {
     TCXState *s = opaque;
     FILE *f;
@@ -601,7 +604,8 @@ static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch)
     return;
 }
 
-static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch)
+static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
+                              Error **errp)
 {
     TCXState *s = opaque;
     FILE *f;
diff --git a/hw/vga.c b/hw/vga.c
index f82ced8..dd703cf 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -166,7 +166,8 @@ static uint32_t expand4[256];
 static uint16_t expand2[256];
 static uint8_t expand4to8[16];
 
-static void vga_screen_dump(void *opaque, const char *filename, bool cswitch);
+static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
+                            Error **errp);
 
 static void vga_update_memory_access(VGACommonState *s)
 {
@@ -2435,7 +2436,8 @@ int ppm_save(const char *filename, struct DisplaySurface *ds)
 
 /* save the vga display in a PPM image even if no display is
    available */
-static void vga_screen_dump(void *opaque, const char *filename, bool cswitch)
+static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
+                            Error **errp)
 {
     VGACommonState *s = opaque;
 
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index f5e4f44..29750e1 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1003,11 +1003,12 @@ static void vmsvga_invalidate_display(void *opaque)
 
 /* save the vga display in a PPM image even if no display is
    available */
-static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch)
+static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch,
+                               Error **errp)
 {
     struct vmsvga_state_s *s = opaque;
     if (!s->enable) {
-        s->vga.screen_dump(&s->vga, filename, cswitch);
+        s->vga.screen_dump(&s->vga, filename, cswitch, errp);
         return;
     }
 
commit 75d789f8d38be693bbee3e77b558e59012e33997
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Aug 29 11:20:57 2012 -0300

    error: add error_setg()
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/error.h b/error.h
index 96fc203..da7fed3 100644
--- a/error.h
+++ b/error.h
@@ -30,6 +30,12 @@ typedef struct Error Error;
 void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(3, 4);
 
 /**
+ * Same as error_set(), but sets a generic error
+ */
+#define error_setg(err, fmt, ...) \
+    error_set(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
+
+/**
  * Returns true if an indirect pointer to an error is pointing to a valid
  * error object.
  */
commit 149474c93490e1c66f838391bd491db83136d91d
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Sep 3 21:19:11 2012 +0200

    json-parser: Fix potential NULL pointer segfault
    
    Report from smatch:
    json-parser.c:474 parse_object(62) error: potential null derefence 'dict'.
    json-parser.c:553 parse_array(75) error: potential null derefence 'list'.
    
    Label 'out' in json-parser.c can be called with list == NULL
    which is passed to QDECREF.
    
    Modify QDECREF to handle a NULL argument (inline function qobject_decref
    already handles them, too).
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qobject.h b/qobject.h
index d42386d..9124649 100644
--- a/qobject.h
+++ b/qobject.h
@@ -71,7 +71,7 @@ typedef struct QObject {
 
 /* High-level interface for qobject_decref() */
 #define QDECREF(obj)              \
-    qobject_decref(QOBJECT(obj))
+    qobject_decref(obj ? QOBJECT(obj) : NULL)
 
 /* Initialize an object to default values */
 #define QOBJECT_INIT(obj, qtype_type)   \
commit 227ccf6bff234c29974c2c18ecd3a29e6b965e3d
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Sep 1 09:30:39 2012 +0200

    qapi: Fix potential NULL pointer segfault
    
    Report from smatch:
    
    qapi-visit.c:1640 visit_type_BlockdevAction(8) error:
     we previously assumed 'obj' could be null (see line 1639)
    qapi-visit.c:2432 visit_type_NetClientOptions(8) error:
     we previously assumed 'obj' could be null (see line 2431)
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index cbec24d..e2093e8 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -157,7 +157,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
     if (!error_is_set(errp)) {
         visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
         if (!err) {
-            if (!obj || *obj) {
+            if (obj && *obj) {
                 visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err);
                 if (!err) {
                     switch ((*obj)->kind) {
commit e4c8f004c55d9da3eae3e14df740238bf805b5d6
Author: Amos Kong <akong at redhat.com>
Date:   Fri Aug 31 10:56:26 2012 +0800

    qapi: convert sendkey
    
    Convert 'sendkey' to use QAPI.
    
    QAPI passes key's index of mapping table to qmp_send_key(),
    not keycode. So we use help functions to convert key/code to
    index of key_defs, and 'index' will be converted to 'keycode'
    inside qmp_send_key().
    
    For qmp, QAPI would check invalid key and raise error.
    For hmp, invalid key is checked in hmp_send_key().
    
    'send-key' of QMP doesn't support key in hexadecimal format.
    
    Signed-off-by: Amos Kong <akong at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/console.h b/console.h
index 7934b11..c702b23 100644
--- a/console.h
+++ b/console.h
@@ -399,7 +399,6 @@ static inline int vnc_display_pw_expire(DisplayState *ds, time_t expires)
 void curses_display_init(DisplayState *ds, int full_screen);
 
 /* input.c */
-extern const int key_defs[];
 int index_from_key(const char *key);
 int index_from_keycode(int code);
 
diff --git a/hmp-commands.hx b/hmp-commands.hx
index bd0c6c9..5cee131 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -505,7 +505,7 @@ ETEXI
         .args_type  = "keys:s,hold-time:i?",
         .params     = "keys [hold_ms]",
         .help       = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)",
-        .mhandler.cmd = do_sendkey,
+        .mhandler.cmd = hmp_send_key,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 81c8acb..ba99b2f 100644
--- a/hmp.c
+++ b/hmp.c
@@ -19,6 +19,7 @@
 #include "qemu-timer.h"
 #include "qmp-commands.h"
 #include "monitor.h"
+#include "console.h"
 
 static void hmp_handle_error(Monitor *mon, Error **errp)
 {
@@ -1102,3 +1103,57 @@ void hmp_closefd(Monitor *mon, const QDict *qdict)
     qmp_closefd(fdname, &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_send_key(Monitor *mon, const QDict *qdict)
+{
+    const char *keys = qdict_get_str(qdict, "keys");
+    QKeyCodeList *keylist, *head = NULL, *tmp = NULL;
+    int has_hold_time = qdict_haskey(qdict, "hold-time");
+    int hold_time = qdict_get_try_int(qdict, "hold-time", -1);
+    Error *err = NULL;
+    char keyname_buf[16];
+    char *separator;
+    int keyname_len, idx;
+
+    while (1) {
+        separator = strchr(keys, '-');
+        keyname_len = separator ? separator - keys : strlen(keys);
+        pstrcpy(keyname_buf, sizeof(keyname_buf), keys);
+
+        /* Be compatible with old interface, convert user inputted "<" */
+        if (!strncmp(keyname_buf, "<", 1) && keyname_len == 1) {
+            pstrcpy(keyname_buf, sizeof(keyname_buf), "less");
+            keyname_len = 4;
+        }
+        keyname_buf[keyname_len] = 0;
+
+        idx = index_from_key(keyname_buf);
+        if (idx == Q_KEY_CODE_MAX) {
+            monitor_printf(mon, "invalid parameter: %s\n", keyname_buf);
+            break;
+        }
+
+        keylist = g_malloc0(sizeof(*keylist));
+        keylist->value = idx;
+        keylist->next = NULL;
+
+        if (!head) {
+            head = keylist;
+        }
+        if (tmp) {
+            tmp->next = keylist;
+        }
+        tmp = keylist;
+
+        if (!separator) {
+            break;
+        }
+        keys = separator + 1;
+    }
+
+    if (idx != Q_KEY_CODE_MAX) {
+        qmp_send_key(head, has_hold_time, hold_time, &err);
+    }
+    hmp_handle_error(mon, &err);
+    qapi_free_QKeyCodeList(head);
+}
diff --git a/hmp.h b/hmp.h
index 7dd93bf..8e7838c 100644
--- a/hmp.h
+++ b/hmp.h
@@ -71,5 +71,6 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict);
 void hmp_netdev_del(Monitor *mon, const QDict *qdict);
 void hmp_getfd(Monitor *mon, const QDict *qdict);
 void hmp_closefd(Monitor *mon, const QDict *qdict);
+void hmp_send_key(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/input.c b/input.c
index 5630cb1..c4b0619 100644
--- a/input.c
+++ b/input.c
@@ -28,6 +28,7 @@
 #include "console.h"
 #include "error.h"
 #include "qmp-commands.h"
+#include "qapi-types.h"
 
 static QEMUPutKBDEvent *qemu_put_kbd_event;
 static void *qemu_put_kbd_event_opaque;
@@ -37,7 +38,7 @@ static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
 static NotifierList mouse_mode_notifiers = 
     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
 
-const int key_defs[] = {
+static const int key_defs[] = {
     [Q_KEY_CODE_SHIFT] = 0x2a,
     [Q_KEY_CODE_SHIFT_R] = 0x36,
 
@@ -223,6 +224,70 @@ int index_from_keycode(int code)
     return i;
 }
 
+static QKeyCodeList *keycodes;
+static QEMUTimer *key_timer;
+
+static void release_keys(void *opaque)
+{
+    int keycode;
+    QKeyCodeList *p;
+
+    for (p = keycodes; p != NULL; p = p->next) {
+        keycode = key_defs[p->value];
+        if (keycode & 0x80) {
+            kbd_put_keycode(0xe0);
+        }
+        kbd_put_keycode(keycode | 0x80);
+    }
+    qapi_free_QKeyCodeList(keycodes);
+    keycodes = NULL;
+}
+
+void qmp_send_key(QKeyCodeList *keys, bool has_hold_time, int64_t hold_time,
+                  Error **errp)
+{
+    int keycode;
+    QKeyCodeList *p, *keylist, *head = NULL, *tmp = NULL;
+
+    if (!key_timer) {
+        key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL);
+    }
+
+    if (keycodes != NULL) {
+        qemu_del_timer(key_timer);
+        release_keys(NULL);
+    }
+    if (!has_hold_time) {
+        hold_time = 100;
+    }
+
+    for (p = keys; p != NULL; p = p->next) {
+        keylist = g_malloc0(sizeof(*keylist));
+        keylist->value = p->value;
+        keylist->next = NULL;
+
+        if (!head) {
+            head = keylist;
+        }
+        if (tmp) {
+            tmp->next = keylist;
+        }
+        tmp = keylist;
+
+        /* key down events */
+        keycode = key_defs[p->value];
+        if (keycode & 0x80) {
+            kbd_put_keycode(0xe0);
+        }
+        kbd_put_keycode(keycode & 0x7f);
+    }
+    keycodes = head;
+
+    /* delayed key up events */
+    qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) +
+                   muldiv64(get_ticks_per_sec(), hold_time, 1000));
+}
+
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
 {
     qemu_put_kbd_event_opaque = opaque;
diff --git a/monitor.c b/monitor.c
index 0c4f86f..d73bad8 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1290,92 +1290,6 @@ static void do_sum(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "%05d\n", sum);
 }
 
-#define MAX_KEYCODES 16
-static uint8_t keycodes[MAX_KEYCODES];
-static int nb_pending_keycodes;
-static QEMUTimer *key_timer;
-
-static void release_keys(void *opaque)
-{
-    int keycode;
-
-    while (nb_pending_keycodes > 0) {
-        nb_pending_keycodes--;
-        keycode = keycodes[nb_pending_keycodes];
-        if (keycode & 0x80)
-            kbd_put_keycode(0xe0);
-        kbd_put_keycode(keycode | 0x80);
-    }
-}
-
-static void do_sendkey(Monitor *mon, const QDict *qdict)
-{
-    char keyname_buf[16];
-    char *separator;
-    int keyname_len, keycode, i, idx;
-    const char *keys = qdict_get_str(qdict, "keys");
-    int has_hold_time = qdict_haskey(qdict, "hold-time");
-    int hold_time = qdict_get_try_int(qdict, "hold-time", -1);
-
-    if (nb_pending_keycodes > 0) {
-        qemu_del_timer(key_timer);
-        release_keys(NULL);
-    }
-    if (!has_hold_time)
-        hold_time = 100;
-    i = 0;
-    while (1) {
-        separator = strchr(keys, '-');
-        keyname_len = separator ? separator - keys : strlen(keys);
-        if (keyname_len > 0) {
-            pstrcpy(keyname_buf, sizeof(keyname_buf), keys);
-            if (keyname_len > sizeof(keyname_buf) - 1) {
-                monitor_printf(mon, "invalid key: '%s...'\n", keyname_buf);
-                return;
-            }
-            if (i == MAX_KEYCODES) {
-                monitor_printf(mon, "too many keys\n");
-                return;
-            }
-
-            /* Be compatible with old interface, convert user inputted "<" */
-            if (!strncmp(keyname_buf, "<", 1) && keyname_len == 1) {
-                pstrcpy(keyname_buf, sizeof(keyname_buf), "less");
-                keyname_len = 4;
-            }
-
-            keyname_buf[keyname_len] = 0;
-
-            idx = index_from_key(keyname_buf);
-            if (idx == Q_KEY_CODE_MAX) {
-                monitor_printf(mon, "invalid parameter: %s\n", keyname_buf);
-                return;
-            }
-
-            keycode = key_defs[idx];
-            if (keycode < 0) {
-                monitor_printf(mon, "unknown key: '%s'\n", keyname_buf);
-                return;
-            }
-            keycodes[i++] = keycode;
-        }
-        if (!separator)
-            break;
-        keys = separator + 1;
-    }
-    nb_pending_keycodes = i;
-    /* key down events */
-    for (i = 0; i < nb_pending_keycodes; i++) {
-        keycode = keycodes[i];
-        if (keycode & 0x80)
-            kbd_put_keycode(0xe0);
-        kbd_put_keycode(keycode & 0x7f);
-    }
-    /* delayed key up events */
-    qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) +
-                   muldiv64(get_ticks_per_sec(), hold_time, 1000));
-}
-
 static int mouse_button_state;
 
 static void do_mouse_move(Monitor *mon, const QDict *qdict)
@@ -4772,7 +4686,6 @@ void monitor_init(CharDriverState *chr, int flags)
     Monitor *mon;
 
     if (is_first_init) {
-        key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL);
         monitor_protocol_event_init();
         is_first_init = 0;
     }
diff --git a/qapi-schema.json b/qapi-schema.json
index 856e11a..5421382 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2519,3 +2519,23 @@
             'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again',
             'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut',
              'lf', 'help', 'meta_l', 'meta_r', 'compose' ] }
+
+##
+# @send-key:
+#
+# Send keys to guest.
+#
+# @keys: key sequence. 'keys' is the name of the key. Use a JSON array to
+#        press several keys simultaneously.
+#
+# @hold-time: #optional time to delay key up events, milliseconds. Defaults
+#             to 100
+#
+# Returns: Nothing on success
+#          If key is unknown or redundant, InvalidParameter
+#
+# Since: 1.3.0
+#
+##
+{ 'command': 'send-key',
+  'data': { 'keys': ['QKeyCode'], '*hold-time': 'int' } }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 3745a21..470f08e 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -335,6 +335,34 @@ Example:
 EQMP
 
     {
+        .name       = "send-key",
+        .args_type  = "keys:O,hold-time:i?",
+        .mhandler.cmd_new = qmp_marshal_input_send_key,
+    },
+
+SQMP
+send-key
+----------
+
+Send keys to VM.
+
+Arguments:
+
+keys array:
+    - "key": key sequence (a json-array of key enum values)
+
+- hold-time: time to delay key up events, milliseconds. Defaults to 100
+             (json-int, optional)
+
+Example:
+
+-> { "execute": "send-key",
+     "arguments": { 'keys': [ 'ctrl', 'alt', 'delete' ] } }
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "cpu",
         .args_type  = "index:i",
         .mhandler.cmd_new = qmp_marshal_input_cpu,
commit 1048c88f03545fa42bdebb077871a743a614d2ab
Author: Amos Kong <akong at redhat.com>
Date:   Fri Aug 31 10:56:25 2012 +0800

    monitor: move key_defs[] table and introduce two help functions
    
    This patch added two help functions to convert key/code to index of
    mapping table, those functions will return Q_KEY_CODE_MAX if the
    code/key is invalid.
    
    Patch also moved key_defs[] to input.c, and removed useless KeyDef struct.
    Key's index in QKeyCode enmu is same as keycode's index in new key_defs[].
    Monitor functions were changed to access key_defs[] directly.
    
    key_defs[] is used in do_send_key(), so export key_defs[]. It will be
    changed to static in next patch.
    
    Signed-off-by: Amos Kong <akong at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/console.h b/console.h
index 4334db5..7934b11 100644
--- a/console.h
+++ b/console.h
@@ -6,6 +6,7 @@
 #include "notify.h"
 #include "monitor.h"
 #include "trace.h"
+#include "qapi-types.h"
 
 /* keyboard/mouse support */
 
@@ -397,4 +398,9 @@ static inline int vnc_display_pw_expire(DisplayState *ds, time_t expires)
 /* curses.c */
 void curses_display_init(DisplayState *ds, int full_screen);
 
+/* input.c */
+extern const int key_defs[];
+int index_from_key(const char *key);
+int index_from_keycode(int code);
+
 #endif
diff --git a/input.c b/input.c
index 6968b31..5630cb1 100644
--- a/input.c
+++ b/input.c
@@ -37,6 +37,192 @@ static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers =
 static NotifierList mouse_mode_notifiers = 
     NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers);
 
+const int key_defs[] = {
+    [Q_KEY_CODE_SHIFT] = 0x2a,
+    [Q_KEY_CODE_SHIFT_R] = 0x36,
+
+    [Q_KEY_CODE_ALT] = 0x38,
+    [Q_KEY_CODE_ALT_R] = 0xb8,
+    [Q_KEY_CODE_ALTGR] = 0x64,
+    [Q_KEY_CODE_ALTGR_R] = 0xe4,
+    [Q_KEY_CODE_CTRL] = 0x1d,
+    [Q_KEY_CODE_CTRL_R] = 0x9d,
+
+    [Q_KEY_CODE_MENU] = 0xdd,
+
+    [Q_KEY_CODE_ESC] = 0x01,
+
+    [Q_KEY_CODE_1] = 0x02,
+    [Q_KEY_CODE_2] = 0x03,
+    [Q_KEY_CODE_3] = 0x04,
+    [Q_KEY_CODE_4] = 0x05,
+    [Q_KEY_CODE_5] = 0x06,
+    [Q_KEY_CODE_6] = 0x07,
+    [Q_KEY_CODE_7] = 0x08,
+    [Q_KEY_CODE_8] = 0x09,
+    [Q_KEY_CODE_9] = 0x0a,
+    [Q_KEY_CODE_0] = 0x0b,
+    [Q_KEY_CODE_MINUS] = 0x0c,
+    [Q_KEY_CODE_EQUAL] = 0x0d,
+    [Q_KEY_CODE_BACKSPACE] = 0x0e,
+
+    [Q_KEY_CODE_TAB] = 0x0f,
+    [Q_KEY_CODE_Q] = 0x10,
+    [Q_KEY_CODE_W] = 0x11,
+    [Q_KEY_CODE_E] = 0x12,
+    [Q_KEY_CODE_R] = 0x13,
+    [Q_KEY_CODE_T] = 0x14,
+    [Q_KEY_CODE_Y] = 0x15,
+    [Q_KEY_CODE_U] = 0x16,
+    [Q_KEY_CODE_I] = 0x17,
+    [Q_KEY_CODE_O] = 0x18,
+    [Q_KEY_CODE_P] = 0x19,
+    [Q_KEY_CODE_BRACKET_LEFT] = 0x1a,
+    [Q_KEY_CODE_BRACKET_RIGHT] = 0x1b,
+    [Q_KEY_CODE_RET] = 0x1c,
+
+    [Q_KEY_CODE_A] = 0x1e,
+    [Q_KEY_CODE_S] = 0x1f,
+    [Q_KEY_CODE_D] = 0x20,
+    [Q_KEY_CODE_F] = 0x21,
+    [Q_KEY_CODE_G] = 0x22,
+    [Q_KEY_CODE_H] = 0x23,
+    [Q_KEY_CODE_J] = 0x24,
+    [Q_KEY_CODE_K] = 0x25,
+    [Q_KEY_CODE_L] = 0x26,
+    [Q_KEY_CODE_SEMICOLON] = 0x27,
+    [Q_KEY_CODE_APOSTROPHE] = 0x28,
+    [Q_KEY_CODE_GRAVE_ACCENT] = 0x29,
+
+    [Q_KEY_CODE_BACKSLASH] = 0x2b,
+    [Q_KEY_CODE_Z] = 0x2c,
+    [Q_KEY_CODE_X] = 0x2d,
+    [Q_KEY_CODE_C] = 0x2e,
+    [Q_KEY_CODE_V] = 0x2f,
+    [Q_KEY_CODE_B] = 0x30,
+    [Q_KEY_CODE_N] = 0x31,
+    [Q_KEY_CODE_M] = 0x32,
+    [Q_KEY_CODE_COMMA] = 0x33,
+    [Q_KEY_CODE_DOT] = 0x34,
+    [Q_KEY_CODE_SLASH] = 0x35,
+
+    [Q_KEY_CODE_ASTERISK] = 0x37,
+
+    [Q_KEY_CODE_SPC] = 0x39,
+    [Q_KEY_CODE_CAPS_LOCK] = 0x3a,
+    [Q_KEY_CODE_F1] = 0x3b,
+    [Q_KEY_CODE_F2] = 0x3c,
+    [Q_KEY_CODE_F3] = 0x3d,
+    [Q_KEY_CODE_F4] = 0x3e,
+    [Q_KEY_CODE_F5] = 0x3f,
+    [Q_KEY_CODE_F6] = 0x40,
+    [Q_KEY_CODE_F7] = 0x41,
+    [Q_KEY_CODE_F8] = 0x42,
+    [Q_KEY_CODE_F9] = 0x43,
+    [Q_KEY_CODE_F10] = 0x44,
+    [Q_KEY_CODE_NUM_LOCK] = 0x45,
+    [Q_KEY_CODE_SCROLL_LOCK] = 0x46,
+
+    [Q_KEY_CODE_KP_DIVIDE] = 0xb5,
+    [Q_KEY_CODE_KP_MULTIPLY] = 0x37,
+    [Q_KEY_CODE_KP_SUBTRACT] = 0x4a,
+    [Q_KEY_CODE_KP_ADD] = 0x4e,
+    [Q_KEY_CODE_KP_ENTER] = 0x9c,
+    [Q_KEY_CODE_KP_DECIMAL] = 0x53,
+    [Q_KEY_CODE_SYSRQ] = 0x54,
+
+    [Q_KEY_CODE_KP_0] = 0x52,
+    [Q_KEY_CODE_KP_1] = 0x4f,
+    [Q_KEY_CODE_KP_2] = 0x50,
+    [Q_KEY_CODE_KP_3] = 0x51,
+    [Q_KEY_CODE_KP_4] = 0x4b,
+    [Q_KEY_CODE_KP_5] = 0x4c,
+    [Q_KEY_CODE_KP_6] = 0x4d,
+    [Q_KEY_CODE_KP_7] = 0x47,
+    [Q_KEY_CODE_KP_8] = 0x48,
+    [Q_KEY_CODE_KP_9] = 0x49,
+
+    [Q_KEY_CODE_LESS] = 0x56,
+
+    [Q_KEY_CODE_F11] = 0x57,
+    [Q_KEY_CODE_F12] = 0x58,
+
+    [Q_KEY_CODE_PRINT] = 0xb7,
+
+    [Q_KEY_CODE_HOME] = 0xc7,
+    [Q_KEY_CODE_PGUP] = 0xc9,
+    [Q_KEY_CODE_PGDN] = 0xd1,
+    [Q_KEY_CODE_END] = 0xcf,
+
+    [Q_KEY_CODE_LEFT] = 0xcb,
+    [Q_KEY_CODE_UP] = 0xc8,
+    [Q_KEY_CODE_DOWN] = 0xd0,
+    [Q_KEY_CODE_RIGHT] = 0xcd,
+
+    [Q_KEY_CODE_INSERT] = 0xd2,
+    [Q_KEY_CODE_DELETE] = 0xd3,
+#ifdef NEED_CPU_H
+#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64)
+    [Q_KEY_CODE_STOP] = 0xf0,
+    [Q_KEY_CODE_AGAIN] = 0xf1,
+    [Q_KEY_CODE_PROPS] = 0xf2,
+    [Q_KEY_CODE_UNDO] = 0xf3,
+    [Q_KEY_CODE_FRONT] = 0xf4,
+    [Q_KEY_CODE_COPY] = 0xf5,
+    [Q_KEY_CODE_OPEN] = 0xf6,
+    [Q_KEY_CODE_PASTE] = 0xf7,
+    [Q_KEY_CODE_FIND] = 0xf8,
+    [Q_KEY_CODE_CUT] = 0xf9,
+    [Q_KEY_CODE_LF] = 0xfa,
+    [Q_KEY_CODE_HELP] = 0xfb,
+    [Q_KEY_CODE_META_L] = 0xfc,
+    [Q_KEY_CODE_META_R] = 0xfd,
+    [Q_KEY_CODE_COMPOSE] = 0xfe,
+#endif
+#endif
+    [Q_KEY_CODE_MAX] = 0,
+};
+
+int index_from_key(const char *key)
+{
+    int i, keycode;
+    char *endp;
+
+    for (i = 0; QKeyCode_lookup[i] != NULL; i++) {
+        if (!strcmp(key, QKeyCode_lookup[i])) {
+            break;
+        }
+    }
+
+    if (strstart(key, "0x", NULL)) {
+        keycode = strtoul(key, &endp, 0);
+        if (*endp == '\0' && keycode >= 0x01 && keycode <= 0xff) {
+            for (i = 0; i < Q_KEY_CODE_MAX; i++) {
+                if (keycode == key_defs[i]) {
+                    break;
+                }
+            }
+        }
+    }
+
+    /* Return Q_KEY_CODE_MAX if the key is invalid */
+    return i;
+}
+
+int index_from_keycode(int code)
+{
+    int i;
+
+    for (i = 0; i < Q_KEY_CODE_MAX; i++) {
+        if (key_defs[i] == code) {
+            break;
+        }
+    }
+
+    /* Return Q_KEY_CODE_MAX if the code is invalid */
+    return i;
+}
+
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
 {
     qemu_put_kbd_event_opaque = opaque;
diff --git a/monitor.c b/monitor.c
index 84176eb..0c4f86f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1290,173 +1290,6 @@ static void do_sum(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "%05d\n", sum);
 }
 
-typedef struct {
-    int keycode;
-    const char *name;
-} KeyDef;
-
-static const KeyDef key_defs[] = {
-    { 0x2a, "shift" },
-    { 0x36, "shift_r" },
-
-    { 0x38, "alt" },
-    { 0xb8, "alt_r" },
-    { 0x64, "altgr" },
-    { 0xe4, "altgr_r" },
-    { 0x1d, "ctrl" },
-    { 0x9d, "ctrl_r" },
-
-    { 0xdd, "menu" },
-
-    { 0x01, "esc" },
-
-    { 0x02, "1" },
-    { 0x03, "2" },
-    { 0x04, "3" },
-    { 0x05, "4" },
-    { 0x06, "5" },
-    { 0x07, "6" },
-    { 0x08, "7" },
-    { 0x09, "8" },
-    { 0x0a, "9" },
-    { 0x0b, "0" },
-    { 0x0c, "minus" },
-    { 0x0d, "equal" },
-    { 0x0e, "backspace" },
-
-    { 0x0f, "tab" },
-    { 0x10, "q" },
-    { 0x11, "w" },
-    { 0x12, "e" },
-    { 0x13, "r" },
-    { 0x14, "t" },
-    { 0x15, "y" },
-    { 0x16, "u" },
-    { 0x17, "i" },
-    { 0x18, "o" },
-    { 0x19, "p" },
-    { 0x1a, "bracket_left" },
-    { 0x1b, "bracket_right" },
-    { 0x1c, "ret" },
-
-    { 0x1e, "a" },
-    { 0x1f, "s" },
-    { 0x20, "d" },
-    { 0x21, "f" },
-    { 0x22, "g" },
-    { 0x23, "h" },
-    { 0x24, "j" },
-    { 0x25, "k" },
-    { 0x26, "l" },
-    { 0x27, "semicolon" },
-    { 0x28, "apostrophe" },
-    { 0x29, "grave_accent" },
-
-    { 0x2b, "backslash" },
-    { 0x2c, "z" },
-    { 0x2d, "x" },
-    { 0x2e, "c" },
-    { 0x2f, "v" },
-    { 0x30, "b" },
-    { 0x31, "n" },
-    { 0x32, "m" },
-    { 0x33, "comma" },
-    { 0x34, "dot" },
-    { 0x35, "slash" },
-
-    { 0x37, "asterisk" },
-
-    { 0x39, "spc" },
-    { 0x3a, "caps_lock" },
-    { 0x3b, "f1" },
-    { 0x3c, "f2" },
-    { 0x3d, "f3" },
-    { 0x3e, "f4" },
-    { 0x3f, "f5" },
-    { 0x40, "f6" },
-    { 0x41, "f7" },
-    { 0x42, "f8" },
-    { 0x43, "f9" },
-    { 0x44, "f10" },
-    { 0x45, "num_lock" },
-    { 0x46, "scroll_lock" },
-
-    { 0xb5, "kp_divide" },
-    { 0x37, "kp_multiply" },
-    { 0x4a, "kp_subtract" },
-    { 0x4e, "kp_add" },
-    { 0x9c, "kp_enter" },
-    { 0x53, "kp_decimal" },
-    { 0x54, "sysrq" },
-
-    { 0x52, "kp_0" },
-    { 0x4f, "kp_1" },
-    { 0x50, "kp_2" },
-    { 0x51, "kp_3" },
-    { 0x4b, "kp_4" },
-    { 0x4c, "kp_5" },
-    { 0x4d, "kp_6" },
-    { 0x47, "kp_7" },
-    { 0x48, "kp_8" },
-    { 0x49, "kp_9" },
-
-    { 0x56, "less" },
-
-    { 0x57, "f11" },
-    { 0x58, "f12" },
-
-    { 0xb7, "print" },
-
-    { 0xc7, "home" },
-    { 0xc9, "pgup" },
-    { 0xd1, "pgdn" },
-    { 0xcf, "end" },
-
-    { 0xcb, "left" },
-    { 0xc8, "up" },
-    { 0xd0, "down" },
-    { 0xcd, "right" },
-
-    { 0xd2, "insert" },
-    { 0xd3, "delete" },
-#if defined(TARGET_SPARC) && !defined(TARGET_SPARC64)
-    { 0xf0, "stop" },
-    { 0xf1, "again" },
-    { 0xf2, "props" },
-    { 0xf3, "undo" },
-    { 0xf4, "front" },
-    { 0xf5, "copy" },
-    { 0xf6, "open" },
-    { 0xf7, "paste" },
-    { 0xf8, "find" },
-    { 0xf9, "cut" },
-    { 0xfa, "lf" },
-    { 0xfb, "help" },
-    { 0xfc, "meta_l" },
-    { 0xfd, "meta_r" },
-    { 0xfe, "compose" },
-#endif
-    { 0, NULL },
-};
-
-static int get_keycode(const char *key)
-{
-    const KeyDef *p;
-    char *endp;
-    int ret;
-
-    for(p = key_defs; p->name != NULL; p++) {
-        if (!strcmp(key, p->name))
-            return p->keycode;
-    }
-    if (strstart(key, "0x", NULL)) {
-        ret = strtoul(key, &endp, 0);
-        if (*endp == '\0' && ret >= 0x01 && ret <= 0xff)
-            return ret;
-    }
-    return -1;
-}
-
 #define MAX_KEYCODES 16
 static uint8_t keycodes[MAX_KEYCODES];
 static int nb_pending_keycodes;
@@ -1479,7 +1312,7 @@ static void do_sendkey(Monitor *mon, const QDict *qdict)
 {
     char keyname_buf[16];
     char *separator;
-    int keyname_len, keycode, i;
+    int keyname_len, keycode, i, idx;
     const char *keys = qdict_get_str(qdict, "keys");
     int has_hold_time = qdict_haskey(qdict, "hold-time");
     int hold_time = qdict_get_try_int(qdict, "hold-time", -1);
@@ -1512,7 +1345,14 @@ static void do_sendkey(Monitor *mon, const QDict *qdict)
             }
 
             keyname_buf[keyname_len] = 0;
-            keycode = get_keycode(keyname_buf);
+
+            idx = index_from_key(keyname_buf);
+            if (idx == Q_KEY_CODE_MAX) {
+                monitor_printf(mon, "invalid parameter: %s\n", keyname_buf);
+                return;
+            }
+
+            keycode = key_defs[idx];
             if (keycode < 0) {
                 monitor_printf(mon, "unknown key: '%s'\n", keyname_buf);
                 return;
@@ -4322,7 +4162,6 @@ static void monitor_find_completion(const char *cmdline)
     int nb_args, i, len;
     const char *ptype, *str;
     const mon_cmd_t *cmd;
-    const KeyDef *key;
 
     parse_cmdline(cmdline, &nb_args, args);
 #ifdef DEBUG_COMPLETION
@@ -4396,8 +4235,8 @@ static void monitor_find_completion(const char *cmdline)
                 if (sep)
                     str = sep + 1;
                 readline_set_completion_index(cur_mon->rs, strlen(str));
-                for(key = key_defs; key->name != NULL; key++) {
-                    cmd_completion(str, key->name);
+                for (i = 0; i < Q_KEY_CODE_MAX; i++) {
+                    cmd_completion(str, QKeyCode_lookup[i]);
                 }
             } else if (!strcmp(cmd->name, "help|?")) {
                 readline_set_completion_index(cur_mon->rs, strlen(str));
commit 411656f48d71131d6d1cb5b6db792fc7b451e72e
Author: Amos Kong <akong at redhat.com>
Date:   Fri Aug 31 10:56:24 2012 +0800

    qapi: add the QKeyCode enum
    
    key_defs[] in monitor.c is a mapping table of keys and keycodes,
    this patch added a QKeyCode enum. Key's index in the enmu is same
    as keycode's index in key_defs[].
    
    Signed-off-by: Amos Kong <akong at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index bd8ad74..856e11a 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2493,3 +2493,29 @@
 # Since: 1.2.0
 ##
 { 'command': 'query-target', 'returns': 'TargetInfo' }
+
+##
+# @QKeyCode:
+#
+# An enumeration of key name.
+#
+# This is used by the send-key command.
+#
+# Since: 1.3.0
+##
+{ 'enum': 'QKeyCode',
+  'data': [ 'shift', 'shift_r', 'alt', 'alt_r', 'altgr', 'altgr_r', 'ctrl',
+            'ctrl_r', 'menu', 'esc', '1', '2', '3', '4', '5', '6', '7', '8',
+            '9', '0', 'minus', 'equal', 'backspace', 'tab', 'q', 'w', 'e',
+            'r', 't', 'y', 'u', 'i', 'o', 'p', 'bracket_left', 'bracket_right',
+            'ret', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'semicolon',
+            'apostrophe', 'grave_accent', 'backslash', 'z', 'x', 'c', 'v', 'b',
+            'n', 'm', 'comma', 'dot', 'slash', 'asterisk', 'spc', 'caps_lock',
+            'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10',
+            'num_lock', 'scroll_lock', 'kp_divide', 'kp_multiply',
+            'kp_subtract', 'kp_add', 'kp_enter', 'kp_decimal', 'sysrq', 'kp_0',
+            'kp_1', 'kp_2', 'kp_3', 'kp_4', 'kp_5', 'kp_6', 'kp_7', 'kp_8',
+            'kp_9', 'less', 'f11', 'f12', 'print', 'home', 'pgup', 'pgdn', 'end',
+            'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again',
+            'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut',
+             'lf', 'help', 'meta_l', 'meta_r', 'compose' ] }
commit b9c4b48d50057b6aee7c70879b240ff76f39c85b
Author: Amos Kong <akong at redhat.com>
Date:   Fri Aug 31 10:56:23 2012 +0800

    qapi: generate list struct and visit_list for enum
    
    Currently, if we define an 'enum' and use it in one command's
    data, list struct for enum could not be generated, but it's
    used in qmp function.
    
    For example: KeyCodesList could not be generated.
    >>> qapi-schema.json:
    { 'enum': 'KeyCodes',
      'data': [ 'shift', 'alt' ... ] }
    { 'command': 'sendkey',
      'data': { 'keys': ['KeyCodes'], '*hold-time': 'int' } }
    
    >>> qmp-command.h:
    void qmp_sendkey(KeyCodesList * keys, bool has_hold_time, int64_t
    hold_time, Error **errp);
    
    This patch lets qapi generate list struct and visit_list for enum.
    
    Signed-off-by: Amos Kong <akong at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index cf601ae..49ef569 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -28,6 +28,16 @@ typedef struct %(name)sList
 ''',
                  name=name)
 
+def generate_fwd_enum_struct(name, members):
+    return mcgen('''
+typedef struct %(name)sList
+{
+    %(name)s value;
+    struct %(name)sList *next;
+} %(name)sList;
+''',
+                 name=name)
+
 def generate_struct(structname, fieldname, members):
     ret = mcgen('''
 struct %(name)s
@@ -276,7 +286,8 @@ for expr in exprs:
     if expr.has_key('type'):
         ret += generate_fwd_struct(expr['type'], expr['data'])
     elif expr.has_key('enum'):
-        ret += generate_enum(expr['enum'], expr['data'])
+        ret += generate_enum(expr['enum'], expr['data']) + "\n"
+        ret += generate_fwd_enum_struct(expr['enum'], expr['data'])
         fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
     elif expr.has_key('union'):
         ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
@@ -300,6 +311,9 @@ for expr in exprs:
         fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
         ret += generate_type_cleanup_decl(expr['union'])
         fdef.write(generate_type_cleanup(expr['union']) + "\n")
+    elif expr.has_key('enum'):
+        ret += generate_type_cleanup_decl(expr['enum'] + "List")
+        fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n")
     else:
         continue
     fdecl.write(ret)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 04ef7c4..cbec24d 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -217,6 +217,16 @@ void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name,
 
     return ret
 
+def generate_enum_declaration(name, members, genlist=True):
+    ret = ""
+    if genlist:
+        ret += mcgen('''
+void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp);
+''',
+                     name=name)
+
+    return ret
+
 def generate_decl_enum(name, members, genlist=True):
     return mcgen('''
 
@@ -335,10 +345,12 @@ for expr in exprs:
         ret += generate_declaration(expr['union'], expr['data'])
         fdecl.write(ret)
     elif expr.has_key('enum'):
-        ret = generate_visit_enum(expr['enum'], expr['data'])
+        ret = generate_visit_list(expr['enum'], expr['data'])
+        ret += generate_visit_enum(expr['enum'], expr['data'])
         fdef.write(ret)
 
         ret = generate_decl_enum(expr['enum'], expr['data'])
+        ret += generate_enum_declaration(expr['enum'], expr['data'])
         fdecl.write(ret)
 
 fdecl.write('''
commit 2ef20c15b4736c9b0afc7ef2b14239182fbcd3e1
Author: Amos Kong <akong at redhat.com>
Date:   Fri Aug 31 10:56:22 2012 +0800

    hmp: rename arguments
    
    Rename 'string' to 'keys', rename 'hold_time' to 'hold-time'.
    
    Signed-off-by: Amos Kong <akong at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 6a70a9c..bd0c6c9 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -502,7 +502,7 @@ ETEXI
 
     {
         .name       = "sendkey",
-        .args_type  = "string:s,hold_time:i?",
+        .args_type  = "keys:s,hold-time:i?",
         .params     = "keys [hold_ms]",
         .help       = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)",
         .mhandler.cmd = do_sendkey,
diff --git a/monitor.c b/monitor.c
index c97c120..84176eb 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1480,9 +1480,9 @@ static void do_sendkey(Monitor *mon, const QDict *qdict)
     char keyname_buf[16];
     char *separator;
     int keyname_len, keycode, i;
-    const char *string = qdict_get_str(qdict, "string");
-    int has_hold_time = qdict_haskey(qdict, "hold_time");
-    int hold_time = qdict_get_try_int(qdict, "hold_time", -1);
+    const char *keys = qdict_get_str(qdict, "keys");
+    int has_hold_time = qdict_haskey(qdict, "hold-time");
+    int hold_time = qdict_get_try_int(qdict, "hold-time", -1);
 
     if (nb_pending_keycodes > 0) {
         qemu_del_timer(key_timer);
@@ -1492,10 +1492,10 @@ static void do_sendkey(Monitor *mon, const QDict *qdict)
         hold_time = 100;
     i = 0;
     while (1) {
-        separator = strchr(string, '-');
-        keyname_len = separator ? separator - string : strlen(string);
+        separator = strchr(keys, '-');
+        keyname_len = separator ? separator - keys : strlen(keys);
         if (keyname_len > 0) {
-            pstrcpy(keyname_buf, sizeof(keyname_buf), string);
+            pstrcpy(keyname_buf, sizeof(keyname_buf), keys);
             if (keyname_len > sizeof(keyname_buf) - 1) {
                 monitor_printf(mon, "invalid key: '%s...'\n", keyname_buf);
                 return;
@@ -1521,7 +1521,7 @@ static void do_sendkey(Monitor *mon, const QDict *qdict)
         }
         if (!separator)
             break;
-        string = separator + 1;
+        keys = separator + 1;
     }
     nb_pending_keycodes = i;
     /* key down events */
commit cd383492bfb5ea805d518e129d7a5402c7b99ef2
Author: Amos Kong <akong at redhat.com>
Date:   Fri Aug 31 10:56:21 2012 +0800

    monitor: rename keyname '<' to 'less'
    
    There are many maps of keycode 0x56 in pc-bios/keymaps/*
      pc-bios/keymaps/common:less 0x56
      pc-bios/keymaps/common:greater 0x56 shift
      pc-bios/keymaps/common:bar 0x56 altgr
      pc-bios/keymaps/common:brokenbar 0x56 shift altgr
    
    This patch just renamed '<' to 'less', QAPI might add new
    variable by adding a prefix to keyname, '$PREFIX_<' is not
    available, '$PREFIX_less' is ok.
    
    For compatibility, convert user inputted '<' to 'less'.
    
    Signed-off-by: Amos Kong <akong at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/monitor.c b/monitor.c
index b17b1bb..c97c120 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1400,7 +1400,7 @@ static const KeyDef key_defs[] = {
     { 0x48, "kp_8" },
     { 0x49, "kp_9" },
 
-    { 0x56, "<" },
+    { 0x56, "less" },
 
     { 0x57, "f11" },
     { 0x58, "f12" },
@@ -1504,6 +1504,13 @@ static void do_sendkey(Monitor *mon, const QDict *qdict)
                 monitor_printf(mon, "too many keys\n");
                 return;
             }
+
+            /* Be compatible with old interface, convert user inputted "<" */
+            if (!strncmp(keyname_buf, "<", 1) && keyname_len == 1) {
+                pstrcpy(keyname_buf, sizeof(keyname_buf), "less");
+                keyname_len = 4;
+            }
+
             keyname_buf[keyname_len] = 0;
             keycode = get_keycode(keyname_buf);
             if (keycode < 0) {
commit 886cc706ce5d4d3d1c296f028ddc2991cfbe3bbe
Author: Amos Kong <akong at redhat.com>
Date:   Fri Aug 31 10:56:20 2012 +0800

    fix doc of using raw values with sendkey
    
    (qemu) sendkey a
    (qemu) sendkey 0x1e
    (qemu) sendkey #0x1e
     unknown key: '#0x1e'
    
    The last command doesn't work, '#' is not requested before
    raw values, and the raw value in decimal format is not supported.
    
    Signed-off-by: Amos Kong <akong at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index f6104b0..6a70a9c 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -512,9 +512,9 @@ STEXI
 @item sendkey @var{keys}
 @findex sendkey
 
-Send @var{keys} to the emulator. @var{keys} could be the name of the
-key or @code{#} followed by the raw value in either decimal or hexadecimal
-format. Use @code{-} to press several keys simultaneously. Example:
+Send @var{keys} to the guest. @var{keys} could be the name of the
+key or the raw value in hexadecimal format. Use @code{-} to press
+several keys simultaneously. Example:
 @example
 sendkey ctrl-alt-f1
 @end example
commit fa779b65fa77d5632df1f8b2df33e9023dbc4cc8
Author: Daniel P. Berrange <berrange at redhat.com>
Date:   Wed Aug 15 11:33:47 2012 +0100

    Add support for pretty-printing response in qmp-shell
    
    Add a '-p' arg to the QMP/qmp-shell test program, which uses
    the python pprint module to pretty-print the dictionary
    returned from a command
    
      $ qmp-shell -p /tmp/qemu
      Welcome to the QMP low-level shell!
      Connected to QEMU 1.1.50
    
      (QEMU) query-cpus
      {   u'return': [   {   u'CPU': 0,
                             u'current': True,
                             u'halted': True,
                             u'pc': 1048556,
                             u'thread_id': 7108}]}
    
    Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/QMP/qmp-shell b/QMP/qmp-shell
index 42dabc8..24b665c 100755
--- a/QMP/qmp-shell
+++ b/QMP/qmp-shell
@@ -33,6 +33,7 @@
 import qmp
 import readline
 import sys
+import pprint
 
 class QMPCompleter(list):
     def complete(self, text, state):
@@ -52,10 +53,11 @@ class QMPShellBadPort(QMPShellError):
 # TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and
 #       _execute_cmd()). Let's design a better one.
 class QMPShell(qmp.QEMUMonitorProtocol):
-    def __init__(self, address):
+    def __init__(self, address, pp=None):
         qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address))
         self._greeting = None
         self._completer = None
+        self._pp = pp
 
     def __get_address(self, arg):
         """
@@ -114,7 +116,11 @@ class QMPShell(qmp.QEMUMonitorProtocol):
         if resp is None:
             print 'Disconnected'
             return False
-        print resp
+
+        if self._pp is not None:
+            self._pp.pprint(resp)
+        else:
+            print resp
         return True
 
     def connect(self):
@@ -222,22 +228,36 @@ def die(msg):
 def fail_cmdline(option=None):
     if option:
         sys.stderr.write('ERROR: bad command-line option \'%s\'\n' % option)
-    sys.stderr.write('qemu-shell [ -H ] < UNIX socket path> | < TCP address:port >\n')
+    sys.stderr.write('qemu-shell [ -p ] [ -H ] < UNIX socket path> | < TCP address:port >\n')
     sys.exit(1)
 
 def main():
     addr = ''
+    qemu = None
+    hmp = False
+    pp = None
+
     try:
-        if len(sys.argv) == 2:
-            qemu = QMPShell(sys.argv[1])
-            addr = sys.argv[1]
-        elif len(sys.argv) == 3:
-            if sys.argv[1] != '-H':
-                fail_cmdline(sys.argv[1])
-            qemu = HMPShell(sys.argv[2])
-            addr = sys.argv[2]
-        else:
-                fail_cmdline()
+        for arg in sys.argv[1:]:
+            if arg == "-H":
+                if qemu is not None:
+                    fail_cmdline(arg)
+                hmp = True
+            elif arg == "-p":
+                if pp is not None:
+                    fail_cmdline(arg)
+                pp = pprint.PrettyPrinter(indent=4)
+            else:
+                if qemu is not None:
+                    fail_cmdline(arg)
+                if hmp:
+                    qemu = HMPShell(arg)
+                else:
+                    qemu = QMPShell(arg, pp)
+                addr = arg
+
+        if qemu is None:
+            fail_cmdline()
     except QMPShellBadPort:
         die('bad port number in command-line')
 
commit f45ddd14209a4d1b95a4096d50a561b7f6270118
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Sep 5 11:44:53 2012 -0500

    Open up 1.3 development tree
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/VERSION b/VERSION
index 26aaba0..99188f0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.0
+1.2.50
commit 265db734901df7d8f24796ad7c43923249651289
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Tue Sep 4 10:14:49 2012 -0400

    Remove #ifdef QXL_COMMAND_FLAG_COMPAT_16BPP
    
    We require spice >= 0.8 now, so this flag is always present.
    
    Signed-off-by: Soren Sandmann <ssp at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 2aa5848..b726c19 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1359,11 +1359,9 @@ static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
 
     d->mode = QXL_MODE_COMPAT;
     d->cmdflags = QXL_COMMAND_FLAG_COMPAT;
-#ifdef QXL_COMMAND_FLAG_COMPAT_16BPP /* new in spice 0.6.1 */
     if (mode->bits == 16) {
         d->cmdflags |= QXL_COMMAND_FLAG_COMPAT_16BPP;
     }
-#endif
     d->shadow_rom.mode = cpu_to_le32(modenr);
     d->rom->mode = cpu_to_le32(modenr);
     qxl_rom_set_dirty(d);
commit c10018d6c77c94a8c703b9e4f026da74cad73d9e
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Tue Sep 4 10:14:48 2012 -0400

    qxl: Add set_client_capabilities() interface to QXLInterface
    
    This new interface lets spice server inform the guest whether
    
    (a) a client is connected
    (b) what capabilities the client has
    
    There is a fixed number (464) of bits reserved for capabilities, and
    when the capabilities bits change, the QXL_INTERRUPT_CLIENT interrupt
    is generated.
    
    Signed-off-by: Soren Sandmann <ssp at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 8725f67..2aa5848 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -944,6 +944,26 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
     }
 }
 
+#if SPICE_SERVER_VERSION >= 0x000b04
+
+/* called from spice server thread context only */
+static void interface_set_client_capabilities(QXLInstance *sin,
+                                              uint8_t client_present,
+                                              uint8_t caps[58])
+{
+    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
+
+    qxl->shadow_rom.client_present = client_present;
+    memcpy(qxl->shadow_rom.client_capabilities, caps, sizeof(caps));
+    qxl->rom->client_present = client_present;
+    memcpy(qxl->rom->client_capabilities, caps, sizeof(caps));
+    qxl_rom_set_dirty(qxl);
+
+    qxl_send_events(qxl, QXL_INTERRUPT_CLIENT);
+}
+
+#endif
+
 static const QXLInterface qxl_interface = {
     .base.type               = SPICE_INTERFACE_QXL,
     .base.description        = "qxl gpu",
@@ -965,6 +985,9 @@ static const QXLInterface qxl_interface = {
     .flush_resources         = interface_flush_resources,
     .async_complete          = interface_async_complete,
     .update_area_complete    = interface_update_area_complete,
+#if SPICE_SERVER_VERSION >= 0x000b04
+    .set_client_capabilities = interface_set_client_capabilities,
+#endif
 };
 
 static void qxl_enter_vga_mode(PCIQXLDevice *d)
commit ddd8fdc78ee30fc445e3d1f5bd2056acfcdefe47
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Sep 4 11:39:41 2012 +0200

    spice: make number of surfaces runtime-configurable.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index adf17fd..8725f67 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -236,7 +236,8 @@ static void qxl_spice_destroy_surfaces_complete(PCIQXLDevice *qxl)
 {
     trace_qxl_spice_destroy_surfaces_complete(qxl->id);
     qemu_mutex_lock(&qxl->track_lock);
-    memset(&qxl->guest_surfaces.cmds, 0, sizeof(qxl->guest_surfaces.cmds));
+    memset(qxl->guest_surfaces.cmds, 0,
+           sizeof(qxl->guest_surfaces.cmds) * qxl->ssd.num_surfaces);
     qxl->guest_surfaces.count = 0;
     qemu_mutex_unlock(&qxl->track_lock);
 }
@@ -345,7 +346,7 @@ static void init_qxl_rom(PCIQXLDevice *d)
     rom->slot_id_bits  = MEMSLOT_SLOT_BITS;
     rom->slots_start   = 1;
     rom->slots_end     = NUM_MEMSLOTS - 1;
-    rom->n_surfaces    = cpu_to_le32(NUM_SURFACES);
+    rom->n_surfaces    = cpu_to_le32(d->ssd.num_surfaces);
 
     for (i = 0, n = 0; i < ARRAY_SIZE(qxl_modes); i++) {
         fb = qxl_modes[i].y_res * qxl_modes[i].stride;
@@ -449,9 +450,9 @@ static int qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext)
         }
         uint32_t id = le32_to_cpu(cmd->surface_id);
 
-        if (id >= NUM_SURFACES) {
+        if (id >= qxl->ssd.num_surfaces) {
             qxl_set_guest_bug(qxl, "QXL_CMD_SURFACE id %d >= %d", id,
-                              NUM_SURFACES);
+                              qxl->ssd.num_surfaces);
             return 1;
         }
         qemu_mutex_lock(&qxl->track_lock);
@@ -527,7 +528,7 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
     info->num_memslots_groups = NUM_MEMSLOTS_GROUPS;
     info->internal_groupslot_id = 0;
     info->qxl_ram_size = le32_to_cpu(qxl->shadow_rom.num_pages) << TARGET_PAGE_BITS;
-    info->n_surfaces = NUM_SURFACES;
+    info->n_surfaces = qxl->ssd.num_surfaces;
 }
 
 static const char *qxl_mode_to_string(int mode)
@@ -1436,7 +1437,7 @@ async_common:
         QXLCookie *cookie = NULL;
         QXLRect update = d->ram->update_area;
 
-        if (d->ram->update_surface > NUM_SURFACES) {
+        if (d->ram->update_surface > d->ssd.num_surfaces) {
             qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: invalid surface id %d\n",
                               d->ram->update_surface);
             return;
@@ -1529,7 +1530,7 @@ async_common:
         }
         break;
     case QXL_IO_DESTROY_SURFACE_WAIT:
-        if (val >= NUM_SURFACES) {
+        if (val >= d->ssd.num_surfaces) {
             qxl_set_guest_bug(d, "QXL_IO_DESTROY_SURFACE (async=%d):"
                              "%" PRIu64 " >= NUM_SURFACES", async, val);
             goto cancel_async;
@@ -1707,7 +1708,7 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
     vram_start =  (intptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
 
     /* dirty the off-screen surfaces */
-    for (i = 0; i < NUM_SURFACES; i++) {
+    for (i = 0; i < qxl->ssd.num_surfaces; i++) {
         QXLSurfaceCmd *cmd;
         intptr_t surface_offset;
         int surface_size;
@@ -1835,7 +1836,6 @@ static int qxl_init_common(PCIQXLDevice *qxl)
     qxl->mode = QXL_MODE_UNDEFINED;
     qxl->generation = 1;
     qxl->num_memslots = NUM_MEMSLOTS;
-    qxl->num_surfaces = NUM_SURFACES;
     qemu_mutex_init(&qxl->track_lock);
     qemu_mutex_init(&qxl->async_lock);
     qxl->current_async = QXL_UNDEFINED_IO;
@@ -1877,6 +1877,7 @@ static int qxl_init_common(PCIQXLDevice *qxl)
     init_qxl_rom(qxl);
     init_qxl_ram(qxl);
 
+    qxl->guest_surfaces.cmds = g_new0(QXLPHYSICAL, qxl->ssd.num_surfaces);
     memory_region_init_ram(&qxl->vram_bar, "qxl.vram", qxl->vram_size);
     vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev);
     memory_region_init_alias(&qxl->vram32_bar, "qxl.vram32", &qxl->vram_bar,
@@ -2042,8 +2043,8 @@ static int qxl_post_load(void *opaque, int version)
         qxl_create_guest_primary(d, 1, QXL_SYNC);
 
         /* replay surface-create and cursor-set commands */
-        cmds = g_malloc0(sizeof(QXLCommandExt) * (NUM_SURFACES + 1));
-        for (in = 0, out = 0; in < NUM_SURFACES; in++) {
+        cmds = g_malloc0(sizeof(QXLCommandExt) * (d->ssd.num_surfaces + 1));
+        for (in = 0, out = 0; in < d->ssd.num_surfaces; in++) {
             if (d->guest_surfaces.cmds[in] == 0) {
                 continue;
             }
@@ -2143,9 +2144,10 @@ static VMStateDescription qxl_vmstate = {
                              qxl_memslot, struct guest_slots),
         VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0,
                        qxl_surface, QXLSurfaceCreate),
-        VMSTATE_INT32_EQUAL(num_surfaces, PCIQXLDevice),
-        VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, 0,
-                      vmstate_info_uint64, uint64_t),
+        VMSTATE_INT32_EQUAL(ssd.num_surfaces, PCIQXLDevice),
+        VMSTATE_VARRAY_INT32(guest_surfaces.cmds, PCIQXLDevice,
+                             ssd.num_surfaces, 0,
+                             vmstate_info_uint64, uint64_t),
         VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
         VMSTATE_END_OF_LIST()
     },
@@ -2173,6 +2175,7 @@ static Property qxl_properties[] = {
         DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram32_size_mb, -1),
         DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1),
         DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 16),
+        DEFINE_PROP_INT32("surfaces", PCIQXLDevice, ssd.num_surfaces, 1024),
         DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/qxl.h b/hw/qxl.h
index 9cfedb7..5553824 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -40,7 +40,6 @@ typedef struct PCIQXLDevice {
     uint32_t           revision;
 
     int32_t            num_memslots;
-    int32_t            num_surfaces;
 
     uint32_t           current_async;
     QemuMutex          async_lock;
@@ -65,7 +64,7 @@ typedef struct PCIQXLDevice {
     } guest_primary;
 
     struct surfaces {
-        QXLPHYSICAL    cmds[NUM_SURFACES];
+        QXLPHYSICAL    *cmds;
         uint32_t       count;
         uint32_t       max;
     } guest_surfaces;
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 1c31418..99bc665 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -317,6 +317,9 @@ void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds)
     qemu_mutex_init(&ssd->lock);
     ssd->mouse_x = -1;
     ssd->mouse_y = -1;
+    if (ssd->num_surfaces == 0) {
+        ssd->num_surfaces = 1024;
+    }
     ssd->bufsize = (16 * 1024 * 1024);
     ssd->buf = g_malloc(ssd->bufsize);
 }
@@ -427,7 +430,7 @@ static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
     info->num_memslots_groups = NUM_MEMSLOTS_GROUPS;
     info->internal_groupslot_id = 0;
     info->qxl_ram_size = ssd->bufsize;
-    info->n_surfaces = NUM_SURFACES;
+    info->n_surfaces = ssd->num_surfaces;
 }
 
 static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
diff --git a/ui/spice-display.h b/ui/spice-display.h
index bcff114..512ab78 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -32,8 +32,6 @@
 #define MEMSLOT_GROUP_GUEST 1
 #define NUM_MEMSLOTS_GROUPS 2
 
-#define NUM_SURFACES 1024
-
 /*
  * Internal enum to differenciate between options for
  * io calls that have a sync (old) version and an _async (new)
@@ -80,6 +78,7 @@ struct SimpleSpiceDisplay {
     QXLInstance qxl;
     uint32_t unique;
     QemuPfConv *conv;
+    int32_t num_surfaces;
 
     QXLRect dirty;
     int notify;
commit 2e0e3c399aa8067148055b9ea0edb822c5b584d2
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Aug 22 11:16:26 2012 +0300

    configure: print spice-protocol and spice-server versions
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/configure b/configure
index 59521ea..9592095 100755
--- a/configure
+++ b/configure
@@ -2701,6 +2701,8 @@ EOF
     spice="yes"
     libs_softmmu="$libs_softmmu $spice_libs"
     QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags"
+    spice_protocol_version=$($pkg_config --modversion spice-protocol)
+    spice_server_version=$($pkg_config --modversion spice-server)
     if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then
         spice_qxl_io_monitors_config_async="yes"
     fi
@@ -3159,7 +3161,7 @@ echo "libcap-ng support $cap_ng"
 echo "vhost-net support $vhost_net"
 echo "Trace backend     $trace_backend"
 echo "Trace output file $trace_file-<pid>"
-echo "spice support     $spice"
+echo "spice support     $spice ($spice_protocol_version/$spice_server_version)"
 echo "rbd support       $rbd"
 echo "xfsctl support    $xfs"
 echo "nss used          $smartcard_nss"
commit 020af1c45fec664d5d4cf3b8e5117f8bc1d691f2
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Aug 22 11:16:25 2012 +0300

    qxl: add QXL_IO_MONITORS_CONFIG_ASYNC
    
    Revision bumped to 4 for new IO support, enabled for spice-server >=
    0.11.1. New io enabled if revision is 4. Revision can be set to 4.
    
    [ kraxel: 3 continues to be the default revision.  Once we have a new
              stable spice-server release and the qemu patches to enable
              the new bits merged we'll go flip the switch and make rev4
              the default ]
    
    This io calls the corresponding new spice api
    spice_qxl_monitors_config_async to let spice-server read a new guest set
    monitors config and notify the client.
    
    On migration reissue spice_qxl_monitors_config_async.
    
    RHBZ: 770842
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    
    fixup
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/configure b/configure
index d97fd81..59521ea 100755
--- a/configure
+++ b/configure
@@ -2701,6 +2701,9 @@ EOF
     spice="yes"
     libs_softmmu="$libs_softmmu $spice_libs"
     QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags"
+    if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then
+        spice_qxl_io_monitors_config_async="yes"
+    fi
   else
     if test "$spice" = "yes" ; then
       feature_not_found "spice"
@@ -3438,6 +3441,10 @@ if test "$spice" = "yes" ; then
   echo "CONFIG_SPICE=y" >> $config_host_mak
 fi
 
+if test "$spice_qxl_io_monitors_config_async" = "yes" ; then
+  echo "CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC=y" >> $config_host_mak
+fi
+
 if test "$smartcard" = "yes" ; then
   echo "CONFIG_SMARTCARD=y" >> $config_host_mak
 fi
diff --git a/hw/qxl.c b/hw/qxl.c
index d134a70..adf17fd 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -27,6 +27,11 @@
 
 #include "qxl.h"
 
+#ifndef CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC
+/* spice-protocol is too old, add missing definitions */
+#define QXL_IO_MONITORS_CONFIG_ASYNC (QXL_IO_FLUSH_RELEASE + 1)
+#endif
+
 /*
  * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as
  * such can be changed by the guest, so to avoid a guest trigerrable
@@ -249,6 +254,39 @@ static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
     }
 }
 
+static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay)
+{
+    trace_qxl_spice_monitors_config(qxl->id);
+/* 0x000b01 == 0.11.1 */
+#if SPICE_SERVER_VERSION >= 0x000b01 && \
+    defined(CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC)
+    if (replay) {
+        /*
+         * don't use QXL_COOKIE_TYPE_IO:
+         *  - we are not running yet (post_load), we will assert
+         *    in send_events
+         *  - this is not a guest io, but a reply, so async_io isn't set.
+         */
+        spice_qxl_monitors_config_async(&qxl->ssd.qxl,
+                qxl->guest_monitors_config,
+                MEMSLOT_GROUP_GUEST,
+                (uintptr_t)qxl_cookie_new(
+                    QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
+                    0));
+    } else {
+        qxl->guest_monitors_config = qxl->ram->monitors_config;
+        spice_qxl_monitors_config_async(&qxl->ssd.qxl,
+                qxl->ram->monitors_config,
+                MEMSLOT_GROUP_GUEST,
+                (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
+                                          QXL_IO_MONITORS_CONFIG_ASYNC));
+    }
+#else
+    fprintf(stderr, "qxl: too old spice-protocol/spice-server for "
+            "QXL_IO_MONITORS_CONFIG_ASYNC\n");
+#endif
+}
+
 void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
 {
     trace_qxl_spice_reset_image_cache(qxl->id);
@@ -538,6 +576,7 @@ static const char *io_port_to_string(uint32_t io_port)
                                         = "QXL_IO_DESTROY_ALL_SURFACES_ASYNC",
         [QXL_IO_FLUSH_SURFACES_ASYNC]   = "QXL_IO_FLUSH_SURFACES_ASYNC",
         [QXL_IO_FLUSH_RELEASE]          = "QXL_IO_FLUSH_RELEASE",
+        [QXL_IO_MONITORS_CONFIG_ASYNC]  = "QXL_IO_MONITORS_CONFIG_ASYNC",
     };
     return io_port_to_string[io_port];
 }
@@ -819,6 +858,7 @@ static void interface_async_complete_io(PCIQXLDevice *qxl, QXLCookie *cookie)
     case QXL_IO_DESTROY_PRIMARY_ASYNC:
     case QXL_IO_UPDATE_AREA_ASYNC:
     case QXL_IO_FLUSH_SURFACES_ASYNC:
+    case QXL_IO_MONITORS_CONFIG_ASYNC:
         break;
     case QXL_IO_CREATE_PRIMARY_ASYNC:
         qxl_create_guest_primary_complete(qxl);
@@ -894,6 +934,8 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
     case QXL_COOKIE_TYPE_RENDER_UPDATE_AREA:
         qxl_render_update_area_done(qxl, cookie);
         break;
+    case QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG:
+        break;
     default:
         fprintf(stderr, "qxl: %s: unexpected cookie type %d\n",
                 __func__, cookie->type);
@@ -1315,6 +1357,13 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
         return;
     }
 
+    if (d->revision <= QXL_REVISION_STABLE_V10 &&
+        io_port >= QXL_IO_FLUSH_SURFACES_ASYNC) {
+        qxl_set_guest_bug(d, "unsupported io %d for revision %d\n",
+            io_port, d->revision);
+        return;
+    }
+
     switch (io_port) {
     case QXL_IO_RESET:
     case QXL_IO_SET_MODE:
@@ -1334,7 +1383,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
             io_port, io_port_to_string(io_port));
         /* be nice to buggy guest drivers */
         if (io_port >= QXL_IO_UPDATE_AREA_ASYNC &&
-            io_port <= QXL_IO_DESTROY_ALL_SURFACES_ASYNC) {
+            io_port < QXL_IO_RANGE_SIZE) {
             qxl_send_events(d, QXL_INTERRUPT_IO_CMD);
         }
         return;
@@ -1362,6 +1411,7 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
         io_port = QXL_IO_DESTROY_ALL_SURFACES;
         goto async_common;
     case QXL_IO_FLUSH_SURFACES_ASYNC:
+    case QXL_IO_MONITORS_CONFIG_ASYNC:
 async_common:
         async = QXL_ASYNC;
         qemu_mutex_lock(&d->async_lock);
@@ -1503,6 +1553,9 @@ async_common:
         d->mode = QXL_MODE_UNDEFINED;
         qxl_spice_destroy_surfaces(d, async);
         break;
+    case QXL_IO_MONITORS_CONFIG_ASYNC:
+        qxl_spice_monitors_config_async(d, 0);
+        break;
     default:
         qxl_set_guest_bug(d, "%s: unexpected ioport=0x%x\n", __func__, io_port);
     }
@@ -1798,9 +1851,17 @@ static int qxl_init_common(PCIQXLDevice *qxl)
         io_size = 16;
         break;
     case 3: /* qxl-3 */
-        pci_device_rev = QXL_DEFAULT_REVISION;
+        pci_device_rev = QXL_REVISION_STABLE_V10;
+        io_size = 32; /* PCI region size must be pow2 */
+        break;
+/* 0x000b01 == 0.11.1 */
+#if SPICE_SERVER_VERSION >= 0x000b01 && \
+        defined(CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC)
+    case 4: /* qxl-4 */
+        pci_device_rev = QXL_REVISION_STABLE_V12;
         io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
         break;
+#endif
     default:
         error_report("Invalid revision %d for qxl device (max %d)",
                      qxl->revision, QXL_DEFAULT_REVISION);
@@ -1999,7 +2060,9 @@ static int qxl_post_load(void *opaque, int version)
         }
         qxl_spice_loadvm_commands(d, cmds, out);
         g_free(cmds);
-
+        if (d->guest_monitors_config) {
+            qxl_spice_monitors_config_async(d, 1);
+        }
         break;
     case QXL_MODE_COMPAT:
         /* note: no need to call qxl_create_memslots, qxl_set_mode
@@ -2012,6 +2075,14 @@ static int qxl_post_load(void *opaque, int version)
 
 #define QXL_SAVE_VERSION 21
 
+static bool qxl_monitors_config_needed(void *opaque)
+{
+    PCIQXLDevice *qxl = opaque;
+
+    return qxl->guest_monitors_config != 0;
+}
+
+
 static VMStateDescription qxl_memslot = {
     .name               = "qxl-memslot",
     .version_id         = QXL_SAVE_VERSION,
@@ -2042,6 +2113,16 @@ static VMStateDescription qxl_surface = {
     }
 };
 
+static VMStateDescription qxl_vmstate_monitors_config = {
+    .name               = "qxl/monitors-config",
+    .version_id         = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(guest_monitors_config, PCIQXLDevice),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
 static VMStateDescription qxl_vmstate = {
     .name               = "qxl",
     .version_id         = QXL_SAVE_VERSION,
@@ -2049,7 +2130,7 @@ static VMStateDescription qxl_vmstate = {
     .pre_save           = qxl_pre_save,
     .pre_load           = qxl_pre_load,
     .post_load          = qxl_post_load,
-    .fields = (VMStateField []) {
+    .fields = (VMStateField[]) {
         VMSTATE_PCI_DEVICE(pci, PCIQXLDevice),
         VMSTATE_STRUCT(vga, PCIQXLDevice, 0, vmstate_vga_common, VGACommonState),
         VMSTATE_UINT32(shadow_rom.mode, PCIQXLDevice),
@@ -2068,6 +2149,14 @@ static VMStateDescription qxl_vmstate = {
         VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
         VMSTATE_END_OF_LIST()
     },
+    .subsections = (VMStateSubsection[]) {
+        {
+            .vmsd = &qxl_vmstate_monitors_config,
+            .needed = qxl_monitors_config_needed,
+        }, {
+            /* empty */
+        }
+    }
 };
 
 static Property qxl_properties[] = {
diff --git a/hw/qxl.h b/hw/qxl.h
index 172baf6..9cfedb7 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -71,6 +71,8 @@ typedef struct PCIQXLDevice {
     } guest_surfaces;
     QXLPHYSICAL        guest_cursor;
 
+    QXLPHYSICAL        guest_monitors_config;
+
     QemuMutex          track_lock;
 
     /* thread signaling */
@@ -128,7 +130,12 @@ typedef struct PCIQXLDevice {
         }                                                               \
     } while (0)
 
+#if 0
+/* spice-server 0.12 is still in development */
+#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V12
+#else
 #define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10
+#endif
 
 /* qxl.c */
 void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
diff --git a/trace-events b/trace-events
index 04b0723..8fcbc50 100644
--- a/trace-events
+++ b/trace-events
@@ -956,6 +956,7 @@ qxl_spice_destroy_surfaces(int qid, int async) "%d async=%d"
 qxl_spice_destroy_surface_wait_complete(int qid, uint32_t id) "%d sid=%d"
 qxl_spice_destroy_surface_wait(int qid, uint32_t id, int async) "%d sid=%d async=%d"
 qxl_spice_flush_surfaces_async(int qid, uint32_t surface_count, uint32_t num_free_res) "%d s#=%d, res#=%d"
+qxl_spice_monitors_config(int id) "%d"
 qxl_spice_loadvm_commands(int qid, void *ext, uint32_t count) "%d ext=%p count=%d"
 qxl_spice_oom(int qid) "%d"
 qxl_spice_reset_cursor(int qid) "%d"
diff --git a/ui/spice-display.h b/ui/spice-display.h
index 672d65e..bcff114 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -51,6 +51,7 @@ typedef enum qxl_async_io {
 enum {
     QXL_COOKIE_TYPE_IO,
     QXL_COOKIE_TYPE_RENDER_UPDATE_AREA,
+    QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
 };
 
 typedef struct QXLCookie {
commit 36839d355e4ffc77d8f937caa6bb4c5530b9237e
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Aug 21 13:51:32 2012 +0300

    qxl: disallow unknown revisions
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index baf9bb4..d134a70 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1798,10 +1798,13 @@ static int qxl_init_common(PCIQXLDevice *qxl)
         io_size = 16;
         break;
     case 3: /* qxl-3 */
-    default:
         pci_device_rev = QXL_DEFAULT_REVISION;
         io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
         break;
+    default:
+        error_report("Invalid revision %d for qxl device (max %d)",
+                     qxl->revision, QXL_DEFAULT_REVISION);
+        return -1;
     }
 
     pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
commit 511b13e2c9b426b3c56060909693de5097f0b496
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Aug 21 13:51:31 2012 +0300

    qxl/update_area_io: guest_bug on invalid parameters
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 95bbc03..baf9bb4 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1386,6 +1386,18 @@ async_common:
         QXLCookie *cookie = NULL;
         QXLRect update = d->ram->update_area;
 
+        if (d->ram->update_surface > NUM_SURFACES) {
+            qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: invalid surface id %d\n",
+                              d->ram->update_surface);
+            return;
+        }
+        if (update.left >= update.right || update.top >= update.bottom) {
+            qxl_set_guest_bug(d,
+                    "QXL_IO_UPDATE_AREA: invalid area (%ux%u)x(%ux%u)\n",
+                    update.left, update.top, update.right, update.bottom);
+            return;
+        }
+
         if (async == QXL_ASYNC) {
             cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO,
                                     QXL_IO_UPDATE_AREA_ASYNC);
commit 27af778828db9aa893fa1de928744141e5de20e5
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Tue Aug 21 13:54:20 2012 +0300

    spice: increase the verbosity of spice section in "qemu --help"
    
    Added all spice options to the help string. This can be used by libvirt
    to determine which spice related features are supported by qemu.
    
    Signed-off-by: Yonit Halperin <yhalperi at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index 96a7bb1..804a2d1 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -838,7 +838,23 @@ Enable SDL.
 ETEXI
 
 DEF("spice", HAS_ARG, QEMU_OPTION_spice,
-    "-spice <args>   enable spice\n", QEMU_ARCH_ALL)
+    "-spice [port=port][,tls-port=secured-port][,x509-dir=<dir>]\n"
+    "       [,x509-key-file=<file>][,x509-key-password=<file>]\n"
+    "       [,x509-cert-file=<file>][,x509-cacert-file=<file>]\n"
+    "       [,x509-dh-key-file=<file>][,addr=addr][,ipv4|ipv6]\n"
+    "       [,tls-ciphers=<list>]\n"
+    "       [,tls-channel=[main|display|cursor|inputs|record|playback]]\n"
+    "       [,plaintext-channel=[main|display|cursor|inputs|record|playback]]\n"
+    "       [,sasl][,password=<secret>][,disable-ticketing]\n"
+    "       [,image-compression=[auto_glz|auto_lz|quic|glz|lz|off]]\n"
+    "       [,jpeg-wan-compression=[auto|never|always]]\n"
+    "       [,zlib-glz-wan-compression=[auto|never|always]]\n"
+    "       [,streaming-video=[off|all|filter]][,disable-copy-paste]\n"
+    "       [,agent-mouse=[on|off]][,playback-compression=[on|off]]\n"
+    "       [,seamless-migration=[on|off]]\n"
+    "   enable spice\n"
+    "   at least one of {port, tls-port} is mandatory\n",
+    QEMU_ARCH_ALL)
 STEXI
 @item -spice @var{option}[, at var{option}[,...]]
 @findex -spice
commit 8c9570530c819821b9b5cc3113d2b2966afe7621
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Tue Aug 21 11:51:59 2012 +0300

    spice: adding seamless-migration option to the command line
    
    The seamless-migration flag is required in order to identify
    whether libvirt supports the new QEVENT_SPICE_MIGRATE_COMPLETED or not
    (by default the flag is off).
    New libvirt versions that wait for QEVENT_SPICE_MIGRATE_COMPLETED should turn on this flag.
    When this flag is off, spice fallbacks to its old migration method, which
    can result in data loss.
    
    Signed-off-by: Yonit Halperin <yhalperi at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qemu-config.c b/qemu-config.c
index c05ffbc..eba977e 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -537,6 +537,9 @@ QemuOptsList qemu_spice_opts = {
         },{
             .name = "playback-compression",
             .type = QEMU_OPT_BOOL,
+        }, {
+            .name = "seamless-migration",
+            .type = QEMU_OPT_BOOL,
         },
         { /* end of list */ }
     },
diff --git a/qemu-options.hx b/qemu-options.hx
index 3c411c4..96a7bb1 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -920,6 +920,9 @@ Enable/disable passing mouse events via vdagent.  Default is on.
 @item playback-compression=[on|off]
 Enable/disable audio stream compression (using celt 0.5.1).  Default is on.
 
+ at item seamless-migration=[on|off]
+Enable/disable spice seamless migration. Default is off.
+
 @end table
 ETEXI
 
diff --git a/ui/spice-core.c b/ui/spice-core.c
index ab069c5..ba0d0bd 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -585,6 +585,9 @@ void qemu_spice_init(void)
     int port, tls_port, len, addr_flags;
     spice_image_compression_t compression;
     spice_wan_compression_t wan_compr;
+#if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */
+    bool seamless_migration;
+#endif
 
     qemu_thread_get_self(&me);
 
@@ -728,6 +731,10 @@ void qemu_spice_init(void)
     spice_server_set_uuid(spice_server, qemu_uuid);
 #endif
 
+#if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */
+    seamless_migration = qemu_opt_get_bool(opts, "seamless-migration", 0);
+    spice_server_set_seamless_migration(spice_server, seamless_migration);
+#endif
     if (0 != spice_server_init(spice_server, &core_interface)) {
         error_report("failed to initialize spice server");
         exit(1);
commit 61c4efe2cb85b0a9c6bc68f6a2dd107c8d7ec080
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Tue Aug 21 11:51:58 2012 +0300

    spice: add 'migrated' flag to spice info
    
    The flag is 'true' when spice migration has completed on the src side.
    It is needed for a case where libvirt dies before migration completes
    and it misses the event QEVENT_SPICE_MIGRATE_COMPLETED.
    When libvirt is restored and queries the migration status, it also needs
    to query spice and check if its migration has completed.
    
    Signed-off-by: Yonit Halperin <yhalperi at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hmp.c b/hmp.c
index 81c8acb..ec4274b 100644
--- a/hmp.c
+++ b/hmp.c
@@ -413,6 +413,8 @@ void hmp_info_spice(Monitor *mon)
         monitor_printf(mon, "     address: %s:%" PRId64 " [tls]\n",
                        info->host, info->tls_port);
     }
+    monitor_printf(mon, "    migrated: %s\n",
+                   info->migrated ? "true" : "false");
     monitor_printf(mon, "        auth: %s\n", info->auth);
     monitor_printf(mon, "    compiled: %s\n", info->compiled_version);
     monitor_printf(mon, "  mouse-mode: %s\n",
diff --git a/qapi-schema.json b/qapi-schema.json
index bd8ad74..8ddde12 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -808,6 +808,9 @@
 #
 # @enabled: true if the SPICE server is enabled, false otherwise
 #
+# @migrated: true if the last guest migration completed and spice
+#            migration had completed as well. false otherwise.
+#
 # @host: #optional The hostname the SPICE server is bound to.  This depends on
 #        the name resolution on the host and may be an IP address.
 #
@@ -833,7 +836,7 @@
 # Since: 0.14.0
 ##
 { 'type': 'SpiceInfo',
-  'data': {'enabled': 'bool', '*host': 'str', '*port': 'int',
+  'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int',
            '*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str',
            'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']} }
 
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 851e869..ab069c5 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -46,6 +46,7 @@ static Notifier migration_state;
 static const char *auth = "spice";
 static char *auth_passwd;
 static time_t auth_expires = TIME_MAX;
+static int spice_migration_completed;
 int using_spice = 0;
 
 static QemuThread me;
@@ -310,6 +311,7 @@ static void migrate_connect_complete_cb(SpiceMigrateInstance *sin)
 static void migrate_end_complete_cb(SpiceMigrateInstance *sin)
 {
     monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL);
+    spice_migration_completed = true;
 }
 #endif
 
@@ -443,6 +445,7 @@ SpiceInfo *qmp_query_spice(Error **errp)
     }
 
     info->enabled = true;
+    info->migrated = spice_migration_completed;
 
     addr = qemu_opt_get(opts, "addr");
     port = qemu_opt_get_number(opts, "port", 0);
@@ -496,6 +499,7 @@ static void migration_state_notifier(Notifier *notifier, void *data)
 #ifndef SPICE_INTERFACE_MIGRATION
         spice_server_migrate_switch(spice_server);
         monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL);
+        spice_migration_completed = true;
 #else
         spice_server_migrate_end(spice_server, true);
     } else if (migration_has_failed(s)) {
commit 2fdd16e239c2a2763aa3266e637718123328688c
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Tue Aug 21 11:51:57 2012 +0300

    spice migration: add QEVENT_SPICE_MIGRATE_COMPLETED
    
    When migrating, libvirt queries the migration status, and upon migration
    completions, it closes the migration src. On the other hand, when
    migration is completed, spice transfers data from the src to destination
    via the client. This data is required for keeping the spice session
    after migration, without suffering from data loss and inconsistencies.
    In order to allow this data transfer, we add QEVENT for signaling
    libvirt that spice migration has completed, and libvirt needs to wait
    for this event before quitting the src process.
    
    Signed-off-by: Yonit Halperin <yhalperi at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/monitor.c b/monitor.c
index b17b1bb..413edf4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -455,6 +455,7 @@ static const char *monitor_event_names[] = {
     [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK",
     [QEVENT_WAKEUP] = "WAKEUP",
     [QEVENT_BALLOON_CHANGE] = "BALLOON_CHANGE",
+    [QEVENT_SPICE_MIGRATE_COMPLETED] = "SPICE_MIGRATE_COMPLETED",
 };
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
 
diff --git a/monitor.h b/monitor.h
index 47d556b..5fc2983 100644
--- a/monitor.h
+++ b/monitor.h
@@ -43,6 +43,7 @@ typedef enum MonitorEvent {
     QEVENT_SUSPEND_DISK,
     QEVENT_WAKEUP,
     QEVENT_BALLOON_CHANGE,
+    QEVENT_SPICE_MIGRATE_COMPLETED,
 
     /* Add to 'monitor_event_names' array in monitor.c when
      * defining new events here */
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 1a7a773..851e869 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -285,6 +285,7 @@ typedef struct SpiceMigration {
 } SpiceMigration;
 
 static void migrate_connect_complete_cb(SpiceMigrateInstance *sin);
+static void migrate_end_complete_cb(SpiceMigrateInstance *sin);
 
 static const SpiceMigrateInterface migrate_interface = {
     .base.type = SPICE_INTERFACE_MIGRATION,
@@ -292,7 +293,7 @@ static const SpiceMigrateInterface migrate_interface = {
     .base.major_version = SPICE_INTERFACE_MIGRATION_MAJOR,
     .base.minor_version = SPICE_INTERFACE_MIGRATION_MINOR,
     .migrate_connect_complete = migrate_connect_complete_cb,
-    .migrate_end_complete = NULL,
+    .migrate_end_complete = migrate_end_complete_cb,
 };
 
 static SpiceMigration spice_migrate;
@@ -305,6 +306,11 @@ static void migrate_connect_complete_cb(SpiceMigrateInstance *sin)
     }
     sm->connect_complete.cb = NULL;
 }
+
+static void migrate_end_complete_cb(SpiceMigrateInstance *sin)
+{
+    monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL);
+}
 #endif
 
 /* config string parsing */
@@ -489,6 +495,7 @@ static void migration_state_notifier(Notifier *notifier, void *data)
     } else if (migration_has_finished(s)) {
 #ifndef SPICE_INTERFACE_MIGRATION
         spice_server_migrate_switch(spice_server);
+        monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL);
 #else
         spice_server_migrate_end(spice_server, true);
     } else if (migration_has_failed(s)) {
commit 71d388d420e68ac77cd42f15f7e68cf5a6fb01b2
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Tue Aug 21 11:51:56 2012 +0300

    spice: notify on vm state change only via spice_server_vm_start/stop
    
    QXLWorker->start/stop are deprecated since spice-server 0.11.2
    
    Signed-off-by: Yonit Halperin <yhalperi at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index c2dd3b4..95bbc03 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -958,9 +958,10 @@ static void qxl_update_irq(PCIQXLDevice *d)
 static void qxl_check_state(PCIQXLDevice *d)
 {
     QXLRam *ram = d->ram;
+    int spice_display_running = qemu_spice_display_is_running(&d->ssd);
 
-    assert(!d->ssd.running || SPICE_RING_IS_EMPTY(&ram->cmd_ring));
-    assert(!d->ssd.running || SPICE_RING_IS_EMPTY(&ram->cursor_ring));
+    assert(!spice_display_running || SPICE_RING_IS_EMPTY(&ram->cmd_ring));
+    assert(!spice_display_running || SPICE_RING_IS_EMPTY(&ram->cursor_ring));
 }
 
 static void qxl_reset_state(PCIQXLDevice *d)
@@ -1538,7 +1539,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
     uint32_t old_pending;
     uint32_t le_events = cpu_to_le32(events);
 
-    assert(d->ssd.running);
+    assert(qemu_spice_display_is_running(&d->ssd));
     old_pending = __sync_fetch_and_or(&d->ram->int_pending, le_events);
     if ((old_pending & le_events) == le_events) {
         return;
diff --git a/ui/spice-core.c b/ui/spice-core.c
index a515c94..1a7a773 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -37,6 +37,7 @@
 #include "migration.h"
 #include "monitor.h"
 #include "hw/hw.h"
+#include "spice-display.h"
 
 /* core bits */
 
@@ -551,9 +552,11 @@ static void vm_change_state_handler(void *opaque, int running,
 {
 #if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */
     if (running) {
+        qemu_spice_display_start();
         spice_server_vm_start(spice_server);
     } else {
         spice_server_vm_stop(spice_server);
+        qemu_spice_display_stop();
     }
 #endif
 }
@@ -755,6 +758,7 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin)
         spice_server = spice_server_new();
         spice_server_init(spice_server, &core_interface);
     }
+
     return spice_server_add_interface(spice_server, sin);
 }
 
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 3e8f0b3..1c31418 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -126,18 +126,44 @@ void qemu_spice_wakeup(SimpleSpiceDisplay *ssd)
     ssd->worker->wakeup(ssd->worker);
 }
 
-void qemu_spice_start(SimpleSpiceDisplay *ssd)
+#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */
+static void qemu_spice_start(SimpleSpiceDisplay *ssd)
 {
     trace_qemu_spice_start(ssd->qxl.id);
     ssd->worker->start(ssd->worker);
 }
 
-void qemu_spice_stop(SimpleSpiceDisplay *ssd)
+static void qemu_spice_stop(SimpleSpiceDisplay *ssd)
 {
     trace_qemu_spice_stop(ssd->qxl.id);
     ssd->worker->stop(ssd->worker);
 }
 
+#else
+
+static int spice_display_is_running;
+
+void qemu_spice_display_start(void)
+{
+    spice_display_is_running = true;
+}
+
+void qemu_spice_display_stop(void)
+{
+    spice_display_is_running = false;
+}
+
+#endif
+
+int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd)
+{
+#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */
+    return ssd->running;
+#else
+    return spice_display_is_running;
+#endif
+}
+
 static SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
 {
     SimpleSpiceUpdate *update;
@@ -272,6 +298,7 @@ void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
 void qemu_spice_vm_change_state_handler(void *opaque, int running,
                                         RunState state)
 {
+#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */
     SimpleSpiceDisplay *ssd = opaque;
 
     if (running) {
@@ -281,6 +308,7 @@ void qemu_spice_vm_change_state_handler(void *opaque, int running,
         qemu_spice_stop(ssd);
         ssd->running = false;
     }
+#endif
 }
 
 void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds)
diff --git a/ui/spice-display.h b/ui/spice-display.h
index 12e50b6..672d65e 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -82,7 +82,9 @@ struct SimpleSpiceDisplay {
 
     QXLRect dirty;
     int notify;
+#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */
     int running;
+#endif
 
     /*
      * All struct members below this comment can be accessed from
@@ -129,5 +131,8 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
 void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
                                         uint32_t id, qxl_async_io async);
 void qemu_spice_wakeup(SimpleSpiceDisplay *ssd);
-void qemu_spice_start(SimpleSpiceDisplay *ssd);
-void qemu_spice_stop(SimpleSpiceDisplay *ssd);
+#if SPICE_SERVER_VERSION >= 0x000b02 /* before 0.11.2 */
+void qemu_spice_display_start(void);
+void qemu_spice_display_stop(void);
+#endif
+int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd);
commit f5bb039c6d97ef3e664094eab3c9a4dc1824ed73
Author: Yonit Halperin <yhalperi at redhat.com>
Date:   Tue Aug 21 11:51:55 2012 +0300

    spice: notify spice server on vm start/stop
    
    Spice server needs to know about the vm state in order to prevent
    attempts to write to devices when they are stopped, mainly during
    the non-live stage of migration.
    Instead, spice will take care of restoring this writes, on the migration
    target side, after migration completes.
    
    Signed-off-by: Yonit Halperin <yhalperi at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/spice-core.c b/ui/spice-core.c
index bb4f585..a515c94 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -546,6 +546,18 @@ static int add_channel(const char *name, const char *value, void *opaque)
     return 0;
 }
 
+static void vm_change_state_handler(void *opaque, int running,
+                                    RunState state)
+{
+#if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */
+    if (running) {
+        spice_server_vm_start(spice_server);
+    } else {
+        spice_server_vm_stop(spice_server);
+    }
+#endif
+}
+
 void qemu_spice_init(void)
 {
     QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
@@ -719,6 +731,8 @@ void qemu_spice_init(void)
     qemu_spice_input_init();
     qemu_spice_audio_init();
 
+    qemu_add_vm_change_state_handler(vm_change_state_handler, &spice_server);
+
     g_free(x509_key_file);
     g_free(x509_cert_file);
     g_free(x509_cacert_file);
commit 835cab85ad83ed8dfe1c13243aeda5959b153e3e
Author: Christophe Fergeau <cfergeau at redhat.com>
Date:   Mon Aug 13 10:32:32 2012 +0200

    spice: abort on invalid streaming cmdline params
    
    When parsing its command line parameters, spice aborts when it
    finds unexpected values, except for the 'streaming-video' option.
    This happens because the parsing of the parameters for this option
    is done using the 'name2enum' helper, which does not error out
    on unknown values. Using the 'parse_name' helper makes sure we
    error out in this case. Looking at git history, the use of
    'name2enum' instead of 'parse_name' seems to have been an oversight,
    so let's change to that now.
    
    Fixes rhbz#831708
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/spice-core.c b/ui/spice-core.c
index 4fc48f8..bb4f585 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -344,7 +344,8 @@ static const char *stream_video_names[] = {
     [ SPICE_STREAM_VIDEO_FILTER ] = "filter",
 };
 #define parse_stream_video(_name) \
-    name2enum(_name, stream_video_names, ARRAY_SIZE(stream_video_names))
+    parse_name(_name, "stream video control", \
+               stream_video_names, ARRAY_SIZE(stream_video_names))
 
 static const char *compression_names[] = {
     [ SPICE_IMAGE_COMPRESS_OFF ]      = "off",


More information about the Spice-commits mailing list