[PATCH v2] target/ppc: Fix fallback to MFSS for MFFS* instructions on pre 3.0 ISAs

2023-05-05 Thread Richard Purdie
The following commits changed the code such that the fallback to MFSS for 
MFFSCRN,
MFFSCRNI, MFFSCE and MFFSL on pre 3.0 ISAs was removed and became an illegal 
instruction:

  bf8adfd88b547680aa857c46098f3a1e94373160 - target/ppc: Move mffscrn[i] to 
decodetree
  394c2e2fda70da722f20fb60412d6c0ca4bfaa03 - target/ppc: Move mffsce to 
decodetree
  3e5bce70efe6bd1f684efbb21fd2a316cbf0657e - target/ppc: Move mffsl to 
decodetree

The hardware will handle them as a MFFS instruction as the code did previously.
This means applications that were segfaulting under qemu when encountering these
instructions which is used in glibc libm functions for example.

The fallback for MFFSCDRN and MFFSCDRNI added in a later patch was also missing.

This patch restores the fallback to MFSS for these instructions on pre 3.0s ISAs
as the hardware decoder would, fixing the segfaulting libm code. It and also 
ensures
the MFSS instruction is used for currently reserved bits to handle other 
potential
ISA additions more correctly.

Signed-off-by: Richard Purdie 
---
 target/ppc/insn32.decode   | 19 ---
 target/ppc/translate/fp-impl.c.inc | 30 --
 2 files changed, 36 insertions(+), 13 deletions(-)

v2 - switch to use decodetree pattern groups per feedback

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index f8f589e9fd..3c4e2c2fc2 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -390,13 +390,18 @@ SETNBCR 01 . . - 00 -   
@X_bi
 
 ### Move To/From FPSCR
 
-MFFS11 . 0 - 1001000111 .   @X_t_rc
-MFFSCE  11 . 1 - 1001000111 -   @X_t
-MFFSCRN 11 . 10110 . 1001000111 -   @X_tb
-MFFSCDRN11 . 10100 . 1001000111 -   @X_tb
-MFFSCRNI11 . 10111 ---.. 1001000111 -   @X_imm2
-MFFSCDRNI   11 . 10101 --... 1001000111 -   @X_imm3
-MFFSL   11 . 11000 - 1001000111 -   @X_t
+{ 
+  # Before Power ISA v3.0, MFFS bits 11~15 were reserved and should be ignored
+  [
+MFFSCE  11 . 1 - 1001000111 -   @X_t
+MFFSCRN 11 . 10110 . 1001000111 -   @X_tb
+MFFSCDRN11 . 10100 . 1001000111 -   @X_tb
+MFFSCRNI11 . 10111 ---.. 1001000111 -   @X_imm2
+MFFSCDRNI   11 . 10101 --... 1001000111 -   @X_imm3
+MFFSL   11 . 11000 - 1001000111 -   @X_t
+  ]
+  MFFS11 . - - 1001000111 .   @X_t_rc
+}
 
 ### Decimal Floating-Point Arithmetic Instructions
 
diff --git a/target/ppc/translate/fp-impl.c.inc 
b/target/ppc/translate/fp-impl.c.inc
index 57d8437851..10dfd91aa4 100644
--- a/target/ppc/translate/fp-impl.c.inc
+++ b/target/ppc/translate/fp-impl.c.inc
@@ -584,7 +584,10 @@ static bool trans_MFFSCE(DisasContext *ctx, arg_X_t *a)
 {
 TCGv_i64 fpscr;
 
-REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+if (!(ctx->insns_flags2 & PPC2_ISA300)) {
+return false;
+}
+
 REQUIRE_FPU(ctx);
 
 gen_reset_fpstatus();
@@ -597,7 +600,10 @@ static bool trans_MFFSCRN(DisasContext *ctx, arg_X_tb *a)
 {
 TCGv_i64 t1, fpscr;
 
-REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+if (!(ctx->insns_flags2 & PPC2_ISA300)) {
+return false;
+}
+
 REQUIRE_FPU(ctx);
 
 t1 = tcg_temp_new_i64();
@@ -614,7 +620,10 @@ static bool trans_MFFSCDRN(DisasContext *ctx, arg_X_tb *a)
 {
 TCGv_i64 t1, fpscr;
 
-REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+if (!(ctx->insns_flags2 & PPC2_ISA300)) {
+return false;
+}
+
 REQUIRE_FPU(ctx);
 
 t1 = tcg_temp_new_i64();
@@ -631,7 +640,10 @@ static bool trans_MFFSCRNI(DisasContext *ctx, arg_X_imm2 
*a)
 {
 TCGv_i64 t1, fpscr;
 
-REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+if (!(ctx->insns_flags2 & PPC2_ISA300)) {
+return false;
+}
+
 REQUIRE_FPU(ctx);
 
 t1 = tcg_temp_new_i64();
@@ -647,7 +659,10 @@ static bool trans_MFFSCDRNI(DisasContext *ctx, arg_X_imm3 
*a)
 {
 TCGv_i64 t1, fpscr;
 
-REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+if (!(ctx->insns_flags2 & PPC2_ISA300)) {
+return false;
+}
+
 REQUIRE_FPU(ctx);
 
 t1 = tcg_temp_new_i64();
@@ -661,7 +676,10 @@ static bool trans_MFFSCDRNI(DisasContext *ctx, arg_X_imm3 
*a)
 
 static bool trans_MFFSL(DisasContext *ctx, arg_X_t *a)
 {
-REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+if (!(ctx->insns_flags2 & PPC2_ISA300)) {
+return false;
+}
+
 REQUIRE_FPU(ctx);
 
 gen_reset_fpstatus();
-- 
2.39.2




[PULL v2 20/45] target/loongarch: Implement vmskltz/vmskgez/vmsknz

2023-05-05 Thread Song Gao
This patch includes:
- VMSKLTZ.{B/H/W/D};
- VMSKGEZ.B;
- VMSKNZ.B.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-21-gaos...@loongson.cn>
---
 target/loongarch/disas.c|   7 ++
 target/loongarch/helper.h   |   7 ++
 target/loongarch/insn_trans/trans_lsx.c.inc |   7 ++
 target/loongarch/insns.decode   |   7 ++
 target/loongarch/lsx_helper.c   | 113 
 5 files changed, 141 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 46e808c321..2725b827ee 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1084,3 +1084,10 @@ INSN_LSX(vsigncov_b,   vvv)
 INSN_LSX(vsigncov_h,   vvv)
 INSN_LSX(vsigncov_w,   vvv)
 INSN_LSX(vsigncov_d,   vvv)
+
+INSN_LSX(vmskltz_b,vv)
+INSN_LSX(vmskltz_h,vv)
+INSN_LSX(vmskltz_w,vv)
+INSN_LSX(vmskltz_d,vv)
+INSN_LSX(vmskgez_b,vv)
+INSN_LSX(vmsknz_b, vv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index e1e5d58697..34b7b2f576 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -343,3 +343,10 @@ DEF_HELPER_FLAGS_4(vsigncov_b, TCG_CALL_NO_RWG, void, ptr, 
ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vsigncov_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vsigncov_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vsigncov_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_3(vmskltz_b, void, env, i32, i32)
+DEF_HELPER_3(vmskltz_h, void, env, i32, i32)
+DEF_HELPER_3(vmskltz_w, void, env, i32, i32)
+DEF_HELPER_3(vmskltz_d, void, env, i32, i32)
+DEF_HELPER_3(vmskgez_b, void, env, i32, i32)
+DEF_HELPER_3(vmsknz_b, void, env, i32,i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 644917a695..64387f2666 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -2867,3 +2867,10 @@ TRANS(vsigncov_b, gvec_vvv, MO_8, do_vsigncov)
 TRANS(vsigncov_h, gvec_vvv, MO_16, do_vsigncov)
 TRANS(vsigncov_w, gvec_vvv, MO_32, do_vsigncov)
 TRANS(vsigncov_d, gvec_vvv, MO_64, do_vsigncov)
+
+TRANS(vmskltz_b, gen_vv, gen_helper_vmskltz_b)
+TRANS(vmskltz_h, gen_vv, gen_helper_vmskltz_h)
+TRANS(vmskltz_w, gen_vv, gen_helper_vmskltz_w)
+TRANS(vmskltz_d, gen_vv, gen_helper_vmskltz_d)
+TRANS(vmskgez_b, gen_vv, gen_helper_vmskgez_b)
+TRANS(vmsknz_b, gen_vv, gen_helper_vmsknz_b)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 4233dd7404..47c1ef78a7 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -783,3 +783,10 @@ vsigncov_b   0111 00010010 11100 . . .
@vvv
 vsigncov_h   0111 00010010 11101 . . .@vvv
 vsigncov_w   0111 00010010 0 . . .@vvv
 vsigncov_d   0111 00010010 1 . . .@vvv
+
+vmskltz_b0111 00101001 11000 1 . .@vv
+vmskltz_h0111 00101001 11000 10001 . .@vv
+vmskltz_w0111 00101001 11000 10010 . .@vv
+vmskltz_d0111 00101001 11000 10011 . .@vv
+vmskgez_b0111 00101001 11000 10100 . .@vv
+vmsknz_b 0111 00101001 11000 11000 . .@vv
diff --git a/target/loongarch/lsx_helper.c b/target/loongarch/lsx_helper.c
index 408815ea45..2359c63fdf 100644
--- a/target/loongarch/lsx_helper.c
+++ b/target/loongarch/lsx_helper.c
@@ -669,3 +669,116 @@ DO_3OP(vsigncov_b, 8, B, DO_SIGNCOV)
 DO_3OP(vsigncov_h, 16, H, DO_SIGNCOV)
 DO_3OP(vsigncov_w, 32, W, DO_SIGNCOV)
 DO_3OP(vsigncov_d, 64, D, DO_SIGNCOV)
+
+static uint64_t do_vmskltz_b(int64_t val)
+{
+uint64_t m = 0x8080808080808080ULL;
+uint64_t c =  val & m;
+c |= c << 7;
+c |= c << 14;
+c |= c << 28;
+return c >> 56;
+}
+
+void HELPER(vmskltz_b)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
+{
+uint16_t temp = 0;
+VReg *Vd = &(env->fpr[vd].vreg);
+VReg *Vj = &(env->fpr[vj].vreg);
+
+temp = do_vmskltz_b(Vj->D(0));
+temp |= (do_vmskltz_b(Vj->D(1)) << 8);
+Vd->D(0) = temp;
+Vd->D(1) = 0;
+}
+
+static uint64_t do_vmskltz_h(int64_t val)
+{
+uint64_t m = 0x8000800080008000ULL;
+uint64_t c =  val & m;
+c |= c << 15;
+c |= c << 30;
+return c >> 60;
+}
+
+void HELPER(vmskltz_h)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
+{
+uint16_t temp = 0;
+VReg *Vd = &(env->fpr[vd].vreg);
+VReg *Vj = &(env->fpr[vj].vreg);
+
+temp = do_vmskltz_h(Vj->D(0));
+temp |= (do_vmskltz_h(Vj->D(1)) << 4);
+Vd->D(0) = temp;
+Vd->D(1) = 0;
+}
+
+static uint64_t do_vmskltz_w(int64_t val)
+{
+uint64_t m = 0x80008000ULL;
+uint64_t c =  val & m;
+c |= c << 31;
+return c >> 62;
+}
+
+void HELPER(vmskltz_w)(CPULoongArchState *env, uint32_t vd, uint32_t vj)
+{
+uint16_t temp = 0;
+VReg *Vd = &

[PULL v2 43/45] target/loongarch: Use {set/get}_gpr replace to cpu_fpr

2023-05-05 Thread Song Gao
Introduce set_fpr() and get_fpr() and remove cpu_fpr.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-44-gaos...@loongson.cn>
---
 .../loongarch/insn_trans/trans_farith.c.inc   | 72 +++
 target/loongarch/insn_trans/trans_fcmp.c.inc  | 12 ++--
 .../loongarch/insn_trans/trans_fmemory.c.inc  | 37 ++
 target/loongarch/insn_trans/trans_fmov.c.inc  | 31 +---
 target/loongarch/translate.c  | 20 --
 5 files changed, 129 insertions(+), 43 deletions(-)

diff --git a/target/loongarch/insn_trans/trans_farith.c.inc 
b/target/loongarch/insn_trans/trans_farith.c.inc
index 7081fbb89b..21ea47308b 100644
--- a/target/loongarch/insn_trans/trans_farith.c.inc
+++ b/target/loongarch/insn_trans/trans_farith.c.inc
@@ -17,18 +17,29 @@
 static bool gen_fff(DisasContext *ctx, arg_fff *a,
 void (*func)(TCGv, TCGv_env, TCGv, TCGv))
 {
+TCGv dest = get_fpr(ctx, a->fd);
+TCGv src1 = get_fpr(ctx, a->fj);
+TCGv src2 = get_fpr(ctx, a->fk);
+
 CHECK_FPE;
 
-func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk]);
+func(dest, cpu_env, src1, src2);
+set_fpr(a->fd, dest);
+
 return true;
 }
 
 static bool gen_ff(DisasContext *ctx, arg_ff *a,
void (*func)(TCGv, TCGv_env, TCGv))
 {
+TCGv dest = get_fpr(ctx, a->fd);
+TCGv src = get_fpr(ctx, a->fj);
+
 CHECK_FPE;
 
-func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj]);
+func(dest, cpu_env, src);
+set_fpr(a->fd, dest);
+
 return true;
 }
 
@@ -37,61 +48,98 @@ static bool gen_muladd(DisasContext *ctx, arg_ *a,
int flag)
 {
 TCGv_i32 tflag = tcg_constant_i32(flag);
+TCGv dest = get_fpr(ctx, a->fd);
+TCGv src1 = get_fpr(ctx, a->fj);
+TCGv src2 = get_fpr(ctx, a->fk);
+TCGv src3 = get_fpr(ctx, a->fa);
 
 CHECK_FPE;
 
-func(cpu_fpr[a->fd], cpu_env, cpu_fpr[a->fj],
- cpu_fpr[a->fk], cpu_fpr[a->fa], tflag);
+func(dest, cpu_env, src1, src2, src3, tflag);
+set_fpr(a->fd, dest);
+
 return true;
 }
 
 static bool trans_fcopysign_s(DisasContext *ctx, arg_fcopysign_s *a)
 {
+TCGv dest = get_fpr(ctx, a->fd);
+TCGv src1 = get_fpr(ctx, a->fk);
+TCGv src2 = get_fpr(ctx, a->fj);
+
 CHECK_FPE;
 
-tcg_gen_deposit_i64(cpu_fpr[a->fd], cpu_fpr[a->fk], cpu_fpr[a->fj], 0, 31);
+tcg_gen_deposit_i64(dest, src1, src2, 0, 31);
+set_fpr(a->fd, dest);
+
 return true;
 }
 
 static bool trans_fcopysign_d(DisasContext *ctx, arg_fcopysign_d *a)
 {
+TCGv dest = get_fpr(ctx, a->fd);
+TCGv src1 = get_fpr(ctx, a->fk);
+TCGv src2 = get_fpr(ctx, a->fj);
+
 CHECK_FPE;
 
-tcg_gen_deposit_i64(cpu_fpr[a->fd], cpu_fpr[a->fk], cpu_fpr[a->fj], 0, 63);
+tcg_gen_deposit_i64(dest, src1, src2, 0, 63);
+set_fpr(a->fd, dest);
+
 return true;
 }
 
 static bool trans_fabs_s(DisasContext *ctx, arg_fabs_s *a)
 {
+TCGv dest = get_fpr(ctx, a->fd);
+TCGv src = get_fpr(ctx, a->fj);
+
 CHECK_FPE;
 
-tcg_gen_andi_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], MAKE_64BIT_MASK(0, 31));
-gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+tcg_gen_andi_i64(dest, src, MAKE_64BIT_MASK(0, 31));
+gen_nanbox_s(dest, dest);
+set_fpr(a->fd, dest);
+
 return true;
 }
 
 static bool trans_fabs_d(DisasContext *ctx, arg_fabs_d *a)
 {
+TCGv dest = get_fpr(ctx, a->fd);
+TCGv src = get_fpr(ctx, a->fj);
+
 CHECK_FPE;
 
-tcg_gen_andi_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], MAKE_64BIT_MASK(0, 63));
+tcg_gen_andi_i64(dest, src, MAKE_64BIT_MASK(0, 63));
+set_fpr(a->fd, dest);
+
 return true;
 }
 
 static bool trans_fneg_s(DisasContext *ctx, arg_fneg_s *a)
 {
+TCGv dest = get_fpr(ctx, a->fd);
+TCGv src = get_fpr(ctx, a->fj);
+
 CHECK_FPE;
 
-tcg_gen_xori_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], 0x8000);
-gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+tcg_gen_xori_i64(dest, src, 0x8000);
+gen_nanbox_s(dest, dest);
+set_fpr(a->fd, dest);
+
 return true;
 }
 
 static bool trans_fneg_d(DisasContext *ctx, arg_fneg_d *a)
 {
+TCGv dest = get_fpr(ctx, a->fd);
+TCGv src = get_fpr(ctx, a->fj);
+
 CHECK_FPE;
 
-tcg_gen_xori_i64(cpu_fpr[a->fd], cpu_fpr[a->fj], 0x8000LL);
+tcg_gen_xori_i64(dest, src, 0x8000LL);
+set_fpr(a->fd, dest);
+
 return true;
 }
 
diff --git a/target/loongarch/insn_trans/trans_fcmp.c.inc 
b/target/loongarch/insn_trans/trans_fcmp.c.inc
index 3b0da2b9f4..a78868dbc4 100644
--- a/target/loongarch/insn_trans/trans_fcmp.c.inc
+++ b/target/loongarch/insn_trans/trans_fcmp.c.inc
@@ -25,17 +25,19 @@ static uint32_t get_fcmp_flags(int cond)
 
 static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a)
 {
-TCGv var;
+TCGv var, src1, src2;
 uint32_t flags;
 void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32);
 
 CHECK_FPE;
 
 var = tcg_temp_new();
+src1 = get_fpr(ctx, a->fj);
+src2 = get_fp

[PULL v2 08/45] target/loongarch: Implement vhaddw/vhsubw

2023-05-05 Thread Song Gao
This patch includes:
- VHADDW.{H.B/W.H/D.W/Q.D/HU.BU/WU.HU/DU.WU/QU.DU};
- VHSUBW.{H.B/W.H/D.W/Q.D/HU.BU/WU.HU/DU.WU/QU.DU}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-9-gaos...@loongson.cn>
---
 target/loongarch/disas.c| 17 +
 target/loongarch/helper.h   | 18 +
 target/loongarch/insn_trans/trans_lsx.c.inc | 17 +
 target/loongarch/insns.decode   | 17 +
 target/loongarch/lsx_helper.c   | 81 +
 5 files changed, 150 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index b7f9320ba0..adfd693938 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -848,3 +848,20 @@ INSN_LSX(vssub_bu, vvv)
 INSN_LSX(vssub_hu, vvv)
 INSN_LSX(vssub_wu, vvv)
 INSN_LSX(vssub_du, vvv)
+
+INSN_LSX(vhaddw_h_b,   vvv)
+INSN_LSX(vhaddw_w_h,   vvv)
+INSN_LSX(vhaddw_d_w,   vvv)
+INSN_LSX(vhaddw_q_d,   vvv)
+INSN_LSX(vhaddw_hu_bu, vvv)
+INSN_LSX(vhaddw_wu_hu, vvv)
+INSN_LSX(vhaddw_du_wu, vvv)
+INSN_LSX(vhaddw_qu_du, vvv)
+INSN_LSX(vhsubw_h_b,   vvv)
+INSN_LSX(vhsubw_w_h,   vvv)
+INSN_LSX(vhsubw_d_w,   vvv)
+INSN_LSX(vhsubw_q_d,   vvv)
+INSN_LSX(vhsubw_hu_bu, vvv)
+INSN_LSX(vhsubw_wu_hu, vvv)
+INSN_LSX(vhsubw_du_wu, vvv)
+INSN_LSX(vhsubw_qu_du, vvv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 9c01823a26..6d58dabaed 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -130,3 +130,21 @@ DEF_HELPER_4(ldpte, void, env, tl, tl, i32)
 DEF_HELPER_1(ertn, void, env)
 DEF_HELPER_1(idle, void, env)
 #endif
+
+/* LoongArch LSX  */
+DEF_HELPER_4(vhaddw_h_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vhaddw_w_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vhaddw_d_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vhaddw_q_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vhaddw_hu_bu, void, env, i32, i32, i32)
+DEF_HELPER_4(vhaddw_wu_hu, void, env, i32, i32, i32)
+DEF_HELPER_4(vhaddw_du_wu, void, env, i32, i32, i32)
+DEF_HELPER_4(vhaddw_qu_du, void, env, i32, i32, i32)
+DEF_HELPER_4(vhsubw_h_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vhsubw_w_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vhsubw_d_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vhsubw_q_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vhsubw_hu_bu, void, env, i32, i32, i32)
+DEF_HELPER_4(vhsubw_wu_hu, void, env, i32, i32, i32)
+DEF_HELPER_4(vhsubw_du_wu, void, env, i32, i32, i32)
+DEF_HELPER_4(vhsubw_qu_du, void, env, i32, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 082bd738ce..562096c0d7 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -157,3 +157,20 @@ TRANS(vssub_bu, gvec_vvv, MO_8, tcg_gen_gvec_ussub)
 TRANS(vssub_hu, gvec_vvv, MO_16, tcg_gen_gvec_ussub)
 TRANS(vssub_wu, gvec_vvv, MO_32, tcg_gen_gvec_ussub)
 TRANS(vssub_du, gvec_vvv, MO_64, tcg_gen_gvec_ussub)
+
+TRANS(vhaddw_h_b, gen_vvv, gen_helper_vhaddw_h_b)
+TRANS(vhaddw_w_h, gen_vvv, gen_helper_vhaddw_w_h)
+TRANS(vhaddw_d_w, gen_vvv, gen_helper_vhaddw_d_w)
+TRANS(vhaddw_q_d, gen_vvv, gen_helper_vhaddw_q_d)
+TRANS(vhaddw_hu_bu, gen_vvv, gen_helper_vhaddw_hu_bu)
+TRANS(vhaddw_wu_hu, gen_vvv, gen_helper_vhaddw_wu_hu)
+TRANS(vhaddw_du_wu, gen_vvv, gen_helper_vhaddw_du_wu)
+TRANS(vhaddw_qu_du, gen_vvv, gen_helper_vhaddw_qu_du)
+TRANS(vhsubw_h_b, gen_vvv, gen_helper_vhsubw_h_b)
+TRANS(vhsubw_w_h, gen_vvv, gen_helper_vhsubw_w_h)
+TRANS(vhsubw_d_w, gen_vvv, gen_helper_vhsubw_d_w)
+TRANS(vhsubw_q_d, gen_vvv, gen_helper_vhsubw_q_d)
+TRANS(vhsubw_hu_bu, gen_vvv, gen_helper_vhsubw_hu_bu)
+TRANS(vhsubw_wu_hu, gen_vvv, gen_helper_vhsubw_wu_hu)
+TRANS(vhsubw_du_wu, gen_vvv, gen_helper_vhsubw_du_wu)
+TRANS(vhsubw_qu_du, gen_vvv, gen_helper_vhsubw_qu_du)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 3a29f0a9ab..10a20858e5 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -542,3 +542,20 @@ vssub_bu 0111 0100 11000 . . .
@vvv
 vssub_hu 0111 0100 11001 . . .@vvv
 vssub_wu 0111 0100 11010 . . .@vvv
 vssub_du 0111 0100 11011 . . .@vvv
+
+vhaddw_h_b   0111 0101 01000 . . .@vvv
+vhaddw_w_h   0111 0101 01001 . . .@vvv
+vhaddw_d_w   0111 0101 01010 . . .@vvv
+vhaddw_q_d   0111 0101 01011 . . .@vvv
+vhaddw_hu_bu 0111 0101 1 . . .@vvv
+vhaddw_wu_hu 0111 0101 10001 . . .@vvv
+vhaddw_du_wu 0111 0101 10010 . . .@vvv
+vhaddw_qu_du 0111 0101 10011 . . .@vvv
+vhsubw_h_b   0111 0101 01100 . . .@vvv
+vhsubw_w_h   0111 0101 01101 

[PULL v2 09/45] target/loongarch: Implement vaddw/vsubw

2023-05-05 Thread Song Gao
This patch includes:
- VADDW{EV/OD}.{H.B/W.H/D.W/Q.D}[U];
- VSUBW{EV/OD}.{H.B/W.H/D.W/Q.D}[U];
- VADDW{EV/OD}.{H.BU.B/W.HU.H/D.WU.W/Q.DU.D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-10-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  43 ++
 target/loongarch/helper.h   |  45 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 795 
 target/loongarch/insns.decode   |  43 ++
 target/loongarch/lsx_helper.c   | 190 +
 5 files changed, 1116 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index adfd693938..8ee14916f3 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -865,3 +865,46 @@ INSN_LSX(vhsubw_hu_bu, vvv)
 INSN_LSX(vhsubw_wu_hu, vvv)
 INSN_LSX(vhsubw_du_wu, vvv)
 INSN_LSX(vhsubw_qu_du, vvv)
+
+INSN_LSX(vaddwev_h_b,  vvv)
+INSN_LSX(vaddwev_w_h,  vvv)
+INSN_LSX(vaddwev_d_w,  vvv)
+INSN_LSX(vaddwev_q_d,  vvv)
+INSN_LSX(vaddwod_h_b,  vvv)
+INSN_LSX(vaddwod_w_h,  vvv)
+INSN_LSX(vaddwod_d_w,  vvv)
+INSN_LSX(vaddwod_q_d,  vvv)
+INSN_LSX(vsubwev_h_b,  vvv)
+INSN_LSX(vsubwev_w_h,  vvv)
+INSN_LSX(vsubwev_d_w,  vvv)
+INSN_LSX(vsubwev_q_d,  vvv)
+INSN_LSX(vsubwod_h_b,  vvv)
+INSN_LSX(vsubwod_w_h,  vvv)
+INSN_LSX(vsubwod_d_w,  vvv)
+INSN_LSX(vsubwod_q_d,  vvv)
+
+INSN_LSX(vaddwev_h_bu, vvv)
+INSN_LSX(vaddwev_w_hu, vvv)
+INSN_LSX(vaddwev_d_wu, vvv)
+INSN_LSX(vaddwev_q_du, vvv)
+INSN_LSX(vaddwod_h_bu, vvv)
+INSN_LSX(vaddwod_w_hu, vvv)
+INSN_LSX(vaddwod_d_wu, vvv)
+INSN_LSX(vaddwod_q_du, vvv)
+INSN_LSX(vsubwev_h_bu, vvv)
+INSN_LSX(vsubwev_w_hu, vvv)
+INSN_LSX(vsubwev_d_wu, vvv)
+INSN_LSX(vsubwev_q_du, vvv)
+INSN_LSX(vsubwod_h_bu, vvv)
+INSN_LSX(vsubwod_w_hu, vvv)
+INSN_LSX(vsubwod_d_wu, vvv)
+INSN_LSX(vsubwod_q_du, vvv)
+
+INSN_LSX(vaddwev_h_bu_b,   vvv)
+INSN_LSX(vaddwev_w_hu_h,   vvv)
+INSN_LSX(vaddwev_d_wu_w,   vvv)
+INSN_LSX(vaddwev_q_du_d,   vvv)
+INSN_LSX(vaddwod_h_bu_b,   vvv)
+INSN_LSX(vaddwod_w_hu_h,   vvv)
+INSN_LSX(vaddwod_d_wu_w,   vvv)
+INSN_LSX(vaddwod_q_du_d,   vvv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 6d58dabaed..505c336ff3 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -148,3 +148,48 @@ DEF_HELPER_4(vhsubw_hu_bu, void, env, i32, i32, i32)
 DEF_HELPER_4(vhsubw_wu_hu, void, env, i32, i32, i32)
 DEF_HELPER_4(vhsubw_du_wu, void, env, i32, i32, i32)
 DEF_HELPER_4(vhsubw_qu_du, void, env, i32, i32, i32)
+
+DEF_HELPER_FLAGS_4(vaddwev_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwev_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwev_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwev_q_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwod_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwod_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwod_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwod_q_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vsubwev_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwev_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwev_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwev_q_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwod_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwod_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwod_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwod_q_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vaddwev_h_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwev_w_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwev_d_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwev_q_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwod_h_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwod_w_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwod_d_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vaddwod_q_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vsubwev_h_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwev_w_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwev_d_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwev_q_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwod_h_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwod_w_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsubwod_d_wu, TCG_CALL_NO_RWG, void, ptr,

[PULL v2 21/45] target/loongarch: Implement LSX logic instructions

2023-05-05 Thread Song Gao
This patch includes:
- V{AND/OR/XOR/NOR/ANDN/ORN}.V;
- V{AND/OR/XOR/NOR}I.B.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-22-gaos...@loongson.cn>
---
 target/loongarch/disas.c| 12 +
 target/loongarch/helper.h   |  2 +
 target/loongarch/insn_trans/trans_lsx.c.inc | 56 +
 target/loongarch/insns.decode   | 13 +
 target/loongarch/lsx_helper.c   | 11 
 5 files changed, 94 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 2725b827ee..eca0a4bb7b 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1091,3 +1091,15 @@ INSN_LSX(vmskltz_w,vv)
 INSN_LSX(vmskltz_d,vv)
 INSN_LSX(vmskgez_b,vv)
 INSN_LSX(vmsknz_b, vv)
+
+INSN_LSX(vand_v,   vvv)
+INSN_LSX(vor_v,vvv)
+INSN_LSX(vxor_v,   vvv)
+INSN_LSX(vnor_v,   vvv)
+INSN_LSX(vandn_v,  vvv)
+INSN_LSX(vorn_v,   vvv)
+
+INSN_LSX(vandi_b,  vv_i)
+INSN_LSX(vori_b,   vv_i)
+INSN_LSX(vxori_b,  vv_i)
+INSN_LSX(vnori_b,  vv_i)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 34b7b2f576..617c579592 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -350,3 +350,5 @@ DEF_HELPER_3(vmskltz_w, void, env, i32, i32)
 DEF_HELPER_3(vmskltz_d, void, env, i32, i32)
 DEF_HELPER_3(vmskgez_b, void, env, i32, i32)
 DEF_HELPER_3(vmsknz_b, void, env, i32,i32)
+
+DEF_HELPER_FLAGS_4(vnori_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 64387f2666..e5e194106b 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -2874,3 +2874,59 @@ TRANS(vmskltz_w, gen_vv, gen_helper_vmskltz_w)
 TRANS(vmskltz_d, gen_vv, gen_helper_vmskltz_d)
 TRANS(vmskgez_b, gen_vv, gen_helper_vmskgez_b)
 TRANS(vmsknz_b, gen_vv, gen_helper_vmsknz_b)
+
+TRANS(vand_v, gvec_vvv, MO_64, tcg_gen_gvec_and)
+TRANS(vor_v, gvec_vvv, MO_64, tcg_gen_gvec_or)
+TRANS(vxor_v, gvec_vvv, MO_64, tcg_gen_gvec_xor)
+TRANS(vnor_v, gvec_vvv, MO_64, tcg_gen_gvec_nor)
+
+static bool trans_vandn_v(DisasContext *ctx, arg_vvv *a)
+{
+uint32_t vd_ofs, vj_ofs, vk_ofs;
+
+CHECK_SXE;
+
+vd_ofs = vec_full_offset(a->vd);
+vj_ofs = vec_full_offset(a->vj);
+vk_ofs = vec_full_offset(a->vk);
+
+tcg_gen_gvec_andc(MO_64, vd_ofs, vk_ofs, vj_ofs, 16, ctx->vl/8);
+return true;
+}
+TRANS(vorn_v, gvec_vvv, MO_64, tcg_gen_gvec_orc)
+TRANS(vandi_b, gvec_vv_i, MO_8, tcg_gen_gvec_andi)
+TRANS(vori_b, gvec_vv_i, MO_8, tcg_gen_gvec_ori)
+TRANS(vxori_b, gvec_vv_i, MO_8, tcg_gen_gvec_xori)
+
+static void gen_vnori(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
+{
+TCGv_vec t1;
+
+t1 = tcg_constant_vec_matching(t, vece, imm);
+tcg_gen_nor_vec(vece, t, a, t1);
+}
+
+static void gen_vnori_b(TCGv_i64 t, TCGv_i64 a, int64_t imm)
+{
+tcg_gen_movi_i64(t, dup_const(MO_8, imm));
+tcg_gen_nor_i64(t, a, t);
+}
+
+static void do_vnori_b(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
+   int64_t imm, uint32_t oprsz, uint32_t maxsz)
+{
+static const TCGOpcode vecop_list[] = {
+INDEX_op_nor_vec, 0
+};
+static const GVecGen2i op = {
+   .fni8 = gen_vnori_b,
+   .fniv = gen_vnori,
+   .fnoi = gen_helper_vnori_b,
+   .opt_opc = vecop_list,
+   .vece = MO_8
+};
+
+tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op);
+}
+
+TRANS(vnori_b, gvec_vv_i, MO_8, do_vnori_b)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 47c1ef78a7..6309683be9 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -503,6 +503,7 @@ dbcl  0010 10101 ...  
@i15
 @vv_ui4   . . imm:4 vj:5 vd:5&vv_i
 @vv_ui5     . imm:5 vj:5 vd:5&vv_i
 @vv_ui6   imm:6 vj:5 vd:5&vv_i
+@vv_ui8    .. imm:8 vj:5 vd:5&vv_i
 @vv_i5     . imm:s5 vj:5 vd:5&vv_i
 
 vadd_b   0111  10100 . . .@vvv
@@ -790,3 +791,15 @@ vmskltz_w0111 00101001 11000 10010 . .
@vv
 vmskltz_d0111 00101001 11000 10011 . .@vv
 vmskgez_b0111 00101001 11000 10100 . .@vv
 vmsknz_b 0111 00101001 11000 11000 . .@vv
+
+vand_v   0111 00010010 01100 . . .@vvv
+vor_v0111 00010010 01101 . . .@vvv
+vxor_v   0111 00010010 01110 . . .@vvv
+vnor_v   0111 00010010 0 . . .@vvv
+vandn_v  0111 00010010 1 . . .@vvv
+vorn_v   0111 00010010 10001 . . .@vvv
+
+vandi_

[PULL v2 14/45] target/loongarch: Implement vmul/vmuh/vmulw{ev/od}

2023-05-05 Thread Song Gao
This patch includes:
- VMUL.{B/H/W/D};
- VMUH.{B/H/W/D}[U];
- VMULW{EV/OD}.{H.B/W.H/D.W/Q.D}[U];
- VMULW{EV/OD}.{H.BU.B/W.HU.H/D.WU.W/Q.DU.D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-15-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  38 ++
 target/loongarch/helper.h   |  30 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 550 
 target/loongarch/insns.decode   |  38 ++
 target/loongarch/lsx_helper.c   |  76 +++
 5 files changed, 732 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 6b0e518bfa..48e6ef5309 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -972,3 +972,41 @@ INSN_LSX(vmini_bu, vv_i)
 INSN_LSX(vmini_hu, vv_i)
 INSN_LSX(vmini_wu, vv_i)
 INSN_LSX(vmini_du, vv_i)
+
+INSN_LSX(vmul_b,   vvv)
+INSN_LSX(vmul_h,   vvv)
+INSN_LSX(vmul_w,   vvv)
+INSN_LSX(vmul_d,   vvv)
+INSN_LSX(vmuh_b,   vvv)
+INSN_LSX(vmuh_h,   vvv)
+INSN_LSX(vmuh_w,   vvv)
+INSN_LSX(vmuh_d,   vvv)
+INSN_LSX(vmuh_bu,  vvv)
+INSN_LSX(vmuh_hu,  vvv)
+INSN_LSX(vmuh_wu,  vvv)
+INSN_LSX(vmuh_du,  vvv)
+
+INSN_LSX(vmulwev_h_b,  vvv)
+INSN_LSX(vmulwev_w_h,  vvv)
+INSN_LSX(vmulwev_d_w,  vvv)
+INSN_LSX(vmulwev_q_d,  vvv)
+INSN_LSX(vmulwod_h_b,  vvv)
+INSN_LSX(vmulwod_w_h,  vvv)
+INSN_LSX(vmulwod_d_w,  vvv)
+INSN_LSX(vmulwod_q_d,  vvv)
+INSN_LSX(vmulwev_h_bu, vvv)
+INSN_LSX(vmulwev_w_hu, vvv)
+INSN_LSX(vmulwev_d_wu, vvv)
+INSN_LSX(vmulwev_q_du, vvv)
+INSN_LSX(vmulwod_h_bu, vvv)
+INSN_LSX(vmulwod_w_hu, vvv)
+INSN_LSX(vmulwod_d_wu, vvv)
+INSN_LSX(vmulwod_q_du, vvv)
+INSN_LSX(vmulwev_h_bu_b,   vvv)
+INSN_LSX(vmulwev_w_hu_h,   vvv)
+INSN_LSX(vmulwev_d_wu_w,   vvv)
+INSN_LSX(vmulwev_q_du_d,   vvv)
+INSN_LSX(vmulwod_h_bu_b,   vvv)
+INSN_LSX(vmulwod_w_hu_h,   vvv)
+INSN_LSX(vmulwod_d_wu_w,   vvv)
+INSN_LSX(vmulwod_q_du_d,   vvv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 379f961d1e..830d8cbe62 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -243,3 +243,33 @@ DEF_HELPER_FLAGS_4(vmaxi_bu, TCG_CALL_NO_RWG, void, ptr, 
ptr, i64, i32)
 DEF_HELPER_FLAGS_4(vmaxi_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
 DEF_HELPER_FLAGS_4(vmaxi_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
 DEF_HELPER_FLAGS_4(vmaxi_du, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+
+DEF_HELPER_FLAGS_4(vmuh_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmuh_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmuh_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmuh_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmuh_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmuh_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmuh_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmuh_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vmulwev_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwev_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwev_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwod_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwod_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwod_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vmulwev_h_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwev_w_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwev_d_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwod_h_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwod_w_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwod_d_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vmulwev_h_bu_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwev_w_hu_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwev_d_wu_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwod_h_bu_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwod_w_hu_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmulwod_d_wu_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 15bb7888d3..9a36f942e2 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -1514,3 +1514,553 @@ TRANS(vmaxi_bu, gvec_vv_i, MO_8, do_vmaxi_u)
 TRANS(vmaxi_hu, gvec_vv_i, MO_16, do_vmaxi_u)
 TRANS(vmaxi_wu, gvec_vv_i, MO_32, do_vmaxi_u)
 TRANS(vmaxi_du, gvec_vv_i, MO_64, do_vmax

[PULL v2 36/45] target/loongarch: Implement vfcmp

2023-05-05 Thread Song Gao
This patch includes:
- VFCMP.cond.{S/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-37-gaos...@loongson.cn>
---
 target/loongarch/disas.c| 94 +
 target/loongarch/helper.h   |  5 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 32 +++
 target/loongarch/insns.decode   |  5 ++
 target/loongarch/lsx_helper.c   | 54 
 5 files changed, 190 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index e589b23f4c..64db01d2f9 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1447,3 +1447,97 @@ INSN_LSX(vslti_bu, vv_i)
 INSN_LSX(vslti_hu, vv_i)
 INSN_LSX(vslti_wu, vv_i)
 INSN_LSX(vslti_du, vv_i)
+
+#define output_vfcmp(C, PREFIX, SUFFIX) \
+{   \
+(C)->info->fprintf_func((C)->info->stream, "%08x   %s%s\t%d, f%d, f%d", \
+(C)->insn, PREFIX, SUFFIX, a->vd,   \
+a->vj, a->vk);  \
+}
+
+static bool output_vvv_fcond(DisasContext *ctx, arg_vvv_fcond * a,
+ const char *suffix)
+{
+bool ret = true;
+switch (a->fcond) {
+case 0x0:
+output_vfcmp(ctx, "vfcmp_caf_", suffix);
+break;
+case 0x1:
+output_vfcmp(ctx, "vfcmp_saf_", suffix);
+break;
+case 0x2:
+output_vfcmp(ctx, "vfcmp_clt_", suffix);
+break;
+case 0x3:
+output_vfcmp(ctx, "vfcmp_slt_", suffix);
+break;
+case 0x4:
+output_vfcmp(ctx, "vfcmp_ceq_", suffix);
+break;
+case 0x5:
+output_vfcmp(ctx, "vfcmp_seq_", suffix);
+break;
+case 0x6:
+output_vfcmp(ctx, "vfcmp_cle_", suffix);
+break;
+case 0x7:
+output_vfcmp(ctx, "vfcmp_sle_", suffix);
+break;
+case 0x8:
+output_vfcmp(ctx, "vfcmp_cun_", suffix);
+break;
+case 0x9:
+output_vfcmp(ctx, "vfcmp_sun_", suffix);
+break;
+case 0xA:
+output_vfcmp(ctx, "vfcmp_cult_", suffix);
+break;
+case 0xB:
+output_vfcmp(ctx, "vfcmp_sult_", suffix);
+break;
+case 0xC:
+output_vfcmp(ctx, "vfcmp_cueq_", suffix);
+break;
+case 0xD:
+output_vfcmp(ctx, "vfcmp_sueq_", suffix);
+break;
+case 0xE:
+output_vfcmp(ctx, "vfcmp_cule_", suffix);
+break;
+case 0xF:
+output_vfcmp(ctx, "vfcmp_sule_", suffix);
+break;
+case 0x10:
+output_vfcmp(ctx, "vfcmp_cne_", suffix);
+break;
+case 0x11:
+output_vfcmp(ctx, "vfcmp_sne_", suffix);
+break;
+case 0x14:
+output_vfcmp(ctx, "vfcmp_cor_", suffix);
+break;
+case 0x15:
+output_vfcmp(ctx, "vfcmp_sor_", suffix);
+break;
+case 0x18:
+output_vfcmp(ctx, "vfcmp_cune_", suffix);
+break;
+case 0x19:
+output_vfcmp(ctx, "vfcmp_sune_", suffix);
+break;
+default:
+ret = false;
+}
+return ret;
+}
+
+#define LSX_FCMP_INSN(suffix)\
+static bool trans_vfcmp_cond_##suffix(DisasContext *ctx, \
+ arg_vvv_fcond * a)  \
+{\
+return output_vvv_fcond(ctx, a, #suffix);\
+}
+
+LSX_FCMP_INSN(s)
+LSX_FCMP_INSN(d)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index e9e9fa7f87..867756fdb5 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -637,3 +637,8 @@ DEF_HELPER_FLAGS_4(vslti_bu, TCG_CALL_NO_RWG, void, ptr, 
ptr, i64, i32)
 DEF_HELPER_FLAGS_4(vslti_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
 DEF_HELPER_FLAGS_4(vslti_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
 DEF_HELPER_FLAGS_4(vslti_du, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+
+DEF_HELPER_5(vfcmp_c_s, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vfcmp_s_s, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vfcmp_c_d, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vfcmp_s_d, void, env, i32, i32, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 4d9f88bf4f..abb6efc09d 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3717,3 +3717,35 @@ TRANS(vslti_bu, do_vslti_u, MO_8)
 TRANS(vslti_hu, do_vslti_u, MO_16)
 TRANS(vslti_wu, do_vslti_u, MO_32)
 TRANS(vslti_du, do_vslti_u, MO_64)
+
+static bool trans_vfcmp_cond_s(DisasContext *ctx, arg_vvv_fcond *a)
+{
+uint32_t flags;
+void (*fn)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
+TCGv_i32 vd = tcg_constant_i32(a->vd);
+TCGv_i32 vj = tcg_constant_i32(a->vj);
+TCGv_i32 vk = tcg_constant_i32(a->vk);
+
+

[PULL v2 10/45] target/loongarch: Implement vavg/vavgr

2023-05-05 Thread Song Gao
This patch includes:
- VAVG.{B/H/W/D}[U];
- VAVGR.{B/H/W/D}[U].

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-11-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  17 ++
 target/loongarch/helper.h   |  18 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 197 
 target/loongarch/insns.decode   |  17 ++
 target/loongarch/lsx_helper.c   |  32 
 5 files changed, 281 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 8ee14916f3..e7592e7a34 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -908,3 +908,20 @@ INSN_LSX(vaddwod_h_bu_b,   vvv)
 INSN_LSX(vaddwod_w_hu_h,   vvv)
 INSN_LSX(vaddwod_d_wu_w,   vvv)
 INSN_LSX(vaddwod_q_du_d,   vvv)
+
+INSN_LSX(vavg_b,   vvv)
+INSN_LSX(vavg_h,   vvv)
+INSN_LSX(vavg_w,   vvv)
+INSN_LSX(vavg_d,   vvv)
+INSN_LSX(vavg_bu,  vvv)
+INSN_LSX(vavg_hu,  vvv)
+INSN_LSX(vavg_wu,  vvv)
+INSN_LSX(vavg_du,  vvv)
+INSN_LSX(vavgr_b,  vvv)
+INSN_LSX(vavgr_h,  vvv)
+INSN_LSX(vavgr_w,  vvv)
+INSN_LSX(vavgr_d,  vvv)
+INSN_LSX(vavgr_bu, vvv)
+INSN_LSX(vavgr_hu, vvv)
+INSN_LSX(vavgr_wu, vvv)
+INSN_LSX(vavgr_du, vvv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 505c336ff3..af0f9f9b0d 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -193,3 +193,21 @@ DEF_HELPER_FLAGS_4(vaddwod_h_bu_b, TCG_CALL_NO_RWG, void, 
ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vaddwod_w_hu_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vaddwod_d_wu_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vaddwod_q_du_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vavg_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavg_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavg_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavg_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavg_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavg_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavg_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavg_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vavgr_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavgr_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavgr_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavgr_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavgr_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavgr_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavgr_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vavgr_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 8edff83157..5fa4792305 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -969,3 +969,200 @@ TRANS(vaddwod_h_bu_b, gvec_vvv, MO_8, do_vaddwod_u_s)
 TRANS(vaddwod_w_hu_h, gvec_vvv, MO_16, do_vaddwod_u_s)
 TRANS(vaddwod_d_wu_w, gvec_vvv, MO_32, do_vaddwod_u_s)
 TRANS(vaddwod_q_du_d, gvec_vvv, MO_64, do_vaddwod_u_s)
+
+static void do_vavg(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
+void (*gen_shr_vec)(unsigned, TCGv_vec,
+TCGv_vec, int64_t),
+void (*gen_round_vec)(unsigned, TCGv_vec,
+  TCGv_vec, TCGv_vec))
+{
+TCGv_vec tmp = tcg_temp_new_vec_matching(t);
+gen_round_vec(vece, tmp, a, b);
+tcg_gen_and_vec(vece, tmp, tmp, tcg_constant_vec_matching(t, vece, 1));
+gen_shr_vec(vece, a, a, 1);
+gen_shr_vec(vece, b, b, 1);
+tcg_gen_add_vec(vece, t, a, b);
+tcg_gen_add_vec(vece, t, t, tmp);
+}
+
+static void gen_vavg_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+do_vavg(vece, t, a, b, tcg_gen_sari_vec, tcg_gen_and_vec);
+}
+
+static void gen_vavg_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+do_vavg(vece, t, a, b, tcg_gen_shri_vec, tcg_gen_and_vec);
+}
+
+static void gen_vavgr_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+do_vavg(vece, t, a, b, tcg_gen_sari_vec, tcg_gen_or_vec);
+}
+
+static void gen_vavgr_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+do_vavg(vece, t, a, b, tcg_gen_shri_vec, tcg_gen_or_vec);
+}
+
+static void do_vavg_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
+  uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
+{
+static const TCGOpcode vecop_list[] = {
+INDEX_op_sari_vec, INDEX_op_add_vec, 0
+};
+static const GV

[PULL v2 34/45] target/loongarch: Implement LSX fpu fcvt instructions

2023-05-05 Thread Song Gao
This patch includes:
- VFCVT{L/H}.{S.H/D.S};
- VFCVT.{H.S/S.D};
- VFRINT[{RNE/RZ/RP/RM}].{S/D};
- VFTINT[{RNE/RZ/RP/RM}].{W.S/L.D};
- VFTINT[RZ].{WU.S/LU.D};
- VFTINT[{RNE/RZ/RP/RM}].W.D;
- VFTINT[{RNE/RZ/RP/RM}]{L/H}.L.S;
- VFFINT.{S.W/D.L}[U];
- VFFINT.S.L, VFFINT{L/H}.D.W.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-35-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  56 +++
 target/loongarch/helper.h   |  56 +++
 target/loongarch/insn_trans/trans_lsx.c.inc |  56 +++
 target/loongarch/insns.decode   |  56 +++
 target/loongarch/lsx_helper.c   | 376 
 5 files changed, 600 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index b57b284e49..c04271081f 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1348,3 +1348,59 @@ INSN_LSX(vfrecip_s,vv)
 INSN_LSX(vfrecip_d,vv)
 INSN_LSX(vfrsqrt_s,vv)
 INSN_LSX(vfrsqrt_d,vv)
+
+INSN_LSX(vfcvtl_s_h,   vv)
+INSN_LSX(vfcvth_s_h,   vv)
+INSN_LSX(vfcvtl_d_s,   vv)
+INSN_LSX(vfcvth_d_s,   vv)
+INSN_LSX(vfcvt_h_s,vvv)
+INSN_LSX(vfcvt_s_d,vvv)
+
+INSN_LSX(vfrint_s, vv)
+INSN_LSX(vfrint_d, vv)
+INSN_LSX(vfrintrm_s,   vv)
+INSN_LSX(vfrintrm_d,   vv)
+INSN_LSX(vfrintrp_s,   vv)
+INSN_LSX(vfrintrp_d,   vv)
+INSN_LSX(vfrintrz_s,   vv)
+INSN_LSX(vfrintrz_d,   vv)
+INSN_LSX(vfrintrne_s,  vv)
+INSN_LSX(vfrintrne_d,  vv)
+
+INSN_LSX(vftint_w_s,   vv)
+INSN_LSX(vftint_l_d,   vv)
+INSN_LSX(vftintrm_w_s, vv)
+INSN_LSX(vftintrm_l_d, vv)
+INSN_LSX(vftintrp_w_s, vv)
+INSN_LSX(vftintrp_l_d, vv)
+INSN_LSX(vftintrz_w_s, vv)
+INSN_LSX(vftintrz_l_d, vv)
+INSN_LSX(vftintrne_w_s,vv)
+INSN_LSX(vftintrne_l_d,vv)
+INSN_LSX(vftint_wu_s,  vv)
+INSN_LSX(vftint_lu_d,  vv)
+INSN_LSX(vftintrz_wu_s,vv)
+INSN_LSX(vftintrz_lu_d,vv)
+INSN_LSX(vftint_w_d,   vvv)
+INSN_LSX(vftintrm_w_d, vvv)
+INSN_LSX(vftintrp_w_d, vvv)
+INSN_LSX(vftintrz_w_d, vvv)
+INSN_LSX(vftintrne_w_d,vvv)
+INSN_LSX(vftintl_l_s,  vv)
+INSN_LSX(vftinth_l_s,  vv)
+INSN_LSX(vftintrml_l_s,vv)
+INSN_LSX(vftintrmh_l_s,vv)
+INSN_LSX(vftintrpl_l_s,vv)
+INSN_LSX(vftintrph_l_s,vv)
+INSN_LSX(vftintrzl_l_s,vv)
+INSN_LSX(vftintrzh_l_s,vv)
+INSN_LSX(vftintrnel_l_s,   vv)
+INSN_LSX(vftintrneh_l_s,   vv)
+
+INSN_LSX(vffint_s_w,   vv)
+INSN_LSX(vffint_s_wu,  vv)
+INSN_LSX(vffint_d_l,   vv)
+INSN_LSX(vffint_d_lu,  vv)
+INSN_LSX(vffintl_d_w,  vv)
+INSN_LSX(vffinth_d_w,  vv)
+INSN_LSX(vffint_s_l,   vvv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index a0c9de271d..f32235aa97 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -558,3 +558,59 @@ DEF_HELPER_3(vfrecip_s, void, env, i32, i32)
 DEF_HELPER_3(vfrecip_d, void, env, i32, i32)
 DEF_HELPER_3(vfrsqrt_s, void, env, i32, i32)
 DEF_HELPER_3(vfrsqrt_d, void, env, i32, i32)
+
+DEF_HELPER_3(vfcvtl_s_h, void, env, i32, i32)
+DEF_HELPER_3(vfcvth_s_h, void, env, i32, i32)
+DEF_HELPER_3(vfcvtl_d_s, void, env, i32, i32)
+DEF_HELPER_3(vfcvth_d_s, void, env, i32, i32)
+DEF_HELPER_4(vfcvt_h_s, void, env, i32, i32, i32)
+DEF_HELPER_4(vfcvt_s_d, void, env, i32, i32, i32)
+
+DEF_HELPER_3(vfrintrne_s, void, env, i32, i32)
+DEF_HELPER_3(vfrintrne_d, void, env, i32, i32)
+DEF_HELPER_3(vfrintrz_s, void, env, i32, i32)
+DEF_HELPER_3(vfrintrz_d, void, env, i32, i32)
+DEF_HELPER_3(vfrintrp_s, void, env, i32, i32)
+DEF_HELPER_3(vfrintrp_d, void, env, i32, i32)
+DEF_HELPER_3(vfrintrm_s, void, env, i32, i32)
+DEF_HELPER_3(vfrintrm_d, void, env, i32, i32)
+DEF_HELPER_3(vfrint_s, void, env, i32, i32)
+DEF_HELPER_3(vfrint_d, void, env, i32, i32)
+
+DEF_HELPER_3(vftintrne_w_s, void, env, i32, i32)
+DEF_HELPER_3(vftintrne_l_d, void, env, i32, i32)
+DEF_HELPER_3(vftintrz_w_s, void, env, i32, i32)
+DEF_HELPER_3(vftintrz_l_d, void, env, i32, i32)
+DEF_HELPER_3(vftintrp_w_s, void, env, i32, i32)
+DEF_HELPER_3(vftintrp_l_d, void, env, i32, i32)
+DEF_HELPER_3(vftintrm_w_s, void, env, i32, i32)
+DEF_HELPER_3(vftintrm_l_d, void, env, i32, i32)
+DEF_HELPER_3(vftint_w_s, void, env, i32, i32)
+DEF_HELPER_3(vftint_l_d, void, env, i32, i32)
+DEF_HELPER_3(vftintrz_wu_s, void, env, i32, i32)
+DEF_HELPER_3(vftintrz_lu_d, void, env, i32, i32)
+DEF_HELPER_3(vftint_wu_s, void, env, i32, i32)
+DEF_HELPER_3(vftint_lu_d, void, env, i32, i32)
+DEF_HELPER_4(vftintrne_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vftintrz_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vftintrp_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vftintrm_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vftint_w_d, void, env, i32, i32, i32)
+DEF_HELPER_3(vftintrnel_l_s, void, env, i32, i32)
+DEF_HELPER_3(vftintrneh_l_s, void, env, i32, i32)
+DEF_HELPER_3(vftintrzl_l_s, void, env, i32, i32)
+DEF_HELPER_3(vftintrzh_l_s, void, env

[PULL v2 25/45] target/loongarch: Implement vsrln vsran

2023-05-05 Thread Song Gao
This patch includes:
- VSRLN.{B.H/H.W/W.D};
- VSRAN.{B.H/H.W/W.D};
- VSRLNI.{B.H/H.W/W.D/D.Q};
- VSRANI.{B.H/H.W/W.D/D.Q}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-26-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  16 +++
 target/loongarch/helper.h   |  16 +++
 target/loongarch/insn_trans/trans_lsx.c.inc |  16 +++
 target/loongarch/insns.decode   |  17 +++
 target/loongarch/lsx_helper.c   | 114 
 5 files changed, 179 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index c62b6720ec..f0fc2ff84b 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1166,3 +1166,19 @@ INSN_LSX(vsrari_b, vv_i)
 INSN_LSX(vsrari_h, vv_i)
 INSN_LSX(vsrari_w, vv_i)
 INSN_LSX(vsrari_d, vv_i)
+
+INSN_LSX(vsrln_b_h,   vvv)
+INSN_LSX(vsrln_h_w,   vvv)
+INSN_LSX(vsrln_w_d,   vvv)
+INSN_LSX(vsran_b_h,   vvv)
+INSN_LSX(vsran_h_w,   vvv)
+INSN_LSX(vsran_w_d,   vvv)
+
+INSN_LSX(vsrlni_b_h,   vv_i)
+INSN_LSX(vsrlni_h_w,   vv_i)
+INSN_LSX(vsrlni_w_d,   vv_i)
+INSN_LSX(vsrlni_d_q,   vv_i)
+INSN_LSX(vsrani_b_h,   vv_i)
+INSN_LSX(vsrani_h_w,   vv_i)
+INSN_LSX(vsrani_w_d,   vv_i)
+INSN_LSX(vsrani_d_q,   vv_i)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 20a5e7c8e6..afe7e3d2d0 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -379,3 +379,19 @@ DEF_HELPER_4(vsrari_b, void, env, i32, i32, i32)
 DEF_HELPER_4(vsrari_h, void, env, i32, i32, i32)
 DEF_HELPER_4(vsrari_w, void, env, i32, i32, i32)
 DEF_HELPER_4(vsrari_d, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vsrln_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrln_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrln_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vsran_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsran_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsran_w_d, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vsrlni_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlni_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlni_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlni_d_q, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrani_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrani_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrani_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrani_d_q, void, env, i32, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index fb43e1b3ce..ad34378ada 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3005,3 +3005,19 @@ TRANS(vsrari_b, gen_vv_i, gen_helper_vsrari_b)
 TRANS(vsrari_h, gen_vv_i, gen_helper_vsrari_h)
 TRANS(vsrari_w, gen_vv_i, gen_helper_vsrari_w)
 TRANS(vsrari_d, gen_vv_i, gen_helper_vsrari_d)
+
+TRANS(vsrln_b_h, gen_vvv, gen_helper_vsrln_b_h)
+TRANS(vsrln_h_w, gen_vvv, gen_helper_vsrln_h_w)
+TRANS(vsrln_w_d, gen_vvv, gen_helper_vsrln_w_d)
+TRANS(vsran_b_h, gen_vvv, gen_helper_vsran_b_h)
+TRANS(vsran_h_w, gen_vvv, gen_helper_vsran_h_w)
+TRANS(vsran_w_d, gen_vvv, gen_helper_vsran_w_d)
+
+TRANS(vsrlni_b_h, gen_vv_i, gen_helper_vsrlni_b_h)
+TRANS(vsrlni_h_w, gen_vv_i, gen_helper_vsrlni_h_w)
+TRANS(vsrlni_w_d, gen_vv_i, gen_helper_vsrlni_w_d)
+TRANS(vsrlni_d_q, gen_vv_i, gen_helper_vsrlni_d_q)
+TRANS(vsrani_b_h, gen_vv_i, gen_helper_vsrani_b_h)
+TRANS(vsrani_h_w, gen_vv_i, gen_helper_vsrani_h_w)
+TRANS(vsrani_w_d, gen_vv_i, gen_helper_vsrani_w_d)
+TRANS(vsrani_d_q, gen_vv_i, gen_helper_vsrani_d_q)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index a21743..ee54b632a7 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -503,6 +503,7 @@ dbcl  0010 10101 ...  
@i15
 @vv_ui4   . . imm:4 vj:5 vd:5&vv_i
 @vv_ui5     . imm:5 vj:5 vd:5&vv_i
 @vv_ui6   imm:6 vj:5 vd:5&vv_i
+@vv_ui7   ... imm:7 vj:5 vd:5&vv_i
 @vv_ui8    .. imm:8 vj:5 vd:5&vv_i
 @vv_i5     . imm:s5 vj:5 vd:5&vv_i
 
@@ -866,3 +867,19 @@ vsrari_b 0111 00101010 1 01 ... . .   
@vv_ui3
 vsrari_h 0111 00101010 1 1  . .   @vv_ui4
 vsrari_w 0111 00101010 10001 . . .@vv_ui5
 vsrari_d 0111 00101010 1001 .. . .@vv_ui6
+
+vsrln_b_h0111  01001 . . .@vvv
+vsrln_h_w0111  01010 . . .@vvv
+vsrln_w_d0111  01011 . . .@vvv
+vsran_b_h0111  01101 . . .@vvv
+vsran_h_w0111  01110 . . .@vvv
+vsran_w_d0111  0 . . .@vvv
+
+vsrlni_b_h   0111 00

[PULL v2 31/45] target/loongarch: Implement vbitclr vbitset vbitrev

2023-05-05 Thread Song Gao
This patch includes:
- VBITCLR[I].{B/H/W/D};
- VBITSET[I].{B/H/W/D};
- VBITREV[I].{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-32-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  25 ++
 target/loongarch/helper.h   |  27 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 305 
 target/loongarch/insns.decode   |  25 ++
 target/loongarch/lsx_helper.c   |  55 
 5 files changed, 437 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 0ca51de9d8..48c7ea47a4 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1272,3 +1272,28 @@ INSN_LSX(vpcnt_b,  vv)
 INSN_LSX(vpcnt_h,  vv)
 INSN_LSX(vpcnt_w,  vv)
 INSN_LSX(vpcnt_d,  vv)
+
+INSN_LSX(vbitclr_b,vvv)
+INSN_LSX(vbitclr_h,vvv)
+INSN_LSX(vbitclr_w,vvv)
+INSN_LSX(vbitclr_d,vvv)
+INSN_LSX(vbitclri_b,   vv_i)
+INSN_LSX(vbitclri_h,   vv_i)
+INSN_LSX(vbitclri_w,   vv_i)
+INSN_LSX(vbitclri_d,   vv_i)
+INSN_LSX(vbitset_b,vvv)
+INSN_LSX(vbitset_h,vvv)
+INSN_LSX(vbitset_w,vvv)
+INSN_LSX(vbitset_d,vvv)
+INSN_LSX(vbitseti_b,   vv_i)
+INSN_LSX(vbitseti_h,   vv_i)
+INSN_LSX(vbitseti_w,   vv_i)
+INSN_LSX(vbitseti_d,   vv_i)
+INSN_LSX(vbitrev_b,vvv)
+INSN_LSX(vbitrev_h,vvv)
+INSN_LSX(vbitrev_w,vvv)
+INSN_LSX(vbitrev_d,vvv)
+INSN_LSX(vbitrevi_b,   vv_i)
+INSN_LSX(vbitrevi_h,   vv_i)
+INSN_LSX(vbitrevi_w,   vv_i)
+INSN_LSX(vbitrevi_d,   vv_i)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 96b9b16923..75120ca55e 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -485,3 +485,30 @@ DEF_HELPER_3(vpcnt_b, void, env, i32, i32)
 DEF_HELPER_3(vpcnt_h, void, env, i32, i32)
 DEF_HELPER_3(vpcnt_w, void, env, i32, i32)
 DEF_HELPER_3(vpcnt_d, void, env, i32, i32)
+
+DEF_HELPER_FLAGS_4(vbitclr_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vbitclr_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vbitclr_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vbitclr_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vbitclri_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vbitclri_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vbitclri_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vbitclri_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+
+DEF_HELPER_FLAGS_4(vbitset_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vbitset_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vbitset_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vbitset_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vbitseti_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vbitseti_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vbitseti_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vbitseti_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+
+DEF_HELPER_FLAGS_4(vbitrev_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vbitrev_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vbitrev_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vbitrev_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vbitrevi_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vbitrevi_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vbitrevi_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vbitrevi_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index f4ebdca63c..86243b54ba 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3111,3 +3111,308 @@ TRANS(vpcnt_b, gen_vv, gen_helper_vpcnt_b)
 TRANS(vpcnt_h, gen_vv, gen_helper_vpcnt_h)
 TRANS(vpcnt_w, gen_vv, gen_helper_vpcnt_w)
 TRANS(vpcnt_d, gen_vv, gen_helper_vpcnt_d)
+
+static void do_vbit(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
+void (*func)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
+{
+TCGv_vec mask, lsh, t1, one;
+
+lsh = tcg_temp_new_vec_matching(t);
+t1 = tcg_temp_new_vec_matching(t);
+mask = tcg_constant_vec_matching(t, vece, (8 << vece) - 1);
+one = tcg_constant_vec_matching(t, vece, 1);
+
+tcg_gen_and_vec(vece, lsh, b, mask);
+tcg_gen_shlv_vec(vece, t1, one, lsh);
+func(vece, t, a, t1);
+}
+
+static void gen_vbitclr(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+do_vbit(vece, t, a, b, tcg_gen_andc_vec);
+}
+
+static void gen_vbitset(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+do_vbit(vece, t, a, b, t

[PULL v2 44/45] target/loongarch: CPUCFG support LSX

2023-05-05 Thread Song Gao
Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-45-gaos...@loongson.cn>
---
 target/loongarch/cpu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 55d7f9255e..c0afc21b2f 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -388,6 +388,7 @@ static void loongarch_la464_initfn(Object *obj)
 data = FIELD_DP32(data, CPUCFG2, FP_SP, 1);
 data = FIELD_DP32(data, CPUCFG2, FP_DP, 1);
 data = FIELD_DP32(data, CPUCFG2, FP_VER, 1);
+data = FIELD_DP32(data, CPUCFG2, LSX, 1),
 data = FIELD_DP32(data, CPUCFG2, LLFTP, 1);
 data = FIELD_DP32(data, CPUCFG2, LLFTP_VER, 1);
 data = FIELD_DP32(data, CPUCFG2, LAM, 1);
-- 
2.31.1




[PULL v2 41/45] target/loongarch: Implement vld vst

2023-05-05 Thread Song Gao
This patch includes:
- VLD[X], VST[X];
- VLDREPL.{B/H/W/D};
- VSTELM.{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-42-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  34 +
 target/loongarch/insn_trans/trans_lsx.c.inc | 159 
 target/loongarch/insns.decode   |  36 +
 target/loongarch/translate.c|  10 ++
 4 files changed, 239 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 0b62bbb8be..8627908fc9 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -21,11 +21,21 @@ static inline int plus_1(DisasContext *ctx, int x)
 return x + 1;
 }
 
+static inline int shl_1(DisasContext *ctx, int x)
+{
+return x << 1;
+}
+
 static inline int shl_2(DisasContext *ctx, int x)
 {
 return x << 2;
 }
 
+static inline int shl_3(DisasContext *ctx, int x)
+{
+return x << 3;
+}
+
 #define CSR_NAME(REG) \
 [LOONGARCH_CSR_##REG] = (#REG)
 
@@ -823,6 +833,11 @@ static void output_vr_i(DisasContext *ctx, arg_vr_i *a, 
const char *mnemonic)
 output(ctx, mnemonic, "v%d, r%d, 0x%x", a->vd, a->rj, a->imm);
 }
 
+static void output_vr_ii(DisasContext *ctx, arg_vr_ii *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "v%d, r%d, 0x%x, 0x%x", a->vd, a->rj, a->imm, 
a->imm2);
+}
+
 static void output_rv_i(DisasContext *ctx, arg_rv_i *a, const char *mnemonic)
 {
 output(ctx, mnemonic, "r%d, v%d, 0x%x", a->rd, a->vj,  a->imm);
@@ -838,6 +853,11 @@ static void output_vvr(DisasContext *ctx, arg_vvr *a, 
const char *mnemonic)
 output(ctx, mnemonic, "v%d, v%d, r%d", a->vd, a->vj, a->rk);
 }
 
+static void output_vrr(DisasContext *ctx, arg_vrr *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "v%d, r%d, r%d", a->vd, a->rj, a->rk);
+}
+
 INSN_LSX(vadd_b,   vvv)
 INSN_LSX(vadd_h,   vvv)
 INSN_LSX(vadd_w,   vvv)
@@ -1654,3 +1674,17 @@ INSN_LSX(vextrins_d,   vv_i)
 INSN_LSX(vextrins_w,   vv_i)
 INSN_LSX(vextrins_h,   vv_i)
 INSN_LSX(vextrins_b,   vv_i)
+
+INSN_LSX(vld,  vr_i)
+INSN_LSX(vst,  vr_i)
+INSN_LSX(vldx, vrr)
+INSN_LSX(vstx, vrr)
+
+INSN_LSX(vldrepl_d,vr_i)
+INSN_LSX(vldrepl_w,vr_i)
+INSN_LSX(vldrepl_h,vr_i)
+INSN_LSX(vldrepl_b,vr_i)
+INSN_LSX(vstelm_d, vr_ii)
+INSN_LSX(vstelm_w, vr_ii)
+INSN_LSX(vstelm_h, vr_ii)
+INSN_LSX(vstelm_b, vr_ii)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index e1eee6bc4c..86dfd2b399 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -4102,3 +4102,162 @@ TRANS(vextrins_b, gen_vv_i, gen_helper_vextrins_b)
 TRANS(vextrins_h, gen_vv_i, gen_helper_vextrins_h)
 TRANS(vextrins_w, gen_vv_i, gen_helper_vextrins_w)
 TRANS(vextrins_d, gen_vv_i, gen_helper_vextrins_d)
+
+static bool trans_vld(DisasContext *ctx, arg_vr_i *a)
+{
+TCGv addr, temp;
+TCGv_i64 rl, rh;
+TCGv_i128 val;
+
+CHECK_SXE;
+
+addr = gpr_src(ctx, a->rj, EXT_NONE);
+val = tcg_temp_new_i128();
+rl = tcg_temp_new_i64();
+rh = tcg_temp_new_i64();
+
+if (a->imm) {
+temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, addr, a->imm);
+addr = temp;
+}
+
+tcg_gen_qemu_ld_i128(val, addr, ctx->mem_idx, MO_128 | MO_TE);
+tcg_gen_extr_i128_i64(rl, rh, val);
+set_vreg64(rh, a->vd, 1);
+set_vreg64(rl, a->vd, 0);
+
+return true;
+}
+
+static bool trans_vst(DisasContext *ctx, arg_vr_i *a)
+{
+TCGv addr, temp;
+TCGv_i128 val;
+TCGv_i64 ah, al;
+
+CHECK_SXE;
+
+addr = gpr_src(ctx, a->rj, EXT_NONE);
+val = tcg_temp_new_i128();
+ah = tcg_temp_new_i64();
+al = tcg_temp_new_i64();
+
+if (a->imm) {
+temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, addr, a->imm);
+addr = temp;
+}
+
+get_vreg64(ah, a->vd, 1);
+get_vreg64(al, a->vd, 0);
+tcg_gen_concat_i64_i128(val, al, ah);
+tcg_gen_qemu_st_i128(val, addr, ctx->mem_idx, MO_128 | MO_TE);
+
+return true;
+}
+
+static bool trans_vldx(DisasContext *ctx, arg_vrr *a)
+{
+TCGv addr, src1, src2;
+TCGv_i64 rl, rh;
+TCGv_i128 val;
+
+CHECK_SXE;
+
+addr = tcg_temp_new();
+src1 = gpr_src(ctx, a->rj, EXT_NONE);
+src2 = gpr_src(ctx, a->rk, EXT_NONE);
+val = tcg_temp_new_i128();
+rl = tcg_temp_new_i64();
+rh = tcg_temp_new_i64();
+
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_ld_i128(val, addr, ctx->mem_idx, MO_128 | MO_TE);
+tcg_gen_extr_i128_i64(rl, rh, val);
+set_vreg64(rh, a->vd, 1);
+set_vreg64(rl, a->vd, 0);
+
+return true;
+}
+
+static bool trans_vstx(DisasContext *ctx, arg_vrr *a)
+{
+TCGv addr, src1, src2;
+TCGv_i64 ah, al;
+TCGv_i128 val;
+
+CHECK_SXE;
+
+addr = tcg_temp_new();
+src1 = gpr_src(ctx, a

[PULL v2 22/45] target/loongarch: Implement vsll vsrl vsra vrotr

2023-05-05 Thread Song Gao
This patch includes:
- VSLL[I].{B/H/W/D};
- VSRL[I].{B/H/W/D};
- VSRA[I].{B/H/W/D};
- VROTR[I].{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-23-gaos...@loongson.cn>
---
 target/loongarch/disas.c| 36 +
 target/loongarch/insn_trans/trans_lsx.c.inc | 36 +
 target/loongarch/insns.decode   | 36 +
 3 files changed, 108 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index eca0a4bb7b..f7d0fb4441 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1103,3 +1103,39 @@ INSN_LSX(vandi_b,  vv_i)
 INSN_LSX(vori_b,   vv_i)
 INSN_LSX(vxori_b,  vv_i)
 INSN_LSX(vnori_b,  vv_i)
+
+INSN_LSX(vsll_b,   vvv)
+INSN_LSX(vsll_h,   vvv)
+INSN_LSX(vsll_w,   vvv)
+INSN_LSX(vsll_d,   vvv)
+INSN_LSX(vslli_b,  vv_i)
+INSN_LSX(vslli_h,  vv_i)
+INSN_LSX(vslli_w,  vv_i)
+INSN_LSX(vslli_d,  vv_i)
+
+INSN_LSX(vsrl_b,   vvv)
+INSN_LSX(vsrl_h,   vvv)
+INSN_LSX(vsrl_w,   vvv)
+INSN_LSX(vsrl_d,   vvv)
+INSN_LSX(vsrli_b,  vv_i)
+INSN_LSX(vsrli_h,  vv_i)
+INSN_LSX(vsrli_w,  vv_i)
+INSN_LSX(vsrli_d,  vv_i)
+
+INSN_LSX(vsra_b,   vvv)
+INSN_LSX(vsra_h,   vvv)
+INSN_LSX(vsra_w,   vvv)
+INSN_LSX(vsra_d,   vvv)
+INSN_LSX(vsrai_b,  vv_i)
+INSN_LSX(vsrai_h,  vv_i)
+INSN_LSX(vsrai_w,  vv_i)
+INSN_LSX(vsrai_d,  vv_i)
+
+INSN_LSX(vrotr_b,  vvv)
+INSN_LSX(vrotr_h,  vvv)
+INSN_LSX(vrotr_w,  vvv)
+INSN_LSX(vrotr_d,  vvv)
+INSN_LSX(vrotri_b, vv_i)
+INSN_LSX(vrotri_h, vv_i)
+INSN_LSX(vrotri_w, vv_i)
+INSN_LSX(vrotri_d, vv_i)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index e5e194106b..ad8f32ed18 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -2930,3 +2930,39 @@ static void do_vnori_b(unsigned vece, uint32_t vd_ofs, 
uint32_t vj_ofs,
 }
 
 TRANS(vnori_b, gvec_vv_i, MO_8, do_vnori_b)
+
+TRANS(vsll_b, gvec_vvv, MO_8, tcg_gen_gvec_shlv)
+TRANS(vsll_h, gvec_vvv, MO_16, tcg_gen_gvec_shlv)
+TRANS(vsll_w, gvec_vvv, MO_32, tcg_gen_gvec_shlv)
+TRANS(vsll_d, gvec_vvv, MO_64, tcg_gen_gvec_shlv)
+TRANS(vslli_b, gvec_vv_i, MO_8, tcg_gen_gvec_shli)
+TRANS(vslli_h, gvec_vv_i, MO_16, tcg_gen_gvec_shli)
+TRANS(vslli_w, gvec_vv_i, MO_32, tcg_gen_gvec_shli)
+TRANS(vslli_d, gvec_vv_i, MO_64, tcg_gen_gvec_shli)
+
+TRANS(vsrl_b, gvec_vvv, MO_8, tcg_gen_gvec_shrv)
+TRANS(vsrl_h, gvec_vvv, MO_16, tcg_gen_gvec_shrv)
+TRANS(vsrl_w, gvec_vvv, MO_32, tcg_gen_gvec_shrv)
+TRANS(vsrl_d, gvec_vvv, MO_64, tcg_gen_gvec_shrv)
+TRANS(vsrli_b, gvec_vv_i, MO_8, tcg_gen_gvec_shri)
+TRANS(vsrli_h, gvec_vv_i, MO_16, tcg_gen_gvec_shri)
+TRANS(vsrli_w, gvec_vv_i, MO_32, tcg_gen_gvec_shri)
+TRANS(vsrli_d, gvec_vv_i, MO_64, tcg_gen_gvec_shri)
+
+TRANS(vsra_b, gvec_vvv, MO_8, tcg_gen_gvec_sarv)
+TRANS(vsra_h, gvec_vvv, MO_16, tcg_gen_gvec_sarv)
+TRANS(vsra_w, gvec_vvv, MO_32, tcg_gen_gvec_sarv)
+TRANS(vsra_d, gvec_vvv, MO_64, tcg_gen_gvec_sarv)
+TRANS(vsrai_b, gvec_vv_i, MO_8, tcg_gen_gvec_sari)
+TRANS(vsrai_h, gvec_vv_i, MO_16, tcg_gen_gvec_sari)
+TRANS(vsrai_w, gvec_vv_i, MO_32, tcg_gen_gvec_sari)
+TRANS(vsrai_d, gvec_vv_i, MO_64, tcg_gen_gvec_sari)
+
+TRANS(vrotr_b, gvec_vvv, MO_8, tcg_gen_gvec_rotrv)
+TRANS(vrotr_h, gvec_vvv, MO_16, tcg_gen_gvec_rotrv)
+TRANS(vrotr_w, gvec_vvv, MO_32, tcg_gen_gvec_rotrv)
+TRANS(vrotr_d, gvec_vvv, MO_64, tcg_gen_gvec_rotrv)
+TRANS(vrotri_b, gvec_vv_i, MO_8, tcg_gen_gvec_rotri)
+TRANS(vrotri_h, gvec_vv_i, MO_16, tcg_gen_gvec_rotri)
+TRANS(vrotri_w, gvec_vv_i, MO_32, tcg_gen_gvec_rotri)
+TRANS(vrotri_d, gvec_vv_i, MO_64, tcg_gen_gvec_rotri)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 6309683be9..7c0b0c4ac8 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -803,3 +803,39 @@ vandi_b  0111 0001 00  . .
@vv_ui8
 vori_b   0111 0001 01  . .@vv_ui8
 vxori_b  0111 0001 10  . .@vv_ui8
 vnori_b  0111 0001 11  . .@vv_ui8
+
+vsll_b   0111 1110 1 . . .@vvv
+vsll_h   0111 1110 10001 . . .@vvv
+vsll_w   0111 1110 10010 . . .@vvv
+vsll_d   0111 1110 10011 . . .@vvv
+vslli_b  0111 00110010 11000 01 ... . .   @vv_ui3
+vslli_h  0111 00110010 11000 1  . .   @vv_ui4
+vslli_w  0111 00110010 11001 . . .@vv_ui5
+vslli_d  0111 00110010 1101 .. . .@vv_ui6
+
+vsrl_b   0111 1110 10100 . . .

[PULL v2 38/45] target/loongarch: Implement vinsgr2vr vpickve2gr vreplgr2vr

2023-05-05 Thread Song Gao
This patch includes:
- VINSGR2VR.{B/H/W/D};
- VPICKVE2GR.{B/H/W/D}[U];
- VREPLGR2VR.{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-39-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  33 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 110 
 target/loongarch/insns.decode   |  30 ++
 3 files changed, 173 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index ecf0c7b577..7255a2aa4f 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -818,6 +818,21 @@ static void output_(DisasContext *ctx, arg_ *a, 
const char *mnemonic)
 output(ctx, mnemonic, "v%d, v%d, v%d, v%d", a->vd, a->vj, a->vk, a->va);
 }
 
+static void output_vr_i(DisasContext *ctx, arg_vr_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "v%d, r%d, 0x%x", a->vd, a->rj, a->imm);
+}
+
+static void output_rv_i(DisasContext *ctx, arg_rv_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, v%d, 0x%x", a->rd, a->vj,  a->imm);
+}
+
+static void output_vr(DisasContext *ctx, arg_vr *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "v%d, r%d", a->vd, a->rj);
+}
+
 INSN_LSX(vadd_b,   vvv)
 INSN_LSX(vadd_h,   vvv)
 INSN_LSX(vadd_w,   vvv)
@@ -1561,3 +1576,21 @@ INSN_LSX(vsetallnez_b, cv)
 INSN_LSX(vsetallnez_h, cv)
 INSN_LSX(vsetallnez_w, cv)
 INSN_LSX(vsetallnez_d, cv)
+
+INSN_LSX(vinsgr2vr_b,  vr_i)
+INSN_LSX(vinsgr2vr_h,  vr_i)
+INSN_LSX(vinsgr2vr_w,  vr_i)
+INSN_LSX(vinsgr2vr_d,  vr_i)
+INSN_LSX(vpickve2gr_b, rv_i)
+INSN_LSX(vpickve2gr_h, rv_i)
+INSN_LSX(vpickve2gr_w, rv_i)
+INSN_LSX(vpickve2gr_d, rv_i)
+INSN_LSX(vpickve2gr_bu,rv_i)
+INSN_LSX(vpickve2gr_hu,rv_i)
+INSN_LSX(vpickve2gr_wu,rv_i)
+INSN_LSX(vpickve2gr_du,rv_i)
+
+INSN_LSX(vreplgr2vr_b, vr)
+INSN_LSX(vreplgr2vr_h, vr)
+INSN_LSX(vreplgr2vr_w, vr)
+INSN_LSX(vreplgr2vr_d, vr)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 964c3c47bf..e722b79bea 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3823,3 +3823,113 @@ TRANS(vsetallnez_b, gen_cv, gen_helper_vsetallnez_b)
 TRANS(vsetallnez_h, gen_cv, gen_helper_vsetallnez_h)
 TRANS(vsetallnez_w, gen_cv, gen_helper_vsetallnez_w)
 TRANS(vsetallnez_d, gen_cv, gen_helper_vsetallnez_d)
+
+static bool trans_vinsgr2vr_b(DisasContext *ctx, arg_vr_i *a)
+{
+CHECK_SXE;
+tcg_gen_st8_i64(cpu_gpr[a->rj], cpu_env,
+offsetof(CPULoongArchState, fpr[a->vd].vreg.B(a->imm)));
+return true;
+}
+
+static bool trans_vinsgr2vr_h(DisasContext *ctx, arg_vr_i *a)
+{
+CHECK_SXE;
+tcg_gen_st16_i64(cpu_gpr[a->rj], cpu_env,
+offsetof(CPULoongArchState, fpr[a->vd].vreg.H(a->imm)));
+return true;
+}
+
+static bool trans_vinsgr2vr_w(DisasContext *ctx, arg_vr_i *a)
+{
+CHECK_SXE;
+tcg_gen_st32_i64(cpu_gpr[a->rj], cpu_env,
+ offsetof(CPULoongArchState, fpr[a->vd].vreg.W(a->imm)));
+return true;
+}
+
+static bool trans_vinsgr2vr_d(DisasContext *ctx, arg_vr_i *a)
+{
+CHECK_SXE;
+tcg_gen_st_i64(cpu_gpr[a->rj], cpu_env,
+   offsetof(CPULoongArchState, fpr[a->vd].vreg.D(a->imm)));
+return true;
+}
+
+static bool trans_vpickve2gr_b(DisasContext *ctx, arg_rv_i *a)
+{
+CHECK_SXE;
+tcg_gen_ld8s_i64(cpu_gpr[a->rd], cpu_env,
+ offsetof(CPULoongArchState, fpr[a->vj].vreg.B(a->imm)));
+return true;
+}
+
+static bool trans_vpickve2gr_h(DisasContext *ctx, arg_rv_i *a)
+{
+CHECK_SXE;
+tcg_gen_ld16s_i64(cpu_gpr[a->rd], cpu_env,
+  offsetof(CPULoongArchState, fpr[a->vj].vreg.H(a->imm)));
+return true;
+}
+
+static bool trans_vpickve2gr_w(DisasContext *ctx, arg_rv_i *a)
+{
+CHECK_SXE;
+tcg_gen_ld32s_i64(cpu_gpr[a->rd], cpu_env,
+  offsetof(CPULoongArchState, fpr[a->vj].vreg.W(a->imm)));
+return true;
+}
+
+static bool trans_vpickve2gr_d(DisasContext *ctx, arg_rv_i *a)
+{
+CHECK_SXE;
+tcg_gen_ld_i64(cpu_gpr[a->rd], cpu_env,
+   offsetof(CPULoongArchState, fpr[a->vj].vreg.D(a->imm)));
+return true;
+}
+
+static bool trans_vpickve2gr_bu(DisasContext *ctx, arg_rv_i *a)
+{
+CHECK_SXE;
+tcg_gen_ld8u_i64(cpu_gpr[a->rd], cpu_env,
+ offsetof(CPULoongArchState, fpr[a->vj].vreg.B(a->imm)));
+return true;
+}
+
+static bool trans_vpickve2gr_hu(DisasContext *ctx, arg_rv_i *a)
+{
+CHECK_SXE;
+tcg_gen_ld16u_i64(cpu_gpr[a->rd], cpu_env,
+  offsetof(CPULoongArchState, fpr[a->vj].vreg.H(a->imm)));
+return true;
+}
+
+static bool trans_vpickve2gr_wu(DisasContext *ctx, arg_rv_i *a)
+{
+CHECK_SXE;
+tcg_gen_ld32u_i64(cpu_gpr[a->rd], cpu_env,
+  offsetof(CPULoongArchStat

[PULL v2 03/45] target/loongarch: Add CHECK_SXE maccro for check LSX enable

2023-05-05 Thread Song Gao
Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-4-gaos...@loongson.cn>
---
 target/loongarch/cpu.c  |  2 ++
 target/loongarch/cpu.h  |  2 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 11 +++
 3 files changed, 15 insertions(+)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 18b41221a6..55d7f9255e 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -52,6 +52,7 @@ static const char * const excp_names[] = {
 [EXCCODE_FPE] = "Floating Point Exception",
 [EXCCODE_DBP] = "Debug breakpoint",
 [EXCCODE_BCE] = "Bound Check Exception",
+[EXCCODE_SXD] = "128 bit vector instructions Disable exception",
 };
 
 const char *loongarch_exception_name(int32_t exception)
@@ -187,6 +188,7 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
 case EXCCODE_FPD:
 case EXCCODE_FPE:
 case EXCCODE_BCE:
+case EXCCODE_SXD:
 env->CSR_BADV = env->pc;
 QEMU_FALLTHROUGH;
 case EXCCODE_ADEM:
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index fd0f61936d..6755b1f0c7 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -419,6 +419,7 @@ static inline int cpu_mmu_index(CPULoongArchState *env, 
bool ifetch)
 #define HW_FLAGS_PLV_MASK   R_CSR_CRMD_PLV_MASK  /* 0x03 */
 #define HW_FLAGS_CRMD_PGR_CSR_CRMD_PG_MASK   /* 0x10 */
 #define HW_FLAGS_EUEN_FPE   0x04
+#define HW_FLAGS_EUEN_SXE   0x08
 
 static inline void cpu_get_tb_cpu_state(CPULoongArchState *env,
 target_ulong *pc,
@@ -429,6 +430,7 @@ static inline void cpu_get_tb_cpu_state(CPULoongArchState 
*env,
 *cs_base = 0;
 *flags = env->CSR_CRMD & (R_CSR_CRMD_PLV_MASK | R_CSR_CRMD_PG_MASK);
 *flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, FPE) * HW_FLAGS_EUEN_FPE;
+*flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE) * HW_FLAGS_EUEN_SXE;
 }
 
 void loongarch_cpu_list(void);
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 1cf3ab34a9..5dedb044d7 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3,3 +3,14 @@
  * LSX translate functions
  * Copyright (c) 2022-2023 Loongson Technology Corporation Limited
  */
+
+#ifndef CONFIG_USER_ONLY
+#define CHECK_SXE do { \
+if ((ctx->base.tb->flags & HW_FLAGS_EUEN_SXE) == 0) { \
+generate_exception(ctx, EXCCODE_SXD); \
+return true; \
+} \
+} while (0)
+#else
+#define CHECK_SXE
+#endif
-- 
2.31.1




[PULL v2 18/45] target/loongarch: Implement vexth

2023-05-05 Thread Song Gao
This patch includes:
- VEXTH.{H.B/W.H/D.W/Q.D};
- VEXTH.{HU.BU/WU.HU/DU.WU/QU.DU}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-19-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  9 ++
 target/loongarch/helper.h   |  9 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 20 
 target/loongarch/insns.decode   |  9 ++
 target/loongarch/lsx_helper.c   | 35 +
 5 files changed, 82 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index b04aefe3ed..412c1cedcb 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1070,3 +1070,12 @@ INSN_LSX(vsat_bu,  vv_i)
 INSN_LSX(vsat_hu,  vv_i)
 INSN_LSX(vsat_wu,  vv_i)
 INSN_LSX(vsat_du,  vv_i)
+
+INSN_LSX(vexth_h_b,vv)
+INSN_LSX(vexth_w_h,vv)
+INSN_LSX(vexth_d_w,vv)
+INSN_LSX(vexth_q_d,vv)
+INSN_LSX(vexth_hu_bu,  vv)
+INSN_LSX(vexth_wu_hu,  vv)
+INSN_LSX(vexth_du_wu,  vv)
+INSN_LSX(vexth_qu_du,  vv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index d2b1c9f2a4..005988be25 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -329,3 +329,12 @@ DEF_HELPER_FLAGS_4(vsat_bu, TCG_CALL_NO_RWG, void, ptr, 
ptr, i64, i32)
 DEF_HELPER_FLAGS_4(vsat_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
 DEF_HELPER_FLAGS_4(vsat_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
 DEF_HELPER_FLAGS_4(vsat_du, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+
+DEF_HELPER_3(vexth_h_b, void, env, i32, i32)
+DEF_HELPER_3(vexth_w_h, void, env, i32, i32)
+DEF_HELPER_3(vexth_d_w, void, env, i32, i32)
+DEF_HELPER_3(vexth_q_d, void, env, i32, i32)
+DEF_HELPER_3(vexth_hu_bu, void, env, i32, i32)
+DEF_HELPER_3(vexth_wu_hu, void, env, i32, i32)
+DEF_HELPER_3(vexth_du_wu, void, env, i32, i32)
+DEF_HELPER_3(vexth_qu_du, void, env, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index b8f05c66a5..93ae76bc4c 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -28,6 +28,17 @@ static bool gen_vvv(DisasContext *ctx, arg_vvv *a,
 return true;
 }
 
+static bool gen_vv(DisasContext *ctx, arg_vv *a,
+   void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32))
+{
+TCGv_i32 vd = tcg_constant_i32(a->vd);
+TCGv_i32 vj = tcg_constant_i32(a->vj);
+
+CHECK_SXE;
+func(cpu_env, vd, vj);
+return true;
+}
+
 static bool gvec_vvv(DisasContext *ctx, arg_vvv *a, MemOp mop,
  void (*func)(unsigned, uint32_t, uint32_t,
   uint32_t, uint32_t, uint32_t))
@@ -2794,3 +2805,12 @@ TRANS(vsat_bu, gvec_vv_i, MO_8, do_vsat_u)
 TRANS(vsat_hu, gvec_vv_i, MO_16, do_vsat_u)
 TRANS(vsat_wu, gvec_vv_i, MO_32, do_vsat_u)
 TRANS(vsat_du, gvec_vv_i, MO_64, do_vsat_u)
+
+TRANS(vexth_h_b, gen_vv, gen_helper_vexth_h_b)
+TRANS(vexth_w_h, gen_vv, gen_helper_vexth_w_h)
+TRANS(vexth_d_w, gen_vv, gen_helper_vexth_d_w)
+TRANS(vexth_q_d, gen_vv, gen_helper_vexth_q_d)
+TRANS(vexth_hu_bu, gen_vv, gen_helper_vexth_hu_bu)
+TRANS(vexth_wu_hu, gen_vv, gen_helper_vexth_wu_hu)
+TRANS(vexth_du_wu, gen_vv, gen_helper_vexth_du_wu)
+TRANS(vexth_qu_du, gen_vv, gen_helper_vexth_qu_du)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 3ed61b3d68..39c582d098 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -769,3 +769,12 @@ vsat_bu  0111 00110010 1 01 ... . .   
@vv_ui3
 vsat_hu  0111 00110010 1 1  . .   @vv_ui4
 vsat_wu  0111 00110010 10001 . . .@vv_ui5
 vsat_du  0111 00110010 1001 .. . .@vv_ui6
+
+vexth_h_b0111 00101001 11101 11000 . .@vv
+vexth_w_h0111 00101001 11101 11001 . .@vv
+vexth_d_w0111 00101001 11101 11010 . .@vv
+vexth_q_d0111 00101001 11101 11011 . .@vv
+vexth_hu_bu  0111 00101001 11101 11100 . .@vv
+vexth_wu_hu  0111 00101001 11101 11101 . .@vv
+vexth_du_wu  0111 00101001 11101 0 . .@vv
+vexth_qu_du  0111 00101001 11101 1 . .@vv
diff --git a/target/loongarch/lsx_helper.c b/target/loongarch/lsx_helper.c
index 9ba16ac631..b4582a49d9 100644
--- a/target/loongarch/lsx_helper.c
+++ b/target/loongarch/lsx_helper.c
@@ -627,3 +627,38 @@ VSAT_U(vsat_bu, 8, UB)
 VSAT_U(vsat_hu, 16, UH)
 VSAT_U(vsat_wu, 32, UW)
 VSAT_U(vsat_du, 64, UD)
+
+#define VEXTH(NAME, BIT, E1, E2)\
+void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
+{   \
+int i;  \
+VReg *Vd = &(env->fpr[vd].vreg);   

[PULL v2 29/45] target/loongarch: Implement vclo vclz

2023-05-05 Thread Song Gao
This patch includes:
- VCLO.{B/H/W/D};
- VCLZ.{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-30-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  9 ++
 target/loongarch/helper.h   |  9 ++
 target/loongarch/insn_trans/trans_lsx.c.inc |  9 ++
 target/loongarch/insns.decode   |  9 ++
 target/loongarch/lsx_helper.c   | 31 +
 5 files changed, 67 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 405e8885cd..0c82a1d9d1 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1258,3 +1258,12 @@ INSN_LSX(vssrarni_bu_h,vv_i)
 INSN_LSX(vssrarni_hu_w,vv_i)
 INSN_LSX(vssrarni_wu_d,vv_i)
 INSN_LSX(vssrarni_du_q,vv_i)
+
+INSN_LSX(vclo_b,   vv)
+INSN_LSX(vclo_h,   vv)
+INSN_LSX(vclo_w,   vv)
+INSN_LSX(vclo_d,   vv)
+INSN_LSX(vclz_b,   vv)
+INSN_LSX(vclz_h,   vv)
+INSN_LSX(vclz_w,   vv)
+INSN_LSX(vclz_d,   vv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 724112da81..e21e9b9704 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -471,3 +471,12 @@ DEF_HELPER_4(vssrarni_bu_h, void, env, i32, i32, i32)
 DEF_HELPER_4(vssrarni_hu_w, void, env, i32, i32, i32)
 DEF_HELPER_4(vssrarni_wu_d, void, env, i32, i32, i32)
 DEF_HELPER_4(vssrarni_du_q, void, env, i32, i32, i32)
+
+DEF_HELPER_3(vclo_b, void, env, i32, i32)
+DEF_HELPER_3(vclo_h, void, env, i32, i32)
+DEF_HELPER_3(vclo_w, void, env, i32, i32)
+DEF_HELPER_3(vclo_d, void, env, i32, i32)
+DEF_HELPER_3(vclz_b, void, env, i32, i32)
+DEF_HELPER_3(vclz_h, void, env, i32, i32)
+DEF_HELPER_3(vclz_w, void, env, i32, i32)
+DEF_HELPER_3(vclz_d, void, env, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 9c24cbc297..c7649fb777 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3097,3 +3097,12 @@ TRANS(vssrarni_bu_h, gen_vv_i, gen_helper_vssrarni_bu_h)
 TRANS(vssrarni_hu_w, gen_vv_i, gen_helper_vssrarni_hu_w)
 TRANS(vssrarni_wu_d, gen_vv_i, gen_helper_vssrarni_wu_d)
 TRANS(vssrarni_du_q, gen_vv_i, gen_helper_vssrarni_du_q)
+
+TRANS(vclo_b, gen_vv, gen_helper_vclo_b)
+TRANS(vclo_h, gen_vv, gen_helper_vclo_h)
+TRANS(vclo_w, gen_vv, gen_helper_vclo_w)
+TRANS(vclo_d, gen_vv, gen_helper_vclo_d)
+TRANS(vclz_b, gen_vv, gen_helper_vclz_b)
+TRANS(vclz_h, gen_vv, gen_helper_vclz_h)
+TRANS(vclz_w, gen_vv, gen_helper_vclz_w)
+TRANS(vclz_d, gen_vv, gen_helper_vclz_d)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index bb4b2a8632..7591ec1bab 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -959,3 +959,12 @@ vssrarni_bu_h0111 00110110 11000 1  . .   
@vv_ui4
 vssrarni_hu_w0111 00110110 11001 . . .@vv_ui5
 vssrarni_wu_d0111 00110110 1101 .. . .@vv_ui6
 vssrarni_du_q0111 00110110 111 ... . .@vv_ui7
+
+vclo_b   0111 00101001 11000 0 . .@vv
+vclo_h   0111 00101001 11000 1 . .@vv
+vclo_w   0111 00101001 11000 00010 . .@vv
+vclo_d   0111 00101001 11000 00011 . .@vv
+vclz_b   0111 00101001 11000 00100 . .@vv
+vclz_h   0111 00101001 11000 00101 . .@vv
+vclz_w   0111 00101001 11000 00110 . .@vv
+vclz_d   0111 00101001 11000 00111 . .@vv
diff --git a/target/loongarch/lsx_helper.c b/target/loongarch/lsx_helper.c
index 5fc22eab0b..e808e5fc83 100644
--- a/target/loongarch/lsx_helper.c
+++ b/target/loongarch/lsx_helper.c
@@ -1915,3 +1915,34 @@ void HELPER(vssrarni_du_q)(CPULoongArchState *env,
 VSSRARNUI(vssrarni_bu_h, 16, B, H)
 VSSRARNUI(vssrarni_hu_w, 32, H, W)
 VSSRARNUI(vssrarni_wu_d, 64, W, D)
+
+#define DO_2OP(NAME, BIT, E, DO_OP) \
+void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
+{   \
+int i;  \
+VReg *Vd = &(env->fpr[vd].vreg);\
+VReg *Vj = &(env->fpr[vj].vreg);\
+\
+for (i = 0; i < LSX_LEN/BIT; i++)   \
+{   \
+Vd->E(i) = DO_OP(Vj->E(i)); \
+}   \
+}
+
+#define DO_CLO_B(N)  (clz32(~N & 0xff) - 24)
+#define DO_CLO_H(N)  (clz32(~N & 0x) - 16)
+#define DO_CLO_W(N)  (clz32(~N))
+#define DO_CLO_D(N)  (clz64(~N))
+#define DO_CLZ_B(N)  (clz3

[PULL v2 45/45] hw/intc: don't use target_ulong for LoongArch ipi

2023-05-05 Thread Song Gao
From: Alex Bennée 

The calling function is already working with hwaddr and uint64_t so
lets avoid bringing target_ulong in if we don't need to.

Signed-off-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Song Gao 
Message-Id: <20230404132711.2563638-1-alex.ben...@linaro.org>
Signed-off-by: Song Gao 
---
 hw/intc/loongarch_ipi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index aa4bf9eb74..bdba0f8107 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -50,7 +50,7 @@ static uint64_t loongarch_ipi_readl(void *opaque, hwaddr 
addr, unsigned size)
 return ret;
 }
 
-static void send_ipi_data(CPULoongArchState *env, target_ulong val, 
target_ulong addr)
+static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr)
 {
 int i, mask = 0, data = 0;
 
-- 
2.31.1




[PULL v2 40/45] target/loongarch: Implement vilvl vilvh vextrins vshuf

2023-05-05 Thread Song Gao
This patch includes:
- VILV{L/H}.{B/H/W/D};
- VSHUF.{B/H/W/D};
- VSHUF4I.{B/H/W/D};
- VPERMI.W;
- VEXTRINS.{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-41-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  25 
 target/loongarch/helper.h   |  25 
 target/loongarch/insn_trans/trans_lsx.c.inc |  25 
 target/loongarch/insns.decode   |  25 
 target/loongarch/lsx_helper.c   | 148 
 5 files changed, 248 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index c6cf782725..0b62bbb8be 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1629,3 +1629,28 @@ INSN_LSX(vpickod_b,vvv)
 INSN_LSX(vpickod_h,vvv)
 INSN_LSX(vpickod_w,vvv)
 INSN_LSX(vpickod_d,vvv)
+
+INSN_LSX(vilvl_b,  vvv)
+INSN_LSX(vilvl_h,  vvv)
+INSN_LSX(vilvl_w,  vvv)
+INSN_LSX(vilvl_d,  vvv)
+INSN_LSX(vilvh_b,  vvv)
+INSN_LSX(vilvh_h,  vvv)
+INSN_LSX(vilvh_w,  vvv)
+INSN_LSX(vilvh_d,  vvv)
+
+INSN_LSX(vshuf_b,  )
+INSN_LSX(vshuf_h,  vvv)
+INSN_LSX(vshuf_w,  vvv)
+INSN_LSX(vshuf_d,  vvv)
+INSN_LSX(vshuf4i_b,vv_i)
+INSN_LSX(vshuf4i_h,vv_i)
+INSN_LSX(vshuf4i_w,vv_i)
+INSN_LSX(vshuf4i_d,vv_i)
+
+INSN_LSX(vpermi_w, vv_i)
+
+INSN_LSX(vextrins_d,   vv_i)
+INSN_LSX(vextrins_w,   vv_i)
+INSN_LSX(vextrins_h,   vv_i)
+INSN_LSX(vextrins_b,   vv_i)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 51ad694be2..b9de77d926 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -671,3 +671,28 @@ DEF_HELPER_4(vpickod_b, void, env, i32, i32, i32)
 DEF_HELPER_4(vpickod_h, void, env, i32, i32, i32)
 DEF_HELPER_4(vpickod_w, void, env, i32, i32, i32)
 DEF_HELPER_4(vpickod_d, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vilvl_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vilvl_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vilvl_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vilvl_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vilvh_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vilvh_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vilvh_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vilvh_d, void, env, i32, i32, i32)
+
+DEF_HELPER_5(vshuf_b, void, env, i32, i32, i32, i32)
+DEF_HELPER_4(vshuf_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vshuf_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vshuf_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vshuf4i_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vshuf4i_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vshuf4i_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vshuf4i_d, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vpermi_w, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vextrins_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vextrins_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vextrins_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vextrins_d, void, env, i32, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 1146ace1b7..e1eee6bc4c 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -4077,3 +4077,28 @@ TRANS(vpickod_b, gen_vvv, gen_helper_vpickod_b)
 TRANS(vpickod_h, gen_vvv, gen_helper_vpickod_h)
 TRANS(vpickod_w, gen_vvv, gen_helper_vpickod_w)
 TRANS(vpickod_d, gen_vvv, gen_helper_vpickod_d)
+
+TRANS(vilvl_b, gen_vvv, gen_helper_vilvl_b)
+TRANS(vilvl_h, gen_vvv, gen_helper_vilvl_h)
+TRANS(vilvl_w, gen_vvv, gen_helper_vilvl_w)
+TRANS(vilvl_d, gen_vvv, gen_helper_vilvl_d)
+TRANS(vilvh_b, gen_vvv, gen_helper_vilvh_b)
+TRANS(vilvh_h, gen_vvv, gen_helper_vilvh_h)
+TRANS(vilvh_w, gen_vvv, gen_helper_vilvh_w)
+TRANS(vilvh_d, gen_vvv, gen_helper_vilvh_d)
+
+TRANS(vshuf_b, gen_, gen_helper_vshuf_b)
+TRANS(vshuf_h, gen_vvv, gen_helper_vshuf_h)
+TRANS(vshuf_w, gen_vvv, gen_helper_vshuf_w)
+TRANS(vshuf_d, gen_vvv, gen_helper_vshuf_d)
+TRANS(vshuf4i_b, gen_vv_i, gen_helper_vshuf4i_b)
+TRANS(vshuf4i_h, gen_vv_i, gen_helper_vshuf4i_h)
+TRANS(vshuf4i_w, gen_vv_i, gen_helper_vshuf4i_w)
+TRANS(vshuf4i_d, gen_vv_i, gen_helper_vshuf4i_d)
+
+TRANS(vpermi_w, gen_vv_i, gen_helper_vpermi_w)
+
+TRANS(vextrins_b, gen_vv_i, gen_helper_vextrins_b)
+TRANS(vextrins_h, gen_vv_i, gen_helper_vextrins_h)
+TRANS(vextrins_w, gen_vv_i, gen_helper_vextrins_w)
+TRANS(vextrins_d, gen_vv_i, gen_helper_vextrins_d)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index ab9e9e422f..0263bce28e 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -1231,3 +1231,28 @@ vpickod_b0111 00010010 0 . . .   
 @vvv
 vpickod_h0111 00010010 1 . . .@vvv
 vpickod_w0111 00010010 00010 . . .@vvv
 vpickod_d0111 00010010 00011 . . .@vvv
+
+vilvl_b 

[PULL v2 37/45] target/loongarch: Implement vbitsel vset

2023-05-05 Thread Song Gao
This patch includes:
- VBITSEL.V;
- VBITSELI.B;
- VSET{EQZ/NEZ}.V;
- VSETANYEQZ.{B/H/W/D};
- VSETALLNEZ.{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-38-gaos...@loongson.cn>
---
 target/loongarch/disas.c| 20 ++
 target/loongarch/helper.h   | 11 +++
 target/loongarch/insn_trans/trans_lsx.c.inc | 74 +
 target/loongarch/insns.decode   | 17 +
 target/loongarch/lsx_helper.c   | 52 +++
 5 files changed, 174 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 64db01d2f9..ecf0c7b577 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -792,6 +792,12 @@ static bool trans_##insn(DisasContext *ctx, arg_##type * 
a) \
 return true;\
 }
 
+static void output_cv(DisasContext *ctx, arg_cv *a,
+const char *mnemonic)
+{
+output(ctx, mnemonic, "fcc%d, v%d", a->cd, a->vj);
+}
+
 static void output_vvv(DisasContext *ctx, arg_vvv *a, const char *mnemonic)
 {
 output(ctx, mnemonic, "v%d, v%d, v%d", a->vd, a->vj, a->vk);
@@ -1541,3 +1547,17 @@ static bool trans_vfcmp_cond_##suffix(DisasContext *ctx, 
\
 
 LSX_FCMP_INSN(s)
 LSX_FCMP_INSN(d)
+
+INSN_LSX(vbitsel_v,)
+INSN_LSX(vbitseli_b,   vv_i)
+
+INSN_LSX(vseteqz_v,cv)
+INSN_LSX(vsetnez_v,cv)
+INSN_LSX(vsetanyeqz_b, cv)
+INSN_LSX(vsetanyeqz_h, cv)
+INSN_LSX(vsetanyeqz_w, cv)
+INSN_LSX(vsetanyeqz_d, cv)
+INSN_LSX(vsetallnez_b, cv)
+INSN_LSX(vsetallnez_h, cv)
+INSN_LSX(vsetallnez_w, cv)
+INSN_LSX(vsetallnez_d, cv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 867756fdb5..8eb2738cd0 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -642,3 +642,14 @@ DEF_HELPER_5(vfcmp_c_s, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(vfcmp_s_s, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(vfcmp_c_d, void, env, i32, i32, i32, i32)
 DEF_HELPER_5(vfcmp_s_d, void, env, i32, i32, i32, i32)
+
+DEF_HELPER_FLAGS_4(vbitseli_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+
+DEF_HELPER_3(vsetanyeqz_b, void, env, i32, i32)
+DEF_HELPER_3(vsetanyeqz_h, void, env, i32, i32)
+DEF_HELPER_3(vsetanyeqz_w, void, env, i32, i32)
+DEF_HELPER_3(vsetanyeqz_d, void, env, i32, i32)
+DEF_HELPER_3(vsetallnez_b, void, env, i32, i32)
+DEF_HELPER_3(vsetallnez_h, void, env, i32, i32)
+DEF_HELPER_3(vsetallnez_w, void, env, i32, i32)
+DEF_HELPER_3(vsetallnez_d, void, env, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index abb6efc09d..964c3c47bf 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -65,6 +65,17 @@ static bool gen_vv_i(DisasContext *ctx, arg_vv_i *a,
 return true;
 }
 
+static bool gen_cv(DisasContext *ctx, arg_cv *a,
+void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32))
+{
+TCGv_i32 vj = tcg_constant_i32(a->vj);
+TCGv_i32 cd = tcg_constant_i32(a->cd);
+
+CHECK_SXE;
+func(cpu_env, cd, vj);
+return true;
+}
+
 static bool gvec_vvv(DisasContext *ctx, arg_vvv *a, MemOp mop,
  void (*func)(unsigned, uint32_t, uint32_t,
   uint32_t, uint32_t, uint32_t))
@@ -3749,3 +3760,66 @@ static bool trans_vfcmp_cond_d(DisasContext *ctx, 
arg_vvv_fcond *a)
 
 return true;
 }
+
+static bool trans_vbitsel_v(DisasContext *ctx, arg_ *a)
+{
+CHECK_SXE;
+
+tcg_gen_gvec_bitsel(MO_64, vec_full_offset(a->vd), vec_full_offset(a->va),
+vec_full_offset(a->vk), vec_full_offset(a->vj),
+16, ctx->vl/8);
+return true;
+}
+
+static void gen_vbitseli(unsigned vece, TCGv_vec a, TCGv_vec b, int64_t imm)
+{
+tcg_gen_bitsel_vec(vece, a, a, tcg_constant_vec_matching(a, vece, imm), b);
+}
+
+static bool trans_vbitseli_b(DisasContext *ctx, arg_vv_i *a)
+{
+static const GVecGen2i op = {
+   .fniv = gen_vbitseli,
+   .fnoi = gen_helper_vbitseli_b,
+   .vece = MO_8,
+   .load_dest = true
+};
+
+CHECK_SXE;
+
+tcg_gen_gvec_2i(vec_full_offset(a->vd), vec_full_offset(a->vj),
+16, ctx->vl/8, a->imm, &op);
+return true;
+}
+
+#define VSET(NAME, COND)   
\
+static bool trans_## NAME (DisasContext *ctx, arg_cv *a)   
\
+{  
\
+TCGv_i64 t1, al, ah;   
\
+   
\
+al = tcg_temp_new_i64();   
\
+ah = tcg_temp_new_i64();   
\
+t1 = tcg_temp_new_i64();   

[PULL v2 27/45] target/loongarch: Implement vssrln vssran

2023-05-05 Thread Song Gao
This patch includes:
- VSSRLN.{B.H/H.W/W.D};
- VSSRAN.{B.H/H.W/W.D};
- VSSRLN.{BU.H/HU.W/WU.D};
- VSSRAN.{BU.H/HU.W/WU.D};
- VSSRLNI.{B.H/H.W/W.D/D.Q};
- VSSRANI.{B.H/H.W/W.D/D.Q};
- VSSRLNI.{BU.H/HU.W/WU.D/DU.Q};
- VSSRANI.{BU.H/HU.W/WU.D/DU.Q}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-28-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  30 ++
 target/loongarch/helper.h   |  30 ++
 target/loongarch/insn_trans/trans_lsx.c.inc |  30 ++
 target/loongarch/insns.decode   |  30 ++
 target/loongarch/lsx_helper.c   | 379 
 5 files changed, 499 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 185cd36381..426d30dc01 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1198,3 +1198,33 @@ INSN_LSX(vsrarni_b_h,  vv_i)
 INSN_LSX(vsrarni_h_w,  vv_i)
 INSN_LSX(vsrarni_w_d,  vv_i)
 INSN_LSX(vsrarni_d_q,  vv_i)
+
+INSN_LSX(vssrln_b_h,   vvv)
+INSN_LSX(vssrln_h_w,   vvv)
+INSN_LSX(vssrln_w_d,   vvv)
+INSN_LSX(vssran_b_h,   vvv)
+INSN_LSX(vssran_h_w,   vvv)
+INSN_LSX(vssran_w_d,   vvv)
+INSN_LSX(vssrln_bu_h,  vvv)
+INSN_LSX(vssrln_hu_w,  vvv)
+INSN_LSX(vssrln_wu_d,  vvv)
+INSN_LSX(vssran_bu_h,  vvv)
+INSN_LSX(vssran_hu_w,  vvv)
+INSN_LSX(vssran_wu_d,  vvv)
+
+INSN_LSX(vssrlni_b_h,  vv_i)
+INSN_LSX(vssrlni_h_w,  vv_i)
+INSN_LSX(vssrlni_w_d,  vv_i)
+INSN_LSX(vssrlni_d_q,  vv_i)
+INSN_LSX(vssrani_b_h,  vv_i)
+INSN_LSX(vssrani_h_w,  vv_i)
+INSN_LSX(vssrani_w_d,  vv_i)
+INSN_LSX(vssrani_d_q,  vv_i)
+INSN_LSX(vssrlni_bu_h, vv_i)
+INSN_LSX(vssrlni_hu_w, vv_i)
+INSN_LSX(vssrlni_wu_d, vv_i)
+INSN_LSX(vssrlni_du_q, vv_i)
+INSN_LSX(vssrani_bu_h, vv_i)
+INSN_LSX(vssrani_hu_w, vv_i)
+INSN_LSX(vssrani_wu_d, vv_i)
+INSN_LSX(vssrani_du_q, vv_i)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 0a8cfe3625..28f159768c 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -411,3 +411,33 @@ DEF_HELPER_4(vsrarni_b_h, void, env, i32, i32, i32)
 DEF_HELPER_4(vsrarni_h_w, void, env, i32, i32, i32)
 DEF_HELPER_4(vsrarni_w_d, void, env, i32, i32, i32)
 DEF_HELPER_4(vsrarni_d_q, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vssrln_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrln_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrln_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssran_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssran_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssran_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrln_bu_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrln_hu_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrln_wu_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssran_bu_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssran_hu_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssran_wu_d, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vssrlni_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlni_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlni_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlni_d_q, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrani_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrani_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrani_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrani_d_q, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlni_bu_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlni_hu_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlni_wu_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlni_du_q, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrani_bu_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrani_hu_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrani_wu_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrani_du_q, void, env, i32, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 6034a74bfb..5d7e45a793 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3037,3 +3037,33 @@ TRANS(vsrarni_b_h, gen_vv_i, gen_helper_vsrarni_b_h)
 TRANS(vsrarni_h_w, gen_vv_i, gen_helper_vsrarni_h_w)
 TRANS(vsrarni_w_d, gen_vv_i, gen_helper_vsrarni_w_d)
 TRANS(vsrarni_d_q, gen_vv_i, gen_helper_vsrarni_d_q)
+
+TRANS(vssrln_b_h, gen_vvv, gen_helper_vssrln_b_h)
+TRANS(vssrln_h_w, gen_vvv, gen_helper_vssrln_h_w)
+TRANS(vssrln_w_d, gen_vvv, gen_helper_vssrln_w_d)
+TRANS(vssran_b_h, gen_vvv, gen_helper_vssran_b_h)
+TRANS(vssran_h_w, gen_vvv, gen_helper_vssran_h_w)
+TRANS(vssran_w_d, gen_vvv, gen_helper_vssran_w_d)
+TRANS(vssrln_bu_h, gen_vvv, gen_helper_vssrln_bu_h)
+TRANS(vssrln_hu_w, gen_vvv, gen_helper_vssrln_hu_w)
+TRANS(vssrln_wu_d, gen_vvv, gen_helper_vssrln_wu_d)
+TRANS(vssran_bu_h, gen_vvv, gen_helper_vssran_bu_h)
+TRANS(vssran_hu_w, gen_vvv, gen_helper_vssran_hu_w)
+TRANS(vssran_wu_d, gen_vvv, gen_helper_vssran_wu_d)
+
+TRANS(vssrlni_b_h, gen_vv_i, gen_helper_vssr

[PULL v2 13/45] target/loongarch: Implement vmax/vmin

2023-05-05 Thread Song Gao
This patch includes:
- VMAX[I].{B/H/W/D}[U];
- VMIN[I].{B/H/W/D}[U].

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-14-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  33 
 target/loongarch/helper.h   |  18 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 200 
 target/loongarch/insns.decode   |  35 
 target/loongarch/lsx_helper.c   |  33 
 5 files changed, 319 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 1f61e67d1f..6b0e518bfa 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -939,3 +939,36 @@ INSN_LSX(vadda_b,  vvv)
 INSN_LSX(vadda_h,  vvv)
 INSN_LSX(vadda_w,  vvv)
 INSN_LSX(vadda_d,  vvv)
+
+INSN_LSX(vmax_b,   vvv)
+INSN_LSX(vmax_h,   vvv)
+INSN_LSX(vmax_w,   vvv)
+INSN_LSX(vmax_d,   vvv)
+INSN_LSX(vmin_b,   vvv)
+INSN_LSX(vmin_h,   vvv)
+INSN_LSX(vmin_w,   vvv)
+INSN_LSX(vmin_d,   vvv)
+INSN_LSX(vmax_bu,  vvv)
+INSN_LSX(vmax_hu,  vvv)
+INSN_LSX(vmax_wu,  vvv)
+INSN_LSX(vmax_du,  vvv)
+INSN_LSX(vmin_bu,  vvv)
+INSN_LSX(vmin_hu,  vvv)
+INSN_LSX(vmin_wu,  vvv)
+INSN_LSX(vmin_du,  vvv)
+INSN_LSX(vmaxi_b,  vv_i)
+INSN_LSX(vmaxi_h,  vv_i)
+INSN_LSX(vmaxi_w,  vv_i)
+INSN_LSX(vmaxi_d,  vv_i)
+INSN_LSX(vmini_b,  vv_i)
+INSN_LSX(vmini_h,  vv_i)
+INSN_LSX(vmini_w,  vv_i)
+INSN_LSX(vmini_d,  vv_i)
+INSN_LSX(vmaxi_bu, vv_i)
+INSN_LSX(vmaxi_hu, vv_i)
+INSN_LSX(vmaxi_wu, vv_i)
+INSN_LSX(vmaxi_du, vv_i)
+INSN_LSX(vmini_bu, vv_i)
+INSN_LSX(vmini_hu, vv_i)
+INSN_LSX(vmini_wu, vv_i)
+INSN_LSX(vmini_du, vv_i)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 85fb8f60d2..379f961d1e 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -225,3 +225,21 @@ DEF_HELPER_FLAGS_4(vadda_b, TCG_CALL_NO_RWG, void, ptr, 
ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vadda_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vadda_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vadda_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vmini_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmini_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmini_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmini_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmini_bu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmini_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmini_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmini_du, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+
+DEF_HELPER_FLAGS_4(vmaxi_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmaxi_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmaxi_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmaxi_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmaxi_bu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmaxi_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmaxi_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vmaxi_du, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 8ad81c8517..15bb7888d3 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -1314,3 +1314,203 @@ TRANS(vadda_b, gvec_vvv, MO_8, do_vadda)
 TRANS(vadda_h, gvec_vvv, MO_16, do_vadda)
 TRANS(vadda_w, gvec_vvv, MO_32, do_vadda)
 TRANS(vadda_d, gvec_vvv, MO_64, do_vadda)
+
+TRANS(vmax_b, gvec_vvv, MO_8, tcg_gen_gvec_smax)
+TRANS(vmax_h, gvec_vvv, MO_16, tcg_gen_gvec_smax)
+TRANS(vmax_w, gvec_vvv, MO_32, tcg_gen_gvec_smax)
+TRANS(vmax_d, gvec_vvv, MO_64, tcg_gen_gvec_smax)
+TRANS(vmax_bu, gvec_vvv, MO_8, tcg_gen_gvec_umax)
+TRANS(vmax_hu, gvec_vvv, MO_16, tcg_gen_gvec_umax)
+TRANS(vmax_wu, gvec_vvv, MO_32, tcg_gen_gvec_umax)
+TRANS(vmax_du, gvec_vvv, MO_64, tcg_gen_gvec_umax)
+
+TRANS(vmin_b, gvec_vvv, MO_8, tcg_gen_gvec_smin)
+TRANS(vmin_h, gvec_vvv, MO_16, tcg_gen_gvec_smin)
+TRANS(vmin_w, gvec_vvv, MO_32, tcg_gen_gvec_smin)
+TRANS(vmin_d, gvec_vvv, MO_64, tcg_gen_gvec_smin)
+TRANS(vmin_bu, gvec_vvv, MO_8, tcg_gen_gvec_umin)
+TRANS(vmin_hu, gvec_vvv, MO_16, tcg_gen_gvec_umin)
+TRANS(vmin_wu, gvec_vvv, MO_32, tcg_gen_gvec_umin)
+TRANS(vmin_du, gvec_vvv, MO_64, tcg_gen_gvec_umin)
+
+static void gen_vmini_s(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
+{
+tcg_gen_smin_vec(vece, t, a, tcg_constant_vec_matching(t, vece, imm));
+}
+
+static void gen_vmini_u(un

[PULL v2 07/45] target/loongarch: Implement vsadd/vssub

2023-05-05 Thread Song Gao
This patch includes:
- VSADD.{B/H/W/D}[U];
- VSSUB.{B/H/W/D}[U].

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-8-gaos...@loongson.cn>
---
 target/loongarch/disas.c| 17 +
 target/loongarch/insn_trans/trans_lsx.c.inc | 17 +
 target/loongarch/insns.decode   | 17 +
 3 files changed, 51 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 5eabb8c47a..b7f9320ba0 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -831,3 +831,20 @@ INSN_LSX(vneg_b,   vv)
 INSN_LSX(vneg_h,   vv)
 INSN_LSX(vneg_w,   vv)
 INSN_LSX(vneg_d,   vv)
+
+INSN_LSX(vsadd_b,  vvv)
+INSN_LSX(vsadd_h,  vvv)
+INSN_LSX(vsadd_w,  vvv)
+INSN_LSX(vsadd_d,  vvv)
+INSN_LSX(vsadd_bu, vvv)
+INSN_LSX(vsadd_hu, vvv)
+INSN_LSX(vsadd_wu, vvv)
+INSN_LSX(vsadd_du, vvv)
+INSN_LSX(vssub_b,  vvv)
+INSN_LSX(vssub_h,  vvv)
+INSN_LSX(vssub_w,  vvv)
+INSN_LSX(vssub_d,  vvv)
+INSN_LSX(vssub_bu, vvv)
+INSN_LSX(vssub_hu, vvv)
+INSN_LSX(vssub_wu, vvv)
+INSN_LSX(vssub_du, vvv)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index d02db6285f..082bd738ce 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -140,3 +140,20 @@ TRANS(vneg_b, gvec_vv, MO_8, tcg_gen_gvec_neg)
 TRANS(vneg_h, gvec_vv, MO_16, tcg_gen_gvec_neg)
 TRANS(vneg_w, gvec_vv, MO_32, tcg_gen_gvec_neg)
 TRANS(vneg_d, gvec_vv, MO_64, tcg_gen_gvec_neg)
+
+TRANS(vsadd_b, gvec_vvv, MO_8, tcg_gen_gvec_ssadd)
+TRANS(vsadd_h, gvec_vvv, MO_16, tcg_gen_gvec_ssadd)
+TRANS(vsadd_w, gvec_vvv, MO_32, tcg_gen_gvec_ssadd)
+TRANS(vsadd_d, gvec_vvv, MO_64, tcg_gen_gvec_ssadd)
+TRANS(vsadd_bu, gvec_vvv, MO_8, tcg_gen_gvec_usadd)
+TRANS(vsadd_hu, gvec_vvv, MO_16, tcg_gen_gvec_usadd)
+TRANS(vsadd_wu, gvec_vvv, MO_32, tcg_gen_gvec_usadd)
+TRANS(vsadd_du, gvec_vvv, MO_64, tcg_gen_gvec_usadd)
+TRANS(vssub_b, gvec_vvv, MO_8, tcg_gen_gvec_sssub)
+TRANS(vssub_h, gvec_vvv, MO_16, tcg_gen_gvec_sssub)
+TRANS(vssub_w, gvec_vvv, MO_32, tcg_gen_gvec_sssub)
+TRANS(vssub_d, gvec_vvv, MO_64, tcg_gen_gvec_sssub)
+TRANS(vssub_bu, gvec_vvv, MO_8, tcg_gen_gvec_ussub)
+TRANS(vssub_hu, gvec_vvv, MO_16, tcg_gen_gvec_ussub)
+TRANS(vssub_wu, gvec_vvv, MO_32, tcg_gen_gvec_ussub)
+TRANS(vssub_du, gvec_vvv, MO_64, tcg_gen_gvec_ussub)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index d90798be11..3a29f0a9ab 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -525,3 +525,20 @@ vneg_b   0111 00101001 11000 01100 . .
@vv
 vneg_h   0111 00101001 11000 01101 . .@vv
 vneg_w   0111 00101001 11000 01110 . .@vv
 vneg_d   0111 00101001 11000 0 . .@vv
+
+vsadd_b  0111 0100 01100 . . .@vvv
+vsadd_h  0111 0100 01101 . . .@vvv
+vsadd_w  0111 0100 01110 . . .@vvv
+vsadd_d  0111 0100 0 . . .@vvv
+vsadd_bu 0111 0100 10100 . . .@vvv
+vsadd_hu 0111 0100 10101 . . .@vvv
+vsadd_wu 0111 0100 10110 . . .@vvv
+vsadd_du 0111 0100 10111 . . .@vvv
+vssub_b  0111 0100 1 . . .@vvv
+vssub_h  0111 0100 10001 . . .@vvv
+vssub_w  0111 0100 10010 . . .@vvv
+vssub_d  0111 0100 10011 . . .@vvv
+vssub_bu 0111 0100 11000 . . .@vvv
+vssub_hu 0111 0100 11001 . . .@vvv
+vssub_wu 0111 0100 11010 . . .@vvv
+vssub_du 0111 0100 11011 . . .@vvv
-- 
2.31.1




[PULL v2 15/45] target/loongarch: Implement vmadd/vmsub/vmaddw{ev/od}

2023-05-05 Thread Song Gao
This patch includes:
- VMADD.{B/H/W/D};
- VMSUB.{B/H/W/D};
- VMADDW{EV/OD}.{H.B/W.H/D.W/Q.D}[U];
- VMADDW{EV/OD}.{H.BU.B/W.HU.H/D.WU.W/Q.DU.D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-16-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  34 ++
 target/loongarch/helper.h   |  30 +
 target/loongarch/insn_trans/trans_lsx.c.inc | 612 
 target/loongarch/insns.decode   |  34 ++
 target/loongarch/lsx_helper.c   | 107 
 5 files changed, 817 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 48e6ef5309..980e6e6375 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1010,3 +1010,37 @@ INSN_LSX(vmulwod_h_bu_b,   vvv)
 INSN_LSX(vmulwod_w_hu_h,   vvv)
 INSN_LSX(vmulwod_d_wu_w,   vvv)
 INSN_LSX(vmulwod_q_du_d,   vvv)
+
+INSN_LSX(vmadd_b,  vvv)
+INSN_LSX(vmadd_h,  vvv)
+INSN_LSX(vmadd_w,  vvv)
+INSN_LSX(vmadd_d,  vvv)
+INSN_LSX(vmsub_b,  vvv)
+INSN_LSX(vmsub_h,  vvv)
+INSN_LSX(vmsub_w,  vvv)
+INSN_LSX(vmsub_d,  vvv)
+
+INSN_LSX(vmaddwev_h_b, vvv)
+INSN_LSX(vmaddwev_w_h, vvv)
+INSN_LSX(vmaddwev_d_w, vvv)
+INSN_LSX(vmaddwev_q_d, vvv)
+INSN_LSX(vmaddwod_h_b, vvv)
+INSN_LSX(vmaddwod_w_h, vvv)
+INSN_LSX(vmaddwod_d_w, vvv)
+INSN_LSX(vmaddwod_q_d, vvv)
+INSN_LSX(vmaddwev_h_bu,vvv)
+INSN_LSX(vmaddwev_w_hu,vvv)
+INSN_LSX(vmaddwev_d_wu,vvv)
+INSN_LSX(vmaddwev_q_du,vvv)
+INSN_LSX(vmaddwod_h_bu,vvv)
+INSN_LSX(vmaddwod_w_hu,vvv)
+INSN_LSX(vmaddwod_d_wu,vvv)
+INSN_LSX(vmaddwod_q_du,vvv)
+INSN_LSX(vmaddwev_h_bu_b,  vvv)
+INSN_LSX(vmaddwev_w_hu_h,  vvv)
+INSN_LSX(vmaddwev_d_wu_w,  vvv)
+INSN_LSX(vmaddwev_q_du_d,  vvv)
+INSN_LSX(vmaddwod_h_bu_b,  vvv)
+INSN_LSX(vmaddwod_w_hu_h,  vvv)
+INSN_LSX(vmaddwod_d_wu_w,  vvv)
+INSN_LSX(vmaddwod_q_du_d,  vvv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 830d8cbe62..8cf9620702 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -273,3 +273,33 @@ DEF_HELPER_FLAGS_4(vmulwev_d_wu_w, TCG_CALL_NO_RWG, void, 
ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vmulwod_h_bu_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vmulwod_w_hu_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vmulwod_d_wu_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vmadd_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmadd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmadd_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmadd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmsub_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmsub_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmsub_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmsub_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vmaddwev_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwev_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwev_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwod_h_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwod_w_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwod_d_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vmaddwev_h_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwev_w_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwev_d_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwod_h_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwod_w_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwod_d_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vmaddwev_h_bu_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwev_w_hu_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwev_d_wu_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwod_h_bu_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwod_w_hu_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vmaddwod_d_wu_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 9a36f942e2..400c3a0339 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -2064,3 +2064,615 @@ static void do_vmulwod_u_s(unsigned vece, uint32_t 
vd_ofs, uint32_t vj_ofs,
 TRANS(vmulwod_h_bu_b, gvec_vvv, MO_8, do_vmulwod_u_s)
 TRANS(vmulwod_w_hu_h, gvec_vvv, MO_16, do_vmulwod_u_s)
 TRANS(vmulwod_d_wu_w, gvec_vvv, MO_32, do_vmulwod_u_s)
+
+static void gen_vmadd

[PULL v2 02/45] target/loongarch: meson.build support build LSX

2023-05-05 Thread Song Gao
Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-3-gaos...@loongson.cn>
---
 target/loongarch/insn_trans/trans_lsx.c.inc | 5 +
 target/loongarch/lsx_helper.c   | 6 ++
 target/loongarch/meson.build| 1 +
 target/loongarch/translate.c| 1 +
 4 files changed, 13 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_lsx.c.inc
 create mode 100644 target/loongarch/lsx_helper.c

diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
new file mode 100644
index 00..1cf3ab34a9
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LSX translate functions
+ * Copyright (c) 2022-2023 Loongson Technology Corporation Limited
+ */
diff --git a/target/loongarch/lsx_helper.c b/target/loongarch/lsx_helper.c
new file mode 100644
index 00..9332163aff
--- /dev/null
+++ b/target/loongarch/lsx_helper.c
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch LSX helper functions.
+ *
+ * Copyright (c) 2022-2023 Loongson Technology Corporation Limited
+ */
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 9293a8ab78..1117a51c52 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -11,6 +11,7 @@ loongarch_tcg_ss.add(files(
   'op_helper.c',
   'translate.c',
   'gdbstub.c',
+  'lsx_helper.c',
 ))
 loongarch_tcg_ss.add(zlib)
 
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 21d86077f4..97e019aeb4 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -171,6 +171,7 @@ static void gen_set_gpr(int reg_num, TCGv t, DisasExtend 
dst_ext)
 #include "insn_trans/trans_fmemory.c.inc"
 #include "insn_trans/trans_branch.c.inc"
 #include "insn_trans/trans_privileged.c.inc"
+#include "insn_trans/trans_lsx.c.inc"
 
 static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
-- 
2.31.1




[PULL v2 23/45] target/loongarch: Implement vsllwil vextl

2023-05-05 Thread Song Gao
This patch includes:
- VSLLWIL.{H.B/W.H/D.W};
- VSLLWIL.{HU.BU/WU.HU/DU.WU};
- VEXTL.Q.D, VEXTL.QU.DU.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-24-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  9 +
 target/loongarch/helper.h   |  9 +
 target/loongarch/insn_trans/trans_lsx.c.inc | 21 +++
 target/loongarch/insns.decode   |  9 +
 target/loongarch/lsx_helper.c   | 41 +
 5 files changed, 89 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index f7d0fb4441..087cac10ad 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1139,3 +1139,12 @@ INSN_LSX(vrotri_b, vv_i)
 INSN_LSX(vrotri_h, vv_i)
 INSN_LSX(vrotri_w, vv_i)
 INSN_LSX(vrotri_d, vv_i)
+
+INSN_LSX(vsllwil_h_b,  vv_i)
+INSN_LSX(vsllwil_w_h,  vv_i)
+INSN_LSX(vsllwil_d_w,  vv_i)
+INSN_LSX(vextl_q_d,vv)
+INSN_LSX(vsllwil_hu_bu,vv_i)
+INSN_LSX(vsllwil_wu_hu,vv_i)
+INSN_LSX(vsllwil_du_wu,vv_i)
+INSN_LSX(vextl_qu_du,  vv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 617c579592..e98f7c3e6f 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -352,3 +352,12 @@ DEF_HELPER_3(vmskgez_b, void, env, i32, i32)
 DEF_HELPER_3(vmsknz_b, void, env, i32,i32)
 
 DEF_HELPER_FLAGS_4(vnori_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+
+DEF_HELPER_4(vsllwil_h_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vsllwil_w_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsllwil_d_w, void, env, i32, i32, i32)
+DEF_HELPER_3(vextl_q_d, void, env, i32, i32)
+DEF_HELPER_4(vsllwil_hu_bu, void, env, i32, i32, i32)
+DEF_HELPER_4(vsllwil_wu_hu, void, env, i32, i32, i32)
+DEF_HELPER_4(vsllwil_du_wu, void, env, i32, i32, i32)
+DEF_HELPER_3(vextl_qu_du, void, env, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index ad8f32ed18..037c742aa4 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -39,6 +39,18 @@ static bool gen_vv(DisasContext *ctx, arg_vv *a,
 return true;
 }
 
+static bool gen_vv_i(DisasContext *ctx, arg_vv_i *a,
+ void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32))
+{
+TCGv_i32 vd = tcg_constant_i32(a->vd);
+TCGv_i32 vj = tcg_constant_i32(a->vj);
+TCGv_i32 imm = tcg_constant_i32(a->imm);
+
+CHECK_SXE;
+func(cpu_env, vd, vj, imm);
+return true;
+}
+
 static bool gvec_vvv(DisasContext *ctx, arg_vvv *a, MemOp mop,
  void (*func)(unsigned, uint32_t, uint32_t,
   uint32_t, uint32_t, uint32_t))
@@ -2966,3 +2978,12 @@ TRANS(vrotri_b, gvec_vv_i, MO_8, tcg_gen_gvec_rotri)
 TRANS(vrotri_h, gvec_vv_i, MO_16, tcg_gen_gvec_rotri)
 TRANS(vrotri_w, gvec_vv_i, MO_32, tcg_gen_gvec_rotri)
 TRANS(vrotri_d, gvec_vv_i, MO_64, tcg_gen_gvec_rotri)
+
+TRANS(vsllwil_h_b, gen_vv_i, gen_helper_vsllwil_h_b)
+TRANS(vsllwil_w_h, gen_vv_i, gen_helper_vsllwil_w_h)
+TRANS(vsllwil_d_w, gen_vv_i, gen_helper_vsllwil_d_w)
+TRANS(vextl_q_d, gen_vv, gen_helper_vextl_q_d)
+TRANS(vsllwil_hu_bu, gen_vv_i, gen_helper_vsllwil_hu_bu)
+TRANS(vsllwil_wu_hu, gen_vv_i, gen_helper_vsllwil_wu_hu)
+TRANS(vsllwil_du_wu, gen_vv_i, gen_helper_vsllwil_du_wu)
+TRANS(vextl_qu_du, gen_vv, gen_helper_vextl_qu_du)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 7c0b0c4ac8..23dd338026 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -839,3 +839,12 @@ vrotri_b 0111 00101010 0 01 ... . .   
@vv_ui3
 vrotri_h 0111 00101010 0 1  . .   @vv_ui4
 vrotri_w 0111 00101010 1 . . .@vv_ui5
 vrotri_d 0111 00101010 0001 .. . .@vv_ui6
+
+vsllwil_h_b  0111 0011 1 01 ... . .   @vv_ui3
+vsllwil_w_h  0111 0011 1 1  . .   @vv_ui4
+vsllwil_d_w  0111 0011 10001 . . .@vv_ui5
+vextl_q_d0111 0011 10010 0 . .@vv
+vsllwil_hu_bu0111 0011 11000 01 ... . .   @vv_ui3
+vsllwil_wu_hu0111 0011 11000 1  . .   @vv_ui4
+vsllwil_du_wu0111 0011 11001 . . .@vv_ui5
+vextl_qu_du  0111 0011 11010 0 . .@vv
diff --git a/target/loongarch/lsx_helper.c b/target/loongarch/lsx_helper.c
index ff00d60ab8..de86f41cce 100644
--- a/target/loongarch/lsx_helper.c
+++ b/target/loongarch/lsx_helper.c
@@ -793,3 +793,44 @@ void HELPER(vnori_b)(void *vd, void *vj, uint64_t imm, 
uint32_t v)
 Vd->B(i) = ~(Vj->B(i) | (uint8_t)imm);
 }
 }
+
+#define VSLLWIL(NAME, BIT, E1, E2)\
+void HELPER(NAME)(CPULoongArchState *env, \
+  uint32_t vd, uint32_t vj, uint32_t imm) \
+{ 

[PULL v2 39/45] target/loongarch: Implement vreplve vpack vpick

2023-05-05 Thread Song Gao
This patch includes:
- VREPLVE[I].{B/H/W/D};
- VBSLL.V, VBSRL.V;
- VPACK{EV/OD}.{B/H/W/D};
- VPICK{EV/OD}.{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-40-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  35 +
 target/loongarch/helper.h   |  18 +++
 target/loongarch/insn_trans/trans_lsx.c.inc | 144 
 target/loongarch/insns.decode   |  34 +
 target/loongarch/lsx_helper.c   |  88 
 5 files changed, 319 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 7255a2aa4f..c6cf782725 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -833,6 +833,11 @@ static void output_vr(DisasContext *ctx, arg_vr *a, const 
char *mnemonic)
 output(ctx, mnemonic, "v%d, r%d", a->vd, a->rj);
 }
 
+static void output_vvr(DisasContext *ctx, arg_vvr *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "v%d, v%d, r%d", a->vd, a->vj, a->rk);
+}
+
 INSN_LSX(vadd_b,   vvv)
 INSN_LSX(vadd_h,   vvv)
 INSN_LSX(vadd_w,   vvv)
@@ -1594,3 +1599,33 @@ INSN_LSX(vreplgr2vr_b, vr)
 INSN_LSX(vreplgr2vr_h, vr)
 INSN_LSX(vreplgr2vr_w, vr)
 INSN_LSX(vreplgr2vr_d, vr)
+
+INSN_LSX(vreplve_b,vvr)
+INSN_LSX(vreplve_h,vvr)
+INSN_LSX(vreplve_w,vvr)
+INSN_LSX(vreplve_d,vvr)
+INSN_LSX(vreplvei_b,   vv_i)
+INSN_LSX(vreplvei_h,   vv_i)
+INSN_LSX(vreplvei_w,   vv_i)
+INSN_LSX(vreplvei_d,   vv_i)
+
+INSN_LSX(vbsll_v,  vv_i)
+INSN_LSX(vbsrl_v,  vv_i)
+
+INSN_LSX(vpackev_b,vvv)
+INSN_LSX(vpackev_h,vvv)
+INSN_LSX(vpackev_w,vvv)
+INSN_LSX(vpackev_d,vvv)
+INSN_LSX(vpackod_b,vvv)
+INSN_LSX(vpackod_h,vvv)
+INSN_LSX(vpackod_w,vvv)
+INSN_LSX(vpackod_d,vvv)
+
+INSN_LSX(vpickev_b,vvv)
+INSN_LSX(vpickev_h,vvv)
+INSN_LSX(vpickev_w,vvv)
+INSN_LSX(vpickev_d,vvv)
+INSN_LSX(vpickod_b,vvv)
+INSN_LSX(vpickod_h,vvv)
+INSN_LSX(vpickod_w,vvv)
+INSN_LSX(vpickod_d,vvv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 8eb2738cd0..51ad694be2 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -653,3 +653,21 @@ DEF_HELPER_3(vsetallnez_b, void, env, i32, i32)
 DEF_HELPER_3(vsetallnez_h, void, env, i32, i32)
 DEF_HELPER_3(vsetallnez_w, void, env, i32, i32)
 DEF_HELPER_3(vsetallnez_d, void, env, i32, i32)
+
+DEF_HELPER_4(vpackev_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vpackev_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vpackev_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vpackev_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vpackod_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vpackod_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vpackod_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vpackod_d, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vpickev_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vpickev_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vpickev_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vpickev_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vpickod_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vpickod_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vpickod_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vpickod_d, void, env, i32, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index e722b79bea..1146ace1b7 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3933,3 +3933,147 @@ TRANS(vreplgr2vr_b, gvec_dup, MO_8)
 TRANS(vreplgr2vr_h, gvec_dup, MO_16)
 TRANS(vreplgr2vr_w, gvec_dup, MO_32)
 TRANS(vreplgr2vr_d, gvec_dup, MO_64)
+
+static bool trans_vreplvei_b(DisasContext *ctx, arg_vv_i *a)
+{
+CHECK_SXE;
+tcg_gen_gvec_dup_mem(MO_8,vec_full_offset(a->vd),
+ offsetof(CPULoongArchState,
+  fpr[a->vj].vreg.B((a->imm))),
+ 16, ctx->vl/8);
+return true;
+}
+
+static bool trans_vreplvei_h(DisasContext *ctx, arg_vv_i *a)
+{
+CHECK_SXE;
+tcg_gen_gvec_dup_mem(MO_16, vec_full_offset(a->vd),
+ offsetof(CPULoongArchState,
+  fpr[a->vj].vreg.H((a->imm))),
+ 16, ctx->vl/8);
+return true;
+}
+static bool trans_vreplvei_w(DisasContext *ctx, arg_vv_i *a)
+{
+CHECK_SXE;
+tcg_gen_gvec_dup_mem(MO_32, vec_full_offset(a->vd),
+ offsetof(CPULoongArchState,
+  fpr[a->vj].vreg.W((a->imm))),
+16, ctx->vl/8);
+return true;
+}
+static bool trans_vreplvei_d(DisasContext *ctx, arg_vv_i *a)
+{
+CHECK_SXE;
+tcg_gen_gvec_dup_mem(MO_64, vec_full_offset(a->vd),
+ offsetof(CPULoongArchState,
+  fpr[a->vj].vreg.D((a->i

[PULL v2 11/45] target/loongarch: Implement vabsd

2023-05-05 Thread Song Gao
This patch includes:
- VABSD.{B/H/W/D}[U].

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-12-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  9 ++
 target/loongarch/helper.h   |  9 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 95 +
 target/loongarch/insns.decode   |  9 ++
 target/loongarch/lsx_helper.c   | 11 +++
 5 files changed, 133 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index e7592e7a34..e98ea37793 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -925,3 +925,12 @@ INSN_LSX(vavgr_bu, vvv)
 INSN_LSX(vavgr_hu, vvv)
 INSN_LSX(vavgr_wu, vvv)
 INSN_LSX(vavgr_du, vvv)
+
+INSN_LSX(vabsd_b,  vvv)
+INSN_LSX(vabsd_h,  vvv)
+INSN_LSX(vabsd_w,  vvv)
+INSN_LSX(vabsd_d,  vvv)
+INSN_LSX(vabsd_bu, vvv)
+INSN_LSX(vabsd_hu, vvv)
+INSN_LSX(vabsd_wu, vvv)
+INSN_LSX(vabsd_du, vvv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index af0f9f9b0d..c3a5d2566e 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -211,3 +211,12 @@ DEF_HELPER_FLAGS_4(vavgr_bu, TCG_CALL_NO_RWG, void, ptr, 
ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vavgr_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vavgr_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vavgr_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vabsd_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vabsd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vabsd_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vabsd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vabsd_bu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vabsd_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vabsd_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vabsd_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 5fa4792305..0e9301bf93 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -1166,3 +1166,98 @@ TRANS(vavgr_bu, gvec_vvv, MO_8, do_vavgr_u)
 TRANS(vavgr_hu, gvec_vvv, MO_16, do_vavgr_u)
 TRANS(vavgr_wu, gvec_vvv, MO_32, do_vavgr_u)
 TRANS(vavgr_du, gvec_vvv, MO_64, do_vavgr_u)
+
+static void gen_vabsd_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+tcg_gen_smax_vec(vece, t, a, b);
+tcg_gen_smin_vec(vece, a, a, b);
+tcg_gen_sub_vec(vece, t, t, a);
+}
+
+static void do_vabsd_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
+   uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
+{
+static const TCGOpcode vecop_list[] = {
+INDEX_op_smax_vec, INDEX_op_smin_vec, INDEX_op_sub_vec, 0
+};
+static const GVecGen3 op[4] = {
+{
+.fniv = gen_vabsd_s,
+.fno = gen_helper_vabsd_b,
+.opt_opc = vecop_list,
+.vece = MO_8
+},
+{
+.fniv = gen_vabsd_s,
+.fno = gen_helper_vabsd_h,
+.opt_opc = vecop_list,
+.vece = MO_16
+},
+{
+.fniv = gen_vabsd_s,
+.fno = gen_helper_vabsd_w,
+.opt_opc = vecop_list,
+.vece = MO_32
+},
+{
+.fniv = gen_vabsd_s,
+.fno = gen_helper_vabsd_d,
+.opt_opc = vecop_list,
+.vece = MO_64
+},
+};
+
+tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
+}
+
+static void gen_vabsd_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+tcg_gen_umax_vec(vece, t, a, b);
+tcg_gen_umin_vec(vece, a, a, b);
+tcg_gen_sub_vec(vece, t, t, a);
+}
+
+static void do_vabsd_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
+   uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
+{
+static const TCGOpcode vecop_list[] = {
+INDEX_op_umax_vec, INDEX_op_umin_vec, INDEX_op_sub_vec, 0
+};
+static const GVecGen3 op[4] = {
+{
+.fniv = gen_vabsd_u,
+.fno = gen_helper_vabsd_bu,
+.opt_opc = vecop_list,
+.vece = MO_8
+},
+{
+.fniv = gen_vabsd_u,
+.fno = gen_helper_vabsd_hu,
+.opt_opc = vecop_list,
+.vece = MO_16
+},
+{
+.fniv = gen_vabsd_u,
+.fno = gen_helper_vabsd_wu,
+.opt_opc = vecop_list,
+.vece = MO_32
+},
+{
+.fniv = gen_vabsd_u,
+.fno = gen_helper_vabsd_du,
+.opt_opc = vecop_list,
+.vece = MO_64
+},
+};
+
+tcg_gen_gvec_3(vd_ofs, vj_

[PULL v2 30/45] target/loongarch: Implement vpcnt

2023-05-05 Thread Song Gao
This patch includes:
- VPCNT.{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-31-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  5 +
 target/loongarch/helper.h   |  5 +
 target/loongarch/insn_trans/trans_lsx.c.inc |  5 +
 target/loongarch/insns.decode   |  5 +
 target/loongarch/lsx_helper.c   | 18 ++
 5 files changed, 38 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 0c82a1d9d1..0ca51de9d8 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1267,3 +1267,8 @@ INSN_LSX(vclz_b,   vv)
 INSN_LSX(vclz_h,   vv)
 INSN_LSX(vclz_w,   vv)
 INSN_LSX(vclz_d,   vv)
+
+INSN_LSX(vpcnt_b,  vv)
+INSN_LSX(vpcnt_h,  vv)
+INSN_LSX(vpcnt_w,  vv)
+INSN_LSX(vpcnt_d,  vv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index e21e9b9704..96b9b16923 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -480,3 +480,8 @@ DEF_HELPER_3(vclz_b, void, env, i32, i32)
 DEF_HELPER_3(vclz_h, void, env, i32, i32)
 DEF_HELPER_3(vclz_w, void, env, i32, i32)
 DEF_HELPER_3(vclz_d, void, env, i32, i32)
+
+DEF_HELPER_3(vpcnt_b, void, env, i32, i32)
+DEF_HELPER_3(vpcnt_h, void, env, i32, i32)
+DEF_HELPER_3(vpcnt_w, void, env, i32, i32)
+DEF_HELPER_3(vpcnt_d, void, env, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index c7649fb777..f4ebdca63c 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3106,3 +3106,8 @@ TRANS(vclz_b, gen_vv, gen_helper_vclz_b)
 TRANS(vclz_h, gen_vv, gen_helper_vclz_h)
 TRANS(vclz_w, gen_vv, gen_helper_vclz_w)
 TRANS(vclz_d, gen_vv, gen_helper_vclz_d)
+
+TRANS(vpcnt_b, gen_vv, gen_helper_vpcnt_b)
+TRANS(vpcnt_h, gen_vv, gen_helper_vpcnt_h)
+TRANS(vpcnt_w, gen_vv, gen_helper_vpcnt_w)
+TRANS(vpcnt_d, gen_vv, gen_helper_vpcnt_d)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 7591ec1bab..f865e83da5 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -968,3 +968,8 @@ vclz_b   0111 00101001 11000 00100 . .
@vv
 vclz_h   0111 00101001 11000 00101 . .@vv
 vclz_w   0111 00101001 11000 00110 . .@vv
 vclz_d   0111 00101001 11000 00111 . .@vv
+
+vpcnt_b  0111 00101001 11000 01000 . .@vv
+vpcnt_h  0111 00101001 11000 01001 . .@vv
+vpcnt_w  0111 00101001 11000 01010 . .@vv
+vpcnt_d  0111 00101001 11000 01011 . .@vv
diff --git a/target/loongarch/lsx_helper.c b/target/loongarch/lsx_helper.c
index e808e5fc83..9f91a47e66 100644
--- a/target/loongarch/lsx_helper.c
+++ b/target/loongarch/lsx_helper.c
@@ -1946,3 +1946,21 @@ DO_2OP(vclz_b, 8, UB, DO_CLZ_B)
 DO_2OP(vclz_h, 16, UH, DO_CLZ_H)
 DO_2OP(vclz_w, 32, UW, DO_CLZ_W)
 DO_2OP(vclz_d, 64, UD, DO_CLZ_D)
+
+#define VPCNT(NAME, BIT, E, FN) \
+void HELPER(NAME)(CPULoongArchState *env, uint32_t vd, uint32_t vj) \
+{   \
+int i;  \
+VReg *Vd = &(env->fpr[vd].vreg);\
+VReg *Vj = &(env->fpr[vj].vreg);\
+\
+for (i = 0; i < LSX_LEN/BIT; i++)   \
+{   \
+Vd->E(i) = FN(Vj->E(i));\
+}   \
+}
+
+VPCNT(vpcnt_b, 8, UB, ctpop8)
+VPCNT(vpcnt_h, 16, UH, ctpop16)
+VPCNT(vpcnt_w, 32, UW, ctpop32)
+VPCNT(vpcnt_d, 64, UD, ctpop64)
-- 
2.31.1




[PULL v2 33/45] target/loongarch: Implement LSX fpu arith instructions

2023-05-05 Thread Song Gao
This patch includes:
- VF{ADD/SUB/MUL/DIV}.{S/D};
- VF{MADD/MSUB/NMADD/NMSUB}.{S/D};
- VF{MAX/MIN}.{S/D};
- VF{MAXA/MINA}.{S/D};
- VFLOGB.{S/D};
- VFCLASS.{S/D};
- VF{SQRT/RECIP/RSQRT}.{S/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-34-gaos...@loongson.cn>
---
 target/loongarch/cpu.h  |   4 +
 target/loongarch/disas.c|  46 +
 target/loongarch/fpu_helper.c   |   2 +-
 target/loongarch/helper.h   |  41 +
 target/loongarch/insn_trans/trans_lsx.c.inc |  55 ++
 target/loongarch/insns.decode   |  43 +
 target/loongarch/internals.h|   1 +
 target/loongarch/lsx_helper.c   | 186 
 8 files changed, 377 insertions(+), 1 deletion(-)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 6755b1f0c7..1f37e36b7c 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -55,6 +55,10 @@ FIELD(FCSR0, CAUSE, 24, 5)
 do { \
 (REG) = FIELD_DP32(REG, FCSR0, CAUSE, V); \
 } while (0)
+#define UPDATE_FP_CAUSE(REG, V) \
+do { \
+(REG) |= FIELD_DP32(0, FCSR0, CAUSE, V); \
+} while (0)
 
 #define GET_FP_ENABLES(REG)FIELD_EX32(REG, FCSR0, ENABLES)
 #define SET_FP_ENABLES(REG, V) \
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index be2bb9cc42..b57b284e49 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -807,6 +807,11 @@ static void output_vv(DisasContext *ctx, arg_vv *a, const 
char *mnemonic)
 output(ctx, mnemonic, "v%d, v%d", a->vd, a->vj);
 }
 
+static void output_(DisasContext *ctx, arg_ *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "v%d, v%d, v%d, v%d", a->vd, a->vj, a->vk, a->va);
+}
+
 INSN_LSX(vadd_b,   vvv)
 INSN_LSX(vadd_h,   vvv)
 INSN_LSX(vadd_w,   vvv)
@@ -1302,3 +1307,44 @@ INSN_LSX(vfrstp_b, vvv)
 INSN_LSX(vfrstp_h, vvv)
 INSN_LSX(vfrstpi_b,vv_i)
 INSN_LSX(vfrstpi_h,vv_i)
+
+INSN_LSX(vfadd_s,  vvv)
+INSN_LSX(vfadd_d,  vvv)
+INSN_LSX(vfsub_s,  vvv)
+INSN_LSX(vfsub_d,  vvv)
+INSN_LSX(vfmul_s,  vvv)
+INSN_LSX(vfmul_d,  vvv)
+INSN_LSX(vfdiv_s,  vvv)
+INSN_LSX(vfdiv_d,  vvv)
+
+INSN_LSX(vfmadd_s, )
+INSN_LSX(vfmadd_d, )
+INSN_LSX(vfmsub_s, )
+INSN_LSX(vfmsub_d, )
+INSN_LSX(vfnmadd_s,)
+INSN_LSX(vfnmadd_d,)
+INSN_LSX(vfnmsub_s,)
+INSN_LSX(vfnmsub_d,)
+
+INSN_LSX(vfmax_s,  vvv)
+INSN_LSX(vfmax_d,  vvv)
+INSN_LSX(vfmin_s,  vvv)
+INSN_LSX(vfmin_d,  vvv)
+
+INSN_LSX(vfmaxa_s, vvv)
+INSN_LSX(vfmaxa_d, vvv)
+INSN_LSX(vfmina_s, vvv)
+INSN_LSX(vfmina_d, vvv)
+
+INSN_LSX(vflogb_s, vv)
+INSN_LSX(vflogb_d, vv)
+
+INSN_LSX(vfclass_s,vv)
+INSN_LSX(vfclass_d,vv)
+
+INSN_LSX(vfsqrt_s, vv)
+INSN_LSX(vfsqrt_d, vv)
+INSN_LSX(vfrecip_s,vv)
+INSN_LSX(vfrecip_d,vv)
+INSN_LSX(vfrsqrt_s,vv)
+INSN_LSX(vfrsqrt_d,vv)
diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index 4b9637210a..f6753c5875 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -33,7 +33,7 @@ void restore_fp_status(CPULoongArchState *env)
 set_flush_to_zero(0, &env->fp_status);
 }
 
-static int ieee_ex_to_loongarch(int xcpt)
+int ieee_ex_to_loongarch(int xcpt)
 {
 int ret = 0;
 if (xcpt & float_flag_invalid) {
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 2cc235d019..a0c9de271d 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -517,3 +517,44 @@ DEF_HELPER_4(vfrstp_b, void, env, i32, i32, i32)
 DEF_HELPER_4(vfrstp_h, void, env, i32, i32, i32)
 DEF_HELPER_4(vfrstpi_b, void, env, i32, i32, i32)
 DEF_HELPER_4(vfrstpi_h, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vfadd_s, void, env, i32, i32, i32)
+DEF_HELPER_4(vfadd_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vfsub_s, void, env, i32, i32, i32)
+DEF_HELPER_4(vfsub_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vfmul_s, void, env, i32, i32, i32)
+DEF_HELPER_4(vfmul_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vfdiv_s, void, env, i32, i32, i32)
+DEF_HELPER_4(vfdiv_d, void, env, i32, i32, i32)
+
+DEF_HELPER_5(vfmadd_s, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vfmadd_d, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vfmsub_s, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vfmsub_d, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vfnmadd_s, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vfnmadd_d, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vfnmsub_s, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vfnmsub_d, void, env, i32, i32, i32, i32)
+
+DEF_HELPER_4(vfmax_s, void, env, i32, i32, i32)
+DEF_HELPER_4(vfmax_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vfmin_s, void, env, i32

[PULL v2 01/45] target/loongarch: Add LSX data type VReg

2023-05-05 Thread Song Gao
Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-2-gaos...@loongson.cn>
---
 linux-user/loongarch64/signal.c |  4 +-
 target/loongarch/cpu.c  |  2 +-
 target/loongarch/cpu.h  | 21 -
 target/loongarch/gdbstub.c  |  4 +-
 target/loongarch/internals.h| 22 +
 target/loongarch/machine.c  | 79 ++---
 6 files changed, 119 insertions(+), 13 deletions(-)

diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c
index 7c7afb652e..bb8efb1172 100644
--- a/linux-user/loongarch64/signal.c
+++ b/linux-user/loongarch64/signal.c
@@ -128,7 +128,7 @@ static void setup_sigframe(CPULoongArchState *env,
 
 fpu_ctx = (struct target_fpu_context *)(info + 1);
 for (i = 0; i < 32; ++i) {
-__put_user(env->fpr[i], &fpu_ctx->regs[i]);
+__put_user(env->fpr[i].vreg.D(0), &fpu_ctx->regs[i]);
 }
 __put_user(read_fcc(env), &fpu_ctx->fcc);
 __put_user(env->fcsr0, &fpu_ctx->fcsr);
@@ -193,7 +193,7 @@ static void restore_sigframe(CPULoongArchState *env,
 uint64_t fcc;
 
 for (i = 0; i < 32; ++i) {
-__get_user(env->fpr[i], &fpu_ctx->regs[i]);
+__get_user(env->fpr[i].vreg.D(0), &fpu_ctx->regs[i]);
 }
 __get_user(fcc, &fpu_ctx->fcc);
 write_fcc(env, fcc);
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 97e6579f6a..18b41221a6 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -656,7 +656,7 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 /* fpr */
 if (flags & CPU_DUMP_FPU) {
 for (i = 0; i < 32; i++) {
-qemu_fprintf(f, " %s %016" PRIx64, fregnames[i], env->fpr[i]);
+qemu_fprintf(f, " %s %016" PRIx64, fregnames[i], 
env->fpr[i].vreg.D(0));
 if ((i & 3) == 3) {
 qemu_fprintf(f, "\n");
 }
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index e11c875188..fd0f61936d 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -8,6 +8,7 @@
 #ifndef LOONGARCH_CPU_H
 #define LOONGARCH_CPU_H
 
+#include "qemu/int128.h"
 #include "exec/cpu-defs.h"
 #include "fpu/softfloat-types.h"
 #include "hw/registerfields.h"
@@ -241,6 +242,24 @@ FIELD(TLB_MISC, ASID, 1, 10)
 FIELD(TLB_MISC, VPPN, 13, 35)
 FIELD(TLB_MISC, PS, 48, 6)
 
+#define LSX_LEN   (128)
+typedef union VReg {
+int8_t   B[LSX_LEN / 8];
+int16_t  H[LSX_LEN / 16];
+int32_t  W[LSX_LEN / 32];
+int64_t  D[LSX_LEN / 64];
+uint8_t  UB[LSX_LEN / 8];
+uint16_t UH[LSX_LEN / 16];
+uint32_t UW[LSX_LEN / 32];
+uint64_t UD[LSX_LEN / 64];
+Int128   Q[LSX_LEN / 128];
+}VReg;
+
+typedef union fpr_t fpr_t;
+union fpr_t {
+VReg  vreg;
+};
+
 struct LoongArchTLB {
 uint64_t tlb_misc;
 /* Fields corresponding to CSR_TLBELO0/1 */
@@ -253,7 +272,7 @@ typedef struct CPUArchState {
 uint64_t gpr[32];
 uint64_t pc;
 
-uint64_t fpr[32];
+fpr_t fpr[32];
 float_status fp_status;
 bool cf[8];
 
diff --git a/target/loongarch/gdbstub.c b/target/loongarch/gdbstub.c
index fa3e034d15..0752fff924 100644
--- a/target/loongarch/gdbstub.c
+++ b/target/loongarch/gdbstub.c
@@ -69,7 +69,7 @@ static int loongarch_gdb_get_fpu(CPULoongArchState *env,
  GByteArray *mem_buf, int n)
 {
 if (0 <= n && n < 32) {
-return gdb_get_reg64(mem_buf, env->fpr[n]);
+return gdb_get_reg64(mem_buf, env->fpr[n].vreg.D(0));
 } else if (n == 32) {
 uint64_t val = read_fcc(env);
 return gdb_get_reg64(mem_buf, val);
@@ -85,7 +85,7 @@ static int loongarch_gdb_set_fpu(CPULoongArchState *env,
 int length = 0;
 
 if (0 <= n && n < 32) {
-env->fpr[n] = ldq_p(mem_buf);
+env->fpr[n].vreg.D(0) = ldq_p(mem_buf);
 length = 8;
 } else if (n == 32) {
 uint64_t val = ldq_p(mem_buf);
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index f01635aed6..4c5752fc01 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -21,6 +21,28 @@
 /* Global bit for huge page */
 #define LOONGARCH_HGLOBAL_SHIFT 12
 
+#if  HOST_BIG_ENDIAN
+#define B(x)  B[15 - (x)]
+#define H(x)  H[7 - (x)]
+#define W(x)  W[3 - (x)]
+#define D(x)  D[1 - (x)]
+#define UB(x) UB[15 - (x)]
+#define UH(x) UH[7 - (x)]
+#define UW(x) UW[3 - (x)]
+#define UD(x) UD[1 -(x)]
+#define Q(x)  Q[x]
+#else
+#define B(x)  B[x]
+#define H(x)  H[x]
+#define W(x)  W[x]
+#define D(x)  D[x]
+#define UB(x) UB[x]
+#define UH(x) UH[x]
+#define UW(x) UW[x]
+#define UD(x) UD[x]
+#define Q(x)  Q[x]
+#endif
+
 void loongarch_translate_init(void);
 
 void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
index b1e523ea72..7adc1bdff9 100644
--- a/target/loongarch/machine.c
+++ b/target/loongarch/machine.c
@@ -10,6 +10,72 @@
 #include "migrati

[PULL v2 17/45] target/loongarch: Implement vsat

2023-05-05 Thread Song Gao
This patch includes:
- VSAT.{B/H/W/D}[U].

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-18-gaos...@loongson.cn>
---
 target/loongarch/disas.c|   9 ++
 target/loongarch/helper.h   |   9 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 101 
 target/loongarch/insns.decode   |  12 +++
 target/loongarch/lsx_helper.c   |  37 +++
 5 files changed, 168 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 6e4f676a42..b04aefe3ed 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1061,3 +1061,12 @@ INSN_LSX(vmod_bu,  vvv)
 INSN_LSX(vmod_hu,  vvv)
 INSN_LSX(vmod_wu,  vvv)
 INSN_LSX(vmod_du,  vvv)
+
+INSN_LSX(vsat_b,   vv_i)
+INSN_LSX(vsat_h,   vv_i)
+INSN_LSX(vsat_w,   vv_i)
+INSN_LSX(vsat_d,   vv_i)
+INSN_LSX(vsat_bu,  vv_i)
+INSN_LSX(vsat_hu,  vv_i)
+INSN_LSX(vsat_wu,  vv_i)
+INSN_LSX(vsat_du,  vv_i)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 7b7c685ede..d2b1c9f2a4 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -320,3 +320,12 @@ DEF_HELPER_4(vmod_bu, void, env, i32, i32, i32)
 DEF_HELPER_4(vmod_hu, void, env, i32, i32, i32)
 DEF_HELPER_4(vmod_wu, void, env, i32, i32, i32)
 DEF_HELPER_4(vmod_du, void, env, i32, i32, i32)
+
+DEF_HELPER_FLAGS_4(vsat_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsat_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsat_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsat_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsat_bu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsat_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsat_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vsat_du, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index b295a9c4df..b8f05c66a5 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -2693,3 +2693,104 @@ TRANS(vmod_bu, gen_vvv, gen_helper_vmod_bu)
 TRANS(vmod_hu, gen_vvv, gen_helper_vmod_hu)
 TRANS(vmod_wu, gen_vvv, gen_helper_vmod_wu)
 TRANS(vmod_du, gen_vvv, gen_helper_vmod_du)
+
+static void gen_vsat_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec max)
+{
+TCGv_vec min;
+
+min = tcg_temp_new_vec_matching(t);
+tcg_gen_not_vec(vece, min, max);
+tcg_gen_smax_vec(vece, t, a, min);
+tcg_gen_smin_vec(vece, t, t, max);
+}
+
+static void do_vsat_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
+  int64_t imm, uint32_t oprsz, uint32_t maxsz)
+{
+static const TCGOpcode vecop_list[] = {
+INDEX_op_smax_vec, INDEX_op_smin_vec, 0
+};
+static const GVecGen2s op[4] = {
+{
+.fniv = gen_vsat_s,
+.fno = gen_helper_vsat_b,
+.opt_opc = vecop_list,
+.vece = MO_8
+},
+{
+.fniv = gen_vsat_s,
+.fno = gen_helper_vsat_h,
+.opt_opc = vecop_list,
+.vece = MO_16
+},
+{
+.fniv = gen_vsat_s,
+.fno = gen_helper_vsat_w,
+.opt_opc = vecop_list,
+.vece = MO_32
+},
+{
+.fniv = gen_vsat_s,
+.fno = gen_helper_vsat_d,
+.opt_opc = vecop_list,
+.vece = MO_64
+},
+};
+
+tcg_gen_gvec_2s(vd_ofs, vj_ofs, oprsz, maxsz,
+tcg_constant_i64((1ll<< imm) -1), &op[vece]);
+}
+
+TRANS(vsat_b, gvec_vv_i, MO_8, do_vsat_s)
+TRANS(vsat_h, gvec_vv_i, MO_16, do_vsat_s)
+TRANS(vsat_w, gvec_vv_i, MO_32, do_vsat_s)
+TRANS(vsat_d, gvec_vv_i, MO_64, do_vsat_s)
+
+static void gen_vsat_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec max)
+{
+tcg_gen_umin_vec(vece, t, a, max);
+}
+
+static void do_vsat_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
+   int64_t imm, uint32_t oprsz, uint32_t maxsz)
+{
+uint64_t max;
+static const TCGOpcode vecop_list[] = {
+INDEX_op_umin_vec, 0
+};
+static const GVecGen2s op[4] = {
+{
+.fniv = gen_vsat_u,
+.fno = gen_helper_vsat_bu,
+.opt_opc = vecop_list,
+.vece = MO_8
+},
+{
+.fniv = gen_vsat_u,
+.fno = gen_helper_vsat_hu,
+.opt_opc = vecop_list,
+.vece = MO_16
+},
+{
+.fniv = gen_vsat_u,
+.fno = gen_helper_vsat_wu,
+.opt_opc = vecop_list,
+.vece = MO_32
+},
+{
+.fniv = gen_vsat_u,
+.fno = gen_helper_vsat_du,
+.opt_opc = vecop_list,
+

[PULL v2 19/45] target/loongarch: Implement vsigncov

2023-05-05 Thread Song Gao
This patch includes:
- VSIGNCOV.{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-20-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  5 ++
 target/loongarch/helper.h   |  5 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 53 +
 target/loongarch/insns.decode   |  5 ++
 target/loongarch/lsx_helper.c   |  7 +++
 5 files changed, 75 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 412c1cedcb..46e808c321 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1079,3 +1079,8 @@ INSN_LSX(vexth_hu_bu,  vv)
 INSN_LSX(vexth_wu_hu,  vv)
 INSN_LSX(vexth_du_wu,  vv)
 INSN_LSX(vexth_qu_du,  vv)
+
+INSN_LSX(vsigncov_b,   vvv)
+INSN_LSX(vsigncov_h,   vvv)
+INSN_LSX(vsigncov_w,   vvv)
+INSN_LSX(vsigncov_d,   vvv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 005988be25..e1e5d58697 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -338,3 +338,8 @@ DEF_HELPER_3(vexth_hu_bu, void, env, i32, i32)
 DEF_HELPER_3(vexth_wu_hu, void, env, i32, i32)
 DEF_HELPER_3(vexth_du_wu, void, env, i32, i32)
 DEF_HELPER_3(vexth_qu_du, void, env, i32, i32)
+
+DEF_HELPER_FLAGS_4(vsigncov_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsigncov_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsigncov_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vsigncov_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 93ae76bc4c..644917a695 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -2814,3 +2814,56 @@ TRANS(vexth_hu_bu, gen_vv, gen_helper_vexth_hu_bu)
 TRANS(vexth_wu_hu, gen_vv, gen_helper_vexth_wu_hu)
 TRANS(vexth_du_wu, gen_vv, gen_helper_vexth_du_wu)
 TRANS(vexth_qu_du, gen_vv, gen_helper_vexth_qu_du)
+
+static void gen_vsigncov(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+TCGv_vec t1, zero;
+
+t1 = tcg_temp_new_vec_matching(t);
+zero = tcg_constant_vec_matching(t, vece, 0);
+
+tcg_gen_neg_vec(vece, t1, b);
+tcg_gen_cmpsel_vec(TCG_COND_LT, vece, t, a, zero, t1, b);
+tcg_gen_cmpsel_vec(TCG_COND_EQ, vece, t, a, zero, zero, t);
+}
+
+static void do_vsigncov(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
+uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
+{
+static const TCGOpcode vecop_list[] = {
+INDEX_op_neg_vec, INDEX_op_cmpsel_vec, 0
+};
+static const GVecGen3 op[4] = {
+{
+.fniv = gen_vsigncov,
+.fno = gen_helper_vsigncov_b,
+.opt_opc = vecop_list,
+.vece = MO_8
+},
+{
+.fniv = gen_vsigncov,
+.fno = gen_helper_vsigncov_h,
+.opt_opc = vecop_list,
+.vece = MO_16
+},
+{
+.fniv = gen_vsigncov,
+.fno = gen_helper_vsigncov_w,
+.opt_opc = vecop_list,
+.vece = MO_32
+},
+{
+.fniv = gen_vsigncov,
+.fno = gen_helper_vsigncov_d,
+.opt_opc = vecop_list,
+.vece = MO_64
+},
+};
+
+tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
+}
+
+TRANS(vsigncov_b, gvec_vvv, MO_8, do_vsigncov)
+TRANS(vsigncov_h, gvec_vvv, MO_16, do_vsigncov)
+TRANS(vsigncov_w, gvec_vvv, MO_32, do_vsigncov)
+TRANS(vsigncov_d, gvec_vvv, MO_64, do_vsigncov)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 39c582d098..4233dd7404 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -778,3 +778,8 @@ vexth_hu_bu  0111 00101001 11101 11100 . .
@vv
 vexth_wu_hu  0111 00101001 11101 11101 . .@vv
 vexth_du_wu  0111 00101001 11101 0 . .@vv
 vexth_qu_du  0111 00101001 11101 1 . .@vv
+
+vsigncov_b   0111 00010010 11100 . . .@vvv
+vsigncov_h   0111 00010010 11101 . . .@vvv
+vsigncov_w   0111 00010010 0 . . .@vvv
+vsigncov_d   0111 00010010 1 . . .@vvv
diff --git a/target/loongarch/lsx_helper.c b/target/loongarch/lsx_helper.c
index b4582a49d9..408815ea45 100644
--- a/target/loongarch/lsx_helper.c
+++ b/target/loongarch/lsx_helper.c
@@ -662,3 +662,10 @@ VEXTH(vexth_d_w, 64, D, W)
 VEXTH(vexth_hu_bu, 16, UH, UB)
 VEXTH(vexth_wu_hu, 32, UW, UH)
 VEXTH(vexth_du_wu, 64, UD, UW)
+
+#define DO_SIGNCOV(a, b)  (a == 0 ? 0 : a < 0 ? -b : b)
+
+DO_3OP(vsigncov_b, 8, B, DO_SIGNCOV)
+DO_3OP(vsigncov_h, 16, H, DO_SIGNCOV)
+DO_3OP(vsigncov_w, 32, W, DO_SIGNCOV)
+DO_3OP(vsigncov_d, 64, D, DO_SIGNCOV)
-- 
2.31.1




[PULL v2 16/45] target/loongarch: Implement vdiv/vmod

2023-05-05 Thread Song Gao
This patch includes:
- VDIV.{B/H/W/D}[U];
- VMOD.{B/H/W/D}[U].

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-17-gaos...@loongson.cn>
---
 target/loongarch/disas.c| 17 ++
 target/loongarch/helper.h   | 17 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 17 ++
 target/loongarch/insns.decode   | 17 ++
 target/loongarch/lsx_helper.c   | 37 +
 5 files changed, 105 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 980e6e6375..6e4f676a42 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1044,3 +1044,20 @@ INSN_LSX(vmaddwod_h_bu_b,  vvv)
 INSN_LSX(vmaddwod_w_hu_h,  vvv)
 INSN_LSX(vmaddwod_d_wu_w,  vvv)
 INSN_LSX(vmaddwod_q_du_d,  vvv)
+
+INSN_LSX(vdiv_b,   vvv)
+INSN_LSX(vdiv_h,   vvv)
+INSN_LSX(vdiv_w,   vvv)
+INSN_LSX(vdiv_d,   vvv)
+INSN_LSX(vdiv_bu,  vvv)
+INSN_LSX(vdiv_hu,  vvv)
+INSN_LSX(vdiv_wu,  vvv)
+INSN_LSX(vdiv_du,  vvv)
+INSN_LSX(vmod_b,   vvv)
+INSN_LSX(vmod_h,   vvv)
+INSN_LSX(vmod_w,   vvv)
+INSN_LSX(vmod_d,   vvv)
+INSN_LSX(vmod_bu,  vvv)
+INSN_LSX(vmod_hu,  vvv)
+INSN_LSX(vmod_wu,  vvv)
+INSN_LSX(vmod_du,  vvv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 8cf9620702..7b7c685ede 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -303,3 +303,20 @@ DEF_HELPER_FLAGS_4(vmaddwev_d_wu_w, TCG_CALL_NO_RWG, void, 
ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vmaddwod_h_bu_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vmaddwod_w_hu_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vmaddwod_d_wu_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_4(vdiv_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vdiv_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vdiv_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vdiv_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vdiv_bu, void, env, i32, i32, i32)
+DEF_HELPER_4(vdiv_hu, void, env, i32, i32, i32)
+DEF_HELPER_4(vdiv_wu, void, env, i32, i32, i32)
+DEF_HELPER_4(vdiv_du, void, env, i32, i32, i32)
+DEF_HELPER_4(vmod_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vmod_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vmod_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vmod_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vmod_bu, void, env, i32, i32, i32)
+DEF_HELPER_4(vmod_hu, void, env, i32, i32, i32)
+DEF_HELPER_4(vmod_wu, void, env, i32, i32, i32)
+DEF_HELPER_4(vmod_du, void, env, i32, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 400c3a0339..b295a9c4df 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -2676,3 +2676,20 @@ static void do_vmaddwod_u_s(unsigned vece, uint32_t 
vd_ofs, uint32_t vj_ofs,
 TRANS(vmaddwod_h_bu_b, gvec_vvv, MO_8, do_vmaddwod_u_s)
 TRANS(vmaddwod_w_hu_h, gvec_vvv, MO_16, do_vmaddwod_u_s)
 TRANS(vmaddwod_d_wu_w, gvec_vvv, MO_32, do_vmaddwod_u_s)
+
+TRANS(vdiv_b, gen_vvv, gen_helper_vdiv_b)
+TRANS(vdiv_h, gen_vvv, gen_helper_vdiv_h)
+TRANS(vdiv_w, gen_vvv, gen_helper_vdiv_w)
+TRANS(vdiv_d, gen_vvv, gen_helper_vdiv_d)
+TRANS(vdiv_bu, gen_vvv, gen_helper_vdiv_bu)
+TRANS(vdiv_hu, gen_vvv, gen_helper_vdiv_hu)
+TRANS(vdiv_wu, gen_vvv, gen_helper_vdiv_wu)
+TRANS(vdiv_du, gen_vvv, gen_helper_vdiv_du)
+TRANS(vmod_b, gen_vvv, gen_helper_vmod_b)
+TRANS(vmod_h, gen_vvv, gen_helper_vmod_h)
+TRANS(vmod_w, gen_vvv, gen_helper_vmod_w)
+TRANS(vmod_d, gen_vvv, gen_helper_vmod_d)
+TRANS(vmod_bu, gen_vvv, gen_helper_vmod_bu)
+TRANS(vmod_hu, gen_vvv, gen_helper_vmod_hu)
+TRANS(vmod_wu, gen_vvv, gen_helper_vmod_wu)
+TRANS(vmod_du, gen_vvv, gen_helper_vmod_du)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index df23d4ee1e..67d016edb7 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -740,3 +740,20 @@ vmaddwod_h_bu_b  0111 1011 11100 . . .
@vvv
 vmaddwod_w_hu_h  0111 1011 11101 . . .@vvv
 vmaddwod_d_wu_w  0111 1011 0 . . .@vvv
 vmaddwod_q_du_d  0111 1011 1 . . .@vvv
+
+vdiv_b   0111 1110 0 . . .@vvv
+vdiv_h   0111 1110 1 . . .@vvv
+vdiv_w   0111 1110 00010 . . .@vvv
+vdiv_d   0111 1110 00011 . . .@vvv
+vdiv_bu  0111 1110 01000 . . .@vvv
+vdiv_hu  0111 1110 01001 . . .@vvv
+vdiv_wu  0111 1110 01010 . . .@vvv
+vdiv_du  0111 1110 01011 . . .@vvv
+vmod_b   0111 1110 00100 . . .@vvv
+vmod_h   0111 1110 00101 . . .@vvv
+vmod_

[PULL v2 42/45] target/loongarch: Implement vldi

2023-05-05 Thread Song Gao
This patch includes:
- VLDI.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-43-gaos...@loongson.cn>
---
 target/loongarch/disas.c|   7 +
 target/loongarch/insn_trans/trans_lsx.c.inc | 137 
 target/loongarch/insns.decode   |   4 +
 3 files changed, 148 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 8627908fc9..5c402d944d 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -858,6 +858,11 @@ static void output_vrr(DisasContext *ctx, arg_vrr *a, 
const char *mnemonic)
 output(ctx, mnemonic, "v%d, r%d, r%d", a->vd, a->rj, a->rk);
 }
 
+static void output_v_i(DisasContext *ctx, arg_v_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "v%d, 0x%x", a->vd, a->imm);
+}
+
 INSN_LSX(vadd_b,   vvv)
 INSN_LSX(vadd_h,   vvv)
 INSN_LSX(vadd_w,   vvv)
@@ -1143,6 +1148,8 @@ INSN_LSX(vmskltz_d,vv)
 INSN_LSX(vmskgez_b,vv)
 INSN_LSX(vmsknz_b, vv)
 
+INSN_LSX(vldi, v_i)
+
 INSN_LSX(vand_v,   vvv)
 INSN_LSX(vor_v,vvv)
 INSN_LSX(vxor_v,   vvv)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 86dfd2b399..0be2b5a3a8 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -2912,6 +2912,143 @@ TRANS(vmskltz_d, gen_vv, gen_helper_vmskltz_d)
 TRANS(vmskgez_b, gen_vv, gen_helper_vmskgez_b)
 TRANS(vmsknz_b, gen_vv, gen_helper_vmsknz_b)
 
+#define EXPAND_BYTE(bit)  ((uint64_t)(bit ? 0xff : 0))
+
+static uint64_t vldi_get_value(DisasContext *ctx, uint32_t imm)
+{
+int mode;
+uint64_t data, t;
+
+/*
+ * imm bit [11:8] is mode, mode value is 0-12.
+ * other values are invalid.
+ */
+mode = (imm >> 8) & 0xf;
+t =  imm & 0xff;
+switch (mode) {
+case 0:
+/* data: {2{24'0, imm[7:0]}} */
+data =  (t << 32) | t ;
+break;
+case 1:
+/* data: {2{16'0, imm[7:0], 8'0}} */
+data = (t << 24) | (t << 8);
+break;
+case 2:
+/* data: {2{8'0, imm[7:0], 16'0}} */
+data = (t << 48) | (t << 16);
+break;
+case 3:
+/* data: {2{imm[7:0], 24'0}} */
+data = (t << 56) | (t << 24);
+break;
+case 4:
+/* data: {4{8'0, imm[7:0]}} */
+data = (t << 48) | (t << 32) | (t << 16) | t;
+break;
+case 5:
+/* data: {4{imm[7:0], 8'0}} */
+data = (t << 56) |(t << 40) | (t << 24) | (t << 8);
+break;
+case 6:
+/* data: {2{16'0, imm[7:0], 8'1}} */
+data = (t << 40) | ((uint64_t)0xff << 32) | (t << 8) | 0xff;
+break;
+case 7:
+/* data: {2{8'0, imm[7:0], 16'1}} */
+data = (t << 48) | ((uint64_t)0x << 32) | (t << 16) | 0x;
+break;
+case 8:
+/* data: {8{imm[7:0]}} */
+data =(t << 56) | (t << 48) | (t << 40) | (t << 32) |
+  (t << 24) | (t << 16) | (t << 8) | t;
+break;
+case 9:
+/* data: {{8{imm[7]}, ..., 8{imm[0]}}} */
+{
+uint64_t b0,b1,b2,b3,b4,b5,b6,b7;
+b0 = t& 0x1;
+b1 = (t & 0x2) >> 1;
+b2 = (t & 0x4) >> 2;
+b3 = (t & 0x8) >> 3;
+b4 = (t & 0x10) >> 4;
+b5 = (t & 0x20) >> 5;
+b6 = (t & 0x40) >> 6;
+b7 = (t & 0x80) >> 7;
+data = (EXPAND_BYTE(b7) << 56) |
+   (EXPAND_BYTE(b6) << 48) |
+   (EXPAND_BYTE(b5) << 40) |
+   (EXPAND_BYTE(b4) << 32) |
+   (EXPAND_BYTE(b3) << 24) |
+   (EXPAND_BYTE(b2) << 16) |
+   (EXPAND_BYTE(b1) <<  8) |
+   EXPAND_BYTE(b0);
+}
+break;
+case 10:
+/* data: {2{imm[7], ~imm[6], {5{imm[6]}}, imm[5:0], 19'0}} */
+{
+uint64_t b6, b7;
+uint64_t t0, t1;
+b6 = (imm & 0x40) >> 6;
+b7 = (imm & 0x80) >> 7;
+t0 = (imm & 0x3f);
+t1 = (b7 << 6) | ((1-b6) << 5) | (uint64_t)(b6 ? 0x1f : 0);
+data  = (t1 << 57) | (t0 << 51) | (t1 << 25) | (t0 << 19);
+}
+break;
+case 11:
+/* data: {32'0, imm[7], ~{imm[6]}, 5{imm[6]}, imm[5:0], 19'0} */
+{
+uint64_t b6,b7;
+uint64_t t0, t1;
+b6 = (imm & 0x40) >> 6;
+b7 = (imm & 0x80) >> 7;
+t0 = (imm & 0x3f);
+t1 = (b7 << 6) | ((1-b6) << 5) | (b6 ? 0x1f : 0);
+data = (t1 << 25) | (t0 << 19);
+}
+break;
+case 12:
+/* data: {imm[7], ~imm[6], 8{imm[6]}, imm[5:0], 48'0} */
+{
+uint64_t b6,b7;
+uint64_t t0, t1;
+b6 = (imm & 0x40) >> 6;
+b7 = (imm & 0x80) >> 7;
+t0 = (imm & 0x3f);
+t1 = (b7 << 9

[PULL v2 24/45] target/loongarch: Implement vsrlr vsrar

2023-05-05 Thread Song Gao
This patch includes:
- VSRLR[I].{B/H/W/D};
- VSRAR[I].{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-25-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  18 
 target/loongarch/helper.h   |  18 
 target/loongarch/insn_trans/trans_lsx.c.inc |  18 
 target/loongarch/insns.decode   |  18 
 target/loongarch/lsx_helper.c   | 104 
 5 files changed, 176 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 087cac10ad..c62b6720ec 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1148,3 +1148,21 @@ INSN_LSX(vsllwil_hu_bu,vv_i)
 INSN_LSX(vsllwil_wu_hu,vv_i)
 INSN_LSX(vsllwil_du_wu,vv_i)
 INSN_LSX(vextl_qu_du,  vv)
+
+INSN_LSX(vsrlr_b,  vvv)
+INSN_LSX(vsrlr_h,  vvv)
+INSN_LSX(vsrlr_w,  vvv)
+INSN_LSX(vsrlr_d,  vvv)
+INSN_LSX(vsrlri_b, vv_i)
+INSN_LSX(vsrlri_h, vv_i)
+INSN_LSX(vsrlri_w, vv_i)
+INSN_LSX(vsrlri_d, vv_i)
+
+INSN_LSX(vsrar_b,  vvv)
+INSN_LSX(vsrar_h,  vvv)
+INSN_LSX(vsrar_w,  vvv)
+INSN_LSX(vsrar_d,  vvv)
+INSN_LSX(vsrari_b, vv_i)
+INSN_LSX(vsrari_h, vv_i)
+INSN_LSX(vsrari_w, vv_i)
+INSN_LSX(vsrari_d, vv_i)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index e98f7c3e6f..20a5e7c8e6 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -361,3 +361,21 @@ DEF_HELPER_4(vsllwil_hu_bu, void, env, i32, i32, i32)
 DEF_HELPER_4(vsllwil_wu_hu, void, env, i32, i32, i32)
 DEF_HELPER_4(vsllwil_du_wu, void, env, i32, i32, i32)
 DEF_HELPER_3(vextl_qu_du, void, env, i32, i32)
+
+DEF_HELPER_4(vsrlr_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlr_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlr_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlr_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlri_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlri_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlri_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlri_d, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vsrar_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrar_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrar_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrar_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrari_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrari_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrari_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrari_d, void, env, i32, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 037c742aa4..fb43e1b3ce 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -2987,3 +2987,21 @@ TRANS(vsllwil_hu_bu, gen_vv_i, gen_helper_vsllwil_hu_bu)
 TRANS(vsllwil_wu_hu, gen_vv_i, gen_helper_vsllwil_wu_hu)
 TRANS(vsllwil_du_wu, gen_vv_i, gen_helper_vsllwil_du_wu)
 TRANS(vextl_qu_du, gen_vv, gen_helper_vextl_qu_du)
+
+TRANS(vsrlr_b, gen_vvv, gen_helper_vsrlr_b)
+TRANS(vsrlr_h, gen_vvv, gen_helper_vsrlr_h)
+TRANS(vsrlr_w, gen_vvv, gen_helper_vsrlr_w)
+TRANS(vsrlr_d, gen_vvv, gen_helper_vsrlr_d)
+TRANS(vsrlri_b, gen_vv_i, gen_helper_vsrlri_b)
+TRANS(vsrlri_h, gen_vv_i, gen_helper_vsrlri_h)
+TRANS(vsrlri_w, gen_vv_i, gen_helper_vsrlri_w)
+TRANS(vsrlri_d, gen_vv_i, gen_helper_vsrlri_d)
+
+TRANS(vsrar_b, gen_vvv, gen_helper_vsrar_b)
+TRANS(vsrar_h, gen_vvv, gen_helper_vsrar_h)
+TRANS(vsrar_w, gen_vvv, gen_helper_vsrar_w)
+TRANS(vsrar_d, gen_vvv, gen_helper_vsrar_d)
+TRANS(vsrari_b, gen_vv_i, gen_helper_vsrari_b)
+TRANS(vsrari_h, gen_vv_i, gen_helper_vsrari_h)
+TRANS(vsrari_w, gen_vv_i, gen_helper_vsrari_w)
+TRANS(vsrari_d, gen_vv_i, gen_helper_vsrari_d)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 23dd338026..a21743 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -848,3 +848,21 @@ vsllwil_hu_bu0111 0011 11000 01 ... . .   
@vv_ui3
 vsllwil_wu_hu0111 0011 11000 1  . .   @vv_ui4
 vsllwil_du_wu0111 0011 11001 . . .@vv_ui5
 vextl_qu_du  0111 0011 11010 0 . .@vv
+
+vsrlr_b  0111  0 . . .@vvv
+vsrlr_h  0111  1 . . .@vvv
+vsrlr_w  0111  00010 . . .@vvv
+vsrlr_d  0111  00011 . . .@vvv
+vsrlri_b 0111 00101010 01000 01 ... . .   @vv_ui3
+vsrlri_h 0111 00101010 01000 1  . .   @vv_ui4
+vsrlri_w 0111 00101010 01001 . . .@vv_ui5
+vsrlri_d 0111 00101010 0101 .. . .@vv_ui6
+
+vsrar_b  0111  00100 . . .@vvv
+vsrar_h  0111  00101 . . .@vvv
+vsrar_w  0111  00110 . . .@vvv

[PULL v2 32/45] target/loongarch: Implement vfrstp

2023-05-05 Thread Song Gao
This patch includes:
- VFRSTP[I].{B/H}.

Acked-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-33-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  5 +++
 target/loongarch/helper.h   |  5 +++
 target/loongarch/insn_trans/trans_lsx.c.inc |  5 +++
 target/loongarch/insns.decode   |  5 +++
 target/loongarch/lsx_helper.c   | 41 +
 5 files changed, 61 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 48c7ea47a4..be2bb9cc42 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1297,3 +1297,8 @@ INSN_LSX(vbitrevi_b,   vv_i)
 INSN_LSX(vbitrevi_h,   vv_i)
 INSN_LSX(vbitrevi_w,   vv_i)
 INSN_LSX(vbitrevi_d,   vv_i)
+
+INSN_LSX(vfrstp_b, vvv)
+INSN_LSX(vfrstp_h, vvv)
+INSN_LSX(vfrstpi_b,vv_i)
+INSN_LSX(vfrstpi_h,vv_i)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 75120ca55e..2cc235d019 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -512,3 +512,8 @@ DEF_HELPER_FLAGS_4(vbitrevi_b, TCG_CALL_NO_RWG, void, ptr, 
ptr, i64, i32)
 DEF_HELPER_FLAGS_4(vbitrevi_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
 DEF_HELPER_FLAGS_4(vbitrevi_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
 DEF_HELPER_FLAGS_4(vbitrevi_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+
+DEF_HELPER_4(vfrstp_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vfrstp_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vfrstpi_b, void, env, i32, i32, i32)
+DEF_HELPER_4(vfrstpi_h, void, env, i32, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 86243b54ba..ee84a5a4ee 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3416,3 +3416,8 @@ TRANS(vbitrevi_b, gvec_vv_i, MO_8, do_vbitrevi)
 TRANS(vbitrevi_h, gvec_vv_i, MO_16, do_vbitrevi)
 TRANS(vbitrevi_w, gvec_vv_i, MO_32, do_vbitrevi)
 TRANS(vbitrevi_d, gvec_vv_i, MO_64, do_vbitrevi)
+
+TRANS(vfrstp_b, gen_vvv, gen_helper_vfrstp_b)
+TRANS(vfrstp_h, gen_vvv, gen_helper_vfrstp_h)
+TRANS(vfrstpi_b, gen_vv_i, gen_helper_vfrstpi_b)
+TRANS(vfrstpi_h, gen_vv_i, gen_helper_vfrstpi_h)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 801c97714e..4cb286ffe5 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -998,3 +998,8 @@ vbitrevi_b   0111 00110001 1 01 ... . .   
@vv_ui3
 vbitrevi_h   0111 00110001 1 1  . .   @vv_ui4
 vbitrevi_w   0111 00110001 10001 . . .@vv_ui5
 vbitrevi_d   0111 00110001 1001 .. . .@vv_ui6
+
+vfrstp_b 0111 00010010 10110 . . .@vvv
+vfrstp_h 0111 00010010 10111 . . .@vvv
+vfrstpi_b0111 00101001 10100 . . .@vv_ui5
+vfrstpi_h0111 00101001 10101 . . .@vv_ui5
diff --git a/target/loongarch/lsx_helper.c b/target/loongarch/lsx_helper.c
index 14e2df254d..66e9d405a4 100644
--- a/target/loongarch/lsx_helper.c
+++ b/target/loongarch/lsx_helper.c
@@ -2019,3 +2019,44 @@ DO_BITI(vbitrevi_b, 8, UB, DO_BITREV)
 DO_BITI(vbitrevi_h, 16, UH, DO_BITREV)
 DO_BITI(vbitrevi_w, 32, UW, DO_BITREV)
 DO_BITI(vbitrevi_d, 64, UD, DO_BITREV)
+
+#define VFRSTP(NAME, BIT, MASK, E)   \
+void HELPER(NAME)(CPULoongArchState *env,\
+  uint32_t vd, uint32_t vj, uint32_t vk) \
+{\
+int i, m;\
+VReg *Vd = &(env->fpr[vd].vreg); \
+VReg *Vj = &(env->fpr[vj].vreg); \
+VReg *Vk = &(env->fpr[vk].vreg); \
+ \
+for (i = 0; i < LSX_LEN/BIT; i++) {  \
+if (Vj->E(i) < 0) {  \
+break;   \
+}\
+}\
+m = Vk->E(0) & MASK; \
+Vd->E(m) = i;\
+}
+
+VFRSTP(vfrstp_b, 8, 0xf, B)
+VFRSTP(vfrstp_h, 16, 0x7, H)
+
+#define VFRSTPI(NAME, BIT, E) \
+void HELPER(NAME)(CPULoongArchState *env, \
+  uint32_t vd, uint32_t vj, uint32_t imm) \
+{ \
+int i, m; \
+VReg *Vd = &(env->fpr[vd].vreg);  \
+VReg *Vj = &(env->fpr[vj].vreg);  \
+  \
+for (i = 0; i < LSX_LEN/BIT; i++) {   \
+if (Vj->E(i) < 0) { 

[PULL v2 05/45] target/loongarch: Implement vaddi/vsubi

2023-05-05 Thread Song Gao
This patch includes:
- VADDI.{B/H/W/D}U;
- VSUBI.{B/H/W/D}U.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-6-gaos...@loongson.cn>
---
 target/loongarch/disas.c| 14 
 target/loongarch/insn_trans/trans_lsx.c.inc | 37 +
 target/loongarch/insns.decode   | 11 ++
 3 files changed, 62 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index a5948d7847..c1960610c2 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -797,6 +797,11 @@ static void output_vvv(DisasContext *ctx, arg_vvv *a, 
const char *mnemonic)
 output(ctx, mnemonic, "v%d, v%d, v%d", a->vd, a->vj, a->vk);
 }
 
+static void output_vv_i(DisasContext *ctx, arg_vv_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "v%d, v%d, 0x%x", a->vd, a->vj, a->imm);
+}
+
 INSN_LSX(vadd_b,   vvv)
 INSN_LSX(vadd_h,   vvv)
 INSN_LSX(vadd_w,   vvv)
@@ -807,3 +812,12 @@ INSN_LSX(vsub_h,   vvv)
 INSN_LSX(vsub_w,   vvv)
 INSN_LSX(vsub_d,   vvv)
 INSN_LSX(vsub_q,   vvv)
+
+INSN_LSX(vaddi_bu, vv_i)
+INSN_LSX(vaddi_hu, vv_i)
+INSN_LSX(vaddi_wu, vv_i)
+INSN_LSX(vaddi_du, vv_i)
+INSN_LSX(vsubi_bu, vv_i)
+INSN_LSX(vsubi_hu, vv_i)
+INSN_LSX(vsubi_wu, vv_i)
+INSN_LSX(vsubi_du, vv_i)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index ddeb9fde28..e6c1d0d2cc 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -44,6 +44,34 @@ static bool gvec_vvv(DisasContext *ctx, arg_vvv *a, MemOp 
mop,
 return true;
 }
 
+static bool gvec_vv_i(DisasContext *ctx, arg_vv_i *a, MemOp mop,
+  void (*func)(unsigned, uint32_t, uint32_t,
+   int64_t, uint32_t, uint32_t))
+{
+uint32_t vd_ofs, vj_ofs;
+
+CHECK_SXE;
+
+vd_ofs = vec_full_offset(a->vd);
+vj_ofs = vec_full_offset(a->vj);
+
+func(mop, vd_ofs, vj_ofs, a->imm , 16, ctx->vl/8);
+return true;
+}
+
+static bool gvec_subi(DisasContext *ctx, arg_vv_i *a, MemOp mop)
+{
+uint32_t vd_ofs, vj_ofs;
+
+CHECK_SXE;
+
+vd_ofs = vec_full_offset(a->vd);
+vj_ofs = vec_full_offset(a->vj);
+
+tcg_gen_gvec_addi(mop, vd_ofs, vj_ofs, -a->imm, 16, ctx->vl/8);
+return true;
+}
+
 TRANS(vadd_b, gvec_vvv, MO_8, tcg_gen_gvec_add)
 TRANS(vadd_h, gvec_vvv, MO_16, tcg_gen_gvec_add)
 TRANS(vadd_w, gvec_vvv, MO_32, tcg_gen_gvec_add)
@@ -83,3 +111,12 @@ TRANS(vsub_b, gvec_vvv, MO_8, tcg_gen_gvec_sub)
 TRANS(vsub_h, gvec_vvv, MO_16, tcg_gen_gvec_sub)
 TRANS(vsub_w, gvec_vvv, MO_32, tcg_gen_gvec_sub)
 TRANS(vsub_d, gvec_vvv, MO_64, tcg_gen_gvec_sub)
+
+TRANS(vaddi_bu, gvec_vv_i, MO_8, tcg_gen_gvec_addi)
+TRANS(vaddi_hu, gvec_vv_i, MO_16, tcg_gen_gvec_addi)
+TRANS(vaddi_wu, gvec_vv_i, MO_32, tcg_gen_gvec_addi)
+TRANS(vaddi_du, gvec_vv_i, MO_64, tcg_gen_gvec_addi)
+TRANS(vsubi_bu, gvec_subi, MO_8)
+TRANS(vsubi_hu, gvec_subi, MO_16)
+TRANS(vsubi_wu, gvec_subi, MO_32)
+TRANS(vsubi_du, gvec_subi, MO_64)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index d18db68d51..2a98c14518 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -491,11 +491,13 @@ dbcl  0010 10101 ...  
@i15
 #
 
 &vvv  vd vj vk
+&vv_i vd vj imm
 
 #
 # LSX Formats
 #
 @vvv     . vk:5 vj:5 vd:5&vvv
+@vv_ui5     . imm:5 vj:5 vd:5&vv_i
 
 vadd_b   0111  10100 . . .@vvv
 vadd_h   0111  10101 . . .@vvv
@@ -507,3 +509,12 @@ vsub_h   0111  11001 . . .
@vvv
 vsub_w   0111  11010 . . .@vvv
 vsub_d   0111  11011 . . .@vvv
 vsub_q   0111 00010010 11011 . . .@vvv
+
+vaddi_bu 0111 00101000 10100 . . .@vv_ui5
+vaddi_hu 0111 00101000 10101 . . .@vv_ui5
+vaddi_wu 0111 00101000 10110 . . .@vv_ui5
+vaddi_du 0111 00101000 10111 . . .@vv_ui5
+vsubi_bu 0111 00101000 11000 . . .@vv_ui5
+vsubi_hu 0111 00101000 11001 . . .@vv_ui5
+vsubi_wu 0111 00101000 11010 . . .@vv_ui5
+vsubi_du 0111 00101000 11011 . . .@vv_ui5
-- 
2.31.1




[PULL v2 35/45] target/loongarch: Implement vseq vsle vslt

2023-05-05 Thread Song Gao
This patch includes:
- VSEQ[I].{B/H/W/D};
- VSLE[I].{B/H/W/D}[U];
- VSLT[I].{B/H/W/D/}[U].

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-36-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  43 +
 target/loongarch/helper.h   |  23 +++
 target/loongarch/insn_trans/trans_lsx.c.inc | 185 
 target/loongarch/insns.decode   |  43 +
 target/loongarch/lsx_helper.c   |  38 
 5 files changed, 332 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index c04271081f..e589b23f4c 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1404,3 +1404,46 @@ INSN_LSX(vffint_d_lu,  vv)
 INSN_LSX(vffintl_d_w,  vv)
 INSN_LSX(vffinth_d_w,  vv)
 INSN_LSX(vffint_s_l,   vvv)
+
+INSN_LSX(vseq_b,   vvv)
+INSN_LSX(vseq_h,   vvv)
+INSN_LSX(vseq_w,   vvv)
+INSN_LSX(vseq_d,   vvv)
+INSN_LSX(vseqi_b,  vv_i)
+INSN_LSX(vseqi_h,  vv_i)
+INSN_LSX(vseqi_w,  vv_i)
+INSN_LSX(vseqi_d,  vv_i)
+
+INSN_LSX(vsle_b,   vvv)
+INSN_LSX(vsle_h,   vvv)
+INSN_LSX(vsle_w,   vvv)
+INSN_LSX(vsle_d,   vvv)
+INSN_LSX(vslei_b,  vv_i)
+INSN_LSX(vslei_h,  vv_i)
+INSN_LSX(vslei_w,  vv_i)
+INSN_LSX(vslei_d,  vv_i)
+INSN_LSX(vsle_bu,  vvv)
+INSN_LSX(vsle_hu,  vvv)
+INSN_LSX(vsle_wu,  vvv)
+INSN_LSX(vsle_du,  vvv)
+INSN_LSX(vslei_bu, vv_i)
+INSN_LSX(vslei_hu, vv_i)
+INSN_LSX(vslei_wu, vv_i)
+INSN_LSX(vslei_du, vv_i)
+
+INSN_LSX(vslt_b,   vvv)
+INSN_LSX(vslt_h,   vvv)
+INSN_LSX(vslt_w,   vvv)
+INSN_LSX(vslt_d,   vvv)
+INSN_LSX(vslti_b,  vv_i)
+INSN_LSX(vslti_h,  vv_i)
+INSN_LSX(vslti_w,  vv_i)
+INSN_LSX(vslti_d,  vv_i)
+INSN_LSX(vslt_bu,  vvv)
+INSN_LSX(vslt_hu,  vvv)
+INSN_LSX(vslt_wu,  vvv)
+INSN_LSX(vslt_du,  vvv)
+INSN_LSX(vslti_bu, vv_i)
+INSN_LSX(vslti_hu, vv_i)
+INSN_LSX(vslti_wu, vv_i)
+INSN_LSX(vslti_du, vv_i)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index f32235aa97..e9e9fa7f87 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -614,3 +614,26 @@ DEF_HELPER_3(vffint_d_lu, void, env, i32, i32)
 DEF_HELPER_3(vffintl_d_w, void, env, i32, i32)
 DEF_HELPER_3(vffinth_d_w, void, env, i32, i32)
 DEF_HELPER_4(vffint_s_l, void, env, i32, i32, i32)
+
+DEF_HELPER_FLAGS_4(vseqi_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vseqi_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vseqi_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vseqi_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+
+DEF_HELPER_FLAGS_4(vslei_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslei_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslei_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslei_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslei_bu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslei_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslei_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslei_du, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+
+DEF_HELPER_FLAGS_4(vslti_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslti_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslti_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslti_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslti_bu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslti_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslti_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
+DEF_HELPER_FLAGS_4(vslti_du, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index e0c72c6bff..4d9f88bf4f 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3532,3 +3532,188 @@ TRANS(vffint_d_lu, gen_vv, gen_helper_vffint_d_lu)
 TRANS(vffintl_d_w, gen_vv, gen_helper_vffintl_d_w)
 TRANS(vffinth_d_w, gen_vv, gen_helper_vffinth_d_w)
 TRANS(vffint_s_l, gen_vvv, gen_helper_vffint_s_l)
+
+static bool do_cmp(DisasContext *ctx, arg_vvv *a, MemOp mop, TCGCond cond)
+{
+uint32_t vd_ofs, vj_ofs, vk_ofs;
+
+CHECK_SXE;
+
+vd_ofs = vec_full_offset(a->vd);
+vj_ofs = vec_full_offset(a->vj);
+vk_ofs = vec_full_offset(a->vk);
+
+tcg_gen_gvec_cmp(cond, mop, vd_ofs, vj_ofs, vk_ofs, 16, ctx->vl/8);
+return true;
+}
+
+static void do_cmpi_vec(TCGCond cond,
+unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
+{
+tcg_gen_cm

[PULL v2 04/45] target/loongarch: Implement vadd/vsub

2023-05-05 Thread Song Gao
This patch includes:
- VADD.{B/H/W/D/Q};
- VSUB.{B/H/W/D/Q}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-5-gaos...@loongson.cn>
---
 target/loongarch/disas.c| 23 +++
 target/loongarch/insn_trans/trans_lsx.c.inc | 69 +
 target/loongarch/insns.decode   | 22 +++
 target/loongarch/translate.c| 24 +++
 target/loongarch/translate.h|  1 +
 5 files changed, 139 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 2e93e77e0d..a5948d7847 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -784,3 +784,26 @@ PCADD_INSN(pcaddi)
 PCADD_INSN(pcalau12i)
 PCADD_INSN(pcaddu12i)
 PCADD_INSN(pcaddu18i)
+
+#define INSN_LSX(insn, type)\
+static bool trans_##insn(DisasContext *ctx, arg_##type * a) \
+{   \
+output_##type(ctx, a, #insn);   \
+return true;\
+}
+
+static void output_vvv(DisasContext *ctx, arg_vvv *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "v%d, v%d, v%d", a->vd, a->vj, a->vk);
+}
+
+INSN_LSX(vadd_b,   vvv)
+INSN_LSX(vadd_h,   vvv)
+INSN_LSX(vadd_w,   vvv)
+INSN_LSX(vadd_d,   vvv)
+INSN_LSX(vadd_q,   vvv)
+INSN_LSX(vsub_b,   vvv)
+INSN_LSX(vsub_h,   vvv)
+INSN_LSX(vsub_w,   vvv)
+INSN_LSX(vsub_d,   vvv)
+INSN_LSX(vsub_q,   vvv)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 5dedb044d7..ddeb9fde28 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -14,3 +14,72 @@
 #else
 #define CHECK_SXE
 #endif
+
+static bool gen_vvv(DisasContext *ctx, arg_vvv *a,
+void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32))
+{
+TCGv_i32 vd = tcg_constant_i32(a->vd);
+TCGv_i32 vj = tcg_constant_i32(a->vj);
+TCGv_i32 vk = tcg_constant_i32(a->vk);
+
+CHECK_SXE;
+
+func(cpu_env, vd, vj, vk);
+return true;
+}
+
+static bool gvec_vvv(DisasContext *ctx, arg_vvv *a, MemOp mop,
+ void (*func)(unsigned, uint32_t, uint32_t,
+  uint32_t, uint32_t, uint32_t))
+{
+uint32_t vd_ofs, vj_ofs, vk_ofs;
+
+CHECK_SXE;
+
+vd_ofs = vec_full_offset(a->vd);
+vj_ofs = vec_full_offset(a->vj);
+vk_ofs = vec_full_offset(a->vk);
+
+func(mop, vd_ofs, vj_ofs, vk_ofs, 16, ctx->vl/8);
+return true;
+}
+
+TRANS(vadd_b, gvec_vvv, MO_8, tcg_gen_gvec_add)
+TRANS(vadd_h, gvec_vvv, MO_16, tcg_gen_gvec_add)
+TRANS(vadd_w, gvec_vvv, MO_32, tcg_gen_gvec_add)
+TRANS(vadd_d, gvec_vvv, MO_64, tcg_gen_gvec_add)
+
+#define VADDSUB_Q(NAME)\
+static bool trans_v## NAME ##_q(DisasContext *ctx, arg_vvv *a) \
+{  \
+TCGv_i64 rh, rl, ah, al, bh, bl;   \
+   \
+CHECK_SXE; \
+   \
+rh = tcg_temp_new_i64();   \
+rl = tcg_temp_new_i64();   \
+ah = tcg_temp_new_i64();   \
+al = tcg_temp_new_i64();   \
+bh = tcg_temp_new_i64();   \
+bl = tcg_temp_new_i64();   \
+   \
+get_vreg64(ah, a->vj, 1);  \
+get_vreg64(al, a->vj, 0);  \
+get_vreg64(bh, a->vk, 1);  \
+get_vreg64(bl, a->vk, 0);  \
+   \
+tcg_gen_## NAME ##2_i64(rl, rh, al, ah, bl, bh);   \
+   \
+set_vreg64(rh, a->vd, 1);  \
+set_vreg64(rl, a->vd, 0);  \
+   \
+return true;   \
+}
+
+VADDSUB_Q(add)
+VADDSUB_Q(sub)
+
+TRANS(vsub_b, gvec_vvv, MO_8, tcg_gen_gvec_sub)
+TRANS(vsub_h, gvec_vvv, MO_16, tcg_gen_gvec_sub)
+TRANS(vsub_w, gvec_vvv, MO_32, tcg_gen_gvec_sub)
+TRANS(vsub_d, gvec_vvv, MO_64, tcg_gen_gvec_sub)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index de7b8f0f3c..d18db68d51 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -485,3 +485,25 @@ ldpte 01100100 0

[PULL v2 26/45] target/loongarch: Implement vsrlrn vsrarn

2023-05-05 Thread Song Gao
This patch includes:
- VSRLRN.{B.H/H.W/W.D};
- VSRARN.{B.H/H.W/W.D};
- VSRLRNI.{B.H/H.W/W.D/D.Q};
- VSRARNI.{B.H/H.W/W.D/D.Q}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-27-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  16 +++
 target/loongarch/helper.h   |  16 +++
 target/loongarch/insn_trans/trans_lsx.c.inc |  16 +++
 target/loongarch/insns.decode   |  16 +++
 target/loongarch/lsx_helper.c   | 126 
 5 files changed, 190 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index f0fc2ff84b..185cd36381 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1182,3 +1182,19 @@ INSN_LSX(vsrani_b_h,   vv_i)
 INSN_LSX(vsrani_h_w,   vv_i)
 INSN_LSX(vsrani_w_d,   vv_i)
 INSN_LSX(vsrani_d_q,   vv_i)
+
+INSN_LSX(vsrlrn_b_h,   vvv)
+INSN_LSX(vsrlrn_h_w,   vvv)
+INSN_LSX(vsrlrn_w_d,   vvv)
+INSN_LSX(vsrarn_b_h,   vvv)
+INSN_LSX(vsrarn_h_w,   vvv)
+INSN_LSX(vsrarn_w_d,   vvv)
+
+INSN_LSX(vsrlrni_b_h,  vv_i)
+INSN_LSX(vsrlrni_h_w,  vv_i)
+INSN_LSX(vsrlrni_w_d,  vv_i)
+INSN_LSX(vsrlrni_d_q,  vv_i)
+INSN_LSX(vsrarni_b_h,  vv_i)
+INSN_LSX(vsrarni_h_w,  vv_i)
+INSN_LSX(vsrarni_w_d,  vv_i)
+INSN_LSX(vsrarni_d_q,  vv_i)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index afe7e3d2d0..0a8cfe3625 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -395,3 +395,19 @@ DEF_HELPER_4(vsrani_b_h, void, env, i32, i32, i32)
 DEF_HELPER_4(vsrani_h_w, void, env, i32, i32, i32)
 DEF_HELPER_4(vsrani_w_d, void, env, i32, i32, i32)
 DEF_HELPER_4(vsrani_d_q, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vsrlrn_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlrn_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlrn_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrarn_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrarn_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrarn_w_d, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vsrlrni_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlrni_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlrni_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrlrni_d_q, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrarni_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrarni_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrarni_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vsrarni_d_q, void, env, i32, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index ad34378ada..6034a74bfb 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3021,3 +3021,19 @@ TRANS(vsrani_b_h, gen_vv_i, gen_helper_vsrani_b_h)
 TRANS(vsrani_h_w, gen_vv_i, gen_helper_vsrani_h_w)
 TRANS(vsrani_w_d, gen_vv_i, gen_helper_vsrani_w_d)
 TRANS(vsrani_d_q, gen_vv_i, gen_helper_vsrani_d_q)
+
+TRANS(vsrlrn_b_h, gen_vvv, gen_helper_vsrlrn_b_h)
+TRANS(vsrlrn_h_w, gen_vvv, gen_helper_vsrlrn_h_w)
+TRANS(vsrlrn_w_d, gen_vvv, gen_helper_vsrlrn_w_d)
+TRANS(vsrarn_b_h, gen_vvv, gen_helper_vsrarn_b_h)
+TRANS(vsrarn_h_w, gen_vvv, gen_helper_vsrarn_h_w)
+TRANS(vsrarn_w_d, gen_vvv, gen_helper_vsrarn_w_d)
+
+TRANS(vsrlrni_b_h, gen_vv_i, gen_helper_vsrlrni_b_h)
+TRANS(vsrlrni_h_w, gen_vv_i, gen_helper_vsrlrni_h_w)
+TRANS(vsrlrni_w_d, gen_vv_i, gen_helper_vsrlrni_w_d)
+TRANS(vsrlrni_d_q, gen_vv_i, gen_helper_vsrlrni_d_q)
+TRANS(vsrarni_b_h, gen_vv_i, gen_helper_vsrarni_b_h)
+TRANS(vsrarni_h_w, gen_vv_i, gen_helper_vsrarni_h_w)
+TRANS(vsrarni_w_d, gen_vv_i, gen_helper_vsrarni_w_d)
+TRANS(vsrarni_d_q, gen_vv_i, gen_helper_vsrarni_d_q)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index ee54b632a7..29bf4a8a6a 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -883,3 +883,19 @@ vsrani_b_h   0111 00110101 1 1  . .   
@vv_ui4
 vsrani_h_w   0111 00110101 10001 . . .@vv_ui5
 vsrani_w_d   0111 00110101 1001 .. . .@vv_ui6
 vsrani_d_q   0111 00110101 101 ... . .@vv_ui7
+
+vsrlrn_b_h   0111  10001 . . .@vvv
+vsrlrn_h_w   0111  10010 . . .@vvv
+vsrlrn_w_d   0111  10011 . . .@vvv
+vsrarn_b_h   0111  10101 . . .@vvv
+vsrarn_h_w   0111  10110 . . .@vvv
+vsrarn_w_d   0111  10111 . . .@vvv
+
+vsrlrni_b_h  0111 00110100 01000 1  . .   @vv_ui4
+vsrlrni_h_w  0111 00110100 01001 . . .@vv_ui5
+vsrlrni_w_d  0111 00110100 0101 .. . .@vv_ui6
+vsrlrni_d_q  0111 00110100 011 ... . .@vv_ui7
+vsrarni_b_h  0111 00110101 11000 1  . .   @vv_ui4
+vsrarni_h_w  0111 00110101 11001 . . .@vv_ui5
+vsrarni_w_d 

[PULL v2 00/45] loongarch-to-apply queue

2023-05-05 Thread Song Gao
The following changes since commit eb5c3932a383ba1ef3a911232c644f2e053ef66c:

  Merge tag 'pw-pull-request' of https://gitlab.com/marcandre.lureau/qemu into 
staging (2023-05-05 19:18:05 +0100)

are available in the Git repository at:

  https://gitlab.com/gaosong/qemu.git tags/pull-loongarch-20230506

for you to fetch changes up to 725d7e763a802321e1bb303348afc551d564d31e:

  hw/intc: don't use target_ulong for LoongArch ipi (2023-05-06 11:19:50 +0800)


Add LoongArch LSX instructions.

v2: Fixes build error.


Alex Bennée (1):
  hw/intc: don't use target_ulong for LoongArch ipi

Song Gao (44):
  target/loongarch: Add LSX data type VReg
  target/loongarch: meson.build support build LSX
  target/loongarch: Add CHECK_SXE maccro for check LSX enable
  target/loongarch: Implement vadd/vsub
  target/loongarch: Implement vaddi/vsubi
  target/loongarch: Implement vneg
  target/loongarch: Implement vsadd/vssub
  target/loongarch: Implement vhaddw/vhsubw
  target/loongarch: Implement vaddw/vsubw
  target/loongarch: Implement vavg/vavgr
  target/loongarch: Implement vabsd
  target/loongarch: Implement vadda
  target/loongarch: Implement vmax/vmin
  target/loongarch: Implement vmul/vmuh/vmulw{ev/od}
  target/loongarch: Implement vmadd/vmsub/vmaddw{ev/od}
  target/loongarch: Implement vdiv/vmod
  target/loongarch: Implement vsat
  target/loongarch: Implement vexth
  target/loongarch: Implement vsigncov
  target/loongarch: Implement vmskltz/vmskgez/vmsknz
  target/loongarch: Implement LSX logic instructions
  target/loongarch: Implement vsll vsrl vsra vrotr
  target/loongarch: Implement vsllwil vextl
  target/loongarch: Implement vsrlr vsrar
  target/loongarch: Implement vsrln vsran
  target/loongarch: Implement vsrlrn vsrarn
  target/loongarch: Implement vssrln vssran
  target/loongarch: Implement vssrlrn vssrarn
  target/loongarch: Implement vclo vclz
  target/loongarch: Implement vpcnt
  target/loongarch: Implement vbitclr vbitset vbitrev
  target/loongarch: Implement vfrstp
  target/loongarch: Implement LSX fpu arith instructions
  target/loongarch: Implement LSX fpu fcvt instructions
  target/loongarch: Implement vseq vsle vslt
  target/loongarch: Implement vfcmp
  target/loongarch: Implement vbitsel vset
  target/loongarch: Implement vinsgr2vr vpickve2gr vreplgr2vr
  target/loongarch: Implement vreplve vpack vpick
  target/loongarch: Implement vilvl vilvh vextrins vshuf
  target/loongarch: Implement vld vst
  target/loongarch: Implement vldi
  target/loongarch: Use {set/get}_gpr replace to cpu_fpr
  target/loongarch: CPUCFG support LSX

 hw/intc/loongarch_ipi.c |2 +-
 linux-user/loongarch64/signal.c |4 +-
 target/loongarch/cpu.c  |5 +-
 target/loongarch/cpu.h  |   27 +-
 target/loongarch/disas.c|  911 +
 target/loongarch/fpu_helper.c   |2 +-
 target/loongarch/gdbstub.c  |4 +-
 target/loongarch/helper.h   |  566 +++
 target/loongarch/insn_trans/trans_farith.c.inc  |   72 +-
 target/loongarch/insn_trans/trans_fcmp.c.inc|   12 +-
 target/loongarch/insn_trans/trans_fmemory.c.inc |   37 +-
 target/loongarch/insn_trans/trans_fmov.c.inc|   31 +-
 target/loongarch/insn_trans/trans_lsx.c.inc | 4400 +++
 target/loongarch/insns.decode   |  811 +
 target/loongarch/internals.h|   23 +
 target/loongarch/lsx_helper.c   | 3004 
 target/loongarch/machine.c  |   79 +-
 target/loongarch/meson.build|1 +
 target/loongarch/translate.c|   55 +-
 target/loongarch/translate.h|1 +
 20 files changed, 9989 insertions(+), 58 deletions(-)
 create mode 100644 target/loongarch/insn_trans/trans_lsx.c.inc
 create mode 100644 target/loongarch/lsx_helper.c




[PULL v2 06/45] target/loongarch: Implement vneg

2023-05-05 Thread Song Gao
This patch includes;
- VNEG.{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-7-gaos...@loongson.cn>
---
 target/loongarch/disas.c| 10 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 20 
 target/loongarch/insns.decode   |  7 +++
 3 files changed, 37 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index c1960610c2..5eabb8c47a 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -802,6 +802,11 @@ static void output_vv_i(DisasContext *ctx, arg_vv_i *a, 
const char *mnemonic)
 output(ctx, mnemonic, "v%d, v%d, 0x%x", a->vd, a->vj, a->imm);
 }
 
+static void output_vv(DisasContext *ctx, arg_vv *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "v%d, v%d", a->vd, a->vj);
+}
+
 INSN_LSX(vadd_b,   vvv)
 INSN_LSX(vadd_h,   vvv)
 INSN_LSX(vadd_w,   vvv)
@@ -821,3 +826,8 @@ INSN_LSX(vsubi_bu, vv_i)
 INSN_LSX(vsubi_hu, vv_i)
 INSN_LSX(vsubi_wu, vv_i)
 INSN_LSX(vsubi_du, vv_i)
+
+INSN_LSX(vneg_b,   vv)
+INSN_LSX(vneg_h,   vv)
+INSN_LSX(vneg_w,   vv)
+INSN_LSX(vneg_d,   vv)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index e6c1d0d2cc..d02db6285f 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -44,6 +44,21 @@ static bool gvec_vvv(DisasContext *ctx, arg_vvv *a, MemOp 
mop,
 return true;
 }
 
+static bool gvec_vv(DisasContext *ctx, arg_vv *a, MemOp mop,
+void (*func)(unsigned, uint32_t, uint32_t,
+ uint32_t, uint32_t))
+{
+uint32_t vd_ofs, vj_ofs;
+
+CHECK_SXE;
+
+vd_ofs = vec_full_offset(a->vd);
+vj_ofs = vec_full_offset(a->vj);
+
+func(mop, vd_ofs, vj_ofs, 16, ctx->vl/8);
+return true;
+}
+
 static bool gvec_vv_i(DisasContext *ctx, arg_vv_i *a, MemOp mop,
   void (*func)(unsigned, uint32_t, uint32_t,
int64_t, uint32_t, uint32_t))
@@ -120,3 +135,8 @@ TRANS(vsubi_bu, gvec_subi, MO_8)
 TRANS(vsubi_hu, gvec_subi, MO_16)
 TRANS(vsubi_wu, gvec_subi, MO_32)
 TRANS(vsubi_du, gvec_subi, MO_64)
+
+TRANS(vneg_b, gvec_vv, MO_8, tcg_gen_gvec_neg)
+TRANS(vneg_h, gvec_vv, MO_16, tcg_gen_gvec_neg)
+TRANS(vneg_w, gvec_vv, MO_32, tcg_gen_gvec_neg)
+TRANS(vneg_d, gvec_vv, MO_64, tcg_gen_gvec_neg)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 2a98c14518..d90798be11 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -490,12 +490,14 @@ dbcl  0010 10101 ...  
@i15
 # LSX Argument sets
 #
 
+&vv   vd vj
 &vvv  vd vj vk
 &vv_i vd vj imm
 
 #
 # LSX Formats
 #
+@vv     . . vj:5 vd:5&vv
 @vvv     . vk:5 vj:5 vd:5&vvv
 @vv_ui5     . imm:5 vj:5 vd:5&vv_i
 
@@ -518,3 +520,8 @@ vsubi_bu 0111 00101000 11000 . . .
@vv_ui5
 vsubi_hu 0111 00101000 11001 . . .@vv_ui5
 vsubi_wu 0111 00101000 11010 . . .@vv_ui5
 vsubi_du 0111 00101000 11011 . . .@vv_ui5
+
+vneg_b   0111 00101001 11000 01100 . .@vv
+vneg_h   0111 00101001 11000 01101 . .@vv
+vneg_w   0111 00101001 11000 01110 . .@vv
+vneg_d   0111 00101001 11000 0 . .@vv
-- 
2.31.1




[PULL v2 28/45] target/loongarch: Implement vssrlrn vssrarn

2023-05-05 Thread Song Gao
This patch includes:
- VSSRLRN.{B.H/H.W/W.D};
- VSSRARN.{B.H/H.W/W.D};
- VSSRLRN.{BU.H/HU.W/WU.D};
- VSSRARN.{BU.H/HU.W/WU.D};
- VSSRLRNI.{B.H/H.W/W.D/D.Q};
- VSSRARNI.{B.H/H.W/W.D/D.Q};
- VSSRLRNI.{BU.H/HU.W/WU.D/DU.Q};
- VSSRARNI.{BU.H/HU.W/WU.D/DU.Q}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-29-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  30 ++
 target/loongarch/helper.h   |  30 ++
 target/loongarch/insn_trans/trans_lsx.c.inc |  30 ++
 target/loongarch/insns.decode   |  30 ++
 target/loongarch/lsx_helper.c   | 358 
 5 files changed, 478 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 426d30dc01..405e8885cd 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -1228,3 +1228,33 @@ INSN_LSX(vssrani_bu_h, vv_i)
 INSN_LSX(vssrani_hu_w, vv_i)
 INSN_LSX(vssrani_wu_d, vv_i)
 INSN_LSX(vssrani_du_q, vv_i)
+
+INSN_LSX(vssrlrn_b_h,  vvv)
+INSN_LSX(vssrlrn_h_w,  vvv)
+INSN_LSX(vssrlrn_w_d,  vvv)
+INSN_LSX(vssrarn_b_h,  vvv)
+INSN_LSX(vssrarn_h_w,  vvv)
+INSN_LSX(vssrarn_w_d,  vvv)
+INSN_LSX(vssrlrn_bu_h, vvv)
+INSN_LSX(vssrlrn_hu_w, vvv)
+INSN_LSX(vssrlrn_wu_d, vvv)
+INSN_LSX(vssrarn_bu_h, vvv)
+INSN_LSX(vssrarn_hu_w, vvv)
+INSN_LSX(vssrarn_wu_d, vvv)
+
+INSN_LSX(vssrlrni_b_h, vv_i)
+INSN_LSX(vssrlrni_h_w, vv_i)
+INSN_LSX(vssrlrni_w_d, vv_i)
+INSN_LSX(vssrlrni_d_q, vv_i)
+INSN_LSX(vssrlrni_bu_h,vv_i)
+INSN_LSX(vssrlrni_hu_w,vv_i)
+INSN_LSX(vssrlrni_wu_d,vv_i)
+INSN_LSX(vssrlrni_du_q,vv_i)
+INSN_LSX(vssrarni_b_h, vv_i)
+INSN_LSX(vssrarni_h_w, vv_i)
+INSN_LSX(vssrarni_w_d, vv_i)
+INSN_LSX(vssrarni_d_q, vv_i)
+INSN_LSX(vssrarni_bu_h,vv_i)
+INSN_LSX(vssrarni_hu_w,vv_i)
+INSN_LSX(vssrarni_wu_d,vv_i)
+INSN_LSX(vssrarni_du_q,vv_i)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 28f159768c..724112da81 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -441,3 +441,33 @@ DEF_HELPER_4(vssrani_bu_h, void, env, i32, i32, i32)
 DEF_HELPER_4(vssrani_hu_w, void, env, i32, i32, i32)
 DEF_HELPER_4(vssrani_wu_d, void, env, i32, i32, i32)
 DEF_HELPER_4(vssrani_du_q, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vssrlrn_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlrn_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlrn_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarn_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarn_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarn_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlrn_bu_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlrn_hu_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlrn_wu_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarn_bu_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarn_hu_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarn_wu_d, void, env, i32, i32, i32)
+
+DEF_HELPER_4(vssrlrni_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlrni_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlrni_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlrni_d_q, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarni_b_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarni_h_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarni_w_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarni_d_q, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlrni_bu_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlrni_hu_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlrni_wu_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrlrni_du_q, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarni_bu_h, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarni_hu_w, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarni_wu_d, void, env, i32, i32, i32)
+DEF_HELPER_4(vssrarni_du_q, void, env, i32, i32, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 5d7e45a793..9c24cbc297 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -3067,3 +3067,33 @@ TRANS(vssrani_bu_h, gen_vv_i, gen_helper_vssrani_bu_h)
 TRANS(vssrani_hu_w, gen_vv_i, gen_helper_vssrani_hu_w)
 TRANS(vssrani_wu_d, gen_vv_i, gen_helper_vssrani_wu_d)
 TRANS(vssrani_du_q, gen_vv_i, gen_helper_vssrani_du_q)
+
+TRANS(vssrlrn_b_h, gen_vvv, gen_helper_vssrlrn_b_h)
+TRANS(vssrlrn_h_w, gen_vvv, gen_helper_vssrlrn_h_w)
+TRANS(vssrlrn_w_d, gen_vvv, gen_helper_vssrlrn_w_d)
+TRANS(vssrarn_b_h, gen_vvv, gen_helper_vssrarn_b_h)
+TRANS(vssrarn_h_w, gen_vvv, gen_helper_vssrarn_h_w)
+TRANS(vssrarn_w_d, gen_vvv, gen_helper_vssrarn_w_d)
+TRANS(vssrlrn_bu_h, gen_vvv, gen_helper_vssrlrn_bu_h)
+TRANS(vssrlrn_hu_w, gen_vvv, gen_helper_vssrlrn_hu_w)
+TRANS(vssrlrn_wu_d, gen_vvv, gen_helper_vssrlrn_wu_d)
+TRANS(vssrarn_bu_h, gen_vvv, gen_helper_vssrarn_bu_h)
+TRANS(vssrarn_hu_w, gen_vvv, gen_helper_vssrarn_hu_w)
+TRANS(vssrarn_wu_d, gen_vvv, 

[PULL v2 12/45] target/loongarch: Implement vadda

2023-05-05 Thread Song Gao
This patch includes:
- VADDA.{B/H/W/D}.

Reviewed-by: Richard Henderson 
Signed-off-by: Song Gao 
Message-Id: <20230504122810.4094787-13-gaos...@loongson.cn>
---
 target/loongarch/disas.c|  5 ++
 target/loongarch/helper.h   |  5 ++
 target/loongarch/insn_trans/trans_lsx.c.inc | 53 +
 target/loongarch/insns.decode   |  5 ++
 target/loongarch/lsx_helper.c   | 19 
 5 files changed, 87 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index e98ea37793..1f61e67d1f 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -934,3 +934,8 @@ INSN_LSX(vabsd_bu, vvv)
 INSN_LSX(vabsd_hu, vvv)
 INSN_LSX(vabsd_wu, vvv)
 INSN_LSX(vabsd_du, vvv)
+
+INSN_LSX(vadda_b,  vvv)
+INSN_LSX(vadda_h,  vvv)
+INSN_LSX(vadda_w,  vvv)
+INSN_LSX(vadda_d,  vvv)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index c3a5d2566e..85fb8f60d2 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -220,3 +220,8 @@ DEF_HELPER_FLAGS_4(vabsd_bu, TCG_CALL_NO_RWG, void, ptr, 
ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vabsd_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vabsd_wu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(vabsd_du, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(vadda_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vadda_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vadda_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(vadda_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
diff --git a/target/loongarch/insn_trans/trans_lsx.c.inc 
b/target/loongarch/insn_trans/trans_lsx.c.inc
index 0e9301bf93..8ad81c8517 100644
--- a/target/loongarch/insn_trans/trans_lsx.c.inc
+++ b/target/loongarch/insn_trans/trans_lsx.c.inc
@@ -1261,3 +1261,56 @@ TRANS(vabsd_bu, gvec_vvv, MO_8, do_vabsd_u)
 TRANS(vabsd_hu, gvec_vvv, MO_16, do_vabsd_u)
 TRANS(vabsd_wu, gvec_vvv, MO_32, do_vabsd_u)
 TRANS(vabsd_du, gvec_vvv, MO_64, do_vabsd_u)
+
+static void gen_vadda(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+TCGv_vec t1, t2;
+
+t1 = tcg_temp_new_vec_matching(a);
+t2 = tcg_temp_new_vec_matching(b);
+
+tcg_gen_abs_vec(vece, t1, a);
+tcg_gen_abs_vec(vece, t2, b);
+tcg_gen_add_vec(vece, t, t1, t2);
+}
+
+static void do_vadda(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
+ uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
+{
+static const TCGOpcode vecop_list[] = {
+INDEX_op_abs_vec, INDEX_op_add_vec, 0
+};
+static const GVecGen3 op[4] = {
+{
+.fniv = gen_vadda,
+.fno = gen_helper_vadda_b,
+.opt_opc = vecop_list,
+.vece = MO_8
+},
+{
+.fniv = gen_vadda,
+.fno = gen_helper_vadda_h,
+.opt_opc = vecop_list,
+.vece = MO_16
+},
+{
+.fniv = gen_vadda,
+.fno = gen_helper_vadda_w,
+.opt_opc = vecop_list,
+.vece = MO_32
+},
+{
+.fniv = gen_vadda,
+.fno = gen_helper_vadda_d,
+.opt_opc = vecop_list,
+.vece = MO_64
+},
+};
+
+tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
+}
+
+TRANS(vadda_b, gvec_vvv, MO_8, do_vadda)
+TRANS(vadda_h, gvec_vvv, MO_16, do_vadda)
+TRANS(vadda_w, gvec_vvv, MO_32, do_vadda)
+TRANS(vadda_d, gvec_vvv, MO_64, do_vadda)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 825ddedf4d..6cb22f9297 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -628,3 +628,8 @@ vabsd_bu 0111 0110 00100 . . .
@vvv
 vabsd_hu 0111 0110 00101 . . .@vvv
 vabsd_wu 0111 0110 00110 . . .@vvv
 vabsd_du 0111 0110 00111 . . .@vvv
+
+vadda_b  0111 0101 11000 . . .@vvv
+vadda_h  0111 0101 11001 . . .@vvv
+vadda_w  0111 0101 11010 . . .@vvv
+vadda_d  0111 0101 11011 . . .@vvv
diff --git a/target/loongarch/lsx_helper.c b/target/loongarch/lsx_helper.c
index f0baffa9e3..8230fe2ed5 100644
--- a/target/loongarch/lsx_helper.c
+++ b/target/loongarch/lsx_helper.c
@@ -318,3 +318,22 @@ DO_3OP(vabsd_bu, 8, UB, DO_VABSD)
 DO_3OP(vabsd_hu, 16, UH, DO_VABSD)
 DO_3OP(vabsd_wu, 32, UW, DO_VABSD)
 DO_3OP(vabsd_du, 64, UD, DO_VABSD)
+
+#define DO_VABS(a)  ((a < 0) ? (-a) : (a))
+
+#define DO_VADDA(NAME, BIT, E, DO_OP)   \
+void HELPER(NAME)(void *vd, void *vj, void *vk, uint32_t v) \
+{   \
+int i;  \
+VReg *Vd 

[PATCH RFC v3 1/9] linux-headers: Add KVM headers for loongarch

2023-05-05 Thread Tianrui Zhao
This patch is only a placeholder now, which is used to
show some kvm structures and macros for reviewers.
And it will be replaced by using update-linux-headers.sh
when the linux loongarch kvm patches are accepted.

Signed-off-by: Tianrui Zhao 
---
 linux-headers/asm-loongarch/kvm.h | 99 +++
 linux-headers/linux/kvm.h |  9 +++
 2 files changed, 108 insertions(+)
 create mode 100644 linux-headers/asm-loongarch/kvm.h

diff --git a/linux-headers/asm-loongarch/kvm.h 
b/linux-headers/asm-loongarch/kvm.h
new file mode 100644
index 00..6420f59f9e
--- /dev/null
+++ b/linux-headers/asm-loongarch/kvm.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (C) 2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef __UAPI_ASM_LOONGARCH_KVM_H
+#define __UAPI_ASM_LOONGARCH_KVM_H
+
+#include 
+
+/*
+ * KVM Loongarch specific structures and definitions.
+ */
+
+#define __KVM_HAVE_READONLY_MEM
+
+#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+
+/*
+ * for KVM_GET_REGS and KVM_SET_REGS
+ */
+struct kvm_regs {
+   /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+   __u64 gpr[32];
+   __u64 pc;
+};
+
+/*
+ * for KVM_GET_FPU and KVM_SET_FPU
+ */
+struct kvm_fpu {
+   __u32 fcsr;
+   __u32 none;
+   __u64 fcc;/* 8x8 */
+   struct kvm_fpureg {
+   __u64 val64[4];
+   } fpr[32];
+};
+
+/*
+ * For LoongArch, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various
+ * registers.  The id field is broken down as follows:
+ *
+ *  bits[63..52] - As per linux/kvm.h
+ *  bits[51..32] - Must be zero.
+ *  bits[31..16] - Register set.
+ *
+ * Register set = 0: GP registers from kvm_regs (see definitions below).
+ *
+ * Register set = 1: CSR registers.
+ *
+ * Register set = 2: KVM specific registers (see definitions below).
+ *
+ * Register set = 3: FPU / SIMD registers (see definitions below).
+ *
+ * Other sets registers may be added in the future.  Each set would
+ * have its own identifier in bits[31..16].
+ */
+
+#define KVM_REG_LOONGARCH_GP   (KVM_REG_LOONGARCH | 0x0ULL)
+#define KVM_REG_LOONGARCH_CSR  (KVM_REG_LOONGARCH | 0x1ULL)
+#define KVM_REG_LOONGARCH_KVM  (KVM_REG_LOONGARCH | 0x2ULL)
+#define KVM_REG_LOONGARCH_FPU  (KVM_REG_LOONGARCH | 0x3ULL)
+#define KVM_REG_LOONGARCH_MASK (KVM_REG_LOONGARCH | 0x3ULL)
+#define KVM_CSR_IDX_MASK   (0x1 - 1)
+
+/*
+ * KVM_REG_LOONGARCH_KVM - KVM specific control registers.
+ */
+
+#define KVM_REG_LOONGARCH_COUNTER  (KVM_REG_LOONGARCH_KVM | 
KVM_REG_SIZE_U64 | 3)
+#define KVM_REG_LOONGARCH_VCPU_RESET   (KVM_REG_LOONGARCH_KVM | 
KVM_REG_SIZE_U64 | 4)
+
+struct kvm_debug_exit_arch {
+};
+
+/* for KVM_SET_GUEST_DEBUG */
+struct kvm_guest_debug_arch {
+};
+
+/* definition of registers in kvm_run */
+struct kvm_sync_regs {
+};
+
+/* dummy definition */
+struct kvm_sregs {
+};
+
+struct kvm_loongarch_interrupt {
+   /* in */
+   __u32 cpu;
+   __u32 irq;
+};
+
+#define KVM_NR_IRQCHIPS1
+#define KVM_IRQCHIP_NUM_PINS   64
+#define KVM_MAX_CORES  256
+
+#endif /* __UAPI_ASM_LOONGARCH_KVM_H */
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 599de3c6e3..d82e1da7a8 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -264,6 +264,7 @@ struct kvm_xen_exit {
 #define KVM_EXIT_RISCV_SBI35
 #define KVM_EXIT_RISCV_CSR36
 #define KVM_EXIT_NOTIFY   37
+#define KVM_EXIT_LOONGARCH_IOCSR  38
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -336,6 +337,13 @@ struct kvm_run {
__u32 len;
__u8  is_write;
} mmio;
+   /* KVM_EXIT_LOONGARCH_IOCSR */
+   struct {
+   __u64 phys_addr;
+   __u8  data[8];
+   __u32 len;
+   __u8  is_write;
+   } iocsr_io;
/* KVM_EXIT_HYPERCALL */
struct {
__u64 nr;
@@ -1352,6 +1360,7 @@ struct kvm_dirty_tlb {
 #define KVM_REG_ARM64  0x6000ULL
 #define KVM_REG_MIPS   0x7000ULL
 #define KVM_REG_RISCV  0x8000ULL
+#define KVM_REG_LOONGARCH  0x9000ULL
 
 #define KVM_REG_SIZE_SHIFT 52
 #define KVM_REG_SIZE_MASK  0x00f0ULL
-- 
2.31.1




[PATCH RFC v3 4/9] target/loongarch: Implement kvm get/set registers

2023-05-05 Thread Tianrui Zhao
Implement kvm_arch_get/set_registers interfaces, many regs
can be get/set in the function, such as core regs, csr regs,
fpu regs, mp state, etc.

Signed-off-by: Tianrui Zhao 
Reviewed-by: Richard Henderson 
---
 meson.build   |   1 +
 target/loongarch/cpu.c|   3 +
 target/loongarch/cpu.h|   2 +
 target/loongarch/kvm.c| 362 +-
 target/loongarch/trace-events |  11 ++
 target/loongarch/trace.h  |   1 +
 6 files changed, 378 insertions(+), 2 deletions(-)
 create mode 100644 target/loongarch/trace-events
 create mode 100644 target/loongarch/trace.h

diff --git a/meson.build b/meson.build
index 77d42898c8..ad0b02f65b 100644
--- a/meson.build
+++ b/meson.build
@@ -3033,6 +3033,7 @@ if have_system or have_user
 'target/hppa',
 'target/i386',
 'target/i386/kvm',
+'target/loongarch',
 'target/mips/tcg',
 'target/nios2',
 'target/ppc',
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index d15b4b2844..f20345de34 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -508,6 +508,9 @@ static void loongarch_cpu_reset_hold(Object *obj)
 #ifndef CONFIG_USER_ONLY
 env->pc = 0x1c00;
 memset(env->tlb, 0, sizeof(env->tlb));
+if (kvm_enabled()) {
+kvm_arch_reset_vcpu(env);
+}
 #endif
 
 restore_fp_status(env);
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 1d9a4009b9..cf3fce4577 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -329,6 +329,7 @@ typedef struct CPUArchState {
 MemoryRegion iocsr_mem;
 bool load_elf;
 uint64_t elf_address;
+uint32_t mp_state;
 #endif
 } CPULoongArchState;
 
@@ -414,6 +415,7 @@ static inline void cpu_get_tb_cpu_state(CPULoongArchState 
*env,
 }
 
 void loongarch_cpu_list(void);
+void kvm_arch_reset_vcpu(CPULoongArchState *env);
 
 #define cpu_list loongarch_cpu_list
 
diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 24327aaf71..640fca52fa 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -26,19 +26,377 @@
 #include "sysemu/runstate.h"
 #include "cpu-csr.h"
 #include "kvm_loongarch.h"
+#include "trace.h"
 
 static bool cap_has_mp_state;
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 KVM_CAP_LAST_INFO
 };
 
+static int kvm_loongarch_get_regs_core(CPUState *cs)
+{
+int ret = 0;
+int i;
+struct kvm_regs regs;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = &cpu->env;
+
+/* Get the current register set as KVM seems it */
+ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s);
+if (ret < 0) {
+trace_kvm_failed_get_regs_core(strerror(errno));
+return ret;
+}
+/* gpr[0] value is always 0 */
+env->gpr[0] = 0;
+for (i = 1; i < 32; i++) {
+env->gpr[i] = regs.gpr[i];
+}
+
+env->pc = regs.pc;
+return ret;
+}
+
+static int kvm_loongarch_put_regs_core(CPUState *cs)
+{
+int ret = 0;
+int i;
+struct kvm_regs regs;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = &cpu->env;
+
+/* Set the registers based on QEMU's view of things */
+for (i = 0; i < 32; i++) {
+regs.gpr[i] = env->gpr[i];
+}
+
+regs.pc = env->pc;
+ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s);
+if (ret < 0) {
+trace_kvm_failed_put_regs_core(strerror(errno));
+}
+
+return ret;
+}
+
+static int kvm_larch_getq(CPUState *cs, uint64_t reg_id,
+ uint64_t *addr)
+{
+struct kvm_one_reg csrreg = {
+.id = reg_id,
+.addr = (uintptr_t)addr
+};
+
+return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg);
+}
+static int kvm_larch_putq(CPUState *cs, uint64_t reg_id,
+ uint64_t *addr)
+{
+struct kvm_one_reg csrreg = {
+.id = reg_id,
+.addr = (uintptr_t)addr
+};
+
+return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg);
+}
+
+#define LOONGARCH_CSR_64(_R, _S)  \
+(KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U64 | (8 * (_R) + (_S)))
+
+#define KVM_IOC_CSRID(id) LOONGARCH_CSR_64(id, 0)
+
+#define KVM_GET_ONE_UREG64(cs, ret, regidx, addr) \
+({\
+err = kvm_larch_getq(cs, KVM_IOC_CSRID(regidx), addr);\
+if (err < 0) {\
+ret = err;\
+trace_kvm_failed_get_csr(regidx, strerror(errno));\
+} \
+})
+
+#define KVM_PUT_ONE_UREG64(cs, ret, regidx, addr) \
+({\
+err = kvm_larch_putq(cs, KVM_IOC_CSRID(regidx), addr);\
+if (err < 0) {\
+ret = err;\
+tr

[PATCH RFC v3 8/9] target/loongarch: Implement set vcpu intr for kvm

2023-05-05 Thread Tianrui Zhao
Implement loongarch kvm set vcpu interrupt interface,
when a irq is set in vcpu, we use the KVM_INTERRUPT
ioctl to set intr into kvm.

Signed-off-by: Tianrui Zhao 
---
 target/loongarch/cpu.c   | 18 +-
 target/loongarch/kvm-stub.c  | 11 +++
 target/loongarch/kvm.c   | 16 
 target/loongarch/kvm_loongarch.h | 13 +
 target/loongarch/trace-events|  1 +
 5 files changed, 54 insertions(+), 5 deletions(-)
 create mode 100644 target/loongarch/kvm-stub.c
 create mode 100644 target/loongarch/kvm_loongarch.h

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index f20345de34..fb4bb3ede7 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -18,6 +18,11 @@
 #include "cpu-csr.h"
 #include "sysemu/reset.h"
 #include "tcg/tcg.h"
+#include "sysemu/kvm.h"
+#include "kvm_loongarch.h"
+#ifdef CONFIG_KVM
+#include 
+#endif
 
 const char * const regnames[32] = {
 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -104,12 +109,15 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int 
level)
 return;
 }
 
-env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
-
-if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
-cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+if (kvm_enabled()) {
+kvm_loongarch_set_interrupt(cpu, irq, level);
 } else {
-cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
+if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
 }
 }
 
diff --git a/target/loongarch/kvm-stub.c b/target/loongarch/kvm-stub.c
new file mode 100644
index 00..9965c1f119
--- /dev/null
+++ b/target/loongarch/kvm-stub.c
@@ -0,0 +1,11 @@
+/*
+ * QEMU KVM LoongArch specific function stubs
+ *
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
+ */
+#include "cpu.h"
+
+void kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level)
+{
+   g_assert_not_reached();
+}
diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 6554013a9d..ec6a962e18 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -525,6 +525,22 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
 return ret;
 }
 
+int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level)
+{
+struct kvm_loongarch_interrupt intr;
+CPUState *cs = CPU(cpu);
+
+intr.cpu = cs->cpu_index;
+if (level) {
+intr.irq = irq;
+} else {
+intr.irq = -irq;
+}
+
+trace_kvm_set_intr(irq, level);
+return kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
+}
+
 void kvm_arch_accel_class_init(ObjectClass *oc)
 {
 }
diff --git a/target/loongarch/kvm_loongarch.h b/target/loongarch/kvm_loongarch.h
new file mode 100644
index 00..cdef980eec
--- /dev/null
+++ b/target/loongarch/kvm_loongarch.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch kvm interface
+ *
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef QEMU_KVM_LOONGARCH_H
+#define QEMU_KVM_LOONGARCH_H
+
+int  kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level);
+
+#endif
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
index c79e01663a..2673e43bfd 100644
--- a/target/loongarch/trace-events
+++ b/target/loongarch/trace-events
@@ -12,3 +12,4 @@ kvm_failed_put_mpstate(const char *msg) "Failed to put 
mp_state into KVM: %s"
 kvm_failed_get_counter(const char *msg) "Failed to get counter from KVM: %s"
 kvm_failed_put_counter(const char *msg) "Failed to put counter into KVM: %s"
 kvm_arch_handle_exit(int num) "kvm arch handle exit, the reason number: %d"
+kvm_set_intr(int irq, int level) "kvm set interrupt, irq num: %d, level: %d"
-- 
2.31.1




[PATCH RFC v3 9/9] target/loongarch: Add loongarch kvm into meson build

2023-05-05 Thread Tianrui Zhao
Add kvm.c and kvm-stub.c into meson.build to compile
it when kvm is configed. Meanwhile in meson.build,
we set the kvm_targets to loongarch64-softmmu when
the cpu is loongarch.

Signed-off-by: Tianrui Zhao 
Reviewed-by: Richard Henderson 
---
 meson.build  | 2 ++
 target/loongarch/meson.build | 1 +
 2 files changed, 3 insertions(+)

diff --git a/meson.build b/meson.build
index ad0b02f65b..38a343e952 100644
--- a/meson.build
+++ b/meson.build
@@ -114,6 +114,8 @@ elif cpu in ['mips', 'mips64']
   kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 
'mips64el-softmmu']
 elif cpu in ['riscv']
   kvm_targets = ['riscv32-softmmu', 'riscv64-softmmu']
+elif cpu in ['loongarch64']
+  kvm_targets = ['loongarch64-softmmu']
 else
   kvm_targets = []
 endif
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 9293a8ab78..0c6cec81e4 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -26,6 +26,7 @@ loongarch_softmmu_ss.add(files(
 
 common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: [files('disas.c'), gen])
 
+loongarch_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: 
files('kvm-stub.c'))
 loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
 
 target_arch += {'loongarch': loongarch_ss}
-- 
2.31.1




Re: [PATCH] virtio-net: not enable vq reset feature unconditionally

2023-05-05 Thread Xuan Zhuo
On Thu,  4 May 2023 12:14:47 +0200, =?utf-8?q?Eugenio_P=C3=A9rez?= 
 wrote:
> The commit 93a97dc5200a ("virtio-net: enable vq reset feature") enables
> unconditionally vq reset feature as long as the device is emulated.
> This makes impossible to actually disable the feature, and it causes
> migration problems from qemu version previous than 7.2.
>
> The entire final commit is unneeded as device system already enable or
> disable the feature properly.
>
> This reverts commit 93a97dc5200a95e63b99cb625f20b7ae802ba413.
> Fixes: 93a97dc5200a ("virtio-net: enable vq reset feature")
> Signed-off-by: Eugenio Pérez 
>
> ---
> Tested by checking feature bit at  /sys/devices/pci.../virtio0/features
> enabling and disabling queue_reset virtio-net feature and vhost=on/off
> on net device backend.

Do you mean that this feature cannot be closed?

I tried to close in the guest, it was successful.

In addition, in this case, could you try to repair the problem instead of
directly revert.

Thanks.

> ---
>  hw/net/virtio-net.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index 53e1c32643..4ea33b6e2e 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -805,7 +805,6 @@ static uint64_t virtio_net_get_features(VirtIODevice 
> *vdev, uint64_t features,
>  }
>
>  if (!get_vhost_net(nc->peer)) {
> -virtio_add_feature(&features, VIRTIO_F_RING_RESET);
>  return features;
>  }
>
> --
> 2.31.1
>



[PATCH RFC v3 7/9] target/loongarch: Implement kvm_arch_handle_exit

2023-05-05 Thread Tianrui Zhao
Implement kvm_arch_handle_exit for loongarch. In this
function, the KVM_EXIT_LOONGARCH_IOCSR is handled,
we read or write the iocsr address space by the addr,
length and is_write argument in kvm_run.

Signed-off-by: Tianrui Zhao 
Reviewed-by: Richard Henderson 
---
 target/loongarch/kvm.c| 24 +++-
 target/loongarch/trace-events |  1 +
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 5a07cc58c8..6554013a9d 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -500,7 +500,29 @@ bool kvm_arch_cpu_check_are_resettable(void)
 
 int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
 {
-return 0;
+int ret = 0;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = &cpu->env;
+MemTxAttrs attrs = {};
+
+attrs.requester_id = env_cpu(env)->cpu_index;
+
+trace_kvm_arch_handle_exit(run->exit_reason);
+switch (run->exit_reason) {
+case KVM_EXIT_LOONGARCH_IOCSR:
+address_space_rw(&env->address_space_iocsr,
+ run->iocsr_io.phys_addr,
+ attrs,
+ run->iocsr_io.data,
+ run->iocsr_io.len,
+ run->iocsr_io.is_write);
+break;
+default:
+ret = -1;
+warn_report("KVM: unknown exit reason %d", run->exit_reason);
+break;
+}
+return ret;
 }
 
 void kvm_arch_accel_class_init(ObjectClass *oc)
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
index 6926bbe399..c79e01663a 100644
--- a/target/loongarch/trace-events
+++ b/target/loongarch/trace-events
@@ -11,3 +11,4 @@ kvm_failed_get_mpstate(const char *msg) "Failed to get 
mp_state from KVM: %s"
 kvm_failed_put_mpstate(const char *msg) "Failed to put mp_state into KVM: %s"
 kvm_failed_get_counter(const char *msg) "Failed to get counter from KVM: %s"
 kvm_failed_put_counter(const char *msg) "Failed to put counter into KVM: %s"
+kvm_arch_handle_exit(int num) "kvm arch handle exit, the reason number: %d"
-- 
2.31.1




[PATCH RFC v3 0/9] Add loongarch kvm accel support

2023-05-05 Thread Tianrui Zhao
This series add loongarch kvm support, mainly implement
some interfaces used by kvm such as kvm_arch_get/set_regs,
kvm_arch_handle_exit, kvm_loongarch_set_interrupt, etc.

Currently, we are able to boot LoongArch KVM Linux Guests.
In loongarch VM, mmio devices and iocsr devices are emulated
in user space such as APIC, IPI, pci devices, etc, other
hardwares such as MMU, timer and csr are emulated in kernel.

It is based on temporarily unaccepted linux kvm:
https://github.com/loongson/linux-loongarch-kvm
And We will remove the RFC flag until the linux kvm patches
are merged.

The running environment of LoongArch virt machine:
1. Get the linux source by the above mentioned link.
   git checkout kvm-loongarch
   make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- 
loongson3_defconfig
   make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu-
2. Get the qemu source: https://github.com/loongson/qemu
   git checkout kvm-loongarch
   ./configure --target-list="loongarch64-softmmu"  --enable-kvm
   make
3. Get uefi bios of LoongArch virt machine:
   Link: 
https://github.com/tianocore/edk2-platforms/tree/master/Platform/Loongson/LoongArchQemuPkg#readme
4. Also you can access the binary files we have already build:
   https://github.com/yangxiaojuan-loongson/qemu-binary

The command to boot loongarch virt machine:
   $ qemu-system-loongarch64 -machine virt -m 4G -cpu la464 \
   -smp 1 -bios QEMU_EFI.fd -kernel vmlinuz.efi -initrd ramdisk \
   -serial stdio   -monitor telnet:localhost:4495,server,nowait \
   -append "root=/dev/ram rdinit=/sbin/init console=ttyS0,115200" \
   --nographic

Changes for RFC v3:
1. Move the init mp_state to KVM_MP_STATE_RUNNABLE function into kvm.c.
2. Fix some unstandard code problems in kvm_get/set_regs_ioctl, such as 
sort loongarch to keep alphabetic ordering in meson.build, gpr[0] should
be always 0, remove unnecessary inline statement, etc.
3. Rename the counter_value variable to kvm_state_counter in cpu_env,
and add comments for it to explain the meaning.

Changes for RFC v2:
1. Mark the "Add KVM headers for loongarch" patch as a placeholder,
as we will use the update-linux-headers.sh to generate the kvm headers
when the linux loongarch KVM patch series are accepted.
2. Remove the DPRINTF macro in kvm.c and use trace events to replace
it, we add some trace functions such as trace_kvm_handle_exit,
trace_kvm_set_intr, trace_kvm_failed_get_csr, etc.
3. Remove the unused functions in kvm_stub.c and move stub function into
the suitable patch.

Tianrui Zhao (9):
  linux-headers: Add KVM headers for loongarch
  target/loongarch: Define some kvm_arch interfaces
  target/loongarch: Supplement vcpu env initial when vcpu reset
  target/loongarch: Implement kvm get/set registers
  target/loongarch: Implement kvm_arch_init function
  target/loongarch: Implement kvm_arch_init_vcpu
  target/loongarch: Implement kvm_arch_handle_exit
  target/loongarch: Implement set vcpu intr for kvm
  target/loongarch: Add loongarch kvm into meson build

 linux-headers/asm-loongarch/kvm.h |  99 ++
 linux-headers/linux/kvm.h |   9 +
 meson.build   |   3 +
 target/loongarch/cpu.c|  23 +-
 target/loongarch/cpu.h|   5 +
 target/loongarch/kvm-stub.c   |  11 +
 target/loongarch/kvm.c| 546 ++
 target/loongarch/kvm_loongarch.h  |  13 +
 target/loongarch/meson.build  |   1 +
 target/loongarch/trace-events |  15 +
 target/loongarch/trace.h  |   1 +
 11 files changed, 721 insertions(+), 5 deletions(-)
 create mode 100644 linux-headers/asm-loongarch/kvm.h
 create mode 100644 target/loongarch/kvm-stub.c
 create mode 100644 target/loongarch/kvm.c
 create mode 100644 target/loongarch/kvm_loongarch.h
 create mode 100644 target/loongarch/trace-events
 create mode 100644 target/loongarch/trace.h

-- 
2.31.1




[PATCH RFC v3 3/9] target/loongarch: Supplement vcpu env initial when vcpu reset

2023-05-05 Thread Tianrui Zhao
Supplement vcpu env initial when vcpu reset, including
init vcpu CSR_CPUID,CSR_TID to cpu->cpu_index. The two
regs will be used in kvm_get/set_csr_ioctl.

Signed-off-by: Tianrui Zhao 
---
 target/loongarch/cpu.c | 2 ++
 target/loongarch/cpu.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 97e6579f6a..d15b4b2844 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -486,10 +486,12 @@ static void loongarch_cpu_reset_hold(Object *obj)
 
 env->CSR_ESTAT = env->CSR_ESTAT & (~MAKE_64BIT_MASK(0, 2));
 env->CSR_RVACFG = FIELD_DP64(env->CSR_RVACFG, CSR_RVACFG, RBITS, 0);
+env->CSR_CPUID = cs->cpu_index;
 env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
 env->CSR_LLBCTL = FIELD_DP64(env->CSR_LLBCTL, CSR_LLBCTL, KLO, 0);
 env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0);
 env->CSR_MERRCTL = FIELD_DP64(env->CSR_MERRCTL, CSR_MERRCTL, ISMERR, 0);
+env->CSR_TID = cs->cpu_index;
 
 env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, TLB_TYPE, 2);
 env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, MTLB_ENTRY, 63);
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index e11c875188..1d9a4009b9 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -288,6 +288,7 @@ typedef struct CPUArchState {
 uint64_t CSR_PWCH;
 uint64_t CSR_STLBPS;
 uint64_t CSR_RVACFG;
+uint64_t CSR_CPUID;
 uint64_t CSR_PRCFG1;
 uint64_t CSR_PRCFG2;
 uint64_t CSR_PRCFG3;
-- 
2.31.1




[PATCH RFC v3 5/9] target/loongarch: Implement kvm_arch_init function

2023-05-05 Thread Tianrui Zhao
Implement the kvm_arch_init of loongarch, in the function, the
KVM_CAP_MP_STATE cap is checked by kvm ioctl.

Signed-off-by: Tianrui Zhao 
Reviewed-by: Richard Henderson 
---
 target/loongarch/kvm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 640fca52fa..dac65f546e 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -442,6 +442,7 @@ void kvm_arch_init_irq_routing(KVMState *s)
 
 int kvm_arch_init(MachineState *ms, KVMState *s)
 {
+cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
 return 0;
 }
 
-- 
2.31.1




[PATCH RFC v3 6/9] target/loongarch: Implement kvm_arch_init_vcpu

2023-05-05 Thread Tianrui Zhao
Implement kvm_arch_init_vcpu interface for loongarch,
in this function, we register VM change state handler.
And when VM state changes to running, the counter value
should be put into kvm to keep consistent with kvm,
and when state change to stop, counter value should be
refreshed from kvm.

Signed-off-by: Tianrui Zhao 
---
 target/loongarch/cpu.h|  2 ++
 target/loongarch/kvm.c| 23 +++
 target/loongarch/trace-events |  2 ++
 3 files changed, 27 insertions(+)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index cf3fce4577..beb070de25 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -350,6 +350,8 @@ struct ArchCPU {
 
 /* 'compatible' string for this CPU for Linux device trees */
 const char *dtb_compatible;
+/* used by KVM_REG_LOONGARCH_COUNTER ioctl to access guest time counters */
+uint64_t kvm_state_counter;
 };
 
 #define TYPE_LOONGARCH_CPU "loongarch-cpu"
diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index dac65f546e..5a07cc58c8 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -399,8 +399,31 @@ int kvm_arch_put_registers(CPUState *cs, int level)
 return ret;
 }
 
+static void kvm_loongarch_vm_stage_change(void *opaque, bool running,
+  RunState state)
+{
+int ret;
+CPUState *cs = opaque;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+
+if (running) {
+ret = kvm_larch_putq(cs, KVM_REG_LOONGARCH_COUNTER,
+ &cpu->kvm_state_counter);
+if (ret < 0) {
+trace_kvm_failed_put_counter(strerror(errno));
+}
+} else {
+ret = kvm_larch_getq(cs, KVM_REG_LOONGARCH_COUNTER,
+ &cpu->kvm_state_counter);
+if (ret < 0) {
+trace_kvm_failed_get_counter(strerror(errno));
+}
+}
+}
+
 int kvm_arch_init_vcpu(CPUState *cs)
 {
+qemu_add_vm_change_state_handler(kvm_loongarch_vm_stage_change, cs);
 return 0;
 }
 
diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events
index 67817fee67..6926bbe399 100644
--- a/target/loongarch/trace-events
+++ b/target/loongarch/trace-events
@@ -9,3 +9,5 @@ kvm_failed_get_fpu(const char *msg) "Failed to get fpu from 
KVM: %s"
 kvm_failed_put_fpu(const char *msg) "Failed to put fpu into KVM: %s"
 kvm_failed_get_mpstate(const char *msg) "Failed to get mp_state from KVM: %s"
 kvm_failed_put_mpstate(const char *msg) "Failed to put mp_state into KVM: %s"
+kvm_failed_get_counter(const char *msg) "Failed to get counter from KVM: %s"
+kvm_failed_put_counter(const char *msg) "Failed to put counter into KVM: %s"
-- 
2.31.1




[PATCH RFC v3 2/9] target/loongarch: Define some kvm_arch interfaces

2023-05-05 Thread Tianrui Zhao
Define some functions in target/loongarch/kvm.c, such as
kvm_arch_put_registers, kvm_arch_get_registers and
kvm_arch_handle_exit, etc. which are needed by kvm/kvm-all.c.
Now the most functions has no content and they will be
implemented in the next patches.

Signed-off-by: Tianrui Zhao 
Reviewed-by: Richard Henderson 
---
 target/loongarch/kvm.c | 126 +
 1 file changed, 126 insertions(+)
 create mode 100644 target/loongarch/kvm.c

diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
new file mode 100644
index 00..24327aaf71
--- /dev/null
+++ b/target/loongarch/kvm.c
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch KVM
+ *
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include 
+
+#include "qemu/timer.h"
+#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "sysemu/kvm_int.h"
+#include "hw/pci/pci.h"
+#include "exec/memattrs.h"
+#include "exec/address-spaces.h"
+#include "hw/boards.h"
+#include "hw/irq.h"
+#include "qemu/log.h"
+#include "hw/loader.h"
+#include "migration/migration.h"
+#include "sysemu/runstate.h"
+#include "cpu-csr.h"
+#include "kvm_loongarch.h"
+
+static bool cap_has_mp_state;
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+KVM_CAP_LAST_INFO
+};
+
+int kvm_arch_get_registers(CPUState *cs)
+{
+return 0;
+}
+int kvm_arch_put_registers(CPUState *cs, int level)
+{
+return 0;
+}
+
+int kvm_arch_init_vcpu(CPUState *cs)
+{
+return 0;
+}
+
+int kvm_arch_destroy_vcpu(CPUState *cs)
+{
+return 0;
+}
+
+unsigned long kvm_arch_vcpu_id(CPUState *cs)
+{
+return cs->cpu_index;
+}
+
+int kvm_arch_release_virq_post(int virq)
+{
+return 0;
+}
+
+int kvm_arch_msi_data_to_gsi(uint32_t data)
+{
+abort();
+}
+
+int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
+ uint64_t address, uint32_t data, PCIDevice *dev)
+{
+return 0;
+}
+
+int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
+int vector, PCIDevice *dev)
+{
+return 0;
+}
+
+void kvm_arch_init_irq_routing(KVMState *s)
+{
+}
+
+int kvm_arch_init(MachineState *ms, KVMState *s)
+{
+return 0;
+}
+
+int kvm_arch_irqchip_create(KVMState *s)
+{
+return 0;
+}
+
+void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
+{
+}
+
+MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
+{
+return MEMTXATTRS_UNSPECIFIED;
+}
+
+int kvm_arch_process_async_events(CPUState *cs)
+{
+return cs->halted;
+}
+
+bool kvm_arch_stop_on_emulation_error(CPUState *cs)
+{
+return true;
+}
+
+bool kvm_arch_cpu_check_are_resettable(void)
+{
+return true;
+}
+
+int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
+{
+return 0;
+}
+
+void kvm_arch_accel_class_init(ObjectClass *oc)
+{
+}
-- 
2.31.1




Re: [PATCH v4 36/57] tcg/loongarch64: Assert the host supports unaligned accesses

2023-05-05 Thread Song Gao

Hi,

在 2023/5/5 下午9:24, WANG Xuerui 写道:

Hi,

On 2023/5/3 15:06, Richard Henderson wrote:

This should be true of all server class loongarch64.

And desktop-class (i.e. all Loongson-3 series).


Signed-off-by: Richard Henderson 
---
  tcg/loongarch64/tcg-target.c.inc | 6 ++
  1 file changed, 6 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc 
b/tcg/loongarch64/tcg-target.c.inc

index e651ec5c71..ccc13ffdb4 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -30,6 +30,7 @@
   */
    #include "../tcg-ldst.c.inc"
+#include 
    #ifdef CONFIG_DEBUG_TCG
  static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
@@ -1674,6 +1675,11 @@ static void 
tcg_target_qemu_prologue(TCGContext *s)

    static void tcg_target_init(TCGContext *s)
  {
+    unsigned long hwcap = qemu_getauxval(AT_HWCAP);
+
+    /* All server class loongarch have UAL; only embedded do not. */
+    assert(hwcap & HWCAP_LOONGARCH_UAL);
+
It is a bit worrying that a future SoC (the octa-core Loongson 2K3000) 
might get used for light desktop use cases (e.g. laptops) where QEMU 
is arguably relevant, but it's currently unclear whether its LA364 
micro-architecture will have UAL. The Loongson folks may have more to 
share.

'LA364' support UAL.

Thanks.
Song Gao




Re: [PULL 00/45] loongarch-to-apply queue

2023-05-05 Thread Song Gao




在 2023/5/6 上午2:16, Richard Henderson 写道:

On 5/5/23 03:27, Song Gao wrote:
The following changes since commit 
f6b761bdbd8ba63cee7428d52fb6b46e4224ddab:


   Merge tag 'qga-pull-2023-05-04' 
ofhttps://github.com/kostyanf14/qemu  into staging (2023-05-04 
12:08:00 +0100)


are available in the Git repository at:

   https://gitlab.com/gaosong/qemu.git tags/pull-loongarch-20230505

for you to fetch changes up to 9dd207d409cc2eb08fe52965b9d1fd4a12a82bd5:

   hw/intc: don't use target_ulong for LoongArch ipi (2023-05-05 
10:00:47 +0800)



Add LoongArch LSX instructions.


This has CI failures:

https://gitlab.com/qemu-project/qemu/-/pipelines/858609469/failures

Importantly, it does not build on 32-bit hosts:

https://gitlab.com/qemu-project/qemu/-/jobs/4235054589#L2631

../target/loongarch/lsx_helper.c:1013:17: error: incompatible types 
when assigning to type 'int64_t' {aka 'long long int'} from type 'Int128'

 1013 | temp.D(0) = int128_urshift(Vj->Q(0), imm % 128);
  | ^~


Sorry about this,   I will fix it,  and test on 32-bit hosts.

Thanks.
Song Gao




Re: [PATCH 0/1] Updated: Ensure PV ring is drained on disconenct

2023-05-05 Thread Stefano Stabellini
On Thu, 20 Apr 2023, Mark Syms wrote:
> Updated patch to address intermittent SIGSEGV on domain disconnect/shutdown.
> 
> Mark Syms (1):
>   Ensure the PV ring is drained on disconnect
> 
>  hw/block/dataplane/xen-block.c | 31 +--
>  1 file changed, 25 insertions(+), 6 deletions(-)
> 
> -- 
> 2.40.0
> 
> >From 21724baa15a72534d98aa2653e9ec39e83559319 Mon Sep 17 00:00:00 2001
> From: Mark Syms 
> Date: Thu, 20 Apr 2023 11:08:34 +0100
> Subject: [PATCH 1/1] Ensure the PV ring is drained on disconnect
> 
> Also ensure all pending AIO is complete.

Hi Mark, can you please add more info on the problem you are trying to
solve? Also add any stacktrace if you get any due to this error.


> Signed-off-by: Mark Syms 
> ---
>  hw/block/dataplane/xen-block.c | 31 +--
>  1 file changed, 25 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
> index 734da42ea7..d9da4090bf 100644
> --- a/hw/block/dataplane/xen-block.c
> +++ b/hw/block/dataplane/xen-block.c
> @@ -523,6 +523,10 @@ static bool xen_block_handle_requests(XenBlockDataPlane 
> *dataplane)
>  
>  dataplane->more_work = 0;
>  
> +if (dataplane->sring == 0) {
> +return done_something;

done_something cannot be changed by now, so I would just do

return false;


> +}
> +
>  rc = dataplane->rings.common.req_cons;
>  rp = dataplane->rings.common.sring->req_prod;
>  xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
> @@ -666,14 +670,35 @@ void xen_block_dataplane_destroy(XenBlockDataPlane 
> *dataplane)
>  void xen_block_dataplane_stop(XenBlockDataPlane *dataplane)
>  {
>  XenDevice *xendev;
> +XenBlockRequest *request, *next;
>  
>  if (!dataplane) {
>  return;
>  }
>  
> +/* We're about to drain the ring. We can cancel the scheduling of any
> + * bottom half now */
> +qemu_bh_cancel(dataplane->bh);
> +
> +/* Ensure we have drained the ring */
> +aio_context_acquire(dataplane->ctx);

Would it make sense to move the 2 loops below under the existing
aio_context_acquire also below?


> +do {
> +xen_block_handle_requests(dataplane);
> +} while (dataplane->more_work);
> +aio_context_release(dataplane->ctx);
> +
> +/* Now ensure that all inflight requests are complete */
> +while (!QLIST_EMPTY(&dataplane->inflight)) {
> +QLIST_FOREACH_SAFE(request, &dataplane->inflight, list, next) {
> +blk_aio_flush(request->dataplane->blk, xen_block_complete_aio,
> +request);
> +}
> +}

especially because I would think that blk_aio_flush needs to be called
with aio_context_acquired ?



>  xendev = dataplane->xendev;
>  
>  aio_context_acquire(dataplane->ctx);
> +

move the new code here


>  if (dataplane->event_channel) {
>  /* Only reason for failure is a NULL channel */
>  xen_device_set_event_channel_context(xendev, 
> dataplane->event_channel,
> @@ -684,12 +709,6 @@ void xen_block_dataplane_stop(XenBlockDataPlane 
> *dataplane)
>  blk_set_aio_context(dataplane->blk, qemu_get_aio_context(), 
> &error_abort);
>  aio_context_release(dataplane->ctx);
>  
> -/*
> - * Now that the context has been moved onto the main thread, cancel
> - * further processing.
> - */
> -qemu_bh_cancel(dataplane->bh);
> -
>  if (dataplane->event_channel) {
>  Error *local_err = NULL;
>  
> -- 
> 2.40.0
> 



Re: [PATCH] 9pfs/xen: Fix segfault on shutdown

2023-05-05 Thread Stefano Stabellini
On Tue, 2 May 2023, Jason Andryuk wrote:
> xen_9pfs_free can't use gnttabdev since it is already closed and NULL-ed
> out when free is called.  Do the teardown in _disconnect().  This
> matches the setup done in _connect().
> 
> trace-events are also added for the XenDevOps functions.
> 
> Signed-off-by: Jason Andryuk 
> ---
>  hw/9pfs/trace-events |  5 +
>  hw/9pfs/xen-9p-backend.c | 36 +++-
>  2 files changed, 28 insertions(+), 13 deletions(-)
> 
> diff --git a/hw/9pfs/trace-events b/hw/9pfs/trace-events
> index 6c77966c0b..7b5b0b5a48 100644
> --- a/hw/9pfs/trace-events
> +++ b/hw/9pfs/trace-events
> @@ -48,3 +48,8 @@ v9fs_readlink(uint16_t tag, uint8_t id, int32_t fid) "tag 
> %d id %d fid %d"
>  v9fs_readlink_return(uint16_t tag, uint8_t id, char* target) "tag %d id %d 
> name %s"
>  v9fs_setattr(uint16_t tag, uint8_t id, int32_t fid, int32_t valid, int32_t 
> mode, int32_t uid, int32_t gid, int64_t size, int64_t atime_sec, int64_t 
> mtime_sec) "tag %u id %u fid %d iattr={valid %d mode %d uid %d gid %d size 
> %"PRId64" atime=%"PRId64" mtime=%"PRId64" }"
>  v9fs_setattr_return(uint16_t tag, uint8_t id) "tag %u id %u"
> +
> +xen_9pfs_alloc(char *name) "name %s"
> +xen_9pfs_connect(char *name) "name %s"
> +xen_9pfs_disconnect(char *name) "name %s"
> +xen_9pfs_free(char *name) "name %s"
> diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
> index 0e266c552b..c646a0b3d1 100644
> --- a/hw/9pfs/xen-9p-backend.c
> +++ b/hw/9pfs/xen-9p-backend.c
> @@ -25,6 +25,8 @@
>  #include "qemu/iov.h"
>  #include "fsdev/qemu-fsdev.h"
>  
> +#include "trace.h"
> +
>  #define VERSIONS "1"
>  #define MAX_RINGS 8
>  #define MAX_RING_ORDER 9
> @@ -337,6 +339,8 @@ static void xen_9pfs_disconnect(struct XenLegacyDevice 
> *xendev)
>  Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
>  int i;
>  
> +trace_xen_9pfs_disconnect(xendev->name);
> +
>  for (i = 0; i < xen_9pdev->num_rings; i++) {
>  if (xen_9pdev->rings[i].evtchndev != NULL) {
>  
> qemu_set_fd_handler(qemu_xen_evtchn_fd(xen_9pdev->rings[i].evtchndev),
> @@ -345,40 +349,42 @@ static void xen_9pfs_disconnect(struct XenLegacyDevice 
> *xendev)
> xen_9pdev->rings[i].local_port);
>  xen_9pdev->rings[i].evtchndev = NULL;
>  }
> -}
> -}
> -
> -static int xen_9pfs_free(struct XenLegacyDevice *xendev)
> -{
> -Xen9pfsDev *xen_9pdev = container_of(xendev, Xen9pfsDev, xendev);
> -int i;
> -
> -if (xen_9pdev->rings[0].evtchndev != NULL) {
> -xen_9pfs_disconnect(xendev);
> -}
> -
> -for (i = 0; i < xen_9pdev->num_rings; i++) {
>  if (xen_9pdev->rings[i].data != NULL) {
>  xen_be_unmap_grant_refs(&xen_9pdev->xendev,
>  xen_9pdev->rings[i].data,
>  xen_9pdev->rings[i].intf->ref,
>  (1 << xen_9pdev->rings[i].ring_order));
> +xen_9pdev->rings[i].data = NULL;
>  }
>  if (xen_9pdev->rings[i].intf != NULL) {
>  xen_be_unmap_grant_ref(&xen_9pdev->xendev,
> xen_9pdev->rings[i].intf,
> xen_9pdev->rings[i].ref);
> +xen_9pdev->rings[i].intf = NULL;
>  }
>  if (xen_9pdev->rings[i].bh != NULL) {
>  qemu_bh_delete(xen_9pdev->rings[i].bh);
> +xen_9pdev->rings[i].bh = NULL;
>  }
>  }
>  
>  g_free(xen_9pdev->id);
> +xen_9pdev->id = NULL;
>  g_free(xen_9pdev->tag);
> +xen_9pdev->tag = NULL;
>  g_free(xen_9pdev->path);
> +xen_9pdev->path = NULL;
>  g_free(xen_9pdev->security_model);
> +xen_9pdev->security_model = NULL;
>  g_free(xen_9pdev->rings);
> +xen_9pdev->rings = NULL;
> +return;

NIT: this return is redudant.

Aside from that:

Reviewed-by: Stefano Stabellini 


> +}
> +
> +static int xen_9pfs_free(struct XenLegacyDevice *xendev)
> +{
> +trace_xen_9pfs_free(xendev->name);
> +
>  return 0;
>  }
>  
> @@ -390,6 +396,8 @@ static int xen_9pfs_connect(struct XenLegacyDevice 
> *xendev)
>  V9fsState *s = &xen_9pdev->state;
>  QemuOpts *fsdev;
>  
> +trace_xen_9pfs_connect(xendev->name);
> +
>  if (xenstore_read_fe_int(&xen_9pdev->xendev, "num-rings",
>   &xen_9pdev->num_rings) == -1 ||
>  xen_9pdev->num_rings > MAX_RINGS || xen_9pdev->num_rings < 1) {
> @@ -499,6 +507,8 @@ out:
>  
>  static void xen_9pfs_alloc(struct XenLegacyDevice *xendev)
>  {
> +trace_xen_9pfs_alloc(xendev->name);
> +
>  xenstore_write_be_str(xendev, "versions", VERSIONS);
>  xenstore_write_be_int(xendev, "max-rings", MAX_RINGS);
>  xenstore_write_be_int(xendev, "max-ring-page-order", MAX_RING_ORDER);
> -- 
> 2.40.1
> 



[PATCH v2] vfio/pci: Static Resizable BAR capability

2023-05-05 Thread Alex Williamson
The PCI Resizable BAR (ReBAR) capability is currently hidden from the
VM because the protocol for interacting with the capability does not
support a mechanism for the device to reject an advertised supported
BAR size.  However, when assigned to a VM, the act of resizing the
BAR requires adjustment of host resources for the device, which
absolutely can fail.  Linux does not currently allow us to reserve
resources for the device independent of the current usage.

The only writable field within the ReBAR capability is the BAR Size
register.  The PCIe spec indicates that when written, the device
should immediately begin to operate with the provided BAR size.  The
spec however also notes that software must only write values
corresponding to supported sizes as indicated in the capability and
control registers.  Writing unsupported sizes produces undefined
results.  Therefore, if the hypervisor were to virtualize the
capability and control registers such that the current size is the
only indicated available size, then a write of anything other than
the current size falls into the category of undefined behavior,
where we can essentially expose the modified ReBAR capability as
read-only.

This may seem pointless, but users have reported that virtualizing
the capability in this way not only allows guest software to expose
related features as available (even if only cosmetic), but in some
scenarios can resolve guest driver issues.  Additionally, no
regressions in behavior have been reported for this change.

A caveat here is that the PCIe spec requires for compatibility that
devices report support for a size in the range of 1MB to 512GB,
therefore if the current BAR size falls outside that range we revert
to hiding the capability.

Signed-off-by: Alex Williamson 
---
v2:
 - Add spec reference
 - Use PCI_REBAR_CAP_SIZES to check sizes in range
 - Try to clarify capability bit generation
 - Rename s/bars/nbar/ to match #defines
 - More complete masking of NBAR value

 hw/vfio/pci.c | 54 ++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index cf27f28936cb..3ab849767a92 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2066,6 +2066,54 @@ static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t 
pos, Error **errp)
 return 0;
 }
 
+static int vfio_setup_rebar_ecap(VFIOPCIDevice *vdev, uint16_t pos)
+{
+uint32_t ctrl;
+int i, nbar;
+
+ctrl = pci_get_long(vdev->pdev.config + pos + PCI_REBAR_CTRL);
+nbar = (ctrl & PCI_REBAR_CTRL_NBAR_MASK) >> PCI_REBAR_CTRL_NBAR_SHIFT;
+
+for (i = 0; i < nbar; i++) {
+uint32_t cap;
+int size;
+
+ctrl = pci_get_long(vdev->pdev.config + pos + PCI_REBAR_CTRL + (i * 
8));
+size = (ctrl & PCI_REBAR_CTRL_BAR_SIZE) >> PCI_REBAR_CTRL_BAR_SHIFT;
+
+/* The cap register reports sizes 1MB to 127TB, with 4 reserved bits */
+cap = size <= 27 ? 1U << (size + 4) : 0;
+
+/*
+ * The PCIe spec (v6.0.1, 7.8.6) requires HW to support at least one
+ * size in the range 1MB to 512GB.  We intend to mask all sizes except
+ * the one currently enabled in the size field, therefore if it's
+ * outside the range, hide the whole capability as this virtualization
+ * trick won't work.  If >512GB resizable BARs start to appear, we
+ * might need an opt-in or reservation scheme in the kernel.
+ */
+if (!(cap & PCI_REBAR_CAP_SIZES)) {
+return -EINVAL;
+}
+
+/* Hide all sizes reported in the ctrl reg per above requirement. */
+ctrl &= (PCI_REBAR_CTRL_BAR_SIZE |
+ PCI_REBAR_CTRL_NBAR_MASK |
+ PCI_REBAR_CTRL_BAR_IDX);
+
+/*
+ * The BAR size field is RW, however we've mangled the capability
+ * register such that we only report a single size, ie. the current
+ * BAR size.  A write of an unsupported value is undefined, therefore
+ * the register field is essentially RO.
+ */
+vfio_add_emulated_long(vdev, pos + PCI_REBAR_CAP + (i * 8), cap, ~0);
+vfio_add_emulated_long(vdev, pos + PCI_REBAR_CTRL + (i * 8), ctrl, ~0);
+}
+
+return 0;
+}
+
 static void vfio_add_ext_cap(VFIOPCIDevice *vdev)
 {
 PCIDevice *pdev = &vdev->pdev;
@@ -2139,9 +2187,13 @@ static void vfio_add_ext_cap(VFIOPCIDevice *vdev)
 case 0: /* kernel masked capability */
 case PCI_EXT_CAP_ID_SRIOV: /* Read-only VF BARs confuse OVMF */
 case PCI_EXT_CAP_ID_ARI: /* XXX Needs next function virtualization */
-case PCI_EXT_CAP_ID_REBAR: /* Can't expose read-only */
 trace_vfio_add_ext_cap_dropped(vdev->vbasedev.name, cap_id, next);
 break;
+case PCI_EXT_CAP_ID_REBAR:
+if (!vfio_setup_rebar_ecap(vdev, next)) {
+pcie_add_capability(pdev, cap_id, cap_ver, next, size);
+}
+break;

Question: PCIe P2P Guidance

2023-05-05 Thread Thomas Barrett
Hi,

I have been struggling for a few months now with achieving full bandwidth
PCIe P2P in a qemu virtual machine. I am working with a number of PCIe
endpoints (NVIDIA A100 GPUs and Mellanox ConnectX 7 Infiniband NICs) behind
a PCIe switch. In all configurations I have tried, P2P traffic gets router
back to the root complex. Does. Anyone have guidance on whether full
bandwidth PCIe P2P is even supported by qemu?

Through my research, I have found have found two main approaches to solve
this.

[ 1 ] ATS came up frequently In my research. Unfortunetaly, I do not
believe that all of my PCIe endpoints support the use of ATS for P2P
traffic. at the very least, toggling the DirectTrans flag on my PCI switch
didn’t have any affect on bandwidth on either the host or the guest. I’m
think that this might be a dead end.

[ 2 ] Another potential option is to disable ACS on the PCIe switch and
pass all devices on the same switch to a virtual machine. Based on
everything that I have read, this “should” work. When toggling the
RequestRedir flag on the PCIe switch using “setpci”, P2P bandwidth
increased and decreased as expected on the host. However, the P2P bandwidth
did not increase or decrease in the guest.

I can’t really explain the behavior that I am seeing in approach [ 2 ].
Should disabling the RequestRedir flag on a PCIe switch enable P2P traffic
between different IOMMU groups? If not, why?

Best,
Thomas

Disclaimer

The information contained in this communication from the sender is 
confidential. It is intended solely for use by the recipient and others 
authorized to receive it. If you are not the recipient, you are hereby notified 
that any disclosure, copying, distribution or taking action in relation of the 
contents of this information is strictly prohibited and may be unlawful.

This email has been scanned for viruses and malware, and may have been 
automatically archived by Mimecast, a leader in email security and cyber 
resilience. Mimecast integrates email defenses with brand protection, security 
awareness training, web security, compliance and other essential capabilities. 
Mimecast helps protect large and small organizations from malicious activity, 
human error and technology failure; and to lead the movement toward building a 
more resilient world. To find out more, visit our website.


Re: [PATCH v3 0/3] ACPI: i386: bump MADT to revision 5

2023-05-05 Thread Eric DeVolder

Thoughts?
eric

On 4/21/23 16:48, Eric DeVolder wrote:

The following Linux kernel change broke CPU hotplug for MADT revision
less than 5.

  e2869bd7af60 ("x86/acpi/boot: Do not register processors that cannot be onlined 
for x2APIC")

Discussion on this topic can be located here:

  
https://lore.kernel.org/linux-acpi/20230327191026.3454-1-eric.devol...@oracle.com/T/#t

which resulted in the following fixes Linux in 6.3-rc5:

  a74fabfbd1b7: ("x86/ACPI/boot: Use FADT version to check support for online 
capable")
  fed8d8773b8e: ("x86/acpi/boot: Correct acpi_is_processor_usable() check")

However, as part of the investigation into resolving this breakage, I
learned that i386 QEMU reports revision 1, while technically it
generates revision 3. Aarch64 generates and reports revision 4.

ACPI 6.3 bumps MADT revision to 5 as it introduces an Online Capable
flag that the above Linux patch utilizes to denote hot pluggable CPUs.

So in order to bump MADT to the current revision of 5, need to
validate that all MADT table changes between 1 and 5 are present
in QEMU.

Below is a table summarizing the changes to the MADT. This information
gleamed from the ACPI specs on uefi.org.

ACPIMADTWhat
Version Version
1.0 MADT not present
2.0 1   Section 5.2.10.4
3.0 2   Section 5.2.11.4
  5.2.11.13 Local SAPIC Structure added two new fields:
   ACPI Processor UID Value
   ACPI Processor UID String
  5.2.10.14 Platform Interrupt Sources Structure:
   Reserved changed to Platform Interrupt Sources Flags
3.0b2   Section 5.2.11.4
  Added a section describing guidelines for the ordering of
  processors in the MADT to support proper boot processor
  and multi-threaded logical processor operation.
4.0 3   Section 5.2.12
  Adds Processor Local x2APIC structure type 9
  Adds Local x2APIC NMI structure type 0xA
5.0 3   Section 5.2.12
6.0 3   Section 5.2.12
6.0a4   Section 5.2.12
  Adds ARM GIC structure types 0xB-0xF
6.2a45  Section 5.2.12   <--- version 45, is indeed accurate!
6.2b5   Section 5.2.12
  GIC ITS last Reserved offset changed to 16 from 20 (typo)
6.3 5   Section 5.2.12
  Adds Local APIC Flags Online Capable!
  Adds GICC SPE Overflow Interrupt field
6.4 5   Section 5.2.12
  Adds Multiprocessor Wakeup Structure type 0x10
  (change notes says structure previously misplaced?)
6.5 5   Section 5.2.12

For the MADT revision change 1 -> 2, the spec has a change to the
SAPIC structure. In general, QEMU does not generate/support SAPIC.
So the QEMU i386 MADT revision can safely be moved to 2.

For the MADT revision change 2 -> 3, the spec adds Local x2APIC
structures. QEMU has long supported x2apic ACPI structures. A simple
search of x2apic within QEMU source and hw/i386/acpi-common.c
specifically reveals this. So the QEMU i386 MADT revision can safely
be moved to 3.

For the MADT revision change 3 -> 4, the spec adds support for the ARM
GIC structures. QEMU ARM does in fact generate and report revision 4.
As these will not be used by i386 QEMU, so then the QEMU i386 MADT
revision can safely be moved to 4 as well.

Now for the MADT revision change 4 -> 5, the spec adds the Online
Capable flag to the Local APIC structure, and the ARM GICC SPE
Overflow Interrupt field.

For i386, the ARM SPE is not applicable.

For the i386 Local APIC flag Online Capable, the spec has certain rules
about this value. And in particuar setting this value now explicitly
indicates a hotpluggable CPU.

So this patch makes the needed changes to move i386 MADT to
revision 5.

Without these changes, the information below shows "how" CPU hotplug
breaks with the current upstream Linux kernel 6.3.  For example, a Linux
guest started with:

  qemu-system-x86_64 -smp 30,maxcpus=32 ...

and then attempting to hotplug a CPU:

   (QEMU) device_add id=cpu30 driver=host-x86_64-cpu socket-id=0 core-id=30 
thread-id=0

fails with the following:

   APIC: NR_CPUS/possible_cpus limit of 30 reached. Processor 30/0x.
   ACPI: Unable to map lapic to logical cpu number
   acpi LNXCPU:1e: Enumeration failure

   # dmesg | grep smpboot
   smpboot: Allowing 30 CPUs, 0 hotplug CPUs
   smpboot: CPU0: Intel(R) Xeon(R) CPU D-1533 @ 2.10GHz (family: 0x)
   smpboot: Max logical packages: 1
   smpboot: Total of 30 processors activated (125708.76 BogoMIPS)

   # iasl -d /sys/firmware/tables/acpi/APIC
   [000h    4]Signature : "APIC"[Multiple APIC 
Descript
   [004h 0004   4] Table Length : 0170
   [008h 0008   1] Revision : 01  <=
   [009h 0009   1] Checksum : 9C
   [00Ah 0010   6]   Oem ID : "BOCHS "
   

[PULL 19/42] tcg/i386: Rationalize args to tcg_out_qemu_{ld,st}

2023-05-05 Thread Richard Henderson
Interpret the variable argument placement in the caller.  Pass data_type
instead of is64 -- there are several places where we already convert back
from bool to type.  Clean things up by using type throughout.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/i386/tcg-target.c.inc | 111 +-
 1 file changed, 50 insertions(+), 61 deletions(-)

diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index caf91a3151..cfa2349b03 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -1884,8 +1884,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg 
addrlo, TCGReg addrhi,
  * Record the context of a call to the out of line helper code for the slow 
path
  * for a load or store, so that we can later generate the correct helper code
  */
-static void add_qemu_ldst_label(TCGContext *s, bool is_ld, bool is_64,
-MemOpIdx oi,
+static void add_qemu_ldst_label(TCGContext *s, bool is_ld,
+TCGType type, MemOpIdx oi,
 TCGReg datalo, TCGReg datahi,
 TCGReg addrlo, TCGReg addrhi,
 tcg_insn_unit *raddr,
@@ -1895,7 +1895,7 @@ static void add_qemu_ldst_label(TCGContext *s, bool 
is_ld, bool is_64,
 
 label->is_ld = is_ld;
 label->oi = oi;
-label->type = is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
+label->type = type;
 label->datalo_reg = datalo;
 label->datahi_reg = datahi;
 label->addrlo_reg = addrlo;
@@ -2152,11 +2152,10 @@ static inline int setup_guest_base_seg(void)
 
 static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
TCGReg base, int index, intptr_t ofs,
-   int seg, bool is64, MemOp memop)
+   int seg, TCGType type, MemOp memop)
 {
-TCGType type = is64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
 bool use_movbe = false;
-int rexw = is64 * P_REXW;
+int rexw = (type == TCG_TYPE_I32 ? 0 : P_REXW);
 int movop = OPC_MOVL_GvEv;
 
 /* Do big-endian loads with movbe.  */
@@ -2246,50 +2245,34 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, 
TCGReg datalo, TCGReg datahi,
 }
 }
 
-/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
-   EAX. It will be useful once fixed registers globals are less
-   common. */
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
+static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi,
+TCGReg addrlo, TCGReg addrhi,
+MemOpIdx oi, TCGType data_type)
 {
-TCGReg datalo, datahi, addrlo;
-TCGReg addrhi __attribute__((unused));
-MemOpIdx oi;
-MemOp opc;
+MemOp opc = get_memop(oi);
+
 #if defined(CONFIG_SOFTMMU)
-int mem_index;
 tcg_insn_unit *label_ptr[2];
-#else
-unsigned a_bits;
-#endif
 
-datalo = *args++;
-datahi = (TCG_TARGET_REG_BITS == 32 && is64 ? *args++ : 0);
-addrlo = *args++;
-addrhi = (TARGET_LONG_BITS > TCG_TARGET_REG_BITS ? *args++ : 0);
-oi = *args++;
-opc = get_memop(oi);
-
-#if defined(CONFIG_SOFTMMU)
-mem_index = get_mmuidx(oi);
-
-tcg_out_tlb_load(s, addrlo, addrhi, mem_index, opc,
+tcg_out_tlb_load(s, addrlo, addrhi, get_mmuidx(oi), opc,
  label_ptr, offsetof(CPUTLBEntry, addr_read));
 
 /* TLB Hit.  */
-tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, -1, 0, 0, is64, opc);
+tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1,
+   -1, 0, 0, data_type, opc);
 
 /* Record the current context of a load into ldst label */
-add_qemu_ldst_label(s, true, is64, oi, datalo, datahi, addrlo, addrhi,
-s->code_ptr, label_ptr);
+add_qemu_ldst_label(s, true, data_type, oi, datalo, datahi,
+addrlo, addrhi, s->code_ptr, label_ptr);
 #else
-a_bits = get_alignment_bits(opc);
+unsigned a_bits = get_alignment_bits(opc);
 if (a_bits) {
 tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits);
 }
 
 tcg_out_qemu_ld_direct(s, datalo, datahi, addrlo, x86_guest_base_index,
x86_guest_base_offset, x86_guest_base_seg,
-   is64, opc);
+   data_type, opc);
 #endif
 }
 
@@ -2345,40 +2328,26 @@ static void tcg_out_qemu_st_direct(TCGContext *s, 
TCGReg datalo, TCGReg datahi,
 }
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
+static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi,
+TCGReg addrlo, TCGReg addrhi,
+MemOpIdx oi, TCGType data_type)
 {
-TCGReg datalo, datahi, addrlo;
-TCGReg addrhi __attribute__((unused));
-MemOpIdx oi;
-MemOp opc;
+MemOp opc = get_memo

[PULL 30/42] tcg/mips: Rationalize args to tcg_out_qemu_{ld,st}

2023-05-05 Thread Richard Henderson
Interpret the variable argument placement in the caller.  There are
several places where we already convert back from bool to type.
Clean things up by using type throughout.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c.inc | 186 +++---
 1 file changed, 95 insertions(+), 91 deletions(-)

diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index a83ebe8729..ef8350e9cd 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -1479,7 +1479,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
 #endif /* SOFTMMU */
 
 static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
-   TCGReg base, MemOp opc, bool is_64)
+   TCGReg base, MemOp opc, TCGType type)
 {
 switch (opc & (MO_SSIZE | MO_BSWAP)) {
 case MO_UB:
@@ -1503,7 +1503,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg 
lo, TCGReg hi,
 tcg_out_opc_imm(s, OPC_LH, lo, base, 0);
 break;
 case MO_UL | MO_BSWAP:
-if (TCG_TARGET_REG_BITS == 64 && is_64) {
+if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64) {
 if (use_mips32r2_instructions) {
 tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
 tcg_out_bswap32(s, lo, lo, TCG_BSWAP_IZ | TCG_BSWAP_OZ);
@@ -1528,7 +1528,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg 
lo, TCGReg hi,
 }
 break;
 case MO_UL:
-if (TCG_TARGET_REG_BITS == 64 && is_64) {
+if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64) {
 tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
 break;
 }
@@ -1583,7 +1583,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg 
lo, TCGReg hi,
 }
 
 static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
-TCGReg base, MemOp opc, bool is_64)
+TCGReg base, MemOp opc, TCGType type)
 {
 const MIPSInsn lw1 = MIPS_BE ? OPC_LWL : OPC_LWR;
 const MIPSInsn lw2 = MIPS_BE ? OPC_LWR : OPC_LWL;
@@ -1623,7 +1623,7 @@ static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg 
lo, TCGReg hi,
 case MO_UL:
 tcg_out_opc_imm(s, lw1, lo, base, 0);
 tcg_out_opc_imm(s, lw2, lo, base, 3);
-if (TCG_TARGET_REG_BITS == 64 && is_64 && !sgn) {
+if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64 && !sgn) {
 tcg_out_ext32u(s, lo, lo);
 }
 break;
@@ -1634,18 +1634,18 @@ static void tcg_out_qemu_ld_unalign(TCGContext *s, 
TCGReg lo, TCGReg hi,
 tcg_out_opc_imm(s, lw1, lo, base, 0);
 tcg_out_opc_imm(s, lw2, lo, base, 3);
 tcg_out_bswap32(s, lo, lo,
-TCG_TARGET_REG_BITS == 64 && is_64
+TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64
 ? (sgn ? TCG_BSWAP_OS : TCG_BSWAP_OZ) : 0);
 } else {
 const tcg_insn_unit *subr =
-(TCG_TARGET_REG_BITS == 64 && is_64 && !sgn
+(TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64 && !sgn
  ? bswap32u_addr : bswap32_addr);
 
 tcg_out_opc_imm(s, lw1, TCG_TMP0, base, 0);
 tcg_out_bswap_subr(s, subr);
 /* delay slot */
 tcg_out_opc_imm(s, lw2, TCG_TMP0, base, 3);
-tcg_out_mov(s, is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32, lo, TCG_TMP3);
+tcg_out_mov(s, type, lo, TCG_TMP3);
 }
 break;
 
@@ -1702,68 +1702,59 @@ static void tcg_out_qemu_ld_unalign(TCGContext *s, 
TCGReg lo, TCGReg hi,
 }
 }
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
+static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi,
+TCGReg addrlo, TCGReg addrhi,
+MemOpIdx oi, TCGType data_type)
 {
-TCGReg addr_regl, addr_regh __attribute__((unused));
-TCGReg data_regl, data_regh;
-MemOpIdx oi;
-MemOp opc;
-#if defined(CONFIG_SOFTMMU)
-tcg_insn_unit *label_ptr[2];
-#else
-#endif
-unsigned a_bits, s_bits;
-TCGReg base = TCG_REG_A0;
-
-data_regl = *args++;
-data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
-addr_regl = *args++;
-addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
-oi = *args++;
-opc = get_memop(oi);
-a_bits = get_alignment_bits(opc);
-s_bits = opc & MO_SIZE;
+MemOp opc = get_memop(oi);
+unsigned a_bits = get_alignment_bits(opc);
+unsigned s_bits = opc & MO_SIZE;
+TCGReg base;
 
 /*
  * R6 removes the left/right instructions but requires the
  * system to support misaligned memory accesses.
  */
 #if defined(CONFIG_SOFTMMU)
-tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 1);
+

[PULL 41/42] tcg: Introduce arg_slot_stk_ofs

2023-05-05 Thread Richard Henderson
Unify all computation of argument stack offset in one function.
This requires that we adjust ref_slot to be in the same units,
by adding max_reg_slots during init_call_layout.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/tcg.c | 29 +
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index fa28db0188..057423c121 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -816,6 +816,15 @@ static inline bool arg_slot_reg_p(unsigned arg_slot)
 return arg_slot < nreg;
 }
 
+static inline int arg_slot_stk_ofs(unsigned arg_slot)
+{
+unsigned max = TCG_STATIC_CALL_ARGS_SIZE / sizeof(tcg_target_long);
+unsigned stk_slot = arg_slot - ARRAY_SIZE(tcg_target_call_iarg_regs);
+
+tcg_debug_assert(stk_slot < max);
+return TCG_TARGET_CALL_STACK_OFFSET + stk_slot * sizeof(tcg_target_long);
+}
+
 typedef struct TCGCumulativeArgs {
 int arg_idx;/* tcg_gen_callN args[] */
 int info_in_idx;/* TCGHelperInfo in[] */
@@ -1055,6 +1064,7 @@ static void init_call_layout(TCGHelperInfo *info)
 }
 }
 assert(ref_base + cum.ref_slot <= max_stk_slots);
+ref_base += max_reg_slots;
 
 if (ref_base != 0) {
 for (int i = cum.info_in_idx - 1; i >= 0; --i) {
@@ -4826,7 +4836,7 @@ static void load_arg_reg(TCGContext *s, TCGReg reg, 
TCGTemp *ts,
 }
 }
 
-static void load_arg_stk(TCGContext *s, int stk_slot, TCGTemp *ts,
+static void load_arg_stk(TCGContext *s, unsigned arg_slot, TCGTemp *ts,
  TCGRegSet allocated_regs)
 {
 /*
@@ -4836,8 +4846,7 @@ static void load_arg_stk(TCGContext *s, int stk_slot, 
TCGTemp *ts,
  */
 temp_load(s, ts, tcg_target_available_regs[ts->type], allocated_regs, 0);
 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK,
-   TCG_TARGET_CALL_STACK_OFFSET +
-   stk_slot * sizeof(tcg_target_long));
+   arg_slot_stk_ofs(arg_slot));
 }
 
 static void load_arg_normal(TCGContext *s, const TCGCallArgumentLoc *l,
@@ -4848,18 +4857,16 @@ static void load_arg_normal(TCGContext *s, const 
TCGCallArgumentLoc *l,
 load_arg_reg(s, reg, ts, *allocated_regs);
 tcg_regset_set_reg(*allocated_regs, reg);
 } else {
-load_arg_stk(s, l->arg_slot - ARRAY_SIZE(tcg_target_call_iarg_regs),
- ts, *allocated_regs);
+load_arg_stk(s, l->arg_slot, ts, *allocated_regs);
 }
 }
 
-static void load_arg_ref(TCGContext *s, int arg_slot, TCGReg ref_base,
+static void load_arg_ref(TCGContext *s, unsigned arg_slot, TCGReg ref_base,
  intptr_t ref_off, TCGRegSet *allocated_regs)
 {
 TCGReg reg;
-int stk_slot = arg_slot - ARRAY_SIZE(tcg_target_call_iarg_regs);
 
-if (stk_slot < 0) {
+if (arg_slot_reg_p(arg_slot)) {
 reg = tcg_target_call_iarg_regs[arg_slot];
 tcg_reg_free(s, reg, *allocated_regs);
 tcg_out_addi_ptr(s, reg, ref_base, ref_off);
@@ -4869,8 +4876,7 @@ static void load_arg_ref(TCGContext *s, int arg_slot, 
TCGReg ref_base,
 *allocated_regs, 0, false);
 tcg_out_addi_ptr(s, reg, ref_base, ref_off);
 tcg_out_st(s, TCG_TYPE_PTR, reg, TCG_REG_CALL_STACK,
-   TCG_TARGET_CALL_STACK_OFFSET
-   + stk_slot * sizeof(tcg_target_long));
+   arg_slot_stk_ofs(arg_slot));
 }
 }
 
@@ -4900,8 +4906,7 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op)
 case TCG_CALL_ARG_BY_REF:
 load_arg_stk(s, loc->ref_slot, ts, allocated_regs);
 load_arg_ref(s, loc->arg_slot, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET
- + loc->ref_slot * sizeof(tcg_target_long),
+ arg_slot_stk_ofs(loc->ref_slot),
  &allocated_regs);
 break;
 case TCG_CALL_ARG_BY_REF_N:
-- 
2.34.1




[PULL 27/42] tcg/arm: Introduce HostAddress

2023-05-05 Thread Richard Henderson
Collect the parts of the host address, and condition, into a struct.
Merge tcg_out_qemu_*_{index,direct} and use it.

Signed-off-by: Richard Henderson 
---
 tcg/arm/tcg-target.c.inc | 248 ++-
 1 file changed, 115 insertions(+), 133 deletions(-)

diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index 6ce52b9612..b6b4ffc546 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -1337,6 +1337,13 @@ static void tcg_out_vldst(TCGContext *s, ARMInsn insn,
 tcg_out32(s, insn | (rn << 16) | encode_vd(rd) | 0xf);
 }
 
+typedef struct {
+ARMCond cond;
+TCGReg base;
+int index;
+bool index_scratch;
+} HostAddress;
+
 #ifdef CONFIG_SOFTMMU
 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
  * int mmu_idx, uintptr_t ra)
@@ -1696,29 +1703,49 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
 }
 #endif /* SOFTMMU */
 
-static void tcg_out_qemu_ld_index(TCGContext *s, MemOp opc,
-  TCGReg datalo, TCGReg datahi,
-  TCGReg addrlo, TCGReg addend,
-  bool scratch_addend)
+static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg datalo,
+   TCGReg datahi, HostAddress h)
 {
+TCGReg base;
+
 /* Byte swapping is left to middle-end expansion. */
 tcg_debug_assert((opc & MO_BSWAP) == 0);
 
 switch (opc & MO_SSIZE) {
 case MO_UB:
-tcg_out_ld8_r(s, COND_AL, datalo, addrlo, addend);
+if (h.index < 0) {
+tcg_out_ld8_12(s, h.cond, datalo, h.base, 0);
+} else {
+tcg_out_ld8_r(s, h.cond, datalo, h.base, h.index);
+}
 break;
 case MO_SB:
-tcg_out_ld8s_r(s, COND_AL, datalo, addrlo, addend);
+if (h.index < 0) {
+tcg_out_ld8s_8(s, h.cond, datalo, h.base, 0);
+} else {
+tcg_out_ld8s_r(s, h.cond, datalo, h.base, h.index);
+}
 break;
 case MO_UW:
-tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
+if (h.index < 0) {
+tcg_out_ld16u_8(s, h.cond, datalo, h.base, 0);
+} else {
+tcg_out_ld16u_r(s, h.cond, datalo, h.base, h.index);
+}
 break;
 case MO_SW:
-tcg_out_ld16s_r(s, COND_AL, datalo, addrlo, addend);
+if (h.index < 0) {
+tcg_out_ld16s_8(s, h.cond, datalo, h.base, 0);
+} else {
+tcg_out_ld16s_r(s, h.cond, datalo, h.base, h.index);
+}
 break;
 case MO_UL:
-tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend);
+if (h.index < 0) {
+tcg_out_ld32_12(s, h.cond, datalo, h.base, 0);
+} else {
+tcg_out_ld32_r(s, h.cond, datalo, h.base, h.index);
+}
 break;
 case MO_UQ:
 /* We used pair allocation for datalo, so already should be aligned. */
@@ -1726,87 +1753,59 @@ static void tcg_out_qemu_ld_index(TCGContext *s, MemOp 
opc,
 tcg_debug_assert(datahi == datalo + 1);
 /* LDRD requires alignment; double-check that. */
 if (get_alignment_bits(opc) >= MO_64) {
+if (h.index < 0) {
+tcg_out_ldrd_8(s, h.cond, datalo, h.base, 0);
+break;
+}
 /*
  * Rm (the second address op) must not overlap Rt or Rt + 1.
  * Since datalo is aligned, we can simplify the test via alignment.
  * Flip the two address arguments if that works.
  */
-if ((addend & ~1) != datalo) {
-tcg_out_ldrd_r(s, COND_AL, datalo, addrlo, addend);
+if ((h.index & ~1) != datalo) {
+tcg_out_ldrd_r(s, h.cond, datalo, h.base, h.index);
 break;
 }
-if ((addrlo & ~1) != datalo) {
-tcg_out_ldrd_r(s, COND_AL, datalo, addend, addrlo);
+if ((h.base & ~1) != datalo) {
+tcg_out_ldrd_r(s, h.cond, datalo, h.index, h.base);
 break;
 }
 }
-if (scratch_addend) {
-tcg_out_ld32_rwb(s, COND_AL, datalo, addend, addrlo);
-tcg_out_ld32_12(s, COND_AL, datahi, addend, 4);
+if (h.index < 0) {
+base = h.base;
+if (datalo == h.base) {
+tcg_out_mov_reg(s, h.cond, TCG_REG_TMP, base);
+base = TCG_REG_TMP;
+}
+} else if (h.index_scratch) {
+tcg_out_ld32_rwb(s, h.cond, datalo, h.index, h.base);
+tcg_out_ld32_12(s, h.cond, datahi, h.index, 4);
+break;
 } else {
-tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_TMP,
-addend, addrlo, SHIFT_IMM_LSL(0));
-tcg_out_ld32_12(s, COND_AL, datalo, TCG_REG_TMP, 0);
-tcg_out_ld32_12(s, COND_AL, da

[PULL 17/42] target/sparc: Use cpu_ld*_code_mmu

2023-05-05 Thread Richard Henderson
This passes on the memop as given as argument to
helper_ld_asi to the ultimate load primitive.

Reviewed-by: Mark Cave-Ayland 
Signed-off-by: Richard Henderson 
---
 target/sparc/ldst_helper.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c
index a53580d9e4..7972d56a72 100644
--- a/target/sparc/ldst_helper.c
+++ b/target/sparc/ldst_helper.c
@@ -593,6 +593,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong 
addr,
 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
 uint32_t last_addr = addr;
 #endif
+MemOpIdx oi;
 
 do_check_align(env, addr, size - 1, GETPC());
 switch (asi) {
@@ -692,19 +693,20 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong 
addr,
 case ASI_M_IODIAG:  /* Turbosparc IOTLB Diagnostic */
 break;
 case ASI_KERNELTXT: /* Supervisor code access */
+oi = make_memop_idx(memop, cpu_mmu_index(env, true));
 switch (size) {
 case 1:
-ret = cpu_ldub_code(env, addr);
+ret = cpu_ldb_code_mmu(env, addr, oi, GETPC());
 break;
 case 2:
-ret = cpu_lduw_code(env, addr);
+ret = cpu_ldw_code_mmu(env, addr, oi, GETPC());
 break;
 default:
 case 4:
-ret = cpu_ldl_code(env, addr);
+ret = cpu_ldl_code_mmu(env, addr, oi, GETPC());
 break;
 case 8:
-ret = cpu_ldq_code(env, addr);
+ret = cpu_ldq_code_mmu(env, addr, oi, GETPC());
 break;
 }
 break;
-- 
2.34.1




[PULL 11/42] target/alpha: Use MO_ALIGN for system UNALIGN()

2023-05-05 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/alpha/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 9d25e21164..ffbac1c114 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -72,7 +72,7 @@ struct DisasContext {
 #ifdef CONFIG_USER_ONLY
 #define UNALIGN(C)  (C)->unalign
 #else
-#define UNALIGN(C)  0
+#define UNALIGN(C)  MO_ALIGN
 #endif
 
 /* Target-specific return values from translate_one, indicating the
-- 
2.34.1




[PULL 40/42] tcg: Replace REG_P with arg_loc_reg_p

2023-05-05 Thread Richard Henderson
An inline function is safer than a macro, and REG_P
was rather too generic.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/tcg-internal.h |  4 
 tcg/tcg.c  | 16 +---
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/tcg/tcg-internal.h b/tcg/tcg-internal.h
index e542a4e9b7..0f1ba01a9a 100644
--- a/tcg/tcg-internal.h
+++ b/tcg/tcg-internal.h
@@ -58,10 +58,6 @@ typedef struct TCGCallArgumentLoc {
 unsigned tmp_subindex   : 2;
 } TCGCallArgumentLoc;
 
-/* Avoid "unsigned < 0 is always false" Werror, when iarg_regs is empty. */
-#define REG_P(L) \
-((int)(L)->arg_slot < (int)ARRAY_SIZE(tcg_target_call_iarg_regs))
-
 typedef struct TCGHelperInfo {
 void *func;
 const char *name;
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 6f5daaee5f..fa28db0188 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -806,6 +806,16 @@ static void init_ffi_layouts(void)
 }
 #endif /* CONFIG_TCG_INTERPRETER */
 
+static inline bool arg_slot_reg_p(unsigned arg_slot)
+{
+/*
+ * Split the sizeof away from the comparison to avoid Werror from
+ * "unsigned < 0 is always false", when iarg_regs is empty.
+ */
+unsigned nreg = ARRAY_SIZE(tcg_target_call_iarg_regs);
+return arg_slot < nreg;
+}
+
 typedef struct TCGCumulativeArgs {
 int arg_idx;/* tcg_gen_callN args[] */
 int info_in_idx;/* TCGHelperInfo in[] */
@@ -3231,7 +3241,7 @@ liveness_pass_1(TCGContext *s)
 case TCG_CALL_ARG_NORMAL:
 case TCG_CALL_ARG_EXTEND_U:
 case TCG_CALL_ARG_EXTEND_S:
-if (REG_P(loc)) {
+if (arg_slot_reg_p(loc->arg_slot)) {
 *la_temp_pref(ts) = 0;
 break;
 }
@@ -3258,7 +3268,7 @@ liveness_pass_1(TCGContext *s)
 case TCG_CALL_ARG_NORMAL:
 case TCG_CALL_ARG_EXTEND_U:
 case TCG_CALL_ARG_EXTEND_S:
-if (REG_P(loc)) {
+if (arg_slot_reg_p(loc->arg_slot)) {
 tcg_regset_set_reg(*la_temp_pref(ts),
 tcg_target_call_iarg_regs[loc->arg_slot]);
 }
@@ -4833,7 +4843,7 @@ static void load_arg_stk(TCGContext *s, int stk_slot, 
TCGTemp *ts,
 static void load_arg_normal(TCGContext *s, const TCGCallArgumentLoc *l,
 TCGTemp *ts, TCGRegSet *allocated_regs)
 {
-if (REG_P(l)) {
+if (arg_slot_reg_p(l->arg_slot)) {
 TCGReg reg = tcg_target_call_iarg_regs[l->arg_slot];
 load_arg_reg(s, reg, ts, *allocated_regs);
 tcg_regset_set_reg(*allocated_regs, reg);
-- 
2.34.1




[PULL 26/42] tcg/arm: Rationalize args to tcg_out_qemu_{ld,st}

2023-05-05 Thread Richard Henderson
Interpret the variable argument placement in the caller.
Pass data_type instead of is_64.  We need to set this in
TCGLabelQemuLdst, so plumb this all the way through from tcg_out_op.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/arm/tcg-target.c.inc | 113 +++
 1 file changed, 56 insertions(+), 57 deletions(-)

diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index 83c818a58b..6ce52b9612 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -1526,15 +1526,18 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg 
addrlo, TCGReg addrhi,
 /* Record the context of a call to the out of line helper code for the slow
path for a load or store, so that we can later generate the correct
helper code.  */
-static void add_qemu_ldst_label(TCGContext *s, bool is_ld, MemOpIdx oi,
-TCGReg datalo, TCGReg datahi, TCGReg addrlo,
-TCGReg addrhi, tcg_insn_unit *raddr,
+static void add_qemu_ldst_label(TCGContext *s, bool is_ld,
+MemOpIdx oi, TCGType type,
+TCGReg datalo, TCGReg datahi,
+TCGReg addrlo, TCGReg addrhi,
+tcg_insn_unit *raddr,
 tcg_insn_unit *label_ptr)
 {
 TCGLabelQemuLdst *label = new_ldst_label(s);
 
 label->is_ld = is_ld;
 label->oi = oi;
+label->type = type;
 label->datalo_reg = datalo;
 label->datahi_reg = datahi;
 label->addrlo_reg = addrlo;
@@ -1796,41 +1799,28 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp 
opc, TCGReg datalo,
 }
 #endif
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
+static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi,
+TCGReg addrlo, TCGReg addrhi,
+MemOpIdx oi, TCGType data_type)
 {
-TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
-MemOpIdx oi;
-MemOp opc;
-#ifdef CONFIG_SOFTMMU
-int mem_index;
-TCGReg addend;
-tcg_insn_unit *label_ptr;
-#else
-unsigned a_bits;
-#endif
-
-datalo = *args++;
-datahi = (is64 ? *args++ : 0);
-addrlo = *args++;
-addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
-oi = *args++;
-opc = get_memop(oi);
+MemOp opc = get_memop(oi);
 
 #ifdef CONFIG_SOFTMMU
-mem_index = get_mmuidx(oi);
-addend = tcg_out_tlb_read(s, addrlo, addrhi, opc, mem_index, 1);
+TCGReg addend= tcg_out_tlb_read(s, addrlo, addrhi, opc, get_mmuidx(oi), 1);
 
-/* This a conditional BL only to load a pointer within this opcode into LR
-   for the slow path.  We will not be using the value for a tail call.  */
-label_ptr = s->code_ptr;
+/*
+ * This a conditional BL only to load a pointer within this opcode into
+ * LR for the slow path.  We will not be using the value for a tail call.
+ */
+tcg_insn_unit *label_ptr = s->code_ptr;
 tcg_out_bl_imm(s, COND_NE, 0);
 
 tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, addend, true);
 
-add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi,
-s->code_ptr, label_ptr);
+add_qemu_ldst_label(s, true, oi, data_type, datalo, datahi,
+addrlo, addrhi, s->code_ptr, label_ptr);
 #else /* !CONFIG_SOFTMMU */
-a_bits = get_alignment_bits(opc);
+unsigned a_bits = get_alignment_bits(opc);
 if (a_bits) {
 tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits);
 }
@@ -1918,41 +1908,26 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp 
opc, TCGReg datalo,
 }
 #endif
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
+static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi,
+TCGReg addrlo, TCGReg addrhi,
+MemOpIdx oi, TCGType data_type)
 {
-TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
-MemOpIdx oi;
-MemOp opc;
-#ifdef CONFIG_SOFTMMU
-int mem_index;
-TCGReg addend;
-tcg_insn_unit *label_ptr;
-#else
-unsigned a_bits;
-#endif
-
-datalo = *args++;
-datahi = (is64 ? *args++ : 0);
-addrlo = *args++;
-addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
-oi = *args++;
-opc = get_memop(oi);
+MemOp opc = get_memop(oi);
 
 #ifdef CONFIG_SOFTMMU
-mem_index = get_mmuidx(oi);
-addend = tcg_out_tlb_read(s, addrlo, addrhi, opc, mem_index, 0);
+TCGReg addend = tcg_out_tlb_read(s, addrlo, addrhi, opc, get_mmuidx(oi), 
0);
 
 tcg_out_qemu_st_index(s, COND_EQ, opc, datalo, datahi,
   addrlo, addend, true);
 
 /* The conditional call must come last, as we're going to return here.  */
-label_ptr = s->code_ptr;
+tcg_insn_unit *label_ptr = s->code_ptr;
 tcg_out_bl_imm(s, COND_NE, 0)

[PULL 12/42] target/alpha: Use MO_ALIGN where required

2023-05-05 Thread Richard Henderson
Mark all memory operations that are not already marked with UNALIGN.

Signed-off-by: Richard Henderson 
---
 target/alpha/translate.c | 36 
 1 file changed, 20 insertions(+), 16 deletions(-)

diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index ffbac1c114..be8adb2526 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -2399,21 +2399,21 @@ static DisasJumpType translate_one(DisasContext *ctx, 
uint32_t insn)
 switch ((insn >> 12) & 0xF) {
 case 0x0:
 /* Longword physical access (hw_ldl/p) */
-tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL);
+tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL | 
MO_ALIGN);
 break;
 case 0x1:
 /* Quadword physical access (hw_ldq/p) */
-tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ);
+tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ | 
MO_ALIGN);
 break;
 case 0x2:
 /* Longword physical access with lock (hw_ldl_l/p) */
-tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL);
+tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL | 
MO_ALIGN);
 tcg_gen_mov_i64(cpu_lock_addr, addr);
 tcg_gen_mov_i64(cpu_lock_value, va);
 break;
 case 0x3:
 /* Quadword physical access with lock (hw_ldq_l/p) */
-tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ);
+tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ | 
MO_ALIGN);
 tcg_gen_mov_i64(cpu_lock_addr, addr);
 tcg_gen_mov_i64(cpu_lock_value, va);
 break;
@@ -2438,11 +2438,13 @@ static DisasJumpType translate_one(DisasContext *ctx, 
uint32_t insn)
 goto invalid_opc;
 case 0xA:
 /* Longword virtual access with protection check (hw_ldl/w) */
-tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LESL);
+tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX,
+MO_LESL | MO_ALIGN);
 break;
 case 0xB:
 /* Quadword virtual access with protection check (hw_ldq/w) */
-tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LEUQ);
+tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX,
+MO_LEUQ | MO_ALIGN);
 break;
 case 0xC:
 /* Longword virtual access with alt access mode (hw_ldl/a)*/
@@ -2453,12 +2455,14 @@ static DisasJumpType translate_one(DisasContext *ctx, 
uint32_t insn)
 case 0xE:
 /* Longword virtual access with alternate access mode and
protection checks (hw_ldl/wa) */
-tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LESL);
+tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX,
+MO_LESL | MO_ALIGN);
 break;
 case 0xF:
 /* Quadword virtual access with alternate access mode and
protection checks (hw_ldq/wa) */
-tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LEUQ);
+tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX,
+MO_LEUQ | MO_ALIGN);
 break;
 }
 break;
@@ -2659,7 +2663,7 @@ static DisasJumpType translate_one(DisasContext *ctx, 
uint32_t insn)
 vb = load_gpr(ctx, rb);
 tmp = tcg_temp_new();
 tcg_gen_addi_i64(tmp, vb, disp12);
-tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LESL);
+tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
 break;
 case 0x1:
 /* Quadword physical access */
@@ -2667,17 +2671,17 @@ static DisasJumpType translate_one(DisasContext *ctx, 
uint32_t insn)
 vb = load_gpr(ctx, rb);
 tmp = tcg_temp_new();
 tcg_gen_addi_i64(tmp, vb, disp12);
-tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEUQ);
+tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
 break;
 case 0x2:
 /* Longword physical access with lock */
 ret = gen_store_conditional(ctx, ra, rb, disp12,
-MMU_PHYS_IDX, MO_LESL);
+MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
 break;
 case 0x3:
 /* Quadword physical access with lock */
 ret = gen_store_conditional(ctx, ra, rb, disp12,
-MMU_PHYS_IDX, MO_LEUQ);
+MMU_PH

[PULL 22/42] tcg/i386: Drop r0+r1 local variables from tcg_out_tlb_load

2023-05-05 Thread Richard Henderson
Use TCG_REG_L[01] constants directly.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/i386/tcg-target.c.inc | 32 
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 909eecd4a3..78160f453b 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -1810,8 +1810,6 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg 
addrlo, TCGReg addrhi,
 int mem_index, MemOp opc,
 tcg_insn_unit **label_ptr, int which)
 {
-const TCGReg r0 = TCG_REG_L0;
-const TCGReg r1 = TCG_REG_L1;
 TCGType ttype = TCG_TYPE_I32;
 TCGType tlbtype = TCG_TYPE_I32;
 int trexw = 0, hrexw = 0, tlbrexw = 0;
@@ -1835,15 +1833,15 @@ static inline void tcg_out_tlb_load(TCGContext *s, 
TCGReg addrlo, TCGReg addrhi,
 }
 }
 
-tcg_out_mov(s, tlbtype, r0, addrlo);
-tcg_out_shifti(s, SHIFT_SHR + tlbrexw, r0,
+tcg_out_mov(s, tlbtype, TCG_REG_L0, addrlo);
+tcg_out_shifti(s, SHIFT_SHR + tlbrexw, TCG_REG_L0,
TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
 
-tcg_out_modrm_offset(s, OPC_AND_GvEv + trexw, r0, TCG_AREG0,
+tcg_out_modrm_offset(s, OPC_AND_GvEv + trexw, TCG_REG_L0, TCG_AREG0,
  TLB_MASK_TABLE_OFS(mem_index) +
  offsetof(CPUTLBDescFast, mask));
 
-tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, r0, TCG_AREG0,
+tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, TCG_REG_L0, TCG_AREG0,
  TLB_MASK_TABLE_OFS(mem_index) +
  offsetof(CPUTLBDescFast, table));
 
@@ -1851,19 +1849,21 @@ static inline void tcg_out_tlb_load(TCGContext *s, 
TCGReg addrlo, TCGReg addrhi,
copy the address and mask.  For lesser alignments, check that we don't
cross pages for the complete access.  */
 if (a_bits >= s_bits) {
-tcg_out_mov(s, ttype, r1, addrlo);
+tcg_out_mov(s, ttype, TCG_REG_L1, addrlo);
 } else {
-tcg_out_modrm_offset(s, OPC_LEA + trexw, r1, addrlo, s_mask - a_mask);
+tcg_out_modrm_offset(s, OPC_LEA + trexw, TCG_REG_L1,
+ addrlo, s_mask - a_mask);
 }
 tlb_mask = (target_ulong)TARGET_PAGE_MASK | a_mask;
-tgen_arithi(s, ARITH_AND + trexw, r1, tlb_mask, 0);
+tgen_arithi(s, ARITH_AND + trexw, TCG_REG_L1, tlb_mask, 0);
 
-/* cmp 0(r0), r1 */
-tcg_out_modrm_offset(s, OPC_CMP_GvEv + trexw, r1, r0, which);
+/* cmp 0(TCG_REG_L0), TCG_REG_L1 */
+tcg_out_modrm_offset(s, OPC_CMP_GvEv + trexw,
+ TCG_REG_L1, TCG_REG_L0, which);
 
 /* Prepare for both the fast path add of the tlb addend, and the slow
path function argument setup.  */
-tcg_out_mov(s, ttype, r1, addrlo);
+tcg_out_mov(s, ttype, TCG_REG_L1, addrlo);
 
 /* jne slow_path */
 tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
@@ -1871,8 +1871,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg 
addrlo, TCGReg addrhi,
 s->code_ptr += 4;
 
 if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
-/* cmp 4(r0), addrhi */
-tcg_out_modrm_offset(s, OPC_CMP_GvEv, addrhi, r0, which + 4);
+/* cmp 4(TCG_REG_L0), addrhi */
+tcg_out_modrm_offset(s, OPC_CMP_GvEv, addrhi, TCG_REG_L0, which + 4);
 
 /* jne slow_path */
 tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
@@ -1882,8 +1882,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg 
addrlo, TCGReg addrhi,
 
 /* TLB Hit.  */
 
-/* add addend(r0), r1 */
-tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, r1, r0,
+/* add addend(TCG_REG_L0), TCG_REG_L1 */
+tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, TCG_REG_L1, TCG_REG_L0,
  offsetof(CPUTLBEntry, addend));
 }
 
-- 
2.34.1




[PULL 42/42] tcg: Widen helper_*_st[bw]_mmu val arguments

2023-05-05 Thread Richard Henderson
While the old type was correct in the ideal sense, some ABIs require
the argument to be zero-extended.  Using uint32_t for all such values
is a decent compromise.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-ldst.h | 10 +++---
 accel/tcg/cputlb.c |  6 +++---
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/include/tcg/tcg-ldst.h b/include/tcg/tcg-ldst.h
index 2ba22bd5fe..684e394b06 100644
--- a/include/tcg/tcg-ldst.h
+++ b/include/tcg/tcg-ldst.h
@@ -55,15 +55,19 @@ tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, 
target_ulong addr,
 tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
 MemOpIdx oi, uintptr_t retaddr);
 
-void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
+/*
+ * Value extended to at least uint32_t, so that some ABIs do not require
+ * zero-extension from uint8_t or uint16_t.
+ */
+void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
 MemOpIdx oi, uintptr_t retaddr);
-void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
MemOpIdx oi, uintptr_t retaddr);
 void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
MemOpIdx oi, uintptr_t retaddr);
 void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr);
-void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
MemOpIdx oi, uintptr_t retaddr);
 void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
MemOpIdx oi, uintptr_t retaddr);
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index c8bd642d0e..3117886af1 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -2508,7 +2508,7 @@ full_stb_mmu(CPUArchState *env, target_ulong addr, 
uint64_t val,
 store_helper(env, addr, val, oi, retaddr, MO_UB);
 }
 
-void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
+void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
 MemOpIdx oi, uintptr_t retaddr)
 {
 full_stb_mmu(env, addr, val, oi, retaddr);
@@ -2521,7 +2521,7 @@ static void full_le_stw_mmu(CPUArchState *env, 
target_ulong addr, uint64_t val,
 store_helper(env, addr, val, oi, retaddr, MO_LEUW);
 }
 
-void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
MemOpIdx oi, uintptr_t retaddr)
 {
 full_le_stw_mmu(env, addr, val, oi, retaddr);
@@ -2534,7 +2534,7 @@ static void full_be_stw_mmu(CPUArchState *env, 
target_ulong addr, uint64_t val,
 store_helper(env, addr, val, oi, retaddr, MO_BEUW);
 }
 
-void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
MemOpIdx oi, uintptr_t retaddr)
 {
 full_be_stw_mmu(env, addr, val, oi, retaddr);
-- 
2.34.1




[PULL 14/42] target/hppa: Use MO_ALIGN for system UNALIGN()

2023-05-05 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 6a3154ebc6..59e4688bfa 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -271,7 +271,7 @@ typedef struct DisasContext {
 #ifdef CONFIG_USER_ONLY
 #define UNALIGN(C)  (C)->unalign
 #else
-#define UNALIGN(C)  0
+#define UNALIGN(C)  MO_ALIGN
 #endif
 
 /* Note that ssm/rsm instructions number PSW_W and PSW_E differently.  */
-- 
2.34.1




[PULL 34/42] tcg/riscv: Rationalize args to tcg_out_qemu_{ld,st}

2023-05-05 Thread Richard Henderson
Interpret the variable argument placement in the caller.  Pass data_type
instead of is64 -- there are several places where we already convert back
from bool to type.  Clean things up by using type throughout.

Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Richard Henderson 
---
 tcg/riscv/tcg-target.c.inc | 66 ++
 1 file changed, 24 insertions(+), 42 deletions(-)

diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 7a674ff5ce..a4cf60ca75 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -1087,7 +1087,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
 #endif /* CONFIG_SOFTMMU */
 
 static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val,
-   TCGReg base, MemOp opc, bool is_64)
+   TCGReg base, MemOp opc, TCGType type)
 {
 /* Byte swapping is left to middle-end expansion. */
 tcg_debug_assert((opc & MO_BSWAP) == 0);
@@ -1106,7 +1106,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg 
val,
 tcg_out_opc_imm(s, OPC_LH, val, base, 0);
 break;
 case MO_UL:
-if (is_64) {
+if (type == TCG_TYPE_I64) {
 tcg_out_opc_imm(s, OPC_LWU, val, base, 0);
 break;
 }
@@ -1122,30 +1122,21 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, 
TCGReg val,
 }
 }
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
+static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
+MemOpIdx oi, TCGType data_type)
 {
-TCGReg addr_reg, data_reg;
-MemOpIdx oi;
-MemOp opc;
-#if defined(CONFIG_SOFTMMU)
-tcg_insn_unit *label_ptr[1];
-#else
-unsigned a_bits;
-#endif
+MemOp opc = get_memop(oi);
 TCGReg base;
 
-data_reg = *args++;
-addr_reg = *args++;
-oi = *args++;
-opc = get_memop(oi);
-
 #if defined(CONFIG_SOFTMMU)
+tcg_insn_unit *label_ptr[1];
+
 base = tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 1);
-tcg_out_qemu_ld_direct(s, data_reg, base, opc, is_64);
-add_qemu_ldst_label(s, 1, oi, (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
-data_reg, addr_reg, s->code_ptr, label_ptr);
+tcg_out_qemu_ld_direct(s, data_reg, base, opc, data_type);
+add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg,
+s->code_ptr, label_ptr);
 #else
-a_bits = get_alignment_bits(opc);
+unsigned a_bits = get_alignment_bits(opc);
 if (a_bits) {
 tcg_out_test_alignment(s, true, addr_reg, a_bits);
 }
@@ -1158,7 +1149,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg 
*args, bool is_64)
 tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_GUEST_BASE_REG, base);
 base = TCG_REG_TMP0;
 }
-tcg_out_qemu_ld_direct(s, data_reg, base, opc, is_64);
+tcg_out_qemu_ld_direct(s, data_reg, base, opc, data_type);
 #endif
 }
 
@@ -1186,30 +1177,21 @@ static void tcg_out_qemu_st_direct(TCGContext *s, 
TCGReg val,
 }
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
+static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
+MemOpIdx oi, TCGType data_type)
 {
-TCGReg addr_reg, data_reg;
-MemOpIdx oi;
-MemOp opc;
-#if defined(CONFIG_SOFTMMU)
-tcg_insn_unit *label_ptr[1];
-#else
-unsigned a_bits;
-#endif
+MemOp opc = get_memop(oi);
 TCGReg base;
 
-data_reg = *args++;
-addr_reg = *args++;
-oi = *args++;
-opc = get_memop(oi);
-
 #if defined(CONFIG_SOFTMMU)
+tcg_insn_unit *label_ptr[1];
+
 base = tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 0);
 tcg_out_qemu_st_direct(s, data_reg, base, opc);
-add_qemu_ldst_label(s, 0, oi, (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
-data_reg, addr_reg, s->code_ptr, label_ptr);
+add_qemu_ldst_label(s, false, oi, data_type, data_reg, addr_reg,
+s->code_ptr, label_ptr);
 #else
-a_bits = get_alignment_bits(opc);
+unsigned a_bits = get_alignment_bits(opc);
 if (a_bits) {
 tcg_out_test_alignment(s, false, addr_reg, a_bits);
 }
@@ -1508,16 +1490,16 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 break;
 
 case INDEX_op_qemu_ld_i32:
-tcg_out_qemu_ld(s, args, false);
+tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32);
 break;
 case INDEX_op_qemu_ld_i64:
-tcg_out_qemu_ld(s, args, true);
+tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64);
 break;
 case INDEX_op_qemu_st_i32:
-tcg_out_qemu_st(s, args, false);
+tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32);
 break;
 case INDEX_op_qemu_st_i64:
-tcg_out_qemu_st(s, args, true);
+tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64);
 break;
 
 case INDEX_

[PULL 23/42] tcg/i386: Introduce tcg_out_testi

2023-05-05 Thread Richard Henderson
Split out a helper for choosing testb vs testl.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/i386/tcg-target.c.inc | 30 ++
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 78160f453b..aae698121a 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -1751,6 +1751,23 @@ static void tcg_out_nopn(TCGContext *s, int n)
 tcg_out8(s, 0x90);
 }
 
+/* Test register R vs immediate bits I, setting Z flag for EQ/NE. */
+static void __attribute__((unused))
+tcg_out_testi(TCGContext *s, TCGReg r, uint32_t i)
+{
+/*
+ * This is used for testing alignment, so we can usually use testb.
+ * For i686, we have to use testl for %esi/%edi.
+ */
+if (i <= 0xff && (TCG_TARGET_REG_BITS == 64 || r < 4)) {
+tcg_out_modrm(s, OPC_GRP3_Eb | P_REXB_RM, EXT3_TESTi, r);
+tcg_out8(s, i);
+} else {
+tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_TESTi, r);
+tcg_out32(s, i);
+}
+}
+
 typedef struct {
 TCGReg base;
 int index;
@@ -2051,18 +2068,7 @@ static void tcg_out_test_alignment(TCGContext *s, bool 
is_ld, TCGReg addrlo,
 unsigned a_mask = (1 << a_bits) - 1;
 TCGLabelQemuLdst *label;
 
-/*
- * We are expecting a_bits to max out at 7, so we can usually use testb.
- * For i686, we have to use testl for %esi/%edi.
- */
-if (a_mask <= 0xff && (TCG_TARGET_REG_BITS == 64 || addrlo < 4)) {
-tcg_out_modrm(s, OPC_GRP3_Eb | P_REXB_RM, EXT3_TESTi, addrlo);
-tcg_out8(s, a_mask);
-} else {
-tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_TESTi, addrlo);
-tcg_out32(s, a_mask);
-}
-
+tcg_out_testi(s, addrlo, a_mask);
 /* jne slow_path */
 tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
 
-- 
2.34.1




[PULL 02/42] target/avr: Finish conversion to tcg_gen_qemu_{ld,st}_*

2023-05-05 Thread Richard Henderson
Convert away from the old interface with the implicit
MemOp argument.

Signed-off-by: Richard Henderson 
Reviewed-by: Anton Johansson 
Message-Id: <20230502135741.1158035-2-richard.hender...@linaro.org>
---
 target/avr/translate.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/target/avr/translate.c b/target/avr/translate.c
index a6aeae6dfa..cd82f5d591 100644
--- a/target/avr/translate.c
+++ b/target/avr/translate.c
@@ -1492,7 +1492,7 @@ static void gen_data_store(DisasContext *ctx, TCGv data, 
TCGv addr)
 if (ctx->base.tb->flags & TB_FLAGS_FULL_ACCESS) {
 gen_helper_fullwr(cpu_env, data, addr);
 } else {
-tcg_gen_qemu_st8(data, addr, MMU_DATA_IDX); /* mem[addr] = data */
+tcg_gen_qemu_st_tl(data, addr, MMU_DATA_IDX, MO_UB);
 }
 }
 
@@ -1501,7 +1501,7 @@ static void gen_data_load(DisasContext *ctx, TCGv data, 
TCGv addr)
 if (ctx->base.tb->flags & TB_FLAGS_FULL_ACCESS) {
 gen_helper_fullrd(data, cpu_env, addr);
 } else {
-tcg_gen_qemu_ld8u(data, addr, MMU_DATA_IDX); /* data = mem[addr] */
+tcg_gen_qemu_ld_tl(data, addr, MMU_DATA_IDX, MO_UB);
 }
 }
 
@@ -1979,7 +1979,7 @@ static bool trans_LPM1(DisasContext *ctx, arg_LPM1 *a)
 
 tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
 tcg_gen_or_tl(addr, addr, L);
-tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+tcg_gen_qemu_ld_tl(Rd, addr, MMU_CODE_IDX, MO_UB);
 return true;
 }
 
@@ -1996,7 +1996,7 @@ static bool trans_LPM2(DisasContext *ctx, arg_LPM2 *a)
 
 tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
 tcg_gen_or_tl(addr, addr, L);
-tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+tcg_gen_qemu_ld_tl(Rd, addr, MMU_CODE_IDX, MO_UB);
 return true;
 }
 
@@ -2013,7 +2013,7 @@ static bool trans_LPMX(DisasContext *ctx, arg_LPMX *a)
 
 tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
 tcg_gen_or_tl(addr, addr, L);
-tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+tcg_gen_qemu_ld_tl(Rd, addr, MMU_CODE_IDX, MO_UB);
 tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
 tcg_gen_andi_tl(L, addr, 0xff);
 tcg_gen_shri_tl(addr, addr, 8);
@@ -2045,7 +2045,7 @@ static bool trans_ELPM1(DisasContext *ctx, arg_ELPM1 *a)
 TCGv Rd = cpu_r[0];
 TCGv addr = gen_get_zaddr();
 
-tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+tcg_gen_qemu_ld_tl(Rd, addr, MMU_CODE_IDX, MO_UB);
 return true;
 }
 
@@ -2058,7 +2058,7 @@ static bool trans_ELPM2(DisasContext *ctx, arg_ELPM2 *a)
 TCGv Rd = cpu_r[a->rd];
 TCGv addr = gen_get_zaddr();
 
-tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+tcg_gen_qemu_ld_tl(Rd, addr, MMU_CODE_IDX, MO_UB);
 return true;
 }
 
@@ -2071,7 +2071,7 @@ static bool trans_ELPMX(DisasContext *ctx, arg_ELPMX *a)
 TCGv Rd = cpu_r[a->rd];
 TCGv addr = gen_get_zaddr();
 
-tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+tcg_gen_qemu_ld_tl(Rd, addr, MMU_CODE_IDX, MO_UB);
 tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
 gen_set_zaddr(addr);
 return true;
-- 
2.34.1




[PULL 06/42] target/mips: Finish conversion to tcg_gen_qemu_{ld, st}_*

2023-05-05 Thread Richard Henderson
Convert away from the old interface with the implicit
MemOp argument.

Signed-off-by: Richard Henderson 
Reviewed-by: Anton Johansson 
Message-Id: <20230502135741.1158035-6-richard.hender...@linaro.org>
---
 target/mips/tcg/translate.c  | 8 
 target/mips/tcg/nanomips_translate.c.inc | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 999fbb7cc1..a6ca2e5a3b 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -1949,13 +1949,13 @@ FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
 
 /* load/store instructions. */
 #ifdef CONFIG_USER_ONLY
-#define OP_LD_ATOMIC(insn, fname)  \
+#define OP_LD_ATOMIC(insn, memop)  \
 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_qemu_ld_tl(ret, arg1, ctx->mem_idx, memop);\
 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr));\
 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval));\
 }
@@ -1967,9 +1967,9 @@ static inline void op_ld_##insn(TCGv ret, TCGv arg1, int 
mem_idx,  \
 gen_helper_##insn(ret, cpu_env, arg1, tcg_constant_i32(mem_idx));  \
 }
 #endif
-OP_LD_ATOMIC(ll, ld32s);
+OP_LD_ATOMIC(ll, MO_TESL);
 #if defined(TARGET_MIPS64)
-OP_LD_ATOMIC(lld, ld64);
+OP_LD_ATOMIC(lld, MO_TEUQ);
 #endif
 #undef OP_LD_ATOMIC
 
diff --git a/target/mips/tcg/nanomips_translate.c.inc 
b/target/mips/tcg/nanomips_translate.c.inc
index 9398e28000..97b9572caa 100644
--- a/target/mips/tcg/nanomips_translate.c.inc
+++ b/target/mips/tcg/nanomips_translate.c.inc
@@ -998,7 +998,7 @@ static void gen_llwp(DisasContext *ctx, uint32_t base, 
int16_t offset,
 TCGv tmp2 = tcg_temp_new();
 
 gen_base_offset_addr(ctx, taddr, base, offset);
-tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
+tcg_gen_qemu_ld_i64(tval, taddr, ctx->mem_idx, MO_TEUQ);
 if (cpu_is_bigendian(ctx)) {
 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
 } else {
-- 
2.34.1




[PULL 28/42] tcg/loongarch64: Rationalize args to tcg_out_qemu_{ld, st}

2023-05-05 Thread Richard Henderson
Interpret the variable argument placement in the caller.  Shift some
code around slightly to share more between softmmu and user-only.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 100 +--
 1 file changed, 42 insertions(+), 58 deletions(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 0940788c6f..2e3c67054b 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1049,39 +1049,31 @@ static void tcg_out_qemu_ld_indexed(TCGContext *s, 
TCGReg rd, TCGReg rj,
 }
 }
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGType type)
+static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
+MemOpIdx oi, TCGType data_type)
 {
-TCGReg addr_regl;
-TCGReg data_regl;
-MemOpIdx oi;
-MemOp opc;
-#if defined(CONFIG_SOFTMMU)
+MemOp opc = get_memop(oi);
+TCGReg base, index;
+
+#ifdef CONFIG_SOFTMMU
 tcg_insn_unit *label_ptr[1];
-#else
-unsigned a_bits;
-#endif
-TCGReg base;
 
-data_regl = *args++;
-addr_regl = *args++;
-oi = *args++;
-opc = get_memop(oi);
-
-#if defined(CONFIG_SOFTMMU)
-tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 1);
-base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0);
-tcg_out_qemu_ld_indexed(s, data_regl, base, TCG_REG_TMP2, opc, type);
-add_qemu_ldst_label(s, 1, oi, type,
-data_regl, addr_regl,
-s->code_ptr, label_ptr);
+tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 1);
+index = TCG_REG_TMP2;
 #else
-a_bits = get_alignment_bits(opc);
+unsigned a_bits = get_alignment_bits(opc);
 if (a_bits) {
-tcg_out_test_alignment(s, true, addr_regl, a_bits);
+tcg_out_test_alignment(s, true, addr_reg, a_bits);
 }
-base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0);
-TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO;
-tcg_out_qemu_ld_indexed(s, data_regl, base, guest_base_reg, opc, type);
+index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO;
+#endif
+
+base = tcg_out_zext_addr_if_32_bit(s, addr_reg, TCG_REG_TMP0);
+tcg_out_qemu_ld_indexed(s, data_reg, base, index, opc, data_type);
+
+#ifdef CONFIG_SOFTMMU
+add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg,
+s->code_ptr, label_ptr);
 #endif
 }
 
@@ -1109,39 +1101,31 @@ static void tcg_out_qemu_st_indexed(TCGContext *s, 
TCGReg data,
 }
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGType type)
+static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
+MemOpIdx oi, TCGType data_type)
 {
-TCGReg addr_regl;
-TCGReg data_regl;
-MemOpIdx oi;
-MemOp opc;
-#if defined(CONFIG_SOFTMMU)
+MemOp opc = get_memop(oi);
+TCGReg base, index;
+
+#ifdef CONFIG_SOFTMMU
 tcg_insn_unit *label_ptr[1];
-#else
-unsigned a_bits;
-#endif
-TCGReg base;
 
-data_regl = *args++;
-addr_regl = *args++;
-oi = *args++;
-opc = get_memop(oi);
-
-#if defined(CONFIG_SOFTMMU)
-tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 0);
-base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0);
-tcg_out_qemu_st_indexed(s, data_regl, base, TCG_REG_TMP2, opc);
-add_qemu_ldst_label(s, 0, oi, type,
-data_regl, addr_regl,
-s->code_ptr, label_ptr);
+tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 0);
+index = TCG_REG_TMP2;
 #else
-a_bits = get_alignment_bits(opc);
+unsigned a_bits = get_alignment_bits(opc);
 if (a_bits) {
-tcg_out_test_alignment(s, false, addr_regl, a_bits);
+tcg_out_test_alignment(s, false, addr_reg, a_bits);
 }
-base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0);
-TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO;
-tcg_out_qemu_st_indexed(s, data_regl, base, guest_base_reg, opc);
+index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO;
+#endif
+
+base = tcg_out_zext_addr_if_32_bit(s, addr_reg, TCG_REG_TMP0);
+tcg_out_qemu_st_indexed(s, data_reg, base, index, opc);
+
+#ifdef CONFIG_SOFTMMU
+add_qemu_ldst_label(s, false, oi, data_type, data_reg, addr_reg,
+s->code_ptr, label_ptr);
 #endif
 }
 
@@ -1564,16 +1548,16 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 break;
 
 case INDEX_op_qemu_ld_i32:
-tcg_out_qemu_ld(s, args, TCG_TYPE_I32);
+tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32);
 break;
 case INDEX_op_qemu_ld_i64:
-tcg_out_qemu_ld(s, args, TCG_TYPE_I64);
+tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64);
 break;
 case INDEX_op_qemu_st_i32:
-tcg_out_qemu_st(s, args, TCG_TYPE_I32);
+tcg_out_qemu_

[PULL 25/42] tcg/aarch64: Introduce HostAddress

2023-05-05 Thread Richard Henderson
Collect the 3 potential parts of the host address into a struct.
Reorg tcg_out_qemu_{ld,st}_direct to use it.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/aarch64/tcg-target.c.inc | 86 +---
 1 file changed, 59 insertions(+), 27 deletions(-)

diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index ecbf6564fc..d8d464e4a0 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -1587,6 +1587,12 @@ static void tcg_out_adr(TCGContext *s, TCGReg rd, const 
void *target)
 tcg_out_insn(s, 3406, ADR, rd, offset);
 }
 
+typedef struct {
+TCGReg base;
+TCGReg index;
+TCGType index_ext;
+} HostAddress;
+
 #ifdef CONFIG_SOFTMMU
 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
  * MemOpIdx oi, uintptr_t ra)
@@ -1796,32 +1802,31 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
 #endif /* CONFIG_SOFTMMU */
 
 static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp memop, TCGType ext,
-   TCGReg data_r, TCGReg addr_r,
-   TCGType otype, TCGReg off_r)
+   TCGReg data_r, HostAddress h)
 {
 switch (memop & MO_SSIZE) {
 case MO_UB:
-tcg_out_ldst_r(s, I3312_LDRB, data_r, addr_r, otype, off_r);
+tcg_out_ldst_r(s, I3312_LDRB, data_r, h.base, h.index_ext, h.index);
 break;
 case MO_SB:
 tcg_out_ldst_r(s, ext ? I3312_LDRSBX : I3312_LDRSBW,
-   data_r, addr_r, otype, off_r);
+   data_r, h.base, h.index_ext, h.index);
 break;
 case MO_UW:
-tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, otype, off_r);
+tcg_out_ldst_r(s, I3312_LDRH, data_r, h.base, h.index_ext, h.index);
 break;
 case MO_SW:
 tcg_out_ldst_r(s, (ext ? I3312_LDRSHX : I3312_LDRSHW),
-   data_r, addr_r, otype, off_r);
+   data_r, h.base, h.index_ext, h.index);
 break;
 case MO_UL:
-tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, otype, off_r);
+tcg_out_ldst_r(s, I3312_LDRW, data_r, h.base, h.index_ext, h.index);
 break;
 case MO_SL:
-tcg_out_ldst_r(s, I3312_LDRSWX, data_r, addr_r, otype, off_r);
+tcg_out_ldst_r(s, I3312_LDRSWX, data_r, h.base, h.index_ext, h.index);
 break;
 case MO_UQ:
-tcg_out_ldst_r(s, I3312_LDRX, data_r, addr_r, otype, off_r);
+tcg_out_ldst_r(s, I3312_LDRX, data_r, h.base, h.index_ext, h.index);
 break;
 default:
 g_assert_not_reached();
@@ -1829,21 +1834,20 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp 
memop, TCGType ext,
 }
 
 static void tcg_out_qemu_st_direct(TCGContext *s, MemOp memop,
-   TCGReg data_r, TCGReg addr_r,
-   TCGType otype, TCGReg off_r)
+   TCGReg data_r, HostAddress h)
 {
 switch (memop & MO_SIZE) {
 case MO_8:
-tcg_out_ldst_r(s, I3312_STRB, data_r, addr_r, otype, off_r);
+tcg_out_ldst_r(s, I3312_STRB, data_r, h.base, h.index_ext, h.index);
 break;
 case MO_16:
-tcg_out_ldst_r(s, I3312_STRH, data_r, addr_r, otype, off_r);
+tcg_out_ldst_r(s, I3312_STRH, data_r, h.base, h.index_ext, h.index);
 break;
 case MO_32:
-tcg_out_ldst_r(s, I3312_STRW, data_r, addr_r, otype, off_r);
+tcg_out_ldst_r(s, I3312_STRW, data_r, h.base, h.index_ext, h.index);
 break;
 case MO_64:
-tcg_out_ldst_r(s, I3312_STRX, data_r, addr_r, otype, off_r);
+tcg_out_ldst_r(s, I3312_STRX, data_r, h.base, h.index_ext, h.index);
 break;
 default:
 g_assert_not_reached();
@@ -1855,6 +1859,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg 
data_reg, TCGReg addr_reg,
 {
 MemOp memop = get_memop(oi);
 TCGType addr_type = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
+HostAddress h;
 
 /* Byte swapping is left to middle-end expansion. */
 tcg_debug_assert((memop & MO_BSWAP) == 0);
@@ -1863,8 +1868,14 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg 
data_reg, TCGReg addr_reg,
 tcg_insn_unit *label_ptr;
 
 tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, get_mmuidx(oi), 1);
-tcg_out_qemu_ld_direct(s, memop, data_type, data_reg,
-   TCG_REG_X1, addr_type, addr_reg);
+
+h = (HostAddress){
+.base = TCG_REG_X1,
+.index = addr_reg,
+.index_ext = addr_type
+};
+tcg_out_qemu_ld_direct(s, memop, data_type, data_reg, h);
+
 add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg,
 s->code_ptr, label_ptr);
 #else /* !CONFIG_SOFTMMU */
@@ -1873,12 +1884,19 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg 
data_reg, TCGReg addr_reg

[PULL 32/42] tcg/ppc: Introduce HostAddress

2023-05-05 Thread Richard Henderson
Collect the parts of the host address into a struct.
Reorg tcg_out_qemu_{ld,st} to use it.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/ppc/tcg-target.c.inc | 90 +---
 1 file changed, 47 insertions(+), 43 deletions(-)

diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index d1aa2a9f53..cd473deb36 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -2287,67 +2287,71 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
 {
 return tcg_out_fail_alignment(s, l);
 }
-
 #endif /* SOFTMMU */
 
+typedef struct {
+TCGReg base;
+TCGReg index;
+} HostAddress;
+
 static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi,
 TCGReg addrlo, TCGReg addrhi,
 MemOpIdx oi, TCGType data_type)
 {
 MemOp opc = get_memop(oi);
 MemOp s_bits = opc & MO_SIZE;
-TCGReg rbase;
+HostAddress h;
 
 #ifdef CONFIG_SOFTMMU
 tcg_insn_unit *label_ptr;
 
-addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, get_mmuidx(oi), true);
+h.index = tcg_out_tlb_read(s, opc, addrlo, addrhi, get_mmuidx(oi), true);
+h.base = TCG_REG_R3;
 
 /* Load a pointer into the current opcode w/conditional branch-link. */
 label_ptr = s->code_ptr;
 tcg_out32(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
-
-rbase = TCG_REG_R3;
 #else  /* !CONFIG_SOFTMMU */
 unsigned a_bits = get_alignment_bits(opc);
 if (a_bits) {
 tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits);
 }
-rbase = guest_base ? TCG_GUEST_BASE_REG : 0;
+h.base = guest_base ? TCG_GUEST_BASE_REG : 0;
+h.index = addrlo;
 if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
 tcg_out_ext32u(s, TCG_REG_TMP1, addrlo);
-addrlo = TCG_REG_TMP1;
+h.index = TCG_REG_TMP1;
 }
 #endif
 
 if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
 if (opc & MO_BSWAP) {
-tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
-tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
-tcg_out32(s, LWBRX | TAB(datahi, rbase, TCG_REG_R0));
-} else if (rbase != 0) {
-tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
-tcg_out32(s, LWZX | TAB(datahi, rbase, addrlo));
-tcg_out32(s, LWZX | TAB(datalo, rbase, TCG_REG_R0));
-} else if (addrlo == datahi) {
-tcg_out32(s, LWZ | TAI(datalo, addrlo, 4));
-tcg_out32(s, LWZ | TAI(datahi, addrlo, 0));
+tcg_out32(s, ADDI | TAI(TCG_REG_R0, h.index, 4));
+tcg_out32(s, LWBRX | TAB(datalo, h.base, h.index));
+tcg_out32(s, LWBRX | TAB(datahi, h.base, TCG_REG_R0));
+} else if (h.base != 0) {
+tcg_out32(s, ADDI | TAI(TCG_REG_R0, h.index, 4));
+tcg_out32(s, LWZX | TAB(datahi, h.base, h.index));
+tcg_out32(s, LWZX | TAB(datalo, h.base, TCG_REG_R0));
+} else if (h.index == datahi) {
+tcg_out32(s, LWZ | TAI(datalo, h.index, 4));
+tcg_out32(s, LWZ | TAI(datahi, h.index, 0));
 } else {
-tcg_out32(s, LWZ | TAI(datahi, addrlo, 0));
-tcg_out32(s, LWZ | TAI(datalo, addrlo, 4));
+tcg_out32(s, LWZ | TAI(datahi, h.index, 0));
+tcg_out32(s, LWZ | TAI(datalo, h.index, 4));
 }
 } else {
 uint32_t insn = qemu_ldx_opc[opc & (MO_BSWAP | MO_SSIZE)];
 if (!have_isa_2_06 && insn == LDBRX) {
-tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
-tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
-tcg_out32(s, LWBRX | TAB(TCG_REG_R0, rbase, TCG_REG_R0));
+tcg_out32(s, ADDI | TAI(TCG_REG_R0, h.index, 4));
+tcg_out32(s, LWBRX | TAB(datalo, h.base, h.index));
+tcg_out32(s, LWBRX | TAB(TCG_REG_R0, h.base, TCG_REG_R0));
 tcg_out_rld(s, RLDIMI, datalo, TCG_REG_R0, 32, 0);
 } else if (insn) {
-tcg_out32(s, insn | TAB(datalo, rbase, addrlo));
+tcg_out32(s, insn | TAB(datalo, h.base, h.index));
 } else {
 insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
-tcg_out32(s, insn | TAB(datalo, rbase, addrlo));
+tcg_out32(s, insn | TAB(datalo, h.base, h.index));
 tcg_out_movext(s, TCG_TYPE_REG, datalo,
TCG_TYPE_REG, opc & MO_SSIZE, datalo);
 }
@@ -2365,52 +2369,52 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg 
datalo, TCGReg datahi,
 {
 MemOp opc = get_memop(oi);
 MemOp s_bits = opc & MO_SIZE;
-TCGReg rbase;
+HostAddress h;
 
 #ifdef CONFIG_SOFTMMU
 tcg_insn_unit *label_ptr;
 
-addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, get_mmuidx(oi), false);
+h.index = tcg_out_tlb_read(s, opc, addrlo, addrhi, get_mmuidx(oi), false);
+h.base = TCG_REG_R3;
 
 /* Load a pointer into the current opcode w/co

[PULL 13/42] target/alpha: Remove TARGET_ALIGNED_ONLY

2023-05-05 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 configs/targets/alpha-linux-user.mak | 1 -
 configs/targets/alpha-softmmu.mak| 1 -
 2 files changed, 2 deletions(-)

diff --git a/configs/targets/alpha-linux-user.mak 
b/configs/targets/alpha-linux-user.mak
index 7e62fd796a..f7d3fb4afa 100644
--- a/configs/targets/alpha-linux-user.mak
+++ b/configs/targets/alpha-linux-user.mak
@@ -1,4 +1,3 @@
 TARGET_ARCH=alpha
 TARGET_SYSTBL_ABI=common
 TARGET_SYSTBL=syscall.tbl
-TARGET_ALIGNED_ONLY=y
diff --git a/configs/targets/alpha-softmmu.mak 
b/configs/targets/alpha-softmmu.mak
index e4b874a19e..9dbe160740 100644
--- a/configs/targets/alpha-softmmu.mak
+++ b/configs/targets/alpha-softmmu.mak
@@ -1,3 +1,2 @@
 TARGET_ARCH=alpha
-TARGET_ALIGNED_ONLY=y
 TARGET_SUPPORTS_MTTCG=y
-- 
2.34.1




[PULL 21/42] tcg/i386: Introduce HostAddress

2023-05-05 Thread Richard Henderson
Collect the 4 potential parts of the host address into a struct.
Reorg tcg_out_qemu_{ld,st}_direct to use it.
Reorg guest_base handling to use it.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/i386/tcg-target.c.inc | 165 +-
 1 file changed, 90 insertions(+), 75 deletions(-)

diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 173f3c3172..909eecd4a3 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -1751,6 +1751,13 @@ static void tcg_out_nopn(TCGContext *s, int n)
 tcg_out8(s, 0x90);
 }
 
+typedef struct {
+TCGReg base;
+int index;
+int ofs;
+int seg;
+} HostAddress;
+
 #if defined(CONFIG_SOFTMMU)
 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
  * int mmu_idx, uintptr_t ra)
@@ -2113,17 +2120,13 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
 return tcg_out_fail_alignment(s, l);
 }
 
-#if TCG_TARGET_REG_BITS == 32
-# define x86_guest_base_seg 0
-# define x86_guest_base_index   -1
-# define x86_guest_base_offset  guest_base
-#else
-static int x86_guest_base_seg;
-static int x86_guest_base_index = -1;
-static int32_t x86_guest_base_offset;
-# if defined(__x86_64__) && defined(__linux__)
-#  include 
-#  include 
+static HostAddress x86_guest_base = {
+.index = -1
+};
+
+#if defined(__x86_64__) && defined(__linux__)
+# include 
+# include 
 int arch_prctl(int code, unsigned long addr);
 static inline int setup_guest_base_seg(void)
 {
@@ -2132,8 +2135,9 @@ static inline int setup_guest_base_seg(void)
 }
 return 0;
 }
-# elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
-#  include 
+#elif defined(__x86_64__) && \
+  (defined (__FreeBSD__) || defined (__FreeBSD_kernel__))
+# include 
 static inline int setup_guest_base_seg(void)
 {
 if (sysarch(AMD64_SET_GSBASE, &guest_base) == 0) {
@@ -2141,18 +2145,16 @@ static inline int setup_guest_base_seg(void)
 }
 return 0;
 }
-# else
+#else
 static inline int setup_guest_base_seg(void)
 {
 return 0;
 }
-# endif
-#endif
+#endif /* setup_guest_base_seg */
 #endif /* SOFTMMU */
 
 static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
-   TCGReg base, int index, intptr_t ofs,
-   int seg, TCGType type, MemOp memop)
+   HostAddress h, TCGType type, MemOp memop)
 {
 bool use_movbe = false;
 int rexw = (type == TCG_TYPE_I32 ? 0 : P_REXW);
@@ -2167,60 +2169,61 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, 
TCGReg datalo, TCGReg datahi,
 
 switch (memop & MO_SSIZE) {
 case MO_UB:
-tcg_out_modrm_sib_offset(s, OPC_MOVZBL + seg, datalo,
- base, index, 0, ofs);
+tcg_out_modrm_sib_offset(s, OPC_MOVZBL + h.seg, datalo,
+ h.base, h.index, 0, h.ofs);
 break;
 case MO_SB:
-tcg_out_modrm_sib_offset(s, OPC_MOVSBL + rexw + seg, datalo,
- base, index, 0, ofs);
+tcg_out_modrm_sib_offset(s, OPC_MOVSBL + rexw + h.seg, datalo,
+ h.base, h.index, 0, h.ofs);
 break;
 case MO_UW:
 if (use_movbe) {
 /* There is no extending movbe; only low 16-bits are modified.  */
-if (datalo != base && datalo != index) {
+if (datalo != h.base && datalo != h.index) {
 /* XOR breaks dependency chains.  */
 tgen_arithr(s, ARITH_XOR, datalo, datalo);
-tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg,
- datalo, base, index, 0, ofs);
+tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + h.seg,
+ datalo, h.base, h.index, 0, h.ofs);
 } else {
-tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg,
- datalo, base, index, 0, ofs);
+tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + h.seg,
+ datalo, h.base, h.index, 0, h.ofs);
 tcg_out_ext16u(s, datalo, datalo);
 }
 } else {
-tcg_out_modrm_sib_offset(s, OPC_MOVZWL + seg, datalo,
- base, index, 0, ofs);
+tcg_out_modrm_sib_offset(s, OPC_MOVZWL + h.seg, datalo,
+ h.base, h.index, 0, h.ofs);
 }
 break;
 case MO_SW:
 if (use_movbe) {
-tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg,
- datalo, base, index, 0, ofs);
+tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + h.seg,
+ datalo, h.bas

[PULL 03/42] target/cris: Finish conversion to tcg_gen_qemu_{ld, st}_*

2023-05-05 Thread Richard Henderson
Convert away from the old interface with the implicit
MemOp argument.  In this case we can fold the calls
using the size bits of MemOp.

Signed-off-by: Richard Henderson 
Reviewed-by: Anton Johansson 
Message-Id: <20230502135741.1158035-3-richard.hender...@linaro.org>
---
 target/cris/translate_v10.c.inc | 18 --
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/target/cris/translate_v10.c.inc b/target/cris/translate_v10.c.inc
index 32338bb69b..b7b0517982 100644
--- a/target/cris/translate_v10.c.inc
+++ b/target/cris/translate_v10.c.inc
@@ -80,13 +80,9 @@ static void gen_store_v10_conditional(DisasContext *dc, TCGv 
addr, TCGv val,
 /* Store only if F flag isn't set */
 tcg_gen_andi_tl(t1, cpu_PR[PR_CCS], F_FLAG_V10);
 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
-if (size == 1) {
-tcg_gen_qemu_st8(tval, taddr, mem_index);
-} else if (size == 2) {
-tcg_gen_qemu_st16(tval, taddr, mem_index);
-} else {
-tcg_gen_qemu_st32(tval, taddr, mem_index);
-}
+
+tcg_gen_qemu_st_tl(tval, taddr, mem_index, ctz32(size) | MO_TE);
+
 gen_set_label(l1);
 tcg_gen_shri_tl(t1, t1, 1);  /* shift F to P position */
 tcg_gen_or_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], t1); /*P=F*/
@@ -109,13 +105,7 @@ static void gen_store_v10(DisasContext *dc, TCGv addr, 
TCGv val,
 return;
 }
 
-if (size == 1) {
-tcg_gen_qemu_st8(val, addr, mem_index);
-} else if (size == 2) {
-tcg_gen_qemu_st16(val, addr, mem_index);
-} else {
-tcg_gen_qemu_st32(val, addr, mem_index);
-}
+tcg_gen_qemu_st_tl(val, addr, mem_index, ctz32(size) | MO_TE);
 }
 
 
-- 
2.34.1




[PULL 31/42] tcg/ppc: Rationalize args to tcg_out_qemu_{ld,st}

2023-05-05 Thread Richard Henderson
Interpret the variable argument placement in the caller.  Pass data_type
instead of is64 -- there are several places where we already convert back
from bool to type.  Clean things up by using type throughout.

Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Richard Henderson 
---
 tcg/ppc/tcg-target.c.inc | 110 +--
 1 file changed, 59 insertions(+), 51 deletions(-)

diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 77abb7d20c..d1aa2a9f53 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -2118,7 +2118,8 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, MemOp opc,
 /* Record the context of a call to the out of line helper code for the slow
path for a load or store, so that we can later generate the correct
helper code.  */
-static void add_qemu_ldst_label(TCGContext *s, bool is_ld, MemOpIdx oi,
+static void add_qemu_ldst_label(TCGContext *s, bool is_ld,
+TCGType type, MemOpIdx oi,
 TCGReg datalo_reg, TCGReg datahi_reg,
 TCGReg addrlo_reg, TCGReg addrhi_reg,
 tcg_insn_unit *raddr, tcg_insn_unit *lptr)
@@ -2126,6 +2127,7 @@ static void add_qemu_ldst_label(TCGContext *s, bool 
is_ld, MemOpIdx oi,
 TCGLabelQemuLdst *label = new_ldst_label(s);
 
 label->is_ld = is_ld;
+label->type = type;
 label->oi = oi;
 label->datalo_reg = datalo_reg;
 label->datahi_reg = datahi_reg;
@@ -2288,30 +2290,18 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
 
 #endif /* SOFTMMU */
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
+static void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi,
+TCGReg addrlo, TCGReg addrhi,
+MemOpIdx oi, TCGType data_type)
 {
-TCGReg datalo, datahi, addrlo, rbase;
-TCGReg addrhi __attribute__((unused));
-MemOpIdx oi;
-MemOp opc, s_bits;
+MemOp opc = get_memop(oi);
+MemOp s_bits = opc & MO_SIZE;
+TCGReg rbase;
+
 #ifdef CONFIG_SOFTMMU
-int mem_index;
 tcg_insn_unit *label_ptr;
-#else
-unsigned a_bits;
-#endif
 
-datalo = *args++;
-datahi = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
-addrlo = *args++;
-addrhi = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
-oi = *args++;
-opc = get_memop(oi);
-s_bits = opc & MO_SIZE;
-
-#ifdef CONFIG_SOFTMMU
-mem_index = get_mmuidx(oi);
-addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, mem_index, true);
+addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, get_mmuidx(oi), true);
 
 /* Load a pointer into the current opcode w/conditional branch-link. */
 label_ptr = s->code_ptr;
@@ -2319,7 +2309,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg 
*args, bool is_64)
 
 rbase = TCG_REG_R3;
 #else  /* !CONFIG_SOFTMMU */
-a_bits = get_alignment_bits(opc);
+unsigned a_bits = get_alignment_bits(opc);
 if (a_bits) {
 tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits);
 }
@@ -2364,35 +2354,23 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg 
*args, bool is_64)
 }
 
 #ifdef CONFIG_SOFTMMU
-add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi,
-s->code_ptr, label_ptr);
+add_qemu_ldst_label(s, true, data_type, oi, datalo, datahi,
+addrlo, addrhi, s->code_ptr, label_ptr);
 #endif
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
+static void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi,
+TCGReg addrlo, TCGReg addrhi,
+MemOpIdx oi, TCGType data_type)
 {
-TCGReg datalo, datahi, addrlo, rbase;
-TCGReg addrhi __attribute__((unused));
-MemOpIdx oi;
-MemOp opc, s_bits;
+MemOp opc = get_memop(oi);
+MemOp s_bits = opc & MO_SIZE;
+TCGReg rbase;
+
 #ifdef CONFIG_SOFTMMU
-int mem_index;
 tcg_insn_unit *label_ptr;
-#else
-unsigned a_bits;
-#endif
 
-datalo = *args++;
-datahi = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
-addrlo = *args++;
-addrhi = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
-oi = *args++;
-opc = get_memop(oi);
-s_bits = opc & MO_SIZE;
-
-#ifdef CONFIG_SOFTMMU
-mem_index = get_mmuidx(oi);
-addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, mem_index, false);
+addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, get_mmuidx(oi), false);
 
 /* Load a pointer into the current opcode w/conditional branch-link. */
 label_ptr = s->code_ptr;
@@ -2400,7 +2378,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg 
*args, bool is_64)
 
 rbase = TCG_REG_R3;
 #else  /* !CONFIG_SOFTMMU */
-a_bits = get_alignment_bits(opc);
+unsigned a_bits = get_ali

[PULL 01/42] softfloat: Fix the incorrect computation in float32_exp2

2023-05-05 Thread Richard Henderson
From: Shivaprasad G Bhat 

The float32_exp2 function is computing wrong exponent of 2.

For example, with the following set of values {0.1, 2.0, 2.0, -1.0},
the expected output would be {1.071773, 4.00, 4.00, 0.50}.
Instead, the function is computing {1.119102, 3.382044, 3.382044, -0.191022}

Looking at the code, the float32_exp2() attempts to do this

  2 3 4 5   n
  xx x x x x   x
 e  = 1 + --- + --- + --- + --- + --- + ... + --- + ...
   1!2!3!4!5!  n!

But because of the typo it ends up doing

  xx x x x x   x
 e  = 1 + --- + --- + --- + --- + --- + ... + --- + ...
   1!2!3!4!5!  n!

This is because instead of the xnp which holds the numerator, parts_muladd
is using the xp which is just 'x'.  Commit '572c4d862ff2' refactored this
function, and mistakenly used xp instead of xnp.

Cc: qemu-sta...@nongnu.org
Fixes: 572c4d862ff2 "softfloat: Convert float32_exp2 to FloatParts"
Partially-Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1623
Reported-By: Luca Barbato (https://gitlab.com/lu-zero)
Signed-off-by: Shivaprasad G Bhat 
Signed-off-by: Vaibhav Jain 
Message-Id: 
<168304110865.537992.13059030916325018670.stgit@localhost.localdomain>
Reviewed-by: Richard Henderson 
Signed-off-by: Richard Henderson 
---
 fpu/softfloat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index c7454c3eb1..108f9cb224 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -5135,7 +5135,7 @@ float32 float32_exp2(float32 a, float_status *status)
 float64_unpack_canonical(&rp, float64_one, status);
 for (i = 0 ; i < 15 ; i++) {
 float64_unpack_canonical(&tp, float32_exp2_coefficients[i], status);
-rp = *parts_muladd(&tp, &xp, &rp, 0, status);
+rp = *parts_muladd(&tp, &xnp, &rp, 0, status);
 xnp = *parts_mul(&xnp, &xp, status);
 }
 
-- 
2.34.1




[PULL 39/42] tcg: Move TCGLabelQemuLdst to tcg.c

2023-05-05 Thread Richard Henderson
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/tcg.c  | 13 +
 tcg/tcg-ldst.c.inc | 14 --
 2 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index cfd3262a4a..6f5daaee5f 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -94,6 +94,19 @@ typedef struct QEMU_PACKED {
 DebugFrameFDEHeader fde;
 } DebugFrameHeader;
 
+typedef struct TCGLabelQemuLdst {
+bool is_ld; /* qemu_ld: true, qemu_st: false */
+MemOpIdx oi;
+TCGType type;   /* result type of a load */
+TCGReg addrlo_reg;  /* reg index for low word of guest virtual addr */
+TCGReg addrhi_reg;  /* reg index for high word of guest virtual addr */
+TCGReg datalo_reg;  /* reg index for low word to be loaded or stored */
+TCGReg datahi_reg;  /* reg index for high word to be loaded or stored 
*/
+const tcg_insn_unit *raddr;   /* addr of the next IR of qemu_ld/st IR */
+tcg_insn_unit *label_ptr[2]; /* label pointers to be updated */
+QSIMPLEQ_ENTRY(TCGLabelQemuLdst) next;
+} TCGLabelQemuLdst;
+
 static void tcg_register_jit_int(const void *buf, size_t size,
  const void *debug_frame,
  size_t debug_frame_size)
diff --git a/tcg/tcg-ldst.c.inc b/tcg/tcg-ldst.c.inc
index 403cbb0f06..ffada04af0 100644
--- a/tcg/tcg-ldst.c.inc
+++ b/tcg/tcg-ldst.c.inc
@@ -20,20 +20,6 @@
  * THE SOFTWARE.
  */
 
-typedef struct TCGLabelQemuLdst {
-bool is_ld; /* qemu_ld: true, qemu_st: false */
-MemOpIdx oi;
-TCGType type;   /* result type of a load */
-TCGReg addrlo_reg;  /* reg index for low word of guest virtual addr */
-TCGReg addrhi_reg;  /* reg index for high word of guest virtual addr */
-TCGReg datalo_reg;  /* reg index for low word to be loaded or stored */
-TCGReg datahi_reg;  /* reg index for high word to be loaded or stored 
*/
-const tcg_insn_unit *raddr;   /* addr of the next IR of qemu_ld/st IR */
-tcg_insn_unit *label_ptr[2]; /* label pointers to be updated */
-QSIMPLEQ_ENTRY(TCGLabelQemuLdst) next;
-} TCGLabelQemuLdst;
-
-
 /*
  * Generate TB finalization at the end of block
  */
-- 
2.34.1




[PULL 35/42] tcg/s390x: Pass TCGType to tcg_out_qemu_{ld,st}

2023-05-05 Thread Richard Henderson
We need to set this in TCGLabelQemuLdst, so plumb this
all the way through from tcg_out_op.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/s390x/tcg-target.c.inc | 22 ++
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
index b399798664..e931f0cde4 100644
--- a/tcg/s390x/tcg-target.c.inc
+++ b/tcg/s390x/tcg-target.c.inc
@@ -1770,13 +1770,14 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg 
addr_reg, MemOp opc,
 }
 
 static void add_qemu_ldst_label(TCGContext *s, bool is_ld, MemOpIdx oi,
-TCGReg data, TCGReg addr,
+TCGType type, TCGReg data, TCGReg addr,
 tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
 {
 TCGLabelQemuLdst *label = new_ldst_label(s);
 
 label->is_ld = is_ld;
 label->oi = oi;
+label->type = type;
 label->datalo_reg = data;
 label->addrlo_reg = addr;
 label->raddr = tcg_splitwx_to_rx(raddr);
@@ -1900,7 +1901,7 @@ static void tcg_prepare_user_ldst(TCGContext *s, TCGReg 
*addr_reg,
 #endif /* CONFIG_SOFTMMU */
 
 static void tcg_out_qemu_ld(TCGContext* s, TCGReg data_reg, TCGReg addr_reg,
-MemOpIdx oi)
+MemOpIdx oi, TCGType data_type)
 {
 MemOp opc = get_memop(oi);
 #ifdef CONFIG_SOFTMMU
@@ -1916,7 +1917,8 @@ static void tcg_out_qemu_ld(TCGContext* s, TCGReg 
data_reg, TCGReg addr_reg,
 
 tcg_out_qemu_ld_direct(s, opc, data_reg, base_reg, TCG_REG_R2, 0);
 
-add_qemu_ldst_label(s, 1, oi, data_reg, addr_reg, s->code_ptr, label_ptr);
+add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg,
+s->code_ptr, label_ptr);
 #else
 TCGReg index_reg;
 tcg_target_long disp;
@@ -1931,7 +1933,7 @@ static void tcg_out_qemu_ld(TCGContext* s, TCGReg 
data_reg, TCGReg addr_reg,
 }
 
 static void tcg_out_qemu_st(TCGContext* s, TCGReg data_reg, TCGReg addr_reg,
-MemOpIdx oi)
+MemOpIdx oi, TCGType data_type)
 {
 MemOp opc = get_memop(oi);
 #ifdef CONFIG_SOFTMMU
@@ -1947,7 +1949,8 @@ static void tcg_out_qemu_st(TCGContext* s, TCGReg 
data_reg, TCGReg addr_reg,
 
 tcg_out_qemu_st_direct(s, opc, data_reg, base_reg, TCG_REG_R2, 0);
 
-add_qemu_ldst_label(s, 0, oi, data_reg, addr_reg, s->code_ptr, label_ptr);
+add_qemu_ldst_label(s, false, oi, data_type, data_reg, addr_reg,
+s->code_ptr, label_ptr);
 #else
 TCGReg index_reg;
 tcg_target_long disp;
@@ -2307,13 +2310,16 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
 break;
 
 case INDEX_op_qemu_ld_i32:
-/* ??? Technically we can use a non-extending instruction.  */
+tcg_out_qemu_ld(s, args[0], args[1], args[2], TCG_TYPE_I32);
+break;
 case INDEX_op_qemu_ld_i64:
-tcg_out_qemu_ld(s, args[0], args[1], args[2]);
+tcg_out_qemu_ld(s, args[0], args[1], args[2], TCG_TYPE_I64);
 break;
 case INDEX_op_qemu_st_i32:
+tcg_out_qemu_st(s, args[0], args[1], args[2], TCG_TYPE_I32);
+break;
 case INDEX_op_qemu_st_i64:
-tcg_out_qemu_st(s, args[0], args[1], args[2]);
+tcg_out_qemu_st(s, args[0], args[1], args[2], TCG_TYPE_I64);
 break;
 
 case INDEX_op_ld16s_i64:
-- 
2.34.1




[PULL 36/42] tcg/s390x: Introduce HostAddress

2023-05-05 Thread Richard Henderson
Collect the 3 potential parts of the host address into a struct.
Reorg tcg_out_qemu_{ld,st}_direct to use it.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/s390x/tcg-target.c.inc | 109 -
 1 file changed, 60 insertions(+), 49 deletions(-)

diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
index e931f0cde4..da7ee5b085 100644
--- a/tcg/s390x/tcg-target.c.inc
+++ b/tcg/s390x/tcg-target.c.inc
@@ -1606,58 +1606,64 @@ static void tcg_out_call(TCGContext *s, const 
tcg_insn_unit *dest,
 tcg_out_call_int(s, dest);
 }
 
+typedef struct {
+TCGReg base;
+TCGReg index;
+int disp;
+} HostAddress;
+
 static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg data,
-   TCGReg base, TCGReg index, int disp)
+   HostAddress h)
 {
 switch (opc & (MO_SSIZE | MO_BSWAP)) {
 case MO_UB:
-tcg_out_insn(s, RXY, LLGC, data, base, index, disp);
+tcg_out_insn(s, RXY, LLGC, data, h.base, h.index, h.disp);
 break;
 case MO_SB:
-tcg_out_insn(s, RXY, LGB, data, base, index, disp);
+tcg_out_insn(s, RXY, LGB, data, h.base, h.index, h.disp);
 break;
 
 case MO_UW | MO_BSWAP:
 /* swapped unsigned halfword load with upper bits zeroed */
-tcg_out_insn(s, RXY, LRVH, data, base, index, disp);
+tcg_out_insn(s, RXY, LRVH, data, h.base, h.index, h.disp);
 tcg_out_ext16u(s, data, data);
 break;
 case MO_UW:
-tcg_out_insn(s, RXY, LLGH, data, base, index, disp);
+tcg_out_insn(s, RXY, LLGH, data, h.base, h.index, h.disp);
 break;
 
 case MO_SW | MO_BSWAP:
 /* swapped sign-extended halfword load */
-tcg_out_insn(s, RXY, LRVH, data, base, index, disp);
+tcg_out_insn(s, RXY, LRVH, data, h.base, h.index, h.disp);
 tcg_out_ext16s(s, TCG_TYPE_REG, data, data);
 break;
 case MO_SW:
-tcg_out_insn(s, RXY, LGH, data, base, index, disp);
+tcg_out_insn(s, RXY, LGH, data, h.base, h.index, h.disp);
 break;
 
 case MO_UL | MO_BSWAP:
 /* swapped unsigned int load with upper bits zeroed */
-tcg_out_insn(s, RXY, LRV, data, base, index, disp);
+tcg_out_insn(s, RXY, LRV, data, h.base, h.index, h.disp);
 tcg_out_ext32u(s, data, data);
 break;
 case MO_UL:
-tcg_out_insn(s, RXY, LLGF, data, base, index, disp);
+tcg_out_insn(s, RXY, LLGF, data, h.base, h.index, h.disp);
 break;
 
 case MO_SL | MO_BSWAP:
 /* swapped sign-extended int load */
-tcg_out_insn(s, RXY, LRV, data, base, index, disp);
+tcg_out_insn(s, RXY, LRV, data, h.base, h.index, h.disp);
 tcg_out_ext32s(s, data, data);
 break;
 case MO_SL:
-tcg_out_insn(s, RXY, LGF, data, base, index, disp);
+tcg_out_insn(s, RXY, LGF, data, h.base, h.index, h.disp);
 break;
 
 case MO_UQ | MO_BSWAP:
-tcg_out_insn(s, RXY, LRVG, data, base, index, disp);
+tcg_out_insn(s, RXY, LRVG, data, h.base, h.index, h.disp);
 break;
 case MO_UQ:
-tcg_out_insn(s, RXY, LG, data, base, index, disp);
+tcg_out_insn(s, RXY, LG, data, h.base, h.index, h.disp);
 break;
 
 default:
@@ -1666,44 +1672,44 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp 
opc, TCGReg data,
 }
 
 static void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg data,
-   TCGReg base, TCGReg index, int disp)
+   HostAddress h)
 {
 switch (opc & (MO_SIZE | MO_BSWAP)) {
 case MO_UB:
-if (disp >= 0 && disp < 0x1000) {
-tcg_out_insn(s, RX, STC, data, base, index, disp);
+if (h.disp >= 0 && h.disp < 0x1000) {
+tcg_out_insn(s, RX, STC, data, h.base, h.index, h.disp);
 } else {
-tcg_out_insn(s, RXY, STCY, data, base, index, disp);
+tcg_out_insn(s, RXY, STCY, data, h.base, h.index, h.disp);
 }
 break;
 
 case MO_UW | MO_BSWAP:
-tcg_out_insn(s, RXY, STRVH, data, base, index, disp);
+tcg_out_insn(s, RXY, STRVH, data, h.base, h.index, h.disp);
 break;
 case MO_UW:
-if (disp >= 0 && disp < 0x1000) {
-tcg_out_insn(s, RX, STH, data, base, index, disp);
+if (h.disp >= 0 && h.disp < 0x1000) {
+tcg_out_insn(s, RX, STH, data, h.base, h.index, h.disp);
 } else {
-tcg_out_insn(s, RXY, STHY, data, base, index, disp);
+tcg_out_insn(s, RXY, STHY, data, h.base, h.index, h.disp);
 }
 break;
 
 case MO_UL | MO_BSWAP:
-tcg_out_insn(s, RXY, STRV, data, base, index, disp);
+tcg_out_insn(s, RXY, STRV, data, h.base, h.index, h.disp);
 break;
 case MO_UL:
-if (disp >= 0 && disp < 0x1000) {
-tcg_

[PULL 38/42] tcg/sparc64: Pass TCGType to tcg_out_qemu_{ld,st}

2023-05-05 Thread Richard Henderson
We need to set this in TCGLabelQemuLdst, so plumb this
all the way through from tcg_out_op.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/sparc64/tcg-target.c.inc | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
index dbe4bf96b9..7e6466d3b6 100644
--- a/tcg/sparc64/tcg-target.c.inc
+++ b/tcg/sparc64/tcg-target.c.inc
@@ -1178,7 +1178,7 @@ static const int qemu_st_opc[(MO_SIZE | MO_BSWAP) + 1] = {
 };
 
 static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
-MemOpIdx oi, bool is_64)
+MemOpIdx oi, TCGType data_type)
 {
 MemOp memop = get_memop(oi);
 tcg_insn_unit *label_ptr;
@@ -1636,10 +1636,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 break;
 
 case INDEX_op_qemu_ld_i32:
-tcg_out_qemu_ld(s, a0, a1, a2, false);
+tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32);
 break;
 case INDEX_op_qemu_ld_i64:
-tcg_out_qemu_ld(s, a0, a1, a2, true);
+tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64);
 break;
 case INDEX_op_qemu_st_i32:
 tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32);
-- 
2.34.1




[PULL 24/42] tcg/aarch64: Rationalize args to tcg_out_qemu_{ld,st}

2023-05-05 Thread Richard Henderson
Rename the 'ext' parameter 'data_type' to make the use clearer;
pass it to tcg_out_qemu_st as well to even out the interfaces.
Rename the 'otype' local 'addr_type' to make the use clearer.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/aarch64/tcg-target.c.inc | 36 +---
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 4ec3cf3172..ecbf6564fc 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -1851,22 +1851,21 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp 
memop,
 }
 
 static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
-MemOpIdx oi, TCGType ext)
+MemOpIdx oi, TCGType data_type)
 {
 MemOp memop = get_memop(oi);
-const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
+TCGType addr_type = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
 
 /* Byte swapping is left to middle-end expansion. */
 tcg_debug_assert((memop & MO_BSWAP) == 0);
 
 #ifdef CONFIG_SOFTMMU
-unsigned mem_index = get_mmuidx(oi);
 tcg_insn_unit *label_ptr;
 
-tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, mem_index, 1);
-tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
-   TCG_REG_X1, otype, addr_reg);
-add_qemu_ldst_label(s, true, oi, ext, data_reg, addr_reg,
+tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, get_mmuidx(oi), 1);
+tcg_out_qemu_ld_direct(s, memop, data_type, data_reg,
+   TCG_REG_X1, addr_type, addr_reg);
+add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg,
 s->code_ptr, label_ptr);
 #else /* !CONFIG_SOFTMMU */
 unsigned a_bits = get_alignment_bits(memop);
@@ -1874,33 +1873,32 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg 
data_reg, TCGReg addr_reg,
 tcg_out_test_alignment(s, true, addr_reg, a_bits);
 }
 if (USE_GUEST_BASE) {
-tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
-   TCG_REG_GUEST_BASE, otype, addr_reg);
+tcg_out_qemu_ld_direct(s, memop, data_type, data_reg,
+   TCG_REG_GUEST_BASE, addr_type, addr_reg);
 } else {
-tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
+tcg_out_qemu_ld_direct(s, memop, data_type, data_reg,
addr_reg, TCG_TYPE_I64, TCG_REG_XZR);
 }
 #endif /* CONFIG_SOFTMMU */
 }
 
 static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
-MemOpIdx oi)
+MemOpIdx oi, TCGType data_type)
 {
 MemOp memop = get_memop(oi);
-const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
+TCGType addr_type = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
 
 /* Byte swapping is left to middle-end expansion. */
 tcg_debug_assert((memop & MO_BSWAP) == 0);
 
 #ifdef CONFIG_SOFTMMU
-unsigned mem_index = get_mmuidx(oi);
 tcg_insn_unit *label_ptr;
 
-tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, mem_index, 0);
+tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, get_mmuidx(oi), 0);
 tcg_out_qemu_st_direct(s, memop, data_reg,
-   TCG_REG_X1, otype, addr_reg);
-add_qemu_ldst_label(s, false, oi, (memop & MO_SIZE)== MO_64,
-data_reg, addr_reg, s->code_ptr, label_ptr);
+   TCG_REG_X1, addr_type, addr_reg);
+add_qemu_ldst_label(s, false, oi, data_type, data_reg, addr_reg,
+s->code_ptr, label_ptr);
 #else /* !CONFIG_SOFTMMU */
 unsigned a_bits = get_alignment_bits(memop);
 if (a_bits) {
@@ -1908,7 +1906,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg 
data_reg, TCGReg addr_reg,
 }
 if (USE_GUEST_BASE) {
 tcg_out_qemu_st_direct(s, memop, data_reg,
-   TCG_REG_GUEST_BASE, otype, addr_reg);
+   TCG_REG_GUEST_BASE, addr_type, addr_reg);
 } else {
 tcg_out_qemu_st_direct(s, memop, data_reg,
addr_reg, TCG_TYPE_I64, TCG_REG_XZR);
@@ -2249,7 +2247,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 break;
 case INDEX_op_qemu_st_i32:
 case INDEX_op_qemu_st_i64:
-tcg_out_qemu_st(s, REG0(0), a1, a2);
+tcg_out_qemu_st(s, REG0(0), a1, a2, ext);
 break;
 
 case INDEX_op_bswap64_i64:
-- 
2.34.1




[PULL 29/42] tcg/loongarch64: Introduce HostAddress

2023-05-05 Thread Richard Henderson
Collect the 2 parts of the host address into a struct.
Reorg tcg_out_qemu_{ld,st}_direct to use it.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 55 +---
 1 file changed, 30 insertions(+), 25 deletions(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 2e3c67054b..6a87a5e5a3 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1013,36 +1013,41 @@ static TCGReg tcg_out_zext_addr_if_32_bit(TCGContext *s,
 return addr;
 }
 
-static void tcg_out_qemu_ld_indexed(TCGContext *s, TCGReg rd, TCGReg rj,
-   TCGReg rk, MemOp opc, TCGType type)
+typedef struct {
+TCGReg base;
+TCGReg index;
+} HostAddress;
+
+static void tcg_out_qemu_ld_indexed(TCGContext *s, MemOp opc, TCGType type,
+TCGReg rd, HostAddress h)
 {
 /* Byte swapping is left to middle-end expansion.  */
 tcg_debug_assert((opc & MO_BSWAP) == 0);
 
 switch (opc & MO_SSIZE) {
 case MO_UB:
-tcg_out_opc_ldx_bu(s, rd, rj, rk);
+tcg_out_opc_ldx_bu(s, rd, h.base, h.index);
 break;
 case MO_SB:
-tcg_out_opc_ldx_b(s, rd, rj, rk);
+tcg_out_opc_ldx_b(s, rd, h.base, h.index);
 break;
 case MO_UW:
-tcg_out_opc_ldx_hu(s, rd, rj, rk);
+tcg_out_opc_ldx_hu(s, rd, h.base, h.index);
 break;
 case MO_SW:
-tcg_out_opc_ldx_h(s, rd, rj, rk);
+tcg_out_opc_ldx_h(s, rd, h.base, h.index);
 break;
 case MO_UL:
 if (type == TCG_TYPE_I64) {
-tcg_out_opc_ldx_wu(s, rd, rj, rk);
+tcg_out_opc_ldx_wu(s, rd, h.base, h.index);
 break;
 }
 /* fallthrough */
 case MO_SL:
-tcg_out_opc_ldx_w(s, rd, rj, rk);
+tcg_out_opc_ldx_w(s, rd, h.base, h.index);
 break;
 case MO_UQ:
-tcg_out_opc_ldx_d(s, rd, rj, rk);
+tcg_out_opc_ldx_d(s, rd, h.base, h.index);
 break;
 default:
 g_assert_not_reached();
@@ -1053,23 +1058,23 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg 
data_reg, TCGReg addr_reg,
 MemOpIdx oi, TCGType data_type)
 {
 MemOp opc = get_memop(oi);
-TCGReg base, index;
+HostAddress h;
 
 #ifdef CONFIG_SOFTMMU
 tcg_insn_unit *label_ptr[1];
 
 tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 1);
-index = TCG_REG_TMP2;
+h.index = TCG_REG_TMP2;
 #else
 unsigned a_bits = get_alignment_bits(opc);
 if (a_bits) {
 tcg_out_test_alignment(s, true, addr_reg, a_bits);
 }
-index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO;
+h.index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO;
 #endif
 
-base = tcg_out_zext_addr_if_32_bit(s, addr_reg, TCG_REG_TMP0);
-tcg_out_qemu_ld_indexed(s, data_reg, base, index, opc, data_type);
+h.base = tcg_out_zext_addr_if_32_bit(s, addr_reg, TCG_REG_TMP0);
+tcg_out_qemu_ld_indexed(s, opc, data_type, data_reg, h);
 
 #ifdef CONFIG_SOFTMMU
 add_qemu_ldst_label(s, true, oi, data_type, data_reg, addr_reg,
@@ -1077,24 +1082,24 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg 
data_reg, TCGReg addr_reg,
 #endif
 }
 
-static void tcg_out_qemu_st_indexed(TCGContext *s, TCGReg data,
-   TCGReg rj, TCGReg rk, MemOp opc)
+static void tcg_out_qemu_st_indexed(TCGContext *s, MemOp opc,
+TCGReg rd, HostAddress h)
 {
 /* Byte swapping is left to middle-end expansion.  */
 tcg_debug_assert((opc & MO_BSWAP) == 0);
 
 switch (opc & MO_SIZE) {
 case MO_8:
-tcg_out_opc_stx_b(s, data, rj, rk);
+tcg_out_opc_stx_b(s, rd, h.base, h.index);
 break;
 case MO_16:
-tcg_out_opc_stx_h(s, data, rj, rk);
+tcg_out_opc_stx_h(s, rd, h.base, h.index);
 break;
 case MO_32:
-tcg_out_opc_stx_w(s, data, rj, rk);
+tcg_out_opc_stx_w(s, rd, h.base, h.index);
 break;
 case MO_64:
-tcg_out_opc_stx_d(s, data, rj, rk);
+tcg_out_opc_stx_d(s, rd, h.base, h.index);
 break;
 default:
 g_assert_not_reached();
@@ -1105,23 +1110,23 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg 
data_reg, TCGReg addr_reg,
 MemOpIdx oi, TCGType data_type)
 {
 MemOp opc = get_memop(oi);
-TCGReg base, index;
+HostAddress h;
 
 #ifdef CONFIG_SOFTMMU
 tcg_insn_unit *label_ptr[1];
 
 tcg_out_tlb_load(s, addr_reg, oi, label_ptr, 0);
-index = TCG_REG_TMP2;
+h.index = TCG_REG_TMP2;
 #else
 unsigned a_bits = get_alignment_bits(opc);
 if (a_bits) {
 tcg_out_test_alignment(s, false, addr_reg, a_bits);
 }
-index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO;
+h.index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO;
 #endif
 
-base = tcg_out_ze

[PULL 00/42] tcg patch queue

2023-05-05 Thread Richard Henderson
The following changes since commit a9fe9e191b4305b88c356a1ed9ac3baf89eb18aa:

  Merge tag 'pull-riscv-to-apply-20230505-1' of 
https://github.com/alistair23/qemu into staging (2023-05-05 09:25:13 +0100)

are available in the Git repository at:

  https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20230505

for you to fetch changes up to 35a0bd63b458f30389b6bc6b7471c1665fe7b9d8:

  tcg: Widen helper_*_st[bw]_mmu val arguments (2023-05-05 17:21:03 +0100)


softfloat: Fix the incorrect computation in float32_exp2
tcg: Remove compatability helpers for qemu ld/st
target/alpha: Remove TARGET_ALIGNED_ONLY
target/hppa: Remove TARGET_ALIGNED_ONLY
target/sparc: Remove TARGET_ALIGNED_ONLY
tcg: Cleanups preparing to unify calls to qemu_ld/st helpers


Richard Henderson (41):
  target/avr: Finish conversion to tcg_gen_qemu_{ld,st}_*
  target/cris: Finish conversion to tcg_gen_qemu_{ld,st}_*
  target/Hexagon: Finish conversion to tcg_gen_qemu_{ld, st}_*
  target/m68k: Finish conversion to tcg_gen_qemu_{ld,st}_*
  target/mips: Finish conversion to tcg_gen_qemu_{ld,st}_*
  target/s390x: Finish conversion to tcg_gen_qemu_{ld, st}_*
  target/sparc: Finish conversion to tcg_gen_qemu_{ld, st}_*
  target/xtensa: Finish conversion to tcg_gen_qemu_{ld, st}_*
  tcg: Remove compatability helpers for qemu ld/st
  target/alpha: Use MO_ALIGN for system UNALIGN()
  target/alpha: Use MO_ALIGN where required
  target/alpha: Remove TARGET_ALIGNED_ONLY
  target/hppa: Use MO_ALIGN for system UNALIGN()
  target/hppa: Remove TARGET_ALIGNED_ONLY
  target/sparc: Use MO_ALIGN where required
  target/sparc: Use cpu_ld*_code_mmu
  target/sparc: Remove TARGET_ALIGNED_ONLY
  tcg/i386: Rationalize args to tcg_out_qemu_{ld,st}
  tcg/i386: Generalize multi-part load overlap test
  tcg/i386: Introduce HostAddress
  tcg/i386: Drop r0+r1 local variables from tcg_out_tlb_load
  tcg/i386: Introduce tcg_out_testi
  tcg/aarch64: Rationalize args to tcg_out_qemu_{ld,st}
  tcg/aarch64: Introduce HostAddress
  tcg/arm: Rationalize args to tcg_out_qemu_{ld,st}
  tcg/arm: Introduce HostAddress
  tcg/loongarch64: Rationalize args to tcg_out_qemu_{ld,st}
  tcg/loongarch64: Introduce HostAddress
  tcg/mips: Rationalize args to tcg_out_qemu_{ld,st}
  tcg/ppc: Rationalize args to tcg_out_qemu_{ld,st}
  tcg/ppc: Introduce HostAddress
  tcg/riscv: Require TCG_TARGET_REG_BITS == 64
  tcg/riscv: Rationalize args to tcg_out_qemu_{ld,st}
  tcg/s390x: Pass TCGType to tcg_out_qemu_{ld,st}
  tcg/s390x: Introduce HostAddress
  tcg/sparc64: Drop is_64 test from tcg_out_qemu_ld data return
  tcg/sparc64: Pass TCGType to tcg_out_qemu_{ld,st}
  tcg: Move TCGLabelQemuLdst to tcg.c
  tcg: Replace REG_P with arg_loc_reg_p
  tcg: Introduce arg_slot_stk_ofs
  tcg: Widen helper_*_st[bw]_mmu val arguments

Shivaprasad G Bhat (1):
  softfloat: Fix the incorrect computation in float32_exp2

 configs/targets/alpha-linux-user.mak|   1 -
 configs/targets/alpha-softmmu.mak   |   1 -
 configs/targets/hppa-linux-user.mak |   1 -
 configs/targets/hppa-softmmu.mak|   1 -
 configs/targets/sparc-linux-user.mak|   1 -
 configs/targets/sparc-softmmu.mak   |   1 -
 configs/targets/sparc32plus-linux-user.mak  |   1 -
 configs/targets/sparc64-linux-user.mak  |   1 -
 configs/targets/sparc64-softmmu.mak |   1 -
 include/tcg/tcg-ldst.h  |  10 +-
 include/tcg/tcg-op.h|  55 -
 target/hexagon/macros.h |  14 +-
 tcg/riscv/tcg-target-con-set.h  |   8 -
 tcg/riscv/tcg-target.h  |  22 +-
 tcg/tcg-internal.h  |   4 -
 accel/tcg/cputlb.c  |   6 +-
 fpu/softfloat.c |   2 +-
 target/alpha/translate.c|  38 +--
 target/avr/translate.c  |  16 +-
 target/hexagon/genptr.c |   8 +-
 target/hexagon/idef-parser/parser-helpers.c |  28 +--
 target/hexagon/translate.c  |  32 +--
 target/hppa/translate.c |   2 +-
 target/m68k/translate.c |  76 ++
 target/mips/tcg/translate.c |   8 +-
 target/s390x/tcg/translate.c| 152 ++--
 target/sparc/ldst_helper.c  |  10 +-
 target/sparc/translate.c|  85 ---
 target/xtensa/translate.c   |   4 +-
 tcg/tcg.c   |  58 +++--
 target/cris/translate_v10.c.inc |  18 +-
 target/mips/tcg/nanomips_translate.c.inc|   2 +-
 tcg/aarch64/tcg-target.c.inc| 108 ++---
 tcg/arm/tcg-ta

[PULL 04/42] target/Hexagon: Finish conversion to tcg_gen_qemu_{ld, st}_*

2023-05-05 Thread Richard Henderson
Convert away from the old interface with the implicit
MemOp argument.  Importantly, this removes some incorrect
casts generated by idef-parser's gen_load().

Signed-off-by: Richard Henderson 
Tested-by: Taylor Simpson 
Reviewed-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230502135741.1158035-4-richard.hender...@linaro.org>
---
 target/hexagon/macros.h | 14 -
 target/hexagon/genptr.c |  8 +++---
 target/hexagon/idef-parser/parser-helpers.c | 28 +-
 target/hexagon/translate.c  | 32 ++---
 4 files changed, 40 insertions(+), 42 deletions(-)

diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 3e162de3a7..760630de8f 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -99,37 +99,37 @@
 #define MEM_LOAD1s(DST, VA) \
 do { \
 CHECK_NOSHUF(VA, 1); \
-tcg_gen_qemu_ld8s(DST, VA, ctx->mem_idx); \
+tcg_gen_qemu_ld_tl(DST, VA, ctx->mem_idx, MO_SB); \
 } while (0)
 #define MEM_LOAD1u(DST, VA) \
 do { \
 CHECK_NOSHUF(VA, 1); \
-tcg_gen_qemu_ld8u(DST, VA, ctx->mem_idx); \
+tcg_gen_qemu_ld_tl(DST, VA, ctx->mem_idx, MO_UB); \
 } while (0)
 #define MEM_LOAD2s(DST, VA) \
 do { \
 CHECK_NOSHUF(VA, 2); \
-tcg_gen_qemu_ld16s(DST, VA, ctx->mem_idx); \
+tcg_gen_qemu_ld_tl(DST, VA, ctx->mem_idx, MO_TESW); \
 } while (0)
 #define MEM_LOAD2u(DST, VA) \
 do { \
 CHECK_NOSHUF(VA, 2); \
-tcg_gen_qemu_ld16u(DST, VA, ctx->mem_idx); \
+tcg_gen_qemu_ld_tl(DST, VA, ctx->mem_idx, MO_TEUW); \
 } while (0)
 #define MEM_LOAD4s(DST, VA) \
 do { \
 CHECK_NOSHUF(VA, 4); \
-tcg_gen_qemu_ld32s(DST, VA, ctx->mem_idx); \
+tcg_gen_qemu_ld_tl(DST, VA, ctx->mem_idx, MO_TESL); \
 } while (0)
 #define MEM_LOAD4u(DST, VA) \
 do { \
 CHECK_NOSHUF(VA, 4); \
-tcg_gen_qemu_ld32s(DST, VA, ctx->mem_idx); \
+tcg_gen_qemu_ld_tl(DST, VA, ctx->mem_idx, MO_TEUL); \
 } while (0)
 #define MEM_LOAD8u(DST, VA) \
 do { \
 CHECK_NOSHUF(VA, 8); \
-tcg_gen_qemu_ld64(DST, VA, ctx->mem_idx); \
+tcg_gen_qemu_ld_i64(DST, VA, ctx->mem_idx, MO_TEUQ); \
 } while (0)
 
 #define MEM_STORE1_FUNC(X) \
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 502c85ae35..244063b1d2 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -320,14 +320,14 @@ void gen_set_byte_i64(int N, TCGv_i64 result, TCGv src)
 
 static inline void gen_load_locked4u(TCGv dest, TCGv vaddr, int mem_index)
 {
-tcg_gen_qemu_ld32u(dest, vaddr, mem_index);
+tcg_gen_qemu_ld_tl(dest, vaddr, mem_index, MO_TEUL);
 tcg_gen_mov_tl(hex_llsc_addr, vaddr);
 tcg_gen_mov_tl(hex_llsc_val, dest);
 }
 
 static inline void gen_load_locked8u(TCGv_i64 dest, TCGv vaddr, int mem_index)
 {
-tcg_gen_qemu_ld64(dest, vaddr, mem_index);
+tcg_gen_qemu_ld_i64(dest, vaddr, mem_index, MO_TEUQ);
 tcg_gen_mov_tl(hex_llsc_addr, vaddr);
 tcg_gen_mov_i64(hex_llsc_val_i64, dest);
 }
@@ -678,7 +678,7 @@ static void gen_load_frame(DisasContext *ctx, TCGv_i64 
frame, TCGv EA)
 {
 Insn *insn = ctx->insn;  /* Needed for CHECK_NOSHUF */
 CHECK_NOSHUF(EA, 8);
-tcg_gen_qemu_ld64(frame, EA, ctx->mem_idx);
+tcg_gen_qemu_ld_i64(frame, EA, ctx->mem_idx, MO_TEUQ);
 }
 
 static void gen_return(DisasContext *ctx, TCGv_i64 dst, TCGv src)
@@ -1019,7 +1019,7 @@ static void gen_vreg_load(DisasContext *ctx, intptr_t 
dstoff, TCGv src,
 tcg_gen_andi_tl(src, src, ~((int32_t)sizeof(MMVector) - 1));
 }
 for (int i = 0; i < sizeof(MMVector) / 8; i++) {
-tcg_gen_qemu_ld64(tmp, src, ctx->mem_idx);
+tcg_gen_qemu_ld_i64(tmp, src, ctx->mem_idx, MO_TEUQ);
 tcg_gen_addi_tl(src, src, 8);
 tcg_gen_st_i64(tmp, cpu_env, dstoff + i * 8);
 }
diff --git a/target/hexagon/idef-parser/parser-helpers.c 
b/target/hexagon/idef-parser/parser-helpers.c
index 86511efb62..8734218e51 100644
--- a/target/hexagon/idef-parser/parser-helpers.c
+++ b/target/hexagon/idef-parser/parser-helpers.c
@@ -1737,36 +1737,34 @@ void gen_load_cancel(Context *c, YYLTYPE *locp)
 void gen_load(Context *c, YYLTYPE *locp, HexValue *width,
   HexSignedness signedness, HexValue *ea, HexValue *dst)
 {
-char size_suffix[4] = {0};
-const char *sign_suffix;
+unsigned dst_bit_width;
+unsigned src_bit_width;
+
 /* Memop width is specified in the load macro */
 assert_signedness(c, locp, signedness);
-sign_suffix = (width->imm.value > 4)
-   ? ""
-   : ((signedness == UNSIGNED) ? "u" : "s");
+
 /* If dst is a variable, assert that is declared and load the type info */
 if (dst->type == VARID) {
 find_variable(c, locp, dst, dst);
 }
 
-snprintf(size_suffix, 4, "%" PRIu64, width->imm.value * 8);
+src_bit_width = width->imm.value * 8;
+  

[PULL 20/42] tcg/i386: Generalize multi-part load overlap test

2023-05-05 Thread Richard Henderson
Test for both base and index; use datahi as a temporary, overwritten
by the final load.  Always perform the loads in ascending order, so
that any (user-only) fault sees the correct address.

Signed-off-by: Richard Henderson 
---
 tcg/i386/tcg-target.c.inc | 31 +++
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index cfa2349b03..173f3c3172 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -2221,23 +2221,22 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, 
TCGReg datalo, TCGReg datahi,
 if (TCG_TARGET_REG_BITS == 64) {
 tcg_out_modrm_sib_offset(s, movop + P_REXW + seg, datalo,
  base, index, 0, ofs);
+break;
+}
+if (use_movbe) {
+TCGReg t = datalo;
+datalo = datahi;
+datahi = t;
+}
+if (base == datalo || index == datalo) {
+tcg_out_modrm_sib_offset(s, OPC_LEA, datahi, base, index, 0, ofs);
+tcg_out_modrm_offset(s, movop + seg, datalo, datahi, 0);
+tcg_out_modrm_offset(s, movop + seg, datahi, datahi, 4);
 } else {
-if (use_movbe) {
-TCGReg t = datalo;
-datalo = datahi;
-datahi = t;
-}
-if (base != datalo) {
-tcg_out_modrm_sib_offset(s, movop + seg, datalo,
- base, index, 0, ofs);
-tcg_out_modrm_sib_offset(s, movop + seg, datahi,
- base, index, 0, ofs + 4);
-} else {
-tcg_out_modrm_sib_offset(s, movop + seg, datahi,
- base, index, 0, ofs + 4);
-tcg_out_modrm_sib_offset(s, movop + seg, datalo,
- base, index, 0, ofs);
-}
+tcg_out_modrm_sib_offset(s, movop + seg, datalo,
+ base, index, 0, ofs);
+tcg_out_modrm_sib_offset(s, movop + seg, datahi,
+ base, index, 0, ofs + 4);
 }
 break;
 default:
-- 
2.34.1




[PULL 08/42] target/sparc: Finish conversion to tcg_gen_qemu_{ld, st}_*

2023-05-05 Thread Richard Henderson
Convert away from the old interface with the implicit
MemOp argument.

Signed-off-by: Richard Henderson 
Reviewed-by: Anton Johansson 
Message-Id: <20230502135741.1158035-8-richard.hender...@linaro.org>
---
 target/sparc/translate.c | 43 ++--
 1 file changed, 28 insertions(+), 15 deletions(-)

diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 137bdc5159..bc71e44e66 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -5179,15 +5179,18 @@ static void disas_sparc_insn(DisasContext * dc, 
unsigned int insn)
 switch (xop) {
 case 0x0:   /* ld, V9 lduw, load unsigned word */
 gen_address_mask(dc, cpu_addr);
-tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx);
+tcg_gen_qemu_ld_tl(cpu_val, cpu_addr,
+   dc->mem_idx, MO_TEUL);
 break;
 case 0x1:   /* ldub, load unsigned byte */
 gen_address_mask(dc, cpu_addr);
-tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx);
+tcg_gen_qemu_ld_tl(cpu_val, cpu_addr,
+   dc->mem_idx, MO_UB);
 break;
 case 0x2:   /* lduh, load unsigned halfword */
 gen_address_mask(dc, cpu_addr);
-tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx);
+tcg_gen_qemu_ld_tl(cpu_val, cpu_addr,
+   dc->mem_idx, MO_TEUW);
 break;
 case 0x3:   /* ldd, load double word */
 if (rd & 1)
@@ -5197,7 +5200,8 @@ static void disas_sparc_insn(DisasContext * dc, unsigned 
int insn)
 
 gen_address_mask(dc, cpu_addr);
 t64 = tcg_temp_new_i64();
-tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx);
+tcg_gen_qemu_ld_i64(t64, cpu_addr,
+dc->mem_idx, MO_TEUQ);
 tcg_gen_trunc_i64_tl(cpu_val, t64);
 tcg_gen_ext32u_tl(cpu_val, cpu_val);
 gen_store_gpr(dc, rd + 1, cpu_val);
@@ -5208,11 +5212,12 @@ static void disas_sparc_insn(DisasContext * dc, 
unsigned int insn)
 break;
 case 0x9:   /* ldsb, load signed byte */
 gen_address_mask(dc, cpu_addr);
-tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx);
+tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, dc->mem_idx, MO_SB);
 break;
 case 0xa:   /* ldsh, load signed halfword */
 gen_address_mask(dc, cpu_addr);
-tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx);
+tcg_gen_qemu_ld_tl(cpu_val, cpu_addr,
+   dc->mem_idx, MO_TESW);
 break;
 case 0xd:   /* ldstub */
 gen_ldstub(dc, cpu_val, cpu_addr, dc->mem_idx);
@@ -5266,11 +5271,13 @@ static void disas_sparc_insn(DisasContext * dc, 
unsigned int insn)
 #ifdef TARGET_SPARC64
 case 0x08: /* V9 ldsw */
 gen_address_mask(dc, cpu_addr);
-tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx);
+tcg_gen_qemu_ld_tl(cpu_val, cpu_addr,
+   dc->mem_idx, MO_TESL);
 break;
 case 0x0b: /* V9 ldx */
 gen_address_mask(dc, cpu_addr);
-tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx);
+tcg_gen_qemu_ld_tl(cpu_val, cpu_addr,
+   dc->mem_idx, MO_TEUQ);
 break;
 case 0x18: /* V9 ldswa */
 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESL);
@@ -5369,15 +5376,17 @@ static void disas_sparc_insn(DisasContext * dc, 
unsigned int insn)
 switch (xop) {
 case 0x4: /* st, store word */
 gen_address_mask(dc, cpu_addr);
-tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx);
+tcg_gen_qemu_st_tl(cpu_val, cpu_addr,
+   dc->mem_idx, MO_TEUL);
 break;
 case 0x5: /* stb, store byte */
 gen_address_mask(dc, cpu_addr);
-tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx);
+tcg_gen_qemu_st_tl(cpu_val, cpu_addr, dc->mem_idx, MO_UB);
 break;
 case 0x6: /* sth, store halfword */
 gen_address_mask(dc, cpu_addr);
-tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx);
+tcg_gen_qemu_

[PULL 18/42] target/sparc: Remove TARGET_ALIGNED_ONLY

2023-05-05 Thread Richard Henderson
Reviewed-by: Mark Cave-Ayland 
Signed-off-by: Richard Henderson 
---
 configs/targets/sparc-linux-user.mak   | 1 -
 configs/targets/sparc-softmmu.mak  | 1 -
 configs/targets/sparc32plus-linux-user.mak | 1 -
 configs/targets/sparc64-linux-user.mak | 1 -
 configs/targets/sparc64-softmmu.mak| 1 -
 5 files changed, 5 deletions(-)

diff --git a/configs/targets/sparc-linux-user.mak 
b/configs/targets/sparc-linux-user.mak
index 00e7bc1f07..abcfb8fc62 100644
--- a/configs/targets/sparc-linux-user.mak
+++ b/configs/targets/sparc-linux-user.mak
@@ -1,5 +1,4 @@
 TARGET_ARCH=sparc
 TARGET_SYSTBL_ABI=common,32
 TARGET_SYSTBL=syscall.tbl
-TARGET_ALIGNED_ONLY=y
 TARGET_BIG_ENDIAN=y
diff --git a/configs/targets/sparc-softmmu.mak 
b/configs/targets/sparc-softmmu.mak
index a849190f01..454eb35499 100644
--- a/configs/targets/sparc-softmmu.mak
+++ b/configs/targets/sparc-softmmu.mak
@@ -1,3 +1,2 @@
 TARGET_ARCH=sparc
-TARGET_ALIGNED_ONLY=y
 TARGET_BIG_ENDIAN=y
diff --git a/configs/targets/sparc32plus-linux-user.mak 
b/configs/targets/sparc32plus-linux-user.mak
index a65c0951a1..6cc8fa516b 100644
--- a/configs/targets/sparc32plus-linux-user.mak
+++ b/configs/targets/sparc32plus-linux-user.mak
@@ -4,5 +4,4 @@ TARGET_BASE_ARCH=sparc
 TARGET_ABI_DIR=sparc
 TARGET_SYSTBL_ABI=common,32
 TARGET_SYSTBL=syscall.tbl
-TARGET_ALIGNED_ONLY=y
 TARGET_BIG_ENDIAN=y
diff --git a/configs/targets/sparc64-linux-user.mak 
b/configs/targets/sparc64-linux-user.mak
index 20fcb93fa4..52f05ec000 100644
--- a/configs/targets/sparc64-linux-user.mak
+++ b/configs/targets/sparc64-linux-user.mak
@@ -3,5 +3,4 @@ TARGET_BASE_ARCH=sparc
 TARGET_ABI_DIR=sparc
 TARGET_SYSTBL_ABI=common,64
 TARGET_SYSTBL=syscall.tbl
-TARGET_ALIGNED_ONLY=y
 TARGET_BIG_ENDIAN=y
diff --git a/configs/targets/sparc64-softmmu.mak 
b/configs/targets/sparc64-softmmu.mak
index c626ac3eae..d3f8a3b710 100644
--- a/configs/targets/sparc64-softmmu.mak
+++ b/configs/targets/sparc64-softmmu.mak
@@ -1,4 +1,3 @@
 TARGET_ARCH=sparc64
 TARGET_BASE_ARCH=sparc
-TARGET_ALIGNED_ONLY=y
 TARGET_BIG_ENDIAN=y
-- 
2.34.1




  1   2   3   4   >