diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-01-04 22:15:45 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-01-07 19:17:59 +0000 |
commit | b0d2b7d0f084f6b33acf7c722790da683916fee3 (patch) | |
tree | b54464113094ead3227aa55fde63c3de0aba7358 /target-arm/translate-a64.c | |
parent | fea505221eaf87889000378d4d33ad0dfd5f4d9d (diff) |
target-arm: A64: Implement minimal set of EL0-visible sysregs
Implement an initial minimal set of EL0-visible system registers:
* NZCV
* FPCR
* FPSR
* CTR_EL0
* DCZID_EL0
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Diffstat (limited to 'target-arm/translate-a64.c')
-rw-r--r-- | target-arm/translate-a64.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 7a9ee828e7..c8ed799834 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; } |