Hi Jiaxun,

On 21/5/23 23:48, Jiaxun Yang wrote:
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.y...@flygoat.com>
---
  target/mips/cpu-defs.c.inc           |  9 ++++
  target/mips/cpu.c                    |  8 ++++
  target/mips/cpu.h                    | 40 ++++++++++++++++
  target/mips/helper.h                 |  4 ++
  target/mips/internal.h               |  2 +
  target/mips/tcg/lcsr.decode          | 17 +++++++
  target/mips/tcg/lcsr_translate.c     | 69 ++++++++++++++++++++++++++++
  target/mips/tcg/meson.build          |  2 +
  target/mips/tcg/op_helper.c          | 16 +++++++
  target/mips/tcg/sysemu/lcsr_helper.c | 45 ++++++++++++++++++
  target/mips/tcg/sysemu/meson.build   |  4 ++
  target/mips/tcg/sysemu_helper.h.inc  |  8 ++++
  target/mips/tcg/translate.c          |  3 ++
  target/mips/tcg/translate.h          |  7 +++
  14 files changed, 234 insertions(+)
  create mode 100644 target/mips/tcg/lcsr.decode
  create mode 100644 target/mips/tcg/lcsr_translate.c
  create mode 100644 target/mips/tcg/sysemu/lcsr_helper.c


  static char *mips_cpu_type_name(const char *cpu_model)
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 1b8107b0af86..f63b128ff3d3 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -3,6 +3,9 @@
#include "cpu-qom.h"
  #include "exec/cpu-defs.h"
+#ifndef CONFIG_USER_ONLY
+#include "exec/memory.h"
+#endif
  #include "fpu/softfloat-types.h"
  #include "hw/clock.h"
  #include "mips-defs.h"
@@ -1068,6 +1071,33 @@ typedef struct CPUArchState {
   */
      int32_t CP0_DESAVE;
      target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
+/*
+ * Loongson CSR CPUCFG registers
+ */
+    uint32_t lcsr_cpucfg1;
+#define CPUCFG1_FP     0
+#define CPUCFG1_FPREV  1
+#define CPUCFG1_MMI    4
+#define CPUCFG1_MSA1   5
+#define CPUCFG1_MSA2   6
+#define CPUCFG1_LSLDR0 16
+#define CPUCFG1_LSPERF 17
+#define CPUCFG1_LSPERFX 18
+#define CPUCFG1_LSSYNCI 19
+#define CPUCFG1_LLEXC   20
+#define CPUCFG1_SCRAND  21
+#define CPUCFG1_MUALP   25
+#define CPUCFG1_KMUALEN 26
+#define CPUCFG1_ITLBT   27
+#define CPUCFG1_SFBP    29
+#define CPUCFG1_CDMAP   30
+    uint32_t lcsr_cpucfg2;
+#define CPUCFG2_LEXT1   0
+#define CPUCFG2_LEXT2   1
+#define CPUCFG2_LEXT3   2
+#define CPUCFG2_LSPW    3
+#define CPUCFG2_LCSRP   27
+#define CPUCFG2_LDISBLIKELY 28
/* We waste some space so we can handle shadow registers like TCs. */
      TCState tcs[MIPS_SHADOW_SET_MAX];
@@ -1162,6 +1192,10 @@ typedef struct CPUArchState {
      QEMUTimer *timer; /* Internal timer */
      Clock *count_clock; /* CP0_Count clock */
      target_ulong exception_base; /* ExceptionBase input to the core */
+
+    /* Loongson IOCSR memory */

Preferrably:

   struct {

+    AddressSpace address_space_iocsr;

       AddressSpace as;

+    MemoryRegion system_iocsr;

       MemoryRegion mr;

    } iocsr;

  } CPUMIPSState;
/**
@@ -1281,6 +1315,12 @@ static inline bool ase_msa_available(CPUMIPSState *env)
      return env->CP0_Config3 & (1 << CP0C3_MSAP);
  }
+/* Check presence of Loongson CSR instructions */
+static inline bool ase_lcsr_available(CPUMIPSState *env)
+{
+    return env->lcsr_cpucfg1 & (1 << CPUCFG2_LCSRP);

You are checking CPUCFG1_ITLBT. Surely you want lcsr_cpucfg2 instead.

+}

--- a/target/mips/tcg/translate.h
+++ b/target/mips/tcg/translate.h
@@ -218,6 +218,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
@@ -231,6 +232,12 @@ bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn);
      static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
      { return FUNC(ctx, a, __VA_ARGS__); }
+#define GEN_FALSE_TRANS(name) \
+static bool trans_##name(DisasContext *ctx, arg_##name * a)  \
+{   \
+    return false;   \
+}

I'm not a big fan of this generic GEN_FALSE_TRANS() macro.

Otherwise LGTM!

Reply via email to