]> git.proxmox.com Git - qemu.git/commitdiff
Merge branch 'queue/qmp' of git://repo.or.cz/qemu/qmp-unstable
authorAurelien Jarno <aurelien@aurel32.net>
Mon, 10 Sep 2012 13:04:36 +0000 (15:04 +0200)
committerAurelien Jarno <aurelien@aurel32.net>
Mon, 10 Sep 2012 13:04:36 +0000 (15:04 +0200)
* '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

29 files changed:
MAINTAINERS
configure
hw/elf_ops.h
hw/lan9118.c
hw/mcf5206.c
hw/musicpal.c
hw/pl110.c
hw/pl110_template.h
hw/wm8750.c
scripts/checkpatch.pl
target-arm/helper.c
target-cris/translate.c
target-mips/cpu.h
target-mips/op_helper.c
target-mips/translate.c
target-s390x/Makefile.objs
target-s390x/cc_helper.c [new file with mode: 0644]
target-s390x/cpu.h
target-s390x/fpu_helper.c [new file with mode: 0644]
target-s390x/helper.c
target-s390x/helper.h
target-s390x/int_helper.c [new file with mode: 0644]
target-s390x/mem_helper.c [new file with mode: 0644]
target-s390x/misc_helper.c [new file with mode: 0644]
target-s390x/op_helper.c [deleted file]
target-s390x/translate.c
target-sparc/fop_helper.c
target-xtensa/xtensa-semi.c
tcg/s390/tcg-target.c

index 6d864c1ceb933d362a602c44d7c1942979b4a62b..61f8b45cb5d9dbd474fb374de6af944a232b8b2d 100644 (file)
@@ -398,6 +398,12 @@ M: Blue Swirl <blauwirbel@gmail.com>
 S: Maintained
 F: hw/sun4u.c
 
+Leon3
+M: Fabien Chouteau <chouteau@adacore.com>
+S: Maintained
+F: hw/leon3.c
+F: hw/grlib*
+
 S390 Machines
 -------------
 S390 Virtio
index d97fd817096fa51e82b4f22e49ceeef6c9515300..a88a4659b745a07f7ddbeddcdeae83af316bcf65 100755 (executable)
--- 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
index fa65ce2f9306e3adc36c48dd8cde1aa0ef1a9603..731a983854bce7fa375e3cc473067c8e70743619 100644 (file)
@@ -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);
 
index ff0a50be19604cf7758f632f5084b02a7550af3f..ceaf96fc3eed3d347a6e6f865f0a84a7c522cdcf 100644 (file)
@@ -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 {
index 539b39133803654385eace1c284d1b7e605c2123..27753e2717b36f12e8a16ee75a02c8c7751bf399 100644 (file)
@@ -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];
index ad725b559981aaed58a501d399a65ff5223648a2..f305e21038fde4e216fe00e0fcf70da5a729a359 100644 (file)
@@ -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,
index f94608cb62b222096f1f08edef27aa692276141d..a5826407aba07f080d186d62f4cf29ae294d594f 100644 (file)
@@ -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) {
index 1dce32a0c3494a69d19aeecb2fd619242b118a1b..e738e4a241bf2eb268db26feb9f1edc7b17f356d 100644 (file)
@@ -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)
index 11bcec34106ee99145d09ffcdf9c4c1ada61484f..44f138fd51dc5927889f7f143f7065bacd9113ee 100644 (file)
@@ -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)
index b98dc6cad198f74c4ba3fe334b0a378d78a5cf35..ec0aa4cd935333d4ce3d1d8c3786c5a802165ebe 100755 (executable)
@@ -97,6 +97,9 @@ my $dbg_values = 0;
 my $dbg_possible = 0;
 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}';";
@@ -2486,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;
@@ -2512,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)) {
@@ -2537,32 +2547,41 @@ sub process {
                                        $line !~ /\#\s*else/) {
                        my $allowed = 0;
 
-                       # Check the pre-context.
-                       if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
-                               #print "APW: ALLOWED: pre<$1>\n";
-                               $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]);
 
                        # 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), '');
                        }
                        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]) {
@@ -2571,10 +2590,13 @@ 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"
+                            if $dbg_adv_dcs;
                        if ($level == 0 && $block !~ /^\s*\{/ && !$allowed) {
                                my $herectx = $here . "\n";;
                                my $cnt = statement_rawlines($block);
index dceaa95c80272217ad94649134e3f586f35191f4..e27df96272c71c1562984720bf29dd46b66df66c 100644 (file)
@@ -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;
index 1ad9ec788e53d7c72ebc825a9b89d0a2daf237aa..ad3187773e1023c72f5ed1a6310b42842407fefd 100644 (file)
@@ -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]);
index ce3467f14047526673e136eeb9cc537bbb1a7c23..88d92f1182582ad2a3c2c193d99984286ee0c04f 100644 (file)
@@ -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__) */
index e5bc93e2265f9f15369133b1a5de03e9697a9369..3d242aafda466d90aa58eeaabb48cbf9d0f1d368 100644 (file)
 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 */
 
index b29341953622c0464d7f8043ce52db64ba02c972..a884f751bcf6453a4c510d0490ca26748d1a13db 100644 (file)
@@ -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;
 }
 
index 80be3bbdb27c5a6d571c99b26fa5d51480ee9a65..e728abf7598312f2e54744e33bb0eec4b7d7da76 100644 (file)
@@ -1,5 +1,4 @@
-obj-y += translate.o op_helper.o helper.o cpu.o interrupt.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)
diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
new file mode 100644 (file)
index 0000000..19ef145
--- /dev/null
@@ -0,0 +1,550 @@
+/*
+ *  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 "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(env, src, dst);
+        break;
+    case CC_OP_LTGT_F64:
+        r = set_cc_f64(env, 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)(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)(CPUS390XState *env, 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)(CPUS390XState *env, uint64_t mask, uint64_t addr)
+{
+    load_psw(env, mask, addr);
+    cpu_loop_exit(env);
+}
+
+void HELPER(sacf)(CPUS390XState *env, 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
index 18ac6e3938ea4f426290168a39d4f3f2b34471b8..ed81af33a16830d5e348d2a2cba36806c8a16e46 100644 (file)
@@ -999,4 +999,13 @@ static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb)
     env->psw.addr = tb->pc;
 }
 
+/* fpu_helper.c */
+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);
+
 #endif
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
new file mode 100644 (file)
index 0000000..ee9420d
--- /dev/null
@@ -0,0 +1,843 @@
+/*
+ *  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 "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(CPUS390XState *env, 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(CPUS390XState *env, float32 v1, float32 v2)
+{
+    return float_comp_to_cc(env, float32_compare_quiet(v1, v2,
+                                                       &env->fpu_status));
+}
+
+uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2)
+{
+    return float_comp_to_cc(env, 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)(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)(CPUS390XState *env, 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)(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)(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)(CPUS390XState *env, 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)(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,
+               env->fregs[f1].l.upper, f1);
+}
+
+/* 32-bit FP addition RR */
+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,
+                                         &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)(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);
+    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)(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,
+                                         &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)(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);
+    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)(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,
+                                         &env->fpu_status);
+}
+
+/* 128-bit FP division RR */
+void HELPER(dxbr)(CPUS390XState *env, 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)(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)(CPUS390XState *env, 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)(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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(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)(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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(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(env, v1, v2);
+}
+
+/* 64-bit FP compare RR */
+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(env, v1, v2);
+}
+
+/* 128-bit FP compare RR */
+uint32_t HELPER(cxbr)(CPUS390XState *env, 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(env, float128_compare_quiet(v1.q, v2.q,
+                                                   &env->fpu_status));
+}
+
+/* 64-bit FP compare RM */
+uint32_t HELPER(cdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
+{
+    float64 v1 = env->fregs[f1].d;
+    CPU_DoubleU v2;
+
+    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(env, v1, v2.d);
+}
+
+/* 64-bit FP addition RM */
+uint32_t HELPER(adb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
+{
+    float64 v1 = env->fregs[f1].d;
+    CPU_DoubleU v2;
+
+    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);
+    return set_cc_nz_f64(v1);
+}
+
+/* 32-bit FP subtraction RM */
+void HELPER(seb)(CPUS390XState *env, 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)(CPUS390XState *env, uint32_t f1, uint64_t a2)
+{
+    float64 v1 = env->fregs[f1].d;
+    CPU_DoubleU v2;
+
+    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)(CPUS390XState *env, uint32_t f1, uint64_t a2)
+{
+    float64 v1 = env->fregs[f1].d;
+    CPU_DoubleU v2;
+
+    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)(CPUS390XState *env, uint32_t f1, uint64_t a2)
+{
+    float64 v1 = env->fregs[f1].d;
+    CPU_DoubleU v2;
+
+    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(CPUS390XState *env, 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)(CPUS390XState *env, uint32_t r1, uint32_t f2,
+                       uint32_t m3)
+{
+    float32 v2 = env->fregs[f2].l.upper;
+
+    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)(CPUS390XState *env, uint32_t r1, uint32_t f2,
+                       uint32_t m3)
+{
+    float64 v2 = env->fregs[f2].d;
+
+    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)(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(env, 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)(CPUS390XState *env, uint32_t r1, uint32_t f2,
+                       uint32_t m3)
+{
+    float32 v2 = env->fregs[f2].l.upper;
+
+    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)(CPUS390XState *env, uint32_t r1, uint32_t f2,
+                       uint32_t m3)
+{
+    float64 v2 = env->fregs[f2].d;
+
+    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)(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;
+    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)(CPUS390XState *env, uint32_t f1)
+{
+    env->fregs[f1].l.upper = float32_zero;
+}
+
+/* load 64-bit FP zero */
+void HELPER(lzdr)(CPUS390XState *env, uint32_t f1)
+{
+    env->fregs[f1].d = float64_zero;
+}
+
+/* load 128-bit FP zero */
+void HELPER(lzxr)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(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,
+                                         &env->fpu_status);
+}
+
+/* 64-bit FP division RR */
+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)(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 = 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),
+                                   &env->fpu_status);
+}
+
+/* 64-bit FP multiply and add RR */
+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,
+                                               env->fregs[f3].d,
+                                               &env->fpu_status),
+                                   env->fregs[f1].d, &env->fpu_status);
+}
+
+/* 64-bit FP multiply and subtract RR */
+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,
+                                               env->fregs[f3].d,
+                                               &env->fpu_status),
+                                   env->fregs[f1].d, &env->fpu_status);
+}
+
+/* 32-bit FP multiply and add RR */
+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,
+                                                     env->fregs[f3].l.upper,
+                                                     &env->fpu_status),
+                                         &env->fpu_status);
+}
+
+/* convert 32-bit float to 64-bit float */
+void HELPER(ldeb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
+{
+    uint32_t v2;
+
+    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)(CPUS390XState *env, uint32_t f1, uint64_t a2)
+{
+    CPU_DoubleU v2;
+    CPU_QuadU v1;
+
+    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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+{
+    env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
+}
index d0a1180a83404243ed6d7ac4e62b4b83230f047d..a5741ecde1a4d4c888d4712fa7673877b3462066 100644 (file)
@@ -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;
@@ -497,19 +499,19 @@ 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;
     }
 
-    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);
index 01c8d0ea84f2bc44abf24b6148e2e237203e3fcb..5419f37dca436a42a058ebcd6d572a51adf502af 100644 (file)
@@ -1,19 +1,19 @@
 #include "def-helper.h"
 
-DEF_HELPER_1(exception, void, 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_2(exception, void, env, 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_2(mlg, void, i32, i64)
-DEF_HELPER_2(dlg, void, 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)
 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)
@@ -22,131 +22,131 @@ 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_2(ipm, void, i32, 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_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_2(flogr, i32, i32, i64)
-DEF_HELPER_2(sqdbr, void, i32, 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)
+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_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_2(servc, i32, i32, i64)
-DEF_HELPER_3(diag, i64, i32, i64, i64)
-DEF_HELPER_2(load_psw, void, 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_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_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_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_3(sigp, i32, i64, i32, i64)
-DEF_HELPER_1(sacf, void, 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_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_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_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/int_helper.c b/target-s390x/int_helper.c
new file mode 100644 (file)
index 0000000..f202a7e
--- /dev/null
@@ -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 "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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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/mem_helper.c b/target-s390x/mem_helper.c
new file mode 100644 (file)
index 0000000..b21b37c
--- /dev/null
@@ -0,0 +1,1203 @@
+/*
+ *  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 "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 *env, target_ulong addr, int is_write, int mmu_idx,
+              uintptr_t retaddr)
+{
+    TranslationBlock *tb;
+    int ret;
+
+    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);
+    }
+}
+
+#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)) {
+        cpu_stb_data(env, 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)) {
+        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)) {
+        cpu_ldub_data(env, 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)(CPUS390XState *env, 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 = cpu_ldub_data(env, dest + i) & cpu_ldub_data(env, src + i);
+        if (x) {
+            cc = 1;
+        }
+        cpu_stb_data(env, dest + i, x);
+    }
+    return cc;
+}
+
+/* xor on array */
+uint32_t HELPER(xc)(CPUS390XState *env, 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 = cpu_ldub_data(env, dest + i) ^ cpu_ldub_data(env, src + i);
+        if (x) {
+            cc = 1;
+        }
+        cpu_stb_data(env, dest + i, x);
+    }
+    return cc;
+}
+
+/* or on array */
+uint32_t HELPER(oc)(CPUS390XState *env, 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 = cpu_ldub_data(env, dest + i) | cpu_ldub_data(env, src + i);
+        if (x) {
+            cc = 1;
+        }
+        cpu_stb_data(env, dest + i, x);
+    }
+    return cc;
+}
+
+/* memmove */
+void HELPER(mvc)(CPUS390XState *env, 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, cpu_ldub_data(env, 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), cpu_ldub_data(env, 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++) {
+            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++) {
+        cpu_stb_data(env, dest + i, cpu_ldub_data(env, src + i));
+    }
+}
+
+/* compare unsigned byte arrays */
+uint32_t HELPER(clc)(CPUS390XState *env, 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 = 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;
+            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)(CPUS390XState *env, 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 = cpu_ldub_data(env, 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)(CPUS390XState *env, 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;
+            cpu_stb_data(env, 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(CPUS390XState *env, 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(CPUS390XState *env, 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)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
+{
+    uint64_t i;
+    uint32_t cc = 2;
+    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 (cpu_ldub_data(env, i) == c) {
+            env->regs[r1] = i;
+            cc = 1;
+            break;
+        }
+    }
+
+    return cc;
+}
+
+/* unsigned string compare (c is string terminator) */
+uint32_t HELPER(clst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
+{
+    uint64_t s1 = get_address_31fix(env, r1);
+    uint64_t s2 = get_address_31fix(env, 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 = cpu_ldub_data(env, s1);
+        v2 = cpu_ldub_data(env, 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)(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++) {
+        cpu_stb_data(env, r1 + i, cpu_ldub_data(env, r2 + i));
+    }
+#else
+    mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2);
+#endif
+}
+
+/* string copy (c is string terminator) */
+void HELPER(mvst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
+{
+    uint64_t dest = get_address_31fix(env, r1);
+    uint64_t src = get_address_31fix(env, 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 = cpu_ldub_data(env, src);
+        cpu_stb_data(env, 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)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    /* FIXME: locking? */
+    uint32_t cc;
+    uint64_t v2 = cpu_ldq_data(env, a2);
+
+    if (env->regs[r1] == v2) {
+        cc = 0;
+        cpu_stq_data(env, a2, env->regs[r3]);
+    } else {
+        cc = 1;
+        env->regs[r1] = v2;
+    }
+    return cc;
+}
+
+/* compare double and swap 64-bit */
+uint32_t HELPER(cdsg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    /* FIXME: locking? */
+    uint32_t cc;
+    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;
+        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;
+        env->regs[r1 + 1] = v2_lo;
+    }
+
+    return cc;
+}
+
+/* compare and swap 32-bit */
+uint32_t HELPER(cs)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    /* FIXME: locking? */
+    uint32_t cc;
+    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;
+        cpu_stl_data(env, a2, (uint32_t)env->regs[r3]);
+    } else {
+        cc = 1;
+        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2;
+    }
+    return cc;
+}
+
+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;
+    uint8_t val = 0;
+    int ccd = 0;
+    uint32_t cc = 0;
+
+    while (mask) {
+        if (mask & 8) {
+            env->regs[r1] &= ~rmask;
+            val = cpu_ldub_data(env, 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)(CPUS390XState *env, uint32_t cc, uint64_t v1,
+                    uint64_t addr, uint64_t ret)
+{
+    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);
+    if ((insn & 0xf0ff) == 0xd000) {
+        uint32_t l, insn2, b1, b2, d1, d2;
+
+        l = v1 & 0xff;
+        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(env, l, get_address(env, 0, b1, d1),
+                       get_address(env, 0, b2, d2));
+            break;
+        case 0x500:
+            cc = helper_clc(env, l, get_address(env, 0, b1, d1),
+                            get_address(env, 0, b2, d2));
+            break;
+        case 0x700:
+            cc = helper_xc(env, l, get_address(env, 0, b1, d1),
+                           get_address(env, 0, b2, d2));
+            break;
+        case 0xc00:
+            helper_tr(env, l, get_address(env, 0, b1, d1),
+                      get_address(env, 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(env, EXCP_SVC);
+    } else if ((insn & 0xff00) == 0xbf00) {
+        uint32_t insn2, r1, r3, b2, d2;
+
+        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(env, r1, get_address(env, 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)(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) {
+            cpu_stb_data(env, 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)(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;
+    uint8_t val = 0;
+    int ccd = 0;
+    uint32_t cc = 0;
+
+    while (mask) {
+        if (mask & 8) {
+            env->regs[r1] &= ~rmask;
+            val = cpu_ldub_data(env, 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)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    int i;
+
+    for (i = r1;; i = (i + 1) % 16) {
+        env->aregs[i] = cpu_ldl_data(env, a2);
+        a2 += 4;
+
+        if (i == r3) {
+            break;
+        }
+    }
+}
+
+/* store access registers r1 to r3 in memory at a2 */
+void HELPER(stam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
+{
+    int i;
+
+    for (i = r1;; i = (i + 1) % 16) {
+        cpu_stl_data(env, a2, env->aregs[i]);
+        a2 += 4;
+
+        if (i == r3) {
+            break;
+        }
+    }
+}
+
+/* move long */
+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(env, r1);
+    uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
+    uint64_t src = get_address_31fix(env, 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 = cpu_ldub_data(env, src);
+        cpu_stb_data(env, dest, v);
+    }
+
+    for (; destlen; dest++, destlen--) {
+        cpu_stb_data(env, 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)(CPUS390XState *env, 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 = cpu_ldub_data(env, src);
+        cpu_stb_data(env, dest, v);
+    }
+
+    for (; destlen; dest++, destlen--) {
+        cpu_stb_data(env, 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)(CPUS390XState *env, uint32_t r1, uint64_t a2,
+                       uint32_t r3)
+{
+    uint64_t destlen = env->regs[r1 + 1];
+    uint64_t dest = get_address_31fix(env, r1);
+    uint64_t srclen = env->regs[r3 + 1];
+    uint64_t src = get_address_31fix(env, 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 ? cpu_ldub_data(env, src) : pad;
+        v2 = destlen ? cpu_ldub_data(env, 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)(CPUS390XState *env, uint32_t r1, uint32_t 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 += cpu_ldl_data(env, src);
+
+        /* move to next word */
+        src_len -= 4;
+        src += 4;
+    }
+
+    switch (src_len) {
+    case 0:
+        break;
+    case 1:
+        cksm += cpu_ldub_data(env, src) << 24;
+        break;
+    case 2:
+        cksm += cpu_lduw_data(env, src) << 16;
+        break;
+    case 3:
+        cksm += cpu_lduw_data(env, src) << 16;
+        cksm += cpu_ldub_data(env, 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)(CPUS390XState *env, 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 = cpu_ldub_data(env, src);
+    cpu_stb_data(env, 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 = cpu_ldub_data(env, 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;
+
+        cpu_stb_data(env, dest, cur_byte);
+    }
+}
+
+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 = cpu_ldub_data(env, array + i);
+        uint8_t new_byte = cpu_ldub_data(env, trans + byte);
+
+        cpu_stb_data(env, array + i, new_byte);
+    }
+}
+
+#if !defined(CONFIG_USER_ONLY)
+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] = 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);
+
+        if (i == r3) {
+            break;
+        }
+    }
+
+    tlb_flush(env, 1);
+}
+
+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) |
+            cpu_ldl_data(env, src);
+        src += sizeof(uint32_t);
+
+        if (i == r3) {
+            break;
+        }
+    }
+
+    tlb_flush(env, 1);
+}
+
+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) {
+        cpu_stq_data(env, dest, env->cregs[i]);
+        dest += sizeof(uint64_t);
+
+        if (i == r3) {
+            break;
+        }
+    }
+}
+
+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) {
+        cpu_stl_data(env, 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)(CPUS390XState *env, uint64_t r2)
+{
+    uint64_t addr = get_address(env, 0, 0, r2);
+
+    if (addr > ram_size) {
+        return 0;
+    }
+
+    return env->storage_keys[addr / TARGET_PAGE_SIZE];
+}
+
+/* set storage key extended */
+void HELPER(sske)(CPUS390XState *env, uint32_t r1, uint64_t r2)
+{
+    uint64_t addr = get_address(env, 0, 0, r2);
+
+    if (addr > ram_size) {
+        return;
+    }
+
+    env->storage_keys[addr / TARGET_PAGE_SIZE] = r1;
+}
+
+/* reset reference bit extended */
+uint32_t HELPER(rrbe)(CPUS390XState *env, 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)(CPUS390XState *env, uint32_t r1, uint32_t r2)
+{
+    uint32_t cc;
+    uint32_t o1 = env->regs[r1];
+    uint64_t a2 = get_address_31fix(env, r2) & ~3ULL;
+    uint32_t o2 = cpu_ldl_data(env, a2);
+
+    if (o1 == o2) {
+        cpu_stl_data(env, 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(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;
+
+    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(env, l - i, a1 + i, mode1, a2 + i, mode2);
+            break;
+        }
+        stb_phys(dest + i, ldub_phys(src + i));
+    }
+
+    return cc;
+}
+
+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(env, l, a1, PSW_ASC_SECONDARY, a2, PSW_ASC_PRIMARY);
+}
+
+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(env, l, a1, PSW_ASC_PRIMARY, a2, PSW_ASC_SECONDARY);
+}
+
+/* invalidate pte */
+void HELPER(ipte)(CPUS390XState *env, 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)(CPUS390XState *env)
+{
+    tlb_flush(env, 1);
+}
+
+/* store using real address */
+void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint32_t v1)
+{
+    stw_phys(get_address(env, 0, 0, addr), v1);
+}
+
+/* load real address */
+uint32_t HELPER(lra)(CPUS390XState *env, 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/misc_helper.c b/target-s390x/misc_helper.c
new file mode 100644 (file)
index 0000000..2938ac9
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ *  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 "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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, 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)(CPUS390XState *env, uint64_t a1)
+{
+    cpu_stq_data(env, a1, env->cpu_num);
+}
+
+/* Set Prefix */
+void HELPER(spx)(CPUS390XState *env, uint64_t a1)
+{
+    uint32_t prefix;
+
+    prefix = cpu_ldl_data(env, 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)(CPUS390XState *env, uint64_t a1)
+{
+    cpu_stq_data(env, a1, clock_value(env));
+
+    return 0;
+}
+
+/* Store Clock Extended */
+uint32_t HELPER(stcke)(CPUS390XState *env, uint64_t a1)
+{
+    cpu_stb_data(env, a1, 0);
+    /* basically the same value as stck */
+    cpu_stq_data(env, a1 + 1, clock_value(env) | env->cpu_num);
+    /* more fine grained than stck */
+    cpu_stq_data(env, a1 + 9, 0);
+    /* XXX programmable fields */
+    cpu_stw_data(env, a1 + 17, 0);
+
+    return 0;
+}
+
+/* Set Clock Comparator */
+void HELPER(sckc)(CPUS390XState *env, uint64_t a1)
+{
+    uint64_t time = cpu_ldq_data(env, 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)(CPUS390XState *env, uint64_t a1)
+{
+    /* XXX implement */
+    cpu_stq_data(env, a1, 0);
+}
+
+/* Set CPU Timer */
+void HELPER(spt)(CPUS390XState *env, uint64_t a1)
+{
+    uint64_t time = cpu_ldq_data(env, 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)(CPUS390XState *env, uint64_t a1)
+{
+    /* XXX implement */
+    cpu_stq_data(env, a1, 0);
+}
+
+/* Store System Information */
+uint32_t HELPER(stsi)(CPUS390XState *env, 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)(CPUS390XState *env, 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 (file)
index abc35dd..0000000
+++ /dev/null
@@ -1,3019 +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 "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;
-}
-
-#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", __FUNCTION__, excp);
-    env->exception_index = excp;
-    cpu_loop_exit(env);
-}
-
-#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",
-               __FUNCTION__, 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",
-               __FUNCTION__, 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",
-               __FUNCTION__, 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",
-               __FUNCTION__, 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",
-               __FUNCTION__, 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", __FUNCTION__, 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", __FUNCTION__, 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");
-}
-
-/* 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;
-        env->regs[r1+1] = quotient;
-        __uint128_t remainder = dividend % divisor;
-        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;
-
-    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", __FUNCTION__,
-               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",
-                   __FUNCTION__, (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", __FUNCTION__, (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;
-    HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __FUNCTION__, r1, a2, r3);
-    uint32_t v2 = ldl(a2);
-    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", __FUNCTION__, 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", __FUNCTION__, (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;
-}
-
-/* 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", __FUNCTION__, 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)
-{
-    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;
-}
-
-/* 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", __FUNCTION__,
-               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)
-{
-    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;
-}
-
-/* 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;
-    }
-}
-
-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", __FUNCTION__, 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", __FUNCTION__, 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);
-    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", __FUNCTION__, 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", __FUNCTION__, 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", __FUNCTION__,
-               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", __FUNCTION__,
-               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", __FUNCTION__,
-               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",
-               __FUNCTION__, 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;
-    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;
-}
-
-/* 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;
-    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;
-}
-
-/* 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", __FUNCTION__, 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", __FUNCTION__, 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", __FUNCTION__,
-               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", __FUNCTION__,
-               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", __FUNCTION__,
-               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", __FUNCTION__,
-               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", __FUNCTION__,
-               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;
-    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));
-}
-
-/* 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", __FUNCTION__, 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", __FUNCTION__,
-               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", __FUNCTION__,
-               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", __FUNCTION__,
-               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;
-    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;
-    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;
-    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;
-    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)
-{
-    HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __FUNCTION__, f1, a2, f3);
-    CPU_DoubleU v2;
-    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", __FUNCTION__, 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", __FUNCTION__, 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;
-    v2.ll = ldq(a2);
-    CPU_QuadU v1;
-    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", __FUNCTION__, (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", __FUNCTION__, 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;
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
-
-    int 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)
-{
-    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;
-    }
-}
-
-/* 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)
-{
-    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));
-}
-
-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)
-{
-    HELPER_LOG("%s: val 0x%x mask 0x%x\n", __FUNCTION__, val, mask);
-    uint16_t r = 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", __FUNCTION__, 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)
-{
-    HELPER_LOG("%s: mask 0x%x val %d\n", __FUNCTION__, mask, val);
-    uint32_t cc;
-
-    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", __FUNCTION__,
-               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 */
-    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;
-    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 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)
-{
-    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;
-}
-
-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",
-               __FUNCTION__, 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",
-               __FUNCTION__, 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;
-
-    HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
-               __FUNCTION__, 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;
-}
-
-void HELPER(sacf)(uint64_t a1)
-{
-    HELPER_LOG("%s: %16" PRIx64 "\n", __FUNCTION__, 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)
-{
-    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
index 1c1baf53425a9326f466bad0906bdf8751052c29..66119cd122706699dc23c896d2ebea29e2a06bbe 100644 (file)
@@ -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;
 }
 
@@ -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 */
@@ -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)
 {
@@ -727,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:
@@ -740,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:
@@ -751,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();
@@ -1268,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;
     }
@@ -1460,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);
 }
@@ -1808,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;
@@ -1816,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;
@@ -1842,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);
@@ -1922,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);
@@ -2099,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);
@@ -2112,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);
@@ -2124,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);
@@ -2136,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);
@@ -2148,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);
@@ -2188,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);
@@ -2211,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();
@@ -2230,12 +2225,12 @@ 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);
 
         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] */
@@ -2243,12 +2238,12 @@ 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);
 
         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] */
@@ -2256,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] */
@@ -2280,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:
@@ -2633,14 +2628,14 @@ 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] */
         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);
@@ -2669,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);
@@ -2681,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);
@@ -2692,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);
@@ -2703,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);
@@ -2717,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] */
@@ -2735,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;
@@ -2745,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] */
@@ -2754,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] */
@@ -2763,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] */
@@ -2772,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] */
@@ -2790,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 */
@@ -2798,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] */
@@ -2833,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;
@@ -2844,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);
@@ -2856,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);
@@ -2868,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;
@@ -2885,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;
@@ -2896,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);
@@ -2911,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;
@@ -2921,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;
@@ -2935,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);
@@ -2972,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);
@@ -2985,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);
@@ -3006,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);
@@ -3085,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();
@@ -3143,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] */
@@ -3174,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();
@@ -3196,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();
@@ -3218,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();
@@ -3232,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;
@@ -3240,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);
@@ -3250,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);
@@ -3260,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);
@@ -3540,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);
@@ -3560,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;
@@ -3585,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);
@@ -3652,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);
@@ -3870,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);
@@ -3931,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);
@@ -3956,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);
@@ -4170,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);
@@ -4532,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);
@@ -4548,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);
@@ -4699,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);
@@ -4711,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);
@@ -4737,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);
@@ -4750,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);
@@ -4782,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);
@@ -4794,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);
@@ -4840,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);
@@ -4854,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);
@@ -4874,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);
@@ -4887,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);
@@ -4900,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);
@@ -4997,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:
@@ -5005,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();
@@ -5045,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);
index 9c64ef89fe2368e280bbe7ecc62ef538428988a2..f4b62a5ba28b2ca59552e34138ea7fe63cb7a7c5 100644 (file)
@@ -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:                                                        \
index 6d001c2c1aa2d1d53fa109235fd5b31078ff327c..52be07a368e076e18d271604af117542c7555400 100644 (file)
@@ -54,6 +54,102 @@ 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,
+#ifdef ENOTBLK
+        [ENOTBLK]       = TARGET_ENOTBLK,
+#endif
+        [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,
+#ifdef ETXTBSY
+        [ETXTBSY]       = TARGET_ETXTBSY,
+#endif
+        [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,
+#ifdef ELOOP
+        [ELOOP]         = TARGET_ELOOP,
+#endif
+    };
+
+    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 +183,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 +213,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 +226,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 +259,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 +315,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;
     }
 }
index 04662c15fd70623629d42d8850a04b0286a7906c..99b53390c5b783417a2aed3666eacd3af4586f08 100644 (file)
@@ -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]);