aboutsummaryrefslogtreecommitdiff
path: root/target/mips/tcg
diff options
context:
space:
mode:
authorJiaxun Yang <jiaxun.yang@flygoat.com>2023-05-21 19:01:46 +0100
committerPhilippe Mathieu-Daudé <philmd@linaro.org>2023-07-10 23:33:37 +0200
commit03afdc28b3ffb9315f9612052b2b1c250370c344 (patch)
treeee249151653cd27e74de274c92e23b31d4e10adb /target/mips/tcg
parentb263688d236bc07266ce393fdce8c9b6bfd9d8d8 (diff)
downloadqemu-03afdc28b3ffb9315f9612052b2b1c250370c344.zip
qemu-03afdc28b3ffb9315f9612052b2b1c250370c344.tar.gz
qemu-03afdc28b3ffb9315f9612052b2b1c250370c344.tar.bz2
target/mips: Implement Loongson CSR instructions
Loongson introduced CSR instructions since 3A4000, which looks similar to IOCSR and CPUCFG instructions we seen in LoongArch. Unfortunately we don't have much document about those instructions, bit fields of CPUCFG instructions and IOCSR registers can be found at 3A4000's user manual, while instruction encodings can be found at arch/mips/include/asm/mach-loongson64/loongson_regs.h from Linux Kernel. Our predefined CPUCFG bits are differ from actual 3A4000, since we can't emulate all CPUCFG features present in 3A4000 for now, we just enable bits for what we have in TCG. Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com> Message-Id: <20230521214832.20145-2-jiaxun.yang@flygoat.com> [JY: Fixed typo in ase_lcsr_available(), retrict GEN_FALSE_TRANS] [PMD: Fix meson's mips_softmmu_ss -> mips_system_ss, restrict AddressSpace/MemoryRegion to SysEmu] Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Diffstat (limited to 'target/mips/tcg')
-rw-r--r--target/mips/tcg/lcsr.decode17
-rw-r--r--target/mips/tcg/lcsr_translate.c75
-rw-r--r--target/mips/tcg/meson.build2
-rw-r--r--target/mips/tcg/op_helper.c16
-rw-r--r--target/mips/tcg/sysemu/lcsr_helper.c45
-rw-r--r--target/mips/tcg/sysemu/meson.build4
-rw-r--r--target/mips/tcg/sysemu_helper.h.inc8
-rw-r--r--target/mips/tcg/translate.c3
-rw-r--r--target/mips/tcg/translate.h1
9 files changed, 171 insertions, 0 deletions
diff --git a/target/mips/tcg/lcsr.decode b/target/mips/tcg/lcsr.decode
new file mode 100644
index 0000000..960ef8b
--- /dev/null
+++ b/target/mips/tcg/lcsr.decode
@@ -0,0 +1,17 @@
+# Loongson CSR instructions
+#
+# Copyright (C) 2023 Jiaxun Yang <jiaxun.yang@flygoat.com>
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+
+&r rs rt rd sa
+
+@rs_rd ...... rs:5 ..... rd:5 ..... ...... &r rt=0 sa=0
+
+CPUCFG 110010 ..... 01000 ..... 00100 011000 @rs_rd
+
+RDCSR 110010 ..... 00000 ..... 00100 011000 @rs_rd
+WRCSR 110010 ..... 00001 ..... 00100 011000 @rs_rd
+DRDCSR 110010 ..... 00010 ..... 00100 011000 @rs_rd
+DWRCSR 110010 ..... 00011 ..... 00100 011000 @rs_rd
diff --git a/target/mips/tcg/lcsr_translate.c b/target/mips/tcg/lcsr_translate.c
new file mode 100644
index 0000000..9f2a5f4
--- /dev/null
+++ b/target/mips/tcg/lcsr_translate.c
@@ -0,0 +1,75 @@
+/*
+ * Loongson CSR instructions translation routines
+ *
+ * Copyright (c) 2023 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "tcg/tcg-op.h"
+#include "tcg/tcg-op-gvec.h"
+#include "exec/helper-gen.h"
+#include "translate.h"
+
+/* Include the auto-generated decoder. */
+#include "decode-lcsr.c.inc"
+
+static bool trans_CPUCFG(DisasContext *ctx, arg_CPUCFG *a)
+{
+ TCGv dest = tcg_temp_new();
+ TCGv src1 = tcg_temp_new();
+
+ gen_load_gpr(src1, a->rs);
+ gen_helper_lcsr_cpucfg(dest, cpu_env, src1);
+ gen_store_gpr(dest, a->rd);
+
+ return true;
+}
+
+#ifndef CONFIG_USER_ONLY
+static bool gen_rdcsr(DisasContext *ctx, arg_r *a,
+ void (*func)(TCGv, TCGv_ptr, TCGv))
+{
+ TCGv dest = tcg_temp_new();
+ TCGv src1 = tcg_temp_new();
+
+ check_cp0_enabled(ctx);
+ gen_load_gpr(src1, a->rs);
+ func(dest, cpu_env, src1);
+ gen_store_gpr(dest, a->rd);
+
+ return true;
+}
+
+static bool gen_wrcsr(DisasContext *ctx, arg_r *a,
+ void (*func)(TCGv_ptr, TCGv, TCGv))
+{
+ TCGv val = tcg_temp_new();
+ TCGv addr = tcg_temp_new();
+
+ check_cp0_enabled(ctx);
+ gen_load_gpr(addr, a->rs);
+ gen_load_gpr(val, a->rd);
+ func(cpu_env, addr, val);
+
+ return true;
+}
+
+TRANS(RDCSR, gen_rdcsr, gen_helper_lcsr_rdcsr)
+TRANS(DRDCSR, gen_rdcsr, gen_helper_lcsr_drdcsr)
+TRANS(WRCSR, gen_wrcsr, gen_helper_lcsr_wrcsr)
+TRANS(DWRCSR, gen_wrcsr, gen_helper_lcsr_dwrcsr)
+#else
+#define GEN_FALSE_TRANS(name) \
+static bool trans_##name(DisasContext *ctx, arg_##name * a) \
+{ \
+ return false; \
+}
+
+GEN_FALSE_TRANS(RDCSR)
+GEN_FALSE_TRANS(DRDCSR)
+GEN_FALSE_TRANS(WRCSR)
+GEN_FALSE_TRANS(DWRCSR)
+#endif
diff --git a/target/mips/tcg/meson.build b/target/mips/tcg/meson.build
index 7ee969e..ea7fb58 100644
--- a/target/mips/tcg/meson.build
+++ b/target/mips/tcg/meson.build
@@ -4,6 +4,7 @@ gen = [
decodetree.process('tx79.decode', extra_args: '--static-decode=decode_tx79'),
decodetree.process('vr54xx.decode', extra_args: '--decode=decode_ext_vr54xx'),
decodetree.process('octeon.decode', extra_args: '--decode=decode_ext_octeon'),
+ decodetree.process('lcsr.decode', extra_args: '--decode=decode_ase_lcsr'),
]
mips_ss.add(gen)
@@ -26,6 +27,7 @@ mips_ss.add(files(
mips_ss.add(when: 'TARGET_MIPS64', if_true: files(
'tx79_translate.c',
'octeon_translate.c',
+ 'lcsr_translate.c',
), if_false: files(
'mxu_translate.c',
))
diff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c
index ef3dafc..98935b5 100644
--- a/target/mips/tcg/op_helper.c
+++ b/target/mips/tcg/op_helper.c
@@ -257,6 +257,22 @@ void helper_pmon(CPUMIPSState *env, int function)
}
}
+#ifdef TARGET_MIPS64
+target_ulong helper_lcsr_cpucfg(CPUMIPSState *env, target_ulong rs)
+{
+ switch (rs) {
+ case 0:
+ return env->CP0_PRid;
+ case 1:
+ return env->lcsr_cpucfg1;
+ case 2:
+ return env->lcsr_cpucfg2;
+ default:
+ return 0;
+ }
+}
+#endif
+
#if !defined(CONFIG_USER_ONLY)
void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
diff --git a/target/mips/tcg/sysemu/lcsr_helper.c b/target/mips/tcg/sysemu/lcsr_helper.c
new file mode 100644
index 0000000..942143d
--- /dev/null
+++ b/target/mips/tcg/sysemu/lcsr_helper.c
@@ -0,0 +1,45 @@
+/*
+ * Loongson CSR instructions translation routines
+ *
+ * Copyright (c) 2023 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "cpu.h"
+#include "internal.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+
+#define GET_MEMTXATTRS(cas) \
+ ((MemTxAttrs){.requester_id = env_cpu(cas)->cpu_index})
+
+uint64_t helper_lcsr_rdcsr(CPUMIPSState *env, target_ulong r_addr)
+{
+ return address_space_ldl(&env->iocsr.as, r_addr,
+ GET_MEMTXATTRS(env), NULL);
+}
+
+uint64_t helper_lcsr_drdcsr(CPUMIPSState *env, target_ulong r_addr)
+{
+ return address_space_ldq(&env->iocsr.as, r_addr,
+ GET_MEMTXATTRS(env), NULL);
+}
+
+void helper_lcsr_wrcsr(CPUMIPSState *env, target_ulong w_addr,
+ target_ulong val)
+{
+ address_space_stl(&env->iocsr.as, w_addr,
+ val, GET_MEMTXATTRS(env), NULL);
+}
+
+void helper_lcsr_dwrcsr(CPUMIPSState *env, target_ulong w_addr,
+ target_ulong val)
+{
+ address_space_stq(&env->iocsr.as, w_addr,
+ val, GET_MEMTXATTRS(env), NULL);
+}
diff --git a/target/mips/tcg/sysemu/meson.build b/target/mips/tcg/sysemu/meson.build
index 43b35b3..ec665a4 100644
--- a/target/mips/tcg/sysemu/meson.build
+++ b/target/mips/tcg/sysemu/meson.build
@@ -4,3 +4,7 @@ mips_system_ss.add(files(
'special_helper.c',
'tlb_helper.c',
))
+
+mips_system_ss.add(when: 'TARGET_MIPS64', if_true: files(
+ 'lcsr_helper.c',
+))
diff --git a/target/mips/tcg/sysemu_helper.h.inc b/target/mips/tcg/sysemu_helper.h.inc
index af585b5..f163af1 100644
--- a/target/mips/tcg/sysemu_helper.h.inc
+++ b/target/mips/tcg/sysemu_helper.h.inc
@@ -181,3 +181,11 @@ DEF_HELPER_1(eret, void, env)
DEF_HELPER_1(eretnc, void, env)
DEF_HELPER_1(deret, void, env)
DEF_HELPER_3(cache, void, env, tl, i32)
+
+#ifdef TARGET_MIPS64
+/* Longson CSR */
+DEF_HELPER_2(lcsr_rdcsr, i64, env, tl)
+DEF_HELPER_2(lcsr_drdcsr, i64, env, tl)
+DEF_HELPER_3(lcsr_wrcsr, void, env, tl, tl)
+DEF_HELPER_3(lcsr_dwrcsr, void, env, tl, tl)
+#endif
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 74af91e..7abbb0b 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -15352,6 +15352,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
return;
}
#if defined(TARGET_MIPS64)
+ if (ase_lcsr_available(env) && decode_ase_lcsr(ctx, ctx->opcode)) {
+ return;
+ }
if (cpu_supports_isa(env, INSN_OCTEON) && decode_ext_octeon(ctx, ctx->opcode)) {
return;
}
diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h
index 3b0498a..db3dc93 100644
--- a/target/mips/tcg/translate.h
+++ b/target/mips/tcg/translate.h
@@ -221,6 +221,7 @@ bool decode_isa_rel6(DisasContext *ctx, uint32_t insn);
bool decode_ase_msa(DisasContext *ctx, uint32_t insn);
bool decode_ext_txx9(DisasContext *ctx, uint32_t insn);
#if defined(TARGET_MIPS64)
+bool decode_ase_lcsr(DisasContext *ctx, uint32_t insn);
bool decode_ext_tx79(DisasContext *ctx, uint32_t insn);
bool decode_ext_octeon(DisasContext *ctx, uint32_t insn);
#endif