aboutsummaryrefslogtreecommitdiff
path: root/target/loongarch/op_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/loongarch/op_helper.c')
-rw-r--r--target/loongarch/op_helper.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index 18e565ce7f..a9ba72d5b2 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -6,6 +6,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/log.h"
#include "qemu/main-loop.h"
#include "cpu.h"
#include "qemu/host-utils.h"
@@ -15,6 +16,7 @@
#include "internals.h"
#include "qemu/crc32c.h"
#include <zlib.h>
+#include "cpu-csr.h"
/* Exceptions helpers */
void helper_raise_exception(CPULoongArchState *env, uint32_t exception)
@@ -81,3 +83,38 @@ target_ulong helper_cpucfg(CPULoongArchState *env, target_ulong rj)
{
return rj > 21 ? 0 : env->cpucfg[rj];
}
+
+void helper_ertn(CPULoongArchState *env)
+{
+ uint64_t csr_pplv, csr_pie;
+ if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) {
+ csr_pplv = FIELD_EX64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV);
+ csr_pie = FIELD_EX64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE);
+
+ env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0);
+ env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DA, 0);
+ env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PG, 1);
+ env->pc = env->CSR_TLBRERA;
+ qemu_log_mask(CPU_LOG_INT, "%s: TLBRERA " TARGET_FMT_lx "\n",
+ __func__, env->CSR_TLBRERA);
+ } else {
+ csr_pplv = FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PPLV);
+ csr_pie = FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PIE);
+
+ env->pc = env->CSR_ERA;
+ qemu_log_mask(CPU_LOG_INT, "%s: ERA " TARGET_FMT_lx "\n",
+ __func__, env->CSR_ERA);
+ }
+ env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, csr_pplv);
+ env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, csr_pie);
+
+ env->lladdr = 1;
+}
+
+void helper_idle(CPULoongArchState *env)
+{
+ CPUState *cs = env_cpu(env);
+
+ cs->halted = 1;
+ do_raise_exception(env, EXCP_HLT, 0);
+}