From: Brian Cain <brian.cain@oss.qualcomm.com>
To: qemu-devel@nongnu.org
Cc: "Philippe Mathieu-Daudé" <philmd@oss.qualcomm.com>,
"Pierrick Bouvier" <pierrick.bouvier@oss.qualcomm.com>,
"Brian Cain" <brian.cain@oss.qualcomm.com>,
marco.liebel@oss.qualcomm.com, "Helge Deller" <deller@gmx.de>,
"Paolo Bonzini" <pbonzini@redhat.com>,
richard.henderson@linaro.org,
"Laurent Vivier" <laurent@vivier.eu>
Subject: [PATCH v3 5/6] target/hexagon: share HVX contexts among CPUs
Date: Sun, 13 Sep 2026 08:59:27 -0700 [thread overview]
Message-ID: <20260913155928.365928-6-brian.cain@oss.qualcomm.com> (raw)
In-Reply-To: <20260913155928.365928-1-brian.cain@oss.qualcomm.com>
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
next prev parent reply other threads:[~2026-09-13 16:02 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` [PATCH v3 3/6] tcg: split out _var forms of gvec saturating/mul/shift-immediate ops Brian Cain
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 [this message]
2026-09-13 22:02 ` [PATCH v3 5/6] target/hexagon: share HVX contexts among CPUs Richard Henderson
2026-09-13 15:59 ` [PATCH v3 6/6] tests/functional/hexagon: add HVX tests Brian Cain
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260913155928.365928-6-brian.cain@oss.qualcomm.com \
--to=brian.cain@oss.qualcomm.com \
--cc=deller@gmx.de \
--cc=laurent@vivier.eu \
--cc=marco.liebel@oss.qualcomm.com \
--cc=pbonzini@redhat.com \
--cc=philmd@oss.qualcomm.com \
--cc=pierrick.bouvier@oss.qualcomm.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.