# Ghidra Processor Module Differences: Comparing x86, ARM, AArch64, and MIPS

> Explore Ghidra processor module differences for x86, ARM, AArch64, and MIPS. Understand SLEIGH definitions, register specs, plugins & emulation handlers to optimize your reverse engineering workflow.

- Repository: [National Security Agency/ghidra](https://github.com/NationalSecurityAgency/ghidra)
- Tags: deep-dive
- Published: 2026-03-04

---

**Ghidra processor modules for x86, ARM, AArch64, and MIPS each implement architecture-specific semantics through distinct SLEIGH language definitions, register specifications, analysis plugins, and emulation handlers located under `Ghidra/Processors/`.**

Ghidra's open-source reverse engineering framework maintained by the NationalSecurityAgency provides specialized support for CPU architectures through dedicated processor modules. Each module resides in its own subdirectory—such as `Ghidra/Processors/x86` or `Ghidra/Processors/AARCH64`—and contains the complete infrastructure needed to disassemble, analyze, and emulate binaries for that specific instruction set architecture.

## SLEIGH Language Definitions and Instruction Semantics

The **SLEIGH** language definition serves as the authoritative description of an ISA's instruction encoding and semantics, implemented in `.slaspec` files that generate p-code for Ghidra's intermediate representation.

**x86** utilizes `Ghidra/Processors/x86/data/languages/x86.slaspec`, which includes dozens of supplemental `.sinc` files adding vector-extension semantics such as `avx.sinc`, `bmi1.sinc`, and SHA instructions. This modular approach accommodates the architecture's extensive vendor-specific extensions across 16-bit real-mode, 32-bit protected-mode, and 64-bit long-mode variants.

**ARM (32-bit)** splits definitions across multiple files like `ARM8_le.slaspec` and `ARM8_be.slaspec` to capture differing register banks, endianness, and instruction sets including Thumb-1 and Thumb-2. The SLEIGH file expands ARM's three-operand format to p-code while handling condition codes and mode-specific banked registers.

**AArch64** employs a minimal `AARCH64.slaspec` that functions as a thin wrapper including `AARCH64instructions.sinc`. Because the ARMv8-A ISA is more orthogonal than its predecessor, this architecture requires fewer conditional variations in its language definition while supporting fixed-width 64-bit operations and advanced SIMD (ASIMD) extensions.

**MIPS** provides separate specifications for each address-space width and endianness, such as `mips32le.slaspec` and `mips32be.slaspec`, with additional variants for MIPS-64, micro-MIPS, and MIPS-R6. The SLEIGH definitions specifically handle the architecture's characteristic branch delay slots and coprocessor instructions.

## Register Metadata and Processor Specifications

Each processor module defines its register set through `.pspec` and `.ldefs` files that map architectural registers into Ghidra's internal `Register` objects.

In `Ghidra/Processors/x86/data/languages/x86.pspec` and `x86.ldefs`, definitions span 16-, 32-, and 64-bit general-purpose registers, segment registers, flags, and extensive SIMD registers (XMM/YMM/ZMM). The **x86** module must accommodate overlapping register views (such as `al`/`ah`/`ax`/`eax`/`rax`) within its specification.

The **ARM** module's `ARM8.pspec` enumerates R0-R15, the CPSR, and banked registers for different processor modes (FIQ, IRQ, Supervisor, etc.), reflecting the architecture's exception model.

**AArch64** defines a cleaner register file in `AARCH64.pspec` featuring X0-X30 general-purpose registers, SP, PC, PSTATE, and 128-bit SIMD/FP registers V0-V31. This 64-bit specification eliminates the banking complexity present in the 32-bit ARM module.

For **MIPS**, `mips.ldefs` catalogs the general-purpose registers `$0-$31`, the HI/LO registers for multiplication results, CP0 system control registers, and floating-point registers. The specification must account for both the 32-bit and 64-bit register widths across different MIPS variants.

## Analysis Plugins and Auto-Analysis

Architecture-specific analysis is implemented through Java classes extending Ghidra's analyzer framework, with each processor module containing specialized logic for detecting compiler idioms and architecture quirks.

The **x86** module includes [`X86Analyzer.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/X86Analyzer.java) located at [`Ghidra/Processors/x86/src/main/java/ghidra/app/plugin/core/analysis/X86Analyzer.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Processors/x86/src/main/java/ghidra/app/plugin/core/analysis/X86Analyzer.java). This analyzer provides constant-propagation analysis with special handling for `LEA` (Load Effective Address) operand references and x86-specific addressing modes.

**ARM** analysis is handled by `ARMProcessorAnalyzer` within `ARM/src/main/java/ghidra/app/plugin/core/analysis`, which adds Thumb/ARM mode detection and conditional-execution analysis to handle the architecture's predicated instructions.

For **AArch64**, the [`AARCH64PltThunkAnalyzer.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/AARCH64PltThunkAnalyzer.java) at [`Ghidra/Processors/AARCH64/src/main/java/ghidra/app/plugin/core/analysis/AARCH64PltThunkAnalyzer.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Processors/AARCH64/src/main/java/ghidra/app/plugin/core/analysis/AARCH64PltThunkAnalyzer.java) focuses on PLT (Procedure Linkage Table) thunk discovery and linker-generated symbol identification specific to 64-bit ARM binaries.

The **MIPS** module provides [`MipsSymbolAnalyzer.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/MipsSymbolAnalyzer.java) and `MipsPreAnalyzer` in `Ghidra/Processors/MIPS/src/main/java/ghidra/app/plugin/core/analysis`, which analyze GP-relative code sequences and handle the architectural conventions of the `$gp` register for global data access.

## Emulation State Modifiers

Ghidra's generic p-code emulator requires architecture-specific adapters to handle privileged state transitions and ISA quirks, implemented through `EmulateInstructionStateModifier` subclasses.

The **x86** module provides `X86EmulateInstructionStateModifier` to manage privileged mode changes, segment overrides, and the complex flag behaviors of the x86 family.

**ARM** emulation uses `ARMEmulateInstructionStateModifier` to handle processor mode switches, CPSR updates, and the transition between ARM and Thumb instruction sets during execution.

For **AArch64**, `AARCH64EmulateInstructionStateModifier` tracks PSTATE updates and Exception Level (EL) transitions critical to the ARMv8 security model and privileged execution environments.

The **MIPS** implementation, `MIPSEmulateInstructionStateModifier`, specifically manages HI/LO register semantics and properly emulates branch delay slots, ensuring that instructions following branches execute before the branch takes effect.

## Binary Format and Relocation Handling

Processor modules implement architecture-specific relocation handlers to fix up addresses during binary import, parsing ELF and Mach-O relocation tables according to each ISA's addressing models.

**x86** provides `X86_64_ElfRelocationHandler`, `X86_32_ElfRelocationHandler`, and `X86_64_MachoRelocationHandler` to process RIP-relative relocations in position-independent code and handle the various addressing modes specific to Intel and AMD extensions.

**ARM** relies on `ARM_ElfRelocationHandler` to manage Thumb interworking thunks and ARM-specific relocation types that support the architecture's mixed 16/32-bit instruction sets.

**AArch64** uses `AARCH64_ElfRelocationHandler` to process the larger 64-bit relocation addends and PLT-related fixups common in modern ARM64 Linux and Android binaries.

**MIPS** implements `MIPS_ElfRelocationHandler` and `MIPS_Elf64RelocationHandler` to handle GP-relative relocations, micro-MIPS extension fixups, and the architecture-specific HI16/LO16 relocation pairs used for loading 32-bit constants.

## Pattern Files and Heuristics

Auto-analysis heuristics reside in XML pattern files within each processor's `data/patterns` directory, enabling Ghidra to identify function prologues, thunks, and compiler-specific idioms.

The **x86** module includes [`x86gcc_patterns.xml`](https://github.com/NationalSecurityAgency/ghidra/blob/main/x86gcc_patterns.xml) and [`x86win_patterns.xml`](https://github.com/NationalSecurityAgency/ghidra/blob/main/x86win_patterns.xml) to detect GCC and Microsoft Visual C++ function prologues, frame pointer setups, and calling convention variations.

**ARM** patterns detect Thumb prologues, LDR-PC loading sequences, and compiler-specific register save patterns across different ARM variants.

**AArch64** pattern files focus on PLT stub detection and linker-generated symbol identifiers that facilitate automatic function recognition in stripped binaries.

**MIPS** patterns identify GP-relative code sequences and account for branch delay slot patterns when determining function boundaries and cross-references.

## Working with Processor Modules in Ghidra Scripts

When programmatically interacting with Ghidra's processor modules, the framework automatically instantiates the correct language definition and analysis classes based on the imported binary's architecture.

### Detecting Processor Module Assignment

```java
import ghidra.app.script.GhidraScript;
import ghidra.program.model.listing.Program;

public class ShowProcessorInfo extends GhidraScript {
    @Override
    protected void run() throws Exception {
        // Prompt the user to select a file
        String path = askFile("Select binary", "Open").getAbsolutePath();
        // Import the file; Ghidra will auto-detect the appropriate language
        Program prog = importFileIntoProject(path, false);
        println("Language: " + prog.getLanguage().getLanguageID());   // e.g. x86:LE:64:default
        println("Processor: " + prog.getLanguage().getProcessor());   // x86, ARM, AARCH64, MIPS
        println("Endianness: " + prog.getLanguage().isBigEndian() ? "big" : "little");
    }
}

```

When opening a 32-bit little-endian MIPS ELF, this script reports `LanguageID: MIPS:LE:32:default`, automatically selecting the appropriate processor module from `Ghidra/Processors/MIPS`.

### Accessing Architecture-Specific Registers

```java
// Inside a Ghidra script or plugin
import ghidra.program.model.lang.Register;

// Assume 'program' is already open
Register pc = program.getLanguage().getProgramCounter();
Register sp = program.getLanguage().getRegister("sp");   // works for all CPUs

println("PC = " + pc.getName() + "  SP = " + sp.getName());

```

Note that register names vary by processor module: the **x86** module uses `eip` or `rip` for the program counter, while **ARM** and **AArch64** use `pc`, and **MIPS** typically uses a numerical representation depending on the specific variant.

### Running the Architecture-Aware Emulator

```java
import ghidra.pcode.emulate.EmulateInstructionStateModifier;
import ghidra.pcode.emulate.Emulate;
import ghidra.program.model.mem.MemoryAccessException;

Address addr = program.getAddressFactory().getDefaultAddressSpace().getAddress(0x401000);
Emulate emulate = new Emulate(program);
EmulateInstructionStateModifier modifier = 
        EmulateInstructionStateModifier.getProcessorEmulator(program);
emulate.setStateModifier(modifier);

try {
    emulate.executeInstruction(addr);
    println("Emulated instruction at " + addr);
} catch (MemoryAccessException e) {
    printerr("Failed to read memory: " + e.getMessage());
}

```

The `modifier` instance resolves to `X86EmulateInstructionStateModifier`, `ARMEmulateInstructionStateModifier`, `AARCH64EmulateInstructionStateModifier`, or `MIPSEmulateInstructionStateModifier` based on the loaded program's language, ensuring correct emulation of architecture-specific behaviors such as x86 segment overrides or MIPS branch delay slots.

## Summary

- **SLEIGH Definitions**: x86 uses extensive included `.sinc` files for extensions, ARM splits by mode/endianness, AArch64 uses a minimal wrapper, and MIPS provides separate files for width/endianness variants.
- **Register Specifications**: Each module defines its register set in `.pspec` files, with x86 supporting overlapping register views, ARM supporting banked registers, and AArch64 providing a flat 64-bit register file.
- **Analysis Plugins**: x86 focuses on `LEA` handling ([`X86Analyzer.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/X86Analyzer.java)), AArch64 on PLT thunks ([`AARCH64PltThunkAnalyzer.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/AARCH64PltThunkAnalyzer.java)), ARM on mode detection, and MIPS on symbol analysis ([`MipsSymbolAnalyzer.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/MipsSymbolAnalyzer.java)).
- **Emulation**: State modifiers handle x86 segments, ARM CPSR/modes, AArch64 exception levels, and MIPS HI/LO registers with branch delay slots.
- **Relocations**: Each processor implements ELF handlers for architecture-specific fixups including x86 RIP-relative, MIPS GP-relative, and ARM/AArch64 thunk relocations.

## Frequently Asked Questions

### How does Ghidra determine which processor module to use when importing a binary?

Ghidra examines the binary's file format headers—such as the ELF `e_machine` field or PE COFF header—to determine the target architecture, then maps this value to a language ID (e.g., `x86:LE:64:default` or `MIPS:LE:32:default`) defined in the processor module's `.ldefs` files. The importer automatically loads the corresponding SLEIGH specification and register definitions from the appropriate `Ghidra/Processors/` subdirectory.

### Can I manually specify a different processor module if Ghidra auto-detects incorrectly?

Yes, during the import process you can override the auto-detected language by selecting "Options" in the import dialog and choosing from the available languages in the dropdown menu. This allows you to force a specific processor module—for example, selecting a big-endian MIPS variant when Ghidra defaults to little-endian, or choosing a specific ARM variant with Thumb support.

### What are the main differences between ARM and AArch64 processor modules in Ghidra?

The **ARM** (32-bit) module supports ARMv4-v8 architectures including Thumb-1 and Thumb-2 instruction sets, with register banking for different processor modes (FIQ, IRQ, etc.) and complex condition code handling. The **AArch64** module implements the 64-bit ARMv8-A ISA with a streamlined, orthogonal instruction set, 64-bit general-purpose registers (X0-X30), and support for the PSTATE register rather than the separate CPSR found in 32-bit ARM. The AArch64 module also removes the complexity of Thumb mode switching and register banking present in the 32-bit implementation.

### How do SLEIGH specification files differ between x86 and MIPS architectures?

The **x86** SLEIGH specification in `x86.slaspec` is highly decomposed, including separate `.sinc` files for each instruction set extension (AVX, AVX-512, BMI, SHA) to manage the architecture's complexity and variability across vendors. The **MIPS** SLEIGH specifications, such as `mips32le.slaspec`, are self-contained per-variant (addressing 32/64-bit, endianness, and micro-MIPS) and explicitly define branch delay slot semantics and coprocessor interactions that are architectural hallmarks of MIPS, rather than using an included-file approach for extensions.