During decoding, check that the opcode is supported in the current
Hexagon CPU version
Co-authored-by: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com>
Co-authored-by: Brian Cain <brian.cain@oss.qualcomm.com>
Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
---
target/hexagon/decode.h | 2 ++
target/hexagon/decode.c | 26 ++++++++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/target/hexagon/decode.h b/target/hexagon/decode.h
index 3f3012b978..44fea2b37c 100644
--- a/target/hexagon/decode.h
+++ b/target/hexagon/decode.h
@@ -30,4 +30,6 @@ void decode_send_insn_to(Packet *packet, int start, int newloc);
int decode_packet(DisasContext *ctx, int max_words, const uint32_t *words,
Packet *pkt, bool disas_only);
+bool opcode_supported(uint16_t opcode, HexagonVersion hex_version);
+
#endif
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index dbc9c630e8..b02a402dfa 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -647,6 +647,21 @@ decode_set_slot_number(Packet *pkt)
return has_valid_slot_assignment(pkt);
}
+bool opcode_supported(uint16_t opcode, HexagonVersion hex_version)
+{
+#include "tag_rev_info.c.inc"
+
+ struct tag_rev_info info = tag_rev_info[opcode];
+ if (hex_version == HEX_VER_ANY) {
+ return true;
+ }
+ if ((info.introduced != HEX_VER_NONE && hex_version < info.introduced) ||
+ (info.removed != HEX_VER_NONE && hex_version >= info.removed)) {
+ return false;
+ }
+ return true;
+}
+
/*
* Check for GPR write conflicts in the packet.
* A conflict exists when a register is written by more than one instruction
@@ -746,6 +761,17 @@ int decode_packet(DisasContext *ctx, int max_words, const uint32_t *words,
/* Ran out of words! */
return 0;
}
+
+ /*
+ * Check that all the opcodes are supported in this Hexagon version
+ * If not, return decode error
+ */
+ for (i = 0; i < num_insns; i++) {
+ if (!opcode_supported(pkt->insn[i].opcode, ctx->hex_version)) {
+ return 0;
+ }
+ }
+
pkt->encod_pkt_size_in_bytes = words_read * 4;
pkt->pkt_has_hvx = false;
for (i = 0; i < num_insns; i++) {
--
2.43.0