Merge branch 'for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm
authorBlue Swirl <blauwirbel@gmail.com>
Wed, 20 Jul 2011 20:23:01 +0000 (20:23 +0000)
committerBlue Swirl <blauwirbel@gmail.com>
Wed, 20 Jul 2011 20:23:01 +0000 (20:23 +0000)
* 'for-upstream' of git://git.linaro.org/people/pmaydell/qemu-arm:
  target-arm: Fix BASEPRI, BASEPRI_MAX, and FAULTMASK access
  target-arm: Minimal implementation of performance counters
  Revert "Makefile.target: Allow target helpers to be in any *_helper.c file"
  Revert "target-arm: Use global env in neon_helper.c helpers"
  target-arm: Pass fp status pointer explicitly to neon fp helpers
  target-arm: Make VFP binop helpers take pointer to fpstatus, not CPUState
  target-arm: Add helper function to generate code to get fpstatus pointer
  Revert "target-arm: Use global env in iwmmxt_helper.c helpers"

Conflicts:
Makefile.target

1  2 
Makefile.target
target-arm/cpu.h
target-arm/helper.c
target-arm/translate.c

diff --combined Makefile.target
index c566eb1149276f27bcf1a04c89c8b8934983ec17,37bb28ed8a2e004cced198bf18bf0064c181efb2..fe785161cb40d3423201618b0336614297aeaeb5
@@@ -3,7 -3,6 +3,7 @@@
  GENERATED_HEADERS = config-target.h
  CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
  CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
 +CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
  
  include ../config-host.mak
  include config-devices.mak
@@@ -15,10 -14,7 +15,10 @@@ endi
  
  TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
  $(call set-vpath, $(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw)
 -QEMU_CFLAGS+= -I.. -I../linux-headers -I$(TARGET_PATH) -DNEED_CPU_H
 +ifdef CONFIG_LINUX
 +QEMU_CFLAGS += -I../linux-headers
 +endif
 +QEMU_CFLAGS += -I.. -I$(TARGET_PATH) -DNEED_CPU_H
  
  include $(SRC_PATH)/Makefile.objs
  
@@@ -95,7 -91,7 +95,7 @@@ tcg/tcg.o: cpu.
  
  # HELPER_CFLAGS is used for all the code compiled with static register
  # variables
- %_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 -op_helper.o cpu-exec.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
++op_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
  
  # Note: this is a workaround. The real fix is to avoid compiling
  # cpu_signal_handler() in user-exec.c.
@@@ -205,9 -201,20 +205,9 @@@ QEMU_CFLAGS += $(VNC_SASL_CFLAGS
  QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
  QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
  
 -# xen backend driver support
 -obj-i386-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
 -
 -ifeq ($(TARGET_BASE_ARCH), i386)
 -  CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
 -else
 -  CONFIG_NO_XEN = y
 -endif
  # xen support
 -CONFIG_NO_XEN_MAPCACHE = $(if $(subst n,,$(CONFIG_XEN_MAPCACHE)),n,y)
 -obj-i386-$(CONFIG_XEN) += xen-all.o
 +obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
  obj-$(CONFIG_NO_XEN) += xen-stub.o
 -obj-i386-$(CONFIG_XEN_MAPCACHE) += xen-mapcache.o
 -obj-$(CONFIG_NO_XEN_MAPCACHE) += xen-mapcache-stub.o
  
  obj-i386-$(CONFIG_XEN) += xen_platform.o
  
@@@ -227,8 -234,7 +227,8 @@@ obj-i386-y += cirrus_vga.o sga.o apic.
  obj-i386-y += vmport.o
  obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
  obj-i386-y += debugcon.o multiboot.o
 -obj-i386-y += pc_piix.o kvmclock.o
 +obj-i386-y += pc_piix.o
 +obj-i386-$(CONFIG_KVM) += kvmclock.o
  obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
  
  # shared objects
@@@ -250,7 -256,7 +250,7 @@@ endi
  obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
  obj-ppc-y += ppc440.o ppc440_bamboo.o
  # PowerPC E500 boards
 -obj-ppc-y += ppce500_mpc8544ds.o
 +obj-ppc-y += ppce500_mpc8544ds.o mpc8544_guts.o
  # PowerPC 440 Xilinx ML507 reference board.
  obj-ppc-y += virtex_ml507.o
  obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
diff --combined target-arm/cpu.h
index 1022a037536e3f9906675001c3ec8ec2f1c1008b,1276e6985aa3c24775b5349ae624110b18a2c09a..adef42785c50af5e760459e656227ec5db1cb20c
@@@ -133,6 -133,12 +133,12 @@@ typedef struct CPUARMState 
          uint32_t c7_par;  /* Translation result. */
          uint32_t c9_insn; /* Cache lockdown registers.  */
          uint32_t c9_data;
+         uint32_t c9_pmcr; /* performance monitor control register */
+         uint32_t c9_pmcnten; /* perf monitor counter enables */
+         uint32_t c9_pmovsr; /* perf monitor overflow status */
+         uint32_t c9_pmxevtyper; /* perf monitor event type */
+         uint32_t c9_pmuserenr; /* perf monitor user enable */
+         uint32_t c9_pminten; /* perf monitor interrupt enables */
          uint32_t c13_fcse; /* FCSE PID.  */
          uint32_t c13_context; /* Context ID.  */
          uint32_t c13_tls1; /* User RW Thread register.  */
          void *opaque;
      } cp[15];
      void *nvic;
 -    struct arm_boot_info *boot_info;
 +    const struct arm_boot_info *boot_info;
  } CPUARMState;
  
  CPUARMState *cpu_arm_init(const char *cpu_model);
@@@ -438,7 -444,7 +444,7 @@@ void cpu_arm_set_cp_io(CPUARMState *env
  #define cpu_signal_handler cpu_arm_signal_handler
  #define cpu_list arm_cpu_list
  
- #define CPU_SAVE_VERSION 3
+ #define CPU_SAVE_VERSION 4
  
  /* MMU modes definitions */
  #define MMU_MODE0_SUFFIX _kernel
@@@ -512,17 -518,4 +518,17 @@@ static inline void cpu_get_tb_cpu_state
      }
  }
  
 +static inline bool cpu_has_work(CPUState *env)
 +{
 +    return env->interrupt_request &
 +        (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
 +}
 +
 +#include "exec-all.h"
 +
 +static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
 +{
 +    env->regs[15] = tb->pc;
 +}
 +
  #endif
diff --combined target-arm/helper.c
index f4d12aab55dcdbba2b6751b2d47654dad608608f,a0f23147994dd868b5e0415ab2aecf395cbd4239..ae4f334e40a5b4c1725f1ec077088766d6fb9d09
@@@ -3,6 -3,7 +3,6 @@@
  #include <string.h>
  
  #include "cpu.h"
 -#include "exec-all.h"
  #include "gdbstub.h"
  #include "helper.h"
  #include "qemu-common.h"
@@@ -269,6 -270,10 +269,10 @@@ void cpu_reset(CPUARMState *env
      }
      env->vfp.xregs[ARM_VFP_FPEXC] = 0;
      env->cp15.c2_base_mask = 0xffffc000u;
+     /* v7 performance monitor control register: same implementor
+      * field as main ID register, and we implement no event counters.
+      */
+     env->cp15.c9_pmcr = (id & 0xff000000);
  #endif
      set_flush_to_zero(1, &env->vfp.standard_fp_status);
      set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
@@@ -1587,6 -1592,81 +1591,81 @@@ void HELPER(set_cp15)(CPUState *env, ui
          case 1: /* TCM memory region registers.  */
              /* Not implemented.  */
              goto bad_reg;
+         case 12: /* Performance monitor control */
+             /* Performance monitors are implementation defined in v7,
+              * but with an ARM recommended set of registers, which we
+              * follow (although we don't actually implement any counters)
+              */
+             if (!arm_feature(env, ARM_FEATURE_V7)) {
+                 goto bad_reg;
+             }
+             switch (op2) {
+             case 0: /* performance monitor control register */
+                 /* only the DP, X, D and E bits are writable */
+                 env->cp15.c9_pmcr &= ~0x39;
+                 env->cp15.c9_pmcr |= (val & 0x39);
+                 break;
+             case 1: /* Count enable set register */
+                 val &= (1 << 31);
+                 env->cp15.c9_pmcnten |= val;
+                 break;
+             case 2: /* Count enable clear */
+                 val &= (1 << 31);
+                 env->cp15.c9_pmcnten &= ~val;
+                 break;
+             case 3: /* Overflow flag status */
+                 env->cp15.c9_pmovsr &= ~val;
+                 break;
+             case 4: /* Software increment */
+                 /* RAZ/WI since we don't implement the software-count event */
+                 break;
+             case 5: /* Event counter selection register */
+                 /* Since we don't implement any events, writing to this register
+                  * is actually UNPREDICTABLE. So we choose to RAZ/WI.
+                  */
+                 break;
+             default:
+                 goto bad_reg;
+             }
+             break;
+         case 13: /* Performance counters */
+             if (!arm_feature(env, ARM_FEATURE_V7)) {
+                 goto bad_reg;
+             }
+             switch (op2) {
+             case 0: /* Cycle count register: not implemented, so RAZ/WI */
+                 break;
+             case 1: /* Event type select */
+                 env->cp15.c9_pmxevtyper = val & 0xff;
+                 break;
+             case 2: /* Event count register */
+                 /* Unimplemented (we have no events), RAZ/WI */
+                 break;
+             default:
+                 goto bad_reg;
+             }
+             break;
+         case 14: /* Performance monitor control */
+             if (!arm_feature(env, ARM_FEATURE_V7)) {
+                 goto bad_reg;
+             }
+             switch (op2) {
+             case 0: /* user enable */
+                 env->cp15.c9_pmuserenr = val & 1;
+                 /* changes access rights for cp registers, so flush tbs */
+                 tb_flush(env);
+                 break;
+             case 1: /* interrupt enable set */
+                 /* We have no event counters so only the C bit can be changed */
+                 val &= (1 << 31);
+                 env->cp15.c9_pminten |= val;
+                 break;
+             case 2: /* interrupt enable clear */
+                 val &= (1 << 31);
+                 env->cp15.c9_pminten &= ~val;
+                 break;
+             }
+             break;
          default:
              goto bad_reg;
          }
@@@ -1878,27 -1958,81 +1957,81 @@@ uint32_t HELPER(get_cp15)(CPUState *env
          return 0;
      case 8: /* MMU TLB control.  */
          goto bad_reg;
-     case 9: /* Cache lockdown.  */
-         switch (op1) {
-         case 0: /* L1 cache.  */
-           if (arm_feature(env, ARM_FEATURE_OMAPCP))
-               return 0;
+     case 9:
+         switch (crm) {
+         case 0: /* Cache lockdown */
+             switch (op1) {
+             case 0: /* L1 cache.  */
+                 if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
+                     return 0;
+                 }
+                 switch (op2) {
+                 case 0:
+                     return env->cp15.c9_data;
+                 case 1:
+                     return env->cp15.c9_insn;
+                 default:
+                     goto bad_reg;
+                 }
+             case 1: /* L2 cache */
+                 if (crm != 0) {
+                     goto bad_reg;
+                 }
+                 /* L2 Lockdown and Auxiliary control.  */
+                 return 0;
+             default:
+                 goto bad_reg;
+             }
+             break;
+         case 12: /* Performance monitor control */
+             if (!arm_feature(env, ARM_FEATURE_V7)) {
+                 goto bad_reg;
+             }
              switch (op2) {
-             case 0:
-                 return env->cp15.c9_data;
-             case 1:
-                 return env->cp15.c9_insn;
+             case 0: /* performance monitor control register */
+                 return env->cp15.c9_pmcr;
+             case 1: /* count enable set */
+             case 2: /* count enable clear */
+                 return env->cp15.c9_pmcnten;
+             case 3: /* overflow flag status */
+                 return env->cp15.c9_pmovsr;
+             case 4: /* software increment */
+             case 5: /* event counter selection register */
+                 return 0; /* Unimplemented, RAZ/WI */
              default:
                  goto bad_reg;
              }
-         case 1: /* L2 cache */
-             if (crm != 0)
+         case 13: /* Performance counters */
+             if (!arm_feature(env, ARM_FEATURE_V7)) {
+                 goto bad_reg;
+             }
+             switch (op2) {
+             case 1: /* Event type select */
+                 return env->cp15.c9_pmxevtyper;
+             case 0: /* Cycle count register */
+             case 2: /* Event count register */
+                 /* Unimplemented, so RAZ/WI */
+                 return 0;
+             default:
                  goto bad_reg;
-             /* L2 Lockdown and Auxiliary control.  */
-             return 0;
+             }
+         case 14: /* Performance monitor control */
+             if (!arm_feature(env, ARM_FEATURE_V7)) {
+                 goto bad_reg;
+             }
+             switch (op2) {
+             case 0: /* user enable */
+                 return env->cp15.c9_pmuserenr;
+             case 1: /* interrupt enable set */
+             case 2: /* interrupt enable clear */
+                 return env->cp15.c9_pminten;
+             default:
+                 goto bad_reg;
+             }
          default:
              goto bad_reg;
          }
+         break;
      case 10: /* MMU TLB lockdown.  */
          /* ??? TLB lockdown not implemented.  */
          return 0;
@@@ -1994,11 -2128,11 +2127,11 @@@ uint32_t HELPER(v7m_mrs)(CPUState *env
          return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
      case 16: /* PRIMASK */
          return (env->uncached_cpsr & CPSR_I) != 0;
-     case 17: /* FAULTMASK */
-         return (env->uncached_cpsr & CPSR_F) != 0;
-     case 18: /* BASEPRI */
-     case 19: /* BASEPRI_MAX */
+     case 17: /* BASEPRI */
+     case 18: /* BASEPRI_MAX */
          return env->v7m.basepri;
+     case 19: /* FAULTMASK */
+         return (env->uncached_cpsr & CPSR_F) != 0;
      case 20: /* CONTROL */
          return env->v7m.control;
      default:
@@@ -2050,20 -2184,20 +2183,20 @@@ void HELPER(v7m_msr)(CPUState *env, uin
          else
              env->uncached_cpsr &= ~CPSR_I;
          break;
-     case 17: /* FAULTMASK */
-         if (val & 1)
-             env->uncached_cpsr |= CPSR_F;
-         else
-             env->uncached_cpsr &= ~CPSR_F;
-         break;
-     case 18: /* BASEPRI */
+     case 17: /* BASEPRI */
          env->v7m.basepri = val & 0xff;
          break;
-     case 19: /* BASEPRI_MAX */
+     case 18: /* BASEPRI_MAX */
          val &= 0xff;
          if (val != 0 && (val < env->v7m.basepri || env->v7m.basepri == 0))
              env->v7m.basepri = val;
          break;
+     case 19: /* FAULTMASK */
+         if (val & 1)
+             env->uncached_cpsr |= CPSR_F;
+         else
+             env->uncached_cpsr &= ~CPSR_F;
+         break;
      case 20: /* CONTROL */
          env->v7m.control = val & 3;
          switch_v7m_sp(env, (val & 2) != 0);
@@@ -2452,13 -2586,15 +2585,15 @@@ void vfp_set_fpscr(CPUState *env, uint3
  #define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
  
  #define VFP_BINOP(name) \
- float32 VFP_HELPER(name, s)(float32 a, float32 b, CPUState *env) \
+ float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
  { \
-     return float32_ ## name (a, b, &env->vfp.fp_status); \
+     float_status *fpst = fpstp; \
+     return float32_ ## name(a, b, fpst); \
  } \
- float64 VFP_HELPER(name, d)(float64 a, float64 b, CPUState *env) \
+ float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
  { \
-     return float64_ ## name (a, b, &env->vfp.fp_status); \
+     float_status *fpst = fpstp; \
+     return float64_ ## name(a, b, fpst); \
  }
  VFP_BINOP(add)
  VFP_BINOP(sub)
diff --combined target-arm/translate.c
index badbc5ff315c9639d5520efd8aca729c388d08f8,3e431e15cb9c68ae4bf394dbd852cfd0ae26e8f4..34d5e6ef1a7b908af9dee5d14f6bd62e93da09a7
@@@ -25,6 -25,7 +25,6 @@@
  #include <inttypes.h>
  
  #include "cpu.h"
 -#include "exec-all.h"
  #include "disas.h"
  #include "tcg-op.h"
  #include "qemu-log.h"
@@@ -892,13 -893,29 +892,29 @@@ static inline void gen_add_datah_offset
      }
  }
  
+ static TCGv_ptr get_fpstatus_ptr(int neon)
+ {
+     TCGv_ptr statusptr = tcg_temp_new_ptr();
+     int offset;
+     if (neon) {
+         offset = offsetof(CPUState, vfp.standard_fp_status);
+     } else {
+         offset = offsetof(CPUState, vfp.fp_status);
+     }
+     tcg_gen_addi_ptr(statusptr, cpu_env, offset);
+     return statusptr;
+ }
  #define VFP_OP2(name)                                                 \
  static inline void gen_vfp_##name(int dp)                             \
  {                                                                     \
-     if (dp)                                                           \
-         gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
-     else                                                              \
-         gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
+     TCGv_ptr fpst = get_fpstatus_ptr(0);                              \
+     if (dp) {                                                         \
+         gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst);    \
+     } else {                                                          \
+         gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst);    \
+     }                                                                 \
+     tcg_temp_free_ptr(fpst);                                          \
  }
  
  VFP_OP2(add)
@@@ -911,11 -928,13 +927,13 @@@ VFP_OP2(div
  static inline void gen_vfp_F1_mul(int dp)
  {
      /* Like gen_vfp_mul() but put result in F1 */
+     TCGv_ptr fpst = get_fpstatus_ptr(0);
      if (dp) {
-         gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, cpu_env);
+         gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
      } else {
-         gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, cpu_env);
+         gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
      }
+     tcg_temp_free_ptr(fpst);
  }
  
  static inline void gen_vfp_F1_neg(int dp)
@@@ -979,14 -998,7 +997,7 @@@ static inline void gen_vfp_F1_ld0(int d
  #define VFP_GEN_ITOF(name) \
  static inline void gen_vfp_##name(int dp, int neon) \
  { \
-     TCGv_ptr statusptr = tcg_temp_new_ptr(); \
-     int offset; \
-     if (neon) { \
-         offset = offsetof(CPUState, vfp.standard_fp_status); \
-     } else { \
-         offset = offsetof(CPUState, vfp.fp_status); \
-     } \
-     tcg_gen_addi_ptr(statusptr, cpu_env, offset); \
+     TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
      if (dp) { \
          gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
      } else { \
@@@ -1002,14 -1014,7 +1013,7 @@@ VFP_GEN_ITOF(sito
  #define VFP_GEN_FTOI(name) \
  static inline void gen_vfp_##name(int dp, int neon) \
  { \
-     TCGv_ptr statusptr = tcg_temp_new_ptr(); \
-     int offset; \
-     if (neon) { \
-         offset = offsetof(CPUState, vfp.standard_fp_status); \
-     } else { \
-         offset = offsetof(CPUState, vfp.fp_status); \
-     } \
-     tcg_gen_addi_ptr(statusptr, cpu_env, offset); \
+     TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
      if (dp) { \
          gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
      } else { \
@@@ -1028,14 -1033,7 +1032,7 @@@ VFP_GEN_FTOI(tosiz
  static inline void gen_vfp_##name(int dp, int shift, int neon) \
  { \
      TCGv tmp_shift = tcg_const_i32(shift); \
-     TCGv_ptr statusptr = tcg_temp_new_ptr(); \
-     int offset; \
-     if (neon) { \
-         offset = offsetof(CPUState, vfp.standard_fp_status); \
-     } else { \
-         offset = offsetof(CPUState, vfp.fp_status); \
-     } \
-     tcg_gen_addi_ptr(statusptr, cpu_env, offset); \
+     TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
      if (dp) { \
          gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
      } else { \
@@@ -1206,15 -1204,22 +1203,22 @@@ static inline void gen_op_iwmmxt_##name
      gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
  }
  
- #define IWMMXT_OP_SIZE(name) \
- IWMMXT_OP(name##b) \
- IWMMXT_OP(name##w) \
- IWMMXT_OP(name##l)
+ #define IWMMXT_OP_ENV(name) \
+ static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
+ { \
+     iwmmxt_load_reg(cpu_V1, rn); \
+     gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
+ }
+ #define IWMMXT_OP_ENV_SIZE(name) \
+ IWMMXT_OP_ENV(name##b) \
+ IWMMXT_OP_ENV(name##w) \
+ IWMMXT_OP_ENV(name##l)
  
- #define IWMMXT_OP_1(name) \
+ #define IWMMXT_OP_ENV1(name) \
  static inline void gen_op_iwmmxt_##name##_M0(void) \
  { \
-     gen_helper_iwmmxt_##name(cpu_M0, cpu_M0); \
+     gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
  }
  
  IWMMXT_OP(maddsq)
@@@ -1228,51 -1233,51 +1232,51 @@@ IWMMXT_OP(muluhw
  IWMMXT_OP(macsw)
  IWMMXT_OP(macuw)
  
- IWMMXT_OP_SIZE(unpackl)
- IWMMXT_OP_SIZE(unpackh)
- IWMMXT_OP_1(unpacklub)
- IWMMXT_OP_1(unpackluw)
- IWMMXT_OP_1(unpacklul)
- IWMMXT_OP_1(unpackhub)
- IWMMXT_OP_1(unpackhuw)
- IWMMXT_OP_1(unpackhul)
- IWMMXT_OP_1(unpacklsb)
- IWMMXT_OP_1(unpacklsw)
- IWMMXT_OP_1(unpacklsl)
- IWMMXT_OP_1(unpackhsb)
- IWMMXT_OP_1(unpackhsw)
- IWMMXT_OP_1(unpackhsl)
- IWMMXT_OP_SIZE(cmpeq)
- IWMMXT_OP_SIZE(cmpgtu)
- IWMMXT_OP_SIZE(cmpgts)
- IWMMXT_OP_SIZE(mins)
- IWMMXT_OP_SIZE(minu)
- IWMMXT_OP_SIZE(maxs)
- IWMMXT_OP_SIZE(maxu)
- IWMMXT_OP_SIZE(subn)
- IWMMXT_OP_SIZE(addn)
- IWMMXT_OP_SIZE(subu)
- IWMMXT_OP_SIZE(addu)
- IWMMXT_OP_SIZE(subs)
- IWMMXT_OP_SIZE(adds)
- IWMMXT_OP(avgb0)
- IWMMXT_OP(avgb1)
- IWMMXT_OP(avgw0)
- IWMMXT_OP(avgw1)
+ IWMMXT_OP_ENV_SIZE(unpackl)
+ IWMMXT_OP_ENV_SIZE(unpackh)
+ IWMMXT_OP_ENV1(unpacklub)
+ IWMMXT_OP_ENV1(unpackluw)
+ IWMMXT_OP_ENV1(unpacklul)
+ IWMMXT_OP_ENV1(unpackhub)
+ IWMMXT_OP_ENV1(unpackhuw)
+ IWMMXT_OP_ENV1(unpackhul)
+ IWMMXT_OP_ENV1(unpacklsb)
+ IWMMXT_OP_ENV1(unpacklsw)
+ IWMMXT_OP_ENV1(unpacklsl)
+ IWMMXT_OP_ENV1(unpackhsb)
+ IWMMXT_OP_ENV1(unpackhsw)
+ IWMMXT_OP_ENV1(unpackhsl)
+ IWMMXT_OP_ENV_SIZE(cmpeq)
+ IWMMXT_OP_ENV_SIZE(cmpgtu)
+ IWMMXT_OP_ENV_SIZE(cmpgts)
+ IWMMXT_OP_ENV_SIZE(mins)
+ IWMMXT_OP_ENV_SIZE(minu)
+ IWMMXT_OP_ENV_SIZE(maxs)
+ IWMMXT_OP_ENV_SIZE(maxu)
+ IWMMXT_OP_ENV_SIZE(subn)
+ IWMMXT_OP_ENV_SIZE(addn)
+ IWMMXT_OP_ENV_SIZE(subu)
+ IWMMXT_OP_ENV_SIZE(addu)
+ IWMMXT_OP_ENV_SIZE(subs)
+ IWMMXT_OP_ENV_SIZE(adds)
+ IWMMXT_OP_ENV(avgb0)
+ IWMMXT_OP_ENV(avgb1)
+ IWMMXT_OP_ENV(avgw0)
+ IWMMXT_OP_ENV(avgw1)
  
  IWMMXT_OP(msadb)
  
- IWMMXT_OP(packuw)
- IWMMXT_OP(packul)
- IWMMXT_OP(packuq)
- IWMMXT_OP(packsw)
- IWMMXT_OP(packsl)
- IWMMXT_OP(packsq)
+ IWMMXT_OP_ENV(packuw)
+ IWMMXT_OP_ENV(packul)
+ IWMMXT_OP_ENV(packuq)
+ IWMMXT_OP_ENV(packsw)
+ IWMMXT_OP_ENV(packsl)
+ IWMMXT_OP_ENV(packsq)
  
  static void gen_op_iwmmxt_set_mup(void)
  {
@@@ -2006,13 -2011,13 +2010,13 @@@ static int disas_iwmmxt_insn(CPUState *
          }
          switch ((insn >> 22) & 3) {
          case 1:
-             gen_helper_iwmmxt_srlw(cpu_M0, cpu_M0, tmp);
+             gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
              break;
          case 2:
-             gen_helper_iwmmxt_srll(cpu_M0, cpu_M0, tmp);
+             gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
              break;
          case 3:
-             gen_helper_iwmmxt_srlq(cpu_M0, cpu_M0, tmp);
+             gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
              break;
          }
          tcg_temp_free_i32(tmp);
          }
          switch ((insn >> 22) & 3) {
          case 1:
-             gen_helper_iwmmxt_sraw(cpu_M0, cpu_M0, tmp);
+             gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
              break;
          case 2:
-             gen_helper_iwmmxt_sral(cpu_M0, cpu_M0, tmp);
+             gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
              break;
          case 3:
-             gen_helper_iwmmxt_sraq(cpu_M0, cpu_M0, tmp);
+             gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
              break;
          }
          tcg_temp_free_i32(tmp);
          }
          switch ((insn >> 22) & 3) {
          case 1:
-             gen_helper_iwmmxt_sllw(cpu_M0, cpu_M0, tmp);
+             gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
              break;
          case 2:
-             gen_helper_iwmmxt_slll(cpu_M0, cpu_M0, tmp);
+             gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
              break;
          case 3:
-             gen_helper_iwmmxt_sllq(cpu_M0, cpu_M0, tmp);
+             gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
              break;
          }
          tcg_temp_free_i32(tmp);
                  tcg_temp_free_i32(tmp);
                  return 1;
              }
-             gen_helper_iwmmxt_rorw(cpu_M0, cpu_M0, tmp);
+             gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
              break;
          case 2:
              if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
                  tcg_temp_free_i32(tmp);
                  return 1;
              }
-             gen_helper_iwmmxt_rorl(cpu_M0, cpu_M0, tmp);
+             gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
              break;
          case 3:
              if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
                  tcg_temp_free_i32(tmp);
                  return 1;
              }
-             gen_helper_iwmmxt_rorq(cpu_M0, cpu_M0, tmp);
+             gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
              break;
          }
          tcg_temp_free_i32(tmp);
          rd0 = (insn >> 16) & 0xf;
          gen_op_iwmmxt_movq_M0_wRn(rd0);
          tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
-         gen_helper_iwmmxt_shufh(cpu_M0, cpu_M0, tmp);
+         gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
          tcg_temp_free(tmp);
          gen_op_iwmmxt_movq_wRn_M0(wrd);
          gen_op_iwmmxt_set_mup();
@@@ -2467,12 -2472,28 +2471,28 @@@ static int disas_cp_insn(CPUState *env
      return 0;
  }
  
- static int cp15_user_ok(uint32_t insn)
+ static int cp15_user_ok(CPUState *env, uint32_t insn)
  {
      int cpn = (insn >> 16) & 0xf;
      int cpm = insn & 0xf;
      int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
  
+     if (arm_feature(env, ARM_FEATURE_V7) && cpn == 9) {
+         /* Performance monitor registers fall into three categories:
+          *  (a) always UNDEF in usermode
+          *  (b) UNDEF only if PMUSERENR.EN is 0
+          *  (c) always read OK and UNDEF on write (PMUSERENR only)
+          */
+         if ((cpm == 12 && (op < 6)) ||
+             (cpm == 13 && (op < 3))) {
+             return env->cp15.c9_pmuserenr;
+         } else if (cpm == 14 && op == 0 && (insn & ARM_CP_RW_BIT)) {
+             /* PMUSERENR, read only */
+             return 1;
+         }
+         return 0;
+     }
      if (cpn == 13 && cpm == 0) {
          /* TLS register.  */
          if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
@@@ -2559,7 -2580,7 +2579,7 @@@ static int disas_cp15_insn(CPUState *en
          /* cdp */
          return 1;
      }
-     if (IS_USER(s) && !cp15_user_ok(insn)) {
+     if (IS_USER(s) && !cp15_user_ok(env, insn)) {
          return 1;
      }
  
@@@ -3706,13 -3727,13 +3726,13 @@@ static int gen_neon_unzip(int rd, int r
      if (q) {
          switch (size) {
          case 0:
-             gen_helper_neon_qunzip8(tmp, tmp2);
+             gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
              break;
          case 1:
-             gen_helper_neon_qunzip16(tmp, tmp2);
+             gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
              break;
          case 2:
-             gen_helper_neon_qunzip32(tmp, tmp2);
+             gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
              break;
          default:
              abort();
      } else {
          switch (size) {
          case 0:
-             gen_helper_neon_unzip8(tmp, tmp2);
+             gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
              break;
          case 1:
-             gen_helper_neon_unzip16(tmp, tmp2);
+             gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
              break;
          default:
              abort();
@@@ -3745,13 -3766,13 +3765,13 @@@ static int gen_neon_zip(int rd, int rm
      if (q) {
          switch (size) {
          case 0:
-             gen_helper_neon_qzip8(tmp, tmp2);
+             gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
              break;
          case 1:
-             gen_helper_neon_qzip16(tmp, tmp2);
+             gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
              break;
          case 2:
-             gen_helper_neon_qzip32(tmp, tmp2);
+             gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
              break;
          default:
              abort();
      } else {
          switch (size) {
          case 0:
-             gen_helper_neon_zip8(tmp, tmp2);
+             gen_helper_neon_zip8(cpu_env, tmp, tmp2);
              break;
          case 1:
-             gen_helper_neon_zip16(tmp, tmp2);
+             gen_helper_neon_zip16(cpu_env, tmp, tmp2);
              break;
          default:
              abort();
@@@ -4162,9 -4183,9 +4182,9 @@@ static inline void gen_neon_narrow(int 
  static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
  {
      switch (size) {
-     case 0: gen_helper_neon_narrow_sat_s8(dest, src); break;
-     case 1: gen_helper_neon_narrow_sat_s16(dest, src); break;
-     case 2: gen_helper_neon_narrow_sat_s32(dest, src); break;
+     case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
+     case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
+     case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
      default: abort();
      }
  }
  static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
  {
      switch (size) {
-     case 0: gen_helper_neon_narrow_sat_u8(dest, src); break;
-     case 1: gen_helper_neon_narrow_sat_u16(dest, src); break;
-     case 2: gen_helper_neon_narrow_sat_u32(dest, src); break;
+     case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
+     case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
+     case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
      default: abort();
      }
  }
  static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
  {
      switch (size) {
-     case 0: gen_helper_neon_unarrow_sat8(dest, src); break;
-     case 1: gen_helper_neon_unarrow_sat16(dest, src); break;
-     case 2: gen_helper_neon_unarrow_sat32(dest, src); break;
+     case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
+     case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
+     case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
      default: abort();
      }
  }
@@@ -4276,8 -4297,8 +4296,8 @@@ static inline void gen_neon_negl(TCGv_i
  static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
  {
      switch (size) {
-     case 1: gen_helper_neon_addl_saturate_s32(op0, op0, op1); break;
-     case 2: gen_helper_neon_addl_saturate_s64(op0, op0, op1); break;
+     case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
+     case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
      default: abort();
      }
  }
@@@ -4553,16 -4574,20 +4573,20 @@@ static int disas_neon_data_insn(CPUStat
                  switch (op) {
                  case NEON_3R_VQADD:
                      if (u) {
-                         gen_helper_neon_qadd_u64(cpu_V0, cpu_V0, cpu_V1);
+                         gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
+                                                  cpu_V0, cpu_V1);
                      } else {
-                         gen_helper_neon_qadd_s64(cpu_V0, cpu_V0, cpu_V1);
+                         gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
+                                                  cpu_V0, cpu_V1);
                      }
                      break;
                  case NEON_3R_VQSUB:
                      if (u) {
-                         gen_helper_neon_qsub_u64(cpu_V0, cpu_V0, cpu_V1);
+                         gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
+                                                  cpu_V0, cpu_V1);
                      } else {
-                         gen_helper_neon_qsub_s64(cpu_V0, cpu_V0, cpu_V1);
+                         gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
+                                                  cpu_V0, cpu_V1);
                      }
                      break;
                  case NEON_3R_VSHL:
                      break;
                  case NEON_3R_VQSHL:
                      if (u) {
-                         gen_helper_neon_qshl_u64(cpu_V0, cpu_V1, cpu_V0);
+                         gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
+                                                  cpu_V1, cpu_V0);
                      } else {
-                         gen_helper_neon_qshl_s64(cpu_V0, cpu_V1, cpu_V0);
+                         gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
+                                                  cpu_V1, cpu_V0);
                      }
                      break;
                  case NEON_3R_VRSHL:
                      break;
                  case NEON_3R_VQRSHL:
                      if (u) {
-                         gen_helper_neon_qrshl_u64(cpu_V0, cpu_V1, cpu_V0);
+                         gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
+                                                   cpu_V1, cpu_V0);
                      } else {
-                         gen_helper_neon_qrshl_s64(cpu_V0, cpu_V1, cpu_V0);
+                         gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
+                                                   cpu_V1, cpu_V0);
                      }
                      break;
                  case NEON_3R_VADD_VSUB:
              GEN_NEON_INTEGER_OP(hadd);
              break;
          case NEON_3R_VQADD:
-             GEN_NEON_INTEGER_OP(qadd);
+             GEN_NEON_INTEGER_OP_ENV(qadd);
              break;
          case NEON_3R_VRHADD:
              GEN_NEON_INTEGER_OP(rhadd);
              GEN_NEON_INTEGER_OP(hsub);
              break;
          case NEON_3R_VQSUB:
-             GEN_NEON_INTEGER_OP(qsub);
+             GEN_NEON_INTEGER_OP_ENV(qsub);
              break;
          case NEON_3R_VCGT:
              GEN_NEON_INTEGER_OP(cgt);
              GEN_NEON_INTEGER_OP(shl);
              break;
          case NEON_3R_VQSHL:
-             GEN_NEON_INTEGER_OP(qshl);
+             GEN_NEON_INTEGER_OP_ENV(qshl);
              break;
          case NEON_3R_VRSHL:
              GEN_NEON_INTEGER_OP(rshl);
              break;
          case NEON_3R_VQRSHL:
-             GEN_NEON_INTEGER_OP(qrshl);
+             GEN_NEON_INTEGER_OP_ENV(qrshl);
              break;
          case NEON_3R_VMAX:
              GEN_NEON_INTEGER_OP(max);
          case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high.  */
              if (!u) { /* VQDMULH */
                  switch (size) {
-                 case 1: gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2); break;
-                 case 2: gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2); break;
+                 case 1:
+                     gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
+                     break;
+                 case 2:
+                     gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
+                     break;
                  default: abort();
                  }
              } else { /* VQRDMULH */
                  switch (size) {
-                 case 1: gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2); break;
-                 case 2: gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2); break;
+                 case 1:
+                     gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
+                     break;
+                 case 2:
+                     gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
+                     break;
                  default: abort();
                  }
              }
              }
              break;
          case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
+         {
+             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
              switch ((u << 2) | size) {
              case 0: /* VADD */
-                 gen_helper_neon_add_f32(tmp, tmp, tmp2);
+             case 4: /* VPADD */
+                 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
                  break;
              case 2: /* VSUB */
-                 gen_helper_neon_sub_f32(tmp, tmp, tmp2);
-                 break;
-             case 4: /* VPADD */
-                 gen_helper_neon_add_f32(tmp, tmp, tmp2);
+                 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
                  break;
              case 6: /* VABD */
-                 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
+                 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
                  break;
              default:
                  abort();
              }
+             tcg_temp_free_ptr(fpstatus);
              break;
+         }
          case NEON_3R_FLOAT_MULTIPLY:
-             gen_helper_neon_mul_f32(tmp, tmp, tmp2);
+         {
+             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+             gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
              if (!u) {
                  tcg_temp_free_i32(tmp2);
                  tmp2 = neon_load_reg(rd, pass);
                  if (size == 0) {
-                     gen_helper_neon_add_f32(tmp, tmp, tmp2);
+                     gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
                  } else {
-                     gen_helper_neon_sub_f32(tmp, tmp2, tmp);
+                     gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
                  }
              }
+             tcg_temp_free_ptr(fpstatus);
              break;
+         }
          case NEON_3R_FLOAT_CMP:
+         {
+             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
              if (!u) {
-                 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
+                 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
              } else {
-                 if (size == 0)
-                     gen_helper_neon_cge_f32(tmp, tmp, tmp2);
-                 else
-                     gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
+                 if (size == 0) {
+                     gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
+                 } else {
+                     gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
+                 }
              }
+             tcg_temp_free_ptr(fpstatus);
              break;
+         }
          case NEON_3R_FLOAT_ACMP:
-             if (size == 0)
-                 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
-             else
-                 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
+         {
+             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+             if (size == 0) {
+                 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
+             } else {
+                 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
+             }
+             tcg_temp_free_ptr(fpstatus);
              break;
+         }
          case NEON_3R_FLOAT_MINMAX:
-             if (size == 0)
-                 gen_helper_neon_max_f32(tmp, tmp, tmp2);
-             else
-                 gen_helper_neon_min_f32(tmp, tmp, tmp2);
+         {
+             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+             if (size == 0) {
+                 gen_helper_neon_max_f32(tmp, tmp, tmp2, fpstatus);
+             } else {
+                 gen_helper_neon_min_f32(tmp, tmp, tmp2, fpstatus);
+             }
+             tcg_temp_free_ptr(fpstatus);
              break;
+         }
          case NEON_3R_VRECPS_VRSQRTS:
              if (size == 0)
                  gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
                              gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
                              break;
                          case 6: /* VQSHLU */
-                             gen_helper_neon_qshlu_s64(cpu_V0, cpu_V0, cpu_V1);
+                             gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
+                                                       cpu_V0, cpu_V1);
                              break;
                          case 7: /* VQSHL */
                              if (u) {
-                                 gen_helper_neon_qshl_u64(cpu_V0,
+                                 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
                                                           cpu_V0, cpu_V1);
                              } else {
-                                 gen_helper_neon_qshl_s64(cpu_V0,
+                                 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
                                                           cpu_V0, cpu_V1);
                              }
                              break;
                          case 6: /* VQSHLU */
                              switch (size) {
                              case 0:
-                                 gen_helper_neon_qshlu_s8(tmp, tmp, tmp2);
+                                 gen_helper_neon_qshlu_s8(tmp, cpu_env,
+                                                          tmp, tmp2);
                                  break;
                              case 1:
-                                 gen_helper_neon_qshlu_s16(tmp, tmp, tmp2);
+                                 gen_helper_neon_qshlu_s16(tmp, cpu_env,
+                                                           tmp, tmp2);
                                  break;
                              case 2:
-                                 gen_helper_neon_qshlu_s32(tmp, tmp, tmp2);
+                                 gen_helper_neon_qshlu_s32(tmp, cpu_env,
+                                                           tmp, tmp2);
                                  break;
                              default:
                                  abort();
                              }
                              break;
                          case 7: /* VQSHL */
-                             GEN_NEON_INTEGER_OP(qshl);
+                             GEN_NEON_INTEGER_OP_ENV(qshl);
                              break;
                          }
                          tcg_temp_free_i32(tmp2);
                          tmp2 = neon_load_reg(rn, pass);
                          if (op == 12) {
                              if (size == 1) {
-                                 gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2);
+                                 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
                              } else {
-                                 gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2);
+                                 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
                              }
                          } else if (op == 13) {
                              if (size == 1) {
-                                 gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2);
+                                 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
                              } else {
-                                 gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2);
+                                 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
                              }
                          } else if (op & 1) {
-                             gen_helper_neon_mul_f32(tmp, tmp, tmp2);
+                             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+                             gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
+                             tcg_temp_free_ptr(fpstatus);
                          } else {
                              switch (size) {
                              case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
                                  gen_neon_add(size, tmp, tmp2);
                                  break;
                              case 1:
-                                 gen_helper_neon_add_f32(tmp, tmp, tmp2);
+                             {
+                                 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+                                 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
+                                 tcg_temp_free_ptr(fpstatus);
                                  break;
+                             }
                              case 4:
                                  gen_neon_rsb(size, tmp, tmp2);
                                  break;
                              case 5:
-                                 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
+                             {
+                                 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+                                 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
+                                 tcg_temp_free_ptr(fpstatus);
                                  break;
+                             }
                              default:
                                  abort();
                              }
                              break;
                          case NEON_2RM_VQABS:
                              switch (size) {
-                             case 0: gen_helper_neon_qabs_s8(tmp, tmp); break;
-                             case 1: gen_helper_neon_qabs_s16(tmp, tmp); break;
-                             case 2: gen_helper_neon_qabs_s32(tmp, tmp); break;
+                             case 0:
+                                 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
+                                 break;
+                             case 1:
+                                 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
+                                 break;
+                             case 2:
+                                 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
+                                 break;
                              default: abort();
                              }
                              break;
                          case NEON_2RM_VQNEG:
                              switch (size) {
-                             case 0: gen_helper_neon_qneg_s8(tmp, tmp); break;
-                             case 1: gen_helper_neon_qneg_s16(tmp, tmp); break;
-                             case 2: gen_helper_neon_qneg_s32(tmp, tmp); break;
+                             case 0:
+                                 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
+                                 break;
+                             case 1:
+                                 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
+                                 break;
+                             case 2:
+                                 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
+                                 break;
                              default: abort();
                              }
                              break;
                              tcg_temp_free(tmp2);
                              break;
                          case NEON_2RM_VCGT0_F:
+                         {
+                             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
                              tmp2 = tcg_const_i32(0);
-                             gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
+                             gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
                              tcg_temp_free(tmp2);
+                             tcg_temp_free_ptr(fpstatus);
                              break;
+                         }
                          case NEON_2RM_VCGE0_F:
+                         {
+                             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
                              tmp2 = tcg_const_i32(0);
-                             gen_helper_neon_cge_f32(tmp, tmp, tmp2);
+                             gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
                              tcg_temp_free(tmp2);
+                             tcg_temp_free_ptr(fpstatus);
                              break;
+                         }
                          case NEON_2RM_VCEQ0_F:
+                         {
+                             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
                              tmp2 = tcg_const_i32(0);
-                             gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
+                             gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
                              tcg_temp_free(tmp2);
+                             tcg_temp_free_ptr(fpstatus);
                              break;
+                         }
                          case NEON_2RM_VCLE0_F:
+                         {
+                             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
                              tmp2 = tcg_const_i32(0);
-                             gen_helper_neon_cge_f32(tmp, tmp2, tmp);
+                             gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
                              tcg_temp_free(tmp2);
+                             tcg_temp_free_ptr(fpstatus);
                              break;
+                         }
                          case NEON_2RM_VCLT0_F:
+                         {
+                             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
                              tmp2 = tcg_const_i32(0);
-                             gen_helper_neon_cgt_f32(tmp, tmp2, tmp);
+                             gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
                              tcg_temp_free(tmp2);
+                             tcg_temp_free_ptr(fpstatus);
                              break;
+                         }
                          case NEON_2RM_VABS_F:
                              gen_vfp_abs(0);
                              break;