mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-18 23:52:14 -06:00
Hexagon (target/hexagon) Improve code gen for predicated HVX instructions
The following improvements are made for predicated HVX instructions During gen_commit_hvx, unconditionally move the "new" value into the dest Don't set slot_cancelled Remove runtime bookkeeping of which registers were updated Reduce the cases where gen_log_vreg_write[_pair] is called It's only needed for special operands VxxV and VyV Remove gen_log_qreg_write Signed-off-by: Taylor Simpson <tsimpson@quicinc.com> Reviewed-by: Anton Johansson <anjo@rev.ng> Message-Id: <20230307025828.1612809-15-tsimpson@quicinc.com>
This commit is contained in:
parent
7b84fd04bd
commit
c2b33d0be9
8 changed files with 34 additions and 168 deletions
|
@ -136,12 +136,9 @@ For HVX vectors, the generator behaves slightly differently. The wide vectors
|
||||||
won't fit in a TCGv or TCGv_i64, so we pass TCGv_ptr variables to pass the
|
won't fit in a TCGv or TCGv_i64, so we pass TCGv_ptr variables to pass the
|
||||||
address to helper functions. Here's an example for an HVX vector-add-word
|
address to helper functions. Here's an example for an HVX vector-add-word
|
||||||
istruction.
|
istruction.
|
||||||
static void generate_V6_vaddw(
|
static void generate_V6_vaddw(DisasContext *ctx)
|
||||||
CPUHexagonState *env,
|
|
||||||
DisasContext *ctx,
|
|
||||||
Insn *insn,
|
|
||||||
Packet *pkt)
|
|
||||||
{
|
{
|
||||||
|
Insn *insn __attribute__((unused)) = ctx->insn;
|
||||||
const int VdN = insn->regno[0];
|
const int VdN = insn->regno[0];
|
||||||
const intptr_t VdV_off =
|
const intptr_t VdV_off =
|
||||||
ctx_future_vreg_off(ctx, VdN, 1, true);
|
ctx_future_vreg_off(ctx, VdN, 1, true);
|
||||||
|
@ -157,9 +154,7 @@ istruction.
|
||||||
TCGv_ptr VvV = tcg_temp_new_ptr();
|
TCGv_ptr VvV = tcg_temp_new_ptr();
|
||||||
tcg_gen_addi_ptr(VuV, cpu_env, VuV_off);
|
tcg_gen_addi_ptr(VuV, cpu_env, VuV_off);
|
||||||
tcg_gen_addi_ptr(VvV, cpu_env, VvV_off);
|
tcg_gen_addi_ptr(VvV, cpu_env, VvV_off);
|
||||||
TCGv slot = tcg_constant_tl(insn->slot);
|
gen_helper_V6_vaddw(cpu_env, VdV, VuV, VvV);
|
||||||
gen_helper_V6_vaddw(cpu_env, VdV, VuV, VvV, slot);
|
|
||||||
gen_log_vreg_write(ctx, VdV_off, VdN, EXT_DFL, insn->slot, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Notice that we also generate a variable named <operand>_off for each operand of
|
Notice that we also generate a variable named <operand>_off for each operand of
|
||||||
|
@ -172,12 +167,9 @@ functions from tcg-op-gvec.h. Here's the override for this instruction.
|
||||||
Finally, we notice that the override doesn't use the TCGv_ptr variables, so
|
Finally, we notice that the override doesn't use the TCGv_ptr variables, so
|
||||||
we don't generate them when an override is present. Here is what we generate
|
we don't generate them when an override is present. Here is what we generate
|
||||||
when the override is present.
|
when the override is present.
|
||||||
static void generate_V6_vaddw(
|
static void generate_V6_vaddw(DisasContext *ctx)
|
||||||
CPUHexagonState *env,
|
|
||||||
DisasContext *ctx,
|
|
||||||
Insn *insn,
|
|
||||||
Packet *pkt)
|
|
||||||
{
|
{
|
||||||
|
Insn *insn __attribute__((unused)) = ctx->insn;
|
||||||
const int VdN = insn->regno[0];
|
const int VdN = insn->regno[0];
|
||||||
const intptr_t VdV_off =
|
const intptr_t VdV_off =
|
||||||
ctx_future_vreg_off(ctx, VdN, 1, true);
|
ctx_future_vreg_off(ctx, VdN, 1, true);
|
||||||
|
@ -188,7 +180,6 @@ when the override is present.
|
||||||
const intptr_t VvV_off =
|
const intptr_t VvV_off =
|
||||||
vreg_src_off(ctx, VvN);
|
vreg_src_off(ctx, VvN);
|
||||||
fGEN_TCG_V6_vaddw({ fHIDE(int i;) fVFOREACH(32, i) { VdV.w[i] = VuV.w[i] + VvV.w[i] ; } });
|
fGEN_TCG_V6_vaddw({ fHIDE(int i;) fVFOREACH(32, i) { VdV.w[i] = VuV.w[i] + VvV.w[i] ; } });
|
||||||
gen_log_vreg_write(ctx, VdV_off, VdN, EXT_DFL, insn->slot, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
We also generate an analyze_<tag> function for each instruction. Currently,
|
We also generate an analyze_<tag> function for each instruction. Currently,
|
||||||
|
@ -281,10 +272,8 @@ For Hexagon Vector eXtensions (HVX), the following fields are used
|
||||||
VRegs Vector registers
|
VRegs Vector registers
|
||||||
future_VRegs Registers to be stored during packet commit
|
future_VRegs Registers to be stored during packet commit
|
||||||
tmp_VRegs Temporary registers *not* stored during commit
|
tmp_VRegs Temporary registers *not* stored during commit
|
||||||
VRegs_updated Mask of predicated vector writes
|
|
||||||
QRegs Q (vector predicate) registers
|
QRegs Q (vector predicate) registers
|
||||||
future_QRegs Registers to be stored during packet commit
|
future_QRegs Registers to be stored during packet commit
|
||||||
QRegs_updated Mask of predicated vector writes
|
|
||||||
|
|
||||||
*** Debugging ***
|
*** Debugging ***
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
* Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -111,11 +111,8 @@ typedef struct CPUArchState {
|
||||||
MMVector future_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
|
MMVector future_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
|
||||||
MMVector tmp_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
|
MMVector tmp_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
|
||||||
|
|
||||||
VRegMask VRegs_updated;
|
|
||||||
|
|
||||||
MMQReg QRegs[NUM_QREGS] QEMU_ALIGNED(16);
|
MMQReg QRegs[NUM_QREGS] QEMU_ALIGNED(16);
|
||||||
MMQReg future_QRegs[NUM_QREGS] QEMU_ALIGNED(16);
|
MMQReg future_QRegs[NUM_QREGS] QEMU_ALIGNED(16);
|
||||||
QRegMask QRegs_updated;
|
|
||||||
|
|
||||||
/* Temporaries used within instructions */
|
/* Temporaries used within instructions */
|
||||||
MMVectorPair VuuV QEMU_ALIGNED(16);
|
MMVectorPair VuuV QEMU_ALIGNED(16);
|
||||||
|
|
|
@ -110,8 +110,7 @@ def analyze_opn_old(f, tag, regtype, regid, regno):
|
||||||
if (regid in {"d", "e", "x"}):
|
if (regid in {"d", "e", "x"}):
|
||||||
f.write(" const int %s = insn->regno[%d];\n" % \
|
f.write(" const int %s = insn->regno[%d];\n" % \
|
||||||
(regN, regno))
|
(regN, regno))
|
||||||
f.write(" ctx_log_qreg_write(ctx, %s, %s);\n" % \
|
f.write(" ctx_log_qreg_write(ctx, %s);\n" % (regN))
|
||||||
(regN, predicated))
|
|
||||||
elif (regid in {"s", "t", "u", "v"}):
|
elif (regid in {"s", "t", "u", "v"}):
|
||||||
f.write("// const int %s = insn->regno[%d];\n" % \
|
f.write("// const int %s = insn->regno[%d];\n" % \
|
||||||
(regN, regno))
|
(regN, regno))
|
||||||
|
|
|
@ -176,8 +176,7 @@ def genptr_decl(f, tag, regtype, regid, regno):
|
||||||
(regtype, regid, regno))
|
(regtype, regid, regno))
|
||||||
f.write(" const intptr_t %s%sV_off =\n" % \
|
f.write(" const intptr_t %s%sV_off =\n" % \
|
||||||
(regtype, regid))
|
(regtype, regid))
|
||||||
f.write(" offsetof(CPUHexagonState,\n")
|
f.write(" get_result_qreg(ctx, %s%sN);\n" % \
|
||||||
f.write(" future_QRegs[%s%sN]);\n" % \
|
|
||||||
(regtype, regid))
|
(regtype, regid))
|
||||||
if (not hex_common.skip_qemu_helper(tag)):
|
if (not hex_common.skip_qemu_helper(tag)):
|
||||||
f.write(" TCGv_ptr %s%sV = tcg_temp_new_ptr();\n" % \
|
f.write(" TCGv_ptr %s%sV = tcg_temp_new_ptr();\n" % \
|
||||||
|
@ -406,36 +405,18 @@ def genptr_dst_write(f, tag, regtype, regid):
|
||||||
|
|
||||||
def genptr_dst_write_ext(f, tag, regtype, regid, newv="EXT_DFL"):
|
def genptr_dst_write_ext(f, tag, regtype, regid, newv="EXT_DFL"):
|
||||||
if (regtype == "V"):
|
if (regtype == "V"):
|
||||||
if (regid in {"dd", "xx", "yy"}):
|
if (regid in {"xx"}):
|
||||||
if ('A_CONDEXEC' in hex_common.attribdict[tag]):
|
|
||||||
is_predicated = "true"
|
|
||||||
else:
|
|
||||||
is_predicated = "false"
|
|
||||||
f.write(" gen_log_vreg_write_pair(ctx, %s%sV_off, %s%sN, " % \
|
f.write(" gen_log_vreg_write_pair(ctx, %s%sV_off, %s%sN, " % \
|
||||||
(regtype, regid, regtype, regid))
|
(regtype, regid, regtype, regid))
|
||||||
f.write("%s, insn->slot, %s);\n" % \
|
f.write("%s);\n" % \
|
||||||
(newv, is_predicated))
|
(newv))
|
||||||
elif (regid in {"d", "x", "y"}):
|
elif (regid in {"y"}):
|
||||||
if ('A_CONDEXEC' in hex_common.attribdict[tag]):
|
f.write(" gen_log_vreg_write(ctx, %s%sV_off, %s%sN, %s);\n" % \
|
||||||
is_predicated = "true"
|
|
||||||
else:
|
|
||||||
is_predicated = "false"
|
|
||||||
f.write(" gen_log_vreg_write(ctx, %s%sV_off, %s%sN, %s, " % \
|
|
||||||
(regtype, regid, regtype, regid, newv))
|
(regtype, regid, regtype, regid, newv))
|
||||||
f.write("insn->slot, %s);\n" % \
|
elif (regid not in {"dd", "d", "x"}):
|
||||||
(is_predicated))
|
|
||||||
else:
|
|
||||||
print("Bad register parse: ", regtype, regid)
|
print("Bad register parse: ", regtype, regid)
|
||||||
elif (regtype == "Q"):
|
elif (regtype == "Q"):
|
||||||
if (regid in {"d", "e", "x"}):
|
if (regid not in {"d", "e", "x"}):
|
||||||
if ('A_CONDEXEC' in hex_common.attribdict[tag]):
|
|
||||||
is_predicated = "true"
|
|
||||||
else:
|
|
||||||
is_predicated = "false"
|
|
||||||
f.write(" gen_log_qreg_write(%s%sV_off, %s%sN, %s, " % \
|
|
||||||
(regtype, regid, regtype, regid, newv))
|
|
||||||
f.write("insn->slot, %s);\n" % (is_predicated))
|
|
||||||
else:
|
|
||||||
print("Bad register parse: ", regtype, regid)
|
print("Bad register parse: ", regtype, regid)
|
||||||
else:
|
else:
|
||||||
print("Bad register parse: ", regtype, regid)
|
print("Bad register parse: ", regtype, regid)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
* Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -133,16 +133,11 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
|
||||||
do { \
|
do { \
|
||||||
TCGv lsb = tcg_temp_new(); \
|
TCGv lsb = tcg_temp_new(); \
|
||||||
TCGLabel *false_label = gen_new_label(); \
|
TCGLabel *false_label = gen_new_label(); \
|
||||||
TCGLabel *end_label = gen_new_label(); \
|
|
||||||
tcg_gen_andi_tl(lsb, PsV, 1); \
|
tcg_gen_andi_tl(lsb, PsV, 1); \
|
||||||
tcg_gen_brcondi_tl(TCG_COND_NE, lsb, PRED, false_label); \
|
tcg_gen_brcondi_tl(TCG_COND_NE, lsb, PRED, false_label); \
|
||||||
tcg_gen_gvec_mov(MO_64, VdV_off, VuV_off, \
|
tcg_gen_gvec_mov(MO_64, VdV_off, VuV_off, \
|
||||||
sizeof(MMVector), sizeof(MMVector)); \
|
sizeof(MMVector), sizeof(MMVector)); \
|
||||||
tcg_gen_br(end_label); \
|
|
||||||
gen_set_label(false_label); \
|
gen_set_label(false_label); \
|
||||||
tcg_gen_ori_tl(hex_slot_cancelled, hex_slot_cancelled, \
|
|
||||||
1 << insn->slot); \
|
|
||||||
gen_set_label(end_label); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
@ -547,17 +542,12 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
|
||||||
do { \
|
do { \
|
||||||
TCGv LSB = tcg_temp_new(); \
|
TCGv LSB = tcg_temp_new(); \
|
||||||
TCGLabel *false_label = gen_new_label(); \
|
TCGLabel *false_label = gen_new_label(); \
|
||||||
TCGLabel *end_label = gen_new_label(); \
|
|
||||||
GET_EA; \
|
GET_EA; \
|
||||||
PRED; \
|
PRED; \
|
||||||
tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, false_label); \
|
tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, false_label); \
|
||||||
gen_vreg_load(ctx, DSTOFF, EA, true); \
|
gen_vreg_load(ctx, DSTOFF, EA, true); \
|
||||||
INC; \
|
INC; \
|
||||||
tcg_gen_br(end_label); \
|
|
||||||
gen_set_label(false_label); \
|
gen_set_label(false_label); \
|
||||||
tcg_gen_ori_tl(hex_slot_cancelled, hex_slot_cancelled, \
|
|
||||||
1 << insn->slot); \
|
|
||||||
gen_set_label(end_label); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define fGEN_TCG_PRED_VEC_LOAD_pred_pi \
|
#define fGEN_TCG_PRED_VEC_LOAD_pred_pi \
|
||||||
|
@ -717,17 +707,12 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
|
||||||
do { \
|
do { \
|
||||||
TCGv LSB = tcg_temp_new(); \
|
TCGv LSB = tcg_temp_new(); \
|
||||||
TCGLabel *false_label = gen_new_label(); \
|
TCGLabel *false_label = gen_new_label(); \
|
||||||
TCGLabel *end_label = gen_new_label(); \
|
|
||||||
GET_EA; \
|
GET_EA; \
|
||||||
PRED; \
|
PRED; \
|
||||||
tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, false_label); \
|
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, SRCOFF, insn->slot, ALIGN); \
|
||||||
INC; \
|
INC; \
|
||||||
tcg_gen_br(end_label); \
|
|
||||||
gen_set_label(false_label); \
|
gen_set_label(false_label); \
|
||||||
tcg_gen_ori_tl(hex_slot_cancelled, hex_slot_cancelled, \
|
|
||||||
1 << insn->slot); \
|
|
||||||
gen_set_label(end_label); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define fGEN_TCG_PRED_VEC_STORE_pred_pi(ALIGN) \
|
#define fGEN_TCG_PRED_VEC_STORE_pred_pi(ALIGN) \
|
||||||
|
|
|
@ -985,68 +985,32 @@ static intptr_t vreg_src_off(DisasContext *ctx, int num)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_log_vreg_write(DisasContext *ctx, intptr_t srcoff, int num,
|
static void gen_log_vreg_write(DisasContext *ctx, intptr_t srcoff, int num,
|
||||||
VRegWriteType type, int slot_num,
|
VRegWriteType type)
|
||||||
bool is_predicated)
|
|
||||||
{
|
{
|
||||||
TCGLabel *label_end = NULL;
|
|
||||||
intptr_t dstoff;
|
intptr_t dstoff;
|
||||||
|
|
||||||
if (is_predicated) {
|
|
||||||
TCGv cancelled = tcg_temp_new();
|
|
||||||
label_end = gen_new_label();
|
|
||||||
|
|
||||||
/* Don't do anything if the slot was cancelled */
|
|
||||||
tcg_gen_extract_tl(cancelled, hex_slot_cancelled, slot_num, 1);
|
|
||||||
tcg_gen_brcondi_tl(TCG_COND_NE, cancelled, 0, label_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type != EXT_TMP) {
|
if (type != EXT_TMP) {
|
||||||
dstoff = ctx_future_vreg_off(ctx, num, 1, true);
|
dstoff = ctx_future_vreg_off(ctx, num, 1, true);
|
||||||
tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
|
tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
|
||||||
sizeof(MMVector), sizeof(MMVector));
|
sizeof(MMVector), sizeof(MMVector));
|
||||||
tcg_gen_ori_tl(hex_VRegs_updated, hex_VRegs_updated, 1 << num);
|
|
||||||
} else {
|
} else {
|
||||||
dstoff = ctx_tmp_vreg_off(ctx, num, 1, false);
|
dstoff = ctx_tmp_vreg_off(ctx, num, 1, false);
|
||||||
tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
|
tcg_gen_gvec_mov(MO_64, dstoff, srcoff,
|
||||||
sizeof(MMVector), sizeof(MMVector));
|
sizeof(MMVector), sizeof(MMVector));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_predicated) {
|
|
||||||
gen_set_label(label_end);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_log_vreg_write_pair(DisasContext *ctx, intptr_t srcoff, int num,
|
static void gen_log_vreg_write_pair(DisasContext *ctx, intptr_t srcoff, int num,
|
||||||
VRegWriteType type, int slot_num,
|
VRegWriteType type)
|
||||||
bool is_predicated)
|
|
||||||
{
|
{
|
||||||
gen_log_vreg_write(ctx, srcoff, num ^ 0, type, slot_num, is_predicated);
|
gen_log_vreg_write(ctx, srcoff, num ^ 0, type);
|
||||||
srcoff += sizeof(MMVector);
|
srcoff += sizeof(MMVector);
|
||||||
gen_log_vreg_write(ctx, srcoff, num ^ 1, type, slot_num, is_predicated);
|
gen_log_vreg_write(ctx, srcoff, num ^ 1, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_log_qreg_write(intptr_t srcoff, int num, int vnew,
|
static intptr_t get_result_qreg(DisasContext *ctx, int qnum)
|
||||||
int slot_num, bool is_predicated)
|
|
||||||
{
|
{
|
||||||
TCGLabel *label_end = NULL;
|
return offsetof(CPUHexagonState, future_QRegs[qnum]);
|
||||||
intptr_t dstoff;
|
|
||||||
|
|
||||||
if (is_predicated) {
|
|
||||||
TCGv cancelled = tcg_temp_new();
|
|
||||||
label_end = gen_new_label();
|
|
||||||
|
|
||||||
/* Don't do anything if the slot was cancelled */
|
|
||||||
tcg_gen_extract_tl(cancelled, hex_slot_cancelled, slot_num, 1);
|
|
||||||
tcg_gen_brcondi_tl(TCG_COND_NE, cancelled, 0, label_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
dstoff = offsetof(CPUHexagonState, future_QRegs[num]);
|
|
||||||
tcg_gen_gvec_mov(MO_64, dstoff, srcoff, sizeof(MMQReg), sizeof(MMQReg));
|
|
||||||
|
|
||||||
if (is_predicated) {
|
|
||||||
tcg_gen_ori_tl(hex_QRegs_updated, hex_QRegs_updated, 1 << num);
|
|
||||||
gen_set_label(label_end);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_vreg_load(DisasContext *ctx, intptr_t dstoff, TCGv src,
|
static void gen_vreg_load(DisasContext *ctx, intptr_t dstoff, TCGv src,
|
||||||
|
|
|
@ -56,8 +56,6 @@ TCGv hex_dczero_addr;
|
||||||
TCGv hex_llsc_addr;
|
TCGv hex_llsc_addr;
|
||||||
TCGv hex_llsc_val;
|
TCGv hex_llsc_val;
|
||||||
TCGv_i64 hex_llsc_val_i64;
|
TCGv_i64 hex_llsc_val_i64;
|
||||||
TCGv hex_VRegs_updated;
|
|
||||||
TCGv hex_QRegs_updated;
|
|
||||||
TCGv hex_vstore_addr[VSTORES_MAX];
|
TCGv hex_vstore_addr[VSTORES_MAX];
|
||||||
TCGv hex_vstore_size[VSTORES_MAX];
|
TCGv hex_vstore_size[VSTORES_MAX];
|
||||||
TCGv hex_vstore_pending[VSTORES_MAX];
|
TCGv hex_vstore_pending[VSTORES_MAX];
|
||||||
|
@ -248,12 +246,11 @@ static bool check_for_attrib(Packet *pkt, int attrib)
|
||||||
|
|
||||||
static bool need_slot_cancelled(Packet *pkt)
|
static bool need_slot_cancelled(Packet *pkt)
|
||||||
{
|
{
|
||||||
/* We only need slot_cancelled for conditional store and HVX instructions */
|
/* We only need slot_cancelled for conditional store instructions */
|
||||||
for (int i = 0; i < pkt->num_insns; i++) {
|
for (int i = 0; i < pkt->num_insns; i++) {
|
||||||
uint16_t opcode = pkt->insn[i].opcode;
|
uint16_t opcode = pkt->insn[i].opcode;
|
||||||
if (GET_ATTRIB(opcode, A_CONDEXEC) &&
|
if (GET_ATTRIB(opcode, A_CONDEXEC) &&
|
||||||
(GET_ATTRIB(opcode, A_STORE) ||
|
GET_ATTRIB(opcode, A_SCALAR_STORE)) {
|
||||||
GET_ATTRIB(opcode, A_CVI))) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,11 +450,6 @@ static void gen_start_packet(DisasContext *ctx)
|
||||||
i = find_next_bit(ctx->predicated_tmp_vregs, NUM_VREGS, i + 1);
|
i = find_next_bit(ctx->predicated_tmp_vregs, NUM_VREGS, i + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkt->pkt_has_hvx) {
|
|
||||||
tcg_gen_movi_tl(hex_VRegs_updated, 0);
|
|
||||||
tcg_gen_movi_tl(hex_QRegs_updated, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_gather_store_insn(DisasContext *ctx)
|
bool is_gather_store_insn(DisasContext *ctx)
|
||||||
|
@ -725,65 +717,31 @@ static void gen_commit_hvx(DisasContext *ctx)
|
||||||
/*
|
/*
|
||||||
* for (i = 0; i < ctx->vreg_log_idx; i++) {
|
* for (i = 0; i < ctx->vreg_log_idx; i++) {
|
||||||
* int rnum = ctx->vreg_log[i];
|
* int rnum = ctx->vreg_log[i];
|
||||||
* if (ctx->vreg_is_predicated[i]) {
|
|
||||||
* if (env->VRegs_updated & (1 << rnum)) {
|
|
||||||
* env->VRegs[rnum] = env->future_VRegs[rnum];
|
* env->VRegs[rnum] = env->future_VRegs[rnum];
|
||||||
* }
|
* }
|
||||||
* } else {
|
|
||||||
* env->VRegs[rnum] = env->future_VRegs[rnum];
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < ctx->vreg_log_idx; i++) {
|
for (i = 0; i < ctx->vreg_log_idx; i++) {
|
||||||
int rnum = ctx->vreg_log[i];
|
int rnum = ctx->vreg_log[i];
|
||||||
bool is_predicated = ctx->vreg_is_predicated[i];
|
|
||||||
intptr_t dstoff = offsetof(CPUHexagonState, VRegs[rnum]);
|
intptr_t dstoff = offsetof(CPUHexagonState, VRegs[rnum]);
|
||||||
intptr_t srcoff = ctx_future_vreg_off(ctx, rnum, 1, false);
|
intptr_t srcoff = ctx_future_vreg_off(ctx, rnum, 1, false);
|
||||||
size_t size = sizeof(MMVector);
|
size_t size = sizeof(MMVector);
|
||||||
|
|
||||||
if (is_predicated) {
|
|
||||||
TCGv cmp = tcg_temp_new();
|
|
||||||
TCGLabel *label_skip = gen_new_label();
|
|
||||||
|
|
||||||
tcg_gen_andi_tl(cmp, hex_VRegs_updated, 1 << rnum);
|
|
||||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cmp, 0, label_skip);
|
|
||||||
tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
|
tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
|
||||||
gen_set_label(label_skip);
|
|
||||||
} else {
|
|
||||||
tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* for (i = 0; i < ctx->qreg_log_idx; i++) {
|
* for (i = 0; i < ctx->qreg_log_idx; i++) {
|
||||||
* int rnum = ctx->qreg_log[i];
|
* int rnum = ctx->qreg_log[i];
|
||||||
* if (ctx->qreg_is_predicated[i]) {
|
|
||||||
* if (env->QRegs_updated) & (1 << rnum)) {
|
|
||||||
* env->QRegs[rnum] = env->future_QRegs[rnum];
|
* env->QRegs[rnum] = env->future_QRegs[rnum];
|
||||||
* }
|
* }
|
||||||
* } else {
|
|
||||||
* env->QRegs[rnum] = env->future_QRegs[rnum];
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < ctx->qreg_log_idx; i++) {
|
for (i = 0; i < ctx->qreg_log_idx; i++) {
|
||||||
int rnum = ctx->qreg_log[i];
|
int rnum = ctx->qreg_log[i];
|
||||||
bool is_predicated = ctx->qreg_is_predicated[i];
|
|
||||||
intptr_t dstoff = offsetof(CPUHexagonState, QRegs[rnum]);
|
intptr_t dstoff = offsetof(CPUHexagonState, QRegs[rnum]);
|
||||||
intptr_t srcoff = offsetof(CPUHexagonState, future_QRegs[rnum]);
|
intptr_t srcoff = offsetof(CPUHexagonState, future_QRegs[rnum]);
|
||||||
size_t size = sizeof(MMQReg);
|
size_t size = sizeof(MMQReg);
|
||||||
|
|
||||||
if (is_predicated) {
|
|
||||||
TCGv cmp = tcg_temp_new();
|
|
||||||
TCGLabel *label_skip = gen_new_label();
|
|
||||||
|
|
||||||
tcg_gen_andi_tl(cmp, hex_QRegs_updated, 1 << rnum);
|
|
||||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cmp, 0, label_skip);
|
|
||||||
tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
|
tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
|
||||||
gen_set_label(label_skip);
|
|
||||||
} else {
|
|
||||||
tcg_gen_gvec_mov(MO_64, dstoff, srcoff, size, size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkt_has_hvx_store(ctx->pkt)) {
|
if (pkt_has_hvx_store(ctx->pkt)) {
|
||||||
|
@ -1129,10 +1087,6 @@ void hexagon_translate_init(void)
|
||||||
offsetof(CPUHexagonState, llsc_val), "llsc_val");
|
offsetof(CPUHexagonState, llsc_val), "llsc_val");
|
||||||
hex_llsc_val_i64 = tcg_global_mem_new_i64(cpu_env,
|
hex_llsc_val_i64 = tcg_global_mem_new_i64(cpu_env,
|
||||||
offsetof(CPUHexagonState, llsc_val_i64), "llsc_val_i64");
|
offsetof(CPUHexagonState, llsc_val_i64), "llsc_val_i64");
|
||||||
hex_VRegs_updated = tcg_global_mem_new(cpu_env,
|
|
||||||
offsetof(CPUHexagonState, VRegs_updated), "VRegs_updated");
|
|
||||||
hex_QRegs_updated = tcg_global_mem_new(cpu_env,
|
|
||||||
offsetof(CPUHexagonState, QRegs_updated), "QRegs_updated");
|
|
||||||
for (i = 0; i < STORES_MAX; i++) {
|
for (i = 0; i < STORES_MAX; i++) {
|
||||||
snprintf(store_addr_names[i], NAME_LEN, "store_addr_%d", i);
|
snprintf(store_addr_names[i], NAME_LEN, "store_addr_%d", i);
|
||||||
hex_store_addr[i] = tcg_global_mem_new(cpu_env,
|
hex_store_addr[i] = tcg_global_mem_new(cpu_env,
|
||||||
|
|
|
@ -49,7 +49,6 @@ typedef struct DisasContext {
|
||||||
int tmp_vregs_idx;
|
int tmp_vregs_idx;
|
||||||
int tmp_vregs_num[VECTOR_TEMPS_MAX];
|
int tmp_vregs_num[VECTOR_TEMPS_MAX];
|
||||||
int vreg_log[NUM_VREGS];
|
int vreg_log[NUM_VREGS];
|
||||||
bool vreg_is_predicated[NUM_VREGS];
|
|
||||||
int vreg_log_idx;
|
int vreg_log_idx;
|
||||||
DECLARE_BITMAP(vregs_updated_tmp, NUM_VREGS);
|
DECLARE_BITMAP(vregs_updated_tmp, NUM_VREGS);
|
||||||
DECLARE_BITMAP(vregs_updated, NUM_VREGS);
|
DECLARE_BITMAP(vregs_updated, NUM_VREGS);
|
||||||
|
@ -57,7 +56,6 @@ typedef struct DisasContext {
|
||||||
DECLARE_BITMAP(predicated_future_vregs, NUM_VREGS);
|
DECLARE_BITMAP(predicated_future_vregs, NUM_VREGS);
|
||||||
DECLARE_BITMAP(predicated_tmp_vregs, NUM_VREGS);
|
DECLARE_BITMAP(predicated_tmp_vregs, NUM_VREGS);
|
||||||
int qreg_log[NUM_QREGS];
|
int qreg_log[NUM_QREGS];
|
||||||
bool qreg_is_predicated[NUM_QREGS];
|
|
||||||
int qreg_log_idx;
|
int qreg_log_idx;
|
||||||
bool pre_commit;
|
bool pre_commit;
|
||||||
TCGCond branch_cond;
|
TCGCond branch_cond;
|
||||||
|
@ -111,9 +109,11 @@ static inline void ctx_log_vreg_write(DisasContext *ctx,
|
||||||
bool is_predicated)
|
bool is_predicated)
|
||||||
{
|
{
|
||||||
if (type != EXT_TMP) {
|
if (type != EXT_TMP) {
|
||||||
|
if (!test_bit(rnum, ctx->vregs_updated)) {
|
||||||
ctx->vreg_log[ctx->vreg_log_idx] = rnum;
|
ctx->vreg_log[ctx->vreg_log_idx] = rnum;
|
||||||
ctx->vreg_is_predicated[ctx->vreg_log_idx] = is_predicated;
|
|
||||||
ctx->vreg_log_idx++;
|
ctx->vreg_log_idx++;
|
||||||
|
set_bit(rnum, ctx->vregs_updated);
|
||||||
|
}
|
||||||
|
|
||||||
set_bit(rnum, ctx->vregs_updated);
|
set_bit(rnum, ctx->vregs_updated);
|
||||||
if (is_predicated) {
|
if (is_predicated) {
|
||||||
|
@ -140,10 +140,9 @@ static inline void ctx_log_vreg_write_pair(DisasContext *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ctx_log_qreg_write(DisasContext *ctx,
|
static inline void ctx_log_qreg_write(DisasContext *ctx,
|
||||||
int rnum, bool is_predicated)
|
int rnum)
|
||||||
{
|
{
|
||||||
ctx->qreg_log[ctx->qreg_log_idx] = rnum;
|
ctx->qreg_log[ctx->qreg_log_idx] = rnum;
|
||||||
ctx->qreg_is_predicated[ctx->qreg_log_idx] = is_predicated;
|
|
||||||
ctx->qreg_log_idx++;
|
ctx->qreg_log_idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,8 +163,6 @@ extern TCGv hex_dczero_addr;
|
||||||
extern TCGv hex_llsc_addr;
|
extern TCGv hex_llsc_addr;
|
||||||
extern TCGv hex_llsc_val;
|
extern TCGv hex_llsc_val;
|
||||||
extern TCGv_i64 hex_llsc_val_i64;
|
extern TCGv_i64 hex_llsc_val_i64;
|
||||||
extern TCGv hex_VRegs_updated;
|
|
||||||
extern TCGv hex_QRegs_updated;
|
|
||||||
extern TCGv hex_vstore_addr[VSTORES_MAX];
|
extern TCGv hex_vstore_addr[VSTORES_MAX];
|
||||||
extern TCGv hex_vstore_size[VSTORES_MAX];
|
extern TCGv hex_vstore_size[VSTORES_MAX];
|
||||||
extern TCGv hex_vstore_pending[VSTORES_MAX];
|
extern TCGv hex_vstore_pending[VSTORES_MAX];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue