Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Arm64EC to inline-assembly documentation #1653

Merged
merged 1 commit into from
Nov 11, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 32 additions & 14 deletions src/inline-assembly.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ r[asm.stable-targets]
Support for inline assembly is stable on the following architectures:
- x86 and x86-64
- ARM
- AArch64
- AArch64 and Arm64EC
- RISC-V
- LoongArch
- s390x
Expand Down Expand Up @@ -235,6 +235,9 @@ Here is the list of currently supported register classes:
| AArch64 | `vreg` | `v[0-31]` | `w` |
| AArch64 | `vreg_low16` | `v[0-15]` | `x` |
| AArch64 | `preg` | `p[0-15]`, `ffr` | Only clobbers |
| Arm64EC | `reg` | `x[0-12]`, `x[15-22]`, `x[25-27]`, `x30` | `r` |
| Arm64EC | `vreg` | `v[0-15]` | `w` |
| Arm64EC | `vreg_low16` | `v[0-15]` | `x` |
| ARM (ARM/Thumb2) | `reg` | `r[0-12]`, `r14` | `r` |
| ARM (Thumb1) | `reg` | `r[0-7]` | `r` |
| ARM | `sreg` | `s[0-31]` | `t` |
Expand Down Expand Up @@ -283,6 +286,8 @@ The availability of supported types for a particular register class may depend o
| AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
| AArch64 | `vreg` | `neon` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
| AArch64 | `preg` | N/A | Only clobbers |
| Arm64EC | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
| Arm64EC | `vreg` | `neon` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
| ARM | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| ARM | `sreg` | `vfp2` | `i32`, `f32` |
| ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` |
Expand Down Expand Up @@ -339,6 +344,12 @@ Here is the list of all supported register aliases:
| AArch64 | `sp` | `wsp` |
| AArch64 | `xzr` | `wzr` |
| AArch64 | `v[0-31]` | `b[0-31]`, `h[0-31]`, `s[0-31]`, `d[0-31]`, `q[0-31]` |
| Arm64EC | `x[0-30]` | `w[0-30]` |
| Arm64EC | `x29` | `fp` |
| Arm64EC | `x30` | `lr` |
| Arm64EC | `sp` | `wsp` |
| Arm64EC | `xzr` | `wzr` |
| Arm64EC | `v[0-15]` | `b[0-15]`, `h[0-15]`, `s[0-15]`, `d[0-15]`, `q[0-15]` |
| ARM | `r[0-3]` | `a[1-4]` |
| ARM | `r[4-9]` | `v[1-6]` |
| ARM | `r9` | `rfp` |
Expand Down Expand Up @@ -383,12 +394,15 @@ Some registers cannot be used for input or output operands:
| Architecture | Unsupported register | Reason |
| ------------ | -------------------- | ------ |
| All | `sp`, `r15` (s390x) | The stack pointer must be restored to its original value at the end of an asm code block. |
| All | `bp` (x86), `x29` (AArch64), `x8` (RISC-V), `$fp` (LoongArch), `r11` (s390x) | The frame pointer cannot be used as an input or output. |
| All | `bp` (x86), `x29` (AArch64 and Arm64EC), `x8` (RISC-V), `$fp` (LoongArch), `r11` (s390x) | The frame pointer cannot be used as an input or output. |
| ARM | `r7` or `r11` | On ARM the frame pointer can be either `r7` or `r11` depending on the target. The frame pointer cannot be used as an input or output. |
| All | `si` (x86-32), `bx` (x86-64), `r6` (ARM), `x19` (AArch64), `x9` (RISC-V), `$s8` (LoongArch) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. |
| All | `si` (x86-32), `bx` (x86-64), `r6` (ARM), `x19` (AArch64 and Arm64EC), `x9` (RISC-V), `$s8` (LoongArch) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. |
| x86 | `ip` | This is the program counter, not a real register. |
| AArch64 | `xzr` | This is a constant zero register which can't be modified. |
| AArch64 | `x18` | This is an OS-reserved register on some AArch64 targets. |
| Arm64EC | `xzr` | This is a constant zero register which can't be modified. |
| Arm64EC | `x18` | This is an OS-reserved register. |
| Arm64EC | `x13`, `x14`, `x23`, `x24`, `x28`, `v[16-31]`, `p[0-15]`, `ffr` | These are AArch64 registers that are not supported for Arm64EC. |
| ARM | `pc` | This is the program counter, not a real register. |
| ARM | `r9` | This is an OS-reserved register on some ARM targets. |
| RISC-V | `x0` | This is a constant zero register which can't be modified. |
Expand Down Expand Up @@ -434,16 +448,16 @@ The supported modifiers are a subset of LLVM's (and GCC's) [asm template argumen
| x86 | `*mm_reg` | `y` | `ymm0` | `t` |
| x86 | `*mm_reg` | `z` | `zmm0` | `g` |
| x86 | `kreg` | None | `k1` | None |
| AArch64 | `reg` | None | `x0` | `x` |
| AArch64 | `reg` | `w` | `w0` | `w` |
| AArch64 | `reg` | `x` | `x0` | `x` |
| AArch64 | `vreg` | None | `v0` | None |
| AArch64 | `vreg` | `v` | `v0` | None |
| AArch64 | `vreg` | `b` | `b0` | `b` |
| AArch64 | `vreg` | `h` | `h0` | `h` |
| AArch64 | `vreg` | `s` | `s0` | `s` |
| AArch64 | `vreg` | `d` | `d0` | `d` |
| AArch64 | `vreg` | `q` | `q0` | `q` |
| AArch64/Arm64EC | `reg` | None | `x0` | `x` |
| AArch64/Arm64EC | `reg` | `w` | `w0` | `w` |
| AArch64/Arm64EC | `reg` | `x` | `x0` | `x` |
| AArch64/Arm64EC | `vreg` | None | `v0` | None |
| AArch64/Arm64EC | `vreg` | `v` | `v0` | None |
| AArch64/Arm64EC | `vreg` | `b` | `b0` | `b` |
| AArch64/Arm64EC | `vreg` | `h` | `h0` | `h` |
| AArch64/Arm64EC | `vreg` | `s` | `s0` | `s` |
| AArch64/Arm64EC | `vreg` | `d` | `d0` | `d` |
| AArch64/Arm64EC | `vreg` | `q` | `q0` | `q` |
| ARM | `reg` | None | `r0` | None |
| ARM | `sreg` | None | `s0` | None |
| ARM | `dreg` | None | `d0` | `P` |
Expand Down Expand Up @@ -497,6 +511,7 @@ The following ABIs can be used with `clobber_abi`:
| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[0-7]`, `st([0-7])`, `tmm[0-7]` |
| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[0-7]`, `st([0-7])`, `tmm[0-7]` |
| AArch64 | `"C"`, `"system"`, `"efiapi"` | `x[0-17]`, `x18`\*, `x30`, `v[0-31]`, `p[0-15]`, `ffr` |
| Arm64EC | `"C"`, `"system"` | `x[0-12]`, `x[15-17]`, `x30`, `v[0-15]` |
| ARM | `"C"`, `"system"`, `"efiapi"`, `"aapcs"` | `r[0-3]`, `r12`, `r14`, `s[0-15]`, `d[0-7]`, `d[16-31]` |
| RISC-V | `"C"`, `"system"`, `"efiapi"` | `x1`, `x[5-7]`, `x[10-17]`, `x[28-31]`, `f[0-7]`, `f[10-17]`, `f[28-31]`, `v[0-31]` |
| LoongArch | `"C"`, `"system"` | `$r1`, `$r[4-20]`, `$f[0-23]` |
Expand Down Expand Up @@ -632,7 +647,7 @@ r[asm.rules.preserved-registers]
- Condition flags in `FPSCR` (N, Z, C, V)
- Saturation flag in `FPSCR` (QC)
- Floating-point exception flags in `FPSCR` (IDC, IXC, UFC, OFC, DZC, IOC).
- AArch64
- AArch64 and Arm64EC
- Condition flags (`NZCV` register).
- Floating-point status (`FPSR` register).
- RISC-V
Expand All @@ -651,6 +666,9 @@ r[asm.rules.x86-x87]
- On x86, the x87 floating-point register stack must remain unchanged unless all of the `st([0-7])` registers have been marked as clobbered with `out("st(0)") _, out("st(1)") _, ...`.
- If all x87 registers are clobbered then the x87 register stack is guaranteed to be empty upon entering an `asm` block. Assembly code must ensure that the x87 register stack is also empty when exiting the asm block.

r[asm.rules.arm64ec]
- On arm64ec, [call checkers with appropriate thunks](https://learn.microsoft.com/en-us/windows/arm/arm64ec-abi#authoring-arm64ec-in-assembly) are mandatory when calling functions.

r[asm.rules.only-on-exit]
- The requirement of restoring the stack pointer and non-output registers to their original value only applies when exiting an `asm!` block.
- This means that `asm!` blocks that never return (even if not marked `noreturn`) don't need to preserve these registers.
Expand Down