func: void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
  
  {
  
      /* We're passed bits [11..0] of the instruction; extract
  
       * SYSm and the mask bits.
  
       * Invalid combinations of SYSm and mask are UNPREDICTABLE;
  
       * we choose to treat them as if the mask bits were valid.
  
       * NB that the pseudocode 'mask' variable is bits [11..10],
  
       * whereas ours is [11..8].
  
       */
  
      uint32_t mask = extract32(maskreg, 8, 4);
  
      uint32_t reg = extract32(maskreg, 0, 8);
  
  
  
      if (arm_current_el(env) == 0 && reg > 7) {
  
          /* only xPSR sub-fields may be written by unprivileged */
  
          return;
  
      }
  
  
  
      switch (reg) {
  
      case 0 ... 7: /* xPSR sub-fields */
  
          /* only APSR is actually writable */
  
          if (!(reg & 4)) {
  
              uint32_t apsrmask = 0;
  
  
  
              if (mask & 8) {
  
                  apsrmask |= XPSR_NZCV | XPSR_Q;
  
              }
  
              if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
  
                  apsrmask |= XPSR_GE;
  
              }
  
              xpsr_write(env, val, apsrmask);
  
          }
  
          break;
  
      case 8: /* MSP */
  
          if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) {
  
              env->v7m.other_sp = val;
  
          } else {
  
              env->regs[13] = val;
  
          }
  
          break;
  
      case 9: /* PSP */
  
          if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) {
  
              env->regs[13] = val;
  
          } else {
  
              env->v7m.other_sp = val;
  
          }
  
          break;
  
      case 16: /* PRIMASK */
  
          env->v7m.primask[env->v7m.secure] = val & 1;
  
          break;
  
      case 17: /* BASEPRI */
  
          env->v7m.basepri[env->v7m.secure] = val & 0xff;
  
          break;
  
      case 18: /* BASEPRI_MAX */
  
          val &= 0xff;
  
          if (val != 0 && (val < env->v7m.basepri[env->v7m.secure]
  
                           || env->v7m.basepri[env->v7m.secure] == 0)) {
  
              env->v7m.basepri[env->v7m.secure] = val;
  
          }
  
          break;
  
      case 19: /* FAULTMASK */
  
          env->v7m.faultmask = val & 1;
  
          break;
  
      case 20: /* CONTROL */
  
          /* Writing to the SPSEL bit only has an effect if we are in
  
           * thread mode; other bits can be updated by any privileged code.
  
           * switch_v7m_sp() deals with updating the SPSEL bit in
  
           * env->v7m.control, so we only need update the others.
  
           */
  
          if (!arm_v7m_is_handler_mode(env)) {
  
              switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
  
          }
  
          env->v7m.control &= ~R_V7M_CONTROL_NPRIV_MASK;
  
          env->v7m.control |= val & R_V7M_CONTROL_NPRIV_MASK;
  
          break;
  
      default:
  
          qemu_log_mask(LOG_GUEST_ERROR, "Attempt to write unknown special"
  
                                         " register %d\n", reg);
  
          return;
  
      }
  
  }
  