Hexagon (target/hexagon) Only use branch_taken when packet has multi cof
When a packet has more than one change-of-flow instruction, only the first one to branch is considered. We use the branch_taken variable to keep track of this. However, when there is a single cof instruction, we don't need the same amount of bookkeeping. We add the pkt_has_multi_cof member to the Packet structure, and pass this information to the needed functions. When there is a generated helper function with cof, the generator will pass this pkt_has_multi_cof as a runtime value. Acked-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Taylor Simpson <tsimpson@quicinc.com> Message-Id: <20221108162906.3166-5-tsimpson@quicinc.com>
This commit is contained in:
parent
8e8a85c14e
commit
fb67c2bf24
|
@ -388,6 +388,7 @@ static void decode_set_insn_attr_fields(Packet *pkt)
|
|||
uint16_t opcode;
|
||||
|
||||
pkt->pkt_has_cof = false;
|
||||
pkt->pkt_has_multi_cof = false;
|
||||
pkt->pkt_has_endloop = false;
|
||||
pkt->pkt_has_dczeroa = false;
|
||||
|
||||
|
@ -412,13 +413,23 @@ static void decode_set_insn_attr_fields(Packet *pkt)
|
|||
}
|
||||
}
|
||||
|
||||
pkt->pkt_has_cof |= decode_opcode_can_jump(opcode);
|
||||
if (decode_opcode_can_jump(opcode)) {
|
||||
if (pkt->pkt_has_cof) {
|
||||
pkt->pkt_has_multi_cof = true;
|
||||
}
|
||||
pkt->pkt_has_cof = true;
|
||||
}
|
||||
|
||||
pkt->insn[i].is_endloop = decode_opcode_ends_loop(opcode);
|
||||
|
||||
pkt->pkt_has_endloop |= pkt->insn[i].is_endloop;
|
||||
|
||||
pkt->pkt_has_cof |= pkt->pkt_has_endloop;
|
||||
if (pkt->pkt_has_endloop) {
|
||||
if (pkt->pkt_has_cof) {
|
||||
pkt->pkt_has_multi_cof = true;
|
||||
}
|
||||
pkt->pkt_has_cof = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
## Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## 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
|
||||
|
@ -238,6 +238,9 @@ def gen_helper_function(f, tag, tagregs, tagimms):
|
|||
gen_helper_arg_imm(f,immlett)
|
||||
i += 1
|
||||
|
||||
if (hex_common.need_pkt_has_multi_cof(tag)):
|
||||
f.write(", uint32_t pkt_has_multi_cof")
|
||||
|
||||
if hex_common.need_slot(tag):
|
||||
if i > 0: f.write(", ")
|
||||
f.write("uint32_t slot")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
## Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## 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
|
||||
|
@ -82,6 +82,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
|
|||
## Figure out how many arguments the helper will take
|
||||
if (numscalarresults == 0):
|
||||
def_helper_size = len(regs)+len(imms)+numscalarreadwrite+1
|
||||
if hex_common.need_pkt_has_multi_cof(tag): def_helper_size += 1
|
||||
if hex_common.need_part1(tag): def_helper_size += 1
|
||||
if hex_common.need_slot(tag): def_helper_size += 1
|
||||
f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
|
||||
|
@ -89,6 +90,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
|
|||
f.write(', void' )
|
||||
else:
|
||||
def_helper_size = len(regs)+len(imms)+numscalarreadwrite
|
||||
if hex_common.need_pkt_has_multi_cof(tag): def_helper_size += 1
|
||||
if hex_common.need_part1(tag): def_helper_size += 1
|
||||
if hex_common.need_slot(tag): def_helper_size += 1
|
||||
f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
|
||||
|
@ -126,7 +128,9 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
|
|||
for immlett,bits,immshift in imms:
|
||||
f.write(", s32")
|
||||
|
||||
## Add the arguments for the instruction slot and part1 (if needed)
|
||||
## Add the arguments for the instruction pkt_has_multi_cof, slot and
|
||||
## part1 (if needed)
|
||||
if hex_common.need_pkt_has_multi_cof(tag): f.write(', i32')
|
||||
if hex_common.need_slot(tag): f.write(', i32' )
|
||||
if hex_common.need_part1(tag): f.write(' , i32' )
|
||||
f.write(')\n')
|
||||
|
|
|
@ -622,6 +622,9 @@ def gen_tcg_func(f, tag, regs, imms):
|
|||
## Generate the call to the helper
|
||||
for immlett,bits,immshift in imms:
|
||||
gen_helper_decl_imm(f,immlett)
|
||||
if hex_common.need_pkt_has_multi_cof(tag):
|
||||
f.write(" TCGv pkt_has_multi_cof = ")
|
||||
f.write("tcg_constant_tl(ctx->pkt->pkt_has_multi_cof);\n")
|
||||
if hex_common.need_part1(tag):
|
||||
f.write(" TCGv part1 = tcg_constant_tl(insn->part1);\n")
|
||||
if hex_common.need_slot(tag):
|
||||
|
@ -654,6 +657,8 @@ def gen_tcg_func(f, tag, regs, imms):
|
|||
for immlett,bits,immshift in imms:
|
||||
gen_helper_call_imm(f,immlett)
|
||||
|
||||
if hex_common.need_pkt_has_multi_cof(tag):
|
||||
f.write(", pkt_has_multi_cof")
|
||||
if hex_common.need_slot(tag): f.write(", slot")
|
||||
if hex_common.need_part1(tag): f.write(", part1" )
|
||||
f.write(");\n")
|
||||
|
|
|
@ -207,6 +207,9 @@ def need_part1(tag):
|
|||
def need_ea(tag):
|
||||
return re.compile(r"\bEA\b").search(semdict[tag])
|
||||
|
||||
def need_pkt_has_multi_cof(tag):
|
||||
return 'A_COF' in attribdict[tag]
|
||||
|
||||
def skip_qemu_helper(tag):
|
||||
return tag in overrides.keys()
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ struct Packet {
|
|||
|
||||
/* Pre-decodes about COF */
|
||||
bool pkt_has_cof; /* Has any change-of-flow */
|
||||
bool pkt_has_multi_cof; /* Has more than one change-of-flow */
|
||||
bool pkt_has_endloop;
|
||||
|
||||
bool pkt_has_dczeroa;
|
||||
|
|
|
@ -407,7 +407,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
|
|||
|
||||
#define fCHECK_PCALIGN(A)
|
||||
|
||||
#define fWRITE_NPC(A) write_new_pc(env, A)
|
||||
#define fWRITE_NPC(A) write_new_pc(env, pkt_has_multi_cof != 0, A)
|
||||
|
||||
#define fBRANCH(LOC, TYPE) fWRITE_NPC(LOC)
|
||||
#define fJUMPR(REGNO, TARGET, TYPE) fBRANCH(TARGET, COF_TYPE_JUMPR)
|
||||
|
|
|
@ -104,20 +104,26 @@ static void log_store64(CPUHexagonState *env, target_ulong addr,
|
|||
env->mem_log_stores[slot].data64 = val;
|
||||
}
|
||||
|
||||
static void write_new_pc(CPUHexagonState *env, target_ulong addr)
|
||||
static void write_new_pc(CPUHexagonState *env, bool pkt_has_multi_cof,
|
||||
target_ulong addr)
|
||||
{
|
||||
HEX_DEBUG_LOG("write_new_pc(0x" TARGET_FMT_lx ")\n", addr);
|
||||
|
||||
/*
|
||||
* If more than one branch is taken in a packet, only the first one
|
||||
* is actually done.
|
||||
*/
|
||||
if (env->branch_taken) {
|
||||
HEX_DEBUG_LOG("INFO: multiple branches taken in same packet, "
|
||||
"ignoring the second one\n");
|
||||
if (pkt_has_multi_cof) {
|
||||
/*
|
||||
* If more than one branch is taken in a packet, only the first one
|
||||
* is actually done.
|
||||
*/
|
||||
if (env->branch_taken) {
|
||||
HEX_DEBUG_LOG("INFO: multiple branches taken in same packet, "
|
||||
"ignoring the second one\n");
|
||||
} else {
|
||||
fCHECK_PCALIGN(addr);
|
||||
env->next_PC = addr;
|
||||
env->branch_taken = 1;
|
||||
}
|
||||
} else {
|
||||
fCHECK_PCALIGN(addr);
|
||||
env->branch_taken = 1;
|
||||
env->next_PC = addr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -248,7 +248,9 @@ static void gen_start_packet(DisasContext *ctx)
|
|||
tcg_gen_movi_tl(hex_slot_cancelled, 0);
|
||||
}
|
||||
if (pkt->pkt_has_cof) {
|
||||
tcg_gen_movi_tl(hex_branch_taken, 0);
|
||||
if (pkt->pkt_has_multi_cof) {
|
||||
tcg_gen_movi_tl(hex_branch_taken, 0);
|
||||
}
|
||||
tcg_gen_movi_tl(hex_next_PC, next_PC);
|
||||
}
|
||||
if (need_pred_written(pkt)) {
|
||||
|
|
Loading…
Reference in New Issue