diff --git a/src/inline-assembly.md b/src/inline-assembly.md index a8bbc41ec..a6cdb1ed8 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -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 @@ -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` | @@ -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`,
`i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`,
`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`,
`i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`,
`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` | @@ -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` | @@ -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. | @@ -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` | @@ -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]` | @@ -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 @@ -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.