aboutsummaryrefslogtreecommitdiff
path: root/target/riscv/internals.h
diff options
context:
space:
mode:
Diffstat (limited to 'target/riscv/internals.h')
-rw-r--r--target/riscv/internals.h69
1 files changed, 68 insertions, 1 deletions
diff --git a/target/riscv/internals.h b/target/riscv/internals.h
index 0ac17bc..4570bd5 100644
--- a/target/riscv/internals.h
+++ b/target/riscv/internals.h
@@ -19,7 +19,10 @@
#ifndef RISCV_CPU_INTERNALS_H
#define RISCV_CPU_INTERNALS_H
+#include "exec/cpu-common.h"
#include "hw/registerfields.h"
+#include "fpu/softfloat-types.h"
+#include "target/riscv/cpu_bits.h"
/*
* The current MMU Modes are:
@@ -30,12 +33,15 @@
* - U+2STAGE 0b100
* - S+2STAGE 0b101
* - S+SUM+2STAGE 0b110
+ * - Shadow stack+U 0b1000
+ * - Shadow stack+S 0b1001
*/
#define MMUIdx_U 0
#define MMUIdx_S 1
#define MMUIdx_S_SUM 2
#define MMUIdx_M 3
#define MMU_2STAGE_BIT (1 << 2)
+#define MMU_IDX_SS_WRITE (1 << 3)
static inline int mmuidx_priv(int mmu_idx)
{
@@ -136,7 +142,68 @@ static inline float16 check_nanbox_h(CPURISCVState *env, uint64_t f)
}
}
-/* Our implementation of CPUClass::has_work */
+#ifndef CONFIG_USER_ONLY
+/* Our implementation of SysemuCPUOps::has_work */
bool riscv_cpu_has_work(CPUState *cs);
+#endif
+
+/* Zjpm addr masking routine */
+static inline target_ulong adjust_addr_body(CPURISCVState *env,
+ target_ulong addr,
+ bool is_virt_addr)
+{
+ RISCVPmPmm pmm = PMM_FIELD_DISABLED;
+ uint32_t pmlen = 0;
+ bool signext = false;
+
+ /* do nothing for rv32 mode */
+ if (riscv_cpu_mxl(env) == MXL_RV32) {
+ return addr;
+ }
+
+ /* get pmm field depending on whether addr is */
+ if (is_virt_addr) {
+ pmm = riscv_pm_get_virt_pmm(env);
+ } else {
+ pmm = riscv_pm_get_pmm(env);
+ }
+
+ /* if pointer masking is disabled, return original addr */
+ if (pmm == PMM_FIELD_DISABLED) {
+ return addr;
+ }
+
+ if (!is_virt_addr) {
+ signext = riscv_cpu_virt_mem_enabled(env);
+ }
+ addr = addr << pmlen;
+ pmlen = riscv_pm_get_pmlen(pmm);
+
+ /* sign/zero extend masked address by N-1 bit */
+ if (signext) {
+ addr = (target_long)addr >> pmlen;
+ } else {
+ addr = addr >> pmlen;
+ }
+
+ return addr;
+}
+
+static inline target_ulong adjust_addr(CPURISCVState *env,
+ target_ulong addr)
+{
+ return adjust_addr_body(env, addr, false);
+}
+
+static inline target_ulong adjust_addr_virt(CPURISCVState *env,
+ target_ulong addr)
+{
+ return adjust_addr_body(env, addr, true);
+}
+
+static inline int insn_len(uint16_t first_word)
+{
+ return (first_word & 3) == 3 ? 4 : 2;
+}
#endif