Xtensa: gate ESP32-S3 and HIFI3 ops behind CS_MODE_XTENSA_ESP32S3#2979
Open
germiBest wants to merge 1 commit into
Open
Xtensa: gate ESP32-S3 and HIFI3 ops behind CS_MODE_XTENSA_ESP32S3#2979germiBest wants to merge 1 commit into
germiBest wants to merge 1 commit into
Conversation
fd7af34 to
84545f4
Compare
Rot127
reviewed
Jun 28, 2026
Rot127
approved these changes
Jun 28, 2026
Collaborator
|
@b1llow Please take a look. |
Collaborator
|
@germiBest Please fix the existing tests |
Author
|
working on it, my bad, lost some changes on local |
The Xtensa disassembler enabled the ESP32-S3 SIMD/AI (ee.*) and HiFi3 ops for every target because the subtarget feature gates were stubbed to return true (Xtensa_getFeatureBits and hasDensity/hasESP32S3Ops/hasHIFI3). As a result, on a non-ESP32-S3 Xtensa config any instruction with op0=0xE/0xF was matched as a 4-byte ee.* op, so a base-ISA byte stream desynced. Make Xtensa_getFeatureBits map the mode to a feature set (mirroring the SystemZ precedent), thread MI->csh->mode into the three has*Ops gates, and add an opt-in CS_MODE_XTENSA_ESP32S3. Base/esp32/esp32s2/esp8266 no longer emit ESP32-S3 ops; CS_MODE_XTENSA_ESP32S3 preserves them. Concrete instance of issue capstone-engine#1992. The saved auto-sync patch hashes are updated so the fix survives the next LLVM re-sync. Adds tests/MC/Xtensa/esp32s3.s.yaml.
84545f4 to
8d4ab6e
Compare
Author
|
tests are resolved |
wargio
approved these changes
Jun 29, 2026
wargio
left a comment
Collaborator
There was a problem hiding this comment.
It's a quite reasonable patch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Your checklist for this pull request
Detailed description
The Xtensa disassembler enabled the ESP32-S3 SIMD/AI (
ee.*) and HiFi3 ops for every target,because the subtarget feature gates in
arch/Xtensa/XtensaDisassembler.cwere stubbed to alwaysreturn true:
Xtensa_getFeatureBits()was// we support everything; return true;, andhasDensity()/hasESP32S3Ops()/hasHIFI3()were hardcodedreturn true;.Because op0
0xE/0xFalways has bit 3 set, on a non-ESP32-S3 Xtensa config any such byte wasmatched as a 4-byte
ee.*op via the ESP32-S3 32-bit table, so a base-ISA byte stream over-read byone byte and desynced everything after it. LLVM itself gates these ops behind a real subtarget
feature and only decodes them for an esp32s3 target; capstone's auto-translated port dropped that
gating.
Found on real MediaTek MT7961 Wi-Fi firmware (Tensilica Xtensa LX with a vendor TIE coprocessor;
those op0
0xE/0xFops are 3-byte vendor ops, not ESP32-S3ee.*).This PR:
Xtensa_getFeatureBits(mode, feature)map the mode to a feature set, mirroring the SystemZprecedent in
arch/SystemZ/SystemZDisassemblerExtension.c.ESP32S3OpsandHIFI3are enabledonly when the new
CS_MODE_XTENSA_ESP32S3is set;Densitystays on (base Tensilica default);anything else keeps the allow-all fallback.
MI->csh->modeintohasDensity()/hasESP32S3Ops()/hasHIFI3()and their callsites in
getInstruction(). The generatedcheckDecoderPredicatealready reads the mode, so thissingle change gates both the outer probe and the inner table predicate, and
readInstruction32isno longer entered for op0
0xE/0xFin non-S3 modes.CS_MODE_XTENSA_ESP32S3, wired throughcs.c(valid-mode mask),cstool, and thepython binding.
suite/auto-syncsaved patch hashes for the four functions so the gated bodies survivethe next LLVM re-sync. The stubs had been re-introduced by auto-sync, which is why this regressed
silently; without this the fix would be reverted on the next sync.
This is a concrete instance of #1992 (features enabled by default produce wrong disassembly on
targets that do not have them).
Behavior change worth calling out: ESP32-S3 SIMD/AI and HiFi3 ops become opt-in via
CS_MODE_XTENSA_ESP32S3. Callers that previously receivedee.*without passing a mode will need topass the new mode. That previous behavior was the bug, since it mis-decoded every non-ESP32-S3 Xtensa
config.
Files changed:
arch/Xtensa/XtensaDisassembler.c,cs.c,include/capstone/capstone.h,cstool/cstool.c,bindings/python/capstone/__init__.py,suite/cstest/include/test_mapping.h,suite/auto-sync/src/autosync/cpptranslator/saved_patches.json, and newtests/MC/Xtensa/esp32s3.s.yaml.Test plan
Before/after with
cstoolon real MT7961 bytes9e3e0940and3e194548:Base and density ops still decode in every mode (no regression):
Added
tests/MC/Xtensa/esp32s3.s.yaml: 2 positive cases (both vectors decodeee.vmulas.u16.accx.ld.ip.qup, size 4, underCS_MODE_XTENSA_ESP32S3) and 4 negative cases (bothvectors expect a decode failure under
CS_MODE_XTENSA_ESP32and baseCS_MODE_LITTLE_ENDIAN). Thesefollow the existing Xtensa test convention under
tests/MC/Xtensa/(this tree has nosuite/cstest/issues.cs; all Xtensa disassembly tests are MC YAML files there).Full run:
tests/MC/Xtensa/105/105 pass (99 pre-existing + 6 new),tests/details/xtensa.yaml3/3 pass.
Closing issues
No existing issue tracks this specific Xtensa decode bug. It is a concrete instance of the umbrella
issue #1992, which this PR does not fully close.