# ARM64Encoder in vphone-cli Firmware Patching: Pure-Swift ARM64 Instruction Generation

> Discover how ARM64Encoder in vphone-cli generates pure-Swift ARM64 instructions for safe iOS firmware patching. Rewrite binaries without external assemblers.

- Repository: [Lakr/vphone-cli](https://github.com/Lakr233/vphone-cli)
- Tags: internals
- Published: 2026-09-10

---

**ARM64Encoder is a lightweight, pure-Swift utility that generates PC-relative ARM64 machine instructions on-the-fly, enabling vphone-cli to safely rewrite iOS firmware binaries without relying on external assemblers.**

The vphone-cli project provides specialized tools for modifying iOS kernel and boot components. At its core, **ARM64Encoder** handles the deterministic construction of binary instructions, allowing developers to patch iBoot, TXM, and kernel binaries using in-memory encoding rather than platform-specific external tooling.

## Core Instruction Encoding Capabilities

The encoder supports deterministic generation of essential ARM64 instruction types required for firmware manipulation. Each method returns a 4-byte `Data` value representing the encoded instruction, ready for direct binary injection.

### Branch Instructions (B, BL, TBZ/TBNZ)

**ARM64Encoder** encodes unconditional and conditional branches with correct signed offset handling. This allows patchers to redirect execution flow by calculating PC-relative offsets between the current instruction and target addresses.

```swift
// Encode an unconditional branch from 0x1000 to 0x2000
if let branch = ARM64Encoder.encodeB(from: 0x1000, to: 0x2000) {
    print(branch.hexEncodedString())   // → 0x14000000
}

```

The encoder also supports **BL** (branch with link) for function calls and **TBZ/TBNZ** (test bit and branch) for conditional flow control.

### Address Loading Sequences (ADRP + ADD)

Firmware patches frequently need to materialize absolute addresses relative to the current program counter. **ARM64Encoder** generates the standard `ADRP` + `ADD` sequence used across Apple's 64-bit ARM architecture.

```swift
let pc      = UInt64(0x1000)
let target  = UInt64(0x2000)      // 4 KB-aligned pages
let adrp    = ARM64Encoder.encodeADRP(rd: 2, pc: pc, target: target)!
let addImm  = ARM64Encoder.encodeAddImm12(rd: 2, rn: 2, imm12: 0x0)!

```

According to the vphone-cli source code, this pattern appears in [`sources/FirmwarePatcher/IBoot/IBootPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/IBoot/IBootPatcher.swift) at lines 348-356, where the encoder builds an address-loading pair to redirect a function pointer within iBoot firmware.

### Immediate and Register Moves (MOVZ, MOV)

The utility encodes immediate value loading and register-to-register transfers essential for modifying constants and clearing registers during jailbreak patches.

```swift
// Load immediate 0x1 into register W6
let bytes = ARM64Encoder.encodeMovzW(rd: 6, imm16: 0x1)

// Move XZR (zero register) to X8: mov x8, xzr
let mov = ARM64Encoder.encodeMovX(rd: 8, rm: 31)

```

This capability is heavily utilized in [`sources/FirmwarePatcher/Kernel/JBPatches/KernelJBPatchSecureRoot.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/Kernel/JBPatches/KernelJBPatchSecureRoot.swift) at line 49, where immediate moves replace existing instructions to disable security checks.

### Branch Target Decoding

Beyond encoding, **ARM64Encoder** decodes branch targets from existing instructions. This allows patchers to analyze firmware code before applying modifications, ensuring that replaced instructions preserve original execution semantics.

```swift
let pc   = 0x1000
let dest = 0x2000
if let bl = ARM64Encoder.encodeBL(from: pc, to: dest) {
    let insn = UInt32(littleEndian: bl.withUnsafeBytes { $0.load(as: UInt32.self) })
    let target = ARM64Encoder.decodeBranchTarget(insn: insn, pc: UInt64(pc))
    assert(target == UInt64(dest))
}

```

## Advantages Over External Assemblers

Using **ARM64Encoder** instead of the Keystone assembler provides three critical benefits for firmware patching workflows:

1. **Deterministic output** – The pure-Swift implementation produces identical byte sequences across platforms without requiring external binaries or dynamic libraries.
2. **Safety validation** – Encoders strictly validate operands including alignment, immediate ranges, and register limits before emitting bytes, reducing the risk of corrupting firmware images.
3. **Performance** – Encoding occurs entirely in-memory using simple bitwise operations, making it ideal for batch patch generation scenarios where speed matters.

## Real-World Implementation in vphone-cli

The encoder serves as the foundation for multiple firmware patching modules within the repository.

### iBoot Patching

In [`sources/FirmwarePatcher/IBoot/IBootPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/IBoot/IBootPatcher.swift), the encoder constructs PC-relative address calculations to modify bootloader behavior:

```swift
guard let newAdrp = ARM64Encoder.encodeADRP(rd: 2, pc: UInt64(adrpOff), target: UInt64(newOff)) else { … }
guard let newAdd   = ARM64Encoder.encodeAddImm12(rd: 2, rn: 2, imm12: imm12) else { … }

```

This pattern appears at lines 348-356, demonstrating how the tool rewrites function pointer tables within iBoot binaries.

### TXM Device Patching

The TXM patching module at [`sources/FirmwarePatcher/TXM/TXMDevPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/TXM/TXMDevPatcher.swift) utilizes branch encoding to redirect execution back to stub code. At line 300, the implementation generates a branch instruction using:

```swift
guard let bInsn = ARM64Encoder.encodeB(from: body + 4, to: epilogueOff) else { … }

```

### Kernel Jailbreak Patches

Various kernel patches located in `sources/FirmwarePatcher/Kernel/JBPatches/` leverage the encoder for safe instruction replacement. The secure root patch specifically uses `encodeMovzW` to inject immediate values that bypass security constraints.

## Project Structure and Testing

The encoder implementation spans several key files within the vphone-cli repository:

- **[`sources/FirmwarePatcher/ARM64/ARM64Encoder.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/ARM64/ARM64Encoder.swift)** – Core encoding and decoding routines for all supported instruction types.
- **[`sources/FirmwarePatcher/ARM64/ARM64Constants.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/ARM64/ARM64Constants.swift)** – Pre-computed constant tables generated by the encoder at build time.
- **[`tests/FirmwarePatcherTests/FirmwarePatcherTests.swift`](https://github.com/Lakr233/vphone-cli/blob/main/tests/FirmwarePatcherTests/FirmwarePatcherTests.swift)** – Unit tests verifying correctness of `encodeB`, `encodeBL`, `encodeADRP`, and other critical methods.

These files collectively ensure that **ARM64Encoder** maintains bit-perfect accuracy when generating instructions for ARM64 firmware components.

## Summary

- **ARM64Encoder** provides pure-Swift generation of PC-relative ARM64 instructions for firmware modification.
- The encoder supports branches (`B`, `BL`), address loading (`ADRP`+`ADD`), and immediate moves (`MOVZ`, `MOV`) with built-in operand validation.
- It eliminates dependencies on external assemblers like Keystone, offering deterministic, cross-platform patch generation.
- Core usage appears in [`IBootPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/IBootPatcher.swift), [`TXMDevPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/TXMDevPatcher.swift), and various kernel jailbreak patches across the vphone-cli codebase.
- Comprehensive unit tests in [`FirmwarePatcherTests.swift`](https://github.com/Lakr233/vphone-cli/blob/main/FirmwarePatcherTests.swift) verify encoding correctness for production firmware manipulation.

## Frequently Asked Questions

### How does ARM64Encoder differ from the Keystone assembler?

**ARM64Encoder** is a self-contained Swift implementation that generates instructions deterministically without external dependencies. Unlike Keystone, which requires platform-specific binaries and runtime linking, the encoder performs all operations in-memory using bitwise calculations, ensuring consistent output across macOS, Linux, and other development environments.

### What types of ARM64 instructions can ARM64Encoder generate?

The encoder supports **unconditional branches** (`B`), **branch-with-link** (`BL`), **test-and-branch** (`TBZ`/`TBNZ`), **address page loading** (`ADRP`), **immediate additions** (`ADD` with 12-bit immediates), **immediate moves** (`MOVZ`), and **register moves** (`MOV Xd, Xm`). It also decodes branch targets from existing instructions for analysis purposes.

### How does ARM64Encoder ensure patch safety?

Each encoding method validates operands before emission, checking for proper 4-byte alignment in branch targets, valid immediate ranges, and legal register numbers. This strict validation prevents the generation of malformed instructions that could corrupt iBoot, kernel, or TXM firmware images during the patching process.

### Where is ARM64Encoder used within the vphone-cli codebase?

The encoder appears throughout the firmware patching system, specifically in [`sources/FirmwarePatcher/IBoot/IBootPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/IBoot/IBootPatcher.swift) for bootloader modifications, [`sources/FirmwarePatcher/TXM/TXMDevPatcher.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/FirmwarePatcher/TXM/TXMDevPatcher.swift) for device-specific patches, and multiple files under `sources/FirmwarePatcher/Kernel/JBPatches/` for jailbreak implementations including [`KernelJBPatchSecureRoot.swift`](https://github.com/Lakr233/vphone-cli/blob/main/KernelJBPatchSecureRoot.swift).