Skip to content

harm: ADR/ADRP - #43

Merged
monoid merged 6 commits into
masterfrom
feat/adrp
Dec 7, 2025
Merged

harm: ADR/ADRP#43
monoid merged 6 commits into
masterfrom
feat/adrp

Conversation

@monoid

@monoidmonoid commented Nov 22, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added ADR and ADRP support for AArch64 PC-relative address generation.
    • New public constructors to build ADR/ADRP operands, including wider-offset input support (i64).
  • Tests

    • Added unit tests covering encoding and overflow/edge cases for ADR/ADRP offsets.

✏️ Tip: You can customize this high-level summary in your review settings.

@monoidmonoid self-assigned this Nov 22, 2025
@monoidmonoid added enhancement New feature or request harm The `harm` dynamic assembler labels Nov 22, 2025
@coderabbitai

coderabbitaiBot commented Nov 22, 2025

Copy link
Copy Markdown

Walkthrough

Adds a new public pcreladdr module implementing ADR/ADRP pc‑relative address instructions (types, constructors, encoders, tests) and extends SBitValue with TryFrom<i64> to support i64 offset conversion.

Changes

Cohort / File(s)Summary
New pcreladdr instruction module
harm/src/instructions/dpimm.rs, harm/src/instructions/dpimm/pcreladdr.rs
Adds pub mod pcreladdr; and pub use self::pcreladdr::*; and implements ADR/ADRP: AdrOffset/AdrpOffset aliases, Adr/Adrp generic structs, MakeAdr/MakeAdrp traits and impls, adr()/adrp() constructors, LO_BITS/LO_BITS_MASK, RawInstruction::to_code encoders computing immlo/immhi, plus unit tests covering offsets and edge cases.
SBitValue i64 conversion
harm/src/bits.rs
Adds impl TryFrom<i64> for SBitValue<const SIGNIFICANT_BITS: u32, const ALIGN: u32> delegating to SBitValue::new_i64, enabling i64 → SBitValue conversions used by Adrp constructors.

Sequence Diagram(s)

sequenceDiagram
participant Caller as Caller (user code)
participant Ctor as adr()/adrp()
participant Make as MakeAdr/MakeAdrp impl
participant Instr as Adr/Adrp instance
participant Encoder as RawInstruction::to_code
participant Emit as ADR(_only)_pcreladdr
Caller->>Ctor: call adr(rd, offset) or adrp(rd, offset)
Ctor->>Make: offset conversion (i32 / i64) via TryFrom / new_i64
Make->>Instr: construct Adr/Adrp with rd and validated offset
Instr->>Encoder: to_code()
Encoder->>Encoder: immlo = bits & LO_BITS_MASK
Encoder->>Encoder: immhi = bits >> LO_BITS
Encoder->>Emit: ADR_only_pcreladdr(immlo, immhi, rd) / ADRP_only_pcreladdr(...)
Emit-->>Encoder: InstructionCode
Encoder-->>Caller: InstructionCode
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify LO_BITS / LO_BITS_MASK and the shift/mask math vs. ARMv8 spec (pcreladdr encoding).
  • Check TryFrom<i64> correctness and sign/align handling in SBitValue::new_i64.
  • Review trait impls (MakeAdr/MakeAdrp) and adr/adrp generic signatures for ergonomic/compile-time behavior.
  • Inspect unit tests for comprehensive edge-case coverage (alignment, overflow, sign-extension).

Possibly related PRs

Poem

🐰 I nibble bits and split them fine,
ADR and ADRP hop in line.
Low bits tucked and highs take flight,
I stitch the word and send it right. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 20.00% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'harm: ADR/ADRP' directly and specifically summarizes the main changes, which introduce ADR and ADRP instruction support to the harm crate.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/adrp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
harm/src/instructions/dpimm/pcreladdr.rs (5)

19-29: Add documentation comments for public structs.

The public Adr and Adrp structs lack documentation. Consider adding doc comments explaining their purpose, the instruction encoding they represent, and usage examples.

Example:

+/// ADR (Address to Register) instruction.+///+/// Loads a PC-relative address with a byte offset into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adr<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}
+/// ADRP (Address of 4KB Page to Register) instruction.+///+/// Loads a PC-relative address of a 4KB page into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adrp<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}

31-57: Consider simplifying the trait-based construction pattern.

The MakeAdr and MakeAdrp traits currently have only one implementation each. Unless additional implementations are planned, consider using direct constructors to reduce complexity.

If you anticipate adding more implementations (e.g., for different offset representations), this pattern makes sense for future extensibility. Otherwise, the traits add indirection without immediate benefit.


59-77: Add documentation comments for public constructor functions.

The adr and adrp functions are the primary public API but lack documentation. Add doc comments explaining parameters, usage, and return types.

Example:

+/// Constructs an ADR (Address to Register) instruction.+///+/// # Arguments+/// * `rd` - Destination register+/// * `offset` - PC-relative byte offset+///+/// # Example+/// ```ignore+/// let instr = adr(X0, AdrOffset::new(0x1000).unwrap());+/// ```
pub fn adr<OffsetIn>(
rd: impl IntoReg<RegOrZero64>,
offset: OffsetIn,
) -> <Adr<AdrOffset> as MakeAdr<OffsetIn>>::Outcome

79-80: Consider adding a comment explaining the encoding split.

The constants define how the offset is split for instruction encoding. A brief comment would improve maintainability.

Example:

+// ADR/ADRP encoding splits the 19-bit offset into:+// immlo (bits 0-1) and immhi (bits 2-18)
const LO_BITS: u32 = 2;
const LO_BITS_MASK: u32 = (1 << LO_BITS) - 1;

98-137: Expand test coverage to include edge cases.

The current tests only cover 4 specific values. Consider adding tests for:

  • Minimum valid offset (e.g., -262144 for ADR, -262144 << 12 for ADRP)
  • Maximum valid offset (e.g., 262143 for ADR, 262143 << 12 for ADRP)
  • Zero offset
  • Boundary values that test the 19-bit signed range
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4112605 and f000acb.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🪛 GitHub Actions: Rust
harm/src/instructions/dpimm/pcreladdr.rs

[error] 10-10: Rustfmt formatting check failed (imports order). Run 'cargo fmt' to fix formatting in this file.


[error] 99-99: Rustfmt formatting check failed (test module formatting). Run 'cargo fmt' to fix formatting in this file.

🔇 Additional comments (3)
harm/src/instructions/dpimm.rs (1)

8-11: LGTM! Module integration follows established pattern.

The new pcreladdr module is correctly declared and re-exported, following the same pattern as existing modules (log_imm, movewide).

harm/src/instructions/dpimm/pcreladdr.rs (2)

82-96: LGTM! Encoding implementations are correct.

The RawInstruction implementations correctly split the offset into immlo (low 2 bits) and immhi (high bits) for ARM64 ADR/ADRP instruction encoding.


116-134: Verify and document expected instruction codes in tests.

Multiple TODO comments indicate the test values haven't been verified against a reference. Consider:

  1. Verifying the expected instruction codes against the ARM Architecture Reference Manual or using a reference assembler
  2. Adding comments documenting how the expected values were derived
  3. Removing the TODO comments once verified

Do you want me to help generate a verification script to compare these encodings against a reference implementation or documentation?

Comment threadharm/src/instructions/dpimm/pcreladdr.rs
Comment threadharm/src/instructions/dpimm/pcreladdr.rs

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

34-60: Consider simplifying the constructor pattern if not required by codebase conventions.

The trait-based constructor pattern (MakeAdr/MakeAdrp with associated types) adds complexity compared to direct impl blocks with new() methods. Unless this pattern is used consistently across the codebase for extensibility, consider a simpler approach:

implAdr<AdrOffset>{pubfnnew(rd:RegOrZero64,offset:AdrOffset) -> Self{Self{reg: rd, offset }}}

However, if this pattern enables future support for multiple offset input types (which the generic OffsetIn parameter suggests), the current design is reasonable.


114-139: Verify and document the expected instruction encodings.

Three tests contain TODO comments about checking correctness of the hardcoded assertion values. Consider verifying these encodings against the ARM Architecture Reference Manual or using an assembler/disassembler to confirm, then document why each expected value is correct (similar to how test_adr_m4 is clear about encoding -4).

You can verify the encodings by:

  1. Cross-referencing with ARM documentation for ADR/ADRP encoding format
  2. Using an ARM assembler/disassembler to generate and verify the instruction bytes
  3. Adding comments explaining the bit layout for each test case
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f000acb and ff98029.

📒 Files selected for processing (1)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

62-80: LGTM on public constructors.

The generic constructor functions provide a flexible API with proper type conversions via IntoReg<RegOrZero64> and trait-based constraints.


82-99: Correct bit manipulation for instruction encoding.

The immediate splitting logic correctly extracts immlo (low 2 bits) and immhi (high bits) for ADR/ADRP encoding. The minor code duplication between Adr and Adrp implementations is acceptable given the simplicity.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff98029 and 592c05a.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm.rs (1)

8-11: Consistent wiring of new pcreladdr module

The new submodule and re-export mirror the existing log_imm/movewide pattern and cleanly expose ADR/ADRP under dpimm. No issues here.

harm/src/instructions/dpimm/pcreladdr.rs (1)

82-99: ADR/ADRP immediate encoding verified correct per ARM AArch64 specification

The immediate splitting into 2-bit immlo and 19-bit immhi fields is correct and properly placed at instruction bits [30:29] and [23:5] respectively. Verified test encodings against ARM specification:

  • ADR offset -4, Rd=X29 → 0x103ffffd ✓
  • ADR offset 0x12345, Rd=X28 → 0x30091a3c ✓
  • ADRP offset -4<<12, Rd=X27 → 0x903ffffb ✓

All encodings match ARM AArch64 ADR/ADRP specification.

Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
@coderabbitai

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)

38-84: Trait‑based adr/adrp constructors are type‑safe and future‑proof

The MakeAdr/MakeAdrp traits plus the generic adr/adrp helpers cleanly separate construction from encoding and ensure all range/alignment checks go through SBitValue::try_from (i32 for ADR, i64 for ADRP). This yields a nice API where adr/adrp work both with pre‑validated offsets and raw integers without duplicating logic.

If you ever want adr to accept i64 offsets as well (for symmetry with adrp and the new TryFrom<i64> on SBitValue), adding an impl MakeAdr<i64> for Adr<AdrOffset> that calls offset.try_into() would be a straightforward extension.

Also applies to: 86-104

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc1f706 and 996e9f7.

📒 Files selected for processing (2)
  • harm/src/bits.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
harm/src/bits.rs (1)
harm/src/instructions/arith.rs (2)
  • try_from (123-125)
  • try_from (197-206)
harm/src/instructions/dpimm/pcreladdr.rs (1)
harm/src/bits.rs (2)
  • bits (83-85)
  • bits (213-215)
🔇 Additional comments (3)
harm/src/bits.rs (1)

144-153: TryFrom<i64> for SBitValue cleanly reuses existing validation

Delegating TryFrom<i64> to new_i64 keeps all range/alignment checks in one place and matches how AdrpOffset is consumed in pcreladdr.rs. With the existing new_i64 tests, this addition looks correct and low‑risk.

harm/src/instructions/dpimm/pcreladdr.rs (2)

19-36: Offset type aliases correctly model ADR/ADRP immediates

Using AdrOffset = SBitValue<21> for ADR and AdrpOffset = SBitValue<21, 12> for ADRP matches the 21‑bit signed PC‑relative immediate, with ALIGN = 12 enforcing 4 KiB page alignment for ADRP while still letting callers think in byte offsets. The accompanying doc comment on AdrpOffset makes the “real address offset” semantics explicit.


106-123: Encoding and tests correctly split and validate 21‑bit PC‑relative offsets

The encoding logic

  • uses LO_BITS = 2,
  • derives immlo = offset.bits() & LO_BITS_MASK and immhi = offset.bits() >> LO_BITS,

which is exactly the ADR/ADRP layout (low 2 bits in immlo, high 19 in immhi). For AdrpOffset, bits() already returns the shifted page offset, so reusing the same split is correct for both instructions.

The PCRELADDR_CASES table plus the test_cases! macro exercise:

  • ADR with negative and positive offsets,
  • ADRP with small and near‑limit positive/negative offsets,
  • both “pre‑validated” (SBitValue::new/new_i64) and “fallible” (adr(..., i32), adrp(..., i64)) constructors.

Together with the GNU as–verified constants, this gives strong coverage that the encoding matches the ARM ISA.

Also applies to: 151-177

@monoid
monoid merged commit 1e9d52f into masterDec 7, 2025
2 checks passed
@monoid
monoid deleted the feat/adrp branch December 7, 2025 16:49
@coderabbitaicoderabbitaiBot mentioned this pull request Dec 25, 2025
@coderabbitaicoderabbitaiBot mentioned this pull request Mar 8, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or requestharmThe `harm` dynamic assembler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@monoid
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
harm: ADR/ADRP by monoid · Pull Request #43 · monoid/harm · GitHub
Skip to content

harm: ADR/ADRP - #43

Merged
monoid merged 6 commits into
masterfrom
feat/adrp
Dec 7, 2025
Merged

harm: ADR/ADRP#43
monoid merged 6 commits into
masterfrom
feat/adrp

Conversation

@monoid

@monoidmonoid commented Nov 22, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added ADR and ADRP support for AArch64 PC-relative address generation.
    • New public constructors to build ADR/ADRP operands, including wider-offset input support (i64).
  • Tests

    • Added unit tests covering encoding and overflow/edge cases for ADR/ADRP offsets.

✏️ Tip: You can customize this high-level summary in your review settings.

@monoidmonoid self-assigned this Nov 22, 2025
@monoidmonoid added enhancement New feature or request harm The `harm` dynamic assembler labels Nov 22, 2025
@coderabbitai

coderabbitaiBot commented Nov 22, 2025

Copy link
Copy Markdown

Walkthrough

Adds a new public pcreladdr module implementing ADR/ADRP pc‑relative address instructions (types, constructors, encoders, tests) and extends SBitValue with TryFrom<i64> to support i64 offset conversion.

Changes

Cohort / File(s)Summary
New pcreladdr instruction module
harm/src/instructions/dpimm.rs, harm/src/instructions/dpimm/pcreladdr.rs
Adds pub mod pcreladdr; and pub use self::pcreladdr::*; and implements ADR/ADRP: AdrOffset/AdrpOffset aliases, Adr/Adrp generic structs, MakeAdr/MakeAdrp traits and impls, adr()/adrp() constructors, LO_BITS/LO_BITS_MASK, RawInstruction::to_code encoders computing immlo/immhi, plus unit tests covering offsets and edge cases.
SBitValue i64 conversion
harm/src/bits.rs
Adds impl TryFrom<i64> for SBitValue<const SIGNIFICANT_BITS: u32, const ALIGN: u32> delegating to SBitValue::new_i64, enabling i64 → SBitValue conversions used by Adrp constructors.

Sequence Diagram(s)

sequenceDiagram
participant Caller as Caller (user code)
participant Ctor as adr()/adrp()
participant Make as MakeAdr/MakeAdrp impl
participant Instr as Adr/Adrp instance
participant Encoder as RawInstruction::to_code
participant Emit as ADR(_only)_pcreladdr
Caller->>Ctor: call adr(rd, offset) or adrp(rd, offset)
Ctor->>Make: offset conversion (i32 / i64) via TryFrom / new_i64
Make->>Instr: construct Adr/Adrp with rd and validated offset
Instr->>Encoder: to_code()
Encoder->>Encoder: immlo = bits & LO_BITS_MASK
Encoder->>Encoder: immhi = bits >> LO_BITS
Encoder->>Emit: ADR_only_pcreladdr(immlo, immhi, rd) / ADRP_only_pcreladdr(...)
Emit-->>Encoder: InstructionCode
Encoder-->>Caller: InstructionCode
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify LO_BITS / LO_BITS_MASK and the shift/mask math vs. ARMv8 spec (pcreladdr encoding).
  • Check TryFrom<i64> correctness and sign/align handling in SBitValue::new_i64.
  • Review trait impls (MakeAdr/MakeAdrp) and adr/adrp generic signatures for ergonomic/compile-time behavior.
  • Inspect unit tests for comprehensive edge-case coverage (alignment, overflow, sign-extension).

Possibly related PRs

Poem

🐰 I nibble bits and split them fine,
ADR and ADRP hop in line.
Low bits tucked and highs take flight,
I stitch the word and send it right. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 20.00% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'harm: ADR/ADRP' directly and specifically summarizes the main changes, which introduce ADR and ADRP instruction support to the harm crate.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/adrp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
harm/src/instructions/dpimm/pcreladdr.rs (5)

19-29: Add documentation comments for public structs.

The public Adr and Adrp structs lack documentation. Consider adding doc comments explaining their purpose, the instruction encoding they represent, and usage examples.

Example:

+/// ADR (Address to Register) instruction.+///+/// Loads a PC-relative address with a byte offset into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adr<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}
+/// ADRP (Address of 4KB Page to Register) instruction.+///+/// Loads a PC-relative address of a 4KB page into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adrp<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}

31-57: Consider simplifying the trait-based construction pattern.

The MakeAdr and MakeAdrp traits currently have only one implementation each. Unless additional implementations are planned, consider using direct constructors to reduce complexity.

If you anticipate adding more implementations (e.g., for different offset representations), this pattern makes sense for future extensibility. Otherwise, the traits add indirection without immediate benefit.


59-77: Add documentation comments for public constructor functions.

The adr and adrp functions are the primary public API but lack documentation. Add doc comments explaining parameters, usage, and return types.

Example:

+/// Constructs an ADR (Address to Register) instruction.+///+/// # Arguments+/// * `rd` - Destination register+/// * `offset` - PC-relative byte offset+///+/// # Example+/// ```ignore+/// let instr = adr(X0, AdrOffset::new(0x1000).unwrap());+/// ```
pub fn adr<OffsetIn>(
rd: impl IntoReg<RegOrZero64>,
offset: OffsetIn,
) -> <Adr<AdrOffset> as MakeAdr<OffsetIn>>::Outcome

79-80: Consider adding a comment explaining the encoding split.

The constants define how the offset is split for instruction encoding. A brief comment would improve maintainability.

Example:

+// ADR/ADRP encoding splits the 19-bit offset into:+// immlo (bits 0-1) and immhi (bits 2-18)
const LO_BITS: u32 = 2;
const LO_BITS_MASK: u32 = (1 << LO_BITS) - 1;

98-137: Expand test coverage to include edge cases.

The current tests only cover 4 specific values. Consider adding tests for:

  • Minimum valid offset (e.g., -262144 for ADR, -262144 << 12 for ADRP)
  • Maximum valid offset (e.g., 262143 for ADR, 262143 << 12 for ADRP)
  • Zero offset
  • Boundary values that test the 19-bit signed range
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4112605 and f000acb.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🪛 GitHub Actions: Rust
harm/src/instructions/dpimm/pcreladdr.rs

[error] 10-10: Rustfmt formatting check failed (imports order). Run 'cargo fmt' to fix formatting in this file.


[error] 99-99: Rustfmt formatting check failed (test module formatting). Run 'cargo fmt' to fix formatting in this file.

🔇 Additional comments (3)
harm/src/instructions/dpimm.rs (1)

8-11: LGTM! Module integration follows established pattern.

The new pcreladdr module is correctly declared and re-exported, following the same pattern as existing modules (log_imm, movewide).

harm/src/instructions/dpimm/pcreladdr.rs (2)

82-96: LGTM! Encoding implementations are correct.

The RawInstruction implementations correctly split the offset into immlo (low 2 bits) and immhi (high bits) for ARM64 ADR/ADRP instruction encoding.


116-134: Verify and document expected instruction codes in tests.

Multiple TODO comments indicate the test values haven't been verified against a reference. Consider:

  1. Verifying the expected instruction codes against the ARM Architecture Reference Manual or using a reference assembler
  2. Adding comments documenting how the expected values were derived
  3. Removing the TODO comments once verified

Do you want me to help generate a verification script to compare these encodings against a reference implementation or documentation?

Comment threadharm/src/instructions/dpimm/pcreladdr.rs
Comment threadharm/src/instructions/dpimm/pcreladdr.rs

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

34-60: Consider simplifying the constructor pattern if not required by codebase conventions.

The trait-based constructor pattern (MakeAdr/MakeAdrp with associated types) adds complexity compared to direct impl blocks with new() methods. Unless this pattern is used consistently across the codebase for extensibility, consider a simpler approach:

implAdr<AdrOffset>{pubfnnew(rd:RegOrZero64,offset:AdrOffset) -> Self{Self{reg: rd, offset }}}

However, if this pattern enables future support for multiple offset input types (which the generic OffsetIn parameter suggests), the current design is reasonable.


114-139: Verify and document the expected instruction encodings.

Three tests contain TODO comments about checking correctness of the hardcoded assertion values. Consider verifying these encodings against the ARM Architecture Reference Manual or using an assembler/disassembler to confirm, then document why each expected value is correct (similar to how test_adr_m4 is clear about encoding -4).

You can verify the encodings by:

  1. Cross-referencing with ARM documentation for ADR/ADRP encoding format
  2. Using an ARM assembler/disassembler to generate and verify the instruction bytes
  3. Adding comments explaining the bit layout for each test case
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f000acb and ff98029.

📒 Files selected for processing (1)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

62-80: LGTM on public constructors.

The generic constructor functions provide a flexible API with proper type conversions via IntoReg<RegOrZero64> and trait-based constraints.


82-99: Correct bit manipulation for instruction encoding.

The immediate splitting logic correctly extracts immlo (low 2 bits) and immhi (high bits) for ADR/ADRP encoding. The minor code duplication between Adr and Adrp implementations is acceptable given the simplicity.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff98029 and 592c05a.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm.rs (1)

8-11: Consistent wiring of new pcreladdr module

The new submodule and re-export mirror the existing log_imm/movewide pattern and cleanly expose ADR/ADRP under dpimm. No issues here.

harm/src/instructions/dpimm/pcreladdr.rs (1)

82-99: ADR/ADRP immediate encoding verified correct per ARM AArch64 specification

The immediate splitting into 2-bit immlo and 19-bit immhi fields is correct and properly placed at instruction bits [30:29] and [23:5] respectively. Verified test encodings against ARM specification:

  • ADR offset -4, Rd=X29 → 0x103ffffd ✓
  • ADR offset 0x12345, Rd=X28 → 0x30091a3c ✓
  • ADRP offset -4<<12, Rd=X27 → 0x903ffffb ✓

All encodings match ARM AArch64 ADR/ADRP specification.

Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
@coderabbitai

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)

38-84: Trait‑based adr/adrp constructors are type‑safe and future‑proof

The MakeAdr/MakeAdrp traits plus the generic adr/adrp helpers cleanly separate construction from encoding and ensure all range/alignment checks go through SBitValue::try_from (i32 for ADR, i64 for ADRP). This yields a nice API where adr/adrp work both with pre‑validated offsets and raw integers without duplicating logic.

If you ever want adr to accept i64 offsets as well (for symmetry with adrp and the new TryFrom<i64> on SBitValue), adding an impl MakeAdr<i64> for Adr<AdrOffset> that calls offset.try_into() would be a straightforward extension.

Also applies to: 86-104

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc1f706 and 996e9f7.

📒 Files selected for processing (2)
  • harm/src/bits.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
harm/src/bits.rs (1)
harm/src/instructions/arith.rs (2)
  • try_from (123-125)
  • try_from (197-206)
harm/src/instructions/dpimm/pcreladdr.rs (1)
harm/src/bits.rs (2)
  • bits (83-85)
  • bits (213-215)
🔇 Additional comments (3)
harm/src/bits.rs (1)

144-153: TryFrom<i64> for SBitValue cleanly reuses existing validation

Delegating TryFrom<i64> to new_i64 keeps all range/alignment checks in one place and matches how AdrpOffset is consumed in pcreladdr.rs. With the existing new_i64 tests, this addition looks correct and low‑risk.

harm/src/instructions/dpimm/pcreladdr.rs (2)

19-36: Offset type aliases correctly model ADR/ADRP immediates

Using AdrOffset = SBitValue<21> for ADR and AdrpOffset = SBitValue<21, 12> for ADRP matches the 21‑bit signed PC‑relative immediate, with ALIGN = 12 enforcing 4 KiB page alignment for ADRP while still letting callers think in byte offsets. The accompanying doc comment on AdrpOffset makes the “real address offset” semantics explicit.


106-123: Encoding and tests correctly split and validate 21‑bit PC‑relative offsets

The encoding logic

  • uses LO_BITS = 2,
  • derives immlo = offset.bits() & LO_BITS_MASK and immhi = offset.bits() >> LO_BITS,

which is exactly the ADR/ADRP layout (low 2 bits in immlo, high 19 in immhi). For AdrpOffset, bits() already returns the shifted page offset, so reusing the same split is correct for both instructions.

The PCRELADDR_CASES table plus the test_cases! macro exercise:

  • ADR with negative and positive offsets,
  • ADRP with small and near‑limit positive/negative offsets,
  • both “pre‑validated” (SBitValue::new/new_i64) and “fallible” (adr(..., i32), adrp(..., i64)) constructors.

Together with the GNU as–verified constants, this gives strong coverage that the encoding matches the ARM ISA.

Also applies to: 151-177

@monoid
monoid merged commit 1e9d52f into masterDec 7, 2025
2 checks passed
@monoid
monoid deleted the feat/adrp branch December 7, 2025 16:49
@coderabbitaicoderabbitaiBot mentioned this pull request Dec 25, 2025
@coderabbitaicoderabbitaiBot mentioned this pull request Mar 8, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or requestharmThe `harm` dynamic assembler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@monoid
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' harm: ADR/ADRP by monoid · Pull Request #43 · monoid/harm · GitHub
Skip to content

harm: ADR/ADRP - #43

Merged
monoid merged 6 commits into
masterfrom
feat/adrp
Dec 7, 2025
Merged

harm: ADR/ADRP#43
monoid merged 6 commits into
masterfrom
feat/adrp

Conversation

@monoid

@monoidmonoid commented Nov 22, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added ADR and ADRP support for AArch64 PC-relative address generation.
    • New public constructors to build ADR/ADRP operands, including wider-offset input support (i64).
  • Tests

    • Added unit tests covering encoding and overflow/edge cases for ADR/ADRP offsets.

✏️ Tip: You can customize this high-level summary in your review settings.

@monoidmonoid self-assigned this Nov 22, 2025
@monoidmonoid added enhancement New feature or request harm The `harm` dynamic assembler labels Nov 22, 2025
@coderabbitai

coderabbitaiBot commented Nov 22, 2025

Copy link
Copy Markdown

Walkthrough

Adds a new public pcreladdr module implementing ADR/ADRP pc‑relative address instructions (types, constructors, encoders, tests) and extends SBitValue with TryFrom<i64> to support i64 offset conversion.

Changes

Cohort / File(s)Summary
New pcreladdr instruction module
harm/src/instructions/dpimm.rs, harm/src/instructions/dpimm/pcreladdr.rs
Adds pub mod pcreladdr; and pub use self::pcreladdr::*; and implements ADR/ADRP: AdrOffset/AdrpOffset aliases, Adr/Adrp generic structs, MakeAdr/MakeAdrp traits and impls, adr()/adrp() constructors, LO_BITS/LO_BITS_MASK, RawInstruction::to_code encoders computing immlo/immhi, plus unit tests covering offsets and edge cases.
SBitValue i64 conversion
harm/src/bits.rs
Adds impl TryFrom<i64> for SBitValue<const SIGNIFICANT_BITS: u32, const ALIGN: u32> delegating to SBitValue::new_i64, enabling i64 → SBitValue conversions used by Adrp constructors.

Sequence Diagram(s)

sequenceDiagram
participant Caller as Caller (user code)
participant Ctor as adr()/adrp()
participant Make as MakeAdr/MakeAdrp impl
participant Instr as Adr/Adrp instance
participant Encoder as RawInstruction::to_code
participant Emit as ADR(_only)_pcreladdr
Caller->>Ctor: call adr(rd, offset) or adrp(rd, offset)
Ctor->>Make: offset conversion (i32 / i64) via TryFrom / new_i64
Make->>Instr: construct Adr/Adrp with rd and validated offset
Instr->>Encoder: to_code()
Encoder->>Encoder: immlo = bits & LO_BITS_MASK
Encoder->>Encoder: immhi = bits >> LO_BITS
Encoder->>Emit: ADR_only_pcreladdr(immlo, immhi, rd) / ADRP_only_pcreladdr(...)
Emit-->>Encoder: InstructionCode
Encoder-->>Caller: InstructionCode
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify LO_BITS / LO_BITS_MASK and the shift/mask math vs. ARMv8 spec (pcreladdr encoding).
  • Check TryFrom<i64> correctness and sign/align handling in SBitValue::new_i64.
  • Review trait impls (MakeAdr/MakeAdrp) and adr/adrp generic signatures for ergonomic/compile-time behavior.
  • Inspect unit tests for comprehensive edge-case coverage (alignment, overflow, sign-extension).

Possibly related PRs

Poem

🐰 I nibble bits and split them fine,
ADR and ADRP hop in line.
Low bits tucked and highs take flight,
I stitch the word and send it right. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 20.00% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'harm: ADR/ADRP' directly and specifically summarizes the main changes, which introduce ADR and ADRP instruction support to the harm crate.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/adrp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
harm/src/instructions/dpimm/pcreladdr.rs (5)

19-29: Add documentation comments for public structs.

The public Adr and Adrp structs lack documentation. Consider adding doc comments explaining their purpose, the instruction encoding they represent, and usage examples.

Example:

+/// ADR (Address to Register) instruction.+///+/// Loads a PC-relative address with a byte offset into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adr<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}
+/// ADRP (Address of 4KB Page to Register) instruction.+///+/// Loads a PC-relative address of a 4KB page into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adrp<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}

31-57: Consider simplifying the trait-based construction pattern.

The MakeAdr and MakeAdrp traits currently have only one implementation each. Unless additional implementations are planned, consider using direct constructors to reduce complexity.

If you anticipate adding more implementations (e.g., for different offset representations), this pattern makes sense for future extensibility. Otherwise, the traits add indirection without immediate benefit.


59-77: Add documentation comments for public constructor functions.

The adr and adrp functions are the primary public API but lack documentation. Add doc comments explaining parameters, usage, and return types.

Example:

+/// Constructs an ADR (Address to Register) instruction.+///+/// # Arguments+/// * `rd` - Destination register+/// * `offset` - PC-relative byte offset+///+/// # Example+/// ```ignore+/// let instr = adr(X0, AdrOffset::new(0x1000).unwrap());+/// ```
pub fn adr<OffsetIn>(
rd: impl IntoReg<RegOrZero64>,
offset: OffsetIn,
) -> <Adr<AdrOffset> as MakeAdr<OffsetIn>>::Outcome

79-80: Consider adding a comment explaining the encoding split.

The constants define how the offset is split for instruction encoding. A brief comment would improve maintainability.

Example:

+// ADR/ADRP encoding splits the 19-bit offset into:+// immlo (bits 0-1) and immhi (bits 2-18)
const LO_BITS: u32 = 2;
const LO_BITS_MASK: u32 = (1 << LO_BITS) - 1;

98-137: Expand test coverage to include edge cases.

The current tests only cover 4 specific values. Consider adding tests for:

  • Minimum valid offset (e.g., -262144 for ADR, -262144 << 12 for ADRP)
  • Maximum valid offset (e.g., 262143 for ADR, 262143 << 12 for ADRP)
  • Zero offset
  • Boundary values that test the 19-bit signed range
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4112605 and f000acb.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🪛 GitHub Actions: Rust
harm/src/instructions/dpimm/pcreladdr.rs

[error] 10-10: Rustfmt formatting check failed (imports order). Run 'cargo fmt' to fix formatting in this file.


[error] 99-99: Rustfmt formatting check failed (test module formatting). Run 'cargo fmt' to fix formatting in this file.

🔇 Additional comments (3)
harm/src/instructions/dpimm.rs (1)

8-11: LGTM! Module integration follows established pattern.

The new pcreladdr module is correctly declared and re-exported, following the same pattern as existing modules (log_imm, movewide).

harm/src/instructions/dpimm/pcreladdr.rs (2)

82-96: LGTM! Encoding implementations are correct.

The RawInstruction implementations correctly split the offset into immlo (low 2 bits) and immhi (high bits) for ARM64 ADR/ADRP instruction encoding.


116-134: Verify and document expected instruction codes in tests.

Multiple TODO comments indicate the test values haven't been verified against a reference. Consider:

  1. Verifying the expected instruction codes against the ARM Architecture Reference Manual or using a reference assembler
  2. Adding comments documenting how the expected values were derived
  3. Removing the TODO comments once verified

Do you want me to help generate a verification script to compare these encodings against a reference implementation or documentation?

Comment threadharm/src/instructions/dpimm/pcreladdr.rs
Comment threadharm/src/instructions/dpimm/pcreladdr.rs

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

34-60: Consider simplifying the constructor pattern if not required by codebase conventions.

The trait-based constructor pattern (MakeAdr/MakeAdrp with associated types) adds complexity compared to direct impl blocks with new() methods. Unless this pattern is used consistently across the codebase for extensibility, consider a simpler approach:

implAdr<AdrOffset>{pubfnnew(rd:RegOrZero64,offset:AdrOffset) -> Self{Self{reg: rd, offset }}}

However, if this pattern enables future support for multiple offset input types (which the generic OffsetIn parameter suggests), the current design is reasonable.


114-139: Verify and document the expected instruction encodings.

Three tests contain TODO comments about checking correctness of the hardcoded assertion values. Consider verifying these encodings against the ARM Architecture Reference Manual or using an assembler/disassembler to confirm, then document why each expected value is correct (similar to how test_adr_m4 is clear about encoding -4).

You can verify the encodings by:

  1. Cross-referencing with ARM documentation for ADR/ADRP encoding format
  2. Using an ARM assembler/disassembler to generate and verify the instruction bytes
  3. Adding comments explaining the bit layout for each test case
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f000acb and ff98029.

📒 Files selected for processing (1)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

62-80: LGTM on public constructors.

The generic constructor functions provide a flexible API with proper type conversions via IntoReg<RegOrZero64> and trait-based constraints.


82-99: Correct bit manipulation for instruction encoding.

The immediate splitting logic correctly extracts immlo (low 2 bits) and immhi (high bits) for ADR/ADRP encoding. The minor code duplication between Adr and Adrp implementations is acceptable given the simplicity.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff98029 and 592c05a.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm.rs (1)

8-11: Consistent wiring of new pcreladdr module

The new submodule and re-export mirror the existing log_imm/movewide pattern and cleanly expose ADR/ADRP under dpimm. No issues here.

harm/src/instructions/dpimm/pcreladdr.rs (1)

82-99: ADR/ADRP immediate encoding verified correct per ARM AArch64 specification

The immediate splitting into 2-bit immlo and 19-bit immhi fields is correct and properly placed at instruction bits [30:29] and [23:5] respectively. Verified test encodings against ARM specification:

  • ADR offset -4, Rd=X29 → 0x103ffffd ✓
  • ADR offset 0x12345, Rd=X28 → 0x30091a3c ✓
  • ADRP offset -4<<12, Rd=X27 → 0x903ffffb ✓

All encodings match ARM AArch64 ADR/ADRP specification.

Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
@coderabbitai

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)

38-84: Trait‑based adr/adrp constructors are type‑safe and future‑proof

The MakeAdr/MakeAdrp traits plus the generic adr/adrp helpers cleanly separate construction from encoding and ensure all range/alignment checks go through SBitValue::try_from (i32 for ADR, i64 for ADRP). This yields a nice API where adr/adrp work both with pre‑validated offsets and raw integers without duplicating logic.

If you ever want adr to accept i64 offsets as well (for symmetry with adrp and the new TryFrom<i64> on SBitValue), adding an impl MakeAdr<i64> for Adr<AdrOffset> that calls offset.try_into() would be a straightforward extension.

Also applies to: 86-104

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc1f706 and 996e9f7.

📒 Files selected for processing (2)
  • harm/src/bits.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
harm/src/bits.rs (1)
harm/src/instructions/arith.rs (2)
  • try_from (123-125)
  • try_from (197-206)
harm/src/instructions/dpimm/pcreladdr.rs (1)
harm/src/bits.rs (2)
  • bits (83-85)
  • bits (213-215)
🔇 Additional comments (3)
harm/src/bits.rs (1)

144-153: TryFrom<i64> for SBitValue cleanly reuses existing validation

Delegating TryFrom<i64> to new_i64 keeps all range/alignment checks in one place and matches how AdrpOffset is consumed in pcreladdr.rs. With the existing new_i64 tests, this addition looks correct and low‑risk.

harm/src/instructions/dpimm/pcreladdr.rs (2)

19-36: Offset type aliases correctly model ADR/ADRP immediates

Using AdrOffset = SBitValue<21> for ADR and AdrpOffset = SBitValue<21, 12> for ADRP matches the 21‑bit signed PC‑relative immediate, with ALIGN = 12 enforcing 4 KiB page alignment for ADRP while still letting callers think in byte offsets. The accompanying doc comment on AdrpOffset makes the “real address offset” semantics explicit.


106-123: Encoding and tests correctly split and validate 21‑bit PC‑relative offsets

The encoding logic

  • uses LO_BITS = 2,
  • derives immlo = offset.bits() & LO_BITS_MASK and immhi = offset.bits() >> LO_BITS,

which is exactly the ADR/ADRP layout (low 2 bits in immlo, high 19 in immhi). For AdrpOffset, bits() already returns the shifted page offset, so reusing the same split is correct for both instructions.

The PCRELADDR_CASES table plus the test_cases! macro exercise:

  • ADR with negative and positive offsets,
  • ADRP with small and near‑limit positive/negative offsets,
  • both “pre‑validated” (SBitValue::new/new_i64) and “fallible” (adr(..., i32), adrp(..., i64)) constructors.

Together with the GNU as–verified constants, this gives strong coverage that the encoding matches the ARM ISA.

Also applies to: 151-177

@monoid
monoid merged commit 1e9d52f into masterDec 7, 2025
2 checks passed
@monoid
monoid deleted the feat/adrp branch December 7, 2025 16:49
@coderabbitaicoderabbitaiBot mentioned this pull request Dec 25, 2025
@coderabbitaicoderabbitaiBot mentioned this pull request Mar 8, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or requestharmThe `harm` dynamic assembler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@monoid
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' harm: ADR/ADRP by monoid · Pull Request #43 · monoid/harm · GitHub
Skip to content

harm: ADR/ADRP - #43

Merged
monoid merged 6 commits into
masterfrom
feat/adrp
Dec 7, 2025
Merged

harm: ADR/ADRP#43
monoid merged 6 commits into
masterfrom
feat/adrp

Conversation

@monoid

@monoidmonoid commented Nov 22, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added ADR and ADRP support for AArch64 PC-relative address generation.
    • New public constructors to build ADR/ADRP operands, including wider-offset input support (i64).
  • Tests

    • Added unit tests covering encoding and overflow/edge cases for ADR/ADRP offsets.

✏️ Tip: You can customize this high-level summary in your review settings.

@monoidmonoid self-assigned this Nov 22, 2025
@monoidmonoid added enhancement New feature or request harm The `harm` dynamic assembler labels Nov 22, 2025
@coderabbitai

coderabbitaiBot commented Nov 22, 2025

Copy link
Copy Markdown

Walkthrough

Adds a new public pcreladdr module implementing ADR/ADRP pc‑relative address instructions (types, constructors, encoders, tests) and extends SBitValue with TryFrom<i64> to support i64 offset conversion.

Changes

Cohort / File(s)Summary
New pcreladdr instruction module
harm/src/instructions/dpimm.rs, harm/src/instructions/dpimm/pcreladdr.rs
Adds pub mod pcreladdr; and pub use self::pcreladdr::*; and implements ADR/ADRP: AdrOffset/AdrpOffset aliases, Adr/Adrp generic structs, MakeAdr/MakeAdrp traits and impls, adr()/adrp() constructors, LO_BITS/LO_BITS_MASK, RawInstruction::to_code encoders computing immlo/immhi, plus unit tests covering offsets and edge cases.
SBitValue i64 conversion
harm/src/bits.rs
Adds impl TryFrom<i64> for SBitValue<const SIGNIFICANT_BITS: u32, const ALIGN: u32> delegating to SBitValue::new_i64, enabling i64 → SBitValue conversions used by Adrp constructors.

Sequence Diagram(s)

sequenceDiagram
participant Caller as Caller (user code)
participant Ctor as adr()/adrp()
participant Make as MakeAdr/MakeAdrp impl
participant Instr as Adr/Adrp instance
participant Encoder as RawInstruction::to_code
participant Emit as ADR(_only)_pcreladdr
Caller->>Ctor: call adr(rd, offset) or adrp(rd, offset)
Ctor->>Make: offset conversion (i32 / i64) via TryFrom / new_i64
Make->>Instr: construct Adr/Adrp with rd and validated offset
Instr->>Encoder: to_code()
Encoder->>Encoder: immlo = bits & LO_BITS_MASK
Encoder->>Encoder: immhi = bits >> LO_BITS
Encoder->>Emit: ADR_only_pcreladdr(immlo, immhi, rd) / ADRP_only_pcreladdr(...)
Emit-->>Encoder: InstructionCode
Encoder-->>Caller: InstructionCode
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify LO_BITS / LO_BITS_MASK and the shift/mask math vs. ARMv8 spec (pcreladdr encoding).
  • Check TryFrom<i64> correctness and sign/align handling in SBitValue::new_i64.
  • Review trait impls (MakeAdr/MakeAdrp) and adr/adrp generic signatures for ergonomic/compile-time behavior.
  • Inspect unit tests for comprehensive edge-case coverage (alignment, overflow, sign-extension).

Possibly related PRs

Poem

🐰 I nibble bits and split them fine,
ADR and ADRP hop in line.
Low bits tucked and highs take flight,
I stitch the word and send it right. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 20.00% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'harm: ADR/ADRP' directly and specifically summarizes the main changes, which introduce ADR and ADRP instruction support to the harm crate.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/adrp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
harm/src/instructions/dpimm/pcreladdr.rs (5)

19-29: Add documentation comments for public structs.

The public Adr and Adrp structs lack documentation. Consider adding doc comments explaining their purpose, the instruction encoding they represent, and usage examples.

Example:

+/// ADR (Address to Register) instruction.+///+/// Loads a PC-relative address with a byte offset into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adr<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}
+/// ADRP (Address of 4KB Page to Register) instruction.+///+/// Loads a PC-relative address of a 4KB page into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adrp<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}

31-57: Consider simplifying the trait-based construction pattern.

The MakeAdr and MakeAdrp traits currently have only one implementation each. Unless additional implementations are planned, consider using direct constructors to reduce complexity.

If you anticipate adding more implementations (e.g., for different offset representations), this pattern makes sense for future extensibility. Otherwise, the traits add indirection without immediate benefit.


59-77: Add documentation comments for public constructor functions.

The adr and adrp functions are the primary public API but lack documentation. Add doc comments explaining parameters, usage, and return types.

Example:

+/// Constructs an ADR (Address to Register) instruction.+///+/// # Arguments+/// * `rd` - Destination register+/// * `offset` - PC-relative byte offset+///+/// # Example+/// ```ignore+/// let instr = adr(X0, AdrOffset::new(0x1000).unwrap());+/// ```
pub fn adr<OffsetIn>(
rd: impl IntoReg<RegOrZero64>,
offset: OffsetIn,
) -> <Adr<AdrOffset> as MakeAdr<OffsetIn>>::Outcome

79-80: Consider adding a comment explaining the encoding split.

The constants define how the offset is split for instruction encoding. A brief comment would improve maintainability.

Example:

+// ADR/ADRP encoding splits the 19-bit offset into:+// immlo (bits 0-1) and immhi (bits 2-18)
const LO_BITS: u32 = 2;
const LO_BITS_MASK: u32 = (1 << LO_BITS) - 1;

98-137: Expand test coverage to include edge cases.

The current tests only cover 4 specific values. Consider adding tests for:

  • Minimum valid offset (e.g., -262144 for ADR, -262144 << 12 for ADRP)
  • Maximum valid offset (e.g., 262143 for ADR, 262143 << 12 for ADRP)
  • Zero offset
  • Boundary values that test the 19-bit signed range
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4112605 and f000acb.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🪛 GitHub Actions: Rust
harm/src/instructions/dpimm/pcreladdr.rs

[error] 10-10: Rustfmt formatting check failed (imports order). Run 'cargo fmt' to fix formatting in this file.


[error] 99-99: Rustfmt formatting check failed (test module formatting). Run 'cargo fmt' to fix formatting in this file.

🔇 Additional comments (3)
harm/src/instructions/dpimm.rs (1)

8-11: LGTM! Module integration follows established pattern.

The new pcreladdr module is correctly declared and re-exported, following the same pattern as existing modules (log_imm, movewide).

harm/src/instructions/dpimm/pcreladdr.rs (2)

82-96: LGTM! Encoding implementations are correct.

The RawInstruction implementations correctly split the offset into immlo (low 2 bits) and immhi (high bits) for ARM64 ADR/ADRP instruction encoding.


116-134: Verify and document expected instruction codes in tests.

Multiple TODO comments indicate the test values haven't been verified against a reference. Consider:

  1. Verifying the expected instruction codes against the ARM Architecture Reference Manual or using a reference assembler
  2. Adding comments documenting how the expected values were derived
  3. Removing the TODO comments once verified

Do you want me to help generate a verification script to compare these encodings against a reference implementation or documentation?

Comment threadharm/src/instructions/dpimm/pcreladdr.rs
Comment threadharm/src/instructions/dpimm/pcreladdr.rs

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

34-60: Consider simplifying the constructor pattern if not required by codebase conventions.

The trait-based constructor pattern (MakeAdr/MakeAdrp with associated types) adds complexity compared to direct impl blocks with new() methods. Unless this pattern is used consistently across the codebase for extensibility, consider a simpler approach:

implAdr<AdrOffset>{pubfnnew(rd:RegOrZero64,offset:AdrOffset) -> Self{Self{reg: rd, offset }}}

However, if this pattern enables future support for multiple offset input types (which the generic OffsetIn parameter suggests), the current design is reasonable.


114-139: Verify and document the expected instruction encodings.

Three tests contain TODO comments about checking correctness of the hardcoded assertion values. Consider verifying these encodings against the ARM Architecture Reference Manual or using an assembler/disassembler to confirm, then document why each expected value is correct (similar to how test_adr_m4 is clear about encoding -4).

You can verify the encodings by:

  1. Cross-referencing with ARM documentation for ADR/ADRP encoding format
  2. Using an ARM assembler/disassembler to generate and verify the instruction bytes
  3. Adding comments explaining the bit layout for each test case
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f000acb and ff98029.

📒 Files selected for processing (1)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

62-80: LGTM on public constructors.

The generic constructor functions provide a flexible API with proper type conversions via IntoReg<RegOrZero64> and trait-based constraints.


82-99: Correct bit manipulation for instruction encoding.

The immediate splitting logic correctly extracts immlo (low 2 bits) and immhi (high bits) for ADR/ADRP encoding. The minor code duplication between Adr and Adrp implementations is acceptable given the simplicity.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff98029 and 592c05a.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm.rs (1)

8-11: Consistent wiring of new pcreladdr module

The new submodule and re-export mirror the existing log_imm/movewide pattern and cleanly expose ADR/ADRP under dpimm. No issues here.

harm/src/instructions/dpimm/pcreladdr.rs (1)

82-99: ADR/ADRP immediate encoding verified correct per ARM AArch64 specification

The immediate splitting into 2-bit immlo and 19-bit immhi fields is correct and properly placed at instruction bits [30:29] and [23:5] respectively. Verified test encodings against ARM specification:

  • ADR offset -4, Rd=X29 → 0x103ffffd ✓
  • ADR offset 0x12345, Rd=X28 → 0x30091a3c ✓
  • ADRP offset -4<<12, Rd=X27 → 0x903ffffb ✓

All encodings match ARM AArch64 ADR/ADRP specification.

Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
@coderabbitai

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)

38-84: Trait‑based adr/adrp constructors are type‑safe and future‑proof

The MakeAdr/MakeAdrp traits plus the generic adr/adrp helpers cleanly separate construction from encoding and ensure all range/alignment checks go through SBitValue::try_from (i32 for ADR, i64 for ADRP). This yields a nice API where adr/adrp work both with pre‑validated offsets and raw integers without duplicating logic.

If you ever want adr to accept i64 offsets as well (for symmetry with adrp and the new TryFrom<i64> on SBitValue), adding an impl MakeAdr<i64> for Adr<AdrOffset> that calls offset.try_into() would be a straightforward extension.

Also applies to: 86-104

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc1f706 and 996e9f7.

📒 Files selected for processing (2)
  • harm/src/bits.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
harm/src/bits.rs (1)
harm/src/instructions/arith.rs (2)
  • try_from (123-125)
  • try_from (197-206)
harm/src/instructions/dpimm/pcreladdr.rs (1)
harm/src/bits.rs (2)
  • bits (83-85)
  • bits (213-215)
🔇 Additional comments (3)
harm/src/bits.rs (1)

144-153: TryFrom<i64> for SBitValue cleanly reuses existing validation

Delegating TryFrom<i64> to new_i64 keeps all range/alignment checks in one place and matches how AdrpOffset is consumed in pcreladdr.rs. With the existing new_i64 tests, this addition looks correct and low‑risk.

harm/src/instructions/dpimm/pcreladdr.rs (2)

19-36: Offset type aliases correctly model ADR/ADRP immediates

Using AdrOffset = SBitValue<21> for ADR and AdrpOffset = SBitValue<21, 12> for ADRP matches the 21‑bit signed PC‑relative immediate, with ALIGN = 12 enforcing 4 KiB page alignment for ADRP while still letting callers think in byte offsets. The accompanying doc comment on AdrpOffset makes the “real address offset” semantics explicit.


106-123: Encoding and tests correctly split and validate 21‑bit PC‑relative offsets

The encoding logic

  • uses LO_BITS = 2,
  • derives immlo = offset.bits() & LO_BITS_MASK and immhi = offset.bits() >> LO_BITS,

which is exactly the ADR/ADRP layout (low 2 bits in immlo, high 19 in immhi). For AdrpOffset, bits() already returns the shifted page offset, so reusing the same split is correct for both instructions.

The PCRELADDR_CASES table plus the test_cases! macro exercise:

  • ADR with negative and positive offsets,
  • ADRP with small and near‑limit positive/negative offsets,
  • both “pre‑validated” (SBitValue::new/new_i64) and “fallible” (adr(..., i32), adrp(..., i64)) constructors.

Together with the GNU as–verified constants, this gives strong coverage that the encoding matches the ARM ISA.

Also applies to: 151-177

@monoid
monoid merged commit 1e9d52f into masterDec 7, 2025
2 checks passed
@monoid
monoid deleted the feat/adrp branch December 7, 2025 16:49
@coderabbitaicoderabbitaiBot mentioned this pull request Dec 25, 2025
@coderabbitaicoderabbitaiBot mentioned this pull request Mar 8, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or requestharmThe `harm` dynamic assembler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@monoid
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' harm: ADR/ADRP by monoid · Pull Request #43 · monoid/harm · GitHub
Skip to content

harm: ADR/ADRP - #43

Merged
monoid merged 6 commits into
masterfrom
feat/adrp
Dec 7, 2025
Merged

harm: ADR/ADRP#43
monoid merged 6 commits into
masterfrom
feat/adrp

Conversation

@monoid

@monoidmonoid commented Nov 22, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added ADR and ADRP support for AArch64 PC-relative address generation.
    • New public constructors to build ADR/ADRP operands, including wider-offset input support (i64).
  • Tests

    • Added unit tests covering encoding and overflow/edge cases for ADR/ADRP offsets.

✏️ Tip: You can customize this high-level summary in your review settings.

@monoidmonoid self-assigned this Nov 22, 2025
@monoidmonoid added enhancement New feature or request harm The `harm` dynamic assembler labels Nov 22, 2025
@coderabbitai

coderabbitaiBot commented Nov 22, 2025

Copy link
Copy Markdown

Walkthrough

Adds a new public pcreladdr module implementing ADR/ADRP pc‑relative address instructions (types, constructors, encoders, tests) and extends SBitValue with TryFrom<i64> to support i64 offset conversion.

Changes

Cohort / File(s)Summary
New pcreladdr instruction module
harm/src/instructions/dpimm.rs, harm/src/instructions/dpimm/pcreladdr.rs
Adds pub mod pcreladdr; and pub use self::pcreladdr::*; and implements ADR/ADRP: AdrOffset/AdrpOffset aliases, Adr/Adrp generic structs, MakeAdr/MakeAdrp traits and impls, adr()/adrp() constructors, LO_BITS/LO_BITS_MASK, RawInstruction::to_code encoders computing immlo/immhi, plus unit tests covering offsets and edge cases.
SBitValue i64 conversion
harm/src/bits.rs
Adds impl TryFrom<i64> for SBitValue<const SIGNIFICANT_BITS: u32, const ALIGN: u32> delegating to SBitValue::new_i64, enabling i64 → SBitValue conversions used by Adrp constructors.

Sequence Diagram(s)

sequenceDiagram
participant Caller as Caller (user code)
participant Ctor as adr()/adrp()
participant Make as MakeAdr/MakeAdrp impl
participant Instr as Adr/Adrp instance
participant Encoder as RawInstruction::to_code
participant Emit as ADR(_only)_pcreladdr
Caller->>Ctor: call adr(rd, offset) or adrp(rd, offset)
Ctor->>Make: offset conversion (i32 / i64) via TryFrom / new_i64
Make->>Instr: construct Adr/Adrp with rd and validated offset
Instr->>Encoder: to_code()
Encoder->>Encoder: immlo = bits & LO_BITS_MASK
Encoder->>Encoder: immhi = bits >> LO_BITS
Encoder->>Emit: ADR_only_pcreladdr(immlo, immhi, rd) / ADRP_only_pcreladdr(...)
Emit-->>Encoder: InstructionCode
Encoder-->>Caller: InstructionCode
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify LO_BITS / LO_BITS_MASK and the shift/mask math vs. ARMv8 spec (pcreladdr encoding).
  • Check TryFrom<i64> correctness and sign/align handling in SBitValue::new_i64.
  • Review trait impls (MakeAdr/MakeAdrp) and adr/adrp generic signatures for ergonomic/compile-time behavior.
  • Inspect unit tests for comprehensive edge-case coverage (alignment, overflow, sign-extension).

Possibly related PRs

Poem

🐰 I nibble bits and split them fine,
ADR and ADRP hop in line.
Low bits tucked and highs take flight,
I stitch the word and send it right. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 20.00% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'harm: ADR/ADRP' directly and specifically summarizes the main changes, which introduce ADR and ADRP instruction support to the harm crate.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/adrp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
harm/src/instructions/dpimm/pcreladdr.rs (5)

19-29: Add documentation comments for public structs.

The public Adr and Adrp structs lack documentation. Consider adding doc comments explaining their purpose, the instruction encoding they represent, and usage examples.

Example:

+/// ADR (Address to Register) instruction.+///+/// Loads a PC-relative address with a byte offset into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adr<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}
+/// ADRP (Address of 4KB Page to Register) instruction.+///+/// Loads a PC-relative address of a 4KB page into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adrp<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}

31-57: Consider simplifying the trait-based construction pattern.

The MakeAdr and MakeAdrp traits currently have only one implementation each. Unless additional implementations are planned, consider using direct constructors to reduce complexity.

If you anticipate adding more implementations (e.g., for different offset representations), this pattern makes sense for future extensibility. Otherwise, the traits add indirection without immediate benefit.


59-77: Add documentation comments for public constructor functions.

The adr and adrp functions are the primary public API but lack documentation. Add doc comments explaining parameters, usage, and return types.

Example:

+/// Constructs an ADR (Address to Register) instruction.+///+/// # Arguments+/// * `rd` - Destination register+/// * `offset` - PC-relative byte offset+///+/// # Example+/// ```ignore+/// let instr = adr(X0, AdrOffset::new(0x1000).unwrap());+/// ```
pub fn adr<OffsetIn>(
rd: impl IntoReg<RegOrZero64>,
offset: OffsetIn,
) -> <Adr<AdrOffset> as MakeAdr<OffsetIn>>::Outcome

79-80: Consider adding a comment explaining the encoding split.

The constants define how the offset is split for instruction encoding. A brief comment would improve maintainability.

Example:

+// ADR/ADRP encoding splits the 19-bit offset into:+// immlo (bits 0-1) and immhi (bits 2-18)
const LO_BITS: u32 = 2;
const LO_BITS_MASK: u32 = (1 << LO_BITS) - 1;

98-137: Expand test coverage to include edge cases.

The current tests only cover 4 specific values. Consider adding tests for:

  • Minimum valid offset (e.g., -262144 for ADR, -262144 << 12 for ADRP)
  • Maximum valid offset (e.g., 262143 for ADR, 262143 << 12 for ADRP)
  • Zero offset
  • Boundary values that test the 19-bit signed range
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4112605 and f000acb.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🪛 GitHub Actions: Rust
harm/src/instructions/dpimm/pcreladdr.rs

[error] 10-10: Rustfmt formatting check failed (imports order). Run 'cargo fmt' to fix formatting in this file.


[error] 99-99: Rustfmt formatting check failed (test module formatting). Run 'cargo fmt' to fix formatting in this file.

🔇 Additional comments (3)
harm/src/instructions/dpimm.rs (1)

8-11: LGTM! Module integration follows established pattern.

The new pcreladdr module is correctly declared and re-exported, following the same pattern as existing modules (log_imm, movewide).

harm/src/instructions/dpimm/pcreladdr.rs (2)

82-96: LGTM! Encoding implementations are correct.

The RawInstruction implementations correctly split the offset into immlo (low 2 bits) and immhi (high bits) for ARM64 ADR/ADRP instruction encoding.


116-134: Verify and document expected instruction codes in tests.

Multiple TODO comments indicate the test values haven't been verified against a reference. Consider:

  1. Verifying the expected instruction codes against the ARM Architecture Reference Manual or using a reference assembler
  2. Adding comments documenting how the expected values were derived
  3. Removing the TODO comments once verified

Do you want me to help generate a verification script to compare these encodings against a reference implementation or documentation?

Comment threadharm/src/instructions/dpimm/pcreladdr.rs
Comment threadharm/src/instructions/dpimm/pcreladdr.rs

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

34-60: Consider simplifying the constructor pattern if not required by codebase conventions.

The trait-based constructor pattern (MakeAdr/MakeAdrp with associated types) adds complexity compared to direct impl blocks with new() methods. Unless this pattern is used consistently across the codebase for extensibility, consider a simpler approach:

implAdr<AdrOffset>{pubfnnew(rd:RegOrZero64,offset:AdrOffset) -> Self{Self{reg: rd, offset }}}

However, if this pattern enables future support for multiple offset input types (which the generic OffsetIn parameter suggests), the current design is reasonable.


114-139: Verify and document the expected instruction encodings.

Three tests contain TODO comments about checking correctness of the hardcoded assertion values. Consider verifying these encodings against the ARM Architecture Reference Manual or using an assembler/disassembler to confirm, then document why each expected value is correct (similar to how test_adr_m4 is clear about encoding -4).

You can verify the encodings by:

  1. Cross-referencing with ARM documentation for ADR/ADRP encoding format
  2. Using an ARM assembler/disassembler to generate and verify the instruction bytes
  3. Adding comments explaining the bit layout for each test case
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f000acb and ff98029.

📒 Files selected for processing (1)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

62-80: LGTM on public constructors.

The generic constructor functions provide a flexible API with proper type conversions via IntoReg<RegOrZero64> and trait-based constraints.


82-99: Correct bit manipulation for instruction encoding.

The immediate splitting logic correctly extracts immlo (low 2 bits) and immhi (high bits) for ADR/ADRP encoding. The minor code duplication between Adr and Adrp implementations is acceptable given the simplicity.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff98029 and 592c05a.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm.rs (1)

8-11: Consistent wiring of new pcreladdr module

The new submodule and re-export mirror the existing log_imm/movewide pattern and cleanly expose ADR/ADRP under dpimm. No issues here.

harm/src/instructions/dpimm/pcreladdr.rs (1)

82-99: ADR/ADRP immediate encoding verified correct per ARM AArch64 specification

The immediate splitting into 2-bit immlo and 19-bit immhi fields is correct and properly placed at instruction bits [30:29] and [23:5] respectively. Verified test encodings against ARM specification:

  • ADR offset -4, Rd=X29 → 0x103ffffd ✓
  • ADR offset 0x12345, Rd=X28 → 0x30091a3c ✓
  • ADRP offset -4<<12, Rd=X27 → 0x903ffffb ✓

All encodings match ARM AArch64 ADR/ADRP specification.

Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
@coderabbitai

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)

38-84: Trait‑based adr/adrp constructors are type‑safe and future‑proof

The MakeAdr/MakeAdrp traits plus the generic adr/adrp helpers cleanly separate construction from encoding and ensure all range/alignment checks go through SBitValue::try_from (i32 for ADR, i64 for ADRP). This yields a nice API where adr/adrp work both with pre‑validated offsets and raw integers without duplicating logic.

If you ever want adr to accept i64 offsets as well (for symmetry with adrp and the new TryFrom<i64> on SBitValue), adding an impl MakeAdr<i64> for Adr<AdrOffset> that calls offset.try_into() would be a straightforward extension.

Also applies to: 86-104

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc1f706 and 996e9f7.

📒 Files selected for processing (2)
  • harm/src/bits.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
harm/src/bits.rs (1)
harm/src/instructions/arith.rs (2)
  • try_from (123-125)
  • try_from (197-206)
harm/src/instructions/dpimm/pcreladdr.rs (1)
harm/src/bits.rs (2)
  • bits (83-85)
  • bits (213-215)
🔇 Additional comments (3)
harm/src/bits.rs (1)

144-153: TryFrom<i64> for SBitValue cleanly reuses existing validation

Delegating TryFrom<i64> to new_i64 keeps all range/alignment checks in one place and matches how AdrpOffset is consumed in pcreladdr.rs. With the existing new_i64 tests, this addition looks correct and low‑risk.

harm/src/instructions/dpimm/pcreladdr.rs (2)

19-36: Offset type aliases correctly model ADR/ADRP immediates

Using AdrOffset = SBitValue<21> for ADR and AdrpOffset = SBitValue<21, 12> for ADRP matches the 21‑bit signed PC‑relative immediate, with ALIGN = 12 enforcing 4 KiB page alignment for ADRP while still letting callers think in byte offsets. The accompanying doc comment on AdrpOffset makes the “real address offset” semantics explicit.


106-123: Encoding and tests correctly split and validate 21‑bit PC‑relative offsets

The encoding logic

  • uses LO_BITS = 2,
  • derives immlo = offset.bits() & LO_BITS_MASK and immhi = offset.bits() >> LO_BITS,

which is exactly the ADR/ADRP layout (low 2 bits in immlo, high 19 in immhi). For AdrpOffset, bits() already returns the shifted page offset, so reusing the same split is correct for both instructions.

The PCRELADDR_CASES table plus the test_cases! macro exercise:

  • ADR with negative and positive offsets,
  • ADRP with small and near‑limit positive/negative offsets,
  • both “pre‑validated” (SBitValue::new/new_i64) and “fallible” (adr(..., i32), adrp(..., i64)) constructors.

Together with the GNU as–verified constants, this gives strong coverage that the encoding matches the ARM ISA.

Also applies to: 151-177

@monoid
monoid merged commit 1e9d52f into masterDec 7, 2025
2 checks passed
@monoid
monoid deleted the feat/adrp branch December 7, 2025 16:49
@coderabbitaicoderabbitaiBot mentioned this pull request Dec 25, 2025
@coderabbitaicoderabbitaiBot mentioned this pull request Mar 8, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or requestharmThe `harm` dynamic assembler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@monoid
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' harm: ADR/ADRP by monoid · Pull Request #43 · monoid/harm · GitHub
Skip to content

harm: ADR/ADRP - #43

Merged
monoid merged 6 commits into
masterfrom
feat/adrp
Dec 7, 2025
Merged

harm: ADR/ADRP#43
monoid merged 6 commits into
masterfrom
feat/adrp

Conversation

@monoid

@monoidmonoid commented Nov 22, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added ADR and ADRP support for AArch64 PC-relative address generation.
    • New public constructors to build ADR/ADRP operands, including wider-offset input support (i64).
  • Tests

    • Added unit tests covering encoding and overflow/edge cases for ADR/ADRP offsets.

✏️ Tip: You can customize this high-level summary in your review settings.

@monoidmonoid self-assigned this Nov 22, 2025
@monoidmonoid added enhancement New feature or request harm The `harm` dynamic assembler labels Nov 22, 2025
@coderabbitai

coderabbitaiBot commented Nov 22, 2025

Copy link
Copy Markdown

Walkthrough

Adds a new public pcreladdr module implementing ADR/ADRP pc‑relative address instructions (types, constructors, encoders, tests) and extends SBitValue with TryFrom<i64> to support i64 offset conversion.

Changes

Cohort / File(s)Summary
New pcreladdr instruction module
harm/src/instructions/dpimm.rs, harm/src/instructions/dpimm/pcreladdr.rs
Adds pub mod pcreladdr; and pub use self::pcreladdr::*; and implements ADR/ADRP: AdrOffset/AdrpOffset aliases, Adr/Adrp generic structs, MakeAdr/MakeAdrp traits and impls, adr()/adrp() constructors, LO_BITS/LO_BITS_MASK, RawInstruction::to_code encoders computing immlo/immhi, plus unit tests covering offsets and edge cases.
SBitValue i64 conversion
harm/src/bits.rs
Adds impl TryFrom<i64> for SBitValue<const SIGNIFICANT_BITS: u32, const ALIGN: u32> delegating to SBitValue::new_i64, enabling i64 → SBitValue conversions used by Adrp constructors.

Sequence Diagram(s)

sequenceDiagram
participant Caller as Caller (user code)
participant Ctor as adr()/adrp()
participant Make as MakeAdr/MakeAdrp impl
participant Instr as Adr/Adrp instance
participant Encoder as RawInstruction::to_code
participant Emit as ADR(_only)_pcreladdr
Caller->>Ctor: call adr(rd, offset) or adrp(rd, offset)
Ctor->>Make: offset conversion (i32 / i64) via TryFrom / new_i64
Make->>Instr: construct Adr/Adrp with rd and validated offset
Instr->>Encoder: to_code()
Encoder->>Encoder: immlo = bits & LO_BITS_MASK
Encoder->>Encoder: immhi = bits >> LO_BITS
Encoder->>Emit: ADR_only_pcreladdr(immlo, immhi, rd) / ADRP_only_pcreladdr(...)
Emit-->>Encoder: InstructionCode
Encoder-->>Caller: InstructionCode
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify LO_BITS / LO_BITS_MASK and the shift/mask math vs. ARMv8 spec (pcreladdr encoding).
  • Check TryFrom<i64> correctness and sign/align handling in SBitValue::new_i64.
  • Review trait impls (MakeAdr/MakeAdrp) and adr/adrp generic signatures for ergonomic/compile-time behavior.
  • Inspect unit tests for comprehensive edge-case coverage (alignment, overflow, sign-extension).

Possibly related PRs

Poem

🐰 I nibble bits and split them fine,
ADR and ADRP hop in line.
Low bits tucked and highs take flight,
I stitch the word and send it right. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 20.00% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'harm: ADR/ADRP' directly and specifically summarizes the main changes, which introduce ADR and ADRP instruction support to the harm crate.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/adrp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
harm/src/instructions/dpimm/pcreladdr.rs (5)

19-29: Add documentation comments for public structs.

The public Adr and Adrp structs lack documentation. Consider adding doc comments explaining their purpose, the instruction encoding they represent, and usage examples.

Example:

+/// ADR (Address to Register) instruction.+///+/// Loads a PC-relative address with a byte offset into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adr<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}
+/// ADRP (Address of 4KB Page to Register) instruction.+///+/// Loads a PC-relative address of a 4KB page into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adrp<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}

31-57: Consider simplifying the trait-based construction pattern.

The MakeAdr and MakeAdrp traits currently have only one implementation each. Unless additional implementations are planned, consider using direct constructors to reduce complexity.

If you anticipate adding more implementations (e.g., for different offset representations), this pattern makes sense for future extensibility. Otherwise, the traits add indirection without immediate benefit.


59-77: Add documentation comments for public constructor functions.

The adr and adrp functions are the primary public API but lack documentation. Add doc comments explaining parameters, usage, and return types.

Example:

+/// Constructs an ADR (Address to Register) instruction.+///+/// # Arguments+/// * `rd` - Destination register+/// * `offset` - PC-relative byte offset+///+/// # Example+/// ```ignore+/// let instr = adr(X0, AdrOffset::new(0x1000).unwrap());+/// ```
pub fn adr<OffsetIn>(
rd: impl IntoReg<RegOrZero64>,
offset: OffsetIn,
) -> <Adr<AdrOffset> as MakeAdr<OffsetIn>>::Outcome

79-80: Consider adding a comment explaining the encoding split.

The constants define how the offset is split for instruction encoding. A brief comment would improve maintainability.

Example:

+// ADR/ADRP encoding splits the 19-bit offset into:+// immlo (bits 0-1) and immhi (bits 2-18)
const LO_BITS: u32 = 2;
const LO_BITS_MASK: u32 = (1 << LO_BITS) - 1;

98-137: Expand test coverage to include edge cases.

The current tests only cover 4 specific values. Consider adding tests for:

  • Minimum valid offset (e.g., -262144 for ADR, -262144 << 12 for ADRP)
  • Maximum valid offset (e.g., 262143 for ADR, 262143 << 12 for ADRP)
  • Zero offset
  • Boundary values that test the 19-bit signed range
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4112605 and f000acb.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🪛 GitHub Actions: Rust
harm/src/instructions/dpimm/pcreladdr.rs

[error] 10-10: Rustfmt formatting check failed (imports order). Run 'cargo fmt' to fix formatting in this file.


[error] 99-99: Rustfmt formatting check failed (test module formatting). Run 'cargo fmt' to fix formatting in this file.

🔇 Additional comments (3)
harm/src/instructions/dpimm.rs (1)

8-11: LGTM! Module integration follows established pattern.

The new pcreladdr module is correctly declared and re-exported, following the same pattern as existing modules (log_imm, movewide).

harm/src/instructions/dpimm/pcreladdr.rs (2)

82-96: LGTM! Encoding implementations are correct.

The RawInstruction implementations correctly split the offset into immlo (low 2 bits) and immhi (high bits) for ARM64 ADR/ADRP instruction encoding.


116-134: Verify and document expected instruction codes in tests.

Multiple TODO comments indicate the test values haven't been verified against a reference. Consider:

  1. Verifying the expected instruction codes against the ARM Architecture Reference Manual or using a reference assembler
  2. Adding comments documenting how the expected values were derived
  3. Removing the TODO comments once verified

Do you want me to help generate a verification script to compare these encodings against a reference implementation or documentation?

Comment threadharm/src/instructions/dpimm/pcreladdr.rs
Comment threadharm/src/instructions/dpimm/pcreladdr.rs

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

34-60: Consider simplifying the constructor pattern if not required by codebase conventions.

The trait-based constructor pattern (MakeAdr/MakeAdrp with associated types) adds complexity compared to direct impl blocks with new() methods. Unless this pattern is used consistently across the codebase for extensibility, consider a simpler approach:

implAdr<AdrOffset>{pubfnnew(rd:RegOrZero64,offset:AdrOffset) -> Self{Self{reg: rd, offset }}}

However, if this pattern enables future support for multiple offset input types (which the generic OffsetIn parameter suggests), the current design is reasonable.


114-139: Verify and document the expected instruction encodings.

Three tests contain TODO comments about checking correctness of the hardcoded assertion values. Consider verifying these encodings against the ARM Architecture Reference Manual or using an assembler/disassembler to confirm, then document why each expected value is correct (similar to how test_adr_m4 is clear about encoding -4).

You can verify the encodings by:

  1. Cross-referencing with ARM documentation for ADR/ADRP encoding format
  2. Using an ARM assembler/disassembler to generate and verify the instruction bytes
  3. Adding comments explaining the bit layout for each test case
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f000acb and ff98029.

📒 Files selected for processing (1)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

62-80: LGTM on public constructors.

The generic constructor functions provide a flexible API with proper type conversions via IntoReg<RegOrZero64> and trait-based constraints.


82-99: Correct bit manipulation for instruction encoding.

The immediate splitting logic correctly extracts immlo (low 2 bits) and immhi (high bits) for ADR/ADRP encoding. The minor code duplication between Adr and Adrp implementations is acceptable given the simplicity.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff98029 and 592c05a.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm.rs (1)

8-11: Consistent wiring of new pcreladdr module

The new submodule and re-export mirror the existing log_imm/movewide pattern and cleanly expose ADR/ADRP under dpimm. No issues here.

harm/src/instructions/dpimm/pcreladdr.rs (1)

82-99: ADR/ADRP immediate encoding verified correct per ARM AArch64 specification

The immediate splitting into 2-bit immlo and 19-bit immhi fields is correct and properly placed at instruction bits [30:29] and [23:5] respectively. Verified test encodings against ARM specification:

  • ADR offset -4, Rd=X29 → 0x103ffffd ✓
  • ADR offset 0x12345, Rd=X28 → 0x30091a3c ✓
  • ADRP offset -4<<12, Rd=X27 → 0x903ffffb ✓

All encodings match ARM AArch64 ADR/ADRP specification.

Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
@coderabbitai

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)

38-84: Trait‑based adr/adrp constructors are type‑safe and future‑proof

The MakeAdr/MakeAdrp traits plus the generic adr/adrp helpers cleanly separate construction from encoding and ensure all range/alignment checks go through SBitValue::try_from (i32 for ADR, i64 for ADRP). This yields a nice API where adr/adrp work both with pre‑validated offsets and raw integers without duplicating logic.

If you ever want adr to accept i64 offsets as well (for symmetry with adrp and the new TryFrom<i64> on SBitValue), adding an impl MakeAdr<i64> for Adr<AdrOffset> that calls offset.try_into() would be a straightforward extension.

Also applies to: 86-104

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc1f706 and 996e9f7.

📒 Files selected for processing (2)
  • harm/src/bits.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
harm/src/bits.rs (1)
harm/src/instructions/arith.rs (2)
  • try_from (123-125)
  • try_from (197-206)
harm/src/instructions/dpimm/pcreladdr.rs (1)
harm/src/bits.rs (2)
  • bits (83-85)
  • bits (213-215)
🔇 Additional comments (3)
harm/src/bits.rs (1)

144-153: TryFrom<i64> for SBitValue cleanly reuses existing validation

Delegating TryFrom<i64> to new_i64 keeps all range/alignment checks in one place and matches how AdrpOffset is consumed in pcreladdr.rs. With the existing new_i64 tests, this addition looks correct and low‑risk.

harm/src/instructions/dpimm/pcreladdr.rs (2)

19-36: Offset type aliases correctly model ADR/ADRP immediates

Using AdrOffset = SBitValue<21> for ADR and AdrpOffset = SBitValue<21, 12> for ADRP matches the 21‑bit signed PC‑relative immediate, with ALIGN = 12 enforcing 4 KiB page alignment for ADRP while still letting callers think in byte offsets. The accompanying doc comment on AdrpOffset makes the “real address offset” semantics explicit.


106-123: Encoding and tests correctly split and validate 21‑bit PC‑relative offsets

The encoding logic

  • uses LO_BITS = 2,
  • derives immlo = offset.bits() & LO_BITS_MASK and immhi = offset.bits() >> LO_BITS,

which is exactly the ADR/ADRP layout (low 2 bits in immlo, high 19 in immhi). For AdrpOffset, bits() already returns the shifted page offset, so reusing the same split is correct for both instructions.

The PCRELADDR_CASES table plus the test_cases! macro exercise:

  • ADR with negative and positive offsets,
  • ADRP with small and near‑limit positive/negative offsets,
  • both “pre‑validated” (SBitValue::new/new_i64) and “fallible” (adr(..., i32), adrp(..., i64)) constructors.

Together with the GNU as–verified constants, this gives strong coverage that the encoding matches the ARM ISA.

Also applies to: 151-177

@monoid
monoid merged commit 1e9d52f into masterDec 7, 2025
2 checks passed
@monoid
monoid deleted the feat/adrp branch December 7, 2025 16:49
@coderabbitaicoderabbitaiBot mentioned this pull request Dec 25, 2025
@coderabbitaicoderabbitaiBot mentioned this pull request Mar 8, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or requestharmThe `harm` dynamic assembler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@monoid
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' harm: ADR/ADRP by monoid · Pull Request #43 · monoid/harm · GitHub
Skip to content

harm: ADR/ADRP - #43

Merged
monoid merged 6 commits into
masterfrom
feat/adrp
Dec 7, 2025
Merged

harm: ADR/ADRP#43
monoid merged 6 commits into
masterfrom
feat/adrp

Conversation

@monoid

@monoidmonoid commented Nov 22, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added ADR and ADRP support for AArch64 PC-relative address generation.
    • New public constructors to build ADR/ADRP operands, including wider-offset input support (i64).
  • Tests

    • Added unit tests covering encoding and overflow/edge cases for ADR/ADRP offsets.

✏️ Tip: You can customize this high-level summary in your review settings.

@monoidmonoid self-assigned this Nov 22, 2025
@monoidmonoid added enhancement New feature or request harm The `harm` dynamic assembler labels Nov 22, 2025
@coderabbitai

coderabbitaiBot commented Nov 22, 2025

Copy link
Copy Markdown

Walkthrough

Adds a new public pcreladdr module implementing ADR/ADRP pc‑relative address instructions (types, constructors, encoders, tests) and extends SBitValue with TryFrom<i64> to support i64 offset conversion.

Changes

Cohort / File(s)Summary
New pcreladdr instruction module
harm/src/instructions/dpimm.rs, harm/src/instructions/dpimm/pcreladdr.rs
Adds pub mod pcreladdr; and pub use self::pcreladdr::*; and implements ADR/ADRP: AdrOffset/AdrpOffset aliases, Adr/Adrp generic structs, MakeAdr/MakeAdrp traits and impls, adr()/adrp() constructors, LO_BITS/LO_BITS_MASK, RawInstruction::to_code encoders computing immlo/immhi, plus unit tests covering offsets and edge cases.
SBitValue i64 conversion
harm/src/bits.rs
Adds impl TryFrom<i64> for SBitValue<const SIGNIFICANT_BITS: u32, const ALIGN: u32> delegating to SBitValue::new_i64, enabling i64 → SBitValue conversions used by Adrp constructors.

Sequence Diagram(s)

sequenceDiagram
participant Caller as Caller (user code)
participant Ctor as adr()/adrp()
participant Make as MakeAdr/MakeAdrp impl
participant Instr as Adr/Adrp instance
participant Encoder as RawInstruction::to_code
participant Emit as ADR(_only)_pcreladdr
Caller->>Ctor: call adr(rd, offset) or adrp(rd, offset)
Ctor->>Make: offset conversion (i32 / i64) via TryFrom / new_i64
Make->>Instr: construct Adr/Adrp with rd and validated offset
Instr->>Encoder: to_code()
Encoder->>Encoder: immlo = bits & LO_BITS_MASK
Encoder->>Encoder: immhi = bits >> LO_BITS
Encoder->>Emit: ADR_only_pcreladdr(immlo, immhi, rd) / ADRP_only_pcreladdr(...)
Emit-->>Encoder: InstructionCode
Encoder-->>Caller: InstructionCode
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify LO_BITS / LO_BITS_MASK and the shift/mask math vs. ARMv8 spec (pcreladdr encoding).
  • Check TryFrom<i64> correctness and sign/align handling in SBitValue::new_i64.
  • Review trait impls (MakeAdr/MakeAdrp) and adr/adrp generic signatures for ergonomic/compile-time behavior.
  • Inspect unit tests for comprehensive edge-case coverage (alignment, overflow, sign-extension).

Possibly related PRs

Poem

🐰 I nibble bits and split them fine,
ADR and ADRP hop in line.
Low bits tucked and highs take flight,
I stitch the word and send it right. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 20.00% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'harm: ADR/ADRP' directly and specifically summarizes the main changes, which introduce ADR and ADRP instruction support to the harm crate.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/adrp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
harm/src/instructions/dpimm/pcreladdr.rs (5)

19-29: Add documentation comments for public structs.

The public Adr and Adrp structs lack documentation. Consider adding doc comments explaining their purpose, the instruction encoding they represent, and usage examples.

Example:

+/// ADR (Address to Register) instruction.+///+/// Loads a PC-relative address with a byte offset into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adr<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}
+/// ADRP (Address of 4KB Page to Register) instruction.+///+/// Loads a PC-relative address of a 4KB page into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adrp<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}

31-57: Consider simplifying the trait-based construction pattern.

The MakeAdr and MakeAdrp traits currently have only one implementation each. Unless additional implementations are planned, consider using direct constructors to reduce complexity.

If you anticipate adding more implementations (e.g., for different offset representations), this pattern makes sense for future extensibility. Otherwise, the traits add indirection without immediate benefit.


59-77: Add documentation comments for public constructor functions.

The adr and adrp functions are the primary public API but lack documentation. Add doc comments explaining parameters, usage, and return types.

Example:

+/// Constructs an ADR (Address to Register) instruction.+///+/// # Arguments+/// * `rd` - Destination register+/// * `offset` - PC-relative byte offset+///+/// # Example+/// ```ignore+/// let instr = adr(X0, AdrOffset::new(0x1000).unwrap());+/// ```
pub fn adr<OffsetIn>(
rd: impl IntoReg<RegOrZero64>,
offset: OffsetIn,
) -> <Adr<AdrOffset> as MakeAdr<OffsetIn>>::Outcome

79-80: Consider adding a comment explaining the encoding split.

The constants define how the offset is split for instruction encoding. A brief comment would improve maintainability.

Example:

+// ADR/ADRP encoding splits the 19-bit offset into:+// immlo (bits 0-1) and immhi (bits 2-18)
const LO_BITS: u32 = 2;
const LO_BITS_MASK: u32 = (1 << LO_BITS) - 1;

98-137: Expand test coverage to include edge cases.

The current tests only cover 4 specific values. Consider adding tests for:

  • Minimum valid offset (e.g., -262144 for ADR, -262144 << 12 for ADRP)
  • Maximum valid offset (e.g., 262143 for ADR, 262143 << 12 for ADRP)
  • Zero offset
  • Boundary values that test the 19-bit signed range
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4112605 and f000acb.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🪛 GitHub Actions: Rust
harm/src/instructions/dpimm/pcreladdr.rs

[error] 10-10: Rustfmt formatting check failed (imports order). Run 'cargo fmt' to fix formatting in this file.


[error] 99-99: Rustfmt formatting check failed (test module formatting). Run 'cargo fmt' to fix formatting in this file.

🔇 Additional comments (3)
harm/src/instructions/dpimm.rs (1)

8-11: LGTM! Module integration follows established pattern.

The new pcreladdr module is correctly declared and re-exported, following the same pattern as existing modules (log_imm, movewide).

harm/src/instructions/dpimm/pcreladdr.rs (2)

82-96: LGTM! Encoding implementations are correct.

The RawInstruction implementations correctly split the offset into immlo (low 2 bits) and immhi (high bits) for ARM64 ADR/ADRP instruction encoding.


116-134: Verify and document expected instruction codes in tests.

Multiple TODO comments indicate the test values haven't been verified against a reference. Consider:

  1. Verifying the expected instruction codes against the ARM Architecture Reference Manual or using a reference assembler
  2. Adding comments documenting how the expected values were derived
  3. Removing the TODO comments once verified

Do you want me to help generate a verification script to compare these encodings against a reference implementation or documentation?

Comment threadharm/src/instructions/dpimm/pcreladdr.rs
Comment threadharm/src/instructions/dpimm/pcreladdr.rs

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

34-60: Consider simplifying the constructor pattern if not required by codebase conventions.

The trait-based constructor pattern (MakeAdr/MakeAdrp with associated types) adds complexity compared to direct impl blocks with new() methods. Unless this pattern is used consistently across the codebase for extensibility, consider a simpler approach:

implAdr<AdrOffset>{pubfnnew(rd:RegOrZero64,offset:AdrOffset) -> Self{Self{reg: rd, offset }}}

However, if this pattern enables future support for multiple offset input types (which the generic OffsetIn parameter suggests), the current design is reasonable.


114-139: Verify and document the expected instruction encodings.

Three tests contain TODO comments about checking correctness of the hardcoded assertion values. Consider verifying these encodings against the ARM Architecture Reference Manual or using an assembler/disassembler to confirm, then document why each expected value is correct (similar to how test_adr_m4 is clear about encoding -4).

You can verify the encodings by:

  1. Cross-referencing with ARM documentation for ADR/ADRP encoding format
  2. Using an ARM assembler/disassembler to generate and verify the instruction bytes
  3. Adding comments explaining the bit layout for each test case
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f000acb and ff98029.

📒 Files selected for processing (1)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

62-80: LGTM on public constructors.

The generic constructor functions provide a flexible API with proper type conversions via IntoReg<RegOrZero64> and trait-based constraints.


82-99: Correct bit manipulation for instruction encoding.

The immediate splitting logic correctly extracts immlo (low 2 bits) and immhi (high bits) for ADR/ADRP encoding. The minor code duplication between Adr and Adrp implementations is acceptable given the simplicity.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff98029 and 592c05a.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm.rs (1)

8-11: Consistent wiring of new pcreladdr module

The new submodule and re-export mirror the existing log_imm/movewide pattern and cleanly expose ADR/ADRP under dpimm. No issues here.

harm/src/instructions/dpimm/pcreladdr.rs (1)

82-99: ADR/ADRP immediate encoding verified correct per ARM AArch64 specification

The immediate splitting into 2-bit immlo and 19-bit immhi fields is correct and properly placed at instruction bits [30:29] and [23:5] respectively. Verified test encodings against ARM specification:

  • ADR offset -4, Rd=X29 → 0x103ffffd ✓
  • ADR offset 0x12345, Rd=X28 → 0x30091a3c ✓
  • ADRP offset -4<<12, Rd=X27 → 0x903ffffb ✓

All encodings match ARM AArch64 ADR/ADRP specification.

Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
@coderabbitai

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)

38-84: Trait‑based adr/adrp constructors are type‑safe and future‑proof

The MakeAdr/MakeAdrp traits plus the generic adr/adrp helpers cleanly separate construction from encoding and ensure all range/alignment checks go through SBitValue::try_from (i32 for ADR, i64 for ADRP). This yields a nice API where adr/adrp work both with pre‑validated offsets and raw integers without duplicating logic.

If you ever want adr to accept i64 offsets as well (for symmetry with adrp and the new TryFrom<i64> on SBitValue), adding an impl MakeAdr<i64> for Adr<AdrOffset> that calls offset.try_into() would be a straightforward extension.

Also applies to: 86-104

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc1f706 and 996e9f7.

📒 Files selected for processing (2)
  • harm/src/bits.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
harm/src/bits.rs (1)
harm/src/instructions/arith.rs (2)
  • try_from (123-125)
  • try_from (197-206)
harm/src/instructions/dpimm/pcreladdr.rs (1)
harm/src/bits.rs (2)
  • bits (83-85)
  • bits (213-215)
🔇 Additional comments (3)
harm/src/bits.rs (1)

144-153: TryFrom<i64> for SBitValue cleanly reuses existing validation

Delegating TryFrom<i64> to new_i64 keeps all range/alignment checks in one place and matches how AdrpOffset is consumed in pcreladdr.rs. With the existing new_i64 tests, this addition looks correct and low‑risk.

harm/src/instructions/dpimm/pcreladdr.rs (2)

19-36: Offset type aliases correctly model ADR/ADRP immediates

Using AdrOffset = SBitValue<21> for ADR and AdrpOffset = SBitValue<21, 12> for ADRP matches the 21‑bit signed PC‑relative immediate, with ALIGN = 12 enforcing 4 KiB page alignment for ADRP while still letting callers think in byte offsets. The accompanying doc comment on AdrpOffset makes the “real address offset” semantics explicit.


106-123: Encoding and tests correctly split and validate 21‑bit PC‑relative offsets

The encoding logic

  • uses LO_BITS = 2,
  • derives immlo = offset.bits() & LO_BITS_MASK and immhi = offset.bits() >> LO_BITS,

which is exactly the ADR/ADRP layout (low 2 bits in immlo, high 19 in immhi). For AdrpOffset, bits() already returns the shifted page offset, so reusing the same split is correct for both instructions.

The PCRELADDR_CASES table plus the test_cases! macro exercise:

  • ADR with negative and positive offsets,
  • ADRP with small and near‑limit positive/negative offsets,
  • both “pre‑validated” (SBitValue::new/new_i64) and “fallible” (adr(..., i32), adrp(..., i64)) constructors.

Together with the GNU as–verified constants, this gives strong coverage that the encoding matches the ARM ISA.

Also applies to: 151-177

@monoid
monoid merged commit 1e9d52f into masterDec 7, 2025
2 checks passed
@monoid
monoid deleted the feat/adrp branch December 7, 2025 16:49
@coderabbitaicoderabbitaiBot mentioned this pull request Dec 25, 2025
@coderabbitaicoderabbitaiBot mentioned this pull request Mar 8, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or requestharmThe `harm` dynamic assembler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@monoid
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); harm: ADR/ADRP by monoid · Pull Request #43 · monoid/harm · GitHub
Skip to content

harm: ADR/ADRP - #43

Merged
monoid merged 6 commits into
masterfrom
feat/adrp
Dec 7, 2025
Merged

harm: ADR/ADRP#43
monoid merged 6 commits into
masterfrom
feat/adrp

Conversation

@monoid

@monoidmonoid commented Nov 22, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added ADR and ADRP support for AArch64 PC-relative address generation.
    • New public constructors to build ADR/ADRP operands, including wider-offset input support (i64).
  • Tests

    • Added unit tests covering encoding and overflow/edge cases for ADR/ADRP offsets.

✏️ Tip: You can customize this high-level summary in your review settings.

@monoidmonoid self-assigned this Nov 22, 2025
@monoidmonoid added enhancement New feature or request harm The `harm` dynamic assembler labels Nov 22, 2025
@coderabbitai

coderabbitaiBot commented Nov 22, 2025

Copy link
Copy Markdown

Walkthrough

Adds a new public pcreladdr module implementing ADR/ADRP pc‑relative address instructions (types, constructors, encoders, tests) and extends SBitValue with TryFrom<i64> to support i64 offset conversion.

Changes

Cohort / File(s)Summary
New pcreladdr instruction module
harm/src/instructions/dpimm.rs, harm/src/instructions/dpimm/pcreladdr.rs
Adds pub mod pcreladdr; and pub use self::pcreladdr::*; and implements ADR/ADRP: AdrOffset/AdrpOffset aliases, Adr/Adrp generic structs, MakeAdr/MakeAdrp traits and impls, adr()/adrp() constructors, LO_BITS/LO_BITS_MASK, RawInstruction::to_code encoders computing immlo/immhi, plus unit tests covering offsets and edge cases.
SBitValue i64 conversion
harm/src/bits.rs
Adds impl TryFrom<i64> for SBitValue<const SIGNIFICANT_BITS: u32, const ALIGN: u32> delegating to SBitValue::new_i64, enabling i64 → SBitValue conversions used by Adrp constructors.

Sequence Diagram(s)

sequenceDiagram
participant Caller as Caller (user code)
participant Ctor as adr()/adrp()
participant Make as MakeAdr/MakeAdrp impl
participant Instr as Adr/Adrp instance
participant Encoder as RawInstruction::to_code
participant Emit as ADR(_only)_pcreladdr
Caller->>Ctor: call adr(rd, offset) or adrp(rd, offset)
Ctor->>Make: offset conversion (i32 / i64) via TryFrom / new_i64
Make->>Instr: construct Adr/Adrp with rd and validated offset
Instr->>Encoder: to_code()
Encoder->>Encoder: immlo = bits & LO_BITS_MASK
Encoder->>Encoder: immhi = bits >> LO_BITS
Encoder->>Emit: ADR_only_pcreladdr(immlo, immhi, rd) / ADRP_only_pcreladdr(...)
Emit-->>Encoder: InstructionCode
Encoder-->>Caller: InstructionCode
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify LO_BITS / LO_BITS_MASK and the shift/mask math vs. ARMv8 spec (pcreladdr encoding).
  • Check TryFrom<i64> correctness and sign/align handling in SBitValue::new_i64.
  • Review trait impls (MakeAdr/MakeAdrp) and adr/adrp generic signatures for ergonomic/compile-time behavior.
  • Inspect unit tests for comprehensive edge-case coverage (alignment, overflow, sign-extension).

Possibly related PRs

Poem

🐰 I nibble bits and split them fine,
ADR and ADRP hop in line.
Low bits tucked and highs take flight,
I stitch the word and send it right. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 20.00% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'harm: ADR/ADRP' directly and specifically summarizes the main changes, which introduce ADR and ADRP instruction support to the harm crate.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/adrp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
harm/src/instructions/dpimm/pcreladdr.rs (5)

19-29: Add documentation comments for public structs.

The public Adr and Adrp structs lack documentation. Consider adding doc comments explaining their purpose, the instruction encoding they represent, and usage examples.

Example:

+/// ADR (Address to Register) instruction.+///+/// Loads a PC-relative address with a byte offset into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adr<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}
+/// ADRP (Address of 4KB Page to Register) instruction.+///+/// Loads a PC-relative address of a 4KB page into a register.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Adrp<Offset> {
pub reg: RegOrZero64,
pub offset: Offset,
}

31-57: Consider simplifying the trait-based construction pattern.

The MakeAdr and MakeAdrp traits currently have only one implementation each. Unless additional implementations are planned, consider using direct constructors to reduce complexity.

If you anticipate adding more implementations (e.g., for different offset representations), this pattern makes sense for future extensibility. Otherwise, the traits add indirection without immediate benefit.


59-77: Add documentation comments for public constructor functions.

The adr and adrp functions are the primary public API but lack documentation. Add doc comments explaining parameters, usage, and return types.

Example:

+/// Constructs an ADR (Address to Register) instruction.+///+/// # Arguments+/// * `rd` - Destination register+/// * `offset` - PC-relative byte offset+///+/// # Example+/// ```ignore+/// let instr = adr(X0, AdrOffset::new(0x1000).unwrap());+/// ```
pub fn adr<OffsetIn>(
rd: impl IntoReg<RegOrZero64>,
offset: OffsetIn,
) -> <Adr<AdrOffset> as MakeAdr<OffsetIn>>::Outcome

79-80: Consider adding a comment explaining the encoding split.

The constants define how the offset is split for instruction encoding. A brief comment would improve maintainability.

Example:

+// ADR/ADRP encoding splits the 19-bit offset into:+// immlo (bits 0-1) and immhi (bits 2-18)
const LO_BITS: u32 = 2;
const LO_BITS_MASK: u32 = (1 << LO_BITS) - 1;

98-137: Expand test coverage to include edge cases.

The current tests only cover 4 specific values. Consider adding tests for:

  • Minimum valid offset (e.g., -262144 for ADR, -262144 << 12 for ADRP)
  • Maximum valid offset (e.g., 262143 for ADR, 262143 << 12 for ADRP)
  • Zero offset
  • Boundary values that test the 19-bit signed range
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4112605 and f000acb.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🪛 GitHub Actions: Rust
harm/src/instructions/dpimm/pcreladdr.rs

[error] 10-10: Rustfmt formatting check failed (imports order). Run 'cargo fmt' to fix formatting in this file.


[error] 99-99: Rustfmt formatting check failed (test module formatting). Run 'cargo fmt' to fix formatting in this file.

🔇 Additional comments (3)
harm/src/instructions/dpimm.rs (1)

8-11: LGTM! Module integration follows established pattern.

The new pcreladdr module is correctly declared and re-exported, following the same pattern as existing modules (log_imm, movewide).

harm/src/instructions/dpimm/pcreladdr.rs (2)

82-96: LGTM! Encoding implementations are correct.

The RawInstruction implementations correctly split the offset into immlo (low 2 bits) and immhi (high bits) for ARM64 ADR/ADRP instruction encoding.


116-134: Verify and document expected instruction codes in tests.

Multiple TODO comments indicate the test values haven't been verified against a reference. Consider:

  1. Verifying the expected instruction codes against the ARM Architecture Reference Manual or using a reference assembler
  2. Adding comments documenting how the expected values were derived
  3. Removing the TODO comments once verified

Do you want me to help generate a verification script to compare these encodings against a reference implementation or documentation?

Comment threadharm/src/instructions/dpimm/pcreladdr.rs
Comment threadharm/src/instructions/dpimm/pcreladdr.rs

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

34-60: Consider simplifying the constructor pattern if not required by codebase conventions.

The trait-based constructor pattern (MakeAdr/MakeAdrp with associated types) adds complexity compared to direct impl blocks with new() methods. Unless this pattern is used consistently across the codebase for extensibility, consider a simpler approach:

implAdr<AdrOffset>{pubfnnew(rd:RegOrZero64,offset:AdrOffset) -> Self{Self{reg: rd, offset }}}

However, if this pattern enables future support for multiple offset input types (which the generic OffsetIn parameter suggests), the current design is reasonable.


114-139: Verify and document the expected instruction encodings.

Three tests contain TODO comments about checking correctness of the hardcoded assertion values. Consider verifying these encodings against the ARM Architecture Reference Manual or using an assembler/disassembler to confirm, then document why each expected value is correct (similar to how test_adr_m4 is clear about encoding -4).

You can verify the encodings by:

  1. Cross-referencing with ARM documentation for ADR/ADRP encoding format
  2. Using an ARM assembler/disassembler to generate and verify the instruction bytes
  3. Adding comments explaining the bit layout for each test case
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f000acb and ff98029.

📒 Files selected for processing (1)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm/pcreladdr.rs (2)

62-80: LGTM on public constructors.

The generic constructor functions provide a flexible API with proper type conversions via IntoReg<RegOrZero64> and trait-based constraints.


82-99: Correct bit manipulation for instruction encoding.

The immediate splitting logic correctly extracts immlo (low 2 bits) and immhi (high bits) for ADR/ADRP encoding. The minor code duplication between Adr and Adrp implementations is acceptable given the simplicity.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff98029 and 592c05a.

📒 Files selected for processing (2)
  • harm/src/instructions/dpimm.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
harm/src/instructions/dpimm/pcreladdr.rs (2)
harm/src/instructions.rs (1)
  • instructions (48-50)
aarchmrs-types/src/instruction_code.rs (1)
  • unpack (22-24)
🔇 Additional comments (2)
harm/src/instructions/dpimm.rs (1)

8-11: Consistent wiring of new pcreladdr module

The new submodule and re-export mirror the existing log_imm/movewide pattern and cleanly expose ADR/ADRP under dpimm. No issues here.

harm/src/instructions/dpimm/pcreladdr.rs (1)

82-99: ADR/ADRP immediate encoding verified correct per ARM AArch64 specification

The immediate splitting into 2-bit immlo and 19-bit immhi fields is correct and properly placed at instruction bits [30:29] and [23:5] respectively. Verified test encodings against ARM specification:

  • ADR offset -4, Rd=X29 → 0x103ffffd ✓
  • ADR offset 0x12345, Rd=X28 → 0x30091a3c ✓
  • ADRP offset -4<<12, Rd=X27 → 0x903ffffb ✓

All encodings match ARM AArch64 ADR/ADRP specification.

Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
Comment threadharm/src/instructions/dpimm/pcreladdr.rs Outdated
@coderabbitai

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
harm/src/instructions/dpimm/pcreladdr.rs (1)

38-84: Trait‑based adr/adrp constructors are type‑safe and future‑proof

The MakeAdr/MakeAdrp traits plus the generic adr/adrp helpers cleanly separate construction from encoding and ensure all range/alignment checks go through SBitValue::try_from (i32 for ADR, i64 for ADRP). This yields a nice API where adr/adrp work both with pre‑validated offsets and raw integers without duplicating logic.

If you ever want adr to accept i64 offsets as well (for symmetry with adrp and the new TryFrom<i64> on SBitValue), adding an impl MakeAdr<i64> for Adr<AdrOffset> that calls offset.try_into() would be a straightforward extension.

Also applies to: 86-104

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc1f706 and 996e9f7.

📒 Files selected for processing (2)
  • harm/src/bits.rs (1 hunks)
  • harm/src/instructions/dpimm/pcreladdr.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
harm/src/bits.rs (1)
harm/src/instructions/arith.rs (2)
  • try_from (123-125)
  • try_from (197-206)
harm/src/instructions/dpimm/pcreladdr.rs (1)
harm/src/bits.rs (2)
  • bits (83-85)
  • bits (213-215)
🔇 Additional comments (3)
harm/src/bits.rs (1)

144-153: TryFrom<i64> for SBitValue cleanly reuses existing validation

Delegating TryFrom<i64> to new_i64 keeps all range/alignment checks in one place and matches how AdrpOffset is consumed in pcreladdr.rs. With the existing new_i64 tests, this addition looks correct and low‑risk.

harm/src/instructions/dpimm/pcreladdr.rs (2)

19-36: Offset type aliases correctly model ADR/ADRP immediates

Using AdrOffset = SBitValue<21> for ADR and AdrpOffset = SBitValue<21, 12> for ADRP matches the 21‑bit signed PC‑relative immediate, with ALIGN = 12 enforcing 4 KiB page alignment for ADRP while still letting callers think in byte offsets. The accompanying doc comment on AdrpOffset makes the “real address offset” semantics explicit.


106-123: Encoding and tests correctly split and validate 21‑bit PC‑relative offsets

The encoding logic

  • uses LO_BITS = 2,
  • derives immlo = offset.bits() & LO_BITS_MASK and immhi = offset.bits() >> LO_BITS,

which is exactly the ADR/ADRP layout (low 2 bits in immlo, high 19 in immhi). For AdrpOffset, bits() already returns the shifted page offset, so reusing the same split is correct for both instructions.

The PCRELADDR_CASES table plus the test_cases! macro exercise:

  • ADR with negative and positive offsets,
  • ADRP with small and near‑limit positive/negative offsets,
  • both “pre‑validated” (SBitValue::new/new_i64) and “fallible” (adr(..., i32), adrp(..., i64)) constructors.

Together with the GNU as–verified constants, this gives strong coverage that the encoding matches the ARM ISA.

Also applies to: 151-177

@monoid
monoid merged commit 1e9d52f into masterDec 7, 2025
2 checks passed
@monoid
monoid deleted the feat/adrp branch December 7, 2025 16:49
@coderabbitaicoderabbitaiBot mentioned this pull request Dec 25, 2025
@coderabbitaicoderabbitaiBot mentioned this pull request Mar 8, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or requestharmThe `harm` dynamic assembler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@monoid