Caution

You’re reading a draft of the Ferrocene Language Specification. Some parts of this document might be missing, incomplete or incorrect. Our aim is to have the specification ready by the end of 2022.

22. Inline Assembly

Note

The contents of this section are informational.

Legality Rules

22:1 Inline assembly is hand-written assembly code that is integrated into a Rust program.

22:2 Inline assembly is written as an assembly code block that is wrapped inside a macro invocation of macro core::arch::asm or macro core::arch::global_asm.

22:3 Inline assembly is available on the following architectures:

  • 22:4 AArch64

  • 22:5 ARM

  • 22:6 RISC-V

  • 22:7 x86 and x86-64

22.1. Registers

Syntax

RegisterName ::=
    " ExplicitRegisterName "
  | RegisterClassName

ExplicitRegisterName ::=
    a[0-31]
  | ah    | al    | ax
  | b[0-31]
  | bh    | bl    | bp    | bpl   | bx
  | ch    | cl    | cx
  | d[0-31]
  | dh    | di    | dil   | dl    | dx
  | eax   | ebp   | ebx   | ecx   | edi   | edx   | eip   | esi
  | esp
  | f[0-31]
  | fa[0-7]
  | ffr   | fp
  | fs[0-11]
  | ft[0-11]
  | gp
  | h[0-31]
  | ip
  | k[0-7]
  | lr
  | m[0-7]
  | p[0-15]
  | pc
  | q[0-31]
  | r[0-15]
  | r[8-15]d
  | r[8-15]w
  | ra    | rax
  | rb[8-15]
  | rbp   | rbx   | rcx
  | rdi   | rdx   | rfp   | rip   | rsi   | rsp
  | s[0-31]
  | si    | sil   | sl    | sp    | spl
  | st([0-7])
  | t[0-6]
  | tmm[0-7]
  | tp
  | v[0-31]
  | w[0-31]
  | wsp   | wzr
  | x[0-31]
  | xmm[0-31]
  | xzr
  | ymm[0-31]
  | zero
  | zmm[0-31]

Legality Rules

22.1:1 A register is a hardware component capable of holding data that can be read and written.

22.1:2 An input register is a register whose register name is used in a register argument subject to direction modifier in, inout, or inlateout.

22.1:3 An output register is a register whose register name is used in a register argument subject to direction modifier out, lateout, inout, or inlateout.

22.1:4 A register that is not specified as an output register shall have the same value upon exit from an assembly code block as it did upon entry into the assembly code block.

22.1:5 A register name is either the explicit register name of a register, or the register class name of the register class a register belongs to.

22.1:6 An explicit register name is a target-specific string that identifies a register.

22.1:7 An explicit register name may be aliased as follows:

22.1:8

Architecture

Explicit register name

Aliases

22.1:9

AArch64

sp

wsp

22.1:10

AArch64

v[0-31]

b[0-31], d[0-31], h[0-31], q[0-31], s[0-31]

22.1:11

AArch64

x[0-30]

w[0-30]

22.1:12

AArch64

x29

fp

22.1:13

AArch64

x30

lr

22.1:14

AArch64

xzr

wzr

22.1:15

ARM

r[0-3]

a[1-4]

22.1:16

ARM

r[4-9]

v[1-6]

22.1:17

ARM

r9

rfp

22.1:18

ARM

r10

sl

22.1:19

ARM

r11

fp

22.1:20

ARM

r12

ip

22.1:21

ARM

r13

sp

22.1:22

ARM

r14

lr

22.1:23

ARM

r15

pc

22.1:24

RISC-V

f[0-7]

ft[0-7]

22.1:25

RISC-V

f[8-9]

fs[0-1]

22.1:26

RISC-V

f[10-17]

fa[0-7]

22.1:27

RISC-V

f[18-27]

fs[2-11]

22.1:28

RISC-V

f[28-31]

ft[8-11]

22.1:29

RISC-V

x0

zero

22.1:30

RISC-V

x1

ra

22.1:31

RISC-V

x2

sp

22.1:32

RISC-V

x3

gp

22.1:33

RISC-V

x4

tp

22.1:34

RISC-V

x[5-7]

t[0-2]

22.1:35

RISC-V

x8

fp, s0

22.1:36

RISC-V

x9

s1

22.1:37

RISC-V

x[10-17]

a[0-7]

22.1:38

RISC-V

x[18-27]

s[2-11]

22.1:39

RISC-V

x[28-31]

t[3-6]

22.1:40

x86

ax

eax, rax

22.1:41

x86

bp

bpl, ebp, rbp

22.1:42

x86

bx

ebx, rbx

22.1:43

x86

cx

ecx, rcx

22.1:44

x86

di

edi, rdi

22.1:45

x86

dx

edx, rdx

22.1:46

x86

ip

eip, rip

22.1:47

x86

r[8-15]

r[8-15]b, r[8-15]d, r[8-15]w

22.1:48

x86

si

esi, rsi

22.1:49

x86

sp

esp, rsp, spl

22.1:50

x86

st(0)

st

22.1:51

x86

xmm[0-31]

ymm[0-31], zmm[0-31]

22.1:52 Certain explicit register names are not supported on selected architectures, as follows:

22.1:53

Architecture

Explicit register name

Reason

22.1:54

all

sp

The stack pointer must be restored to its original value on exit from an assembly code block.

22.1:55

AArch64

x18

OS-reserved register on some AArch64 targets.

22.1:56

AArch64

x19

Internally used by LLVM as a base pointer for functions with complex stack frames.

22.1:57

AArch64

x29

The frame pointer cannot be used as an input or output.

22.1:58

AArch64

xzr

The constant zero register cannot be modified.

22.1:59

ARM

pc

The program counter cannot be modified.

22.1:60

ARM

r6

Internally used by LLVM as a base pointer for functions with complex stack frames.

22.1:61

ARM

r7, r11

The frame pointer cannot be used as an input or output.

22.1:62

ARM

r9

OS-reserved register on some ARM targets.

22.1:63

RISC-V

gp, tp

Reserved registers.

22.1:64

RISC-V

x0

The constant zero register cannot be modified.

22.1:65

RISC-V

x8

The frame pointer cannot be used as an input or output.

22.1:66

RISC-V

x9

Internally used by LLVM as a base pointer for functions with complex stack frames.

22.1:67

x86

bp

The frame pointer cannot be used as an input or output.

22.1:68

x86

ip

The program counter cannot be modified.

22.1:69

x86-32

si

Internally used by LLVM as a base pointer for functions with complex stack frames.

22.1:70

x86-64

bx

Internally used by LLVM as a base pointer for functions with complex stack frames.

22.1:71 It is a static error to use an unsupported explicit register name.

Undefined Behavior

22.1:72 It is undefined behavior if a register that is not specified as an output register has a different value upon exit from an assembly code block from the value it had upon entry into the assembly code block.

22.2. Register Classes

Syntax

RegisterClassName ::=
    dreg
  | dreg_low16
  | dreg_low8
  | freg
  | kreg
  | kreg0
  | mmx_reg
  | preg
  | qreg
  | qreg_low4
  | qreg_low8
  | reg
  | reg_abcd
  | reg_byte
  | sreg
  | sreg_low16
  | tmm_reg
  | vreg
  | vreg_low16
  | x86_reg
  | xmm_reg
  | ymm_reg
  | zmm_reg

Legality Rules

22.2:1 A register class represents a set of registers.

22.2:2 A register class name is a target-specific string that identifies a register class.

22.2:3 Registers are organized into register classes as follows:

22.2:4

Architecture

Register class name

Explicit register names

22.2:5

AArch64

preg

p[0-15], ffr

22.2:6

AArch64

reg

x[0-30]

22.2:7

AArch64

vreg

v[0-31]

22.2:8

AArch64

vreg_low16

v[0-15]

22.2:9

ARM / Thumb2

reg

r[0-12], r14

22.2:10

ARM / Thumb1

reg

r[0-7]

22.2:11

ARM

dreg

d[0-31]

22.2:12

ARM

dreg_low8

d[0-8]

22.2:13

ARM

dreg_low16

d[0-15]

22.2:14

ARM

qreg

q[0-15]

22.2:15

ARM

qreg_low4

q[0-3]

22.2:16

ARM

qreg_low8

q[0-8]

22.2:17

ARM

sreg

s[0-31]

22.2:18

ARM

sreg_low16

s[0-15]

22.2:19

RISC-V

freg

f[0-31]

22.2:20

RISC-V

reg

x1, x[0-7], x[9-15], x[16-31] (on non-RV32E)

22.2:21

RISC-V

vreg

v[0-31]

22.2:22

x86

kreg

k[1-7]

22.2:23

x86

kreg0

k0

22.2:24

x86

mmx_reg

mm[0-7]

22.2:25

x86

reg

ax, bp, bx, cx, di, dx, r[8-15], si

22.2:26

x86

reg_abcd

ax, bx, cx, dx

22.2:27

x86

x87_reg

st([0-7])

22.2:28

x86

xmm_reg

xmm[0-7], xmm[8-15] (on 64bit only)

22.2:29

x86

ymm_reg

ymm[0-7], ymm[8-15] (on 64bit only)

22.2:30

x86

zmm_reg

zmm[0-7], zmm[8-15] (on 64bit only)

22.2:31

x86-32

reg_byte

ah, al, bh, bl, ch, cl, dh, dl

22.2:32

x86-64

reg_byte

al, bl, bpl, cl, dil, dl, sil, r[8-15]b

22.2:33

x86-64

tmm_reg

tmm[0-7]

22.2:34 If a value has a smaller size than the register it is allocated in, then

22.2:38 If a register argument has direction modifier inout and an input-output register expression, then the input register expression and the output register expression shall have the same type.

22.3. Register Arguments

Syntax

RegisterArgument ::=
    (Identifier =)? DirectionModifier ( RegisterName ) RegisterExpression

DirectionModifier ::=
    in
  | inlateout
  | inout
  | lateout
  | out

RegisterExpression ::=
    InputOutputRegisterExpression
  | SimpleRegisterExpression

InputOutputRegisterExpression ::=
    InputRegisterExpression => OutputRegisterExpression
  | InputRegisterExpression => UnderscoreExpression

InputRegisterExpression ::=
    Expression

OutputRegisterExpression ::=
    Expression

SimpleRegisterExpression ::=
    Expression
  | UnderscoreExpression

Legality Rules

22.3:1 A register argument is a construct that configures the input and output of a register, and optionally binds the configuration to an identifier.

22.3:2 A register argument shall be used within an assembly instruction.

22.3:3 A named register argument is a register argument whose configuration is bound to an identifier.

22.3:4 A positional register argument is a register argument whose configuration is not bound to an identifier.

22.3:5 A named register argument shall appear after a positional register argument.

22.3:6 An explicit register argument is a register argument that uses an explicit register name.

22.3:7 An explicit register argument shall appear after a named register argument.

22.3:8 A register class argument is a register argument that uses a register class name.

22.3:9 A register class argument causes an assembler to select a suitable register from the related register class.

22.3:10 A direction modifier is a construct that indicates whether a register argument initializes a register, assigns the value of a register to an expression, or both.

22.3:11 An input register expression is an expression that provides the initial value of a register.

22.3:12 An output register expression is an expression that is assigned the value of a register.

22.3:13 An input-output register expression is a construct that specifies both an input register expression and an output register expression.

22.3:14 A simple register expression is either an expression or an underscore expression.

22.3:15 A register expression is either an input-output register expression or a simple register expression.

22.3:16 The type of an input register expression, output register expression, or simple register expression shall depend on the architecture and the target feature in effect, as follows:

22.3:17

Architecture

Register class name

Target feature

Allowed types

22.3:18

AArch64

preg

n/a

Only clobbers

22.3:19

AArch64

reg

none

i8, i16, i32, f32, i64, f64

22.3:20

AArch64

vreg

neon

i8, i16, i32, f32, i64, f64

22.3:21

ARM

dreg

vfp2

i64, f64

22.3:22

ARM

reg

none

i8, i16, i32, f32

22.3:23

ARM

sreg

vfp2

i32, f32

22.3:24

RISC-V

freg

f

f32

22.3:25

RISC-V

freg

d

f64

22.3:26

RISC-V

vreg

n/a

Only clobbers

22.3:27

RISC-V32

reg

none

i8, i16, i32, f32

22.3:28

RISC-V64

reg

none

i8, i16, i32, f32, i64, f64

22.3:29

x86

kreg

avx512f

i8, i16

22.3:30

x86

kreg

avx512bw

i32, i64

22.3:31

x86

mmx_reg

n/a

Only clobbers

22.3:32

x86

reg_byte

none

i8

22.3:33

x86

tmm_reg

n/a

Only clobbers

22.3:34

x86

x87_reg

n/a

Only clobbers

22.3:35

x86

xmm_reg

sse

i32, f32, i64, f64

22.3:36

x86

ymm_reg

avx

i32, f32, i64, f64

22.3:37

x86

zmm_reg

avx512f

i32, f32, i64, f64

22.3:38

x86-32

reg

none

i16, i32, f32

22.3:39

x86-64

reg

none

i16, i32, f32, i64, f64

22.3:40 If a register argument has direction modifier in and a simple register expression, then

22.3:43 If a register argument has direction modifier out and a simple register expression, then

22.3:47 If a register argument has direction modifier lateout and a simple register expression, then the register argument behaves as a register argument with direction modifier out, except that the register can be reused with direction modifier in.

22.3:48 If a register argument has direction modifier inout and a simple register expression, then

22.3:51 If a register argument has direction modifier inout and an input-output register expression, then

22.3:55 If a register argument has direction modifier inlateout and a simple register expression, then the register argument behaves as a register argument with direction modifier inout, except that the register can be reused with direction modifier in.

22.3:56 If a register argument has direction modifier inlateout and an input-output register expression, then the register argument behaves as a register argument with direction modifier inout, except that the register can be reused with direction modifier in.

22.3:57 It is a static error to specify a register argument with direction modifier and register expression other than the combinations listed above.

Dynamic Semantics

22.3:58 The evaluation of a register argument proceeds as follows:

Examples

let mut left_value: i32 = 1;
let right_value: i32 = 2;

unsafe {
    asm!(
        "add {left} {right}",
        left = inout(reg) left_value,
        right = in(reg) right_value,
    );
}

22.4. Assembly Instructions

Syntax

AssemblyCodeBlock ::=
    AssemblyInstruction (, AssemblyInstruction)*

AssemblyInstruction ::=
    StringLiteral

Legality Rules

22.4:1 An assembly instruction is a string literal that represents a low-level assembly operation or an assembly directive.

22.4:2 An assembly instruction shall use the syntax of format strings as defined in module std::fmt, and contain zero or more register parameters.

22.4:3 An assembly code block is a sequence of assembly instructions.

22.4:4 When an assembly code block contains multiple assembly instructions, the assembly instructions are treated as concatenated into a single string literal, with character 0x0A (new line) between them.

22.4:5 The set of memory locations that an assembly code block is allowed to read and write are the same as those for an external function, excluding the memory locations that are private to the assembly code block.

22.4:6 A tool is not required to guarantee that an assembly code block appears exactly once in the final assembly output.

22.4:7 A tool is not required to guarantee that two assembly code blocks appear in the same declarative order in the final assembly output, or appear contiguously in successive addresses.

22.4:8 A register parameter is a substring delimited by characters 0x7B (left curly bracket) and 0x7D (right curly bracket) that is substituted with a register argument in an assembly instruction.

22.4:9 On x86 architectures, direction flag DF in register EFLAGS shall be cleared on exit from an assembly code block.

Undefined Behavior

22.4:10 On x86 architectures, it is undefined behavior if direction flag DF in register EFLAGS remains set on exit from an assembly code block.

Examples

"shl {value} 2"

22.4.1. Register Parameter Modifiers

Legality Rules

22.4.1:1 A register parameter modifier is a substring that starts with character 0x3A (colon), follows a register parameter, and changes the formatting of the related register parameter.

22.4.1:2 The effects of a register parameter modifier depends on the architecture and register class, as follows:

22.4.1:3

Architecture

Register class

Modifier

Example output

22.4.1:4

AArch64

reg

none

x0

22.4.1:5

AArch64

reg

:w

w0

22.4.1:6

AArch64

reg

:x

x0

22.4.1:7

AArch64

vreg

none

v0

22.4.1:8

AArch64

vreg

:b

b0

22.4.1:9

AArch64

vreg

:d

d0

22.4.1:10

AArch64

vreg

:h

h0

22.4.1:11

AArch64

vreg

:q

q0

22.4.1:12

AArch64

vreg

:s

s0

22.4.1:13

AArch64

vreg

:v

v0

22.4.1:14

ARM

dreg

none

d0

22.4.1:15

ARM

qreg

none

q0

22.4.1:16

ARM

qreg

:e, :f

d0, d1

22.4.1:17

ARM

reg

none

r0

22.4.1:18

ARM

sreg

none

s0

22.4.1:19

RISC-V

freg

none

f0

22.4.1:20

RISC-V

reg

none

x1

22.4.1:21

x86

kreg

none

k1

22.4.1:22

x86

reg

:e

eax

22.4.1:23

x86

reg

:x

ax

22.4.1:24

x86

reg_abcd

:h

ah

22.4.1:25

x86

reg_byte

none

al / ah

22.4.1:26

x86

xmm_reg

none

xmm0

22.4.1:27

x86

ymm_reg

none

ymm0

22.4.1:28

x86

zmm_reg

none

zmm0

22.4.1:29

x86

xmm_reg, ymm_reg, zmm_reg

:x

xmm0

22.4.1:30

x86

xmm_reg, ymm_reg, zmm_reg

:y

ymm0

22.4.1:31

x86

xmm_reg, ymm_reg, zmm_reg

:z

zmm0

22.4.1:32

x86-32

reg

none

eax

22.4.1:33

x86-32

reg_abcd

:l

al

22.4.1:34

x86-64

reg

none

rax

22.4.1:35

x86-64

reg

:l

al

22.4.1:36

x86-64

reg

:r

rax

Examples

let mut left_value: i32 = 1;
let right_value: i32 = 2;

unsafe {
    asm!(
        "add {left}:e {right}:x",
        left = inout(reg) left_value,
        right = in(reg) right_value,
    );
}

22.4.2. Directive Support

Legality Rules

22.4.2:1 An assembly directive is a request to the assembler to perform a particular action or change a setting.

22.4.2:2 If an assembly code block contains stateful assembly directives that modify how subsequent assembly code is processed, then the assembly code block shall undo the effects of the stateful assembly directives before the assembly code block is completed.

22.4.2:3 The common assembly directives are as follows:

  1. 22.4.2:4 .2byte, .4byte, .8byte

  2. 22.4.2:5 .align, .ascii, .asciz, .alt_entry

  3. 22.4.2:6 .balign, .balignl, .balignw, .balign, .balignl, .balignw, .bss, .byte

  4. 22.4.2:7 .comm

  5. 22.4.2:8 .data, .def, .double

  6. 22.4.2:9 .endef, .equ, .equiv, .eqv

  7. 22.4.2:10 .fill, .float

  8. 22.4.2:11 .globl, .global

  9. 22.4.2:12 .inst

  10. 22.4.2:13 .lcomm, .long

  11. 22.4.2:14 .octa, .option

  12. 22.4.2:15 .private_extern, .p2align, .pushsection, .popsection

  13. 22.4.2:16 .quad

  14. 22.4.2:17 .scl, .section, .set, .short, .size, .skip, .sleb128, .space, .string

  15. 22.4.2:18 .text, .type

  16. 22.4.2:19 .uleb128

  17. 22.4.2:20 .word

22.4.2:21 The following assembly directives are relevant on ELF targets that support DWARF unwind info.

  1. 22.4.2:22 .cfi_adjust_cfa_offset

  2. 22.4.2:23 .cfi_def_cfa, .cfi_def_cfa_offset, .cfi_def_cfa_register

  3. 22.4.2:24 .cfi_endproc, .cfi_escape

  4. 22.4.2:25 .cfi_lsda

  5. 22.4.2:26 .cfi_offset

  6. 22.4.2:27 .cfi_personality

  7. 22.4.2:28 .cfi_register, .cfi_rel_offset, .cfi_remember_state, .cfi_restore, .cfi_restore_state, .cfi_return_column

  8. 22.4.2:29 .cfi_same_value, .cfi_sections, .cfi_signal_frame, .cfi_startproc

  9. 22.4.2:30 .cfi_undefined

  10. 22.4.2:31 .cfi_window_save

22.4.2:32 The following assembly directives are relevant on targets with structured exception handling.

  1. 22.4.2:33 .seh_endproc, .seh_endprologue

  2. 22.4.2:34 .seh_proc, .seh_pushreg

  3. 22.4.2:35 .seh_savereg, .seh_setframe, .seh_stackalloc

22.4.2:36 The following assembly directives are relevant on ARM targets.

  1. 22.4.2:37 .code

  2. 22.4.2:38 .even

  3. 22.4.2:39 .fnstart, .fnend

  4. 22.4.2:40 .movsp

  5. 22.4.2:41 .save

  6. 22.4.2:42 .thumb, .thumb_func

22.4.2:43 The following assembly directives are relevant on x86 targets.

  1. 22.4.2:44 .code16, .code32, .code64

  2. 22.4.2:45 .nops

22.5. ABI Clobbers

Syntax

AbiClobber ::=
    clobber_abi ( AbiKindList )

AbiKindList ::=
    AbiKind (, AbiKind)* ,?

Legality Rules

22.5:1 An ABI clobber is an argument to macro core::arch::asm which indicates that the values of selected registers might be overwritten during the execution of an assembly code block.

22.5:2 Multiple ABI clobbers may be specified for an assembly code block. Clobber constraints are applied for all unique registers in the union of all specified ABIs.

22.5:3 The effects of an ABI clobber depend on the ABI in effect, as follows:

22.5:4

Architecture

AbiKind

Clobbered registers

22.5:5

AArch64

"C", "efiapi", "system"

ffr, p[0-15], v[0-31], x[0-17], x18 (when not reserved), x30

22.5:6

ARM

"aapcs", "C", "efiapi", "system"

d[0-7], d[16-31], r[0-3], r12, r14, s[0-15]

22.5:7

RISC-V

"C", "efiapi", "system"

f[0-7], f[10-17], f[28-31], v[0-31], x1, x[5-7], x[10-17], x[28-31]

22.5:8

x86-32

"C", "cdecl", "efiapi", "fastcall", "stdcall", "system"

ax, cx, dx, k[0-7], mm[0-7], st([0-7]), xmm[0-7]

22.5:9

x86-64

"C", "efiapi", "system" (on Windows), "win64"

ax, cx, dx, k[0-7], mm[0-7], st([0-7]), r[8-11], tmm[0-7], xmm[0-31]

22.5:10

x86-64

"C", "system" (on non-Windows), "sysv64"

ax, cx, di, dx, k[0-7], mm[0-7], r[8-11], si, st([0-7]), tmm[0-7], xmm[0-31]

22.5:11 On x86 architectures, the x87 floating-point register stack shall remain unchanged unless all st([0-7]) registers have been clobbered.

22.5:12 On x86 architectures, if all x87 registers are clobbered, then the x87 register stack is presumed empty upon entry of an assembly code block. The x87 register stack shall be empty on exit from an assembly code block.

Examples

clobber_abi("C", "system")

22.6. Assembly Options

Syntax

AssemblyOption ::=
    options ( OptionList )

OptionList ::=
    Option (, Option)* ,?

Option ::=
    att_syntax
  | nomem
  | noreturn
  | nostack
  | preserves_flags
  | pure
  | raw
  | readonly

Legality Rules

22.6:1 An assembly option is used to specify a characteristic of or a restriction on the related assembly code block.

22.6:2 Assembly option att_syntax is applicable only to x86 architectures and causes the assembler to use the .att_syntax prefix mode which prefixes registers with %.

22.6:3 Assembly option nomem indicates that the assembly code block does not read or write memory.

22.6:4 Assembly option noreturn indicates that the assembly code block does not return, preventing the dropping of variables.

22.6:5 Assembly option nostack indicates that the assembly code block does not push on the stack, or write to the stack red-zone (if supported).

22.6:6 If assembly option nostack is not in effect, then an assembly code block is allowed to use stack space below the stack pointer. Upon entry of an assembly code block, the stack pointer is suitably aligned according to the target ABI for call expressions. The stack pointer shall be restored to its original value on exit from the assembly code block.

22.6:7 Assembly option preserves_flags indicates that the assembly code block does not modify the flags register.

22.6:8 If assembly option preserves_flags is in effect, then the values of the following flags registers shall be restored on exit from an assembly code block:

22.6:9

Architecture

Flag registers

22.6:10

AArch64

Floating-point status FPRS register

Condition flags NZCV register

22.6:11

ARM

Condition flags C, N, V, Z in register CPSR

Condition flags C, N, V, Z in register FPSCR

Floating-point exception flags DZC, IDC, IOC, IXC, OFC, UFC in register FPSCR

Greater than or equal flag GE in register CPRS

Saturation flag Q in register CPRS

Saturation flag QC in register FPSCR

22.6:12

RISC-V

Floating-point exception flags fflags in register fcsr

Vector extension state vcsr, vl, vtype

22.6:13

x86

Status flags AF, CF, OF, PF, SF, ZF in register EFLAGS

Floating-point exception flags DE, IE, OE, PE, UE, ZE in register MXCSR

Floating-point status word

22.6:14 Assembly option pure indicates that the assembly code block has no side effects, and its outputs depend only on direct inputs.

22.6:15 Assembly option raw causes assembly instructions to be parsed raw, without any special handling of register parameters.

22.6:16 Assembly option readonly indicates that the assembly code block does not write memory.

22.6:17 Assembly options att_syntax and raw shall appear only in GlobalAsmArguments.

22.6:18 Assembly options nomem and readonly shall not be used together.

22.6:19 Assembly option noreturn shall not be specified on an assembly code block that has output registers.

22.6:20 Assembly option pure shall appear with either assembly option nomem or assembly option readonly.

22.6:21 Assembly option pure shall not be specified on an assembly code block that either lacks output registers or all register expressions of output registers are underscore expressions.

Undefined Behavior

22.6:22 It is undefined behavior if an assembly code block subject to assembly option pure has side effects other than its direct outputs.

22.6:23 It is undefined behavior if control reaches the end of an assembly code block subject to assembly option noreturn.

Examples

options(nomem, pure)

22.7. Macros asm and global_asm

Syntax

AsmArguments ::=
    ( AssemblyCodeBlock (, RegisterArgument)* (, AbiClobber)* (, AssemblyOption)* ,? )

GlobalAsmArguments ::=
    ( AssemblyCodeBlock (, RegisterArgument)* (, AssemblyOption)* ,? )

Legality Rules

22.7:1 Assembly code blocks are embedded within Rust source code using macros core::arch::asm and core::arch::global_asm.

22.7:2 When invoking macro core::arch::asm, the DelimitedTokenTree of the related macro invocation shall follow the syntax of AsmArguments.

22.7:3 Invoking macro core::arch::asm causes the related assembly code block to be integrated into the generated assembly of the function where the macro invocation took place. A tool is free to encapsulate the assembly code block in a separate function and generate a call expression to it.

22.7:4 When invoking macro core::arch::global_asm, the DelimitedTokenTree of the related macro invocation shall follow the syntax of GlobalAsmArguments.

22.7:5 Invoking macro core::arch::global_asm causes the related assembly code block to be emitted outside the function where the macro invocation took place.

Dynamic Semantics

22.7:6 The evaluation of a macro invocation to macro core::arch::asm or macro core::arch::global_asm evaluates register arguments in declarative order.

22.7:7 The execution of an assembly code block produced by inline assembly proceeds as follows:

  1. 22.7:8 All input registers are initialized to the values provided by the respective register arguments, in an undefined order.

  2. 22.7:9 The assembly instructions of the assembly code block are executed in declarative order.

  3. 22.7:10 The values of all output registers are assigned to the register expressions provided by the respective register arguments, in an undefined order.

Examples

fn asm_example() -> u32 {
    let basepri;
    unsafe {
        asm!("
            mrs {}, BASEPRI
        ",
        out(reg) basepri,
        options(nomem, nostack, preserves_flags))
    }
    basepri
}

global_asm!("
    do_nothing:
        push {r7, lr}
        mov  r7, sp
        pop  {r7, pc}
    ",
    options(raw)
);

fn global_asm_example() {
    extern "C" {
        fn do_nothing();
    }

    unsafe { do_nothing() }
}