On 8/30/23 01:48, Song Gao wrote:
+#ifndef CONFIG_USER_ONLY
+ #define CHECK_VEC do { \
+ if ((ctx->vl == LSX_LEN) && \
+ (ctx->base.tb->flags & HW_FLAGS_EUEN_SXE) == 0) { \
+ generate_exception(ctx, EXCCODE_SXD); \
+ return true; \
+ } \
+ if ((ctx->vl == LASX_LEN) && \
+ (ctx->base.tb->flags & HW_FLAGS_EUEN_ASXE) == 0) { \
+ generate_exception(ctx, EXCCODE_ASXD); \
+ return true; \
+ } \
+ } while (0)
+#else
+ #define CHECK_VEC
+#endif /*!CONFIG_USER_ONLY */
I think this is wrong. The check would seem to be determined by the instruction (oprsz)
rather than a fixed configuration of the cpu (vl).
You're also replacing
-#ifndef CONFIG_USER_ONLY
-#define CHECK_ASXE do { \
- if ((ctx->base.tb->flags & HW_FLAGS_EUEN_ASXE) == 0) { \
- generate_exception(ctx, EXCCODE_ASXD); \
- return true; \
- } \
-} while (0)
-#else
-#define CHECK_ASXE
-#endif
this, the correct test, which you just added in patch 3.
+TRANS(xvadd_b, LASX, gvec_vvv, 32, MO_8, tcg_gen_gvec_add)
+TRANS(xvadd_h, LASX, gvec_vvv, 32, MO_16, tcg_gen_gvec_add)
+TRANS(xvadd_w, LASX, gvec_vvv, 32, MO_32, tcg_gen_gvec_add)
+TRANS(xvadd_d, LASX, gvec_vvv, 32, MO_64, tcg_gen_gvec_add)
The size of the changes required to add oprsz to gen_vvv would seem to be an poor choice.
If you do go that way, all of the LSX changes would need to be a separate patch.
Perhaps better as
static bool gvec_vvv_vl(DisasContext *ctx, arg_vvv *a, uint32_t oprsz, MemOp
mop,
void (*func)(unsigned, uint32_t, uint32_t,
uint32_t, uint32_t, uint32_t))
{
uint32_t vd_ofs = vec_full_offset(a->vd);
uint32_t vj_ofs = vec_full_offset(a->vj);
uint32_t vk_ofs = vec_full_offset(a->vk);
func(mop, vd_ofs, vj_ofs, vk_ofs, oprsz, ctx->vl / 8);
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))
{
CHECK_SXE;
return gvec_vvv_vl(ctx, a, 16, mop, func);
}
static bool gvec_xxx(DisasContext *ctx, arg_vvv *a, MemOp mop,
void (*func)(unsigned, uint32_t, uint32_t,
uint32_t, uint32_t, uint32_t))
{
CHECK_ASXE;
return gvec_vvv_vl(ctx, a, 32, mop, func);
}
so that you don't have to replicate "16" or "32" across each instruction.
+#define XVADDSUB_Q(NAME) \
+static bool trans_xv## NAME ##_q(DisasContext *ctx, arg_vvv * a) \
+{ \
+ TCGv_i64 rh, rl, ah, al, bh, bl; \
+ int i; \
+ \
+ if (!avail_LASX(ctx)) { \
+ return false; \
+ } \
+ \
+ CHECK_VEC; \
+ \
+ 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(); \
+ \
+ for (i = 0; i < 2; i++) { \
+ get_vreg64(ah, a->vj, 1 + i * 2); \
+ get_vreg64(al, a->vj, 0 + i * 2); \
+ get_vreg64(bh, a->vk, 1 + i * 2); \
+ get_vreg64(bl, a->vk, 0 + i * 2); \
+ \
+ tcg_gen_## NAME ##2_i64(rl, rh, al, ah, bl, bh); \
+ \
+ set_vreg64(rh, a->vd, 1 + i * 2); \
+ set_vreg64(rl, a->vd, 0 + i * 2); \
+ } \
+ \
+ return true; \
+}
This should be a function, not a macro, passing in tcg_gen_{add,sub}2_i64.
+
+XVADDSUB_Q(add)
+XVADDSUB_Q(sub)
Which lets these be normal TRANS expansions.
r~