Generate the HLX decoder and apply its packet rules. Add HLX loads and stores, including .tmp load forwarding and .new store handling.
HLX .new fields name the forwarded L register. A store without a producer writes zeroes. Signed-off-by: Marco Liebel <[email protected]> Signed-off-by: Brian Cain <[email protected]> --- target/hexagon/attribs_def.h.inc | 5 + target/hexagon/decode.c | 118 ++++++++++++++++----- target/hexagon/gen_dectree_import.c | 9 +- target/hexagon/gen_hlx_ext.py | 25 +++++ target/hexagon/gen_idef_parser_funcs.py | 3 + target/hexagon/gen_tcg_funcs.py | 3 + target/hexagon/imported/allext.idef | 6 ++ target/hexagon/imported/allextenc.def | 4 + target/hexagon/imported/hlx/encode_ext.def | 18 ++++ target/hexagon/imported/hlx_ext.idef | 45 ++++++++ target/hexagon/insn.h | 1 + target/hexagon/meson.build | 39 +++++++ target/hexagon/opcodes.h | 1 + target/hexagon/translate.c | 12 +++ 14 files changed, 259 insertions(+), 30 deletions(-) create mode 100755 target/hexagon/gen_hlx_ext.py create mode 100644 target/hexagon/imported/hlx/encode_ext.def create mode 100644 target/hexagon/imported/hlx_ext.idef diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc index a02261ee5e..e9779a33ee 100644 --- a/target/hexagon/attribs_def.h.inc +++ b/target/hexagon/attribs_def.h.inc @@ -19,6 +19,9 @@ DEF_ATTRIB(AA_DUMMY, "Dummy Zeroth Attribute", "", "") /* Misc */ +DEF_ATTRIB(FAKEINSN, "Not a real instruction", "", "") +DEF_ATTRIB(MAPPING, "Not real -- asm mapped", "", "") +DEF_ATTRIB(CONDMAPPING, "Not real -- mapped based on values", "", "") DEF_ATTRIB(EXTENSION, "Extension instruction", "", "") DEF_ATTRIB(NA_NT, "Non-Allocating Non-Temporal instruction", "", "") @@ -228,5 +231,7 @@ DEF_ATTRIB(HVX_IEEE_FP_OUT_32, "HVX IEEE FP 32-bit output", "", "") DEF_ATTRIB(CVI_VX_NO_TMP_LD, "HVX multiply without tmp load", "", "") DEF_ATTRIB(HVX_FLT, "This a floating point HVX instruction.", "", "") +DEF_ATTRIB(NO_IDEF_PARSER, "Skip idef-parser for this instruction", "", "") + /* Keep this as the last attribute: */ DEF_ATTRIB(ZZ_LASTATTRIB, "Last attribute in the file", "", "") diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c index 0ac87bbee0..0c3dc67e12 100644 --- a/target/hexagon/decode.c +++ b/target/hexagon/decode.c @@ -23,6 +23,7 @@ #include "insn.h" #include "printinsn.h" #include "mmvec/decode_ext_mmvec.h" +#include "hlx/decode_ext_hlx.h" #define fZXTN(N, M, VAL) ((VAL) & ((1LL << (N)) - 1)) @@ -69,6 +70,7 @@ static int shift_left(DisasContext *ctx, int x, int n, int immno) /* Include the generated decoder for 32 bit insn */ #include "decode_normal_generated.c.inc" #include "decode_hvx_generated.c.inc" +#include "decode_hlx_generated.c.inc" /* Include the generated decoder for 16 bit insn */ #include "decode_subinsn_a_generated.c.inc" @@ -102,40 +104,77 @@ void decode_send_insn_to(Packet *packet, int start, int newloc) } } -/* Fill newvalue registers with the correct regno */ -static void +/* An HLX .new N-field names its producer register. */ +static int hlx_find_new_value_producer(Packet *packet, int consumer, + int lreg) +{ + for (int i = 0; i < packet->num_insns; i++) { + Insn *insn = &packet->insn[i]; + + if (i != consumer && GET_ATTRIB(insn->opcode, A_HLX) && + insn->dest_idx != -1 && insn->regno[insn->dest_idx] == lreg) { + return i; + } + } + return -1; +} + +/* Fill newvalue registers with the correct regno. */ +static bool decode_fill_newvalue_regno(Packet *packet) { int i, use_regidx, offset, def_idx, dst_idx; - for (i = 1; i < packet->num_insns; i++) { + for (i = 0; i < packet->num_insns; i++) { if (GET_ATTRIB(packet->insn[i].opcode, A_DOTNEWVALUE) && - !GET_ATTRIB(packet->insn[i].opcode, A_EXTENSION)) { + (!GET_ATTRIB(packet->insn[i].opcode, A_EXTENSION) || + GET_ATTRIB(packet->insn[i].opcode, A_HLX))) { - g_assert(packet->insn[i].new_read_idx != -1); + if (i == 0 && !GET_ATTRIB(packet->insn[i].opcode, A_HLX)) { + continue; + } + if (packet->insn[i].new_read_idx == -1) { + return false; + } use_regidx = packet->insn[i].new_read_idx; - /* - * What's encoded at the N-field is the offset to who's producing - * the value. Shift off the LSB which indicates odd/even register, - * then walk backwards and skip over the constant extenders. - */ - offset = packet->insn[i].regno[use_regidx] >> 1; - def_idx = i - offset; - for (int j = 0; j < offset; j++) { - if (GET_ATTRIB(packet->insn[i - j - 1].opcode, A_IT_EXTENDER)) { - def_idx--; + if (GET_ATTRIB(packet->insn[i].opcode, A_HLX)) { + def_idx = hlx_find_new_value_producer( + packet, i, packet->insn[i].regno[use_regidx]); + if (def_idx < 0) { + /* No producer means a 2KB zero store. */ + packet->insn[i].hlx_new_zero = true; + continue; + } + } else { + /* + * What's encoded at the N-field is the offset to who's + * producing the value. Shift off the LSB which indicates + * odd/even register, then walk backwards and skip over the + * constant extenders. + */ + offset = packet->insn[i].regno[use_regidx] >> 1; + if (offset == 0 || offset > i) { + return false; + } + def_idx = i - offset; + for (int j = 0; j < offset; j++) { + if (GET_ATTRIB(packet->insn[i - j - 1].opcode, + A_IT_EXTENDER)) { + def_idx--; + } } - } - /* - * Check for a badly encoded N-field which points to an instruction - * out-of-range - */ - g_assert(!((def_idx < 0) || (def_idx > (packet->num_insns - 1)))); + /* + * Check for a badly encoded N-field which points to an + * instruction out-of-range + */ + if (def_idx < 0 || packet->insn[def_idx].dest_idx == -1) { + return false; + } + } /* Now patch up the consumer with the register number */ - g_assert(packet->insn[def_idx].dest_idx != -1); dst_idx = packet->insn[def_idx].dest_idx; packet->insn[i].regno[use_regidx] = packet->insn[def_idx].regno[dst_idx]; @@ -147,6 +186,7 @@ decode_fill_newvalue_regno(Packet *packet) packet->insn[def_idx].slot; } } + return true; } /* Split CJ into a compare and a jump */ @@ -422,7 +462,12 @@ static void decode_remove_extenders(Packet *packet) static SlotMask get_valid_slots(const Packet *pkt, unsigned int slot) { if (GET_ATTRIB(pkt->insn[slot].opcode, A_EXTENSION)) { - return mmvec_ext_decode_find_iclass_slots(pkt->insn[slot].opcode); + if (GET_ATTRIB(pkt->insn[slot].opcode, A_HLX)) { + return hlx_ext_decode_find_iclass_slots( + pkt->insn[slot].opcode); + } + return mmvec_ext_decode_find_iclass_slots( + pkt->insn[slot].opcode); } else { return find_iclass_slots(pkt->insn[slot].opcode, pkt->insn[slot].iclass); @@ -491,7 +536,8 @@ decode_insns(DisasContext *ctx, Insn *insn, uint32_t encoding) { if (parse_bits(encoding) != 0) { if (decode_normal(ctx, encoding) || - decode_hvx(ctx, encoding)) { + decode_hvx(ctx, encoding) || + decode_hlx(ctx, encoding)) { insn->generate = opcode_genptr[insn->opcode]; insn->iclass = iclass_bits(encoding); return 1; @@ -614,8 +660,11 @@ decode_set_slot_number(Packet *pkt) } } - /* Fix the exceptions - mem insns to slot 0,1 */ + /* HLX instructions already have extension-assigned slots. */ for (i = pkt->num_insns - 1; i >= 0; i--) { + if (GET_ATTRIB(pkt->insn[i].opcode, A_HLX)) { + continue; + } /* First memory instruction always goes to slot 0 */ if ((GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE) || GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE_PACKET_RULES)) && @@ -671,8 +720,9 @@ decode_set_slot_number(Packet *pkt) } } /* Is slot0 empty and slot1 used? */ - if ((!slot0_found) && slot1_found) { - /* Then push it to slot0 */ + if ((!slot0_found) && slot1_found && + !GET_ATTRIB(pkt->insn[slot1_iidx].opcode, A_HLX)) { + /* Push it to slot 0. HLX loads remain in slot 1. */ pkt->insn[slot1_iidx].slot = 0; } @@ -688,6 +738,10 @@ bool opcode_supported(uint16_t opcode, const HexagonCPUDef *hex_def) if (hex_version == HEX_VER_ANY) { return true; } + /* HLX was added in V85. */ + if (GET_ATTRIB(opcode, A_HLX) && hex_version < HEX_VER_V85) { + return false; + } if ((info.introduced != HEX_VER_NONE && hex_version < info.introduced) || (info.removed != HEX_VER_NONE && hex_version >= info.removed)) { return false; @@ -773,9 +827,12 @@ int decode_packet(DisasContext *ctx, int max_words, const uint32_t *words, pkt->encod_pkt_size_in_bytes = words_read * 4; pkt->pkt_has_hvx = false; + pkt->pkt_has_hlx = false; for (i = 0; i < num_insns; i++) { pkt->pkt_has_hvx |= GET_ATTRIB(pkt->insn[i].opcode, A_CVI); + pkt->pkt_has_hlx |= + GET_ATTRIB(pkt->insn[i].opcode, A_HLX); } /* @@ -808,11 +865,16 @@ int decode_packet(DisasContext *ctx, int max_words, const uint32_t *words, return 0; } } - decode_fill_newvalue_regno(pkt); + if (!decode_fill_newvalue_regno(pkt)) { + return 0; + } if (pkt->pkt_has_hvx) { mmvec_ext_decode_checks(pkt, disas_only); } + if (pkt->pkt_has_hlx && !hlx_ext_decode_checks(pkt, disas_only)) { + return 0; + } if (!disas_only) { decode_shuffle_for_execution(pkt); diff --git a/target/hexagon/gen_dectree_import.c b/target/hexagon/gen_dectree_import.c index 87f20c14f1..8ed369f699 100644 --- a/target/hexagon/gen_dectree_import.c +++ b/target/hexagon/gen_dectree_import.c @@ -79,6 +79,7 @@ static const char * const opcode_enc_class_names[XX_LAST_ENC_CLASS] = { "SUBINSN_S2", "EXT_noext", "EXT_mmvec", + "EXT_hlx", }; static const char *get_opcode_enc(int opcode) @@ -94,11 +95,15 @@ static const char *get_opcode_enc_class(int opcode) { const char *tmp = opcode_encodings[opcode].encoding; if (tmp == NULL) { - const char *test = "V6_"; /* HVX */ + const char *test_hvx = "V6_"; + const char *test_hlx = "LX_"; const char *name = opcode_names[opcode]; - if (strncmp(name, test, strlen(test)) == 0) { + if (strncmp(name, test_hvx, strlen(test_hvx)) == 0) { return "EXT_mmvec"; } + if (strncmp(name, test_hlx, strlen(test_hlx)) == 0) { + return "EXT_hlx"; + } } return opcode_enc_class_names[opcode_encodings[opcode].enc_class]; } diff --git a/target/hexagon/gen_hlx_ext.py b/target/hexagon/gen_hlx_ext.py new file mode 100755 index 0000000000..d0385c3ac7 --- /dev/null +++ b/target/hexagon/gen_hlx_ext.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +## +## Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +## SPDX-License-Identifier: GPL-2.0-or-later +## + +"""Process HLX extension instruction definitions.""" + +import sys + +def main(): + """Copy preprocessed HLX instruction definitions.""" + input_file = sys.argv[1] + output_file = sys.argv[2] + + with open(input_file, "rt") as infile: + with open(output_file, "w") as outfile: + for line in infile: + # Skip preprocessor directives. + if not line.startswith("#"): + outfile.write(line) + +if __name__ == "__main__": + main() diff --git a/target/hexagon/gen_idef_parser_funcs.py b/target/hexagon/gen_idef_parser_funcs.py index 9293be4c39..3f5879ce19 100644 --- a/target/hexagon/gen_idef_parser_funcs.py +++ b/target/hexagon/gen_idef_parser_funcs.py @@ -62,6 +62,9 @@ def main(): for tag in hex_common.tags: if hex_common.tag_ignore(tag): continue + ## Skip instructions that explicitly request no idef-parser + if "A_NO_IDEF_PARSER" in hex_common.attribdict[tag]: + continue ## Skip the priv instructions if "A_PRIV" in hex_common.attribdict[tag]: continue diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py index 4305eda996..eb2e5f3a7e 100755 --- a/target/hexagon/gen_tcg_funcs.py +++ b/target/hexagon/gen_tcg_funcs.py @@ -118,6 +118,9 @@ def gen_tcg_func(f, tag, regs, imms): arguments = ", ".join(["ctx", "ctx->insn", "&ctx->pkt"] + declared) f.write(f" emit_{tag}({arguments});\n") + elif hex_common.is_hlx_inline_tag(tag): + hex_common.gen_hlx_inline(f, tag, regs) + elif hex_common.skip_qemu_helper(tag): if "A_FPOP" in hex_common.attribdict[tag]: f.write(" TCGv pkt_need_commit = ") diff --git a/target/hexagon/imported/allext.idef b/target/hexagon/imported/allext.idef index 9d4b23e9de..fa17b0de5d 100644 --- a/target/hexagon/imported/allext.idef +++ b/target/hexagon/imported/allext.idef @@ -23,3 +23,9 @@ #include "mmvec/ext.idef" #undef EXTNAME #undef EXTSTR + +#define EXTNAME hlx +#define EXTSTR "hlx" +#include "generated_hlx_ext.idef" +#undef EXTNAME +#undef EXTSTR diff --git a/target/hexagon/imported/allextenc.def b/target/hexagon/imported/allextenc.def index 39a3e93fad..c72807c4b1 100644 --- a/target/hexagon/imported/allextenc.def +++ b/target/hexagon/imported/allextenc.def @@ -18,3 +18,7 @@ #define EXTNAME mmvec #include "mmvec/encode_ext.def" #undef EXTNAME + +#define EXTNAME hlx +#include "hlx/encode_ext.def" +#undef EXTNAME diff --git a/target/hexagon/imported/hlx/encode_ext.def b/target/hexagon/imported/hlx/encode_ext.def new file mode 100644 index 0000000000..10d13db376 --- /dev/null +++ b/target/hexagon/imported/hlx/encode_ext.def @@ -0,0 +1,18 @@ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#define CONCAT(A,B) A##B +#define EXTEXTNAME(X) CONCAT(EXT_,X) +#define DEF_ENC(TAG,STR) DEF_EXT_ENC(TAG,EXTEXTNAME(EXTNAME),STR) + +DEF_ENC(LX_L16b_tmp,"1001100----sssssPP-10----000dddd") +DEF_ENC(LX_L16b_p_tmp,"1001100----sssssPP-10vv--100dddd") + +DEF_ENC(LX_S16b_new,"1010-1001--sssssPP000----000uuuu") +DEF_ENC(LX_S16b_p_new,"1010-1001--sssssPP000vv--100uuuu") + +#undef DEF_ENC +#undef EXTEXTNAME +#undef CONCAT diff --git a/target/hexagon/imported/hlx_ext.idef b/target/hexagon/imported/hlx_ext.idef new file mode 100644 index 0000000000..3685596e5e --- /dev/null +++ b/target/hexagon/imported/hlx_ext.idef @@ -0,0 +1,45 @@ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef EXTINSN +#define EXTINSN Q6INSN +#define __SELF_DEF_EXTINSN 1 +#endif + +#ifndef NO_HLX + +/* HLX vectors hold 1024 halfwords or 512 words. */ +#define HLX_FOR_EACH_CODE(CODE) \ +{ \ + fHIDE(int i;) \ + fLVFOREACH(1024, i) { \ + CODE ; \ + } \ +} + +EXTINSN(LX_L16b_tmp,"Ld16.tmp=mem(Rs32)",ATTRIBS(A_HLX,A_EXTENSION,A_NO_IDEF_PARSER,A_NOTE_HLX_MEM,A_HLX_MEM,A_VTCM_ALLBANK_ACCESS,A_LOAD,A_RESTRICT_SLOT1ONLY,A_HLX_TMP),"Aligned HLX load", +{ fEA_REG(RsV); fLOADMML(EA,LdV,false,false);}) + +EXTINSN(LX_L16b_p_tmp,"if (Pv4) Ld16.tmp=mem(Rs32)",ATTRIBS(A_HLX,A_EXTENSION,A_NO_IDEF_PARSER,A_NOTE_HLX_MEM,A_HLX_MEM,A_VTCM_ALLBANK_ACCESS,A_LOAD,A_RESTRICT_SLOT1ONLY,A_HLX_TMP,A_CONDEXEC),"Aligned HLX load", +{ fEA_REG(RsV); if(fLSBOLD(PvV)){fLOADMML(EA,LdV,false,false);} else {LOAD_CANCEL(EA);};}) + +EXTINSN(LX_S16b_new,"mem(Rs32)=Ku16.new",ATTRIBS(A_HLX,A_EXTENSION,A_NO_IDEF_PARSER,A_NOTE_HLX_MEM,A_HLX_MEM,A_VTCM_ALLBANK_ACCESS,A_STORE,A_HLX_NEW,A_DOTNEWVALUE,A_RESTRICT_SLOT0ONLY),"Aligned HLX new halfword store", +{ fEA_REG(RsV); fSTOREMML(EA,fNEWLREG(KuN),false,false);}) + +EXTINSN(LX_S16b_p_new,"if (Pv4) mem(Rs32)=Ku16.new",ATTRIBS(A_HLX,A_EXTENSION,A_NO_IDEF_PARSER,A_NOTE_HLX_MEM,A_HLX_MEM,A_VTCM_ALLBANK_ACCESS,A_STORE,A_HLX_NEW,A_DOTNEWVALUE,A_RESTRICT_SLOT0ONLY,A_CONDEXEC),"Aligned HLX new halfword store", +{ fEA_REG(RsV); if(fLSBOLD(PvV)){fSTOREMML(EA,fNEWLREG(KuN),false,false);} else {STORE_CANCEL(EA);};}) + +Q6INSN(LX_LL16b_tmp,"Ldd16.tmp=mem(Rs32)",ATTRIBS(A_MAPPING,A_HLX,A_NO_IDEF_PARSER),"Mapping from Ldd16.tmp=mem(Rs32) to LWd.tmp=mem(R)", +fASM_MAP("Ldd16.tmp=mem(Rs32)","LWd.tmp=mem(R)")) + +Q6INSN(LX_SS16b_new,"mem(Rs32)=Kuu16.new",ATTRIBS(A_MAPPING,A_HLX,A_NO_IDEF_PARSER),"Mapping from mem(Rs32)=Kuu16.new to mem(R)=KWnew", +fASM_MAP("mem(Rs32)=Kuu16.new","mem(R)=KWnew")) + +#endif /* NO_HLX */ + +#ifdef __SELF_DEF_EXTINSN +#undef EXTINSN +#undef __SELF_DEF_EXTINSN +#endif diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h index 5751c9ced9..cfd4072669 100644 --- a/target/hexagon/insn.h +++ b/target/hexagon/insn.h @@ -49,6 +49,7 @@ struct Instruction { */ bool extension_valid; /* Has a constant extender attached */ bool is_endloop; /* This is an end of loop */ + bool hlx_new_zero; /* HLX .new store without a producer. */ int32_t immed[IMMEDS_MAX]; /* immediate field */ }; diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build index f9e820286e..3bffbef6c1 100644 --- a/target/hexagon/meson.build +++ b/target/hexagon/meson.build @@ -22,6 +22,26 @@ gen_tcg_h = meson.current_source_dir() / 'gen_tcg.h' gen_tcg_hvx_h = meson.current_source_dir() / 'gen_tcg_hvx.h' gen_tcg_sys_h = meson.current_source_dir() / 'gen_tcg_sys.h' idef_parser_dir = meson.current_source_dir() / 'idef-parser' +imported_dir = meson.current_source_dir() / 'imported' + +# +# Create the HLX ext.idef. +# +preprocessed_hlx_ext = custom_target( + 'hlx_ext.preprocessed.idef', + output: 'hlx_ext.preprocessed.idef', + input: imported_dir / 'hlx_ext.idef', + command: meson.get_compiler('c').cmd_array() + + ['-x', 'c', '-E', '-o', '@OUTPUT@', '@INPUT@'] +) +generated_hlx_ext = custom_target( + 'generated_hlx_ext.idef', + output: 'generated_hlx_ext.idef', + input: preprocessed_hlx_ext, + depend_files: [hex_common_py], + command: [python, files('gen_hlx_ext.py'), '@INPUT@', '@OUTPUT@'], +) +hexagon_ss.add(generated_hlx_ext) # # Step 1 @@ -30,6 +50,7 @@ idef_parser_dir = meson.current_source_dir() / 'idef-parser' gen_semantics = executable( 'gen_semantics', 'gen_semantics.c', + sources: generated_hlx_ext, native: true, build_by_default: false) semantics_generated = custom_target( @@ -123,6 +144,15 @@ hvx_decode_generated = custom_target( ) hexagon_ss.add(hvx_decode_generated) +hlx_decode_generated = custom_target( + 'hlx_decode_generated', + output: 'hlx_decode_generated', + depends: [iset_py, semantics_generated], + env: {'PYTHONPATH': meson.current_build_dir()}, + command: [python, files('gen_decodetree.py'), semantics_generated, 'EXT_hlx', '@OUTPUT@'], +) +hexagon_ss.add(hlx_decode_generated) + subinsn_a_decode_generated = custom_target( 'subinsn_a_decode_generated', output: 'subinsn_a_decode_generated', @@ -190,6 +220,15 @@ decode_hvx_generated = custom_target( ) hexagon_ss.add(decode_hvx_generated) +decode_hlx_generated = custom_target( + 'decode_hlx_generated.c.inc', + output: 'decode_hlx_generated.c.inc', + input: hlx_decode_generated, + env: {'PYTHONPATH': meson.current_build_dir()}, + command: [python, files(decodetree_py), hlx_decode_generated, '--static-decode=decode_hlx', '-o', '@OUTPUT@'], +) +hexagon_ss.add(decode_hlx_generated) + decode_subinsn_a_generated = custom_target( 'decode_subinsn_a_generated.c.inc', output: 'decode_subinsn_a_generated.c.inc', diff --git a/target/hexagon/opcodes.h b/target/hexagon/opcodes.h index 0ee11bd445..d6bc2de21c 100644 --- a/target/hexagon/opcodes.h +++ b/target/hexagon/opcodes.h @@ -35,6 +35,7 @@ typedef enum { SUBINSN_S2, EXT_noext, EXT_mmvec, + EXT_hlx, XX_LAST_ENC_CLASS } EncClass; diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index 41b7d3b0fb..ce0f215230 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -1264,6 +1264,15 @@ static void gen_commit_hvx(DisasContext *ctx) } } +/* A .new store without a producer reads zeroed future_LRegs. */ +static void gen_hlx_new_zero(Insn *insn) +{ + int rnum = insn->regno[insn->new_read_idx]; + + tcg_gen_gvec_dup_imm(MO_64, offsetof(CPUHexagonState, future_LRegs[rnum]), + sizeof(HLXVector), sizeof(HLXVector), 0); +} + static void gen_commit_hlx(DisasContext *ctx) { int i; @@ -1490,6 +1499,9 @@ static void decode_and_translate_packet(CPUHexagonState *env, DisasContext *ctx) continue; } ctx->insn = insn; + if (insn->hlx_new_zero) { + gen_hlx_new_zero(insn); + } if (GET_ATTRIB(insn->opcode, A_HLX) && trace_event_get_state_backends( TRACE_HEXAGON_HLX_OP)) { -- 2.43.0
