diff options
author | Alistair Francis <alistair.francis@wdc.com> | 2020-08-12 12:13:19 -0700 |
---|---|---|
committer | Alistair Francis <alistair.francis@wdc.com> | 2020-08-25 09:11:35 -0700 |
commit | 8c5362acb573b8b1913238a5ddefdeef12f513a8 (patch) | |
tree | 60ea64b5e11dcd847a60ca41e7a1cb19cc9ccea0 /target/riscv/op_helper.c | |
parent | 5a894dd7709f3b6a9f3e861dec71f78098bb3373 (diff) |
target/riscv: Allow generating hlv/hlvx/hsv instructions
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Message-id: 477c864312280ea55a98dc84cb01d826751b6c14.1597259519.git.alistair.francis@wdc.com
Message-Id: <477c864312280ea55a98dc84cb01d826751b6c14.1597259519.git.alistair.francis@wdc.com>
Diffstat (limited to 'target/riscv/op_helper.c')
-rw-r--r-- | target/riscv/op_helper.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 7cccd42a1e..3d306c343c 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -207,4 +207,118 @@ void helper_hyp_tlb_flush(CPURISCVState *env) riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); } +target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address, + target_ulong attrs, target_ulong memop) +{ + if (env->priv == PRV_M || + (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || + (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && + get_field(env->hstatus, HSTATUS_HU))) { + target_ulong pte; + + riscv_cpu_set_two_stage_lookup(env, true); + + switch (memop) { + case MO_SB: + pte = cpu_ldsb_data_ra(env, address, GETPC()); + break; + case MO_UB: + pte = cpu_ldub_data_ra(env, address, GETPC()); + break; + case MO_TESW: + pte = cpu_ldsw_data_ra(env, address, GETPC()); + break; + case MO_TEUW: + pte = cpu_lduw_data_ra(env, address, GETPC()); + break; + case MO_TESL: + pte = cpu_ldl_data_ra(env, address, GETPC()); + break; + case MO_TEUL: + pte = cpu_ldl_data_ra(env, address, GETPC()); + break; + case MO_TEQ: + pte = cpu_ldq_data_ra(env, address, GETPC()); + break; + default: + g_assert_not_reached(); + } + + riscv_cpu_set_two_stage_lookup(env, false); + + return pte; + } + + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + return 0; +} + +void helper_hyp_store(CPURISCVState *env, target_ulong address, + target_ulong val, target_ulong attrs, target_ulong memop) +{ + if (env->priv == PRV_M || + (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || + (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && + get_field(env->hstatus, HSTATUS_HU))) { + riscv_cpu_set_two_stage_lookup(env, true); + + switch (memop) { + case MO_SB: + case MO_UB: + cpu_stb_data_ra(env, address, val, GETPC()); + break; + case MO_TESW: + case MO_TEUW: + cpu_stw_data_ra(env, address, val, GETPC()); + break; + case MO_TESL: + case MO_TEUL: + cpu_stl_data_ra(env, address, val, GETPC()); + break; + case MO_TEQ: + cpu_stq_data_ra(env, address, val, GETPC()); + break; + default: + g_assert_not_reached(); + } + + riscv_cpu_set_two_stage_lookup(env, false); + + return; + } + + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); +} + +target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address, + target_ulong attrs, target_ulong memop) +{ + if (env->priv == PRV_M || + (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || + (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && + get_field(env->hstatus, HSTATUS_HU))) { + target_ulong pte; + + riscv_cpu_set_two_stage_lookup(env, true); + + switch (memop) { + case MO_TEUL: + pte = cpu_ldub_data_ra(env, address, GETPC()); + break; + case MO_TEUW: + pte = cpu_lduw_data_ra(env, address, GETPC()); + break; + default: + g_assert_not_reached(); + } + + riscv_cpu_set_two_stage_lookup(env, false); + + return pte; + } + + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + return 0; +} + #endif /* !CONFIG_USER_ONLY */ |