@@ -0,0 +1,4750 @@
+Currently only does userspace with 64-bit addressing, but it's quite good
+at that.
+
+Signed-off-by: Ulrich Hecht <uli@suse.de>
+---
+ cpu-exec.c | 42 +
+ disas.c | 3 +
+ s390-dis.c | 4 +-
+ target-s390x/cpu.h | 131 +++
+ target-s390x/exec.h | 51 +
+ target-s390x/helper.c | 81 ++
+ target-s390x/helpers.h | 128 +++
+ target-s390x/op_helper.c | 1719 ++++++++++++++++++++++++++++++++
+ target-s390x/translate.c | 2479 ++++++++++++++++++++++++++++++++++++++++++++++
+ 9 files changed, 4636 insertions(+), 2 deletions(-)
+ create mode 100644 target-s390x/cpu.h
+ create mode 100644 target-s390x/exec.h
+ create mode 100644 target-s390x/helper.c
+ create mode 100644 target-s390x/helpers.h
+ create mode 100644 target-s390x/op_helper.c
+ create mode 100644 target-s390x/translate.c
+
+diff --git a/cpu-exec.c b/cpu-exec.c
+index 2385d56..855ea3e 100644
+--- a/cpu-exec.c
++++ b/cpu-exec.c
+@@ -249,6 +249,7 @@ int cpu_exec(CPUState *env1)
+ #elif defined(TARGET_MIPS)
+ #elif defined(TARGET_SH4)
+ #elif defined(TARGET_CRIS)
++#elif defined(TARGET_S390X)
+ /* XXXXX */
+ #else
+ #error unsupported target CPU
+@@ -712,6 +713,7 @@ int cpu_exec(CPUState *env1)
+ #elif defined(TARGET_SH4)
+ #elif defined(TARGET_ALPHA)
+ #elif defined(TARGET_CRIS)
++#elif defined(TARGET_S390X)
+ /* XXXXX */
+ #else
+ #error unsupported target CPU
+@@ -1234,6 +1236,46 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+ return 1;
+ }
+
++#elif defined (TARGET_S390X)
++static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
++ int is_write, sigset_t *old_set,
++ void *puc)
++{
++ TranslationBlock *tb;
++ int ret;
++
++ if (cpu_single_env)
++ env = cpu_single_env; /* XXX: find a correct solution for multithread */
++#if defined(DEBUG_SIGNAL)
++ printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
++ pc, address, is_write, *(unsigned long *)old_set);
++#endif
++ /* XXX: locking issue */
++ if (is_write && page_unprotect(h2g(address), pc, puc)) {
++ return 1;
++ }
++
++ /* see if it is an MMU fault */
++ ret = cpu_s390x_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
++ if (ret < 0)
++ return 0; /* not an MMU fault */
++ if (ret == 0)
++ return 1; /* the MMU fault was handled without causing real CPU fault */
++
++ /* now we have a real cpu fault */
++ tb = tb_find_pc(pc);
++ if (tb) {
++ /* the PC is inside the translated code. It means that we have
++ a virtual CPU fault */
++ cpu_restore_state(tb, env, pc, puc);
++ }
++ /* we restore the process signal mask as the sigreturn should
++ do it (XXX: use sigsetjmp) */
++ sigprocmask(SIG_SETMASK, old_set, NULL);
++ cpu_loop_exit();
++ /* never comes here */
++ return 1;
++}
+ #else
+ #error unsupported target CPU
+ #endif
+diff --git a/disas.c b/disas.c
+index af5a9ea..da5b1a5 100644
+--- a/disas.c
++++ b/disas.c
+@@ -195,6 +195,9 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
+ #elif defined(TARGET_CRIS)
+ disasm_info.mach = bfd_mach_cris_v32;
+ print_insn = print_insn_crisv32;
++#elif defined(TARGET_S390X)
++ disasm_info.mach = bfd_mach_s390_64;
++ print_insn = print_insn_s390;
+ #elif defined(TARGET_MICROBLAZE)
+ disasm_info.mach = bfd_arch_microblaze;
+ print_insn = print_insn_microblaze;
+diff --git a/s390-dis.c b/s390-dis.c
+index 86dd84f..9a73a57 100644
+--- a/s390-dis.c
++++ b/s390-dis.c
+@@ -191,10 +191,10 @@ init_disasm (struct disassemble_info *info)
+ // switch (info->mach)
+ // {
+ // case bfd_mach_s390_31:
+- current_arch_mask = 1 << S390_OPCODE_ESA;
++// current_arch_mask = 1 << S390_OPCODE_ESA;
+ // break;
+ // case bfd_mach_s390_64:
+-// current_arch_mask = 1 << S390_OPCODE_ZARCH;
++ current_arch_mask = 1 << S390_OPCODE_ZARCH;
+ // break;
+ // default:
+ // abort ();
+diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
+new file mode 100644
+index 0000000..3505df4
+--- /dev/null
++++ b/target-s390x/cpu.h
+@@ -0,0 +1,131 @@
++/*
++ * S/390 virtual CPU header
++ *
++ * Copyright (c) 2009 Ulrich Hecht
++ *
++ * 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, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
++ */
++#ifndef CPU_S390X_H
++#define CPU_S390X_H
++
++#define TARGET_LONG_BITS 64
++
++#define ELF_MACHINE EM_S390
++
++#define CPUState struct CPUS390XState
++
++#include "cpu-defs.h"
++
++#include "softfloat.h"
++
++#define NB_MMU_MODES 2 // guess
++#define MMU_USER_IDX 0 // guess
++
++typedef union FPReg {
++ struct {
++#ifdef WORDS_BIGENDIAN
++ float32 e;
++ int32_t __pad;
++#else
++ int32_t __pad;
++ float32 e;
++#endif
++ };
++ float64 d;
++ uint64_t i;
++} FPReg;
++
++typedef struct CPUS390XState {
++ uint64_t regs[16]; /* GP registers */
++
++ uint32_t aregs[16]; /* access registers */
++
++ uint32_t fpc; /* floating-point control register */
++ FPReg fregs[16]; /* FP registers */
++ float_status fpu_status; /* passed to softfloat lib */
++
++ struct {
++ uint64_t mask;
++ uint64_t addr;
++ } psw;
++
++ int cc; /* condition code (0-3) */
++
++ uint64_t __excp_addr;
++
++ CPU_COMMON
++} CPUS390XState;
++
++#if defined(CONFIG_USER_ONLY)
++static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
++{
|