This includes:
- IOCSR{RD/WR}.{B/H/W/D}
Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao<gaosong@loongson.cn>
---
target/loongarch/cpu.c | 8 ++
target/loongarch/cpu.h | 4 +
target/loongarch/disas.c | 8 ++
target/loongarch/helper.h | 2 +
target/loongarch/insn_trans/trans_core.c.inc | 103 ++++++++++++++++
target/loongarch/insns.decode | 9 ++
target/loongarch/iocsr_helper.c | 120 +++++++++++++++++++
target/loongarch/meson.build | 1 +
8 files changed, 255 insertions(+)
create mode 100644 target/loongarch/iocsr_helper.c
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 780eb96a3c..571092ce53 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -158,6 +158,14 @@ static void loongarch_3a5000_initfn(Object *obj)
env->cpucfg[20] = data;
env->CSR_ASID = FIELD_DP64(0, CSR_ASID, ASIDBITS, 0xa);
+
+#ifndef CONFIG_USER_ONLY
+ env->address_space_iocsr = g_malloc(sizeof(*env->address_space_iocsr));
+ env->system_iocsr = g_malloc(sizeof(*env->system_iocsr));
+ memory_region_init_io(env->system_iocsr, obj, NULL,
+ env, "iocsr", UINT64_MAX);
+ address_space_init(env->address_space_iocsr, env->system_iocsr, "IOCSR");
+#endif
}
static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 2a1841a708..ddb69ffecf 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -151,6 +151,7 @@ extern const char * const fregnames[32];
#define N_IRQS 14
#define IRQ_TIMER 11
+#define IRQ_IPI 12
#define LOONGARCH_TLB_MAX (2048 + 64) /* 2048 STLB + 64 MTLB */
#define LOONGARCH_STLB 2048 /* 2048 STLB */
@@ -257,6 +258,9 @@ struct CPULoongArchState {
#ifndef CONFIG_USER_ONLY
LoongArchTLB tlb[LOONGARCH_TLB_MAX];
+
+ AddressSpace *address_space_iocsr;
+ MemoryRegion *system_iocsr;
#endif
};
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index de683bb88b..cbb264a318 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -531,6 +531,14 @@ INSN(bgeu, rr_offs)
INSN(csrrd, r_csr)
INSN(csrwr, r_csr)
INSN(csrxchg, rr_csr)
+INSN(iocsrrd_b, rr)
+INSN(iocsrrd_h, rr)
+INSN(iocsrrd_w, rr)
+INSN(iocsrrd_d, rr)
+INSN(iocsrwr_b, rr)
+INSN(iocsrwr_h, rr)
+INSN(iocsrwr_w, rr)
+INSN(iocsrwr_d, rr)
#define output_fcmp(C, PREFIX, SUFFIX) \
{
\
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 036dbf31f8..1bcd082858 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -98,4 +98,6 @@ DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void,
env, i32)
DEF_HELPER_2(csr_rdq, i64, env, i64)
DEF_HELPER_3(csr_wrq, i64, env, tl, i64)
DEF_HELPER_4(csr_xchgq, i64, env, tl, tl, i64)
+DEF_HELPER_3(iocsr_read, i64, env, tl, i32)
+DEF_HELPER_4(iocsr_write, void, env, tl, tl, i32)
#endif /* !CONFIG_USER_ONLY */
diff --git a/target/loongarch/insn_trans/trans_core.c.inc
b/target/loongarch/insn_trans/trans_core.c.inc
index 7d2cfe3534..592d2a339e 100644
--- a/target/loongarch/insn_trans/trans_core.c.inc
+++ b/target/loongarch/insn_trans/trans_core.c.inc
@@ -20,6 +20,14 @@ static bool trans_##name(DisasContext *ctx, arg_##name * a)
\
GEN_FALSE_TRANS(csrrd)
GEN_FALSE_TRANS(csrwr)
GEN_FALSE_TRANS(csrxchg)
+GEN_FALSE_TRANS(iocsrrd_b)
+GEN_FALSE_TRANS(iocsrrd_h)
+GEN_FALSE_TRANS(iocsrrd_w)
+GEN_FALSE_TRANS(iocsrrd_d)
+GEN_FALSE_TRANS(iocsrwr_b)
+GEN_FALSE_TRANS(iocsrwr_h)
+GEN_FALSE_TRANS(iocsrwr_w)
+GEN_FALSE_TRANS(iocsrwr_d)
#else
@@ -120,4 +128,99 @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a)
return true;
}
+static bool trans_iocsrrd_b(DisasContext *ctx, arg_iocsrrd_b *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if (check_plv(ctx)) {
+ return false;
+ }
+ gen_helper_iocsr_read(dest, cpu_env, src1, tcg_constant_i32(1));
+ return true;
+}
+
+static bool trans_iocsrrd_h(DisasContext *ctx, arg_iocsrrd_h *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if (check_plv(ctx)) {
+ return false;
+ }
+ gen_helper_iocsr_read(dest, cpu_env, src1, tcg_constant_i32(2));
+ return true;
+}
+
+static bool trans_iocsrrd_w(DisasContext *ctx, arg_iocsrrd_w *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if (check_plv(ctx)) {
+ return false;
+ }
+ gen_helper_iocsr_read(dest, cpu_env, src1, tcg_constant_i32(4));
+ return true;
+}
+
+static bool trans_iocsrrd_d(DisasContext *ctx, arg_iocsrrd_d *a)
+{
+ TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+ TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if (check_plv(ctx)) {
+ return false;
+ }
+ gen_helper_iocsr_read(dest, cpu_env, src1, tcg_constant_i32(8));
+ return true;
+}
+
+static bool trans_iocsrwr_b(DisasContext *ctx, arg_iocsrwr_b *a)
+{
+ TCGv val = gpr_src(ctx, a->rd, EXT_NONE);
+ TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if (check_plv(ctx)) {
+ return false;
+ }
+ gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(1));
+ return true;
+}
+
+static bool trans_iocsrwr_h(DisasContext *ctx, arg_iocsrwr_h *a)
+{
+ TCGv val = gpr_src(ctx, a->rd, EXT_NONE);
+ TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if (check_plv(ctx)) {
+ return false;
+ }
+ gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(2));
+ return true;
+}
+
+static bool trans_iocsrwr_w(DisasContext *ctx, arg_iocsrwr_w *a)
+{
+ TCGv val = gpr_src(ctx, a->rd, EXT_NONE);
+ TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if (check_plv(ctx)) {
+ return false;
+ }
+ gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(4));
+ return true;
+}
+
+static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a)
+{
+ TCGv val = gpr_src(ctx, a->rd, EXT_NONE);
+ TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+
+ if (check_plv(ctx)) {
+ return false;
+ }
+ gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(8));
+ return true;
+}
#endif
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 647fcb9def..9a43f288c3 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -453,3 +453,12 @@ bgeu 0110 11 ................ ..... .....
@rr_offs16
csrwr 0000 0100 .............. 00001 ..... @r_csr
csrxchg 0000 0100 .............. ..... ..... @rr_csr
}
+
+iocsrrd_b 0000 01100100 10000 00000 ..... ..... @rr
+iocsrrd_h 0000 01100100 10000 00001 ..... ..... @rr
+iocsrrd_w 0000 01100100 10000 00010 ..... ..... @rr
+iocsrrd_d 0000 01100100 10000 00011 ..... ..... @rr
+iocsrwr_b 0000 01100100 10000 00100 ..... ..... @rr
+iocsrwr_h 0000 01100100 10000 00101 ..... ..... @rr
+iocsrwr_w 0000 01100100 10000 00110 ..... ..... @rr
+iocsrwr_d 0000 01100100 10000 00111 ..... ..... @rr
diff --git a/target/loongarch/iocsr_helper.c b/target/loongarch/iocsr_helper.c
new file mode 100644
index 0000000000..f9efe2517f
--- /dev/null
+++ b/target/loongarch/iocsr_helper.c
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation helpers for iocsr read/write