VirtualBox

source: vbox/trunk/include/iprt/asm-arm.h@ 100201

Last change on this file since 100201 was 100201, checked in by vboxsync, 12 months ago

include/iprt/asm-arm.h: Some ASM*() helpers for arm64. [doxygen fix] bugref:10457

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.3 KB
Line 
1/** @file
2 * IPRT - ARM Specific Assembly Functions.
3 */
4
5/*
6 * Copyright (C) 2015-2023 Oracle and/or its affiliates.
7 *
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, in version 3 of the
14 * License.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses>.
23 *
24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
26 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
27 * in the VirtualBox distribution, in which case the provisions of the
28 * CDDL are applicable instead of those of the GPL.
29 *
30 * You may elect to license modified versions of this file under the
31 * terms and conditions of either the GPL or the CDDL or both.
32 *
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
34 */
35
36#ifndef IPRT_INCLUDED_asm_arm_h
37#define IPRT_INCLUDED_asm_arm_h
38#ifndef RT_WITHOUT_PRAGMA_ONCE
39# pragma once
40#endif
41
42#include <iprt/types.h>
43#if !defined(RT_ARCH_ARM64) && !defined(RT_ARCH_ARM32)
44# error "Not on ARM64 or ARM32"
45#endif
46
47/** @defgroup grp_rt_asm_arm ARM Specific ASM Routines
48 * @ingroup grp_rt_asm
49 * @{
50 */
51
52/**
53 * Gets the content of the CNTVCT_EL0 (or CNTPCT) register.
54 *
55 * @returns CNTVCT_EL0 value.
56 * @note We call this TSC to better fit in with existing x86/amd64 based code.
57 */
58#if RT_INLINE_ASM_EXTERNAL
59DECLASM(uint64_t) ASMReadTSC(void);
60#else
61DECLINLINE(uint64_t) ASMReadTSC(void)
62{
63# if RT_INLINE_ASM_GNU_STYLE
64 uint64_t u64;
65# ifdef RT_ARCH_ARM64
66 __asm__ __volatile__("isb\n\t"
67 "mrs %0, CNTVCT_EL0\n\t"
68 : "=r" (u64));
69# else
70 uint32_t u32Spill;
71 uint32_t u32Comp;
72 __asm__ __volatile__("isb\n"
73 "Lagain:\n\t"
74 "mrrc p15, 0, %[uSpill], %H[uRet], c14\n\t" /* CNTPCT high into uRet.hi */
75 "mrrc p15, 0, %[uRet], %[uSpill], c14\n\t" /* CNTPCT low into uRet.lo */
76 "mrrc p15, 0, %[uSpill], %[uHiComp], c14\n\t" /* CNTPCT high into uHiComp */
77 "cmp %H[uRet], %[uHiComp]\n\t"
78 "b.eq Lagain\n\t" /* Redo if high value changed. */
79 : [uRet] "=r" (u64)
80 , "=r" (uHiComp)
81 , "=r" (uSpill));
82# endif
83 return u64;
84
85# else
86# error "Unsupported compiler"
87# endif
88}
89#endif
90
91
92/**
93 * Gets the content of the CNTFRQ_EL0 register.
94 *
95 * @returns CNTFRQ_EL0 value.
96 */
97#if RT_INLINE_ASM_EXTERNAL
98DECLASM(uint64_t) ASMReadCntFrqEl0(void);
99#else
100DECLINLINE(uint64_t) ASMReadCntFrqEl0(void)
101{
102# if RT_INLINE_ASM_GNU_STYLE
103 uint64_t u64;
104# ifdef RT_ARCH_ARM64
105 __asm__ __volatile__("isb\n\t"
106 "mrs %0, CNTFRQ_EL0\n\t"
107 : "=r" (u64));
108# else
109 u64 = 0;
110 __asm__ __volatile__("isb\n"
111 "mrc p15, 0, %[uRet], c14, 0, 0\n\t" /* CNTFRQ */
112 : [uRet] "=r" (u64));
113# endif
114 return u64;
115
116# else
117# error "Unsupported compiler"
118# endif
119}
120#endif
121
122
123/**
124 * Enables interrupts (IRQ and FIQ).
125 */
126#if RT_INLINE_ASM_EXTERNAL
127DECLASM(void) ASMIntEnable(void);
128#else
129DECLINLINE(void) ASMIntEnable(void)
130{
131# if RT_INLINE_ASM_GNU_STYLE
132# ifdef RT_ARCH_ARM64
133 __asm__ __volatile__("msr daifclr, #0xf\n\t");
134# else
135 RTCCUINTREG uFlags;
136 __asm__ __volatile__("mrs %0, cpsr\n\t"
137 "bic %0, %0, #0xc0\n\t"
138 "msr cpsr_c, %0\n\t"
139 : "=r" (uFlags));
140# endif
141# else
142# error "Unsupported compiler"
143# endif
144}
145#endif
146
147
148/**
149 * Disables interrupts (IRQ and FIQ).
150 */
151#if RT_INLINE_ASM_EXTERNAL
152DECLASM(void) ASMIntDisable(void);
153#else
154DECLINLINE(void) ASMIntDisable(void)
155{
156# if RT_INLINE_ASM_GNU_STYLE
157# ifdef RT_ARCH_ARM64
158 __asm__ __volatile__("msr daifset, #0xf\n\t");
159# else
160 RTCCUINTREG uFlags;
161 __asm__ __volatile__("mrs %0, cpsr\n\t"
162 "orr %0, %0, #0xc0\n\t"
163 "msr cpsr_c, %0\n\t"
164 : "=r" (uFlags));
165# endif
166# else
167# error "Unsupported compiler"
168# endif
169}
170#endif
171
172
173/**
174 * Disables interrupts and returns previous uFLAGS.
175 */
176#if RT_INLINE_ASM_EXTERNAL
177DECLASM(RTCCUINTREG) ASMIntDisableFlags(void);
178#else
179DECLINLINE(RTCCUINTREG) ASMIntDisableFlags(void)
180{
181 RTCCUINTREG uFlags;
182# if RT_INLINE_ASM_GNU_STYLE
183# ifdef RT_ARCH_ARM64
184 __asm__ __volatile__("mrs %[uRet], daif\n\t"
185 "msr daifset, #0xf\n\t"
186 : [uRet] "=r" (uFlags));
187# else
188 RTCCUINTREG uNewFlags;
189 __asm__ __volatile__("mrs %0, cpsr\n\t"
190 "orr %1, %0, #0xc0\n\t"
191 "msr cpsr_c, %1\n\t"
192 : "=r" (uFlags)
193 , "=r" (uNewFlags));
194# endif
195# else
196# error "Unsupported compiler"
197# endif
198 return uFlags;
199}
200
201
202/**
203 * Get the CPSR/PSTATE register.
204 * @returns CPSR/PSTATE.
205 */
206#if RT_INLINE_ASM_EXTERNAL
207DECLASM(RTCCUINTREG) ASMGetFlags(void);
208#else
209DECLINLINE(RTCCUINTREG) ASMGetFlags(void)
210{
211 RTCCUINTREG uFlags;
212# if RT_INLINE_ASM_GNU_STYLE
213# ifdef RT_ARCH_ARM64
214 __asm__ __volatile__("isb\n\t"
215 "mrs %0, daif\n\t"
216 : "=r" (uFlags));
217# else
218# error "Implementation required for arm32"
219# endif
220# else
221# error "Unsupported compiler"
222# endif
223 return uFlags;
224}
225#endif
226
227
228/**
229 * Get the CPSR/PSTATE register.
230 */
231#if RT_INLINE_ASM_EXTERNAL
232DECLASM(void) ASMSetFlags(RTCCUINTREG uFlags);
233#else
234DECLINLINE(void) ASMSetFlags(RTCCUINTREG uFlags)
235{
236# if RT_INLINE_ASM_GNU_STYLE
237# ifdef RT_ARCH_ARM64
238 __asm__ __volatile__("isb\n\t"
239 "msr daif, %[uFlags]\n\t"
240 : : [uFlags] "r" (uFlags));
241# else
242# error "Implementation required for arm32"
243# endif
244# else
245# error "Unsupported compiler"
246# endif
247}
248#endif
249
250
251/**
252 * Are interrupts enabled?
253 *
254 * @returns true / false.
255 */
256DECLINLINE(bool) ASMIntAreEnabled(void)
257{
258 return ASMGetFlags() & 0xc0 /* IRQ and FIQ bits */ ? true : false;
259}
260
261#endif
262
263/**
264 * Halts the CPU until interrupted.
265 */
266#if RT_INLINE_ASM_EXTERNAL
267DECLASM(void) ASMHalt(void);
268#else
269DECLINLINE(void) ASMHalt(void)
270{
271# if RT_INLINE_ASM_GNU_STYLE
272 __asm__ __volatile__ ("wfi\n\t"); /* wait for interrupt */
273# else
274# error "Unsupported compiler"
275# endif
276}
277#endif
278
279#if 0
280/**
281 * Gets the CPU ID of the current CPU.
282 *
283 * @returns the CPU ID.
284 * @note the name of this method is a bit misleading but serves the purpose
285 * and prevents #ifdef orgies in other places.
286 */
287#if RT_INLINE_ASM_EXTERNAL
288DECLASM(uint8_t) ASMGetApicId(void);
289#else
290DECLINLINE(uint8_t) ASMGetApicId(void)
291{
292# if RT_INLINE_ASM_GNU_STYLE
293 RTCCUINTREG uCpuId;
294 __asm__ ("mrc p15, 0, %0, c0, c0, 5\n\t" /* CPU ID Register, privileged */
295 : "=r" (uCpuId));
296 return uCpuId;
297# else
298# error "Unsupported compiler"
299# endif
300}
301#endif
302#endif
303
304#if 0
305
306/**
307 * Invalidate page.
308 *
309 * @param pv Address of the page to invalidate.
310 */
311#if RT_INLINE_ASM_EXTERNAL
312DECLASM(void) ASMInvalidatePage(void *pv);
313#else
314DECLINLINE(void) ASMInvalidatePage(void *pv)
315{
316# if RT_INLINE_ASM_GNU_STYLE
317
318# else
319# error "Unsupported compiler"
320# endif
321}
322#endif
323
324
325/**
326 * Write back the internal caches and invalidate them.
327 */
328#if RT_INLINE_ASM_EXTERNAL
329DECLASM(void) ASMWriteBackAndInvalidateCaches(void);
330#else
331DECLINLINE(void) ASMWriteBackAndInvalidateCaches(void)
332{
333# if RT_INLINE_ASM_GNU_STYLE
334
335# else
336# error "Unsupported compiler"
337# endif
338}
339#endif
340
341
342/**
343 * Invalidate internal and (perhaps) external caches without first
344 * flushing dirty cache lines. Use with extreme care.
345 */
346#if RT_INLINE_ASM_EXTERNAL
347DECLASM(void) ASMInvalidateInternalCaches(void);
348#else
349DECLINLINE(void) ASMInvalidateInternalCaches(void)
350{
351# if RT_INLINE_ASM_GNU_STYLE
352
353# else
354# error "Unsupported compiler"
355# endif
356}
357#endif
358
359#endif
360
361
362/** @} */
363#endif /* !IPRT_INCLUDED_asm_arm_h */
364
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use