DUJINLABS.COM

Linux v6.18.37 · ARM64

entry-fpsimd.S — FP/SIMD·SVE·SME 레지스터 저장과 복원

이 파일의 함수들은 fpsimdmacros.h에 정의된 매크로를 호출합니다. 짧은 함수 한 줄이 여러 레지스터 저장 명령으로 확장됩니다. FP/SIMD의 고정 크기 상태와 SVE·SME의 가변 크기 상태를 구분해서 읽어야 합니다.

역할과 입력

  • FP/SIMD: x0=상태 구조체
  • SVE: x0=매크로용 상태 기준, x1=FPSR 위치, x2=FFR 처리 여부
  • SME: x0=ZA 버퍼, x1=ZT 저장·복원 여부

원본 .S · 빌드 조건: Makefile · 명령·주소 표기 읽는 법

134줄 · SHA-256: 6c856dfeffd897cab180000319b196cddf24f2e0778c3f554ade9dc6fbaa666d

구조와 흐름

FP/SIMD·SVE·SME 레지스터 저장과 복원
각 상자는 독립된 기능입니다. 위에서 아래로 이어서 호출하는 순서가 아닙니다.

고정 크기 FP/SIMD 상태의 저장 배치

고정 크기 FP/SIMD 상태의 저장 배치
B는 함수 진입 시 x0입니다. 아래 방향은 저장 주소 증가이며 SP 이동이나 실행 분기가 아닙니다.

고정 크기 FP/SIMD 상태

fpsimd_save는 q0–q31의 512바이트를 저장하고 이어 FPSR·FPCR을 각각 4바이트로 저장합니다. 두 번째 인자 8은 임시 x8/w8의 번호입니다. 마지막 q30/q31 접근은 writeback이 있어 x0가 원래 값에서 480바이트 증가합니다. 복원 매크로는 x0를 임시값으로도 사용하므로 호출 후 입력 포인터가 유지되지 않습니다.

entry-fpsimd.S · L1–L33
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * FP/SIMD state saving and restoring
4 *
5 * Copyright (C) 2012 ARM Ltd.
6 * Author: Catalin Marinas <[email protected]>
7 */
8
9#include <linux/linkage.h>
10
11#include <asm/assembler.h>
12#include <asm/fpsimdmacros.h>
13
14/*
15 * Save the FP registers.
16 *
17 * x0 - pointer to struct fpsimd_state
18 */
19SYM_FUNC_START(fpsimd_save_state)
20	fpsimd_save x0, 8
21	ret
22SYM_FUNC_END(fpsimd_save_state)
23
24/*
25 * Load the FP registers.
26 *
27 * x0 - pointer to struct fpsimd_state
28 */
29SYM_FUNC_START(fpsimd_load_state)
30	fpsimd_restore x0, 8
31	ret
32SYM_FUNC_END(fpsimd_load_state)
33
L9
SYM_FUNC_START·SYM_CODE_START·SYM_INNER_LABEL 등의 심볼 선언 규칙을 가져옵니다. 함수인지 코드 내부 라벨인지, 다른 오브젝트에 보일 이름인지와 정렬·크기 정보를 빌드 도구에 전달하는 데 필요합니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.
L11
ARM64의 큰 주소 구성, CPU별 값 조회, 시스템 레지스터 처리, 동기화 등에 쓰는 어셈블리 매크로를 가져옵니다. 각 사용 위치에서 일반 명령 여러 개로 펼쳐지는 작업입니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.
L12
FP/SIMD·SVE·SME 레지스터 저장 형식과 명령 인코딩 매크로를 가져옵니다. 어떤 상태를 어느 offset에 저장하는지, 임시 레지스터 인수가 무엇인지가 여기에 정의됩니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.
L19
(fpsimd_save_state)의 시작 심볼을 정의합니다. 외부에서 참조할 수 있습니다. 정의에 따른 정렬을 적용합니다. ARM64 함수 시작에는 BTI C가 들어갑니다.
L20
x0가 가리키는 저장 영역에 q0~q31의 SIMD/FP 값과 FPSR·FPCR을 보존합니다. 8은 주소나 벡터 수가 아니라 임시 x8/w8을 고르는 매크로 인수입니다. task 전환·시그널 등에서 계산 상태를 잃지 않으려는 저장이며 매크로 내부에서 x0도 이동합니다.
L21
x30(LR)에 든 주소로 이동합니다. SPSR/PSTATE를 복원하는 ERET와는 다릅니다.
L22
(fpsimd_save_state)의 심볼 타입과 크기를 기록합니다. 실행을 끝내는 RET를 생성하지 않습니다.
L29
(fpsimd_load_state)의 시작 심볼을 정의합니다. 외부에서 참조할 수 있습니다. 정의에 따른 정렬을 적용합니다. ARM64 함수 시작에는 BTI C가 들어갑니다.
L30
x0의 메모리 사본에서 q0~q31과 FPSR·FPCR을 CPU에 복원합니다. 임시 레지스터는 x8/w8이며 FPCR은 기존 값과 같으면 불필요한 쓰기를 피합니다. 저장 때와 같은 레이아웃의 버퍼가 필요합니다.
L31
x30(LR)에 든 주소로 이동합니다. SPSR/PSTATE를 복원하는 ERET와는 다릅니다.
L32
(fpsimd_load_state)의 심볼 타입과 크기를 기록합니다. 실행을 끝내는 RET를 생성하지 않습니다.

SVE 저장과 벡터 길이

매크로의 첫 인자 0은 x0의 번호입니다. Z 저장 오프셋은 -34부터, P 저장 오프셋은 -16부터 시작하므로 x0를 단순히 첫 Z 레지스터 저장 주소로 읽으면 안 됩니다. 헤더의 실제 주소식을 함께 봅니다. x2가 0이면 FFR 읽기를 생략하고 저장 슬롯을 0으로 채웁니다. sve_set_vq의 x0는 VQ가 아닌 VQ−1이며, LEN 필드가 바뀔 때만 레지스터에 씁니다.

entry-fpsimd.S · L34–L68
34#ifdef CONFIG_ARM64_SVE
35
36/*
37 * Save the SVE state
38 *
39 * x0 - pointer to buffer for state
40 * x1 - pointer to storage for FPSR
41 * x2 - Save FFR if non-zero
42 */
43SYM_FUNC_START(sve_save_state)
44	sve_save 0, x1, x2, 3
45	ret
46SYM_FUNC_END(sve_save_state)
47
48/*
49 * Load the SVE state
50 *
51 * x0 - pointer to buffer for state
52 * x1 - pointer to storage for FPSR
53 * x2 - Restore FFR if non-zero
54 */
55SYM_FUNC_START(sve_load_state)
56	sve_load 0, x1, x2, 4
57	ret
58SYM_FUNC_END(sve_load_state)
59
60SYM_FUNC_START(sve_get_vl)
61	_sve_rdvl	0, 1
62	ret
63SYM_FUNC_END(sve_get_vl)
64
65SYM_FUNC_START(sve_set_vq)
66	sve_load_vq x0, x1, x2
67	ret
68SYM_FUNC_END(sve_set_vq)
L34
SVE는 기본 128비트 SIMD보다 긴 Z 벡터, P predicate와 FFR 상태를 추가하는 확장입니다. 이 설정을 켜야 아래 저장·복원·길이 조정 코드를 커널에 포함하여 지원 CPU의 task 상태를 관리할 수 있습니다. 꺼지면 아래 SVE 함수들은 빌드되지 않습니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.
L43
(sve_save_state)의 시작 심볼을 정의합니다. 외부에서 참조할 수 있습니다. 정의에 따른 정렬을 적용합니다. ARM64 함수 시작에는 BTI C가 들어갑니다.
L44
x0를 SVE 저장 레이아웃의 FFR 기준 위치로 사용해 Z0~Z31과 P0~P15를 정해진 음수 offset에 저장합니다. 첫 인수 0은 주소 0이 아니라 x0 레지스터 번호입니다. x1은 FPSR/FPCR 저장 위치, x2는 FFR 보존 여부, 3은 임시 x3 번호입니다. x2=0이면 저장 이미지의 FFR은 0으로 만듭니다. 저장 공간의 크기와 Z·P·FFR 사이 오프셋은 현재 SVE 벡터 길이에 따라 달라집니다. 고정 크기인 FPSIMD 저장 형식과 구분해야 합니다.
L45
x30(LR)에 든 주소로 이동합니다. SPSR/PSTATE를 복원하는 ERET와는 다릅니다.
L46
(sve_save_state)의 심볼 타입과 크기를 기록합니다. 실행을 끝내는 RET를 생성하지 않습니다.
L55
(sve_load_state)의 시작 심볼을 정의합니다. 외부에서 참조할 수 있습니다. 정의에 따른 정렬을 적용합니다. ARM64 함수 시작에는 BTI C가 들어갑니다.
L56
x0 기준의 Z·P 상태와 x1 위치의 FPSR/FPCR을 복원합니다. x2가 0이 아니면 FFR도 복원하고 0이면 FFR 로드를 생략합니다. 첫 인수 0과 마지막 4는 각각 x0 기준 주소와 임시 x4를 뜻하는 레지스터 번호입니다. 저장할 때와 같은 SVE 벡터 길이와 레이아웃을 사용해야 각 레지스터의 데이터를 올바른 위치에서 읽을 수 있습니다.
L57
x30(LR)에 든 주소로 이동합니다. SPSR/PSTATE를 복원하는 ERET와는 다릅니다.
L58
(sve_load_state)의 심볼 타입과 크기를 기록합니다. 실행을 끝내는 RET를 생성하지 않습니다.
L60
(sve_get_vl)의 시작 심볼을 정의합니다. 외부에서 참조할 수 있습니다. 정의에 따른 정렬을 적용합니다. ARM64 함수 시작에는 BTI C가 들어갑니다.
L61
RDVL 명령을 인코딩해 현재 SVE 벡터 길이의 1배를 바이트 단위로 x0에 반환합니다. 인수 0은 결과 레지스터 x0, 1은 길이 배수이며 bit 수나 저장 버퍼 주소가 아닙니다.
L62
x30(LR)에 든 주소로 이동합니다. SPSR/PSTATE를 복원하는 ERET와는 다릅니다.
L63
(sve_get_vl)의 심볼 타입과 크기를 기록합니다. 실행을 끝내는 RET를 생성하지 않습니다.
L65
(sve_set_vq)의 시작 심볼을 정의합니다. 외부에서 참조할 수 있습니다. 정의에 따른 정렬을 적용합니다. ARM64 함수 시작에는 BTI C가 들어갑니다.
L66
x0의 VQ-1 값을 ZCR_EL1.LEN 필드에 반영하여 SVE 벡터 길이를 선택합니다. VQ는 16바이트 단위이며 0 인코딩은 128비트 길이입니다. x1·x2는 기존 제어값과 수정값을 계산할 임시 레지스터이고 같은 설정이면 레지스터 쓰기를 생략합니다.
L67
x30(LR)에 든 주소로 이동합니다. SPSR/PSTATE를 복원하는 ERET와는 다릅니다.
L68
(sve_set_vq)의 심볼 타입과 크기를 기록합니다. 실행을 끝내는 RET를 생성하지 않습니다.

SVE 상위 영역 지우기

VQ−1이 0이면 Z의 추가 영역이 없어 sve_flush_z를 생략합니다. 그 외에는 각 V 레지스터의 128비트를 자기 자신에게 써서 Z의 상위 영역을 0으로 만듭니다. P 레지스터는 항상 0으로 만들고 x0의 비트 0이 설정된 경우에만 FFR도 지웁니다.

entry-fpsimd.S · L69–L89
69
70/*
71 * Zero all SVE registers but the first 128-bits of each vector
72 *
73 * VQ must already be configured by caller, any further updates of VQ
74 * will need to ensure that the register state remains valid.
75 *
76 * x0 = include FFR?
77 * x1 = VQ - 1
78 */
79SYM_FUNC_START(sve_flush_live)
80	cbz		x1, 1f	// A VQ-1 of 0 is 128 bits so no extra Z state
81	sve_flush_z
821:	sve_flush_p
83	tbz		x0, #0, 2f
84	sve_flush_ffr
852:	ret
86SYM_FUNC_END(sve_flush_live)
87
88#endif /* CONFIG_ARM64_SVE */
89
L79
(sve_flush_live)의 시작 심볼을 정의합니다. 외부에서 참조할 수 있습니다. 정의에 따른 정렬을 적용합니다. ARM64 함수 시작에는 BTI C가 들어갑니다.
L80
x1은 VQ-1입니다. 값 0이면 Z 레지스터가 기본 128비트뿐이므로 지울 상위 SVE 부분이 없어 sve_flush_z를 건너뜁니다. 이 분기는 지정 레지스터의 값이나 비트를 직접 검사하며 CMP가 남긴 NZCV를 읽거나 바꾸지 않습니다. 조건이 맞지 않으면 바로 다음 명령으로 진행합니다.
L81
모든 Z 레지스터의 하위 128비트 FP/SIMD 값은 유지하고 그 위의 SVE 부분만 0으로 만듭니다. 전체 계산 상태를 버리는 것이 아니라 기본 FPSIMD에서 확장 SVE 상태로 넘어갈 때의 잔여값을 정리합니다.
L82
P0~P15를 모두 false로 만듭니다. predicate는 각 벡터 원소가 연산에 참여할지 정하는 마스크이므로, 이전 사용자의 predicate 상태가 확장 상태에 남지 않게 합니다. 각 predicate 레지스터에 PFALSE 명령을 적용합니다.
L83
x0의 bit 0은 FFR도 정리할지 나타내는 인수입니다. 0이면 해당 작업을 생략하고, 1이면 다음 sve_flush_ffr를 실행합니다. 이 분기는 지정 레지스터의 값이나 비트를 직접 검사하며 CMP가 남긴 NZCV를 읽거나 바꾸지 않습니다. 조건이 맞지 않으면 바로 다음 명령으로 진행합니다.
L84
이미 false로 만든 P0를 FFR에 써서 first-fault 상태를 0으로 정리합니다. FFR은 fault-first load에서 어느 원소까지 유효했는지 나타내는 상태이며 일반 condition flags가 아닙니다.
L85
2 라벨: 다음 코드나 데이터의 위치에 이름을 붙입니다. x30(LR)에 든 주소로 이동합니다. SPSR/PSTATE를 복원하는 ERET와는 다릅니다.
L86
(sve_flush_live)의 심볼 타입과 크기를 기록합니다. 실행을 끝내는 RET를 생성하지 않습니다.
L88
— 전처리 조건 구간을 끝냅니다.

SME의 ZA와 ZT

RDSVL은 스트리밍 벡터 길이를 바이트 단위로 x2에 돌려줍니다. sme_save_za/sme_load_za는 행 인덱스 w12를 증가시키며 행마다 x0를 x2만큼 이동합니다. 완료 후 x0는 ZA 끝을 가리키며, x1이 0이 아니면 이 위치에서 ZT0을 처리합니다. SVE와 SME 경로는 각각의 CONFIG에 따라 포함됩니다.

entry-fpsimd.S · L90–L134
90#ifdef CONFIG_ARM64_SME
91
92SYM_FUNC_START(sme_get_vl)
93	_sme_rdsvl	0, 1
94	ret
95SYM_FUNC_END(sme_get_vl)
96
97SYM_FUNC_START(sme_set_vq)
98	sme_load_vq x0, x1, x2
99	ret
100SYM_FUNC_END(sme_set_vq)
101
102/*
103 * Save the ZA and ZT state
104 *
105 * x0 - pointer to buffer for state
106 * x1 - number of ZT registers to save
107 */
108SYM_FUNC_START(sme_save_state)
109	_sme_rdsvl	2, 1		// x2 = VL/8
110	sme_save_za 0, x2, 12		// Leaves x0 pointing to the end of ZA
111
112	cbz	x1, 1f
113	_str_zt 0
1141:
115	ret
116SYM_FUNC_END(sme_save_state)
117
118/*
119 * Load the ZA and ZT state
120 *
121 * x0 - pointer to buffer for state
122 * x1 - number of ZT registers to save
123 */
124SYM_FUNC_START(sme_load_state)
125	_sme_rdsvl	2, 1		// x2 = VL/8
126	sme_load_za 0, x2, 12		// Leaves x0 pointing to the end of ZA
127
128	cbz	x1, 1f
129	_ldr_zt 0
1301:
131	ret
132SYM_FUNC_END(sme_load_state)
133
134#endif /* CONFIG_ARM64_SME */
L90
SME는 streaming vector 실행과 2차원 행렬 누산 상태 ZA 등을 추가합니다. 이 설정을 켜면 아래 streaming 길이·ZA·선택적 ZT 저장 복원 함수를 빌드하고, 꺼지면 포함하지 않습니다. 실제 SME/SME2 사용 가능 여부와 mode 활성화는 호출자도 확인해야 합니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.
L92
(sme_get_vl)의 시작 심볼을 정의합니다. 외부에서 참조할 수 있습니다. 정의에 따른 정렬을 적용합니다. ARM64 함수 시작에는 BTI C가 들어갑니다.
L93
RDSVL로 streaming vector 길이의 1배를 바이트 단위로 x0에 읽습니다. 일반 SVE VL과 SME의 SVL은 별도로 선택될 수 있으므로 sve_get_vl 대신 이 함수를 사용합니다. 매크로 인수 0은 목적 레지스터 x0의 번호이고 1은 길이에 곱할 배수입니다. 어셈블러가 이 인수로 RDSVL 인코딩을 만듭니다.
L94
x30(LR)에 든 주소로 이동합니다. SPSR/PSTATE를 복원하는 ERET와는 다릅니다.
L95
(sme_get_vl)의 심볼 타입과 크기를 기록합니다. 실행을 끝내는 RET를 생성하지 않습니다.
L97
(sme_set_vq)의 시작 심볼을 정의합니다. 외부에서 참조할 수 있습니다. 정의에 따른 정렬을 적용합니다. ARM64 함수 시작에는 BTI C가 들어갑니다.
L98
x0의 VQ-1 인코딩을 SMCR_EL1.LEN에 반영해 streaming vector 길이를 정합니다. x1·x2는 임시 값이며 ZCR_EL1을 쓰는 일반 SVE 길이 설정과 구분합니다.
L99
x30(LR)에 든 주소로 이동합니다. SPSR/PSTATE를 복원하는 ERET와는 다릅니다.
L100
(sme_set_vq)의 심볼 타입과 크기를 기록합니다. 실행을 끝내는 RET를 생성하지 않습니다.
L108
(sme_save_state)의 시작 심볼을 정의합니다. 외부에서 참조할 수 있습니다. 정의에 따른 정렬을 적용합니다. ARM64 함수 시작에는 BTI C가 들어갑니다.
L109
streaming vector 길이를 바이트 수로 x2에 읽습니다. ZA 한 행의 크기이자 ZA 행 개수의 기준이므로 뒤의 반복 저장에 필요합니다. 매크로 인수 2은 목적 레지스터 x2의 번호이고 1은 길이에 곱할 배수입니다. 어셈블러가 이 인수로 RDSVL 인코딩을 만듭니다.
L110
ZA의 각 행을 x0가 가리키는 버퍼에 저장합니다. 0은 기준 x0 번호, x2는 행 크기, 12는 행 선택용 w12 번호입니다. 매 행 뒤 x0를 늘려 전체 SVL_bytes² 영역을 저장하고 끝 위치를 남깁니다.
L112
호출자가 x1로 ZT 상태 저장 필요 여부를 전달합니다. 0이면 ZA만 저장한 뒤 반환하고, 0이 아니면 바로 뒤의 ZT 저장을 실행합니다. 이 분기는 지정 레지스터의 값이나 비트를 직접 검사하며 CMP가 남긴 NZCV를 읽거나 바꾸지 않습니다. 조건이 맞지 않으면 바로 다음 명령으로 진행합니다.
L113
현재 x0, 즉 ZA 이미지 뒤의 위치에 ZT0 상태를 저장하는 인코딩을 출력합니다. ZT0는 지원 SME 확장의 추가 상태이며 이 줄이 모든 SME CPU에서 무조건 실행된다고 가정하지 않습니다.
L114
1 라벨: 다음 코드나 데이터의 위치에 이름을 붙입니다.
L115
x30(LR)에 든 주소로 이동합니다. SPSR/PSTATE를 복원하는 ERET와는 다릅니다.
L116
(sme_save_state)의 심볼 타입과 크기를 기록합니다. 실행을 끝내는 RET를 생성하지 않습니다.
L124
(sme_load_state)의 시작 심볼을 정의합니다. 외부에서 참조할 수 있습니다. 정의에 따른 정렬을 적용합니다. ARM64 함수 시작에는 BTI C가 들어갑니다.
L125
현재 streaming vector 길이를 바이트 단위로 x2에 읽어 ZA 복원 행 크기를 정합니다. 저장 버퍼의 레이아웃과 복원 시 길이가 맞아야 합니다. 매크로 인수 2은 목적 레지스터 x2의 번호이고 1은 길이에 곱할 배수입니다. 어셈블러가 이 인수로 RDSVL 인코딩을 만듭니다.
L126
x0 기준 버퍼에서 ZA를 행 단위로 복원하고 x0를 ZA 이미지 끝으로 이동합니다. w12가 행 선택을 위한 임시 레지스터이며 x2가 각 행의 바이트 수입니다.
L128
x1=0이면 추가 ZT 상태 복원을 생략하고, 그 외에는 저장 이미지에서 ZA 뒤의 ZT0를 읽습니다. 하드웨어 지원에 맞는 인수를 주는 것은 호출자의 책임입니다. 이 분기는 지정 레지스터의 값이나 비트를 직접 검사하며 CMP가 남긴 NZCV를 읽거나 바꾸지 않습니다. 조건이 맞지 않으면 바로 다음 명령으로 진행합니다.
L129
ZA 복원 뒤의 x0 위치에서 ZT0를 읽습니다. 첫 인수 0은 주소 상수가 아니라 x0 레지스터를 고르는 매크로 인수입니다.
L130
1 라벨: 다음 코드나 데이터의 위치에 이름을 붙입니다.
L131
x30(LR)에 든 주소로 이동합니다. SPSR/PSTATE를 복원하는 ERET와는 다릅니다.
L132
(sme_load_state)의 심볼 타입과 크기를 기록합니다. 실행을 끝내는 RET를 생성하지 않습니다.
L134
— 전처리 조건 구간을 끝냅니다.

매크로 정의와 확장

각 정의는 v6.18.37 원문입니다. 역슬래시 인자는 사용 위치의 값으로 치환되며, 안쪽 매크로와 조건부 블록은 이후 단계에서 다시 처리됩니다.

SYM_FUNC_END

아래 정의의 인자 치환, 조건부 생성과 중첩 매크로를 통해 코드를 만듭니다. SYM 계열의 타입·범위·BTI 차이는 공통 표기 설명에 정리했습니다.

include/linux/linkage.h L248–L249

앞뒤 조건을 포함한 원문

#define SYM_FUNC_END(name)				\
	SYM_END(name, SYM_T_FUNC)

SYM_FUNC_START

아래 정의의 인자 치환, 조건부 생성과 중첩 매크로를 통해 코드를 만듭니다. SYM 계열의 타입·범위·BTI 차이는 공통 표기 설명에 정리했습니다.

arch/arm64/include/asm/linkage.h L18–L20

앞뒤 조건을 포함한 원문

#define SYM_FUNC_START(name)				\
	SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)	\
	bti c ;
include/linux/linkage.h L209–L210

앞뒤 조건을 포함한 원문

#define SYM_FUNC_START(name)				\
	SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)

_ldr_zt

레지스터 번호 인자가 가리키는 주소에서 ZT0을 복원합니다.

arch/arm64/include/asm/fpsimdmacros.h L228–L232

앞뒤 조건을 포함한 원문

.macro _ldr_zt nx
	_check_general_reg \nx
	.inst	0xe11f8000	\
		 | (\nx << 5)
.endm
인자 치환 예: _ldr_zt 0

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

	_check_general_reg 0
	.inst	0xe11f8000	\
		 | (0 << 5)

_sme_rdsvl

첫 인자가 가리키는 X 레지스터에 스트리밍 벡터 길이×즉시값을 바이트 단위로 반환하는 RDSVL 인코딩을 생성합니다.

arch/arm64/include/asm/fpsimdmacros.h L187–L193

앞뒤 조건을 포함한 원문

.macro _sme_rdsvl nx, imm
	_check_general_reg \nx
	_check_num (\imm), -0x20, 0x1f
	.inst	0x04bf5800			\
		| (\nx)				\
		| (((\imm) & 0x3f) << 5)
.endm
인자 치환 예: _sme_rdsvl 0, 1

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

	_check_general_reg 0
	_check_num (1), -0x20, 0x1f
	.inst	0x04bf5800			\
		| (0)				\
		| (((1) & 0x3f) << 5)

_str_zt

레지스터 번호 인자가 가리키는 주소에 ZT0을 저장합니다.

arch/arm64/include/asm/fpsimdmacros.h L239–L243

앞뒤 조건을 포함한 원문

.macro _str_zt nx
	_check_general_reg \nx
	.inst	0xe13f8000		\
		| (\nx << 5)
.endm
인자 치환 예: _str_zt 0

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

	_check_general_reg 0
	.inst	0xe13f8000		\
		| (0 << 5)

_sve_rdvl

첫 인자가 가리키는 X 레지스터에 현재 SVE 벡터 길이×즉시값을 바이트 단위로 반환하는 RDVL 인코딩을 생성합니다.

arch/arm64/include/asm/fpsimdmacros.h L154–L160

앞뒤 조건을 포함한 원문

.macro _sve_rdvl nx, imm
	_check_general_reg \nx
	_check_num (\imm), -0x20, 0x1f
	.inst	0x04bf5000			\
		| (\nx)				\
		| (((\imm) & 0x3f) << 5)
.endm
인자 치환 예: _sve_rdvl 0, 1

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

	_check_general_reg 0
	_check_num (1), -0x20, 0x1f
	.inst	0x04bf5000			\
		| (0)				\
		| (((1) & 0x3f) << 5)

fpsimd_restore

q0–q31·FPSR·FPCR을 복원합니다. FPCR이 기존 값과 같은 경우 쓰기를 생략합니다. 상태 포인터는 보존되지 않습니다.

arch/arm64/include/asm/fpsimdmacros.h L47–L68

앞뒤 조건을 포함한 원문

.macro fpsimd_restore state, tmpnr
	ldp	q0, q1, [\state, #16 * 0]
	ldp	q2, q3, [\state, #16 * 2]
	ldp	q4, q5, [\state, #16 * 4]
	ldp	q6, q7, [\state, #16 * 6]
	ldp	q8, q9, [\state, #16 * 8]
	ldp	q10, q11, [\state, #16 * 10]
	ldp	q12, q13, [\state, #16 * 12]
	ldp	q14, q15, [\state, #16 * 14]
	ldp	q16, q17, [\state, #16 * 16]
	ldp	q18, q19, [\state, #16 * 18]
	ldp	q20, q21, [\state, #16 * 20]
	ldp	q22, q23, [\state, #16 * 22]
	ldp	q24, q25, [\state, #16 * 24]
	ldp	q26, q27, [\state, #16 * 26]
	ldp	q28, q29, [\state, #16 * 28]
	ldp	q30, q31, [\state, #16 * 30]!
	ldr	w\tmpnr, [\state, #16 * 2]
	msr	fpsr, x\tmpnr
	ldr	w\tmpnr, [\state, #16 * 2 + 4]
	fpsimd_restore_fpcr x\tmpnr, \state
.endm
인자 치환 예: fpsimd_restore x0, 8

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

	ldp	q0, q1, [x0, #16 * 0]
	ldp	q2, q3, [x0, #16 * 2]
	ldp	q4, q5, [x0, #16 * 4]
	ldp	q6, q7, [x0, #16 * 6]
	ldp	q8, q9, [x0, #16 * 8]
	ldp	q10, q11, [x0, #16 * 10]
	ldp	q12, q13, [x0, #16 * 12]
	ldp	q14, q15, [x0, #16 * 14]
	ldp	q16, q17, [x0, #16 * 16]
	ldp	q18, q19, [x0, #16 * 18]
	ldp	q20, q21, [x0, #16 * 20]
	ldp	q22, q23, [x0, #16 * 22]
	ldp	q24, q25, [x0, #16 * 24]
	ldp	q26, q27, [x0, #16 * 26]
	ldp	q28, q29, [x0, #16 * 28]
	ldp	q30, q31, [x0, #16 * 30]!
	ldr	w8, [x0, #16 * 2]
	msr	fpsr, x8
	ldr	w8, [x0, #16 * 2 + 4]
	fpsimd_restore_fpcr x8, x0

fpsimd_save

q0–q31과 FPSR·FPCR을 저장합니다. 두 번째 인자는 임시 레지스터 번호이며, 마지막 쌍 저장의 writeback으로 상태 포인터도 바뀝니다.

arch/arm64/include/asm/fpsimdmacros.h L11–L32

앞뒤 조건을 포함한 원문

.macro fpsimd_save state, tmpnr
	stp	q0, q1, [\state, #16 * 0]
	stp	q2, q3, [\state, #16 * 2]
	stp	q4, q5, [\state, #16 * 4]
	stp	q6, q7, [\state, #16 * 6]
	stp	q8, q9, [\state, #16 * 8]
	stp	q10, q11, [\state, #16 * 10]
	stp	q12, q13, [\state, #16 * 12]
	stp	q14, q15, [\state, #16 * 14]
	stp	q16, q17, [\state, #16 * 16]
	stp	q18, q19, [\state, #16 * 18]
	stp	q20, q21, [\state, #16 * 20]
	stp	q22, q23, [\state, #16 * 22]
	stp	q24, q25, [\state, #16 * 24]
	stp	q26, q27, [\state, #16 * 26]
	stp	q28, q29, [\state, #16 * 28]
	stp	q30, q31, [\state, #16 * 30]!
	mrs	x\tmpnr, fpsr
	str	w\tmpnr, [\state, #16 * 2]
	mrs	x\tmpnr, fpcr
	str	w\tmpnr, [\state, #16 * 2 + 4]
.endm
인자 치환 예: fpsimd_save x0, 8

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

	stp	q0, q1, [x0, #16 * 0]
	stp	q2, q3, [x0, #16 * 2]
	stp	q4, q5, [x0, #16 * 4]
	stp	q6, q7, [x0, #16 * 6]
	stp	q8, q9, [x0, #16 * 8]
	stp	q10, q11, [x0, #16 * 10]
	stp	q12, q13, [x0, #16 * 12]
	stp	q14, q15, [x0, #16 * 14]
	stp	q16, q17, [x0, #16 * 16]
	stp	q18, q19, [x0, #16 * 18]
	stp	q20, q21, [x0, #16 * 20]
	stp	q22, q23, [x0, #16 * 22]
	stp	q24, q25, [x0, #16 * 24]
	stp	q26, q27, [x0, #16 * 26]
	stp	q28, q29, [x0, #16 * 28]
	stp	q30, q31, [x0, #16 * 30]!
	mrs	x8, fpsr
	str	w8, [x0, #16 * 2]
	mrs	x8, fpcr
	str	w8, [x0, #16 * 2 + 4]

sme_load_vq

VQ−1을 SMCR_EL1.LEN에 반영하여 스트리밍 벡터 길이를 설정합니다.

arch/arm64/include/asm/fpsimdmacros.h L280–L288

앞뒤 조건을 포함한 원문

.macro sme_load_vq xvqminus1, xtmp, xtmp2
		mrs_s		\xtmp, SYS_SMCR_EL1
		bic		\xtmp2, \xtmp, SMCR_ELx_LEN_MASK
		orr		\xtmp2, \xtmp2, \xvqminus1
		cmp		\xtmp2, \xtmp
		b.eq		921f
		msr_s		SYS_SMCR_EL1, \xtmp2	//self-synchronising
921:
.endm
인자 치환 예: sme_load_vq x0, x1, x2

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

		mrs_s		x1, SYS_SMCR_EL1
		bic		x2, x1, SMCR_ELx_LEN_MASK
		orr		x2, x2, x0
		cmp		x2, x1
		b.eq		921f
		msr_s		SYS_SMCR_EL1, x2	//self-synchronising
921:

sme_load_za

ZA의 각 행을 버퍼에서 읽으며 포인터를 ZA 끝까지 증가시킵니다.

arch/arm64/include/asm/fpsimdmacros.h L348–L357

앞뒤 조건을 포함한 원문

.macro sme_load_za nxbase, xvl, nw
	mov	w\nw, #0

423:
	_sme_ldr_zav \nw, \nxbase
	add	x\nxbase, x\nxbase, \xvl
	add	x\nw, x\nw, #1
	cmp	\xvl, x\nw
	bne	423b
.endm
인자 치환 예: sme_load_za 0, x2, 12

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

	mov	w12, #0

423:
	_sme_ldr_zav 12, 0
	add	x0, x0, x2
	add	x12, x12, #1
	cmp	x2, x12
	bne	423b

sme_save_za

ZA를 스트리밍 벡터 길이만큼의 행 단위로 저장하고 버퍼 포인터를 ZA 끝까지 증가시킵니다.

arch/arm64/include/asm/fpsimdmacros.h L337–L346

앞뒤 조건을 포함한 원문

.macro sme_save_za nxbase, xvl, nw
	mov	w\nw, #0

423:
	_sme_str_zav \nw, \nxbase
	add	x\nxbase, x\nxbase, \xvl
	add	x\nw, x\nw, #1
	cmp	\xvl, x\nw
	bne	423b
.endm
인자 치환 예: sme_save_za 0, x2, 12

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

	mov	w12, #0

423:
	_sme_str_zav 12, 0
	add	x0, x0, x2
	add	x12, x12, #1
	cmp	x2, x12
	bne	423b

sve_flush_ffr

앞에서 0으로 만든 P0를 FFR에 씁니다.

arch/arm64/include/asm/fpsimdmacros.h L302–L304

앞뒤 조건을 포함한 원문

.macro sve_flush_ffr
		_sve_wrffr	0
.endm
인자 치환 예: sve_flush_ffr

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

		_sve_wrffr	0

sve_flush_p

P0–P15에 PFALSE를 적용합니다.

arch/arm64/include/asm/fpsimdmacros.h L299–L301

앞뒤 조건을 포함한 원문

.macro sve_flush_p
 _for n, 0, 15, _sve_pfalse	\n
.endm
인자 치환 예: sve_flush_p

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

 _for n, 0, 15, _sve_pfalse	\n

sve_flush_z

각 Z 레지스터의 하위 128비트는 유지하고 나머지 비트를 0으로 만듭니다.

arch/arm64/include/asm/fpsimdmacros.h L296–L298

앞뒤 조건을 포함한 원문

.macro sve_flush_z
 _for n, 0, 31, _sve_flush_z	\n
.endm
인자 치환 예: sve_flush_z

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

 _for n, 0, 31, _sve_flush_z	\n

sve_load

Z·P와 선택적 FFR을 복구하고 별도 포인터의 FPSR/FPCR을 읽습니다.

arch/arm64/include/asm/fpsimdmacros.h L323–L335

앞뒤 조건을 포함한 원문

.macro sve_load nxbase, xpfpsr, restore_ffr, nxtmp
 _for n, 0, 31,	_sve_ldr_v	\n, \nxbase, \n - 34
		cbz		\restore_ffr, 921f
		_sve_ldr_p	0, \nxbase
		_sve_wrffr	0
921:
 _for n, 0, 15,	_sve_ldr_p	\n, \nxbase, \n - 16

		ldr		w\nxtmp, [\xpfpsr]
		msr		fpsr, x\nxtmp
		ldr		w\nxtmp, [\xpfpsr, #4]
		msr		fpcr, x\nxtmp
.endm
인자 치환 예: sve_load 0, x1, x2, 4

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

 _for n, 0, 31,	_sve_ldr_v	\n, 0, \n - 34
		cbz		x2, 921f
		_sve_ldr_p	0, 0
		_sve_wrffr	0
921:
 _for n, 0, 15,	_sve_ldr_p	\n, 0, \n - 16

		ldr		w4, [x1]
		msr		fpsr, x4
		ldr		w4, [x1, #4]
		msr		fpcr, x4

sve_load_vq

x0에 해당하는 VQ−1을 ZCR_EL1.LEN에 반영합니다. 현재 값과 다를 때만 MSR을 수행합니다.

arch/arm64/include/asm/fpsimdmacros.h L269–L277

앞뒤 조건을 포함한 원문

.macro sve_load_vq xvqminus1, xtmp, xtmp2
		mrs_s		\xtmp, SYS_ZCR_EL1
		bic		\xtmp2, \xtmp, ZCR_ELx_LEN_MASK
		orr		\xtmp2, \xtmp2, \xvqminus1
		cmp		\xtmp2, \xtmp
		b.eq		921f
		msr_s		SYS_ZCR_EL1, \xtmp2	//self-synchronising
921:
.endm
인자 치환 예: sve_load_vq x0, x1, x2

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

		mrs_s		x1, SYS_ZCR_EL1
		bic		x2, x1, ZCR_ELx_LEN_MASK
		orr		x2, x2, x0
		cmp		x2, x1
		b.eq		921f
		msr_s		SYS_ZCR_EL1, x2	//self-synchronising
921:

sve_save

Z0–Z31, P0–P15와 FFR 슬롯을 저장합니다. FFR을 읽지 않는 경로에서는 슬롯을 0으로 저장합니다. FPSR/FPCR은 별도 포인터에 저장합니다.

arch/arm64/include/asm/fpsimdmacros.h L306–L321

앞뒤 조건을 포함한 원문

.macro sve_save nxbase, xpfpsr, save_ffr, nxtmp
 _for n, 0, 31,	_sve_str_v	\n, \nxbase, \n - 34
 _for n, 0, 15,	_sve_str_p	\n, \nxbase, \n - 16
		cbz		\save_ffr, 921f
		_sve_rdffr	0
		b		922f
921:
		_sve_pfalse	0			// Zero out FFR
922:
		_sve_str_p	0, \nxbase
		_sve_ldr_p	0, \nxbase, -16
		mrs		x\nxtmp, fpsr
		str		w\nxtmp, [\xpfpsr]
		mrs		x\nxtmp, fpcr
		str		w\nxtmp, [\xpfpsr, #4]
.endm
인자 치환 예: sve_save 0, x1, x2, 3

1단계 치환 결과입니다. 내부 매크로·조건·고유 라벨 번호는 아직 펼치지 않았습니다.

 _for n, 0, 31,	_sve_str_v	\n, 0, \n - 34
 _for n, 0, 15,	_sve_str_p	\n, 0, \n - 16
		cbz		x2, 921f
		_sve_rdffr	0
		b		922f
921:
		_sve_pfalse	0			// Zero out FFR
922:
		_sve_str_p	0, 0
		_sve_ldr_p	0, 0, -16
		mrs		x3, fpsr
		str		w3, [x1]
		mrs		x3, fpcr
		str		w3, [x1, #4]

상수·구조체 오프셋

S_*·THREAD_*·FREGS_* 등의 구조체 오프셋은 빌드한 C 구조체 배치에서 생성됩니다. 숫자를 고정하지 않고 원래 기호를 사용했습니다.

asm-offsets.c의 생성 식

    맨 위로 ↑