[arch][arm64] add some helpful assembly macros for arm64

Pulled from Fuchsia Zircon kernel code.
This commit is contained in:
Travis Geiselbrecht
2025-10-04 16:21:17 -07:00
parent 6fb675d3a5
commit 0ca529182e

View File

@@ -1,13 +1,18 @@
/* /*
* Copyright (c) 2014 Travis Geiselbrecht * Copyright (c) 2014 Travis Geiselbrecht
* * Copyright 2020 The Fuchsia Authors
* Use of this source code is governed by a MIT-style * Use of this source code is governed by a MIT-style
* license that can be found in the LICENSE file or at * license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
*/ */
#pragma once #pragma once
/* *INDENT-OFF* */ #ifdef __ASSEMBLER__ // clang-format off
#ifndef __has_feature
#define __has_feature(x) 0
#endif
.macro push ra, rb .macro push ra, rb
stp \ra, \rb, [sp,#-16]! stp \ra, \rb, [sp,#-16]!
.endm .endm
@@ -16,6 +21,84 @@ stp \ra, \rb, [sp,#-16]!
ldp \ra, \rb, [sp], #16 ldp \ra, \rb, [sp], #16
.endm .endm
/// Fill a register with a wide integer literal.
///
/// This emits the one to four instructions required to fill a 64-bit
/// register with a given bit pattern. It uses as few instructions as
/// suffice for the particular value.
///
/// Parameters
///
/// * reg
/// - Required: Output 64-bit register.
///
/// * literal
/// - Required: An integer expression that can be evaluated immediately
/// without relocation.
///
.macro movlit reg, literal
mov \reg, #((\literal) & 0xffff)
.ifne (((\literal) >> 16) & 0xffff)
movk \reg, #(((\literal) >> 16) & 0xffff), lsl #16
.endif
.ifne (((\literal) >> 32) & 0xffff)
movk \reg, #(((\literal) >> 32) & 0xffff), lsl #32
.endif
.ifne (((\literal) >> 48) & 0xffff)
movk \reg, #(((\literal) >> 48) & 0xffff), lsl #48
.endif
.endm // movlit
/// Materialize a symbol (with optional addend) into a register.
///
/// This emits the `adr` instruction or two-instruction sequence required
/// to materialize the address of a global variable or function symbol.
///
/// Parameters
///
/// * reg
/// - Required: Output 64-bit register.
///
/// * symbol
/// - Required: A symbolic expression requiring at most PC-relative reloc.
///
.macro adr_global reg, symbol
#if __has_feature(hwaddress_sanitizer)
adrp \reg, :pg_hi21_nc:\symbol
movk \reg, #:prel_g3:\symbol+0x100000000
add \reg, \reg, #:lo12:\symbol
#elif defined(__AARCH64_CMODEL_TINY__)
adr \reg, \symbol
#else
adrp \reg, \symbol
add \reg, \reg, #:lo12:\symbol
#endif
.endm // adr_global
/// Load a 64-bit fixed global symbol (with optional addend) into a register.
///
/// This emits the `ldr` instruction or two-instruction sequence required to
/// load a global variable. If multiple words are required, it's more
/// efficient to use `adr_global` and then `ldp` than to repeat `ldr_global`
/// with related locations.
///
/// Parameters
///
/// * reg
/// - Required: Output 64-bit register.
///
/// * symbol
/// - Required: A symbolic expression requiring at most PC-relative reloc.
///
.macro ldr_global reg, symbol
#ifdef __AARCH64_CMODEL_TINY__
ldr \reg, \symbol
#else
adrp \reg, \symbol
ldr \reg, [\reg, #:lo12:\symbol]
#endif
.endm // adr_global
.macro tbzmask, reg, mask, label, shift=0 .macro tbzmask, reg, mask, label, shift=0
.if \shift >= 64 .if \shift >= 64
.error "tbzmask: unsupported mask, \mask" .error "tbzmask: unsupported mask, \mask"
@@ -88,3 +171,5 @@ ldp \ra, \rb, [sp], #16
.quad \handler .quad \handler
.popsection .popsection
.endm .endm
#endif // __ASSEMBLER__