Skip to content

py: Add AArch64 native emitter and inline assembler. - #19697

Open
StrideZhou wants to merge 1 commit into
micropython:masterfrom
StrideZhou:aarch64-pr
Open

StrideZhou wants to merge 1 commit into
micropython:masterfrom
StrideZhou:aarch64-pr

Conversation

@StrideZhou

@StrideZhou StrideZhou commented Sep 11, 2026

Copy link
Copy Markdown

1. Motivation & Problem Statement

Currently, MicroPython lacks runtime native code generation (Native/Viper) and inline assembler support for the 64-bit ARM (AArch64/ARMv8-A) architecture. This limits performance optimization opportunities on modern 64-bit ARM platforms, such as native Unix hosts or QEMU-emulated environments. This PR aims to bridge this gap by providing a complete, robust AArch64 instruction emission and inline assembly framework.

2. Summary of Changes

This PR introduces ~5,400+ lines of code, structured across the following areas:

  • Core Compiler (py/): Added the AArch64 assembler, Native/Viper code emitters, and inline assembler instruction encoders.
  • QEMU Port (ports/qemu/):
    • Introduced VIRT_AARCH64 and VIRT_AARCH64_FLOAT board configurations.
    • Added low-level support: startup code, exception handling, generic timer, PL011 UART, and semihosting (shared/runtime/semihosting_aarch64.c).
    • Math library optimization: Added hardware-accelerated sqrt and sqrtf implementations using the AArch64 fsqrt instruction (lib/libm/ and lib/libm_dbl/).
  • Unix Port: Enabled AArch64 native and inline emitters for the Unix port, supporting both native 64-bit ARM hosts and qemu-aarch64 user-mode emulation.
  • Documentation: Added docs/reference/asm_aarch64.rst, detailing register calling conventions, supported instruction subsets (including Python keyword workarounds like and_), and known limitations.
  • Test Suite (tests/):
    • Added targeted regression tests: 64-bit large constants (native_const64.py, viper_const64.py), large stack frame locals (viper_many_locals.py), and large pointer offsets (viper_ptr_large_offset.py).
    • Updated existing QEMU tests (asm_test.py, native_test.py, viper_test.py) to gracefully SKIP if the target lacks a .mpy architecture ID, preventing false CI failures.
  • CI/CD Pipeline: Added comprehensive AArch64 jobs in .github/workflows/ and tools/ci.sh, including automated ARM GNU toolchain download/verification, QEMU bare-metal build/test, Unix user-mode emulation test, and dedicated gcov coverage collection for the new emitter files.

3. Testing & Verification

Strictly adhering to project CI standards, the following verifications have been completed:

  • Local Build & Execution: Successfully built mpy-cross and the Unix port with AArch64 emitters enabled. Feature detection correctly reports aarch64.
  • Test Pass Rate: Successfully compiled all 20 AArch64 inline-assembler test files and 4 new Native/Viper regression tests. Basic regression tests resulted in 313 passed, 0 failed (feature-dependent tests unsupported by the minimal host config were correctly skipped).
  • CI Coverage: New CI jobs successfully build and run the QEMU VIRT_AARCH64 test suite, inline-assembler tests, and Unix AArch64 bytecode/native test suites, generating accurate gcov reports for asmaarch64.c, emitnaarch64.c, and emitinlineaarch64.c.

4. Trade-offs, Limitations & Alternatives

(Addressing MicroPython's core concerns regarding code size and architectural compatibility)

  • Code Size Impact: The new assembler, emitters, and runtime helpers increase the AArch64-specific source and CI footprint. However, because other architectures do not enable these emitters, there is zero runtime code-size increase for other ports. (Confirmed by the CI Code Size Report: all non-AArch64 ports show +0 +0.000%).
  • No .mpy Architecture ID (Critical Limitation): The current .mpy file format has exhausted its available architecture IDs. Consequently, persistent native .mpy loading is deliberately disabled for AArch64. Inline assembler and Native/Viper code are compiled at runtime only. This is a pragmatic trade-off; architecture-ID allocation is deferred until the .mpy v7 format and native toolchain design are updated (see Issue mpy-cross/mpy-ld/natmod Please add target for aarch64 #19386).
  • Instruction Set Limitations:
    • Floating-point (SIMD/FP) registers and instructions are not supported.
    • Load/store operations only support constant offsets; register-offset addressing and pre/post-indexed forms are not supported.
    • push and pop operations automatically pad an odd number of registers with a dummy slot (using the zero register) to maintain strict 16-byte stack pointer (sp) alignment.

5. Compliance & Generative AI Declaration

  • Git History: The commit history is strictly linear with no merge commits, adhering to MicroPython's rebase standards.
  • Generative AI Policy: Generative AI tools were utilized during the creation of this PR. However, all code and descriptions have been thoroughly read, manually validated, and are the sole responsibility of the human contributor, fully complying with the MicroPython Generative AI Policy.

@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown

Code size report:

Reference:  rp2: Page-align the C heap ceiling. [11094ea]
Comparison: py,ports,tests,tools: Add AArch64 native emitter and inline assembler. [merge of a1f9857]
  mpy-cross:    +0 +0.000% 
   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:    +0 +0.000% standard
      stm32:    +0 +0.000% PYBV10
      esp32:    +0 +0.000% ESP32_GENERIC
     mimxrt:    +0 +0.000% TEENSY40
        rp2:    +0 +0.000% RPI_PICO_W
       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS
  qemu rv32:    +0 +0.000% VIRT_RV32

@codecov

codecov Bot commented Sep 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.59%. Comparing base (0414173) to head (a1f9857).
⚠️ Report is 7 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #19697      +/-   ##
==========================================
+ Coverage   98.55%   98.59%   +0.03%     
==========================================
  Files         182      182              
  Lines       23335    23335              
  Branches        5        5              
==========================================
+ Hits        22998    23006       +8     
+ Misses        336      328       -8     
  Partials        1        1              
Flag Coverage Δ
unix-coverage-32bit 98.59% <ø> (+0.03%) ⬆️
unix-coverage-64bit 98.52% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@StrideZhou
StrideZhou force-pushed the aarch64-pr branch 3 times, most recently from 2316851 to 7d3d35b Compare September 13, 2026 15:12
@StrideZhou
StrideZhou marked this pull request as ready for review September 13, 2026 16:38
@StrideZhou
StrideZhou marked this pull request as draft September 14, 2026 06:27
@StrideZhou
StrideZhou force-pushed the aarch64-pr branch 4 times, most recently from b402048 to d48085c Compare September 16, 2026 15:56
@StrideZhou
StrideZhou marked this pull request as ready for review September 20, 2026 10:02
Add a complete AArch64 (ARMv8-A) assembler and native/Viper emitter to
the MicroPython compiler. This enables runtime native code generation
and an inline assembler for 64-bit ARM targets.

Key additions include:
- Core AArch64 assembler, native/Viper emitters, and instruction
  encoders in py/.
- QEMU port support: VIRT_AARCH64 and VIRT_AARCH64_FLOAT boards,
  including startup, exception handling, timer, PL011 UART, and
  semihosting. Hardware-accelerated sqrt/sqrtf in libm.
- Unix port support for AArch64 native/inline emitters.
- Comprehensive test suite covering 64-bit constants, large stack
  frames, and large pointer offsets.
- CI jobs for QEMU bare-metal and Unix AArch64 emulation.

Note that persistent native .mpy loading is deliberately disabled for
AArch64 because the current .mpy format has no available architecture
IDs. This is deferred to the .mpy v7 toolchain work (see micropython#19386).

This change does not increase the code size for any other architecture,
as the new emitters are only compiled when targeting AArch64.

Signed-off-by: Stride Zhou <stride_anderson@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant