During decoding, check that the opcode is supported in the current
Hexagon CPU definition

Co-authored-by: Matheus Tavares Bernardino <[email protected]>
Co-authored-by: Brian Cain <[email protected]>
Signed-off-by: Taylor Simpson <[email protected]>
---
 target/hexagon/decode.h |  2 ++
 target/hexagon/decode.c | 27 +++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/target/hexagon/decode.h b/target/hexagon/decode.h
index 3f3012b978..d4b049961e 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, const HexagonCPUDef *hex_def);
+
 #endif
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index dbc9c630e8..b8a1cd5b12 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -647,6 +647,22 @@ decode_set_slot_number(Packet *pkt)
     return has_valid_slot_assignment(pkt);
 }
 
+bool opcode_supported(uint16_t opcode, const HexagonCPUDef *hex_def)
+{
+    HexagonVersion hex_version = hex_def->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 +762,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 definition
+     * If not, return decode error
+     */
+    for (i = 0; i < num_insns; i++) {
+        if (!opcode_supported(pkt->insn[i].opcode, ctx->hex_def)) {
+            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


Reply via email to