Skip to content

[A64] Remap on the effective address and shorten guest addressing - #247

Open
xenios-jp wants to merge 1 commit into
has207:edgefrom
xenios-jp:pr/5-addressing
Open

[A64] Remap on the effective address and shorten guest addressing#247
xenios-jp wants to merge 1 commit into
has207:edgefrom
xenios-jp:pr/5-addressing

Conversation

@xenios-jp

Copy link
Copy Markdown

On hosts whose allocation granularity exceeds 4 KiB the 0xE0000000 view
cannot be mapped at its true offset (it aliases the 0xC0000000 view
4 KiB further in, closer than one host page), so the CPU side adds
0x1000 to guest addresses at or above 0xE0000000. LOAD_OFFSET and
STORE_OFFSET applied that remap to the base register before adding the
displacement, so a base just below the boundary whose displacement
carried it above was not remapped, and a base above it with a negative
displacement was remapped when it should not have been: the same guest
address resolved two different ways depending on how constant folding
had split it. ComputeMemoryAddressOffset now forms the 32-bit effective
address first (base plus displacement in W registers, so the wrap at
bit 31 is preserved) and decides the remap on that, which is what the
x64 backend's ComputeMemoryAddressOffset does.

Addressing shortcuts, all on the same helpers:

  • Register guest addresses on hosts without the remap index guest
    memory directly as [membase, Wsrc, UXTW]; the addressing mode's
    zero-extension replaces the mov that ComputeMemoryAddress emitted.
    The offset forms take the direct form only for a zero constant
    displacement, since a nonzero one must be added in W first.
  • The remap itself is a predicted-not-taken branch (lsr, cmp, b_near,
    add) rather than mov/cmp/add/csel, keeping it off the load's
    dependency chain. TryInlinePPCGprLrSaveRestore in a64_emitter.cc still
    carries its own csel form of the remap; routing it through
    ApplyPhysicalRemapW0 is left for a follow-up.
  • The inline MMIO range test is one shift and a 9-bit compare
    (EmitMmioRangeTest: lsr, cmp, b_near) instead of two materialised
    bounds and two compares.
  • STORE_V128 resolves its source into a Q register before forming the
    address. ZERO_EXTEND_I64_I32 with dest == src emits nothing: I32
    values are only produced through W forms, whose upper half is
    already zero (TRUNCATE_I32_I64 is not elidable for the mirror
    reason).
  • EmitPartialVectorStore uses the near branch forms; every label is
    bound within the helper. This is an encoding-only change and is not
    covered by the corpus.

Evidence: emitted size (corpus replay -356,444 host bytes from the
zero-extend elision) and the PPC corpus gate 169,044/169,044 passing.
The remap branch and the MMIO test change are unmeasured at runtime.

@codacy-production

codacy-production Bot commented Aug 27, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics -30 complexity · -74 duplication

Metric Results
Complexity -30
Duplication -74

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

On hosts whose allocation granularity exceeds 4 KiB the 0xE0000000 view
cannot be mapped at its true offset (it aliases the 0xC0000000 view
4 KiB further in, closer than one host page), so the CPU side adds
0x1000 to guest addresses at or above 0xE0000000. LOAD_OFFSET and
STORE_OFFSET applied that remap to the base register before adding the
displacement, so a base just below the boundary whose displacement
carried it above was not remapped, and a base above it with a negative
displacement was remapped when it should not have been: the same guest
address resolved two different ways depending on how constant folding
had split it. ComputeMemoryAddressOffset now forms the 32-bit effective
address first (base plus displacement in W registers, so the wrap at
bit 31 is preserved) and decides the remap on that, which is what the
x64 backend's ComputeMemoryAddressOffset does.

Addressing shortcuts, all on the same helpers:
- Register guest addresses on hosts without the remap index guest
  memory directly as [membase, Wsrc, UXTW]; the addressing mode's
  zero-extension replaces the mov that ComputeMemoryAddress emitted.
  The offset forms take the direct form only for a zero constant
  displacement, since a nonzero one must be added in W first.
- The remap itself is a predicted-not-taken branch (lsr, cmp, b_near,
  add) rather than mov/cmp/add/csel, keeping it off the load's
  dependency chain. TryInlinePPCGprLrSaveRestore in a64_emitter.cc still
  carries its own csel form of the remap; routing it through
  ApplyPhysicalRemapW0 is left for a follow-up.
- The inline MMIO range test is one shift and a 9-bit compare
  (EmitMmioRangeTest: lsr, cmp, b_near) instead of two materialised
  bounds and two compares.
- STORE_V128 resolves its source into a Q register before forming the
  address. ZERO_EXTEND_I64_I32 with dest == src emits nothing: I32
  values are only produced through W forms, whose upper half is
  already zero (TRUNCATE_I32_I64 is not elidable for the mirror
  reason).
- EmitPartialVectorStore uses the near branch forms; every label is
  bound within the helper. This is an encoding-only change and is not
  covered by the corpus.

Evidence: emitted size (corpus replay -356,444 host bytes from the
zero-extend elision) and the PPC corpus gate 169,044/169,044 passing.
The remap branch and the MMIO test change are unmeasured at runtime.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant