Repository navigation
Phase 4: Thumb-2 LDR/STR with negative offsets - #5
Merged
Merged
Conversation
arm_ldr_imm and arm_str_imm picked the 16-bit LDR/STR (immediate) encoding for low registers whenever imm < 128 and imm was a multiple of 4, without checking imm >= 0. That encoding has an unsigned word offset (0-124), so a negative offset was emitted as a large positive one: ARM_STR_IMM (code, r1, r7, -4) became "str r1, [r7, dotnet#124]". The interp-to-native trampoline saves its CallContext pointer and target address that way, so every P/Invoke or icall from interpreted code wrote into its caller's stack frame and read back uninitialised slots. Under the interpreter the Mono main thread ended up with SP = 0 and the core locked up in a double fault. Require imm >= 0 for the 16-bit form, as the byte and halfword variants already do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NevynUK
added a commit
to WildernessLabs/Meadow.OS
that referenced
this pull request
Oct 14, 2026
WildernessLabs/runtime#5: the 32-bit Thumb-2 LDR/STR encoding for negative offsets, which fixes the interpreter (--interp) crash. To be moved to the MergeManagedCode merge commit once that pull request is merged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NevynUK
added a commit
to WildernessLabs/Meadow.OS
that referenced
this pull request
Oct 14, 2026
WildernessLabs/runtime#5 is merged; the tree is the same as the Phase4b commit pinned before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
arm_ldr_immandarm_str_imminthumb-codegen.hchose the 16-bit LDR/STR (immediate) encoding for low registers wheneverimm < 128andimm % 4 == 0, but never checkedimm >= 0. That encoding takes only an unsigned word offset (0-124), so negative offsets were emitted as large positive ones. The byte and halfword variants already have the check; this adds it to the word variants.How it showed up
Under
--interp, a GC stress app on a Meadow F7 (CCM) locked the core in a double fault: the Mono main thread's SP had become 0. I dumped the interp-to-native trampoline from SDRAM and disassembled it:On every P/Invoke and icall from interpreted code, the trampoline overwrote its caller's frame (saved registers and frame pointers) and called through uninitialised slots. JIT-compiled code doesn't use this trampoline, but any negative-offset low-register LDR/STR the JIT emitted was affected in the same way.
Testing (CCM, Meadow.OS Phase4 / WildernessLabs/Meadow.OS#697)
--interp: 5 passes in 229 s, no failures. Before the fix, the first test never completed.--debug), as a regression check: 30/30 tests pass in 121 s.🤖 Generated with Claude Code