@samitouri / QOSamiQemu / commits / 0177efb9b7

target/hexagon: accept valid packets rejected by check

has_valid_slot_assignment() rejected any packet with two instructions assigned to the same slot. That is too strict. When a memory instruction is encoded before a slot-flexible instruction in a packet, the descending slot assignment places the memory op in slot 1 and the other in slot 0, then the "mem insns to slot 0" fixup moves the memory op to slot 0 as well, leaving both in slot 0. Such a packet is valid and executes correctly, but the uniqueness test flagged it as HEX_CAUSE_INVALID_PACKET, raising SIGILL in linux-user and a precise exception in system mode. For example this packet, with the load encoded first, was wrongly rejected: { r6 = memw(r3+#-4) r7 = #0x4ae6 } Replace the uniqueness test with a slot-exhaustion check: walk the instructions in encoding order handing out slots in strictly decreasing order and fail only if an instruction has no valid slot at or below the running slot. This accepts packets that legally share a slot while still rejecting genuinely unassignable packets, such as a memory instruction grouped with a duplex, or a load followed by an instruction that requires a high slot. Reviewed-by: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Brian Cain committed Jul 24, 2026 at 10:18 UTC 0177efb9b75891717c45667e20efe6d6e64f7c82
1 file changed +22 -8
target/hexagon/decode.c
+22 -8
@@ -549,21 +549,35 @@ static bool decode_parsebits_is_loopend(uint32_t encoding32)
549 return bits == 0x2;
550 }
551
552 +/*
553 + * Check that the packet's instructions can be grouped into slots: walk them
554 + * in encoding order handing out slots in strictly decreasing order, and fail
555 + * if an instruction has no valid slot at or below the running slot. Two
556 + * instructions may legally share a slot, so this does not require unique
557 + * slots, only that every instruction fits.
558 + */
559 static bool has_valid_slot_assignment(Packet *pkt)
560 {
554 - int used_slots = 0;
555 - for (int i = 0; i < pkt->num_insns; i++) {
556 - int slot_mask;
557 - Insn *insn = &pkt->insn[i];
558 - if (decode_opcode_ends_loop(insn->opcode)) {
561 + int i;
562 + int slot = 3;
563 +
564 + for (i = 0; i < pkt->num_insns; i++) {
565 + SlotMask valid_slots;
566 + if (decode_opcode_ends_loop(pkt->insn[i].opcode)) {
567 /* We overload slot 0 for endloop. */
568 continue;
569 }
562 - slot_mask = 1 << insn->slot;
563 - if (used_slots & slot_mask) {
570 + if (slot < 0) {
571 return false;
572 }
566 - used_slots |= slot_mask;
573 + valid_slots = get_valid_slots(pkt, i);
574 + while (!(valid_slots & (1 << slot))) {
575 + if (slot <= 0) {
576 + return false;
577 + }
578 + slot--;
579 + }
580 + slot--;
581 }
582 return true;
583 }