VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/IEMAllN8veHlpA-arm64.S@ 107044

Last change on this file since 107044 was 105490, checked in by vboxsync, 4 months ago

VMM/IEM: Basic infrastructure to natively recompile SIMD floating point instructions, bugref:10652

SIMD floating point operation behavior depends on the guest MXCSR value which needs to be written to the
host's floating point control register (MXCSR on x86, FPCR on arm64 which needs conversion) and needs to be
restored to the host's value when the TB finished execution to avoid inconsistencies in case the guest
changes MXCSR. The ARM implementation does not conform to the x86 behavior because default NaN values have
the sign bit clear on arm64 while they are set on x86. There are rounding differences as well and earlier
ARMv8 revisions don't support the FPCR.FIZ and FPCR.AH features. Should still work out as long as the guest
doesn't try to do funny stuff.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
Line 
1/* $Id: IEMAllN8veHlpA-arm64.S 105490 2024-07-24 14:49:29Z vboxsync $ */
2/** @file
3 * IEM - Native Recompiler Assembly Helpers, ARM64 variant.
4 */
5
6/*
7 * Copyright (C) 2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <iprt/asmdefs-arm.h>
33#include <iprt/armv8.h>
34
35#include "IEMInternal.h"
36#include "IEMN8veRecompiler.h"
37#include "IEMAssemblyOffsets.h"
38
39
40/*********************************************************************************************************************************
41* Defined Constants And Macros *
42*********************************************************************************************************************************/
43#define IEM_HLP_FUNCTION_ALIGNMENT 0x20
44
45
46/*********************************************************************************************************************************
47* External Functions *
48*********************************************************************************************************************************/
49.extern NAME(iemThreadedFunc_BltIn_LogCpuStateWorker)
50
51
52BEGINCODE
53
54/**
55 * This is the common prologue of a TB, saving all volatile registers
56 * and creating the stack frame for saving temporary values.
57 *
58 * @param pVCpu (x0) The cross-context vCPU structure pointer.
59 * @param pCpumCtx (x1) The cross-context CPUM context structure pointer.
60 * @param pTbStart (x2) The TB instruction start pointer.
61 */
62ALIGNCODE(IEM_HLP_FUNCTION_ALIGNMENT)
63BEGINPROC_HIDDEN iemNativeTbEntry
64#ifdef RT_OS_DARWIN
65 pacibsp
66#endif
67 /*
68 * We set up a stack frame exactly like on x86, only we have to push the
69 * return address our selves here. We save all non-volatile registers.
70 */
71 /* Allocate space for saving registers and place x19+x20 at the bottom. */
72 stp x19, x20, [sp, #-IEMNATIVE_FRAME_SAVE_REG_SIZE]!
73 /* Save x21 thru x28 (SP remains unchanged). */
74 stp x21, x22, [sp, #0x10]
75 stp x23, x24, [sp, #0x20]
76 stp x25, x26, [sp, #0x30]
77 stp x27, x28, [sp, #0x40]
78 /* Save the BP (x29) and LR (x30) (ret address) registers at the top of the frame. */
79 stp x29, x30, [sp, #0x50]
80 /* Set BP to point to the old BP stack address */
81 add x29, sp, #(IEMNATIVE_FRAME_SAVE_REG_SIZE - 16)
82 /* Allocate the variable area from SP. */
83 sub sp, sp, #IEMNATIVE_FRAME_VAR_SIZE
84 /* Load the fixed register values from parameters. */
85 mov IEMNATIVE_REG_FIXED_PVMCPU_ASM, x0
86 mov IEMNATIVE_REG_FIXED_PCPUMCTX_ASM, x1
87#ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER_LONGJMP
88 /* Save the frame pointer to pvTbFramePointerR3 */
89 str x29, [IEMNATIVE_REG_FIXED_PVMCPU_ASM, #(VMCPU_OFF_iem + IEMCPU_OFF_pvTbFramePointerR3)]
90#endif
91
92 /*
93 * Everything is done, jump to the start of the TB.
94 */
95 br x2
96
97
98/**
99 * This does the epilogue of a TB, given the RBP for the frame and eax value to return.
100 *
101 * @param pFrame (x0) The frame pointer.
102 * @param rc (w1) The return value.
103 *
104 * @note This doesn't really work for MSC since xmm6 thru xmm15 are non-volatile
105 * and since we don't save them in the TB prolog we'll potentially return
106 * with different values if any functions on the calling stack uses them
107 * as they're unlikely to restore them till they return.
108 *
109 * For the GCC calling convention all xmm registers are volatile and the
110 * only worry would be someone fiddling the control bits of MXCSR or FCW
111 * without restoring them. This is highly unlikely, unless we're doing
112 * it ourselves, I think.
113 */
114ALIGNCODE(IEM_HLP_FUNCTION_ALIGNMENT)
115BEGINPROC_HIDDEN iemNativeTbLongJmp
116 /*
117 * This must exactly match what iemNativeEmitEpilog does.
118 */
119 sub sp, x0, #0x50
120 ldp x19, x20, [sp, #0x00]
121 ldp x21, x22, [sp, #0x10]
122 ldp x23, x24, [sp, #0x20]
123 ldp x25, x26, [sp, #0x30]
124 ldp x27, x28, [sp, #0x40]
125 ldp x29, x30, [sp, #0x50] /* the pFrame address points to this entry */
126 add sp, sp, #0x60
127 mov w0, w1 /* The return value */
128#ifdef RT_OS_DARWIN
129 retab
130#else
131 ret
132#endif
133 brk #1
134
135
136
137#define IEMNATIVE_HLP_FRAME_SIZE (11 * 16)
138
139/**
140 * This is wrapper function that saves and restores all volatile registers
141 * so the impact of inserting LogCpuState is minimal to the other TB code.
142 */
143ALIGNCODE(IEM_HLP_FUNCTION_ALIGNMENT)
144BEGINPROC_HIDDEN iemNativeHlpAsmSafeWrapLogCpuState
145#ifdef RT_OS_DARWIN
146 pacibsp
147#endif
148
149 /*
150 * Save all volatile registers.
151 */
152 stp x29, x30, [sp, #-IEMNATIVE_HLP_FRAME_SIZE]!
153 stp x0, x1, [sp, #( 1 * 16)]
154 stp x2, x3, [sp, #( 2 * 16)]
155 stp x4, x5, [sp, #( 3 * 16)]
156 stp x5, x6, [sp, #( 4 * 16)]
157 stp x7, x8, [sp, #( 5 * 16)]
158 stp x9, x10, [sp, #( 6 * 16)]
159 stp x11, x12, [sp, #( 7 * 16)]
160 stp x13, x14, [sp, #( 8 * 16)]
161 stp x15, x16, [sp, #( 9 * 16)]
162 stp x17, x18, [sp, #(10 * 16)]
163
164 /*
165 * Move the pVCpu pointer from the fixed register to the first argument.
166 */
167 mov x0, IEMNATIVE_REG_FIXED_PVMCPU_ASM
168
169 /*
170 * Call C function to do the actual work.
171 */
172 bl NAME(iemThreadedFunc_BltIn_LogCpuStateWorker)
173
174 /*
175 * Restore volatile registers and return to the TB code.
176 */
177 ldp x29, x30, [sp, #( 0 * 16)]
178 ldp x0, x1, [sp, #( 1 * 16)]
179 ldp x2, x3, [sp, #( 2 * 16)]
180 ldp x4, x5, [sp, #( 3 * 16)]
181 ldp x5, x6, [sp, #( 4 * 16)]
182 ldp x7, x8, [sp, #( 5 * 16)]
183 ldp x9, x10, [sp, #( 6 * 16)]
184 ldp x11, x12, [sp, #( 7 * 16)]
185 ldp x13, x14, [sp, #( 8 * 16)]
186 ldp x15, x16, [sp, #( 9 * 16)]
187 ldp x17, x18, [sp, #(10 * 16)]
188 add sp, sp, #IEMNATIVE_HLP_FRAME_SIZE
189
190#ifdef RT_OS_DARWIN
191 retab
192#else
193 ret
194#endif
195 brk #1
196
197
198/**
199 * This is wrapper function that saves and restores all volatile registers
200 * so the impact of inserting CheckTlbLookup is minimal to the other TB code.
201 */
202ALIGNCODE(IEM_HLP_FUNCTION_ALIGNMENT)
203BEGINPROC_HIDDEN iemNativeHlpAsmSafeWrapCheckTlbLookup
204#ifdef RT_OS_DARWIN
205 ; pacibsp - see retab comment below.
206#endif
207
208 /*
209 * Save all volatile registers.
210 */
211 stp x0, x1, [sp, #-IEMNATIVE_HLP_FRAME_SIZE]!
212 stp x2, x3, [sp, #( 1 * 16)]
213 stp x4, x5, [sp, #( 2 * 16)]
214 stp x5, x6, [sp, #( 3 * 16)]
215 stp x7, x8, [sp, #( 4 * 16)]
216 stp x9, x10, [sp, #( 5 * 16)]
217 stp x11, x12, [sp, #( 6 * 16)]
218 stp x13, x14, [sp, #( 7 * 16)]
219 stp x15, x16, [sp, #( 8 * 16)]
220 stp x17, x18, [sp, #( 9 * 16)]
221 stp x29, x30, [sp, #(10 * 16)] /* At the top, save BP followed by LR. */
222 add x29, sp, #(IEMNATIVE_HLP_FRAME_SIZE - 16) /* x29 (BP) = &SavedBP; Creates a traditional call frame. */
223
224 /*
225 * Load parameters off the stack.
226 */
227 ldp x0, x1, [x29, #16]
228 ldp x2, x3, [x29, #32]
229
230 /*
231 * Call C function to do the actual work.
232 */
233 bl NAME(iemNativeHlpCheckTlbLookup)
234
235 /*
236 * Restore volatile registers and return to the TB code.
237 */
238 ldp x0, x1, [sp, #( 0 * 16)]
239 ldp x2, x3, [sp, #( 1 * 16)]
240 ldp x4, x5, [sp, #( 2 * 16)]
241 ldp x5, x6, [sp, #( 3 * 16)]
242 ldp x7, x8, [sp, #( 4 * 16)]
243 ldp x9, x10, [sp, #( 5 * 16)]
244 ldp x11, x12, [sp, #( 6 * 16)]
245 ldp x13, x14, [sp, #( 7 * 16)]
246 ldp x15, x16, [sp, #( 8 * 16)]
247 ldp x17, x18, [sp, #( 9 * 16)]
248 ldp x29, x30, [sp, #(10 * 16)]
249 add sp, sp, #(IEMNATIVE_HLP_FRAME_SIZE + 32)
250
251#ifdef RT_OS_DARWIN
252 ; retab - doesn't work with the wrong SP (+32 compared to the original).
253 ret
254#else
255 ret
256#endif
257 brk #1
258
259
260/**
261 * Restores the FPCR register from the given argument.
262 *
263 * @param u64RegFpCtrl (x0) The value to restore FPCR with.
264 */
265ALIGNCODE(IEM_HLP_FUNCTION_ALIGNMENT)
266BEGINPROC_HIDDEN iemNativeFpCtrlRegRestore
267#ifdef RT_OS_DARWIN
268 pacibsp
269#endif
270
271 msr FPCR, x0
272
273#ifdef RT_OS_DARWIN
274 retab
275#else
276 ret
277#endif
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