Merge tag 'pull-loongarch-20250124' of https://gitlab.com/bibo-mao/qemu into staging
loongarch queue
# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQQNhkKjomWfgLCz0aQfewwSUazn0QUCZ5M4AwAKCRAfewwSUazn
# 0aJAAP45/9qfbGSYiMCrBXpRFlyvtRN+GEXHEsERfk9Q1V+tQgEA/mMiUEcyc/xc
# Z1Z27cDoqUFRhPmxbd6/KyTGHzo2+As=
# =Zanw
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 24 Jan 2025 01:49:39 EST
# gpg: using EDDSA key 0D8642A3A2659F80B0B3D1A41F7B0C1251ACE7D1
# gpg: Good signature from "bibo mao <maobibo@loongson.cn>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 7044 3A00 19C0 E97A 31C7 13C4 8E86 8FB7 A176 9D4C
# Subkey fingerprint: 0D86 42A3 A265 9F80 B0B3 D1A4 1F7B 0C12 51AC E7D1
* tag 'pull-loongarch-20250124' of https://gitlab.com/bibo-mao/qemu:
target/loongarch: Dump all generic CSR registers
target/loongarch: Set unused flag with CSR registers
target/loongarch: Add common source file for CSR register
target/loongarch: Add common header file for CSR registers
target/loongarch: Add generic csr function type
target/loongarch: Remove static CSR function setting
target/loongarch: Add dynamic function access with CSR register
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index d611a60..e91f4a5 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -19,7 +19,7 @@
#include "cpu.h"
#include "internals.h"
#include "fpu/softfloat-helpers.h"
-#include "cpu-csr.h"
+#include "csr.h"
#ifndef CONFIG_USER_ONLY
#include "system/reset.h"
#endif
@@ -375,6 +375,33 @@
return MMU_DA_IDX;
}
+static void loongarch_la464_init_csr(Object *obj)
+{
+#ifndef CONFIG_USER_ONLY
+ static bool initialized;
+ LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+ CPULoongArchState *env = &cpu->env;
+ int i, num;
+
+ if (!initialized) {
+ initialized = true;
+ num = FIELD_EX64(env->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM);
+ for (i = num; i < 16; i++) {
+ set_csr_flag(LOONGARCH_CSR_SAVE(i), CSRFL_UNUSED);
+ }
+ set_csr_flag(LOONGARCH_CSR_IMPCTL1, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_IMPCTL2, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_MERRCTL, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_MERRINFO1, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_MERRINFO2, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_MERRENTRY, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_MERRERA, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_MERRSAVE, CSRFL_UNUSED);
+ set_csr_flag(LOONGARCH_CSR_CTAG, CSRFL_UNUSED);
+ }
+#endif
+}
+
static void loongarch_la464_initfn(Object *obj)
{
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
@@ -470,6 +497,7 @@
env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7);
env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8);
+ loongarch_la464_init_csr(obj);
loongarch_cpu_post_init(obj);
}
@@ -765,6 +793,54 @@
return oc;
}
+static void loongarch_cpu_dump_csr(CPUState *cs, FILE *f)
+{
+#ifndef CONFIG_USER_ONLY
+ CPULoongArchState *env = cpu_env(cs);
+ CSRInfo *csr_info;
+ int64_t *addr;
+ int i, j, len, col = 0;
+
+ qemu_fprintf(f, "\n");
+
+ /* Dump all generic CSR register */
+ for (i = 0; i < LOONGARCH_CSR_DBG; i++) {
+ csr_info = get_csr(i);
+ if (!csr_info || (csr_info->flags & CSRFL_UNUSED)) {
+ if (i == (col + 3)) {
+ qemu_fprintf(f, "\n");
+ }
+
+ continue;
+ }
+
+ if ((i > (col + 3)) || (i == col)) {
+ col = i & ~3;
+ qemu_fprintf(f, " CSR%03d:", col);
+ }
+
+ addr = (void *)env + csr_info->offset;
+ qemu_fprintf(f, " %s ", csr_info->name);
+ len = strlen(csr_info->name);
+ for (; len < 6; len++) {
+ qemu_fprintf(f, " ");
+ }
+
+ qemu_fprintf(f, "%" PRIx64, *addr);
+ j = find_last_bit((void *)addr, BITS_PER_LONG) & (BITS_PER_LONG - 1);
+ len += j / 4 + 1;
+ for (; len < 22; len++) {
+ qemu_fprintf(f, " ");
+ }
+
+ if (i == (col + 3)) {
+ qemu_fprintf(f, "\n");
+ }
+ }
+ qemu_fprintf(f, "\n");
+#endif
+}
+
static void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
{
CPULoongArchState *env = cpu_env(cs);
@@ -784,22 +860,8 @@
}
}
- qemu_fprintf(f, "CRMD=%016" PRIx64 "\n", env->CSR_CRMD);
- qemu_fprintf(f, "PRMD=%016" PRIx64 "\n", env->CSR_PRMD);
- qemu_fprintf(f, "EUEN=%016" PRIx64 "\n", env->CSR_EUEN);
- qemu_fprintf(f, "ESTAT=%016" PRIx64 "\n", env->CSR_ESTAT);
- qemu_fprintf(f, "ERA=%016" PRIx64 "\n", env->CSR_ERA);
- qemu_fprintf(f, "BADV=%016" PRIx64 "\n", env->CSR_BADV);
- qemu_fprintf(f, "BADI=%016" PRIx64 "\n", env->CSR_BADI);
- qemu_fprintf(f, "EENTRY=%016" PRIx64 "\n", env->CSR_EENTRY);
- qemu_fprintf(f, "PRCFG1=%016" PRIx64 ", PRCFG2=%016" PRIx64 ","
- " PRCFG3=%016" PRIx64 "\n",
- env->CSR_PRCFG1, env->CSR_PRCFG2, env->CSR_PRCFG3);
- qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY);
- qemu_fprintf(f, "TLBRBADV=%016" PRIx64 "\n", env->CSR_TLBRBADV);
- qemu_fprintf(f, "TLBRERA=%016" PRIx64 "\n", env->CSR_TLBRERA);
- qemu_fprintf(f, "TCFG=%016" PRIx64 "\n", env->CSR_TCFG);
- qemu_fprintf(f, "TVAL=%016" PRIx64 "\n", env->CSR_TVAL);
+ /* csr */
+ loongarch_cpu_dump_csr(cs, f);
/* fpr */
if (flags & CPU_DUMP_FPU) {
diff --git a/target/loongarch/csr.c b/target/loongarch/csr.c
new file mode 100644
index 0000000..7ea0a30
--- /dev/null
+++ b/target/loongarch/csr.c
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2025 Loongson Technology Corporation Limited
+ */
+#include <stddef.h>
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "csr.h"
+
+#define CSR_OFF_FUNCS(NAME, FL, RD, WR) \
+ [LOONGARCH_CSR_##NAME] = { \
+ .name = (stringify(NAME)), \
+ .offset = offsetof(CPULoongArchState, CSR_##NAME), \
+ .flags = FL, .readfn = RD, .writefn = WR \
+ }
+
+#define CSR_OFF_ARRAY(NAME, N) \
+ [LOONGARCH_CSR_##NAME(N)] = { \
+ .name = (stringify(NAME##N)), \
+ .offset = offsetof(CPULoongArchState, CSR_##NAME[N]), \
+ .flags = 0, .readfn = NULL, .writefn = NULL \
+ }
+
+#define CSR_OFF_FLAGS(NAME, FL) CSR_OFF_FUNCS(NAME, FL, NULL, NULL)
+#define CSR_OFF(NAME) CSR_OFF_FLAGS(NAME, 0)
+
+static CSRInfo csr_info[] = {
+ CSR_OFF_FLAGS(CRMD, CSRFL_EXITTB),
+ CSR_OFF(PRMD),
+ CSR_OFF_FLAGS(EUEN, CSRFL_EXITTB),
+ CSR_OFF_FLAGS(MISC, CSRFL_READONLY),
+ CSR_OFF(ECFG),
+ CSR_OFF_FLAGS(ESTAT, CSRFL_EXITTB),
+ CSR_OFF(ERA),
+ CSR_OFF(BADV),
+ CSR_OFF_FLAGS(BADI, CSRFL_READONLY),
+ CSR_OFF(EENTRY),
+ CSR_OFF(TLBIDX),
+ CSR_OFF(TLBEHI),
+ CSR_OFF(TLBELO0),
+ CSR_OFF(TLBELO1),
+ CSR_OFF_FLAGS(ASID, CSRFL_EXITTB),
+ CSR_OFF(PGDL),
+ CSR_OFF(PGDH),
+ CSR_OFF_FLAGS(PGD, CSRFL_READONLY),
+ CSR_OFF(PWCL),
+ CSR_OFF(PWCH),
+ CSR_OFF(STLBPS),
+ CSR_OFF(RVACFG),
+ CSR_OFF_FLAGS(CPUID, CSRFL_READONLY),
+ CSR_OFF_FLAGS(PRCFG1, CSRFL_READONLY),
+ CSR_OFF_FLAGS(PRCFG2, CSRFL_READONLY),
+ CSR_OFF_FLAGS(PRCFG3, CSRFL_READONLY),
+ CSR_OFF_ARRAY(SAVE, 0),
+ CSR_OFF_ARRAY(SAVE, 1),
+ CSR_OFF_ARRAY(SAVE, 2),
+ CSR_OFF_ARRAY(SAVE, 3),
+ CSR_OFF_ARRAY(SAVE, 4),
+ CSR_OFF_ARRAY(SAVE, 5),
+ CSR_OFF_ARRAY(SAVE, 6),
+ CSR_OFF_ARRAY(SAVE, 7),
+ CSR_OFF_ARRAY(SAVE, 8),
+ CSR_OFF_ARRAY(SAVE, 9),
+ CSR_OFF_ARRAY(SAVE, 10),
+ CSR_OFF_ARRAY(SAVE, 11),
+ CSR_OFF_ARRAY(SAVE, 12),
+ CSR_OFF_ARRAY(SAVE, 13),
+ CSR_OFF_ARRAY(SAVE, 14),
+ CSR_OFF_ARRAY(SAVE, 15),
+ CSR_OFF(TID),
+ CSR_OFF_FLAGS(TCFG, CSRFL_IO),
+ CSR_OFF_FLAGS(TVAL, CSRFL_READONLY | CSRFL_IO),
+ CSR_OFF(CNTC),
+ CSR_OFF_FLAGS(TICLR, CSRFL_IO),
+ CSR_OFF(LLBCTL),
+ CSR_OFF(IMPCTL1),
+ CSR_OFF(IMPCTL2),
+ CSR_OFF(TLBRENTRY),
+ CSR_OFF(TLBRBADV),
+ CSR_OFF(TLBRERA),
+ CSR_OFF(TLBRSAVE),
+ CSR_OFF(TLBRELO0),
+ CSR_OFF(TLBRELO1),
+ CSR_OFF(TLBREHI),
+ CSR_OFF(TLBRPRMD),
+ CSR_OFF(MERRCTL),
+ CSR_OFF(MERRINFO1),
+ CSR_OFF(MERRINFO2),
+ CSR_OFF(MERRENTRY),
+ CSR_OFF(MERRERA),
+ CSR_OFF(MERRSAVE),
+ CSR_OFF(CTAG),
+ CSR_OFF_ARRAY(DMW, 0),
+ CSR_OFF_ARRAY(DMW, 1),
+ CSR_OFF_ARRAY(DMW, 2),
+ CSR_OFF_ARRAY(DMW, 3),
+ CSR_OFF(DBG),
+ CSR_OFF(DERA),
+ CSR_OFF(DSAVE),
+};
+
+CSRInfo *get_csr(unsigned int csr_num)
+{
+ CSRInfo *csr;
+
+ if (csr_num >= ARRAY_SIZE(csr_info)) {
+ return NULL;
+ }
+
+ csr = &csr_info[csr_num];
+ if (csr->offset == 0) {
+ return NULL;
+ }
+
+ return csr;
+}
+
+bool set_csr_flag(unsigned int csr_num, int flag)
+{
+ CSRInfo *csr;
+
+ csr = get_csr(csr_num);
+ if (!csr) {
+ return false;
+ }
+
+ csr->flags |= flag;
+ return true;
+}
diff --git a/target/loongarch/csr.h b/target/loongarch/csr.h
new file mode 100644
index 0000000..81a656b
--- /dev/null
+++ b/target/loongarch/csr.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2025 Loongson Technology Corporation Limited
+ */
+
+#ifndef TARGET_LOONGARCH_CSR_H
+#define TARGET_LOONGARCH_CSR_H
+
+#include "cpu-csr.h"
+
+typedef void (*GenCSRFunc)(void);
+enum {
+ CSRFL_READONLY = (1 << 0),
+ CSRFL_EXITTB = (1 << 1),
+ CSRFL_IO = (1 << 2),
+ CSRFL_UNUSED = (1 << 3),
+};
+
+typedef struct {
+ const char *name;
+ int offset;
+ int flags;
+ GenCSRFunc readfn;
+ GenCSRFunc writefn;
+} CSRInfo;
+
+CSRInfo *get_csr(unsigned int csr_num);
+bool set_csr_flag(unsigned int csr_num, int flag);
+#endif /* TARGET_LOONGARCH_CSR_H */
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 7817318..20bd3e2 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -10,6 +10,7 @@
loongarch_system_ss.add(files(
'arch_dump.c',
'cpu_helper.c',
+ 'csr.c',
'loongarch-qmp-cmds.c',
'machine.c',
))
diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
index 30f9b83..3afa23a 100644
--- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
@@ -5,7 +5,7 @@
* LoongArch translation routines for the privileged instructions.
*/
-#include "cpu-csr.h"
+#include "csr.h"
#ifdef CONFIG_USER_ONLY
@@ -45,112 +45,6 @@
typedef void (*GenCSRRead)(TCGv dest, TCGv_ptr env);
typedef void (*GenCSRWrite)(TCGv dest, TCGv_ptr env, TCGv src);
-typedef struct {
- int offset;
- int flags;
- GenCSRRead readfn;
- GenCSRWrite writefn;
-} CSRInfo;
-
-enum {
- CSRFL_READONLY = (1 << 0),
- CSRFL_EXITTB = (1 << 1),
- CSRFL_IO = (1 << 2),
-};
-
-#define CSR_OFF_FUNCS(NAME, FL, RD, WR) \
- [LOONGARCH_CSR_##NAME] = { \
- .offset = offsetof(CPULoongArchState, CSR_##NAME), \
- .flags = FL, .readfn = RD, .writefn = WR \
- }
-
-#define CSR_OFF_ARRAY(NAME, N) \
- [LOONGARCH_CSR_##NAME(N)] = { \
- .offset = offsetof(CPULoongArchState, CSR_##NAME[N]), \
- .flags = 0, .readfn = NULL, .writefn = NULL \
- }
-
-#define CSR_OFF_FLAGS(NAME, FL) \
- CSR_OFF_FUNCS(NAME, FL, NULL, NULL)
-
-#define CSR_OFF(NAME) \
- CSR_OFF_FLAGS(NAME, 0)
-
-static const CSRInfo csr_info[] = {
- CSR_OFF_FLAGS(CRMD, CSRFL_EXITTB),
- CSR_OFF(PRMD),
- CSR_OFF_FLAGS(EUEN, CSRFL_EXITTB),
- CSR_OFF_FLAGS(MISC, CSRFL_READONLY),
- CSR_OFF(ECFG),
- CSR_OFF_FUNCS(ESTAT, CSRFL_EXITTB, NULL, gen_helper_csrwr_estat),
- CSR_OFF(ERA),
- CSR_OFF(BADV),
- CSR_OFF_FLAGS(BADI, CSRFL_READONLY),
- CSR_OFF(EENTRY),
- CSR_OFF(TLBIDX),
- CSR_OFF(TLBEHI),
- CSR_OFF(TLBELO0),
- CSR_OFF(TLBELO1),
- CSR_OFF_FUNCS(ASID, CSRFL_EXITTB, NULL, gen_helper_csrwr_asid),
- CSR_OFF(PGDL),
- CSR_OFF(PGDH),
- CSR_OFF_FUNCS(PGD, CSRFL_READONLY, gen_helper_csrrd_pgd, NULL),
- CSR_OFF_FUNCS(PWCL, 0, NULL, gen_helper_csrwr_pwcl),
- CSR_OFF(PWCH),
- CSR_OFF(STLBPS),
- CSR_OFF(RVACFG),
- CSR_OFF_FUNCS(CPUID, CSRFL_READONLY, gen_helper_csrrd_cpuid, NULL),
- CSR_OFF_FLAGS(PRCFG1, CSRFL_READONLY),
- CSR_OFF_FLAGS(PRCFG2, CSRFL_READONLY),
- CSR_OFF_FLAGS(PRCFG3, CSRFL_READONLY),
- CSR_OFF_ARRAY(SAVE, 0),
- CSR_OFF_ARRAY(SAVE, 1),
- CSR_OFF_ARRAY(SAVE, 2),
- CSR_OFF_ARRAY(SAVE, 3),
- CSR_OFF_ARRAY(SAVE, 4),
- CSR_OFF_ARRAY(SAVE, 5),
- CSR_OFF_ARRAY(SAVE, 6),
- CSR_OFF_ARRAY(SAVE, 7),
- CSR_OFF_ARRAY(SAVE, 8),
- CSR_OFF_ARRAY(SAVE, 9),
- CSR_OFF_ARRAY(SAVE, 10),
- CSR_OFF_ARRAY(SAVE, 11),
- CSR_OFF_ARRAY(SAVE, 12),
- CSR_OFF_ARRAY(SAVE, 13),
- CSR_OFF_ARRAY(SAVE, 14),
- CSR_OFF_ARRAY(SAVE, 15),
- CSR_OFF(TID),
- CSR_OFF_FUNCS(TCFG, CSRFL_IO, NULL, gen_helper_csrwr_tcfg),
- CSR_OFF_FUNCS(TVAL, CSRFL_READONLY | CSRFL_IO, gen_helper_csrrd_tval, NULL),
- CSR_OFF(CNTC),
- CSR_OFF_FUNCS(TICLR, CSRFL_IO, NULL, gen_helper_csrwr_ticlr),
- CSR_OFF(LLBCTL),
- CSR_OFF(IMPCTL1),
- CSR_OFF(IMPCTL2),
- CSR_OFF(TLBRENTRY),
- CSR_OFF(TLBRBADV),
- CSR_OFF(TLBRERA),
- CSR_OFF(TLBRSAVE),
- CSR_OFF(TLBRELO0),
- CSR_OFF(TLBRELO1),
- CSR_OFF(TLBREHI),
- CSR_OFF(TLBRPRMD),
- CSR_OFF(MERRCTL),
- CSR_OFF(MERRINFO1),
- CSR_OFF(MERRINFO2),
- CSR_OFF(MERRENTRY),
- CSR_OFF(MERRERA),
- CSR_OFF(MERRSAVE),
- CSR_OFF(CTAG),
- CSR_OFF_ARRAY(DMW, 0),
- CSR_OFF_ARRAY(DMW, 1),
- CSR_OFF_ARRAY(DMW, 2),
- CSR_OFF_ARRAY(DMW, 3),
- CSR_OFF(DBG),
- CSR_OFF(DERA),
- CSR_OFF(DSAVE),
-};
-
static bool check_plv(DisasContext *ctx)
{
if (ctx->plv == MMU_PLV_USER) {
@@ -160,20 +54,37 @@
return false;
}
-static const CSRInfo *get_csr(unsigned csr_num)
+static bool set_csr_trans_func(unsigned int csr_num, GenCSRRead readfn,
+ GenCSRWrite writefn)
{
- const CSRInfo *csr;
+ CSRInfo *csr;
- if (csr_num >= ARRAY_SIZE(csr_info)) {
- return NULL;
+ csr = get_csr(csr_num);
+ if (!csr) {
+ return false;
}
- csr = &csr_info[csr_num];
- if (csr->offset == 0) {
- return NULL;
- }
- return csr;
+
+ csr->readfn = (GenCSRFunc)readfn;
+ csr->writefn = (GenCSRFunc)writefn;
+ return true;
}
+#define SET_CSR_FUNC(NAME, read, write) \
+ set_csr_trans_func(LOONGARCH_CSR_##NAME, read, write)
+
+void loongarch_csr_translate_init(void)
+{
+ SET_CSR_FUNC(ESTAT, NULL, gen_helper_csrwr_estat);
+ SET_CSR_FUNC(ASID, NULL, gen_helper_csrwr_asid);
+ SET_CSR_FUNC(PGD, gen_helper_csrrd_pgd, NULL);
+ SET_CSR_FUNC(PWCL, NULL, gen_helper_csrwr_pwcl);
+ SET_CSR_FUNC(CPUID, gen_helper_csrrd_cpuid, NULL);
+ SET_CSR_FUNC(TCFG, NULL, gen_helper_csrwr_tcfg);
+ SET_CSR_FUNC(TVAL, gen_helper_csrrd_tval, NULL);
+ SET_CSR_FUNC(TICLR, NULL, gen_helper_csrwr_ticlr);
+}
+#undef SET_CSR_FUNC
+
static bool check_csr_flags(DisasContext *ctx, const CSRInfo *csr, bool write)
{
if ((csr->flags & CSRFL_READONLY) && write) {
@@ -191,6 +102,7 @@
{
TCGv dest;
const CSRInfo *csr;
+ GenCSRRead readfn;
if (check_plv(ctx)) {
return false;
@@ -202,8 +114,9 @@
} else {
check_csr_flags(ctx, csr, false);
dest = gpr_dst(ctx, a->rd, EXT_NONE);
- if (csr->readfn) {
- csr->readfn(dest, tcg_env);
+ readfn = (GenCSRRead)csr->readfn;
+ if (readfn) {
+ readfn(dest, tcg_env);
} else {
tcg_gen_ld_tl(dest, tcg_env, csr->offset);
}
@@ -216,6 +129,7 @@
{
TCGv dest, src1;
const CSRInfo *csr;
+ GenCSRWrite writefn;
if (check_plv(ctx)) {
return false;
@@ -231,9 +145,10 @@
return false;
}
src1 = gpr_src(ctx, a->rd, EXT_NONE);
- if (csr->writefn) {
+ writefn = (GenCSRWrite)csr->writefn;
+ if (writefn) {
dest = gpr_dst(ctx, a->rd, EXT_NONE);
- csr->writefn(dest, tcg_env, src1);
+ writefn(dest, tcg_env, src1);
} else {
dest = tcg_temp_new();
tcg_gen_ld_tl(dest, tcg_env, csr->offset);
@@ -247,6 +162,7 @@
{
TCGv src1, mask, oldv, newv, temp;
const CSRInfo *csr;
+ GenCSRWrite writefn;
if (check_plv(ctx)) {
return false;
@@ -277,8 +193,9 @@
tcg_gen_andc_tl(temp, oldv, mask);
tcg_gen_or_tl(newv, newv, temp);
- if (csr->writefn) {
- csr->writefn(oldv, tcg_env, newv);
+ writefn = (GenCSRWrite)csr->writefn;
+ if (writefn) {
+ writefn(oldv, tcg_env, newv);
} else {
tcg_gen_st_tl(newv, tcg_env, csr->offset);
}
diff --git a/target/loongarch/tcg/tcg_loongarch.h b/target/loongarch/tcg/tcg_loongarch.h
new file mode 100644
index 0000000..da2539e
--- /dev/null
+++ b/target/loongarch/tcg/tcg_loongarch.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch TCG interface
+ *
+ * Copyright (c) 2025 Loongson Technology Corporation Limited
+ */
+#ifndef TARGET_LOONGARCH_TCG_LOONGARCH_H
+#define TARGET_LOONGARCH_TCG_LOONGARCH_H
+
+void loongarch_csr_translate_init(void);
+
+#endif /* TARGET_LOONGARCH_TCG_LOONGARCH_H */
diff --git a/target/loongarch/tcg/translate.c b/target/loongarch/tcg/translate.c
index 68be999..3480f54 100644
--- a/target/loongarch/tcg/translate.c
+++ b/target/loongarch/tcg/translate.c
@@ -16,6 +16,7 @@
#include "exec/log.h"
#include "qemu/qemu-print.h"
#include "fpu/softfloat.h"
+#include "tcg_loongarch.h"
#include "translate.h"
#include "internals.h"
#include "vec.h"
@@ -358,4 +359,8 @@
offsetof(CPULoongArchState, lladdr), "lladdr");
cpu_llval = tcg_global_mem_new(tcg_env,
offsetof(CPULoongArchState, llval), "llval");
+
+#ifndef CONFIG_USER_ONLY
+ loongarch_csr_translate_init();
+#endif
}