VirtualBox

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

Last change on this file since 104070 was 101228, checked in by vboxsync, 15 months ago

iprt/asm.h,asm-arm.h: Fixed incorrect local labels (no leading '.', duh) so clang doesn't get confused and messes up C++ exception throwing/catching (iemOpcodeFetchBytesJmp). bugref:10370

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.1 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__("Lstart_ASMReadTSC_%=:\n\t"
67 "isb\n\t"
68 "mrs %0, CNTVCT_EL0\n\t"
69 : "=r" (u64));
70# else
71 uint32_t u32Spill;
72 uint32_t u32Comp;
73 __asm__ __volatile__("Lstart_ASMReadTSC_%=:\n\t"
74 "isb\n"
75 "Ltry_again_ASMReadTSC_%=:\n\t"
76 "mrrc p15, 0, %[uSpill], %H[uRet], c14\n\t" /* CNTPCT high into uRet.hi */
77 "mrrc p15, 0, %[uRet], %[uSpill], c14\n\t" /* CNTPCT low into uRet.lo */
78 "mrrc p15, 0, %[uSpill], %[uHiComp], c14\n\t" /* CNTPCT high into uHiComp */
79 "cmp %H[uRet], %[uHiComp]\n\t"
80 "b.eq Ltry_again_ASMReadTSC_%=\n\t" /* Redo if high value changed. */
81 : [uRet] "=r" (u64)
82 , "=r" (uHiComp)
83 , "=r" (uSpill));
84# endif
85 return u64;
86
87# else
88# error "Unsupported compiler"
89# endif
90}
91#endif
92
93
94/**
95 * Gets the content of the CNTFRQ_EL0 register.
96 *
97 * @returns CNTFRQ_EL0 value.
98 */
99#if RT_INLINE_ASM_EXTERNAL
100DECLASM(uint64_t) ASMReadCntFrqEl0(void);
101#else
102DECLINLINE(uint64_t) ASMReadCntFrqEl0(void)
103{
104# if RT_INLINE_ASM_GNU_STYLE
105 uint64_t u64;
106# ifdef RT_ARCH_ARM64
107 __asm__ __volatile__("Lstart_ASMReadCntFrqEl0_%=:\n\t"
108 "isb\n\t"
109 "mrs %0, CNTFRQ_EL0\n\t"
110 : "=r" (u64));
111# else
112 u64 = 0;
113 __asm__ __volatile__("Lstart_ASMReadCntFrqEl0_%=:\n\t"
114 "isb\n\t"
115 "mrc p15, 0, %[uRet], c14, 0, 0\n\t" /* CNTFRQ */
116 : [uRet] "=r" (u64));
117# endif
118 return u64;
119
120# else
121# error "Unsupported compiler"
122# endif
123}
124#endif
125
126
127/**
128 * Enables interrupts (IRQ and FIQ).
129 */
130#if RT_INLINE_ASM_EXTERNAL
131DECLASM(void) ASMIntEnable(void);
132#else
133DECLINLINE(void) ASMIntEnable(void)
134{
135# if RT_INLINE_ASM_GNU_STYLE
136# ifdef RT_ARCH_ARM64
137 __asm__ __volatile__("Lstart_ASMIntEnable_%=:\n\t"
138 "msr daifclr, #0xf\n\t");
139# else
140 RTCCUINTREG uFlags;
141 __asm__ __volatile__("Lstart_ASMIntEnable_%=:\n\t"
142 "mrs %0, cpsr\n\t"
143 "bic %0, %0, #0xc0\n\t"
144 "msr cpsr_c, %0\n\t"
145 : "=r" (uFlags));
146# endif
147# else
148# error "Unsupported compiler"
149# endif
150}
151#endif
152
153
154/**
155 * Disables interrupts (IRQ and FIQ).
156 */
157#if RT_INLINE_ASM_EXTERNAL
158DECLASM(void) ASMIntDisable(void);
159#else
160DECLINLINE(void) ASMIntDisable(void)
161{
162# if RT_INLINE_ASM_GNU_STYLE
163# ifdef RT_ARCH_ARM64
164 __asm__ __volatile__("Lstart_ASMIntDisable_%=:\n\t"
165 "msr daifset, #0xf\n\t");
166# else
167 RTCCUINTREG uFlags;
168 __asm__ __volatile__("Lstart_ASMIntDisable_%=:\n\t"
169 "mrs %0, cpsr\n\t"
170 "orr %0, %0, #0xc0\n\t"
171 "msr cpsr_c, %0\n\t"
172 : "=r" (uFlags));
173# endif
174# else
175# error "Unsupported compiler"
176# endif
177}
178#endif
179
180
181/**
182 * Disables interrupts and returns previous uFLAGS.
183 */
184#if RT_INLINE_ASM_EXTERNAL
185DECLASM(RTCCUINTREG) ASMIntDisableFlags(void);
186#else
187DECLINLINE(RTCCUINTREG) ASMIntDisableFlags(void)
188{
189 RTCCUINTREG uFlags;
190# if RT_INLINE_ASM_GNU_STYLE
191# ifdef RT_ARCH_ARM64
192 __asm__ __volatile__("Lstart_ASMIntDisableFlags_%=:\n\t"
193 "mrs %[uRet], daif\n\t"
194 "msr daifset, #0xf\n\t"
195 : [uRet] "=r" (uFlags));
196# else
197 RTCCUINTREG uNewFlags;
198 __asm__ __volatile__("Lstart_ASMIntDisableFlags_%=:\n\t"
199 "mrs %0, cpsr\n\t"
200 "orr %1, %0, #0xc0\n\t"
201 "msr cpsr_c, %1\n\t"
202 : "=r" (uFlags)
203 , "=r" (uNewFlags));
204# endif
205# else
206# error "Unsupported compiler"
207# endif
208 return uFlags;
209}
210
211
212/**
213 * Get the CPSR/PSTATE register.
214 * @returns CPSR/PSTATE.
215 */
216#if RT_INLINE_ASM_EXTERNAL
217DECLASM(RTCCUINTREG) ASMGetFlags(void);
218#else
219DECLINLINE(RTCCUINTREG) ASMGetFlags(void)
220{
221 RTCCUINTREG uFlags;
222# if RT_INLINE_ASM_GNU_STYLE
223# ifdef RT_ARCH_ARM64
224 __asm__ __volatile__("Lstart_ASMGetFlags_%=:\n\t"
225 "isb\n\t"
226 "mrs %0, daif\n\t"
227 : "=r" (uFlags));
228# else
229# error "Implementation required for arm32"
230# endif
231# else
232# error "Unsupported compiler"
233# endif
234 return uFlags;
235}
236#endif
237
238
239/**
240 * Get the CPSR/PSTATE register.
241 */
242#if RT_INLINE_ASM_EXTERNAL
243DECLASM(void) ASMSetFlags(RTCCUINTREG uFlags);
244#else
245DECLINLINE(void) ASMSetFlags(RTCCUINTREG uFlags)
246{
247# if RT_INLINE_ASM_GNU_STYLE
248# ifdef RT_ARCH_ARM64
249 __asm__ __volatile__("Lstart_ASMSetFlags_%=:\n\t"
250 "isb\n\t"
251 "msr daif, %[uFlags]\n\t"
252 : : [uFlags] "r" (uFlags));
253# else
254# error "Implementation required for arm32"
255# endif
256# else
257# error "Unsupported compiler"
258# endif
259}
260#endif
261
262
263/**
264 * Are interrupts enabled?
265 *
266 * @returns true / false.
267 */
268DECLINLINE(bool) ASMIntAreEnabled(void)
269{
270 return ASMGetFlags() & 0xc0 /* IRQ and FIQ bits */ ? true : false;
271}
272
273#endif
274
275/**
276 * Halts the CPU until interrupted.
277 */
278#if RT_INLINE_ASM_EXTERNAL
279DECLASM(void) ASMHalt(void);
280#else
281DECLINLINE(void) ASMHalt(void)
282{
283# if RT_INLINE_ASM_GNU_STYLE
284 __asm__ __volatile__ ("Lstart_ASMHalt_%=:\n\t"
285 "wfi\n\t"); /* wait for interrupt */
286# else
287# error "Unsupported compiler"
288# endif
289}
290#endif
291
292#if 0
293/**
294 * Gets the CPU ID of the current CPU.
295 *
296 * @returns the CPU ID.
297 * @note the name of this method is a bit misleading but serves the purpose
298 * and prevents #ifdef orgies in other places.
299 */
300#if RT_INLINE_ASM_EXTERNAL
301DECLASM(uint8_t) ASMGetApicId(void);
302#else
303DECLINLINE(uint8_t) ASMGetApicId(void)
304{
305# if RT_INLINE_ASM_GNU_STYLE
306 RTCCUINTREG uCpuId;
307 __asm__ ("Lstart_ASMGetApicId_%=:\n\t"
308 "mrc p15, 0, %0, c0, c0, 5\n\t" /* CPU ID Register, privileged */
309 : "=r" (uCpuId));
310 return uCpuId;
311# else
312# error "Unsupported compiler"
313# endif
314}
315#endif
316#endif
317
318#if 0
319
320/**
321 * Invalidate page.
322 *
323 * @param pv Address of the page to invalidate.
324 */
325#if RT_INLINE_ASM_EXTERNAL
326DECLASM(void) ASMInvalidatePage(void *pv);
327#else
328DECLINLINE(void) ASMInvalidatePage(void *pv)
329{
330# if RT_INLINE_ASM_GNU_STYLE
331
332# else
333# error "Unsupported compiler"
334# endif
335}
336#endif
337
338
339/**
340 * Write back the internal caches and invalidate them.
341 */
342#if RT_INLINE_ASM_EXTERNAL
343DECLASM(void) ASMWriteBackAndInvalidateCaches(void);
344#else
345DECLINLINE(void) ASMWriteBackAndInvalidateCaches(void)
346{
347# if RT_INLINE_ASM_GNU_STYLE
348
349# else
350# error "Unsupported compiler"
351# endif
352}
353#endif
354
355
356/**
357 * Invalidate internal and (perhaps) external caches without first
358 * flushing dirty cache lines. Use with extreme care.
359 */
360#if RT_INLINE_ASM_EXTERNAL
361DECLASM(void) ASMInvalidateInternalCaches(void);
362#else
363DECLINLINE(void) ASMInvalidateInternalCaches(void)
364{
365# if RT_INLINE_ASM_GNU_STYLE
366
367# else
368# error "Unsupported compiler"
369# endif
370}
371#endif
372
373#endif
374
375
376/** @} */
377#endif /* !IPRT_INCLUDED_asm_arm_h */
378
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette