qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 15/25] target-arm: A64: Implement minimal set


From: Peter Crosthwaite
Subject: Re: [Qemu-devel] [PATCH v2 15/25] target-arm: A64: Implement minimal set of EL0-visible sysregs
Date: Sat, 4 Jan 2014 23:32:44 +1000

On Mon, Dec 23, 2013 at 8:49 AM, Peter Maydell <address@hidden> wrote:
> Implement an initial minimal set of EL0-visible system registers:
>  * NZCV
>  * FPCR
>  * FPSR
>  * CTR_EL0
>  * DCZID_EL0
>
> Signed-off-by: Peter Maydell <address@hidden>
> Reviewed-by: Richard Henderson <address@hidden>
> ---
>  target-arm/cpu.h           |  3 ++-
>  target-arm/helper.c        | 61 
> ++++++++++++++++++++++++++++++++++++++++++++++
>  target-arm/translate-a64.c | 52 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 115 insertions(+), 1 deletion(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 66490ce..1e0800e 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -660,7 +660,8 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
>  #define ARM_CP_IO 64
>  #define ARM_CP_NOP (ARM_CP_SPECIAL | (1 << 8))
>  #define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8))
> -#define ARM_LAST_SPECIAL ARM_CP_WFI
> +#define ARM_CP_NZCV (ARM_CP_SPECIAL | (3 << 8))
> +#define ARM_LAST_SPECIAL ARM_CP_NZCV
>  /* Used only as a terminator for ARMCPRegInfo lists */
>  #define ARM_CP_SENTINEL 0xffff
>  /* Mask of only the flag bits in a type field */
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 66214293..ca27c8e 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -1560,6 +1560,64 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
>      REGINFO_SENTINEL
>  };
>
> +static int aa64_fpcr_read(CPUARMState *env, const ARMCPRegInfo *ri,
> +                          uint64_t *value)
> +{
> +    *value = vfp_get_fpcr(env);
> +    return 0;
> +}
> +
> +static int aa64_fpcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                           uint64_t value)
> +{
> +    vfp_set_fpcr(env, value);
> +    return 0;
> +}
> +
> +static int aa64_fpsr_read(CPUARMState *env, const ARMCPRegInfo *ri,
> +                          uint64_t *value)
> +{
> +    *value = vfp_get_fpsr(env);
> +    return 0;
> +}
> +
> +static int aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> +                           uint64_t value)
> +{
> +    vfp_set_fpsr(env, value);
> +    return 0;
> +}
> +
> +static const ARMCPRegInfo v8_cp_reginfo[] = {
> +    /* Minimal set of EL0-visible registers. This will need to be expanded
> +     * significantly for system emulation of AArch64 CPUs.
> +     */
> +    { .name = "NZCV", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 2,
> +      .access = PL0_RW, .type = ARM_CP_NZCV },
> +    {. name = "FPCR", .state = ARM_CP_STATE_AA64,
> +     .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4,
> +     .access = PL0_RW, .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write 
> },
> +    {. name = "FPSR", .state = ARM_CP_STATE_AA64,
> +     .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 4,
> +     .access = PL0_RW, .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write 
> },
> +    /* This claims a 32 byte cacheline size for icache and dcache, VIPT 
> icache.
> +     * It will eventually need to have a CPU-specified reset value.
> +     */

Not sure why this can't be solved short term as there is already the
ctr field in cpu state struct as used by 32.

> +    { .name = "CTR_EL0", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 0, .crm = 0,
> +      .access = PL0_R, .type = ARM_CP_CONST,
> +      .resetvalue = 0x80030003 },
> +    /* Prohibit use of DC ZVA. OPTME: implement DC ZVA and allow its use.
> +     * For system mode the DZP bit here will need to be computed, not 
> constant.
> +     */
> +    { .name = "DCZID_EL0", .state = ARM_CP_STATE_AA64,
> +      .opc0 = 3, .opc1 = 3, .opc2 = 7, .crn = 0, .crm = 0,
> +      .access = PL0_R, .type = ARM_CP_CONST,
> +      .resetvalue = 0x10 },
> +    REGINFO_SENTINEL
> +};
> +
>  static int sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t 
> value)
>  {
>      env->cp15.c1_sys = value;
> @@ -1662,6 +1720,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
>      } else {
>          define_arm_cp_regs(cpu, not_v7_cp_reginfo);
>      }
> +    if (arm_feature(env, ARM_FEATURE_V8)) {
> +        define_arm_cp_regs(cpu, v8_cp_reginfo);
> +    }

But I guess this exact approach wouldn't work. v8_cp_reginfo
declaration would have to be brought inline here (like it is for the
existing A32 MIDR/CTR/friends RegInfo decl.).

Regards,
Peter

>      if (arm_feature(env, ARM_FEATURE_MPU)) {
>          /* These are the MPU registers prior to PMSAv6. Any new
>           * PMSA core later than the ARM946 will require that we
> diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
> index 7a9ee82..c8ed799 100644
> --- a/target-arm/translate-a64.c
> +++ b/target-arm/translate-a64.c,
> @@ -733,6 +733,50 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
>      unsupported_encoding(s, insn);
>  }
>
> +static void gen_get_nzcv(TCGv_i64 tcg_rt)
> +{
> +    TCGv_i32 tmp = tcg_temp_new_i32();
> +    TCGv_i32 nzcv = tcg_temp_new_i32();
> +
> +    /* build bit 31, N */
> +    tcg_gen_andi_i32(nzcv, cpu_NF, (1 << 31));
> +    /* build bit 30, Z */
> +    tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_ZF, 0);
> +    tcg_gen_deposit_i32(nzcv, nzcv, tmp, 30, 1);
> +    /* build bit 29, C */
> +    tcg_gen_deposit_i32(nzcv, nzcv, cpu_CF, 29, 1);
> +    /* build bit 28, V */
> +    tcg_gen_shri_i32(tmp, cpu_VF, 31);
> +    tcg_gen_deposit_i32(nzcv, nzcv, tmp, 28, 1);
> +    /* generate result */
> +    tcg_gen_extu_i32_i64(tcg_rt, nzcv);
> +
> +    tcg_temp_free_i32(nzcv);
> +    tcg_temp_free_i32(tmp);
> +}
> +
> +static void gen_set_nzcv(TCGv_i64 tcg_rt)
> +
> +{
> +    TCGv_i32 nzcv = tcg_temp_new_i32();
> +
> +    /* take NZCV from R[t] */
> +    tcg_gen_trunc_i64_i32(nzcv, tcg_rt);
> +
> +    /* bit 31, N */
> +    tcg_gen_andi_i32(cpu_NF, nzcv, (1 << 31));
> +    /* bit 30, Z */
> +    tcg_gen_andi_i32(cpu_ZF, nzcv, (1 << 30));
> +    tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_ZF, cpu_ZF, 0);
> +    /* bit 29, C */
> +    tcg_gen_andi_i32(cpu_CF, nzcv, (1 << 29));
> +    tcg_gen_shri_i32(cpu_CF, cpu_CF, 29);
> +    /* bit 28, V */
> +    tcg_gen_andi_i32(cpu_VF, nzcv, (1 << 28));
> +    tcg_gen_shli_i32(cpu_VF, cpu_VF, 3);
> +    tcg_temp_free_i32(nzcv);
> +}
> +
>  /* C5.6.129 MRS - move from system register
>   * C5.6.131 MSR (register) - move to system register
>   * C5.6.204 SYS
> @@ -767,6 +811,14 @@ static void handle_sys(DisasContext *s, uint32_t insn, 
> bool isread,
>      switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
>      case ARM_CP_NOP:
>          return;
> +    case ARM_CP_NZCV:
> +        tcg_rt = cpu_reg(s, rt);
> +        if (isread) {
> +            gen_get_nzcv(tcg_rt);
> +        } else {
> +            gen_set_nzcv(tcg_rt);
> +        }
> +        return;
>      default:
>          break;
>      }
> --
> 1.8.5
>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]