* [PATCH v3 1/6] tcg: split out _var forms of gvec logical, abs and min/max ops
2026-09-13 15:59 [PATCH v3 0/6] hexagon: Add HVX context Brian Cain
@ 2026-09-13 15:59 ` Brian Cain
2026-09-13 15:59 ` [PATCH v3 2/6] tcg: add base arguments to the gvec 2s, dup_i32 and cmp expanders Brian Cain
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Brian Cain @ 2026-09-13 15:59 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Pierrick Bouvier, Brian Cain,
marco.liebel, Helge Deller, Paolo Bonzini, richard.henderson,
Laurent Vivier
target/hexagon is about to address its HVX register file through a
runtime base pointer rather than a constant offset from env, in order to
share one register file between several vCPUs. The gvec ops it needs
have no base-parameterized form yet.
Split tcg_gen_gvec_{and,or,xor,andc,orc,not,abs,smin,umin,smax,umax}
the same way tcg_gen_gvec_{add,sub,mov,dup_imm} already are: the work
moves to a _var function taking a TCGv_ptr base per operand, and the
existing entry point becomes a wrapper passing tcg_env.
The aofs == bofs shortcuts also have to compare the bases, since equal
offsets into different objects are not the same operand.
Reviewed-by: Marco Liebel <marco.liebel@oss.qualcomm.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
include/tcg/tcg-op-gvec-common.h | 45 ++++++++
tcg/tcg-op-gvec.c | 184 ++++++++++++++++++++++++-------
2 files changed, 189 insertions(+), 40 deletions(-)
diff --git a/include/tcg/tcg-op-gvec-common.h b/include/tcg/tcg-op-gvec-common.h
index ea0c87f4db6..99a6685e8a5 100644
--- a/include/tcg/tcg-op-gvec-common.h
+++ b/include/tcg/tcg-op-gvec-common.h
@@ -287,6 +287,13 @@ void tcg_gen_gvec_mov_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
TCGv_ptr abase, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_not_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_abs_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ uint32_t oprsz, uint32_t maxsz);
+
void tcg_gen_gvec_mov(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs,
@@ -335,6 +342,23 @@ void tcg_gen_gvec_ussub(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
/* Min/max. */
+void tcg_gen_gvec_smin_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_umin_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_smax_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_umax_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+
void tcg_gen_gvec_smin(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_umin(unsigned vece, uint32_t dofs, uint32_t aofs,
@@ -344,6 +368,27 @@ void tcg_gen_gvec_smax(unsigned vece, uint32_t dofs, uint32_t aofs,
void tcg_gen_gvec_umax(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_and_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_or_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_xor_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_andc_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_orc_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+
void tcg_gen_gvec_and(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_or(unsigned vece, uint32_t dofs, uint32_t aofs,
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
index 27f3807b004..191ac0fa864 100644
--- a/tcg/tcg-op-gvec.c
+++ b/tcg/tcg-op-gvec.c
@@ -1911,8 +1911,9 @@ void tcg_gen_gvec_dup_imm(unsigned vece, uint32_t dofs, uint32_t oprsz,
tcg_gen_gvec_dup_imm_var(vece, tcg_env, dofs, oprsz, maxsz, x);
}
-void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_not_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const GVecGen2 g = {
.fni8 = tcg_gen_not_i64,
@@ -1920,7 +1921,13 @@ void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs,
.fno = gen_helper_gvec_not,
.prefer_i64 = true,
};
- tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g);
+ tcg_gen_gvec_2_var(dbase, dofs, abase, aofs, oprsz, maxsz, &g);
+}
+
+void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_not_var(vece, tcg_env, dofs, tcg_env, aofs, oprsz, maxsz);
}
/* Perform a vector addition using normal addition and a mask. The mask
@@ -2427,8 +2434,10 @@ void tcg_gen_gvec_ussub(unsigned vece, uint32_t dofs, uint32_t aofs,
tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
}
-void tcg_gen_gvec_smin(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_smin_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = { INDEX_op_smin_vec, 0 };
static const GVecGen3 g[4] = {
@@ -2452,11 +2461,21 @@ void tcg_gen_gvec_smin(unsigned vece, uint32_t dofs, uint32_t aofs,
.vece = MO_64 }
};
tcg_debug_assert(vece <= MO_64);
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g[vece]);
}
-void tcg_gen_gvec_umin(unsigned vece, uint32_t dofs, uint32_t aofs,
+void tcg_gen_gvec_smin(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_smin_var(vece, tcg_env, dofs, tcg_env, aofs,
+ tcg_env, bofs, oprsz, maxsz);
+}
+
+void tcg_gen_gvec_umin_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = { INDEX_op_umin_vec, 0 };
static const GVecGen3 g[4] = {
@@ -2480,11 +2499,21 @@ void tcg_gen_gvec_umin(unsigned vece, uint32_t dofs, uint32_t aofs,
.vece = MO_64 }
};
tcg_debug_assert(vece <= MO_64);
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g[vece]);
}
-void tcg_gen_gvec_smax(unsigned vece, uint32_t dofs, uint32_t aofs,
+void tcg_gen_gvec_umin(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_umin_var(vece, tcg_env, dofs, tcg_env, aofs,
+ tcg_env, bofs, oprsz, maxsz);
+}
+
+void tcg_gen_gvec_smax_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = { INDEX_op_smax_vec, 0 };
static const GVecGen3 g[4] = {
@@ -2508,11 +2537,21 @@ void tcg_gen_gvec_smax(unsigned vece, uint32_t dofs, uint32_t aofs,
.vece = MO_64 }
};
tcg_debug_assert(vece <= MO_64);
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g[vece]);
}
-void tcg_gen_gvec_umax(unsigned vece, uint32_t dofs, uint32_t aofs,
+void tcg_gen_gvec_smax(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_smax_var(vece, tcg_env, dofs, tcg_env, aofs,
+ tcg_env, bofs, oprsz, maxsz);
+}
+
+void tcg_gen_gvec_umax_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = { INDEX_op_umax_vec, 0 };
static const GVecGen3 g[4] = {
@@ -2536,7 +2575,15 @@ void tcg_gen_gvec_umax(unsigned vece, uint32_t dofs, uint32_t aofs,
.vece = MO_64 }
};
tcg_debug_assert(vece <= MO_64);
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g[vece]);
+}
+
+void tcg_gen_gvec_umax(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_umax_var(vece, tcg_env, dofs, tcg_env, aofs,
+ tcg_env, bofs, oprsz, maxsz);
}
/* Perform a vector negation using normal negation and a mask.
@@ -2645,8 +2692,9 @@ static void tcg_gen_vec_abs16_i64(TCGv_i64 d, TCGv_i64 b)
gen_absv_mask(d, b, MO_16);
}
-void tcg_gen_gvec_abs(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_abs_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = { INDEX_op_abs_vec, 0 };
static const GVecGen2 g[4] = {
@@ -2674,11 +2722,19 @@ void tcg_gen_gvec_abs(unsigned vece, uint32_t dofs, uint32_t aofs,
};
tcg_debug_assert(vece <= MO_64);
- tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g[vece]);
+ tcg_gen_gvec_2_var(dbase, dofs, abase, aofs, oprsz, maxsz, &g[vece]);
}
-void tcg_gen_gvec_and(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_abs(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_abs_var(vece, tcg_env, dofs, tcg_env, aofs, oprsz, maxsz);
+}
+
+void tcg_gen_gvec_and_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const GVecGen3 g = {
.fni8 = tcg_gen_and_i64,
@@ -2687,15 +2743,25 @@ void tcg_gen_gvec_and(unsigned vece, uint32_t dofs, uint32_t aofs,
.prefer_i64 = true,
};
- if (aofs == bofs) {
- tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz);
+ if (abase == bbase && aofs == bofs) {
+ tcg_gen_gvec_mov_var(vece, dbase, dofs, abase, aofs, oprsz, maxsz);
} else {
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g);
}
}
-void tcg_gen_gvec_or(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_and(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_and_var(vece, tcg_env, dofs, tcg_env, aofs, tcg_env, bofs,
+ oprsz, maxsz);
+}
+
+void tcg_gen_gvec_or_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const GVecGen3 g = {
.fni8 = tcg_gen_or_i64,
@@ -2704,15 +2770,25 @@ void tcg_gen_gvec_or(unsigned vece, uint32_t dofs, uint32_t aofs,
.prefer_i64 = true,
};
- if (aofs == bofs) {
- tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz);
+ if (abase == bbase && aofs == bofs) {
+ tcg_gen_gvec_mov_var(vece, dbase, dofs, abase, aofs, oprsz, maxsz);
} else {
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g);
}
}
-void tcg_gen_gvec_xor(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_or(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_or_var(vece, tcg_env, dofs, tcg_env, aofs, tcg_env, bofs,
+ oprsz, maxsz);
+}
+
+void tcg_gen_gvec_xor_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const GVecGen3 g = {
.fni8 = tcg_gen_xor_i64,
@@ -2721,15 +2797,25 @@ void tcg_gen_gvec_xor(unsigned vece, uint32_t dofs, uint32_t aofs,
.prefer_i64 = true,
};
- if (aofs == bofs) {
- tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, 0);
+ if (abase == bbase && aofs == bofs) {
+ tcg_gen_gvec_dup_imm_var(MO_64, dbase, dofs, oprsz, maxsz, 0);
} else {
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g);
}
}
-void tcg_gen_gvec_andc(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_xor(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_xor_var(vece, tcg_env, dofs, tcg_env, aofs, tcg_env, bofs,
+ oprsz, maxsz);
+}
+
+void tcg_gen_gvec_andc_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const GVecGen3 g = {
.fni8 = tcg_gen_andc_i64,
@@ -2738,15 +2824,25 @@ void tcg_gen_gvec_andc(unsigned vece, uint32_t dofs, uint32_t aofs,
.prefer_i64 = true,
};
- if (aofs == bofs) {
- tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, 0);
+ if (abase == bbase && aofs == bofs) {
+ tcg_gen_gvec_dup_imm_var(MO_64, dbase, dofs, oprsz, maxsz, 0);
} else {
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g);
}
}
-void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_andc(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_andc_var(vece, tcg_env, dofs, tcg_env, aofs, tcg_env, bofs,
+ oprsz, maxsz);
+}
+
+void tcg_gen_gvec_orc_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const GVecGen3 g = {
.fni8 = tcg_gen_orc_i64,
@@ -2755,13 +2851,21 @@ void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs,
.prefer_i64 = true,
};
- if (aofs == bofs) {
- tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, -1);
+ if (abase == bbase && aofs == bofs) {
+ tcg_gen_gvec_dup_imm_var(MO_64, dbase, dofs, oprsz, maxsz, -1);
} else {
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g);
}
}
+void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_orc_var(vece, tcg_env, dofs, tcg_env, aofs, tcg_env, bofs,
+ oprsz, maxsz);
+}
+
void tcg_gen_gvec_nand(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
{
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v3 2/6] tcg: add base arguments to the gvec 2s, dup_i32 and cmp expanders
2026-09-13 15:59 [PATCH v3 0/6] hexagon: Add HVX context Brian Cain
2026-09-13 15:59 ` [PATCH v3 1/6] tcg: split out _var forms of gvec logical, abs and min/max ops Brian Cain
@ 2026-09-13 15:59 ` Brian Cain
2026-09-13 15:59 ` [PATCH v3 3/6] tcg: split out _var forms of gvec saturating/mul/shift-immediate ops Brian Cain
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Brian Cain @ 2026-09-13 15:59 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Pierrick Bouvier, Brian Cain,
marco.liebel, Helge Deller, Paolo Bonzini, richard.henderson,
Laurent Vivier
These three families still name tcg_env directly, so they cannot be
reached from a _var entry point. Thread a TCGv_ptr base per operand
through expand_2s_{i32,i64,vec}, expand_2sh_vec, expand_cmp_{i32,i64,vec}
and do_gvec_shifts, and split expand_2i_ool out of tcg_gen_gvec_2i_ool
the way expand_2_ool already is, so the out-of-line fallback is reachable
too.
Add tcg_gen_gvec_{2s,shls,shrs,sars,dup_i32,cmp}_var; the existing entry
points become wrappers passing tcg_env and generate identical code.
Note that the operand swap in tcg_gen_gvec_cmp_var, used when a condition
has no helper, now has to swap the bases along with the offsets.
Reviewed-by: Marco Liebel <marco.liebel@oss.qualcomm.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
include/tcg/tcg-op-gvec-common.h | 21 +++
tcg/tcg-op-gvec.c | 256 +++++++++++++++++++++----------
2 files changed, 192 insertions(+), 85 deletions(-)
diff --git a/include/tcg/tcg-op-gvec-common.h b/include/tcg/tcg-op-gvec-common.h
index 99a6685e8a5..fa28ebdde0f 100644
--- a/include/tcg/tcg-op-gvec-common.h
+++ b/include/tcg/tcg-op-gvec-common.h
@@ -237,6 +237,10 @@ void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs,
/* Similarly, expand (env+dofs) = op(env+aofs, c). */
void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
uint32_t maxsz, int64_t c, const GVecGen2i *op);
+/* Expand (dbase+dofs) = op(abase+aofs, s), length @oprsz. */
+void tcg_gen_gvec_2s_var(TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs, uint32_t oprsz,
+ uint32_t maxsz, TCGv_i64 c, const GVecGen2s *op);
/* Similarly, expand (env+dofs) = op(env+aofs, s). */
void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
uint32_t maxsz, TCGv_i64 c, const GVecGen2s *op);
@@ -433,6 +437,8 @@ void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t s,
void tcg_gen_gvec_dup_imm_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
uint32_t oprsz, uint32_t maxsz, uint64_t imm);
+void tcg_gen_gvec_dup_i32_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ uint32_t oprsz, uint32_t maxsz, TCGv_i32 in);
void tcg_gen_gvec_shli(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
@@ -445,6 +451,16 @@ void tcg_gen_gvec_rotli(unsigned vece, uint32_t dofs, uint32_t aofs,
void tcg_gen_gvec_rotri(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_shls_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_shrs_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_sars_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
+
void tcg_gen_gvec_shls(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_shrs(unsigned vece, uint32_t dofs, uint32_t aofs,
@@ -471,6 +487,11 @@ void tcg_gen_gvec_rotlv(unsigned vece, uint32_t dofs, uint32_t aofs,
void tcg_gen_gvec_rotrv(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_cmp_var(TCGCond cond, unsigned vece,
+ TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs,
uint32_t aofs, uint32_t bofs,
uint32_t oprsz, uint32_t maxsz);
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
index 191ac0fa864..fc1a70434c5 100644
--- a/tcg/tcg-op-gvec.c
+++ b/tcg/tcg-op-gvec.c
@@ -162,23 +162,31 @@ void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
/* Generate a call to a gvec-style helper with two vector operands
and one scalar operand. */
+static void expand_2i_ool(TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs, TCGv_i64 c,
+ uint32_t oprsz, uint32_t maxsz, int32_t data,
+ gen_helper_gvec_2i *fn)
+{
+ TCGv_ptr a0, a1;
+ TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
+
+ a0 = tcg_temp_ebb_new_ptr();
+ a1 = tcg_temp_ebb_new_ptr();
+
+ tcg_gen_addi_ptr(a0, dbase, dofs);
+ tcg_gen_addi_ptr(a1, abase, aofs);
+
+ fn(a0, a1, c, desc);
+
+ tcg_temp_free_ptr(a0);
+ tcg_temp_free_ptr(a1);
+}
+
void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, TCGv_i64 c,
uint32_t oprsz, uint32_t maxsz, int32_t data,
gen_helper_gvec_2i *fn)
{
- TCGv_ptr a0, a1;
- TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
-
- a0 = tcg_temp_ebb_new_ptr();
- a1 = tcg_temp_ebb_new_ptr();
-
- tcg_gen_addi_ptr(a0, tcg_env, dofs);
- tcg_gen_addi_ptr(a1, tcg_env, aofs);
-
- fn(a0, a1, c, desc);
-
- tcg_temp_free_ptr(a0);
- tcg_temp_free_ptr(a1);
+ expand_2i_ool(tcg_env, dofs, tcg_env, aofs, c, oprsz, maxsz, data, fn);
}
/* Generate a call to a gvec-style helper with three vector operands. */
@@ -783,7 +791,8 @@ static void expand_2i_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
tcg_temp_free_i32(t1);
}
-static void expand_2s_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
+static void expand_2s_i32(TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs, uint32_t oprsz,
TCGv_i32 c, bool scalar_first,
void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32))
{
@@ -792,13 +801,13 @@ static void expand_2s_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
uint32_t i;
for (i = 0; i < oprsz; i += 4) {
- tcg_gen_ld_i32(t0, tcg_env, aofs + i);
+ tcg_gen_ld_i32(t0, abase, aofs + i);
if (scalar_first) {
fni(t1, c, t0);
} else {
fni(t1, t0, c);
}
- tcg_gen_st_i32(t1, tcg_env, dofs + i);
+ tcg_gen_st_i32(t1, dbase, dofs + i);
}
tcg_temp_free_i32(t0);
tcg_temp_free_i32(t1);
@@ -949,7 +958,8 @@ static void expand_2i_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
tcg_temp_free_i64(t1);
}
-static void expand_2s_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
+static void expand_2s_i64(TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs, uint32_t oprsz,
TCGv_i64 c, bool scalar_first,
void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64))
{
@@ -958,13 +968,13 @@ static void expand_2s_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
uint32_t i;
for (i = 0; i < oprsz; i += 8) {
- tcg_gen_ld_i64(t0, tcg_env, aofs + i);
+ tcg_gen_ld_i64(t0, abase, aofs + i);
if (scalar_first) {
fni(t1, c, t0);
} else {
fni(t1, t0, c);
}
- tcg_gen_st_i64(t1, tcg_env, dofs + i);
+ tcg_gen_st_i64(t1, dbase, dofs + i);
}
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
@@ -1114,7 +1124,8 @@ static void expand_2i_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
}
}
-static void expand_2s_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
+static void expand_2s_vec(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
uint32_t oprsz, uint32_t tysz, TCGType type,
TCGv_vec c, bool scalar_first,
void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
@@ -1123,13 +1134,13 @@ static void expand_2s_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_vec t0 = tcg_temp_new_vec(type);
TCGv_vec t1 = tcg_temp_new_vec(type);
- tcg_gen_ld_vec(t0, tcg_env, aofs + i);
+ tcg_gen_ld_vec(t0, abase, aofs + i);
if (scalar_first) {
fni(vece, t1, c, t0);
} else {
fni(vece, t1, t0, c);
}
- tcg_gen_st_vec(t1, tcg_env, dofs + i);
+ tcg_gen_st_vec(t1, dbase, dofs + i);
}
}
@@ -1375,14 +1386,18 @@ void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
}
}
-/* Expand a vector operation with two vectors and a scalar. */
-void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
- uint32_t maxsz, TCGv_i64 c, const GVecGen2s *g)
+/*
+ * Expand a vector operation with two vectors and a scalar,
+ * (dbase+dofs) = op(abase+aofs, c).
+ */
+void tcg_gen_gvec_2s_var(TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs, uint32_t oprsz,
+ uint32_t maxsz, TCGv_i64 c, const GVecGen2s *g)
{
TCGType type;
check_size_align(oprsz, maxsz, dofs | aofs);
- check_overlap_2(tcg_env, dofs, tcg_env, aofs, maxsz);
+ check_overlap_2(dbase, dofs, abase, aofs, maxsz);
type = 0;
if (g->fniv) {
@@ -1403,7 +1418,8 @@ void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
* that e.g. size == 80 would be expanded with 2x32 + 1x16.
*/
some = QEMU_ALIGN_DOWN(oprsz, 32);
- expand_2s_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256,
+ expand_2s_vec(g->vece, dbase, dofs, abase, aofs,
+ some, 32, TCG_TYPE_V256,
t_vec, g->scalar_first, g->fniv);
if (some == oprsz) {
break;
@@ -1415,12 +1431,14 @@ void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
/* fallthru */
case TCG_TYPE_V128:
- expand_2s_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128,
+ expand_2s_vec(g->vece, dbase, dofs, abase, aofs,
+ oprsz, 16, TCG_TYPE_V128,
t_vec, g->scalar_first, g->fniv);
break;
case TCG_TYPE_V64:
- expand_2s_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64,
+ expand_2s_vec(g->vece, dbase, dofs, abase, aofs,
+ oprsz, 8, TCG_TYPE_V64,
t_vec, g->scalar_first, g->fniv);
break;
@@ -1433,25 +1451,33 @@ void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
TCGv_i64 t64 = tcg_temp_new_i64();
tcg_gen_dup_i64(g->vece, t64, c);
- expand_2s_i64(dofs, aofs, oprsz, t64, g->scalar_first, g->fni8);
+ expand_2s_i64(dbase, dofs, abase, aofs, oprsz, t64,
+ g->scalar_first, g->fni8);
tcg_temp_free_i64(t64);
} else if (g->fni4 && check_size_impl(oprsz, 4)) {
TCGv_i32 t32 = tcg_temp_new_i32();
tcg_gen_extrl_i64_i32(t32, c);
tcg_gen_dup_i32(g->vece, t32, t32);
- expand_2s_i32(dofs, aofs, oprsz, t32, g->scalar_first, g->fni4);
+ expand_2s_i32(dbase, dofs, abase, aofs, oprsz, t32,
+ g->scalar_first, g->fni4);
tcg_temp_free_i32(t32);
} else {
- tcg_gen_gvec_2i_ool(dofs, aofs, c, oprsz, maxsz, 0, g->fno);
+ expand_2i_ool(dbase, dofs, abase, aofs, c, oprsz, maxsz, 0, g->fno);
return;
}
if (oprsz < maxsz) {
- expand_clr(tcg_env, dofs + oprsz, maxsz - oprsz);
+ expand_clr(dbase, dofs + oprsz, maxsz - oprsz);
}
}
+void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
+ uint32_t maxsz, TCGv_i64 c, const GVecGen2s *g)
+{
+ tcg_gen_gvec_2s_var(tcg_env, dofs, tcg_env, aofs, oprsz, maxsz, c, g);
+}
+
/* Expand a vector three-operand operation. */
void tcg_gen_gvec_3_var(TCGv_ptr dbase, uint32_t dofs,
TCGv_ptr abase, uint32_t aofs,
@@ -1775,12 +1801,18 @@ void tcg_gen_gvec_mov(unsigned vece, uint32_t dofs, uint32_t aofs,
tcg_gen_gvec_mov_var(vece, tcg_env, dofs, tcg_env, aofs, oprsz, maxsz);
}
+void tcg_gen_gvec_dup_i32_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ uint32_t oprsz, uint32_t maxsz, TCGv_i32 in)
+{
+ check_size_align(oprsz, maxsz, dofs);
+ tcg_debug_assert(vece <= MO_32);
+ do_dup(vece, dbase, dofs, oprsz, maxsz, in, NULL, 0);
+}
+
void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t oprsz,
uint32_t maxsz, TCGv_i32 in)
{
- check_size_align(oprsz, maxsz, dofs);
- tcg_debug_assert(vece <= MO_32);
- do_dup(vece, tcg_env, dofs, oprsz, maxsz, in, NULL, 0);
+ tcg_gen_gvec_dup_i32_var(vece, tcg_env, dofs, oprsz, maxsz, in);
}
void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t oprsz,
@@ -3311,7 +3343,8 @@ typedef struct {
TCGOpcode v_list[2];
} GVecGen2sh;
-static void expand_2sh_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
+static void expand_2sh_vec(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
uint32_t oprsz, uint32_t tysz, TCGType type,
TCGv_i32 shift,
void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_i32))
@@ -3320,21 +3353,22 @@ static void expand_2sh_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_vec t0 = tcg_temp_new_vec(type);
TCGv_vec t1 = tcg_temp_new_vec(type);
- tcg_gen_ld_vec(t0, tcg_env, aofs + i);
+ tcg_gen_ld_vec(t0, abase, aofs + i);
fni(vece, t1, t0, shift);
- tcg_gen_st_vec(t1, tcg_env, dofs + i);
+ tcg_gen_st_vec(t1, dbase, dofs + i);
}
}
static void
-do_gvec_shifts(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift,
+do_gvec_shifts(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs, TCGv_i32 shift,
uint32_t oprsz, uint32_t maxsz, const GVecGen2sh *g)
{
TCGType type;
uint32_t some;
check_size_align(oprsz, maxsz, dofs | aofs);
- check_overlap_2(tcg_env, dofs, tcg_env, aofs, maxsz);
+ check_overlap_2(dbase, dofs, abase, aofs, maxsz);
/* If the backend has a scalar expansion, great. */
type = choose_vector_type(g->s_list, vece, oprsz, vece == MO_64);
@@ -3343,7 +3377,7 @@ do_gvec_shifts(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift,
switch (type) {
case TCG_TYPE_V256:
some = QEMU_ALIGN_DOWN(oprsz, 32);
- expand_2sh_vec(vece, dofs, aofs, some, 32,
+ expand_2sh_vec(vece, dbase, dofs, abase, aofs, some, 32,
TCG_TYPE_V256, shift, g->fniv_s);
if (some == oprsz) {
break;
@@ -3354,11 +3388,11 @@ do_gvec_shifts(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift,
maxsz -= some;
/* fallthru */
case TCG_TYPE_V128:
- expand_2sh_vec(vece, dofs, aofs, oprsz, 16,
+ expand_2sh_vec(vece, dbase, dofs, abase, aofs, oprsz, 16,
TCG_TYPE_V128, shift, g->fniv_s);
break;
case TCG_TYPE_V64:
- expand_2sh_vec(vece, dofs, aofs, oprsz, 8,
+ expand_2sh_vec(vece, dbase, dofs, abase, aofs, oprsz, 8,
TCG_TYPE_V64, shift, g->fniv_s);
break;
default:
@@ -3386,7 +3420,8 @@ do_gvec_shifts(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift,
switch (type) {
case TCG_TYPE_V256:
some = QEMU_ALIGN_DOWN(oprsz, 32);
- expand_2s_vec(vece, dofs, aofs, some, 32, TCG_TYPE_V256,
+ expand_2s_vec(vece, dbase, dofs, abase, aofs,
+ some, 32, TCG_TYPE_V256,
v_shift, false, g->fniv_v);
if (some == oprsz) {
break;
@@ -3397,11 +3432,13 @@ do_gvec_shifts(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift,
maxsz -= some;
/* fallthru */
case TCG_TYPE_V128:
- expand_2s_vec(vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128,
+ expand_2s_vec(vece, dbase, dofs, abase, aofs,
+ oprsz, 16, TCG_TYPE_V128,
v_shift, false, g->fniv_v);
break;
case TCG_TYPE_V64:
- expand_2s_vec(vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64,
+ expand_2s_vec(vece, dbase, dofs, abase, aofs,
+ oprsz, 8, TCG_TYPE_V64,
v_shift, false, g->fniv_v);
break;
default:
@@ -3414,11 +3451,13 @@ do_gvec_shifts(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift,
/* Otherwise fall back to integral... */
if (vece == MO_32 && check_size_impl(oprsz, 4)) {
- expand_2s_i32(dofs, aofs, oprsz, shift, false, g->fni4);
+ expand_2s_i32(dbase, dofs, abase, aofs, oprsz, shift,
+ false, g->fni4);
} else if (vece == MO_64 && check_size_impl(oprsz, 8)) {
TCGv_i64 sh64 = tcg_temp_ebb_new_i64();
tcg_gen_extu_i32_i64(sh64, shift);
- expand_2s_i64(dofs, aofs, oprsz, sh64, false, g->fni8);
+ expand_2s_i64(dbase, dofs, abase, aofs, oprsz, sh64,
+ false, g->fni8);
tcg_temp_free_i64(sh64);
} else {
TCGv_ptr a0 = tcg_temp_ebb_new_ptr();
@@ -3427,8 +3466,8 @@ do_gvec_shifts(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift,
tcg_gen_shli_i32(desc, shift, SIMD_DATA_SHIFT);
tcg_gen_ori_i32(desc, desc, simd_desc(oprsz, maxsz, 0));
- tcg_gen_addi_ptr(a0, tcg_env, dofs);
- tcg_gen_addi_ptr(a1, tcg_env, aofs);
+ tcg_gen_addi_ptr(a0, dbase, dofs);
+ tcg_gen_addi_ptr(a1, abase, aofs);
g->fno[vece](a0, a1, desc);
@@ -3440,12 +3479,13 @@ do_gvec_shifts(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift,
clear_tail:
if (oprsz < maxsz) {
- expand_clr(tcg_env, dofs + oprsz, maxsz - oprsz);
+ expand_clr(dbase, dofs + oprsz, maxsz - oprsz);
}
}
-void tcg_gen_gvec_shls(unsigned vece, uint32_t dofs, uint32_t aofs,
- TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_shls_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz)
{
static const GVecGen2sh g = {
.fni4 = tcg_gen_shl_i32,
@@ -3463,11 +3503,19 @@ void tcg_gen_gvec_shls(unsigned vece, uint32_t dofs, uint32_t aofs,
};
tcg_debug_assert(vece <= MO_64);
- do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g);
+ do_gvec_shifts(vece, dbase, dofs, abase, aofs, shift, oprsz, maxsz, &g);
}
-void tcg_gen_gvec_shrs(unsigned vece, uint32_t dofs, uint32_t aofs,
+void tcg_gen_gvec_shls(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_shls_var(vece, tcg_env, dofs, tcg_env, aofs,
+ shift, oprsz, maxsz);
+}
+
+void tcg_gen_gvec_shrs_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz)
{
static const GVecGen2sh g = {
.fni4 = tcg_gen_shr_i32,
@@ -3485,11 +3533,19 @@ void tcg_gen_gvec_shrs(unsigned vece, uint32_t dofs, uint32_t aofs,
};
tcg_debug_assert(vece <= MO_64);
- do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g);
+ do_gvec_shifts(vece, dbase, dofs, abase, aofs, shift, oprsz, maxsz, &g);
}
-void tcg_gen_gvec_sars(unsigned vece, uint32_t dofs, uint32_t aofs,
+void tcg_gen_gvec_shrs(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_shrs_var(vece, tcg_env, dofs, tcg_env, aofs,
+ shift, oprsz, maxsz);
+}
+
+void tcg_gen_gvec_sars_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz)
{
static const GVecGen2sh g = {
.fni4 = tcg_gen_sar_i32,
@@ -3507,7 +3563,14 @@ void tcg_gen_gvec_sars(unsigned vece, uint32_t dofs, uint32_t aofs,
};
tcg_debug_assert(vece <= MO_64);
- do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g);
+ do_gvec_shifts(vece, dbase, dofs, abase, aofs, shift, oprsz, maxsz, &g);
+}
+
+void tcg_gen_gvec_sars(unsigned vece, uint32_t dofs, uint32_t aofs,
+ TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_sars_var(vece, tcg_env, dofs, tcg_env, aofs,
+ shift, oprsz, maxsz);
}
void tcg_gen_gvec_rotls(unsigned vece, uint32_t dofs, uint32_t aofs,
@@ -3529,7 +3592,8 @@ void tcg_gen_gvec_rotls(unsigned vece, uint32_t dofs, uint32_t aofs,
};
tcg_debug_assert(vece <= MO_64);
- do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g);
+ do_gvec_shifts(vece, tcg_env, dofs, tcg_env, aofs, shift,
+ oprsz, maxsz, &g);
}
void tcg_gen_gvec_rotrs(unsigned vece, uint32_t dofs, uint32_t aofs,
@@ -3861,7 +3925,9 @@ void tcg_gen_gvec_rotrv(unsigned vece, uint32_t dofs, uint32_t aofs,
}
/* Expand OPSZ bytes worth of three-operand operations using i32 elements. */
-static void expand_cmp_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs,
+static void expand_cmp_i32(TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
uint32_t oprsz, TCGCond cond)
{
TCGv_i32 t0 = tcg_temp_ebb_new_i32();
@@ -3869,16 +3935,18 @@ static void expand_cmp_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t i;
for (i = 0; i < oprsz; i += 4) {
- tcg_gen_ld_i32(t0, tcg_env, aofs + i);
- tcg_gen_ld_i32(t1, tcg_env, bofs + i);
+ tcg_gen_ld_i32(t0, abase, aofs + i);
+ tcg_gen_ld_i32(t1, bbase, bofs + i);
tcg_gen_negsetcond_i32(cond, t0, t0, t1);
- tcg_gen_st_i32(t0, tcg_env, dofs + i);
+ tcg_gen_st_i32(t0, dbase, dofs + i);
}
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
}
-static void expand_cmp_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs,
+static void expand_cmp_i64(TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
uint32_t oprsz, TCGCond cond)
{
TCGv_i64 t0 = tcg_temp_ebb_new_i64();
@@ -3886,17 +3954,19 @@ static void expand_cmp_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t i;
for (i = 0; i < oprsz; i += 8) {
- tcg_gen_ld_i64(t0, tcg_env, aofs + i);
- tcg_gen_ld_i64(t1, tcg_env, bofs + i);
+ tcg_gen_ld_i64(t0, abase, aofs + i);
+ tcg_gen_ld_i64(t1, bbase, bofs + i);
tcg_gen_negsetcond_i64(cond, t0, t0, t1);
- tcg_gen_st_i64(t0, tcg_env, dofs + i);
+ tcg_gen_st_i64(t0, dbase, dofs + i);
}
tcg_temp_free_i64(t1);
tcg_temp_free_i64(t0);
}
-static void expand_cmp_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t bofs, uint32_t oprsz, uint32_t tysz,
+static void expand_cmp_vec(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t tysz,
TCGType type, TCGCond cond)
{
for (uint32_t i = 0; i < oprsz; i += tysz) {
@@ -3904,16 +3974,18 @@ static void expand_cmp_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_vec t1 = tcg_temp_new_vec(type);
TCGv_vec t2 = tcg_temp_new_vec(type);
- tcg_gen_ld_vec(t0, tcg_env, aofs + i);
- tcg_gen_ld_vec(t1, tcg_env, bofs + i);
+ tcg_gen_ld_vec(t0, abase, aofs + i);
+ tcg_gen_ld_vec(t1, bbase, bofs + i);
tcg_gen_cmp_vec(cond, vece, t2, t0, t1);
- tcg_gen_st_vec(t2, tcg_env, dofs + i);
+ tcg_gen_st_vec(t2, dbase, dofs + i);
}
}
-void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs,
- uint32_t aofs, uint32_t bofs,
- uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_cmp_var(TCGCond cond, unsigned vece,
+ TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode cmp_list[] = { INDEX_op_cmp_vec, 0 };
static gen_helper_gvec_3 * const eq_fn[4] = {
@@ -3954,10 +4026,10 @@ void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs,
uint32_t some;
check_size_align(oprsz, maxsz, dofs | aofs | bofs);
- check_overlap_3(tcg_env, dofs, tcg_env, aofs, tcg_env, bofs, maxsz);
+ check_overlap_3(dbase, dofs, abase, aofs, bbase, bofs, maxsz);
if (cond == TCG_COND_NEVER || cond == TCG_COND_ALWAYS) {
- do_dup(MO_8, tcg_env, dofs, oprsz, maxsz,
+ do_dup(MO_8, dbase, dofs, oprsz, maxsz,
NULL, NULL, -(cond == TCG_COND_ALWAYS));
return;
}
@@ -3975,7 +4047,8 @@ void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs,
* that e.g. size == 80 would be expanded with 2x32 + 1x16.
*/
some = QEMU_ALIGN_DOWN(oprsz, 32);
- expand_cmp_vec(vece, dofs, aofs, bofs, some, 32, TCG_TYPE_V256, cond);
+ expand_cmp_vec(vece, dbase, dofs, abase, aofs, bbase, bofs,
+ some, 32, TCG_TYPE_V256, cond);
if (some == oprsz) {
break;
}
@@ -3986,28 +4059,33 @@ void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs,
maxsz -= some;
/* fallthru */
case TCG_TYPE_V128:
- expand_cmp_vec(vece, dofs, aofs, bofs, oprsz, 16, TCG_TYPE_V128, cond);
+ expand_cmp_vec(vece, dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, 16, TCG_TYPE_V128, cond);
break;
case TCG_TYPE_V64:
- expand_cmp_vec(vece, dofs, aofs, bofs, oprsz, 8, TCG_TYPE_V64, cond);
+ expand_cmp_vec(vece, dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, 8, TCG_TYPE_V64, cond);
break;
case 0:
if (vece == MO_64 && check_size_impl(oprsz, 8)) {
- expand_cmp_i64(dofs, aofs, bofs, oprsz, cond);
+ expand_cmp_i64(dbase, dofs, abase, aofs, bbase, bofs, oprsz, cond);
} else if (vece == MO_32 && check_size_impl(oprsz, 4)) {
- expand_cmp_i32(dofs, aofs, bofs, oprsz, cond);
+ expand_cmp_i32(dbase, dofs, abase, aofs, bbase, bofs, oprsz, cond);
} else {
gen_helper_gvec_3 * const *fn = fns[cond];
if (fn == NULL) {
uint32_t tmp;
+ TCGv_ptr tmpb;
tmp = aofs, aofs = bofs, bofs = tmp;
+ tmpb = abase, abase = bbase, bbase = tmpb;
cond = tcg_swap_cond(cond);
fn = fns[cond];
assert(fn != NULL);
}
- tcg_gen_gvec_3_ool(dofs, aofs, bofs, oprsz, maxsz, 0, fn[vece]);
+ expand_3_ool(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, 0, fn[vece]);
oprsz = maxsz;
}
break;
@@ -4018,10 +4096,18 @@ void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs,
tcg_swap_vecop_list(hold_list);
if (oprsz < maxsz) {
- expand_clr(tcg_env, dofs + oprsz, maxsz - oprsz);
+ expand_clr(dbase, dofs + oprsz, maxsz - oprsz);
}
}
+void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs,
+ uint32_t aofs, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_cmp_var(cond, vece, tcg_env, dofs, tcg_env, aofs,
+ tcg_env, bofs, oprsz, maxsz);
+}
+
static void expand_cmps_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t tysz, TCGType type,
TCGCond cond, TCGv_vec c)
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v3 3/6] tcg: split out _var forms of gvec saturating/mul/shift-immediate ops
2026-09-13 15:59 [PATCH v3 0/6] hexagon: Add HVX context Brian Cain
2026-09-13 15:59 ` [PATCH v3 1/6] tcg: split out _var forms of gvec logical, abs and min/max ops Brian Cain
2026-09-13 15:59 ` [PATCH v3 2/6] tcg: add base arguments to the gvec 2s, dup_i32 and cmp expanders Brian Cain
@ 2026-09-13 15:59 ` Brian Cain
2026-09-13 15:59 ` [PATCH v3 4/6] target/hexagon: raise an exception for HVX with SSR:XE clear Brian Cain
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Brian Cain @ 2026-09-13 15:59 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Pierrick Bouvier, Brian Cain,
marco.liebel, Helge Deller, Paolo Bonzini, richard.henderson,
Laurent Vivier
target/hexagon is about to address its HVX register file through a
runtime base pointer rather than a constant offset from env, in order to
share one register file between several vCPUs. Split the other
gvec op families it needs like tcg_gen_gvec_{add,sub,mov,and,etc}.
Add tcg_gen_gvec_{ssadd,sssub,usadd,ussub,mul}_var and
tcg_gen_gvec_{shri,sari}_var, plus the tcg_gen_gvec_2i_var plumbing the
immediate-shift forms are built on.
Reviewed-by: Marco Liebel <marco.liebel@oss.qualcomm.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
include/tcg/tcg-op-gvec-common.h | 31 ++++++
tcg/tcg-op-gvec.c | 177 ++++++++++++++++++++++---------
2 files changed, 160 insertions(+), 48 deletions(-)
diff --git a/include/tcg/tcg-op-gvec-common.h b/include/tcg/tcg-op-gvec-common.h
index fa28ebdde0f..6d3c2bae57a 100644
--- a/include/tcg/tcg-op-gvec-common.h
+++ b/include/tcg/tcg-op-gvec-common.h
@@ -234,6 +234,10 @@ void tcg_gen_gvec_2_var(TCGv_ptr dbase, uint32_t dofs,
/* Similarly, expand (env+dofs) = op(env+aofs). */
void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs,
uint32_t oprsz, uint32_t maxsz, const GVecGen2 *op);
+/* Expand (dbase+dofs) = op(abase+aofs, c), clearing @oprsz..@maxsz. */
+void tcg_gen_gvec_2i_var(TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs, uint32_t oprsz,
+ uint32_t maxsz, int64_t c, const GVecGen2i *op);
/* Similarly, expand (env+dofs) = op(env+aofs, c). */
void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
uint32_t maxsz, int64_t c, const GVecGen2i *op);
@@ -315,6 +319,10 @@ void tcg_gen_gvec_sub_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
TCGv_ptr abase, uint32_t aofs,
TCGv_ptr bbase, uint32_t bofs,
uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_mul_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_add(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
@@ -336,6 +344,23 @@ void tcg_gen_gvec_muls(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
/* Saturated arithmetic. */
+void tcg_gen_gvec_ssadd_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_sssub_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_usadd_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_ussub_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+
void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_sssub(unsigned vece, uint32_t dofs, uint32_t aofs,
@@ -442,8 +467,14 @@ void tcg_gen_gvec_dup_i32_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
void tcg_gen_gvec_shli(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_shri_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
+void tcg_gen_gvec_sari_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs,
int64_t shift, uint32_t oprsz, uint32_t maxsz);
void tcg_gen_gvec_rotli(unsigned vece, uint32_t dofs, uint32_t aofs,
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
index fc1a70434c5..0d649cc13b2 100644
--- a/tcg/tcg-op-gvec.c
+++ b/tcg/tcg-op-gvec.c
@@ -771,7 +771,8 @@ static void expand_2_i32(TCGv_ptr dbase, uint32_t dofs, TCGv_ptr abase,
tcg_temp_free_i32(t1);
}
-static void expand_2i_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
+static void expand_2i_i32(TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs, uint32_t oprsz,
int32_t c, bool load_dest,
void (*fni)(TCGv_i32, TCGv_i32, int32_t))
{
@@ -780,12 +781,12 @@ static void expand_2i_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
uint32_t i;
for (i = 0; i < oprsz; i += 4) {
- tcg_gen_ld_i32(t0, tcg_env, aofs + i);
+ tcg_gen_ld_i32(t0, abase, aofs + i);
if (load_dest) {
- tcg_gen_ld_i32(t1, tcg_env, dofs + i);
+ tcg_gen_ld_i32(t1, dbase, dofs + i);
}
fni(t1, t0, c);
- tcg_gen_st_i32(t1, tcg_env, dofs + i);
+ tcg_gen_st_i32(t1, dbase, dofs + i);
}
tcg_temp_free_i32(t0);
tcg_temp_free_i32(t1);
@@ -938,7 +939,8 @@ static void expand_2_i64(TCGv_ptr dbase, uint32_t dofs, TCGv_ptr abase,
tcg_temp_free_i64(t1);
}
-static void expand_2i_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
+static void expand_2i_i64(TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs, uint32_t oprsz,
int64_t c, bool load_dest,
void (*fni)(TCGv_i64, TCGv_i64, int64_t))
{
@@ -947,12 +949,12 @@ static void expand_2i_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
uint32_t i;
for (i = 0; i < oprsz; i += 8) {
- tcg_gen_ld_i64(t0, tcg_env, aofs + i);
+ tcg_gen_ld_i64(t0, abase, aofs + i);
if (load_dest) {
- tcg_gen_ld_i64(t1, tcg_env, dofs + i);
+ tcg_gen_ld_i64(t1, dbase, dofs + i);
}
fni(t1, t0, c);
- tcg_gen_st_i64(t1, tcg_env, dofs + i);
+ tcg_gen_st_i64(t1, dbase, dofs + i);
}
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
@@ -1106,7 +1108,8 @@ static void expand_2_vec(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
/* Expand OPSZ bytes worth of two-vector operands and an immediate operand
using host vectors. */
-static void expand_2i_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
+static void expand_2i_vec(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
uint32_t oprsz, uint32_t tysz, TCGType type,
int64_t c, bool load_dest,
void (*fni)(unsigned, TCGv_vec, TCGv_vec, int64_t))
@@ -1115,12 +1118,12 @@ static void expand_2i_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
TCGv_vec t0 = tcg_temp_new_vec(type);
TCGv_vec t1 = tcg_temp_new_vec(type);
- tcg_gen_ld_vec(t0, tcg_env, aofs + i);
+ tcg_gen_ld_vec(t0, abase, aofs + i);
if (load_dest) {
- tcg_gen_ld_vec(t1, tcg_env, dofs + i);
+ tcg_gen_ld_vec(t1, dbase, dofs + i);
}
fni(vece, t1, t0, c);
- tcg_gen_st_vec(t1, tcg_env, dofs + i);
+ tcg_gen_st_vec(t1, dbase, dofs + i);
}
}
@@ -1318,8 +1321,9 @@ void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs,
}
/* Expand a vector operation with two vectors and an immediate. */
-void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
- uint32_t maxsz, int64_t c, const GVecGen2i *g)
+void tcg_gen_gvec_2i_var(TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs, uint32_t oprsz,
+ uint32_t maxsz, int64_t c, const GVecGen2i *g)
{
const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty;
const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list);
@@ -1327,7 +1331,7 @@ void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
uint32_t some;
check_size_align(oprsz, maxsz, dofs | aofs);
- check_overlap_2(tcg_env, dofs, tcg_env, aofs, maxsz);
+ check_overlap_2(dbase, dofs, abase, aofs, maxsz);
type = 0;
if (g->fniv) {
@@ -1340,8 +1344,8 @@ void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
* that e.g. size == 80 would be expanded with 2x32 + 1x16.
*/
some = QEMU_ALIGN_DOWN(oprsz, 32);
- expand_2i_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256,
- c, g->load_dest, g->fniv);
+ expand_2i_vec(g->vece, dbase, dofs, abase, aofs, some, 32,
+ TCG_TYPE_V256, c, g->load_dest, g->fniv);
if (some == oprsz) {
break;
}
@@ -1351,26 +1355,29 @@ void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
maxsz -= some;
/* fallthru */
case TCG_TYPE_V128:
- expand_2i_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128,
- c, g->load_dest, g->fniv);
+ expand_2i_vec(g->vece, dbase, dofs, abase, aofs, oprsz, 16,
+ TCG_TYPE_V128, c, g->load_dest, g->fniv);
break;
case TCG_TYPE_V64:
- expand_2i_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64,
- c, g->load_dest, g->fniv);
+ expand_2i_vec(g->vece, dbase, dofs, abase, aofs, oprsz, 8,
+ TCG_TYPE_V64, c, g->load_dest, g->fniv);
break;
case 0:
if (g->fni8 && check_size_impl(oprsz, 8)) {
- expand_2i_i64(dofs, aofs, oprsz, c, g->load_dest, g->fni8);
+ expand_2i_i64(dbase, dofs, abase, aofs, oprsz, c,
+ g->load_dest, g->fni8);
} else if (g->fni4 && check_size_impl(oprsz, 4)) {
- expand_2i_i32(dofs, aofs, oprsz, c, g->load_dest, g->fni4);
+ expand_2i_i32(dbase, dofs, abase, aofs, oprsz, c,
+ g->load_dest, g->fni4);
} else {
if (g->fno) {
- tcg_gen_gvec_2_ool(dofs, aofs, oprsz, maxsz, c, g->fno);
+ expand_2_ool(dbase, dofs, abase, aofs, oprsz, maxsz,
+ c, g->fno);
} else {
TCGv_i64 tcg_c = tcg_constant_i64(c);
- tcg_gen_gvec_2i_ool(dofs, aofs, tcg_c, oprsz,
- maxsz, c, g->fnoi);
+ expand_2i_ool(dbase, dofs, abase, aofs, tcg_c, oprsz,
+ maxsz, c, g->fnoi);
}
oprsz = maxsz;
}
@@ -1382,10 +1389,16 @@ void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
tcg_swap_vecop_list(hold_list);
if (oprsz < maxsz) {
- expand_clr(tcg_env, dofs + oprsz, maxsz - oprsz);
+ expand_clr(dbase, dofs + oprsz, maxsz - oprsz);
}
}
+void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
+ uint32_t maxsz, int64_t c, const GVecGen2i *g)
+{
+ tcg_gen_gvec_2i_var(tcg_env, dofs, tcg_env, aofs, oprsz, maxsz, c, g);
+}
+
/*
* Expand a vector operation with two vectors and a scalar,
* (dbase+dofs) = op(abase+aofs, c).
@@ -2279,8 +2292,10 @@ void tcg_gen_gvec_sub(unsigned vece, uint32_t dofs, uint32_t aofs,
static const TCGOpcode vecop_list_mul[] = { INDEX_op_mul_vec, 0 };
-void tcg_gen_gvec_mul(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_mul_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const GVecGen3 g[4] = {
{ .fniv = tcg_gen_mul_vec,
@@ -2305,7 +2320,15 @@ void tcg_gen_gvec_mul(unsigned vece, uint32_t dofs, uint32_t aofs,
};
tcg_debug_assert(vece <= MO_64);
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g[vece]);
+}
+
+void tcg_gen_gvec_mul(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_mul_var(vece, tcg_env, dofs, tcg_env, aofs, tcg_env, bofs,
+ oprsz, maxsz);
}
void tcg_gen_gvec_muls(unsigned vece, uint32_t dofs, uint32_t aofs,
@@ -2344,8 +2367,10 @@ void tcg_gen_gvec_muli(unsigned vece, uint32_t dofs, uint32_t aofs,
tcg_gen_gvec_muls(vece, dofs, aofs, tmp, oprsz, maxsz);
}
-void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_ssadd_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = { INDEX_op_ssadd_vec, 0 };
static const GVecGen3 g[4] = {
@@ -2367,11 +2392,21 @@ void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs,
.vece = MO_64 },
};
tcg_debug_assert(vece <= MO_64);
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g[vece]);
}
-void tcg_gen_gvec_sssub(unsigned vece, uint32_t dofs, uint32_t aofs,
+void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_ssadd_var(vece, tcg_env, dofs, tcg_env, aofs,
+ tcg_env, bofs, oprsz, maxsz);
+}
+
+void tcg_gen_gvec_sssub_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = { INDEX_op_sssub_vec, 0 };
static const GVecGen3 g[4] = {
@@ -2393,7 +2428,15 @@ void tcg_gen_gvec_sssub(unsigned vece, uint32_t dofs, uint32_t aofs,
.vece = MO_64 },
};
tcg_debug_assert(vece <= MO_64);
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g[vece]);
+}
+
+void tcg_gen_gvec_sssub(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_sssub_var(vece, tcg_env, dofs, tcg_env, aofs,
+ tcg_env, bofs, oprsz, maxsz);
}
static void tcg_gen_usadd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
@@ -2410,8 +2453,10 @@ static void tcg_gen_usadd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
tcg_gen_movcond_i64(TCG_COND_LTU, d, d, a, max, d);
}
-void tcg_gen_gvec_usadd(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_usadd_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = { INDEX_op_usadd_vec, 0 };
static const GVecGen3 g[4] = {
@@ -2435,11 +2480,21 @@ void tcg_gen_gvec_usadd(unsigned vece, uint32_t dofs, uint32_t aofs,
.vece = MO_64 }
};
tcg_debug_assert(vece <= MO_64);
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g[vece]);
}
-void tcg_gen_gvec_ussub(unsigned vece, uint32_t dofs, uint32_t aofs,
+void tcg_gen_gvec_usadd(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_usadd_var(vece, tcg_env, dofs, tcg_env, aofs,
+ tcg_env, bofs, oprsz, maxsz);
+}
+
+void tcg_gen_gvec_ussub_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = { INDEX_op_ussub_vec, 0 };
static const GVecGen3 g[4] = {
@@ -2463,7 +2518,15 @@ void tcg_gen_gvec_ussub(unsigned vece, uint32_t dofs, uint32_t aofs,
.vece = MO_64 }
};
tcg_debug_assert(vece <= MO_64);
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &g[vece]);
+}
+
+void tcg_gen_gvec_ussub(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_ussub_var(vece, tcg_env, dofs, tcg_env, aofs,
+ tcg_env, bofs, oprsz, maxsz);
}
void tcg_gen_gvec_smin_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
@@ -3131,8 +3194,9 @@ void tcg_gen_vec_shr16i_i32(TCGv_i32 d, TCGv_i32 a, int32_t c)
tcg_gen_andi_i32(d, d, mask);
}
-void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs,
- int64_t shift, uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_shri_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ int64_t shift, uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 };
static const GVecGen2i g[4] = {
@@ -3162,12 +3226,20 @@ void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs,
tcg_debug_assert(vece <= MO_64);
tcg_debug_assert(shift >= 0 && shift < (8 << vece));
if (shift == 0) {
- tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz);
+ tcg_gen_gvec_mov_var(vece, dbase, dofs, abase, aofs, oprsz, maxsz);
} else {
- tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]);
+ tcg_gen_gvec_2i_var(dbase, dofs, abase, aofs, oprsz, maxsz,
+ shift, &g[vece]);
}
}
+void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs,
+ int64_t shift, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_shri_var(vece, tcg_env, dofs, tcg_env, aofs,
+ shift, oprsz, maxsz);
+}
+
void tcg_gen_vec_sar8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c)
{
uint64_t s_mask = dup_const(MO_8, 0x80 >> c);
@@ -3224,8 +3296,9 @@ void tcg_gen_vec_sar16i_i32(TCGv_i32 d, TCGv_i32 a, int32_t c)
tcg_temp_free_i32(s);
}
-void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs,
- int64_t shift, uint32_t oprsz, uint32_t maxsz)
+void tcg_gen_gvec_sari_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ int64_t shift, uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = { INDEX_op_sari_vec, 0 };
static const GVecGen2i g[4] = {
@@ -3255,12 +3328,20 @@ void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs,
tcg_debug_assert(vece <= MO_64);
tcg_debug_assert(shift >= 0 && shift < (8 << vece));
if (shift == 0) {
- tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz);
+ tcg_gen_gvec_mov_var(vece, dbase, dofs, abase, aofs, oprsz, maxsz);
} else {
- tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]);
+ tcg_gen_gvec_2i_var(dbase, dofs, abase, aofs, oprsz, maxsz,
+ shift, &g[vece]);
}
}
+void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs,
+ int64_t shift, uint32_t oprsz, uint32_t maxsz)
+{
+ tcg_gen_gvec_sari_var(vece, tcg_env, dofs, tcg_env, aofs,
+ shift, oprsz, maxsz);
+}
+
void tcg_gen_vec_rotl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c)
{
uint64_t mask = dup_const(MO_8, 0xff << c);
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v3 5/6] target/hexagon: share HVX contexts among CPUs
2026-09-13 15:59 [PATCH v3 0/6] hexagon: Add HVX context Brian Cain
` (3 preceding siblings ...)
2026-09-13 15:59 ` [PATCH v3 4/6] target/hexagon: raise an exception for HVX with SSR:XE clear Brian Cain
@ 2026-09-13 15:59 ` Brian Cain
2026-09-13 22:02 ` Richard Henderson
2026-09-13 15:59 ` [PATCH v3 6/6] tests/functional/hexagon: add HVX tests Brian Cain
5 siblings, 1 reply; 8+ messages in thread
From: Brian Cain @ 2026-09-13 15:59 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Pierrick Bouvier, Brian Cain,
marco.liebel, Helge Deller, Paolo Bonzini, richard.henderson,
Laurent Vivier
The HVX register file belongs to an extension context, not a hardware thread.
Model each system-emulation context as a QOM device, link the contexts to
each vCPU, and use SSR:XA to select the active context.
Keep one embedded context per linux-user CPU. Carry the selected register-file
base with HVX operands so translated code can address the selected context
at run time.
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
include/hw/hexagon/hexagon.h | 1 +
include/hw/hexagon/hexagon_hvx_context.h | 27 +
target/hexagon/cpu.h | 27 +-
target/hexagon/cpu_helper.h | 1 +
target/hexagon/gen_tcg_hvx.h | 608 +++++++++++++----------
target/hexagon/genptr.h | 8 +
target/hexagon/mmvec/macros.h | 14 +-
target/hexagon/translate.h | 12 +-
hw/hexagon/hex-subsys.c | 36 ++
hw/hexagon/hexagon_hvx_context.c | 84 ++++
linux-user/main.c | 3 +
target/hexagon/cpu.c | 30 +-
target/hexagon/cpu_helper.c | 72 +++
target/hexagon/gdbstub.c | 16 +-
target/hexagon/genptr.c | 102 ++--
target/hexagon/machine.c | 12 +
target/hexagon/op_helper.c | 37 +-
target/hexagon/translate.c | 60 ++-
hw/hexagon/meson.build | 1 +
target/hexagon/hex_common.py | 179 ++++---
20 files changed, 881 insertions(+), 449 deletions(-)
create mode 100644 include/hw/hexagon/hexagon_hvx_context.h
create mode 100644 hw/hexagon/hexagon_hvx_context.c
diff --git a/include/hw/hexagon/hexagon.h b/include/hw/hexagon/hexagon.h
index 62398eeb359..9b5d33ffc3b 100644
--- a/include/hw/hexagon/hexagon.h
+++ b/include/hw/hexagon/hexagon.h
@@ -173,6 +173,7 @@ struct HexagonCommonMachineState {
DeviceState *qtimer;
DeviceState *glob_regs;
DeviceState *tlb;
+ unsigned num_hvx_ctx;
};
#endif
diff --git a/include/hw/hexagon/hexagon_hvx_context.h b/include/hw/hexagon/hexagon_hvx_context.h
new file mode 100644
index 00000000000..ab85816a7ff
--- /dev/null
+++ b/include/hw/hexagon/hexagon_hvx_context.h
@@ -0,0 +1,27 @@
+/*
+ * Hexagon HVX Extension Context QOM Object
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HEXAGON_HVX_CONTEXT_H
+#define HEXAGON_HVX_CONTEXT_H
+
+#include "hw/core/sysbus.h"
+#include "qom/object.h"
+#include "target/hexagon/cpu.h"
+
+#define TYPE_HEXAGON_HVX_CONTEXT "hexagon-hvx-context"
+OBJECT_DECLARE_SIMPLE_TYPE(HexagonHVXContextState, HEXAGON_HVX_CONTEXT)
+
+struct HexagonHVXContextState {
+ SysBusDevice parent_obj;
+
+ /* Physical context number, as SSR:XA maps to it. */
+ uint32_t index;
+
+ HexagonHVXContext regs;
+};
+
+#endif /* HEXAGON_HVX_CONTEXT_H */
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 97f689fda22..48401cc71eb 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -29,6 +29,7 @@
typedef struct HexagonTLBState HexagonTLBState;
typedef struct HexagonGlobalRegState HexagonGlobalRegState;
+typedef struct HexagonHVXContextState HexagonHVXContextState;
#include "cpu-qom.h"
#include "exec/cpu-common.h"
@@ -49,6 +50,7 @@ typedef struct HexagonGlobalRegState HexagonGlobalRegState;
#define REG_WRITES_MAX 32
#define PRED_WRITES_MAX 5 /* 4 insns + endloop */
#define VSTORES_MAX 2
+#define HVX_CONTEXTS_MAX 8
#define MAX_TLB_ENTRIES 1024
#define THREADS_MAX 16
@@ -120,6 +122,11 @@ typedef struct {
/* Maximum number of vector temps in a packet */
#define VECTOR_TEMPS_MAX 4
+typedef struct HexagonHVXContext {
+ MMVector VRegs[NUM_VREGS];
+ MMQReg QRegs[NUM_QREGS];
+} QEMU_ALIGNED(16) HexagonHVXContext;
+
typedef struct CPUArchState {
target_ulong gpr[TOTAL_PER_THREAD_REGS];
target_ulong pred[NUM_PREGS];
@@ -159,11 +166,13 @@ typedef struct CPUArchState {
target_ulong llsc_val;
uint64_t llsc_val_i64;
- MMVector VRegs[NUM_VREGS] QEMU_ALIGNED(16);
+#ifndef CONFIG_USER_ONLY
+ HexagonHVXContext *hvx;
+#endif
+
MMVector future_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
MMVector tmp_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
- MMQReg QRegs[NUM_QREGS] QEMU_ALIGNED(16);
MMQReg future_QRegs[NUM_QREGS] QEMU_ALIGNED(16);
/* Temporaries used within instructions */
@@ -195,7 +204,10 @@ struct ArchCPU {
CPUHexagonState env;
HexagonCPUConfig cfg;
-#ifndef CONFIG_USER_ONLY
+#ifdef CONFIG_USER_ONLY
+ HexagonHVXContext hvx_ctx;
+#else
+ HexagonHVXContextState *hvx_ctx[HVX_CONTEXTS_MAX];
HexagonTLBState *tlb;
uint32_t boot_addr;
HexagonGlobalRegState *globalregs;
@@ -204,6 +216,15 @@ struct ArchCPU {
#endif
};
+static inline HexagonHVXContext *hex_hvx(CPUHexagonState *env)
+{
+#ifdef CONFIG_USER_ONLY
+ return &env_archcpu(env)->hvx_ctx;
+#else
+ return env->hvx;
+#endif
+}
+
FIELD(TB_FLAGS, IS_TIGHT_LOOP, 0, 1)
FIELD(TB_FLAGS, MMU_INDEX, 1, 3)
FIELD(TB_FLAGS, PCYCLE_ENABLED, 4, 1)
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index 12512efd74f..afb4df59f80 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -15,6 +15,7 @@ void hexagon_peek_memory_range(CPUHexagonState *env, uint32_t start_addr,
uint32_t length, uintptr_t retaddr);
uint32_t hexagon_get_pmu_counter(CPUHexagonState *cur_env, int index);
void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old);
+unsigned hexagon_hvx_select_context(CPUHexagonState *env, uint32_t ssr);
int get_cpu_mode(const CPUHexagonState *env);
int get_exe_mode(const CPUHexagonState *env);
void clear_wait_mode(CPUHexagonState *env);
diff --git a/target/hexagon/gen_tcg_hvx.h b/target/hexagon/gen_tcg_hvx.h
index 2a342cdee69..f399291dc66 100644
--- a/target/hexagon/gen_tcg_hvx.h
+++ b/target/hexagon/gen_tcg_hvx.h
@@ -49,8 +49,8 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
do { \
if (ctx->pre_commit) { \
intptr_t dstoff = offsetof(CPUHexagonState, qtmp); \
- tcg_gen_gvec_mov(MO_64, dstoff, QvV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, tcg_env, dstoff, QvV_base, QvV_off, \
+ sizeof(MMVector), sizeof(MMVector)); \
} else { \
assert_vhist_tmp(ctx); \
gen_helper_vhistq(tcg_env); \
@@ -65,8 +65,8 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
do { \
if (ctx->pre_commit) { \
intptr_t dstoff = offsetof(CPUHexagonState, qtmp); \
- tcg_gen_gvec_mov(MO_64, dstoff, QvV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, tcg_env, dstoff, QvV_base, QvV_off, \
+ sizeof(MMVector), sizeof(MMVector)); \
} else { \
assert_vhist_tmp(ctx); \
gen_helper_vwhist256q(tcg_env); \
@@ -81,8 +81,8 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
do { \
if (ctx->pre_commit) { \
intptr_t dstoff = offsetof(CPUHexagonState, qtmp); \
- tcg_gen_gvec_mov(MO_64, dstoff, QvV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, tcg_env, dstoff, QvV_base, QvV_off, \
+ sizeof(MMVector), sizeof(MMVector)); \
} else { \
assert_vhist_tmp(ctx); \
gen_helper_vwhist256q_sat(tcg_env); \
@@ -97,8 +97,8 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
do { \
if (ctx->pre_commit) { \
intptr_t dstoff = offsetof(CPUHexagonState, qtmp); \
- tcg_gen_gvec_mov(MO_64, dstoff, QvV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, tcg_env, dstoff, QvV_base, QvV_off, \
+ sizeof(MMVector), sizeof(MMVector)); \
} else { \
assert_vhist_tmp(ctx); \
gen_helper_vwhist128q(tcg_env); \
@@ -114,8 +114,8 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
do { \
if (ctx->pre_commit) { \
intptr_t dstoff = offsetof(CPUHexagonState, qtmp); \
- tcg_gen_gvec_mov(MO_64, dstoff, QvV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, tcg_env, dstoff, QvV_base, QvV_off, \
+ sizeof(MMVector), sizeof(MMVector)); \
} else { \
TCGv tcgv_uiV = tcg_constant_tl(uiV); \
assert_vhist_tmp(ctx); \
@@ -125,19 +125,20 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
#define fGEN_TCG_V6_vassign(SHORTCODE) \
- tcg_gen_gvec_mov(MO_64, VdV_off, VuV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_mov_var(MO_64, VdV_base, VdV_off, VuV_base, VuV_off, \
+ sizeof(MMVector), sizeof(MMVector))
#define fGEN_TCG_V6_vassign_tmp(SHORTCODE) \
- tcg_gen_gvec_mov(MO_64, VdV_off, VuV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_mov_var(MO_64, VdV_base, VdV_off, VuV_base, VuV_off, \
+ sizeof(MMVector), sizeof(MMVector))
#define fGEN_TCG_V6_vcombine_tmp(SHORTCODE) \
do { \
- tcg_gen_gvec_mov(MO_64, VddV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
- tcg_gen_gvec_mov(MO_64, VddV_off + sizeof(MMVector), VuV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, VddV_base, VddV_off, VvV_base, VvV_off, \
+ sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, VddV_base, VddV_off + sizeof(MMVector), \
+ VuV_base, VuV_off, sizeof(MMVector), \
+ sizeof(MMVector)); \
} while (0)
/*
@@ -148,18 +149,20 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
#define fGEN_TCG_V6_vcombine(SHORTCODE) \
do { \
if (VddV_off != VuV_off) { \
- tcg_gen_gvec_mov(MO_64, VddV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
- tcg_gen_gvec_mov(MO_64, VddV_off + sizeof(MMVector), VuV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, VddV_base, VddV_off, VvV_base, \
+ VvV_off, sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, VddV_base, \
+ VddV_off + sizeof(MMVector), VuV_base, \
+ VuV_off, sizeof(MMVector), sizeof(MMVector)); \
} else { \
intptr_t tmpoff = offsetof(CPUHexagonState, vtmp); \
- tcg_gen_gvec_mov(MO_64, tmpoff, VuV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
- tcg_gen_gvec_mov(MO_64, VddV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
- tcg_gen_gvec_mov(MO_64, VddV_off + sizeof(MMVector), tmpoff, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, tcg_env, tmpoff, VuV_base, VuV_off, \
+ sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, VddV_base, VddV_off, VvV_base, \
+ VvV_off, sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, VddV_base, \
+ VddV_off + sizeof(MMVector), tcg_env, tmpoff, \
+ sizeof(MMVector), sizeof(MMVector)); \
} \
} while (0)
@@ -170,8 +173,8 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
TCGLabel *false_label = gen_new_label(); \
tcg_gen_andi_tl(lsb, PsV, 1); \
tcg_gen_brcondi_tl(TCG_COND_NE, lsb, PRED, false_label); \
- tcg_gen_gvec_mov(MO_64, VdV_off, VuV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_mov_var(MO_64, VdV_base, VdV_off, VuV_base, VuV_off, \
+ sizeof(MMVector), sizeof(MMVector)); \
gen_set_label(false_label); \
} while (0)
@@ -186,231 +189,276 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
/* Vector add - various forms */
#define fGEN_TCG_V6_vaddb(SHORTCODE) \
- tcg_gen_gvec_add(MO_8, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_add_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, VvV_base, \
+ VvV_off, sizeof(MMVector), sizeof(MMVector))
#define fGEN_TCG_V6_vaddh(SHORTCYDE) \
- tcg_gen_gvec_add(MO_16, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_add_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vaddw(SHORTCODE) \
- tcg_gen_gvec_add(MO_32, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_add_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vaddb_dv(SHORTCODE) \
- tcg_gen_gvec_add(MO_8, VddV_off, VuuV_off, VvvV_off, \
- sizeof(MMVector) * 2, sizeof(MMVector) * 2)
+ tcg_gen_gvec_add_var(MO_8, VddV_base, VddV_off, VuuV_base, VuuV_off, \
+ VvvV_base, VvvV_off, sizeof(MMVector) * 2, \
+ sizeof(MMVector) * 2)
#define fGEN_TCG_V6_vaddh_dv(SHORTCYDE) \
- tcg_gen_gvec_add(MO_16, VddV_off, VuuV_off, VvvV_off, \
- sizeof(MMVector) * 2, sizeof(MMVector) * 2)
+ tcg_gen_gvec_add_var(MO_16, VddV_base, VddV_off, VuuV_base, VuuV_off, \
+ VvvV_base, VvvV_off, sizeof(MMVector) * 2, \
+ sizeof(MMVector) * 2)
#define fGEN_TCG_V6_vaddw_dv(SHORTCODE) \
- tcg_gen_gvec_add(MO_32, VddV_off, VuuV_off, VvvV_off, \
- sizeof(MMVector) * 2, sizeof(MMVector) * 2)
+ tcg_gen_gvec_add_var(MO_32, VddV_base, VddV_off, VuuV_base, VuuV_off, \
+ VvvV_base, VvvV_off, sizeof(MMVector) * 2, \
+ sizeof(MMVector) * 2)
/* Vector sub - various forms */
#define fGEN_TCG_V6_vsubb(SHORTCODE) \
- tcg_gen_gvec_sub(MO_8, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_sub_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, VvV_base, \
+ VvV_off, sizeof(MMVector), sizeof(MMVector))
#define fGEN_TCG_V6_vsubh(SHORTCODE) \
- tcg_gen_gvec_sub(MO_16, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_sub_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vsubw(SHORTCODE) \
- tcg_gen_gvec_sub(MO_32, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_sub_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vsubb_dv(SHORTCODE) \
- tcg_gen_gvec_sub(MO_8, VddV_off, VuuV_off, VvvV_off, \
- sizeof(MMVector) * 2, sizeof(MMVector) * 2)
+ tcg_gen_gvec_sub_var(MO_8, VddV_base, VddV_off, VuuV_base, VuuV_off, \
+ VvvV_base, VvvV_off, sizeof(MMVector) * 2, \
+ sizeof(MMVector) * 2)
#define fGEN_TCG_V6_vsubh_dv(SHORTCODE) \
- tcg_gen_gvec_sub(MO_16, VddV_off, VuuV_off, VvvV_off, \
- sizeof(MMVector) * 2, sizeof(MMVector) * 2)
+ tcg_gen_gvec_sub_var(MO_16, VddV_base, VddV_off, VuuV_base, VuuV_off, \
+ VvvV_base, VvvV_off, sizeof(MMVector) * 2, \
+ sizeof(MMVector) * 2)
#define fGEN_TCG_V6_vsubw_dv(SHORTCODE) \
- tcg_gen_gvec_sub(MO_32, VddV_off, VuuV_off, VvvV_off, \
- sizeof(MMVector) * 2, sizeof(MMVector) * 2)
+ tcg_gen_gvec_sub_var(MO_32, VddV_base, VddV_off, VuuV_base, VuuV_off, \
+ VvvV_base, VvvV_off, sizeof(MMVector) * 2, \
+ sizeof(MMVector) * 2)
#define fGEN_TCG_V6_vaddbsat(SHORTCODE) \
- tcg_gen_gvec_ssadd(MO_8, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_ssadd_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vaddhsat(SHORTCODE) \
- tcg_gen_gvec_ssadd(MO_16, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_ssadd_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vaddwsat(SHORTCODE) \
- tcg_gen_gvec_ssadd(MO_32, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_ssadd_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vaddubsat(SHORTCODE) \
- tcg_gen_gvec_usadd(MO_8, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_usadd_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vadduhsat(SHORTCODE) \
- tcg_gen_gvec_usadd(MO_16, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_usadd_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vadduwsat(SHORTCODE) \
- tcg_gen_gvec_usadd(MO_32, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_usadd_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
-#define fGEN_TCG_PAIR_ADDSUB(OP, VECE, DST, SRC_A, SRC_B) \
- tcg_gen_gvec_##OP(VECE, DST, SRC_A, SRC_B, \
- 2 * VECTOR_SIZE_BYTE, 2 * VECTOR_SIZE_BYTE)
+#define fGEN_TCG_PAIR_ADDSUB(OP, VECE, DBASE, DST, ABASE, SRC_A, BBASE, SRC_B) \
+ tcg_gen_gvec_##OP##_var(VECE, DBASE, DST, ABASE, SRC_A, BBASE, SRC_B, \
+ 2 * VECTOR_SIZE_BYTE, 2 * VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vaddbsat_dv(SHORTCODE) \
- fGEN_TCG_PAIR_ADDSUB(ssadd, MO_8, VddV_off, VuuV_off, VvvV_off)
+ fGEN_TCG_PAIR_ADDSUB(ssadd, MO_8, VddV_base, VddV_off, \
+ VuuV_base, VuuV_off, VvvV_base, VvvV_off)
#define fGEN_TCG_V6_vaddhsat_dv(SHORTCODE) \
- fGEN_TCG_PAIR_ADDSUB(ssadd, MO_16, VddV_off, VuuV_off, VvvV_off)
+ fGEN_TCG_PAIR_ADDSUB(ssadd, MO_16, VddV_base, VddV_off, \
+ VuuV_base, VuuV_off, VvvV_base, VvvV_off)
#define fGEN_TCG_V6_vaddwsat_dv(SHORTCODE) \
- fGEN_TCG_PAIR_ADDSUB(ssadd, MO_32, VddV_off, VuuV_off, VvvV_off)
+ fGEN_TCG_PAIR_ADDSUB(ssadd, MO_32, VddV_base, VddV_off, \
+ VuuV_base, VuuV_off, VvvV_base, VvvV_off)
#define fGEN_TCG_V6_vaddubsat_dv(SHORTCODE) \
- fGEN_TCG_PAIR_ADDSUB(usadd, MO_8, VddV_off, VuuV_off, VvvV_off)
+ fGEN_TCG_PAIR_ADDSUB(usadd, MO_8, VddV_base, VddV_off, \
+ VuuV_base, VuuV_off, VvvV_base, VvvV_off)
#define fGEN_TCG_V6_vadduhsat_dv(SHORTCODE) \
- fGEN_TCG_PAIR_ADDSUB(usadd, MO_16, VddV_off, VuuV_off, VvvV_off)
+ fGEN_TCG_PAIR_ADDSUB(usadd, MO_16, VddV_base, VddV_off, \
+ VuuV_base, VuuV_off, VvvV_base, VvvV_off)
#define fGEN_TCG_V6_vadduwsat_dv(SHORTCODE) \
- fGEN_TCG_PAIR_ADDSUB(usadd, MO_32, VddV_off, VuuV_off, VvvV_off)
+ fGEN_TCG_PAIR_ADDSUB(usadd, MO_32, VddV_base, VddV_off, \
+ VuuV_base, VuuV_off, VvvV_base, VvvV_off)
#define fGEN_TCG_V6_vsubbsat(SHORTCODE) \
- tcg_gen_gvec_sssub(MO_8, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_sssub_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vsubhsat(SHORTCODE) \
- tcg_gen_gvec_sssub(MO_16, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_sssub_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vsubwsat(SHORTCODE) \
- tcg_gen_gvec_sssub(MO_32, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_sssub_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vsububsat(SHORTCODE) \
- tcg_gen_gvec_ussub(MO_8, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_ussub_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vsubuhsat(SHORTCODE) \
- tcg_gen_gvec_ussub(MO_16, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_ussub_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vsubuwsat(SHORTCODE) \
- tcg_gen_gvec_ussub(MO_32, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_ussub_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vsubbsat_dv(SHORTCODE) \
- fGEN_TCG_PAIR_ADDSUB(sssub, MO_8, VddV_off, VuuV_off, VvvV_off)
+ fGEN_TCG_PAIR_ADDSUB(sssub, MO_8, VddV_base, VddV_off, \
+ VuuV_base, VuuV_off, VvvV_base, VvvV_off)
#define fGEN_TCG_V6_vsubhsat_dv(SHORTCODE) \
- fGEN_TCG_PAIR_ADDSUB(sssub, MO_16, VddV_off, VuuV_off, VvvV_off)
+ fGEN_TCG_PAIR_ADDSUB(sssub, MO_16, VddV_base, VddV_off, \
+ VuuV_base, VuuV_off, VvvV_base, VvvV_off)
#define fGEN_TCG_V6_vsubwsat_dv(SHORTCODE) \
- fGEN_TCG_PAIR_ADDSUB(sssub, MO_32, VddV_off, VuuV_off, VvvV_off)
+ fGEN_TCG_PAIR_ADDSUB(sssub, MO_32, VddV_base, VddV_off, \
+ VuuV_base, VuuV_off, VvvV_base, VvvV_off)
#define fGEN_TCG_V6_vsububsat_dv(SHORTCODE) \
- fGEN_TCG_PAIR_ADDSUB(ussub, MO_8, VddV_off, VuuV_off, VvvV_off)
+ fGEN_TCG_PAIR_ADDSUB(ussub, MO_8, VddV_base, VddV_off, \
+ VuuV_base, VuuV_off, VvvV_base, VvvV_off)
#define fGEN_TCG_V6_vsubuhsat_dv(SHORTCODE) \
- fGEN_TCG_PAIR_ADDSUB(ussub, MO_16, VddV_off, VuuV_off, VvvV_off)
+ fGEN_TCG_PAIR_ADDSUB(ussub, MO_16, VddV_base, VddV_off, \
+ VuuV_base, VuuV_off, VvvV_base, VvvV_off)
#define fGEN_TCG_V6_vsubuwsat_dv(SHORTCODE) \
- fGEN_TCG_PAIR_ADDSUB(ussub, MO_32, VddV_off, VuuV_off, VvvV_off)
+ fGEN_TCG_PAIR_ADDSUB(ussub, MO_32, VddV_base, VddV_off, \
+ VuuV_base, VuuV_off, VvvV_base, VvvV_off)
#define fGEN_TCG_V6_vmpyih(SHORTCODE) \
- tcg_gen_gvec_mul(MO_16, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ tcg_gen_gvec_mul_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vabsdiffub(SHORTCODE) \
- gen_gvec_uabsdiff(MO_8, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ gen_gvec_uabsdiff_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vabsdiffuh(SHORTCODE) \
- gen_gvec_uabsdiff(MO_16, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ gen_gvec_uabsdiff_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vabsdiffh(SHORTCODE) \
- gen_gvec_sabsdiff(MO_16, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ gen_gvec_sabsdiff_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_V6_vabsdiffw(SHORTCODE) \
- gen_gvec_sabsdiff(MO_32, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+ gen_gvec_sabsdiff_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
#define fGEN_TCG_VEC_AVG(VECE, SHIFT_FN) \
do { \
intptr_t tmpoff = offsetof(CPUHexagonState, vtmp); \
- tcg_gen_gvec_and(MO_64, tmpoff, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
- tcg_gen_gvec_xor(MO_64, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
- SHIFT_FN(VECE, VdV_off, VdV_off, 1, \
+ tcg_gen_gvec_and_var(MO_64, tcg_env, tmpoff, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
+ tcg_gen_gvec_xor_var(MO_64, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
+ SHIFT_FN(VECE, VdV_base, VdV_off, VdV_base, VdV_off, 1, \
VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
- tcg_gen_gvec_add(VECE, VdV_off, tmpoff, VdV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
+ tcg_gen_gvec_add_var(VECE, VdV_base, VdV_off, tcg_env, tmpoff, \
+ VdV_base, VdV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
} while (0)
#define fGEN_TCG_V6_vavgub(SHORTCODE) \
- fGEN_TCG_VEC_AVG(MO_8, tcg_gen_gvec_shri)
+ fGEN_TCG_VEC_AVG(MO_8, tcg_gen_gvec_shri_var)
#define fGEN_TCG_V6_vavguh(SHORTCODE) \
- fGEN_TCG_VEC_AVG(MO_16, tcg_gen_gvec_shri)
+ fGEN_TCG_VEC_AVG(MO_16, tcg_gen_gvec_shri_var)
#define fGEN_TCG_V6_vavguw(SHORTCODE) \
- fGEN_TCG_VEC_AVG(MO_32, tcg_gen_gvec_shri)
+ fGEN_TCG_VEC_AVG(MO_32, tcg_gen_gvec_shri_var)
#define fGEN_TCG_V6_vavgb(SHORTCODE) \
- fGEN_TCG_VEC_AVG(MO_8, tcg_gen_gvec_sari)
+ fGEN_TCG_VEC_AVG(MO_8, tcg_gen_gvec_sari_var)
#define fGEN_TCG_V6_vavgh(SHORTCODE) \
- fGEN_TCG_VEC_AVG(MO_16, tcg_gen_gvec_sari)
+ fGEN_TCG_VEC_AVG(MO_16, tcg_gen_gvec_sari_var)
#define fGEN_TCG_V6_vavgw(SHORTCODE) \
- fGEN_TCG_VEC_AVG(MO_32, tcg_gen_gvec_sari)
+ fGEN_TCG_VEC_AVG(MO_32, tcg_gen_gvec_sari_var)
#define fGEN_TCG_VEC_AVGRND(VECE, SHIFT_FN) \
do { \
intptr_t tmpoff = offsetof(CPUHexagonState, vtmp); \
- tcg_gen_gvec_or(MO_64, tmpoff, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
- tcg_gen_gvec_xor(MO_64, VdV_off, VuV_off, VvV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
- SHIFT_FN(VECE, VdV_off, VdV_off, 1, \
+ tcg_gen_gvec_or_var(MO_64, tcg_env, tmpoff, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
+ tcg_gen_gvec_xor_var(MO_64, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
+ SHIFT_FN(VECE, VdV_base, VdV_off, VdV_base, VdV_off, 1, \
VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
- tcg_gen_gvec_sub(VECE, VdV_off, tmpoff, VdV_off, \
- VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
+ tcg_gen_gvec_sub_var(VECE, VdV_base, VdV_off, tcg_env, tmpoff, \
+ VdV_base, VdV_off, \
+ VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE); \
} while (0)
#define fGEN_TCG_V6_vavgubrnd(SHORTCODE) \
- fGEN_TCG_VEC_AVGRND(MO_8, tcg_gen_gvec_shri)
+ fGEN_TCG_VEC_AVGRND(MO_8, tcg_gen_gvec_shri_var)
#define fGEN_TCG_V6_vavguhrnd(SHORTCODE) \
- fGEN_TCG_VEC_AVGRND(MO_16, tcg_gen_gvec_shri)
+ fGEN_TCG_VEC_AVGRND(MO_16, tcg_gen_gvec_shri_var)
#define fGEN_TCG_V6_vavguwrnd(SHORTCODE) \
- fGEN_TCG_VEC_AVGRND(MO_32, tcg_gen_gvec_shri)
+ fGEN_TCG_VEC_AVGRND(MO_32, tcg_gen_gvec_shri_var)
#define fGEN_TCG_V6_vavgbrnd(SHORTCODE) \
- fGEN_TCG_VEC_AVGRND(MO_8, tcg_gen_gvec_sari)
+ fGEN_TCG_VEC_AVGRND(MO_8, tcg_gen_gvec_sari_var)
#define fGEN_TCG_V6_vavghrnd(SHORTCODE) \
- fGEN_TCG_VEC_AVGRND(MO_16, tcg_gen_gvec_sari)
+ fGEN_TCG_VEC_AVGRND(MO_16, tcg_gen_gvec_sari_var)
#define fGEN_TCG_V6_vavgwrnd(SHORTCODE) \
- fGEN_TCG_VEC_AVGRND(MO_32, tcg_gen_gvec_sari)
+ fGEN_TCG_VEC_AVGRND(MO_32, tcg_gen_gvec_sari_var)
/* Vector shift right - various forms */
#define fGEN_TCG_V6_vasrh(SHORTCODE) \
do { \
TCGv shift = tcg_temp_new(); \
tcg_gen_andi_tl(shift, RtV, 15); \
- tcg_gen_gvec_sars(MO_16, VdV_off, VuV_off, shift, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_sars_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ shift, sizeof(MMVector), sizeof(MMVector)); \
} while (0)
#define fGEN_TCG_V6_vasrh_acc(SHORTCODE) \
@@ -418,18 +466,19 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
intptr_t tmpoff = offsetof(CPUHexagonState, vtmp); \
TCGv shift = tcg_temp_new(); \
tcg_gen_andi_tl(shift, RtV, 15); \
- tcg_gen_gvec_sars(MO_16, tmpoff, VuV_off, shift, \
- sizeof(MMVector), sizeof(MMVector)); \
- tcg_gen_gvec_add(MO_16, VxV_off, VxV_off, tmpoff, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_sars_var(MO_16, tcg_env, tmpoff, VuV_base, VuV_off, \
+ shift, sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_add_var(MO_16, VxV_base, VxV_off, VxV_base, VxV_off, \
+ tcg_env, tmpoff, sizeof(MMVector), \
+ sizeof(MMVector)); \
} while (0)
#define fGEN_TCG_V6_vasrw(SHORTCODE) \
do { \
TCGv shift = tcg_temp_new(); \
tcg_gen_andi_tl(shift, RtV, 31); \
- tcg_gen_gvec_sars(MO_32, VdV_off, VuV_off, shift, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_sars_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ shift, sizeof(MMVector), sizeof(MMVector)); \
} while (0)
#define fGEN_TCG_V6_vasrw_acc(SHORTCODE) \
@@ -437,34 +486,35 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
intptr_t tmpoff = offsetof(CPUHexagonState, vtmp); \
TCGv shift = tcg_temp_new(); \
tcg_gen_andi_tl(shift, RtV, 31); \
- tcg_gen_gvec_sars(MO_32, tmpoff, VuV_off, shift, \
- sizeof(MMVector), sizeof(MMVector)); \
- tcg_gen_gvec_add(MO_32, VxV_off, VxV_off, tmpoff, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_sars_var(MO_32, tcg_env, tmpoff, VuV_base, VuV_off, \
+ shift, sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_add_var(MO_32, VxV_base, VxV_off, VxV_base, VxV_off, \
+ tcg_env, tmpoff, sizeof(MMVector), \
+ sizeof(MMVector)); \
} while (0)
#define fGEN_TCG_V6_vlsrb(SHORTCODE) \
do { \
TCGv shift = tcg_temp_new(); \
tcg_gen_andi_tl(shift, RtV, 7); \
- tcg_gen_gvec_shrs(MO_8, VdV_off, VuV_off, shift, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_shrs_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, \
+ shift, sizeof(MMVector), sizeof(MMVector)); \
} while (0)
#define fGEN_TCG_V6_vlsrh(SHORTCODE) \
do { \
TCGv shift = tcg_temp_new(); \
tcg_gen_andi_tl(shift, RtV, 15); \
- tcg_gen_gvec_shrs(MO_16, VdV_off, VuV_off, shift, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_shrs_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ shift, sizeof(MMVector), sizeof(MMVector)); \
} while (0)
#define fGEN_TCG_V6_vlsrw(SHORTCODE) \
do { \
TCGv shift = tcg_temp_new(); \
tcg_gen_andi_tl(shift, RtV, 31); \
- tcg_gen_gvec_shrs(MO_32, VdV_off, VuV_off, shift, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_shrs_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ shift, sizeof(MMVector), sizeof(MMVector)); \
} while (0)
/* Vector shift left - various forms */
@@ -472,16 +522,16 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
do { \
TCGv shift = tcg_temp_new(); \
tcg_gen_andi_tl(shift, RtV, 7); \
- tcg_gen_gvec_shls(MO_8, VdV_off, VuV_off, shift, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_shls_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, \
+ shift, sizeof(MMVector), sizeof(MMVector)); \
} while (0)
#define fGEN_TCG_V6_vaslh(SHORTCODE) \
do { \
TCGv shift = tcg_temp_new(); \
tcg_gen_andi_tl(shift, RtV, 15); \
- tcg_gen_gvec_shls(MO_16, VdV_off, VuV_off, shift, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_shls_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ shift, sizeof(MMVector), sizeof(MMVector)); \
} while (0)
#define fGEN_TCG_V6_vaslh_acc(SHORTCODE) \
@@ -489,18 +539,19 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
intptr_t tmpoff = offsetof(CPUHexagonState, vtmp); \
TCGv shift = tcg_temp_new(); \
tcg_gen_andi_tl(shift, RtV, 15); \
- tcg_gen_gvec_shls(MO_16, tmpoff, VuV_off, shift, \
- sizeof(MMVector), sizeof(MMVector)); \
- tcg_gen_gvec_add(MO_16, VxV_off, VxV_off, tmpoff, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_shls_var(MO_16, tcg_env, tmpoff, VuV_base, VuV_off, \
+ shift, sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_add_var(MO_16, VxV_base, VxV_off, VxV_base, VxV_off, \
+ tcg_env, tmpoff, sizeof(MMVector), \
+ sizeof(MMVector)); \
} while (0)
#define fGEN_TCG_V6_vaslw(SHORTCODE) \
do { \
TCGv shift = tcg_temp_new(); \
tcg_gen_andi_tl(shift, RtV, 31); \
- tcg_gen_gvec_shls(MO_32, VdV_off, VuV_off, shift, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_shls_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ shift, sizeof(MMVector), sizeof(MMVector)); \
} while (0)
#define fGEN_TCG_V6_vaslw_acc(SHORTCODE) \
@@ -508,95 +559,109 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
intptr_t tmpoff = offsetof(CPUHexagonState, vtmp); \
TCGv shift = tcg_temp_new(); \
tcg_gen_andi_tl(shift, RtV, 31); \
- tcg_gen_gvec_shls(MO_32, tmpoff, VuV_off, shift, \
- sizeof(MMVector), sizeof(MMVector)); \
- tcg_gen_gvec_add(MO_32, VxV_off, VxV_off, tmpoff, \
- sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_shls_var(MO_32, tcg_env, tmpoff, VuV_base, VuV_off, \
+ shift, sizeof(MMVector), sizeof(MMVector)); \
+ tcg_gen_gvec_add_var(MO_32, VxV_base, VxV_off, VxV_base, VxV_off, \
+ tcg_env, tmpoff, sizeof(MMVector), \
+ sizeof(MMVector)); \
} while (0)
/* Vector max - various forms */
#define fGEN_TCG_V6_vmaxw(SHORTCODE) \
- tcg_gen_gvec_smax(MO_32, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_smax_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vmaxh(SHORTCODE) \
- tcg_gen_gvec_smax(MO_16, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_smax_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vmaxuh(SHORTCODE) \
- tcg_gen_gvec_umax(MO_16, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_umax_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vmaxb(SHORTCODE) \
- tcg_gen_gvec_smax(MO_8, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_smax_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vmaxub(SHORTCODE) \
- tcg_gen_gvec_umax(MO_8, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_umax_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
/* Vector min - various forms */
#define fGEN_TCG_V6_vminw(SHORTCODE) \
- tcg_gen_gvec_smin(MO_32, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_smin_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vminh(SHORTCODE) \
- tcg_gen_gvec_smin(MO_16, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_smin_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vminuh(SHORTCODE) \
- tcg_gen_gvec_umin(MO_16, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_umin_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vminb(SHORTCODE) \
- tcg_gen_gvec_smin(MO_8, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_smin_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vminub(SHORTCODE) \
- tcg_gen_gvec_umin(MO_8, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_umin_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
/* Vector logical ops */
#define fGEN_TCG_V6_vxor(SHORTCODE) \
- tcg_gen_gvec_xor(MO_64, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_xor_var(MO_64, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vand(SHORTCODE) \
- tcg_gen_gvec_and(MO_64, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_and_var(MO_64, VdV_base, VdV_off, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector))
#define fGEN_TCG_V6_vor(SHORTCODE) \
- tcg_gen_gvec_or(MO_64, VdV_off, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_or_var(MO_64, VdV_base, VdV_off, VuV_base, VuV_off, VvV_base, \
+ VvV_off, sizeof(MMVector), sizeof(MMVector))
#define fGEN_TCG_V6_vnot(SHORTCODE) \
- tcg_gen_gvec_not(MO_64, VdV_off, VuV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_not_var(MO_64, VdV_base, VdV_off, VuV_base, VuV_off, \
+ sizeof(MMVector), sizeof(MMVector))
/* Q register logical ops */
#define fGEN_TCG_V6_pred_or(SHORTCODE) \
- tcg_gen_gvec_or(MO_64, QdV_off, QsV_off, QtV_off, \
- sizeof(MMQReg), sizeof(MMQReg))
+ tcg_gen_gvec_or_var(MO_64, QdV_base, QdV_off, QsV_base, QsV_off, QtV_base, \
+ QtV_off, sizeof(MMQReg), sizeof(MMQReg))
#define fGEN_TCG_V6_pred_and(SHORTCODE) \
- tcg_gen_gvec_and(MO_64, QdV_off, QsV_off, QtV_off, \
- sizeof(MMQReg), sizeof(MMQReg))
+ tcg_gen_gvec_and_var(MO_64, QdV_base, QdV_off, QsV_base, QsV_off, \
+ QtV_base, QtV_off, sizeof(MMQReg), sizeof(MMQReg))
#define fGEN_TCG_V6_pred_xor(SHORTCODE) \
- tcg_gen_gvec_xor(MO_64, QdV_off, QsV_off, QtV_off, \
- sizeof(MMQReg), sizeof(MMQReg))
+ tcg_gen_gvec_xor_var(MO_64, QdV_base, QdV_off, QsV_base, QsV_off, \
+ QtV_base, QtV_off, sizeof(MMQReg), sizeof(MMQReg))
#define fGEN_TCG_V6_pred_or_n(SHORTCODE) \
- tcg_gen_gvec_orc(MO_64, QdV_off, QsV_off, QtV_off, \
- sizeof(MMQReg), sizeof(MMQReg))
+ tcg_gen_gvec_orc_var(MO_64, QdV_base, QdV_off, QsV_base, QsV_off, \
+ QtV_base, QtV_off, sizeof(MMQReg), sizeof(MMQReg))
#define fGEN_TCG_V6_pred_and_n(SHORTCODE) \
- tcg_gen_gvec_andc(MO_64, QdV_off, QsV_off, QtV_off, \
- sizeof(MMQReg), sizeof(MMQReg))
+ tcg_gen_gvec_andc_var(MO_64, QdV_base, QdV_off, QsV_base, QsV_off, \
+ QtV_base, QtV_off, sizeof(MMQReg), sizeof(MMQReg))
#define fGEN_TCG_V6_pred_not(SHORTCODE) \
- tcg_gen_gvec_not(MO_64, QdV_off, QsV_off, \
- sizeof(MMQReg), sizeof(MMQReg))
+ tcg_gen_gvec_not_var(MO_64, QdV_base, QdV_off, QsV_base, QsV_off, \
+ sizeof(MMQReg), sizeof(MMQReg))
/* Vector compares */
#define fGEN_TCG_VEC_CMP(COND, TYPE, SIZE) \
do { \
intptr_t tmpoff = offsetof(CPUHexagonState, vtmp); \
- tcg_gen_gvec_cmp(COND, TYPE, tmpoff, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
- vec_to_qvec(SIZE, QdV_off, tmpoff); \
+ tcg_gen_gvec_cmp_var(COND, TYPE, tcg_env, tmpoff, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector)); \
+ vec_to_qvec(SIZE, QdV_base, QdV_off, tcg_env, tmpoff); \
} while (0)
#define fGEN_TCG_V6_vgtw(SHORTCODE) \
@@ -624,100 +689,102 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
do { \
intptr_t tmpoff = offsetof(CPUHexagonState, vtmp); \
intptr_t qoff = offsetof(CPUHexagonState, qtmp); \
- tcg_gen_gvec_cmp(COND, TYPE, tmpoff, VuV_off, VvV_off, \
- sizeof(MMVector), sizeof(MMVector)); \
- vec_to_qvec(SIZE, qoff, tmpoff); \
- OP(MO_64, QxV_off, QxV_off, qoff, sizeof(MMQReg), sizeof(MMQReg)); \
+ tcg_gen_gvec_cmp_var(COND, TYPE, tcg_env, tmpoff, VuV_base, VuV_off, \
+ VvV_base, VvV_off, sizeof(MMVector), \
+ sizeof(MMVector)); \
+ vec_to_qvec(SIZE, tcg_env, qoff, tcg_env, tmpoff); \
+ OP(MO_64, QxV_base, QxV_off, QxV_base, QxV_off, tcg_env, qoff, \
+ sizeof(MMQReg), sizeof(MMQReg)); \
} while (0)
#define fGEN_TCG_V6_vgtw_and(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_32, 4, tcg_gen_gvec_and)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_32, 4, tcg_gen_gvec_and_var)
#define fGEN_TCG_V6_vgtw_or(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_32, 4, tcg_gen_gvec_or)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_32, 4, tcg_gen_gvec_or_var)
#define fGEN_TCG_V6_vgtw_xor(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_32, 4, tcg_gen_gvec_xor)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_32, 4, tcg_gen_gvec_xor_var)
#define fGEN_TCG_V6_vgtuw_and(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_32, 4, tcg_gen_gvec_and)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_32, 4, tcg_gen_gvec_and_var)
#define fGEN_TCG_V6_vgtuw_or(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_32, 4, tcg_gen_gvec_or)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_32, 4, tcg_gen_gvec_or_var)
#define fGEN_TCG_V6_vgtuw_xor(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_32, 4, tcg_gen_gvec_xor)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_32, 4, tcg_gen_gvec_xor_var)
#define fGEN_TCG_V6_vgth_and(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_16, 2, tcg_gen_gvec_and)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_16, 2, tcg_gen_gvec_and_var)
#define fGEN_TCG_V6_vgth_or(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_16, 2, tcg_gen_gvec_or)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_16, 2, tcg_gen_gvec_or_var)
#define fGEN_TCG_V6_vgth_xor(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_16, 2, tcg_gen_gvec_xor)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_16, 2, tcg_gen_gvec_xor_var)
#define fGEN_TCG_V6_vgtuh_and(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_16, 2, tcg_gen_gvec_and)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_16, 2, tcg_gen_gvec_and_var)
#define fGEN_TCG_V6_vgtuh_or(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_16, 2, tcg_gen_gvec_or)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_16, 2, tcg_gen_gvec_or_var)
#define fGEN_TCG_V6_vgtuh_xor(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_16, 2, tcg_gen_gvec_xor)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_16, 2, tcg_gen_gvec_xor_var)
#define fGEN_TCG_V6_vgtb_and(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_8, 1, tcg_gen_gvec_and)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_8, 1, tcg_gen_gvec_and_var)
#define fGEN_TCG_V6_vgtb_or(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_8, 1, tcg_gen_gvec_or)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_8, 1, tcg_gen_gvec_or_var)
#define fGEN_TCG_V6_vgtb_xor(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_8, 1, tcg_gen_gvec_xor)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GT, MO_8, 1, tcg_gen_gvec_xor_var)
#define fGEN_TCG_V6_vgtub_and(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_8, 1, tcg_gen_gvec_and)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_8, 1, tcg_gen_gvec_and_var)
#define fGEN_TCG_V6_vgtub_or(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_8, 1, tcg_gen_gvec_or)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_8, 1, tcg_gen_gvec_or_var)
#define fGEN_TCG_V6_vgtub_xor(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_8, 1, tcg_gen_gvec_xor)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_GTU, MO_8, 1, tcg_gen_gvec_xor_var)
#define fGEN_TCG_V6_veqw_and(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_32, 4, tcg_gen_gvec_and)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_32, 4, tcg_gen_gvec_and_var)
#define fGEN_TCG_V6_veqw_or(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_32, 4, tcg_gen_gvec_or)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_32, 4, tcg_gen_gvec_or_var)
#define fGEN_TCG_V6_veqw_xor(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_32, 4, tcg_gen_gvec_xor)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_32, 4, tcg_gen_gvec_xor_var)
#define fGEN_TCG_V6_veqh_and(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_16, 2, tcg_gen_gvec_and)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_16, 2, tcg_gen_gvec_and_var)
#define fGEN_TCG_V6_veqh_or(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_16, 2, tcg_gen_gvec_or)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_16, 2, tcg_gen_gvec_or_var)
#define fGEN_TCG_V6_veqh_xor(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_16, 2, tcg_gen_gvec_xor)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_16, 2, tcg_gen_gvec_xor_var)
#define fGEN_TCG_V6_veqb_and(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_8, 1, tcg_gen_gvec_and)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_8, 1, tcg_gen_gvec_and_var)
#define fGEN_TCG_V6_veqb_or(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_8, 1, tcg_gen_gvec_or)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_8, 1, tcg_gen_gvec_or_var)
#define fGEN_TCG_V6_veqb_xor(SHORTCODE) \
- fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_8, 1, tcg_gen_gvec_xor)
+ fGEN_TCG_VEC_CMP_OP(TCG_COND_EQ, MO_8, 1, tcg_gen_gvec_xor_var)
/* Vector splat - various forms */
#define fGEN_TCG_V6_lvsplatw(SHORTCODE) \
- tcg_gen_gvec_dup_i32(MO_32, VdV_off, \
- sizeof(MMVector), sizeof(MMVector), RtV)
+ tcg_gen_gvec_dup_i32_var(MO_32, VdV_base, VdV_off, sizeof(MMVector), \
+ sizeof(MMVector), RtV)
#define fGEN_TCG_V6_lvsplath(SHORTCODE) \
- tcg_gen_gvec_dup_i32(MO_16, VdV_off, \
- sizeof(MMVector), sizeof(MMVector), RtV)
+ tcg_gen_gvec_dup_i32_var(MO_16, VdV_base, VdV_off, sizeof(MMVector), \
+ sizeof(MMVector), RtV)
#define fGEN_TCG_V6_lvsplatb(SHORTCODE) \
- tcg_gen_gvec_dup_i32(MO_8, VdV_off, \
- sizeof(MMVector), sizeof(MMVector), RtV)
+ tcg_gen_gvec_dup_i32_var(MO_8, VdV_base, VdV_off, sizeof(MMVector), \
+ sizeof(MMVector), RtV)
/* Vector absolute value - various forms */
#define fGEN_TCG_V6_vabsb(SHORTCODE) \
- tcg_gen_gvec_abs(MO_8, VdV_off, VuV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_abs_var(MO_8, VdV_base, VdV_off, VuV_base, VuV_off, \
+ sizeof(MMVector), sizeof(MMVector))
#define fGEN_TCG_V6_vabsh(SHORTCODE) \
- tcg_gen_gvec_abs(MO_16, VdV_off, VuV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_abs_var(MO_16, VdV_base, VdV_off, VuV_base, VuV_off, \
+ sizeof(MMVector), sizeof(MMVector))
#define fGEN_TCG_V6_vabsw(SHORTCODE) \
- tcg_gen_gvec_abs(MO_32, VdV_off, VuV_off, \
- sizeof(MMVector), sizeof(MMVector))
+ tcg_gen_gvec_abs_var(MO_32, VdV_base, VdV_off, VuV_base, VuV_off, \
+ sizeof(MMVector), sizeof(MMVector))
/* Vector loads */
#define fGEN_TCG_V6_vL32b_pi(SHORTCODE) SHORTCODE
@@ -743,14 +810,14 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
#define fGEN_TCG_V6_vL32b_nt_tmp_ppu(SHORTCODE) SHORTCODE
/* Predicated vector loads */
-#define fGEN_TCG_PRED_VEC_LOAD(GET_EA, PRED, DSTOFF, INC) \
+#define fGEN_TCG_PRED_VEC_LOAD(GET_EA, PRED, DST, INC) \
do { \
TCGv LSB = tcg_temp_new(); \
TCGLabel *false_label = gen_new_label(); \
GET_EA; \
PRED; \
tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, false_label); \
- gen_vreg_load(ctx, DSTOFF, EA, true); \
+ gen_vreg_load(ctx, DST##_base, DST##_off, EA, true); \
INC; \
gen_set_label(false_label); \
} while (0)
@@ -758,12 +825,12 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
#define fGEN_TCG_PRED_VEC_LOAD_pred_pi \
fGEN_TCG_PRED_VEC_LOAD(fLSBOLD(PvV), \
fEA_REG(RxV), \
- VdV_off, \
+ VdV, \
fPM_I(RxV, siV * sizeof(MMVector)))
#define fGEN_TCG_PRED_VEC_LOAD_npred_pi \
fGEN_TCG_PRED_VEC_LOAD(fLSBOLDNOT(PvV), \
fEA_REG(RxV), \
- VdV_off, \
+ VdV, \
fPM_I(RxV, siV * sizeof(MMVector)))
#define fGEN_TCG_V6_vL32b_pred_pi(SHORTCODE) \
@@ -794,12 +861,12 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
#define fGEN_TCG_PRED_VEC_LOAD_pred_ai \
fGEN_TCG_PRED_VEC_LOAD(fLSBOLD(PvV), \
fEA_RI(RtV, siV * sizeof(MMVector)), \
- VdV_off, \
+ VdV, \
do {} while (0))
#define fGEN_TCG_PRED_VEC_LOAD_npred_ai \
fGEN_TCG_PRED_VEC_LOAD(fLSBOLDNOT(PvV), \
fEA_RI(RtV, siV * sizeof(MMVector)), \
- VdV_off, \
+ VdV, \
do {} while (0))
#define fGEN_TCG_V6_vL32b_pred_ai(SHORTCODE) \
@@ -830,12 +897,12 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
#define fGEN_TCG_PRED_VEC_LOAD_pred_ppu \
fGEN_TCG_PRED_VEC_LOAD(fLSBOLD(PvV), \
fEA_REG(RxV), \
- VdV_off, \
+ VdV, \
fPM_M(RxV, MuV))
#define fGEN_TCG_PRED_VEC_LOAD_npred_ppu \
fGEN_TCG_PRED_VEC_LOAD(fLSBOLDNOT(PvV), \
fEA_REG(RxV), \
- VdV_off, \
+ VdV, \
fPM_M(RxV, MuV))
#define fGEN_TCG_V6_vL32b_pred_ppu(SHORTCODE) \
@@ -878,7 +945,7 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
#define fGEN_TCG_NEWVAL_VEC_STORE(GET_EA, INC) \
do { \
GET_EA; \
- gen_vreg_store(ctx, EA, OsN_off, insn->slot, true); \
+ gen_vreg_store(ctx, EA, OsN_base, OsN_off, insn->slot, true); \
INC; \
} while (0)
@@ -908,14 +975,15 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
fGEN_TCG_NEWVAL_VEC_STORE_ppu
/* Predicated vector stores */
-#define fGEN_TCG_PRED_VEC_STORE(GET_EA, PRED, SRCOFF, ALIGN, INC) \
+#define fGEN_TCG_PRED_VEC_STORE(GET_EA, PRED, SRC, ALIGN, INC) \
do { \
TCGv LSB = tcg_temp_new(); \
TCGLabel *false_label = gen_new_label(); \
GET_EA; \
PRED; \
tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, false_label); \
- gen_vreg_store(ctx, EA, SRCOFF, insn->slot, ALIGN); \
+ gen_vreg_store(ctx, EA, SRC##_base, SRC##_off, insn->slot, \
+ ALIGN); \
INC; \
gen_set_label(false_label); \
} while (0)
@@ -923,22 +991,22 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
#define fGEN_TCG_PRED_VEC_STORE_pred_pi(ALIGN) \
fGEN_TCG_PRED_VEC_STORE(fLSBOLD(PvV), \
fEA_REG(RxV), \
- VsV_off, ALIGN, \
+ VsV, ALIGN, \
fPM_I(RxV, siV * sizeof(MMVector)))
#define fGEN_TCG_PRED_VEC_STORE_npred_pi(ALIGN) \
fGEN_TCG_PRED_VEC_STORE(fLSBOLDNOT(PvV), \
fEA_REG(RxV), \
- VsV_off, ALIGN, \
+ VsV, ALIGN, \
fPM_I(RxV, siV * sizeof(MMVector)))
#define fGEN_TCG_PRED_VEC_STORE_new_pred_pi \
fGEN_TCG_PRED_VEC_STORE(fLSBOLD(PvV), \
fEA_REG(RxV), \
- OsN_off, true, \
+ OsN, true, \
fPM_I(RxV, siV * sizeof(MMVector)))
#define fGEN_TCG_PRED_VEC_STORE_new_npred_pi \
fGEN_TCG_PRED_VEC_STORE(fLSBOLDNOT(PvV), \
fEA_REG(RxV), \
- OsN_off, true, \
+ OsN, true, \
fPM_I(RxV, siV * sizeof(MMVector)))
#define fGEN_TCG_V6_vS32b_pred_pi(SHORTCODE) \
@@ -965,22 +1033,22 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
#define fGEN_TCG_PRED_VEC_STORE_pred_ai(ALIGN) \
fGEN_TCG_PRED_VEC_STORE(fLSBOLD(PvV), \
fEA_RI(RtV, siV * sizeof(MMVector)), \
- VsV_off, ALIGN, \
+ VsV, ALIGN, \
do { } while (0))
#define fGEN_TCG_PRED_VEC_STORE_npred_ai(ALIGN) \
fGEN_TCG_PRED_VEC_STORE(fLSBOLDNOT(PvV), \
fEA_RI(RtV, siV * sizeof(MMVector)), \
- VsV_off, ALIGN, \
+ VsV, ALIGN, \
do { } while (0))
#define fGEN_TCG_PRED_VEC_STORE_new_pred_ai \
fGEN_TCG_PRED_VEC_STORE(fLSBOLD(PvV), \
fEA_RI(RtV, siV * sizeof(MMVector)), \
- OsN_off, true, \
+ OsN, true, \
do { } while (0))
#define fGEN_TCG_PRED_VEC_STORE_new_npred_ai \
fGEN_TCG_PRED_VEC_STORE(fLSBOLDNOT(PvV), \
fEA_RI(RtV, siV * sizeof(MMVector)), \
- OsN_off, true, \
+ OsN, true, \
do { } while (0))
#define fGEN_TCG_V6_vS32b_pred_ai(SHORTCODE) \
@@ -1007,22 +1075,22 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
#define fGEN_TCG_PRED_VEC_STORE_pred_ppu(ALIGN) \
fGEN_TCG_PRED_VEC_STORE(fLSBOLD(PvV), \
fEA_REG(RxV), \
- VsV_off, ALIGN, \
+ VsV, ALIGN, \
fPM_M(RxV, MuV))
#define fGEN_TCG_PRED_VEC_STORE_npred_ppu(ALIGN) \
fGEN_TCG_PRED_VEC_STORE(fLSBOLDNOT(PvV), \
fEA_REG(RxV), \
- VsV_off, ALIGN, \
+ VsV, ALIGN, \
fPM_M(RxV, MuV))
#define fGEN_TCG_PRED_VEC_STORE_new_pred_ppu \
fGEN_TCG_PRED_VEC_STORE(fLSBOLD(PvV), \
fEA_REG(RxV), \
- OsN_off, true, \
+ OsN, true, \
fPM_M(RxV, MuV))
#define fGEN_TCG_PRED_VEC_STORE_new_npred_ppu \
fGEN_TCG_PRED_VEC_STORE(fLSBOLDNOT(PvV), \
fEA_REG(RxV), \
- OsN_off, true, \
+ OsN, true, \
fPM_M(RxV, MuV))
#define fGEN_TCG_V6_vS32b_pred_ppu(SHORTCODE) \
diff --git a/target/hexagon/genptr.h b/target/hexagon/genptr.h
index f498398367c..238ee089cba 100644
--- a/target/hexagon/genptr.h
+++ b/target/hexagon/genptr.h
@@ -59,6 +59,14 @@ TCGv gen_get_half(TCGv result, int N, TCGv src, bool sign);
void gen_set_half(int N, TCGv result, TCGv src);
void gen_set_half_i64(int N, TCGv_i64 result, TCGv src);
void probe_noshuf_load(TCGv va, int s, int mi);
+void gen_gvec_sabsdiff_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
+void gen_gvec_uabsdiff_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz);
void gen_gvec_sabsdiff(unsigned vece, uint32_t dofs, uint32_t aofs,
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
void gen_gvec_uabsdiff(unsigned vece, uint32_t dofs, uint32_t aofs,
diff --git a/target/hexagon/mmvec/macros.h b/target/hexagon/mmvec/macros.h
index b36f833b1de..df695d0731c 100644
--- a/target/hexagon/mmvec/macros.h
+++ b/target/hexagon/mmvec/macros.h
@@ -286,26 +286,28 @@
fV_AL_CHECK(EA, fVECSIZE() - 1); \
} while (0)
#ifdef QEMU_GENERATE
-#define fLOADMMV(EA, DST) gen_vreg_load(ctx, DST##_off, EA, true)
+#define fLOADMMV(EA, DST) gen_vreg_load(ctx, DST##_base, DST##_off, EA, true)
#endif
#ifdef QEMU_GENERATE
-#define fLOADMMVU(EA, DST) gen_vreg_load(ctx, DST##_off, EA, false)
+#define fLOADMMVU(EA, DST) gen_vreg_load(ctx, DST##_base, DST##_off, EA, false)
#endif
#ifdef QEMU_GENERATE
#define fSTOREMMV(EA, SRC) \
- gen_vreg_store(ctx, EA, SRC##_off, insn->slot, true)
+ gen_vreg_store(ctx, EA, SRC##_base, SRC##_off, insn->slot, true)
#endif
#ifdef QEMU_GENERATE
#define fSTOREMMVQ(EA, SRC, MASK) \
- gen_vreg_masked_store(ctx, EA, SRC##_off, MASK##_off, insn->slot, false)
+ gen_vreg_masked_store(ctx, EA, SRC##_base, SRC##_off, \
+ MASK##_base, MASK##_off, insn->slot, false)
#endif
#ifdef QEMU_GENERATE
#define fSTOREMMVNQ(EA, SRC, MASK) \
- gen_vreg_masked_store(ctx, EA, SRC##_off, MASK##_off, insn->slot, true)
+ gen_vreg_masked_store(ctx, EA, SRC##_base, SRC##_off, \
+ MASK##_base, MASK##_off, insn->slot, true)
#endif
#ifdef QEMU_GENERATE
#define fSTOREMMVU(EA, SRC) \
- gen_vreg_store(ctx, EA, SRC##_off, insn->slot, false)
+ gen_vreg_store(ctx, EA, SRC##_base, SRC##_off, insn->slot, false)
#endif
#define fVFOREACH(WIDTH, VAR) for (VAR = 0; VAR < fVELEM(WIDTH); VAR++)
#define fVARRAY_ELEMENT_ACCESS(ARRAY, TYPE, INDEX) \
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index b87a2b20e2f..e9b7c236b9a 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -192,9 +192,9 @@ static inline void ctx_log_reg_read_pair(DisasContext *ctx, int rnum)
}
intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
- int num, bool alloc_ok);
+ int num, bool alloc_ok, TCGv_ptr *base);
intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
- int num, bool alloc_ok);
+ int num, bool alloc_ok, TCGv_ptr *base);
static inline void ctx_start_hvx_insn(DisasContext *ctx)
{
@@ -328,6 +328,14 @@ extern TCGv_i64 hex_llsc_val_i64;
extern TCGv hex_vstore_addr[VSTORES_MAX];
extern TCGv hex_vstore_size[VSTORES_MAX];
extern TCGv hex_vstore_pending[VSTORES_MAX];
+#ifdef CONFIG_USER_ONLY
+#define hex_hvx_ptr tcg_env
+#define HEX_HVX_OFFSET(member) \
+ (offsetof(HexagonCPU, hvx_ctx.member) - offsetof(HexagonCPU, env))
+#else
+extern TCGv_ptr hex_hvx_ptr;
+#define HEX_HVX_OFFSET(member) offsetof(HexagonHVXContext, member)
+#endif
#ifndef CONFIG_USER_ONLY
extern TCGv_i32 hex_greg[NUM_GREGS];
extern TCGv_i32 hex_t_sreg[NUM_SREGS];
diff --git a/hw/hexagon/hex-subsys.c b/hw/hexagon/hex-subsys.c
index 4e3a418340e..0efcb40d8a3 100644
--- a/hw/hexagon/hex-subsys.c
+++ b/hw/hexagon/hex-subsys.c
@@ -7,8 +7,10 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "qemu/error-report.h"
#include "hw/hexagon/hex-subsys.h"
#include "hw/hexagon/hexagon_globalreg.h"
+#include "hw/hexagon/hexagon_hvx_context.h"
#include "hw/hexagon/hexagon_tlb.h"
#include "hw/intc/hex-l2vic.h"
#include "hw/timer/qct-qtimer.h"
@@ -98,6 +100,33 @@ static DeviceState *tlb_create(HexagonCommonMachineState *hms,
return tlb;
}
+/*
+ * Create the core's HVX extension contexts. There are fewer of them than
+ * there are hardware threads, and SSR:XA picks which one a thread uses, so
+ * they belong to the subsystem rather than to any one CPU.
+ */
+static void hvx_contexts_create(HexagonCommonMachineState *hms,
+ const struct hexagon_machine_config *m_cfg)
+{
+ unsigned n = m_cfg->cfgtable.ext_contexts;
+ unsigned i;
+
+ if (n > HVX_CONTEXTS_MAX) {
+ error_report("machine declares %u HVX contexts, only %u are usable",
+ n, HVX_CONTEXTS_MAX);
+ exit(1);
+ }
+ for (i = 0; i < n; i++) {
+ DeviceState *ctx = qdev_new(TYPE_HEXAGON_HVX_CONTEXT);
+ g_autofree char *name = g_strdup_printf("hvx-context[%u]", i);
+
+ object_property_add_child(OBJECT(hms), name, OBJECT(ctx));
+ qdev_prop_set_uint32(ctx, "index", i);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(ctx), &error_fatal);
+ }
+ hms->num_hvx_ctx = n;
+}
+
static DeviceState *cluster_create(HexagonCommonMachineState *hms)
{
DeviceState *cluster = qdev_new(TYPE_CPU_CLUSTER);
@@ -140,6 +169,7 @@ void hex_subsys_create(HexagonCommonMachineState *hms,
hms->qtimer = qtimer_create(hms, m_cfg);
hms->glob_regs = globalreg_create(hms, m_cfg, rev);
hms->tlb = tlb_create(hms, m_cfg);
+ hvx_contexts_create(hms, m_cfg);
}
void hex_subsys_add_cpu(HexagonCommonMachineState *hms, DeviceState *cpu)
@@ -151,6 +181,12 @@ void hex_subsys_add_cpu(HexagonCommonMachineState *hms, DeviceState *cpu)
&error_fatal);
object_property_set_link(OBJECT(cpu), "l2vic", OBJECT(hms->l2vic),
&error_fatal);
+ for (unsigned i = 0; i < hms->num_hvx_ctx; i++) {
+ g_autofree char *name = g_strdup_printf("hvx-context[%u]", i);
+ Object *ctx = object_resolve_path_component(OBJECT(hms), name);
+
+ object_property_set_link(OBJECT(cpu), name, ctx, &error_fatal);
+ }
}
void hex_subsys_realize_cluster(HexagonCommonMachineState *hms)
diff --git a/hw/hexagon/hexagon_hvx_context.c b/hw/hexagon/hexagon_hvx_context.c
new file mode 100644
index 00000000000..3b73498298e
--- /dev/null
+++ b/hw/hexagon/hexagon_hvx_context.c
@@ -0,0 +1,84 @@
+/*
+ * Hexagon HVX Extension Context QOM Object
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/hexagon/hexagon_hvx_context.h"
+#include "hw/core/qdev-properties.h"
+#include "migration/vmstate.h"
+
+static void hexagon_hvx_context_reset_hold(Object *obj, ResetType type)
+{
+ HexagonHVXContextState *s = HEXAGON_HVX_CONTEXT(obj);
+
+ memset(&s->regs, 0, sizeof(s->regs));
+}
+
+/* gvec needs VRegs/QRegs 16-aligned within the struct. */
+QEMU_BUILD_BUG_ON(offsetof(HexagonHVXContextState, regs) % 16 != 0);
+
+static const VMStateDescription vmstate_mmvector = {
+ .name = "hexagon_mmvector",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (const VMStateField[]){
+ VMSTATE_UINT64_ARRAY(ud, MMVector, MAX_VEC_SIZE_BYTES / 8),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_mmqreg = {
+ .name = "hexagon_mmqreg",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (const VMStateField[]){
+ VMSTATE_UINT64_ARRAY(ud, MMQReg, MAX_VEC_SIZE_BYTES / 8 / 8),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_hexagon_hvx_context = {
+ .name = "hexagon_hvx_context",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (const VMStateField[]){
+ VMSTATE_STRUCT_ARRAY(regs.VRegs, HexagonHVXContextState, NUM_VREGS,
+ 1, vmstate_mmvector, MMVector),
+ VMSTATE_STRUCT_ARRAY(regs.QRegs, HexagonHVXContextState, NUM_QREGS,
+ 1, vmstate_mmqreg, MMQReg),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const Property hexagon_hvx_context_properties[] = {
+ DEFINE_PROP_UINT32("index", HexagonHVXContextState, index, 0),
+};
+
+static void hexagon_hvx_context_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+ rc->phases.hold = hexagon_hvx_context_reset_hold;
+ dc->vmsd = &vmstate_hexagon_hvx_context;
+ dc->user_creatable = false;
+ device_class_set_props(dc, hexagon_hvx_context_properties);
+}
+
+static const TypeInfo hexagon_hvx_context_info = {
+ .name = TYPE_HEXAGON_HVX_CONTEXT,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(HexagonHVXContextState),
+ .instance_align = __alignof(HexagonHVXContextState),
+ .class_init = hexagon_hvx_context_class_init,
+};
+
+static void hexagon_hvx_context_register_types(void)
+{
+ type_register_static(&hexagon_hvx_context_info);
+}
+
+type_init(hexagon_hvx_context_register_types)
diff --git a/linux-user/main.c b/linux-user/main.c
index 60a695b7ca3..918b4930b07 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -244,6 +244,9 @@ CPUArchState *cpu_copy(CPUArchState *env)
new_cpu->tcg_cflags = cpu->tcg_cflags;
memcpy(new_env, env, sizeof(CPUArchState));
+#if defined(TARGET_HEXAGON)
+ HEXAGON_CPU(new_cpu)->hvx_ctx = HEXAGON_CPU(cpu)->hvx_ctx;
+#endif
#if defined(TARGET_I386) || defined(TARGET_X86_64)
new_env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
PROT_READ | PROT_WRITE,
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 19486e0f741..6acd472cd88 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -43,6 +43,7 @@
#include "exec/page-protection.h"
#include "exec/target_page.h"
#include "hw/hexagon/hexagon_globalreg.h"
+#include "hw/hexagon/hexagon_hvx_context.h"
#endif
static ObjectClass *hexagon_cpu_class_by_name(const char *cpu_model)
@@ -191,7 +192,7 @@ static void print_vreg(FILE *f, CPUHexagonState *env, int regnum,
if (skip_if_zero) {
bool nonzero_found = false;
for (int i = 0; i < MAX_VEC_SIZE_BYTES; i++) {
- if (env->VRegs[regnum].ub[i] != 0) {
+ if (hex_hvx(env)->VRegs[regnum].ub[i] != 0) {
nonzero_found = true;
break;
}
@@ -202,9 +203,10 @@ static void print_vreg(FILE *f, CPUHexagonState *env, int regnum,
}
qemu_fprintf(f, " v%d = ( ", regnum);
- qemu_fprintf(f, "0x%02x", env->VRegs[regnum].ub[MAX_VEC_SIZE_BYTES - 1]);
+ qemu_fprintf(f, "0x%02x",
+ hex_hvx(env)->VRegs[regnum].ub[MAX_VEC_SIZE_BYTES - 1]);
for (int i = MAX_VEC_SIZE_BYTES - 2; i >= 0; i--) {
- qemu_fprintf(f, ", 0x%02x", env->VRegs[regnum].ub[i]);
+ qemu_fprintf(f, ", 0x%02x", hex_hvx(env)->VRegs[regnum].ub[i]);
}
qemu_fprintf(f, " )\n");
}
@@ -220,7 +222,7 @@ static void print_qreg(FILE *f, CPUHexagonState *env, int regnum,
if (skip_if_zero) {
bool nonzero_found = false;
for (int i = 0; i < MAX_VEC_SIZE_BYTES / 8; i++) {
- if (env->QRegs[regnum].ub[i] != 0) {
+ if (hex_hvx(env)->QRegs[regnum].ub[i] != 0) {
nonzero_found = true;
break;
}
@@ -232,9 +234,9 @@ static void print_qreg(FILE *f, CPUHexagonState *env, int regnum,
qemu_fprintf(f, " q%d = ( ", regnum);
qemu_fprintf(f, "0x%02x",
- env->QRegs[regnum].ub[MAX_VEC_SIZE_BYTES / 8 - 1]);
+ hex_hvx(env)->QRegs[regnum].ub[MAX_VEC_SIZE_BYTES / 8 - 1]);
for (int i = MAX_VEC_SIZE_BYTES / 8 - 2; i >= 0; i--) {
- qemu_fprintf(f, ", 0x%02x", env->QRegs[regnum].ub[i]);
+ qemu_fprintf(f, ", 0x%02x", hex_hvx(env)->QRegs[regnum].ub[i]);
}
qemu_fprintf(f, " )\n");
}
@@ -327,6 +329,9 @@ static TCGTBCPUState hexagon_get_tb_cpu_state(CPUState *cs)
CPUHexagonState *env = cpu_env(cs);
vaddr pc = env->gpr[HEX_REG_PC];
uint32_t hex_flags = 0;
+#ifndef CONFIG_USER_ONLY
+ HexagonCPU *cpu;
+#endif
if (pc == env->gpr[HEX_REG_SA0]) {
hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP, 1);
@@ -337,10 +342,12 @@ static TCGTBCPUState hexagon_get_tb_cpu_state(CPUState *cs)
}
#ifndef CONFIG_USER_ONLY
+ cpu = env_archcpu(env);
hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, MMU_INDEX,
cpu_mmu_index(env_cpu(env), false));
hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, PCYCLE_ENABLED, 1);
hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, HVX_COPROC_ENABLED,
+ cpu->hvx_ctx[0] &&
GET_SSR_FIELD(SSR_XE, env->t_sreg[HEX_SREG_SSR]));
#else
hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, MMU_INDEX, MMU_USER_IDX);
@@ -448,6 +455,7 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
env->t_sreg[HEX_SREG_HTID] = cpu->htid;
env->threadId = cpu->htid;
hexagon_cpu_soft_reset(env);
+ hexagon_hvx_select_context(env, env->t_sreg[HEX_SREG_SSR]);
env->cause_code = HEX_EVENT_NONE;
env->gpr[HEX_REG_PC] = cpu->boot_addr;
#endif
@@ -553,7 +561,17 @@ static void hexagon_cpu_init(Object *obj)
{
#ifndef CONFIG_USER_ONLY
HexagonCPU *cpu = HEXAGON_CPU(obj);
+ int i;
+
qdev_init_gpio_in(DEVICE(cpu), hexagon_cpu_set_irq, 8);
+
+ for (i = 0; i < HVX_CONTEXTS_MAX; i++) {
+ object_property_add_link(obj, "hvx-context[*]",
+ TYPE_HEXAGON_HVX_CONTEXT,
+ (Object **)&cpu->hvx_ctx[i],
+ qdev_prop_allow_set_link_before_realize,
+ OBJ_PROP_LINK_STRONG);
+ }
#endif
}
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index eea5f60b46c..0803cd18652 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -11,6 +11,7 @@
#include "hw/core/boards.h"
#include "hw/hexagon/hexagon.h"
#include "hw/hexagon/hexagon_globalreg.h"
+#include "hw/hexagon/hexagon_hvx_context.h"
#include "hex_interrupts.h"
#include "hex_mmu.h"
#include "system/runstate.h"
@@ -246,6 +247,65 @@ void hexagon_resume_threads(CPUHexagonState *current_env, uint32_t mask)
}
}
+static unsigned hexagon_hvx_context_count(HexagonCPU *cpu)
+{
+ unsigned n;
+
+ for (n = 0; n < HVX_CONTEXTS_MAX; n++) {
+ if (!cpu->hvx_ctx[n]) {
+ break;
+ }
+ }
+ return n;
+}
+
+static unsigned hexagon_hvx_context_index(HexagonCPU *cpu, uint8_t xa)
+{
+ unsigned n = hexagon_hvx_context_count(cpu);
+
+ if (n == 0) {
+ return 0;
+ }
+ return xa % n;
+}
+
+/*
+ * Diagnostic only. Called separately from hexagon_hvx_select_context()
+ * so migration post_load, where other CPUs' env->hvx may still be stale,
+ * doesn't trip a false positive.
+ */
+static void hexagon_hvx_check_overcommit(CPUHexagonState *env, unsigned idx)
+{
+ CPUState *cs;
+ unsigned users = 0;
+
+ CPU_FOREACH(cs) {
+ CPUHexagonState *other = cpu_env(cs);
+
+ if (other->hvx == env->hvx &&
+ GET_SSR_FIELD(SSR_XE, other->t_sreg[HEX_SREG_SSR])) {
+ users++;
+ }
+ }
+
+ if (users > 1) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "HVX context %u is enabled for %u hardware threads "
+ "at once, which is undefined\n", idx, users);
+ }
+}
+
+unsigned hexagon_hvx_select_context(CPUHexagonState *env, uint32_t ssr)
+{
+ HexagonCPU *cpu = env_archcpu(env);
+ unsigned idx = hexagon_hvx_context_index(cpu, GET_SSR_FIELD(SSR_XA, ssr));
+
+ if (cpu->hvx_ctx[0]) {
+ env->hvx = &cpu->hvx_ctx[idx]->regs;
+ }
+ return idx;
+}
+
void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old)
{
bool old_EX, old_UM, old_GM, old_IE;
@@ -269,6 +329,18 @@ void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old)
hex_mmu_mode_change(env);
}
+ bool xa_changed = GET_SSR_FIELD(SSR_XA, new) != GET_SSR_FIELD(SSR_XA, old);
+ bool xe_changed = GET_SSR_FIELD(SSR_XE, new) != GET_SSR_FIELD(SSR_XE, old);
+
+ if (xa_changed || xe_changed) {
+ unsigned idx = xa_changed
+ ? hexagon_hvx_select_context(env, new)
+ : hexagon_hvx_context_index(env_archcpu(env),
+ GET_SSR_FIELD(SSR_XA, new));
+
+ hexagon_hvx_check_overcommit(env, idx);
+ }
+
old_asid = GET_SSR_FIELD(SSR_ASID, old);
new_asid = GET_SSR_FIELD(SSR_ASID, new);
if (new_asid != old_asid) {
diff --git a/target/hexagon/gdbstub.c b/target/hexagon/gdbstub.c
index b9856cfc978..76ab5235f6e 100644
--- a/target/hexagon/gdbstub.c
+++ b/target/hexagon/gdbstub.c
@@ -80,8 +80,8 @@ static int gdb_get_vreg(CPUHexagonState *env, GByteArray *mem_buf, int n)
{
int total = 0;
int i;
- for (i = 0; i < ARRAY_SIZE(env->VRegs[n].uw); i++) {
- total += gdb_get_reg32(mem_buf, env->VRegs[n].uw[i]);
+ for (i = 0; i < ARRAY_SIZE(hex_hvx(env)->VRegs[n].uw); i++) {
+ total += gdb_get_reg32(mem_buf, hex_hvx(env)->VRegs[n].uw[i]);
}
return total;
}
@@ -90,8 +90,8 @@ static int gdb_get_qreg(CPUHexagonState *env, GByteArray *mem_buf, int n)
{
int total = 0;
int i;
- for (i = 0; i < ARRAY_SIZE(env->QRegs[n].uw); i++) {
- total += gdb_get_reg32(mem_buf, env->QRegs[n].uw[i]);
+ for (i = 0; i < ARRAY_SIZE(hex_hvx(env)->QRegs[n].uw); i++) {
+ total += gdb_get_reg32(mem_buf, hex_hvx(env)->QRegs[n].uw[i]);
}
return total;
}
@@ -116,8 +116,8 @@ int hexagon_hvx_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
static int gdb_put_vreg(CPUHexagonState *env, uint8_t *mem_buf, int n)
{
int i;
- for (i = 0; i < ARRAY_SIZE(env->VRegs[n].uw); i++) {
- env->VRegs[n].uw[i] = ldl_le_p(mem_buf);
+ for (i = 0; i < ARRAY_SIZE(hex_hvx(env)->VRegs[n].uw); i++) {
+ hex_hvx(env)->VRegs[n].uw[i] = ldl_le_p(mem_buf);
mem_buf += 4;
}
return MAX_VEC_SIZE_BYTES;
@@ -126,8 +126,8 @@ static int gdb_put_vreg(CPUHexagonState *env, uint8_t *mem_buf, int n)
static int gdb_put_qreg(CPUHexagonState *env, uint8_t *mem_buf, int n)
{
int i;
- for (i = 0; i < ARRAY_SIZE(env->QRegs[n].uw); i++) {
- env->QRegs[n].uw[i] = ldl_le_p(mem_buf);
+ for (i = 0; i < ARRAY_SIZE(hex_hvx(env)->QRegs[n].uw); i++) {
+ hex_hvx(env)->QRegs[n].uw[i] = ldl_le_p(mem_buf);
mem_buf += 4;
}
return MAX_VEC_SIZE_BYTES / 8;
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 4e9a9670d54..e1330d8e0b2 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -56,8 +56,10 @@ static void gen_sabsdiff_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
tcg_gen_sub_vec(vece, d, d, t);
}
-void gen_gvec_sabsdiff(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+void gen_gvec_sabsdiff_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = {
INDEX_op_sub_vec, INDEX_op_smin_vec, INDEX_op_smax_vec, 0
@@ -75,7 +77,15 @@ void gen_gvec_sabsdiff(unsigned vece, uint32_t dofs, uint32_t aofs,
};
tcg_debug_assert(vece == MO_16 || vece == MO_32);
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &ops[vece]);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &ops[vece]);
+}
+
+void gen_gvec_sabsdiff(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ gen_gvec_sabsdiff_var(vece, tcg_env, dofs, tcg_env, aofs, tcg_env, bofs,
+ oprsz, maxsz);
}
static void gen_uabsdiff_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
@@ -87,8 +97,10 @@ static void gen_uabsdiff_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
tcg_gen_sub_vec(vece, d, d, t);
}
-void gen_gvec_uabsdiff(unsigned vece, uint32_t dofs, uint32_t aofs,
- uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+void gen_gvec_uabsdiff_var(unsigned vece, TCGv_ptr dbase, uint32_t dofs,
+ TCGv_ptr abase, uint32_t aofs,
+ TCGv_ptr bbase, uint32_t bofs,
+ uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = {
INDEX_op_sub_vec, INDEX_op_umin_vec, INDEX_op_umax_vec, 0
@@ -105,7 +117,15 @@ void gen_gvec_uabsdiff(unsigned vece, uint32_t dofs, uint32_t aofs,
};
tcg_debug_assert(vece == MO_8 || vece == MO_16);
- tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &ops[vece]);
+ tcg_gen_gvec_3_var(dbase, dofs, abase, aofs, bbase, bofs,
+ oprsz, maxsz, &ops[vece]);
+}
+
+void gen_gvec_uabsdiff(unsigned vece, uint32_t dofs, uint32_t aofs,
+ uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+ gen_gvec_uabsdiff_var(vece, tcg_env, dofs, tcg_env, aofs, tcg_env, bofs,
+ oprsz, maxsz);
}
TCGv gen_read_reg(TCGv result, int num)
@@ -1435,54 +1455,56 @@ static void gen_asr_r_svw_trun(DisasContext *ctx, TCGv RdV,
gen_set_label(done);
}
-static intptr_t vreg_src_off(DisasContext *ctx, int num)
+static intptr_t vreg_src_off(DisasContext *ctx, int num, TCGv_ptr *base)
{
- intptr_t offset = offsetof(CPUHexagonState, VRegs[num]);
+ intptr_t offset = HEX_HVX_OFFSET(VRegs[num]);
+ *base = hex_hvx_ptr;
if (test_bit(num, ctx->vregs_select)) {
- offset = ctx_future_vreg_off(ctx, num, 1, false);
+ offset = ctx_future_vreg_off(ctx, num, 1, false, base);
}
if (test_bit(num, ctx->vregs_updated_tmp)) {
- offset = ctx_tmp_vreg_off(ctx, num, 1, false);
+ offset = ctx_tmp_vreg_off(ctx, num, 1, false, base);
}
return offset;
}
-static void gen_vreg_write(DisasContext *ctx, intptr_t srcoff, int num,
- VRegWriteType type)
+static void gen_vreg_write(DisasContext *ctx, TCGv_ptr srcbase,
+ intptr_t srcoff, int num, VRegWriteType type)
{
+ TCGv_ptr dstbase;
intptr_t dstoff;
if (type != EXT_TMP) {
- dstoff = ctx_future_vreg_off(ctx, num, 1, true);
- tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
- sizeof(MMVector), sizeof(MMVector));
+ dstoff = ctx_future_vreg_off(ctx, num, 1, true, &dstbase);
} else {
- dstoff = ctx_tmp_vreg_off(ctx, num, 1, false);
- tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
- sizeof(MMVector), sizeof(MMVector));
+ dstoff = ctx_tmp_vreg_off(ctx, num, 1, false, &dstbase);
}
+ tcg_gen_gvec_mov_var(MO_64, dstbase, dstoff, srcbase, srcoff,
+ sizeof(MMVector), sizeof(MMVector));
}
-static void gen_vreg_write_pair(DisasContext *ctx, intptr_t srcoff, int num,
- VRegWriteType type)
+static void gen_vreg_write_pair(DisasContext *ctx, TCGv_ptr srcbase,
+ intptr_t srcoff, int num, VRegWriteType type)
{
- gen_vreg_write(ctx, srcoff, num ^ 0, type);
+ gen_vreg_write(ctx, srcbase, srcoff, num ^ 0, type);
srcoff += sizeof(MMVector);
- gen_vreg_write(ctx, srcoff, num ^ 1, type);
+ gen_vreg_write(ctx, srcbase, srcoff, num ^ 1, type);
}
-static intptr_t get_result_qreg(DisasContext *ctx, int qnum)
+static intptr_t get_result_qreg(DisasContext *ctx, int qnum, TCGv_ptr *base)
{
if (ctx->need_commit) {
+ *base = tcg_env;
return offsetof(CPUHexagonState, future_QRegs[qnum]);
} else {
- return offsetof(CPUHexagonState, QRegs[qnum]);
+ *base = hex_hvx_ptr;
+ return HEX_HVX_OFFSET(QRegs[qnum]);
}
}
-static void gen_vreg_load(DisasContext *ctx, intptr_t dstoff, TCGv src,
- bool aligned)
+static void gen_vreg_load(DisasContext *ctx, TCGv_ptr dstbase,
+ intptr_t dstoff, TCGv src, bool aligned)
{
TCGv_i64 tmp = tcg_temp_new_i64();
if (aligned) {
@@ -1491,12 +1513,12 @@ static void gen_vreg_load(DisasContext *ctx, intptr_t dstoff, TCGv src,
for (int i = 0; i < sizeof(MMVector) / 8; i++) {
tcg_gen_qemu_ld_i64(tmp, src, ctx->mem_idx, MO_LE | MO_UQ);
tcg_gen_addi_tl(src, src, 8);
- tcg_gen_st_i64(tmp, tcg_env, dstoff + i * 8);
+ tcg_gen_st_i64(tmp, dstbase, dstoff + i * 8);
}
}
-static void gen_vreg_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
- int slot, bool aligned)
+static void gen_vreg_store(DisasContext *ctx, TCGv EA, TCGv_ptr srcbase,
+ intptr_t srcoff, int slot, bool aligned)
{
intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data);
intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask);
@@ -1517,13 +1539,16 @@ static void gen_vreg_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
tcg_gen_movi_tl(hex_vstore_size[slot], sizeof(MMVector));
/* Copy the data to the vstore buffer */
- tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMVector), sizeof(MMVector));
+ tcg_gen_gvec_mov_var(MO_64, tcg_env, dstoff, srcbase, srcoff,
+ sizeof(MMVector), sizeof(MMVector));
/* Set the mask to all 1's */
tcg_gen_gvec_dup_imm(MO_64, maskoff, sizeof(MMQReg), sizeof(MMQReg), ~0LL);
}
-static void gen_vreg_masked_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
- intptr_t bitsoff, int slot, bool invert)
+static void gen_vreg_masked_store(DisasContext *ctx, TCGv EA,
+ TCGv_ptr srcbase, intptr_t srcoff,
+ TCGv_ptr bitsbase, intptr_t bitsoff,
+ int slot, bool invert)
{
intptr_t dstoff = offsetof(CPUHexagonState, vstore[slot].data);
intptr_t maskoff = offsetof(CPUHexagonState, vstore[slot].mask);
@@ -1534,16 +1559,19 @@ static void gen_vreg_masked_store(DisasContext *ctx, TCGv EA, intptr_t srcoff,
tcg_gen_movi_tl(hex_vstore_size[slot], sizeof(MMVector));
/* Copy the data to the vstore buffer */
- tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMVector), sizeof(MMVector));
+ tcg_gen_gvec_mov_var(MO_64, tcg_env, dstoff, srcbase, srcoff,
+ sizeof(MMVector), sizeof(MMVector));
/* Copy the mask */
- tcg_gen_gvec_mov(MO_64, maskoff, bitsoff, sizeof(MMQReg), sizeof(MMQReg));
+ tcg_gen_gvec_mov_var(MO_64, tcg_env, maskoff, bitsbase, bitsoff,
+ sizeof(MMQReg), sizeof(MMQReg));
if (invert) {
tcg_gen_gvec_not(MO_64, maskoff, maskoff,
sizeof(MMQReg), sizeof(MMQReg));
}
}
-static void vec_to_qvec(size_t size, intptr_t dstoff, intptr_t srcoff)
+static void vec_to_qvec(size_t size, TCGv_ptr dstbase, intptr_t dstoff,
+ TCGv_ptr srcbase, intptr_t srcoff)
{
TCGv_i64 tmp = tcg_temp_new_i64();
TCGv_i64 word = tcg_temp_new_i64();
@@ -1553,7 +1581,7 @@ static void vec_to_qvec(size_t size, intptr_t dstoff, intptr_t srcoff)
TCGv_i64 ones = tcg_constant_i64(~0);
for (int i = 0; i < sizeof(MMVector) / 8; i++) {
- tcg_gen_ld_i64(tmp, tcg_env, srcoff + i * 8);
+ tcg_gen_ld_i64(tmp, srcbase, srcoff + i * 8);
tcg_gen_movi_i64(mask, 0);
for (int j = 0; j < 8; j += size) {
@@ -1562,7 +1590,7 @@ static void vec_to_qvec(size_t size, intptr_t dstoff, intptr_t srcoff)
tcg_gen_deposit_i64(mask, mask, bits, j, size);
}
- tcg_gen_st8_i64(mask, tcg_env, dstoff + i);
+ tcg_gen_st8_i64(mask, dstbase, dstoff + i);
}
}
diff --git a/target/hexagon/machine.c b/target/hexagon/machine.c
index bf4646f4a8b..179b6f53a2a 100644
--- a/target/hexagon/machine.c
+++ b/target/hexagon/machine.c
@@ -7,11 +7,23 @@
#include "qemu/osdep.h"
#include "migration/vmstate.h"
#include "cpu.h"
+#include "cpu_helper.h"
+
+static int hexagon_cpu_post_load(void *opaque, int version_id)
+{
+ HexagonCPU *cpu = opaque;
+ CPUHexagonState *env = &cpu->env;
+
+ hexagon_hvx_select_context(env, env->t_sreg[HEX_SREG_SSR]);
+
+ return 0;
+}
const VMStateDescription vmstate_hexagon_cpu = {
.name = "cpu",
.version_id = 2,
.minimum_version_id = 2,
+ .post_load = hexagon_cpu_post_load,
.fields = (const VMStateField[]) {
VMSTATE_UINT32_ARRAY(env.gpr, HexagonCPU, TOTAL_PER_THREAD_REGS),
VMSTATE_UINT32_ARRAY(env.pred, HexagonCPU, NUM_PREGS),
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 0d08ac77361..47c7953b92e 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1408,7 +1408,8 @@ void HELPER(vhist)(CPUHexagonState *env)
unsigned char regno = value >> 3;
unsigned char element = value & 7;
- env->VRegs[regno].uh[(sizeof(MMVector) / 16) * lane + element]++;
+ hex_hvx(env)->VRegs[regno]
+ .uh[(sizeof(MMVector) / 16) * lane + element]++;
}
}
}
@@ -1424,7 +1425,7 @@ void HELPER(vhistq)(CPUHexagonState *env)
unsigned char element = value & 7;
if (fGETQBIT(env->qtmp, sizeof(MMVector) / 8 * lane + i)) {
- env->VRegs[regno].uh[
+ hex_hvx(env)->VRegs[regno].uh[
(sizeof(MMVector) / 16) * lane + element]++;
}
}
@@ -1441,8 +1442,8 @@ void HELPER(vwhist256)(CPUHexagonState *env)
unsigned int vindex = (bucket >> 3) & 0x1F;
unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
- env->VRegs[vindex].uh[elindex] =
- env->VRegs[vindex].uh[elindex] + weight;
+ hex_hvx(env)->VRegs[vindex].uh[elindex] =
+ hex_hvx(env)->VRegs[vindex].uh[elindex] + weight;
}
}
@@ -1457,8 +1458,8 @@ void HELPER(vwhist256q)(CPUHexagonState *env)
unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
if (fGETQBIT(env->qtmp, 2 * i)) {
- env->VRegs[vindex].uh[elindex] =
- env->VRegs[vindex].uh[elindex] + weight;
+ hex_hvx(env)->VRegs[vindex].uh[elindex] =
+ hex_hvx(env)->VRegs[vindex].uh[elindex] + weight;
}
}
}
@@ -1473,8 +1474,8 @@ void HELPER(vwhist256_sat)(CPUHexagonState *env)
unsigned int vindex = (bucket >> 3) & 0x1F;
unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
- env->VRegs[vindex].uh[elindex] =
- fVSATUH(env->VRegs[vindex].uh[elindex] + weight);
+ hex_hvx(env)->VRegs[vindex].uh[elindex] =
+ fVSATUH(hex_hvx(env)->VRegs[vindex].uh[elindex] + weight);
}
}
@@ -1489,8 +1490,8 @@ void HELPER(vwhist256q_sat)(CPUHexagonState *env)
unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
if (fGETQBIT(env->qtmp, 2 * i)) {
- env->VRegs[vindex].uh[elindex] =
- fVSATUH(env->VRegs[vindex].uh[elindex] + weight);
+ hex_hvx(env)->VRegs[vindex].uh[elindex] =
+ fVSATUH(hex_hvx(env)->VRegs[vindex].uh[elindex] + weight);
}
}
}
@@ -1505,8 +1506,8 @@ void HELPER(vwhist128)(CPUHexagonState *env)
unsigned int vindex = (bucket >> 3) & 0x1F;
unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
- env->VRegs[vindex].uw[elindex] =
- env->VRegs[vindex].uw[elindex] + weight;
+ hex_hvx(env)->VRegs[vindex].uw[elindex] =
+ hex_hvx(env)->VRegs[vindex].uw[elindex] + weight;
}
}
@@ -1521,8 +1522,8 @@ void HELPER(vwhist128q)(CPUHexagonState *env)
unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
if (fGETQBIT(env->qtmp, 2 * i)) {
- env->VRegs[vindex].uw[elindex] =
- env->VRegs[vindex].uw[elindex] + weight;
+ hex_hvx(env)->VRegs[vindex].uw[elindex] =
+ hex_hvx(env)->VRegs[vindex].uw[elindex] + weight;
}
}
}
@@ -1538,8 +1539,8 @@ void HELPER(vwhist128m)(CPUHexagonState *env, int32_t uiV)
unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
if ((bucket & 1) == uiV) {
- env->VRegs[vindex].uw[elindex] =
- env->VRegs[vindex].uw[elindex] + weight;
+ hex_hvx(env)->VRegs[vindex].uw[elindex] =
+ hex_hvx(env)->VRegs[vindex].uw[elindex] + weight;
}
}
}
@@ -1555,8 +1556,8 @@ void HELPER(vwhist128qm)(CPUHexagonState *env, int32_t uiV)
unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
if (((bucket & 1) == uiV) && fGETQBIT(env->qtmp, 2 * i)) {
- env->VRegs[vindex].uw[elindex] =
- env->VRegs[vindex].uw[elindex] + weight;
+ hex_hvx(env)->VRegs[vindex].uw[elindex] =
+ hex_hvx(env)->VRegs[vindex].uw[elindex] + weight;
}
}
}
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 0cb3dbe5420..38bdcaa9dc9 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -70,6 +70,9 @@ TCGv hex_imprecise_exception;
TCGv hex_vstore_addr[VSTORES_MAX];
TCGv hex_vstore_size[VSTORES_MAX];
TCGv hex_vstore_pending[VSTORES_MAX];
+#ifndef CONFIG_USER_ONLY
+TCGv_ptr hex_hvx_ptr;
+#endif
#ifndef CONFIG_USER_ONLY
TCGv_i32 hex_greg[NUM_GREGS];
@@ -82,14 +85,18 @@ static const char * const hexagon_prednames[] = {
};
intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
- int num, bool alloc_ok)
+ int num, bool alloc_ok, TCGv_ptr *base)
{
intptr_t offset;
if (!ctx->need_commit) {
- return offsetof(CPUHexagonState, VRegs[regnum]);
+ /* Short circuit: the write goes straight to the register file. */
+ *base = hex_hvx_ptr;
+ return HEX_HVX_OFFSET(VRegs[regnum]);
}
+ *base = tcg_env;
+
/* See if it is already allocated */
for (int i = 0; i < ctx->future_vregs_idx; i++) {
if (ctx->future_vregs_num[i] == regnum) {
@@ -108,10 +115,12 @@ intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
}
intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
- int num, bool alloc_ok)
+ int num, bool alloc_ok, TCGv_ptr *base)
{
intptr_t offset;
+ *base = tcg_env;
+
/* See if it is already allocated */
for (int i = 0; i < ctx->tmp_vregs_idx; i++) {
if (ctx->tmp_vregs_num[i] == regnum) {
@@ -697,26 +706,28 @@ static void gen_start_packet(DisasContext *ctx)
if (!bitmap_empty(ctx->predicated_future_vregs, NUM_VREGS)) {
i = find_first_bit(ctx->predicated_future_vregs, NUM_VREGS);
while (i < NUM_VREGS) {
+ TCGv_ptr VdV_base;
const intptr_t VdV_off =
- ctx_future_vreg_off(ctx, i, 1, true);
- intptr_t src_off = offsetof(CPUHexagonState, VRegs[i]);
- tcg_gen_gvec_mov(MO_64, VdV_off,
- src_off,
- sizeof(MMVector),
- sizeof(MMVector));
+ ctx_future_vreg_off(ctx, i, 1, true, &VdV_base);
+ intptr_t src_off = HEX_HVX_OFFSET(VRegs[i]);
+ tcg_gen_gvec_mov_var(MO_64, VdV_base, VdV_off,
+ hex_hvx_ptr, src_off,
+ sizeof(MMVector),
+ sizeof(MMVector));
i = find_next_bit(ctx->predicated_future_vregs, NUM_VREGS, i + 1);
}
}
if (!bitmap_empty(ctx->predicated_tmp_vregs, NUM_VREGS)) {
i = find_first_bit(ctx->predicated_tmp_vregs, NUM_VREGS);
while (i < NUM_VREGS) {
+ TCGv_ptr VdV_base;
const intptr_t VdV_off =
- ctx_tmp_vreg_off(ctx, i, 1, true);
- intptr_t src_off = offsetof(CPUHexagonState, VRegs[i]);
- tcg_gen_gvec_mov(MO_64, VdV_off,
- src_off,
- sizeof(MMVector),
- sizeof(MMVector));
+ ctx_tmp_vreg_off(ctx, i, 1, true, &VdV_base);
+ intptr_t src_off = HEX_HVX_OFFSET(VRegs[i]);
+ tcg_gen_gvec_mov_var(MO_64, VdV_base, VdV_off,
+ hex_hvx_ptr, src_off,
+ sizeof(MMVector),
+ sizeof(MMVector));
i = find_next_bit(ctx->predicated_tmp_vregs, NUM_VREGS, i + 1);
}
}
@@ -1016,31 +1027,34 @@ static void gen_commit_hvx(DisasContext *ctx)
/*
* for (i = 0; i < ctx->vreg_log_idx; i++) {
* int rnum = ctx->vreg_log[i];
- * env->VRegs[rnum] = env->future_VRegs[rnum];
+ * env->hvx->VRegs[rnum] = env->future_VRegs[rnum];
* }
*/
for (i = 0; i < ctx->vreg_log_idx; i++) {
int rnum = ctx->vreg_log[i];
- intptr_t dstoff = offsetof(CPUHexagonState, VRegs[rnum]);
- intptr_t srcoff = ctx_future_vreg_off(ctx, rnum, 1, false);
+ intptr_t dstoff = HEX_HVX_OFFSET(VRegs[rnum]);
+ TCGv_ptr srcbase;
+ intptr_t srcoff = ctx_future_vreg_off(ctx, rnum, 1, false, &srcbase);
size_t size = sizeof(MMVector);
- tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
+ tcg_gen_gvec_mov_var(MO_64, hex_hvx_ptr, dstoff, srcbase, srcoff,
+ size, size);
}
/*
* for (i = 0; i < ctx->qreg_log_idx; i++) {
* int rnum = ctx->qreg_log[i];
- * env->QRegs[rnum] = env->future_QRegs[rnum];
+ * env->hvx->QRegs[rnum] = env->future_QRegs[rnum];
* }
*/
for (i = 0; i < ctx->qreg_log_idx; i++) {
int rnum = ctx->qreg_log[i];
- intptr_t dstoff = offsetof(CPUHexagonState, QRegs[rnum]);
+ intptr_t dstoff = HEX_HVX_OFFSET(QRegs[rnum]);
intptr_t srcoff = offsetof(CPUHexagonState, future_QRegs[rnum]);
size_t size = sizeof(MMQReg);
- tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
+ tcg_gen_gvec_mov_var(MO_64, hex_hvx_ptr, dstoff, tcg_env, srcoff,
+ size, size);
}
if (pkt_has_hvx_store(&ctx->pkt)) {
@@ -1360,6 +1374,8 @@ void hexagon_translate_init(void)
opcode_init();
#ifndef CONFIG_USER_ONLY
+ hex_hvx_ptr = tcg_global_mem_new_ptr(tcg_env,
+ offsetof(CPUHexagonState, hvx), "hvx");
for (i = 0; i < NUM_GREGS; i++) {
hex_greg[i] = tcg_global_mem_new_i32(tcg_env,
offsetof(CPUHexagonState, greg[i]),
diff --git a/hw/hexagon/meson.build b/hw/hexagon/meson.build
index 720a5d54dcc..c4b257dfa28 100644
--- a/hw/hexagon/meson.build
+++ b/hw/hexagon/meson.build
@@ -1,6 +1,7 @@
hexagon_ss = ss.source_set()
hexagon_ss.add(files('hexagon_tlb.c'))
hexagon_ss.add(files('hexagon_globalreg.c'))
+hexagon_ss.add(files('hexagon_hvx_context.c'))
hexagon_ss.add(when: 'CONFIG_HEX_DSP', if_true: files('hex-subsys.c'))
hexagon_ss.add(when: 'CONFIG_HEX_DSP', if_true: files('hexagon_dsp.c'))
hexagon_ss.add(when: 'CONFIG_HEX_VIRT', if_true: files('virt.c'))
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index c180c19b092..02c54506145 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -434,6 +434,14 @@ def is_hvx_reg(self):
return True
def hvx_off(self):
return f"{self.reg_tcg()}_off"
+ def hvx_base(self):
+ return f"{self.reg_tcg()}_base"
+ def decl_tcg_ptr(self, f):
+ ptr = self.reg_tcg()
+ f.write(code_fmt(f"""\
+ TCGv_ptr {ptr} = tcg_temp_new_ptr();
+ tcg_gen_addi_ptr({ptr}, {self.hvx_base()}, {self.hvx_off()});
+ """))
def helper_proto_type(self):
return "ptr"
def helper_arg_type(self):
@@ -778,18 +786,17 @@ class VRegDest(Register, Hvx, Dest):
def decl_tcg(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
+ TCGv_ptr {self.hvx_base()};
const intptr_t {self.hvx_off()} =
- {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true);
+ {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1,
+ true, &{self.hvx_base()});
"""))
if not skip_qemu_helper(tag):
- f.write(code_fmt(f"""\
- TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
- tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
- """))
+ self.decl_tcg_ptr(f)
def gen_zero(self, f):
f.write(code_fmt(f"""\
- tcg_gen_gvec_dup_imm(MO_64, {self.hvx_off()},
- sizeof(MMVector), sizeof(MMVector), 0);
+ tcg_gen_gvec_dup_imm_var(MO_64, {self.hvx_base()},
+ {self.hvx_off()}, sizeof(MMVector), sizeof(MMVector), 0);
"""))
def gen_write(self, f, tag):
pass
@@ -809,13 +816,12 @@ class VRegSource(Register, Hvx, OldSource):
def decl_tcg(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
- const intptr_t {self.hvx_off()} = vreg_src_off(ctx, {self.reg_num});
+ TCGv_ptr {self.hvx_base()};
+ const intptr_t {self.hvx_off()} =
+ vreg_src_off(ctx, {self.reg_num}, &{self.hvx_base()});
"""))
if not skip_qemu_helper(tag):
- f.write(code_fmt(f"""\
- TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
- tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
- """))
+ self.decl_tcg_ptr(f)
def helper_hvx_desc(self, f):
f.write(code_fmt(f"""\
/* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
@@ -830,8 +836,10 @@ def decl_tcg(self, f, tag, regno):
self.decl_reg_num(f, regno)
if skip_qemu_helper(tag):
f.write(code_fmt(f"""\
+ TCGv_ptr {self.hvx_base()};
const intptr_t {self.hvx_off()} =
- ctx_future_vreg_off(ctx, {self.reg_num}, 1, true);
+ ctx_future_vreg_off(ctx, {self.reg_num}, 1,
+ true, &{self.hvx_base()});
"""))
def helper_hvx_desc(self, f):
f.write(code_fmt(f"""\
@@ -846,21 +854,24 @@ class VRegReadWrite(Register, Hvx, ReadWrite):
def decl_tcg(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
+ TCGv_ptr {self.hvx_base()};
+ TCGv_ptr {self.reg_tcg()}_srcbase;
const intptr_t {self.hvx_off()} =
- {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true);
- tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
- vreg_src_off(ctx, {self.reg_num}),
- sizeof(MMVector), sizeof(MMVector));
+ {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1,
+ true, &{self.hvx_base()});
+ const intptr_t {self.reg_tcg()}_srcoff =
+ vreg_src_off(ctx, {self.reg_num}, &{self.reg_tcg()}_srcbase);
+ tcg_gen_gvec_mov_var(MO_64, {self.hvx_base()}, {self.hvx_off()},
+ {self.reg_tcg()}_srcbase,
+ {self.reg_tcg()}_srcoff,
+ sizeof(MMVector), sizeof(MMVector));
"""))
if not skip_qemu_helper(tag):
- f.write(code_fmt(f"""\
- TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
- tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
- """))
+ self.decl_tcg_ptr(f)
def gen_zero(self, f):
f.write(code_fmt(f"""\
- tcg_gen_gvec_dup_imm(MO_64, {self.hvx_off()},
- sizeof(MMVector), sizeof(MMVector), 0);
+ tcg_gen_gvec_dup_imm_var(MO_64, {self.hvx_base()},
+ {self.hvx_off()}, sizeof(MMVector), sizeof(MMVector), 0);
"""))
def gen_write(self, f, tag):
pass
@@ -884,15 +895,21 @@ class VRegTmp(Register, Hvx, ReadWrite):
def decl_tcg(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
+ TCGv_ptr {self.hvx_base()} = tcg_env;
const intptr_t {self.hvx_off()} = offsetof(CPUHexagonState, vtmp);
"""))
if not skip_qemu_helper(tag):
+ self.decl_tcg_ptr(f)
f.write(code_fmt(f"""\
- TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
- tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
- tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
- vreg_src_off(ctx, {self.reg_num}),
- sizeof(MMVector), sizeof(MMVector));
+ TCGv_ptr {self.reg_tcg()}_srcbase;
+ const intptr_t {self.reg_tcg()}_srcoff =
+ vreg_src_off(ctx, {self.reg_num},
+ &{self.reg_tcg()}_srcbase);
+ tcg_gen_gvec_mov_var(MO_64, {self.hvx_base()},
+ {self.hvx_off()},
+ {self.reg_tcg()}_srcbase,
+ {self.reg_tcg()}_srcoff,
+ sizeof(MMVector), sizeof(MMVector));
"""))
def gen_zero(self, f):
f.write(code_fmt(f"""\
@@ -901,8 +918,8 @@ def gen_zero(self, f):
"""))
def gen_write(self, f, tag):
f.write(code_fmt(f"""\
- gen_vreg_write(ctx, {self.hvx_off()}, {self.reg_num},
- {hvx_newv(tag)});
+ gen_vreg_write(ctx, {self.hvx_base()}, {self.hvx_off()},
+ {self.reg_num}, {hvx_newv(tag)});
"""))
def helper_hvx_desc(self, f):
f.write(code_fmt(f"""\
@@ -924,17 +941,16 @@ class VRegPairDest(Register, Hvx, Dest):
def decl_tcg(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
+ TCGv_ptr {self.hvx_base()};
const intptr_t {self.hvx_off()} =
- {vreg_offset_func(tag)}(ctx, {self.reg_num}, 2, true);
+ {vreg_offset_func(tag)}(ctx, {self.reg_num}, 2,
+ true, &{self.hvx_base()});
"""))
if not skip_qemu_helper(tag):
- f.write(code_fmt(f"""\
- TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
- tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
- """))
+ self.decl_tcg_ptr(f)
def gen_zero(self, f):
f.write(code_fmt(f"""\
- tcg_gen_gvec_dup_imm(MO_64, {self.hvx_off()},
+ tcg_gen_gvec_dup_imm_var(MO_64, {self.hvx_base()}, {self.hvx_off()},
sizeof(MMVectorPair), sizeof(MMVectorPair), 0);
"""))
def gen_write(self, f, tag):
@@ -955,20 +971,27 @@ class VRegPairSource(Register, Hvx, OldSource):
def decl_tcg(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
+ TCGv_ptr {self.hvx_base()} = tcg_env;
+ TCGv_ptr {self.reg_tcg()}_srcbase;
const intptr_t {self.hvx_off()} =
offsetof(CPUHexagonState, {self.reg_tcg()});
- tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
- vreg_src_off(ctx, {self.reg_num}),
- sizeof(MMVector), sizeof(MMVector));
- tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector),
- vreg_src_off(ctx, {self.reg_num} ^ 1),
- sizeof(MMVector), sizeof(MMVector));
+ intptr_t {self.reg_tcg()}_srcoff =
+ vreg_src_off(ctx, {self.reg_num}, &{self.reg_tcg()}_srcbase);
+ tcg_gen_gvec_mov_var(MO_64, {self.hvx_base()}, {self.hvx_off()},
+ {self.reg_tcg()}_srcbase,
+ {self.reg_tcg()}_srcoff,
+ sizeof(MMVector), sizeof(MMVector));
+ {self.reg_tcg()}_srcoff =
+ vreg_src_off(ctx, {self.reg_num} ^ 1,
+ &{self.reg_tcg()}_srcbase);
+ tcg_gen_gvec_mov_var(MO_64, {self.hvx_base()},
+ {self.hvx_off()} + sizeof(MMVector),
+ {self.reg_tcg()}_srcbase,
+ {self.reg_tcg()}_srcoff,
+ sizeof(MMVector), sizeof(MMVector));
"""))
if not skip_qemu_helper(tag):
- f.write(code_fmt(f"""\
- TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
- tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
- """))
+ self.decl_tcg_ptr(f)
def helper_hvx_desc(self, f):
f.write(code_fmt(f"""\
/* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
@@ -982,29 +1005,36 @@ class VRegPairReadWrite(Register, Hvx, ReadWrite):
def decl_tcg(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
+ TCGv_ptr {self.hvx_base()} = tcg_env;
+ TCGv_ptr {self.reg_tcg()}_srcbase;
const intptr_t {self.hvx_off()} =
offsetof(CPUHexagonState, {self.reg_tcg()});
- tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
- vreg_src_off(ctx, {self.reg_num}),
- sizeof(MMVector), sizeof(MMVector));
- tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector),
- vreg_src_off(ctx, {self.reg_num} ^ 1),
- sizeof(MMVector), sizeof(MMVector));
+ intptr_t {self.reg_tcg()}_srcoff =
+ vreg_src_off(ctx, {self.reg_num}, &{self.reg_tcg()}_srcbase);
+ tcg_gen_gvec_mov_var(MO_64, {self.hvx_base()}, {self.hvx_off()},
+ {self.reg_tcg()}_srcbase,
+ {self.reg_tcg()}_srcoff,
+ sizeof(MMVector), sizeof(MMVector));
+ {self.reg_tcg()}_srcoff =
+ vreg_src_off(ctx, {self.reg_num} ^ 1,
+ &{self.reg_tcg()}_srcbase);
+ tcg_gen_gvec_mov_var(MO_64, {self.hvx_base()},
+ {self.hvx_off()} + sizeof(MMVector),
+ {self.reg_tcg()}_srcbase,
+ {self.reg_tcg()}_srcoff,
+ sizeof(MMVector), sizeof(MMVector));
"""))
if not skip_qemu_helper(tag):
- f.write(code_fmt(f"""\
- TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
- tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
- """))
+ self.decl_tcg_ptr(f)
def gen_zero(self, f):
f.write(code_fmt(f"""\
- tcg_gen_gvec_dup_imm(MO_64, {self.hvx_off()},
+ tcg_gen_gvec_dup_imm_var(MO_64, {self.hvx_base()}, {self.hvx_off()},
sizeof(MMVectorPair), sizeof(MMVectorPair), 0);
"""))
def gen_write(self, f, tag):
f.write(code_fmt(f"""\
- gen_vreg_write_pair(ctx, {self.hvx_off()}, {self.reg_num},
- {hvx_newv(tag)});
+ gen_vreg_write_pair(ctx, {self.hvx_base()}, {self.hvx_off()},
+ {self.reg_num}, {hvx_newv(tag)});
"""))
def helper_hvx_desc(self, f):
f.write(code_fmt(f"""\
@@ -1026,14 +1056,12 @@ class QRegDest(Register, Hvx, Dest):
def decl_tcg(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
+ TCGv_ptr {self.hvx_base()};
const intptr_t {self.hvx_off()} =
- get_result_qreg(ctx, {self.reg_num});
+ get_result_qreg(ctx, {self.reg_num}, &{self.hvx_base()});
"""))
if not skip_qemu_helper(tag):
- f.write(code_fmt(f"""\
- TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
- tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
- """))
+ self.decl_tcg_ptr(f)
def gen_write(self, f, tag):
pass
def helper_hvx_desc(self, f):
@@ -1049,14 +1077,12 @@ class QRegSource(Register, Hvx, OldSource):
def decl_tcg(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
+ TCGv_ptr {self.hvx_base()} = hex_hvx_ptr;
const intptr_t {self.hvx_off()} =
- offsetof(CPUHexagonState, QRegs[{self.reg_num}]);
+ HEX_HVX_OFFSET(QRegs[{self.reg_num}]);
"""))
if not skip_qemu_helper(tag):
- f.write(code_fmt(f"""\
- TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
- tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
- """))
+ self.decl_tcg_ptr(f)
def helper_hvx_desc(self, f):
f.write(code_fmt(f"""\
/* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
@@ -1070,17 +1096,16 @@ class QRegReadWrite(Register, Hvx, ReadWrite):
def decl_tcg(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
+ TCGv_ptr {self.hvx_base()};
const intptr_t {self.hvx_off()} =
- get_result_qreg(ctx, {self.reg_num});
- tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
- offsetof(CPUHexagonState, QRegs[{self.reg_num}]),
- sizeof(MMQReg), sizeof(MMQReg));
+ get_result_qreg(ctx, {self.reg_num}, &{self.hvx_base()});
+ tcg_gen_gvec_mov_var(MO_64, {self.hvx_base()}, {self.hvx_off()},
+ hex_hvx_ptr,
+ HEX_HVX_OFFSET(QRegs[{self.reg_num}]),
+ sizeof(MMQReg), sizeof(MMQReg));
"""))
if not skip_qemu_helper(tag):
- f.write(code_fmt(f"""\
- TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
- tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
- """))
+ self.decl_tcg_ptr(f)
def gen_write(self, f, tag):
pass
def helper_hvx_desc(self, f):
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread