VirtualBox

source: vbox/trunk/src/VBox/VMM/include/IEMInline.h@ 105123

Last change on this file since 105123 was 105072, checked in by vboxsync, 8 months ago

VMM/IEM,DBGF,bs3-cpu-weird-1: Early data breakpoint support, mostly untested except for the ring transition tests in bs3-cpu-weird-1. bugref:10715

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 166.4 KB
Line 
1/* $Id: IEMInline.h 105072 2024-06-28 12:03:20Z vboxsync $ */
2/** @file
3 * IEM - Interpreted Execution Manager - Inlined Functions.
4 */
5
6/*
7 * Copyright (C) 2011-2023 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#ifndef VMM_INCLUDED_SRC_include_IEMInline_h
29#define VMM_INCLUDED_SRC_include_IEMInline_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34
35
36/**
37 * Makes status code addjustments (pass up from I/O and access handler)
38 * as well as maintaining statistics.
39 *
40 * @returns Strict VBox status code to pass up.
41 * @param pVCpu The cross context virtual CPU structure of the calling thread.
42 * @param rcStrict The status from executing an instruction.
43 */
44DECL_FORCE_INLINE(VBOXSTRICTRC) iemExecStatusCodeFiddling(PVMCPUCC pVCpu, VBOXSTRICTRC rcStrict) RT_NOEXCEPT
45{
46 if (rcStrict != VINF_SUCCESS)
47 {
48 /* Deal with the cases that should be treated as VINF_SUCCESS first. */
49 if ( rcStrict == VINF_IEM_YIELD_PENDING_FF
50#ifdef VBOX_WITH_NESTED_HWVIRT_VMX /** @todo r=bird: Why do we need TWO status codes here? */
51 || rcStrict == VINF_VMX_VMEXIT
52#endif
53#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
54 || rcStrict == VINF_SVM_VMEXIT
55#endif
56 )
57 {
58 rcStrict = pVCpu->iem.s.rcPassUp;
59 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
60 { /* likely */ }
61 else
62 pVCpu->iem.s.cRetPassUpStatus++;
63 }
64 else if (RT_SUCCESS(rcStrict))
65 {
66 AssertMsg( (rcStrict >= VINF_EM_FIRST && rcStrict <= VINF_EM_LAST)
67 || rcStrict == VINF_IOM_R3_IOPORT_READ
68 || rcStrict == VINF_IOM_R3_IOPORT_WRITE
69 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
70 || rcStrict == VINF_IOM_R3_MMIO_READ
71 || rcStrict == VINF_IOM_R3_MMIO_READ_WRITE
72 || rcStrict == VINF_IOM_R3_MMIO_WRITE
73 || rcStrict == VINF_IOM_R3_MMIO_COMMIT_WRITE
74 || rcStrict == VINF_CPUM_R3_MSR_READ
75 || rcStrict == VINF_CPUM_R3_MSR_WRITE
76 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
77 || rcStrict == VINF_EM_RAW_TO_R3
78 || rcStrict == VINF_EM_TRIPLE_FAULT
79 || rcStrict == VINF_EM_EMULATE_SPLIT_LOCK
80 || rcStrict == VINF_GIM_R3_HYPERCALL
81 /* raw-mode / virt handlers only: */
82 || rcStrict == VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT
83 || rcStrict == VINF_EM_RAW_EMULATE_INSTR_TSS_FAULT
84 || rcStrict == VINF_EM_RAW_EMULATE_INSTR_LDT_FAULT
85 || rcStrict == VINF_EM_RAW_EMULATE_INSTR_IDT_FAULT
86 || rcStrict == VINF_SELM_SYNC_GDT
87 || rcStrict == VINF_CSAM_PENDING_ACTION
88 || rcStrict == VINF_PATM_CHECK_PATCH_PAGE
89 /* nested hw.virt codes: */
90 || rcStrict == VINF_VMX_INTERCEPT_NOT_ACTIVE
91 || rcStrict == VINF_VMX_MODIFIES_BEHAVIOR
92 , ("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
93/** @todo adjust for VINF_EM_RAW_EMULATE_INSTR. */
94 int32_t const rcPassUp = pVCpu->iem.s.rcPassUp;
95 if (rcPassUp == VINF_SUCCESS)
96 pVCpu->iem.s.cRetInfStatuses++;
97 else if ( rcPassUp < VINF_EM_FIRST
98 || rcPassUp > VINF_EM_LAST
99 || rcPassUp < VBOXSTRICTRC_VAL(rcStrict))
100 {
101 LogEx(LOG_GROUP_IEM,("IEM: rcPassUp=%Rrc! rcStrict=%Rrc\n", rcPassUp, VBOXSTRICTRC_VAL(rcStrict)));
102 pVCpu->iem.s.cRetPassUpStatus++;
103 rcStrict = rcPassUp;
104 }
105 else
106 {
107 LogEx(LOG_GROUP_IEM,("IEM: rcPassUp=%Rrc rcStrict=%Rrc!\n", rcPassUp, VBOXSTRICTRC_VAL(rcStrict)));
108 pVCpu->iem.s.cRetInfStatuses++;
109 }
110 }
111 else if (rcStrict == VERR_IEM_ASPECT_NOT_IMPLEMENTED)
112 pVCpu->iem.s.cRetAspectNotImplemented++;
113 else if (rcStrict == VERR_IEM_INSTR_NOT_IMPLEMENTED)
114 pVCpu->iem.s.cRetInstrNotImplemented++;
115 else
116 pVCpu->iem.s.cRetErrStatuses++;
117 }
118 else
119 {
120 rcStrict = pVCpu->iem.s.rcPassUp;
121 if (rcStrict != VINF_SUCCESS)
122 pVCpu->iem.s.cRetPassUpStatus++;
123 }
124
125 /* Just clear it here as well. */
126 pVCpu->iem.s.rcPassUp = VINF_SUCCESS;
127
128 return rcStrict;
129}
130
131
132/**
133 * Sets the pass up status.
134 *
135 * @returns VINF_SUCCESS.
136 * @param pVCpu The cross context virtual CPU structure of the
137 * calling thread.
138 * @param rcPassUp The pass up status. Must be informational.
139 * VINF_SUCCESS is not allowed.
140 */
141DECLINLINE(int) iemSetPassUpStatus(PVMCPUCC pVCpu, VBOXSTRICTRC rcPassUp) RT_NOEXCEPT
142{
143 AssertRC(VBOXSTRICTRC_VAL(rcPassUp)); Assert(rcPassUp != VINF_SUCCESS);
144
145 int32_t const rcOldPassUp = pVCpu->iem.s.rcPassUp;
146 if (rcOldPassUp == VINF_SUCCESS)
147 pVCpu->iem.s.rcPassUp = VBOXSTRICTRC_VAL(rcPassUp);
148 /* If both are EM scheduling codes, use EM priority rules. */
149 else if ( rcOldPassUp >= VINF_EM_FIRST && rcOldPassUp <= VINF_EM_LAST
150 && rcPassUp >= VINF_EM_FIRST && rcPassUp <= VINF_EM_LAST)
151 {
152 if (rcPassUp < rcOldPassUp)
153 {
154 LogEx(LOG_GROUP_IEM,("IEM: rcPassUp=%Rrc! rcOldPassUp=%Rrc\n", VBOXSTRICTRC_VAL(rcPassUp), rcOldPassUp));
155 pVCpu->iem.s.rcPassUp = VBOXSTRICTRC_VAL(rcPassUp);
156 }
157 else
158 LogEx(LOG_GROUP_IEM,("IEM: rcPassUp=%Rrc rcOldPassUp=%Rrc!\n", VBOXSTRICTRC_VAL(rcPassUp), rcOldPassUp));
159 }
160 /* Override EM scheduling with specific status code. */
161 else if (rcOldPassUp >= VINF_EM_FIRST && rcOldPassUp <= VINF_EM_LAST)
162 {
163 LogEx(LOG_GROUP_IEM,("IEM: rcPassUp=%Rrc! rcOldPassUp=%Rrc\n", VBOXSTRICTRC_VAL(rcPassUp), rcOldPassUp));
164 pVCpu->iem.s.rcPassUp = VBOXSTRICTRC_VAL(rcPassUp);
165 }
166 /* Don't override specific status code, first come first served. */
167 else
168 LogEx(LOG_GROUP_IEM,("IEM: rcPassUp=%Rrc rcOldPassUp=%Rrc!\n", VBOXSTRICTRC_VAL(rcPassUp), rcOldPassUp));
169 return VINF_SUCCESS;
170}
171
172
173/**
174 * Calculates the IEM_F_X86_AC flags.
175 *
176 * @returns IEM_F_X86_AC or zero
177 * @param pVCpu The cross context virtual CPU structure of the
178 * calling thread.
179 */
180DECL_FORCE_INLINE(uint32_t) iemCalcExecAcFlag(PVMCPUCC pVCpu) RT_NOEXCEPT
181{
182 IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS);
183 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ss));
184
185 if ( !pVCpu->cpum.GstCtx.eflags.Bits.u1AC
186 || (pVCpu->cpum.GstCtx.cr0 & (X86_CR0_AM | X86_CR0_PE)) != (X86_CR0_AM | X86_CR0_PE)
187 || ( !pVCpu->cpum.GstCtx.eflags.Bits.u1VM
188 && pVCpu->cpum.GstCtx.ss.Attr.n.u2Dpl != 3))
189 return 0;
190 return IEM_F_X86_AC;
191}
192
193
194/**
195 * Calculates the IEM_F_MODE_X86_32BIT_FLAT flag.
196 *
197 * Checks if CS, SS, DS and SS are all wide open flat 32-bit segments. This will
198 * reject expand down data segments and conforming code segments.
199 *
200 * ASSUMES that the CPU is in 32-bit mode.
201 *
202 * @note Will return zero when if any of the segment register state is marked
203 * external, this must be factored into assertions checking fExec
204 * consistency.
205 *
206 * @returns IEM_F_MODE_X86_32BIT_FLAT or zero.
207 * @param pVCpu The cross context virtual CPU structure of the
208 * calling thread.
209 * @sa iemCalc32BitFlatIndicatorEsDs
210 */
211DECL_FORCE_INLINE(uint32_t) iemCalc32BitFlatIndicator(PVMCPUCC pVCpu) RT_NOEXCEPT
212{
213 AssertCompile(X86_SEL_TYPE_DOWN == X86_SEL_TYPE_CONF);
214 return ( ( pVCpu->cpum.GstCtx.es.Attr.u
215 | pVCpu->cpum.GstCtx.cs.Attr.u
216 | pVCpu->cpum.GstCtx.ss.Attr.u
217 | pVCpu->cpum.GstCtx.ds.Attr.u)
218 & (X86_SEL_TYPE_ACCESSED | X86DESCATTR_G | X86DESCATTR_D | X86DESCATTR_P | X86_SEL_TYPE_DOWN | X86DESCATTR_UNUSABLE))
219 == (X86_SEL_TYPE_ACCESSED | X86DESCATTR_G | X86DESCATTR_D | X86DESCATTR_P)
220 && ( (pVCpu->cpum.GstCtx.es.u32Limit + 1)
221 | (pVCpu->cpum.GstCtx.cs.u32Limit + 1)
222 | (pVCpu->cpum.GstCtx.ss.u32Limit + 1)
223 | (pVCpu->cpum.GstCtx.ds.u32Limit + 1))
224 == 0
225 && ( pVCpu->cpum.GstCtx.es.u64Base
226 | pVCpu->cpum.GstCtx.cs.u64Base
227 | pVCpu->cpum.GstCtx.ss.u64Base
228 | pVCpu->cpum.GstCtx.ds.u64Base)
229 == 0
230 && !(pVCpu->cpum.GstCtx.fExtrn & (CPUMCTX_EXTRN_ES | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_ES))
231 ? IEM_F_MODE_X86_32BIT_FLAT : 0;
232}
233
234
235/**
236 * Calculates the IEM_F_MODE_X86_32BIT_FLAT flag, ASSUMING the CS and SS are
237 * flat already.
238 *
239 * This is used by sysenter.
240 *
241 * @note Will return zero when if any of the segment register state is marked
242 * external, this must be factored into assertions checking fExec
243 * consistency.
244 *
245 * @returns IEM_F_MODE_X86_32BIT_FLAT or zero.
246 * @param pVCpu The cross context virtual CPU structure of the
247 * calling thread.
248 * @sa iemCalc32BitFlatIndicator
249 */
250DECL_FORCE_INLINE(uint32_t) iemCalc32BitFlatIndicatorEsDs(PVMCPUCC pVCpu) RT_NOEXCEPT
251{
252 AssertCompile(X86_SEL_TYPE_DOWN == X86_SEL_TYPE_CONF);
253 return ( ( pVCpu->cpum.GstCtx.es.Attr.u
254 | pVCpu->cpum.GstCtx.ds.Attr.u)
255 & (X86_SEL_TYPE_ACCESSED | X86DESCATTR_G | X86DESCATTR_D | X86DESCATTR_P | X86_SEL_TYPE_DOWN | X86DESCATTR_UNUSABLE))
256 == (X86_SEL_TYPE_ACCESSED | X86DESCATTR_G | X86DESCATTR_D | X86DESCATTR_P)
257 && ( (pVCpu->cpum.GstCtx.es.u32Limit + 1)
258 | (pVCpu->cpum.GstCtx.ds.u32Limit + 1))
259 == 0
260 && ( pVCpu->cpum.GstCtx.es.u64Base
261 | pVCpu->cpum.GstCtx.ds.u64Base)
262 == 0
263 && !(pVCpu->cpum.GstCtx.fExtrn & (CPUMCTX_EXTRN_ES | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_ES))
264 ? IEM_F_MODE_X86_32BIT_FLAT : 0;
265}
266
267
268/**
269 * Calculates the IEM_F_MODE_XXX, CPL and AC flags.
270 *
271 * @returns IEM_F_MODE_XXX, IEM_F_X86_CPL_MASK and IEM_F_X86_AC.
272 * @param pVCpu The cross context virtual CPU structure of the
273 * calling thread.
274 */
275DECL_FORCE_INLINE(uint32_t) iemCalcExecModeAndCplFlags(PVMCPUCC pVCpu) RT_NOEXCEPT
276{
277 /*
278 * We're duplicates code from CPUMGetGuestCPL and CPUMIsGuestIn64BitCodeEx
279 * here to try get this done as efficiently as possible.
280 */
281 IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_EFER | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS);
282
283 if (pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE)
284 {
285 if (!pVCpu->cpum.GstCtx.eflags.Bits.u1VM)
286 {
287 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ss));
288 uint32_t fExec = ((uint32_t)pVCpu->cpum.GstCtx.ss.Attr.n.u2Dpl << IEM_F_X86_CPL_SHIFT);
289 if ( !pVCpu->cpum.GstCtx.eflags.Bits.u1AC
290 || !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_AM)
291 || fExec != (3U << IEM_F_X86_CPL_SHIFT))
292 { /* likely */ }
293 else
294 fExec |= IEM_F_X86_AC;
295
296 if (pVCpu->cpum.GstCtx.cs.Attr.n.u1DefBig)
297 {
298 Assert(!pVCpu->cpum.GstCtx.cs.Attr.n.u1Long || !(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LMA));
299 fExec |= IEM_F_MODE_X86_32BIT_PROT | iemCalc32BitFlatIndicator(pVCpu);
300 }
301 else if ( pVCpu->cpum.GstCtx.cs.Attr.n.u1Long
302 && (pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LMA))
303 fExec |= IEM_F_MODE_X86_64BIT;
304 else if (IEM_GET_TARGET_CPU(pVCpu) >= IEMTARGETCPU_386)
305 fExec |= IEM_F_MODE_X86_16BIT_PROT;
306 else
307 fExec |= IEM_F_MODE_X86_16BIT_PROT_PRE_386;
308 return fExec;
309 }
310 if ( !pVCpu->cpum.GstCtx.eflags.Bits.u1AC
311 || !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_AM))
312 return IEM_F_MODE_X86_16BIT_PROT_V86 | (UINT32_C(3) << IEM_F_X86_CPL_SHIFT);
313 return IEM_F_MODE_X86_16BIT_PROT_V86 | (UINT32_C(3) << IEM_F_X86_CPL_SHIFT) | IEM_F_X86_AC;
314 }
315
316 /* Real mode is zero; CPL set to 3 for VT-x real-mode emulation. */
317 if (RT_LIKELY(!pVCpu->cpum.GstCtx.cs.Attr.n.u1DefBig))
318 {
319 if (IEM_GET_TARGET_CPU(pVCpu) >= IEMTARGETCPU_386)
320 return IEM_F_MODE_X86_16BIT;
321 return IEM_F_MODE_X86_16BIT_PRE_386;
322 }
323
324 /* 32-bit unreal mode. */
325 return IEM_F_MODE_X86_32BIT | iemCalc32BitFlatIndicator(pVCpu);
326}
327
328
329/**
330 * Calculates the AMD-V and VT-x related context flags.
331 *
332 * @returns 0 or a combination of IEM_F_X86_CTX_IN_GUEST, IEM_F_X86_CTX_SVM and
333 * IEM_F_X86_CTX_VMX.
334 * @param pVCpu The cross context virtual CPU structure of the
335 * calling thread.
336 */
337DECL_FORCE_INLINE(uint32_t) iemCalcExecHwVirtFlags(PVMCPUCC pVCpu) RT_NOEXCEPT
338{
339 /*
340 * This duplicates code from CPUMIsGuestVmxEnabled, CPUMIsGuestSvmEnabled
341 * and CPUMIsGuestInNestedHwvirtMode to some extent.
342 */
343 IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_EFER);
344
345 AssertCompile(X86_CR4_VMXE != MSR_K6_EFER_SVME);
346 uint64_t const fTmp = (pVCpu->cpum.GstCtx.cr4 & X86_CR4_VMXE)
347 | (pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_SVME);
348 if (RT_LIKELY(!fTmp))
349 return 0; /* likely */
350
351 if (fTmp & X86_CR4_VMXE)
352 {
353 Assert(pVCpu->cpum.GstCtx.hwvirt.enmHwvirt == CPUMHWVIRT_VMX);
354 if (pVCpu->cpum.GstCtx.hwvirt.vmx.fInVmxNonRootMode)
355 return IEM_F_X86_CTX_VMX | IEM_F_X86_CTX_IN_GUEST;
356 return IEM_F_X86_CTX_VMX;
357 }
358
359 Assert(pVCpu->cpum.GstCtx.hwvirt.enmHwvirt == CPUMHWVIRT_SVM);
360 if (pVCpu->cpum.GstCtx.hwvirt.svm.Vmcb.ctrl.u64InterceptCtrl & SVM_CTRL_INTERCEPT_VMRUN)
361 return IEM_F_X86_CTX_SVM | IEM_F_X86_CTX_IN_GUEST;
362 return IEM_F_X86_CTX_SVM;
363}
364
365#ifdef VBOX_INCLUDED_vmm_dbgf_h /* VM::dbgf.ro.cEnabledHwBreakpoints is only accessible if VBox/vmm/dbgf.h is included. */
366
367/**
368 * Calculates IEM_F_BRK_PENDING_XXX (IEM_F_PENDING_BRK_MASK) flags.
369 *
370 * @returns IEM_F_BRK_PENDING_XXX or zero.
371 * @param pVCpu The cross context virtual CPU structure of the
372 * calling thread.
373 */
374DECL_FORCE_INLINE(uint32_t) iemCalcExecDbgFlags(PVMCPUCC pVCpu) RT_NOEXCEPT
375{
376 IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DR7);
377
378 if (RT_LIKELY( !(pVCpu->cpum.GstCtx.dr[7] & X86_DR7_ENABLED_MASK)
379 && pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledHwBreakpoints == 0))
380 return 0;
381 return iemCalcExecDbgFlagsSlow(pVCpu);
382}
383
384/**
385 * Calculates the the IEM_F_XXX flags.
386 *
387 * @returns IEM_F_XXX combination match the current CPU state.
388 * @param pVCpu The cross context virtual CPU structure of the
389 * calling thread.
390 */
391DECL_FORCE_INLINE(uint32_t) iemCalcExecFlags(PVMCPUCC pVCpu) RT_NOEXCEPT
392{
393 return iemCalcExecModeAndCplFlags(pVCpu)
394 | iemCalcExecHwVirtFlags(pVCpu)
395 /* SMM is not yet implemented */
396 | iemCalcExecDbgFlags(pVCpu)
397 ;
398}
399
400
401/**
402 * Re-calculates the MODE and CPL parts of IEMCPU::fExec.
403 *
404 * @param pVCpu The cross context virtual CPU structure of the
405 * calling thread.
406 */
407DECL_FORCE_INLINE(void) iemRecalcExecModeAndCplAndAcFlags(PVMCPUCC pVCpu)
408{
409 pVCpu->iem.s.fExec = (pVCpu->iem.s.fExec & ~(IEM_F_MODE_MASK | IEM_F_X86_CPL_MASK | IEM_F_X86_AC))
410 | iemCalcExecModeAndCplFlags(pVCpu);
411}
412
413
414/**
415 * Re-calculates the IEM_F_PENDING_BRK_MASK part of IEMCPU::fExec.
416 *
417 * @param pVCpu The cross context virtual CPU structure of the
418 * calling thread.
419 */
420DECL_FORCE_INLINE(void) iemRecalcExecDbgFlags(PVMCPUCC pVCpu)
421{
422 pVCpu->iem.s.fExec = (pVCpu->iem.s.fExec & ~IEM_F_PENDING_BRK_MASK)
423 | iemCalcExecDbgFlags(pVCpu);
424}
425
426#endif /* VBOX_INCLUDED_vmm_dbgf_h */
427
428
429#ifndef IEM_WITH_OPAQUE_DECODER_STATE
430
431# if defined(VBOX_INCLUDED_vmm_dbgf_h) || defined(DOXYGEN_RUNNING) /* dbgf.ro.cEnabledHwBreakpoints */
432
433/**
434 * Initializes the execution state.
435 *
436 * @param pVCpu The cross context virtual CPU structure of the
437 * calling thread.
438 * @param fExecOpts Optional execution flags:
439 * - IEM_F_BYPASS_HANDLERS
440 * - IEM_F_X86_DISREGARD_LOCK
441 *
442 * @remarks Callers of this must call iemUninitExec() to undo potentially fatal
443 * side-effects in strict builds.
444 */
445DECLINLINE(void) iemInitExec(PVMCPUCC pVCpu, uint32_t fExecOpts) RT_NOEXCEPT
446{
447 IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
448 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_IEM));
449 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.cs));
450 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ss));
451 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.es));
452 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ds));
453 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.fs));
454 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.gs));
455 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ldtr));
456 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.tr));
457
458 pVCpu->iem.s.rcPassUp = VINF_SUCCESS;
459 pVCpu->iem.s.fExec = iemCalcExecFlags(pVCpu) | fExecOpts;
460 pVCpu->iem.s.cActiveMappings = 0;
461 pVCpu->iem.s.iNextMapping = 0;
462
463# ifdef VBOX_STRICT
464 pVCpu->iem.s.enmDefAddrMode = (IEMMODE)0xfe;
465 pVCpu->iem.s.enmEffAddrMode = (IEMMODE)0xfe;
466 pVCpu->iem.s.enmDefOpSize = (IEMMODE)0xfe;
467 pVCpu->iem.s.enmEffOpSize = (IEMMODE)0xfe;
468 pVCpu->iem.s.fPrefixes = 0xfeedbeef;
469 pVCpu->iem.s.uRexReg = 127;
470 pVCpu->iem.s.uRexB = 127;
471 pVCpu->iem.s.offModRm = 127;
472 pVCpu->iem.s.uRexIndex = 127;
473 pVCpu->iem.s.iEffSeg = 127;
474 pVCpu->iem.s.idxPrefix = 127;
475 pVCpu->iem.s.uVex3rdReg = 127;
476 pVCpu->iem.s.uVexLength = 127;
477 pVCpu->iem.s.fEvexStuff = 127;
478 pVCpu->iem.s.uFpuOpcode = UINT16_MAX;
479# ifdef IEM_WITH_CODE_TLB
480 pVCpu->iem.s.offInstrNextByte = UINT16_MAX;
481 pVCpu->iem.s.pbInstrBuf = NULL;
482 pVCpu->iem.s.cbInstrBuf = UINT16_MAX;
483 pVCpu->iem.s.cbInstrBufTotal = UINT16_MAX;
484 pVCpu->iem.s.offCurInstrStart = INT16_MAX;
485 pVCpu->iem.s.uInstrBufPc = UINT64_C(0xc0ffc0ffcff0c0ff);
486# ifdef IEM_WITH_CODE_TLB_AND_OPCODE_BUF
487 pVCpu->iem.s.offOpcode = 127;
488# endif
489# else
490 pVCpu->iem.s.offOpcode = 127;
491 pVCpu->iem.s.cbOpcode = 127;
492# endif
493# endif /* VBOX_STRICT */
494}
495
496
497# if defined(VBOX_WITH_NESTED_HWVIRT_SVM) || defined(VBOX_WITH_NESTED_HWVIRT_VMX)
498/**
499 * Performs a minimal reinitialization of the execution state.
500 *
501 * This is intended to be used by VM-exits, SMM, LOADALL and other similar
502 * 'world-switch' types operations on the CPU. Currently only nested
503 * hardware-virtualization uses it.
504 *
505 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
506 * @param cbInstr The instruction length (for flushing).
507 */
508DECLINLINE(void) iemReInitExec(PVMCPUCC pVCpu, uint8_t cbInstr) RT_NOEXCEPT
509{
510 pVCpu->iem.s.fExec = iemCalcExecFlags(pVCpu) | (pVCpu->iem.s.fExec & IEM_F_USER_OPTS);
511 iemOpcodeFlushHeavy(pVCpu, cbInstr);
512}
513# endif
514
515# endif /* VBOX_INCLUDED_vmm_dbgf_h || DOXYGEN_RUNNING */
516
517/**
518 * Counterpart to #iemInitExec that undoes evil strict-build stuff.
519 *
520 * @param pVCpu The cross context virtual CPU structure of the
521 * calling thread.
522 */
523DECLINLINE(void) iemUninitExec(PVMCPUCC pVCpu) RT_NOEXCEPT
524{
525 /* Note! do not touch fInPatchCode here! (see iemUninitExecAndFiddleStatusAndMaybeReenter) */
526# ifdef VBOX_STRICT
527# ifdef IEM_WITH_CODE_TLB
528 NOREF(pVCpu);
529# else
530 pVCpu->iem.s.cbOpcode = 0;
531# endif
532# else
533 NOREF(pVCpu);
534# endif
535}
536
537
538/**
539 * Calls iemUninitExec, iemExecStatusCodeFiddling and iemRCRawMaybeReenter.
540 *
541 * Only calling iemRCRawMaybeReenter in raw-mode, obviously.
542 *
543 * @returns Fiddled strict vbox status code, ready to return to non-IEM caller.
544 * @param pVCpu The cross context virtual CPU structure of the calling thread.
545 * @param rcStrict The status code to fiddle.
546 */
547DECLINLINE(VBOXSTRICTRC) iemUninitExecAndFiddleStatusAndMaybeReenter(PVMCPUCC pVCpu, VBOXSTRICTRC rcStrict) RT_NOEXCEPT
548{
549 iemUninitExec(pVCpu);
550 return iemExecStatusCodeFiddling(pVCpu, rcStrict);
551}
552
553
554/**
555 * Macro used by the IEMExec* method to check the given instruction length.
556 *
557 * Will return on failure!
558 *
559 * @param a_cbInstr The given instruction length.
560 * @param a_cbMin The minimum length.
561 */
562# define IEMEXEC_ASSERT_INSTR_LEN_RETURN(a_cbInstr, a_cbMin) \
563 AssertMsgReturn((unsigned)(a_cbInstr) - (unsigned)(a_cbMin) <= (unsigned)15 - (unsigned)(a_cbMin), \
564 ("cbInstr=%u cbMin=%u\n", (a_cbInstr), (a_cbMin)), VERR_IEM_INVALID_INSTR_LENGTH)
565
566
567# ifndef IEM_WITH_SETJMP
568
569/**
570 * Fetches the first opcode byte.
571 *
572 * @returns Strict VBox status code.
573 * @param pVCpu The cross context virtual CPU structure of the
574 * calling thread.
575 * @param pu8 Where to return the opcode byte.
576 */
577DECLINLINE(VBOXSTRICTRC) iemOpcodeGetFirstU8(PVMCPUCC pVCpu, uint8_t *pu8) RT_NOEXCEPT
578{
579 /*
580 * Check for hardware instruction breakpoints.
581 * Note! Guest breakpoints are only checked after POP SS or MOV SS on AMD CPUs.
582 */
583 if (RT_LIKELY(!(pVCpu->iem.s.fExec & IEM_F_PENDING_BRK_INSTR)))
584 { /* likely */ }
585 else
586 {
587 VBOXSTRICTRC rcStrict = DBGFBpCheckInstruction(pVCpu->CTX_SUFF(pVM), pVCpu,
588 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base,
589 !(pVCpu->cpum.GstCtx.rflags.uBoth & CPUMCTX_INHIBIT_SHADOW_SS)
590 || IEM_IS_GUEST_CPU_AMD(pVCpu));
591 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
592 { /* likely */ }
593 else
594 {
595 *pu8 = 0xff; /* shut up gcc. sigh */
596 if (rcStrict == VINF_EM_RAW_GUEST_TRAP)
597 return iemRaiseDebugException(pVCpu);
598 return rcStrict;
599 }
600 }
601
602 /*
603 * Fetch the first opcode byte.
604 */
605 uintptr_t const offOpcode = pVCpu->iem.s.offOpcode;
606 if (RT_LIKELY((uint8_t)offOpcode < pVCpu->iem.s.cbOpcode))
607 {
608 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + 1;
609 *pu8 = pVCpu->iem.s.abOpcode[offOpcode];
610 return VINF_SUCCESS;
611 }
612 return iemOpcodeGetNextU8Slow(pVCpu, pu8);
613}
614
615# else /* IEM_WITH_SETJMP */
616
617/**
618 * Fetches the first opcode byte, longjmp on error.
619 *
620 * @returns The opcode byte.
621 * @param pVCpu The cross context virtual CPU structure of the calling thread.
622 */
623DECL_INLINE_THROW(uint8_t) iemOpcodeGetFirstU8Jmp(PVMCPUCC pVCpu) IEM_NOEXCEPT_MAY_LONGJMP
624{
625 /*
626 * Check for hardware instruction breakpoints.
627 * Note! Guest breakpoints are only checked after POP SS or MOV SS on AMD CPUs.
628 */
629 if (RT_LIKELY(!(pVCpu->iem.s.fExec & IEM_F_PENDING_BRK_INSTR)))
630 { /* likely */ }
631 else
632 {
633 VBOXSTRICTRC rcStrict = DBGFBpCheckInstruction(pVCpu->CTX_SUFF(pVM), pVCpu,
634 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base,
635 !(pVCpu->cpum.GstCtx.rflags.uBoth & CPUMCTX_INHIBIT_SHADOW_SS)
636 || IEM_IS_GUEST_CPU_AMD(pVCpu));
637 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
638 { /* likely */ }
639 else
640 {
641 if (rcStrict == VINF_EM_RAW_GUEST_TRAP)
642 rcStrict = iemRaiseDebugException(pVCpu);
643 IEM_DO_LONGJMP(pVCpu, VBOXSTRICTRC_VAL(rcStrict));
644 }
645 }
646
647 /*
648 * Fetch the first opcode byte.
649 */
650# ifdef IEM_WITH_CODE_TLB
651 uint8_t bRet;
652 uintptr_t offBuf = pVCpu->iem.s.offInstrNextByte;
653 uint8_t const *pbBuf = pVCpu->iem.s.pbInstrBuf;
654 if (RT_LIKELY( pbBuf != NULL
655 && offBuf < pVCpu->iem.s.cbInstrBuf))
656 {
657 pVCpu->iem.s.offInstrNextByte = (uint32_t)offBuf + 1;
658 bRet = pbBuf[offBuf];
659 }
660 else
661 bRet = iemOpcodeGetNextU8SlowJmp(pVCpu);
662# ifdef IEM_WITH_CODE_TLB_AND_OPCODE_BUF
663 Assert(pVCpu->iem.s.offOpcode == 0);
664 pVCpu->iem.s.abOpcode[pVCpu->iem.s.offOpcode++] = bRet;
665# endif
666 return bRet;
667
668# else /* !IEM_WITH_CODE_TLB */
669 uintptr_t offOpcode = pVCpu->iem.s.offOpcode;
670 if (RT_LIKELY((uint8_t)offOpcode < pVCpu->iem.s.cbOpcode))
671 {
672 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + 1;
673 return pVCpu->iem.s.abOpcode[offOpcode];
674 }
675 return iemOpcodeGetNextU8SlowJmp(pVCpu);
676# endif
677}
678
679# endif /* IEM_WITH_SETJMP */
680
681/**
682 * Fetches the first opcode byte, returns/throws automatically on failure.
683 *
684 * @param a_pu8 Where to return the opcode byte.
685 * @remark Implicitly references pVCpu.
686 */
687# ifndef IEM_WITH_SETJMP
688# define IEM_OPCODE_GET_FIRST_U8(a_pu8) \
689 do \
690 { \
691 VBOXSTRICTRC rcStrict2 = iemOpcodeGetFirstU8(pVCpu, (a_pu8)); \
692 if (rcStrict2 == VINF_SUCCESS) \
693 { /* likely */ } \
694 else \
695 return rcStrict2; \
696 } while (0)
697# else
698# define IEM_OPCODE_GET_FIRST_U8(a_pu8) (*(a_pu8) = iemOpcodeGetFirstU8Jmp(pVCpu))
699# endif /* IEM_WITH_SETJMP */
700
701
702# ifndef IEM_WITH_SETJMP
703
704/**
705 * Fetches the next opcode byte.
706 *
707 * @returns Strict VBox status code.
708 * @param pVCpu The cross context virtual CPU structure of the
709 * calling thread.
710 * @param pu8 Where to return the opcode byte.
711 */
712DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextU8(PVMCPUCC pVCpu, uint8_t *pu8) RT_NOEXCEPT
713{
714 uintptr_t const offOpcode = pVCpu->iem.s.offOpcode;
715 if (RT_LIKELY((uint8_t)offOpcode < pVCpu->iem.s.cbOpcode))
716 {
717 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + 1;
718 *pu8 = pVCpu->iem.s.abOpcode[offOpcode];
719 return VINF_SUCCESS;
720 }
721 return iemOpcodeGetNextU8Slow(pVCpu, pu8);
722}
723
724# else /* IEM_WITH_SETJMP */
725
726/**
727 * Fetches the next opcode byte, longjmp on error.
728 *
729 * @returns The opcode byte.
730 * @param pVCpu The cross context virtual CPU structure of the calling thread.
731 */
732DECL_INLINE_THROW(uint8_t) iemOpcodeGetNextU8Jmp(PVMCPUCC pVCpu) IEM_NOEXCEPT_MAY_LONGJMP
733{
734# ifdef IEM_WITH_CODE_TLB
735 uint8_t bRet;
736 uintptr_t offBuf = pVCpu->iem.s.offInstrNextByte;
737 uint8_t const *pbBuf = pVCpu->iem.s.pbInstrBuf;
738 if (RT_LIKELY( pbBuf != NULL
739 && offBuf < pVCpu->iem.s.cbInstrBuf))
740 {
741 pVCpu->iem.s.offInstrNextByte = (uint32_t)offBuf + 1;
742 bRet = pbBuf[offBuf];
743 }
744 else
745 bRet = iemOpcodeGetNextU8SlowJmp(pVCpu);
746# ifdef IEM_WITH_CODE_TLB_AND_OPCODE_BUF
747 Assert(pVCpu->iem.s.offOpcode < sizeof(pVCpu->iem.s.abOpcode));
748 pVCpu->iem.s.abOpcode[pVCpu->iem.s.offOpcode++] = bRet;
749# endif
750 return bRet;
751
752# else /* !IEM_WITH_CODE_TLB */
753 uintptr_t offOpcode = pVCpu->iem.s.offOpcode;
754 if (RT_LIKELY((uint8_t)offOpcode < pVCpu->iem.s.cbOpcode))
755 {
756 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + 1;
757 return pVCpu->iem.s.abOpcode[offOpcode];
758 }
759 return iemOpcodeGetNextU8SlowJmp(pVCpu);
760# endif
761}
762
763# endif /* IEM_WITH_SETJMP */
764
765/**
766 * Fetches the next opcode byte, returns automatically on failure.
767 *
768 * @param a_pu8 Where to return the opcode byte.
769 * @remark Implicitly references pVCpu.
770 */
771# ifndef IEM_WITH_SETJMP
772# define IEM_OPCODE_GET_NEXT_U8(a_pu8) \
773 do \
774 { \
775 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextU8(pVCpu, (a_pu8)); \
776 if (rcStrict2 == VINF_SUCCESS) \
777 { /* likely */ } \
778 else \
779 return rcStrict2; \
780 } while (0)
781# else
782# define IEM_OPCODE_GET_NEXT_U8(a_pu8) (*(a_pu8) = iemOpcodeGetNextU8Jmp(pVCpu))
783# endif /* IEM_WITH_SETJMP */
784
785
786# ifndef IEM_WITH_SETJMP
787/**
788 * Fetches the next signed byte from the opcode stream.
789 *
790 * @returns Strict VBox status code.
791 * @param pVCpu The cross context virtual CPU structure of the calling thread.
792 * @param pi8 Where to return the signed byte.
793 */
794DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextS8(PVMCPUCC pVCpu, int8_t *pi8) RT_NOEXCEPT
795{
796 return iemOpcodeGetNextU8(pVCpu, (uint8_t *)pi8);
797}
798# endif /* !IEM_WITH_SETJMP */
799
800
801/**
802 * Fetches the next signed byte from the opcode stream, returning automatically
803 * on failure.
804 *
805 * @param a_pi8 Where to return the signed byte.
806 * @remark Implicitly references pVCpu.
807 */
808# ifndef IEM_WITH_SETJMP
809# define IEM_OPCODE_GET_NEXT_S8(a_pi8) \
810 do \
811 { \
812 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextS8(pVCpu, (a_pi8)); \
813 if (rcStrict2 != VINF_SUCCESS) \
814 return rcStrict2; \
815 } while (0)
816# else /* IEM_WITH_SETJMP */
817# define IEM_OPCODE_GET_NEXT_S8(a_pi8) (*(a_pi8) = (int8_t)iemOpcodeGetNextU8Jmp(pVCpu))
818
819# endif /* IEM_WITH_SETJMP */
820
821
822# ifndef IEM_WITH_SETJMP
823/**
824 * Fetches the next signed byte from the opcode stream, extending it to
825 * unsigned 16-bit.
826 *
827 * @returns Strict VBox status code.
828 * @param pVCpu The cross context virtual CPU structure of the calling thread.
829 * @param pu16 Where to return the unsigned word.
830 */
831DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextS8SxU16(PVMCPUCC pVCpu, uint16_t *pu16) RT_NOEXCEPT
832{
833 uint8_t const offOpcode = pVCpu->iem.s.offOpcode;
834 if (RT_UNLIKELY(offOpcode >= pVCpu->iem.s.cbOpcode))
835 return iemOpcodeGetNextS8SxU16Slow(pVCpu, pu16);
836
837 *pu16 = (uint16_t)(int16_t)(int8_t)pVCpu->iem.s.abOpcode[offOpcode];
838 pVCpu->iem.s.offOpcode = offOpcode + 1;
839 return VINF_SUCCESS;
840}
841# endif /* !IEM_WITH_SETJMP */
842
843/**
844 * Fetches the next signed byte from the opcode stream and sign-extending it to
845 * a word, returning automatically on failure.
846 *
847 * @param a_pu16 Where to return the word.
848 * @remark Implicitly references pVCpu.
849 */
850# ifndef IEM_WITH_SETJMP
851# define IEM_OPCODE_GET_NEXT_S8_SX_U16(a_pu16) \
852 do \
853 { \
854 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextS8SxU16(pVCpu, (a_pu16)); \
855 if (rcStrict2 != VINF_SUCCESS) \
856 return rcStrict2; \
857 } while (0)
858# else
859# define IEM_OPCODE_GET_NEXT_S8_SX_U16(a_pu16) (*(a_pu16) = (uint16_t)(int16_t)(int8_t)iemOpcodeGetNextU8Jmp(pVCpu))
860# endif
861
862# ifndef IEM_WITH_SETJMP
863/**
864 * Fetches the next signed byte from the opcode stream, extending it to
865 * unsigned 32-bit.
866 *
867 * @returns Strict VBox status code.
868 * @param pVCpu The cross context virtual CPU structure of the calling thread.
869 * @param pu32 Where to return the unsigned dword.
870 */
871DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextS8SxU32(PVMCPUCC pVCpu, uint32_t *pu32) RT_NOEXCEPT
872{
873 uint8_t const offOpcode = pVCpu->iem.s.offOpcode;
874 if (RT_UNLIKELY(offOpcode >= pVCpu->iem.s.cbOpcode))
875 return iemOpcodeGetNextS8SxU32Slow(pVCpu, pu32);
876
877 *pu32 = (uint32_t)(int32_t)(int8_t)pVCpu->iem.s.abOpcode[offOpcode];
878 pVCpu->iem.s.offOpcode = offOpcode + 1;
879 return VINF_SUCCESS;
880}
881# endif /* !IEM_WITH_SETJMP */
882
883/**
884 * Fetches the next signed byte from the opcode stream and sign-extending it to
885 * a word, returning automatically on failure.
886 *
887 * @param a_pu32 Where to return the word.
888 * @remark Implicitly references pVCpu.
889 */
890# ifndef IEM_WITH_SETJMP
891# define IEM_OPCODE_GET_NEXT_S8_SX_U32(a_pu32) \
892 do \
893 { \
894 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextS8SxU32(pVCpu, (a_pu32)); \
895 if (rcStrict2 != VINF_SUCCESS) \
896 return rcStrict2; \
897 } while (0)
898# else
899# define IEM_OPCODE_GET_NEXT_S8_SX_U32(a_pu32) (*(a_pu32) = (uint32_t)(int32_t)(int8_t)iemOpcodeGetNextU8Jmp(pVCpu))
900# endif
901
902
903# ifndef IEM_WITH_SETJMP
904/**
905 * Fetches the next signed byte from the opcode stream, extending it to
906 * unsigned 64-bit.
907 *
908 * @returns Strict VBox status code.
909 * @param pVCpu The cross context virtual CPU structure of the calling thread.
910 * @param pu64 Where to return the unsigned qword.
911 */
912DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextS8SxU64(PVMCPUCC pVCpu, uint64_t *pu64) RT_NOEXCEPT
913{
914 uint8_t const offOpcode = pVCpu->iem.s.offOpcode;
915 if (RT_UNLIKELY(offOpcode >= pVCpu->iem.s.cbOpcode))
916 return iemOpcodeGetNextS8SxU64Slow(pVCpu, pu64);
917
918 *pu64 = (uint64_t)(int64_t)(int8_t)pVCpu->iem.s.abOpcode[offOpcode];
919 pVCpu->iem.s.offOpcode = offOpcode + 1;
920 return VINF_SUCCESS;
921}
922# endif /* !IEM_WITH_SETJMP */
923
924/**
925 * Fetches the next signed byte from the opcode stream and sign-extending it to
926 * a word, returning automatically on failure.
927 *
928 * @param a_pu64 Where to return the word.
929 * @remark Implicitly references pVCpu.
930 */
931# ifndef IEM_WITH_SETJMP
932# define IEM_OPCODE_GET_NEXT_S8_SX_U64(a_pu64) \
933 do \
934 { \
935 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextS8SxU64(pVCpu, (a_pu64)); \
936 if (rcStrict2 != VINF_SUCCESS) \
937 return rcStrict2; \
938 } while (0)
939# else
940# define IEM_OPCODE_GET_NEXT_S8_SX_U64(a_pu64) (*(a_pu64) = (uint64_t)(int64_t)(int8_t)iemOpcodeGetNextU8Jmp(pVCpu))
941# endif
942
943
944# ifndef IEM_WITH_SETJMP
945
946/**
947 * Fetches the next opcode word.
948 *
949 * @returns Strict VBox status code.
950 * @param pVCpu The cross context virtual CPU structure of the calling thread.
951 * @param pu16 Where to return the opcode word.
952 */
953DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextU16(PVMCPUCC pVCpu, uint16_t *pu16) RT_NOEXCEPT
954{
955 uintptr_t const offOpcode = pVCpu->iem.s.offOpcode;
956 if (RT_LIKELY((uint8_t)offOpcode + 2 <= pVCpu->iem.s.cbOpcode))
957 {
958 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + 2;
959# ifdef IEM_USE_UNALIGNED_DATA_ACCESS
960 *pu16 = *(uint16_t const *)&pVCpu->iem.s.abOpcode[offOpcode];
961# else
962 *pu16 = RT_MAKE_U16(pVCpu->iem.s.abOpcode[offOpcode], pVCpu->iem.s.abOpcode[offOpcode + 1]);
963# endif
964 return VINF_SUCCESS;
965 }
966 return iemOpcodeGetNextU16Slow(pVCpu, pu16);
967}
968
969# else /* IEM_WITH_SETJMP */
970
971/**
972 * Fetches the next opcode word, longjmp on error.
973 *
974 * @returns The opcode word.
975 * @param pVCpu The cross context virtual CPU structure of the calling thread.
976 */
977DECL_INLINE_THROW(uint16_t) iemOpcodeGetNextU16Jmp(PVMCPUCC pVCpu) IEM_NOEXCEPT_MAY_LONGJMP
978{
979# ifdef IEM_WITH_CODE_TLB
980 uint16_t u16Ret;
981 uintptr_t offBuf = pVCpu->iem.s.offInstrNextByte;
982 uint8_t const *pbBuf = pVCpu->iem.s.pbInstrBuf;
983 if (RT_LIKELY( pbBuf != NULL
984 && offBuf + 2 <= pVCpu->iem.s.cbInstrBuf))
985 {
986 pVCpu->iem.s.offInstrNextByte = (uint32_t)offBuf + 2;
987# ifdef IEM_USE_UNALIGNED_DATA_ACCESS
988 u16Ret = *(uint16_t const *)&pbBuf[offBuf];
989# else
990 u16Ret = RT_MAKE_U16(pbBuf[offBuf], pbBuf[offBuf + 1]);
991# endif
992 }
993 else
994 u16Ret = iemOpcodeGetNextU16SlowJmp(pVCpu);
995
996# ifdef IEM_WITH_CODE_TLB_AND_OPCODE_BUF
997 uintptr_t const offOpcode = pVCpu->iem.s.offOpcode;
998 Assert(offOpcode + 1 < sizeof(pVCpu->iem.s.abOpcode));
999# ifdef IEM_USE_UNALIGNED_DATA_ACCESS
1000 *(uint16_t *)&pVCpu->iem.s.abOpcode[offOpcode] = u16Ret;
1001# else
1002 pVCpu->iem.s.abOpcode[offOpcode] = RT_LO_U8(u16Ret);
1003 pVCpu->iem.s.abOpcode[offOpcode + 1] = RT_HI_U8(u16Ret);
1004# endif
1005 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + (uint8_t)2;
1006# endif
1007
1008 return u16Ret;
1009
1010# else /* !IEM_WITH_CODE_TLB */
1011 uintptr_t const offOpcode = pVCpu->iem.s.offOpcode;
1012 if (RT_LIKELY((uint8_t)offOpcode + 2 <= pVCpu->iem.s.cbOpcode))
1013 {
1014 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + 2;
1015# ifdef IEM_USE_UNALIGNED_DATA_ACCESS
1016 return *(uint16_t const *)&pVCpu->iem.s.abOpcode[offOpcode];
1017# else
1018 return RT_MAKE_U16(pVCpu->iem.s.abOpcode[offOpcode], pVCpu->iem.s.abOpcode[offOpcode + 1]);
1019# endif
1020 }
1021 return iemOpcodeGetNextU16SlowJmp(pVCpu);
1022# endif /* !IEM_WITH_CODE_TLB */
1023}
1024
1025# endif /* IEM_WITH_SETJMP */
1026
1027/**
1028 * Fetches the next opcode word, returns automatically on failure.
1029 *
1030 * @param a_pu16 Where to return the opcode word.
1031 * @remark Implicitly references pVCpu.
1032 */
1033# ifndef IEM_WITH_SETJMP
1034# define IEM_OPCODE_GET_NEXT_U16(a_pu16) \
1035 do \
1036 { \
1037 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextU16(pVCpu, (a_pu16)); \
1038 if (rcStrict2 != VINF_SUCCESS) \
1039 return rcStrict2; \
1040 } while (0)
1041# else
1042# define IEM_OPCODE_GET_NEXT_U16(a_pu16) (*(a_pu16) = iemOpcodeGetNextU16Jmp(pVCpu))
1043# endif
1044
1045# ifndef IEM_WITH_SETJMP
1046/**
1047 * Fetches the next opcode word, zero extending it to a double word.
1048 *
1049 * @returns Strict VBox status code.
1050 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1051 * @param pu32 Where to return the opcode double word.
1052 */
1053DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextU16ZxU32(PVMCPUCC pVCpu, uint32_t *pu32) RT_NOEXCEPT
1054{
1055 uint8_t const offOpcode = pVCpu->iem.s.offOpcode;
1056 if (RT_UNLIKELY(offOpcode + 2 > pVCpu->iem.s.cbOpcode))
1057 return iemOpcodeGetNextU16ZxU32Slow(pVCpu, pu32);
1058
1059 *pu32 = RT_MAKE_U16(pVCpu->iem.s.abOpcode[offOpcode], pVCpu->iem.s.abOpcode[offOpcode + 1]);
1060 pVCpu->iem.s.offOpcode = offOpcode + 2;
1061 return VINF_SUCCESS;
1062}
1063# endif /* !IEM_WITH_SETJMP */
1064
1065/**
1066 * Fetches the next opcode word and zero extends it to a double word, returns
1067 * automatically on failure.
1068 *
1069 * @param a_pu32 Where to return the opcode double word.
1070 * @remark Implicitly references pVCpu.
1071 */
1072# ifndef IEM_WITH_SETJMP
1073# define IEM_OPCODE_GET_NEXT_U16_ZX_U32(a_pu32) \
1074 do \
1075 { \
1076 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextU16ZxU32(pVCpu, (a_pu32)); \
1077 if (rcStrict2 != VINF_SUCCESS) \
1078 return rcStrict2; \
1079 } while (0)
1080# else
1081# define IEM_OPCODE_GET_NEXT_U16_ZX_U32(a_pu32) (*(a_pu32) = iemOpcodeGetNextU16Jmp(pVCpu))
1082# endif
1083
1084# ifndef IEM_WITH_SETJMP
1085/**
1086 * Fetches the next opcode word, zero extending it to a quad word.
1087 *
1088 * @returns Strict VBox status code.
1089 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1090 * @param pu64 Where to return the opcode quad word.
1091 */
1092DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextU16ZxU64(PVMCPUCC pVCpu, uint64_t *pu64) RT_NOEXCEPT
1093{
1094 uint8_t const offOpcode = pVCpu->iem.s.offOpcode;
1095 if (RT_UNLIKELY(offOpcode + 2 > pVCpu->iem.s.cbOpcode))
1096 return iemOpcodeGetNextU16ZxU64Slow(pVCpu, pu64);
1097
1098 *pu64 = RT_MAKE_U16(pVCpu->iem.s.abOpcode[offOpcode], pVCpu->iem.s.abOpcode[offOpcode + 1]);
1099 pVCpu->iem.s.offOpcode = offOpcode + 2;
1100 return VINF_SUCCESS;
1101}
1102# endif /* !IEM_WITH_SETJMP */
1103
1104/**
1105 * Fetches the next opcode word and zero extends it to a quad word, returns
1106 * automatically on failure.
1107 *
1108 * @param a_pu64 Where to return the opcode quad word.
1109 * @remark Implicitly references pVCpu.
1110 */
1111# ifndef IEM_WITH_SETJMP
1112# define IEM_OPCODE_GET_NEXT_U16_ZX_U64(a_pu64) \
1113 do \
1114 { \
1115 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextU16ZxU64(pVCpu, (a_pu64)); \
1116 if (rcStrict2 != VINF_SUCCESS) \
1117 return rcStrict2; \
1118 } while (0)
1119# else
1120# define IEM_OPCODE_GET_NEXT_U16_ZX_U64(a_pu64) (*(a_pu64) = iemOpcodeGetNextU16Jmp(pVCpu))
1121# endif
1122
1123
1124# ifndef IEM_WITH_SETJMP
1125/**
1126 * Fetches the next signed word from the opcode stream.
1127 *
1128 * @returns Strict VBox status code.
1129 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1130 * @param pi16 Where to return the signed word.
1131 */
1132DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextS16(PVMCPUCC pVCpu, int16_t *pi16) RT_NOEXCEPT
1133{
1134 return iemOpcodeGetNextU16(pVCpu, (uint16_t *)pi16);
1135}
1136# endif /* !IEM_WITH_SETJMP */
1137
1138
1139/**
1140 * Fetches the next signed word from the opcode stream, returning automatically
1141 * on failure.
1142 *
1143 * @param a_pi16 Where to return the signed word.
1144 * @remark Implicitly references pVCpu.
1145 */
1146# ifndef IEM_WITH_SETJMP
1147# define IEM_OPCODE_GET_NEXT_S16(a_pi16) \
1148 do \
1149 { \
1150 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextS16(pVCpu, (a_pi16)); \
1151 if (rcStrict2 != VINF_SUCCESS) \
1152 return rcStrict2; \
1153 } while (0)
1154# else
1155# define IEM_OPCODE_GET_NEXT_S16(a_pi16) (*(a_pi16) = (int16_t)iemOpcodeGetNextU16Jmp(pVCpu))
1156# endif
1157
1158# ifndef IEM_WITH_SETJMP
1159
1160/**
1161 * Fetches the next opcode dword.
1162 *
1163 * @returns Strict VBox status code.
1164 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1165 * @param pu32 Where to return the opcode double word.
1166 */
1167DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextU32(PVMCPUCC pVCpu, uint32_t *pu32) RT_NOEXCEPT
1168{
1169 uintptr_t const offOpcode = pVCpu->iem.s.offOpcode;
1170 if (RT_LIKELY((uint8_t)offOpcode + 4 <= pVCpu->iem.s.cbOpcode))
1171 {
1172 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + 4;
1173# ifdef IEM_USE_UNALIGNED_DATA_ACCESS
1174 *pu32 = *(uint32_t const *)&pVCpu->iem.s.abOpcode[offOpcode];
1175# else
1176 *pu32 = RT_MAKE_U32_FROM_U8(pVCpu->iem.s.abOpcode[offOpcode],
1177 pVCpu->iem.s.abOpcode[offOpcode + 1],
1178 pVCpu->iem.s.abOpcode[offOpcode + 2],
1179 pVCpu->iem.s.abOpcode[offOpcode + 3]);
1180# endif
1181 return VINF_SUCCESS;
1182 }
1183 return iemOpcodeGetNextU32Slow(pVCpu, pu32);
1184}
1185
1186# else /* IEM_WITH_SETJMP */
1187
1188/**
1189 * Fetches the next opcode dword, longjmp on error.
1190 *
1191 * @returns The opcode dword.
1192 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1193 */
1194DECL_INLINE_THROW(uint32_t) iemOpcodeGetNextU32Jmp(PVMCPUCC pVCpu) IEM_NOEXCEPT_MAY_LONGJMP
1195{
1196# ifdef IEM_WITH_CODE_TLB
1197 uint32_t u32Ret;
1198 uintptr_t offBuf = pVCpu->iem.s.offInstrNextByte;
1199 uint8_t const *pbBuf = pVCpu->iem.s.pbInstrBuf;
1200 if (RT_LIKELY( pbBuf != NULL
1201 && offBuf + 4 <= pVCpu->iem.s.cbInstrBuf))
1202 {
1203 pVCpu->iem.s.offInstrNextByte = (uint32_t)offBuf + 4;
1204# ifdef IEM_USE_UNALIGNED_DATA_ACCESS
1205 u32Ret = *(uint32_t const *)&pbBuf[offBuf];
1206# else
1207 u32Ret = RT_MAKE_U32_FROM_U8(pbBuf[offBuf],
1208 pbBuf[offBuf + 1],
1209 pbBuf[offBuf + 2],
1210 pbBuf[offBuf + 3]);
1211# endif
1212 }
1213 else
1214 u32Ret = iemOpcodeGetNextU32SlowJmp(pVCpu);
1215
1216# ifdef IEM_WITH_CODE_TLB_AND_OPCODE_BUF
1217 uintptr_t const offOpcode = pVCpu->iem.s.offOpcode;
1218 Assert(offOpcode + 3 < sizeof(pVCpu->iem.s.abOpcode));
1219# ifdef IEM_USE_UNALIGNED_DATA_ACCESS
1220 *(uint32_t *)&pVCpu->iem.s.abOpcode[offOpcode] = u32Ret;
1221# else
1222 pVCpu->iem.s.abOpcode[offOpcode] = RT_BYTE1(u32Ret);
1223 pVCpu->iem.s.abOpcode[offOpcode + 1] = RT_BYTE2(u32Ret);
1224 pVCpu->iem.s.abOpcode[offOpcode + 2] = RT_BYTE3(u32Ret);
1225 pVCpu->iem.s.abOpcode[offOpcode + 3] = RT_BYTE4(u32Ret);
1226# endif
1227 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + (uint8_t)4;
1228# endif /* IEM_WITH_CODE_TLB_AND_OPCODE_BUF */
1229
1230 return u32Ret;
1231
1232# else /* !IEM_WITH_CODE_TLB */
1233 uintptr_t const offOpcode = pVCpu->iem.s.offOpcode;
1234 if (RT_LIKELY((uint8_t)offOpcode + 4 <= pVCpu->iem.s.cbOpcode))
1235 {
1236 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + 4;
1237# ifdef IEM_USE_UNALIGNED_DATA_ACCESS
1238 return *(uint32_t const *)&pVCpu->iem.s.abOpcode[offOpcode];
1239# else
1240 return RT_MAKE_U32_FROM_U8(pVCpu->iem.s.abOpcode[offOpcode],
1241 pVCpu->iem.s.abOpcode[offOpcode + 1],
1242 pVCpu->iem.s.abOpcode[offOpcode + 2],
1243 pVCpu->iem.s.abOpcode[offOpcode + 3]);
1244# endif
1245 }
1246 return iemOpcodeGetNextU32SlowJmp(pVCpu);
1247# endif
1248}
1249
1250# endif /* IEM_WITH_SETJMP */
1251
1252/**
1253 * Fetches the next opcode dword, returns automatically on failure.
1254 *
1255 * @param a_pu32 Where to return the opcode dword.
1256 * @remark Implicitly references pVCpu.
1257 */
1258# ifndef IEM_WITH_SETJMP
1259# define IEM_OPCODE_GET_NEXT_U32(a_pu32) \
1260 do \
1261 { \
1262 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextU32(pVCpu, (a_pu32)); \
1263 if (rcStrict2 != VINF_SUCCESS) \
1264 return rcStrict2; \
1265 } while (0)
1266# else
1267# define IEM_OPCODE_GET_NEXT_U32(a_pu32) (*(a_pu32) = iemOpcodeGetNextU32Jmp(pVCpu))
1268# endif
1269
1270# ifndef IEM_WITH_SETJMP
1271/**
1272 * Fetches the next opcode dword, zero extending it to a quad word.
1273 *
1274 * @returns Strict VBox status code.
1275 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1276 * @param pu64 Where to return the opcode quad word.
1277 */
1278DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextU32ZxU64(PVMCPUCC pVCpu, uint64_t *pu64) RT_NOEXCEPT
1279{
1280 uint8_t const offOpcode = pVCpu->iem.s.offOpcode;
1281 if (RT_UNLIKELY(offOpcode + 4 > pVCpu->iem.s.cbOpcode))
1282 return iemOpcodeGetNextU32ZxU64Slow(pVCpu, pu64);
1283
1284 *pu64 = RT_MAKE_U32_FROM_U8(pVCpu->iem.s.abOpcode[offOpcode],
1285 pVCpu->iem.s.abOpcode[offOpcode + 1],
1286 pVCpu->iem.s.abOpcode[offOpcode + 2],
1287 pVCpu->iem.s.abOpcode[offOpcode + 3]);
1288 pVCpu->iem.s.offOpcode = offOpcode + 4;
1289 return VINF_SUCCESS;
1290}
1291# endif /* !IEM_WITH_SETJMP */
1292
1293/**
1294 * Fetches the next opcode dword and zero extends it to a quad word, returns
1295 * automatically on failure.
1296 *
1297 * @param a_pu64 Where to return the opcode quad word.
1298 * @remark Implicitly references pVCpu.
1299 */
1300# ifndef IEM_WITH_SETJMP
1301# define IEM_OPCODE_GET_NEXT_U32_ZX_U64(a_pu64) \
1302 do \
1303 { \
1304 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextU32ZxU64(pVCpu, (a_pu64)); \
1305 if (rcStrict2 != VINF_SUCCESS) \
1306 return rcStrict2; \
1307 } while (0)
1308# else
1309# define IEM_OPCODE_GET_NEXT_U32_ZX_U64(a_pu64) (*(a_pu64) = iemOpcodeGetNextU32Jmp(pVCpu))
1310# endif
1311
1312
1313# ifndef IEM_WITH_SETJMP
1314/**
1315 * Fetches the next signed double word from the opcode stream.
1316 *
1317 * @returns Strict VBox status code.
1318 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1319 * @param pi32 Where to return the signed double word.
1320 */
1321DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextS32(PVMCPUCC pVCpu, int32_t *pi32) RT_NOEXCEPT
1322{
1323 return iemOpcodeGetNextU32(pVCpu, (uint32_t *)pi32);
1324}
1325# endif
1326
1327/**
1328 * Fetches the next signed double word from the opcode stream, returning
1329 * automatically on failure.
1330 *
1331 * @param a_pi32 Where to return the signed double word.
1332 * @remark Implicitly references pVCpu.
1333 */
1334# ifndef IEM_WITH_SETJMP
1335# define IEM_OPCODE_GET_NEXT_S32(a_pi32) \
1336 do \
1337 { \
1338 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextS32(pVCpu, (a_pi32)); \
1339 if (rcStrict2 != VINF_SUCCESS) \
1340 return rcStrict2; \
1341 } while (0)
1342# else
1343# define IEM_OPCODE_GET_NEXT_S32(a_pi32) (*(a_pi32) = (int32_t)iemOpcodeGetNextU32Jmp(pVCpu))
1344# endif
1345
1346# ifndef IEM_WITH_SETJMP
1347/**
1348 * Fetches the next opcode dword, sign extending it into a quad word.
1349 *
1350 * @returns Strict VBox status code.
1351 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1352 * @param pu64 Where to return the opcode quad word.
1353 */
1354DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextS32SxU64(PVMCPUCC pVCpu, uint64_t *pu64) RT_NOEXCEPT
1355{
1356 uint8_t const offOpcode = pVCpu->iem.s.offOpcode;
1357 if (RT_UNLIKELY(offOpcode + 4 > pVCpu->iem.s.cbOpcode))
1358 return iemOpcodeGetNextS32SxU64Slow(pVCpu, pu64);
1359
1360 int32_t i32 = RT_MAKE_U32_FROM_U8(pVCpu->iem.s.abOpcode[offOpcode],
1361 pVCpu->iem.s.abOpcode[offOpcode + 1],
1362 pVCpu->iem.s.abOpcode[offOpcode + 2],
1363 pVCpu->iem.s.abOpcode[offOpcode + 3]);
1364 *pu64 = (uint64_t)(int64_t)i32;
1365 pVCpu->iem.s.offOpcode = offOpcode + 4;
1366 return VINF_SUCCESS;
1367}
1368# endif /* !IEM_WITH_SETJMP */
1369
1370/**
1371 * Fetches the next opcode double word and sign extends it to a quad word,
1372 * returns automatically on failure.
1373 *
1374 * @param a_pu64 Where to return the opcode quad word.
1375 * @remark Implicitly references pVCpu.
1376 */
1377# ifndef IEM_WITH_SETJMP
1378# define IEM_OPCODE_GET_NEXT_S32_SX_U64(a_pu64) \
1379 do \
1380 { \
1381 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextS32SxU64(pVCpu, (a_pu64)); \
1382 if (rcStrict2 != VINF_SUCCESS) \
1383 return rcStrict2; \
1384 } while (0)
1385# else
1386# define IEM_OPCODE_GET_NEXT_S32_SX_U64(a_pu64) (*(a_pu64) = (uint64_t)(int64_t)(int32_t)iemOpcodeGetNextU32Jmp(pVCpu))
1387# endif
1388
1389# ifndef IEM_WITH_SETJMP
1390
1391/**
1392 * Fetches the next opcode qword.
1393 *
1394 * @returns Strict VBox status code.
1395 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1396 * @param pu64 Where to return the opcode qword.
1397 */
1398DECLINLINE(VBOXSTRICTRC) iemOpcodeGetNextU64(PVMCPUCC pVCpu, uint64_t *pu64) RT_NOEXCEPT
1399{
1400 uintptr_t const offOpcode = pVCpu->iem.s.offOpcode;
1401 if (RT_LIKELY((uint8_t)offOpcode + 8 <= pVCpu->iem.s.cbOpcode))
1402 {
1403# ifdef IEM_USE_UNALIGNED_DATA_ACCESS
1404 *pu64 = *(uint64_t const *)&pVCpu->iem.s.abOpcode[offOpcode];
1405# else
1406 *pu64 = RT_MAKE_U64_FROM_U8(pVCpu->iem.s.abOpcode[offOpcode],
1407 pVCpu->iem.s.abOpcode[offOpcode + 1],
1408 pVCpu->iem.s.abOpcode[offOpcode + 2],
1409 pVCpu->iem.s.abOpcode[offOpcode + 3],
1410 pVCpu->iem.s.abOpcode[offOpcode + 4],
1411 pVCpu->iem.s.abOpcode[offOpcode + 5],
1412 pVCpu->iem.s.abOpcode[offOpcode + 6],
1413 pVCpu->iem.s.abOpcode[offOpcode + 7]);
1414# endif
1415 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + 8;
1416 return VINF_SUCCESS;
1417 }
1418 return iemOpcodeGetNextU64Slow(pVCpu, pu64);
1419}
1420
1421# else /* IEM_WITH_SETJMP */
1422
1423/**
1424 * Fetches the next opcode qword, longjmp on error.
1425 *
1426 * @returns The opcode qword.
1427 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1428 */
1429DECL_INLINE_THROW(uint64_t) iemOpcodeGetNextU64Jmp(PVMCPUCC pVCpu) IEM_NOEXCEPT_MAY_LONGJMP
1430{
1431# ifdef IEM_WITH_CODE_TLB
1432 uint64_t u64Ret;
1433 uintptr_t offBuf = pVCpu->iem.s.offInstrNextByte;
1434 uint8_t const *pbBuf = pVCpu->iem.s.pbInstrBuf;
1435 if (RT_LIKELY( pbBuf != NULL
1436 && offBuf + 8 <= pVCpu->iem.s.cbInstrBuf))
1437 {
1438 pVCpu->iem.s.offInstrNextByte = (uint32_t)offBuf + 8;
1439# ifdef IEM_USE_UNALIGNED_DATA_ACCESS
1440 u64Ret = *(uint64_t const *)&pbBuf[offBuf];
1441# else
1442 u64Ret = RT_MAKE_U64_FROM_U8(pbBuf[offBuf],
1443 pbBuf[offBuf + 1],
1444 pbBuf[offBuf + 2],
1445 pbBuf[offBuf + 3],
1446 pbBuf[offBuf + 4],
1447 pbBuf[offBuf + 5],
1448 pbBuf[offBuf + 6],
1449 pbBuf[offBuf + 7]);
1450# endif
1451 }
1452 else
1453 u64Ret = iemOpcodeGetNextU64SlowJmp(pVCpu);
1454
1455# ifdef IEM_WITH_CODE_TLB_AND_OPCODE_BUF
1456 uintptr_t const offOpcode = pVCpu->iem.s.offOpcode;
1457 Assert(offOpcode + 7 < sizeof(pVCpu->iem.s.abOpcode));
1458# ifdef IEM_USE_UNALIGNED_DATA_ACCESS
1459 *(uint64_t *)&pVCpu->iem.s.abOpcode[offOpcode] = u64Ret;
1460# else
1461 pVCpu->iem.s.abOpcode[offOpcode] = RT_BYTE1(u64Ret);
1462 pVCpu->iem.s.abOpcode[offOpcode + 1] = RT_BYTE2(u64Ret);
1463 pVCpu->iem.s.abOpcode[offOpcode + 2] = RT_BYTE3(u64Ret);
1464 pVCpu->iem.s.abOpcode[offOpcode + 3] = RT_BYTE4(u64Ret);
1465 pVCpu->iem.s.abOpcode[offOpcode + 4] = RT_BYTE5(u64Ret);
1466 pVCpu->iem.s.abOpcode[offOpcode + 5] = RT_BYTE6(u64Ret);
1467 pVCpu->iem.s.abOpcode[offOpcode + 6] = RT_BYTE7(u64Ret);
1468 pVCpu->iem.s.abOpcode[offOpcode + 7] = RT_BYTE8(u64Ret);
1469# endif
1470 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + (uint8_t)8;
1471# endif /* IEM_WITH_CODE_TLB_AND_OPCODE_BUF */
1472
1473 return u64Ret;
1474
1475# else /* !IEM_WITH_CODE_TLB */
1476 uintptr_t const offOpcode = pVCpu->iem.s.offOpcode;
1477 if (RT_LIKELY((uint8_t)offOpcode + 8 <= pVCpu->iem.s.cbOpcode))
1478 {
1479 pVCpu->iem.s.offOpcode = (uint8_t)offOpcode + 8;
1480# ifdef IEM_USE_UNALIGNED_DATA_ACCESS
1481 return *(uint64_t const *)&pVCpu->iem.s.abOpcode[offOpcode];
1482# else
1483 return RT_MAKE_U64_FROM_U8(pVCpu->iem.s.abOpcode[offOpcode],
1484 pVCpu->iem.s.abOpcode[offOpcode + 1],
1485 pVCpu->iem.s.abOpcode[offOpcode + 2],
1486 pVCpu->iem.s.abOpcode[offOpcode + 3],
1487 pVCpu->iem.s.abOpcode[offOpcode + 4],
1488 pVCpu->iem.s.abOpcode[offOpcode + 5],
1489 pVCpu->iem.s.abOpcode[offOpcode + 6],
1490 pVCpu->iem.s.abOpcode[offOpcode + 7]);
1491# endif
1492 }
1493 return iemOpcodeGetNextU64SlowJmp(pVCpu);
1494# endif /* !IEM_WITH_CODE_TLB */
1495}
1496
1497# endif /* IEM_WITH_SETJMP */
1498
1499/**
1500 * Fetches the next opcode quad word, returns automatically on failure.
1501 *
1502 * @param a_pu64 Where to return the opcode quad word.
1503 * @remark Implicitly references pVCpu.
1504 */
1505# ifndef IEM_WITH_SETJMP
1506# define IEM_OPCODE_GET_NEXT_U64(a_pu64) \
1507 do \
1508 { \
1509 VBOXSTRICTRC rcStrict2 = iemOpcodeGetNextU64(pVCpu, (a_pu64)); \
1510 if (rcStrict2 != VINF_SUCCESS) \
1511 return rcStrict2; \
1512 } while (0)
1513# else
1514# define IEM_OPCODE_GET_NEXT_U64(a_pu64) ( *(a_pu64) = iemOpcodeGetNextU64Jmp(pVCpu) )
1515# endif
1516
1517/**
1518 * For fetching the opcode bytes for an ModR/M effective address, but throw
1519 * away the result.
1520 *
1521 * This is used when decoding undefined opcodes and such where we want to avoid
1522 * unnecessary MC blocks.
1523 *
1524 * @note The recompiler code overrides this one so iemOpHlpCalcRmEffAddrJmpEx is
1525 * used instead. At least for now...
1526 */
1527# ifndef IEM_WITH_SETJMP
1528# define IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(a_bRm) do { \
1529 RTGCPTR GCPtrEff; \
1530 VBOXSTRICTRC rcStrict = iemOpHlpCalcRmEffAddr(pVCpu, bRm, 0, &GCPtrEff); \
1531 if (rcStrict != VINF_SUCCESS) \
1532 return rcStrict; \
1533 } while (0)
1534# else
1535# define IEM_OPCODE_SKIP_RM_EFF_ADDR_BYTES(a_bRm) do { \
1536 (void)iemOpHlpCalcRmEffAddrJmp(pVCpu, bRm, 0); \
1537 } while (0)
1538# endif
1539
1540#endif /* !IEM_WITH_OPAQUE_DECODER_STATE */
1541
1542
1543/** @name Misc Worker Functions.
1544 * @{
1545 */
1546
1547/**
1548 * Gets the correct EFLAGS regardless of whether PATM stores parts of them or
1549 * not (kind of obsolete now).
1550 *
1551 * @param a_pVCpu The cross context virtual CPU structure of the calling thread.
1552 */
1553#define IEMMISC_GET_EFL(a_pVCpu) ( (a_pVCpu)->cpum.GstCtx.eflags.u )
1554
1555/**
1556 * Updates the EFLAGS in the correct manner wrt. PATM (kind of obsolete).
1557 *
1558 * @param a_pVCpu The cross context virtual CPU structure of the calling thread.
1559 * @param a_fEfl The new EFLAGS.
1560 */
1561#define IEMMISC_SET_EFL(a_pVCpu, a_fEfl) do { (a_pVCpu)->cpum.GstCtx.eflags.u = (a_fEfl); } while (0)
1562
1563
1564/**
1565 * Loads a NULL data selector into a selector register, both the hidden and
1566 * visible parts, in protected mode.
1567 *
1568 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1569 * @param pSReg Pointer to the segment register.
1570 * @param uRpl The RPL.
1571 */
1572DECLINLINE(void) iemHlpLoadNullDataSelectorProt(PVMCPUCC pVCpu, PCPUMSELREG pSReg, RTSEL uRpl) RT_NOEXCEPT
1573{
1574 /** @todo Testcase: write a testcase checking what happends when loading a NULL
1575 * data selector in protected mode. */
1576 pSReg->Sel = uRpl;
1577 pSReg->ValidSel = uRpl;
1578 pSReg->fFlags = CPUMSELREG_FLAGS_VALID;
1579 if (IEM_IS_GUEST_CPU_INTEL(pVCpu))
1580 {
1581 /* VT-x (Intel 3960x) observed doing something like this. */
1582 pSReg->Attr.u = X86DESCATTR_UNUSABLE | X86DESCATTR_G | X86DESCATTR_D | (IEM_GET_CPL(pVCpu) << X86DESCATTR_DPL_SHIFT);
1583 pSReg->u32Limit = UINT32_MAX;
1584 pSReg->u64Base = 0;
1585 }
1586 else
1587 {
1588 pSReg->Attr.u = X86DESCATTR_UNUSABLE;
1589 pSReg->u32Limit = 0;
1590 pSReg->u64Base = 0;
1591 }
1592}
1593
1594/** @} */
1595
1596
1597/*
1598 *
1599 * Helpers routines.
1600 * Helpers routines.
1601 * Helpers routines.
1602 *
1603 */
1604
1605#ifndef IEM_WITH_OPAQUE_DECODER_STATE
1606
1607/**
1608 * Recalculates the effective operand size.
1609 *
1610 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1611 */
1612DECLINLINE(void) iemRecalEffOpSize(PVMCPUCC pVCpu) RT_NOEXCEPT
1613{
1614 switch (IEM_GET_CPU_MODE(pVCpu))
1615 {
1616 case IEMMODE_16BIT:
1617 pVCpu->iem.s.enmEffOpSize = pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_OP ? IEMMODE_32BIT : IEMMODE_16BIT;
1618 break;
1619 case IEMMODE_32BIT:
1620 pVCpu->iem.s.enmEffOpSize = pVCpu->iem.s.fPrefixes & IEM_OP_PRF_SIZE_OP ? IEMMODE_16BIT : IEMMODE_32BIT;
1621 break;
1622 case IEMMODE_64BIT:
1623 switch (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_SIZE_REX_W | IEM_OP_PRF_SIZE_OP))
1624 {
1625 case 0:
1626 pVCpu->iem.s.enmEffOpSize = pVCpu->iem.s.enmDefOpSize;
1627 break;
1628 case IEM_OP_PRF_SIZE_OP:
1629 pVCpu->iem.s.enmEffOpSize = IEMMODE_16BIT;
1630 break;
1631 case IEM_OP_PRF_SIZE_REX_W:
1632 case IEM_OP_PRF_SIZE_REX_W | IEM_OP_PRF_SIZE_OP:
1633 pVCpu->iem.s.enmEffOpSize = IEMMODE_64BIT;
1634 break;
1635 }
1636 break;
1637 default:
1638 AssertFailed();
1639 }
1640}
1641
1642
1643/**
1644 * Sets the default operand size to 64-bit and recalculates the effective
1645 * operand size.
1646 *
1647 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1648 */
1649DECLINLINE(void) iemRecalEffOpSize64Default(PVMCPUCC pVCpu) RT_NOEXCEPT
1650{
1651 Assert(IEM_IS_64BIT_CODE(pVCpu));
1652 pVCpu->iem.s.enmDefOpSize = IEMMODE_64BIT;
1653 if ((pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_SIZE_REX_W | IEM_OP_PRF_SIZE_OP)) != IEM_OP_PRF_SIZE_OP)
1654 pVCpu->iem.s.enmEffOpSize = IEMMODE_64BIT;
1655 else
1656 pVCpu->iem.s.enmEffOpSize = IEMMODE_16BIT;
1657}
1658
1659
1660/**
1661 * Sets the default operand size to 64-bit and recalculates the effective
1662 * operand size, with intel ignoring any operand size prefix (AMD respects it).
1663 *
1664 * This is for the relative jumps.
1665 *
1666 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1667 */
1668DECLINLINE(void) iemRecalEffOpSize64DefaultAndIntelIgnoresOpSizePrefix(PVMCPUCC pVCpu) RT_NOEXCEPT
1669{
1670 Assert(IEM_IS_64BIT_CODE(pVCpu));
1671 pVCpu->iem.s.enmDefOpSize = IEMMODE_64BIT;
1672 if ( (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_SIZE_REX_W | IEM_OP_PRF_SIZE_OP)) != IEM_OP_PRF_SIZE_OP
1673 || pVCpu->iem.s.enmCpuVendor == CPUMCPUVENDOR_INTEL)
1674 pVCpu->iem.s.enmEffOpSize = IEMMODE_64BIT;
1675 else
1676 pVCpu->iem.s.enmEffOpSize = IEMMODE_16BIT;
1677}
1678
1679#endif /* !IEM_WITH_OPAQUE_DECODER_STATE */
1680
1681
1682
1683/** @name Register Access.
1684 * @{
1685 */
1686
1687/**
1688 * Gets a reference (pointer) to the specified hidden segment register.
1689 *
1690 * @returns Hidden register reference.
1691 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1692 * @param iSegReg The segment register.
1693 */
1694DECL_FORCE_INLINE(PCPUMSELREG) iemSRegGetHid(PVMCPUCC pVCpu, uint8_t iSegReg) RT_NOEXCEPT
1695{
1696 Assert(iSegReg < X86_SREG_COUNT);
1697 IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
1698 PCPUMSELREG pSReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
1699
1700 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, pSReg));
1701 return pSReg;
1702}
1703
1704
1705/**
1706 * Ensures that the given hidden segment register is up to date.
1707 *
1708 * @returns Hidden register reference.
1709 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1710 * @param pSReg The segment register.
1711 */
1712DECL_FORCE_INLINE(PCPUMSELREG) iemSRegUpdateHid(PVMCPUCC pVCpu, PCPUMSELREG pSReg) RT_NOEXCEPT
1713{
1714 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, pSReg));
1715 NOREF(pVCpu);
1716 return pSReg;
1717}
1718
1719
1720/**
1721 * Gets a reference (pointer) to the specified segment register (the selector
1722 * value).
1723 *
1724 * @returns Pointer to the selector variable.
1725 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1726 * @param iSegReg The segment register.
1727 */
1728DECL_FORCE_INLINE(uint16_t *) iemSRegRef(PVMCPUCC pVCpu, uint8_t iSegReg) RT_NOEXCEPT
1729{
1730 Assert(iSegReg < X86_SREG_COUNT);
1731 IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
1732 return &pVCpu->cpum.GstCtx.aSRegs[iSegReg].Sel;
1733}
1734
1735
1736/**
1737 * Fetches the selector value of a segment register.
1738 *
1739 * @returns The selector value.
1740 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1741 * @param iSegReg The segment register.
1742 */
1743DECL_FORCE_INLINE(uint16_t) iemSRegFetchU16(PVMCPUCC pVCpu, uint8_t iSegReg) RT_NOEXCEPT
1744{
1745 Assert(iSegReg < X86_SREG_COUNT);
1746 IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
1747 return pVCpu->cpum.GstCtx.aSRegs[iSegReg].Sel;
1748}
1749
1750
1751/**
1752 * Fetches the base address value of a segment register.
1753 *
1754 * @returns The selector value.
1755 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1756 * @param iSegReg The segment register.
1757 */
1758DECL_FORCE_INLINE(uint64_t) iemSRegBaseFetchU64(PVMCPUCC pVCpu, uint8_t iSegReg) RT_NOEXCEPT
1759{
1760 Assert(iSegReg < X86_SREG_COUNT);
1761 IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
1762 return pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
1763}
1764
1765
1766/**
1767 * Gets a reference (pointer) to the specified general purpose register.
1768 *
1769 * @returns Register reference.
1770 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1771 * @param iReg The general purpose register.
1772 */
1773DECL_FORCE_INLINE(void *) iemGRegRef(PVMCPUCC pVCpu, uint8_t iReg) RT_NOEXCEPT
1774{
1775 Assert(iReg < 16);
1776 return &pVCpu->cpum.GstCtx.aGRegs[iReg];
1777}
1778
1779
1780#ifndef IEM_WITH_OPAQUE_DECODER_STATE
1781/**
1782 * Gets a reference (pointer) to the specified 8-bit general purpose register.
1783 *
1784 * Because of AH, CH, DH and BH we cannot use iemGRegRef directly here.
1785 *
1786 * @returns Register reference.
1787 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1788 * @param iReg The register.
1789 */
1790DECL_FORCE_INLINE(uint8_t *) iemGRegRefU8(PVMCPUCC pVCpu, uint8_t iReg) RT_NOEXCEPT
1791{
1792 if (iReg < 4 || (pVCpu->iem.s.fPrefixes & (IEM_OP_PRF_REX | IEM_OP_PRF_VEX)))
1793 {
1794 Assert(iReg < 16);
1795 return &pVCpu->cpum.GstCtx.aGRegs[iReg].u8;
1796 }
1797 /* high 8-bit register. */
1798 Assert(iReg < 8);
1799 return &pVCpu->cpum.GstCtx.aGRegs[iReg & 3].bHi;
1800}
1801#endif
1802
1803
1804/**
1805 * Gets a reference (pointer) to the specified 8-bit general purpose register,
1806 * alternative version with extended (20) register index.
1807 *
1808 * @returns Register reference.
1809 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1810 * @param iRegEx The register. The 16 first are regular ones,
1811 * whereas 16 thru 19 maps to AH, CH, DH and BH.
1812 */
1813DECL_FORCE_INLINE(uint8_t *) iemGRegRefU8Ex(PVMCPUCC pVCpu, uint8_t iRegEx) RT_NOEXCEPT
1814{
1815 /** @todo This could be done by double indexing on little endian hosts:
1816 * return &pVCpu->cpum.GstCtx.aGRegs[iRegEx & 15].ab[iRegEx >> 4]; */
1817 if (iRegEx < 16)
1818 return &pVCpu->cpum.GstCtx.aGRegs[iRegEx].u8;
1819
1820 /* high 8-bit register. */
1821 Assert(iRegEx < 20);
1822 return &pVCpu->cpum.GstCtx.aGRegs[iRegEx & 3].bHi;
1823}
1824
1825
1826/**
1827 * Gets a reference (pointer) to the specified 16-bit general purpose register.
1828 *
1829 * @returns Register reference.
1830 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1831 * @param iReg The register.
1832 */
1833DECL_FORCE_INLINE(uint16_t *) iemGRegRefU16(PVMCPUCC pVCpu, uint8_t iReg) RT_NOEXCEPT
1834{
1835 Assert(iReg < 16);
1836 return &pVCpu->cpum.GstCtx.aGRegs[iReg].u16;
1837}
1838
1839
1840/**
1841 * Gets a reference (pointer) to the specified 32-bit general purpose register.
1842 *
1843 * @returns Register reference.
1844 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1845 * @param iReg The register.
1846 */
1847DECL_FORCE_INLINE(uint32_t *) iemGRegRefU32(PVMCPUCC pVCpu, uint8_t iReg) RT_NOEXCEPT
1848{
1849 Assert(iReg < 16);
1850 return &pVCpu->cpum.GstCtx.aGRegs[iReg].u32;
1851}
1852
1853
1854/**
1855 * Gets a reference (pointer) to the specified signed 32-bit general purpose register.
1856 *
1857 * @returns Register reference.
1858 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1859 * @param iReg The register.
1860 */
1861DECL_FORCE_INLINE(int32_t *) iemGRegRefI32(PVMCPUCC pVCpu, uint8_t iReg) RT_NOEXCEPT
1862{
1863 Assert(iReg < 16);
1864 return (int32_t *)&pVCpu->cpum.GstCtx.aGRegs[iReg].u32;
1865}
1866
1867
1868/**
1869 * Gets a reference (pointer) to the specified 64-bit general purpose register.
1870 *
1871 * @returns Register reference.
1872 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1873 * @param iReg The register.
1874 */
1875DECL_FORCE_INLINE(uint64_t *) iemGRegRefU64(PVMCPUCC pVCpu, uint8_t iReg) RT_NOEXCEPT
1876{
1877 Assert(iReg < 64);
1878 return &pVCpu->cpum.GstCtx.aGRegs[iReg].u64;
1879}
1880
1881
1882/**
1883 * Gets a reference (pointer) to the specified signed 64-bit general purpose register.
1884 *
1885 * @returns Register reference.
1886 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1887 * @param iReg The register.
1888 */
1889DECL_FORCE_INLINE(int64_t *) iemGRegRefI64(PVMCPUCC pVCpu, uint8_t iReg) RT_NOEXCEPT
1890{
1891 Assert(iReg < 16);
1892 return (int64_t *)&pVCpu->cpum.GstCtx.aGRegs[iReg].u64;
1893}
1894
1895
1896/**
1897 * Gets a reference (pointer) to the specified segment register's base address.
1898 *
1899 * @returns Segment register base address reference.
1900 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1901 * @param iSegReg The segment selector.
1902 */
1903DECL_FORCE_INLINE(uint64_t *) iemSRegBaseRefU64(PVMCPUCC pVCpu, uint8_t iSegReg) RT_NOEXCEPT
1904{
1905 Assert(iSegReg < X86_SREG_COUNT);
1906 IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
1907 return &pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
1908}
1909
1910
1911#ifndef IEM_WITH_OPAQUE_DECODER_STATE
1912/**
1913 * Fetches the value of a 8-bit general purpose register.
1914 *
1915 * @returns The register value.
1916 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1917 * @param iReg The register.
1918 */
1919DECL_FORCE_INLINE(uint8_t) iemGRegFetchU8(PVMCPUCC pVCpu, uint8_t iReg) RT_NOEXCEPT
1920{
1921 return *iemGRegRefU8(pVCpu, iReg);
1922}
1923#endif
1924
1925
1926/**
1927 * Fetches the value of a 8-bit general purpose register, alternative version
1928 * with extended (20) register index.
1929
1930 * @returns The register value.
1931 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1932 * @param iRegEx The register. The 16 first are regular ones,
1933 * whereas 16 thru 19 maps to AH, CH, DH and BH.
1934 */
1935DECL_FORCE_INLINE(uint8_t) iemGRegFetchU8Ex(PVMCPUCC pVCpu, uint8_t iRegEx) RT_NOEXCEPT
1936{
1937 return *iemGRegRefU8Ex(pVCpu, iRegEx);
1938}
1939
1940
1941/**
1942 * Fetches the value of a 16-bit general purpose register.
1943 *
1944 * @returns The register value.
1945 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1946 * @param iReg The register.
1947 */
1948DECL_FORCE_INLINE(uint16_t) iemGRegFetchU16(PVMCPUCC pVCpu, uint8_t iReg) RT_NOEXCEPT
1949{
1950 Assert(iReg < 16);
1951 return pVCpu->cpum.GstCtx.aGRegs[iReg].u16;
1952}
1953
1954
1955/**
1956 * Fetches the value of a 32-bit general purpose register.
1957 *
1958 * @returns The register value.
1959 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1960 * @param iReg The register.
1961 */
1962DECL_FORCE_INLINE(uint32_t) iemGRegFetchU32(PVMCPUCC pVCpu, uint8_t iReg) RT_NOEXCEPT
1963{
1964 Assert(iReg < 16);
1965 return pVCpu->cpum.GstCtx.aGRegs[iReg].u32;
1966}
1967
1968
1969/**
1970 * Fetches the value of a 64-bit general purpose register.
1971 *
1972 * @returns The register value.
1973 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1974 * @param iReg The register.
1975 */
1976DECL_FORCE_INLINE(uint64_t) iemGRegFetchU64(PVMCPUCC pVCpu, uint8_t iReg) RT_NOEXCEPT
1977{
1978 Assert(iReg < 16);
1979 return pVCpu->cpum.GstCtx.aGRegs[iReg].u64;
1980}
1981
1982
1983/**
1984 * Stores a 16-bit value to a general purpose register.
1985 *
1986 * @param pVCpu The cross context virtual CPU structure of the calling thread.
1987 * @param iReg The register.
1988 * @param uValue The value to store.
1989 */
1990DECL_FORCE_INLINE(void) iemGRegStoreU16(PVMCPUCC pVCpu, uint8_t iReg, uint16_t uValue) RT_NOEXCEPT
1991{
1992 Assert(iReg < 16);
1993 pVCpu->cpum.GstCtx.aGRegs[iReg].u16 = uValue;
1994}
1995
1996
1997/**
1998 * Stores a 32-bit value to a general purpose register, implicitly clearing high
1999 * values.
2000 *
2001 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2002 * @param iReg The register.
2003 * @param uValue The value to store.
2004 */
2005DECL_FORCE_INLINE(void) iemGRegStoreU32(PVMCPUCC pVCpu, uint8_t iReg, uint32_t uValue) RT_NOEXCEPT
2006{
2007 Assert(iReg < 16);
2008 pVCpu->cpum.GstCtx.aGRegs[iReg].u64 = uValue;
2009}
2010
2011
2012/**
2013 * Stores a 64-bit value to a general purpose register.
2014 *
2015 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2016 * @param iReg The register.
2017 * @param uValue The value to store.
2018 */
2019DECL_FORCE_INLINE(void) iemGRegStoreU64(PVMCPUCC pVCpu, uint8_t iReg, uint64_t uValue) RT_NOEXCEPT
2020{
2021 Assert(iReg < 16);
2022 pVCpu->cpum.GstCtx.aGRegs[iReg].u64 = uValue;
2023}
2024
2025
2026/**
2027 * Get the address of the top of the stack.
2028 *
2029 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2030 */
2031DECL_FORCE_INLINE(RTGCPTR) iemRegGetEffRsp(PCVMCPU pVCpu) RT_NOEXCEPT
2032{
2033 if (IEM_IS_64BIT_CODE(pVCpu))
2034 return pVCpu->cpum.GstCtx.rsp;
2035 if (pVCpu->cpum.GstCtx.ss.Attr.n.u1DefBig)
2036 return pVCpu->cpum.GstCtx.esp;
2037 return pVCpu->cpum.GstCtx.sp;
2038}
2039
2040
2041/**
2042 * Updates the RIP/EIP/IP to point to the next instruction.
2043 *
2044 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2045 * @param cbInstr The number of bytes to add.
2046 */
2047DECL_FORCE_INLINE(void) iemRegAddToRip(PVMCPUCC pVCpu, uint8_t cbInstr) RT_NOEXCEPT
2048{
2049 /*
2050 * Advance RIP.
2051 *
2052 * When we're targetting 8086/8, 80186/8 or 80286 mode the updates are 16-bit,
2053 * while in all other modes except LM64 the updates are 32-bit. This means
2054 * we need to watch for both 32-bit and 16-bit "carry" situations, i.e.
2055 * 4GB and 64KB rollovers, and decide whether anything needs masking.
2056 *
2057 * See PC wrap around tests in bs3-cpu-weird-1.
2058 */
2059 uint64_t const uRipPrev = pVCpu->cpum.GstCtx.rip;
2060 uint64_t const uRipNext = uRipPrev + cbInstr;
2061 if (RT_LIKELY( !((uRipNext ^ uRipPrev) & (RT_BIT_64(32) | RT_BIT_64(16)))
2062 || IEM_IS_64BIT_CODE(pVCpu)))
2063 pVCpu->cpum.GstCtx.rip = uRipNext;
2064 else if (IEM_GET_TARGET_CPU(pVCpu) >= IEMTARGETCPU_386)
2065 pVCpu->cpum.GstCtx.rip = (uint32_t)uRipNext;
2066 else
2067 pVCpu->cpum.GstCtx.rip = (uint16_t)uRipNext;
2068}
2069
2070
2071/**
2072 * Called by iemRegAddToRipAndFinishingClearingRF and others when any of the
2073 * following EFLAGS bits are set:
2074 * - X86_EFL_RF - clear it.
2075 * - CPUMCTX_INHIBIT_SHADOW (_SS/_STI) - clear them.
2076 * - X86_EFL_TF - generate single step \#DB trap.
2077 * - CPUMCTX_DBG_HIT_DR0/1/2/3 - generate \#DB trap (data or I/O, not
2078 * instruction).
2079 *
2080 * According to @sdmv3{077,200,Table 6-2,Priority Among Concurrent Events},
2081 * a \#DB due to TF (single stepping) or a DRx non-instruction breakpoint
2082 * takes priority over both NMIs and hardware interrupts. So, neither is
2083 * considered here. (The RESET, \#MC, SMI, INIT, STOPCLK and FLUSH events are
2084 * either unsupported will be triggered on-top of any \#DB raised here.)
2085 *
2086 * The RF flag only needs to be cleared here as it only suppresses instruction
2087 * breakpoints which are not raised here (happens synchronously during
2088 * instruction fetching).
2089 *
2090 * The CPUMCTX_INHIBIT_SHADOW_SS flag will be cleared by this function, so its
2091 * status has no bearing on whether \#DB exceptions are raised.
2092 *
2093 * @note This must *NOT* be called by the two instructions setting the
2094 * CPUMCTX_INHIBIT_SHADOW_SS flag.
2095 *
2096 * @see @sdmv3{077,200,Table 6-2,Priority Among Concurrent Events}
2097 * @see @sdmv3{077,200,6.8.3,Masking Exceptions and Interrupts When Switching
2098 * Stacks}
2099 */
2100static VBOXSTRICTRC iemFinishInstructionWithFlagsSet(PVMCPUCC pVCpu, int rcNormal) RT_NOEXCEPT
2101{
2102 /*
2103 * Normally we're just here to clear RF and/or interrupt shadow bits.
2104 */
2105 if (RT_LIKELY((pVCpu->cpum.GstCtx.eflags.uBoth & (X86_EFL_TF | CPUMCTX_DBG_HIT_DRX_MASK | CPUMCTX_DBG_DBGF_MASK)) == 0))
2106 pVCpu->cpum.GstCtx.eflags.uBoth &= ~(X86_EFL_RF | CPUMCTX_INHIBIT_SHADOW);
2107 else
2108 {
2109 /*
2110 * Raise a #DB or/and DBGF event.
2111 */
2112 VBOXSTRICTRC rcStrict;
2113 if (pVCpu->cpum.GstCtx.eflags.uBoth & (X86_EFL_TF | CPUMCTX_DBG_HIT_DRX_MASK))
2114 {
2115 IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_DR6);
2116 pVCpu->cpum.GstCtx.dr[6] &= ~X86_DR6_B_MASK;
2117 if (pVCpu->cpum.GstCtx.eflags.uBoth & X86_EFL_TF)
2118 pVCpu->cpum.GstCtx.dr[6] |= X86_DR6_BS;
2119 pVCpu->cpum.GstCtx.dr[6] |= (pVCpu->cpum.GstCtx.eflags.uBoth & CPUMCTX_DBG_HIT_DRX_MASK_NONSILENT)
2120 >> CPUMCTX_DBG_HIT_DRX_SHIFT;
2121 LogFlowFunc(("Guest #DB fired at %04X:%016llX: DR6=%08X, RFLAGS=%16RX64\n",
2122 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, (unsigned)pVCpu->cpum.GstCtx.dr[6],
2123 pVCpu->cpum.GstCtx.rflags.uBoth));
2124
2125 pVCpu->cpum.GstCtx.eflags.uBoth &= ~(X86_EFL_RF | CPUMCTX_INHIBIT_SHADOW | CPUMCTX_DBG_HIT_DRX_MASK);
2126 rcStrict = iemRaiseDebugException(pVCpu);
2127
2128 /* A DBGF event/breakpoint trumps the iemRaiseDebugException informational status code. */
2129 if ((pVCpu->cpum.GstCtx.eflags.uBoth & CPUMCTX_DBG_DBGF_MASK) && RT_FAILURE(rcStrict))
2130 {
2131 rcStrict = pVCpu->cpum.GstCtx.eflags.uBoth & CPUMCTX_DBG_DBGF_BP ? VINF_EM_DBG_BREAKPOINT : VINF_EM_DBG_EVENT;
2132 LogFlowFunc(("dbgf at %04X:%016llX: %Rrc\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, VBOXSTRICTRC_VAL(rcStrict)));
2133 }
2134 }
2135 else
2136 {
2137 Assert(pVCpu->cpum.GstCtx.eflags.uBoth & CPUMCTX_DBG_DBGF_MASK);
2138 rcStrict = pVCpu->cpum.GstCtx.eflags.uBoth & CPUMCTX_DBG_DBGF_BP ? VINF_EM_DBG_BREAKPOINT : VINF_EM_DBG_EVENT;
2139 LogFlowFunc(("dbgf at %04X:%016llX: %Rrc\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, VBOXSTRICTRC_VAL(rcStrict)));
2140 }
2141 pVCpu->cpum.GstCtx.eflags.uBoth &= ~CPUMCTX_DBG_DBGF_MASK;
2142 Assert(rcStrict != VINF_SUCCESS);
2143 return rcStrict;
2144 }
2145 return rcNormal;
2146}
2147
2148
2149/**
2150 * Clears the RF and CPUMCTX_INHIBIT_SHADOW, triggering \#DB if pending.
2151 *
2152 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2153 * @param rcNormal VINF_SUCCESS to continue TB.
2154 * VINF_IEM_REEXEC_BREAK to force TB exit when
2155 * taking the wrong conditional branhc.
2156 */
2157DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegFinishClearingRF(PVMCPUCC pVCpu, int rcNormal) RT_NOEXCEPT
2158{
2159 /*
2160 * We assume that most of the time nothing actually needs doing here.
2161 */
2162 AssertCompile(CPUMCTX_INHIBIT_SHADOW < UINT32_MAX);
2163 if (RT_LIKELY(!( pVCpu->cpum.GstCtx.eflags.uBoth
2164 & (X86_EFL_TF | X86_EFL_RF | CPUMCTX_INHIBIT_SHADOW | CPUMCTX_DBG_HIT_DRX_MASK | CPUMCTX_DBG_DBGF_MASK)) ))
2165 return rcNormal;
2166 return iemFinishInstructionWithFlagsSet(pVCpu, rcNormal);
2167}
2168
2169
2170/**
2171 * Updates the RIP/EIP/IP to point to the next instruction and clears EFLAGS.RF
2172 * and CPUMCTX_INHIBIT_SHADOW.
2173 *
2174 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2175 * @param cbInstr The number of bytes to add.
2176 */
2177DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegAddToRipAndFinishingClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr) RT_NOEXCEPT
2178{
2179 iemRegAddToRip(pVCpu, cbInstr);
2180 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
2181}
2182
2183
2184/**
2185 * Updates the RIP to point to the next instruction and clears EFLAGS.RF
2186 * and CPUMCTX_INHIBIT_SHADOW.
2187 *
2188 * Only called from 64-bit code.
2189 *
2190 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2191 * @param cbInstr The number of bytes to add.
2192 * @param rcNormal VINF_SUCCESS to continue TB.
2193 * VINF_IEM_REEXEC_BREAK to force TB exit when
2194 * taking the wrong conditional branhc.
2195 */
2196DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegAddToRip64AndFinishingClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, int rcNormal) RT_NOEXCEPT
2197{
2198 pVCpu->cpum.GstCtx.rip = pVCpu->cpum.GstCtx.rip + cbInstr;
2199 return iemRegFinishClearingRF(pVCpu, rcNormal);
2200}
2201
2202
2203/**
2204 * Updates the EIP to point to the next instruction and clears EFLAGS.RF and
2205 * CPUMCTX_INHIBIT_SHADOW.
2206 *
2207 * This is never from 64-bit code.
2208 *
2209 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2210 * @param cbInstr The number of bytes to add.
2211 * @param rcNormal VINF_SUCCESS to continue TB.
2212 * VINF_IEM_REEXEC_BREAK to force TB exit when
2213 * taking the wrong conditional branhc.
2214 */
2215DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegAddToEip32AndFinishingClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, int rcNormal) RT_NOEXCEPT
2216{
2217 pVCpu->cpum.GstCtx.rip = (uint32_t)(pVCpu->cpum.GstCtx.eip + cbInstr);
2218 return iemRegFinishClearingRF(pVCpu, rcNormal);
2219}
2220
2221
2222/**
2223 * Updates the IP to point to the next instruction and clears EFLAGS.RF and
2224 * CPUMCTX_INHIBIT_SHADOW.
2225 *
2226 * This is only ever used from 16-bit code on a pre-386 CPU.
2227 *
2228 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2229 * @param cbInstr The number of bytes to add.
2230 * @param rcNormal VINF_SUCCESS to continue TB.
2231 * VINF_IEM_REEXEC_BREAK to force TB exit when
2232 * taking the wrong conditional branhc.
2233 */
2234DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegAddToIp16AndFinishingClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, int rcNormal) RT_NOEXCEPT
2235{
2236 pVCpu->cpum.GstCtx.rip = (uint16_t)(pVCpu->cpum.GstCtx.ip + cbInstr);
2237 return iemRegFinishClearingRF(pVCpu, rcNormal);
2238}
2239
2240
2241/**
2242 * Tail method for a finish function that does't clear flags or raise \#DB.
2243 *
2244 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2245 * @param rcNormal VINF_SUCCESS to continue TB.
2246 * VINF_IEM_REEXEC_BREAK to force TB exit when
2247 * taking the wrong conditional branhc.
2248 */
2249DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegFinishNoFlags(PVMCPUCC pVCpu, int rcNormal) RT_NOEXCEPT
2250{
2251 AssertCompile(CPUMCTX_INHIBIT_SHADOW < UINT32_MAX);
2252 Assert(!( pVCpu->cpum.GstCtx.eflags.uBoth
2253 & (X86_EFL_TF | X86_EFL_RF | CPUMCTX_INHIBIT_SHADOW | CPUMCTX_DBG_HIT_DRX_MASK | CPUMCTX_DBG_DBGF_MASK)) );
2254 RT_NOREF(pVCpu);
2255 return rcNormal;
2256}
2257
2258
2259/**
2260 * Updates the RIP to point to the next instruction, but does not need to clear
2261 * EFLAGS.RF or CPUMCTX_INHIBIT_SHADOW nor check for debug flags.
2262 *
2263 * Only called from 64-bit code.
2264 *
2265 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2266 * @param cbInstr The number of bytes to add.
2267 * @param rcNormal VINF_SUCCESS to continue TB.
2268 * VINF_IEM_REEXEC_BREAK to force TB exit when
2269 * taking the wrong conditional branhc.
2270 */
2271DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegAddToRip64AndFinishingNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, int rcNormal) RT_NOEXCEPT
2272{
2273 pVCpu->cpum.GstCtx.rip = pVCpu->cpum.GstCtx.rip + cbInstr;
2274 return iemRegFinishNoFlags(pVCpu, rcNormal);
2275}
2276
2277
2278/**
2279 * Updates the EIP to point to the next instruction, but does not need to clear
2280 * EFLAGS.RF or CPUMCTX_INHIBIT_SHADOW nor check for debug flags.
2281 *
2282 * This is never from 64-bit code.
2283 *
2284 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2285 * @param cbInstr The number of bytes to add.
2286 * @param rcNormal VINF_SUCCESS to continue TB.
2287 * VINF_IEM_REEXEC_BREAK to force TB exit when
2288 * taking the wrong conditional branhc.
2289 */
2290DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegAddToEip32AndFinishingNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, int rcNormal) RT_NOEXCEPT
2291{
2292 pVCpu->cpum.GstCtx.rip = (uint32_t)(pVCpu->cpum.GstCtx.eip + cbInstr);
2293 return iemRegFinishNoFlags(pVCpu, rcNormal);
2294}
2295
2296
2297/**
2298 * Updates the IP to point to the next instruction, but does not need to clear
2299 * EFLAGS.RF or CPUMCTX_INHIBIT_SHADOW nor check for debug flags.
2300 *
2301 * This is only ever used from 16-bit code on a pre-386 CPU.
2302 *
2303 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2304 * @param cbInstr The number of bytes to add.
2305 * @param rcNormal VINF_SUCCESS to continue TB.
2306 * VINF_IEM_REEXEC_BREAK to force TB exit when
2307 * taking the wrong conditional branhc.
2308 *
2309 */
2310DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegAddToIp16AndFinishingNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, int rcNormal) RT_NOEXCEPT
2311{
2312 pVCpu->cpum.GstCtx.rip = (uint16_t)(pVCpu->cpum.GstCtx.ip + cbInstr);
2313 return iemRegFinishNoFlags(pVCpu, rcNormal);
2314}
2315
2316
2317/**
2318 * Adds a 8-bit signed jump offset to RIP from 64-bit code.
2319 *
2320 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2321 * segment limit.
2322 *
2323 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2324 * @param cbInstr Instruction size.
2325 * @param offNextInstr The offset of the next instruction.
2326 * @param enmEffOpSize Effective operand size.
2327 * @param rcNormal VINF_SUCCESS to continue TB.
2328 * VINF_IEM_REEXEC_BREAK to force TB exit when
2329 * taking the wrong conditional branhc.
2330 */
2331DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegRip64RelativeJumpS8AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, int8_t offNextInstr,
2332 IEMMODE enmEffOpSize, int rcNormal) RT_NOEXCEPT
2333{
2334 Assert(IEM_IS_64BIT_CODE(pVCpu));
2335 Assert(enmEffOpSize == IEMMODE_64BIT || enmEffOpSize == IEMMODE_16BIT);
2336
2337 uint64_t uNewRip = pVCpu->cpum.GstCtx.rip + cbInstr + (int64_t)offNextInstr;
2338 if (enmEffOpSize == IEMMODE_16BIT)
2339 uNewRip &= UINT16_MAX;
2340
2341 if (RT_LIKELY(IEM_IS_CANONICAL(uNewRip)))
2342 pVCpu->cpum.GstCtx.rip = uNewRip;
2343 else
2344 return iemRaiseGeneralProtectionFault0(pVCpu);
2345
2346#ifndef IEM_WITH_CODE_TLB
2347 iemOpcodeFlushLight(pVCpu, cbInstr);
2348#endif
2349
2350 /*
2351 * Clear RF and finish the instruction (maybe raise #DB).
2352 */
2353 return iemRegFinishClearingRF(pVCpu, rcNormal);
2354}
2355
2356
2357/**
2358 * Adds a 8-bit signed jump offset to EIP, on 386 or later from 16-bit or 32-bit
2359 * code (never 64-bit).
2360 *
2361 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2362 * segment limit.
2363 *
2364 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2365 * @param cbInstr Instruction size.
2366 * @param offNextInstr The offset of the next instruction.
2367 * @param enmEffOpSize Effective operand size.
2368 * @param rcNormal VINF_SUCCESS to continue TB.
2369 * VINF_IEM_REEXEC_BREAK to force TB exit when
2370 * taking the wrong conditional branhc.
2371 */
2372DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegEip32RelativeJumpS8AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, int8_t offNextInstr,
2373 IEMMODE enmEffOpSize, int rcNormal) RT_NOEXCEPT
2374{
2375 Assert(!IEM_IS_64BIT_CODE(pVCpu));
2376 Assert(enmEffOpSize == IEMMODE_32BIT || enmEffOpSize == IEMMODE_16BIT);
2377
2378 uint32_t uNewEip = pVCpu->cpum.GstCtx.eip + cbInstr + (int32_t)offNextInstr;
2379 if (enmEffOpSize == IEMMODE_16BIT)
2380 uNewEip &= UINT16_MAX;
2381 if (RT_LIKELY(uNewEip <= pVCpu->cpum.GstCtx.cs.u32Limit))
2382 pVCpu->cpum.GstCtx.rip = uNewEip;
2383 else
2384 return iemRaiseGeneralProtectionFault0(pVCpu);
2385
2386#ifndef IEM_WITH_CODE_TLB
2387 iemOpcodeFlushLight(pVCpu, cbInstr);
2388#endif
2389
2390 /*
2391 * Clear RF and finish the instruction (maybe raise #DB).
2392 */
2393 return iemRegFinishClearingRF(pVCpu, rcNormal);
2394}
2395
2396
2397/**
2398 * Adds a 8-bit signed jump offset to IP, on a pre-386 CPU.
2399 *
2400 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2401 * segment limit.
2402 *
2403 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2404 * @param cbInstr Instruction size.
2405 * @param offNextInstr The offset of the next instruction.
2406 * @param rcNormal VINF_SUCCESS to continue TB.
2407 * VINF_IEM_REEXEC_BREAK to force TB exit when
2408 * taking the wrong conditional branhc.
2409 */
2410DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegIp16RelativeJumpS8AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr,
2411 int8_t offNextInstr, int rcNormal) RT_NOEXCEPT
2412{
2413 Assert(!IEM_IS_64BIT_CODE(pVCpu));
2414
2415 uint16_t const uNewIp = pVCpu->cpum.GstCtx.ip + cbInstr + (int16_t)offNextInstr;
2416 if (RT_LIKELY(uNewIp <= pVCpu->cpum.GstCtx.cs.u32Limit))
2417 pVCpu->cpum.GstCtx.rip = uNewIp;
2418 else
2419 return iemRaiseGeneralProtectionFault0(pVCpu);
2420
2421#ifndef IEM_WITH_CODE_TLB
2422 iemOpcodeFlushLight(pVCpu, cbInstr);
2423#endif
2424
2425 /*
2426 * Clear RF and finish the instruction (maybe raise #DB).
2427 */
2428 return iemRegFinishClearingRF(pVCpu, rcNormal);
2429}
2430
2431
2432/**
2433 * Adds a 8-bit signed jump offset to RIP from 64-bit code, no checking or
2434 * clearing of flags.
2435 *
2436 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2437 * segment limit.
2438 *
2439 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2440 * @param cbInstr Instruction size.
2441 * @param offNextInstr The offset of the next instruction.
2442 * @param enmEffOpSize Effective operand size.
2443 * @param rcNormal VINF_SUCCESS to continue TB.
2444 * VINF_IEM_REEXEC_BREAK to force TB exit when
2445 * taking the wrong conditional branhc.
2446 */
2447DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegRip64RelativeJumpS8AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, int8_t offNextInstr,
2448 IEMMODE enmEffOpSize, int rcNormal) RT_NOEXCEPT
2449{
2450 Assert(IEM_IS_64BIT_CODE(pVCpu));
2451 Assert(enmEffOpSize == IEMMODE_64BIT || enmEffOpSize == IEMMODE_16BIT);
2452
2453 uint64_t uNewRip = pVCpu->cpum.GstCtx.rip + cbInstr + (int64_t)offNextInstr;
2454 if (enmEffOpSize == IEMMODE_16BIT)
2455 uNewRip &= UINT16_MAX;
2456
2457 if (RT_LIKELY(IEM_IS_CANONICAL(uNewRip)))
2458 pVCpu->cpum.GstCtx.rip = uNewRip;
2459 else
2460 return iemRaiseGeneralProtectionFault0(pVCpu);
2461
2462#ifndef IEM_WITH_CODE_TLB
2463 iemOpcodeFlushLight(pVCpu, cbInstr);
2464#endif
2465 return iemRegFinishNoFlags(pVCpu, rcNormal);
2466}
2467
2468
2469/**
2470 * Adds a 8-bit signed jump offset to EIP, on 386 or later from 16-bit or 32-bit
2471 * code (never 64-bit), no checking or clearing of flags.
2472 *
2473 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2474 * segment limit.
2475 *
2476 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2477 * @param cbInstr Instruction size.
2478 * @param offNextInstr The offset of the next instruction.
2479 * @param enmEffOpSize Effective operand size.
2480 * @param rcNormal VINF_SUCCESS to continue TB.
2481 * VINF_IEM_REEXEC_BREAK to force TB exit when
2482 * taking the wrong conditional branhc.
2483 */
2484DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegEip32RelativeJumpS8AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, int8_t offNextInstr,
2485 IEMMODE enmEffOpSize, int rcNormal) RT_NOEXCEPT
2486{
2487 Assert(!IEM_IS_64BIT_CODE(pVCpu));
2488 Assert(enmEffOpSize == IEMMODE_32BIT || enmEffOpSize == IEMMODE_16BIT);
2489
2490 uint32_t uNewEip = pVCpu->cpum.GstCtx.eip + cbInstr + (int32_t)offNextInstr;
2491 if (enmEffOpSize == IEMMODE_16BIT)
2492 uNewEip &= UINT16_MAX;
2493 if (RT_LIKELY(uNewEip <= pVCpu->cpum.GstCtx.cs.u32Limit))
2494 pVCpu->cpum.GstCtx.rip = uNewEip;
2495 else
2496 return iemRaiseGeneralProtectionFault0(pVCpu);
2497
2498#ifndef IEM_WITH_CODE_TLB
2499 iemOpcodeFlushLight(pVCpu, cbInstr);
2500#endif
2501 return iemRegFinishNoFlags(pVCpu, rcNormal);
2502}
2503
2504
2505/**
2506 * Adds a 8-bit signed jump offset to IP, on a pre-386 CPU, no checking or
2507 * clearing of flags.
2508 *
2509 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2510 * segment limit.
2511 *
2512 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2513 * @param cbInstr Instruction size.
2514 * @param offNextInstr The offset of the next instruction.
2515 * @param rcNormal VINF_SUCCESS to continue TB.
2516 * VINF_IEM_REEXEC_BREAK to force TB exit when
2517 * taking the wrong conditional branhc.
2518 */
2519DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegIp16RelativeJumpS8AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr,
2520 int8_t offNextInstr, int rcNormal) RT_NOEXCEPT
2521{
2522 Assert(!IEM_IS_64BIT_CODE(pVCpu));
2523
2524 uint16_t const uNewIp = pVCpu->cpum.GstCtx.ip + cbInstr + (int16_t)offNextInstr;
2525 if (RT_LIKELY(uNewIp <= pVCpu->cpum.GstCtx.cs.u32Limit))
2526 pVCpu->cpum.GstCtx.rip = uNewIp;
2527 else
2528 return iemRaiseGeneralProtectionFault0(pVCpu);
2529
2530#ifndef IEM_WITH_CODE_TLB
2531 iemOpcodeFlushLight(pVCpu, cbInstr);
2532#endif
2533 return iemRegFinishNoFlags(pVCpu, rcNormal);
2534}
2535
2536
2537/**
2538 * Adds a 16-bit signed jump offset to RIP from 64-bit code.
2539 *
2540 * @returns Strict VBox status code.
2541 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2542 * @param cbInstr Instruction size.
2543 * @param offNextInstr The offset of the next instruction.
2544 * @param rcNormal VINF_SUCCESS to continue TB.
2545 * VINF_IEM_REEXEC_BREAK to force TB exit when
2546 * taking the wrong conditional branhc.
2547 */
2548DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegRip64RelativeJumpS16AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr,
2549 int16_t offNextInstr, int rcNormal) RT_NOEXCEPT
2550{
2551 Assert(IEM_IS_64BIT_CODE(pVCpu));
2552
2553 pVCpu->cpum.GstCtx.rip = (uint16_t)(pVCpu->cpum.GstCtx.ip + cbInstr + offNextInstr);
2554
2555#ifndef IEM_WITH_CODE_TLB
2556 iemOpcodeFlushLight(pVCpu, cbInstr);
2557#endif
2558
2559 /*
2560 * Clear RF and finish the instruction (maybe raise #DB).
2561 */
2562 return iemRegFinishClearingRF(pVCpu, rcNormal);
2563}
2564
2565
2566/**
2567 * Adds a 16-bit signed jump offset to EIP from 16-bit or 32-bit code.
2568 *
2569 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2570 * segment limit.
2571 *
2572 * @returns Strict VBox status code.
2573 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2574 * @param cbInstr Instruction size.
2575 * @param offNextInstr The offset of the next instruction.
2576 * @param rcNormal VINF_SUCCESS to continue TB.
2577 * VINF_IEM_REEXEC_BREAK to force TB exit when
2578 * taking the wrong conditional branhc.
2579 *
2580 * @note This is also used by 16-bit code in pre-386 mode, as the code is
2581 * identical.
2582 */
2583DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegEip32RelativeJumpS16AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr,
2584 int16_t offNextInstr, int rcNormal) RT_NOEXCEPT
2585{
2586 Assert(!IEM_IS_64BIT_CODE(pVCpu));
2587
2588 uint16_t const uNewIp = pVCpu->cpum.GstCtx.ip + cbInstr + offNextInstr;
2589 if (RT_LIKELY(uNewIp <= pVCpu->cpum.GstCtx.cs.u32Limit))
2590 pVCpu->cpum.GstCtx.rip = uNewIp;
2591 else
2592 return iemRaiseGeneralProtectionFault0(pVCpu);
2593
2594#ifndef IEM_WITH_CODE_TLB
2595 iemOpcodeFlushLight(pVCpu, cbInstr);
2596#endif
2597
2598 /*
2599 * Clear RF and finish the instruction (maybe raise #DB).
2600 */
2601 return iemRegFinishClearingRF(pVCpu, rcNormal);
2602}
2603
2604
2605/**
2606 * Adds a 16-bit signed jump offset to RIP from 64-bit code, no checking or
2607 * clearing of flags.
2608 *
2609 * @returns Strict VBox status code.
2610 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2611 * @param cbInstr Instruction size.
2612 * @param offNextInstr The offset of the next instruction.
2613 * @param rcNormal VINF_SUCCESS to continue TB.
2614 * VINF_IEM_REEXEC_BREAK to force TB exit when
2615 * taking the wrong conditional branhc.
2616 */
2617DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegRip64RelativeJumpS16AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr,
2618 int16_t offNextInstr, int rcNormal) RT_NOEXCEPT
2619{
2620 Assert(IEM_IS_64BIT_CODE(pVCpu));
2621
2622 pVCpu->cpum.GstCtx.rip = (uint16_t)(pVCpu->cpum.GstCtx.ip + cbInstr + offNextInstr);
2623
2624#ifndef IEM_WITH_CODE_TLB
2625 iemOpcodeFlushLight(pVCpu, cbInstr);
2626#endif
2627 return iemRegFinishNoFlags(pVCpu, rcNormal);
2628}
2629
2630
2631/**
2632 * Adds a 16-bit signed jump offset to EIP from 16-bit or 32-bit code,
2633 * no checking or clearing of flags.
2634 *
2635 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2636 * segment limit.
2637 *
2638 * @returns Strict VBox status code.
2639 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2640 * @param cbInstr Instruction size.
2641 * @param offNextInstr The offset of the next instruction.
2642 * @param rcNormal VINF_SUCCESS to continue TB.
2643 * VINF_IEM_REEXEC_BREAK to force TB exit when
2644 * taking the wrong conditional branhc.
2645 *
2646 * @note This is also used by 16-bit code in pre-386 mode, as the code is
2647 * identical.
2648 */
2649DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegEip32RelativeJumpS16AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr,
2650 int16_t offNextInstr, int rcNormal) RT_NOEXCEPT
2651{
2652 Assert(!IEM_IS_64BIT_CODE(pVCpu));
2653
2654 uint16_t const uNewIp = pVCpu->cpum.GstCtx.ip + cbInstr + offNextInstr;
2655 if (RT_LIKELY(uNewIp <= pVCpu->cpum.GstCtx.cs.u32Limit))
2656 pVCpu->cpum.GstCtx.rip = uNewIp;
2657 else
2658 return iemRaiseGeneralProtectionFault0(pVCpu);
2659
2660#ifndef IEM_WITH_CODE_TLB
2661 iemOpcodeFlushLight(pVCpu, cbInstr);
2662#endif
2663 return iemRegFinishNoFlags(pVCpu, rcNormal);
2664}
2665
2666
2667/**
2668 * Adds a 32-bit signed jump offset to RIP from 64-bit code.
2669 *
2670 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2671 * segment limit.
2672 *
2673 * We ASSUME that the effective operand size is 64-bit here, as 16-bit is the
2674 * only alternative for relative jumps in 64-bit code and that is already
2675 * handled in the decoder stage.
2676 *
2677 * @returns Strict VBox status code.
2678 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2679 * @param cbInstr Instruction size.
2680 * @param offNextInstr The offset of the next instruction.
2681 * @param rcNormal VINF_SUCCESS to continue TB.
2682 * VINF_IEM_REEXEC_BREAK to force TB exit when
2683 * taking the wrong conditional branhc.
2684 */
2685DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegRip64RelativeJumpS32AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr,
2686 int32_t offNextInstr, int rcNormal) RT_NOEXCEPT
2687{
2688 Assert(IEM_IS_64BIT_CODE(pVCpu));
2689
2690 uint64_t const uNewRip = pVCpu->cpum.GstCtx.rip + cbInstr + (int64_t)offNextInstr;
2691 if (RT_LIKELY(IEM_IS_CANONICAL(uNewRip)))
2692 pVCpu->cpum.GstCtx.rip = uNewRip;
2693 else
2694 return iemRaiseGeneralProtectionFault0(pVCpu);
2695
2696#ifndef IEM_WITH_CODE_TLB
2697 iemOpcodeFlushLight(pVCpu, cbInstr);
2698#endif
2699
2700 /*
2701 * Clear RF and finish the instruction (maybe raise #DB).
2702 */
2703 return iemRegFinishClearingRF(pVCpu, rcNormal);
2704}
2705
2706
2707/**
2708 * Adds a 32-bit signed jump offset to RIP from 64-bit code.
2709 *
2710 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2711 * segment limit.
2712 *
2713 * We ASSUME that the effective operand size is 32-bit here, as 16-bit is the
2714 * only alternative for relative jumps in 32-bit code and that is already
2715 * handled in the decoder stage.
2716 *
2717 * @returns Strict VBox status code.
2718 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2719 * @param cbInstr Instruction size.
2720 * @param offNextInstr The offset of the next instruction.
2721 * @param rcNormal VINF_SUCCESS to continue TB.
2722 * VINF_IEM_REEXEC_BREAK to force TB exit when
2723 * taking the wrong conditional branhc.
2724 */
2725DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegEip32RelativeJumpS32AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr,
2726 int32_t offNextInstr, int rcNormal) RT_NOEXCEPT
2727{
2728 Assert(!IEM_IS_64BIT_CODE(pVCpu));
2729 Assert(pVCpu->cpum.GstCtx.rip <= UINT32_MAX);
2730
2731 uint32_t const uNewEip = pVCpu->cpum.GstCtx.eip + cbInstr + offNextInstr;
2732 if (RT_LIKELY(uNewEip <= pVCpu->cpum.GstCtx.cs.u32Limit))
2733 pVCpu->cpum.GstCtx.rip = uNewEip;
2734 else
2735 return iemRaiseGeneralProtectionFault0(pVCpu);
2736
2737#ifndef IEM_WITH_CODE_TLB
2738 iemOpcodeFlushLight(pVCpu, cbInstr);
2739#endif
2740
2741 /*
2742 * Clear RF and finish the instruction (maybe raise #DB).
2743 */
2744 return iemRegFinishClearingRF(pVCpu, rcNormal);
2745}
2746
2747
2748/**
2749 * Adds a 32-bit signed jump offset to RIP from 64-bit code, no checking or
2750 * clearing of flags.
2751 *
2752 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2753 * segment limit.
2754 *
2755 * We ASSUME that the effective operand size is 64-bit here, as 16-bit is the
2756 * only alternative for relative jumps in 64-bit code and that is already
2757 * handled in the decoder stage.
2758 *
2759 * @returns Strict VBox status code.
2760 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2761 * @param cbInstr Instruction size.
2762 * @param offNextInstr The offset of the next instruction.
2763 * @param rcNormal VINF_SUCCESS to continue TB.
2764 * VINF_IEM_REEXEC_BREAK to force TB exit when
2765 * taking the wrong conditional branhc.
2766 */
2767DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegRip64RelativeJumpS32AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr,
2768 int32_t offNextInstr, int rcNormal) RT_NOEXCEPT
2769{
2770 Assert(IEM_IS_64BIT_CODE(pVCpu));
2771
2772 uint64_t const uNewRip = pVCpu->cpum.GstCtx.rip + cbInstr + (int64_t)offNextInstr;
2773 if (RT_LIKELY(IEM_IS_CANONICAL(uNewRip)))
2774 pVCpu->cpum.GstCtx.rip = uNewRip;
2775 else
2776 return iemRaiseGeneralProtectionFault0(pVCpu);
2777
2778#ifndef IEM_WITH_CODE_TLB
2779 iemOpcodeFlushLight(pVCpu, cbInstr);
2780#endif
2781 return iemRegFinishNoFlags(pVCpu, rcNormal);
2782}
2783
2784
2785/**
2786 * Adds a 32-bit signed jump offset to RIP from 64-bit code, no checking or
2787 * clearing of flags.
2788 *
2789 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2790 * segment limit.
2791 *
2792 * We ASSUME that the effective operand size is 32-bit here, as 16-bit is the
2793 * only alternative for relative jumps in 32-bit code and that is already
2794 * handled in the decoder stage.
2795 *
2796 * @returns Strict VBox status code.
2797 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2798 * @param cbInstr Instruction size.
2799 * @param offNextInstr The offset of the next instruction.
2800 * @param rcNormal VINF_SUCCESS to continue TB.
2801 * VINF_IEM_REEXEC_BREAK to force TB exit when
2802 * taking the wrong conditional branhc.
2803 */
2804DECL_FORCE_INLINE(VBOXSTRICTRC) iemRegEip32RelativeJumpS32AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr,
2805 int32_t offNextInstr, int rcNormal) RT_NOEXCEPT
2806{
2807 Assert(!IEM_IS_64BIT_CODE(pVCpu));
2808 Assert(pVCpu->cpum.GstCtx.rip <= UINT32_MAX);
2809
2810 uint32_t const uNewEip = pVCpu->cpum.GstCtx.eip + cbInstr + offNextInstr;
2811 if (RT_LIKELY(uNewEip <= pVCpu->cpum.GstCtx.cs.u32Limit))
2812 pVCpu->cpum.GstCtx.rip = uNewEip;
2813 else
2814 return iemRaiseGeneralProtectionFault0(pVCpu);
2815
2816#ifndef IEM_WITH_CODE_TLB
2817 iemOpcodeFlushLight(pVCpu, cbInstr);
2818#endif
2819 return iemRegFinishNoFlags(pVCpu, rcNormal);
2820}
2821
2822
2823/**
2824 * Extended version of iemFinishInstructionWithFlagsSet that goes with
2825 * iemRegAddToRipAndFinishingClearingRfEx.
2826 *
2827 * See iemFinishInstructionWithFlagsSet() for details.
2828 */
2829static VBOXSTRICTRC iemFinishInstructionWithTfSet(PVMCPUCC pVCpu) RT_NOEXCEPT
2830{
2831 /*
2832 * Raise a #DB.
2833 */
2834 IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_DR6);
2835 pVCpu->cpum.GstCtx.dr[6] &= ~X86_DR6_B_MASK;
2836 pVCpu->cpum.GstCtx.dr[6] |= X86_DR6_BS
2837 | ( (pVCpu->cpum.GstCtx.eflags.uBoth & CPUMCTX_DBG_HIT_DRX_MASK_NONSILENT)
2838 >> CPUMCTX_DBG_HIT_DRX_SHIFT);
2839 /** @todo Do we set all pending \#DB events, or just one? */
2840 LogFlowFunc(("Guest #DB fired at %04X:%016llX: DR6=%08X, RFLAGS=%16RX64 (popf)\n",
2841 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, (unsigned)pVCpu->cpum.GstCtx.dr[6],
2842 pVCpu->cpum.GstCtx.rflags.uBoth));
2843 pVCpu->cpum.GstCtx.eflags.uBoth &= ~(X86_EFL_RF | CPUMCTX_INHIBIT_SHADOW | CPUMCTX_DBG_HIT_DRX_MASK | CPUMCTX_DBG_DBGF_MASK);
2844 return iemRaiseDebugException(pVCpu);
2845}
2846
2847
2848/**
2849 * Extended version of iemRegAddToRipAndFinishingClearingRF for use by POPF and
2850 * others potentially updating EFLAGS.TF.
2851 *
2852 * The single step event must be generated using the TF value at the start of
2853 * the instruction, not the new value set by it.
2854 *
2855 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2856 * @param cbInstr The number of bytes to add.
2857 * @param fEflOld The EFLAGS at the start of the instruction
2858 * execution.
2859 */
2860DECLINLINE(VBOXSTRICTRC) iemRegAddToRipAndFinishingClearingRfEx(PVMCPUCC pVCpu, uint8_t cbInstr, uint32_t fEflOld) RT_NOEXCEPT
2861{
2862 iemRegAddToRip(pVCpu, cbInstr);
2863 if (!(fEflOld & X86_EFL_TF))
2864 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
2865 return iemFinishInstructionWithTfSet(pVCpu);
2866}
2867
2868
2869#ifndef IEM_WITH_OPAQUE_DECODER_STATE
2870/**
2871 * Updates the RIP/EIP/IP to point to the next instruction and clears EFLAGS.RF.
2872 *
2873 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2874 */
2875DECLINLINE(VBOXSTRICTRC) iemRegUpdateRipAndFinishClearingRF(PVMCPUCC pVCpu) RT_NOEXCEPT
2876{
2877 return iemRegAddToRipAndFinishingClearingRF(pVCpu, IEM_GET_INSTR_LEN(pVCpu));
2878}
2879#endif
2880
2881
2882#ifdef IEM_WITH_CODE_TLB
2883
2884/**
2885 * Performs a near jump to the specified address, no checking or clearing of
2886 * flags
2887 *
2888 * May raise a \#GP(0) if the new IP outside the code segment limit.
2889 *
2890 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2891 * @param uNewIp The new IP value.
2892 */
2893DECLINLINE(VBOXSTRICTRC) iemRegRipJumpU16AndFinishNoFlags(PVMCPUCC pVCpu, uint16_t uNewIp) RT_NOEXCEPT
2894{
2895 if (RT_LIKELY( uNewIp <= pVCpu->cpum.GstCtx.cs.u32Limit
2896 || IEM_IS_64BIT_CODE(pVCpu) /* no limit checks in 64-bit mode */))
2897 pVCpu->cpum.GstCtx.rip = uNewIp;
2898 else
2899 return iemRaiseGeneralProtectionFault0(pVCpu);
2900 return iemRegFinishNoFlags(pVCpu, VINF_SUCCESS);
2901}
2902
2903
2904/**
2905 * Performs a near jump to the specified address, no checking or clearing of
2906 * flags
2907 *
2908 * May raise a \#GP(0) if the new RIP is outside the code segment limit.
2909 *
2910 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2911 * @param uNewEip The new EIP value.
2912 */
2913DECLINLINE(VBOXSTRICTRC) iemRegRipJumpU32AndFinishNoFlags(PVMCPUCC pVCpu, uint32_t uNewEip) RT_NOEXCEPT
2914{
2915 Assert(pVCpu->cpum.GstCtx.rip <= UINT32_MAX);
2916 Assert(!IEM_IS_64BIT_CODE(pVCpu));
2917 if (RT_LIKELY(uNewEip <= pVCpu->cpum.GstCtx.cs.u32Limit))
2918 pVCpu->cpum.GstCtx.rip = uNewEip;
2919 else
2920 return iemRaiseGeneralProtectionFault0(pVCpu);
2921 return iemRegFinishNoFlags(pVCpu, VINF_SUCCESS);
2922}
2923
2924
2925/**
2926 * Performs a near jump to the specified address, no checking or clearing of
2927 * flags.
2928 *
2929 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
2930 * segment limit.
2931 *
2932 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2933 * @param uNewRip The new RIP value.
2934 */
2935DECLINLINE(VBOXSTRICTRC) iemRegRipJumpU64AndFinishNoFlags(PVMCPUCC pVCpu, uint64_t uNewRip) RT_NOEXCEPT
2936{
2937 Assert(IEM_IS_64BIT_CODE(pVCpu));
2938 if (RT_LIKELY(IEM_IS_CANONICAL(uNewRip)))
2939 pVCpu->cpum.GstCtx.rip = uNewRip;
2940 else
2941 return iemRaiseGeneralProtectionFault0(pVCpu);
2942 return iemRegFinishNoFlags(pVCpu, VINF_SUCCESS);
2943}
2944
2945#endif /* IEM_WITH_CODE_TLB */
2946
2947/**
2948 * Performs a near jump to the specified address.
2949 *
2950 * May raise a \#GP(0) if the new IP outside the code segment limit.
2951 *
2952 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2953 * @param uNewIp The new IP value.
2954 * @param cbInstr The instruction length, for flushing in the non-TLB case.
2955 */
2956DECLINLINE(VBOXSTRICTRC) iemRegRipJumpU16AndFinishClearingRF(PVMCPUCC pVCpu, uint16_t uNewIp, uint8_t cbInstr) RT_NOEXCEPT
2957{
2958 if (RT_LIKELY( uNewIp <= pVCpu->cpum.GstCtx.cs.u32Limit
2959 || IEM_IS_64BIT_CODE(pVCpu) /* no limit checks in 64-bit mode */))
2960 pVCpu->cpum.GstCtx.rip = uNewIp;
2961 else
2962 return iemRaiseGeneralProtectionFault0(pVCpu);
2963#ifndef IEM_WITH_CODE_TLB
2964 iemOpcodeFlushLight(pVCpu, cbInstr);
2965#else
2966 RT_NOREF_PV(cbInstr);
2967#endif
2968 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
2969}
2970
2971
2972/**
2973 * Performs a near jump to the specified address.
2974 *
2975 * May raise a \#GP(0) if the new RIP is outside the code segment limit.
2976 *
2977 * @param pVCpu The cross context virtual CPU structure of the calling thread.
2978 * @param uNewEip The new EIP value.
2979 * @param cbInstr The instruction length, for flushing in the non-TLB case.
2980 */
2981DECLINLINE(VBOXSTRICTRC) iemRegRipJumpU32AndFinishClearingRF(PVMCPUCC pVCpu, uint32_t uNewEip, uint8_t cbInstr) RT_NOEXCEPT
2982{
2983 Assert(pVCpu->cpum.GstCtx.rip <= UINT32_MAX);
2984 Assert(!IEM_IS_64BIT_CODE(pVCpu));
2985 if (RT_LIKELY(uNewEip <= pVCpu->cpum.GstCtx.cs.u32Limit))
2986 pVCpu->cpum.GstCtx.rip = uNewEip;
2987 else
2988 return iemRaiseGeneralProtectionFault0(pVCpu);
2989#ifndef IEM_WITH_CODE_TLB
2990 iemOpcodeFlushLight(pVCpu, cbInstr);
2991#else
2992 RT_NOREF_PV(cbInstr);
2993#endif
2994 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
2995}
2996
2997
2998/**
2999 * Performs a near jump to the specified address.
3000 *
3001 * May raise a \#GP(0) if the new RIP is non-canonical or outside the code
3002 * segment limit.
3003 *
3004 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3005 * @param uNewRip The new RIP value.
3006 * @param cbInstr The instruction length, for flushing in the non-TLB case.
3007 */
3008DECLINLINE(VBOXSTRICTRC) iemRegRipJumpU64AndFinishClearingRF(PVMCPUCC pVCpu, uint64_t uNewRip, uint8_t cbInstr) RT_NOEXCEPT
3009{
3010 Assert(IEM_IS_64BIT_CODE(pVCpu));
3011 if (RT_LIKELY(IEM_IS_CANONICAL(uNewRip)))
3012 pVCpu->cpum.GstCtx.rip = uNewRip;
3013 else
3014 return iemRaiseGeneralProtectionFault0(pVCpu);
3015#ifndef IEM_WITH_CODE_TLB
3016 iemOpcodeFlushLight(pVCpu, cbInstr);
3017#else
3018 RT_NOREF_PV(cbInstr);
3019#endif
3020 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
3021}
3022
3023
3024/**
3025 * Implements a 16-bit relative call, no checking or clearing of
3026 * flags.
3027 *
3028 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3029 * @param cbInstr The instruction length.
3030 * @param offDisp The 16-bit displacement.
3031 */
3032DECL_FORCE_INLINE(VBOXSTRICTRC)
3033iemRegRipRelativeCallS16AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, int16_t offDisp) RT_NOEXCEPT
3034{
3035 uint16_t const uOldIp = pVCpu->cpum.GstCtx.ip + cbInstr;
3036 uint16_t const uNewIp = uOldIp + offDisp;
3037 if ( uNewIp <= pVCpu->cpum.GstCtx.cs.u32Limit
3038 || IEM_IS_64BIT_CODE(pVCpu) /* no CS limit checks in 64-bit mode */)
3039 { /* likely */ }
3040 else
3041 return iemRaiseGeneralProtectionFault0(pVCpu);
3042
3043 VBOXSTRICTRC rcStrict = iemMemStackPushU16(pVCpu, uOldIp);
3044 if (rcStrict == VINF_SUCCESS)
3045 { /* likely */ }
3046 else
3047 return rcStrict;
3048
3049 pVCpu->cpum.GstCtx.rip = uNewIp;
3050#ifndef IEM_WITH_CODE_TLB
3051 iemOpcodeFlushLight(pVCpu, cbInstr);
3052#endif
3053 return iemRegFinishNoFlags(pVCpu, VINF_SUCCESS);
3054}
3055
3056
3057/**
3058 * Implements a 16-bit relative call.
3059 *
3060 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3061 * @param cbInstr The instruction length.
3062 * @param offDisp The 16-bit displacement.
3063 */
3064DECL_FORCE_INLINE(VBOXSTRICTRC)
3065iemRegRipRelativeCallS16AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, int16_t offDisp) RT_NOEXCEPT
3066{
3067 uint16_t const uOldIp = pVCpu->cpum.GstCtx.ip + cbInstr;
3068 uint16_t const uNewIp = uOldIp + offDisp;
3069 if ( uNewIp <= pVCpu->cpum.GstCtx.cs.u32Limit
3070 || IEM_IS_64BIT_CODE(pVCpu) /* no CS limit checks in 64-bit mode */)
3071 { /* likely */ }
3072 else
3073 return iemRaiseGeneralProtectionFault0(pVCpu);
3074
3075 VBOXSTRICTRC rcStrict = iemMemStackPushU16(pVCpu, uOldIp);
3076 if (rcStrict == VINF_SUCCESS)
3077 { /* likely */ }
3078 else
3079 return rcStrict;
3080
3081 pVCpu->cpum.GstCtx.rip = uNewIp;
3082#ifndef IEM_WITH_CODE_TLB
3083 iemOpcodeFlushLight(pVCpu, cbInstr);
3084#endif
3085 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
3086}
3087
3088
3089/**
3090 * Implements a 32-bit relative call, no checking or clearing of flags.
3091 *
3092 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3093 * @param cbInstr The instruction length.
3094 * @param offDisp The 32-bit displacement.
3095 */
3096DECL_FORCE_INLINE(VBOXSTRICTRC)
3097iemRegEip32RelativeCallS32AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, int32_t offDisp) RT_NOEXCEPT
3098{
3099 Assert(pVCpu->cpum.GstCtx.rip <= UINT32_MAX); Assert(!IEM_IS_64BIT_CODE(pVCpu));
3100
3101 uint32_t const uOldRip = pVCpu->cpum.GstCtx.eip + cbInstr;
3102 uint32_t const uNewRip = uOldRip + offDisp;
3103 if (uNewRip <= pVCpu->cpum.GstCtx.cs.u32Limit)
3104 { /* likely */ }
3105 else
3106 return iemRaiseGeneralProtectionFault0(pVCpu);
3107
3108 VBOXSTRICTRC rcStrict = iemMemStackPushU32(pVCpu, uOldRip);
3109 if (rcStrict == VINF_SUCCESS)
3110 { /* likely */ }
3111 else
3112 return rcStrict;
3113
3114 pVCpu->cpum.GstCtx.rip = uNewRip;
3115#ifndef IEM_WITH_CODE_TLB
3116 iemOpcodeFlushLight(pVCpu, cbInstr);
3117#endif
3118 return iemRegFinishNoFlags(pVCpu, VINF_SUCCESS);
3119}
3120
3121
3122/**
3123 * Implements a 32-bit relative call.
3124 *
3125 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3126 * @param cbInstr The instruction length.
3127 * @param offDisp The 32-bit displacement.
3128 */
3129DECL_FORCE_INLINE(VBOXSTRICTRC)
3130iemRegEip32RelativeCallS32AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, int32_t offDisp) RT_NOEXCEPT
3131{
3132 Assert(pVCpu->cpum.GstCtx.rip <= UINT32_MAX); Assert(!IEM_IS_64BIT_CODE(pVCpu));
3133
3134 uint32_t const uOldRip = pVCpu->cpum.GstCtx.eip + cbInstr;
3135 uint32_t const uNewRip = uOldRip + offDisp;
3136 if (uNewRip <= pVCpu->cpum.GstCtx.cs.u32Limit)
3137 { /* likely */ }
3138 else
3139 return iemRaiseGeneralProtectionFault0(pVCpu);
3140
3141 VBOXSTRICTRC rcStrict = iemMemStackPushU32(pVCpu, uOldRip);
3142 if (rcStrict == VINF_SUCCESS)
3143 { /* likely */ }
3144 else
3145 return rcStrict;
3146
3147 pVCpu->cpum.GstCtx.rip = uNewRip;
3148#ifndef IEM_WITH_CODE_TLB
3149 iemOpcodeFlushLight(pVCpu, cbInstr);
3150#endif
3151 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
3152}
3153
3154
3155/**
3156 * Implements a 64-bit relative call, no checking or clearing of flags.
3157 *
3158 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3159 * @param cbInstr The instruction length.
3160 * @param offDisp The 64-bit displacement.
3161 */
3162DECL_FORCE_INLINE(VBOXSTRICTRC)
3163iemRegRip64RelativeCallS64AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, int64_t offDisp) RT_NOEXCEPT
3164{
3165 uint64_t const uOldRip = pVCpu->cpum.GstCtx.rip + cbInstr;
3166 uint64_t const uNewRip = uOldRip + (int64_t)offDisp;
3167 if (IEM_IS_CANONICAL(uNewRip))
3168 { /* likely */ }
3169 else
3170 return iemRaiseNotCanonical(pVCpu);
3171
3172 VBOXSTRICTRC rcStrict = iemMemStackPushU64(pVCpu, uOldRip);
3173 if (rcStrict == VINF_SUCCESS)
3174 { /* likely */ }
3175 else
3176 return rcStrict;
3177
3178 pVCpu->cpum.GstCtx.rip = uNewRip;
3179#ifndef IEM_WITH_CODE_TLB
3180 iemOpcodeFlushLight(pVCpu, cbInstr);
3181#endif
3182 return iemRegFinishNoFlags(pVCpu, VINF_SUCCESS);
3183}
3184
3185
3186/**
3187 * Implements a 64-bit relative call.
3188 *
3189 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3190 * @param cbInstr The instruction length.
3191 * @param offDisp The 64-bit displacement.
3192 */
3193DECL_FORCE_INLINE(VBOXSTRICTRC)
3194iemRegRip64RelativeCallS64AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, int64_t offDisp) RT_NOEXCEPT
3195{
3196 uint64_t const uOldRip = pVCpu->cpum.GstCtx.rip + cbInstr;
3197 uint64_t const uNewRip = uOldRip + (int64_t)offDisp;
3198 if (IEM_IS_CANONICAL(uNewRip))
3199 { /* likely */ }
3200 else
3201 return iemRaiseNotCanonical(pVCpu);
3202
3203 VBOXSTRICTRC rcStrict = iemMemStackPushU64(pVCpu, uOldRip);
3204 if (rcStrict == VINF_SUCCESS)
3205 { /* likely */ }
3206 else
3207 return rcStrict;
3208
3209 pVCpu->cpum.GstCtx.rip = uNewRip;
3210#ifndef IEM_WITH_CODE_TLB
3211 iemOpcodeFlushLight(pVCpu, cbInstr);
3212#endif
3213 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
3214}
3215
3216
3217/**
3218 * Implements an 16-bit indirect call, no checking or clearing of
3219 * flags.
3220 *
3221 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3222 * @param cbInstr The instruction length.
3223 * @param uNewRip The new RIP value.
3224 */
3225DECL_FORCE_INLINE(VBOXSTRICTRC)
3226iemRegIp16IndirectCallU16AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t uNewRip) RT_NOEXCEPT
3227{
3228 uint16_t const uOldRip = pVCpu->cpum.GstCtx.ip + cbInstr;
3229 if (uNewRip <= pVCpu->cpum.GstCtx.cs.u32Limit)
3230 { /* likely */ }
3231 else
3232 return iemRaiseGeneralProtectionFault0(pVCpu);
3233
3234 VBOXSTRICTRC rcStrict = iemMemStackPushU16(pVCpu, uOldRip);
3235 if (rcStrict == VINF_SUCCESS)
3236 { /* likely */ }
3237 else
3238 return rcStrict;
3239
3240 pVCpu->cpum.GstCtx.rip = uNewRip;
3241#ifndef IEM_WITH_CODE_TLB
3242 iemOpcodeFlushLight(pVCpu, cbInstr);
3243#endif
3244 return iemRegFinishNoFlags(pVCpu, VINF_SUCCESS);
3245}
3246
3247
3248/**
3249 * Implements an 16-bit indirect call, no checking or clearing of
3250 * flags.
3251 *
3252 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3253 * @param cbInstr The instruction length.
3254 * @param uNewRip The new RIP value.
3255 */
3256DECL_FORCE_INLINE(VBOXSTRICTRC)
3257iemRegEip32IndirectCallU16AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t uNewRip) RT_NOEXCEPT
3258{
3259 uint16_t const uOldRip = pVCpu->cpum.GstCtx.ip + cbInstr;
3260 if (uNewRip <= pVCpu->cpum.GstCtx.cs.u32Limit)
3261 { /* likely */ }
3262 else
3263 return iemRaiseGeneralProtectionFault0(pVCpu);
3264
3265 VBOXSTRICTRC rcStrict = iemMemStackPushU16(pVCpu, uOldRip);
3266 if (rcStrict == VINF_SUCCESS)
3267 { /* likely */ }
3268 else
3269 return rcStrict;
3270
3271 pVCpu->cpum.GstCtx.rip = uNewRip;
3272#ifndef IEM_WITH_CODE_TLB
3273 iemOpcodeFlushLight(pVCpu, cbInstr);
3274#endif
3275 return iemRegFinishNoFlags(pVCpu, VINF_SUCCESS);
3276}
3277
3278
3279/**
3280 * Implements an 16-bit indirect call.
3281 *
3282 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3283 * @param cbInstr The instruction length.
3284 * @param uNewRip The new RIP value.
3285 */
3286DECL_FORCE_INLINE(VBOXSTRICTRC)
3287iemRegIp16IndirectCallU16AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t uNewRip) RT_NOEXCEPT
3288{
3289 uint16_t const uOldRip = pVCpu->cpum.GstCtx.ip + cbInstr;
3290 if (uNewRip <= pVCpu->cpum.GstCtx.cs.u32Limit)
3291 { /* likely */ }
3292 else
3293 return iemRaiseGeneralProtectionFault0(pVCpu);
3294
3295 VBOXSTRICTRC rcStrict = iemMemStackPushU16(pVCpu, uOldRip);
3296 if (rcStrict == VINF_SUCCESS)
3297 { /* likely */ }
3298 else
3299 return rcStrict;
3300
3301 pVCpu->cpum.GstCtx.rip = uNewRip;
3302#ifndef IEM_WITH_CODE_TLB
3303 iemOpcodeFlushLight(pVCpu, cbInstr);
3304#endif
3305 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
3306}
3307
3308
3309/**
3310 * Implements an 16-bit indirect call.
3311 *
3312 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3313 * @param cbInstr The instruction length.
3314 * @param uNewRip The new RIP value.
3315 */
3316DECL_FORCE_INLINE(VBOXSTRICTRC)
3317iemRegEip32IndirectCallU16AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t uNewRip) RT_NOEXCEPT
3318{
3319 uint16_t const uOldRip = pVCpu->cpum.GstCtx.ip + cbInstr;
3320 if (uNewRip <= pVCpu->cpum.GstCtx.cs.u32Limit)
3321 { /* likely */ }
3322 else
3323 return iemRaiseGeneralProtectionFault0(pVCpu);
3324
3325 VBOXSTRICTRC rcStrict = iemMemStackPushU16(pVCpu, uOldRip);
3326 if (rcStrict == VINF_SUCCESS)
3327 { /* likely */ }
3328 else
3329 return rcStrict;
3330
3331 pVCpu->cpum.GstCtx.rip = uNewRip;
3332#ifndef IEM_WITH_CODE_TLB
3333 iemOpcodeFlushLight(pVCpu, cbInstr);
3334#endif
3335 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
3336}
3337
3338
3339/**
3340 * Implements an 32-bit indirect call, no checking or clearing of
3341 * flags.
3342 *
3343 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3344 * @param cbInstr The instruction length.
3345 * @param uNewRip The new RIP value.
3346 */
3347DECL_FORCE_INLINE(VBOXSTRICTRC)
3348iemRegEip32IndirectCallU32AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, uint32_t uNewRip) RT_NOEXCEPT
3349{
3350 uint32_t const uOldRip = pVCpu->cpum.GstCtx.eip + cbInstr;
3351 if (uNewRip <= pVCpu->cpum.GstCtx.cs.u32Limit)
3352 { /* likely */ }
3353 else
3354 return iemRaiseGeneralProtectionFault0(pVCpu);
3355
3356 VBOXSTRICTRC rcStrict = iemMemStackPushU32(pVCpu, uOldRip);
3357 if (rcStrict == VINF_SUCCESS)
3358 { /* likely */ }
3359 else
3360 return rcStrict;
3361
3362 pVCpu->cpum.GstCtx.rip = uNewRip;
3363#ifndef IEM_WITH_CODE_TLB
3364 iemOpcodeFlushLight(pVCpu, cbInstr);
3365#endif
3366 return iemRegFinishNoFlags(pVCpu, VINF_SUCCESS);
3367}
3368
3369
3370/**
3371 * Implements an 32-bit indirect call.
3372 *
3373 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3374 * @param cbInstr The instruction length.
3375 * @param uNewRip The new RIP value.
3376 */
3377DECL_FORCE_INLINE(VBOXSTRICTRC)
3378iemRegEip32IndirectCallU32AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, uint32_t uNewRip) RT_NOEXCEPT
3379{
3380 uint32_t const uOldRip = pVCpu->cpum.GstCtx.eip + cbInstr;
3381 if (uNewRip <= pVCpu->cpum.GstCtx.cs.u32Limit)
3382 { /* likely */ }
3383 else
3384 return iemRaiseGeneralProtectionFault0(pVCpu);
3385
3386 VBOXSTRICTRC rcStrict = iemMemStackPushU32(pVCpu, uOldRip);
3387 if (rcStrict == VINF_SUCCESS)
3388 { /* likely */ }
3389 else
3390 return rcStrict;
3391
3392 pVCpu->cpum.GstCtx.rip = uNewRip;
3393#ifndef IEM_WITH_CODE_TLB
3394 iemOpcodeFlushLight(pVCpu, cbInstr);
3395#endif
3396 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
3397}
3398
3399
3400/**
3401 * Implements an 64-bit indirect call, no checking or clearing of
3402 * flags.
3403 *
3404 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3405 * @param cbInstr The instruction length.
3406 * @param uNewRip The new RIP value.
3407 */
3408DECL_FORCE_INLINE(VBOXSTRICTRC)
3409iemRegRip64IndirectCallU64AndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, uint64_t uNewRip) RT_NOEXCEPT
3410{
3411 uint64_t const uOldRip = pVCpu->cpum.GstCtx.rip + cbInstr;
3412 if (IEM_IS_CANONICAL(uNewRip))
3413 { /* likely */ }
3414 else
3415 return iemRaiseGeneralProtectionFault0(pVCpu);
3416
3417 VBOXSTRICTRC rcStrict = iemMemStackPushU64(pVCpu, uOldRip);
3418 if (rcStrict == VINF_SUCCESS)
3419 { /* likely */ }
3420 else
3421 return rcStrict;
3422
3423 pVCpu->cpum.GstCtx.rip = uNewRip;
3424#ifndef IEM_WITH_CODE_TLB
3425 iemOpcodeFlushLight(pVCpu, cbInstr);
3426#endif
3427 return iemRegFinishNoFlags(pVCpu, VINF_SUCCESS);
3428}
3429
3430
3431/**
3432 * Implements an 64-bit indirect call.
3433 *
3434 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3435 * @param cbInstr The instruction length.
3436 * @param uNewRip The new RIP value.
3437 */
3438DECL_FORCE_INLINE(VBOXSTRICTRC)
3439iemRegRip64IndirectCallU64AndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, uint64_t uNewRip) RT_NOEXCEPT
3440{
3441 uint64_t const uOldRip = pVCpu->cpum.GstCtx.rip + cbInstr;
3442 if (IEM_IS_CANONICAL(uNewRip))
3443 { /* likely */ }
3444 else
3445 return iemRaiseGeneralProtectionFault0(pVCpu);
3446
3447 VBOXSTRICTRC rcStrict = iemMemStackPushU64(pVCpu, uOldRip);
3448 if (rcStrict == VINF_SUCCESS)
3449 { /* likely */ }
3450 else
3451 return rcStrict;
3452
3453 pVCpu->cpum.GstCtx.rip = uNewRip;
3454#ifndef IEM_WITH_CODE_TLB
3455 iemOpcodeFlushLight(pVCpu, cbInstr);
3456#endif
3457 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
3458}
3459
3460
3461
3462/**
3463 * Adds to the stack pointer.
3464 *
3465 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3466 * @param cbToAdd The number of bytes to add (8-bit!).
3467 */
3468DECLINLINE(void) iemRegAddToRsp(PVMCPUCC pVCpu, uint8_t cbToAdd) RT_NOEXCEPT
3469{
3470 if (IEM_IS_64BIT_CODE(pVCpu))
3471 pVCpu->cpum.GstCtx.rsp += cbToAdd;
3472 else if (pVCpu->cpum.GstCtx.ss.Attr.n.u1DefBig)
3473 pVCpu->cpum.GstCtx.esp += cbToAdd;
3474 else
3475 pVCpu->cpum.GstCtx.sp += cbToAdd;
3476}
3477
3478
3479/**
3480 * Subtracts from the stack pointer.
3481 *
3482 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3483 * @param cbToSub The number of bytes to subtract (8-bit!).
3484 */
3485DECLINLINE(void) iemRegSubFromRsp(PVMCPUCC pVCpu, uint8_t cbToSub) RT_NOEXCEPT
3486{
3487 if (IEM_IS_64BIT_CODE(pVCpu))
3488 pVCpu->cpum.GstCtx.rsp -= cbToSub;
3489 else if (pVCpu->cpum.GstCtx.ss.Attr.n.u1DefBig)
3490 pVCpu->cpum.GstCtx.esp -= cbToSub;
3491 else
3492 pVCpu->cpum.GstCtx.sp -= cbToSub;
3493}
3494
3495
3496/**
3497 * Adds to the temporary stack pointer.
3498 *
3499 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3500 * @param pTmpRsp The temporary SP/ESP/RSP to update.
3501 * @param cbToAdd The number of bytes to add (16-bit).
3502 */
3503DECLINLINE(void) iemRegAddToRspEx(PCVMCPU pVCpu, PRTUINT64U pTmpRsp, uint16_t cbToAdd) RT_NOEXCEPT
3504{
3505 if (IEM_IS_64BIT_CODE(pVCpu))
3506 pTmpRsp->u += cbToAdd;
3507 else if (pVCpu->cpum.GstCtx.ss.Attr.n.u1DefBig)
3508 pTmpRsp->DWords.dw0 += cbToAdd;
3509 else
3510 pTmpRsp->Words.w0 += cbToAdd;
3511}
3512
3513
3514/**
3515 * Subtracts from the temporary stack pointer.
3516 *
3517 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3518 * @param pTmpRsp The temporary SP/ESP/RSP to update.
3519 * @param cbToSub The number of bytes to subtract.
3520 * @remarks The @a cbToSub argument *MUST* be 16-bit, iemCImpl_enter is
3521 * expecting that.
3522 */
3523DECLINLINE(void) iemRegSubFromRspEx(PCVMCPU pVCpu, PRTUINT64U pTmpRsp, uint16_t cbToSub) RT_NOEXCEPT
3524{
3525 if (IEM_IS_64BIT_CODE(pVCpu))
3526 pTmpRsp->u -= cbToSub;
3527 else if (pVCpu->cpum.GstCtx.ss.Attr.n.u1DefBig)
3528 pTmpRsp->DWords.dw0 -= cbToSub;
3529 else
3530 pTmpRsp->Words.w0 -= cbToSub;
3531}
3532
3533
3534/**
3535 * Calculates the effective stack address for a push of the specified size as
3536 * well as the new RSP value (upper bits may be masked).
3537 *
3538 * @returns Effective stack addressf for the push.
3539 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3540 * @param cbItem The size of the stack item to pop.
3541 * @param puNewRsp Where to return the new RSP value.
3542 */
3543DECLINLINE(RTGCPTR) iemRegGetRspForPush(PCVMCPU pVCpu, uint8_t cbItem, uint64_t *puNewRsp) RT_NOEXCEPT
3544{
3545 RTUINT64U uTmpRsp;
3546 RTGCPTR GCPtrTop;
3547 uTmpRsp.u = pVCpu->cpum.GstCtx.rsp;
3548
3549 if (IEM_IS_64BIT_CODE(pVCpu))
3550 GCPtrTop = uTmpRsp.u -= cbItem;
3551 else if (pVCpu->cpum.GstCtx.ss.Attr.n.u1DefBig)
3552 GCPtrTop = uTmpRsp.DWords.dw0 -= cbItem;
3553 else
3554 GCPtrTop = uTmpRsp.Words.w0 -= cbItem;
3555 *puNewRsp = uTmpRsp.u;
3556 return GCPtrTop;
3557}
3558
3559
3560/**
3561 * Gets the current stack pointer and calculates the value after a pop of the
3562 * specified size.
3563 *
3564 * @returns Current stack pointer.
3565 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3566 * @param cbItem The size of the stack item to pop.
3567 * @param puNewRsp Where to return the new RSP value.
3568 */
3569DECLINLINE(RTGCPTR) iemRegGetRspForPop(PCVMCPU pVCpu, uint8_t cbItem, uint64_t *puNewRsp) RT_NOEXCEPT
3570{
3571 RTUINT64U uTmpRsp;
3572 RTGCPTR GCPtrTop;
3573 uTmpRsp.u = pVCpu->cpum.GstCtx.rsp;
3574
3575 if (IEM_IS_64BIT_CODE(pVCpu))
3576 {
3577 GCPtrTop = uTmpRsp.u;
3578 uTmpRsp.u += cbItem;
3579 }
3580 else if (pVCpu->cpum.GstCtx.ss.Attr.n.u1DefBig)
3581 {
3582 GCPtrTop = uTmpRsp.DWords.dw0;
3583 uTmpRsp.DWords.dw0 += cbItem;
3584 }
3585 else
3586 {
3587 GCPtrTop = uTmpRsp.Words.w0;
3588 uTmpRsp.Words.w0 += cbItem;
3589 }
3590 *puNewRsp = uTmpRsp.u;
3591 return GCPtrTop;
3592}
3593
3594
3595/**
3596 * Calculates the effective stack address for a push of the specified size as
3597 * well as the new temporary RSP value (upper bits may be masked).
3598 *
3599 * @returns Effective stack addressf for the push.
3600 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3601 * @param pTmpRsp The temporary stack pointer. This is updated.
3602 * @param cbItem The size of the stack item to pop.
3603 */
3604DECLINLINE(RTGCPTR) iemRegGetRspForPushEx(PCVMCPU pVCpu, PRTUINT64U pTmpRsp, uint8_t cbItem) RT_NOEXCEPT
3605{
3606 RTGCPTR GCPtrTop;
3607
3608 if (IEM_IS_64BIT_CODE(pVCpu))
3609 GCPtrTop = pTmpRsp->u -= cbItem;
3610 else if (pVCpu->cpum.GstCtx.ss.Attr.n.u1DefBig)
3611 GCPtrTop = pTmpRsp->DWords.dw0 -= cbItem;
3612 else
3613 GCPtrTop = pTmpRsp->Words.w0 -= cbItem;
3614 return GCPtrTop;
3615}
3616
3617
3618/**
3619 * Gets the effective stack address for a pop of the specified size and
3620 * calculates and updates the temporary RSP.
3621 *
3622 * @returns Current stack pointer.
3623 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3624 * @param pTmpRsp The temporary stack pointer. This is updated.
3625 * @param cbItem The size of the stack item to pop.
3626 */
3627DECLINLINE(RTGCPTR) iemRegGetRspForPopEx(PCVMCPU pVCpu, PRTUINT64U pTmpRsp, uint8_t cbItem) RT_NOEXCEPT
3628{
3629 RTGCPTR GCPtrTop;
3630 if (IEM_IS_64BIT_CODE(pVCpu))
3631 {
3632 GCPtrTop = pTmpRsp->u;
3633 pTmpRsp->u += cbItem;
3634 }
3635 else if (pVCpu->cpum.GstCtx.ss.Attr.n.u1DefBig)
3636 {
3637 GCPtrTop = pTmpRsp->DWords.dw0;
3638 pTmpRsp->DWords.dw0 += cbItem;
3639 }
3640 else
3641 {
3642 GCPtrTop = pTmpRsp->Words.w0;
3643 pTmpRsp->Words.w0 += cbItem;
3644 }
3645 return GCPtrTop;
3646}
3647
3648
3649/** Common body for iemRegRipNearReturnAndFinishClearingRF()
3650 * and iemRegRipNearReturnAndFinishNoFlags(). */
3651template<bool a_fWithFlags>
3652DECL_FORCE_INLINE(VBOXSTRICTRC)
3653iemRegRipNearReturnCommon(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t cbPop, IEMMODE enmEffOpSize) RT_NOEXCEPT
3654{
3655 /* Fetch the new RIP from the stack. */
3656 VBOXSTRICTRC rcStrict;
3657 RTUINT64U NewRip;
3658 RTUINT64U NewRsp;
3659 NewRsp.u = pVCpu->cpum.GstCtx.rsp;
3660 switch (enmEffOpSize)
3661 {
3662 case IEMMODE_16BIT:
3663 NewRip.u = 0;
3664 rcStrict = iemMemStackPopU16Ex(pVCpu, &NewRip.Words.w0, &NewRsp);
3665 break;
3666 case IEMMODE_32BIT:
3667 NewRip.u = 0;
3668 rcStrict = iemMemStackPopU32Ex(pVCpu, &NewRip.DWords.dw0, &NewRsp);
3669 break;
3670 case IEMMODE_64BIT:
3671 rcStrict = iemMemStackPopU64Ex(pVCpu, &NewRip.u, &NewRsp);
3672 break;
3673 IEM_NOT_REACHED_DEFAULT_CASE_RET();
3674 }
3675 if (rcStrict != VINF_SUCCESS)
3676 return rcStrict;
3677
3678 /* Check the new ew RIP before loading it. */
3679 /** @todo Should test this as the intel+amd pseudo code doesn't mention half
3680 * of it. The canonical test is performed here and for call. */
3681 if (enmEffOpSize != IEMMODE_64BIT)
3682 {
3683 if (RT_LIKELY(NewRip.DWords.dw0 <= pVCpu->cpum.GstCtx.cs.u32Limit))
3684 { /* likely */ }
3685 else
3686 {
3687 Log(("retn newrip=%llx - out of bounds (%x) -> #GP\n", NewRip.u, pVCpu->cpum.GstCtx.cs.u32Limit));
3688 return iemRaiseSelectorBounds(pVCpu, X86_SREG_CS, IEM_ACCESS_INSTRUCTION);
3689 }
3690 }
3691 else
3692 {
3693 if (RT_LIKELY(IEM_IS_CANONICAL(NewRip.u)))
3694 { /* likely */ }
3695 else
3696 {
3697 Log(("retn newrip=%llx - not canonical -> #GP\n", NewRip.u));
3698 return iemRaiseNotCanonical(pVCpu);
3699 }
3700 }
3701
3702 /* Apply cbPop */
3703 if (cbPop)
3704 iemRegAddToRspEx(pVCpu, &NewRsp, cbPop);
3705
3706 /* Commit it. */
3707 pVCpu->cpum.GstCtx.rip = NewRip.u;
3708 pVCpu->cpum.GstCtx.rsp = NewRsp.u;
3709
3710 /* Flush the prefetch buffer. */
3711#ifndef IEM_WITH_CODE_TLB
3712 iemOpcodeFlushLight(pVCpu, cbInstr);
3713#endif
3714 RT_NOREF(cbInstr);
3715
3716
3717 if (a_fWithFlags)
3718 return iemRegFinishClearingRF(pVCpu, VINF_SUCCESS);
3719 return iemRegFinishNoFlags(pVCpu, VINF_SUCCESS);
3720}
3721
3722
3723/**
3724 * Implements retn and retn imm16.
3725 *
3726 * @param pVCpu The cross context virtual CPU structure of the
3727 * calling thread.
3728 * @param cbInstr The current instruction length.
3729 * @param enmEffOpSize The effective operand size. This is constant.
3730 * @param cbPop The amount of arguments to pop from the stack
3731 * (bytes). This can be constant (zero).
3732 */
3733DECL_FORCE_INLINE(VBOXSTRICTRC)
3734iemRegRipNearReturnAndFinishClearingRF(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t cbPop, IEMMODE enmEffOpSize) RT_NOEXCEPT
3735{
3736 return iemRegRipNearReturnCommon<true /*a_fWithFlags*/>(pVCpu, cbInstr, cbPop, enmEffOpSize);
3737}
3738
3739
3740/**
3741 * Implements retn and retn imm16, no checking or clearing of
3742 * flags.
3743 *
3744 * @param pVCpu The cross context virtual CPU structure of the
3745 * calling thread.
3746 * @param cbInstr The current instruction length.
3747 * @param enmEffOpSize The effective operand size. This is constant.
3748 * @param cbPop The amount of arguments to pop from the stack
3749 * (bytes). This can be constant (zero).
3750 */
3751DECL_FORCE_INLINE(VBOXSTRICTRC)
3752iemRegRipNearReturnAndFinishNoFlags(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t cbPop, IEMMODE enmEffOpSize) RT_NOEXCEPT
3753{
3754 return iemRegRipNearReturnCommon<false /*a_fWithFlags*/>(pVCpu, cbInstr, cbPop, enmEffOpSize);
3755}
3756
3757/** @} */
3758
3759
3760/** @name FPU access and helpers.
3761 *
3762 * @{
3763 */
3764
3765
3766/**
3767 * Hook for preparing to use the host FPU.
3768 *
3769 * This is necessary in ring-0 and raw-mode context (nop in ring-3).
3770 *
3771 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3772 */
3773DECLINLINE(void) iemFpuPrepareUsage(PVMCPUCC pVCpu) RT_NOEXCEPT
3774{
3775#ifdef IN_RING3
3776 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_FPU_REM);
3777#else
3778 CPUMRZFpuStatePrepareHostCpuForUse(pVCpu);
3779#endif
3780 IEM_CTX_IMPORT_NORET(pVCpu, CPUMCTX_EXTRN_X87 | CPUMCTX_EXTRN_SSE_AVX | CPUMCTX_EXTRN_OTHER_XSAVE | CPUMCTX_EXTRN_XCRx);
3781}
3782
3783
3784/**
3785 * Hook for preparing to use the host FPU for SSE.
3786 *
3787 * This is necessary in ring-0 and raw-mode context (nop in ring-3).
3788 *
3789 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3790 */
3791DECLINLINE(void) iemFpuPrepareUsageSse(PVMCPUCC pVCpu) RT_NOEXCEPT
3792{
3793 iemFpuPrepareUsage(pVCpu);
3794}
3795
3796
3797/**
3798 * Hook for preparing to use the host FPU for AVX.
3799 *
3800 * This is necessary in ring-0 and raw-mode context (nop in ring-3).
3801 *
3802 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3803 */
3804DECLINLINE(void) iemFpuPrepareUsageAvx(PVMCPUCC pVCpu) RT_NOEXCEPT
3805{
3806 iemFpuPrepareUsage(pVCpu);
3807}
3808
3809
3810/**
3811 * Hook for actualizing the guest FPU state before the interpreter reads it.
3812 *
3813 * This is necessary in ring-0 and raw-mode context (nop in ring-3).
3814 *
3815 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3816 */
3817DECLINLINE(void) iemFpuActualizeStateForRead(PVMCPUCC pVCpu) RT_NOEXCEPT
3818{
3819#ifdef IN_RING3
3820 NOREF(pVCpu);
3821#else
3822 CPUMRZFpuStateActualizeForRead(pVCpu);
3823#endif
3824 IEM_CTX_IMPORT_NORET(pVCpu, CPUMCTX_EXTRN_X87 | CPUMCTX_EXTRN_SSE_AVX | CPUMCTX_EXTRN_OTHER_XSAVE | CPUMCTX_EXTRN_XCRx);
3825}
3826
3827
3828/**
3829 * Hook for actualizing the guest FPU state before the interpreter changes it.
3830 *
3831 * This is necessary in ring-0 and raw-mode context (nop in ring-3).
3832 *
3833 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3834 */
3835DECLINLINE(void) iemFpuActualizeStateForChange(PVMCPUCC pVCpu) RT_NOEXCEPT
3836{
3837#ifdef IN_RING3
3838 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_FPU_REM);
3839#else
3840 CPUMRZFpuStateActualizeForChange(pVCpu);
3841#endif
3842 IEM_CTX_IMPORT_NORET(pVCpu, CPUMCTX_EXTRN_X87 | CPUMCTX_EXTRN_SSE_AVX | CPUMCTX_EXTRN_OTHER_XSAVE | CPUMCTX_EXTRN_XCRx);
3843}
3844
3845
3846/**
3847 * Hook for actualizing the guest XMM0..15 and MXCSR register state for read
3848 * only.
3849 *
3850 * This is necessary in ring-0 and raw-mode context (nop in ring-3).
3851 *
3852 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3853 */
3854DECLINLINE(void) iemFpuActualizeSseStateForRead(PVMCPUCC pVCpu) RT_NOEXCEPT
3855{
3856#if defined(IN_RING3) || defined(VBOX_WITH_KERNEL_USING_XMM)
3857 NOREF(pVCpu);
3858#else
3859 CPUMRZFpuStateActualizeSseForRead(pVCpu);
3860#endif
3861 IEM_CTX_IMPORT_NORET(pVCpu, CPUMCTX_EXTRN_X87 | CPUMCTX_EXTRN_SSE_AVX | CPUMCTX_EXTRN_OTHER_XSAVE | CPUMCTX_EXTRN_XCRx);
3862}
3863
3864
3865/**
3866 * Hook for actualizing the guest XMM0..15 and MXCSR register state for
3867 * read+write.
3868 *
3869 * This is necessary in ring-0 and raw-mode context (nop in ring-3).
3870 *
3871 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3872 */
3873DECLINLINE(void) iemFpuActualizeSseStateForChange(PVMCPUCC pVCpu) RT_NOEXCEPT
3874{
3875#if defined(IN_RING3) || defined(VBOX_WITH_KERNEL_USING_XMM)
3876 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_FPU_REM);
3877#else
3878 CPUMRZFpuStateActualizeForChange(pVCpu);
3879#endif
3880 IEM_CTX_IMPORT_NORET(pVCpu, CPUMCTX_EXTRN_X87 | CPUMCTX_EXTRN_SSE_AVX | CPUMCTX_EXTRN_OTHER_XSAVE | CPUMCTX_EXTRN_XCRx);
3881
3882 /* Make sure any changes are loaded the next time around. */
3883 pVCpu->cpum.GstCtx.XState.Hdr.bmXState |= XSAVE_C_SSE;
3884}
3885
3886
3887/**
3888 * Hook for actualizing the guest YMM0..15 and MXCSR register state for read
3889 * only.
3890 *
3891 * This is necessary in ring-0 and raw-mode context (nop in ring-3).
3892 *
3893 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3894 */
3895DECLINLINE(void) iemFpuActualizeAvxStateForRead(PVMCPUCC pVCpu) RT_NOEXCEPT
3896{
3897#ifdef IN_RING3
3898 NOREF(pVCpu);
3899#else
3900 CPUMRZFpuStateActualizeAvxForRead(pVCpu);
3901#endif
3902 IEM_CTX_IMPORT_NORET(pVCpu, CPUMCTX_EXTRN_X87 | CPUMCTX_EXTRN_SSE_AVX | CPUMCTX_EXTRN_OTHER_XSAVE | CPUMCTX_EXTRN_XCRx);
3903}
3904
3905
3906/**
3907 * Hook for actualizing the guest YMM0..15 and MXCSR register state for
3908 * read+write.
3909 *
3910 * This is necessary in ring-0 and raw-mode context (nop in ring-3).
3911 *
3912 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3913 */
3914DECLINLINE(void) iemFpuActualizeAvxStateForChange(PVMCPUCC pVCpu) RT_NOEXCEPT
3915{
3916#ifdef IN_RING3
3917 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_FPU_REM);
3918#else
3919 CPUMRZFpuStateActualizeForChange(pVCpu);
3920#endif
3921 IEM_CTX_IMPORT_NORET(pVCpu, CPUMCTX_EXTRN_X87 | CPUMCTX_EXTRN_SSE_AVX | CPUMCTX_EXTRN_OTHER_XSAVE | CPUMCTX_EXTRN_XCRx);
3922
3923 /* Just assume we're going to make changes to the SSE and YMM_HI parts. */
3924 pVCpu->cpum.GstCtx.XState.Hdr.bmXState |= XSAVE_C_YMM | XSAVE_C_SSE;
3925}
3926
3927
3928/**
3929 * Stores a QNaN value into a FPU register.
3930 *
3931 * @param pReg Pointer to the register.
3932 */
3933DECLINLINE(void) iemFpuStoreQNan(PRTFLOAT80U pReg) RT_NOEXCEPT
3934{
3935 pReg->au32[0] = UINT32_C(0x00000000);
3936 pReg->au32[1] = UINT32_C(0xc0000000);
3937 pReg->au16[4] = UINT16_C(0xffff);
3938}
3939
3940
3941/**
3942 * Updates the FOP, FPU.CS and FPUIP registers, extended version.
3943 *
3944 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3945 * @param pFpuCtx The FPU context.
3946 * @param uFpuOpcode The FPU opcode value (see IEMCPU::uFpuOpcode).
3947 */
3948DECLINLINE(void) iemFpuUpdateOpcodeAndIpWorkerEx(PVMCPUCC pVCpu, PX86FXSTATE pFpuCtx, uint16_t uFpuOpcode) RT_NOEXCEPT
3949{
3950 Assert(uFpuOpcode != UINT16_MAX);
3951 pFpuCtx->FOP = uFpuOpcode;
3952 /** @todo x87.CS and FPUIP needs to be kept seperately. */
3953 if (IEM_IS_REAL_OR_V86_MODE(pVCpu))
3954 {
3955 /** @todo Testcase: making assumptions about how FPUIP and FPUDP are handled
3956 * happens in real mode here based on the fnsave and fnstenv images. */
3957 pFpuCtx->CS = 0;
3958 pFpuCtx->FPUIP = pVCpu->cpum.GstCtx.eip | ((uint32_t)pVCpu->cpum.GstCtx.cs.Sel << 4);
3959 }
3960 else if (!IEM_IS_LONG_MODE(pVCpu))
3961 {
3962 pFpuCtx->CS = pVCpu->cpum.GstCtx.cs.Sel;
3963 pFpuCtx->FPUIP = pVCpu->cpum.GstCtx.rip;
3964 }
3965 else
3966 *(uint64_t *)&pFpuCtx->FPUIP = pVCpu->cpum.GstCtx.rip;
3967}
3968
3969
3970/**
3971 * Marks the specified stack register as free (for FFREE).
3972 *
3973 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3974 * @param iStReg The register to free.
3975 */
3976DECLINLINE(void) iemFpuStackFree(PVMCPUCC pVCpu, uint8_t iStReg) RT_NOEXCEPT
3977{
3978 Assert(iStReg < 8);
3979 PX86FXSTATE pFpuCtx = &pVCpu->cpum.GstCtx.XState.x87;
3980 uint8_t iReg = (X86_FSW_TOP_GET(pFpuCtx->FSW) + iStReg) & X86_FSW_TOP_SMASK;
3981 pFpuCtx->FTW &= ~RT_BIT(iReg);
3982}
3983
3984
3985/**
3986 * Increments FSW.TOP, i.e. pops an item off the stack without freeing it.
3987 *
3988 * @param pVCpu The cross context virtual CPU structure of the calling thread.
3989 */
3990DECLINLINE(void) iemFpuStackIncTop(PVMCPUCC pVCpu) RT_NOEXCEPT
3991{
3992 PX86FXSTATE pFpuCtx = &pVCpu->cpum.GstCtx.XState.x87;
3993 uint16_t uFsw = pFpuCtx->FSW;
3994 uint16_t uTop = uFsw & X86_FSW_TOP_MASK;
3995 uTop = (uTop + (1 << X86_FSW_TOP_SHIFT)) & X86_FSW_TOP_MASK;
3996 uFsw &= ~X86_FSW_TOP_MASK;
3997 uFsw |= uTop;
3998 pFpuCtx->FSW = uFsw;
3999}
4000
4001
4002/**
4003 * Decrements FSW.TOP, i.e. push an item off the stack without storing anything.
4004 *
4005 * @param pVCpu The cross context virtual CPU structure of the calling thread.
4006 */
4007DECLINLINE(void) iemFpuStackDecTop(PVMCPUCC pVCpu) RT_NOEXCEPT
4008{
4009 PX86FXSTATE pFpuCtx = &pVCpu->cpum.GstCtx.XState.x87;
4010 uint16_t uFsw = pFpuCtx->FSW;
4011 uint16_t uTop = uFsw & X86_FSW_TOP_MASK;
4012 uTop = (uTop + (7 << X86_FSW_TOP_SHIFT)) & X86_FSW_TOP_MASK;
4013 uFsw &= ~X86_FSW_TOP_MASK;
4014 uFsw |= uTop;
4015 pFpuCtx->FSW = uFsw;
4016}
4017
4018
4019
4020
4021DECLINLINE(int) iemFpuStRegNotEmpty(PVMCPUCC pVCpu, uint8_t iStReg) RT_NOEXCEPT
4022{
4023 PX86FXSTATE pFpuCtx = &pVCpu->cpum.GstCtx.XState.x87;
4024 uint16_t iReg = (X86_FSW_TOP_GET(pFpuCtx->FSW) + iStReg) & X86_FSW_TOP_SMASK;
4025 if (pFpuCtx->FTW & RT_BIT(iReg))
4026 return VINF_SUCCESS;
4027 return VERR_NOT_FOUND;
4028}
4029
4030
4031DECLINLINE(int) iemFpuStRegNotEmptyRef(PVMCPUCC pVCpu, uint8_t iStReg, PCRTFLOAT80U *ppRef) RT_NOEXCEPT
4032{
4033 PX86FXSTATE pFpuCtx = &pVCpu->cpum.GstCtx.XState.x87;
4034 uint16_t iReg = (X86_FSW_TOP_GET(pFpuCtx->FSW) + iStReg) & X86_FSW_TOP_SMASK;
4035 if (pFpuCtx->FTW & RT_BIT(iReg))
4036 {
4037 *ppRef = &pFpuCtx->aRegs[iStReg].r80;
4038 return VINF_SUCCESS;
4039 }
4040 return VERR_NOT_FOUND;
4041}
4042
4043
4044DECLINLINE(int) iemFpu2StRegsNotEmptyRef(PVMCPUCC pVCpu, uint8_t iStReg0, PCRTFLOAT80U *ppRef0,
4045 uint8_t iStReg1, PCRTFLOAT80U *ppRef1) RT_NOEXCEPT
4046{
4047 PX86FXSTATE pFpuCtx = &pVCpu->cpum.GstCtx.XState.x87;
4048 uint16_t iTop = X86_FSW_TOP_GET(pFpuCtx->FSW);
4049 uint16_t iReg0 = (iTop + iStReg0) & X86_FSW_TOP_SMASK;
4050 uint16_t iReg1 = (iTop + iStReg1) & X86_FSW_TOP_SMASK;
4051 if ((pFpuCtx->FTW & (RT_BIT(iReg0) | RT_BIT(iReg1))) == (RT_BIT(iReg0) | RT_BIT(iReg1)))
4052 {
4053 *ppRef0 = &pFpuCtx->aRegs[iStReg0].r80;
4054 *ppRef1 = &pFpuCtx->aRegs[iStReg1].r80;
4055 return VINF_SUCCESS;
4056 }
4057 return VERR_NOT_FOUND;
4058}
4059
4060
4061DECLINLINE(int) iemFpu2StRegsNotEmptyRefFirst(PVMCPUCC pVCpu, uint8_t iStReg0, PCRTFLOAT80U *ppRef0, uint8_t iStReg1) RT_NOEXCEPT
4062{
4063 PX86FXSTATE pFpuCtx = &pVCpu->cpum.GstCtx.XState.x87;
4064 uint16_t iTop = X86_FSW_TOP_GET(pFpuCtx->FSW);
4065 uint16_t iReg0 = (iTop + iStReg0) & X86_FSW_TOP_SMASK;
4066 uint16_t iReg1 = (iTop + iStReg1) & X86_FSW_TOP_SMASK;
4067 if ((pFpuCtx->FTW & (RT_BIT(iReg0) | RT_BIT(iReg1))) == (RT_BIT(iReg0) | RT_BIT(iReg1)))
4068 {
4069 *ppRef0 = &pFpuCtx->aRegs[iStReg0].r80;
4070 return VINF_SUCCESS;
4071 }
4072 return VERR_NOT_FOUND;
4073}
4074
4075
4076/**
4077 * Rotates the stack registers when setting new TOS.
4078 *
4079 * @param pFpuCtx The FPU context.
4080 * @param iNewTop New TOS value.
4081 * @remarks We only do this to speed up fxsave/fxrstor which
4082 * arrange the FP registers in stack order.
4083 * MUST be done before writing the new TOS (FSW).
4084 */
4085DECLINLINE(void) iemFpuRotateStackSetTop(PX86FXSTATE pFpuCtx, uint16_t iNewTop) RT_NOEXCEPT
4086{
4087 uint16_t iOldTop = X86_FSW_TOP_GET(pFpuCtx->FSW);
4088 RTFLOAT80U ar80Temp[8];
4089
4090 if (iOldTop == iNewTop)
4091 return;
4092
4093 /* Unscrew the stack and get it into 'native' order. */
4094 ar80Temp[0] = pFpuCtx->aRegs[(8 - iOldTop + 0) & X86_FSW_TOP_SMASK].r80;
4095 ar80Temp[1] = pFpuCtx->aRegs[(8 - iOldTop + 1) & X86_FSW_TOP_SMASK].r80;
4096 ar80Temp[2] = pFpuCtx->aRegs[(8 - iOldTop + 2) & X86_FSW_TOP_SMASK].r80;
4097 ar80Temp[3] = pFpuCtx->aRegs[(8 - iOldTop + 3) & X86_FSW_TOP_SMASK].r80;
4098 ar80Temp[4] = pFpuCtx->aRegs[(8 - iOldTop + 4) & X86_FSW_TOP_SMASK].r80;
4099 ar80Temp[5] = pFpuCtx->aRegs[(8 - iOldTop + 5) & X86_FSW_TOP_SMASK].r80;
4100 ar80Temp[6] = pFpuCtx->aRegs[(8 - iOldTop + 6) & X86_FSW_TOP_SMASK].r80;
4101 ar80Temp[7] = pFpuCtx->aRegs[(8 - iOldTop + 7) & X86_FSW_TOP_SMASK].r80;
4102
4103 /* Now rotate the stack to the new position. */
4104 pFpuCtx->aRegs[0].r80 = ar80Temp[(iNewTop + 0) & X86_FSW_TOP_SMASK];
4105 pFpuCtx->aRegs[1].r80 = ar80Temp[(iNewTop + 1) & X86_FSW_TOP_SMASK];
4106 pFpuCtx->aRegs[2].r80 = ar80Temp[(iNewTop + 2) & X86_FSW_TOP_SMASK];
4107 pFpuCtx->aRegs[3].r80 = ar80Temp[(iNewTop + 3) & X86_FSW_TOP_SMASK];
4108 pFpuCtx->aRegs[4].r80 = ar80Temp[(iNewTop + 4) & X86_FSW_TOP_SMASK];
4109 pFpuCtx->aRegs[5].r80 = ar80Temp[(iNewTop + 5) & X86_FSW_TOP_SMASK];
4110 pFpuCtx->aRegs[6].r80 = ar80Temp[(iNewTop + 6) & X86_FSW_TOP_SMASK];
4111 pFpuCtx->aRegs[7].r80 = ar80Temp[(iNewTop + 7) & X86_FSW_TOP_SMASK];
4112}
4113
4114
4115/**
4116 * Updates the FPU exception status after FCW is changed.
4117 *
4118 * @param pFpuCtx The FPU context.
4119 */
4120DECLINLINE(void) iemFpuRecalcExceptionStatus(PX86FXSTATE pFpuCtx) RT_NOEXCEPT
4121{
4122 uint16_t u16Fsw = pFpuCtx->FSW;
4123 if ((u16Fsw & X86_FSW_XCPT_MASK) & ~(pFpuCtx->FCW & X86_FCW_XCPT_MASK))
4124 u16Fsw |= X86_FSW_ES | X86_FSW_B;
4125 else
4126 u16Fsw &= ~(X86_FSW_ES | X86_FSW_B);
4127 pFpuCtx->FSW = u16Fsw;
4128}
4129
4130
4131/**
4132 * Calculates the full FTW (FPU tag word) for use in FNSTENV and FNSAVE.
4133 *
4134 * @returns The full FTW.
4135 * @param pFpuCtx The FPU context.
4136 */
4137DECLINLINE(uint16_t) iemFpuCalcFullFtw(PCX86FXSTATE pFpuCtx) RT_NOEXCEPT
4138{
4139 uint8_t const u8Ftw = (uint8_t)pFpuCtx->FTW;
4140 uint16_t u16Ftw = 0;
4141 unsigned const iTop = X86_FSW_TOP_GET(pFpuCtx->FSW);
4142 for (unsigned iSt = 0; iSt < 8; iSt++)
4143 {
4144 unsigned const iReg = (iSt + iTop) & 7;
4145 if (!(u8Ftw & RT_BIT(iReg)))
4146 u16Ftw |= 3 << (iReg * 2); /* empty */
4147 else
4148 {
4149 uint16_t uTag;
4150 PCRTFLOAT80U const pr80Reg = &pFpuCtx->aRegs[iSt].r80;
4151 if (pr80Reg->s.uExponent == 0x7fff)
4152 uTag = 2; /* Exponent is all 1's => Special. */
4153 else if (pr80Reg->s.uExponent == 0x0000)
4154 {
4155 if (pr80Reg->s.uMantissa == 0x0000)
4156 uTag = 1; /* All bits are zero => Zero. */
4157 else
4158 uTag = 2; /* Must be special. */
4159 }
4160 else if (pr80Reg->s.uMantissa & RT_BIT_64(63)) /* The J bit. */
4161 uTag = 0; /* Valid. */
4162 else
4163 uTag = 2; /* Must be special. */
4164
4165 u16Ftw |= uTag << (iReg * 2);
4166 }
4167 }
4168
4169 return u16Ftw;
4170}
4171
4172
4173/**
4174 * Converts a full FTW to a compressed one (for use in FLDENV and FRSTOR).
4175 *
4176 * @returns The compressed FTW.
4177 * @param u16FullFtw The full FTW to convert.
4178 */
4179DECLINLINE(uint16_t) iemFpuCompressFtw(uint16_t u16FullFtw) RT_NOEXCEPT
4180{
4181 uint8_t u8Ftw = 0;
4182 for (unsigned i = 0; i < 8; i++)
4183 {
4184 if ((u16FullFtw & 3) != 3 /*empty*/)
4185 u8Ftw |= RT_BIT(i);
4186 u16FullFtw >>= 2;
4187 }
4188
4189 return u8Ftw;
4190}
4191
4192/** @} */
4193
4194
4195/** @name Memory access.
4196 *
4197 * @{
4198 */
4199
4200
4201/**
4202 * Checks whether alignment checks are enabled or not.
4203 *
4204 * @returns true if enabled, false if not.
4205 * @param pVCpu The cross context virtual CPU structure of the calling thread.
4206 */
4207DECLINLINE(bool) iemMemAreAlignmentChecksEnabled(PVMCPUCC pVCpu) RT_NOEXCEPT
4208{
4209#if 0
4210 AssertCompile(X86_CR0_AM == X86_EFL_AC);
4211 return IEM_GET_CPL(pVCpu) == 3
4212 && (((uint32_t)pVCpu->cpum.GstCtx.cr0 & pVCpu->cpum.GstCtx.eflags.u) & X86_CR0_AM);
4213#else
4214 return RT_BOOL(pVCpu->iem.s.fExec & IEM_F_X86_AC);
4215#endif
4216}
4217
4218/**
4219 * Checks if the given segment can be written to, raise the appropriate
4220 * exception if not.
4221 *
4222 * @returns VBox strict status code.
4223 *
4224 * @param pVCpu The cross context virtual CPU structure of the calling thread.
4225 * @param pHid Pointer to the hidden register.
4226 * @param iSegReg The register number.
4227 * @param pu64BaseAddr Where to return the base address to use for the
4228 * segment. (In 64-bit code it may differ from the
4229 * base in the hidden segment.)
4230 */
4231DECLINLINE(VBOXSTRICTRC) iemMemSegCheckWriteAccessEx(PVMCPUCC pVCpu, PCCPUMSELREGHID pHid,
4232 uint8_t iSegReg, uint64_t *pu64BaseAddr) RT_NOEXCEPT
4233{
4234 IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
4235
4236 if (IEM_IS_64BIT_CODE(pVCpu))
4237 *pu64BaseAddr = iSegReg < X86_SREG_FS ? 0 : pHid->u64Base;
4238 else
4239 {
4240 if (!pHid->Attr.n.u1Present)
4241 {
4242 uint16_t uSel = iemSRegFetchU16(pVCpu, iSegReg);
4243 AssertRelease(uSel == 0);
4244 LogEx(LOG_GROUP_IEM,("iemMemSegCheckWriteAccessEx: %#x (index %u) - bad selector -> #GP\n", uSel, iSegReg));
4245 return iemRaiseGeneralProtectionFault0(pVCpu);
4246 }
4247
4248 if ( ( (pHid->Attr.n.u4Type & X86_SEL_TYPE_CODE)
4249 || !(pHid->Attr.n.u4Type & X86_SEL_TYPE_WRITE) )
4250 && !IEM_IS_64BIT_CODE(pVCpu) )
4251 return iemRaiseSelectorInvalidAccess(pVCpu, iSegReg, IEM_ACCESS_DATA_W);
4252 *pu64BaseAddr = pHid->u64Base;
4253 }
4254 return VINF_SUCCESS;
4255}
4256
4257
4258/**
4259 * Checks if the given segment can be read from, raise the appropriate
4260 * exception if not.
4261 *
4262 * @returns VBox strict status code.
4263 *
4264 * @param pVCpu The cross context virtual CPU structure of the calling thread.
4265 * @param pHid Pointer to the hidden register.
4266 * @param iSegReg The register number.
4267 * @param pu64BaseAddr Where to return the base address to use for the
4268 * segment. (In 64-bit code it may differ from the
4269 * base in the hidden segment.)
4270 */
4271DECLINLINE(VBOXSTRICTRC) iemMemSegCheckReadAccessEx(PVMCPUCC pVCpu, PCCPUMSELREGHID pHid,
4272 uint8_t iSegReg, uint64_t *pu64BaseAddr) RT_NOEXCEPT
4273{
4274 IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
4275
4276 if (IEM_IS_64BIT_CODE(pVCpu))
4277 *pu64BaseAddr = iSegReg < X86_SREG_FS ? 0 : pHid->u64Base;
4278 else
4279 {
4280 if (!pHid->Attr.n.u1Present)
4281 {
4282 uint16_t uSel = iemSRegFetchU16(pVCpu, iSegReg);
4283 AssertRelease(uSel == 0);
4284 LogEx(LOG_GROUP_IEM,("iemMemSegCheckReadAccessEx: %#x (index %u) - bad selector -> #GP\n", uSel, iSegReg));
4285 return iemRaiseGeneralProtectionFault0(pVCpu);
4286 }
4287
4288 if ((pHid->Attr.n.u4Type & (X86_SEL_TYPE_CODE | X86_SEL_TYPE_READ)) == X86_SEL_TYPE_CODE)
4289 return iemRaiseSelectorInvalidAccess(pVCpu, iSegReg, IEM_ACCESS_DATA_R);
4290 *pu64BaseAddr = pHid->u64Base;
4291 }
4292 return VINF_SUCCESS;
4293}
4294
4295
4296/**
4297 * Maps a physical page.
4298 *
4299 * @returns VBox status code (see PGMR3PhysTlbGCPhys2Ptr).
4300 * @param pVCpu The cross context virtual CPU structure of the calling thread.
4301 * @param GCPhysMem The physical address.
4302 * @param fAccess The intended access.
4303 * @param ppvMem Where to return the mapping address.
4304 * @param pLock The PGM lock.
4305 */
4306DECLINLINE(int) iemMemPageMap(PVMCPUCC pVCpu, RTGCPHYS GCPhysMem, uint32_t fAccess,
4307 void **ppvMem, PPGMPAGEMAPLOCK pLock) RT_NOEXCEPT
4308{
4309#ifdef IEM_LOG_MEMORY_WRITES
4310 if (fAccess & IEM_ACCESS_TYPE_WRITE)
4311 return VERR_PGM_PHYS_TLB_CATCH_ALL;
4312#endif
4313
4314 /** @todo This API may require some improving later. A private deal with PGM
4315 * regarding locking and unlocking needs to be struct. A couple of TLBs
4316 * living in PGM, but with publicly accessible inlined access methods
4317 * could perhaps be an even better solution. */
4318 int rc = PGMPhysIemGCPhys2Ptr(pVCpu->CTX_SUFF(pVM), pVCpu,
4319 GCPhysMem,
4320 RT_BOOL(fAccess & IEM_ACCESS_TYPE_WRITE),
4321 RT_BOOL(pVCpu->iem.s.fExec & IEM_F_BYPASS_HANDLERS),
4322 ppvMem,
4323 pLock);
4324 /*Log(("PGMPhysIemGCPhys2Ptr %Rrc pLock=%.*Rhxs\n", rc, sizeof(*pLock), pLock));*/
4325 AssertMsg(rc == VINF_SUCCESS || RT_FAILURE_NP(rc), ("%Rrc\n", rc));
4326
4327 return rc;
4328}
4329
4330
4331/**
4332 * Unmap a page previously mapped by iemMemPageMap.
4333 *
4334 * @param pVCpu The cross context virtual CPU structure of the calling thread.
4335 * @param GCPhysMem The physical address.
4336 * @param fAccess The intended access.
4337 * @param pvMem What iemMemPageMap returned.
4338 * @param pLock The PGM lock.
4339 */
4340DECLINLINE(void) iemMemPageUnmap(PVMCPUCC pVCpu, RTGCPHYS GCPhysMem, uint32_t fAccess,
4341 const void *pvMem, PPGMPAGEMAPLOCK pLock) RT_NOEXCEPT
4342{
4343 NOREF(pVCpu);
4344 NOREF(GCPhysMem);
4345 NOREF(fAccess);
4346 NOREF(pvMem);
4347 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), pLock);
4348}
4349
4350#ifdef IEM_WITH_SETJMP
4351
4352/** @todo slim this down */
4353DECL_INLINE_THROW(RTGCPTR) iemMemApplySegmentToReadJmp(PVMCPUCC pVCpu, uint8_t iSegReg,
4354 size_t cbMem, RTGCPTR GCPtrMem) IEM_NOEXCEPT_MAY_LONGJMP
4355{
4356 Assert(cbMem >= 1);
4357 Assert(iSegReg < X86_SREG_COUNT);
4358
4359 /*
4360 * 64-bit mode is simpler.
4361 */
4362 if (IEM_IS_64BIT_CODE(pVCpu))
4363 {
4364 if (iSegReg >= X86_SREG_FS && iSegReg != UINT8_MAX)
4365 {
4366 IEM_CTX_IMPORT_JMP(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
4367 PCPUMSELREGHID const pSel = iemSRegGetHid(pVCpu, iSegReg);
4368 GCPtrMem += pSel->u64Base;
4369 }
4370
4371 if (RT_LIKELY(X86_IS_CANONICAL(GCPtrMem) && X86_IS_CANONICAL(GCPtrMem + cbMem - 1)))
4372 return GCPtrMem;
4373 iemRaiseGeneralProtectionFault0Jmp(pVCpu);
4374 }
4375 /*
4376 * 16-bit and 32-bit segmentation.
4377 */
4378 else if (iSegReg != UINT8_MAX)
4379 {
4380 /** @todo Does this apply to segments with 4G-1 limit? */
4381 uint32_t const GCPtrLast32 = (uint32_t)GCPtrMem + (uint32_t)cbMem - 1;
4382 if (RT_LIKELY(GCPtrLast32 >= (uint32_t)GCPtrMem))
4383 {
4384 IEM_CTX_IMPORT_JMP(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
4385 PCPUMSELREGHID const pSel = iemSRegGetHid(pVCpu, iSegReg);
4386 switch (pSel->Attr.u & ( X86DESCATTR_P | X86DESCATTR_UNUSABLE
4387 | X86_SEL_TYPE_READ | X86_SEL_TYPE_WRITE /* same as read */
4388 | X86_SEL_TYPE_DOWN | X86_SEL_TYPE_CONF /* same as down */
4389 | X86_SEL_TYPE_CODE))
4390 {
4391 case X86DESCATTR_P: /* readonly data, expand up */
4392 case X86DESCATTR_P | X86_SEL_TYPE_WRITE: /* writable data, expand up */
4393 case X86DESCATTR_P | X86_SEL_TYPE_CODE | X86_SEL_TYPE_READ: /* code, read-only */
4394 case X86DESCATTR_P | X86_SEL_TYPE_CODE | X86_SEL_TYPE_READ | X86_SEL_TYPE_CONF: /* conforming code, read-only */
4395 /* expand up */
4396 if (RT_LIKELY(GCPtrLast32 <= pSel->u32Limit))
4397 return (uint32_t)GCPtrMem + (uint32_t)pSel->u64Base;
4398 Log10(("iemMemApplySegmentToReadJmp: out of bounds %#x..%#x vs %#x\n",
4399 (uint32_t)GCPtrMem, GCPtrLast32, pSel->u32Limit));
4400 break;
4401
4402 case X86DESCATTR_P | X86_SEL_TYPE_DOWN: /* readonly data, expand down */
4403 case X86DESCATTR_P | X86_SEL_TYPE_DOWN | X86_SEL_TYPE_WRITE: /* writable data, expand down */
4404 /* expand down */
4405 if (RT_LIKELY( (uint32_t)GCPtrMem > pSel->u32Limit
4406 && ( pSel->Attr.n.u1DefBig
4407 || GCPtrLast32 <= UINT32_C(0xffff)) ))
4408 return (uint32_t)GCPtrMem + (uint32_t)pSel->u64Base;
4409 Log10(("iemMemApplySegmentToReadJmp: expand down out of bounds %#x..%#x vs %#x..%#x\n",
4410 (uint32_t)GCPtrMem, GCPtrLast32, pSel->u32Limit, pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT16_MAX));
4411 break;
4412
4413 default:
4414 Log10(("iemMemApplySegmentToReadJmp: bad selector %#x\n", pSel->Attr.u));
4415 iemRaiseSelectorInvalidAccessJmp(pVCpu, iSegReg, IEM_ACCESS_DATA_R);
4416 break;
4417 }
4418 }
4419 Log10(("iemMemApplySegmentToReadJmp: out of bounds %#x..%#x\n",(uint32_t)GCPtrMem, GCPtrLast32));
4420 iemRaiseSelectorBoundsJmp(pVCpu, iSegReg, IEM_ACCESS_DATA_R);
4421 }
4422 /*
4423 * 32-bit flat address.
4424 */
4425 else
4426 return GCPtrMem;
4427}
4428
4429
4430/** @todo slim this down */
4431DECL_INLINE_THROW(RTGCPTR) iemMemApplySegmentToWriteJmp(PVMCPUCC pVCpu, uint8_t iSegReg, size_t cbMem,
4432 RTGCPTR GCPtrMem) IEM_NOEXCEPT_MAY_LONGJMP
4433{
4434 Assert(cbMem >= 1);
4435 Assert(iSegReg < X86_SREG_COUNT);
4436
4437 /*
4438 * 64-bit mode is simpler.
4439 */
4440 if (IEM_IS_64BIT_CODE(pVCpu))
4441 {
4442 if (iSegReg >= X86_SREG_FS)
4443 {
4444 IEM_CTX_IMPORT_JMP(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
4445 PCPUMSELREGHID pSel = iemSRegGetHid(pVCpu, iSegReg);
4446 GCPtrMem += pSel->u64Base;
4447 }
4448
4449 if (RT_LIKELY(X86_IS_CANONICAL(GCPtrMem) && X86_IS_CANONICAL(GCPtrMem + cbMem - 1)))
4450 return GCPtrMem;
4451 }
4452 /*
4453 * 16-bit and 32-bit segmentation.
4454 */
4455 else
4456 {
4457 Assert(GCPtrMem <= UINT32_MAX);
4458 IEM_CTX_IMPORT_JMP(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
4459 PCPUMSELREGHID pSel = iemSRegGetHid(pVCpu, iSegReg);
4460 uint32_t const fRelevantAttrs = pSel->Attr.u & ( X86DESCATTR_P | X86DESCATTR_UNUSABLE
4461 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_WRITE | X86_SEL_TYPE_DOWN);
4462 if ( fRelevantAttrs == (X86DESCATTR_P | X86_SEL_TYPE_WRITE) /* data, expand up */
4463 /** @todo explore exactly how the CS stuff works in real mode. See also
4464 * http://www.rcollins.org/Productivity/DescriptorCache.html and
4465 * http://www.rcollins.org/ddj/Aug98/Aug98.html for some insight. */
4466 || (iSegReg == X86_SREG_CS && IEM_IS_REAL_OR_V86_MODE(pVCpu)) ) /* Ignored for CS. */ /** @todo testcase! */
4467 {
4468 /* expand up */
4469 uint32_t const GCPtrLast32 = (uint32_t)GCPtrMem + (uint32_t)cbMem - 1;
4470 if (RT_LIKELY( GCPtrLast32 <= pSel->u32Limit
4471 && GCPtrLast32 >= (uint32_t)GCPtrMem))
4472 return (uint32_t)GCPtrMem + (uint32_t)pSel->u64Base;
4473 iemRaiseSelectorBoundsJmp(pVCpu, iSegReg, IEM_ACCESS_DATA_W);
4474 }
4475 else if (fRelevantAttrs == (X86DESCATTR_P | X86_SEL_TYPE_WRITE | X86_SEL_TYPE_DOWN)) /* data, expand up */
4476 {
4477 /* expand down - the uppger boundary is defined by the B bit, not G. */
4478 uint32_t GCPtrLast32 = (uint32_t)GCPtrMem + (uint32_t)cbMem - 1;
4479 if (RT_LIKELY( (uint32_t)GCPtrMem >= pSel->u32Limit
4480 && (pSel->Attr.n.u1DefBig || GCPtrLast32 <= UINT32_C(0xffff))
4481 && GCPtrLast32 >= (uint32_t)GCPtrMem))
4482 return (uint32_t)GCPtrMem + (uint32_t)pSel->u64Base;
4483 iemRaiseSelectorBoundsJmp(pVCpu, iSegReg, IEM_ACCESS_DATA_W);
4484 }
4485 else
4486 iemRaiseSelectorInvalidAccessJmp(pVCpu, iSegReg, IEM_ACCESS_DATA_W);
4487 }
4488 iemRaiseGeneralProtectionFault0Jmp(pVCpu);
4489}
4490
4491#endif /* IEM_WITH_SETJMP */
4492
4493/**
4494 * Fakes a long mode stack selector for SS = 0.
4495 *
4496 * @param pDescSs Where to return the fake stack descriptor.
4497 * @param uDpl The DPL we want.
4498 */
4499DECLINLINE(void) iemMemFakeStackSelDesc(PIEMSELDESC pDescSs, uint32_t uDpl) RT_NOEXCEPT
4500{
4501 pDescSs->Long.au64[0] = 0;
4502 pDescSs->Long.au64[1] = 0;
4503 pDescSs->Long.Gen.u4Type = X86_SEL_TYPE_RW_ACC;
4504 pDescSs->Long.Gen.u1DescType = 1; /* 1 = code / data, 0 = system. */
4505 pDescSs->Long.Gen.u2Dpl = uDpl;
4506 pDescSs->Long.Gen.u1Present = 1;
4507 pDescSs->Long.Gen.u1Long = 1;
4508}
4509
4510
4511/*
4512 * Unmap helpers.
4513 */
4514
4515#ifdef IEM_WITH_SETJMP
4516
4517DECL_INLINE_THROW(void) iemMemCommitAndUnmapRwJmp(PVMCPUCC pVCpu, uint8_t bMapInfo) IEM_NOEXCEPT_MAY_LONGJMP
4518{
4519# if defined(IEM_WITH_DATA_TLB) && defined(IN_RING3)
4520 if (RT_LIKELY(bMapInfo == 0))
4521 return;
4522# endif
4523 iemMemCommitAndUnmapRwSafeJmp(pVCpu, bMapInfo);
4524}
4525
4526
4527DECL_INLINE_THROW(void) iemMemCommitAndUnmapAtJmp(PVMCPUCC pVCpu, uint8_t bMapInfo) IEM_NOEXCEPT_MAY_LONGJMP
4528{
4529# if defined(IEM_WITH_DATA_TLB) && defined(IN_RING3)
4530 if (RT_LIKELY(bMapInfo == 0))
4531 return;
4532# endif
4533 iemMemCommitAndUnmapAtSafeJmp(pVCpu, bMapInfo);
4534}
4535
4536
4537DECL_INLINE_THROW(void) iemMemCommitAndUnmapWoJmp(PVMCPUCC pVCpu, uint8_t bMapInfo) IEM_NOEXCEPT_MAY_LONGJMP
4538{
4539# if defined(IEM_WITH_DATA_TLB) && defined(IN_RING3)
4540 if (RT_LIKELY(bMapInfo == 0))
4541 return;
4542# endif
4543 iemMemCommitAndUnmapWoSafeJmp(pVCpu, bMapInfo);
4544}
4545
4546
4547DECL_INLINE_THROW(void) iemMemCommitAndUnmapRoJmp(PVMCPUCC pVCpu, uint8_t bMapInfo) IEM_NOEXCEPT_MAY_LONGJMP
4548{
4549# if defined(IEM_WITH_DATA_TLB) && defined(IN_RING3)
4550 if (RT_LIKELY(bMapInfo == 0))
4551 return;
4552# endif
4553 iemMemCommitAndUnmapRoSafeJmp(pVCpu, bMapInfo);
4554}
4555
4556DECLINLINE(void) iemMemRollbackAndUnmapWo(PVMCPUCC pVCpu, uint8_t bMapInfo) RT_NOEXCEPT
4557{
4558# if defined(IEM_WITH_DATA_TLB) && defined(IN_RING3)
4559 if (RT_LIKELY(bMapInfo == 0))
4560 return;
4561# endif
4562 iemMemRollbackAndUnmapWoSafe(pVCpu, bMapInfo);
4563}
4564
4565#endif /* IEM_WITH_SETJMP */
4566
4567
4568/*
4569 * Instantiate R/W inline templates.
4570 */
4571
4572/** @def TMPL_MEM_CHECK_UNALIGNED_WITHIN_PAGE_OK
4573 * Used to check if an unaligned access is if within the page and won't
4574 * trigger an \#AC.
4575 *
4576 * This can also be used to deal with misaligned accesses on platforms that are
4577 * senstive to such if desires.
4578 */
4579#if 1
4580# define TMPL_MEM_CHECK_UNALIGNED_WITHIN_PAGE_OK(a_pVCpu, a_GCPtrEff, a_TmplMemType) \
4581 ( ((a_GCPtrEff) & GUEST_PAGE_OFFSET_MASK) <= GUEST_PAGE_SIZE - sizeof(a_TmplMemType) \
4582 && !((a_pVCpu)->iem.s.fExec & IEM_F_X86_AC) )
4583#else
4584# define TMPL_MEM_CHECK_UNALIGNED_WITHIN_PAGE_OK(a_pVCpu, a_GCPtrEff, a_TmplMemType) 0
4585#endif
4586
4587#define TMPL_MEM_WITH_ATOMIC_MAPPING
4588
4589#define TMPL_MEM_TYPE uint8_t
4590#define TMPL_MEM_TYPE_ALIGN 0
4591#define TMPL_MEM_TYPE_SIZE 1
4592#define TMPL_MEM_FN_SUFF U8
4593#define TMPL_MEM_FMT_TYPE "%#04x"
4594#define TMPL_MEM_FMT_DESC "byte"
4595#include "../VMMAll/IEMAllMemRWTmplInline.cpp.h"
4596
4597#define TMPL_MEM_WITH_STACK
4598
4599#define TMPL_MEM_TYPE uint16_t
4600#define TMPL_MEM_TYPE_ALIGN 1
4601#define TMPL_MEM_TYPE_SIZE 2
4602#define TMPL_MEM_FN_SUFF U16
4603#define TMPL_MEM_FMT_TYPE "%#06x"
4604#define TMPL_MEM_FMT_DESC "word"
4605#include "../VMMAll/IEMAllMemRWTmplInline.cpp.h"
4606
4607#define TMPL_WITH_PUSH_SREG
4608#define TMPL_MEM_TYPE uint32_t
4609#define TMPL_MEM_TYPE_ALIGN 3
4610#define TMPL_MEM_TYPE_SIZE 4
4611#define TMPL_MEM_FN_SUFF U32
4612#define TMPL_MEM_FMT_TYPE "%#010x"
4613#define TMPL_MEM_FMT_DESC "dword"
4614#include "../VMMAll/IEMAllMemRWTmplInline.cpp.h"
4615#undef TMPL_WITH_PUSH_SREG
4616
4617#define TMPL_MEM_TYPE uint64_t
4618#define TMPL_MEM_TYPE_ALIGN 7
4619#define TMPL_MEM_TYPE_SIZE 8
4620#define TMPL_MEM_FN_SUFF U64
4621#define TMPL_MEM_FMT_TYPE "%#018RX64"
4622#define TMPL_MEM_FMT_DESC "qword"
4623#include "../VMMAll/IEMAllMemRWTmplInline.cpp.h"
4624
4625#undef TMPL_MEM_WITH_STACK
4626#undef TMPL_MEM_WITH_ATOMIC_MAPPING
4627
4628#define TMPL_MEM_NO_STORE
4629#define TMPL_MEM_NO_MAPPING
4630#define TMPL_MEM_TYPE uint64_t
4631#define TMPL_MEM_TYPE_ALIGN 15
4632#define TMPL_MEM_TYPE_SIZE 8
4633#define TMPL_MEM_FN_SUFF U64AlignedU128
4634#define TMPL_MEM_FMT_TYPE "%#018RX64"
4635#define TMPL_MEM_FMT_DESC "qword"
4636#include "../VMMAll/IEMAllMemRWTmplInline.cpp.h"
4637
4638#undef TMPL_MEM_NO_STORE
4639#undef TMPL_MEM_NO_MAPPING
4640
4641#define TMPL_MEM_TYPE RTFLOAT80U
4642#define TMPL_MEM_TYPE_ALIGN 7
4643#define TMPL_MEM_TYPE_SIZE 10
4644#define TMPL_MEM_FN_SUFF R80
4645#define TMPL_MEM_FMT_TYPE "%.10Rhxs"
4646#define TMPL_MEM_FMT_DESC "tword"
4647#include "../VMMAll/IEMAllMemRWTmplInline.cpp.h"
4648
4649#define TMPL_MEM_TYPE RTPBCD80U
4650#define TMPL_MEM_TYPE_ALIGN 7 /** @todo RTPBCD80U alignment testcase */
4651#define TMPL_MEM_TYPE_SIZE 10
4652#define TMPL_MEM_FN_SUFF D80
4653#define TMPL_MEM_FMT_TYPE "%.10Rhxs"
4654#define TMPL_MEM_FMT_DESC "tword"
4655#include "../VMMAll/IEMAllMemRWTmplInline.cpp.h"
4656
4657#define TMPL_MEM_WITH_ATOMIC_MAPPING
4658#define TMPL_MEM_TYPE RTUINT128U
4659#define TMPL_MEM_TYPE_ALIGN 15
4660#define TMPL_MEM_TYPE_SIZE 16
4661#define TMPL_MEM_FN_SUFF U128
4662#define TMPL_MEM_FMT_TYPE "%.16Rhxs"
4663#define TMPL_MEM_FMT_DESC "dqword"
4664#include "../VMMAll/IEMAllMemRWTmplInline.cpp.h"
4665#undef TMPL_MEM_WITH_ATOMIC_MAPPING
4666
4667#define TMPL_MEM_NO_MAPPING
4668#define TMPL_MEM_TYPE RTUINT128U
4669#define TMPL_MEM_TYPE_ALIGN 0
4670#define TMPL_MEM_TYPE_SIZE 16
4671#define TMPL_MEM_FN_SUFF U128NoAc
4672#define TMPL_MEM_FMT_TYPE "%.16Rhxs"
4673#define TMPL_MEM_FMT_DESC "dqword"
4674#include "../VMMAll/IEMAllMemRWTmplInline.cpp.h"
4675#undef TMPL_MEM_NO_MAPPING
4676
4677
4678/* Every template relying on unaligned accesses inside a page not being okay should go below. */
4679#undef TMPL_MEM_CHECK_UNALIGNED_WITHIN_PAGE_OK
4680#define TMPL_MEM_CHECK_UNALIGNED_WITHIN_PAGE_OK(a_pVCpu, a_GCPtrEff, a_TmplMemType) 0
4681
4682#define TMPL_MEM_NO_MAPPING
4683#define TMPL_MEM_TYPE RTUINT128U
4684#define TMPL_MEM_TYPE_ALIGN 15
4685#define TMPL_MEM_TYPE_SIZE 16
4686#define TMPL_MEM_FN_SUFF U128AlignedSse
4687#define TMPL_MEM_FMT_TYPE "%.16Rhxs"
4688#define TMPL_MEM_FMT_DESC "dqword"
4689#include "../VMMAll/IEMAllMemRWTmplInline.cpp.h"
4690#undef TMPL_MEM_NO_MAPPING
4691
4692#define TMPL_MEM_NO_MAPPING
4693#define TMPL_MEM_TYPE RTUINT256U
4694#define TMPL_MEM_TYPE_ALIGN 0
4695#define TMPL_MEM_TYPE_SIZE 32
4696#define TMPL_MEM_FN_SUFF U256NoAc
4697#define TMPL_MEM_FMT_TYPE "%.32Rhxs"
4698#define TMPL_MEM_FMT_DESC "qqword"
4699#include "../VMMAll/IEMAllMemRWTmplInline.cpp.h"
4700#undef TMPL_MEM_NO_MAPPING
4701
4702#define TMPL_MEM_NO_MAPPING
4703#define TMPL_MEM_TYPE RTUINT256U
4704#define TMPL_MEM_TYPE_ALIGN 31
4705#define TMPL_MEM_TYPE_SIZE 32
4706#define TMPL_MEM_FN_SUFF U256AlignedAvx
4707#define TMPL_MEM_FMT_TYPE "%.32Rhxs"
4708#define TMPL_MEM_FMT_DESC "qqword"
4709#include "../VMMAll/IEMAllMemRWTmplInline.cpp.h"
4710#undef TMPL_MEM_NO_MAPPING
4711
4712#undef TMPL_MEM_CHECK_UNALIGNED_WITHIN_PAGE_OK
4713
4714/** @} */
4715
4716
4717#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4718
4719/**
4720 * Gets CR0 fixed-0 bits in VMX operation.
4721 *
4722 * We do this rather than fetching what we report to the guest (in
4723 * IA32_VMX_CR0_FIXED0 MSR) because real hardware (and so do we) report the same
4724 * values regardless of whether unrestricted-guest feature is available on the CPU.
4725 *
4726 * @returns CR0 fixed-0 bits.
4727 * @param pVCpu The cross context virtual CPU structure.
4728 * @param fVmxNonRootMode Whether the CR0 fixed-0 bits for VMX non-root mode
4729 * must be returned. When @c false, the CR0 fixed-0
4730 * bits for VMX root mode is returned.
4731 *
4732 */
4733DECLINLINE(uint64_t) iemVmxGetCr0Fixed0(PCVMCPUCC pVCpu, bool fVmxNonRootMode) RT_NOEXCEPT
4734{
4735 Assert(IEM_VMX_IS_ROOT_MODE(pVCpu));
4736
4737 PCVMXMSRS pMsrs = &pVCpu->cpum.GstCtx.hwvirt.vmx.Msrs;
4738 if ( fVmxNonRootMode
4739 && (pMsrs->ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_UNRESTRICTED_GUEST))
4740 return VMX_V_CR0_FIXED0_UX;
4741 return VMX_V_CR0_FIXED0;
4742}
4743
4744
4745# ifdef XAPIC_OFF_END /* Requires VBox/apic.h to be included before IEMInline.h. */
4746/**
4747 * Sets virtual-APIC write emulation as pending.
4748 *
4749 * @param pVCpu The cross context virtual CPU structure.
4750 * @param offApic The offset in the virtual-APIC page that was written.
4751 */
4752DECLINLINE(void) iemVmxVirtApicSetPendingWrite(PVMCPUCC pVCpu, uint16_t offApic) RT_NOEXCEPT
4753{
4754 Assert(offApic < XAPIC_OFF_END + 4);
4755
4756 /*
4757 * Record the currently updated APIC offset, as we need this later for figuring
4758 * out whether to perform TPR, EOI or self-IPI virtualization as well as well
4759 * as for supplying the exit qualification when causing an APIC-write VM-exit.
4760 */
4761 pVCpu->cpum.GstCtx.hwvirt.vmx.offVirtApicWrite = offApic;
4762
4763 /*
4764 * Flag that we need to perform virtual-APIC write emulation (TPR/PPR/EOI/Self-IPI
4765 * virtualization or APIC-write emulation).
4766 */
4767 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
4768 VMCPU_FF_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE);
4769}
4770# endif /* XAPIC_OFF_END */
4771
4772#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
4773
4774#endif /* !VMM_INCLUDED_SRC_include_IEMInline_h */
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