From: Song Gao <gaosong@loongson.cn>
To: qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org, thuth@redhat.com,
richard.henderson@linaro.org, laurent@vivier.eu,
maobibo@loongson.cn, alistair.francis@wdc.com,
pbonzini@redhat.com, philmd@redhat.com
Subject: [PATCH 11/20] target/loongarch: Add fixed point atomic instruction translation
Date: Mon, 28 Jun 2021 20:04:36 +0800 [thread overview]
Message-ID: <1624881885-31692-12-git-send-email-gaosong@loongson.cn> (raw)
In-Reply-To: <1624881885-31692-1-git-send-email-gaosong@loongson.cn>
This patch implement fixed point atomic instruction translation.
This includes:
- LL.{W/D}, SC.{W/D}
- AM{SWAP/ADD/AND/OR/XOR/MAX/MIN}[_DB].{W/D}
- AM{MAX/MIN}[_DB].{WU/DU}
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/insns.decode | 44 ++++++++++++
target/loongarch/instmap.h | 2 +
target/loongarch/trans.inc.c | 155 ++++++++++++++++++++++++++++++++++++++++++
target/loongarch/translate.c | 54 +++++++++++++++
4 files changed, 255 insertions(+)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index c5c08c8..beb2e4a 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -219,3 +219,47 @@ stle_b 0011 10000111 11100 ..... ..... ..... @fmt_rdrjrk
stle_h 0011 10000111 11101 ..... ..... ..... @fmt_rdrjrk
stle_w 0011 10000111 11110 ..... ..... ..... @fmt_rdrjrk
stle_d 0011 10000111 11111 ..... ..... ..... @fmt_rdrjrk
+
+#
+# Fixed point atomic instruction
+#
+ll_w 0010 0000 .............. ..... ..... @fmt_rdrjsi14
+sc_w 0010 0001 .............. ..... ..... @fmt_rdrjsi14
+ll_d 0010 0010 .............. ..... ..... @fmt_rdrjsi14
+sc_d 0010 0011 .............. ..... ..... @fmt_rdrjsi14
+amswap_w 0011 10000110 00000 ..... ..... ..... @fmt_rdrjrk
+amswap_d 0011 10000110 00001 ..... ..... ..... @fmt_rdrjrk
+amadd_w 0011 10000110 00010 ..... ..... ..... @fmt_rdrjrk
+amadd_d 0011 10000110 00011 ..... ..... ..... @fmt_rdrjrk
+amand_w 0011 10000110 00100 ..... ..... ..... @fmt_rdrjrk
+amand_d 0011 10000110 00101 ..... ..... ..... @fmt_rdrjrk
+amor_w 0011 10000110 00110 ..... ..... ..... @fmt_rdrjrk
+amor_d 0011 10000110 00111 ..... ..... ..... @fmt_rdrjrk
+amxor_w 0011 10000110 01000 ..... ..... ..... @fmt_rdrjrk
+amxor_d 0011 10000110 01001 ..... ..... ..... @fmt_rdrjrk
+ammax_w 0011 10000110 01010 ..... ..... ..... @fmt_rdrjrk
+ammax_d 0011 10000110 01011 ..... ..... ..... @fmt_rdrjrk
+ammin_w 0011 10000110 01100 ..... ..... ..... @fmt_rdrjrk
+ammin_d 0011 10000110 01101 ..... ..... ..... @fmt_rdrjrk
+ammax_wu 0011 10000110 01110 ..... ..... ..... @fmt_rdrjrk
+ammax_du 0011 10000110 01111 ..... ..... ..... @fmt_rdrjrk
+ammin_wu 0011 10000110 10000 ..... ..... ..... @fmt_rdrjrk
+ammin_du 0011 10000110 10001 ..... ..... ..... @fmt_rdrjrk
+amswap_db_w 0011 10000110 10010 ..... ..... ..... @fmt_rdrjrk
+amswap_db_d 0011 10000110 10011 ..... ..... ..... @fmt_rdrjrk
+amadd_db_w 0011 10000110 10100 ..... ..... ..... @fmt_rdrjrk
+amadd_db_d 0011 10000110 10101 ..... ..... ..... @fmt_rdrjrk
+amand_db_w 0011 10000110 10110 ..... ..... ..... @fmt_rdrjrk
+amand_db_d 0011 10000110 10111 ..... ..... ..... @fmt_rdrjrk
+amor_db_w 0011 10000110 11000 ..... ..... ..... @fmt_rdrjrk
+amor_db_d 0011 10000110 11001 ..... ..... ..... @fmt_rdrjrk
+amxor_db_w 0011 10000110 11010 ..... ..... ..... @fmt_rdrjrk
+amxor_db_d 0011 10000110 11011 ..... ..... ..... @fmt_rdrjrk
+ammax_db_w 0011 10000110 11100 ..... ..... ..... @fmt_rdrjrk
+ammax_db_d 0011 10000110 11101 ..... ..... ..... @fmt_rdrjrk
+ammin_db_w 0011 10000110 11110 ..... ..... ..... @fmt_rdrjrk
+ammin_db_d 0011 10000110 11111 ..... ..... ..... @fmt_rdrjrk
+ammax_db_wu 0011 10000111 00000 ..... ..... ..... @fmt_rdrjrk
+ammax_db_du 0011 10000111 00001 ..... ..... ..... @fmt_rdrjrk
+ammin_db_wu 0011 10000111 00010 ..... ..... ..... @fmt_rdrjrk
+ammin_db_du 0011 10000111 00011 ..... ..... ..... @fmt_rdrjrk
diff --git a/target/loongarch/instmap.h b/target/loongarch/instmap.h
index b6ddb7d..ea5396e 100644
--- a/target/loongarch/instmap.h
+++ b/target/loongarch/instmap.h
@@ -92,6 +92,8 @@ enum {
LA_OPC_LD_HU = (0x0A9 << 22),
LA_OPC_LD_WU = (0x0AA << 22),
+ LA_OPC_LL_W = (0x20 << 24),
+ LA_OPC_LL_D = (0x22 << 24),
LA_OPC_LDPTR_W = (0x24 << 24),
LA_OPC_STPTR_W = (0x25 << 24),
LA_OPC_LDPTR_D = (0x26 << 24),
diff --git a/target/loongarch/trans.inc.c b/target/loongarch/trans.inc.c
index 9880a7f..3f1e64f 100644
--- a/target/loongarch/trans.inc.c
+++ b/target/loongarch/trans.inc.c
@@ -1178,3 +1178,158 @@ static bool trans_stle_d(DisasContext *ctx, arg_stle_d *a)
}
#undef DECL_ARG
+
+/* Fixed point atomic instruction translation */
+static bool trans_ll_w(DisasContext *ctx, arg_ll_w *a)
+{
+ gen_loongarch_ld(ctx, LA_OPC_LL_W, a->rd, a->rj, a->si14 << 2);
+ return true;
+}
+
+static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a)
+{
+ gen_loongarch_st_cond(ctx, a->rd, a->rj, a->si14 << 2, MO_TESL, false);
+ return true;
+}
+
+static bool trans_ll_d(DisasContext *ctx, arg_ll_d *a)
+{
+ gen_loongarch_ld(ctx, LA_OPC_LL_D, a->rd, a->rj, a->si14 << 2);
+ return true;
+}
+
+static bool trans_sc_d(DisasContext *ctx, arg_sc_d *a)
+{
+ gen_loongarch_st_cond(ctx, a->rd, a->rj, a->si14 << 2, MO_TEQ, false);
+ return true;
+}
+
+#define TRANS_AM_W(name, op) \
+static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \
+{ \
+ if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \
+ printf("%s: warning, register equal\n", __func__); \
+ return false; \
+ } \
+ int mem_idx = ctx->mem_idx; \
+ TCGv addr = tcg_temp_new(); \
+ TCGv val = tcg_temp_new(); \
+ TCGv ret = tcg_temp_new(); \
+ \
+ gen_load_gpr(addr, a->rj); \
+ gen_load_gpr(val, a->rk); \
+ tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TESL | \
+ ctx->default_tcg_memop_mask); \
+ gen_store_gpr(ret, a->rd); \
+ \
+ tcg_temp_free(addr); \
+ tcg_temp_free(val); \
+ tcg_temp_free(ret); \
+ return true; \
+}
+#define TRANS_AM_D(name, op) \
+static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \
+{ \
+ if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \
+ printf("%s: warning, register equal\n", __func__); \
+ return false; \
+ } \
+ int mem_idx = ctx->mem_idx; \
+ TCGv addr = tcg_temp_new(); \
+ TCGv val = tcg_temp_new(); \
+ TCGv ret = tcg_temp_new(); \
+ \
+ gen_load_gpr(addr, a->rj); \
+ gen_load_gpr(val, a->rk); \
+ tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TEQ | \
+ ctx->default_tcg_memop_mask); \
+ gen_store_gpr(ret, a->rd); \
+ \
+ tcg_temp_free(addr); \
+ tcg_temp_free(val); \
+ tcg_temp_free(ret); \
+ return true; \
+}
+#define TRANS_AM(name, op) \
+ TRANS_AM_W(name##_w, op) \
+ TRANS_AM_D(name##_d, op)
+TRANS_AM(amswap, xchg) /* trans_amswap_w, trans_amswap_d */
+TRANS_AM(amadd, fetch_add) /* trans_amadd_w, trans_amadd_d */
+TRANS_AM(amand, fetch_and) /* trans_amand_w, trans_amand_d */
+TRANS_AM(amor, fetch_or) /* trans_amor_w, trans_amor_d */
+TRANS_AM(amxor, fetch_xor) /* trans_amxor_w, trans_amxor_d */
+TRANS_AM(ammax, fetch_smax) /* trans_ammax_w, trans_ammax_d */
+TRANS_AM(ammin, fetch_smin) /* trans_ammin_w, trans_ammin_d */
+TRANS_AM_W(ammax_wu, fetch_umax) /* trans_ammax_wu */
+TRANS_AM_D(ammax_du, fetch_umax) /* trans_ammax_du */
+TRANS_AM_W(ammin_wu, fetch_umin) /* trans_ammin_wu */
+TRANS_AM_D(ammin_du, fetch_umin) /* trans_ammin_du */
+#undef TRANS_AM
+#undef TRANS_AM_W
+#undef TRANS_AM_D
+
+#define TRANS_AM_DB_W(name, op) \
+static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \
+{ \
+ if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \
+ printf("%s: warning, register equal\n", __func__); \
+ return false; \
+ } \
+ int mem_idx = ctx->mem_idx; \
+ TCGv addr = tcg_temp_new(); \
+ TCGv val = tcg_temp_new(); \
+ TCGv ret = tcg_temp_new(); \
+ \
+ gen_loongarch_sync(0x10); \
+ gen_load_gpr(addr, a->rj); \
+ gen_load_gpr(val, a->rk); \
+ tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TESL | \
+ ctx->default_tcg_memop_mask); \
+ gen_store_gpr(ret, a->rd); \
+ \
+ tcg_temp_free(addr); \
+ tcg_temp_free(val); \
+ tcg_temp_free(ret); \
+ return true; \
+}
+#define TRANS_AM_DB_D(name, op) \
+static bool trans_ ## name(DisasContext *ctx, arg_ ## name * a) \
+{ \
+ if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { \
+ printf("%s: warning, register equal\n", __func__); \
+ return false; \
+ } \
+ int mem_idx = ctx->mem_idx; \
+ TCGv addr = tcg_temp_new(); \
+ TCGv val = tcg_temp_new(); \
+ TCGv ret = tcg_temp_new(); \
+ \
+ gen_loongarch_sync(0x10); \
+ gen_load_gpr(addr, a->rj); \
+ gen_load_gpr(val, a->rk); \
+ tcg_gen_atomic_##op##_tl(ret, addr, val, mem_idx, MO_TEQ | \
+ ctx->default_tcg_memop_mask); \
+ gen_store_gpr(ret, a->rd); \
+ \
+ tcg_temp_free(addr); \
+ tcg_temp_free(val); \
+ tcg_temp_free(ret); \
+ return true; \
+}
+#define TRANS_AM_DB(name, op) \
+ TRANS_AM_DB_W(name##_db_w, op) \
+ TRANS_AM_DB_D(name##_db_d, op)
+TRANS_AM_DB(amswap, xchg) /* trans_amswap_db_w, trans_amswap_db_d */
+TRANS_AM_DB(amadd, fetch_add) /* trans_amadd_db_w, trans_amadd_db_d */
+TRANS_AM_DB(amand, fetch_and) /* trans_amand_db_w, trans_amand_db_d */
+TRANS_AM_DB(amor, fetch_or) /* trans_amor_db_w, trans_amor_db_d */
+TRANS_AM_DB(amxor, fetch_xor) /* trans_amxor_db_w, trans_amxor_db_d */
+TRANS_AM_DB(ammax, fetch_smax) /* trans_ammax_db_w, trans_ammax_db_d */
+TRANS_AM_DB(ammin, fetch_smin) /* trans_ammin_db_w, trans_ammin_db_d */
+TRANS_AM_DB_W(ammax_db_wu, fetch_umax) /* trans_ammax_db_wu */
+TRANS_AM_DB_D(ammax_db_du, fetch_umax) /* trans_ammax_db_du */
+TRANS_AM_DB_W(ammin_db_wu, fetch_umin) /* trans_ammin_db_wu */
+TRANS_AM_DB_D(ammin_db_du, fetch_umin) /* trans_ammin_db_du */
+#undef TRANS_AM_DB
+#undef TRANS_AM_DB_W
+#undef TRANS_AM_DB_D
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index d9d2f1a..bf14507 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -1181,6 +1181,21 @@ fail:
tcg_temp_free(t1);
}
+#define OP_LD_ATOMIC(insn, fname) \
+static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
+ DisasContext *ctx) \
+{ \
+ TCGv t0 = tcg_temp_new(); \
+ tcg_gen_mov_tl(t0, arg1); \
+ tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
+ tcg_gen_st_tl(t0, cpu_env, offsetof(CPULoongArchState, lladdr)); \
+ tcg_gen_st_tl(ret, cpu_env, offsetof(CPULoongArchState, llval)); \
+ tcg_temp_free(t0); \
+}
+OP_LD_ATOMIC(ll, ld32s);
+OP_LD_ATOMIC(lld, ld64);
+#undef OP_LD_ATOMIC
+
/* loongarch load */
static void gen_loongarch_ld(DisasContext *ctx, uint32_t opc,
int rd, int base, int offset)
@@ -1226,6 +1241,14 @@ static void gen_loongarch_ld(DisasContext *ctx, uint32_t opc,
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
gen_store_gpr(t0, rd);
break;
+ case LA_OPC_LL_W:
+ op_ld_ll(t0, t0, mem_idx, ctx);
+ gen_store_gpr(t0, rd);
+ break;
+ case LA_OPC_LL_D:
+ op_ld_lld(t0, t0, mem_idx, ctx);
+ gen_store_gpr(t0, rd);
+ break;
}
tcg_temp_free(t0);
}
@@ -1264,6 +1287,37 @@ static void gen_loongarch_st(DisasContext *ctx, uint32_t opc, int rd,
tcg_temp_free(t1);
}
+/* loongarch st cond */
+static void gen_loongarch_st_cond(DisasContext *ctx, int rd, int base,
+ int offset, MemOp tcg_mo, bool eva)
+{
+ TCGv t0 = tcg_temp_new();
+ TCGv addr = tcg_temp_new();
+ TCGv val = tcg_temp_new();
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *done = gen_new_label();
+
+ /* compare the address against that of the preceding LL */
+ gen_base_offset_addr(ctx, addr, base, offset);
+ tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
+ tcg_gen_movi_tl(t0, 0);
+ gen_store_gpr(t0, rd);
+ tcg_gen_br(done);
+
+ gen_set_label(l1);
+ /* generate cmpxchg */
+ gen_load_gpr(val, rd);
+ tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
+ eva ? LOONGARCH_HFLAG_UM : ctx->mem_idx, tcg_mo);
+ tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
+ gen_store_gpr(t0, rd);
+
+ gen_set_label(done);
+ tcg_temp_free(t0);
+ tcg_temp_free(addr);
+ tcg_temp_free(val);
+}
+
static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
{
}
--
1.8.3.1
next prev parent reply other threads:[~2021-06-28 12:14 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-28 12:04 [PATCH 00/20] Add LoongArch linux-user emulation support Song Gao
2021-06-28 12:04 ` [PATCH 01/20] target/loongarch: Add README Song Gao
2021-06-28 18:40 ` Philippe Mathieu-Daudé
2021-06-29 7:33 ` Song Gao
2021-06-29 11:13 ` Alex Bennée
2021-06-30 1:09 ` Song Gao
2021-06-29 11:52 ` Peter Maydell
2021-06-30 1:22 ` Song Gao
2021-06-28 12:04 ` [PATCH 02/20] target/loongarch: Add CSR registers definition Song Gao
2021-06-28 12:04 ` [PATCH 03/20] target/loongarch: Add core definition Song Gao
2021-06-28 18:44 ` Philippe Mathieu-Daudé
2021-06-29 7:39 ` Song Gao
2021-06-28 12:04 ` [PATCH 04/20] target/loongarch: Add interrupt handling support Song Gao
2021-06-28 12:04 ` [PATCH 05/20] target/loongarch: Add memory management support Song Gao
2021-06-28 12:04 ` [PATCH 06/20] target/loongarch: Add main translation routines Song Gao
2021-06-28 18:46 ` Philippe Mathieu-Daudé
2021-06-29 8:50 ` Song Gao
2021-06-29 12:26 ` Alex Bennée
2021-06-30 1:04 ` Song Gao
2021-06-28 12:04 ` [PATCH 07/20] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
2021-07-01 20:31 ` Philippe Mathieu-Daudé
2021-07-02 8:15 ` Song Gao
2021-07-02 8:51 ` Philippe Mathieu-Daudé
2021-07-02 9:16 ` Song Gao
2021-07-02 14:46 ` Richard Henderson
2021-07-05 0:45 ` Song Gao
2021-06-28 12:04 ` [PATCH 08/20] target/loongarch: Add fixed point shift " Song Gao
2021-06-28 12:04 ` [PATCH 09/20] target/loongarch: Add fixed point bit " Song Gao
2021-06-28 12:04 ` [PATCH 10/20] target/loongarch: Add fixed point load/store " Song Gao
2021-06-28 12:04 ` Song Gao [this message]
2021-06-28 12:04 ` [PATCH 12/20] target/loongarch: Add fixed point extra " Song Gao
2021-06-28 12:04 ` [PATCH 13/20] target/loongarch: Add floating point arithmetic " Song Gao
2021-06-28 12:04 ` [PATCH 14/20] target/loongarch: Add floating point comparison " Song Gao
2021-06-28 12:04 ` [PATCH 15/20] target/loongarch: Add floating point conversion " Song Gao
2021-06-28 12:04 ` [PATCH 16/20] target/loongarch: Add floating point move " Song Gao
2021-06-28 12:04 ` [PATCH 17/20] target/loongarch: Add floating point load/store " Song Gao
2021-06-28 12:04 ` [PATCH 18/20] target/loongarch: Add branch " Song Gao
2021-06-28 12:04 ` [PATCH 19/20] target/loongarch: Add disassembler Song Gao
2021-06-28 12:04 ` [PATCH 20/20] target/loongarch: Add linux-user emulation support Song Gao
2021-06-29 13:42 ` Peter Maydell
2021-06-30 1:41 ` maobibo
2021-06-30 9:36 ` Alex Bennée
2021-07-01 1:07 ` maobibo
2021-07-01 6:47 ` Thomas Huth
2021-07-01 7:08 ` maobibo
2021-07-01 10:35 ` Alex Bennée
2021-07-01 10:53 ` Peter Maydell
2021-07-01 12:05 ` maobibo
2021-06-30 1:59 ` Song Gao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1624881885-31692-12-git-send-email-gaosong@loongson.cn \
--to=gaosong@loongson.cn \
--cc=alistair.francis@wdc.com \
--cc=laurent@vivier.eu \
--cc=maobibo@loongson.cn \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).